1 package be
.nikiroo
.fanfix
.reader
.ui
;
3 import java
.awt
.BorderLayout
;
5 import java
.awt
.event
.ActionEvent
;
6 import java
.awt
.event
.ActionListener
;
7 import java
.awt
.event
.KeyAdapter
;
8 import java
.awt
.event
.KeyEvent
;
9 import java
.awt
.event
.WindowEvent
;
11 import java
.io
.IOException
;
12 import java
.util
.HashMap
;
13 import java
.util
.List
;
15 import java
.util
.Map
.Entry
;
17 import javax
.swing
.JFileChooser
;
18 import javax
.swing
.JFrame
;
19 import javax
.swing
.JMenu
;
20 import javax
.swing
.JMenuBar
;
21 import javax
.swing
.JMenuItem
;
22 import javax
.swing
.JOptionPane
;
23 import javax
.swing
.JPopupMenu
;
24 import javax
.swing
.SwingUtilities
;
25 import javax
.swing
.filechooser
.FileFilter
;
26 import javax
.swing
.filechooser
.FileNameExtensionFilter
;
28 import be
.nikiroo
.fanfix
.Instance
;
29 import be
.nikiroo
.fanfix
.bundles
.Config
;
30 import be
.nikiroo
.fanfix
.bundles
.StringIdGui
;
31 import be
.nikiroo
.fanfix
.bundles
.UiConfig
;
32 import be
.nikiroo
.fanfix
.data
.MetaData
;
33 import be
.nikiroo
.fanfix
.data
.Story
;
34 import be
.nikiroo
.fanfix
.library
.BasicLibrary
;
35 import be
.nikiroo
.fanfix
.library
.LocalLibrary
;
36 import be
.nikiroo
.fanfix
.output
.BasicOutput
.OutputType
;
37 import be
.nikiroo
.fanfix
.reader
.BasicReader
;
38 import be
.nikiroo
.fanfix
.reader
.ui
.GuiReaderMainPanel
.FrameHelper
;
39 import be
.nikiroo
.fanfix
.reader
.ui
.GuiReaderMainPanel
.StoryRunnable
;
40 import be
.nikiroo
.utils
.Progress
;
41 import be
.nikiroo
.utils
.Version
;
42 import be
.nikiroo
.utils
.ui
.ConfigEditor
;
45 * A {@link Frame} that will show a {@link GuiReaderBook} item for each
46 * {@link Story} in the main cache ({@link Instance#getCache()}), and offer a
47 * way to copy them to the {@link GuiReader} cache (
48 * {@link BasicReader#getLibrary()}), read them, delete them...
52 class GuiReaderFrame
extends JFrame
implements FrameHelper
{
53 private static final long serialVersionUID
= 1L;
54 private GuiReader reader
;
55 private GuiReaderMainPanel mainPanel
;
58 * The different modification actions you can use on {@link Story} items.
62 private enum ChangeAction
{
63 /** Change the source/type, that is, move it to another source. */
65 /** Change its name. */
67 /** Change its author. */
72 * Create a new {@link GuiReaderFrame}.
75 * the associated {@link GuiReader} to forward some commands and
76 * access its {@link LocalLibrary}
78 * the type of {@link Story} to load, or NULL for all types
80 public GuiReaderFrame(GuiReader reader
, String type
) {
81 super(getAppTitle(reader
.getLibrary().getLibraryName()));
85 mainPanel
= new GuiReaderMainPanel(this, type
);
88 setLayout(new BorderLayout());
89 add(mainPanel
, BorderLayout
.CENTER
);
93 public JPopupMenu
createBookPopup() {
94 JPopupMenu popup
= new JPopupMenu();
95 popup
.add(createMenuItemOpenBook());
97 popup
.add(createMenuItemExport());
98 popup
.add(createMenuItemMoveTo(true));
99 popup
.add(createMenuItemSetCoverForSource());
100 popup
.add(createMenuItemSetCoverForAuthor());
101 popup
.add(createMenuItemClearCache());
102 popup
.add(createMenuItemRedownload());
103 popup
.addSeparator();
104 popup
.add(createMenuItemRename(true));
105 popup
.add(createMenuItemSetAuthor(true));
106 popup
.addSeparator();
107 popup
.add(createMenuItemDelete());
108 popup
.addSeparator();
109 popup
.add(createMenuItemProperties());
114 public JPopupMenu
createSourceAuthorPopup() {
115 JPopupMenu popup
= new JPopupMenu();
116 popup
.add(createMenuItemOpenBook());
121 public void createMenu(boolean libOk
) {
124 JMenuBar bar
= new JMenuBar();
126 JMenu file
= new JMenu(GuiReader
.trans(StringIdGui
.MENU_FILE
));
127 file
.setMnemonic(KeyEvent
.VK_F
);
129 JMenuItem imprt
= new JMenuItem(
130 GuiReader
.trans(StringIdGui
.MENU_FILE_IMPORT_URL
),
132 imprt
.addActionListener(new ActionListener() {
134 public void actionPerformed(ActionEvent e
) {
135 mainPanel
.imprt(true);
138 JMenuItem imprtF
= new JMenuItem(
139 GuiReader
.trans(StringIdGui
.MENU_FILE_IMPORT_FILE
),
141 imprtF
.addActionListener(new ActionListener() {
143 public void actionPerformed(ActionEvent e
) {
144 mainPanel
.imprt(false);
147 JMenuItem exit
= new JMenuItem(
148 GuiReader
.trans(StringIdGui
.MENU_FILE_EXIT
), KeyEvent
.VK_X
);
149 exit
.addActionListener(new ActionListener() {
151 public void actionPerformed(ActionEvent e
) {
152 GuiReaderFrame
.this.dispatchEvent(new WindowEvent(
153 GuiReaderFrame
.this, WindowEvent
.WINDOW_CLOSING
));
157 file
.add(createMenuItemOpenBook());
158 file
.add(createMenuItemExport());
159 file
.add(createMenuItemMoveTo(libOk
));
164 file
.add(createMenuItemRename(libOk
));
165 file
.add(createMenuItemSetAuthor(libOk
));
167 file
.add(createMenuItemProperties());
173 JMenu edit
= new JMenu(GuiReader
.trans(StringIdGui
.MENU_EDIT
));
174 edit
.setMnemonic(KeyEvent
.VK_E
);
176 edit
.add(createMenuItemSetCoverForSource());
177 edit
.add(createMenuItemSetCoverForAuthor());
178 edit
.add(createMenuItemClearCache());
179 edit
.add(createMenuItemRedownload());
181 edit
.add(createMenuItemDelete());
185 JMenu view
= new JMenu(GuiReader
.trans(StringIdGui
.MENU_VIEW
));
186 view
.setMnemonic(KeyEvent
.VK_V
);
187 JMenuItem vauthors
= new JMenuItem(
188 GuiReader
.trans(StringIdGui
.MENU_VIEW_AUTHOR
));
189 vauthors
.setMnemonic(KeyEvent
.VK_A
);
190 vauthors
.addActionListener(new ActionListener() {
192 public void actionPerformed(ActionEvent e
) {
193 mainPanel
.setWords(false);
194 mainPanel
.refreshBooks();
198 JMenuItem vwords
= new JMenuItem(
199 GuiReader
.trans(StringIdGui
.MENU_VIEW_WCOUNT
));
200 vwords
.setMnemonic(KeyEvent
.VK_W
);
201 vwords
.addActionListener(new ActionListener() {
203 public void actionPerformed(ActionEvent e
) {
204 mainPanel
.setWords(true);
205 mainPanel
.refreshBooks();
211 Map
<String
, List
<String
>> groupedSources
= new HashMap
<String
, List
<String
>>();
213 groupedSources
= reader
.getLibrary().getSourcesGrouped();
215 JMenu sources
= new JMenu(GuiReader
.trans(StringIdGui
.MENU_SOURCES
));
216 sources
.setMnemonic(KeyEvent
.VK_S
);
217 populateMenuSA(sources
, groupedSources
, true);
220 Map
<String
, List
<String
>> goupedAuthors
= new HashMap
<String
, List
<String
>>();
222 goupedAuthors
= reader
.getLibrary().getAuthorsGrouped();
224 JMenu authors
= new JMenu(GuiReader
.trans(StringIdGui
.MENU_AUTHORS
));
225 authors
.setMnemonic(KeyEvent
.VK_A
);
226 populateMenuSA(authors
, goupedAuthors
, false);
229 JMenu options
= new JMenu(GuiReader
.trans(StringIdGui
.MENU_OPTIONS
));
230 options
.setMnemonic(KeyEvent
.VK_O
);
231 options
.add(createMenuItemConfig());
232 options
.add(createMenuItemUiConfig());
239 private void populateMenuSA(JMenu menu
,
240 Map
<String
, List
<String
>> groupedValues
, boolean type
) {
242 // "All" and "Listing" special items first
243 JMenuItem item
= new JMenuItem(
244 GuiReader
.trans(StringIdGui
.MENU_XXX_ALL_GROUPED
));
245 item
.addActionListener(getActionOpenList(type
, false));
247 item
= new JMenuItem(GuiReader
.trans(StringIdGui
.MENU_XXX_ALL_LISTING
));
248 item
.addActionListener(getActionOpenList(type
, true));
253 for (final String value
: groupedValues
.keySet()) {
254 List
<String
> list
= groupedValues
.get(value
);
255 if (type
&& list
.size() == 1 && list
.get(0).isEmpty()) {
256 // leaf item source/type
257 item
= new JMenuItem(
258 value
.isEmpty() ? GuiReader
259 .trans(StringIdGui
.MENU_AUTHORS_UNKNOWN
)
261 item
.addActionListener(getActionOpen(value
, type
));
265 if (!type
&& groupedValues
.size() == 1) {
266 // only one group of authors
270 value
.isEmpty() ? GuiReader
271 .trans(StringIdGui
.MENU_AUTHORS_UNKNOWN
)
275 for (String sub
: list
) {
276 // " " instead of "" for the visual height
277 String itemName
= sub
;
278 if (itemName
.isEmpty()) {
279 itemName
= type ?
" " : GuiReader
280 .trans(StringIdGui
.MENU_AUTHORS_UNKNOWN
);
283 String actualValue
= value
;
285 if (!sub
.isEmpty()) {
286 actualValue
+= "/" + sub
;
292 item
= new JMenuItem(itemName
);
293 item
.addActionListener(getActionOpen(actualValue
, type
));
305 * Return an {@link ActionListener} that will set the given source (type) as
306 * the selected/displayed one.
309 * the type (source) to select, cannot be NULL
311 * @return the {@link ActionListener}
313 private ActionListener
getActionOpen(final String source
, final boolean type
) {
314 return new ActionListener() {
316 public void actionPerformed(ActionEvent e
) {
317 mainPanel
.removeBookPanes();
318 mainPanel
.addBookPane(source
, type
);
319 mainPanel
.refreshBooks();
324 private ActionListener
getActionOpenList(final boolean type
,
325 final boolean listMode
) {
326 return new ActionListener() {
328 public void actionPerformed(ActionEvent e
) {
329 mainPanel
.removeBookPanes();
330 mainPanel
.addBookPane(type
, listMode
);
331 mainPanel
.refreshBooks();
337 * Create the Fanfix Configuration menu item.
341 private JMenuItem
createMenuItemConfig() {
342 final String title
= GuiReader
.trans(StringIdGui
.TITLE_CONFIG
);
343 JMenuItem item
= new JMenuItem(title
);
344 item
.setMnemonic(KeyEvent
.VK_F
);
346 item
.addActionListener(new ActionListener() {
348 public void actionPerformed(ActionEvent e
) {
349 ConfigEditor
<Config
> ed
= new ConfigEditor
<Config
>(
350 Config
.class, Instance
.getConfig(), GuiReader
351 .trans(StringIdGui
.SUBTITLE_CONFIG
));
352 JFrame frame
= new JFrame(title
);
354 frame
.setSize(800, 600);
355 frame
.setVisible(true);
363 * Create the UI Configuration menu item.
367 private JMenuItem
createMenuItemUiConfig() {
368 final String title
= GuiReader
.trans(StringIdGui
.TITLE_CONFIG_UI
);
369 JMenuItem item
= new JMenuItem(title
);
370 item
.setMnemonic(KeyEvent
.VK_U
);
372 item
.addActionListener(new ActionListener() {
374 public void actionPerformed(ActionEvent e
) {
375 ConfigEditor
<UiConfig
> ed
= new ConfigEditor
<UiConfig
>(
376 UiConfig
.class, Instance
.getUiConfig(), GuiReader
377 .trans(StringIdGui
.SUBTITLE_CONFIG_UI
));
378 JFrame frame
= new JFrame(title
);
380 frame
.setSize(800, 600);
381 frame
.setVisible(true);
389 * Create the export menu item.
393 private JMenuItem
createMenuItemExport() {
394 final JFileChooser fc
= new JFileChooser();
395 fc
.setAcceptAllFileFilterUsed(false);
397 // Add the "ALL" filters first, then the others
398 final Map
<FileFilter
, OutputType
> otherFilters
= new HashMap
<FileFilter
, OutputType
>();
399 for (OutputType type
: OutputType
.values()) {
400 String ext
= type
.getDefaultExtension(false);
401 String desc
= type
.getDesc(false);
403 if (ext
== null || ext
.isEmpty()) {
404 fc
.addChoosableFileFilter(createAllFilter(desc
));
406 otherFilters
.put(new FileNameExtensionFilter(desc
, ext
), type
);
410 for (Entry
<FileFilter
, OutputType
> entry
: otherFilters
.entrySet()) {
411 fc
.addChoosableFileFilter(entry
.getKey());
415 JMenuItem export
= new JMenuItem(
416 GuiReader
.trans(StringIdGui
.MENU_FILE_EXPORT
), KeyEvent
.VK_S
);
417 export
.addActionListener(new ActionListener() {
419 public void actionPerformed(ActionEvent e
) {
420 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
421 if (selectedBook
!= null) {
422 fc
.showDialog(GuiReaderFrame
.this,
423 GuiReader
.trans(StringIdGui
.TITLE_SAVE
));
424 if (fc
.getSelectedFile() != null) {
425 final OutputType type
= otherFilters
.get(fc
.getFileFilter());
426 final String path
= fc
.getSelectedFile()
428 + type
.getDefaultExtension(false);
429 final Progress pg
= new Progress();
430 mainPanel
.outOfUi(pg
, false, new Runnable() {
434 reader
.getLibrary().export(
435 selectedBook
.getInfo().getMeta()
436 .getLuid(), type
, path
, pg
);
437 } catch (IOException e
) {
438 Instance
.getTraceHandler().error(e
);
451 * Create a {@link FileFilter} that accepts all files and return the given
459 private FileFilter
createAllFilter(final String desc
) {
460 return new FileFilter() {
462 public String
getDescription() {
467 public boolean accept(File f
) {
474 * Create the refresh (delete cache) menu item.
478 private JMenuItem
createMenuItemClearCache() {
479 JMenuItem refresh
= new JMenuItem(
480 GuiReader
.trans(StringIdGui
.MENU_EDIT_CLEAR_CACHE
),
482 refresh
.addActionListener(new ActionListener() {
484 public void actionPerformed(ActionEvent e
) {
485 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
486 if (selectedBook
!= null) {
487 mainPanel
.outOfUi(null, false, new Runnable() {
490 reader
.clearLocalReaderCache(selectedBook
.getInfo()
491 .getMeta().getLuid());
492 selectedBook
.setCached(false);
493 GuiReaderCoverImager
.clearIcon(selectedBook
495 SwingUtilities
.invokeLater(new Runnable() {
498 selectedBook
.repaint();
511 * Create the "move to" menu item.
514 * the library can be queried
518 private JMenuItem
createMenuItemMoveTo(boolean libOk
) {
519 JMenu changeTo
= new JMenu(
520 GuiReader
.trans(StringIdGui
.MENU_FILE_MOVE_TO
));
521 changeTo
.setMnemonic(KeyEvent
.VK_M
);
523 Map
<String
, List
<String
>> groupedSources
= new HashMap
<String
, List
<String
>>();
525 groupedSources
= reader
.getLibrary().getSourcesGrouped();
528 JMenuItem item
= new JMenuItem(
529 GuiReader
.trans(StringIdGui
.MENU_FILE_MOVE_TO_NEW_TYPE
));
530 item
.addActionListener(createMoveAction(ChangeAction
.SOURCE
, null));
532 changeTo
.addSeparator();
534 for (final String type
: groupedSources
.keySet()) {
535 List
<String
> list
= groupedSources
.get(type
);
536 if (list
.size() == 1 && list
.get(0).isEmpty()) {
537 item
= new JMenuItem(type
);
538 item
.addActionListener(createMoveAction(ChangeAction
.SOURCE
,
542 JMenu dir
= new JMenu(type
);
543 for (String sub
: list
) {
544 // " " instead of "" for the visual height
545 String itemName
= sub
.isEmpty() ?
" " : sub
;
546 String actualType
= type
;
547 if (!sub
.isEmpty()) {
548 actualType
+= "/" + sub
;
551 item
= new JMenuItem(itemName
);
552 item
.addActionListener(createMoveAction(
553 ChangeAction
.SOURCE
, actualType
));
564 * Create the "set author" menu item.
567 * the library can be queried
571 private JMenuItem
createMenuItemSetAuthor(boolean libOk
) {
572 JMenu changeTo
= new JMenu(
573 GuiReader
.trans(StringIdGui
.MENU_FILE_SET_AUTHOR
));
574 changeTo
.setMnemonic(KeyEvent
.VK_A
);
577 JMenuItem newItem
= new JMenuItem(
578 GuiReader
.trans(StringIdGui
.MENU_FILE_MOVE_TO_NEW_AUTHOR
));
579 changeTo
.add(newItem
);
580 changeTo
.addSeparator();
581 newItem
.addActionListener(createMoveAction(ChangeAction
.AUTHOR
, null));
585 Map
<String
, List
<String
>> groupedAuthors
= reader
.getLibrary()
586 .getAuthorsGrouped();
588 if (groupedAuthors
.size() > 1) {
589 for (String key
: groupedAuthors
.keySet()) {
590 JMenu group
= new JMenu(key
);
591 for (String value
: groupedAuthors
.get(key
)) {
592 JMenuItem item
= new JMenuItem(
593 value
.isEmpty() ? GuiReader
594 .trans(StringIdGui
.MENU_AUTHORS_UNKNOWN
)
596 item
.addActionListener(createMoveAction(
597 ChangeAction
.AUTHOR
, value
));
602 } else if (groupedAuthors
.size() == 1) {
603 for (String value
: groupedAuthors
.values().iterator().next()) {
604 JMenuItem item
= new JMenuItem(
605 value
.isEmpty() ? GuiReader
606 .trans(StringIdGui
.MENU_AUTHORS_UNKNOWN
)
608 item
.addActionListener(createMoveAction(
609 ChangeAction
.AUTHOR
, value
));
619 * Create the "rename" menu item.
622 * the library can be queried
626 private JMenuItem
createMenuItemRename(
627 @SuppressWarnings("unused") boolean libOk
) {
628 JMenuItem changeTo
= new JMenuItem(
629 GuiReader
.trans(StringIdGui
.MENU_FILE_RENAME
));
630 changeTo
.setMnemonic(KeyEvent
.VK_R
);
631 changeTo
.addActionListener(createMoveAction(ChangeAction
.TITLE
, null));
635 private ActionListener
createMoveAction(final ChangeAction what
,
637 return new ActionListener() {
639 public void actionPerformed(ActionEvent e
) {
640 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
641 if (selectedBook
!= null) {
642 boolean refreshRequired
= false;
644 if (what
== ChangeAction
.SOURCE
) {
645 refreshRequired
= mainPanel
.getCurrentType();
646 } else if (what
== ChangeAction
.TITLE
) {
647 refreshRequired
= false;
648 } else if (what
== ChangeAction
.AUTHOR
) {
649 refreshRequired
= !mainPanel
.getCurrentType();
652 String changeTo
= type
;
654 MetaData meta
= selectedBook
.getInfo().getMeta();
656 if (what
== ChangeAction
.SOURCE
) {
657 init
= meta
.getSource();
658 } else if (what
== ChangeAction
.TITLE
) {
659 init
= meta
.getTitle();
660 } else if (what
== ChangeAction
.AUTHOR
) {
661 init
= meta
.getAuthor();
664 Object rep
= JOptionPane
.showInputDialog(
666 GuiReader
.trans(StringIdGui
.SUBTITLE_MOVE_TO
),
667 GuiReader
.trans(StringIdGui
.TITLE_MOVE_TO
),
668 JOptionPane
.QUESTION_MESSAGE
, null, null, init
);
674 changeTo
= rep
.toString();
677 final String fChangeTo
= changeTo
;
678 mainPanel
.outOfUi(null, refreshRequired
, new Runnable() {
681 String luid
= selectedBook
.getInfo().getMeta()
683 if (what
== ChangeAction
.SOURCE
) {
684 reader
.changeSource(luid
, fChangeTo
);
685 } else if (what
== ChangeAction
.TITLE
) {
686 reader
.changeTitle(luid
, fChangeTo
);
687 } else if (what
== ChangeAction
.AUTHOR
) {
688 reader
.changeAuthor(luid
, fChangeTo
);
691 mainPanel
.getSelectedBook().repaint();
692 mainPanel
.unsetSelectedBook();
694 SwingUtilities
.invokeLater(new Runnable() {
708 * Create the re-download (then delete original) menu item.
712 private JMenuItem
createMenuItemRedownload() {
713 JMenuItem refresh
= new JMenuItem(
714 GuiReader
.trans(StringIdGui
.MENU_EDIT_REDOWNLOAD
),
716 refresh
.addActionListener(new ActionListener() {
718 public void actionPerformed(ActionEvent e
) {
719 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
720 if (selectedBook
!= null) {
721 final MetaData meta
= selectedBook
.getInfo().getMeta();
724 new StoryRunnable() {
726 public void run(Story story
) {
727 MetaData newMeta
= story
.getMeta();
728 if (!newMeta
.getSource().equals(
730 reader
.changeSource(newMeta
.getLuid(),
736 .trans(StringIdGui
.PROGRESS_CHANGE_SOURCE
));
745 * Create the delete menu item.
749 private JMenuItem
createMenuItemDelete() {
750 JMenuItem delete
= new JMenuItem(
751 GuiReader
.trans(StringIdGui
.MENU_EDIT_DELETE
), KeyEvent
.VK_D
);
752 delete
.addActionListener(new ActionListener() {
754 public void actionPerformed(ActionEvent e
) {
755 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
756 if (selectedBook
!= null
757 && selectedBook
.getInfo().getMeta() != null) {
759 final MetaData meta
= selectedBook
.getInfo().getMeta();
760 int rep
= JOptionPane
.showConfirmDialog(
762 GuiReader
.trans(StringIdGui
.SUBTITLE_DELETE
,
763 meta
.getLuid(), meta
.getTitle()),
764 GuiReader
.trans(StringIdGui
.TITLE_DELETE
),
765 JOptionPane
.OK_CANCEL_OPTION
);
767 if (rep
== JOptionPane
.OK_OPTION
) {
768 mainPanel
.outOfUi(null, true, new Runnable() {
771 reader
.delete(meta
.getLuid());
772 mainPanel
.unsetSelectedBook();
784 * Create the properties menu item.
788 private JMenuItem
createMenuItemProperties() {
789 JMenuItem delete
= new JMenuItem(
790 GuiReader
.trans(StringIdGui
.MENU_FILE_PROPERTIES
),
792 delete
.addActionListener(new ActionListener() {
794 public void actionPerformed(ActionEvent e
) {
795 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
796 if (selectedBook
!= null) {
797 mainPanel
.outOfUi(null, false, new Runnable() {
800 new GuiReaderPropertiesFrame(reader
.getLibrary(),
801 selectedBook
.getInfo().getMeta())
813 * Create the open menu item for a book, a source/type or an author.
817 public JMenuItem
createMenuItemOpenBook() {
818 JMenuItem open
= new JMenuItem(
819 GuiReader
.trans(StringIdGui
.MENU_FILE_OPEN
), KeyEvent
.VK_O
);
820 open
.addActionListener(new ActionListener() {
822 public void actionPerformed(ActionEvent e
) {
823 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
824 if (selectedBook
!= null) {
825 if (selectedBook
.getInfo().getMeta() == null) {
826 mainPanel
.removeBookPanes();
827 mainPanel
.addBookPane(selectedBook
.getInfo()
828 .getMainInfo(), mainPanel
.getCurrentType());
829 mainPanel
.refreshBooks();
831 mainPanel
.openBook(selectedBook
);
841 * Create the SetCover menu item for a book to change the linked source
846 private JMenuItem
createMenuItemSetCoverForSource() {
847 JMenuItem open
= new JMenuItem(
848 GuiReader
.trans(StringIdGui
.MENU_EDIT_SET_COVER_FOR_SOURCE
),
850 open
.addActionListener(new ActionListener() {
852 public void actionPerformed(ActionEvent e
) {
853 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
854 if (selectedBook
!= null) {
855 BasicLibrary lib
= reader
.getLibrary();
856 String luid
= selectedBook
.getInfo().getMeta().getLuid();
857 String source
= selectedBook
.getInfo().getMeta()
860 lib
.setSourceCover(source
, luid
);
862 GuiReaderBookInfo sourceInfo
= GuiReaderBookInfo
863 .fromSource(lib
, source
);
864 GuiReaderCoverImager
.clearIcon(sourceInfo
);
873 * Create the SetCover menu item for a book to change the linked source
878 private JMenuItem
createMenuItemSetCoverForAuthor() {
879 JMenuItem open
= new JMenuItem(
880 GuiReader
.trans(StringIdGui
.MENU_EDIT_SET_COVER_FOR_AUTHOR
),
882 open
.addActionListener(new ActionListener() {
884 public void actionPerformed(ActionEvent e
) {
885 final GuiReaderBook selectedBook
= mainPanel
.getSelectedBook();
886 if (selectedBook
!= null) {
887 BasicLibrary lib
= reader
.getLibrary();
888 String luid
= selectedBook
.getInfo().getMeta().getLuid();
889 String author
= selectedBook
.getInfo().getMeta()
892 lib
.setAuthorCover(author
, luid
);
894 GuiReaderBookInfo authorInfo
= GuiReaderBookInfo
895 .fromAuthor(lib
, author
);
896 GuiReaderCoverImager
.clearIcon(authorInfo
);
905 * Display an error message and log the linked {@link Exception}.
910 * the title of the error message
912 * the exception to log if any
914 public void error(final String message
, final String title
, Exception e
) {
915 Instance
.getTraceHandler().error(title
+ ": " + message
);
917 Instance
.getTraceHandler().error(e
);
920 SwingUtilities
.invokeLater(new Runnable() {
923 JOptionPane
.showMessageDialog(GuiReaderFrame
.this, message
,
924 title
, JOptionPane
.ERROR_MESSAGE
);
930 public GuiReader
getReader() {
935 * Return the title of the application.
938 * the name of the associated {@link BasicLibrary}, which can be
943 static private String
getAppTitle(String libraryName
) {
944 if (!libraryName
.isEmpty()) {
945 return GuiReader
.trans(StringIdGui
.TITLE_LIBRARY_WITH_NAME
, Version
946 .getCurrentVersion().toString(), libraryName
);
949 return GuiReader
.trans(StringIdGui
.TITLE_LIBRARY
, Version
950 .getCurrentVersion().toString());