X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2Freader%2Ftui%2FTuiReaderApplication.java;h=177c12ab867094cbd61292d88314662a569b0ecc;hb=91b82a5cbd8a9c90798d1bd49bfa9a061e652a6a;hp=b7109ab8d6ae55fba0e225d0604c1a6a139f89e8;hpb=fdc55375d1439a3d70159b8bcb0d433c74d96200;p=fanfix.git diff --git a/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java b/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java index b7109ab..177c12a 100644 --- a/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java +++ b/src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java @@ -4,13 +4,18 @@ import java.awt.Toolkit; import java.awt.datatransfer.DataFlavor; import java.io.IOException; import java.net.URL; +import java.net.UnknownHostException; import jexer.TApplication; import jexer.TCommand; import jexer.TKeypress; import jexer.TMessageBox; +import jexer.TMessageBox.Result; +import jexer.TMessageBox.Type; import jexer.TStatusBar; +import jexer.TWidget; import jexer.TWindow; +import jexer.event.TCommandEvent; import jexer.event.TMenuEvent; import jexer.menu.TMenu; import be.nikiroo.fanfix.Instance; @@ -19,6 +24,8 @@ import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.library.BasicLibrary; import be.nikiroo.fanfix.reader.BasicReader; import be.nikiroo.fanfix.reader.Reader; +import be.nikiroo.fanfix.reader.tui.TuiReaderMainWindow.Mode; +import be.nikiroo.fanfix.supported.SupportType; import be.nikiroo.utils.Progress; /** @@ -34,7 +41,12 @@ class TuiReaderApplication extends TApplication implements Reader { public static final int MENU_IMPORT_URL = 1026; public static final int MENU_IMPORT_FILE = 1027; public static final int MENU_EXPORT = 1028; - public static final int MENU_EXIT = 1029; + public static final int MENU_DELETE = 1029; + public static final int MENU_LIBRARY = 1030; + public static final int MENU_EXIT = 1031; + + public static final TCommand CMD_EXIT = new TCommand(MENU_EXIT) { + }; private Reader reader; private TuiReaderMainWindow main; @@ -45,12 +57,8 @@ class TuiReaderApplication extends TApplication implements Reader { super(backend); init(reader); - MetaData meta = getMeta(); - - main = new TuiReaderMainWindow(this); - main.setMeta(meta); - if (meta != null) { - read(); + if (getMeta() != null) { + read(false); } } @@ -59,31 +67,13 @@ class TuiReaderApplication extends TApplication implements Reader { super(backend); init(reader); - main = new TuiReaderMainWindow(this); - main.setSource(source); + showMain(); + main.setMode(Mode.SOURCE, source); } @Override - public void read() throws IOException { - MetaData meta = getMeta(); - - if (meta == null) { - throw new IOException("No story to read"); - } - - // TODO: open in editor + external option - if (!meta.isImageDocument()) { - @SuppressWarnings("unused") - Object discard = new TuiReaderStoryWindow(this, getLibrary(), meta, - getChapter()); - } else { - try { - openExternal(getLibrary(), meta.getLuid()); - } catch (IOException e) { - messageBox("Error when trying to open the story", - e.getMessage(), TMessageBox.Type.OK); - } - } + public void read(boolean sync) throws IOException { + read(getStory(null), sync); } @Override @@ -135,6 +125,80 @@ class TuiReaderApplication extends TApplication implements Reader { public void setChapter(int chapter) { reader.setChapter(chapter); } + + @Override + public void search(SupportType searchOn, String keywords, int page, int item) { + reader.search(searchOn, keywords, page,item); + } + + @Override + public void searchTag(SupportType searchOn, int page, int item, String... tags) { + reader.searchTag(searchOn, page, item, tags); + } + + /** + * Open the given {@link Story} for reading. This may or may not start an + * external program to read said {@link Story}. + * + * @param story + * the {@link Story} to read + * @param sync + * execute the process synchronously (wait until it is terminated + * before returning) + * + * @throws IOException + * in case of I/O errors + */ + public void read(Story story, boolean sync) throws IOException { + if (story == null) { + throw new IOException("No story to read"); + } + + // TODO: open in editor + external option + if (!story.getMeta().isImageDocument()) { + TWindow window = new TuiReaderStoryWindow(this, story, getChapter()); + window.maximize(); + } else { + try { + openExternal(getLibrary(), story.getMeta().getLuid(), sync); + } catch (IOException e) { + messageBox("Error when trying to open the story", + e.getMessage(), TMessageBox.Type.OK); + } + } + } + + /** + * Set the default status bar when this window appear. + *

+ * Some shortcuts are always visible, and will be put here. + *

+ * Note that shortcuts placed this way on menu won't work unless the menu + * also implement them. + * + * @param window + * the new window or menu on screen + * @param description + * the description to show on the status ba + */ + public TStatusBar setStatusBar(TWindow window, String description) { + TStatusBar statusBar = window.newStatusBar(description); + statusBar.addShortcutKeypress(TKeypress.kbF10, CMD_EXIT, "Exit"); + return statusBar; + + } + + private void showMain() { + if (main != null && main.isVisible()) { + main.activate(); + } else { + if (main != null) { + main.close(); + } + main = new TuiReaderMainWindow(this); + main.maximize(); + } + } private void init(Reader reader) { this.reader = reader; @@ -144,19 +208,20 @@ class TuiReaderApplication extends TApplication implements Reader { // Add the menus TODO: i18n TMenu fileMenu = addMenu("&File"); - fileMenu.addItem(MENU_OPEN, "&Open"); + fileMenu.addItem(MENU_OPEN, "&Open..."); fileMenu.addItem(MENU_EXPORT, "&Save as..."); + fileMenu.addItem(MENU_DELETE, "&Delete..."); // TODO: Move to... fileMenu.addSeparator(); fileMenu.addItem(MENU_IMPORT_URL, "Import &URL..."); fileMenu.addItem(MENU_IMPORT_FILE, "Import &file..."); fileMenu.addSeparator(); + fileMenu.addItem(MENU_LIBRARY, "Lib&rary"); + fileMenu.addSeparator(); fileMenu.addItem(MENU_EXIT, "E&xit"); - TStatusBar statusBar = fileMenu.newStatusBar("File-management " + setStatusBar(fileMenu, "File-management " + "commands (Open, Save, Print, etc.)"); - // TODO: doesn't actually work: - statusBar.addShortcutKeypress(TKeypress.kbF10, TCommand.cmExit, "Exit"); // TODO: Edit: re-download, delete @@ -167,14 +232,62 @@ class TuiReaderApplication extends TApplication implements Reader { getBackend().setTitle("Fanfix"); } + @Override + protected boolean onCommand(TCommandEvent command) { + if (command.getCmd().equals(TuiReaderMainWindow.CMD_SEARCH)) { + messageBox("title", "caption"); + return true; + } + return super.onCommand(command); + } + @Override protected boolean onMenu(TMenuEvent menu) { // TODO: i18n switch (menu.getId()) { case MENU_EXIT: - if (messageBox("Confirmation", "(TODO: i18n) Exit application?", - TMessageBox.Type.YESNO).getResult() == TMessageBox.Result.YES) { - // exit(false); + close(this); + return true; + case MENU_OPEN: + String openfile = null; + try { + openfile = fileOpenBox("."); + reader.setMeta(BasicReader.getUrl(openfile), null); + read(false); + } catch (IOException e) { + // TODO: i18n + error("Fail to open file" + + (openfile == null ? "" : ": " + openfile), + "Import error", e); + } + + return true; + case MENU_DELETE: + String luid = null; + String story = null; + MetaData meta = null; + if (main != null) { + meta = main.getSelectedMeta(); + } + if (meta != null) { + luid = meta.getLuid(); + story = luid + ": " + meta.getTitle(); + } + + // TODO: i18n + TMessageBox mbox = messageBox("Delete story", "Delete story \"" + + story + "\"", Type.OKCANCEL); + if (mbox.getResult() == Result.OK) { + try { + reader.getLibrary().delete(luid); + if (main != null) { + main.refreshStories(); + } + } catch (IOException e) { + // TODO: i18n + error("Fail to delete the story: \"" + story + "\"", + "Error", e); + } } return true; @@ -195,40 +308,131 @@ class TuiReaderApplication extends TApplication implements Reader { String url = inputBox("Import story", "URL to import", clipboard) .getText(); - if (!imprt(url)) { - // TODO: bad import + try { + if (!imprt(url)) { + // TODO: i18n + error("URK not supported: " + url, "Import error"); + } + } catch (IOException e) { + // TODO: i18n + error("Fail to import URL: " + url, "Import error", e); } return true; case MENU_IMPORT_FILE: + String filename = null; try { - String filename = fileOpenBox("."); + filename = fileOpenBox("."); if (!imprt(filename)) { - // TODO: bad import + // TODO: i18n + error("File not supported: " + filename, "Import error"); } } catch (IOException e) { - // TODO: bad file - e.printStackTrace(); + // TODO: i18n + error("Fail to import file" + + (filename == null ? "" : ": " + filename), + "Import error", e); } - + return true; + case MENU_LIBRARY: + showMain(); return true; } return super.onMenu(menu); } - private boolean imprt(String url) { + /** + * Import the given url. + *

+ * Can fail if the host is not supported. + * + * @param url + * + * @return TRUE in case of success, FALSE if the host is not supported + * + * @throws IOException + * in case of I/O error + */ + private boolean imprt(String url) throws IOException { try { reader.getLibrary().imprt(BasicReader.getUrl(url), null); main.refreshStories(); return true; - } catch (IOException e) { + } catch (UnknownHostException e) { return false; } } @Override - public void openExternal(BasicLibrary lib, String luid) throws IOException { - reader.openExternal(lib, luid); + public void openExternal(BasicLibrary lib, String luid, boolean sync) + throws IOException { + reader.openExternal(lib, luid, sync); + } + + /** + * Display an error message and log it. + * + * @param message + * the message + * @param title + * the title of the error message + */ + private void error(String message, String title) { + error(message, title, null); + } + + /** + * Display an error message and log it, including the linked + * {@link Exception}. + * + * @param message + * the message + * @param title + * the title of the error message + * @param e + * the exception to log if any (can be NULL) + */ + private void error(String message, String title, Exception e) { + Instance.getTraceHandler().error(title + ": " + message); + if (e != null) { + Instance.getTraceHandler().error(e); + } + + if (e != null) { + messageBox(title, message // + + "\n" + e.getMessage()); + } else { + messageBox(title, message); + } + } + + /** + * Ask the user and, if confirmed, close the {@link TApplication} this + * {@link TWidget} is running on. + *

+ * This should result in the program terminating. + * + * @param widget + * the {@link TWidget} + */ + static public void close(TWidget widget) { + close(widget.getApplication()); + } + + /** + * Ask the user and, if confirmed, close the {@link TApplication}. + *

+ * This should result in the program terminating. + * + * @param app + * the {@link TApplication} + */ + static void close(TApplication app) { + // TODO: i18n + if (app.messageBox("Confirmation", "(TODO: i18n) Exit application?", + TMessageBox.Type.YESNO).getResult() == TMessageBox.Result.YES) { + app.exit(); + } } }