wip
[fanfix.git] / src / be / nikiroo / fanfix / reader / tui / TuiReaderMainWindow.java
1 package be.nikiroo.fanfix.reader.tui;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.List;
7
8 import jexer.TAction;
9 import jexer.TCommand;
10 import jexer.TField;
11 import jexer.TFileOpenBox.Type;
12 import jexer.TKeypress;
13 import jexer.TList;
14 import jexer.TStatusBar;
15 import jexer.TWindow;
16 import jexer.event.TCommandEvent;
17 import jexer.event.TKeypressEvent;
18 import jexer.event.TMenuEvent;
19 import be.nikiroo.fanfix.Instance;
20 import be.nikiroo.fanfix.data.MetaData;
21 import be.nikiroo.fanfix.library.BasicLibrary;
22 import be.nikiroo.fanfix.output.BasicOutput.OutputType;
23 import be.nikiroo.fanfix.reader.Reader;
24
25 /**
26 * The library window, that will list all the (filtered) stories available in
27 * this {@link BasicLibrary}.
28 *
29 * @author niki
30 */
31 class TuiReaderMainWindow extends TWindow {
32 public static final int MENU_SEARCH = 1100;
33 public static final TCommand CMD_SEARCH = new TCommand(MENU_SEARCH) {
34 };
35
36 private TList list;
37 private List<MetaData> listKeys;
38 private List<String> listItems;
39 private Reader reader;
40 private String source;
41 private String filter = "";
42
43 /**
44 * Create a new {@link TuiReaderMainWindow} without any stories in the list.
45 *
46 * @param reader
47 * the reader and main application
48 */
49 public TuiReaderMainWindow(TuiReaderApplication reader) {
50 // Construct a demo window. X and Y don't matter because it will be
51 // centred on screen.
52 super(reader, "Library", 0, 0, 60, 18, CENTERED | RESIZABLE);
53
54 this.reader = reader;
55
56 listKeys = new ArrayList<MetaData>();
57 listItems = new ArrayList<String>();
58
59 // TODO size + onResize
60
61 addLabel("Search: ", 5, 3);
62 @SuppressWarnings("unused")
63 TField field = new TField(this, 15, 3, 5, true) {
64 @Override
65 public void onKeypress(TKeypressEvent keypress) {
66 super.onKeypress(keypress);
67 TKeypress key = keypress.getKey();
68 if (key.isFnKey() && key.getKeyCode() == TKeypress.ENTER) {
69 TuiReaderMainWindow.this.filter = getText();
70 TuiReaderMainWindow.this.refreshStories();
71 }
72 }
73 };
74
75 addLabel("Sort by: ", 5, 1);
76 // -1 = no default index (0 means first,...) 1=height when visible, null
77 // = action
78 List<String> data = Arrays.asList("(show all)", "Source", "Name",
79 "Author");
80 // must be last so to be able to draw over the rest
81 // TODO: make it so we cannot add manual entries
82 // TODO: how to select the item via keyboard? why double-click via
83 // mouse?
84 addComboBox(15, 1, 12, data, 0,
85 Math.min(data.size() + 1, getHeight() - 1 - 1), null);
86
87 list = addList(listItems, 0, 7, getWidth(), getHeight(), new TAction() {
88 @Override
89 public void DO() {
90 MetaData meta = getSelectedMeta();
91 if (meta != null) {
92 readStory(meta);
93 }
94 }
95 });
96
97 TStatusBar statusBar = reader.setStatusBar(this, "Library");
98 statusBar.addShortcutKeypress(TKeypress.kbCtrlF, CMD_SEARCH, "Search");
99
100 // TODO: remove when not used anymore
101
102 // addLabel("Label (1,1)", 1, 1);
103 // addButton("&Button (35,1)", 35, 1, new TAction() {
104 // public void DO() {
105 // }
106 // });
107 // addCheckbox(1, 2, "Checky (1,2)", false);
108 // addProgressBar(1, 3, 30, 42);
109 // TRadioGroup groupy = addRadioGroup(1, 4, "Radio groupy");
110 // groupy.addRadioButton("Fanfan");
111 // groupy.addRadioButton("Tulipe");
112 // addField(1, 10, 20, false, "text not fixed.");
113 // addField(1, 11, 20, true, "text fixed.");
114 // addText("20x4 Text in (12,20)", 1, 12, 20, 4);
115 //
116 // TTreeView tree = addTreeView(30, 5, 20, 5);
117 // TTreeItem root = new TTreeItem(tree, "expended root", true);
118 // tree.setSelected(root); // needed to allow arrow navigation without
119 // // mouse-clicking before
120 //
121 // root.addChild("child");
122 // root.addChild("child 2").addChild("sub child");
123 }
124
125 @Override
126 public void onClose() {
127 setVisible(false);
128 super.onClose();
129 }
130
131 /**
132 * Refresh the list of stories displayed in this library.
133 * <p>
134 * Will take the current settings into account (filter, source...).
135 */
136 public void refreshStories() {
137 List<MetaData> metas = reader.getLibrary().getListBySource(source);
138 setMetas(metas);
139 }
140
141 /**
142 * Change the source filter and display all stories matching this source.
143 *
144 * @param source
145 * the new source or NULL for all sources
146 */
147 public void setSource(String source) {
148 this.source = source;
149 refreshStories();
150 }
151
152 /**
153 * Update the list of stories displayed in this {@link TWindow}.
154 * <p>
155 * If a filter is set, only the stories which pass the filter will be
156 * displayed.
157 *
158 * @param metas
159 * the new list of stories to display
160 */
161 private void setMetas(List<MetaData> metas) {
162 listKeys.clear();
163 listItems.clear();
164
165 if (metas != null) {
166 for (MetaData meta : metas) {
167 String desc = desc(meta);
168 if (filter.isEmpty()
169 || desc.toLowerCase().contains(filter.toLowerCase())) {
170 listKeys.add(meta);
171 listItems.add(desc);
172 }
173 }
174 }
175
176 list.setList(listItems);
177 }
178
179 public MetaData getSelectedMeta() {
180 if (list.getSelectedIndex() >= 0) {
181 return listKeys.get(list.getSelectedIndex());
182 }
183
184 return null;
185 }
186
187 public void readStory(MetaData meta) {
188 try {
189 reader.setChapter(-1);
190 reader.setMeta(meta);
191 reader.read();
192 } catch (IOException e) {
193 Instance.getTraceHandler().error(e);
194 }
195 }
196
197 private String desc(MetaData meta) {
198 return String.format("%5s: %s", meta.getLuid(), meta.getTitle());
199 }
200
201 @Override
202 public void onCommand(TCommandEvent command) {
203 if (command.getCmd().equals(TuiReaderApplication.CMD_EXIT)) {
204 TuiReaderApplication.close(this);
205 } else {
206 // Handle our own event if needed here
207 super.onCommand(command);
208 }
209 }
210
211 @Override
212 public void onMenu(TMenuEvent menu) {
213 MetaData meta = getSelectedMeta();
214 if (meta != null) {
215 switch (menu.getId()) {
216 case TuiReaderApplication.MENU_OPEN:
217 readStory(meta);
218
219 return;
220 case TuiReaderApplication.MENU_EXPORT:
221
222 try {
223 // TODO: choose type, pg, error
224 OutputType outputType = OutputType.EPUB;
225 String path = fileOpenBox(".", Type.SAVE);
226 reader.getLibrary().export(meta.getLuid(), outputType,
227 path, null);
228 } catch (IOException e) {
229 // TODO
230 e.printStackTrace();
231 }
232
233 return;
234
235 case -1:
236 try {
237 reader.getLibrary().delete(meta.getLuid());
238 } catch (IOException e) {
239 // TODO
240 }
241
242 return;
243 }
244 }
245
246 super.onMenu(menu);
247 }
248 }