GUI search: reorg mostly OK
[fanfix.git] / src / be / nikiroo / fanfix / reader / ui / GuiReaderSearchFrame.java
1 package be.nikiroo.fanfix.reader.ui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.EventQueue;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.lang.reflect.InvocationTargetException;
9 import java.util.ArrayList;
10 import java.util.List;
11
12 import javax.swing.JComboBox;
13 import javax.swing.JFrame;
14 import javax.swing.JLabel;
15 import javax.swing.JPanel;
16 import javax.swing.JScrollPane;
17
18 import be.nikiroo.fanfix.Instance;
19 import be.nikiroo.fanfix.data.MetaData;
20 import be.nikiroo.fanfix.reader.ui.GuiReaderBook.BookActionListener;
21 import be.nikiroo.fanfix.searchable.BasicSearchable;
22 import be.nikiroo.fanfix.searchable.SearchableTag;
23 import be.nikiroo.fanfix.supported.SupportType;
24
25 /**
26 * This frame will allow you to search through the supported websites for new
27 * stories/comics.
28 *
29 * @author niki
30 */
31 // JCombobox<E> not 1.6 compatible
32 @SuppressWarnings({ "unchecked", "rawtypes" })
33 public class GuiReaderSearchFrame extends JFrame {
34 private static final long serialVersionUID = 1L;
35
36 private List<SupportType> supportTypes;
37 private SupportType supportType;
38 private int page;
39 private int maxPage;
40
41 private JComboBox comboSupportTypes;
42 private GuiReaderSearchByNamePanel searchPanel;
43
44 private boolean seeWordcount;
45 private GuiReaderGroup books;
46
47 public GuiReaderSearchFrame(final GuiReader reader) {
48 super("Browse stories");
49 setLayout(new BorderLayout());
50 setSize(800, 600);
51
52 page = 1;
53 maxPage = -1;
54
55 supportTypes = new ArrayList<SupportType>();
56 for (SupportType type : SupportType.values()) {
57 if (BasicSearchable.getSearchable(type) != null) {
58 supportTypes.add(type);
59 }
60 }
61 supportType = supportTypes.isEmpty() ? null : supportTypes.get(0);
62
63 comboSupportTypes = new JComboBox(
64 supportTypes.toArray(new SupportType[] {}));
65 comboSupportTypes.addActionListener(new ActionListener() {
66 @Override
67 public void actionPerformed(ActionEvent e) {
68 setWaitingScreen(true);
69 updateSupportType(
70 (SupportType) comboSupportTypes.getSelectedItem(),
71 new Runnable() {
72 @Override
73 public void run() {
74 setWaitingScreen(false);
75 }
76 });
77 }
78 });
79 JPanel searchSites = new JPanel(new BorderLayout());
80 searchSites.add(comboSupportTypes, BorderLayout.CENTER);
81 searchSites.add(new JLabel(" " + "Website : "), BorderLayout.WEST);
82
83 searchPanel = new GuiReaderSearchByNamePanel(supportType,
84 new Runnable() {
85 @Override
86 public void run() {
87 setWaitingScreen(false);
88 }
89 });
90
91 searchPanel.addActionListener(new ActionListener() {
92 @Override
93 public void actionPerformed(ActionEvent e) {
94 updateMaxPage(searchPanel.getMaxPage());
95 List<GuiReaderBookInfo> infos = new ArrayList<GuiReaderBookInfo>();
96 for (MetaData meta : searchPanel.getStories()) {
97 infos.add(GuiReaderBookInfo.fromMeta(meta));
98 }
99
100 updateBooks(infos);
101
102 // ! 1-based index !
103 int item = searchPanel.getStoryItem();
104 if (item > 0 && item <= books.getBooksCount()) {
105 // TODO: "click" on item ITEM
106 }
107 }
108 });
109
110 JPanel top = new JPanel(new BorderLayout());
111 top.add(searchSites, BorderLayout.NORTH);
112 top.add(searchPanel, BorderLayout.CENTER);
113
114 add(top, BorderLayout.NORTH);
115
116 books = new GuiReaderGroup(reader, null, null);
117 books.setActionListener(new BookActionListener() {
118 @Override
119 public void select(GuiReaderBook book) {
120 }
121
122 @Override
123 public void popupRequested(GuiReaderBook book, Component target,
124 int x, int y) {
125 }
126
127 @Override
128 public void action(GuiReaderBook book) {
129 new GuiReaderSearchAction(reader.getLibrary(), book.getInfo())
130 .setVisible(true);
131 }
132 });
133 JScrollPane scroll = new JScrollPane(books);
134 scroll.getVerticalScrollBar().setUnitIncrement(16);
135 add(scroll, BorderLayout.CENTER);
136
137 setWaitingScreen(true);
138 }
139
140 private void updateSupportType(SupportType supportType, Runnable inUi) {
141 if (supportType != this.supportType) {
142 this.supportType = supportType;
143 comboSupportTypes.setSelectedItem(supportType);
144 books.clear();
145 searchPanel.setSupportType(supportType, inUi);
146 }
147 }
148
149 private void updatePage(final int page) {
150 inUi(new Runnable() {
151 @Override
152 public void run() {
153 GuiReaderSearchFrame.this.page = page;
154
155 // TODO: gui
156 System.out.println("page: " + page);
157 }
158 });
159 }
160
161 private void updateMaxPage(final int maxPage) {
162 inUi(new Runnable() {
163 @Override
164 public void run() {
165 GuiReaderSearchFrame.this.maxPage = maxPage;
166
167 // TODO: gui
168 System.out.println("max page: " + maxPage);
169 }
170 });
171 }
172
173 private void updateBooks(final List<GuiReaderBookInfo> infos) {
174 setWaitingScreen(true);
175 inUi(new Runnable() {
176 @Override
177 public void run() {
178 books.refreshBooks(infos, seeWordcount);
179 setWaitingScreen(false);
180 }
181 });
182 }
183
184 // item 0 = no selection, else = default selection
185 public void search(final SupportType searchOn, final String keywords,
186 final int page, final int item) {
187
188 setWaitingScreen(true);
189
190 searchPanel.setSupportType(searchOn, new Runnable() {
191 @Override
192 public void run() {
193 if (keywords != null) {
194 setWaitingScreen(true);
195 searchPanel.search(keywords, page, item, new Runnable() {
196 @Override
197 public void run() {
198 updateMaxPage(searchPanel.getMaxPage());
199 updatePage(page);
200 setWaitingScreen(false);
201 }
202 });
203 }
204 }
205 });
206 }
207
208 // tag: null = base tags
209 public void searchTag(final SupportType searchOn, final int page,
210 final int item, final SearchableTag tag) {
211
212 setWaitingScreen(true);
213
214 searchPanel.setSupportType(searchOn, new Runnable() {
215 @Override
216 public void run() {
217 setWaitingScreen(true);
218 searchPanel.searchTag(tag, page, item, new Runnable() {
219 @Override
220 public void run() {
221 updateMaxPage(searchPanel.getMaxPage());
222 updatePage(page);
223 setWaitingScreen(false);
224 }
225 });
226 }
227 });
228 }
229
230 /**
231 * Process the given action in the main Swing UI thread.
232 * <p>
233 * The code will make sure the current thread is the main UI thread and, if
234 * not, will switch to it before executing the runnable.
235 * <p>
236 * Synchronous operation.
237 *
238 * @param run
239 * the action to run
240 */
241 static void inUi(final Runnable run) {
242 if (EventQueue.isDispatchThread()) {
243 run.run();
244 } else {
245 try {
246 EventQueue.invokeAndWait(run);
247 } catch (InterruptedException e) {
248 error(e);
249 } catch (InvocationTargetException e) {
250 error(e);
251 }
252 }
253 }
254
255 static void error(Exception e) {
256 Instance.getTraceHandler().error(e);
257 }
258
259 static void error(String e) {
260 Instance.getTraceHandler().error(e);
261 }
262
263 private void setWaitingScreen(final boolean waiting) {
264 inUi(new Runnable() {
265 @Override
266 public void run() {
267 GuiReaderSearchFrame.this.setEnabled(!waiting);
268 books.setEnabled(!waiting);
269 searchPanel.setEnabled(!waiting);
270 }
271 });
272 }
273 }