X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Ffanfix%2Freader%2Fui%2FGuiReaderViewerPanel.java;h=0577a0ab2f4bac5c734e5282d589f5d8004926cc;hb=1387a30ab59dbf4071f2c5e5e0e08ca98c75b726;hp=1ff4fcc45c69de3e2c4ebb7c48cf9b7bc2df536e;hpb=32ba91e9d2443ac9d17d3db66eef4c570d02cdf1;p=nikiroo-utils.git diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReaderViewerPanel.java b/src/be/nikiroo/fanfix/reader/ui/GuiReaderViewerPanel.java index 1ff4fcc..0577a0a 100644 --- a/src/be/nikiroo/fanfix/reader/ui/GuiReaderViewerPanel.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReaderViewerPanel.java @@ -1,6 +1,8 @@ package be.nikiroo.fanfix.reader.ui; import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; @@ -8,13 +10,17 @@ import java.awt.image.BufferedImage; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; +import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; +import javax.swing.SwingConstants; import be.nikiroo.fanfix.Instance; +import be.nikiroo.fanfix.bundles.StringIdGui; import be.nikiroo.fanfix.data.Chapter; +import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; import be.nikiroo.utils.Image; import be.nikiroo.utils.ui.ImageUtilsAwt; @@ -29,9 +35,14 @@ public class GuiReaderViewerPanel extends JPanel { private boolean imageDocument; private Chapter chap; - - private JLabel label; + private JScrollPane scroll; private GuiReaderViewerTextOutput htmlOutput; + + // text only: + private JEditorPane text; + + // image only: + private JLabel image; private JProgressBar imageProgress; private int currentImage; private JButton left; @@ -41,23 +52,42 @@ public class GuiReaderViewerPanel extends JPanel { * Create a new viewer. * * @param story - * the {@link Story} to work on. + * the {@link Story} to work on */ public GuiReaderViewerPanel(Story story) { + this(story.getMeta(), story.getMeta().isImageDocument()); + } + + /** + * Create a new viewer. + * + * @param meta + * the {@link MetaData} of the story to show + * @param isImageDocument + * TRUE if it is an image document, FALSE if not + */ + public GuiReaderViewerPanel(MetaData meta, boolean isImageDocument) { super(new BorderLayout()); - this.imageDocument = story.getMeta().isImageDocument(); - this.label = new JLabel(); - label.setAlignmentY(TOP_ALIGNMENT); + this.imageDocument = isImageDocument; + + this.text = new JEditorPane("text/html", ""); + text.setEditable(false); + text.setAlignmentY(TOP_ALIGNMENT); htmlOutput = new GuiReaderViewerTextOutput(); - if (!imageDocument) { - // TODO: why is it broken? - // text.setPreferredSize(new Dimension(500, 500)); + image = new JLabel(); + image.setHorizontalAlignment(SwingConstants.CENTER); - JScrollPane scroll = new JScrollPane(label); - scroll.getVerticalScrollBar().setUnitIncrement(16); + scroll = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scroll.getVerticalScrollBar().setUnitIncrement(16); + // TODO: + // JButton up = new BasicArrowButton(BasicArrowButton.NORTH); + // JButton down = new BasicArrowButton(BasicArrowButton.SOUTH); + + if (!imageDocument) { add(scroll, BorderLayout.CENTER); } else { imageProgress = new JProgressBar(); @@ -65,9 +95,9 @@ public class GuiReaderViewerPanel extends JPanel { add(imageProgress, BorderLayout.SOUTH); JPanel main = new JPanel(new BorderLayout()); - main.add(label, BorderLayout.CENTER); + main.add(scroll, BorderLayout.CENTER); - left = new JButton(" < "); + left = new JButton("    <    "); left.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -76,7 +106,7 @@ public class GuiReaderViewerPanel extends JPanel { }); main.add(left, BorderLayout.WEST); - right = new JButton(" > "); + right = new JButton("    >    "); right.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -86,9 +116,10 @@ public class GuiReaderViewerPanel extends JPanel { main.add(right, BorderLayout.EAST); add(main, BorderLayout.CENTER); + main.invalidate(); } - setChapter(story.getMeta().getResume()); + setChapter(meta.getResume()); } /** @@ -106,7 +137,7 @@ public class GuiReaderViewerPanel extends JPanel { this.chap = chap; if (!imageDocument) { - label.setText(htmlOutput.convert(chap)); + setText(chap); } else { left.setVisible(chap.getNumber() > 0); right.setVisible(chap.getNumber() > 0); @@ -116,13 +147,56 @@ public class GuiReaderViewerPanel extends JPanel { imageProgress.setMaximum(chap.getParagraphs().size() - 1); if (chap.getNumber() == 0) { - label.setText(htmlOutput.convert(chap)); + setText(chap); } else { setImage(0); } } } + /** + * Will set and display the current chapter text. + * + * @param chap + * the chapter to display + */ + private void setText(final Chapter chap) { + new Thread(new Runnable() { + @Override + public void run() { + final String content = htmlOutput.convert(chap); + // Wait until size computations are correct + while (!scroll.isValid()) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + } + } + + setText(content); + } + }).start(); + } + + /** + * Actually set the text in the UI. + *

+ * Do NOT use this method from the UI thread. + * + * @param content + * the text + */ + private void setText(final String content) { + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + text.setText(content); + text.setCaretPosition(0); + scroll.setViewportView(text); + } + }); + } + /** * Will set and display the current image, take care about the progression * and update the left and right cursors' enabled property. @@ -139,26 +213,86 @@ public class GuiReaderViewerPanel extends JPanel { } imageProgress.setValue(i); - imageProgress.setString(String.format("Image %d / %d", i + 1, chap - .getParagraphs().size())); + imageProgress.setString(GuiReader.trans(StringIdGui.IMAGE_PROGRESSION, + i + 1, chap.getParagraphs().size())); currentImage = i; - label.setText(""); - label.setIcon(null); - Image img = chap.getParagraphs().get(i).getContentImage(); - if (img == null) { - label.setText("Error: cannot render image."); - } else { + final Image img = chap.getParagraphs().get(i).getContentImage(); + + // prepare the viewport to get the right sizes later on + image.setIcon(null); + scroll.setViewportView(image); + + new Thread(new Runnable() { + @Override + public void run() { + // Wait until size computations are correct + while (!scroll.isValid()) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + } + } + + if (img == null) { + setText("Error: cannot render image."); + } else { + setImage(img); + } + } + }).start(); + } + + /** + * Actually set the image in the UI. + *

+ * Do NOT use this method from the UI thread. + * + * @param img + * the image to set + */ + private void setImage(Image img) { + try { + int scrollWidth = scroll.getWidth() + - scroll.getVerticalScrollBar().getWidth(); + + BufferedImage buffImg = ImageUtilsAwt.fromImage(img); + + int iw = buffImg.getWidth(); + int ih = buffImg.getHeight(); + double ratio = ((double) ih) / iw; + + int w = scrollWidth; + int h = (int) (ratio * scrollWidth); + + BufferedImage resizedImage = new BufferedImage(w, h, + BufferedImage.TYPE_4BYTE_ABGR); + + Graphics2D g = resizedImage.createGraphics(); try { - BufferedImage buffImg = ImageUtilsAwt.fromImage(img); - Icon icon = new ImageIcon(buffImg); - label.setIcon(icon); - } catch (Exception e) { - Instance.getTraceHandler().error( - new Exception("Failed to load image into label", e)); - label.setText("Error: cannot load image."); + g.drawImage(buffImg, 0, 0, w, h, null); + } finally { + g.dispose(); } + + final Icon icon = new ImageIcon(resizedImage); + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + image.setIcon(icon); + scroll.setViewportView(image); + } + }); + } catch (Exception e) { + Instance.getInstance().getTraceHandler().error( + new Exception("Failed to load image into label", e)); + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + text.setText("Error: cannot load image."); + } + }); } } }