Localize strings
[fanfix.git] / src / jexer / TFileOpenBox.java
1 /*
2 * Jexer - Java Text User Interface
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (C) 2017 Kevin Lamonte
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29 package jexer;
30
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.ResourceBundle;
34
35 import jexer.bits.GraphicsChars;
36 import jexer.event.TKeypressEvent;
37 import static jexer.TKeypress.*;
38
39 /**
40 * TFileOpenBox is a system-modal dialog for selecting a file to open. Call
41 * it like:
42 *
43 * <p>
44 * <pre>
45 * {@code
46 * filename = application.fileOpenBox("/path/to/file.ext",
47 * TFileOpenBox.Type.OPEN);
48 * if (filename != null) {
49 * ... the user selected a file, go open it ...
50 * }
51 * }
52 * </pre>
53 *
54 */
55 public final class TFileOpenBox extends TWindow {
56
57 /**
58 * Translated strings.
59 */
60 private static final ResourceBundle i18n = ResourceBundle.getBundle(TFileOpenBox.class.getName());
61
62 /**
63 * TFileOpenBox can be called for either Open or Save actions.
64 */
65 public enum Type {
66 /**
67 * Button will be labeled "Open".
68 */
69 OPEN,
70
71 /**
72 * Button will be labeled "Save".
73 */
74 SAVE
75 }
76
77 /**
78 * String to return, or null if the user canceled.
79 */
80 private String filename = null;
81
82 /**
83 * Get the return string.
84 *
85 * @return the filename the user selected, or null if they canceled.
86 */
87 public String getFilename() {
88 return filename;
89 }
90
91 /**
92 * The left-side tree view pane.
93 */
94 private TTreeView treeView;
95
96 /**
97 * The data behind treeView.
98 */
99 private TDirectoryTreeItem treeViewRoot;
100
101 /**
102 * The right-side directory list pane.
103 */
104 private TDirectoryList directoryList;
105
106 /**
107 * The top row text field.
108 */
109 private TField entryField;
110
111 /**
112 * The Open or Save button.
113 */
114 private TButton openButton;
115
116 /**
117 * See if there is a valid filename to return. If the filename is a
118 * directory, then
119 *
120 * @param newFilename the filename to check and return
121 * @throws IOException of a java.io operation throws
122 */
123 private void checkFilename(final String newFilename) throws IOException {
124 File newFile = new File(newFilename);
125 if (newFile.exists()) {
126 if (newFile.isFile()) {
127 filename = newFilename;
128 getApplication().closeWindow(this);
129 return;
130 }
131 if (newFile.isDirectory()) {
132 treeViewRoot = new TDirectoryTreeItem(treeView, newFilename,
133 true);
134 treeView.setTreeRoot(treeViewRoot, true);
135 treeView.reflowData();
136 openButton.setEnabled(false);
137 directoryList.setPath(newFilename);
138 }
139 }
140 }
141
142 /**
143 * Public constructor. The file open box will be centered on screen.
144 *
145 * @param application the TApplication that manages this window
146 * @param path path of selected file
147 * @param type one of the Type constants
148 * @throws IOException of a java.io operation throws
149 */
150 public TFileOpenBox(final TApplication application, final String path,
151 final Type type) throws IOException {
152
153 // Register with the TApplication
154 super(application, "", 0, 0, 76, 22, MODAL);
155
156 // Add text field
157 entryField = addField(1, 1, getWidth() - 4, false,
158 (new File(path)).getCanonicalPath(),
159 new TAction() {
160 public void DO() {
161 try {
162 checkFilename(entryField.getText());
163 } catch (IOException e) {
164 e.printStackTrace();
165 }
166 }
167 }, null);
168 entryField.onKeypress(new TKeypressEvent(kbEnd));
169
170 // Add directory treeView
171 treeView = addTreeView(1, 3, 30, getHeight() - 6,
172 new TAction() {
173 public void DO() {
174 TTreeItem item = treeView.getSelected();
175 File selectedDir = ((TDirectoryTreeItem) item).getFile();
176 try {
177 directoryList.setPath(selectedDir.getCanonicalPath());
178 openButton.setEnabled(false);
179 activate(directoryList);
180 } catch (IOException e) {
181 e.printStackTrace();
182 }
183 }
184 }
185 );
186 treeViewRoot = new TDirectoryTreeItem(treeView, path, true);
187
188 // Add directory files list
189 directoryList = addDirectoryList(path, 34, 3, 28, getHeight() - 6,
190 new TAction() {
191 public void DO() {
192 try {
193 File newPath = directoryList.getPath();
194 entryField.setText(newPath.getCanonicalPath());
195 entryField.onKeypress(new TKeypressEvent(kbEnd));
196 openButton.setEnabled(true);
197 activate(entryField);
198 } catch (IOException e) {
199 e.printStackTrace();
200 }
201 }
202 }
203 );
204
205 String openLabel = "";
206 switch (type) {
207 case OPEN:
208 openLabel = i18n.getString("openButton");
209 setTitle(i18n.getString("openTitle"));
210 break;
211 case SAVE:
212 openLabel = i18n.getString("saveButton");
213 setTitle(i18n.getString("saveTitle"));
214 break;
215 default:
216 throw new IllegalArgumentException("Invalid type: " + type);
217 }
218
219 // Setup button actions
220 openButton = addButton(openLabel, this.getWidth() - 12, 3,
221 new TAction() {
222 public void DO() {
223 try {
224 checkFilename(entryField.getText());
225 } catch (IOException e) {
226 e.printStackTrace();
227 }
228 }
229 }
230 );
231 openButton.setEnabled(false);
232
233 addButton(i18n.getString("cancelButton"), getWidth() - 12, 5,
234 new TAction() {
235 public void DO() {
236 filename = null;
237 getApplication().closeWindow(TFileOpenBox.this);
238 }
239 }
240 );
241
242 // Default to the directory list
243 activate(directoryList);
244
245 // Set the secondaryFiber to run me
246 getApplication().enableSecondaryEventReceiver(this);
247
248 // Yield to the secondary thread. When I come back from the
249 // constructor response will already be set.
250 getApplication().yield();
251 }
252
253 /**
254 * Draw me on screen.
255 */
256 @Override
257 public void draw() {
258 super.draw();
259 getScreen().vLineXY(33, 4, getHeight() - 6, GraphicsChars.WINDOW_SIDE,
260 getBackground());
261 }
262
263 /**
264 * Handle keystrokes.
265 *
266 * @param keypress keystroke event
267 */
268 @Override
269 public void onKeypress(final TKeypressEvent keypress) {
270 // Escape - behave like cancel
271 if (keypress.equals(kbEsc)) {
272 // Close window
273 filename = null;
274 getApplication().closeWindow(this);
275 return;
276 }
277
278 // Pass to my parent
279 super.onKeypress(keypress);
280 }
281
282 }