GUI search: regorg done
[fanfix.git] / src / be / nikiroo / fanfix / reader / ui / GuiReaderSearchByNamePanel.java
1 package be.nikiroo.fanfix.reader.ui;
2
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;
11
12 import javax.swing.JButton;
13 import javax.swing.JPanel;
14 import javax.swing.JTextField;
15
16 import be.nikiroo.fanfix.data.MetaData;
17 import be.nikiroo.fanfix.searchable.BasicSearchable;
18
19 /**
20 * This panel represents a search panel that works for keywords and tags based
21 * searches.
22 *
23 * @author niki
24 */
25 public class GuiReaderSearchByNamePanel extends JPanel {
26 private static final long serialVersionUID = 1L;
27
28 private BasicSearchable searchable;
29
30 private JTextField keywordsField;
31 private JButton submitKeywords;
32
33 private int page;
34 private int maxPage;
35 private List<MetaData> stories = new ArrayList<MetaData>();
36 private int storyItem;
37
38 public GuiReaderSearchByNamePanel(final Runnable fireEvent) {
39 super(new BorderLayout());
40
41 keywordsField = new JTextField();
42 add(keywordsField, BorderLayout.CENTER);
43
44 submitKeywords = new JButton("Search");
45 add(submitKeywords, BorderLayout.EAST);
46
47 keywordsField.addKeyListener(new KeyAdapter() {
48 @Override
49 public void keyReleased(KeyEvent e) {
50 if (e.getKeyCode() == KeyEvent.VK_ENTER) {
51 search(keywordsField.getText(), 1, 0);
52 } else {
53 super.keyReleased(e);
54 }
55 }
56 });
57
58 submitKeywords.addActionListener(new ActionListener() {
59 @Override
60 public void actionPerformed(ActionEvent e) {
61 new Thread(new Runnable() {
62 @Override
63 public void run() {
64 search(keywordsField.getText(), 1, 0);
65 fireEvent.run();
66 }
67 }).start();
68 }
69 });
70
71 setSearchable(null);
72 }
73
74 /**
75 * The {@link BasicSearchable} object use for the searches themselves.
76 * <p>
77 * Can be NULL, but no searches will work.
78 *
79 * @param searchable
80 * the new searchable
81 */
82 public void setSearchable(BasicSearchable searchable) {
83 this.searchable = searchable;
84 page = 1;
85 maxPage = -1;
86 storyItem = 0;
87 stories = new ArrayList<MetaData>();
88 updateKeywords("");
89 }
90
91 public int getPage() {
92 return page;
93 }
94
95 public int getMaxPage() {
96 return maxPage;
97 }
98
99 public String getCurrentKeywords() {
100 return keywordsField.getText();
101 }
102
103 public List<MetaData> getStories() {
104 return stories;
105 }
106
107 // selected item or 0 if none ! one-based !
108 public int getStoryItem() {
109 return storyItem;
110 }
111
112 // cannot be NULL
113 private void updateKeywords(final String keywords) {
114 if (!keywords.equals(keywordsField.getText())) {
115 GuiReaderSearchFrame.inUi(new Runnable() {
116 @Override
117 public void run() {
118 keywordsField.setText(keywords);
119 }
120 });
121 }
122 }
123
124 // item 0 = no selection, else = default selection
125 // throw if page > max
126 public void search(String keywords, int page, int item) {
127 List<MetaData> stories = new ArrayList<MetaData>();
128 int storyItem = 0;
129
130 updateKeywords(keywords);
131
132 int maxPage = -1;
133 try {
134 maxPage = searchable.searchPages(keywords);
135 } catch (IOException e) {
136 GuiReaderSearchFrame.error(e);
137 }
138
139 if (page > 0) {
140 if (maxPage >= 0 && (page <= 0 || page > maxPage)) {
141 throw new IndexOutOfBoundsException("Page " + page + " out of "
142 + maxPage);
143 }
144
145 try {
146 stories = searchable.search(keywords, page);
147 } catch (IOException e) {
148 GuiReaderSearchFrame.error(e);
149 stories = new ArrayList<MetaData>();
150 }
151
152 if (item > 0 && item <= stories.size()) {
153 storyItem = item;
154 } else if (item > 0) {
155 GuiReaderSearchFrame.error(String.format(
156 "Story item does not exist: Search [%s], item %d",
157 keywords, item));
158 }
159 }
160
161 this.page = page;
162 this.maxPage = maxPage;
163 this.stories = stories;
164 this.storyItem = storyItem;
165 }
166
167 /**
168 * Enables or disables this component, depending on the value of the
169 * parameter <code>b</code>. An enabled component can respond to user input
170 * and generate events. Components are enabled initially by default.
171 * <p>
172 * Disabling this component will also affect its children.
173 *
174 * @param b
175 * If <code>true</code>, this component is enabled; otherwise
176 * this component is disabled
177 */
178 @Override
179 public void setEnabled(boolean b) {
180 super.setEnabled(b);
181 keywordsField.setEnabled(b);
182 submitKeywords.setEnabled(b);
183 }
184 }