working on ui refresh for books
authorNiki Roo <niki@nikiroo.be>
Thu, 9 Apr 2020 14:48:54 +0000 (16:48 +0200)
committerNiki Roo <niki@nikiroo.be>
Thu, 9 Apr 2020 14:48:54 +0000 (16:48 +0200)
src/be/nikiroo/fanfix_swing/gui/BooksPanel.java
src/be/nikiroo/fanfix_swing/gui/book/BookCoverImager.java
src/be/nikiroo/fanfix_swing/gui/book/BookInfo.java
src/be/nikiroo/fanfix_swing/gui/utils/DelayWorker.java [new file with mode: 0644]

index 810323f6b76b3494bcefb7136ade645bed48c835..3a07afb77c33af5bd53ad829572f5960431ff756 100644 (file)
@@ -10,10 +10,8 @@ import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Queue;
 import java.util.concurrent.ExecutionException;
 
 import javax.swing.DefaultListModel;
@@ -21,7 +19,6 @@ import javax.swing.JList;
 import javax.swing.JPopupMenu;
 import javax.swing.ListCellRenderer;
 import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
 import javax.swing.SwingWorker;
 
 import be.nikiroo.fanfix.Instance;
@@ -32,6 +29,7 @@ import be.nikiroo.fanfix_swing.gui.book.BookBlock;
 import be.nikiroo.fanfix_swing.gui.book.BookInfo;
 import be.nikiroo.fanfix_swing.gui.book.BookLine;
 import be.nikiroo.fanfix_swing.gui.book.BookPopup;
+import be.nikiroo.fanfix_swing.gui.utils.DelayWorker;
 import be.nikiroo.fanfix_swing.gui.utils.ListenerPanel;
 import be.nikiroo.fanfix_swing.gui.utils.UiHelper;
 
@@ -55,12 +53,10 @@ public class BooksPanel extends ListenerPanel {
        private JList<BookInfo> list;
        private int hoveredIndex = -1;
        private ListModel data = new ListModel();
+       private DelayWorker bookCoverUpdater;
 
        private SearchBar searchBar;
 
-       private Queue<BookBlock> updateBookQueue = new LinkedList<BookBlock>();
-       private Object updateBookQueueLock = new Object();
-
        public BooksPanel(boolean listMode) {
                setLayout(new BorderLayout());
 
@@ -74,51 +70,9 @@ public class BooksPanel extends ListenerPanel {
                        }
                });
 
+               bookCoverUpdater = new DelayWorker(20);
+               bookCoverUpdater.start();
                add(UiHelper.scroll(initList(listMode)), BorderLayout.CENTER);
-
-               Thread bookBlocksUpdater = new Thread(new Runnable() {
-                       @Override
-                       public void run() {
-                               while (true) {
-                                       BasicLibrary lib = Instance.getInstance().getLibrary();
-                                       while (true) {
-                                               final BookBlock book;
-                                               synchronized (updateBookQueueLock) {
-                                                       if (!updateBookQueue.isEmpty()) {
-                                                               book = updateBookQueue.remove();
-                                                       } else {
-                                                               book = null;
-                                                               break;
-                                                       }
-                                               }
-
-                                               try {
-                                                       final Image coverImage = BookBlock
-                                                                       .generateCoverImage(lib, book.getInfo());
-                                                       SwingUtilities.invokeLater(new Runnable() {
-                                                               @Override
-                                                               public void run() {
-                                                                       try {
-                                                                               book.setCoverImage(coverImage);
-                                                                               data.fireElementChanged(book.getInfo());
-                                                                       } catch (Exception e) {
-                                                                       }
-                                                               }
-                                                       });
-                                               } catch (Exception e) {
-                                               }
-                                       }
-
-                                       try {
-                                               Thread.sleep(10);
-                                       } catch (InterruptedException e) {
-                                       }
-                               }
-                       }
-               });
-               bookBlocksUpdater.setName("BookBlocks visual updater");
-               bookBlocksUpdater.setDaemon(true);
-               bookBlocksUpdater.start();
        }
 
        // null or empty -> all sources
