1 package be
.nikiroo
.fanfix
.reader
.ui
;
3 import java
.awt
.BorderLayout
;
5 import java
.awt
.Component
;
6 import java
.awt
.EventQueue
;
7 import java
.awt
.event
.ActionEvent
;
8 import java
.awt
.event
.ActionListener
;
9 import java
.io
.IOException
;
10 import java
.lang
.reflect
.InvocationTargetException
;
11 import java
.util
.ArrayList
;
12 import java
.util
.List
;
14 import javax
.swing
.JButton
;
15 import javax
.swing
.JComboBox
;
16 import javax
.swing
.JFrame
;
17 import javax
.swing
.JPanel
;
18 import javax
.swing
.JScrollPane
;
19 import javax
.swing
.JTabbedPane
;
20 import javax
.swing
.JTextField
;
22 import be
.nikiroo
.fanfix
.Instance
;
23 import be
.nikiroo
.fanfix
.data
.MetaData
;
24 import be
.nikiroo
.fanfix
.reader
.ui
.GuiReaderBook
.BookActionListener
;
25 import be
.nikiroo
.fanfix
.searchable
.BasicSearchable
;
26 import be
.nikiroo
.fanfix
.searchable
.SearchableTag
;
27 import be
.nikiroo
.fanfix
.supported
.SupportType
;
30 * This frame will allow you to search through the supported websites for new
35 public class GuiReaderSearch
extends JFrame
{
36 private static final long serialVersionUID
= 1L;
38 private List
<SupportType
> supportTypes
;
39 private SupportType supportType
;
40 private boolean searchByTags
;
41 private List
<SearchableTag
> tags
;
42 private String keywords
;
46 private JComboBox
<SupportType
> comboSupportTypes
;
47 private JTabbedPane searchTabs
;
48 private JTextField keywordsField
;
50 private boolean seeWordcount
;
51 private GuiReaderGroup books
;
53 public GuiReaderSearch(final GuiReader reader
) {
55 super("Browse stories");
56 setLayout(new BorderLayout());
59 tags
= new ArrayList
<SearchableTag
>();
64 supportTypes
= new ArrayList
<SupportType
>();
65 for (SupportType type
: SupportType
.values()) {
66 if (BasicSearchable
.getSearchable(type
) != null) {
67 supportTypes
.add(type
);
70 supportType
= supportTypes
.isEmpty() ?
null : supportTypes
.get(0);
72 JPanel top
= new JPanel(new BorderLayout());
73 comboSupportTypes
= new JComboBox
<SupportType
>(
74 supportTypes
.toArray(new SupportType
[] {}));
75 comboSupportTypes
.addActionListener(new ActionListener() {
77 public void actionPerformed(ActionEvent e
) {
78 updateSupportType((SupportType
) comboSupportTypes
82 top
.add(comboSupportTypes
, BorderLayout
.NORTH
);
85 searchTabs
= new JTabbedPane();
86 searchTabs
.addTab("By name", createByNameSearchPanel());
87 searchTabs
.addTab("By tags", createByTagSearchPanel());
89 top
.add(searchTabs
, BorderLayout
.CENTER
);
91 add(top
, BorderLayout
.NORTH
);
93 books
= new GuiReaderGroup(reader
, null, null);
94 books
.setActionListener(new BookActionListener() {
96 public void select(GuiReaderBook book
) {
100 public void popupRequested(GuiReaderBook book
, Component target
,
105 public void action(GuiReaderBook book
) {
106 new GuiReaderSearchAction(reader
.getLibrary(), book
.getInfo())
110 JScrollPane scroll
= new JScrollPane(books
);
111 scroll
.getVerticalScrollBar().setUnitIncrement(16);
112 add(scroll
, BorderLayout
.CENTER
);
115 private JPanel
createByNameSearchPanel() {
116 JPanel byName
= new JPanel(new BorderLayout());
118 keywordsField
= new JTextField();
119 byName
.add(keywordsField
, BorderLayout
.CENTER
);
122 JButton submit
= new JButton("Search");
123 byName
.add(submit
, BorderLayout
.EAST
);
125 // TODO: ENTER -> search
127 submit
.addActionListener(new ActionListener() {
129 public void actionPerformed(ActionEvent e
) {
130 search(supportType
, keywordsField
.getText(), page
, 0);
137 private JPanel
createByTagSearchPanel() {
138 JPanel byTag
= new JPanel();
139 JPanel searchBars
= new JPanel();
140 add(searchBars
, BorderLayout
.NORTH
);
145 private void updateSupportType(SupportType supportType
) {
146 if (supportType
!= this.supportType
) {
147 this.supportType
= supportType
;
148 comboSupportTypes
.setSelectedItem(supportType
);
153 private void updateSearchBy(final boolean byTag
) {
154 if (byTag
!= this.searchByTags
) {
155 inUi(new Runnable() {
159 searchTabs
.setSelectedIndex(0);
161 searchTabs
.setSelectedIndex(1);
168 private void updatePages(final int page
, final Integer maxPage
) {
169 inUi(new Runnable() {
172 GuiReaderSearch
.this.page
= page
;
173 GuiReaderSearch
.this.maxPage
= maxPage
;
175 System
.out
.println("page: " + page
);
176 System
.out
.println("max page: " + maxPage
);
181 private void updateKeywords(final String keywords
) {
182 inUi(new Runnable() {
185 GuiReaderSearch
.this.keywords
= keywords
;
186 keywordsField
.setText(keywords
);
192 private void updateTags(final SearchableTag tag
) {
193 inUi(new Runnable() {
201 private void updateBooks(final List
<GuiReaderBookInfo
> infos
) {
202 setWaitingScreen(true);
203 inUi(new Runnable() {
206 books
.refreshBooks(infos
, seeWordcount
);
207 setWaitingScreen(false);
212 // item 0 = no selection, else = default selection
213 public void search(final SupportType searchOn
, final String keywords
,
214 final int page
, final int item
) {
216 updateSupportType(searchOn
);
217 updateSearchBy(false);
218 updateKeywords(keywords
);
219 updatePages(page
, maxPage
);
221 new Thread(new Runnable() {
224 BasicSearchable search
= BasicSearchable
225 .getSearchable(searchOn
);
230 maxPage
= search
.searchPages(keywords
);
231 } catch (IOException e
) {
232 Instance
.getTraceHandler().error(e
);
234 updateBooks(new ArrayList
<GuiReaderBookInfo
>());
235 updatePages(0, maxPage
);
237 List
<GuiReaderBookInfo
> infos
= new ArrayList
<GuiReaderBookInfo
>();
239 for (MetaData meta
: search
.search(keywords
, page
)) {
240 infos
.add(GuiReaderBookInfo
.fromMeta(meta
));
242 } catch (IOException e
) {
243 Instance
.getTraceHandler().error(e
);
247 updatePages(page
, maxPage
);
250 if (item
> 0 && item
<= books
.getBooksCount()) {
251 // TODO: "click" on item ITEM
258 public void searchTag(final SupportType searchOn
, final int page
,
259 final int item
, final SearchableTag tag
) {
261 setWaitingScreen(true);
263 updateSupportType(searchOn
);
264 updateSearchBy(true);
266 updatePages(page
, maxPage
);
268 new Thread(new Runnable() {
271 BasicSearchable search
= BasicSearchable
272 .getSearchable(searchOn
);
277 maxPage
= search
.searchPages(tag
);
278 } catch (IOException e
) {
279 Instance
.getTraceHandler().error(e
);
282 updatePages(page
, maxPage
);
285 List
<MetaData
> metas
= null;
286 List
<SearchableTag
> subtags
= null;
291 metas
= search
.search(tag
, page
);
292 } catch (IOException e
) {
293 metas
= new ArrayList
<MetaData
>();
294 Instance
.getTraceHandler().error(e
);
296 count
= metas
.size();
298 subtags
= tag
.getChildren();
299 count
= subtags
.size();
305 MetaData meta
= metas
.get(item
- 1);
306 // TODO: select story
308 SearchableTag subtag
= subtags
310 // TODO: search on tag
316 setWaitingScreen(false);
322 * Process the given action in the main Swing UI thread.
324 * The code will make sure the current thread is the main UI thread and, if
325 * not, will switch to it before executing the runnable.
327 * Synchronous operation.
332 private void inUi(final Runnable run
) {
333 if (EventQueue
.isDispatchThread()) {
337 EventQueue
.invokeAndWait(run
);
338 } catch (InterruptedException e
) {
339 Instance
.getTraceHandler().error(e
);
340 } catch (InvocationTargetException e
) {
341 Instance
.getTraceHandler().error(e
);
346 private void setWaitingScreen(final boolean waiting
) {
347 inUi(new Runnable() {
350 GuiReaderSearch
.this.setEnabled(!waiting
);
351 // TODO: this is just an example of something to do
353 books
.setBackground(Color
.RED
);
355 books
.setBackground(null);