X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2Freader%2Fui%2FGuiReaderFrame.java;h=d28f941e933e9d2c53e2cbd3f5db4491cad82ec6;hb=97b36d32a43b7fbbd4938c95c4b40db0c68daa71;hp=39187b968b39a970849294f4fe1ac1f046f0199e;hpb=c3b229a10b147a2ca104a13ad0b43e49549b4ed9;p=fanfix.git diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReaderFrame.java b/src/be/nikiroo/fanfix/reader/ui/GuiReaderFrame.java index 39187b9..d28f941 100644 --- a/src/be/nikiroo/fanfix/reader/ui/GuiReaderFrame.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReaderFrame.java @@ -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 values, + final boolean type) { // Sources -> i18n - GuiReaderGroup bookPane = new GuiReaderGroup(reader, "Sources", color); + GuiReaderGroup bookPane = new GuiReaderGroup(reader, name, color); - List sources = new ArrayList(); - for (String source : reader.getLibrary().getSources()) { + List metas = new ArrayList(); + 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. + *

+ * A display of all the sources/types or all the authors will show one icon + * per source/type or author. + *

+ * 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> groupedSources = new HashMap>(); + if (libOk) { + groupedSources = reader.getLibrary().getSourcesGrouped(); + } JMenu sources = new JMenu("Sources"); sources.setMnemonic(KeyEvent.VK_S); + populateMenuSA(sources, groupedSources, true); + bar.add(sources); - List tt = new ArrayList(); + Map> goupedAuthors = new HashMap>(); 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 aa = new ArrayList(); - 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> 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 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 types = new ArrayList(); - types.add(null); + Map> groupedSources = new HashMap>(); 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 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> 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> infos = BasicReader + .getMetaDesc(meta); + + Color trans = new Color(0, 0, 0, 1); + for (Entry 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() {