Implement a text story viewer
[fanfix.git] / src / be / nikiroo / fanfix / reader / ui / GuiReaderTextViewer.java
1 package be.nikiroo.fanfix.reader.ui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import java.awt.Font;
6 import java.awt.LayoutManager;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9
10 import javax.swing.BorderFactory;
11 import javax.swing.BoxLayout;
12 import javax.swing.JButton;
13 import javax.swing.JFrame;
14 import javax.swing.JLabel;
15 import javax.swing.JPanel;
16 import javax.swing.JScrollPane;
17 import javax.swing.SwingConstants;
18
19 import be.nikiroo.fanfix.data.Chapter;
20 import be.nikiroo.fanfix.data.MetaData;
21 import be.nikiroo.fanfix.data.Paragraph;
22 import be.nikiroo.fanfix.data.Story;
23 import be.nikiroo.fanfix.library.BasicLibrary;
24
25 public class GuiReaderTextViewer extends JFrame {
26 private static final long serialVersionUID = 1L;
27
28 private Story story;
29 private MetaData meta;
30 private JLabel title;
31 private JLabel text;
32 private JLabel chapterLabel;
33 private GuiReaderPropertiesPane descPane;
34 private int currentChapter = -42; // cover = -1
35
36 public GuiReaderTextViewer(BasicLibrary lib, Story story) {
37 super(story.getMeta().getLuid() + ": " + story.getMeta().getTitle());
38
39 setSize(800, 600);
40
41 this.story = story;
42 this.meta = story.getMeta();
43
44 initGuiBase(lib);
45 initGuiNavButtons();
46
47 setChapter(-1);
48 }
49
50 private void initGuiBase(BasicLibrary lib) {
51 setLayout(new BorderLayout());
52
53 title = new JLabel();
54 title.setFont(new Font(Font.SERIF, Font.BOLD,
55 title.getFont().getSize() * 3));
56 title.setText(meta.getTitle());
57 title.setHorizontalAlignment(SwingConstants.CENTER);
58 title.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
59 add(title, BorderLayout.NORTH);
60
61 JPanel contentPane = new JPanel(new BorderLayout());
62 add(contentPane, BorderLayout.CENTER);
63
64 descPane = new GuiReaderPropertiesPane(lib, meta);
65 contentPane.add(descPane, BorderLayout.NORTH);
66
67 text = new JLabel();
68 text.setAlignmentY(TOP_ALIGNMENT);
69
70 // TODO: why is it broken?
71 // text.setPreferredSize(new Dimension(500, 500));
72
73 JScrollPane scroll = new JScrollPane(text);
74 scroll.getVerticalScrollBar().setUnitIncrement(16);
75 contentPane.add(scroll, BorderLayout.CENTER);
76 }
77
78 private void initGuiNavButtons() {
79 JPanel navButtons = new JPanel();
80 LayoutManager layout = new BoxLayout(navButtons, BoxLayout.X_AXIS);
81 navButtons.setLayout(layout);
82
83 navButtons.add(createNavButton("<<", new ActionListener() {
84 @Override
85 public void actionPerformed(ActionEvent e) {
86 setChapter(-1);
87 }
88 }));
89 navButtons.add(createNavButton(" < ", new ActionListener() {
90 @Override
91 public void actionPerformed(ActionEvent e) {
92 setChapter(currentChapter - 1);
93 }
94 }));
95 navButtons.add(createNavButton(" > ", new ActionListener() {
96 @Override
97 public void actionPerformed(ActionEvent e) {
98 setChapter(currentChapter + 1);
99 }
100 }));
101 navButtons.add(createNavButton(">>", new ActionListener() {
102 @Override
103 public void actionPerformed(ActionEvent e) {
104 setChapter(story.getChapters().size() - 1);
105 }
106 }));
107
108 add(navButtons, BorderLayout.SOUTH);
109
110 chapterLabel = new JLabel("");
111 navButtons.add(chapterLabel);
112 }
113
114 private JButton createNavButton(String text, ActionListener action) {
115 JButton navButton = new JButton(text);
116 navButton.addActionListener(action);
117 navButton.setForeground(Color.BLUE);
118 return navButton;
119 }
120
121 private void setChapter(int chapter) {
122 if (chapter >= -1 && chapter < story.getChapters().size()
123 && chapter != currentChapter) {
124 currentChapter = chapter;
125
126 Chapter chap;
127 if (chapter == -1) {
128 chap = meta.getResume();
129 setCoverPage();
130 } else {
131 chap = story.getChapters().get(chapter);
132 descPane.setVisible(false);
133 }
134
135 chapterLabel.setText("<HTML>&nbsp;&nbsp;<B>Chapter "
136 + chap.getNumber() + "</B>: " + chap.getName() + "</HTML>");
137
138 StringBuilder builder = new StringBuilder();
139 addChapter(builder, chap);
140 text.setText(builder.toString());
141 }
142 }
143
144 private void setCoverPage() {
145 descPane.setVisible(true);
146 }
147
148 // htmlInsert = no need to add HTML tags
149 private void addChapter(StringBuilder builder, Chapter chap) {
150 builder.append("<HTML>");
151
152 builder.append("<H1>");
153 builder.append("Chapter ");
154 builder.append(chap.getNumber());
155 builder.append(": ");
156 builder.append(chap.getName());
157 builder.append("</H1>");
158
159 builder.append("<JUSTIFY>");
160 for (Paragraph para : chap) {
161 addPara(builder, para);
162 }
163
164 if (paraInQuote) {
165 builder.append("</DIV>");
166 }
167 paraInQuote = false;
168
169 builder.append("</JUSTIFY>");
170
171 builder.append("</HTML>");
172 }
173
174 private boolean paraInQuote;
175
176 private void addPara(StringBuilder builder, Paragraph para) {
177 switch (para.getType()) {
178 case NORMAL:
179 builder.append(para.getContent());
180 builder.append("<BR>");
181 break;
182 case BLANK:
183 builder.append("<BR>");
184 break;
185 case BREAK:
186 builder.append("<BR>* * *<BR><BR>");
187 break;
188 case QUOTE:
189 if (!paraInQuote) {
190 builder.append("<DIV>");
191 } else {
192 builder.append("</DIV>");
193 }
194 paraInQuote = !paraInQuote;
195
196 builder.append("<DIV>");
197 builder.append("&ndash;&nbsp;&nbsp;");
198 builder.append(para.getContent());
199 builder.append("</DIV>");
200
201 break;
202 case IMAGE:
203 }
204 }
205 }