F10 now wired into custom code
[fanfix.git] / src / be / nikiroo / fanfix / reader / tui / TuiReaderApplication.java
1 package be.nikiroo.fanfix.reader.tui;
2
3 import java.awt.Toolkit;
4 import java.awt.datatransfer.DataFlavor;
5 import java.io.IOException;
6 import java.net.URL;
7
8 import jexer.TApplication;
9 import jexer.TCommand;
10 import jexer.TKeypress;
11 import jexer.TMessageBox;
12 import jexer.TStatusBar;
13 import jexer.TWidget;
14 import jexer.TWindow;
15 import jexer.event.TMenuEvent;
16 import jexer.menu.TMenu;
17 import be.nikiroo.fanfix.Instance;
18 import be.nikiroo.fanfix.data.MetaData;
19 import be.nikiroo.fanfix.data.Story;
20 import be.nikiroo.fanfix.library.BasicLibrary;
21 import be.nikiroo.fanfix.reader.BasicReader;
22 import be.nikiroo.fanfix.reader.Reader;
23 import be.nikiroo.utils.Progress;
24
25 /**
26 * Manages the TUI general mode and links and manages the {@link TWindow}s.
27 * <p>
28 * It will also enclose a {@link Reader} and simply handle the reading part
29 * differently (it will create the required sub-windows and display them).
30 *
31 * @author niki
32 */
33 class TuiReaderApplication extends TApplication implements Reader {
34 public static final int MENU_OPEN = 1025;
35 public static final int MENU_IMPORT_URL = 1026;
36 public static final int MENU_IMPORT_FILE = 1027;
37 public static final int MENU_EXPORT = 1028;
38 public static final int MENU_LIBRARY = 1029;
39 public static final int MENU_EXIT = 1030;
40
41 public static final TCommand CMD_EXIT = new TCommand(MENU_EXIT) {
42 };
43
44 private Reader reader;
45 private TuiReaderMainWindow main;
46
47 private MetaData meta;
48 private String source;
49 private boolean useMeta;
50
51 // start reading if meta present
52 public TuiReaderApplication(Reader reader, BackendType backend)
53 throws Exception {
54 super(backend);
55 init(reader);
56
57 showMain(getMeta(), null, true);
58 }
59
60 public TuiReaderApplication(Reader reader, String source,
61 TApplication.BackendType backend) throws Exception {
62 super(backend);
63 init(reader);
64
65 showMain(null, source, false);
66 }
67
68 @Override
69 public void read() throws IOException {
70 MetaData meta = getMeta();
71
72 if (meta == null) {
73 throw new IOException("No story to read");
74 }
75
76 // TODO: open in editor + external option
77 if (!meta.isImageDocument()) {
78 TWindow window = new TuiReaderStoryWindow(this, getLibrary(), meta,
79 getChapter());
80 window.maximize();
81 } else {
82 try {
83 openExternal(getLibrary(), meta.getLuid());
84 } catch (IOException e) {
85 messageBox("Error when trying to open the story",
86 e.getMessage(), TMessageBox.Type.OK);
87 }
88 }
89 }
90
91 @Override
92 public MetaData getMeta() {
93 return reader.getMeta();
94 }
95
96 @Override
97 public Story getStory(Progress pg) {
98 return reader.getStory(pg);
99 }
100
101 @Override
102 public BasicLibrary getLibrary() {
103 return reader.getLibrary();
104 }
105
106 @Override
107 public void setLibrary(BasicLibrary lib) {
108 reader.setLibrary(lib);
109 }
110
111 @Override
112 public void setMeta(MetaData meta) throws IOException {
113 reader.setMeta(meta);
114 }
115
116 @Override
117 public void setMeta(String luid) throws IOException {
118 reader.setMeta(luid);
119 }
120
121 @Override
122 public void setMeta(URL source, Progress pg) throws IOException {
123 reader.setMeta(source, pg);
124 }
125
126 @Override
127 public void browse(String source) {
128 reader.browse(source);
129 }
130
131 @Override
132 public int getChapter() {
133 return reader.getChapter();
134 }
135
136 @Override
137 public void setChapter(int chapter) {
138 reader.setChapter(chapter);
139 }
140
141 /**
142 * Set the default status bar when this window appear.
143 * <p>
144 * Some shortcuts are always visible, and will be put here.
145 * <p>
146 * Note that shortcuts placed this way on menu won't work unless the menu
147 * also implement them.
148 *
149 * @param window
150 * the new window or menu on screen
151 * @param description
152 * the description to show on the status ba
153 */
154 public TStatusBar setStatusBar(TWindow window, String description) {
155 TStatusBar statusBar = window.newStatusBar(description);
156 statusBar.addShortcutKeypress(TKeypress.kbF10, CMD_EXIT, "Exit");
157 return statusBar;
158
159 }
160
161 private void showMain(MetaData meta, String source, boolean useMeta)
162 throws IOException {
163 // TODO: thread-safety
164 this.meta = meta;
165 this.source = source;
166 this.useMeta = useMeta;
167
168 if (main != null && main.isVisible()) {
169 main.activate();
170 } else {
171 if (main != null) {
172 main.close();
173 }
174 main = new TuiReaderMainWindow(this);
175 if (useMeta) {
176 main.setMeta(meta);
177 if (meta != null) {
178 read();
179 }
180 } else {
181 main.setSource(source);
182 }
183 }
184 }
185
186 private void init(Reader reader) {
187 this.reader = reader;
188
189 // TODO: traces/errors?
190 Instance.setTraceHandler(null);
191
192 // Add the menus TODO: i18n
193 TMenu fileMenu = addMenu("&File");
194 fileMenu.addItem(MENU_OPEN, "&Open");
195 fileMenu.addItem(MENU_EXPORT, "&Save as...");
196 // TODO: Move to...
197 fileMenu.addSeparator();
198 fileMenu.addItem(MENU_IMPORT_URL, "Import &URL...");
199 fileMenu.addItem(MENU_IMPORT_FILE, "Import &file...");
200 fileMenu.addSeparator();
201 fileMenu.addItem(MENU_LIBRARY, "Lib&rary");
202 fileMenu.addSeparator();
203 fileMenu.addItem(MENU_EXIT, "E&xit");
204
205 setStatusBar(fileMenu, "File-management "
206 + "commands (Open, Save, Print, etc.)");
207
208 // TODO: Edit: re-download, delete
209
210 //
211
212 addWindowMenu();
213
214 getBackend().setTitle("Fanfix");
215 }
216
217 @Override
218 protected boolean onMenu(TMenuEvent menu) {
219 // TODO: i18n
220 switch (menu.getId()) {
221 case MENU_EXIT:
222 close(this);
223 return true;
224 case MENU_IMPORT_URL:
225 String clipboard = "";
226 try {
227 clipboard = ("" + Toolkit.getDefaultToolkit()
228 .getSystemClipboard().getData(DataFlavor.stringFlavor))
229 .trim();
230 } catch (Exception e) {
231 // No data will be handled
232 }
233
234 if (clipboard == null || !clipboard.startsWith("http")) {
235 clipboard = "";
236 }
237
238 String url = inputBox("Import story", "URL to import", clipboard)
239 .getText();
240
241 if (!imprt(url)) {
242 // TODO: bad import
243 }
244
245 return true;
246 case MENU_IMPORT_FILE:
247 try {
248 String filename = fileOpenBox(".");
249 if (!imprt(filename)) {
250 // TODO: bad import
251 }
252 } catch (IOException e) {
253 // TODO: bad file
254 e.printStackTrace();
255 }
256
257 return true;
258 case MENU_LIBRARY:
259 try {
260 showMain(meta, source, useMeta);
261 } catch (IOException e) {
262 e.printStackTrace();
263 }
264
265 return true;
266 }
267
268 return super.onMenu(menu);
269 }
270
271 private boolean imprt(String url) {
272 try {
273 reader.getLibrary().imprt(BasicReader.getUrl(url), null);
274 main.refreshStories();
275 return true;
276 } catch (IOException e) {
277 return false;
278 }
279 }
280
281 @Override
282 public void openExternal(BasicLibrary lib, String luid) throws IOException {
283 reader.openExternal(lib, luid);
284 }
285
286 /**
287 * Ask the user and, if confirmed, close the {@link TApplication} this
288 * {@link TWidget} is running on.
289 * <p>
290 * This should result in the program terminating.
291 *
292 * @param widget
293 * the {@link TWidget}
294 */
295 static public void close(TWidget widget) {
296 close(widget.getApplication());
297 }
298
299 /**
300 * Ask the user and, if confirmed, close the {@link TApplication}.
301 * <p>
302 * This should result in the program terminating.
303 *
304 * @param app
305 * the {@link TApplication}
306 */
307 static void close(TApplication app) {
308 // TODO: i18n
309 if (app.messageBox("Confirmation", "(TODO: i18n) Exit application?",
310 TMessageBox.Type.YESNO).getResult() == TMessageBox.Result.YES) {
311 app.exit();
312 }
313 }
314 }