1 package be
.nikiroo
.fanfix
.reader
.tui
;
3 import java
.io
.IOException
;
4 import java
.util
.ArrayList
;
8 import jexer
.TComboBox
;
11 import jexer
.TFileOpenBox
.Type
;
12 import jexer
.TKeypress
;
15 import jexer
.TStatusBar
;
17 import jexer
.event
.TCommandEvent
;
18 import jexer
.event
.TKeypressEvent
;
19 import jexer
.event
.TMenuEvent
;
20 import jexer
.event
.TResizeEvent
;
21 import be
.nikiroo
.fanfix
.Instance
;
22 import be
.nikiroo
.fanfix
.data
.MetaData
;
23 import be
.nikiroo
.fanfix
.library
.BasicLibrary
;
24 import be
.nikiroo
.fanfix
.output
.BasicOutput
.OutputType
;
25 import be
.nikiroo
.jexer
.TSizeConstraint
;
28 * The library window, that will list all the (filtered) stories available in
29 * this {@link BasicLibrary}.
33 class TuiReaderMainWindow
extends TWindow
{
34 public static final int MENU_SEARCH
= 1100;
35 public static final TCommand CMD_SEARCH
= new TCommand(MENU_SEARCH
) {
43 private List
<MetaData
> listKeys
;
44 private List
<String
> listItems
;
45 private TuiReaderApplication reader
;
47 private Mode mode
= Mode
.SOURCE
;
48 private String target
= null;
49 private String filter
= "";
51 private List
<TSizeConstraint
> sizeConstraints
= new ArrayList
<TSizeConstraint
>();
53 // The 2 comboboxes used to select by source/author
54 private TComboBox selectTargetBox
;
55 private TComboBox selectBox
;
58 * Create a new {@link TuiReaderMainWindow} without any stories in the list.
61 * the reader and main application
63 public TuiReaderMainWindow(TuiReaderApplication reader
) {
64 // Construct a demo window. X and Y don't matter because it will be
66 super(reader
, "Library", 0, 0, 60, 18, CENTERED
| RESIZABLE
);
70 listKeys
= new ArrayList
<MetaData
>();
71 listItems
= new ArrayList
<String
>();
77 TStatusBar statusBar
= reader
.setStatusBar(this, "Library");
78 statusBar
.addShortcutKeypress(TKeypress
.kbCtrlF
, CMD_SEARCH
, "Search");
80 TSizeConstraint
.resize(sizeConstraints
);
82 // TODO: remove when not used anymore
84 // addLabel("Label (1,1)", 1, 1);
85 // addButton("&Button (35,1)", 35, 1, new TAction() {
89 // addCheckbox(1, 2, "Checky (1,2)", false);
90 // addProgressBar(1, 3, 30, 42);
91 // TRadioGroup groupy = addRadioGroup(1, 4, "Radio groupy");
92 // groupy.addRadioButton("Fanfan");
93 // groupy.addRadioButton("Tulipe");
94 // addField(1, 10, 20, false, "text not fixed.");
95 // addField(1, 11, 20, true, "text fixed.");
96 // addText("20x4 Text in (12,20)", 1, 12, 20, 4);
98 // TTreeView tree = addTreeView(30, 5, 20, 5);
99 // TTreeItem root = new TTreeItem(tree, "expended root", true);
100 // tree.setSelected(root); // needed to allow arrow navigation without
101 // // mouse-clicking before
103 // root.addChild("child");
104 // root.addChild("child 2").addChild("sub child");
107 private void addSearch() {
108 TLabel lblSearch
= addLabel("Search: ", 0, 0);
110 TField search
= new TField(this, 0, 0, 1, true) {
112 public void onKeypress(TKeypressEvent keypress
) {
113 super.onKeypress(keypress
);
114 TKeypress key
= keypress
.getKey();
115 if (key
.isFnKey() && key
.getKeyCode() == TKeypress
.ENTER
) {
116 TuiReaderMainWindow
.this.filter
= getText();
117 TuiReaderMainWindow
.this.refreshStories();
122 TSizeConstraint
.setSize(sizeConstraints
, lblSearch
, 5, 1, null, null);
123 TSizeConstraint
.setSize(sizeConstraints
, search
, 15, 1, -5, null);
126 private void addList() {
127 list
= addList(listItems
, 0, 0, 10, 10, new TAction() {
130 MetaData meta
= getSelectedMeta();
137 TSizeConstraint
.setSize(sizeConstraints
, list
, 0, 7, 0, 0);
140 private void addSelect() {
142 final List
<String
> selects
= new ArrayList
<String
>();
143 selects
.add("(show all)");
144 selects
.add("Sources");
145 selects
.add("Author");
147 final List
<String
> selectTargets
= new ArrayList
<String
>();
148 selectTargets
.add("");
150 TLabel lblSelect
= addLabel("Select: ", 0, 0);
152 TAction onSelect
= new TAction() {
155 String smode
= selectBox
.getText();
157 if (smode
== null || smode
.equals("(show all)")) {
159 } else if (smode
.equals("Sources")) {
160 selectTargets
.clear();
161 selectTargets
.add("(show all)");
163 for (String source
: reader
.getLibrary().getSources()) {
164 selectTargets
.add(source
);
166 } catch (IOException e
) {
167 Instance
.getInstance().getTraceHandler().error(e
);
172 selectTargets
.clear();
173 selectTargets
.add("(show all)");
175 for (String author
: reader
.getLibrary().getAuthors()) {
176 selectTargets
.add(author
);
178 } catch (IOException e
) {
179 Instance
.getInstance().getTraceHandler().error(e
);
185 selectTargetBox
.setVisible(showTarget
);
186 selectTargetBox
.setEnabled(showTarget
);
188 selectTargetBox
.reflowData();
191 selectTargetBox
.setText(selectTargets
.get(0));
193 TuiReaderMainWindow
.this.activate(selectTargetBox
);
195 TuiReaderMainWindow
.this.activate(list
);
200 selectBox
= addComboBox(0, 0, 10, selects
, 0, -1, onSelect
);
202 selectTargetBox
= addComboBox(0, 0, 0, selectTargets
, 0, -1,
206 if (selectTargetBox
.getText().equals(
207 selectTargets
.get(0))) {
210 setMode(mode
, selectTargetBox
.getText());
218 TSizeConstraint
.setSize(sizeConstraints
, lblSelect
, 5, 3, null, null);
219 TSizeConstraint
.setSize(sizeConstraints
, selectBox
, 15, 3, -5, null);
220 TSizeConstraint
.setSize(sizeConstraints
, selectTargetBox
, 15, 4, -5,
225 public void onResize(TResizeEvent resize
) {
226 super.onResize(resize
);
227 TSizeConstraint
.resize(sizeConstraints
);
231 public void onClose() {
237 * Refresh the list of stories displayed in this library.
239 * Will take the current settings into account (filter, source...).
241 public void refreshStories() {
242 List
<MetaData
> metas
;
245 if (mode
== Mode
.SOURCE
) {
246 metas
= reader
.getLibrary().getListBySource(target
);
247 } else if (mode
== Mode
.AUTHOR
) {
248 metas
= reader
.getLibrary().getListByAuthor(target
);
250 metas
= reader
.getLibrary().getList();
252 } catch (IOException e
) {
253 Instance
.getInstance().getTraceHandler().error(e
);
254 metas
= new ArrayList
<MetaData
>();
261 * Change the author/source filter and display all stories matching this
265 * the new mode or NULL for no sorting
267 * the actual target for the given mode, or NULL for all of them
269 public void setMode(Mode mode
, String target
) {
271 this.target
= target
;
276 * Update the list of stories displayed in this {@link TWindow}.
278 * If a filter is set, only the stories which pass the filter will be
282 * the new list of stories to display
284 private void setMetas(List
<MetaData
> metas
) {
289 for (MetaData meta
: metas
) {
290 String desc
= desc(meta
);
292 || desc
.toLowerCase().contains(filter
.toLowerCase())) {
299 list
.setList(listItems
);
300 if (listItems
.size() > 0) {
301 list
.setSelectedIndex(0);
305 public MetaData
getSelectedMeta() {
306 if (list
.getSelectedIndex() >= 0) {
307 return listKeys
.get(list
.getSelectedIndex());
313 public void readStory(MetaData meta
) {
315 reader
.setChapter(-1);
316 reader
.setMeta(meta
);
318 } catch (IOException e
) {
319 Instance
.getInstance().getTraceHandler().error(e
);
323 private String
desc(MetaData meta
) {
324 return String
.format("%5s: %s", meta
.getLuid(), meta
.getTitle());
328 public void onCommand(TCommandEvent command
) {
329 if (command
.getCmd().equals(TuiReaderApplication
.CMD_EXIT
)) {
330 TuiReaderApplication
.close(this);
332 // Handle our own event if needed here
333 super.onCommand(command
);
338 public void onMenu(TMenuEvent menu
) {
339 MetaData meta
= getSelectedMeta();
341 switch (menu
.getId()) {
342 case TuiReaderApplication
.MENU_FILE_OPEN
:
346 case TuiReaderApplication
.MENU_FILE_EXPORT
:
349 // TODO: choose type, pg, error
350 OutputType outputType
= OutputType
.EPUB
;
351 String path
= fileOpenBox(".", Type
.SAVE
);
352 reader
.getLibrary().export(meta
.getLuid(), outputType
,
354 } catch (IOException e
) {
363 reader
.getLibrary().delete(meta
.getLuid());
364 } catch (IOException e
) {