2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2017 Kevin Lamonte
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
32 import java
.io
.IOException
;
33 import java
.util
.ResourceBundle
;
35 import jexer
.bits
.GraphicsChars
;
36 import jexer
.event
.TKeypressEvent
;
37 import static jexer
.TKeypress
.*;
40 * TFileOpenBox is a system-modal dialog for selecting a file to open. Call
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 ...
55 public final class TFileOpenBox
extends TWindow
{
60 private static final ResourceBundle i18n
= ResourceBundle
.getBundle(TFileOpenBox
.class.getName());
63 * TFileOpenBox can be called for either Open or Save actions.
67 * Button will be labeled "Open".
72 * Button will be labeled "Save".
78 * String to return, or null if the user canceled.
80 private String filename
= null;
83 * Get the return string.
85 * @return the filename the user selected, or null if they canceled.
87 public String
getFilename() {
92 * The left-side tree view pane.
94 private TTreeView treeView
;
97 * The data behind treeView.
99 private TDirectoryTreeItem treeViewRoot
;
102 * The right-side directory list pane.
104 private TDirectoryList directoryList
;
107 * The top row text field.
109 private TField entryField
;
112 * The Open or Save button.
114 private TButton openButton
;
117 * See if there is a valid filename to return. If the filename is a
120 * @param newFilename the filename to check and return
121 * @throws IOException of a java.io operation throws
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);
131 if (newFile
.isDirectory()) {
132 treeViewRoot
= new TDirectoryTreeItem(treeView
, newFilename
,
134 treeView
.setTreeRoot(treeViewRoot
, true);
135 treeView
.reflowData();
136 openButton
.setEnabled(false);
137 directoryList
.setPath(newFilename
);
143 * Public constructor. The file open box will be centered on screen.
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
150 public TFileOpenBox(final TApplication application
, final String path
,
151 final Type type
) throws IOException
{
153 // Register with the TApplication
154 super(application
, "", 0, 0, 76, 22, MODAL
);
157 entryField
= addField(1, 1, getWidth() - 4, false,
158 (new File(path
)).getCanonicalPath(),
162 checkFilename(entryField
.getText());
163 } catch (IOException e
) {
168 entryField
.onKeypress(new TKeypressEvent(kbEnd
));
170 // Add directory treeView
171 treeView
= addTreeView(1, 3, 30, getHeight() - 6,
174 TTreeItem item
= treeView
.getSelected();
175 File selectedDir
= ((TDirectoryTreeItem
) item
).getFile();
177 directoryList
.setPath(selectedDir
.getCanonicalPath());
178 openButton
.setEnabled(false);
179 activate(directoryList
);
180 } catch (IOException e
) {
186 treeViewRoot
= new TDirectoryTreeItem(treeView
, path
, true);
188 // Add directory files list
189 directoryList
= addDirectoryList(path
, 34, 3, 28, getHeight() - 6,
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
) {
205 String openLabel
= "";
208 openLabel
= i18n
.getString("openButton");
209 setTitle(i18n
.getString("openTitle"));
212 openLabel
= i18n
.getString("saveButton");
213 setTitle(i18n
.getString("saveTitle"));
216 throw new IllegalArgumentException("Invalid type: " + type
);
219 // Setup button actions
220 openButton
= addButton(openLabel
, this.getWidth() - 12, 3,
224 checkFilename(entryField
.getText());
225 } catch (IOException e
) {
231 openButton
.setEnabled(false);
233 addButton(i18n
.getString("cancelButton"), getWidth() - 12, 5,
237 getApplication().closeWindow(TFileOpenBox
.this);
242 // Default to the directory list
243 activate(directoryList
);
245 // Set the secondaryFiber to run me
246 getApplication().enableSecondaryEventReceiver(this);
248 // Yield to the secondary thread. When I come back from the
249 // constructor response will already be set.
250 getApplication().yield();
259 getScreen().vLineXY(33, 4, getHeight() - 6, GraphicsChars
.WINDOW_SIDE
,
266 * @param keypress keystroke event
269 public void onKeypress(final TKeypressEvent keypress
) {
270 // Escape - behave like cancel
271 if (keypress
.equals(kbEsc
)) {
274 getApplication().closeWindow(this);
279 super.onKeypress(keypress
);