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
.fanfix
.reader
.Reader
;
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
) {
39 private List
<MetaData
> listKeys
;
40 private List
<String
> listItems
;
41 private Reader reader
;
42 private String source
;
43 private String filter
= "";
44 private List
<TSizeConstraint
> sizeConstraints
= new ArrayList
<TSizeConstraint
>();
46 // TODO: because no way to find out the current index!!
47 private TComboBox select
;
50 * Create a new {@link TuiReaderMainWindow} without any stories in the list.
53 * the reader and main application
55 public TuiReaderMainWindow(TuiReaderApplication reader
) {
56 // Construct a demo window. X and Y don't matter because it will be
58 super(reader
, "Library", 0, 0, 60, 18, CENTERED
| RESIZABLE
);
62 listKeys
= new ArrayList
<MetaData
>();
63 listItems
= new ArrayList
<String
>();
67 addSelect(); // TODO: last so it can draw over the rest
69 TStatusBar statusBar
= reader
.setStatusBar(this, "Library");
70 statusBar
.addShortcutKeypress(TKeypress
.kbCtrlF
, CMD_SEARCH
, "Search");
72 TSizeConstraint
.resize(sizeConstraints
);
74 // TODO: remove when not used anymore
76 // addLabel("Label (1,1)", 1, 1);
77 // addButton("&Button (35,1)", 35, 1, new TAction() {
81 // addCheckbox(1, 2, "Checky (1,2)", false);
82 // addProgressBar(1, 3, 30, 42);
83 // TRadioGroup groupy = addRadioGroup(1, 4, "Radio groupy");
84 // groupy.addRadioButton("Fanfan");
85 // groupy.addRadioButton("Tulipe");
86 // addField(1, 10, 20, false, "text not fixed.");
87 // addField(1, 11, 20, true, "text fixed.");
88 // addText("20x4 Text in (12,20)", 1, 12, 20, 4);
90 // TTreeView tree = addTreeView(30, 5, 20, 5);
91 // TTreeItem root = new TTreeItem(tree, "expended root", true);
92 // tree.setSelected(root); // needed to allow arrow navigation without
93 // // mouse-clicking before
95 // root.addChild("child");
96 // root.addChild("child 2").addChild("sub child");
99 private void addSearch() {
100 TLabel lblSearch
= addLabel("Search: ", 0, 0);
102 TField search
= new TField(this, 0, 0, 1, true) {
104 public void onKeypress(TKeypressEvent keypress
) {
105 super.onKeypress(keypress
);
106 TKeypress key
= keypress
.getKey();
107 if (key
.isFnKey() && key
.getKeyCode() == TKeypress
.ENTER
) {
108 TuiReaderMainWindow
.this.filter
= getText();
109 TuiReaderMainWindow
.this.refreshStories();
114 TSizeConstraint
.setSize(sizeConstraints
, lblSearch
, 5, 1, null, null);
115 TSizeConstraint
.setSize(sizeConstraints
, search
, 15, 1, -5, null);
118 private void addList() {
119 list
= addList(listItems
, 0, 0, 10, 10, new TAction() {
122 MetaData meta
= getSelectedMeta();
129 TSizeConstraint
.setSize(sizeConstraints
, list
, 0, 7, 0, 0);
132 private void addSelect() {
133 // TODO: make a full list
134 final List
<String
> options
= new ArrayList
<String
>();
135 options
.add("(all opt)");
136 options
.add("Sources");
137 options
.add("Author");
140 final List
<String
> sources
= new ArrayList
<String
>();
141 sources
.add("(show all)");
142 for (String source
: reader
.getLibrary().getSources()) {
146 TLabel lblSelect
= addLabel("Select: ", 0, 0);
148 // TODO: why must be last so to be able to draw over the rest
149 // TODO: make it so we cannot add manual entries
150 // TODO: how to select the item via keyboard? why double-click via
152 // TODO: how to change the values size on resize?
153 // TODO: setWidth() does not impact the display width, only the control
154 // and the down arrow on the right
155 // TODO: width 1 +resize + click on down arrow = bad format exception
156 select
= addComboBox(0, 0, 10, sources
, 0,
157 Math
.min(sources
.size() + 1, getHeight() - 1 - 1),
162 if (select
.getText().equals("(show all)")) {
165 setSource(select
.getText());
171 final TComboBox option
= addComboBox(0, 0, 10, options
, 0,
172 Math
.min(sources
.size() + 1, getHeight() - 1 - 1),
178 sources
.add("(show all)");
179 for (String source
: reader
.getLibrary().getSources()) {
185 TSizeConstraint
.setSize(sizeConstraints
, lblSelect
, 5, 3, null, null);
186 TSizeConstraint
.setSize(sizeConstraints
, option
, 15, 3, -5, null);
187 TSizeConstraint
.setSize(sizeConstraints
, select
, 15, 4, -5, null);
191 public void onResize(TResizeEvent resize
) {
192 super.onResize(resize
);
193 TSizeConstraint
.resize(sizeConstraints
);
197 public void onClose() {
203 * Refresh the list of stories displayed in this library.
205 * Will take the current settings into account (filter, source...).
207 public void refreshStories() {
208 List
<MetaData
> metas
= reader
.getLibrary().getListBySource(source
);
213 * Change the source filter and display all stories matching this source.
216 * the new source or NULL for all sources
218 public void setSource(String source
) {
219 this.source
= source
;
224 * Update the list of stories displayed in this {@link TWindow}.
226 * If a filter is set, only the stories which pass the filter will be
230 * the new list of stories to display
232 private void setMetas(List
<MetaData
> metas
) {
237 for (MetaData meta
: metas
) {
238 String desc
= desc(meta
);
240 || desc
.toLowerCase().contains(filter
.toLowerCase())) {
247 list
.setList(listItems
);
250 public MetaData
getSelectedMeta() {
251 if (list
.getSelectedIndex() >= 0) {
252 return listKeys
.get(list
.getSelectedIndex());
258 public void readStory(MetaData meta
) {
260 reader
.setChapter(-1);
261 reader
.setMeta(meta
);
263 } catch (IOException e
) {
264 Instance
.getTraceHandler().error(e
);
268 private String
desc(MetaData meta
) {
269 return String
.format("%5s: %s", meta
.getLuid(), meta
.getTitle());
273 public void onCommand(TCommandEvent command
) {
274 if (command
.getCmd().equals(TuiReaderApplication
.CMD_EXIT
)) {
275 TuiReaderApplication
.close(this);
277 // Handle our own event if needed here
278 super.onCommand(command
);
283 public void onMenu(TMenuEvent menu
) {
284 MetaData meta
= getSelectedMeta();
286 switch (menu
.getId()) {
287 case TuiReaderApplication
.MENU_OPEN
:
291 case TuiReaderApplication
.MENU_EXPORT
:
294 // TODO: choose type, pg, error
295 OutputType outputType
= OutputType
.EPUB
;
296 String path
= fileOpenBox(".", Type
.SAVE
);
297 reader
.getLibrary().export(meta
.getLuid(), outputType
,
299 } catch (IOException e
) {
308 reader
.getLibrary().delete(meta
.getLuid());
309 } catch (IOException e
) {