1 package be
.nikiroo
.fanfix
.reader
.tui
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Arrays
;
13 import jexer
.event
.TCommandEvent
;
14 import jexer
.event
.TResizeEvent
;
15 import be
.nikiroo
.fanfix
.data
.Chapter
;
16 import be
.nikiroo
.fanfix
.data
.MetaData
;
17 import be
.nikiroo
.fanfix
.data
.Paragraph
;
18 import be
.nikiroo
.fanfix
.data
.Paragraph
.ParagraphType
;
19 import be
.nikiroo
.fanfix
.data
.Story
;
20 import be
.nikiroo
.fanfix
.reader
.BasicReader
;
21 import be
.nikiroo
.jexer
.TSizeConstraint
;
22 import be
.nikiroo
.jexer
.TTable
;
25 * This window will contain the {@link Story} in a readable format, with a
30 class TuiReaderStoryWindow
extends TWindow
{
32 private TLabel titleField
;
33 private TText textField
;
35 private int chapter
= -99; // invalid value
36 private List
<TButton
> navigationButtons
;
37 private TLabel currentChapter
;
38 private List
<TSizeConstraint
> sizeConstraints
= new ArrayList
<TSizeConstraint
>();
40 // chapter: -1 for "none" (0 is desc)
41 public TuiReaderStoryWindow(TuiReaderApplication app
, Story story
,
43 super(app
, desc(story
.getMeta()), 0, 0, 60, 18, CENTERED
| RESIZABLE
);
47 app
.setStatusBar(this, desc(story
.getMeta()));
49 // last = use window background
50 titleField
= new TLabel(this, " Title", 0, 1, "tlabel", false);
51 textField
= new TText(this, "", 0, 0, 1, 1);
52 table
= new TTable(this, 0, 0, 1, 1, null, null, Arrays
.asList("Key",
55 titleField
.setEnabled(false);
57 navigationButtons
= new ArrayList
<TButton
>(5);
59 navigationButtons
.add(addButton("<<", 0, 0, new TAction() {
65 navigationButtons
.add(addButton("< ", 4, 0, new TAction() {
68 setChapter(TuiReaderStoryWindow
.this.chapter
- 1);
71 navigationButtons
.add(addButton("> ", 7, 0, new TAction() {
74 setChapter(TuiReaderStoryWindow
.this.chapter
+ 1);
77 navigationButtons
.add(addButton(">>", 10, 0, new TAction() {
80 setChapter(getStory().getChapters().size());
84 navigationButtons
.get(0).setEnabled(false);
85 navigationButtons
.get(1).setEnabled(false);
87 currentChapter
= addLabel("", 0, 0);
89 TSizeConstraint
.setSize(sizeConstraints
, textField
, 1, 3, -1, -1);
90 TSizeConstraint
.setSize(sizeConstraints
, table
, 0, 3, 0, -1);
91 TSizeConstraint
.setSize(sizeConstraints
, currentChapter
, 14, -3, -1,
94 for (TButton navigationButton
: navigationButtons
) {
95 navigationButton
.setShadowColor(null);
96 // navigationButton.setEmptyBorders(false);
97 TSizeConstraint
.setSize(sizeConstraints
, navigationButton
, null,
107 public void onResize(TResizeEvent resize
) {
108 if (resize
!= null) {
109 super.onResize(resize
);
112 // TODO: find out why TText and TTable does not behave the same way
113 // (offset of 2 for height and width)
115 TSizeConstraint
.resize(sizeConstraints
);
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);
123 setCurrentChapterText();
127 * Display the current chapter in the window, or the {@link Story} info
131 * the chapter (including "0" which is the description) or "-1"
132 * to display the info page instead
134 private void setChapter(int chapter
) {
135 if (chapter
> getStory().getChapters().size()) {
136 chapter
= getStory().getChapters().size();
139 if (chapter
!= this.chapter
) {
140 this.chapter
= chapter
;
142 int max
= getStory().getChapters().size();
143 navigationButtons
.get(0).setEnabled(chapter
> -1);
144 navigationButtons
.get(1).setEnabled(chapter
> -1);
145 navigationButtons
.get(2).setEnabled(chapter
< max
);
146 navigationButtons
.get(3).setEnabled(chapter
< max
);
151 displayChapterPage();
155 setCurrentChapterText();
159 * Append the info page about the current {@link Story}.
162 * the builder to append to
164 private void displayInfoPage() {
165 textField
.setVisible(false);
166 table
.setVisible(true);
167 textField
.setEnabled(false);
168 table
.setEnabled(true);
170 MetaData meta
= getStory().getMeta();
172 setCurrentTitle(meta
.getTitle());
174 List
<Map
.Entry
<String
, String
>> metaDesc
= BasicReader
176 String
[][] metaDescObj
= new String
[metaDesc
.size()][2];
178 for (Map
.Entry
<String
, String
> entry
: metaDesc
) {
179 metaDescObj
[i
][0] = " " + entry
.getKey();
180 metaDescObj
[i
][1] = entry
.getValue();
184 table
.setRowData(metaDescObj
);
185 table
.setHeaders(Arrays
.asList("key", "value"), false);
190 * Append the current chapter.
193 * the builder to append to
195 private void displayChapterPage() {
196 table
.setVisible(false);
197 textField
.setVisible(true);
198 table
.setEnabled(false);
199 textField
.setEnabled(true);
201 StringBuilder builder
= new StringBuilder();
205 chap
= getStory().getMeta().getResume();
206 } else if (chapter
> 0) {
207 chap
= getStory().getChapters().get(chapter
- 1);
211 String chapName
= chap
== null ?
"[No RESUME]" : chap
.getName();
212 setCurrentTitle(String
.format("Chapter %d: %s", chapter
, chapName
));
215 for (Paragraph para
: chap
) {
216 if (para
.getType() == ParagraphType
.BREAK
) {
217 builder
.append("\n");
219 builder
.append(para
.getContent()).append("\n");
220 if (para
.getType() == ParagraphType
.BREAK
) {
221 builder
.append("\n");
226 setText(builder
.toString());
229 private Story
getStory() {
234 * Display the given text on the window.
237 * the text to display
239 private void setText(String text
) {
240 textField
.setText(text
);
241 textField
.reflowData();
246 * Set the current chapter area to the correct value.
248 private void setCurrentChapterText() {
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());
258 name
= "[No RESUME]";
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());
266 int width
= getWidth() - currentChapter
.getX();
267 name
= String
.format("%-" + width
+ "s", name
);
268 if (name
.length() > width
) {
269 name
= name
.substring(0, width
);
272 currentChapter
.setLabel(name
);
276 * Set the current title in-window.
281 private void setCurrentTitle(String title
) {
283 if (title
.length() < getWidth()) {
284 int padSize
= (getWidth() - title
.length()) / 2;
285 pad
= String
.format("%" + padSize
+ "s", "");
288 title
= pad
+ title
+ pad
;
289 titleField
.setWidth(title
.length());
290 titleField
.setLabel(title
);
293 private static String
desc(MetaData meta
) {
294 return String
.format("%s: %s", meta
.getLuid(), meta
.getTitle());
298 public void onCommand(TCommandEvent command
) {
299 if (command
.getCmd().equals(TuiReaderApplication
.CMD_EXIT
)) {
300 TuiReaderApplication
.close(this);
302 // Handle our own event if needed here
303 super.onCommand(command
);