@@ -156,9 +110,7 @@ public class BooksPanel extends ListenerPanel {
        public void load(List<BookInfo> bookInfos) {
                this.bookInfos.clear();
                this.bookInfos.addAll(bookInfos);
-               synchronized (updateBookQueueLock) {
-                       updateBookQueue.clear();
-               }
+               bookCoverUpdater.clear();
 
                filter(searchBar.getText());
        }
@@ -335,9 +287,7 @@ public class BooksPanel extends ListenerPanel {
                                                book = new BookLine(value, seeWordCount);
                                        } else {
                                                book = new BookBlock(value, seeWordCount);
-                                               synchronized (updateBookQueueLock) {
-                                                       updateBookQueue.add((BookBlock) book);
-                                               }
+                                               startUpdateBookCover((BookBlock) book);
                                        }
                                        books.put(value, book);
                                }
@@ -349,6 +299,27 @@ public class BooksPanel extends ListenerPanel {
                };
        }
 
+       private void startUpdateBookCover(final BookBlock book) {
+               bookCoverUpdater.delay(book.getInfo().getId(),
+                               new SwingWorker<Image, Void>() {
+                                       @Override
+                                       protected Image doInBackground() throws Exception {
+                                               BasicLibrary lib = Instance.getInstance().getLibrary();
+                                               return BookBlock.generateCoverImage(lib,
+                                                               book.getInfo());
+                                       }
+
+                                       protected void done() {
+                                               try {
+                                                       book.setCoverImage(get());
+                                                       data.fireElementChanged(book.getInfo());
+                                               } catch (Exception e) {
+                                                       // TODO ? probably just log
+                                               }
+                                       }
+                               });
+       }
+
        public boolean isListMode() {
                return listMode;
        }
@@ -360,9 +331,7 @@ public class BooksPanel extends ListenerPanel {
                                listMode ? JList.VERTICAL : JList.HORIZONTAL_WRAP);
 
                if (listMode) {
-                       synchronized (updateBookQueueLock) {
-                               updateBookQueue.clear();
-                       }
+                       bookCoverUpdater.clear();
                }
        }
 }
index 8bdcfabfee341b26bea43f05fe04df70c0d78627..95e0aabca17acfdcdd760ffbe36eda9065261f5f 100644 (file)
@@ -15,7 +15,6 @@ import java.net.MalformedURLException;
 import javax.imageio.ImageIO;
 
 import be.nikiroo.fanfix.Instance;
-import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.library.BasicLibrary;
 import be.nikiroo.fanfix.reader.ui.GuiReaderBookInfo;
 import be.nikiroo.utils.Image;
@@ -110,18 +109,6 @@ class BookCoverImager {
                UIUtils.drawEllipse3D(g, UNCACHED_ICON_COLOR, COVER_WIDTH + HOFFSET + 30, 10, 20, 20, cached);
        }
 
