gui: allow 'all' and 'listing' for sources and authors
[fanfix.git] / src / be / nikiroo / fanfix / reader / ui / GuiReaderFrame.java
index 39187b968b39a970849294f4fe1ac1f046f0199e..d28f941e933e9d2c53e2cbd3f5db4491cad82ec6 100644 (file)
@@ -2,6 +2,7 @@ package be.nikiroo.fanfix.reader.ui;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Font;
 import java.awt.Frame;
 import java.awt.Toolkit;
 import java.awt.datatransfer.DataFlavor;
@@ -20,7 +21,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
 import javax.swing.JFileChooser;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
@@ -31,6 +34,7 @@ import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
 import javax.swing.SwingConstants;
 import javax.swing.SwingUtilities;
 import javax.swing.filechooser.FileFilter;
@@ -164,7 +168,11 @@ class GuiReaderFrame extends JFrame {
                                        lib.refresh(pg);
                                        invalidate();
                                        setJMenuBar(createMenu(true));
-                                       addBookPane(typeF, true);
+                                       if (typeF == null) {
+                                               addBookPane(true, false);
+                                       } else {
+                                               addBookPane(typeF, true);
+                                       }
                                        refreshBooks();
                                        validate();
                                        pane.setVisible(true);
@@ -200,20 +208,21 @@ class GuiReaderFrame extends JFrame {
                setVisible(true);
        }
 
-       private void addSourcePanes() {
+       private void addListPane(String name, List<String> values,
+                       final boolean type) {
                // Sources -> i18n
-               GuiReaderGroup bookPane = new GuiReaderGroup(reader, "Sources", color);
+               GuiReaderGroup bookPane = new GuiReaderGroup(reader, name, color);
 
-               List<MetaData> sources = new ArrayList<MetaData>();
-               for (String source : reader.getLibrary().getSources()) {
+               List<MetaData> metas = new ArrayList<MetaData>();
+               for (String source : values) {
                        MetaData mSource = new MetaData();
                        mSource.setLuid(null);
                        mSource.setTitle(source);
                        mSource.setSource(source);
-                       sources.add(mSource);
+                       metas.add(mSource);
                }
 
-               bookPane.refreshBooks(sources, false);
+               bookPane.refreshBooks(metas, false);
 
                this.invalidate();
                pane.invalidate();
@@ -237,35 +246,43 @@ class GuiReaderFrame extends JFrame {
                        @Override
                        public void action(final GuiReaderBook book) {
                                removeBookPanes();
-                               addBookPane(book.getMeta().getSource(), true);
+                               addBookPane(book.getMeta().getSource(), type);
                                refreshBooks();
                        }
                });
        }
 
        /**
-        * Add a new {@link GuiReaderGroup} on the frame to display the books of the
-        * selected type or author.
+        * Add a new {@link GuiReaderGroup} on the frame to display all the
+        * sources/types or all the authors, or a listing of all the books sorted
+        * either by source or author.
+        * <p>
+        * A display of all the sources/types or all the authors will show one icon
+        * per source/type or author.
+        * <p>
+        * A listing of all the books sorted by source/type or author will display
+        * all the books.
         * 
-        * @param value
-        *            the author or the type, or NULL to get all the
-        *            authors-or-types
         * @param type
-        *            TRUE for type, FALSE for author
+        *            TRUE for type/source, FALSE for author
+        * @param listMode
+        *            TRUE to get a listing of all the sources or authors, FALSE to
+        *            get one icon per source or author
         */
-       private void addBookPane(String value, boolean type) {
-               if (value == null) {
-                       if (type) {
-                               if (Instance.getUiConfig().getBoolean(UiConfig.SOURCE_PAGE,
-                                               false)) {
-                                       addSourcePanes();
-                               } else {
-                                       for (String tt : reader.getLibrary().getSources()) {
-                                               if (tt != null) {
-                                                       addBookPane(tt, type);
-                                               }
+       private void addBookPane(boolean type, boolean listMode) {
+               if (type) {
+                       if (!listMode) {
+                               addListPane("Sources", reader.getLibrary().getSources(), type);
+                       } else {
+                               for (String tt : reader.getLibrary().getSources()) {
+                                       if (tt != null) {
+                                               addBookPane(tt, type);
                                        }
                                }
+                       }
+               } else {
+                       if (!listMode) {
+                               addListPane("Authors", reader.getLibrary().getAuthors(), type);
                        } else {
                                for (String tt : reader.getLibrary().getAuthors()) {
                                        if (tt != null) {
@@ -273,10 +290,21 @@ class GuiReaderFrame extends JFrame {
                                        }
                                }
                        }
-
-                       return;
                }
+       }
 
+       /**
+        * Add a new {@link GuiReaderGroup} on the frame to display the books of the
+        * selected type or author.
+        * 
+        * @param value
+        *            the author or the type, or NULL to get all the
+        *            authors-or-types
+        * @param type
+        *            TRUE for type/source, FALSE for author
+        * 
+        */
+       private void addBookPane(String value, boolean type) {
                GuiReaderGroup bookPane = new GuiReaderGroup(reader, value, color);
                if (type) {
                        booksByType.put(bookPane, value);
@@ -302,12 +330,17 @@ class GuiReaderFrame extends JFrame {
                                popup.add(createMenuItemOpenBook());
                                popup.addSeparator();
                                popup.add(createMenuItemExport());
-                               popup.add(createMenuItemMove(true));
+                               popup.add(createMenuItemMoveTo(true));
                                popup.add(createMenuItemSetCover());
                                popup.add(createMenuItemClearCache());
                                popup.add(createMenuItemRedownload());
                                popup.addSeparator();
+                               popup.add(createMenuItemRename(true));
+                               popup.add(createMenuItemSetAuthor(true));
+                               popup.addSeparator();
                                popup.add(createMenuItemDelete());
+                               popup.addSeparator();
+                               popup.add(createMenuItemProperties());
                                popup.show(e.getComponent(), e.getX(), e.getY());
                        }
 
@@ -318,6 +351,10 @@ class GuiReaderFrame extends JFrame {
                });
        }
 
+       /**
+        * Clear the pane from any book that may be present, usually prior to adding
+        * new ones.
+        */
        private void removeBookPanes() {
                booksByType.clear();
                booksByAuthor.clear();
@@ -387,11 +424,14 @@ class GuiReaderFrame extends JFrame {
 
                file.add(createMenuItemOpenBook());
                file.add(createMenuItemExport());
-               file.add(createMenuItemMove(libOk));
+               file.add(createMenuItemMoveTo(libOk));
                file.addSeparator();
                file.add(imprt);
                file.add(imprtF);
                file.addSeparator();
+               file.add(createMenuItemRename(libOk));
+               file.add(createMenuItemSetAuthor(libOk));
+               file.addSeparator();
                file.add(exit);
 
                bar.add(file);
@@ -430,60 +470,22 @@ class GuiReaderFrame extends JFrame {
                view.add(vwords);
                bar.add(view);
 
+               Map<String, List<String>> groupedSources = new HashMap<String, List<String>>();
+               if (libOk) {
+                       groupedSources = reader.getLibrary().getSourcesGrouped();
+               }
                JMenu sources = new JMenu("Sources");
                sources.setMnemonic(KeyEvent.VK_S);
+               populateMenuSA(sources, groupedSources, true);
+               bar.add(sources);
 
-               List<String> tt = new ArrayList<String>();
+               Map<String, List<String>> goupedAuthors = new HashMap<String, List<String>>();
                if (libOk) {
-                       tt.addAll(reader.getLibrary().getSources());
+                       goupedAuthors = reader.getLibrary().getAuthorsGrouped();
                }
-               tt.add(0, null);
-
-               for (final String type : tt) {
-                       JMenuItem item = new JMenuItem(type == null ? "All" : type);
-                       item.addActionListener(new ActionListener() {
-                               @Override
-                               public void actionPerformed(ActionEvent e) {
-                                       removeBookPanes();
-                                       addBookPane(type, true);
-                                       refreshBooks();
-                               }
-                       });
-                       sources.add(item);
-
-                       if (type == null) {
-                               sources.addSeparator();
-                       }
-               }
-
-               bar.add(sources);
-
                JMenu authors = new JMenu("Authors");
                authors.setMnemonic(KeyEvent.VK_A);
-
-               List<String> aa = new ArrayList<String>();
-               if (libOk) {
-                       aa.addAll(reader.getLibrary().getAuthors());
-               }
-               aa.add(0, null);
-               for (final String author : aa) {
-                       JMenuItem item = new JMenuItem(author == null ? "All"
-                                       : author.isEmpty() ? "[unknown]" : author);
-                       item.addActionListener(new ActionListener() {
-                               @Override
-                               public void actionPerformed(ActionEvent e) {
-                                       removeBookPanes();
-                                       addBookPane(author, false);
-                                       refreshBooks();
-                               }
-                       });
-                       authors.add(item);
-
-                       if (author == null || author.isEmpty()) {
-                               authors.addSeparator();
-                       }
-               }
-
+               populateMenuSA(authors, goupedAuthors, false);
                bar.add(authors);
 
                JMenu options = new JMenu("Options");
@@ -495,6 +497,92 @@ class GuiReaderFrame extends JFrame {
                return bar;
        }
 
+       // "" = [unknown]
+       private void populateMenuSA(JMenu menu,
+                       Map<String, List<String>> groupedValues, boolean type) {
+
+               // "All" and "Listing" special items
+               JMenuItem item = new JMenuItem("All");
+               item.addActionListener(getActionOpenList(type, false));
+               menu.add(item);
+               item = new JMenuItem("Listing");
+               item.addActionListener(getActionOpenList(type, true));
+               menu.add(item);
+               menu.addSeparator();
+
+               for (final String value : groupedValues.keySet()) {
+                       List<String> list = groupedValues.get(value);
+                       if (type && list.size() == 1 && list.get(0).isEmpty()) {
+                               // leaf item source/type
+                               item = new JMenuItem(value.isEmpty() ? "[unknown]" : value);
+                               item.addActionListener(getActionOpen(value, type));
+                               menu.add(item);
+                       } else {
+                               JMenu dir;
+                               if (!type && groupedValues.size() == 1) {
+                                       // only one group of authors
+                                       dir = menu;
+                               } else {
+                                       dir = new JMenu(value.isEmpty() ? "[unknown]" : value);
+                               }
+
+                               for (String sub : list) {
+                                       // " " instead of "" for the visual height
+                                       String itemName = sub.isEmpty() ? " " : sub;
+                                       String actualValue = value;
+
+                                       if (type) {
+                                               if (!sub.isEmpty()) {
+                                                       actualValue += "/" + sub;
+                                               }
+                                       } else {
+                                               actualValue = sub;
+                                       }
+
+                                       item = new JMenuItem(itemName);
+                                       item.addActionListener(getActionOpen(actualValue, type));
+                                       dir.add(item);
+                               }
+
+                               if (menu != dir) {
+                                       menu.add(dir);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Return an {@link ActionListener} that will set the given source (type) as
+        * the selected/displayed one.
+        * 
+        * @param type
+        *            the type (source) to select, cannot be NULL
+        * 
+        * @return the {@link ActionListener}
+        */
+       private ActionListener getActionOpen(final String source, final boolean type) {
+               return new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               removeBookPanes();
+                               addBookPane(source, type);
+                               refreshBooks();
+                       }
+               };
+       }
+
+       private ActionListener getActionOpenList(final boolean type,
+                       final boolean listMode) {
+               return new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               removeBookPanes();
+                               addBookPane(type, listMode);
+                               refreshBooks();
+                       }
+               };
+       }
+
        /**
         * Create the Fanfix Configuration menu item.
         * 
@@ -653,7 +741,8 @@ class GuiReaderFrame extends JFrame {
                                                        reader.clearLocalReaderCache(selectedBook.getMeta()
                                                                        .getLuid());
                                                        selectedBook.setCached(false);
-                                                       GuiReaderBook.clearIcon(selectedBook.getMeta());
+                                                       GuiReaderCoverImager.clearIcon(selectedBook
+                                                                       .getMeta());
                                                        SwingUtilities.invokeLater(new Runnable() {
                                                                @Override
                                                                public void run() {
@@ -670,74 +759,172 @@ class GuiReaderFrame extends JFrame {
        }
 
        /**
-        * Create the delete menu item.
+        * Create the "move to" menu item.
         * 
         * @param libOk
         *            the library can be queried
         * 
         * @return the item
         */
-       private JMenuItem createMenuItemMove(boolean libOk) {
-               JMenu moveTo = new JMenu("Move to...");
-               moveTo.setMnemonic(KeyEvent.VK_M);
+       private JMenuItem createMenuItemMoveTo(boolean libOk) {
+               JMenu changeTo = new JMenu("Move to");
+               changeTo.setMnemonic(KeyEvent.VK_M);
 
-               List<String> types = new ArrayList<String>();
-               types.add(null);
+               Map<String, List<String>> groupedSources = new HashMap<String, List<String>>();
                if (libOk) {
-                       types.addAll(reader.getLibrary().getSources());
+                       groupedSources = reader.getLibrary().getSourcesGrouped();
                }
 
-               for (String type : types) {
-                       JMenuItem item = new JMenuItem(type == null ? "New type..." : type);
+               JMenuItem item = new JMenuItem("New type...");
+               item.addActionListener(createMoveAction("SOURCE", null));
+               changeTo.add(item);
+               changeTo.addSeparator();
+
+               for (final String type : groupedSources.keySet()) {
+                       List<String> list = groupedSources.get(type);
+                       if (list.size() == 1 && list.get(0).isEmpty()) {
+                               item = new JMenuItem(type);
+                               item.addActionListener(createMoveAction("SOURCE", type));
+                               changeTo.add(item);
+                       } else {
+                               JMenu dir = new JMenu(type);
+                               for (String sub : list) {
+                                       // " " instead of "" for the visual height
+                                       String itemName = sub.isEmpty() ? " " : sub;
+                                       String actualType = type;
+                                       if (!sub.isEmpty()) {
+                                               actualType += "/" + sub;
+                                       }
 
-                       moveTo.add(item);
-                       if (type == null) {
-                               moveTo.addSeparator();
+                                       item = new JMenuItem(itemName);
+                                       item.addActionListener(createMoveAction("SOURCE",
+                                                       actualType));
+                                       dir.add(item);
+                               }
+                               changeTo.add(dir);
                        }
+               }
 
-                       final String ftype = type;
-                       item.addActionListener(new ActionListener() {
-                               @Override
-                               public void actionPerformed(ActionEvent e) {
-                                       if (selectedBook != null) {
-                                               String type = ftype;
-                                               if (type == null) {
-                                                       Object rep = JOptionPane.showInputDialog(
-                                                                       GuiReaderFrame.this, "Move to:",
-                                                                       "Moving story",
-                                                                       JOptionPane.QUESTION_MESSAGE, null, null,
-                                                                       selectedBook.getMeta().getSource());
-
-                                                       if (rep == null) {
-                                                               return;
-                                                       }
-
-                                                       type = rep.toString();
-                                               }
+               return changeTo;
+       }
 
-                                               final String ftype = type;
-                                               outOfUi(null, new Runnable() {
-                                                       @Override
-                                                       public void run() {
-                                                               reader.changeSource(selectedBook.getMeta()
-                                                                               .getLuid(), ftype);
+       /**
+        * Create the "set author" menu item.
+        * 
+        * @param libOk
+        *            the library can be queried
+        * 
+        * @return the item
+        */
+       private JMenuItem createMenuItemSetAuthor(boolean libOk) {
+               JMenu changeTo = new JMenu("Set author");
+               changeTo.setMnemonic(KeyEvent.VK_A);
 
-                                                               selectedBook = null;
+               // New author
+               JMenuItem newItem = new JMenuItem("New author...");
+               changeTo.add(newItem);
+               changeTo.addSeparator();
+               newItem.addActionListener(createMoveAction("AUTHOR", null));
 
-                                                               SwingUtilities.invokeLater(new Runnable() {
-                                                                       @Override
-                                                                       public void run() {
-                                                                               setJMenuBar(createMenu(true));
-                                                                       }
-                                                               });
-                                                       }
-                                               });
+               // Existing authors
+               if (libOk) {
+                       Map<String, List<String>> groupedAuthors = reader.getLibrary()
+                                       .getAuthorsGrouped();
+
+                       if (groupedAuthors.size() > 1) {
+                               for (String key : groupedAuthors.keySet()) {
+                                       JMenu group = new JMenu(key);
+                                       for (String value : groupedAuthors.get(key)) {
+                                               JMenuItem item = new JMenuItem(value);
+                                               item.addActionListener(createMoveAction("AUTHOR", value));
+                                               group.add(item);
                                        }
+                                       changeTo.add(group);
+                               }
+                       } else if (groupedAuthors.size() == 1) {
+                               for (String value : groupedAuthors.values().iterator().next()) {
+                                       JMenuItem item = new JMenuItem(value);
+                                       item.addActionListener(createMoveAction("AUTHOR", value));
+                                       changeTo.add(item);
                                }
-                       });
+                       }
                }
 
-               return moveTo;
+               return changeTo;
+       }
+
+       /**
+        * Create the "rename" menu item.
+        * 
+        * @param libOk
+        *            the library can be queried
+        * 
+        * @return the item
+        */
+       private JMenuItem createMenuItemRename(
+                       @SuppressWarnings("unused") boolean libOk) {
+               JMenuItem changeTo = new JMenuItem("Rename...");
+               changeTo.setMnemonic(KeyEvent.VK_R);
+               changeTo.addActionListener(createMoveAction("TITLE", null));
+               return changeTo;
+       }
+
+       private ActionListener createMoveAction(final String what, final String type) {
+               return new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               if (selectedBook != null) {
+                                       String changeTo = type;
+                                       if (type == null) {
+                                               String init = "";
+                                               if (what.equals("SOURCE")) {
+                                                       init = selectedBook.getMeta().getSource();
+                                               } else if (what.equals("TITLE")) {
+                                                       init = selectedBook.getMeta().getTitle();
+                                               } else if (what.equals("AUTHOR")) {
+                                                       init = selectedBook.getMeta().getAuthor();
+                                               }
+
+                                               Object rep = JOptionPane.showInputDialog(
+                                                               GuiReaderFrame.this, "Move to:",
+                                                               "Moving story", JOptionPane.QUESTION_MESSAGE,
+                                                               null, null, init);
+
+                                               if (rep == null) {
+                                                       return;
+                                               }
+
+                                               changeTo = rep.toString();
+                                       }
+
+                                       final String fChangeTo = changeTo;
+                                       outOfUi(null, new Runnable() {
+                                               @Override
+                                               public void run() {
+                                                       if (what.equals("SOURCE")) {
+                                                               reader.changeSource(selectedBook.getMeta()
+                                                                               .getLuid(), fChangeTo);
+                                                       } else if (what.equals("TITLE")) {
+                                                               reader.changeTitle(selectedBook.getMeta()
+                                                                               .getLuid(), fChangeTo);
+                                                       } else if (what.equals("AUTHOR")) {
+                                                               reader.changeAuthor(selectedBook.getMeta()
+                                                                               .getLuid(), fChangeTo);
+                                                       }
+
+                                                       selectedBook = null;
+
+                                                       SwingUtilities.invokeLater(new Runnable() {
+                                                               @Override
+                                                               public void run() {
+                                                                       setJMenuBar(createMenu(true));
+                                                               }
+                                                       });
+                                               }
+                                       });
+                               }
+                       }
+               };
        }
 
        /**
@@ -796,6 +983,110 @@ class GuiReaderFrame extends JFrame {
                return delete;
        }
 
+       /**
+        * Create the properties menu item.
+        * 
+        * @return the item
+        */
+       private JMenuItem createMenuItemProperties() {
+               JMenuItem delete = new JMenuItem("Properties", KeyEvent.VK_P);
+               delete.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               if (selectedBook != null) {
+                                       outOfUi(null, new Runnable() {
+                                               @Override
+                                               public void run() {
+                                                       final MetaData meta = selectedBook.getMeta();
+                                                       new JFrame() {
+                                                               private static final long serialVersionUID = 1L;
+                                                               @SuppressWarnings("unused")
+                                                               private Object init = init();
+
+                                                               private Object init() {
+                                                                       // Borders
+                                                                       int top = 20;
+                                                                       int space = 10;
+
+                                                                       // Image
+                                                                       ImageIcon img = GuiReaderCoverImager
+                                                                                       .generateCoverIcon(
+                                                                                                       reader.getLibrary(), meta);
+
+                                                                       // frame
+                                                                       setTitle(meta.getLuid() + ": "
+                                                                                       + meta.getTitle());
+
+                                                                       setSize(800, img.getIconHeight() + 2 * top);
+                                                                       setLayout(new BorderLayout());
+
+                                                                       // Main panel
+                                                                       JPanel mainPanel = new JPanel(
+                                                                                       new BorderLayout());
+                                                                       JPanel mainPanelKeys = new JPanel();
+                                                                       mainPanelKeys.setLayout(new BoxLayout(
+                                                                                       mainPanelKeys, BoxLayout.Y_AXIS));
+                                                                       JPanel mainPanelValues = new JPanel();
+                                                                       mainPanelValues.setLayout(new BoxLayout(
+                                                                                       mainPanelValues, BoxLayout.Y_AXIS));
+
+                                                                       mainPanel.add(mainPanelKeys,
+                                                                                       BorderLayout.WEST);
+                                                                       mainPanel.add(mainPanelValues,
+                                                                                       BorderLayout.CENTER);
+
+                                                                       List<Entry<String, String>> infos = BasicReader
+                                                                                       .getMetaDesc(meta);
+
+                                                                       Color trans = new Color(0, 0, 0, 1);
+                                                                       for (Entry<String, String> info : infos) {
+                                                                               JTextArea key = new JTextArea(info
+                                                                                               .getKey());
+                                                                               key.setFont(new Font(key.getFont()
+                                                                                               .getFontName(), Font.BOLD, key
+                                                                                               .getFont().getSize()));
+                                                                               key.setEditable(false);
+                                                                               key.setLineWrap(false);
+                                                                               key.setBackground(trans);
+                                                                               mainPanelKeys.add(key);
+
+                                                                               JTextArea value = new JTextArea(info
+                                                                                               .getValue());
+                                                                               value.setEditable(false);
+                                                                               value.setLineWrap(false);
+                                                                               value.setBackground(trans);
+                                                                               mainPanelValues.add(value);
+                                                                       }
+
+                                                                       // Image
+                                                                       JLabel imgLabel = new JLabel(img);
+                                                                       imgLabel.setVerticalAlignment(JLabel.TOP);
+
+                                                                       // Borders
+                                                                       mainPanelKeys.setBorder(BorderFactory
+                                                                                       .createEmptyBorder(top, space, 0, 0));
+                                                                       mainPanelValues.setBorder(BorderFactory
+                                                                                       .createEmptyBorder(top, space, 0, 0));
+                                                                       imgLabel.setBorder(BorderFactory
+                                                                                       .createEmptyBorder(0, space, 0, 0));
+
+                                                                       // Add all
+                                                                       add(imgLabel, BorderLayout.WEST);
+                                                                       add(mainPanel, BorderLayout.CENTER);
+
+                                                                       return null;
+                                                               }
+
+                                                       }.setVisible(true);
+                                               }
+                                       });
+                               }
+                       }
+               });
+
+               return delete;
+       }
+
        /**
         * Create the open menu item for a book or a source (no LUID).
         * 
@@ -838,7 +1129,7 @@ class GuiReaderFrame extends JFrame {
                                                        selectedBook.getMeta().getLuid());
                                        MetaData source = selectedBook.getMeta().clone();
                                        source.setLuid(null);
-                                       GuiReaderBook.clearIcon(source);
+                                       GuiReaderCoverImager.clearIcon(source);
                                }
                        }
                });
@@ -858,7 +1149,7 @@ class GuiReaderFrame extends JFrame {
                        @Override
                        public void run() {
                                try {
-                                       reader.read(book.getMeta().getLuid(), pg);
+                                       reader.read(book.getMeta().getLuid(), false, pg);
                                        SwingUtilities.invokeLater(new Runnable() {
                                                @Override
                                                public void run() {