link gui frame to search
[fanfix.git] / src / be / nikiroo / fanfix / reader / ui / GuiReaderFrame.java
index 4a9fa76320b612ea467add021a553fef96fb7bb8..77cd7e019ef4363113e7605330c7ae82386fea7a 100644 (file)
@@ -26,14 +26,18 @@ import javax.swing.filechooser.FileNameExtensionFilter;
 
 import be.nikiroo.fanfix.Instance;
 import be.nikiroo.fanfix.bundles.Config;
+import be.nikiroo.fanfix.bundles.StringIdGui;
 import be.nikiroo.fanfix.bundles.UiConfig;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Story;
+import be.nikiroo.fanfix.library.BasicLibrary;
 import be.nikiroo.fanfix.library.LocalLibrary;
 import be.nikiroo.fanfix.output.BasicOutput.OutputType;
 import be.nikiroo.fanfix.reader.BasicReader;
 import be.nikiroo.fanfix.reader.ui.GuiReaderMainPanel.FrameHelper;
 import be.nikiroo.fanfix.reader.ui.GuiReaderMainPanel.StoryRunnable;
+import be.nikiroo.fanfix.searchable.BasicSearchable;
+import be.nikiroo.fanfix.supported.SupportType;
 import be.nikiroo.utils.Progress;
 import be.nikiroo.utils.Version;
 import be.nikiroo.utils.ui.ConfigEditor;
@@ -51,8 +55,18 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
        private GuiReader reader;
        private GuiReaderMainPanel mainPanel;
 
-       private enum MoveAction {
-               SOURCE, TITLE, AUTHOR
+       /**
+        * The different modification actions you can use on {@link Story} items.
+        * 
+        * @author niki
+        */
+       private enum ChangeAction {
+               /** Change the source/type, that is, move it to another source. */
+               SOURCE,
+               /** Change its name. */
+               TITLE,
+               /** Change its author. */
+               AUTHOR
        }
 
        /**
@@ -65,7 +79,7 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         *            the type of {@link Story} to load, or NULL for all types
         */
        public GuiReaderFrame(GuiReader reader, String type) {
-               super(String.format("Fanfix %s Library", Version.getCurrentVersion()));
+               super(getAppTitle(reader.getLibrary().getLibraryName()));
 
                this.reader = reader;
 
@@ -73,7 +87,7 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
 
                setSize(800, 600);
                setLayout(new BorderLayout());
-               add(mainPanel);
+               add(mainPanel, BorderLayout.CENTER);
        }
 
        @Override
@@ -83,7 +97,8 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                popup.addSeparator();
                popup.add(createMenuItemExport());
                popup.add(createMenuItemMoveTo(true));
-               popup.add(createMenuItemSetCover());
+               popup.add(createMenuItemSetCoverForSource());
+               popup.add(createMenuItemSetCoverForAuthor());
                popup.add(createMenuItemClearCache());
                popup.add(createMenuItemRedownload());
                popup.addSeparator();
@@ -97,7 +112,7 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
        }
 
        @Override
-       public JPopupMenu createSourcePopup() {
+       public JPopupMenu createSourceAuthorPopup() {
                JPopupMenu popup = new JPopupMenu();
                popup.add(createMenuItemOpenBook());
                return popup;
@@ -105,26 +120,33 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
 
        @Override
        public void createMenu(boolean libOk) {
+               invalidate();
+
                JMenuBar bar = new JMenuBar();
 
-               JMenu file = new JMenu("File");
+               JMenu file = new JMenu(GuiReader.trans(StringIdGui.MENU_FILE));
                file.setMnemonic(KeyEvent.VK_F);
 
-               JMenuItem imprt = new JMenuItem("Import URL...", KeyEvent.VK_U);
+               JMenuItem imprt = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_IMPORT_URL),
+                               KeyEvent.VK_U);
                imprt.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                mainPanel.imprt(true);
                        }
                });
-               JMenuItem imprtF = new JMenuItem("Import File...", KeyEvent.VK_F);
+               JMenuItem imprtF = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_IMPORT_FILE),
+                               KeyEvent.VK_F);
                imprtF.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                mainPanel.imprt(false);
                        }
                });
-               JMenuItem exit = new JMenuItem("Exit", KeyEvent.VK_X);
+               JMenuItem exit = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_EXIT), KeyEvent.VK_X);
                exit.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
