Merge branch 'master' into tmp
authorNiki Roo <niki@nikiroo.be>
Sun, 10 Mar 2019 16:23:27 +0000 (17:23 +0100)
committerNiki Roo <niki@nikiroo.be>
Sun, 10 Mar 2019 16:23:27 +0000 (17:23 +0100)
src/be/nikiroo/fanfix/reader/BasicReader.java
src/be/nikiroo/fanfix/reader/tui/TSizeConstraint.java [new file with mode: 0644]
src/be/nikiroo/fanfix/reader/tui/TuiReaderApplication.java
src/be/nikiroo/fanfix/reader/tui/TuiReaderMainWindow.java
src/be/nikiroo/fanfix/reader/tui/TuiReaderStoryWindow.java
src/be/nikiroo/fanfix/test/ConversionTest.java

index 8285edb47e74266bc747662fb3bbec87b5ae5460..778b6338b108f847bea745fbe8fe04c77a0454ec 100644 (file)
@@ -91,18 +91,18 @@ public abstract class BasicReader implements Reader {
        }
 
        @Override
-       public synchronized void setMeta(URL source, Progress pg)
+       public synchronized void setMeta(URL url, Progress pg)
                        throws IOException {
-               BasicSupport support = BasicSupport.getSupport(source);
+               BasicSupport support = BasicSupport.getSupport(url);
                if (support == null) {
-                       throw new IOException("URL not supported: " + source.toString());
+                       throw new IOException("URL not supported: " + url.toString());
                }
 
                story = support.process(pg);
                if (story == null) {
                        throw new IOException(
                                        "Cannot retrieve story from external source: "
-                                                       + source.toString());
+                                                       + url.toString());
                }
 
                meta = story.getMeta();
diff --git a/src/be/nikiroo/fanfix/reader/tui/TSizeConstraint.java b/src/be/nikiroo/fanfix/reader/tui/TSizeConstraint.java
new file mode 100644 (file)
index 0000000..859a6c3
--- /dev/null
@@ -0,0 +1,90 @@
+package be.nikiroo.fanfix.reader.tui;
+
+import java.util.List;
+
+import jexer.TScrollableWidget;
+import jexer.TWidget;
+import jexer.event.TResizeEvent;
+import jexer.event.TResizeEvent.Type;
+
+public class TSizeConstraint {
+       private TWidget widget;
+       private Integer x1;
+       private Integer y1;
+       private Integer x2;
+       private Integer y2;
+
+       // TODO: include in the window classes I use?
+
+       public TSizeConstraint(TWidget widget, Integer x1, Integer y1, Integer x2,
+                       Integer y2) {
+               this.widget = widget;
+               this.x1 = x1;
+               this.y1 = y1;
+               this.x2 = x2;
+               this.y2 = y2;
+       }
+
+       public TWidget getWidget() {
+               return widget;
+       }
+
+       public Integer getX1() {
+               if (x1 != null && x1 < 0)
+                       return widget.getParent().getWidth() + x1;
+               return x1;
+       }
+
+       public Integer getY1() {
+               if (y1 != null && y1 < 0)
+                       return widget.getParent().getHeight() + y1;
+               return y1;
+       }
+
+       public Integer getX2() {
+               if (x2 != null && x2 <= 0)
+                       return widget.getParent().getWidth() - 2 + x2;
+               return x2;
+       }
+
+       public Integer getY2() {
+               if (y2 != null && y2 <= 0)
+                       return widget.getParent().getHeight() - 2 + y2;
+               return y2;
+       }
+
+       // coordinates < 0 = from the other side, x2 or y2 = 0 = max size
+       static void setSize(List<TSizeConstraint> sizeConstraints, TWidget child,
+                       Integer x1, Integer y1, Integer x2, Integer y2) {
+               sizeConstraints.add(new TSizeConstraint(child, x1, y1, x2, y2));
+       }
+
+       static void resize(List<TSizeConstraint> sizeConstraints) {
+               for (TSizeConstraint sizeConstraint : sizeConstraints) {
+                       TWidget widget = sizeConstraint.getWidget();
+                       Integer x1 = sizeConstraint.getX1();
+                       Integer y1 = sizeConstraint.getY1();
+                       Integer x2 = sizeConstraint.getX2();
+                       Integer y2 = sizeConstraint.getY2();
+
+                       if (x1 != null)
+                               widget.setX(x1);
+                       if (y1 != null)
+                               widget.setY(y1);
+
+                       if (x2 != null)
+                               widget.setWidth(x2 - widget.getX());
+                       if (y2 != null)
+                               widget.setHeight(y2 - widget.getY());
+
+                       // Resize the text field
+                       // TODO: why setW/setH/reflow not enough for the scrollbars?
+                       widget.onResize(new TResizeEvent(Type.WIDGET, widget.getWidth(),
+                                       widget.getHeight()));
+
+                       if (widget instanceof TScrollableWidget) {
+                               ((TScrollableWidget) widget).reflowData();
+                       }
+               }
+       }
+}
index 1de62a46a2a420484cf7ea8fa54efee1d83cc692..c08b6c2cc0c42f909c5bbd74cc318ac0b7eac606 100644 (file)
@@ -4,6 +4,7 @@ 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;
@@ -12,6 +13,7 @@ import jexer.TMessageBox;
 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;
