Instance: use getInstance()
[nikiroo-utils.git] / src / be / nikiroo / fanfix / reader / tui / TuiReaderMainWindow.java
CommitLineData
16a81ef7 1package be.nikiroo.fanfix.reader.tui;
c1873e56 2
bc2ea776 3import java.io.IOException;
c1873e56
NR
4import java.util.ArrayList;
5import java.util.List;
6
5dd985cf 7import jexer.TAction;
ce424b19 8import jexer.TComboBox;
bce88a00
NR
9import jexer.TCommand;
10import jexer.TField;
e2d017a3 11import jexer.TFileOpenBox.Type;
bce88a00 12import jexer.TKeypress;
ce424b19 13import jexer.TLabel;
5dd985cf 14import jexer.TList;
bce88a00 15import jexer.TStatusBar;
5dd985cf 16import jexer.TWindow;
cf9c5ed1 17import jexer.event.TCommandEvent;
bce88a00 18import jexer.event.TKeypressEvent;
e2d017a3 19import jexer.event.TMenuEvent;
ce424b19 20import jexer.event.TResizeEvent;
bc2ea776 21import be.nikiroo.fanfix.Instance;
c1873e56 22import be.nikiroo.fanfix.data.MetaData;
bc2ea776 23import be.nikiroo.fanfix.library.BasicLibrary;
e2d017a3 24import be.nikiroo.fanfix.output.BasicOutput.OutputType;
0bcb5c7f 25import be.nikiroo.jexer.TSizeConstraint;
c1873e56 26
6322ab64
NR
27/**
28 * The library window, that will list all the (filtered) stories available in
bc2ea776 29 * this {@link BasicLibrary}.
6322ab64
NR
30 *
31 * @author niki
32 */
5dd985cf 33class TuiReaderMainWindow extends TWindow {
bce88a00
NR
34 public static final int MENU_SEARCH = 1100;
35 public static final TCommand CMD_SEARCH = new TCommand(MENU_SEARCH) {
36 };
37
b2274262
NR
38 public enum Mode {
39 SOURCE, AUTHOR,
40 }
41
c1873e56
NR
42 private TList list;
43 private List<MetaData> listKeys;
44 private List<String> listItems;
350bc060 45 private TuiReaderApplication reader;
b2274262
NR
46
47 private Mode mode = Mode.SOURCE;
48 private String target = null;
bce88a00 49 private String filter = "";
b2274262 50
ce424b19
NR
51 private List<TSizeConstraint> sizeConstraints = new ArrayList<TSizeConstraint>();
52
81a6120d 53 // The 2 comboboxes used to select by source/author
41627937
NR
54 private TComboBox selectTargetBox;
55 private TComboBox selectBox;
6322ab64
NR
56
57 /**
58 * Create a new {@link TuiReaderMainWindow} without any stories in the list.
59 *
60 * @param reader
61 * the reader and main application
62 */
63 public TuiReaderMainWindow(TuiReaderApplication reader) {
c1873e56 64 // Construct a demo window. X and Y don't matter because it will be
bc2ea776 65 // centred on screen.
4f66bfa8 66 super(reader, "Library", 0, 0, 60, 18, CENTERED | RESIZABLE);
c1873e56
NR
67
68 this.reader = reader;
69
c1873e56
NR
70 listKeys = new ArrayList<MetaData>();
71 listItems = new ArrayList<String>();
e9d43c7c 72
ce424b19 73 addList();
41627937 74 addSearch();
81a6120d 75 addSelect();
5dd985cf 76
bce88a00
NR
77 TStatusBar statusBar = reader.setStatusBar(this, "Library");
78 statusBar.addShortcutKeypress(TKeypress.kbCtrlF, CMD_SEARCH, "Search");
c1873e56 79
ce424b19
NR
80 TSizeConstraint.resize(sizeConstraints);
81
bc2ea776
NR
82 // TODO: remove when not used anymore
83
84 // addLabel("Label (1,1)", 1, 1);
85 // addButton("&Button (35,1)", 35, 1, new TAction() {
86 // public void DO() {
87 // }
88 // });
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);
97 //
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
102 //
103 // root.addChild("child");
104 // root.addChild("child 2").addChild("sub child");
105 }
c1873e56 106
ce424b19
NR
107 private void addSearch() {
108 TLabel lblSearch = addLabel("Search: ", 0, 0);
109
110 TField search = new TField(this, 0, 0, 1, true) {
111 @Override
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();
118 }
119 }
120 };
121
122 TSizeConstraint.setSize(sizeConstraints, lblSearch, 5, 1, null, null);
123 TSizeConstraint.setSize(sizeConstraints, search, 15, 1, -5, null);
124 }
125
126 private void addList() {
127 list = addList(listItems, 0, 0, 10, 10, new TAction() {
128 @Override
129 public void DO() {
130 MetaData meta = getSelectedMeta();
131 if (meta != null) {
132 readStory(meta);
133 }
134 }
135 });
136
137 TSizeConstraint.setSize(sizeConstraints, list, 0, 7, 0, 0);
138 }
139
140 private void addSelect() {
41627937 141 // TODO: i18n
b2274262
NR
142 final List<String> selects = new ArrayList<String>();
143 selects.add("(show all)");
41627937
NR
144 selects.add("Sources");
145 selects.add("Author");
146
147 final List<String> selectTargets = new ArrayList<String>();
148 selectTargets.add("");
ce424b19
NR
149
150 TLabel lblSelect = addLabel("Select: ", 0, 0);
151
41627937
NR
152 TAction onSelect = new TAction() {
153 @Override
154 public void DO() {
155 String smode = selectBox.getText();
41627937
NR
156 boolean showTarget;
157 if (smode == null || smode.equals("(show all)")) {
41627937
NR
158 showTarget = false;
159 } else if (smode.equals("Sources")) {
41627937
NR
160 selectTargets.clear();
161 selectTargets.add("(show all)");
0bb51c9c
NR
162 try {
163 for (String source : reader.getLibrary().getSources()) {
164 selectTargets.add(source);
165 }
166 } catch (IOException e) {
d66deb8d 167 Instance.getInstance().getTraceHandler().error(e);
ce424b19 168 }
0bb51c9c 169
41627937
NR
170 showTarget = true;
171 } else {
41627937
NR
172 selectTargets.clear();
173 selectTargets.add("(show all)");
0bb51c9c
NR
174 try {
175 for (String author : reader.getLibrary().getAuthors()) {
176 selectTargets.add(author);
177 }
178 } catch (IOException e) {
d66deb8d 179 Instance.getInstance().getTraceHandler().error(e);
41627937
NR
180 }
181
182 showTarget = true;
183 }
ce424b19 184
41627937
NR
185 selectTargetBox.setVisible(showTarget);
186 selectTargetBox.setEnabled(showTarget);
187 if (showTarget) {
188 selectTargetBox.reflowData();
189 }
190
191 selectTargetBox.setText(selectTargets.get(0));
81a6120d
NR
192 if (showTarget) {
193 TuiReaderMainWindow.this.activate(selectTargetBox);
194 } else {
195 TuiReaderMainWindow.this.activate(list);
196 }
41627937
NR
197 }
198 };
199
200 selectBox = addComboBox(0, 0, 10, selects, 0, -1, onSelect);
41627937
NR
201
202 selectTargetBox = addComboBox(0, 0, 0, selectTargets, 0, -1,
ce424b19
NR
203 new TAction() {
204 @Override
205 public void DO() {
81a6120d
NR
206 if (selectTargetBox.getText().equals(
207 selectTargets.get(0))) {
b2274262
NR
208 setMode(mode, null);
209 } else {
41627937 210 setMode(mode, selectTargetBox.getText());
ce424b19
NR
211 }
212 }
213 });
41627937
NR
214
215 // Set defaults
216 onSelect.DO();
ce424b19
NR
217
218 TSizeConstraint.setSize(sizeConstraints, lblSelect, 5, 3, null, null);
41627937
NR
219 TSizeConstraint.setSize(sizeConstraints, selectBox, 15, 3, -5, null);
220 TSizeConstraint.setSize(sizeConstraints, selectTargetBox, 15, 4, -5,
221 null);
ce424b19
NR
222 }
223
224 @Override
225 public void onResize(TResizeEvent resize) {
226 super.onResize(resize);
227 TSizeConstraint.resize(sizeConstraints);
228 }
229
4f66bfa8
NR
230 @Override
231 public void onClose() {
232 setVisible(false);
233 super.onClose();
234 }
235
e2d017a3 236 /**
bce88a00
NR
237 * Refresh the list of stories displayed in this library.
238 * <p>
239 * Will take the current settings into account (filter, source...).
e2d017a3 240 */
e2d017a3 241 public void refreshStories() {
b2274262 242 List<MetaData> metas;
0bb51c9c
NR
243
244 try {
245 if (mode == Mode.SOURCE) {
246 metas = reader.getLibrary().getListBySource(target);
247 } else if (mode == Mode.AUTHOR) {
248 metas = reader.getLibrary().getListByAuthor(target);
249 } else {
250 metas = reader.getLibrary().getList();
251 }
252 } catch (IOException e) {
d66deb8d 253 Instance.getInstance().getTraceHandler().error(e);
0bb51c9c 254 metas = new ArrayList<MetaData>();
b2274262
NR
255 }
256
e2d017a3
NR
257 setMetas(metas);
258 }
259
bc2ea776 260 /**
b2274262
NR
261 * Change the author/source filter and display all stories matching this
262 * target.
bc2ea776 263 *
b2274262
NR
264 * @param mode
265 * the new mode or NULL for no sorting
266 * @param target
267 * the actual target for the given mode, or NULL for all of them
bc2ea776 268 */
b2274262
NR
269 public void setMode(Mode mode, String target) {
270 this.mode = mode;
271 this.target = target;
bce88a00 272 refreshStories();
c1873e56
NR
273 }
274
6322ab64
NR
275 /**
276 * Update the list of stories displayed in this {@link TWindow}.
bce88a00
NR
277 * <p>
278 * If a filter is set, only the stories which pass the filter will be
279 * displayed.
6322ab64
NR
280 *
281 * @param metas
282 * the new list of stories to display
283 */
e2d017a3 284 private void setMetas(List<MetaData> metas) {
6322ab64
NR
285 listKeys.clear();
286 listItems.clear();
287
288 if (metas != null) {
289 for (MetaData meta : metas) {
bce88a00
NR
290 String desc = desc(meta);
291 if (filter.isEmpty()
292 || desc.toLowerCase().contains(filter.toLowerCase())) {
293 listKeys.add(meta);
294 listItems.add(desc);
295 }
6322ab64
NR
296 }
297 }
298
299 list.setList(listItems);
81a6120d
NR
300 if (listItems.size() > 0) {
301 list.setSelectedIndex(0);
302 }
6322ab64
NR
303 }
304
e2d017a3
NR
305 public MetaData getSelectedMeta() {
306 if (list.getSelectedIndex() >= 0) {
307 return listKeys.get(list.getSelectedIndex());
308 }
309
310 return null;
311 }
312
313 public void readStory(MetaData meta) {
bc2ea776
NR
314 try {
315 reader.setChapter(-1);
316 reader.setMeta(meta);
350bc060 317 reader.read(false);
bc2ea776 318 } catch (IOException e) {
d66deb8d 319 Instance.getInstance().getTraceHandler().error(e);
bc2ea776 320 }
c1873e56
NR
321 }
322
323 private String desc(MetaData meta) {
324 return String.format("%5s: %s", meta.getLuid(), meta.getTitle());
325 }
e2d017a3 326
cf9c5ed1
NR
327 @Override
328 public void onCommand(TCommandEvent command) {
329 if (command.getCmd().equals(TuiReaderApplication.CMD_EXIT)) {
330 TuiReaderApplication.close(this);
331 } else {
332 // Handle our own event if needed here
333 super.onCommand(command);
334 }
335 }
336
e2d017a3
NR
337 @Override
338 public void onMenu(TMenuEvent menu) {
339 MetaData meta = getSelectedMeta();
340 if (meta != null) {
341 switch (menu.getId()) {
b4a60050 342 case TuiReaderApplication.MENU_FILE_OPEN:
e2d017a3
NR
343 readStory(meta);
344
345 return;
b4a60050 346 case TuiReaderApplication.MENU_FILE_EXPORT:
e2d017a3
NR
347
348 try {
349 // TODO: choose type, pg, error
350 OutputType outputType = OutputType.EPUB;
351 String path = fileOpenBox(".", Type.SAVE);
352 reader.getLibrary().export(meta.getLuid(), outputType,
353 path, null);
354 } catch (IOException e) {
355 // TODO
356 e.printStackTrace();
357 }
358
359 return;
bce88a00 360
e2d017a3
NR
361 case -1:
362 try {
363 reader.getLibrary().delete(meta.getLuid());
364 } catch (IOException e) {
365 // TODO
366 }
367
368 return;
369 }
370 }
371
372 super.onMenu(menu);
373 }
374}