X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2Freader%2FLocalReaderFrame.java;h=a90360eed234bde1c99349844d687b02832bf70a;hb=793f1071fae48daed3b545a03a286c85e527d244;hp=e15ee8d17bb4889ac31061fc8313ad1bab6cb618;hpb=39c3c6896743a3b6e375d51499036bb32f752114;p=fanfix.git diff --git a/src/be/nikiroo/fanfix/reader/LocalReaderFrame.java b/src/be/nikiroo/fanfix/reader/LocalReaderFrame.java index e15ee8d..a90360e 100644 --- a/src/be/nikiroo/fanfix/reader/LocalReaderFrame.java +++ b/src/be/nikiroo/fanfix/reader/LocalReaderFrame.java @@ -3,6 +3,8 @@ package be.nikiroo.fanfix.reader; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Frame; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; @@ -11,12 +13,12 @@ import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import javax.swing.BoxLayout; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenu; @@ -40,7 +42,6 @@ import be.nikiroo.fanfix.reader.LocalReaderBook.BookActionListener; import be.nikiroo.utils.Progress; import be.nikiroo.utils.Version; import be.nikiroo.utils.ui.ProgressBar; -import be.nikiroo.utils.ui.WrapLayout; /** * A {@link Frame} that will show a {@link LocalReaderBook} item for each @@ -53,14 +54,14 @@ import be.nikiroo.utils.ui.WrapLayout; class LocalReaderFrame extends JFrame { private static final long serialVersionUID = 1L; private LocalReader reader; - private List stories; - private List books; - private JPanel bookPane; - private String type; + private Map booksByType; + private Map booksByAuthor; + private JPanel pane; private Color color; private ProgressBar pgBar; private JMenuBar bar; private LocalReaderBook selectedBook; + private boolean words; // words or authors (secondary info on books) /** * Create a new {@link LocalReaderFrame}. @@ -80,80 +81,128 @@ class LocalReaderFrame extends JFrame { setSize(800, 600); setLayout(new BorderLayout()); - books = new ArrayList(); - bookPane = new JPanel(new WrapLayout(WrapLayout.LEADING, 5, 5)); + pane = new JPanel(); + pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS)); color = Instance.getUiConfig().getColor(UiConfig.BACKGROUND_COLOR); - if (color != null) { setBackground(color); - bookPane.setBackground(color); + pane.setBackground(color); } - JScrollPane scroll = new JScrollPane(bookPane); + JScrollPane scroll = new JScrollPane(pane); scroll.getVerticalScrollBar().setUnitIncrement(16); add(scroll, BorderLayout.CENTER); pgBar = new ProgressBar(); add(pgBar, BorderLayout.SOUTH); - refreshBooks(type); setJMenuBar(createMenu()); + booksByType = new HashMap(); + booksByAuthor = new HashMap(); + + addBookPane(type, true); + refreshBooks(); + setVisible(true); } /** - * Refresh the list of {@link LocalReaderBook}s from disk. + * Add a new {@link LocalReaderGroup} on the frame to display the books of + * the selected type or author. * + * @param value + * the author or the type * @param type - * the type of {@link Story} to load, or NULL for all types + * TRUE for type, FALSE for author */ - private void refreshBooks(String type) { - this.type = type; - stories = Instance.getLibrary().getList(type); - books.clear(); - bookPane.invalidate(); - bookPane.removeAll(); - for (MetaData meta : stories) { - LocalReaderBook book = new LocalReaderBook(meta, - reader.isCached(meta.getLuid())); - if (color != null) { - book.setBackground(color); + private void addBookPane(String value, boolean type) { + if (value == null) { + if (type) { + for (String tt : Instance.getLibrary().getTypes()) { + if (tt != null) { + addBookPane(tt, type); + } + } + } else { + for (String tt : Instance.getLibrary().getAuthors()) { + if (tt != null) { + addBookPane(tt, type); + } + } } - books.add(book); + return; + } - book.addActionListener(new BookActionListener() { - public void select(LocalReaderBook book) { - selectedBook = book; - for (LocalReaderBook abook : books) { - abook.setSelected(abook == book); - } - } + LocalReaderGroup bookPane = new LocalReaderGroup(reader, value, color); + if (type) { + booksByType.put(bookPane, value); + } else { + booksByAuthor.put(bookPane, value); + } - public void popupRequested(LocalReaderBook book, MouseEvent e) { - JPopupMenu popup = new JPopupMenu(); - popup.add(createMenuItemOpenBook()); - popup.addSeparator(); - popup.add(createMenuItemExport()); - popup.add(createMenuItemClearCache()); - popup.add(createMenuItemRedownload()); - popup.addSeparator(); - popup.add(createMenuItemDelete()); - popup.show(e.getComponent(), e.getX(), e.getY()); - } + this.invalidate(); + pane.invalidate(); + pane.add(bookPane); + pane.validate(); + this.validate(); - public void action(final LocalReaderBook book) { - openBook(book); - } - }); + bookPane.setActionListener(new BookActionListener() { + public void select(LocalReaderBook book) { + selectedBook = book; + } + + public void popupRequested(LocalReaderBook book, MouseEvent e) { + JPopupMenu popup = new JPopupMenu(); + popup.add(createMenuItemOpenBook()); + popup.addSeparator(); + popup.add(createMenuItemExport()); + popup.add(createMenuItemClearCache()); + popup.add(createMenuItemRedownload()); + popup.addSeparator(); + popup.add(createMenuItemDelete()); + popup.show(e.getComponent(), e.getX(), e.getY()); + } + + public void action(final LocalReaderBook book) { + openBook(book); + } + }); + } + + private void removeBookPanes() { + booksByType.clear(); + booksByAuthor.clear(); + pane.invalidate(); + this.invalidate(); + pane.removeAll(); + pane.validate(); + this.validate(); + } + + /** + * Refresh the list of {@link LocalReaderBook}s from disk. + * + * @param type + * the type of {@link Story} to load, or NULL for all types + */ + private void refreshBooks() { + for (LocalReaderGroup group : booksByType.keySet()) { + List stories = Instance.getLibrary().getListByType( + booksByType.get(group)); + group.refreshBooks(stories, words); + } - bookPane.add(book); + for (LocalReaderGroup group : booksByAuthor.keySet()) { + List stories = Instance.getLibrary().getListByAuthor( + booksByAuthor.get(group)); + group.refreshBooks(stories, words); } - bookPane.validate(); - bookPane.repaint(); + pane.repaint(); + this.repaint(); } /** @@ -209,24 +258,72 @@ class LocalReaderFrame extends JFrame { JMenu view = new JMenu("View"); view.setMnemonic(KeyEvent.VK_V); + JMenuItem vauthors = new JMenuItem("Author"); + vauthors.setMnemonic(KeyEvent.VK_A); + vauthors.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + words = false; + refreshBooks(); + } + }); + view.add(vauthors); + JMenuItem vwords = new JMenuItem("Word count"); + vwords.setMnemonic(KeyEvent.VK_W); + vwords.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + words = true; + refreshBooks(); + } + }); + view.add(vwords); + bar.add(view); + + JMenu sources = new JMenu("Sources"); + sources.setMnemonic(KeyEvent.VK_S); List tt = Instance.getLibrary().getTypes(); tt.add(0, null); for (final String type : tt) { - JMenuItem item = new JMenuItem(type == null ? "All books" : type); + JMenuItem item = new JMenuItem(type == null ? "All" : type); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - refreshBooks(type); + removeBookPanes(); + addBookPane(type, true); + refreshBooks(); } }); - view.add(item); + sources.add(item); if (type == null) { - view.addSeparator(); + sources.addSeparator(); } } - bar.add(view); + bar.add(sources); + + JMenu authors = new JMenu("Authors"); + authors.setMnemonic(KeyEvent.VK_A); + + List aa = Instance.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() { + public void actionPerformed(ActionEvent e) { + removeBookPanes(); + addBookPane(author, false); + refreshBooks(); + } + }); + authors.add(item); + + if (author == null || author.isEmpty()) { + authors.addSeparator(); + } + } + + bar.add(authors); return bar; } @@ -244,6 +341,7 @@ class LocalReaderFrame extends JFrame { for (OutputType type : OutputType.values()) { String ext = type.getDefaultExtension(false); String desc = type.getDesc(false); + if (ext == null || ext.isEmpty()) { filters.put(createAllFilter(desc), type); } else { @@ -269,21 +367,24 @@ class LocalReaderFrame extends JFrame { public void actionPerformed(ActionEvent e) { if (selectedBook != null) { fc.showDialog(LocalReaderFrame.this, "Save"); - final OutputType type = filters.get(fc.getFileFilter()); - final String path = fc.getSelectedFile().getAbsolutePath() - + type.getDefaultExtension(false); - final Progress pg = new Progress(); - outOfUi(pg, new Runnable() { - public void run() { - try { - Instance.getLibrary().export( - selectedBook.getMeta().getLuid(), type, - path, pg); - } catch (IOException e) { - Instance.syserr(e); + if (fc.getSelectedFile() != null) { + final OutputType type = filters.get(fc.getFileFilter()); + final String path = fc.getSelectedFile() + .getAbsolutePath() + + type.getDefaultExtension(false); + final Progress pg = new Progress(); + outOfUi(pg, new Runnable() { + public void run() { + try { + Instance.getLibrary().export( + selectedBook.getMeta().getLuid(), + type, path, pg); + } catch (IOException e) { + Instance.syserr(e); + } } - } - }); + }); + } } } }); @@ -381,7 +482,7 @@ class LocalReaderFrame extends JFrame { selectedBook = null; SwingUtilities.invokeLater(new Runnable() { public void run() { - refreshBooks(type); + refreshBooks(); } }); } @@ -486,19 +587,32 @@ class LocalReaderFrame extends JFrame { private void imprt(boolean askUrl) { JFileChooser fc = new JFileChooser(); - String url; + Object url; if (askUrl) { + String clipboard = ""; + try { + clipboard = ("" + Toolkit.getDefaultToolkit() + .getSystemClipboard().getData(DataFlavor.stringFlavor)) + .trim(); + } catch (Exception e) { + // No data will be handled + } + + if (clipboard == null || !clipboard.startsWith("http")) { + clipboard = ""; + } + url = JOptionPane.showInputDialog(LocalReaderFrame.this, "url of the story to import?", "Importing from URL", - JOptionPane.QUESTION_MESSAGE); + JOptionPane.QUESTION_MESSAGE, null, null, clipboard); } else if (fc.showOpenDialog(this) != JFileChooser.CANCEL_OPTION) { url = fc.getSelectedFile().getAbsolutePath(); } else { url = null; } - if (url != null && !url.isEmpty()) { - imprt(url, null); + if (url != null && !url.toString().isEmpty()) { + imprt(url.toString(), null); } } @@ -537,10 +651,10 @@ class LocalReaderFrame extends JFrame { setEnabled(true); } else { - refreshBooks(type); + refreshBooks(); if (onSuccess != null) { onSuccess.run(); - refreshBooks(type); + refreshBooks(); } } } @@ -562,15 +676,13 @@ class LocalReaderFrame extends JFrame { */ @Override public void setEnabled(boolean b) { - for (LocalReaderBook book : books) { - book.setEnabled(b); - book.repaint(); - } - bar.setEnabled(b); - bookPane.setEnabled(b); - bookPane.repaint(); - + for (LocalReaderGroup group : booksByType.keySet()) { + group.setEnabled(b); + } + for (LocalReaderGroup group : booksByAuthor.keySet()) { + group.setEnabled(b); + } super.setEnabled(b); repaint(); }