@@ -43,10 +45,7 @@ class TuiReaderApplication extends TApplication implements Reader {
 
        private Reader reader;
        private TuiReaderMainWindow main;
-
-       private MetaData meta;
        private String source;
-       private boolean useMeta;
 
        // start reading if meta present
        public TuiReaderApplication(Reader reader, BackendType backend)
@@ -54,7 +53,10 @@ class TuiReaderApplication extends TApplication implements Reader {
                super(backend);
                init(reader);
 
-               showMain(getMeta(), null, true);
+               MetaData meta = getMeta();
+               if (meta != null) {
+                       read();
+               }
        }
 
        public TuiReaderApplication(Reader reader, String source,
@@ -62,30 +64,13 @@ class TuiReaderApplication extends TApplication implements Reader {
                super(backend);
                init(reader);
 
-               showMain(null, source, false);
+               showMain();
+               setSource(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()) {
-                       TWindow window = new TuiReaderStoryWindow(this, getLibrary(), meta,
-                                       getChapter());
-                       window.maximize();
-               } else {
-                       try {
-                               openExternal(getLibrary(), meta.getLuid());
-                       } catch (IOException e) {
-                               messageBox("Error when trying to open the story",
-                                               e.getMessage(), TMessageBox.Type.OK);
-                       }
-               }
+               read(getStory(null));
        }
 
        @Override
@@ -138,6 +123,25 @@ class TuiReaderApplication extends TApplication implements Reader {
                reader.setChapter(chapter);
        }
 
+       public void read(Story story) 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());
+                       } 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.
         * <p>
@@ -158,13 +162,7 @@ class TuiReaderApplication extends TApplication implements Reader {
 
        }
 
-       private void showMain(MetaData meta, String source, boolean useMeta)
-                       throws IOException {
-               // TODO: thread-safety
-               this.meta = meta;
-               this.source = source;
-               this.useMeta = useMeta;
-
+       private void showMain() {
                if (main != null && main.isVisible()) {
                        main.activate();
                } else {
@@ -172,17 +170,16 @@ class TuiReaderApplication extends TApplication implements Reader {
                                main.close();
                        }
                        main = new TuiReaderMainWindow(this);
-                       if (useMeta) {
-                               main.setMeta(meta);
-                               if (meta != null) {
-                                       read();
-                               }
-                       } else {
-                               main.setSource(source);
-                       }
+                       main.maximize();
                }
        }
 
+       private void setSource(String source) {
+               this.source = source;
+               showMain();
+               main.setSource(source);
+       }
+
        private void init(Reader reader) {
                this.reader = reader;
 
@@ -214,12 +211,35 @@ 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:
                        close(this);
+                       return true;
+               case MENU_OPEN:
+                       String openfile = null;
+                       try {
+                               openfile = fileOpenBox(".");
+                               reader.setMeta(BasicReader.getUrl(openfile), null);
+                               read();
+                       } catch (IOException e) {
+                               // TODO: i18n
+                               error("Fail to open file"
+                                               + (openfile == null ? "" : ": " + openfile),
+                                               "Import error", e);
+                       }
+
                        return true;
                case MENU_IMPORT_URL:
                        String clipboard = "";
@@ -238,42 +258,59 @@ 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:
-                       try {
-                               showMain(meta, source, useMeta);
-                       } catch (IOException e) {
-                               e.printStackTrace();
-                       }
-
+                       showMain();
+                       setSource(source);
                        return true;
                }
 
                return super.onMenu(menu);
        }
 
