Code cleanup 2 (a third one is pending)
authorNiki Roo <niki@nikiroo.be>
Wed, 5 Jul 2017 17:20:10 +0000 (19:20 +0200)
committerNiki Roo <niki@nikiroo.be>
Wed, 5 Jul 2017 17:20:10 +0000 (19:20 +0200)
README.md
src/be/nikiroo/fanfix/reader/BasicReader.java
src/be/nikiroo/fanfix/reader/GuiReader.java
src/be/nikiroo/fanfix/reader/Reader.java
src/be/nikiroo/fanfix/reader/TuiReader.java
src/be/nikiroo/fanfix/reader/TuiReaderApplication.java
src/be/nikiroo/fanfix/reader/TuiReaderMainWindow.java
src/be/nikiroo/fanfix/reader/TuiReaderStoryWindow.java

index 98a0c9b4f0b211612a784fc59c33f3c0c8bf194d..22a5dc2a9e41ae98152f7276a19069c465df605d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -125,6 +125,7 @@ Currently missing, but either in progress or planned:
   - [ ] Real menus
   - [x] Open a story in the reader and/or natively
   - [ ] Update the screenshots
+  - [ ] Remember the current chapter and current read status of stories
 - [ ] Network support
   - [x] A server that can send the stories
   - [x] A network implementation of the Library
index cbd4e0308a4584895b805d7ed3ac8bbdaf2c3732..2c04006ba0d5fa4f68521ef1c17b39abe197b5a3 100644 (file)
@@ -63,7 +63,7 @@ public abstract class BasicReader implements Reader {
        }
 
        public void setStory(String luid, Progress pg) throws IOException {
-               story = lib.getStory(luid, pg);
+               story = getLibrary().getStory(luid, pg);
                if (story == null) {
                        throw new IOException("Cannot retrieve story from library: " + luid);
                }
@@ -84,6 +84,10 @@ public abstract class BasicReader implements Reader {
                }
        }
 
+       public void read() throws IOException {
+               read(-1);
+       }
+
        /**
         * Return a new {@link BasicReader} ready for use if one is configured.
         * <p>
@@ -177,11 +181,12 @@ public abstract class BasicReader implements Reader {
         * @throws IOException
         *             in case of I/O error
         */
