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
.io
.IOException
;
9 import java
.lang
.reflect
.InvocationTargetException
;
10 import java
.util
.ArrayList
;
11 import java
.util
.List
;
13 import javax
.swing
.JButton
;
14 import javax
.swing
.JComboBox
;
15 import javax
.swing
.JFrame
;
16 import javax
.swing
.JPanel
;
17 import javax
.swing
.JScrollPane
;
18 import javax
.swing
.JTabbedPane
;
19 import javax
.swing
.JTextField
;
21 import be
.nikiroo
.fanfix
.Instance
;
22 import be
.nikiroo
.fanfix
.data
.MetaData
;
23 import be
.nikiroo
.fanfix
.reader
.ui
.GuiReaderBook
.BookActionListener
;
24 import be
.nikiroo
.fanfix
.searchable
.BasicSearchable
;
25 import be
.nikiroo
.fanfix
.searchable
.SearchableTag
;
26 import be
.nikiroo
.fanfix
.supported
.SupportType
;
29 * This frame will allow you to search through the supported websites for new
34 public class GuiReaderSearch
extends JFrame
{
35 private static final long serialVersionUID
= 1L;
37 private List
<SupportType
> supportTypes
;
38 private SupportType supportType
;
39 private boolean searchByTags
;
40 private List
<SearchableTag
> tags
;
41 private String keywords
;
45 private JComboBox
<SupportType
> comboSupportTypes
;
46 private JTabbedPane searchTabs
;
47 private JTextField keywordsField
;
49 private boolean seeWordcount
;
50 private GuiReaderGroup books
;
52 public GuiReaderSearch(final GuiReader reader
) {
54 super("Browse stories");
55 setLayout(new BorderLayout());
58 tags
= new ArrayList
<SearchableTag
>();
63 supportTypes
= new ArrayList
<SupportType
>();
64 for (SupportType type
: SupportType
.values()) {
65 if (BasicSearchable
.getSearchable(type
) != null) {
66 supportTypes
.add(type
);
69 supportType
= supportTypes
.isEmpty() ?
null : supportTypes
.get(0);
71 JPanel top
= new JPanel(new BorderLayout());
72 comboSupportTypes
= new JComboBox
<SupportType
>(
73 supportTypes
.toArray(new SupportType
[] {}));
74 comboSupportTypes
.addActionListener(new ActionListener() {
76 public void actionPerformed(ActionEvent e
) {
77 updateSupportType((SupportType
) comboSupportTypes
81 top
.add(comboSupportTypes
, BorderLayout
.NORTH
);
84 searchTabs
= new JTabbedPane();
85 searchTabs
.addTab("By name", createByNameSearchPanel());
86 searchTabs
.addTab("By tags", createByTagSearchPanel());
88 top
.add(searchTabs
, BorderLayout
.CENTER
);
90 add(top
, BorderLayout
.NORTH
);
92 books
= new GuiReaderGroup(reader
, null, null);
93 books
.setActionListener(new BookActionListener() {
95 public void select(GuiReaderBook book
) {
99 public void popupRequested(GuiReaderBook book
, Component target
,
104 public void action(GuiReaderBook book
) {
105 new GuiReaderSearchAction(reader
.getLibrary(), book
.getInfo())
109 JScrollPane scroll
= new JScrollPane(books
);
110 scroll
.getVerticalScrollBar().setUnitIncrement(16);
111 add(scroll
, BorderLayout
.CENTER
);
114 private JPanel
createByNameSearchPanel() {
115 JPanel byName
= new JPanel(new BorderLayout());
117 keywordsField
= new JTextField();
118 byName
.add(keywordsField
, BorderLayout
.CENTER
);
121 JButton submit
= new JButton("Search");
122 byName
.add(submit
, BorderLayout
.EAST
);
124 // TODO: ENTER -> search
126 submit
.addActionListener(new ActionListener() {
128 public void actionPerformed(ActionEvent e
) {
129 search(supportType
, keywordsField
.getText(), page
, 0);
136 private JPanel
createByTagSearchPanel() {
137 JPanel byTag
= new JPanel();
138 JPanel searchBars
= new JPanel();
139 add(searchBars
, BorderLayout
.NORTH
);
144 private void updateSupportType(SupportType supportType
) {
145 if (supportType
!= this.supportType
) {
146 this.supportType
= supportType
;
147 comboSupportTypes
.setSelectedItem(supportType
);
152 private void updateSearchBy(final boolean byTag
) {
153 if (byTag
!= this.searchByTags
) {
154 inUi(new Runnable() {
158 searchTabs
.setSelectedIndex(0);
160 searchTabs
.setSelectedIndex(1);
167 private void updatePages(final int page
, final Integer maxPage
) {
168 inUi(new Runnable() {
171 GuiReaderSearch
.this.page
= page
;
172 GuiReaderSearch
.this.maxPage
= maxPage
;
174 System
.out
.println("page: " + page
);
175 System
.out
.println("max page: " + maxPage
);
180 private void updateKeywords(final String keywords
) {
181 inUi(new Runnable() {
184 GuiReaderSearch
.this.keywords
= keywords
;
185 keywordsField
.setText(keywords
);
191 private void updateTags(final SearchableTag tag
) {
192 inUi(new Runnable() {
200 private void updateBooks(final List
<GuiReaderBookInfo
> infos
) {
201 inUi(new Runnable() {
204 books
.refreshBooks(infos
, seeWordcount
);
209 // item 0 = no selection, else = default selection
210 public void search(final SupportType searchOn
, final String keywords
,
211 final int page
, final int item
) {
213 updateSupportType(searchOn
);
214 updateSearchBy(false);
215 updateKeywords(keywords
);
216 updatePages(page
, maxPage
);
218 new Thread(new Runnable() {
221 BasicSearchable search
= BasicSearchable
222 .getSearchable(searchOn
);
227 maxPage
= search
.searchPages(keywords
);
228 } catch (IOException e
) {
229 Instance
.getTraceHandler().error(e
);
231 updateBooks(new ArrayList
<GuiReaderBookInfo
>());
232 updatePages(0, maxPage
);
234 List
<GuiReaderBookInfo
> infos
= new ArrayList
<GuiReaderBookInfo
>();
236 for (MetaData meta
: search
.search(keywords
, page
)) {
237 infos
.add(GuiReaderBookInfo
.fromMeta(meta
));
239 } catch (IOException e
) {
240 Instance
.getTraceHandler().error(e
);
244 updatePages(page
, maxPage
);
247 if (item
> 0 && item
<= books
.getBooksCount()) {
248 // TODO: "click" on item ITEM
255 public void searchTag(SupportType searchOn
, int page
, int item
,
258 updateSupportType(searchOn
);
259 updateSearchBy(true);
261 updatePages(page
, maxPage
);
263 BasicSearchable search
= BasicSearchable
.getSearchable(searchOn
);
268 maxPage
= search
.searchPages(tag
);
269 } catch (IOException e
) {
270 Instance
.getTraceHandler().error(e
);
273 updatePages(page
, maxPage
);
276 List
<MetaData
> metas
= null;
277 List
<SearchableTag
> subtags
= null;
282 metas
= search
.search(tag
, page
);
283 } catch (IOException e
) {
284 metas
= new ArrayList
<MetaData
>();
285 Instance
.getTraceHandler().error(e
);
287 count
= metas
.size();
289 subtags
= tag
.getChildren();
290 count
= subtags
.size();
296 MetaData meta
= metas
.get(item
- 1);
297 // TODO: select story
299 SearchableTag subtag
= subtags
.get(item
- 1);
300 // TODO: search on tag
309 * Process the given action in the main Swing UI thread.
311 * The code will make sure the current thread is the main UI thread and, if
312 * not, will switch to it before executing the runnable.
314 * Synchronous operation.
319 public void inUi(final Runnable run
) {
320 if (EventQueue
.isDispatchThread()) {
324 EventQueue
.invokeAndWait(run
);
325 } catch (InterruptedException e
) {
326 Instance
.getTraceHandler().error(e
);
327 } catch (InvocationTargetException e
) {
328 Instance
.getTraceHandler().error(e
);