1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.plugin.news;
21
22 import javax.swing.AbstractAction;
23 import javax.swing.Action;
24 import javax.swing.BorderFactory;
25 import javax.swing.JLabel;
26 import javax.swing.JPanel;
27 import javax.swing.JScrollPane;
28 import javax.swing.SwingConstants;
29
30 import java.awt.BorderLayout;
31 import java.awt.Color;
32 import java.awt.FlowLayout;
33 import java.awt.GridBagConstraints;
34 import java.awt.GridBagLayout;
35 import java.awt.event.ActionEvent;
36 import java.io.File;
37 import java.io.IOException;
38 import java.util.LinkedList;
39 import java.util.List;
40
41 import org.apache.log4j.Logger;
42 import org.xnap.XNap;
43 import org.xnap.gui.StatusBar;
44 import org.xnap.gui.component.EraseButton;
45 import org.xnap.gui.component.HTMLEditorPane;
46 import org.xnap.gui.component.HistoryComboBox;
47 import org.xnap.gui.component.XNapButton;
48 import org.xnap.gui.component.XNapIconButton;
49 import org.xnap.gui.util.GUIHelper;
50 import org.xnap.gui.util.GridBagHelper;
51 import org.xnap.gui.util.IconHelper;
52 import org.xnap.util.Formatter;
53
54 /***
55 */
56 public class NewsPanel extends JPanel {
57
58
59
60
61
62 private static Logger logger = Logger.getLogger(NewsPanel.class);
63
64 private List newsItems = new LinkedList();
65 private HTMLEditorPane pane;
66 private JPanel locationPanel;
67 private JPanel actionPanel;
68 private List actionItems = new LinkedList();
69 private int cursorPos;
70 private StringBuffer content;
71
72 private HistoryComboBox jcbSearch;
73
74 private Action backAction = new BackAction();
75 private Action forwardAction = new ForwardAction();
76 private Action reloadAction = new ReloadAction();
77 private Action stopAction = new StopAction();
78 private Action queryAction = new QueryAction();
79
80
81
82 public NewsPanel()
83 {
84 setLayout(new GridBagLayout());
85
86
87 JLabel jlLogo = new JLabel(IconHelper.getScaledLogo(48));
88
89 jlLogo.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
90 jlLogo.setHorizontalAlignment(SwingConstants.RIGHT);
91 GridBagHelper.add(this, jlLogo);
92
93
94 pane = new HTMLEditorPane();
95 content = new StringBuffer();
96 HTMLEditorPane.addHeader(content);
97 content.append("<table margin=\"5\"><tr><td>");
98 cursorPos = content.length();
99 content.append("</td></tr></table>");
100 HTMLEditorPane.addFooter(content);
101 GridBagHelper.addPanel(this, new JScrollPane(pane));
102
103
104 JPanel locationPanel = new JPanel(new GridBagLayout());
105 GridBagHelper.add(this, locationPanel);
106
107 EraseButton jbErase = new EraseButton();
108 GridBagHelper.addComponent(locationPanel, jbErase, GridBagConstraints.WEST);
109
110 locationPanel.add(new JLabel(XNap.tr("Location", 1)));
111
112 jcbSearch = new HistoryComboBox(20);
113 jcbSearch.setText("news:");
114 jcbSearch.setPreferences("news");
115 GUIHelper.bindEnterKeyLocally(jcbSearch.getTextField(), queryAction);
116 jbErase.setTextField(jcbSearch.getTextField());
117 GridBagHelper.addComponent(locationPanel, jcbSearch, GridBagConstraints.WEST);
118
119 GridBagHelper.addComponent(locationPanel, new XNapIconButton(queryAction));
120 GridBagHelper.addComponent(locationPanel, new XNapIconButton(backAction));
121 GridBagHelper.addComponent(locationPanel, new XNapIconButton(forwardAction));
122 GridBagHelper.addComponent(locationPanel, new XNapIconButton(reloadAction));
123 GridBagHelper.addComponent(locationPanel, new XNapIconButton(stopAction));
124
125
126 actionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
127 GridBagHelper.add(locationPanel, actionPanel);
128 }
129
130
131
132 public void add(NewsItem item)
133 {
134 if (!newsItems.contains(item)) {
135 newsItems.add(item);
136
137 String message
138 = "<b>" + item.getTitle() + "</b> - <i>"
139 + item.getAuthor() + "</i> - <i>"
140 + Formatter.formatDate(item.getDate()) + "</i>"
141 + "<p>" + item.getDescription() + "</p>"
142 + "<hr size=1><br>";
143 insert(message);
144
145 Action[] actions = item.getActions();
146 if (actions != null) {
147 for (int i = 0; i < actions.length; i++) {
148 if (!actionItems.contains(actions[i])) {
149 actionItems.add(actions[i]);
150 actionPanel.add(new XNapButton(actions[i]));
151 }
152 }
153 }
154
155
156
157
158
159 }
160 else {
161 logger.debug("news item already exists ("+item.toString()+").");
162 }
163 }
164
165 public void insert(String text)
166 {
167 content.insert(cursorPos, text);
168 cursorPos += text.length();
169 if (actionPanel.isVisible()) {
170 pane.setText(content.toString());
171 pane.setCaretPosition(0);
172 }
173 }
174
175 public boolean open(String location)
176 {
177 if (location.length() > 0) {
178 if (location.startsWith("news:")) {
179 pane.setText(content.toString());
180 actionPanel.setVisible(true);
181 return true;
182 }
183
184 if (location.indexOf(":") == -1) {
185
186 location = (location.startsWith(File.separator))
187 ? "file:"
188 : "http://"
189 + location;
190 }
191
192 try {
193 pane.setPage(location);
194 actionPanel.setVisible(false);
195 StatusBar.setText(XNap.tr("Retrieving {0}", location));
196 return true;
197 }
198 catch (IOException e) {
199 StatusBar.setText(e.getLocalizedMessage());
200 }
201 }
202 return false;
203 }
204
205 public class NewsItemPanel extends JPanel {
206
207 public NewsItemPanel(NewsItem item)
208 {
209 setLayout(new BorderLayout());
210 setBackground(Color.white);
211
212 String title
213 = "<html><b>" + item.getTitle() + "</b> - <i>"
214 + item.getAuthor() + "</i> - <i>"
215 + Formatter.formatDate(item.getDate()) + "</i>";
216
217 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
218 buttonPanel.setBackground(Color.white);
219 Action[] actions = item.getActions();
220 if (actions != null) {
221 for (int i = 0; i < actions.length; i++) {
222 buttonPanel.add(new XNapButton(actions[i]));
223 }
224 }
225
226 JLabel titleLabel = new JLabel(title);
227
228 JLabel descriptionLabel
229 = new JLabel(GUIHelper.tt(item.getDescription(), 450));
230 descriptionLabel.setBorder(GUIHelper.createEmptyBorder(10));
231
232 this.add(titleLabel, BorderLayout.NORTH);
233 this.add(descriptionLabel, BorderLayout.CENTER);
234 this.add(buttonPanel, BorderLayout.SOUTH);
235 }
236
237 }
238
239
240
241 /***
242 // * Compares {@link NewsItem} objects by date.
243 // */
244
245
246
247
248
249
250
251
252
253
254
255 /***
256 *
257 */
258 private class QueryAction extends AbstractAction {
259
260 public QueryAction()
261 {
262
263 putValue(Action.SHORT_DESCRIPTION, XNap.tr("Perform search"));
264 putValue(IconHelper.XNAP_ICON, "key_enter.png");
265 }
266
267 public void actionPerformed(ActionEvent event)
268 {
269 String location = jcbSearch.getText().trim();
270 if (open(location)) {
271 jcbSearch.addDistinctItemAtTop(location);
272 }
273 }
274
275 }
276
277 /***
278 * Goes back in the browsing history
279 */
280 private class BackAction extends AbstractAction
281 {
282 public BackAction()
283 {
284 putValue(Action.NAME, XNap.tr("Back"));
285 putValue(Action.SHORT_DESCRIPTION, XNap.tr("Go back"));
286 putValue(IconHelper.XNAP_ICON, "1leftarrow.png");
287 }
288
289 public void actionPerformed(ActionEvent event)
290 {
291 int i = jcbSearch.getSelectedIndex();
292 if (i != -1 && i < jcbSearch.getItemCount() - 1) {
293 jcbSearch.setSelectedIndex(i + 1);
294 open((String)jcbSearch.getItemAt(i + 1));
295 }
296 }
297 }
298
299 /***
300 * Goes forward in the browsing history
301 */
302 private class ForwardAction extends AbstractAction
303 {
304 public ForwardAction()
305 {
306 putValue(Action.NAME, XNap.tr("Forward"));
307 putValue(Action.SHORT_DESCRIPTION, XNap.tr("Go forward"));
308 putValue(IconHelper.XNAP_ICON, "1rightarrow.png");
309 }
310
311 public void actionPerformed(ActionEvent event)
312 {
313 int i = jcbSearch.getSelectedIndex();
314 if (i > 0) {
315 jcbSearch.setSelectedIndex(i - 1);
316 open((String)jcbSearch.getItemAt(i - 1));
317 }
318 }
319 }
320
321 /***
322 * Reloads the current document
323 */
324 private class ReloadAction extends AbstractAction
325 {
326 public ReloadAction()
327 {
328 putValue(Action.NAME, XNap.tr("Reload"));
329 putValue(Action.SHORT_DESCRIPTION,
330 XNap.tr("Reload current document"));
331 putValue(IconHelper.XNAP_ICON, "reload.png");
332 }
333
334 public void actionPerformed(ActionEvent event)
335 {
336 int i = jcbSearch.getSelectedIndex();
337 if (i != -1) {
338 open((String)jcbSearch.getItemAt(i));
339 }
340 }
341 }
342 /***
343 * Stops loading the current document
344 */
345 private class StopAction extends AbstractAction
346 {
347 public StopAction()
348 {
349 putValue(Action.NAME, XNap.tr("Stop"));
350 putValue(Action.SHORT_DESCRIPTION,
351 XNap.tr("Stop loading the document"));
352 putValue(IconHelper.XNAP_ICON, "stop.png");
353
354
355 setEnabled(false);
356 }
357
358 public void actionPerformed(ActionEvent event)
359 {
360 }
361 }
362
363 }