1 | //============================================================================ |
2 | // |
3 | // SSSS tt lll lll |
4 | // SS SS tt ll ll |
5 | // SS tttttt eeee ll ll aaaa |
6 | // SSSS tt ee ee ll ll aa |
7 | // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" |
8 | // SS SS tt ee ll ll aa aa |
9 | // SSSS ttt eeeee llll llll aaaaa |
10 | // |
11 | // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony |
12 | // and the Stella Team |
13 | // |
14 | // See the file "License.txt" for information on usage and redistribution of |
15 | // this file, and for a DISCLAIMER OF ALL WARRANTIES. |
16 | //============================================================================ |
17 | |
18 | #include "bspf.hxx" |
19 | #include "Dialog.hxx" |
20 | #include "FSNode.hxx" |
21 | #include "GuiObject.hxx" |
22 | #include "OSystem.hxx" |
23 | #include "EditTextWidget.hxx" |
24 | #include "FileListWidget.hxx" |
25 | #include "Widget.hxx" |
26 | #include "Font.hxx" |
27 | #include "BrowserDialog.hxx" |
28 | |
29 | /* We want to use this as a general directory selector at some point... possible uses |
30 | * - to select the data dir for a game |
31 | * - to select the place where save games are stored |
32 | * - others??? |
33 | */ |
34 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
35 | BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, |
36 | int max_w, int max_h, const string& title) |
37 | : Dialog(boss->instance(), boss->parent(), font, title), |
38 | CommandSender(boss), |
39 | _cmd(0), |
40 | _mode(FileSave) |
41 | { |
42 | // Set real dimensions |
43 | _w = max_w; |
44 | _h = max_h; |
45 | |
46 | const int lineHeight = font.getLineHeight(), |
47 | buttonWidth = font.getStringWidth("Defaults" ) + 20, |
48 | buttonHeight = font.getLineHeight() + 4, |
49 | selectHeight = lineHeight + 12; |
50 | int xpos, ypos; |
51 | ButtonWidget* b; |
52 | |
53 | xpos = 10; ypos = 4 + _th; |
54 | |
55 | // Current path - TODO: handle long paths ? |
56 | StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos + 2, "Path " ); |
57 | _currentPath = new EditTextWidget(this, font, xpos + t->getWidth(), ypos, |
58 | _w - t->getWidth() - 2 * xpos, lineHeight); |
59 | _currentPath->setEditable(false); |
60 | // Add file list |
61 | ypos += lineHeight + 8; |
62 | _fileList = new FileListWidget(this, font, xpos, ypos, _w - 2 * xpos, |
63 | _h - selectHeight - buttonHeight - ypos - 20); |
64 | _fileList->setEditable(false); |
65 | addFocusWidget(_fileList); |
66 | |
67 | // Add currently selected item |
68 | ypos += _fileList->getHeight() + 8; |
69 | |
70 | _type = new StaticTextWidget(this, font, xpos, ypos + 2, "Name " ); |
71 | _selected = new EditTextWidget(this, font, xpos + _type->getWidth(), ypos, |
72 | _w - _type->getWidth() - 2 * xpos, lineHeight, "" ); |
73 | _selected->setEditable(false); |
74 | |
75 | // Buttons |
76 | _goUpButton = new ButtonWidget(this, font, 10, _h - buttonHeight - 10, |
77 | buttonWidth, buttonHeight, "Go up" , kGoUpCmd); |
78 | addFocusWidget(_goUpButton); |
79 | |
80 | _basedirButton = |
81 | new ButtonWidget(this, font, 15 + buttonWidth, _h - buttonHeight - 10, |
82 | buttonWidth, buttonHeight, "Base Dir" , kBaseDirCmd); |
83 | addFocusWidget(_basedirButton); |
84 | |
85 | #ifndef BSPF_MACOS |
86 | b = new ButtonWidget(this, font, _w - 2 * (buttonWidth + 7), _h - buttonHeight - 10, |
87 | buttonWidth, buttonHeight, "Choose" , kChooseCmd); |
88 | addFocusWidget(b); |
89 | addOKWidget(b); |
90 | b = new ButtonWidget(this, font, _w - (buttonWidth + 10), _h - buttonHeight - 10, |
91 | buttonWidth, buttonHeight, "Cancel" , GuiObject::kCloseCmd); |
92 | addFocusWidget(b); |
93 | addCancelWidget(b); |
94 | #else |
95 | b = new ButtonWidget(this, font, _w - 2 * (buttonWidth + 7), _h - buttonHeight - 10, |
96 | buttonWidth, buttonHeight, "Cancel" , GuiObject::kCloseCmd); |
97 | addFocusWidget(b); |
98 | addCancelWidget(b); |
99 | b = new ButtonWidget(this, font, _w - (buttonWidth + 10), _h - buttonHeight - 10, |
100 | buttonWidth, buttonHeight, "Choose" , kChooseCmd); |
101 | addFocusWidget(b); |
102 | addOKWidget(b); |
103 | #endif |
104 | } |
105 | |
106 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
107 | void BrowserDialog::show(const string& startpath, |
108 | BrowserDialog::ListMode mode, int cmd, |
109 | const string& ext) |
110 | { |
111 | _cmd = cmd; |
112 | _mode = mode; |
113 | |
114 | switch(_mode) |
115 | { |
116 | case FileLoad: |
117 | _fileList->setListMode(FilesystemNode::ListMode::All); |
118 | _fileList->setNameFilter([&ext](const FilesystemNode& node) { |
119 | return BSPF::endsWithIgnoreCase(node.getName(), ext); |
120 | }); |
121 | _selected->setEditable(false); |
122 | _selected->clearFlags(Widget::FLAG_INVISIBLE); |
123 | _type->clearFlags(Widget::FLAG_INVISIBLE); |
124 | break; |
125 | |
126 | case FileSave: |
127 | _fileList->setListMode(FilesystemNode::ListMode::All); |
128 | _fileList->setNameFilter([&ext](const FilesystemNode& node) { |
129 | return BSPF::endsWithIgnoreCase(node.getName(), ext); |
130 | }); |
131 | _selected->setEditable(false); // FIXME - disable user input for now |
132 | _selected->clearFlags(Widget::FLAG_INVISIBLE); |
133 | _type->clearFlags(Widget::FLAG_INVISIBLE); |
134 | break; |
135 | |
136 | case Directories: |
137 | _fileList->setListMode(FilesystemNode::ListMode::DirectoriesOnly); |
138 | _fileList->setNameFilter([](const FilesystemNode&) { return true; }); |
139 | _selected->setEditable(false); |
140 | _selected->setFlags(Widget::FLAG_INVISIBLE); |
141 | _type->setFlags(Widget::FLAG_INVISIBLE); |
142 | break; |
143 | } |
144 | |
145 | // Set start path |
146 | _fileList->setDirectory(FilesystemNode(startpath)); |
147 | |
148 | updateUI(); |
149 | |
150 | // Finally, open the dialog after it has been fully updated |
151 | open(); |
152 | } |
153 | |
154 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
155 | const FilesystemNode& BrowserDialog::getResult() const |
156 | { |
157 | if(_mode == FileLoad || _mode == FileSave) |
158 | return _fileList->selected(); |
159 | else |
160 | return _fileList->currentDir(); |
161 | } |
162 | |
163 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
164 | void BrowserDialog::updateUI() |
165 | { |
166 | // Only hilite the 'up' button if there's a parent directory |
167 | _goUpButton->setEnabled(_fileList->currentDir().hasParent()); |
168 | |
169 | // Update the path display |
170 | _currentPath->setText(_fileList->currentDir().getShortPath()); |
171 | |
172 | // Enable/disable OK button based on current mode |
173 | bool enable = _mode == Directories || !_fileList->selected().isDirectory(); |
174 | _okWidget->setEnabled(enable); |
175 | |
176 | if(!_fileList->selected().isDirectory()) |
177 | _selected->setText(_fileList->getSelectedString()); |
178 | else |
179 | _selected->setText("" ); |
180 | } |
181 | |
182 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
183 | void BrowserDialog::handleCommand(CommandSender* sender, int cmd, |
184 | int data, int id) |
185 | { |
186 | switch (cmd) |
187 | { |
188 | case kChooseCmd: |
189 | case FileListWidget::ItemActivated: |
190 | // Send a signal to the calling class that a selection has been made |
191 | // Since we aren't derived from a widget, we don't have a 'data' or 'id' |
192 | if(_cmd) sendCommand(_cmd, -1, -1); |
193 | close(); |
194 | break; |
195 | |
196 | case kGoUpCmd: |
197 | _fileList->selectParent(); |
198 | break; |
199 | |
200 | case kBaseDirCmd: |
201 | _fileList->setDirectory(FilesystemNode(instance().baseDir())); |
202 | break; |
203 | |
204 | case FileListWidget::ItemChanged: |
205 | updateUI(); |
206 | break; |
207 | |
208 | default: |
209 | Dialog::handleCommand(sender, cmd, data, 0); |
210 | break; |
211 | } |
212 | } |
213 | |