stubs for TFileOpenBox, cleanup putStringXY
[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 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 public File path;
61
62 /**
63 * Vertical scrollbar.
64 */
65 private TVScroller vScroller;
66
67 /**
68 * Horizontal scrollbar.
69 */
70 private THScroller hScroller;
71
72 /**
73 * Maximum width of a single line.
74 */
75 private int maxLineWidth;
76
77 /**
78 * The action to perform when the user selects an item.
79 */
80 private TAction action = null;
81
82 /**
83 * Perform user selection action.
84 */
85 public void dispatch() {
86 assert (selectedFile >= 0);
87 assert (selectedFile < files.size());
88 if (action != null) {
89 action.DO();
90 }
91 }
92
93 /**
94 * Format one of the entries for drawing on the screen.
95 *
96 * @param index index into files
97 * @return the line to draw
98 */
99 private String renderFile(int index) {
100 File file = files.get(index);
101 String name = file.getName();
102 if (name.length() > 20) {
103 name = name.substring(0, 17) + "...";
104 }
105 return String.format("%-20s %5dk", name, (file.length() / 1024));
106 }
107
108 /**
109 * Resize for a new width/height.
110 */
111 public void reflow() {
112
113 // Reset the lines
114 selectedFile = -1;
115 maxLineWidth = 0;
116 files.clear();
117
118 // Build a list of files in this directory
119 File [] newFiles = path.listFiles();
120 for (int i = 0; i < newFiles.length; i++) {
121 if (newFiles[i].getName().startsWith(".")) {
122 continue;
123 }
124 if (newFiles[i].isDirectory()) {
125 continue;
126 }
127 files.add(newFiles[i]);
128 }
129
130 for (int i = 0; i < files.size(); i++) {
131 String line = renderFile(i);
132 if (line.length() > maxLineWidth) {
133 maxLineWidth = line.length();
134 }
135 }
136
137 // Start at the top
138 if (vScroller == null) {
139 vScroller = new TVScroller(this, getWidth() - 1, 0,
140 getHeight() - 1);
141 } else {
142 vScroller.setX(getWidth() - 1);
143 vScroller.setHeight(getHeight() - 1);
144 }
145 vScroller.setBottomValue(files.size() - getHeight() - 1);
146 vScroller.setTopValue(0);
147 vScroller.setValue(0);
148 if (vScroller.getBottomValue() < 0) {
149 vScroller.setBottomValue(0);
150 }
151 vScroller.setBigChange(getHeight() - 1);
152
153 // Start at the left
154 if (hScroller == null) {
155 hScroller = new THScroller(this, 0, getHeight() - 1,
156 getWidth() - 1);
157 } else {
158 hScroller.setY(getHeight() - 1);
159 hScroller.setWidth(getWidth() - 1);
160 }
161 hScroller.setRightValue(maxLineWidth - getWidth() + 1);
162 hScroller.setLeftValue(0);
163 hScroller.setValue(0);
164 if (hScroller.getRightValue() < 0) {
165 hScroller.setRightValue(0);
166 }
167 hScroller.setBigChange(getWidth() - 1);
168 }
169
170 /**
171 * Public constructor.
172 *
173 * @param parent parent widget
174 * @param path directory path, must be a directory
175 * @param x column relative to parent
176 * @param y row relative to parent
177 * @param width width of text area
178 * @param height height of text area
179 */
180 public TDirectoryList(final TWidget parent, final String path, final int x,
181 final int y, final int width, final int height) {
182
183 this(parent, path, x, y, width, height, null);
184 }
185
186 /**
187 * Public constructor.
188 *
189 * @param parent parent widget
190 * @param path directory path, must be a directory
191 * @param x column relative to parent
192 * @param y row relative to parent
193 * @param width width of text area
194 * @param height height of text area
195 * @param action action to perform when an item is selected
196 */
197 public TDirectoryList(final TWidget parent, final String path, final int x,
198 final int y, final int width, final int height, final TAction action) {
199
200 this.path = new File(path);
201 this.action = action;
202 files = new ArrayList<File>();
203 reflow();
204 }
205
206 /**
207 * Draw the files list.
208 */
209 @Override
210 public void draw() {
211 CellAttributes color = null;
212 int begin = vScroller.getValue();
213 int topY = 0;
214 for (int i = begin; i < files.size() - 1; i++) {
215 String line = renderFile(i);
216 if (hScroller.getValue() < line.length()) {
217 line = line.substring(hScroller.getValue());
218 } else {
219 line = "";
220 }
221 if (i == selectedFile) {
222 color = getTheme().getColor("tdirectorylist.selected");
223 } else if (isAbsoluteActive()) {
224 color = getTheme().getColor("tdirectorylist");
225 } else {
226 color = getTheme().getColor("tdirectorylist.inactive");
227 }
228 String formatString = "%-" + Integer.toString(getWidth() - 1) + "s";
229 getScreen().putStringXY(0, topY, String.format(formatString, line),
230 color);
231 topY++;
232 if (topY >= getHeight() - 1) {
233 break;
234 }
235 }
236
237 // Pad the rest with blank lines
238 for (int i = topY; i < getHeight() - 1; i++) {
239 getScreen().hLineXY(0, i, getWidth() - 1, ' ', color);
240 }
241 }
242
243 /**
244 * Handle mouse press events.
245 *
246 * @param mouse mouse button press event
247 */
248 @Override
249 public void onMouseDown(final TMouseEvent mouse) {
250 if (mouse.isMouseWheelUp()) {
251 vScroller.decrement();
252 return;
253 }
254 if (mouse.isMouseWheelDown()) {
255 vScroller.increment();
256 return;
257 }
258
259 if ((mouse.getX() < getWidth() - 1)
260 && (mouse.getY() < getHeight() - 1)) {
261 if (vScroller.getValue() + mouse.getY() < files.size()) {
262 selectedFile = vScroller.getValue() + mouse.getY();
263 }
264 path = files.get(selectedFile);
265 dispatch();
266 return;
267 }
268
269 // Pass to children
270 super.onMouseDown(mouse);
271 }
272
273 /**
274 * Handle mouse release events.
275 *
276 * @param mouse mouse button release event
277 */
278 @Override
279 public void onMouseUp(final TMouseEvent mouse) {
280 // Pass to children
281 super.onMouseDown(mouse);
282 }
283
284 /**
285 * Handle keystrokes.
286 *
287 * @param keypress keystroke event
288 */
289 @Override
290 public void onKeypress(final TKeypressEvent keypress) {
291 if (keypress.equals(kbLeft)) {
292 hScroller.decrement();
293 } else if (keypress.equals(kbRight)) {
294 hScroller.increment();
295 } else if (keypress.equals(kbUp)) {
296 vScroller.decrement();
297 } else if (keypress.equals(kbDown)) {
298 vScroller.increment();
299 } else if (keypress.equals(kbPgUp)) {
300 vScroller.bigDecrement();
301 } else if (keypress.equals(kbPgDn)) {
302 vScroller.bigIncrement();
303 } else if (keypress.equals(kbHome)) {
304 vScroller.toTop();
305 } else if (keypress.equals(kbEnd)) {
306 vScroller.toBottom();
307 } else {
308 // Pass other keys (tab etc.) on
309 super.onKeypress(keypress);
310 }
311 }
312
313 }