-       private boolean imprt(String url) {
+       /**
+        * Import the given url.
+        * <p>
+        * 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;
                }
        }
@@ -283,6 +320,43 @@ class TuiReaderApplication extends TApplication implements Reader {
                reader.openExternal(lib, luid);
        }
 
+       /**
+        * 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.
index 18a1223bbe70ea49a2ce9b5bddc244b0fe6c1da8..126cee58071c5105c0bdda3959338d2cf114ac47 100644 (file)
@@ -5,11 +5,19 @@ import java.util.ArrayList;
 import java.util.List;
 
 import jexer.TAction;
+import jexer.TComboBox;
+import jexer.TCommand;
+import jexer.TField;
 import jexer.TFileOpenBox.Type;
+import jexer.TKeypress;
+import jexer.TLabel;
 import jexer.TList;
+import jexer.TStatusBar;
 import jexer.TWindow;
 import jexer.event.TCommandEvent;
+import jexer.event.TKeypressEvent;
 import jexer.event.TMenuEvent;
+import jexer.event.TResizeEvent;
 import be.nikiroo.fanfix.Instance;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.library.BasicLibrary;
@@ -23,11 +31,20 @@ import be.nikiroo.fanfix.reader.Reader;
  * @author niki
  */
 class TuiReaderMainWindow extends TWindow {
+       public static final int MENU_SEARCH = 1100;
+       public static final TCommand CMD_SEARCH = new TCommand(MENU_SEARCH) {
+       };
+
        private TList list;
        private List<MetaData> listKeys;
        private List<String> listItems;
        private Reader reader;
        private String source;
+       private String filter = "";
+       private List<TSizeConstraint> sizeConstraints = new ArrayList<TSizeConstraint>();
+
+       // TODO: because no way to find out the current index!!
+       private TComboBox select;
 
        /**
         * Create a new {@link TuiReaderMainWindow} without any stories in the list.
@@ -42,22 +59,17 @@ class TuiReaderMainWindow extends TWindow {
 
                this.reader = reader;
 
-               maximize();
-
                listKeys = new ArrayList<MetaData>();
                listItems = new ArrayList<String>();
-               list = addList(listItems, 0, 0, getWidth(), getHeight(), new TAction() {
-                       @Override
-                       public void DO() {
-                               MetaData meta = getSelectedMeta();
-                               if (meta != null) {
-                                       readStory(meta);
-                               }
-                       }
-               });
 
-               // TODO: add the current "source/type" or filter
-               reader.setStatusBar(this, "Library");
+               addSearch();
+               addList();
+               addSelect(); // TODO: last so it can draw over the rest
+
+               TStatusBar statusBar = reader.setStatusBar(this, "Library");
+               statusBar.addShortcutKeypress(TKeypress.kbCtrlF, CMD_SEARCH, "Search");
+
+               TSizeConstraint.resize(sizeConstraints);
 
                // TODO: remove when not used anymore
 
@@ -84,6 +96,103 @@ class TuiReaderMainWindow extends TWindow {
                // root.addChild("child 2").addChild("sub child");
        }
 
+       private void addSearch() {
+               TLabel lblSearch = addLabel("Search: ", 0, 0);
+
+               TField search = new TField(this, 0, 0, 1, true) {
+                       @Override
+                       public void onKeypress(TKeypressEvent keypress) {
+                               super.onKeypress(keypress);
+                               TKeypress key = keypress.getKey();
+                               if (key.isFnKey() && key.getKeyCode() == TKeypress.ENTER) {
+                                       TuiReaderMainWindow.this.filter = getText();
+                                       TuiReaderMainWindow.this.refreshStories();
+                               }
+                       }
+               };
+
+               TSizeConstraint.setSize(sizeConstraints, lblSearch, 5, 1, null, null);
+               TSizeConstraint.setSize(sizeConstraints, search, 15, 1, -5, null);
+       }
+
+       private void addList() {
+               list = addList(listItems, 0, 0, 10, 10, new TAction() {
+                       @Override
+                       public void DO() {
+                               MetaData meta = getSelectedMeta();
+                               if (meta != null) {
+                                       readStory(meta);
+                               }
+                       }
+               });
+
+               TSizeConstraint.setSize(sizeConstraints, list, 0, 7, 0, 0);
+       }
+
+       private void addSelect() {
+               // TODO: make a full list
+               final List<String> options = new ArrayList<String>();
+               options.add("(all opt)");
+               options.add("Sources");
+               options.add("Author");
+
+               // TODO
+               final List<String> sources = new ArrayList<String>();
+               sources.add("(show all)");
+               for (String source : reader.getLibrary().getSources()) {
+                       sources.add(source);
+               }
+
+               TLabel lblSelect = addLabel("Select: ", 0, 0);
+
+               // TODO: why must be last so to be able to draw over the rest
+               // TODO: make it so we cannot add manual entries
+               // TODO: how to select the item via keyboard? why double-click via
+               // mouse?
+               // TODO: how to change the values size on resize?
+               // TODO: setWidth() does not impact the display width, only the control
+               // and the down arrow on the right
+               // TODO: width 1 +resize + click on down arrow = bad format exception
+               select = addComboBox(0, 0, 10, sources, 0,
+                               Math.min(sources.size() + 1, getHeight() - 1 - 1),
+                               new TAction() {
+                                       @Override
+                                       public void DO() {
+                                               // TODO: wut?
+                                               if (select.getText().equals("(show all)")) {
+                                                       setSource(null);
+                                               } else {
+                                                       setSource(select.getText());
+                                               }
+                                               refreshStories();
+                                       }
+                               });
+
+               final TComboBox option = addComboBox(0, 0, 10, options, 0,
+                               Math.min(sources.size() + 1, getHeight() - 1 - 1),
+                               new TAction() {
+                                       @Override
+                                       public void DO() {
+                                               // TODO Not working:
+                                               sources.clear();
+                                               sources.add("(show all)");
+                                               for (String source : reader.getLibrary().getSources()) {
+                                                       sources.add(source);
+                                               }
+                                       }
+                               });
+
+               TSizeConstraint.setSize(sizeConstraints, lblSelect, 5, 3, null, null);
+               TSizeConstraint.setSize(sizeConstraints, option, 15, 3, -5, null);
+               TSizeConstraint.setSize(sizeConstraints, select, 15, 4, -5, null);
+       }
+
+       @Override
+       public void onResize(TResizeEvent resize) {
+               super.onResize(resize);
+               TSizeConstraint.resize(sizeConstraints);
+       }
+
        @Override
        public void onClose() {
                setVisible(false);
@@ -91,38 +200,31 @@ class TuiReaderMainWindow extends TWindow {
        }
 
        /**
-        * Change the source filter and display all stories matching this source.
-        * 
-        * @param source
-        *            the new source or NULL for all sources
+        * Refresh the list of stories displayed in this library.
+        * <p>
+        * Will take the current settings into account (filter, source...).
         */
-       public void setSource(String source) {
-               this.source = source;
-               refreshStories();
-       }
-
        public void refreshStories() {
                List<MetaData> metas = reader.getLibrary().getListBySource(source);
                setMetas(metas);
        }
 
        /**
-        * Update the list of stories displayed in this {@link TWindow}.
+        * Change the source filter and display all stories matching this source.
         * 
-        * @param meta
-        *            the new (unique) story to display
+        * @param source
+        *            the new source or NULL for all sources
         */
-       public void setMeta(MetaData meta) {
-               List<MetaData> metas = new ArrayList<MetaData>();
-               if (meta != null) {
-                       metas.add(meta);
-               }
-
-               setMetas(metas);
+       public void setSource(String source) {
+               this.source = source;
+               refreshStories();
        }
 
        /**
         * Update the list of stories displayed in this {@link TWindow}.
+        * <p>
+        * If a filter is set, only the stories which pass the filter will be
+        * displayed.
         * 
         * @param metas
         *            the new list of stories to display
@@ -133,8 +235,12 @@ class TuiReaderMainWindow extends TWindow {
 
                if (metas != null) {
                        for (MetaData meta : metas) {
-                               listKeys.add(meta);
-                               listItems.add(desc(meta));
+                               String desc = desc(meta);
+                               if (filter.isEmpty()
+                                               || desc.toLowerCase().contains(filter.toLowerCase())) {
+                                       listKeys.add(meta);
+                                       listItems.add(desc);
+                               }
                        }
                }
 
@@ -196,6 +302,7 @@ class TuiReaderMainWindow extends TWindow {
                                }
 
                                return;
+
                        case -1:
                                try {
                                        reader.getLibrary().delete(meta.getLuid());
index f5a2bfa547d8804835667f5140d2bcd8f632a873..d4fac73a166594be5ee5d25ff8dde9ab6ddbc922 100644 (file)
@@ -15,13 +15,11 @@ import jexer.TText;
 import jexer.TWindow;
 import jexer.event.TCommandEvent;
 import jexer.event.TResizeEvent;
-import jexer.event.TResizeEvent.Type;
 import be.nikiroo.fanfix.data.Chapter;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Paragraph;
 import be.nikiroo.fanfix.data.Paragraph.ParagraphType;
 import be.nikiroo.fanfix.data.Story;
-import be.nikiroo.fanfix.library.BasicLibrary;
 import be.nikiroo.utils.StringUtils;
 
 /**
@@ -31,8 +29,6 @@ import be.nikiroo.utils.StringUtils;
  * @author niki
  */
 class TuiReaderStoryWindow extends TWindow {
-       private BasicLibrary lib;
-       private MetaData meta;
        private Story story;
        private TLabel titleField;
        private TText textField;
@@ -40,53 +36,48 @@ class TuiReaderStoryWindow extends TWindow {
        private int chapter = -99; // invalid value
        private List<TButton> navigationButtons;
        private TLabel currentChapter;
+       private List<TSizeConstraint> sizeConstraints = new ArrayList<TSizeConstraint>();
 
        // chapter: -1 for "none" (0 is desc)
-       public TuiReaderStoryWindow(TuiReaderApplication app, BasicLibrary lib,
-                       MetaData meta, int chapter) {
-               super(app, desc(meta), 0, 0, 60, 18, CENTERED | RESIZABLE);
+       public TuiReaderStoryWindow(TuiReaderApplication app, Story story,
+                       int chapter) {
+               super(app, desc(story.getMeta()), 0, 0, 60, 18, CENTERED | RESIZABLE);
 
-               this.lib = lib;
-               this.meta = meta;
+               this.story = story;
 
-               app.setStatusBar(this, desc(meta));
+               app.setStatusBar(this, desc(story.getMeta()));
 
                // last = use window background
                titleField = new TLabel(this, "    Title", 0, 1, "tlabel", false);
-               textField = new TText(this, "", 1, 3, getWidth() - 4, getHeight() - 5);
-               table = new TTable(this, 0, 3, getWidth(), getHeight() - 4, null, null,
-                               Arrays.asList("Key", "Value"), true);
+               textField = new TText(this, "", 0, 0, 1, 1);
+               table = new TTable(this, 0, 0, 1, 1, null, null, Arrays.asList("Key",
+                               "Value"), true);
 
                titleField.setEnabled(false);
-               textField.getVerticalScroller().setX(
-                               textField.getVerticalScroller().getX() + 1);
 
                navigationButtons = new ArrayList<TButton>(5);
 
-               // -3 because 0-based and 2 for borders
-               int row = getHeight() - 3;
-
                // for bg colour when << button is pressed
-               navigationButtons.add(addButton(" ", 0, row, null));
-               navigationButtons.add(addButton("<<  ", 0, row, new TAction() {
+               navigationButtons.add(addButton(" ", 0, 0, null));
+               navigationButtons.add(addButton("<<  ", 0, 0, new TAction() {
                        @Override
                        public void DO() {
                                setChapter(-1);
                        }
                }));
-               navigationButtons.add(addButton("<  ", 4, row, new TAction() {
+               navigationButtons.add(addButton("<  ", 4, 0, new TAction() {
                        @Override
                        public void DO() {
                                setChapter(TuiReaderStoryWindow.this.chapter - 1);
                        }
                }));
-               navigationButtons.add(addButton(">  ", 7, row, new TAction() {
+               navigationButtons.add(addButton(">  ", 7, 0, new TAction() {
                        @Override
                        public void DO() {
                                setChapter(TuiReaderStoryWindow.this.chapter + 1);
                        }
                }));
-               navigationButtons.add(addButton(">>  ", 10, row, new TAction() {
+               navigationButtons.add(addButton(">>  ", 10, 0, new TAction() {
                        @Override
                        public void DO() {
                                setChapter(getStory().getChapters().size());
@@ -97,41 +88,38 @@ class TuiReaderStoryWindow extends TWindow {
                navigationButtons.get(1).setEnabled(false);
                navigationButtons.get(2).setEnabled(false);
 
-               currentChapter = addLabel("", 14, row);
-               currentChapter.setWidth(getWidth() - 10);
+               currentChapter = addLabel("", 0, 0);
+
+               TSizeConstraint.setSize(sizeConstraints, textField, 1, 3, -1, 0);
+               TSizeConstraint.setSize(sizeConstraints, table, 0, 3, 0, 0);
+               TSizeConstraint.setSize(sizeConstraints, currentChapter, 14, -3, -1,
+                               null);
+
+               for (TButton navigationButton : navigationButtons) {
+                       TSizeConstraint.setSize(sizeConstraints, navigationButton, null,
+                                       -3, null, null);
+               }
+
+               onResize(null);
 
                setChapter(chapter);
        }
 
        @Override
        public void onResize(TResizeEvent resize) {
-               super.onResize(resize);
-
-               // Resize the text field
-               // TODO: why setW/setH/reflow not enough for the scrollbars?
-               textField.onResize(new TResizeEvent(Type.WIDGET, resize.getWidth() - 4,
-                               resize.getHeight() - 5));
-               textField.getVerticalScroller().setX(
-                               textField.getVerticalScroller().getX() + 1);
+               if (resize != null) {
+                       super.onResize(resize);
+               }
 
-               table.setWidth(getWidth());
-               table.setHeight(getHeight() - 4);
-               table.reflowData();
+               // TODO: find out why TText and TTable does not behave the same way
+               // (offset of 2 for height and width)
 
-               // -3 because 0-based and 2 for borders
-               int row = getHeight() - 3;
+               TSizeConstraint.resize(sizeConstraints);
 
-               String name = currentChapter.getLabel();
-               while (name.length() < resize.getWidth() - currentChapter.getX()) {
-                       name += " ";
-               }
-               currentChapter.setLabel(name);
-               currentChapter.setWidth(resize.getWidth() - 10);
-               currentChapter.setY(row);
+               textField.getVerticalScroller().setX(
+                               textField.getVerticalScroller().getX() + 1);
 
-               for (TButton button : navigationButtons) {
-                       button.setY(row);
-               }
+               setCurrentChapterText();
        }
 
        /**
@@ -274,10 +262,6 @@ class TuiReaderStoryWindow extends TWindow {
        }
 
        private Story getStory() {
-               if (story == null) {
-                       // TODO: progress bar?
-                       story = lib.getStory(meta.getLuid(), null);
-               }
                return story;
        }
 
@@ -315,10 +299,7 @@ class TuiReaderStoryWindow extends TWindow {
                }
 
                int width = getWidth() - currentChapter.getX();
-               while (name.length() < width) {
-                       name += " ";
-               }
-
+               name = String.format("%-" + width + "s", name);
                if (name.length() > width) {
                        name = name.substring(0, width);
                }
index 51b6deb4f817e6a2f451ead2d7b73f554a7795af..0eb1eb04b95eef90cbd749901d673a966bee3144 100644 (file)
@@ -172,10 +172,16 @@ class ConversionTest extends TestLauncher {
                        };
                }
 
-               List<String> resultFiles = Arrays.asList(resultDir.list(filter));
-               resultFiles.sort(null);
-               List<String> expectedFiles = Arrays.asList(expectedDir.list(filter));
-               expectedFiles.sort(null);
+               List<String> resultFiles;
+               List<String> expectedFiles;
+               {
+                       String[] resultArr = resultDir.list(filter);
+                       Arrays.sort(resultArr);
+                       resultFiles = Arrays.asList(resultArr);
+                       String[] expectedArr = expectedDir.list(filter);
+                       Arrays.sort(expectedArr);
+                       expectedFiles = Arrays.asList(expectedArr);
+               }
 
                testCase.assertEquals(errMess, expectedFiles, resultFiles);