@@ -143,13 +165,17 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                file.add(createMenuItemRename(libOk));
                file.add(createMenuItemSetAuthor(libOk));
                file.addSeparator();
+               file.add(createMenuItemProperties());
+               file.addSeparator();
                file.add(exit);
 
                bar.add(file);
 
-               JMenu edit = new JMenu("Edit");
+               JMenu edit = new JMenu(GuiReader.trans(StringIdGui.MENU_EDIT));
                edit.setMnemonic(KeyEvent.VK_E);
 
+               edit.add(createMenuItemSetCoverForSource());
+               edit.add(createMenuItemSetCoverForAuthor());
                edit.add(createMenuItemClearCache());
                edit.add(createMenuItemRedownload());
                edit.addSeparator();
@@ -157,9 +183,28 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
 
                bar.add(edit);
 
-               JMenu view = new JMenu("View");
+               JMenu search = new JMenu(GuiReader.trans(StringIdGui.MENU_SEARCH));
+               search.setMnemonic(KeyEvent.VK_H);
+               for (final SupportType type : SupportType.values()) {
+                       BasicSearchable searchable = BasicSearchable.getSearchable(type);
+                       if (searchable != null) {
+                               JMenuItem searchItem = new JMenuItem(type.getSourceName());
+                               searchItem.addActionListener(new ActionListener() {
+                                       @Override
+                                       public void actionPerformed(ActionEvent e) {
+                                               reader.search(type, "", 1, 0);
+                                       }
+                               });
+                               search.add(searchItem);
+                       }
+               }
+
+               bar.add(search);
+
+               JMenu view = new JMenu(GuiReader.trans(StringIdGui.MENU_VIEW));
                view.setMnemonic(KeyEvent.VK_V);
-               JMenuItem vauthors = new JMenuItem("Author");
+               JMenuItem vauthors = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_VIEW_AUTHOR));
                vauthors.setMnemonic(KeyEvent.VK_A);
                vauthors.addActionListener(new ActionListener() {
                        @Override
@@ -169,7 +214,8 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                        }
                });
                view.add(vauthors);
