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