X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2Freader%2Fui%2FGuiReader.java;fp=src%2Fbe%2Fnikiroo%2Ffanfix%2Freader%2Fui%2FGuiReader.java;h=0000000000000000000000000000000000000000;hb=d7367179b645781b4e0e4fc24893cb1e6725c14c;hp=a02cc84f558892bfa4f055db720cda8db8c21097;hpb=1387a30ab59dbf4071f2c5e5e0e08ca98c75b726;p=fanfix.git diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReader.java b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java deleted file mode 100644 index a02cc84..0000000 --- a/src/be/nikiroo/fanfix/reader/ui/GuiReader.java +++ /dev/null @@ -1,499 +0,0 @@ -package be.nikiroo.fanfix.reader.ui; - -import java.awt.Desktop; -import java.awt.EventQueue; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; - -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; - -import be.nikiroo.fanfix.Instance; -import be.nikiroo.fanfix.VersionCheck; -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.CacheLibrary; -import be.nikiroo.fanfix.reader.BasicReader; -import be.nikiroo.fanfix.reader.Reader; -import be.nikiroo.fanfix.searchable.BasicSearchable; -import be.nikiroo.fanfix.searchable.SearchableTag; -import be.nikiroo.fanfix.supported.SupportType; -import be.nikiroo.utils.Progress; -import be.nikiroo.utils.Version; -import be.nikiroo.utils.ui.UIUtils; - -/** - * This class implements a graphical {@link Reader} using the Swing library from - * Java. - *

- * It can thus be themed to look native-like, or metal-like, or use any other - * theme you may want to try. - *

- * We actually try to enable native look-alike mode on start. - * - * @author niki - */ -class GuiReader extends BasicReader { - static private boolean nativeLookLoaded; - - private CacheLibrary cacheLib; - - private File cacheDir; - - /** - * Create a new graphical {@link Reader}. - * - * @throws IOException - * in case of I/O errors - */ - public GuiReader() throws IOException { - // TODO: allow different themes? - if (!nativeLookLoaded) { - UIUtils.setLookAndFeel(); - nativeLookLoaded = true; - } - - cacheDir = Instance.getInstance().getReaderDir(); - cacheDir.mkdirs(); - if (!cacheDir.exists()) { - throw new IOException( - "Cannote create cache directory for local reader: " - + cacheDir); - } - } - - @Override - public synchronized BasicLibrary getLibrary() { - if (cacheLib == null) { - BasicLibrary lib = super.getLibrary(); - if (lib instanceof CacheLibrary) { - cacheLib = (CacheLibrary) lib; - } else { - cacheLib = new CacheLibrary(cacheDir, lib, Instance.getInstance().getUiConfig()); - } - } - - return cacheLib; - } - - @Override - public void read(boolean sync) throws IOException { - MetaData meta = getMeta(); - - if (meta == null) { - throw new IOException("No story to read"); - } - - read(meta.getLuid(), sync, null); - } - - /** - * Check if the {@link Story} denoted by this Library UID is present in the - * {@link GuiReader} cache. - * - * @param luid - * the Library UID - * - * @return TRUE if it is - */ - public boolean isCached(String luid) { - return cacheLib.isCached(luid); - } - - @Override - public void browse(String type) { - final Boolean[] done = new Boolean[] { false }; - - // TODO: improve presentation of update message - final VersionCheck updates = VersionCheck.check(); - StringBuilder builder = new StringBuilder(); - - final JEditorPane updateMessage = new JEditorPane("text/html", ""); - if (updates.isNewVersionAvailable()) { - builder.append(trans(StringIdGui.NEW_VERSION_AVAILABLE, - "https://github.com/nikiroo/fanfix/releases")); - builder.append("
"); - builder.append("
"); - for (Version v : updates.getNewer()) { - builder.append("\t" - + trans(StringIdGui.NEW_VERSION_VERSION, v.toString()) - + ""); - builder.append("
"); - builder.append("

"); - } - - // html content - updateMessage.setText("" // - + builder// - + ""); - - // handle link events - updateMessage.addHyperlinkListener(new HyperlinkListener() { - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType().equals( - HyperlinkEvent.EventType.ACTIVATED)) - try { - Desktop.getDesktop().browse(e.getURL().toURI()); - } catch (IOException ee) { - Instance.getInstance().getTraceHandler().error(ee); - } catch (URISyntaxException ee) { - Instance.getInstance().getTraceHandler().error(ee); - } - } - }); - updateMessage.setEditable(false); - updateMessage.setBackground(new JLabel().getBackground()); - } - - final String typeFinal = type; - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - if (updates.isNewVersionAvailable()) { - int rep = JOptionPane.showConfirmDialog(null, - updateMessage, - trans(StringIdGui.NEW_VERSION_TITLE), - JOptionPane.OK_CANCEL_OPTION); - if (rep == JOptionPane.OK_OPTION) { - updates.ok(); - } else { - updates.ignore(); - } - } - - new Thread(new Runnable() { - @Override - public void run() { - try { - GuiReaderFrame gui = new GuiReaderFrame( - GuiReader.this, typeFinal); - sync(gui); - } catch (Exception e) { - Instance.getInstance().getTraceHandler().error(e); - } finally { - done[0] = true; - } - - } - }).start(); - } - }); - - // This action must be synchronous, so wait until the frame is closed - while (!done[0]) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - } - } - } - - @Override - public void start(File target, String program, boolean sync) - throws IOException { - - boolean handled = false; - if (program == null && !sync) { - try { - Desktop.getDesktop().browse(target.toURI()); - handled = true; - } catch (UnsupportedOperationException e) { - } - } - - if (!handled) { - super.start(target, program, sync); - } - } - - @Override - public void search(boolean sync) throws IOException { - GuiReaderSearchFrame search = new GuiReaderSearchFrame(this); - if (sync) { - sync(search); - } else { - search.setVisible(true); - } - } - - @Override - public void search(SupportType searchOn, String keywords, int page, - int item, boolean sync) { - GuiReaderSearchFrame search = new GuiReaderSearchFrame(this); - search.search(searchOn, keywords, page, item); - if (sync) { - sync(search); - } else { - search.setVisible(true); - } - } - - @Override - public void searchTag(final SupportType searchOn, final int page, - final int item, final boolean sync, final Integer... tags) { - - final GuiReaderSearchFrame search = new GuiReaderSearchFrame(this); - - final BasicSearchable searchable = BasicSearchable - .getSearchable(searchOn); - - Runnable action = new Runnable() { - @Override - public void run() { - SearchableTag tag = null; - try { - tag = searchable.getTag(tags); - } catch (IOException e) { - Instance.getInstance().getTraceHandler().error(e); - } - - search.searchTag(searchOn, page, item, tag); - - if (sync) { - sync(search); - } else { - search.setVisible(true); - } - } - }; - - if (sync) { - action.run(); - } else { - new Thread(action).start(); - } - } - - /** - * Delete the {@link Story} from the cache if it is present, but NOT - * from the main library. - *

- * The next time we try to retrieve the {@link Story}, it may be required to - * cache it again. - * - * @param luid - * the luid of the {@link Story} - */ - void clearLocalReaderCache(String luid) { - try { - cacheLib.clearFromCache(luid); - } catch (IOException e) { - Instance.getInstance().getTraceHandler().error(e); - } - } - - /** - * Forward the delete operation to the main library. - *

- * The {@link Story} will be deleted from the main library as well as the - * cache if present. - * - * @param luid - * the {@link Story} to delete - */ - void delete(String luid) { - try { - cacheLib.delete(luid); - } catch (IOException e) { - Instance.getInstance().getTraceHandler().error(e); - } - } - - /** - * "Open" the given {@link Story}. It usually involves starting an external - * program adapted to the given file type. - * - * @param luid - * the luid of the {@link Story} to open - * @param sync - * execute the process synchronously (wait until it is terminated - * before returning) - * @param pg - * the optional progress (we may need to prepare the - * {@link Story} for reading - * - * @throws IOException - * in case of I/O errors - */ - void read(String luid, boolean sync, Progress pg) throws IOException { - MetaData meta = cacheLib.getInfo(luid); - - boolean textInternal = Instance.getInstance().getUiConfig() - .getBoolean(UiConfig.NON_IMAGES_DOCUMENT_USE_INTERNAL_READER, true); - boolean imageInternal = Instance.getInstance().getUiConfig() - .getBoolean(UiConfig.IMAGES_DOCUMENT_USE_INTERNAL_READER, true); - - boolean useInternalViewer = true; - if (meta.isImageDocument() && !imageInternal) { - useInternalViewer = false; - } - if (!meta.isImageDocument() && !textInternal) { - useInternalViewer = false; - } - - if (useInternalViewer) { - GuiReaderViewer viewer = new GuiReaderViewer(cacheLib, - cacheLib.getStory(luid, null)); - if (sync) { - sync(viewer); - } else { - viewer.setVisible(true); - } - } else { - File file = cacheLib.getFile(luid, pg); - openExternal(meta, file, sync); - } - } - - - /** - * "Prefetch" the given {@link Story}. - *

- * Synchronous method. - * - * @param luid - * the luid of the {@link Story} to prefetch - * @param pg - * the optional progress (we may need to prepare the - * {@link Story} for reading - * - * @throws IOException - * in case of I/O errors - */ - void prefetch(String luid, Progress pg) throws IOException { - cacheLib.getFile(luid, pg); - } - /** - * Change the source of the given {@link Story} (the source is the main - * information used to group the stories together). - *

- * In other words, move the {@link Story} into other source. - *

- * The source can be a new one, it needs not exist before hand. - * - * @param luid - * the luid of the {@link Story} to move - * @param newSource - * the new source - */ - void changeSource(String luid, String newSource) { - try { - cacheLib.changeSource(luid, newSource, null); - } catch (IOException e) { - Instance.getInstance().getTraceHandler().error(e); - } - } - - /** - * Change the title of the given {@link Story}. - * - * @param luid - * the luid of the {@link Story} to change - * @param newTitle - * the new title - */ - void changeTitle(String luid, String newTitle) { - try { - cacheLib.changeTitle(luid, newTitle, null); - } catch (IOException e) { - Instance.getInstance().getTraceHandler().error(e); - } - } - - /** - * Change the author of the given {@link Story}. - *

- * The author can be a new one, it needs not exist before hand. - * - * @param luid - * the luid of the {@link Story} to change - * @param newAuthor - * the new author - */ - void changeAuthor(String luid, String newAuthor) { - try { - cacheLib.changeAuthor(luid, newAuthor, null); - } catch (IOException e) { - Instance.getInstance().getTraceHandler().error(e); - } - } - - /** - * Simple shortcut method to call {link Instance#getTransGui()#getString()}. - * - * @param id - * the ID to translate - * - * @return the translated result - */ - static String trans(StringIdGui id, Object... params) { - return Instance.getInstance().getTransGui().getString(id, params); - } - - /** - * Start a frame and wait until it is closed before returning. - * - * @param frame - * the frame to start - */ - static private void sync(final JFrame frame) { - if (EventQueue.isDispatchThread()) { - throw new IllegalStateException( - "Cannot call a sync method in the dispatch thread"); - } - - final Boolean[] done = new Boolean[] { false }; - try { - Runnable run = new Runnable() { - @Override - public void run() { - try { - frame.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - super.windowClosing(e); - done[0] = true; - } - }); - - frame.setVisible(true); - } catch (Exception e) { - done[0] = true; - } - } - }; - - if (EventQueue.isDispatchThread()) { - run.run(); - } else { - EventQueue.invokeLater(run); - } - } catch (Exception e) { - Instance.getInstance().getTraceHandler().error(e); - done[0] = true; - } - - // This action must be synchronous, so wait until the frame is closed - while (!done[0]) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - } - } - } -}