checkstyle sweep
[fanfix.git] / src / jexer / TDirectoryList.java
1 /*
2 * Jexer - Java Text User Interface
3 *
4 * License: LGPLv3 or later
5 *
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
9 *
10 * Copyright (C) 2015 Kevin Lamonte
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * 02110-1301 USA
27 *
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 * @version 1
30 */
31 package jexer;
32
33 import java.io.File;
34 import java.util.ArrayList;
35 import java.util.List;
36
37 import jexer.bits.CellAttributes;
38 import jexer.event.TKeypressEvent;
39 import jexer.event.TMouseEvent;
40 import static jexer.TKeypress.*;
41
42 /**
43 * TDirectoryList shows the files within a directory.
44 */
45 public final class TDirectoryList extends TWidget {
46
47 /**
48 * Files in the directory.
49 */
50 private List<File> files;
51
52 /**
53 * Selected file.
54 */
55 private int selectedFile = -1;
56
57 /**
58 * Root path containing files to display.
59 */
60 private File path;
61
62 /**
63 * Set the new path to display.
64 *
65 * @param path new path to list files for
66 */
67 public void setPath(final String path) {
68 this.path = new File(path);
69 reflow();
70 }
71
72 /**
73 * Get the path that is being displayed.
74 *
75 * @return the path
76 */
77 public File getPath() {
78 return path;
79 }
80
81 /**
82 * Vertical scrollbar.
83 */
84 private TVScroller vScroller;
85
86 /**
87 * Horizontal scrollbar.
88 */
89 private THScroller hScroller;
90
91 /**
92 * Maximum width of a single line.
93 */
94 private int maxLineWidth;
95
96 /**
97 * The action to perform when the user selects an item.
98 */
99 private TAction action = null;
100
101 /**
102 * Perform user selection action.
103 */
104 public void dispatch() {
105 assert (selectedFile >= 0);
106 assert (selectedFile < files.size());
107 if (action != null) {
108 action.DO();
109 }
110 }
111
112 /**
113 * Format one of the entries for drawing on the screen.
114 *
115 * @param index index into files
116 * @return the line to draw
117 */
118 private String renderFile(final int index) {
119 File file = files.get(index);
120 String name = file.getName();
121 if (name.length() > 20) {
122 name = name.substring(0, 17) + "...";
123 }
124 return String.format("%-20s %5dk", name, (file.length() / 1024));
125 }
126
127 /**
128 * Resize for a new width/height.
129 */
130 public void reflow() {
131
132 // Reset the lines
133 selectedFile = -1;
134 maxLineWidth = 0;
135 files.clear();
136
137 // Build a list of files in this directory
138 File [] newFiles = path.listFiles();
139 if (newFiles != null) {
140 for (int i = 0; i < newFiles.length; i++) {
141 if (newFiles[i].getName().startsWith(".")) {
142 continue;
143 }
144 if (newFiles[i].isDirectory()) {
145 continue;
146 }
147 files.add(newFiles[i]);
148 }
149 }
150
151 for (int i = 0; i < files.size(); i++) {
152 String line = renderFile(i);
153 if (line.length() > maxLineWidth) {
154 maxLineWidth = line.length();
155 }
156 }
157
158 // Start at the top
159 if (vScroller == null) {
160 vScroller = new TVScroller(this, getWidth() - 1, 0,
161 getHeight() - 1);
162 } else {
163 vScroller.setX(getWidth() - 1);
164 vScroller.setHeight(getHeight() - 1);
165 }
166 vScroller.setBottomValue(files.size() - getHeight() - 1);
167 vScroller.setTopValue(0);
168 vScroller.setValue(0);
169 if (vScroller.getBottomValue() < 0) {
170 vScroller.setBottomValue(0);
171 }
172 vScroller.setBigChange(getHeight() - 1);
173
174 // Start at the left
175 if (hScroller == null) {
176 hScroller = new THScroller(this, 0, getHeight() - 1,
177 getWidth() - 1);
178 } else {
179 hScroller.setY(getHeight() - 1);
180 hScroller.setWidth(getWidth() - 1);
181 }
182 hScroller.setRightValue(maxLineWidth - getWidth() + 1);
183 hScroller.setLeftValue(0);
184 hScroller.setValue(0);
185 if (hScroller.getRightValue() < 0) {
186 hScroller.setRightValue(0);
187 }
188 hScroller.setBigChange(getWidth() - 1);
189 }
190
191 /**
192 * Public constructor.
193 *
194 * @param parent parent widget
195 * @param path directory path, must be a directory
196 * @param x column relative to parent
197 * @param y row relative to parent
198 * @param width width of text area
199 * @param height height of text area
200 */
201 public TDirectoryList(final TWidget parent, final String path, final int x,
202 final int y, final int width, final int height) {
203
204 this(parent, path, x, y, width, height, null);
205 }
206
207 /**
208 * Public constructor.
209 *
210 * @param parent parent widget
211 * @param path directory path, must be a directory
212 * @param x column relative to parent
213 * @param y row relative to parent
214 * @param width width of text area
215 * @param height height of text area
216 * @param action action to perform when an item is selected
217 */
218 public TDirectoryList(final TWidget parent, final String path, final int x,
219 final int y, final int width, final int height, final TAction action) {
220
221 super(parent, x, y, width, height);
222 this.path = new File(path);
223 this.action = action;
224 files = new ArrayList<File>();
225 reflow();
226 }
227
228 /**
229 * Draw the files list.
230 */
231 @Override
232 public void draw() {
233 CellAttributes color = null;
234 int begin = vScroller.getValue();
235 int topY = 0;
236 for (int i = begin; i < files.size(); i++) {
237 String line = renderFile(i);
238 if (hScroller.getValue() < line.length()) {
239 line = line.substring(hScroller.getValue());
240 } else {
241 line = "";
242 }
243 if (i == selectedFile) {
244 color = getTheme().getColor("tdirectorylist.selected");
245 } else if (isAbsoluteActive()) {
246 color = getTheme().getColor("tdirectorylist");
247 } else {
248 color = getTheme().getColor("tdirectorylist.inactive");
249 }
250 String formatString = "%-" + Integer.toString(getWidth() - 1) + "s";
251 getScreen().putStringXY(0, topY, String.format(formatString, line),
252 color);
253 topY++;
254 if (topY >= getHeight() - 1) {
255 break;
256 }
257 }
258
259 if (isAbsoluteActive()) {
260 color = getTheme().getColor("tdirectorylist");
261 } else {
262 color = getTheme().getColor("tdirectorylist.inactive");
263 }
264
265 // Pad the rest with blank lines
266 for (int i = topY; i < getHeight() - 1; i++) {
267 getScreen().hLineXY(0, i, getWidth() - 1, ' ', color);
268 }
269 }
270
271 /**
272 * Handle mouse press events.
273 *
274 * @param mouse mouse button press event
275 */
276 @Override
277 public void onMouseDown(final TMouseEvent mouse) {
278 if (mouse.isMouseWheelUp()) {
279 vScroller.decrement();
280 return;
281 }
282 if (mouse.isMouseWheelDown()) {
283 vScroller.increment();
284 return;
285 }
286
287 if ((mouse.getX() < getWidth() - 1)
288 && (mouse.getY() < getHeight() - 1)) {
289 if (vScroller.getValue() + mouse.getY() < files.size()) {
290 selectedFile = vScroller.getValue() + mouse.getY();
291 }
292 path = files.get(selectedFile);
293 dispatch();
294 return;
295 }
296
297 // Pass to children
298 super.onMouseDown(mouse);
299 }
300
301 /**
302 * Handle mouse release events.
303 *
304 * @param mouse mouse button release event
305 */
306 @Override
307 public void onMouseUp(final TMouseEvent mouse) {
308 // Pass to children
309 super.onMouseDown(mouse);
310 }
311
312 /**
313 * Handle keystrokes.
314 *
315 * @param keypress keystroke event
316 */
317 @Override
318 public void onKeypress(final TKeypressEvent keypress) {
319 if (keypress.equals(kbLeft)) {
320 hScroller.decrement();
321 } else if (keypress.equals(kbRight)) {
322 hScroller.increment();
323 } else if (keypress.equals(kbUp)) {
324 if (files.size() > 0) {
325 if (selectedFile >= 0) {
326 if (selectedFile > 0) {
327 selectedFile--;
328 }
329 } else {
330 selectedFile = files.size() - 1;
331 }
332 path = files.get(selectedFile);
333 }
334 } else if (keypress.equals(kbDown)) {
335 if (files.size() > 0) {
336 if (selectedFile >= 0) {
337 if (selectedFile < files.size() - 1) {
338 selectedFile++;
339 }
340 } else {
341 selectedFile = 0;
342 }
343 path = files.get(selectedFile);
344 }
345 } else if (keypress.equals(kbPgUp)) {
346 vScroller.bigDecrement();
347 } else if (keypress.equals(kbPgDn)) {
348 vScroller.bigIncrement();
349 } else if (keypress.equals(kbHome)) {
350 vScroller.toTop();
351 if (files.size() > 0) {
352 selectedFile = 0;
353 path = files.get(selectedFile);
354 }
355 } else if (keypress.equals(kbEnd)) {
356 vScroller.toBottom();
357 if (files.size() > 0) {
358 selectedFile = files.size() - 1;
359 path = files.get(selectedFile);
360 }
361 } else if (keypress.equals(kbTab)) {
362 getParent().switchWidget(true);
363 } else if (keypress.equals(kbShiftTab) || keypress.equals(kbBackTab)) {
364 getParent().switchWidget(false);
365 } else if (keypress.equals(kbEnter)) {
366 if (selectedFile >= 0) {
367 path = files.get(selectedFile);
368 dispatch();
369 }
370 } else {
371 // Pass other keys (tab etc.) on
372 super.onKeypress(keypress);
373 }
374 }
375
376 }