gui: code cleanup
[fanfix.git] / src / be / nikiroo / fanfix / reader / ui / GuiReaderFrame.java
CommitLineData
16a81ef7 1package be.nikiroo.fanfix.reader.ui;
a6395bef 2
d3c84ac3 3import java.awt.BorderLayout;
4d205683 4import java.awt.Frame;
a6395bef
NR
5import java.awt.event.ActionEvent;
6import java.awt.event.ActionListener;
333f0e7b
NR
7import java.awt.event.KeyEvent;
8import java.awt.event.WindowEvent;
9import java.io.File;
a6395bef 10import java.io.IOException;
4d205683 11import java.util.HashMap;
a6395bef 12import java.util.List;
4d205683
NR
13import java.util.Map;
14import java.util.Map.Entry;
a6395bef 15
10d558d2 16import javax.swing.JFileChooser;
a6395bef 17import javax.swing.JFrame;
333f0e7b
NR
18import javax.swing.JMenu;
19import javax.swing.JMenuBar;
20import javax.swing.JMenuItem;
21import javax.swing.JOptionPane;
9843a5e5 22import javax.swing.JPopupMenu;
3b2b638f 23import javax.swing.SwingUtilities;
4d205683
NR
24import javax.swing.filechooser.FileFilter;
25import javax.swing.filechooser.FileNameExtensionFilter;
a6395bef
NR
26
27import be.nikiroo.fanfix.Instance;
e8eeea0a 28import be.nikiroo.fanfix.bundles.Config;
b4dc6ab5 29import be.nikiroo.fanfix.bundles.UiConfig;
a6395bef 30import be.nikiroo.fanfix.data.MetaData;
4d205683 31import be.nikiroo.fanfix.data.Story;
e42573a0 32import be.nikiroo.fanfix.library.LocalLibrary;
4d205683 33import be.nikiroo.fanfix.output.BasicOutput.OutputType;
16a81ef7 34import be.nikiroo.fanfix.reader.BasicReader;
14bb95fa
NR
35import be.nikiroo.fanfix.reader.ui.GuiReaderMainPanel.FrameHelper;
36import be.nikiroo.fanfix.reader.ui.GuiReaderMainPanel.StoryRunnable;
3b2b638f 37import be.nikiroo.utils.Progress;
39c3c689 38import be.nikiroo.utils.Version;
e8eeea0a 39import be.nikiroo.utils.ui.ConfigEditor;
a6395bef 40
4d205683 41/**
5dd985cf 42 * A {@link Frame} that will show a {@link GuiReaderBook} item for each
4d205683 43 * {@link Story} in the main cache ({@link Instance#getCache()}), and offer a
5dd985cf
NR
44 * way to copy them to the {@link GuiReader} cache (
45 * {@link BasicReader#getLibrary()}), read them, delete them...
4d205683
NR
46 *
47 * @author niki
48 */
14bb95fa 49class GuiReaderFrame extends JFrame implements FrameHelper {
a6395bef 50 private static final long serialVersionUID = 1L;
5dd985cf 51 private GuiReader reader;
14bb95fa 52 private GuiReaderMainPanel helpee;
a6395bef 53
14bb95fa
NR
54 private enum MoveAction {
55 SOURCE, TITLE, AUTHOR
c8faa52a
NR
56 }
57
4d205683 58 /**
5dd985cf 59 * Create a new {@link GuiReaderFrame}.
4d205683
NR
60 *
61 * @param reader
5dd985cf
NR
62 * the associated {@link GuiReader} to forward some commands and
63 * access its {@link LocalLibrary}
4d205683
NR
64 * @param type
65 * the type of {@link Story} to load, or NULL for all types
66 */
5dd985cf 67 public GuiReaderFrame(GuiReader reader, String type) {
39c3c689 68 super(String.format("Fanfix %s Library", Version.getCurrentVersion()));
a6395bef
NR
69
70 this.reader = reader;
71
14bb95fa 72 // TODO: should we still have that??
a6395bef 73 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
754a5bc2 74
14bb95fa 75 helpee = new GuiReaderMainPanel(this, type);
4310bae9 76
14bb95fa
NR
77 setSize(800, 600);
78 setLayout(new BorderLayout());
79 add(helpee);
4310bae9 80
333f0e7b
NR
81 setVisible(true);
82 }
83
14bb95fa
NR
84 @Override
85 public JPopupMenu createBookPopup() {
86 JPopupMenu popup = new JPopupMenu();
87 popup.add(createMenuItemOpenBook());
88 popup.addSeparator();
89 popup.add(createMenuItemExport());
90 popup.add(createMenuItemMoveTo(true));
91 popup.add(createMenuItemSetCover());
92 popup.add(createMenuItemClearCache());
93 popup.add(createMenuItemRedownload());
94 popup.addSeparator();
95 popup.add(createMenuItemRename(true));
96 popup.add(createMenuItemSetAuthor(true));
97 popup.addSeparator();
98 popup.add(createMenuItemDelete());
99 popup.addSeparator();
100 popup.add(createMenuItemProperties());
101 return popup;
4310bae9
NR
102 }
103
14bb95fa
NR
104 @Override
105 public JPopupMenu createSourcePopup() {
106 JPopupMenu popup = new JPopupMenu();
107 popup.add(createMenuItemOpenBook());
108 return popup;
333f0e7b
NR
109 }
110
14bb95fa
NR
111 @Override
112 public void createMenu(boolean libOk) {
113 JMenuBar bar = new JMenuBar();
333f0e7b
NR
114
115 JMenu file = new JMenu("File");
10d558d2 116 file.setMnemonic(KeyEvent.VK_F);
333f0e7b 117
22848428 118 JMenuItem imprt = new JMenuItem("Import URL...", KeyEvent.VK_U);
333f0e7b 119 imprt.addActionListener(new ActionListener() {
211f7ddb 120 @Override
333f0e7b 121 public void actionPerformed(ActionEvent e) {
14bb95fa 122 helpee.imprt(true);
10d558d2
NR
123 }
124 });
22848428 125 JMenuItem imprtF = new JMenuItem("Import File...", KeyEvent.VK_F);
10d558d2 126 imprtF.addActionListener(new ActionListener() {
211f7ddb 127 @Override
10d558d2 128 public void actionPerformed(ActionEvent e) {
14bb95fa 129 helpee.imprt(false);
10d558d2
NR
130 }
131 });
132 JMenuItem exit = new JMenuItem("Exit", KeyEvent.VK_X);
133 exit.addActionListener(new ActionListener() {
211f7ddb 134 @Override
10d558d2 135 public void actionPerformed(ActionEvent e) {
5dd985cf
NR
136 GuiReaderFrame.this.dispatchEvent(new WindowEvent(
137 GuiReaderFrame.this, WindowEvent.WINDOW_CLOSING));
10d558d2
NR
138 }
139 });
3b2b638f 140
9843a5e5
NR
141 file.add(createMenuItemOpenBook());
142 file.add(createMenuItemExport());
c8d48938 143 file.add(createMenuItemMoveTo(libOk));
9843a5e5 144 file.addSeparator();
10d558d2
NR
145 file.add(imprt);
146 file.add(imprtF);
147 file.addSeparator();
c8d48938
NR
148 file.add(createMenuItemRename(libOk));
149 file.add(createMenuItemSetAuthor(libOk));
150 file.addSeparator();
10d558d2 151 file.add(exit);
3b2b638f 152
10d558d2
NR
153 bar.add(file);
154
155 JMenu edit = new JMenu("Edit");
156 edit.setMnemonic(KeyEvent.VK_E);
157
22848428
NR
158 edit.add(createMenuItemClearCache());
159 edit.add(createMenuItemRedownload());
9843a5e5
NR
160 edit.addSeparator();
161 edit.add(createMenuItemDelete());
162
163 bar.add(edit);
164
793f1071
NR
165 JMenu view = new JMenu("View");
166 view.setMnemonic(KeyEvent.VK_V);
167 JMenuItem vauthors = new JMenuItem("Author");
168 vauthors.setMnemonic(KeyEvent.VK_A);
169 vauthors.addActionListener(new ActionListener() {
211f7ddb 170 @Override
793f1071 171 public void actionPerformed(ActionEvent e) {
14bb95fa
NR
172 helpee.setWords(false);
173 helpee.refreshBooks();
793f1071
NR
174 }
175 });
176 view.add(vauthors);
177 JMenuItem vwords = new JMenuItem("Word count");
178 vwords.setMnemonic(KeyEvent.VK_W);
179 vwords.addActionListener(new ActionListener() {
211f7ddb 180 @Override
793f1071 181 public void actionPerformed(ActionEvent e) {
14bb95fa
NR
182 helpee.setWords(true);
183 helpee.refreshBooks();
793f1071
NR
184 }
185 });
186 view.add(vwords);
187 bar.add(view);
188
97b36d32
NR
189 Map<String, List<String>> groupedSources = new HashMap<String, List<String>>();
190 if (libOk) {
191 groupedSources = reader.getLibrary().getSourcesGrouped();
192 }
4310bae9
NR
193 JMenu sources = new JMenu("Sources");
194 sources.setMnemonic(KeyEvent.VK_S);
97b36d32
NR
195 populateMenuSA(sources, groupedSources, true);
196 bar.add(sources);
9843a5e5 197
97b36d32 198 Map<String, List<String>> goupedAuthors = new HashMap<String, List<String>>();
e6249b0f 199 if (libOk) {
97b36d32 200 goupedAuthors = reader.getLibrary().getAuthorsGrouped();
e6249b0f 201 }
97b36d32
NR
202 JMenu authors = new JMenu("Authors");
203 authors.setMnemonic(KeyEvent.VK_A);
204 populateMenuSA(authors, goupedAuthors, false);
205 bar.add(authors);
e6249b0f 206
97b36d32
NR
207 JMenu options = new JMenu("Options");
208 options.setMnemonic(KeyEvent.VK_O);
209 options.add(createMenuItemConfig());
210 options.add(createMenuItemUiConfig());
211 bar.add(options);
c1b93db3 212
14bb95fa 213 setJMenuBar(bar);
97b36d32
NR
214 }
215
216 // "" = [unknown]
217 private void populateMenuSA(JMenu menu,
218 Map<String, List<String>> groupedValues, boolean type) {
219
220 // "All" and "Listing" special items
221 JMenuItem item = new JMenuItem("All");
222 item.addActionListener(getActionOpenList(type, false));
223 menu.add(item);
224 item = new JMenuItem("Listing");
225 item.addActionListener(getActionOpenList(type, true));
226 menu.add(item);
227 menu.addSeparator();
228
229 for (final String value : groupedValues.keySet()) {
230 List<String> list = groupedValues.get(value);
231 if (type && list.size() == 1 && list.get(0).isEmpty()) {
232 // leaf item source/type
233 item = new JMenuItem(value.isEmpty() ? "[unknown]" : value);
234 item.addActionListener(getActionOpen(value, type));
235 menu.add(item);
c1b93db3 236 } else {
97b36d32
NR
237 JMenu dir;
238 if (!type && groupedValues.size() == 1) {
239 // only one group of authors
240 dir = menu;
241 } else {
242 dir = new JMenu(value.isEmpty() ? "[unknown]" : value);
243 }
244
c1b93db3
NR
245 for (String sub : list) {
246 // " " instead of "" for the visual height
247 String itemName = sub.isEmpty() ? " " : sub;
97b36d32
NR
248 String actualValue = value;
249
250 if (type) {
251 if (!sub.isEmpty()) {
252 actualValue += "/" + sub;
253 }
254 } else {
255 actualValue = sub;
c1b93db3 256 }
9843a5e5 257
c1b93db3 258 item = new JMenuItem(itemName);
97b36d32 259 item.addActionListener(getActionOpen(actualValue, type));
c1b93db3
NR
260 dir.add(item);
261 }
5f42f329 262
97b36d32
NR
263 if (menu != dir) {
264 menu.add(dir);
265 }
5f42f329 266 }
4310bae9 267 }
9843a5e5
NR
268 }
269
c1b93db3
NR
270 /**
271 * Return an {@link ActionListener} that will set the given source (type) as
272 * the selected/displayed one.
273 *
274 * @param type
97b36d32 275 * the type (source) to select, cannot be NULL
c1b93db3
NR
276 *
277 * @return the {@link ActionListener}
278 */
97b36d32 279 private ActionListener getActionOpen(final String source, final boolean type) {
c1b93db3
NR
280 return new ActionListener() {
281 @Override
282 public void actionPerformed(ActionEvent e) {
14bb95fa
NR
283 helpee.removeBookPanes();
284 helpee.addBookPane(source, type);
285 helpee.refreshBooks();
c1b93db3
NR
286 }
287 };
288 }
289
97b36d32
NR
290 private ActionListener getActionOpenList(final boolean type,
291 final boolean listMode) {
292 return new ActionListener() {
293 @Override
294 public void actionPerformed(ActionEvent e) {
14bb95fa
NR
295 helpee.removeBookPanes();
296 helpee.addBookPane(type, listMode);
297 helpee.refreshBooks();
5f42f329 298 }
97b36d32 299 };
5f42f329
NR
300 }
301
e8eeea0a
NR
302 /**
303 * Create the Fanfix Configuration menu item.
304 *
305 * @return the item
306 */
307 private JMenuItem createMenuItemConfig() {
308 final String title = "Fanfix Configuration";
309 JMenuItem item = new JMenuItem(title);
310 item.setMnemonic(KeyEvent.VK_F);
311
312 item.addActionListener(new ActionListener() {
211f7ddb 313 @Override
e8eeea0a
NR
314 public void actionPerformed(ActionEvent e) {
315 ConfigEditor<Config> ed = new ConfigEditor<Config>(
316 Config.class, Instance.getConfig(),
317 "This is where you configure the options of the program.");
318 JFrame frame = new JFrame(title);
319 frame.add(ed);
320 frame.setSize(800, 600);
321 frame.setVisible(true);
322 }
323 });
324
325 return item;
326 }
327
328 /**
329 * Create the UI Configuration menu item.
330 *
331 * @return the item
332 */
333 private JMenuItem createMenuItemUiConfig() {
334 final String title = "UI Configuration";
335 JMenuItem item = new JMenuItem(title);
336 item.setMnemonic(KeyEvent.VK_U);
337
338 item.addActionListener(new ActionListener() {
211f7ddb 339 @Override
e8eeea0a
NR
340 public void actionPerformed(ActionEvent e) {
341 ConfigEditor<UiConfig> ed = new ConfigEditor<UiConfig>(
342 UiConfig.class, Instance.getUiConfig(),
343 "This is where you configure the graphical appearence of the program.");
344 JFrame frame = new JFrame(title);
345 frame.add(ed);
346 frame.setSize(800, 600);
347 frame.setVisible(true);
348 }
349 });
350
351 return item;
352 }
353
4d205683
NR
354 /**
355 * Create the export menu item.
356 *
357 * @return the item
358 */
9843a5e5 359 private JMenuItem createMenuItemExport() {
4d205683
NR
360 final JFileChooser fc = new JFileChooser();
361 fc.setAcceptAllFileFilterUsed(false);
362
363 final Map<FileFilter, OutputType> filters = new HashMap<FileFilter, OutputType>();
364 for (OutputType type : OutputType.values()) {
365 String ext = type.getDefaultExtension(false);
366 String desc = type.getDesc(false);
b2612f9d 367
4d205683
NR
368 if (ext == null || ext.isEmpty()) {
369 filters.put(createAllFilter(desc), type);
370 } else {
371 filters.put(new FileNameExtensionFilter(desc, ext), type);
372 }
373 }
374
375 // First the "ALL" filters, then, the extension filters
376 for (Entry<FileFilter, OutputType> entry : filters.entrySet()) {
377 if (!(entry.getKey() instanceof FileNameExtensionFilter)) {
378 fc.addChoosableFileFilter(entry.getKey());
379 }
380 }
381 for (Entry<FileFilter, OutputType> entry : filters.entrySet()) {
382 if (entry.getKey() instanceof FileNameExtensionFilter) {
383 fc.addChoosableFileFilter(entry.getKey());
384 }
385 }
386 //
9843a5e5 387
4d205683 388 JMenuItem export = new JMenuItem("Save as...", KeyEvent.VK_S);
10d558d2 389 export.addActionListener(new ActionListener() {
211f7ddb 390 @Override
10d558d2 391 public void actionPerformed(ActionEvent e) {
14bb95fa 392 final GuiReaderBook selectedBook = helpee.getSelectedBook();
4d205683 393 if (selectedBook != null) {
5dd985cf 394 fc.showDialog(GuiReaderFrame.this, "Save");
b2612f9d
NR
395 if (fc.getSelectedFile() != null) {
396 final OutputType type = filters.get(fc.getFileFilter());
397 final String path = fc.getSelectedFile()
398 .getAbsolutePath()
399 + type.getDefaultExtension(false);
400 final Progress pg = new Progress();
14bb95fa 401 helpee.outOfUi(pg, new Runnable() {
211f7ddb 402 @Override
b2612f9d
NR
403 public void run() {
404 try {
e42573a0 405 reader.getLibrary().export(
b2612f9d
NR
406 selectedBook.getMeta().getLuid(),
407 type, path, pg);
408 } catch (IOException e) {
62c63b07 409 Instance.getTraceHandler().error(e);
b2612f9d 410 }
4d205683 411 }
b2612f9d
NR
412 });
413 }
4d205683 414 }
10d558d2
NR
415 }
416 });
417
9843a5e5
NR
418 return export;
419 }
420
edd46289
NR
421 /**
422 * Create a {@link FileFilter} that accepts all files and return the given
423 * description.
424 *
425 * @param desc
426 * the description
427 *
428 * @return the filter
429 */
4d205683
NR
430 private FileFilter createAllFilter(final String desc) {
431 return new FileFilter() {
432 @Override
433 public String getDescription() {
434 return desc;
435 }
436
437 @Override
438 public boolean accept(File f) {
439 return true;
440 }
441 };
442 }
443
444 /**
445 * Create the refresh (delete cache) menu item.
446 *
447 * @return the item
448 */
22848428 449 private JMenuItem createMenuItemClearCache() {
4d205683 450 JMenuItem refresh = new JMenuItem("Clear cache", KeyEvent.VK_C);
10d558d2 451 refresh.addActionListener(new ActionListener() {
211f7ddb 452 @Override
10d558d2 453 public void actionPerformed(ActionEvent e) {
14bb95fa 454 final GuiReaderBook selectedBook = helpee.getSelectedBook();
10d558d2 455 if (selectedBook != null) {
14bb95fa 456 helpee.outOfUi(null, new Runnable() {
211f7ddb 457 @Override
10d558d2 458 public void run() {
754a5bc2
NR
459 reader.clearLocalReaderCache(selectedBook.getMeta()
460 .getLuid());
10d558d2 461 selectedBook.setCached(false);
df6e2d88
NR
462 GuiReaderCoverImager.clearIcon(selectedBook
463 .getMeta());
3b2b638f 464 SwingUtilities.invokeLater(new Runnable() {
211f7ddb 465 @Override
3b2b638f 466 public void run() {
10d558d2 467 selectedBook.repaint();
3b2b638f
NR
468 }
469 });
470 }
471 });
333f0e7b
NR
472 }
473 }
474 });
10d558d2 475
9843a5e5
NR
476 return refresh;
477 }
478
70c9b112 479 /**
c8d48938 480 * Create the "move to" menu item.
70c9b112 481 *
e6249b0f
NR
482 * @param libOk
483 * the library can be queried
484 *
70c9b112
NR
485 * @return the item
486 */
c8d48938 487 private JMenuItem createMenuItemMoveTo(boolean libOk) {
c1b93db3 488 JMenu changeTo = new JMenu("Move to");
c8d48938 489 changeTo.setMnemonic(KeyEvent.VK_M);
70c9b112 490
c1b93db3 491 Map<String, List<String>> groupedSources = new HashMap<String, List<String>>();
e6249b0f 492 if (libOk) {
c1b93db3 493 groupedSources = reader.getLibrary().getSourcesGrouped();
e6249b0f 494 }
70c9b112 495
c1b93db3 496 JMenuItem item = new JMenuItem("New type...");
14bb95fa 497 item.addActionListener(createMoveAction(MoveAction.SOURCE, null));
c1b93db3
NR
498 changeTo.add(item);
499 changeTo.addSeparator();
70c9b112 500
c1b93db3
NR
501 for (final String type : groupedSources.keySet()) {
502 List<String> list = groupedSources.get(type);
503 if (list.size() == 1 && list.get(0).isEmpty()) {
504 item = new JMenuItem(type);
14bb95fa 505 item.addActionListener(createMoveAction(MoveAction.SOURCE, type));
c1b93db3
NR
506 changeTo.add(item);
507 } else {
508 JMenu dir = new JMenu(type);
509 for (String sub : list) {
510 // " " instead of "" for the visual height
511 String itemName = sub.isEmpty() ? " " : sub;
512 String actualType = type;
513 if (!sub.isEmpty()) {
514 actualType += "/" + sub;
515 }
70c9b112 516
c1b93db3 517 item = new JMenuItem(itemName);
14bb95fa 518 item.addActionListener(createMoveAction(MoveAction.SOURCE,
c1b93db3
NR
519 actualType));
520 dir.add(item);
521 }
522 changeTo.add(dir);
c8d48938
NR
523 }
524 }
211f7ddb 525
c8d48938
NR
526 return changeTo;
527 }
70c9b112 528
c8d48938
NR
529 /**
530 * Create the "set author" menu item.
531 *
532 * @param libOk
533 * the library can be queried
534 *
535 * @return the item
536 */
537 private JMenuItem createMenuItemSetAuthor(boolean libOk) {
538 JMenu changeTo = new JMenu("Set author");
539 changeTo.setMnemonic(KeyEvent.VK_A);
70c9b112 540
c8d48938
NR
541 // New author
542 JMenuItem newItem = new JMenuItem("New author...");
543 changeTo.add(newItem);
544 changeTo.addSeparator();
14bb95fa 545 newItem.addActionListener(createMoveAction(MoveAction.AUTHOR, null));
70c9b112 546
c8d48938
NR
547 // Existing authors
548 if (libOk) {
97b36d32
NR
549 Map<String, List<String>> groupedAuthors = reader.getLibrary()
550 .getAuthorsGrouped();
c8d48938 551
97b36d32
NR
552 if (groupedAuthors.size() > 1) {
553 for (String key : groupedAuthors.keySet()) {
554 JMenu group = new JMenu(key);
555 for (String value : groupedAuthors.get(key)) {
c8d48938 556 JMenuItem item = new JMenuItem(value);
14bb95fa
NR
557 item.addActionListener(createMoveAction(
558 MoveAction.AUTHOR, value));
c8d48938 559 group.add(item);
70c9b112 560 }
c8d48938 561 changeTo.add(group);
70c9b112 562 }
97b36d32
NR
563 } else if (groupedAuthors.size() == 1) {
564 for (String value : groupedAuthors.values().iterator().next()) {
c8d48938 565 JMenuItem item = new JMenuItem(value);
14bb95fa
NR
566 item.addActionListener(createMoveAction(MoveAction.AUTHOR,
567 value));
c8d48938
NR
568 changeTo.add(item);
569 }
570 }
70c9b112
NR
571 }
572
c8d48938
NR
573 return changeTo;
574 }
575
576 /**
577 * Create the "rename" menu item.
578 *
579 * @param libOk
580 * the library can be queried
581 *
582 * @return the item
583 */
584 private JMenuItem createMenuItemRename(
585 @SuppressWarnings("unused") boolean libOk) {
586 JMenuItem changeTo = new JMenuItem("Rename...");
587 changeTo.setMnemonic(KeyEvent.VK_R);
14bb95fa 588 changeTo.addActionListener(createMoveAction(MoveAction.TITLE, null));
c8d48938
NR
589 return changeTo;
590 }
591
14bb95fa
NR
592 private ActionListener createMoveAction(final MoveAction what,
593 final String type) {
c8d48938
NR
594 return new ActionListener() {
595 @Override
596 public void actionPerformed(ActionEvent e) {
14bb95fa 597 final GuiReaderBook selectedBook = helpee.getSelectedBook();
c8d48938
NR
598 if (selectedBook != null) {
599 String changeTo = type;
600 if (type == null) {
601 String init = "";
14bb95fa 602 if (what == MoveAction.SOURCE) {
c8d48938 603 init = selectedBook.getMeta().getSource();
14bb95fa 604 } else if (what == MoveAction.TITLE) {
c8d48938 605 init = selectedBook.getMeta().getTitle();
14bb95fa 606 } else if (what == MoveAction.AUTHOR) {
c8d48938
NR
607 init = selectedBook.getMeta().getAuthor();
608 }
609
610 Object rep = JOptionPane.showInputDialog(
611 GuiReaderFrame.this, "Move to:",
612 "Moving story", JOptionPane.QUESTION_MESSAGE,
613 null, null, init);
614
615 if (rep == null) {
616 return;
617 }
618
619 changeTo = rep.toString();
620 }
621
622 final String fChangeTo = changeTo;
14bb95fa 623 helpee.outOfUi(null, new Runnable() {
c8d48938
NR
624 @Override
625 public void run() {
626 if (what.equals("SOURCE")) {
627 reader.changeSource(selectedBook.getMeta()
628 .getLuid(), fChangeTo);
629 } else if (what.equals("TITLE")) {
630 reader.changeTitle(selectedBook.getMeta()
631 .getLuid(), fChangeTo);
632 } else if (what.equals("AUTHOR")) {
633 reader.changeAuthor(selectedBook.getMeta()
634 .getLuid(), fChangeTo);
635 }
636
14bb95fa 637 helpee.unsetSelectedBook();
c8d48938
NR
638
639 SwingUtilities.invokeLater(new Runnable() {
640 @Override
641 public void run() {
14bb95fa 642 createMenu(true);
c8d48938
NR
643 }
644 });
645 }
646 });
647 }
648 }
649 };
70c9b112
NR
650 }
651
22848428
NR
652 /**
653 * Create the redownload (then delete original) menu item.
654 *
655 * @return the item
656 */
657 private JMenuItem createMenuItemRedownload() {
658 JMenuItem refresh = new JMenuItem("Redownload", KeyEvent.VK_R);
659 refresh.addActionListener(new ActionListener() {
211f7ddb 660 @Override
22848428 661 public void actionPerformed(ActionEvent e) {
14bb95fa 662 final GuiReaderBook selectedBook = helpee.getSelectedBook();
22848428 663 if (selectedBook != null) {
754a5bc2 664 final MetaData meta = selectedBook.getMeta();
14bb95fa 665 helpee.imprt(meta.getUrl(), new StoryRunnable() {
211f7ddb 666 @Override
c8faa52a 667 public void run(Story story) {
754a5bc2 668 reader.delete(meta.getLuid());
14bb95fa 669 helpee.unsetSelectedBook();
c8faa52a
NR
670 MetaData newMeta = story.getMeta();
671 if (!newMeta.getSource().equals(meta.getSource())) {
c3b229a1 672 reader.changeSource(newMeta.getLuid(),
c8faa52a
NR
673 meta.getSource());
674 }
22848428 675 }
754a5bc2 676 }, "Removing old copy");
22848428
NR
677 }
678 }
679 });
680
681 return refresh;
682 }
683
4d205683
NR
684 /**
685 * Create the delete menu item.
686 *
687 * @return the item
688 */
9843a5e5 689 private JMenuItem createMenuItemDelete() {
10d558d2
NR
690 JMenuItem delete = new JMenuItem("Delete", KeyEvent.VK_D);
691 delete.addActionListener(new ActionListener() {
211f7ddb 692 @Override
10d558d2 693 public void actionPerformed(ActionEvent e) {
14bb95fa 694 final GuiReaderBook selectedBook = helpee.getSelectedBook();
10d558d2 695 if (selectedBook != null) {
14bb95fa 696 helpee.outOfUi(null, new Runnable() {
211f7ddb 697 @Override
10d558d2 698 public void run() {
22848428 699 reader.delete(selectedBook.getMeta().getLuid());
14bb95fa 700 helpee.unsetSelectedBook();
10d558d2
NR
701 }
702 });
703 }
704 }
705 });
706
9843a5e5
NR
707 return delete;
708 }
10d558d2 709
df6e2d88
NR
710 /**
711 * Create the properties menu item.
712 *
713 * @return the item
714 */
715 private JMenuItem createMenuItemProperties() {
716 JMenuItem delete = new JMenuItem("Properties", KeyEvent.VK_P);
717 delete.addActionListener(new ActionListener() {
718 @Override
719 public void actionPerformed(ActionEvent e) {
14bb95fa 720 final GuiReaderBook selectedBook = helpee.getSelectedBook();
df6e2d88 721 if (selectedBook != null) {
14bb95fa 722 helpee.outOfUi(null, new Runnable() {
df6e2d88
NR
723 @Override
724 public void run() {
14bb95fa
NR
725 new GuiReaderPropertiesFrame(reader, selectedBook
726 .getMeta()).setVisible(true);
df6e2d88
NR
727 }
728 });
729 }
730 }
731 });
732
733 return delete;
734 }
735
4d205683 736 /**
14bb95fa 737 * Create the open menu item for a book or a source/type (no LUID).
4d205683
NR
738 *
739 * @return the item
740 */
14bb95fa 741 public JMenuItem createMenuItemOpenBook() {
9843a5e5
NR
742 JMenuItem open = new JMenuItem("Open", KeyEvent.VK_O);
743 open.addActionListener(new ActionListener() {
211f7ddb 744 @Override
9843a5e5 745 public void actionPerformed(ActionEvent e) {
14bb95fa 746 final GuiReaderBook selectedBook = helpee.getSelectedBook();
9843a5e5 747 if (selectedBook != null) {
14b57448 748 if (selectedBook.getMeta().getLuid() == null) {
14bb95fa
NR
749 helpee.removeBookPanes();
750 helpee.addBookPane(selectedBook.getMeta().getSource(),
751 true);
752 helpee.refreshBooks();
14b57448 753 } else {
14bb95fa 754 helpee.openBook(selectedBook);
14b57448
NR
755 }
756 }
757 }
758 });
759
760 return open;
761 }
762
763 /**
764 * Create the SetCover menu item for a book to change the linked source
765 * cover.
766 *
767 * @return the item
768 */
769 private JMenuItem createMenuItemSetCover() {
770 JMenuItem open = new JMenuItem("Set as cover for source", KeyEvent.VK_C);
771 open.addActionListener(new ActionListener() {
772 @Override
773 public void actionPerformed(ActionEvent e) {
14bb95fa 774 final GuiReaderBook selectedBook = helpee.getSelectedBook();
14b57448
NR
775 if (selectedBook != null) {
776 reader.getLibrary().setSourceCover(
777 selectedBook.getMeta().getSource(),
778 selectedBook.getMeta().getLuid());
085a2f9a
NR
779 MetaData source = selectedBook.getMeta().clone();
780 source.setLuid(null);
df6e2d88 781 GuiReaderCoverImager.clearIcon(source);
9843a5e5
NR
782 }
783 }
784 });
10d558d2 785
9843a5e5
NR
786 return open;
787 }
10d558d2 788
e6249b0f
NR
789 /**
790 * Display an error message and log the linked {@link Exception}.
791 *
792 * @param message
793 * the message
794 * @param title
795 * the title of the error message
796 * @param e
797 * the exception to log if any
798 */
14bb95fa 799 public void error(final String message, final String title, Exception e) {
e6249b0f
NR
800 Instance.getTraceHandler().error(title + ": " + message);
801 if (e != null) {
802 Instance.getTraceHandler().error(e);
803 }
804
805 SwingUtilities.invokeLater(new Runnable() {
806 @Override
807 public void run() {
808 JOptionPane.showMessageDialog(GuiReaderFrame.this, message,
809 title, JOptionPane.ERROR_MESSAGE);
810 }
811 });
812 }
14bb95fa
NR
813
814 @Override
815 public GuiReader getReader() {
816 return reader;
817 }
a6395bef 818}