1 package be
.nikiroo
.fanfix
.reader
.ui
;
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
;
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
;
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
;
26 * This frame will allow you to search through the supported websites for new
31 // JCombobox<E> not 1.6 compatible
32 @SuppressWarnings({ "unchecked", "rawtypes" })
33 public class GuiReaderSearchFrame
extends JFrame
{
34 private static final long serialVersionUID
= 1L;
36 private List
<SupportType
> supportTypes
;
40 private JComboBox comboSupportTypes
;
41 private ActionListener comboSupportTypesListener
;
42 private GuiReaderSearchByPanel searchPanel
;
44 private boolean seeWordcount
;
45 private GuiReaderGroup books
;
47 public GuiReaderSearchFrame(final GuiReader reader
) {
48 super("Browse stories");
49 setLayout(new BorderLayout());
55 supportTypes
= new ArrayList
<SupportType
>();
56 supportTypes
.add(null);
57 for (SupportType type
: SupportType
.values()) {
58 if (BasicSearchable
.getSearchable(type
) != null) {
59 supportTypes
.add(type
);
63 comboSupportTypes
= new JComboBox(
64 supportTypes
.toArray(new SupportType
[] {}));
66 comboSupportTypesListener
= new ActionListener() {
68 public void actionPerformed(ActionEvent e
) {
69 final SupportType support
= (SupportType
) comboSupportTypes
72 new Thread(new Runnable() {
76 updateSupportType(support
);
84 comboSupportTypes
.addActionListener(comboSupportTypesListener
);
86 JPanel searchSites
= new JPanel(new BorderLayout());
87 searchSites
.add(comboSupportTypes
, BorderLayout
.CENTER
);
88 searchSites
.add(new JLabel(" " + "Website : "), BorderLayout
.WEST
);
90 searchPanel
= new GuiReaderSearchByPanel(
91 new GuiReaderSearchByPanel
.Waitable() {
93 public void setWaiting(boolean waiting
) {
94 GuiReaderSearchFrame
.this.setWaiting(waiting
);
98 public void fireEvent() {
99 updatePages(searchPanel
.getPage(),
100 searchPanel
.getMaxPage());
101 List
<GuiReaderBookInfo
> infos
= new ArrayList
<GuiReaderBookInfo
>();
102 for (MetaData meta
: searchPanel
.getStories()) {
103 infos
.add(GuiReaderBookInfo
.fromMeta(meta
));
109 int item
= searchPanel
.getStoryItem();
110 if (item
> 0 && item
<= books
.getBooksCount()) {
111 books
.setSelectedBook(item
- 1, false);
116 JPanel top
= new JPanel(new BorderLayout());
117 top
.add(searchSites
, BorderLayout
.NORTH
);
118 top
.add(searchPanel
, BorderLayout
.CENTER
);
120 add(top
, BorderLayout
.NORTH
);
122 books
= new GuiReaderGroup(reader
, null, null);
123 books
.setActionListener(new BookActionListener() {
125 public void select(GuiReaderBook book
) {
129 public void popupRequested(GuiReaderBook book
, Component target
,
134 public void action(GuiReaderBook book
) {
135 new GuiReaderSearchAction(reader
.getLibrary(), book
.getInfo())
139 JScrollPane scroll
= new JScrollPane(books
);
140 scroll
.getVerticalScrollBar().setUnitIncrement(16);
141 add(scroll
, BorderLayout
.CENTER
);
145 * Update the {@link SupportType} currently displayed to the user.
147 * Will also cause a search for the new base tags of the given support if
150 * This operation can be long and should be run outside the UI thread.
153 * the new {@link SupportType}
155 private void updateSupportType(final SupportType supportType
) {
156 inUi(new Runnable() {
162 .removeActionListener(comboSupportTypesListener
);
163 comboSupportTypes
.setSelectedItem(supportType
);
164 comboSupportTypes
.addActionListener(comboSupportTypesListener
);
169 searchPanel
.setSupportType(supportType
);
173 * Update the pages and the lined buttons currently displayed on screen.
175 * Those are the same pages and maximum pages used by
176 * {@link GuiReaderSearchByPanel#search(String, int, int)} and
177 * {@link GuiReaderSearchByPanel#searchTag(SearchableTag, int, int)}.
180 * the current page of results
182 * the maximum number of pages of results
184 private void updatePages(final int page
, final int maxPage
) {
185 inUi(new Runnable() {
188 GuiReaderSearchFrame
.this.page
= page
;
189 GuiReaderSearchFrame
.this.maxPage
= maxPage
;
192 System
.out
.println("page: " + page
);
193 System
.out
.println("max page: " + maxPage
);
199 * Update the currently displayed books.
204 private void updateBooks(final List
<GuiReaderBookInfo
> infos
) {
205 inUi(new Runnable() {
208 books
.refreshBooks(infos
, seeWordcount
);
214 * Search for the given terms on the currently selected searchable. This
215 * will update the displayed books if needed.
217 * This operation is asynchronous.
220 * the keywords to search for
222 * the page of results to load
224 * the item to select (or 0 for none by default)
226 public void search(final SupportType searchOn
, final String keywords
,
227 final int page
, final int item
) {
229 new Thread(new Runnable() {
233 updateSupportType(searchOn
);
234 searchPanel
.search(keywords
, page
, item
);
243 * Search for the given tag on the currently selected searchable. This will
244 * update the displayed books if needed.
246 * If the tag contains children tags, those will be displayed so you can
247 * select them; if the tag is a leaf tag, the linked stories will be
250 * This operation is asynchronous.
253 * the tag to search for, or NULL for base tags
255 * the page of results to load
257 * the item to select (or 0 for none by default)
259 public void searchTag(final SupportType searchOn
, final int page
,
260 final int item
, final SearchableTag tag
) {
262 new Thread(new Runnable() {
266 updateSupportType(searchOn
);
267 searchPanel
.searchTag(tag
, page
, item
);
276 * Process the given action in the main Swing UI thread.
278 * The code will make sure the current thread is the main UI thread and, if
279 * not, will switch to it before executing the runnable.
281 * Synchronous operation.
286 static void inUi(final Runnable run
) {
287 if (EventQueue
.isDispatchThread()) {
291 EventQueue
.invokeAndWait(run
);
292 } catch (InterruptedException e
) {
294 } catch (InvocationTargetException e
) {
301 * An error occurred, inform the user and/or log the error.
306 static void error(Exception e
) {
307 Instance
.getTraceHandler().error(e
);
311 * An error occurred, inform the user and/or log the error.
316 static void error(String e
) {
317 Instance
.getTraceHandler().error(e
);
321 * Enables or disables this component, depending on the value of the
322 * parameter <code>b</code>. An enabled component can respond to user input
323 * and generate events. Components are enabled initially by default.
325 * Disabling this component will also affect its children.
328 * If <code>true</code>, this component is enabled; otherwise
329 * this component is disabled
332 public void setEnabled(boolean b
) {
335 searchPanel
.setEnabled(b
);
339 * Set the item in wait mode, blocking it from accepting UI input.
342 * TRUE for wait more, FALSE to restore normal mode
344 private void setWaiting(final boolean waiting
) {
345 inUi(new Runnable() {
348 GuiReaderSearchFrame
.this.setEnabled(!waiting
);