wip
[fanfix.git] / src / be / nikiroo / fanfix / reader / tui / TuiReaderApplication.java
CommitLineData
16a81ef7 1package be.nikiroo.fanfix.reader.tui;
c1873e56 2
e2d017a3
NR
3import java.awt.Toolkit;
4import java.awt.datatransfer.DataFlavor;
c1873e56 5import java.io.IOException;
6322ab64 6import java.net.URL;
c1873e56
NR
7
8import jexer.TApplication;
e2d017a3
NR
9import jexer.TCommand;
10import jexer.TKeypress;
c1873e56 11import jexer.TMessageBox;
e2d017a3 12import jexer.TStatusBar;
cf9c5ed1 13import jexer.TWidget;
6322ab64 14import jexer.TWindow;
e2d017a3
NR
15import jexer.event.TMenuEvent;
16import jexer.menu.TMenu;
a8209dd0 17import be.nikiroo.fanfix.Instance;
c1873e56 18import be.nikiroo.fanfix.data.MetaData;
6322ab64
NR
19import be.nikiroo.fanfix.data.Story;
20import be.nikiroo.fanfix.library.BasicLibrary;
16a81ef7
NR
21import be.nikiroo.fanfix.reader.BasicReader;
22import be.nikiroo.fanfix.reader.Reader;
6322ab64 23import be.nikiroo.utils.Progress;
c1873e56 24
6322ab64 25/**
bc2ea776
NR
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).
6322ab64
NR
30 *
31 * @author niki
32 */
33class TuiReaderApplication extends TApplication implements Reader {
e2d017a3
NR
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;
4f66bfa8
NR
38 public static final int MENU_LIBRARY = 1029;
39 public static final int MENU_EXIT = 1030;
e2d017a3 40
cf9c5ed1
NR
41 public static final TCommand CMD_EXIT = new TCommand(MENU_EXIT) {
42 };
43
6322ab64 44 private Reader reader;
e2d017a3 45 private TuiReaderMainWindow main;
c1873e56 46
4f66bfa8
NR
47 private MetaData meta;
48 private String source;
49 private boolean useMeta;
50
bc2ea776
NR
51 // start reading if meta present
52 public TuiReaderApplication(Reader reader, BackendType backend)
53 throws Exception {
54 super(backend);
55 init(reader);
c1873e56 56
5b00c122 57 showMain(getMeta(), null, true);
6322ab64
NR
58 }
59
e2d017a3 60 public TuiReaderApplication(Reader reader, String source,
bc2ea776 61 TApplication.BackendType backend) throws Exception {
c1873e56 62 super(backend);
bc2ea776 63 init(reader);
c1873e56 64
4f66bfa8
NR
65 showMain(null, source, false);
66 }
67
211f7ddb 68 @Override
6322ab64 69 public void read() throws IOException {
bc2ea776 70 MetaData meta = getMeta();
c1873e56 71
bc2ea776
NR
72 if (meta == null) {
73 throw new IOException("No story to read");
74 }
6322ab64 75
c1873e56 76 // TODO: open in editor + external option
b0e88ebd 77 if (!meta.isImageDocument()) {
cf9c5ed1 78 TWindow window = new TuiReaderStoryWindow(this, getLibrary(), meta,
e2d017a3 79 getChapter());
cf9c5ed1 80 window.maximize();
b0e88ebd
NR
81 } else {
82 try {
16a81ef7 83 openExternal(getLibrary(), meta.getLuid());
b0e88ebd 84 } catch (IOException e) {
c1873e56 85 messageBox("Error when trying to open the story",
b0e88ebd 86 e.getMessage(), TMessageBox.Type.OK);
c1873e56 87 }
c1873e56
NR
88 }
89 }
6322ab64 90
211f7ddb 91 @Override
bc2ea776
NR
92 public MetaData getMeta() {
93 return reader.getMeta();
94 }
95
211f7ddb 96 @Override
bc2ea776
NR
97 public Story getStory(Progress pg) {
98 return reader.getStory(pg);
6322ab64
NR
99 }
100
211f7ddb 101 @Override
6322ab64
NR
102 public BasicLibrary getLibrary() {
103 return reader.getLibrary();
104 }
105
211f7ddb 106 @Override
bc2ea776 107 public void setLibrary(BasicLibrary lib) {
6322ab64
NR
108 reader.setLibrary(lib);
109 }
110
211f7ddb 111 @Override
bc2ea776
NR
112 public void setMeta(MetaData meta) throws IOException {
113 reader.setMeta(meta);
114 }
115
211f7ddb 116 @Override
bc2ea776
NR
117 public void setMeta(String luid) throws IOException {
118 reader.setMeta(luid);
6322ab64
NR
119 }
120
211f7ddb 121 @Override
bc2ea776
NR
122 public void setMeta(URL source, Progress pg) throws IOException {
123 reader.setMeta(source, pg);
6322ab64
NR
124 }
125
211f7ddb 126 @Override
6322ab64
NR
127 public void browse(String source) {
128 reader.browse(source);
129 }
bc2ea776 130
211f7ddb 131 @Override
bc2ea776
NR
132 public int getChapter() {
133 return reader.getChapter();
134 }
135
211f7ddb 136 @Override
bc2ea776
NR
137 public void setChapter(int chapter) {
138 reader.setChapter(chapter);
139 }
140
5b00c122
NR
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);
cf9c5ed1 156 statusBar.addShortcutKeypress(TKeypress.kbF10, CMD_EXIT, "Exit");
5b00c122
NR
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 }
11758a0f 183 main.maximize();
5b00c122
NR
184 }
185 }
186
bc2ea776
NR
187 private void init(Reader reader) {
188 this.reader = reader;
189
581d42c0
NR
190 // TODO: traces/errors?
191 Instance.setTraceHandler(null);
a8209dd0 192
e2d017a3
NR
193 // Add the menus TODO: i18n
194 TMenu fileMenu = addMenu("&File");
195 fileMenu.addItem(MENU_OPEN, "&Open");
196 fileMenu.addItem(MENU_EXPORT, "&Save as...");
197 // TODO: Move to...
198 fileMenu.addSeparator();
199 fileMenu.addItem(MENU_IMPORT_URL, "Import &URL...");
200 fileMenu.addItem(MENU_IMPORT_FILE, "Import &file...");
201 fileMenu.addSeparator();
4f66bfa8
NR
202 fileMenu.addItem(MENU_LIBRARY, "Lib&rary");
203 fileMenu.addSeparator();
e2d017a3
NR
204 fileMenu.addItem(MENU_EXIT, "E&xit");
205
5b00c122 206 setStatusBar(fileMenu, "File-management "
e2d017a3 207 + "commands (Open, Save, Print, etc.)");
e2d017a3
NR
208
209 // TODO: Edit: re-download, delete
210
211 //
212
bc2ea776 213 addWindowMenu();
bc2ea776
NR
214
215 getBackend().setTitle("Fanfix");
216 }
e2d017a3
NR
217
218 @Override
219 protected boolean onMenu(TMenuEvent menu) {
220 // TODO: i18n
221 switch (menu.getId()) {
222 case MENU_EXIT:
cf9c5ed1 223 close(this);
e2d017a3
NR
224 return true;
225 case MENU_IMPORT_URL:
226 String clipboard = "";
227 try {
228 clipboard = ("" + Toolkit.getDefaultToolkit()
229 .getSystemClipboard().getData(DataFlavor.stringFlavor))
230 .trim();
231 } catch (Exception e) {
232 // No data will be handled
233 }
234
235 if (clipboard == null || !clipboard.startsWith("http")) {
236 clipboard = "";
237 }
238
239 String url = inputBox("Import story", "URL to import", clipboard)
240 .getText();
241
242 if (!imprt(url)) {
243 // TODO: bad import
244 }
245
246 return true;
247 case MENU_IMPORT_FILE:
248 try {
249 String filename = fileOpenBox(".");
250 if (!imprt(filename)) {
251 // TODO: bad import
252 }
253 } catch (IOException e) {
254 // TODO: bad file
255 e.printStackTrace();
256 }
257
4f66bfa8
NR
258 return true;
259 case MENU_LIBRARY:
260 try {
261 showMain(meta, source, useMeta);
262 } catch (IOException e) {
263 e.printStackTrace();
264 }
265
e2d017a3
NR
266 return true;
267 }
268
269 return super.onMenu(menu);
270 }
271
272 private boolean imprt(String url) {
273 try {
274 reader.getLibrary().imprt(BasicReader.getUrl(url), null);
275 main.refreshStories();
276 return true;
277 } catch (IOException e) {
278 return false;
279 }
280 }
16a81ef7
NR
281
282 @Override
283 public void openExternal(BasicLibrary lib, String luid) throws IOException {
284 reader.openExternal(lib, luid);
285 }
cf9c5ed1
NR
286
287 /**
288 * Ask the user and, if confirmed, close the {@link TApplication} this
289 * {@link TWidget} is running on.
290 * <p>
291 * This should result in the program terminating.
292 *
293 * @param widget
294 * the {@link TWidget}
295 */
296 static public void close(TWidget widget) {
297 close(widget.getApplication());
298 }
299
300 /**
301 * Ask the user and, if confirmed, close the {@link TApplication}.
302 * <p>
303 * This should result in the program terminating.
304 *
305 * @param app
306 * the {@link TApplication}
307 */
308 static void close(TApplication app) {
309 // TODO: i18n
310 if (app.messageBox("Confirmation", "(TODO: i18n) Exit application?",
311 TMessageBox.Type.YESNO).getResult() == TMessageBox.Result.YES) {
312 app.exit();
313 }
314 }
c1873e56 315}