From 47b1710c92c1a14188a00c433879b94c7c3e7ea1 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Fri, 22 Mar 2019 23:07:58 +0100 Subject: [PATCH] Implement a text story viewer --- .../nikiroo/fanfix/reader/ui/GuiReader.java | 15 +- .../fanfix/reader/ui/GuiReaderTextViewer.java | 205 ++++++++++++++++++ 2 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 src/be/nikiroo/fanfix/reader/ui/GuiReaderTextViewer.java diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReader.java b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java index aed0a92..b1e9802 100644 --- a/src/be/nikiroo/fanfix/reader/ui/GuiReader.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java @@ -268,9 +268,18 @@ class GuiReader extends BasicReader { void read(String luid, boolean sync, Progress pg) throws IOException { File file = cacheLib.getFile(luid, pg); - // TODO: show a special page for the chapter? - // We could also implement an internal viewer, both for image and - // non-image documents + GuiReaderTextViewer viewer = new GuiReaderTextViewer(cacheLib, + cacheLib.getStory(luid, null)); + + // TODO: testing text viewer: + if (false) { + if (sync) { + sync(viewer); + } else { + viewer.setVisible(true); + } + } + openExternal(getLibrary().getInfo(luid), file, sync); } diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReaderTextViewer.java b/src/be/nikiroo/fanfix/reader/ui/GuiReaderTextViewer.java new file mode 100644 index 0000000..8f27c6c --- /dev/null +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReaderTextViewer.java @@ -0,0 +1,205 @@ +package be.nikiroo.fanfix.reader.ui; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.LayoutManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SwingConstants; + +import be.nikiroo.fanfix.data.Chapter; +import be.nikiroo.fanfix.data.MetaData; +import be.nikiroo.fanfix.data.Paragraph; +import be.nikiroo.fanfix.data.Story; +import be.nikiroo.fanfix.library.BasicLibrary; + +public class GuiReaderTextViewer extends JFrame { + private static final long serialVersionUID = 1L; + + private Story story; + private MetaData meta; + private JLabel title; + private JLabel text; + private JLabel chapterLabel; + private GuiReaderPropertiesPane descPane; + private int currentChapter = -42; // cover = -1 + + public GuiReaderTextViewer(BasicLibrary lib, Story story) { + super(story.getMeta().getLuid() + ": " + story.getMeta().getTitle()); + + setSize(800, 600); + + this.story = story; + this.meta = story.getMeta(); + + initGuiBase(lib); + initGuiNavButtons(); + + setChapter(-1); + } + + private void initGuiBase(BasicLibrary lib) { + setLayout(new BorderLayout()); + + title = new JLabel(); + title.setFont(new Font(Font.SERIF, Font.BOLD, + title.getFont().getSize() * 3)); + title.setText(meta.getTitle()); + title.setHorizontalAlignment(SwingConstants.CENTER); + title.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + add(title, BorderLayout.NORTH); + + JPanel contentPane = new JPanel(new BorderLayout()); + add(contentPane, BorderLayout.CENTER); + + descPane = new GuiReaderPropertiesPane(lib, meta); + contentPane.add(descPane, BorderLayout.NORTH); + + text = new JLabel(); + text.setAlignmentY(TOP_ALIGNMENT); + + // TODO: why is it broken? + // text.setPreferredSize(new Dimension(500, 500)); + + JScrollPane scroll = new JScrollPane(text); + scroll.getVerticalScrollBar().setUnitIncrement(16); + contentPane.add(scroll, BorderLayout.CENTER); + } + + private void initGuiNavButtons() { + JPanel navButtons = new JPanel(); + LayoutManager layout = new BoxLayout(navButtons, BoxLayout.X_AXIS); + navButtons.setLayout(layout); + + navButtons.add(createNavButton("<<", new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setChapter(-1); + } + })); + navButtons.add(createNavButton(" < ", new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setChapter(currentChapter - 1); + } + })); + navButtons.add(createNavButton(" > ", new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setChapter(currentChapter + 1); + } + })); + navButtons.add(createNavButton(">>", new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setChapter(story.getChapters().size() - 1); + } + })); + + add(navButtons, BorderLayout.SOUTH); + + chapterLabel = new JLabel(""); + navButtons.add(chapterLabel); + } + + private JButton createNavButton(String text, ActionListener action) { + JButton navButton = new JButton(text); + navButton.addActionListener(action); + navButton.setForeground(Color.BLUE); + return navButton; + } + + private void setChapter(int chapter) { + if (chapter >= -1 && chapter < story.getChapters().size() + && chapter != currentChapter) { + currentChapter = chapter; + + Chapter chap; + if (chapter == -1) { + chap = meta.getResume(); + setCoverPage(); + } else { + chap = story.getChapters().get(chapter); + descPane.setVisible(false); + } + + chapterLabel.setText("  Chapter " + + chap.getNumber() + ": " + chap.getName() + ""); + + StringBuilder builder = new StringBuilder(); + addChapter(builder, chap); + text.setText(builder.toString()); + } + } + + private void setCoverPage() { + descPane.setVisible(true); + } + + // htmlInsert = no need to add HTML tags + private void addChapter(StringBuilder builder, Chapter chap) { + builder.append(""); + + builder.append("

"); + builder.append("Chapter "); + builder.append(chap.getNumber()); + builder.append(": "); + builder.append(chap.getName()); + builder.append("

"); + + builder.append(""); + for (Paragraph para : chap) { + addPara(builder, para); + } + + if (paraInQuote) { + builder.append(""); + } + paraInQuote = false; + + builder.append(""); + + builder.append(""); + } + + private boolean paraInQuote; + + private void addPara(StringBuilder builder, Paragraph para) { + switch (para.getType()) { + case NORMAL: + builder.append(para.getContent()); + builder.append("
"); + break; + case BLANK: + builder.append("
"); + break; + case BREAK: + builder.append("
* * *

"); + break; + case QUOTE: + if (!paraInQuote) { + builder.append("
"); + } else { + builder.append("
"); + } + paraInQuote = !paraInQuote; + + builder.append("
"); + builder.append("–  "); + builder.append(para.getContent()); + builder.append("
"); + + break; + case IMAGE: + } + } +} -- 2.27.0