-               JMenuItem vwords = new JMenuItem("Word count");
+               JMenuItem vwords = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_VIEW_WCOUNT));
                vwords.setMnemonic(KeyEvent.VK_W);
                vwords.addActionListener(new ActionListener() {
                        @Override
@@ -185,7 +231,7 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                if (libOk) {
                        groupedSources = reader.getLibrary().getSourcesGrouped();
                }
-               JMenu sources = new JMenu("Sources");
+               JMenu sources = new JMenu(GuiReader.trans(StringIdGui.MENU_SOURCES));
                sources.setMnemonic(KeyEvent.VK_S);
                populateMenuSA(sources, groupedSources, true);
                bar.add(sources);
@@ -194,12 +240,12 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                if (libOk) {
                        goupedAuthors = reader.getLibrary().getAuthorsGrouped();
                }
-               JMenu authors = new JMenu("Authors");
+               JMenu authors = new JMenu(GuiReader.trans(StringIdGui.MENU_AUTHORS));
                authors.setMnemonic(KeyEvent.VK_A);
                populateMenuSA(authors, goupedAuthors, false);
                bar.add(authors);
 
-               JMenu options = new JMenu("Options");
+               JMenu options = new JMenu(GuiReader.trans(StringIdGui.MENU_OPTIONS));
                options.setMnemonic(KeyEvent.VK_O);
                options.add(createMenuItemConfig());
                options.add(createMenuItemUiConfig());
@@ -212,20 +258,25 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
        private void populateMenuSA(JMenu menu,
                        Map<String, List<String>> groupedValues, boolean type) {
 
-               // "All" and "Listing" special items
-               JMenuItem item = new JMenuItem("All");
+               // "All" and "Listing" special items first
+               JMenuItem item = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_XXX_ALL_GROUPED));
                item.addActionListener(getActionOpenList(type, false));
                menu.add(item);
-               item = new JMenuItem("Listing");
+               item = new JMenuItem(GuiReader.trans(StringIdGui.MENU_XXX_ALL_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 = new JMenuItem(
+                                               value.isEmpty() ? GuiReader
+                                                               .trans(StringIdGui.MENU_AUTHORS_UNKNOWN)
+                                                               : value);
                                item.addActionListener(getActionOpen(value, type));
                                menu.add(item);
                        } else {
@@ -234,14 +285,21 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                                        // only one group of authors
                                        dir = menu;
                                } else {
-                                       dir = new JMenu(value.isEmpty() ? "[unknown]" : value);
+                                       dir = new JMenu(
+                                                       value.isEmpty() ? GuiReader
+                                                                       .trans(StringIdGui.MENU_AUTHORS_UNKNOWN)
+                                                                       : value);
                                }
 
                                for (String sub : list) {
                                        // " " instead of "" for the visual height
-                                       String itemName = sub.isEmpty() ? " " : sub;
-                                       String actualValue = value;
+                                       String itemName = sub;
+                                       if (itemName.isEmpty()) {
+                                               itemName = type ? " " : GuiReader
+                                                               .trans(StringIdGui.MENU_AUTHORS_UNKNOWN);
+                                       }
 
+                                       String actualValue = value;
                                        if (type) {
                                                if (!sub.isEmpty()) {
                                                        actualValue += "/" + sub;
@@ -300,7 +358,7 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         * @return the item
         */
        private JMenuItem createMenuItemConfig() {
-               final String title = "Fanfix Configuration";
+               final String title = GuiReader.trans(StringIdGui.TITLE_CONFIG);
                JMenuItem item = new JMenuItem(title);
                item.setMnemonic(KeyEvent.VK_F);
 
@@ -308,8 +366,8 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                ConfigEditor<Config> ed = new ConfigEditor<Config>(
-                                               Config.class, Instance.getConfig(),
-                                               "This is where you configure the options of the program.");
+                                               Config.class, Instance.getConfig(), GuiReader
+                                                               .trans(StringIdGui.SUBTITLE_CONFIG));
                                JFrame frame = new JFrame(title);
                                frame.add(ed);
                                frame.setSize(800, 600);
@@ -326,7 +384,7 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         * @return the item
         */
        private JMenuItem createMenuItemUiConfig() {
-               final String title = "UI Configuration";
+               final String title = GuiReader.trans(StringIdGui.TITLE_CONFIG_UI);
                JMenuItem item = new JMenuItem(title);
                item.setMnemonic(KeyEvent.VK_U);
 
@@ -334,8 +392,8 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                ConfigEditor<UiConfig> ed = new ConfigEditor<UiConfig>(
-                                               UiConfig.class, Instance.getUiConfig(),
-                                               "This is where you configure the graphical appearence of the program.");
+                                               UiConfig.class, Instance.getUiConfig(), GuiReader
+                                                               .trans(StringIdGui.SUBTITLE_CONFIG_UI));
                                JFrame frame = new JFrame(title);
                                frame.add(ed);
                                frame.setSize(800, 600);
@@ -355,51 +413,47 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                final JFileChooser fc = new JFileChooser();
                fc.setAcceptAllFileFilterUsed(false);
 
-               final Map<FileFilter, OutputType> filters = new HashMap<FileFilter, OutputType>();
+               // Add the "ALL" filters first, then the others
+               final Map<FileFilter, OutputType> otherFilters = new HashMap<FileFilter, OutputType>();
                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);
+                               fc.addChoosableFileFilter(createAllFilter(desc));
                        } else {
-                               filters.put(new FileNameExtensionFilter(desc, ext), type);
+                               otherFilters.put(new FileNameExtensionFilter(desc, ext), type);
                        }
                }
 
-               // First the "ALL" filters, then, the extension filters
-               for (Entry<FileFilter, OutputType> entry : filters.entrySet()) {
-                       if (!(entry.getKey() instanceof FileNameExtensionFilter)) {
-                               fc.addChoosableFileFilter(entry.getKey());
-                       }
-               }
-               for (Entry<FileFilter, OutputType> entry : filters.entrySet()) {
-                       if (entry.getKey() instanceof FileNameExtensionFilter) {
-                               fc.addChoosableFileFilter(entry.getKey());
-                       }
+               for (Entry<FileFilter, OutputType> entry : otherFilters.entrySet()) {
+                       fc.addChoosableFileFilter(entry.getKey());
                }
                //
 
-               JMenuItem export = new JMenuItem("Save as...", KeyEvent.VK_S);
+               JMenuItem export = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_EXPORT), KeyEvent.VK_S);
                export.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
                                if (selectedBook != null) {
-                                       fc.showDialog(GuiReaderFrame.this, "Save");
+                                       fc.showDialog(GuiReaderFrame.this,
+                                                       GuiReader.trans(StringIdGui.TITLE_SAVE));
                                        if (fc.getSelectedFile() != null) {
-                                               final OutputType type = filters.get(fc.getFileFilter());
+                                               final OutputType type = otherFilters.get(fc
+                                                               .getFileFilter());
                                                final String path = fc.getSelectedFile()
                                                                .getAbsolutePath()
                                                                + type.getDefaultExtension(false);
                                                final Progress pg = new Progress();
-                                               mainPanel.outOfUi(pg, new Runnable() {
+                                               mainPanel.outOfUi(pg, false, new Runnable() {
                                                        @Override
                                                        public void run() {
                                                                try {
                                                                        reader.getLibrary().export(
-                                                                                       selectedBook.getMeta().getLuid(),
-                                                                                       type, path, pg);
+                                                                                       selectedBook.getInfo().getMeta()
+                                                                                                       .getLuid(), type, path, pg);
                                                                } catch (IOException e) {
                                                                        Instance.getTraceHandler().error(e);
                                                                }
@@ -442,20 +496,22 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         * @return the item
         */
        private JMenuItem createMenuItemClearCache() {
-               JMenuItem refresh = new JMenuItem("Clear cache", KeyEvent.VK_C);
+               JMenuItem refresh = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_EDIT_CLEAR_CACHE),
+                               KeyEvent.VK_C);
                refresh.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
                                if (selectedBook != null) {
-                                       mainPanel.outOfUi(null, new Runnable() {
+                                       mainPanel.outOfUi(null, false, new Runnable() {
                                                @Override
                                                public void run() {
-                                                       reader.clearLocalReaderCache(selectedBook.getMeta()
-                                                                       .getLuid());
+                                                       reader.clearLocalReaderCache(selectedBook.getInfo()
+                                                                       .getMeta().getLuid());
                                                        selectedBook.setCached(false);
                                                        GuiReaderCoverImager.clearIcon(selectedBook
-                                                                       .getMeta());
+                                                                       .getInfo());
                                                        SwingUtilities.invokeLater(new Runnable() {
                                                                @Override
                                                                public void run() {
@@ -480,7 +536,8 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         * @return the item
         */
        private JMenuItem createMenuItemMoveTo(boolean libOk) {
-               JMenu changeTo = new JMenu("Move to");
+               JMenu changeTo = new JMenu(
+                               GuiReader.trans(StringIdGui.MENU_FILE_MOVE_TO));
                changeTo.setMnemonic(KeyEvent.VK_M);
 
                Map<String, List<String>> groupedSources = new HashMap<String, List<String>>();
@@ -488,8 +545,9 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                        groupedSources = reader.getLibrary().getSourcesGrouped();
                }
 
-               JMenuItem item = new JMenuItem("New type...");
-               item.addActionListener(createMoveAction(MoveAction.SOURCE, null));
+               JMenuItem item = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_MOVE_TO_NEW_TYPE));
+               item.addActionListener(createMoveAction(ChangeAction.SOURCE, null));
                changeTo.add(item);
                changeTo.addSeparator();
 
@@ -497,7 +555,8 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                        List<String> list = groupedSources.get(type);
                        if (list.size() == 1 && list.get(0).isEmpty()) {
                                item = new JMenuItem(type);
-                               item.addActionListener(createMoveAction(MoveAction.SOURCE, type));
+                               item.addActionListener(createMoveAction(ChangeAction.SOURCE,
+                                               type));
                                changeTo.add(item);
                        } else {
                                JMenu dir = new JMenu(type);
@@ -510,8 +569,8 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                                        }
 
                                        item = new JMenuItem(itemName);
-                                       item.addActionListener(createMoveAction(MoveAction.SOURCE,
-                                                       actualType));
+                                       item.addActionListener(createMoveAction(
+                                                       ChangeAction.SOURCE, actualType));
                                        dir.add(item);
                                }
                                changeTo.add(dir);
@@ -530,14 +589,16 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         * @return the item
         */
        private JMenuItem createMenuItemSetAuthor(boolean libOk) {
-               JMenu changeTo = new JMenu("Set author");
+               JMenu changeTo = new JMenu(
+                               GuiReader.trans(StringIdGui.MENU_FILE_SET_AUTHOR));
                changeTo.setMnemonic(KeyEvent.VK_A);
 
                // New author
-               JMenuItem newItem = new JMenuItem("New author...");
+               JMenuItem newItem = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_MOVE_TO_NEW_AUTHOR));
                changeTo.add(newItem);
                changeTo.addSeparator();
-               newItem.addActionListener(createMoveAction(MoveAction.AUTHOR, null));
+               newItem.addActionListener(createMoveAction(ChangeAction.AUTHOR, null));
 
                // Existing authors
                if (libOk) {
@@ -548,18 +609,24 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                                for (String key : groupedAuthors.keySet()) {
                                        JMenu group = new JMenu(key);
                                        for (String value : groupedAuthors.get(key)) {
-                                               JMenuItem item = new JMenuItem(value);
+                                               JMenuItem item = new JMenuItem(
+                                                               value.isEmpty() ? GuiReader
+                                                                               .trans(StringIdGui.MENU_AUTHORS_UNKNOWN)
+                                                                               : value);
                                                item.addActionListener(createMoveAction(
-                                                               MoveAction.AUTHOR, value));
+                                                               ChangeAction.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(MoveAction.AUTHOR,
-                                                       value));
+                                       JMenuItem item = new JMenuItem(
+                                                       value.isEmpty() ? GuiReader
+                                                                       .trans(StringIdGui.MENU_AUTHORS_UNKNOWN)
+                                                                       : value);
+                                       item.addActionListener(createMoveAction(
+                                                       ChangeAction.AUTHOR, value));
                                        changeTo.add(item);
                                }
                        }
@@ -578,34 +645,47 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         */
        private JMenuItem createMenuItemRename(
                        @SuppressWarnings("unused") boolean libOk) {
-               JMenuItem changeTo = new JMenuItem("Rename...");
+               JMenuItem changeTo = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_RENAME));
                changeTo.setMnemonic(KeyEvent.VK_R);
-               changeTo.addActionListener(createMoveAction(MoveAction.TITLE, null));
+               changeTo.addActionListener(createMoveAction(ChangeAction.TITLE, null));
                return changeTo;
        }
 
-       private ActionListener createMoveAction(final MoveAction what,
+       private ActionListener createMoveAction(final ChangeAction what,
                        final String type) {
                return new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
                                if (selectedBook != null) {
+                                       boolean refreshRequired = false;
+
+                                       if (what == ChangeAction.SOURCE) {
+                                               refreshRequired = mainPanel.getCurrentType();
+                                       } else if (what == ChangeAction.TITLE) {
+                                               refreshRequired = false;
+                                       } else if (what == ChangeAction.AUTHOR) {
+                                               refreshRequired = !mainPanel.getCurrentType();
+                                       }
+
                                        String changeTo = type;
                                        if (type == null) {
+                                               MetaData meta = selectedBook.getInfo().getMeta();
                                                String init = "";
-                                               if (what == MoveAction.SOURCE) {
-                                                       init = selectedBook.getMeta().getSource();
-                                               } else if (what == MoveAction.TITLE) {
-                                                       init = selectedBook.getMeta().getTitle();
-                                               } else if (what == MoveAction.AUTHOR) {
-                                                       init = selectedBook.getMeta().getAuthor();
+                                               if (what == ChangeAction.SOURCE) {
+                                                       init = meta.getSource();
+                                               } else if (what == ChangeAction.TITLE) {
+                                                       init = meta.getTitle();
+                                               } else if (what == ChangeAction.AUTHOR) {
+                                                       init = meta.getAuthor();
                                                }
 
                                                Object rep = JOptionPane.showInputDialog(
-                                                               GuiReaderFrame.this, "Move to:",
-                                                               "Moving story", JOptionPane.QUESTION_MESSAGE,
-                                                               null, null, init);
+                                                               GuiReaderFrame.this,
+                                                               GuiReader.trans(StringIdGui.SUBTITLE_MOVE_TO),
+                                                               GuiReader.trans(StringIdGui.TITLE_MOVE_TO),
+                                                               JOptionPane.QUESTION_MESSAGE, null, null, init);
 
                                                if (rep == null) {
                                                        return;
@@ -615,20 +695,20 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
                                        }
 
                                        final String fChangeTo = changeTo;
-                                       mainPanel.outOfUi(null, new Runnable() {
+                                       mainPanel.outOfUi(null, refreshRequired, 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);
+                                                       String luid = selectedBook.getInfo().getMeta()
+                                                                       .getLuid();
+                                                       if (what == ChangeAction.SOURCE) {
+                                                               reader.changeSource(luid, fChangeTo);
+                                                       } else if (what == ChangeAction.TITLE) {
+                                                               reader.changeTitle(luid, fChangeTo);
+                                                       } else if (what == ChangeAction.AUTHOR) {
+                                                               reader.changeAuthor(luid, fChangeTo);
                                                        }
 
+                                                       mainPanel.getSelectedBook().repaint();
                                                        mainPanel.unsetSelectedBook();
 
                                                        SwingUtilities.invokeLater(new Runnable() {
@@ -645,30 +725,30 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
        }
 
        /**
-        * Create the redownload (then delete original) menu item.
+        * Create the re-download (then delete original) menu item.
         * 
         * @return the item
         */
        private JMenuItem createMenuItemRedownload() {
-               JMenuItem refresh = new JMenuItem("Redownload", KeyEvent.VK_R);
+               JMenuItem refresh = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_EDIT_REDOWNLOAD),
+                               KeyEvent.VK_R);
                refresh.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
                                if (selectedBook != null) {
-                                       final MetaData meta = selectedBook.getMeta();
+                                       final MetaData meta = selectedBook.getInfo().getMeta();
                                        mainPanel.imprt(meta.getUrl(), new StoryRunnable() {
                                                @Override
                                                public void run(Story story) {
-                                                       reader.delete(meta.getLuid());
-                                                       mainPanel.unsetSelectedBook();
                                                        MetaData newMeta = story.getMeta();
                                                        if (!newMeta.getSource().equals(meta.getSource())) {
                                                                reader.changeSource(newMeta.getLuid(),
                                                                                meta.getSource());
                                                        }
                                                }
-                                       }, "Removing old copy");
+                                       }, GuiReader.trans(StringIdGui.PROGRESS_CHANGE_SOURCE));
                                }
                        }
                });
@@ -682,19 +762,32 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         * @return the item
         */
        private JMenuItem createMenuItemDelete() {
-               JMenuItem delete = new JMenuItem("Delete", KeyEvent.VK_D);
+               JMenuItem delete = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_EDIT_DELETE), KeyEvent.VK_D);
                delete.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
-                               if (selectedBook != null) {
-                                       mainPanel.outOfUi(null, new Runnable() {
-                                               @Override
-                                               public void run() {
-                                                       reader.delete(selectedBook.getMeta().getLuid());
-                                                       mainPanel.unsetSelectedBook();
-                                               }
-                                       });
+                               if (selectedBook != null
+                                               && selectedBook.getInfo().getMeta() != null) {
+
+                                       final MetaData meta = selectedBook.getInfo().getMeta();
+                                       int rep = JOptionPane.showConfirmDialog(
+                                                       GuiReaderFrame.this,
+                                                       GuiReader.trans(StringIdGui.SUBTITLE_DELETE,
+                                                                       meta.getLuid(), meta.getTitle()),
+                                                       GuiReader.trans(StringIdGui.TITLE_DELETE),
+                                                       JOptionPane.OK_CANCEL_OPTION);
+
+                                       if (rep == JOptionPane.OK_OPTION) {
+                                               mainPanel.outOfUi(null, true, new Runnable() {
+                                                       @Override
+                                                       public void run() {
+                                                               reader.delete(meta.getLuid());
+                                                               mainPanel.unsetSelectedBook();
+                                                       }
+                                               });
+                                       }
                                }
                        }
                });
@@ -708,17 +801,20 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         * @return the item
         */
        private JMenuItem createMenuItemProperties() {
-               JMenuItem delete = new JMenuItem("Properties", KeyEvent.VK_P);
+               JMenuItem delete = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_PROPERTIES),
+                               KeyEvent.VK_P);
                delete.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
                                if (selectedBook != null) {
-                                       mainPanel.outOfUi(null, new Runnable() {
+                                       mainPanel.outOfUi(null, false, new Runnable() {
                                                @Override
                                                public void run() {
-                                                       new GuiReaderPropertiesFrame(reader, selectedBook
-                                                                       .getMeta()).setVisible(true);
+                                                       new GuiReaderPropertiesFrame(reader.getLibrary(),
+                                                                       selectedBook.getInfo().getMeta())
+                                                                       .setVisible(true);
                                                }
                                        });
                                }
@@ -729,21 +825,22 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
        }
 
        /**
-        * Create the open menu item for a book or a source/type (no LUID).
+        * Create the open menu item for a book, a source/type or an author.
         * 
         * @return the item
         */
        public JMenuItem createMenuItemOpenBook() {
-               JMenuItem open = new JMenuItem("Open", KeyEvent.VK_O);
+               JMenuItem open = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_FILE_OPEN), KeyEvent.VK_O);
                open.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
                                if (selectedBook != null) {
-                                       if (selectedBook.getMeta().getLuid() == null) {
+                                       if (selectedBook.getInfo().getMeta() == null) {
                                                mainPanel.removeBookPanes();
-                                               mainPanel.addBookPane(selectedBook.getMeta()
-                                                               .getSource(), true);
+                                               mainPanel.addBookPane(selectedBook.getInfo()
+                                                               .getMainInfo(), mainPanel.getCurrentType());
                                                mainPanel.refreshBooks();
                                        } else {
                                                mainPanel.openBook(selectedBook);
@@ -761,19 +858,57 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
         * 
         * @return the item
         */
-       private JMenuItem createMenuItemSetCover() {
-               JMenuItem open = new JMenuItem("Set as cover for source", KeyEvent.VK_C);
+       private JMenuItem createMenuItemSetCoverForSource() {
+               JMenuItem open = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_EDIT_SET_COVER_FOR_SOURCE),
+                               KeyEvent.VK_C);
                open.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                                final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
                                if (selectedBook != null) {
-                                       reader.getLibrary().setSourceCover(
-                                                       selectedBook.getMeta().getSource(),
-                                                       selectedBook.getMeta().getLuid());
-                                       MetaData source = selectedBook.getMeta().clone();
-                                       source.setLuid(null);
-                                       GuiReaderCoverImager.clearIcon(source);
+                                       BasicLibrary lib = reader.getLibrary();
+                                       String luid = selectedBook.getInfo().getMeta().getLuid();
+                                       String source = selectedBook.getInfo().getMeta()
+                                                       .getSource();
+
+                                       lib.setSourceCover(source, luid);
+
+                                       GuiReaderBookInfo sourceInfo = GuiReaderBookInfo
+                                                       .fromSource(lib, source);
+                                       GuiReaderCoverImager.clearIcon(sourceInfo);
+                               }
+                       }
+               });
+
+               return open;
+       }
+
+       /**
+        * Create the SetCover menu item for a book to change the linked source
+        * cover.
+        * 
+        * @return the item
+        */
+       private JMenuItem createMenuItemSetCoverForAuthor() {
+               JMenuItem open = new JMenuItem(
+                               GuiReader.trans(StringIdGui.MENU_EDIT_SET_COVER_FOR_AUTHOR),
+                               KeyEvent.VK_A);
+               open.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               final GuiReaderBook selectedBook = mainPanel.getSelectedBook();
+                               if (selectedBook != null) {
+                                       BasicLibrary lib = reader.getLibrary();
+                                       String luid = selectedBook.getInfo().getMeta().getLuid();
+                                       String author = selectedBook.getInfo().getMeta()
+                                                       .getAuthor();
+
+                                       lib.setAuthorCover(author, luid);
+
+                                       GuiReaderBookInfo authorInfo = GuiReaderBookInfo
+                                                       .fromAuthor(lib, author);
+                                       GuiReaderCoverImager.clearIcon(authorInfo);
                                }
                        }
                });
@@ -810,4 +945,23 @@ class GuiReaderFrame extends JFrame implements FrameHelper {
        public GuiReader getReader() {
                return reader;
        }
+
+       /**
+        * Return the title of the application.
+        * 
+        * @param libraryName
+        *            the name of the associated {@link BasicLibrary}, which can be
+        *            EMPTY
+        * 
+        * @return the title
+        */
+       static private String getAppTitle(String libraryName) {
+               if (!libraryName.isEmpty()) {
+                       return GuiReader.trans(StringIdGui.TITLE_LIBRARY_WITH_NAME, Version
+                                       .getCurrentVersion().toString(), libraryName);
+               }
+
+               return GuiReader.trans(StringIdGui.TITLE_LIBRARY, Version
+                               .getCurrentVersion().toString());
+       }
 }