-       public static void open(BasicLibrary lib, String luid) throws IOException {
+       public static void openExternal(BasicLibrary lib, String luid)
+                       throws IOException {
                MetaData meta = lib.getInfo(luid);
                File target = lib.getFile(luid);
 
-               open(meta, target);
+               openExternal(meta, target);
        }
 
        /**
@@ -196,7 +201,8 @@ public abstract class BasicReader implements Reader {
         * @throws IOException
         *             in case of I/O error
         */
-       protected static void open(MetaData meta, File target) throws IOException {
+       protected static void openExternal(MetaData meta, File target)
+                       throws IOException {
                String program = null;
                if (meta.isImageDocument()) {
                        program = Instance.getUiConfig().getString(
index 06b3473c74c95f9abe7035f78852b3a1604938f4..2c30ab6740ad49a46a070585fbe581326b75fc1f 100644 (file)
@@ -218,7 +218,7 @@ class GuiReader extends BasicReader {
                        file = localLibrary.getFile(luid);
                }
 
-               open(getLibrary().getInfo(luid), file);
+               openExternal(getLibrary().getInfo(luid), file);
        }
 
        void changeType(String luid, String newType) {
index d7285785b6513dc76badadb96ad8ce49a620e9be..09d45c15f3943ccffac23a7d774e71a351996765 100644 (file)
@@ -70,8 +70,8 @@ public interface Reader {
        public void setLibrary(LocalLibrary lib);
 
        /**
-        * Create a new {@link BasicReader} for a {@link Story} in the
-        * {@link LocalLibrary}.
+        * Set a {@link Story} from the current {@link Library} into the
+        * {@link Reader}.
         * 
         * @param luid
         *            the {@link Story} ID
@@ -84,7 +84,7 @@ public interface Reader {
        public void setStory(String luid, Progress pg) throws IOException;
 
        /**
-        * Create a new {@link BasicReader} for an external {@link Story}.
+        * Set an external {@link Story} into this {@link Reader}.
         * 
         * @param source
         *            the {@link Story} {@link URL}
@@ -106,10 +106,10 @@ public interface Reader {
        public void read() throws IOException;
 
        /**
-        * Read the selected chapter (starting at 1).
+        * Read the selected chapter (starting at 1, 0 = description, -1 = none).
         * 
         * @param chapter
-        *            the chapter
+        *            the chapter, or -1 for "no chapter"
         * 
         * @throws IOException
         *             in case of I/O error or if the {@link Story} was not
@@ -126,5 +126,4 @@ public interface Reader {
         *            all
         */
        public void browse(String source);
-
 }
index e9f909da7674ffd41f580e6e59dc2ec88f27e5ad..91b62683aff9de15da1645a7ac08e62cacb7c916 100644 (file)
@@ -1,27 +1,95 @@
 package be.nikiroo.fanfix.reader;
 
 import java.io.IOException;
+import java.util.List;
 
+import jexer.TApplication;
+import jexer.TApplication.BackendType;
 import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.data.MetaData;
 
+/**
+ * This {@link Reader}is based upon the TUI widget library 'jexer'
+ * (https://github.com/klamonte/jexer/) and offer, as its name suggest, a Text
+ * User Interface.
+ * <p>
+ * It is expected to be on par with the GUI version.
+ * 
+ * @author niki
+ */
 class TuiReader extends BasicReader {
-       public void read() throws IOException {
-               if (getStory() == null) {
-                       throw new IOException("No story to read");
+       /**
+        * Will detect the backend to use.
+        * <p>
+        * Swing is the default backend on Windows and MacOS while evreything else
+        * will use XTERM unless explicitly overridden by <tt>jexer.Swing</tt> =
+        * <tt>true</tt> or <tt>false</tt>.
+        * 
+        * @return the backend to use
+        */
+       private static BackendType guessBackendType() {
+               // TODO: allow a config option to force one or the other?
+               TApplication.BackendType backendType = TApplication.BackendType.XTERM;
+               if (System.getProperty("os.name").startsWith("Windows")) {
+                       backendType = TApplication.BackendType.SWING;
+               }
+
+               if (System.getProperty("os.name").startsWith("Mac")) {
+                       backendType = TApplication.BackendType.SWING;
+               }
+
+               if (System.getProperty("jexer.Swing") != null) {
+                       if (System.getProperty("jexer.Swing", "false").equals("true")) {
+                               backendType = TApplication.BackendType.SWING;
+                       } else {
+                               backendType = TApplication.BackendType.XTERM;
+                       }
                }
 
-               open(getLibrary(), getStory().getMeta().getLuid());
+               return backendType;
        }
 
        public void read(int chapter) throws IOException {
-               // TODO: show a special page?
-               read();
+               if (getStory() == null) {
+                       throw new IOException("No story to read");
+               }
+
+               start(getStory().getMeta(), chapter);
        }
 
        public void browse(String source) {
+               start(getLibrary().getListBySource(source));
+       }
+
+       /**
+        * Start the application with the given stories.
+        * 
+        * @param metas
+        *            the stories to display
+        */
+       private void start(List<MetaData> metas) {
+               try {
+                       TuiReaderApplication app = new TuiReaderApplication(metas, this,
+                                       guessBackendType());
+                       new Thread(app).start();
+               } catch (Exception e) {
+                       Instance.syserr(e);
+               }
+       }
+
+       /**
+        * Start the application with the given {@link MetaData} at the given open
+        * chapter.
+        * 
+        * @param meta
+        *            the story to display
+        * @param chapter
+        *            the chapter to open
+        */
+       private void start(MetaData meta, int chapter) {
                try {
-                       TuiReaderApplication app = new TuiReaderApplication(getLibrary()
-                                       .getListBySource(source), this);
+                       TuiReaderApplication app = new TuiReaderApplication(meta, chapter,
+                                       this, guessBackendType());
                        new Thread(app).start();
                } catch (Exception e) {
                        Instance.syserr(e);
index 719f0954160fc3d90b0e1996dc7f5db744f36121..b7f83085a636f79660443e1d1395b835025b43b2 100644 (file)
@@ -1,42 +1,43 @@
 package be.nikiroo.fanfix.reader;
 
 import java.io.IOException;
+import java.net.URL;
 import java.util.List;
 
 import jexer.TApplication;
 import jexer.TMessageBox;
+import jexer.TWindow;
 import be.nikiroo.fanfix.data.MetaData;
+import be.nikiroo.fanfix.data.Story;
+import be.nikiroo.fanfix.library.BasicLibrary;
+import be.nikiroo.fanfix.library.LocalLibrary;
+import be.nikiroo.utils.Progress;
 
-class TuiReaderApplication extends TApplication {
-       private BasicReader reader;
+/**
+ * Manages the TUI reader, links and manages the {@link TWindow}s, starts the
+ * correct output mode.
+ * 
+ * @author niki
+ */
+class TuiReaderApplication extends TApplication implements Reader {
+       private Reader reader;
 
-       private static BackendType guessBackendType() {
-               // Swing is the default backend on Windows unless explicitly
-               // overridden by jexer.Swing.
-               TApplication.BackendType backendType = TApplication.BackendType.XTERM;
-               if (System.getProperty("os.name").startsWith("Windows")) {
-                       backendType = TApplication.BackendType.SWING;
-               }
-               if (System.getProperty("os.name").startsWith("Mac")) {
-                       backendType = TApplication.BackendType.SWING;
-               }
-               if (System.getProperty("jexer.Swing") != null) {
-                       if (System.getProperty("jexer.Swing", "false").equals("true")) {
-                               backendType = TApplication.BackendType.SWING;
-                       } else {
-                               backendType = TApplication.BackendType.XTERM;
-                       }
-               }
-               return backendType;
-       }
+       public TuiReaderApplication(MetaData meta, int chapter, Reader reader,
+                       BackendType backend) throws Exception {
+               this(reader, backend);
 
-       public TuiReaderApplication(List<MetaData> stories, BasicReader reader)
-                       throws Exception {
-               this(stories, reader, guessBackendType());
+               new TuiReaderMainWindow(this, meta, chapter);
        }
 
-       public TuiReaderApplication(List<MetaData> stories, BasicReader reader,
+       public TuiReaderApplication(List<MetaData> stories, Reader reader,
                        TApplication.BackendType backend) throws Exception {
+               this(reader, backend);
+
+               new TuiReaderMainWindow(this, stories);
+       }
+
+       private TuiReaderApplication(Reader reader, TApplication.BackendType backend)
+                       throws Exception {
                super(backend);
 
                this.reader = reader;
@@ -48,21 +49,55 @@ class TuiReaderApplication extends TApplication {
                addHelpMenu();
 
                getBackend().setTitle("Fanfix");
+       }
 
-               new TuiReaderMainWindow(this, stories);
+       public void read() throws IOException {
+               reader.read();
+       }
+
+       public void read(int chapter) throws IOException {
+               reader.read(chapter);
        }
 
        public void open(MetaData meta) {
+               open(meta, -1);
+       }
+
+       public void open(MetaData meta, int chapter) {
                // TODO: open in editor + external option
                if (!meta.isImageDocument()) {
-                       new TuiReaderStoryWindow(this, reader.getLibrary(), meta);
+                       new TuiReaderStoryWindow(this, getLibrary(), meta, chapter);
                } else {
                        try {
-                               BasicReader.open(reader.getLibrary(), meta.getLuid());
+                               BasicReader.openExternal(getLibrary(), meta.getLuid());
                        } catch (IOException e) {
                                messageBox("Error when trying to open the story",
                                                e.getMessage(), TMessageBox.Type.OK);
                        }
                }
        }
+
+       public Story getStory() {
+               return reader.getStory();
+       }
+
+       public BasicLibrary getLibrary() {
+               return reader.getLibrary();
+       }
+
+       public void setLibrary(LocalLibrary lib) {
+               reader.setLibrary(lib);
+       }
+
+       public void setStory(String luid, Progress pg) throws IOException {
+               reader.setStory(luid, pg);
+       }
+
+       public void setStory(URL source, Progress pg) throws IOException {
+               reader.setStory(source, pg);
+       }
+
+       public void browse(String source) {
+               reader.browse(source);
+       }
 }
index 8f00b493e99238c461746abd46e80fc7b94fbdab..3b5dc5dcfff3901c96f7880c244a963e2116b3a8 100644 (file)
@@ -13,6 +13,12 @@ import jexer.TTreeView;
 import jexer.TWindow;
 import be.nikiroo.fanfix.data.MetaData;
 
+/**
+ * The library window, that will list all the (filtered) stories available in
+ * this {@link Library}.
+ * 
+ * @author niki
+ */
 class TuiReaderMainWindow extends TWindow {
        private TList list;
        private List<MetaData> listKeys;
@@ -20,15 +26,49 @@ class TuiReaderMainWindow extends TWindow {
        private TuiReaderApplication reader;
 
        /**
-        * Constructor.
+        * Create a new {@link TuiReaderMainWindow} with the given stories in the
+        * list.
         * 
         * @param reader
         *            the reader and main application
-        * @param stories
+        * @param metas
         *            the stories to display
         */
-       public TuiReaderMainWindow(TuiReaderApplication reader,
-                       List<MetaData> stories) {
+       public TuiReaderMainWindow(TuiReaderApplication reader, List<MetaData> metas) {
+               this(reader);
+               setMetas(metas);
+       }
+
+       /**
+        * Create a new {@link TuiReaderMainWindow} with only the given
+        * {@link MetaData} in the list, and open this {@link MetaData} at the given
+        * chapter.
+        * 
+        * @param reader
+        *            the reader and main application
+        * @param meta
+        *            the story to display
+        * @param chapter
+        *            the chapter to open
+        */
+       public TuiReaderMainWindow(TuiReaderApplication reader, MetaData meta,
+                       int chapter) {
+               this(reader);
+
+               List<MetaData> metas = new ArrayList<MetaData>();
+               metas.add(meta);
+               setMetas(metas);
+
+               reader.open(meta, chapter);
+       }
+
+       /**
+        * Create a new {@link TuiReaderMainWindow} without any stories in the list.
+        * 
+        * @param reader
+        *            the reader and main application
+        */
+       public TuiReaderMainWindow(TuiReaderApplication reader) {
                // Construct a demo window. X and Y don't matter because it will be
                // centered on screen.
                super(reader, "Library", 0, 0, 60, 18, CENTERED | RESIZABLE
@@ -40,14 +80,6 @@ class TuiReaderMainWindow extends TWindow {
 
                listKeys = new ArrayList<MetaData>();
                listItems = new ArrayList<String>();
-
-               if (stories != null) {
-                       for (MetaData meta : stories) {
-                               listKeys.add(meta);
-                               listItems.add(desc(meta));
-                       }
-               }
-
                list = addList(listItems, 0, 0, getWidth(), getHeight(), new TAction() {
                        @Override
                        public void DO() {
@@ -57,7 +89,7 @@ class TuiReaderMainWindow extends TWindow {
                        }
                });
 
-               // TODO: add the current "type" or filter
+               // TODO: add the current "source/type" or filter
                statusBar = newStatusBar("Library");
                statusBar.addShortcutKeypress(TKeypress.kbF10, TCommand.cmExit, "Exit");
 
@@ -87,6 +119,26 @@ class TuiReaderMainWindow extends TWindow {
                }
        }
 
+       /**
+        * Update the list of stories displayed in this {@link TWindow}.
+        * 
+        * @param metas
+        *            the new list of stories to display
+        */
+       public void setMetas(List<MetaData> metas) {
+               listKeys.clear();
+               listItems.clear();
+
+               if (metas != null) {
+                       for (MetaData meta : metas) {
+                               listKeys.add(meta);
+                               listItems.add(desc(meta));
+                       }
+               }
+
+               list.setList(listItems);
+       }
+
        private void enterOnStory(MetaData meta) {
                reader.open(meta);
        }
index 71b5b5e38374901a68a2aa768ae4a64743020e43..0f6af07b4a8ac28c99e12e76ebca445b0d6cc656 100644 (file)
@@ -27,11 +27,7 @@ class TuiReaderStoryWindow extends TWindow {
        private List<TButton> navigationButtons;
        private TLabel chapterName;
 
-       public TuiReaderStoryWindow(TApplication app, BasicLibrary lib,
-                       MetaData meta) {
-               this(app, lib, meta, 0);
-       }
-
+       // chapter: -1 for "none" (0 is desc)
        public TuiReaderStoryWindow(TApplication app, BasicLibrary lib,
                        MetaData meta, int chapter) {
                super(app, desc(meta), 0, 0, 60, 18, CENTERED | RESIZABLE);