Fix UTF8 bug, create first executable JAR file
[jvcard.git] / src / com / googlecode / lanterna / gui2 / dialogs / FileDialog.java
1 package com.googlecode.lanterna.gui2.dialogs;
2
3 import com.googlecode.lanterna.TerminalTextUtils;
4 import com.googlecode.lanterna.TerminalSize;
5 import com.googlecode.lanterna.gui2.*;
6
7 import java.io.File;
8 import java.util.Arrays;
9 import java.util.Comparator;
10
11 /**
12 * Dialog that allows the user to iterate the file system and pick file to open/save
13 *
14 * @author Martin
15 */
16 public class FileDialog extends DialogWindow {
17
18 private final ActionListBox fileListBox;
19 private final ActionListBox directoryListBox;
20 private final TextBox fileBox;
21 private final Button okButton;
22 private final boolean showHiddenFilesAndDirs;
23
24 private File directory;
25 private File selectedFile;
26
27 /**
28 * Default constructor for {@code FileDialog}
29 * @param title Title of the dialog
30 * @param description Description of the dialog, is displayed at the top of the content area
31 * @param actionLabel Label to use on the "confirm" button, for example "open" or "save"
32 * @param dialogSize Rough estimation of how big you want the dialog to be
33 * @param showHiddenFilesAndDirs If {@code true}, hidden files and directories will be visible
34 * @param selectedObject Initially selected file node
35 */
36 public FileDialog(
37 String title,
38 String description,
39 String actionLabel,
40 TerminalSize dialogSize,
41 boolean showHiddenFilesAndDirs,
42 File selectedObject) {
43 super(title);
44 this.selectedFile = null;
45 this.showHiddenFilesAndDirs = showHiddenFilesAndDirs;
46
47 if(selectedObject == null || !selectedObject.exists()) {
48 selectedObject = new File("").getAbsoluteFile();
49 }
50 selectedObject = selectedObject.getAbsoluteFile();
51
52 Panel contentPane = new Panel();
53 contentPane.setLayoutManager(new GridLayout(2));
54
55 if(description != null) {
56 new Label(description)
57 .setLayoutData(
58 GridLayout.createLayoutData(
59 GridLayout.Alignment.BEGINNING,
60 GridLayout.Alignment.CENTER,
61 false,
62 false,
63 2,
64 1))
65 .addTo(contentPane);
66 }
67
68 int unitWidth = dialogSize.getColumns() / 3;
69 int unitHeight = dialogSize.getRows();
70
71 new FileSystemLocationLabel()
72 .setLayoutData(GridLayout.createLayoutData(
73 GridLayout.Alignment.FILL,
74 GridLayout.Alignment.CENTER,
75 true,
76 false,
77 2,
78 1))
79 .addTo(contentPane);
80
81 fileListBox = new ActionListBox(new TerminalSize(unitWidth * 2, unitHeight));
82 fileListBox.withBorder(Borders.singleLine())
83 .setLayoutData(GridLayout.createLayoutData(
84 GridLayout.Alignment.BEGINNING,
85 GridLayout.Alignment.CENTER,
86 false,
87 false))
88 .addTo(contentPane);
89 directoryListBox = new ActionListBox(new TerminalSize(unitWidth, unitHeight));
90 directoryListBox.withBorder(Borders.singleLine())
91 .addTo(contentPane);
92
93 fileBox = new TextBox()
94 .setLayoutData(GridLayout.createLayoutData(
95 GridLayout.Alignment.FILL,
96 GridLayout.Alignment.CENTER,
97 true,
98 false,
99 2,
100 1))
101 .addTo(contentPane);
102
103 new Separator(Direction.HORIZONTAL)
104 .setLayoutData(
105 GridLayout.createLayoutData(
106 GridLayout.Alignment.FILL,
107 GridLayout.Alignment.CENTER,
108 true,
109 false,
110 2,
111 1))
112 .addTo(contentPane);
113
114 okButton = new Button(actionLabel, new OkHandler());
115 Panels.grid(2,
116 okButton,
117 new Button(LocalizedString.Cancel.toString(), new CancelHandler()))
118 .setLayoutData(GridLayout.createLayoutData(GridLayout.Alignment.END, GridLayout.Alignment.CENTER, false, false, 2, 1))
119 .addTo(contentPane);
120
121 if(selectedObject.isFile()) {
122 directory = selectedObject.getParentFile();
123 fileBox.setText(selectedObject.getName());
124 }
125 else if(selectedObject.isDirectory()) {
126 directory = selectedObject;
127 }
128
129 reloadViews(directory);
130 setComponent(contentPane);
131 }
132
133 /**
134 * {@inheritDoc}
135 * @param textGUI Text GUI to add the dialog to
136 * @return The file which was selected in the dialog or {@code null} if the dialog was cancelled
137 */
138 @Override
139 public File showDialog(WindowBasedTextGUI textGUI) {
140 selectedFile = null;
141 super.showDialog(textGUI);
142 return selectedFile;
143 }
144
145 private class OkHandler implements Runnable {
146 @Override
147 public void run() {
148 if(!fileBox.getText().isEmpty()) {
149 selectedFile = new File(directory, fileBox.getText());
150 close();
151 }
152 else {
153 MessageDialog.showMessageDialog(getTextGUI(), "Error", "Please select a valid file name", MessageDialogButton.OK);
154 }
155 }
156 }
157
158 private class CancelHandler implements Runnable {
159 @Override
160 public void run() {
161 selectedFile = null;
162 close();
163 }
164 }
165
166 private class DoNothing implements Runnable {
167 @Override
168 public void run() {
169 }
170 }
171
172 private void reloadViews(final File directory) {
173 directoryListBox.clearItems();
174 fileListBox.clearItems();
175 File []entries = directory.listFiles();
176 if(entries == null) {
177 return;
178 }
179 Arrays.sort(entries, new Comparator<File>() {
180 @Override
181 public int compare(File o1, File o2) {
182 return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase());
183 }
184 });
185 directoryListBox.addItem("..", new Runnable() {
186 @Override
187 public void run() {
188 FileDialog.this.directory = directory.getAbsoluteFile().getParentFile();
189 reloadViews(directory.getAbsoluteFile().getParentFile());
190 }
191 });
192 for(final File entry: entries) {
193 if(entry.isHidden() && !showHiddenFilesAndDirs) {
194 continue;
195 }
196 if(entry.isDirectory()) {
197 directoryListBox.addItem(entry.getName(), new Runnable() {
198 @Override
199 public void run() {
200 FileDialog.this.directory = entry;
201 reloadViews(entry);
202 }
203 });
204 }
205 else {
206 fileListBox.addItem(entry.getName(), new Runnable() {
207 @Override
208 public void run() {
209 fileBox.setText(entry.getName());
210 setFocusedInteractable(okButton);
211 }
212 });
213 }
214 }
215 if(fileListBox.isEmpty()) {
216 fileListBox.addItem("<empty>", new DoNothing());
217 }
218 }
219
220 private class FileSystemLocationLabel extends Label {
221 public FileSystemLocationLabel() {
222 super("");
223 setPreferredSize(TerminalSize.ONE);
224 }
225
226 @Override
227 public void onBeforeDrawing() {
228 TerminalSize area = getSize();
229 String absolutePath = directory.getAbsolutePath();
230 int absolutePathLengthInColumns = TerminalTextUtils.getColumnWidth(absolutePath);
231 if(area.getColumns() < absolutePathLengthInColumns) {
232 absolutePath = absolutePath.substring(absolutePathLengthInColumns - area.getColumns());
233 absolutePath = "..." + absolutePath.substring(Math.min(absolutePathLengthInColumns, 3));
234 }
235 setText(absolutePath);
236 }
237 }
238 }