1 package be
.nikiroo
.fanfix
.reader
.ui
;
3 import java
.awt
.BorderLayout
;
4 import java
.awt
.event
.ActionEvent
;
5 import java
.awt
.event
.ActionListener
;
6 import java
.awt
.event
.KeyAdapter
;
7 import java
.awt
.event
.KeyEvent
;
8 import java
.io
.IOException
;
9 import java
.util
.ArrayList
;
10 import java
.util
.List
;
12 import javax
.swing
.JButton
;
13 import javax
.swing
.JPanel
;
14 import javax
.swing
.JTextField
;
16 import be
.nikiroo
.fanfix
.data
.MetaData
;
17 import be
.nikiroo
.fanfix
.reader
.ui
.GuiReaderSearchByPanel
.Waitable
;
18 import be
.nikiroo
.fanfix
.searchable
.BasicSearchable
;
21 * This panel represents a search panel that works for keywords and tags based
26 public class GuiReaderSearchByNamePanel
extends JPanel
{
27 private static final long serialVersionUID
= 1L;
29 private BasicSearchable searchable
;
31 private JTextField keywordsField
;
32 private JButton submitKeywords
;
36 private List
<MetaData
> stories
= new ArrayList
<MetaData
>();
37 private int storyItem
;
39 public GuiReaderSearchByNamePanel(final Waitable waitable
) {
40 super(new BorderLayout());
42 keywordsField
= new JTextField();
43 add(keywordsField
, BorderLayout
.CENTER
);
45 submitKeywords
= new JButton("Search");
46 add(submitKeywords
, BorderLayout
.EAST
);
48 // should be done out of UI
49 final Runnable go
= new Runnable() {
52 waitable
.setWaiting(true);
54 search(keywordsField
.getText(), 1, 0);
57 waitable
.setWaiting(false);
62 keywordsField
.addKeyListener(new KeyAdapter() {
64 public void keyReleased(KeyEvent e
) {
65 if (e
.getKeyCode() == KeyEvent
.VK_ENTER
) {
66 new Thread(go
).start();
73 submitKeywords
.addActionListener(new ActionListener() {
75 public void actionPerformed(ActionEvent e
) {
76 new Thread(go
).start();
84 * The {@link BasicSearchable} object use for the searches themselves.
86 * Can be NULL, but no searches will work.
91 public void setSearchable(BasicSearchable searchable
) {
92 this.searchable
= searchable
;
96 stories
= new ArrayList
<MetaData
>();
101 * The currently displayed page of result for the current search (see the
102 * <tt>page</tt> parameter of
103 * {@link GuiReaderSearchByNamePanel#search(String, int, int)}).
105 * @return the currently displayed page of results
107 public int getPage() {
112 * The number of pages of result for the current search (see the
113 * <tt>page</tt> parameter of
114 * {@link GuiReaderSearchByPanel#search(String, int, int)}).
116 * For an unknown number or when not applicable, -1 is returned.
118 * @return the number of pages of results or -1
120 public int getMaxPage() {
125 * Return the keywords used for the current search.
127 * @return the keywords
129 public String
getCurrentKeywords() {
130 return keywordsField
.getText();
134 * The currently loaded stories (the result of the latest search).
136 * @return the stories
138 public List
<MetaData
> getStories() {
143 * Return the currently selected story (the <tt>item</tt>) if it was
144 * specified in the latest, or 0 if not.
146 * Note: this is thus a 1-based index, <b>not</b> a 0-based index.
150 public int getStoryItem() {
155 * Update the keywords displayed on screen.
160 private void updateKeywords(final String keywords
) {
161 if (!keywords
.equals(keywordsField
.getText())) {
162 GuiReaderSearchFrame
.inUi(new Runnable() {
165 keywordsField
.setText(keywords
);
172 * Search for the given terms on the currently selected searchable.
174 * This operation can be long and should be run outside the UI thread.
177 * the keywords to search for
179 * the page of results to load
181 * the item to select (or 0 for none by default)
183 * @throw IndexOutOfBoundsException if the page is out of bounds
185 public void search(String keywords
, int page
, int item
) {
186 List
<MetaData
> stories
= new ArrayList
<MetaData
>();
189 updateKeywords(keywords
);
192 if (searchable
!= null) {
194 maxPage
= searchable
.searchPages(keywords
);
195 } catch (IOException e
) {
196 GuiReaderSearchFrame
.error(e
);
201 if (maxPage
>= 0 && (page
<= 0 || page
> maxPage
)) {
202 throw new IndexOutOfBoundsException("Page " + page
+ " out of "
206 if (searchable
!= null) {
208 stories
= searchable
.search(keywords
, page
);
209 } catch (IOException e
) {
210 GuiReaderSearchFrame
.error(e
);
214 if (item
> 0 && item
<= stories
.size()) {
216 } else if (item
> 0) {
217 GuiReaderSearchFrame
.error(String
.format(
218 "Story item does not exist: Search [%s], item %d",
224 this.maxPage
= maxPage
;
225 this.stories
= stories
;
226 this.storyItem
= storyItem
;
230 * Enables or disables this component, depending on the value of the
231 * parameter <code>b</code>. An enabled component can respond to user input
232 * and generate events. Components are enabled initially by default.
234 * Disabling this component will also affect its children.
237 * If <code>true</code>, this component is enabled; otherwise
238 * this component is disabled
241 public void setEnabled(boolean b
) {
243 keywordsField
.setEnabled(b
);
244 submitKeywords
.setEnabled(b
);