gui: add a Properties page
[fanfix.git] / src / be / nikiroo / fanfix / reader / tui / TuiReaderStoryWindow.java
CommitLineData
16a81ef7 1package be.nikiroo.fanfix.reader.tui;
c1873e56 2
edfd3577 3import java.util.ArrayList;
6a26aa76 4import java.util.Arrays;
edfd3577 5import java.util.List;
df6e2d88 6import java.util.Map;
edfd3577 7
0861d62a 8import jexer.TAction;
0861d62a 9import jexer.TButton;
0861d62a 10import jexer.TLabel;
f63c4267 11import jexer.TText;
0861d62a 12import jexer.TWindow;
cf9c5ed1 13import jexer.event.TCommandEvent;
c1873e56 14import jexer.event.TResizeEvent;
c1873e56
NR
15import be.nikiroo.fanfix.data.Chapter;
16import be.nikiroo.fanfix.data.MetaData;
17import be.nikiroo.fanfix.data.Paragraph;
9293188f 18import be.nikiroo.fanfix.data.Paragraph.ParagraphType;
c1873e56 19import be.nikiroo.fanfix.data.Story;
df6e2d88 20import be.nikiroo.fanfix.reader.BasicReader;
0bcb5c7f 21import be.nikiroo.jexer.TSizeConstraint;
8f34a795 22import be.nikiroo.jexer.TTable;
c1873e56 23
6a26aa76
NR
24/**
25 * This window will contain the {@link Story} in a readable format, with a
26 * chapter browser.
27 *
28 * @author niki
29 */
5dd985cf 30class TuiReaderStoryWindow extends TWindow {
c1873e56 31 private Story story;
6a26aa76 32 private TLabel titleField;
f63c4267 33 private TText textField;
6a26aa76
NR
34 private TTable table;
35 private int chapter = -99; // invalid value
edfd3577 36 private List<TButton> navigationButtons;
5b00c122 37 private TLabel currentChapter;
f00daa5e 38 private List<TSizeConstraint> sizeConstraints = new ArrayList<TSizeConstraint>();
c1873e56 39
6322ab64 40 // chapter: -1 for "none" (0 is desc)
e0fb1417
NR
41 public TuiReaderStoryWindow(TuiReaderApplication app, Story story,
42 int chapter) {
43 super(app, desc(story.getMeta()), 0, 0, 60, 18, CENTERED | RESIZABLE);
68e2c6d2 44
e0fb1417 45 this.story = story;
c1873e56 46
e0fb1417 47 app.setStatusBar(this, desc(story.getMeta()));
c1873e56 48
6a26aa76
NR
49 // last = use window background
50 titleField = new TLabel(this, " Title", 0, 1, "tlabel", false);
f00daa5e 51 textField = new TText(this, "", 0, 0, 1, 1);
494877be
NR
52 table = new TTable(this, 0, 0, 1, 1, null, null, Arrays.asList("Key",
53 "Value"), true);
edfd3577 54
e8796963 55 titleField.setEnabled(false);
e8796963 56
0b7e3d78 57 navigationButtons = new ArrayList<TButton>(5);
edfd3577 58
494877be 59 navigationButtons.add(addButton("<<", 0, 0, new TAction() {
211f7ddb 60 @Override
396e924c 61 public void DO() {
6a26aa76 62 setChapter(-1);
396e924c 63 }
edfd3577 64 }));
494877be 65 navigationButtons.add(addButton("< ", 4, 0, new TAction() {
211f7ddb 66 @Override
edfd3577
NR
67 public void DO() {
68 setChapter(TuiReaderStoryWindow.this.chapter - 1);
69 }
70 }));
494877be 71 navigationButtons.add(addButton("> ", 7, 0, new TAction() {
211f7ddb 72 @Override
edfd3577
NR
73 public void DO() {
74 setChapter(TuiReaderStoryWindow.this.chapter + 1);
75 }
76 }));
494877be 77 navigationButtons.add(addButton(">>", 10, 0, new TAction() {
211f7ddb 78 @Override
edfd3577
NR
79 public void DO() {
80 setChapter(getStory().getChapters().size());
81 }
82 }));
b0e88ebd 83
8670a283
NR
84 navigationButtons.get(0).setEnabled(false);
85 navigationButtons.get(1).setEnabled(false);
edfd3577 86
f00daa5e
NR
87 currentChapter = addLabel("", 0, 0);
88
494877be
NR
89 TSizeConstraint.setSize(sizeConstraints, textField, 1, 3, -1, -1);
90 TSizeConstraint.setSize(sizeConstraints, table, 0, 3, 0, -1);
f00daa5e
NR
91 TSizeConstraint.setSize(sizeConstraints, currentChapter, 14, -3, -1,
92 null);
93
94 for (TButton navigationButton : navigationButtons) {
494877be
NR
95 navigationButton.setShadowColor(null);
96 // navigationButton.setEmptyBorders(false);
f00daa5e
NR
97 TSizeConstraint.setSize(sizeConstraints, navigationButton, null,
98 -3, null, null);
99 }
100
101 onResize(null);
6a26aa76 102
edfd3577 103 setChapter(chapter);
c1873e56
NR
104 }
105
106 @Override
107 public void onResize(TResizeEvent resize) {
f00daa5e
NR
108 if (resize != null) {
109 super.onResize(resize);
110 }
c1873e56 111
f00daa5e
NR
112 // TODO: find out why TText and TTable does not behave the same way
113 // (offset of 2 for height and width)
6a26aa76 114
f00daa5e 115 TSizeConstraint.resize(sizeConstraints);
edfd3577 116
494877be
NR
117 // Improve the disposition of the scrollbars
118 textField.getVerticalScroller().setX(textField.getWidth());
119 textField.getVerticalScroller().setHeight(textField.getHeight());
120 textField.getHorizontalScroller().setX(-1);
121 textField.getHorizontalScroller().setWidth(textField.getWidth() + 1);
edfd3577 122
ce424b19 123 setCurrentChapterText();
edfd3577
NR
124 }
125
5b00c122
NR
126 /**
127 * Display the current chapter in the window, or the {@link Story} info
128 * page.
129 *
130 * @param chapter
131 * the chapter (including "0" which is the description) or "-1"
132 * to display the info page instead
133 */
edfd3577 134 private void setChapter(int chapter) {
edfd3577
NR
135 if (chapter > getStory().getChapters().size()) {
136 chapter = getStory().getChapters().size();
137 }
138
139 if (chapter != this.chapter) {
140 this.chapter = chapter;
b0e88ebd 141
8670a283 142 int max = getStory().getChapters().size();
5b00c122
NR
143 navigationButtons.get(0).setEnabled(chapter > -1);
144 navigationButtons.get(1).setEnabled(chapter > -1);
494877be 145 navigationButtons.get(2).setEnabled(chapter < max);
8670a283 146 navigationButtons.get(3).setEnabled(chapter < max);
b0e88ebd 147
5b00c122 148 if (chapter < 0) {
6a26aa76 149 displayInfoPage();
edfd3577 150 } else {
6a26aa76 151 displayChapterPage();
edfd3577 152 }
5b00c122
NR
153 }
154
155 setCurrentChapterText();
156 }
edfd3577 157
5b00c122
NR
158 /**
159 * Append the info page about the current {@link Story}.
160 *
161 * @param builder
162 * the builder to append to
163 */
6a26aa76
NR
164 private void displayInfoPage() {
165 textField.setVisible(false);
166 table.setVisible(true);
e8796963
NR
167 textField.setEnabled(false);
168 table.setEnabled(true);
5b00c122 169
6a26aa76 170 MetaData meta = getStory().getMeta();
5b00c122 171
6a26aa76 172 setCurrentTitle(meta.getTitle());
5b00c122 173
df6e2d88
NR
174 List<Map.Entry<String, String>> metaDesc = BasicReader
175 .getMetaDesc(meta);
176 String[][] metaDescObj = new String[metaDesc.size()][2];
177 int i = 0;
178 for (Map.Entry<String, String> entry : metaDesc) {
179 metaDescObj[i][0] = " " + entry.getKey();
180 metaDescObj[i][1] = entry.getValue();
181 i++;
f435c113
NR
182 }
183
df6e2d88 184 table.setRowData(metaDescObj);
6a26aa76
NR
185 table.setHeaders(Arrays.asList("key", "value"), false);
186 table.toTop();
5b00c122
NR
187 }
188
189 /**
190 * Append the current chapter.
191 *
192 * @param builder
193 * the builder to append to
194 */
6a26aa76
NR
195 private void displayChapterPage() {
196 table.setVisible(false);
197 textField.setVisible(true);
e8796963
NR
198 table.setEnabled(false);
199 textField.setEnabled(true);
6a26aa76
NR
200
201 StringBuilder builder = new StringBuilder();
202
5b00c122
NR
203 Chapter chap = null;
204 if (chapter == 0) {
205 chap = getStory().getMeta().getResume();
206 } else if (chapter > 0) {
207 chap = getStory().getChapters().get(chapter - 1);
208 }
209
210 // TODO: i18n
211 String chapName = chap == null ? "[No RESUME]" : chap.getName();
6a26aa76 212 setCurrentTitle(String.format("Chapter %d: %s", chapter, chapName));
5b00c122
NR
213
214 if (chap != null) {
215 for (Paragraph para : chap) {
216 if (para.getType() == ParagraphType.BREAK) {
217 builder.append("\n");
218 }
219 builder.append(para.getContent()).append("\n");
220 if (para.getType() == ParagraphType.BREAK) {
221 builder.append("\n");
fdc55375 222 }
edfd3577 223 }
edfd3577 224 }
6a26aa76
NR
225
226 setText(builder.toString());
c1873e56
NR
227 }
228
229 private Story getStory() {
c1873e56
NR
230 return story;
231 }
232
5b00c122
NR
233 /**
234 * Display the given text on the window.
235 *
236 * @param text
237 * the text to display
238 */
239 private void setText(String text) {
240 textField.setText(text);
241 textField.reflowData();
242 textField.toTop();
243 }
244
245 /**
246 * Set the current chapter area to the correct value.
247 */
248 private void setCurrentChapterText() {
249 String name;
250 if (chapter < 0) {
251 name = " " + getStory().getMeta().getTitle();
252 } else if (chapter == 0) {
253 Chapter resume = getStory().getMeta().getResume();
254 if (resume != null) {
255 name = String.format(" %s", resume.getName());
256 } else {
257 // TODO: i18n
258 name = "[No RESUME]";
259 }
260 } else {
261 int max = getStory().getChapters().size();
262 Chapter chap = getStory().getChapters().get(chapter - 1);
263 name = String.format(" %d/%d: %s", chapter, max, chap.getName());
264 }
265
266 int width = getWidth() - currentChapter.getX();
ce424b19 267 name = String.format("%-" + width + "s", name);
5b00c122
NR
268 if (name.length() > width) {
269 name = name.substring(0, width);
270 }
271
272 currentChapter.setLabel(name);
c1873e56 273 }
5b00c122
NR
274
275 /**
6a26aa76 276 * Set the current title in-window.
5b00c122 277 *
5b00c122 278 * @param title
6a26aa76 279 * the new title
5b00c122 280 */
6a26aa76 281 private void setCurrentTitle(String title) {
e8796963
NR
282 String pad = "";
283 if (title.length() < getWidth()) {
284 int padSize = (getWidth() - title.length()) / 2;
285 pad = String.format("%" + padSize + "s", "");
286 }
287
288 title = pad + title + pad;
6a26aa76
NR
289 titleField.setWidth(title.length());
290 titleField.setLabel(title);
291 }
5b00c122 292
6a26aa76
NR
293 private static String desc(MetaData meta) {
294 return String.format("%s: %s", meta.getLuid(), meta.getTitle());
5b00c122 295 }
cf9c5ed1
NR
296
297 @Override
298 public void onCommand(TCommandEvent command) {
299 if (command.getCmd().equals(TuiReaderApplication.CMD_EXIT)) {
300 TuiReaderApplication.close(this);
301 } else {
302 // Handle our own event if needed here
303 super.onCommand(command);
304 }
305 }
c1873e56 306}