-       /**
-        * Generate a cover icon based upon the given {@link MetaData}.
-        * 
-        * @param lib  the library the meta comes from
-        * @param meta the {@link MetaData}
-        * 
-        * @return the image
-        */
-       static public java.awt.Image generateCoverImage(BasicLibrary lib, MetaData meta) {
-               return generateCoverImage(lib, BookInfo.fromMeta(lib, meta));
-       }
-
        /**
         * The width of a cover image.
         * 
@@ -174,16 +161,18 @@ class BookCoverImager {
 
                                Graphics2D g = resizedImage.createGraphics();
                                try {
-                                       g.setColor(Color.white);
-                                       g.fillRect(0, HOFFSET, COVER_WIDTH, COVER_HEIGHT);
-
-                                       if (cover != null) {
-                                               BufferedImage coverb = ImageUtilsAwt.fromImage(cover);
-                                               g.drawImage(coverb, 0, HOFFSET, COVER_WIDTH, COVER_HEIGHT, null);
-                                       } else {
-                                               g.setColor(Color.black);
-                                               g.drawLine(0, HOFFSET, COVER_WIDTH, HOFFSET + COVER_HEIGHT);
-                                               g.drawLine(COVER_WIDTH, HOFFSET, 0, HOFFSET + COVER_HEIGHT);
+                                       if (info != null && info.supportsCover()) {
+                                               g.setColor(Color.white);
+                                               g.fillRect(0, HOFFSET, COVER_WIDTH, COVER_HEIGHT);
+                                               
+                                               if (cover != null) {
+                                                       BufferedImage coverb = ImageUtilsAwt.fromImage(cover);
+                                                       g.drawImage(coverb, 0, HOFFSET, COVER_WIDTH, COVER_HEIGHT, null);
+                                               } else {
+                                                       g.setColor(Color.black);
+                                                       g.drawLine(0, HOFFSET, COVER_WIDTH, HOFFSET + COVER_HEIGHT);
+                                                       g.drawLine(COVER_WIDTH, HOFFSET, 0, HOFFSET + COVER_HEIGHT);
+                                               }
                                        }
                                } finally {
                                        g.dispose();
index 6859cfab119d9bbecf8b122a8640373b3e6b2b68..72aee900d51893a25b31b8b1bacbc9878a2bd49a 100644 (file)
@@ -186,6 +186,16 @@ public class BookInfo {
 
                return null;
        }
+       
+       /**
+        * This {@link BookInfo} could have a cover (so we need to somehow represent
+        * that to the user).
+        * 
+        * @return TRUE if it does
+        */
+       public boolean supportsCover() {
+               return type != Type.TAG;
+       }
 
        /**
         * Create a new book describing the given {@link Story}.
diff --git a/src/be/nikiroo/fanfix_swing/gui/utils/DelayWorker.java b/src/be/nikiroo/fanfix_swing/gui/utils/DelayWorker.java
new file mode 100644 (file)
index 0000000..19a9b5c
--- /dev/null
@@ -0,0 +1,109 @@
+package be.nikiroo.fanfix_swing.gui.utils;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.SwingWorker;
+
+@SuppressWarnings("rawtypes")
+public class DelayWorker {
+       private Map<String, SwingWorker> lazyEnCours;
+       private Object lazyEnCoursLock;
+
+       private Object waiter;
+
+       private boolean cont;
+       private boolean paused;
+       private Thread loop;
+
+       public DelayWorker(final int delayMs) {
+               lazyEnCours = new HashMap<String, SwingWorker>();
+               lazyEnCoursLock = new Object();
+               waiter = new Object();
+               cont = true;
+               paused = false;
+
+               loop = new Thread(new Runnable() {
+                       @Override
+                       public void run() {
+                               while (cont) {
+                                       try {
+                                               Thread.sleep(delayMs);
+                                       } catch (InterruptedException e) {
+                                       }
+
+                                       List<SwingWorker> workers;
+                                       synchronized (lazyEnCoursLock) {
+                                               workers = new LinkedList<SwingWorker>(
+                                                               lazyEnCours.values());
+                                               lazyEnCours.clear();
+                                       }
+                                       for (SwingWorker worker : workers) {
+                                               worker.execute();
+                                       }
+
+                                       synchronized (waiter) {
+                                               do {
+                                                       try {
+                                                               if (cont)
+                                                                       waiter.wait();
+                                                       } catch (InterruptedException e) {
+                                                       }
+                                               } while (cont && paused);
+                                       }
+                               }
+                       }
+               });
+               loop.setDaemon(true);
+               loop.setName("Loop for DelayWorker");
+       }
+
+       // twice = not legal
+       public void start() {
+               loop.start();
+       }
+
+       public void pause() {
+               paused = true;
+       }
+
+       public boolean isPaused() {
+               return paused;
+       }
+
+       public void resume() {
+               synchronized (waiter) {
+                       paused = false;
+                       wakeup();
+               }
+       }
+
+       public void stop() {
+               synchronized (waiter) {
+                       cont = false;
+                       wakeup();
+               }
+       }
+
+       public void clear() {
+               synchronized (lazyEnCoursLock) {
+                       lazyEnCours.clear();
+               }
+       }
+
+       public <T, V> void delay(final String id, final SwingWorker<T, V> worker) {
+               synchronized (lazyEnCoursLock) {
+                       lazyEnCours.put(id, worker);
+               }
+
+               wakeup();
+       }
+
+       private void wakeup() {
+               synchronized (waiter) {
+                       waiter.notifyAll();
+               }
+       }
+}