Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
BlogReader | 93 | 233 | 99 | ||
BlogReader.LaunchJvBrowserOnItem | 534 | 15 | 7 | ||
ChannelsRenderer | 821 | 7 | 2 | ||
ItemsRenderer | 846 | 11 | 4 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.gui; | |
22 | ||
23 | import jalview.bin.Cache; | |
24 | import jalview.bin.Console; | |
25 | import jalview.util.MessageManager; | |
26 | ||
27 | import java.awt.BorderLayout; | |
28 | import java.awt.Component; | |
29 | import java.awt.Dialog.ModalExclusionType; | |
30 | import java.awt.Dimension; | |
31 | import java.awt.Font; | |
32 | import java.awt.Rectangle; | |
33 | import java.awt.event.ActionEvent; | |
34 | import java.awt.event.ActionListener; | |
35 | import java.awt.event.KeyEvent; | |
36 | import java.awt.event.MouseEvent; | |
37 | import java.awt.event.WindowAdapter; | |
38 | import java.awt.event.WindowEvent; | |
39 | import java.beans.PropertyChangeListener; | |
40 | import java.text.DateFormat; | |
41 | import java.text.SimpleDateFormat; | |
42 | import java.util.ArrayList; | |
43 | import java.util.Calendar; | |
44 | import java.util.Collections; | |
45 | import java.util.Date; | |
46 | import java.util.Iterator; | |
47 | import java.util.List; | |
48 | import java.util.Map; | |
49 | ||
50 | import javax.swing.AbstractAction; | |
51 | import javax.swing.AbstractButton; | |
52 | import javax.swing.Action; | |
53 | import javax.swing.DefaultListCellRenderer; | |
54 | import javax.swing.DefaultListModel; | |
55 | import javax.swing.Icon; | |
56 | import javax.swing.ImageIcon; | |
57 | import javax.swing.JButton; | |
58 | import javax.swing.JFrame; | |
59 | import javax.swing.JLabel; | |
60 | import javax.swing.JList; | |
61 | import javax.swing.JMenuItem; | |
62 | import javax.swing.JPanel; | |
63 | import javax.swing.JPopupMenu; | |
64 | import javax.swing.JScrollPane; | |
65 | import javax.swing.JSplitPane; | |
66 | import javax.swing.JToolBar; | |
67 | import javax.swing.ListSelectionModel; | |
68 | import javax.swing.SwingUtilities; | |
69 | import javax.swing.event.HyperlinkEvent; | |
70 | import javax.swing.event.HyperlinkListener; | |
71 | import javax.swing.event.ListSelectionEvent; | |
72 | import javax.swing.event.ListSelectionListener; | |
73 | ||
74 | import org.robsite.jswingreader.action.MarkChannelAsRead; | |
75 | import org.robsite.jswingreader.action.MarkChannelAsUnread; | |
76 | import org.robsite.jswingreader.action.MarkItemAsRead; | |
77 | import org.robsite.jswingreader.action.MarkItemAsUnread; | |
78 | import org.robsite.jswingreader.action.UpdatableAction; | |
79 | import org.robsite.jswingreader.model.Channel; | |
80 | import org.robsite.jswingreader.model.ChannelListModel; | |
81 | import org.robsite.jswingreader.model.Item; | |
82 | import org.robsite.jswingreader.model.SimpleRSSParser; | |
83 | import org.robsite.jswingreader.ui.BlogContentPane; | |
84 | import org.robsite.jswingreader.ui.ItemReadTimer; | |
85 | import org.robsite.jswingreader.ui.Main; | |
86 | import org.robsite.jswingreader.ui.util.ContextMenuMouseAdapter; | |
87 | ||
88 | /** | |
89 | * Blog reading window, adapted from JSwingReader's | |
90 | * org.robsite.jswingreader.ui.MainWindow class | |
91 | */ | |
92 | ||
93 | public class BlogReader extends JPanel | |
94 | { | |
95 | private JButton buttonRefresh = new JButton(); | |
96 | ||
97 | private JToolBar toolBar = new JToolBar(); | |
98 | ||
99 | private JLabel statusBar = new JLabel(); | |
100 | ||
101 | private JPanel panelMain = new JPanel(); | |
102 | ||
103 | private BorderLayout layoutMain = new BorderLayout(); | |
104 | ||
105 | private BorderLayout borderLayout1 = new BorderLayout(); | |
106 | ||
107 | private JPanel topPanel = new JPanel(); | |
108 | ||
109 | private JPanel bottomPanel = new JPanel(); | |
110 | ||
111 | private JSplitPane topBottomSplitPane = new JSplitPane(); | |
112 | ||
113 | private JList listItems = new JList(new DefaultListModel()); | |
114 | ||
115 | // SWITCH IN JALVIEW HTML VIEWER PANE HERE | |
116 | private BlogContentPane textDescription = new BlogContentPane(); | |
117 | ||
118 | // ADD IN JALVIEW BANNER FOR PRETTINESS | |
119 | private BorderLayout borderLayout4 = new BorderLayout(); | |
120 | ||
121 | private BorderLayout borderLayout5 = new BorderLayout(); | |
122 | ||
123 | private ChannelListModel _channelModel = null; | |
124 | ||
125 | private JList listChannels = new JList(); | |
126 | ||
127 | private Action exitAction = new Action() | |
128 | { | |
129 | ||
130 | 0 | @Override |
131 | public void actionPerformed(ActionEvent arg0) | |
132 | { | |
133 | 0 | if (xf != null) |
134 | { | |
135 | 0 | xf.dispose(); |
136 | } | |
137 | 0 | xf = null; |
138 | 0 | jd = null; |
139 | 0 | if (parent != null) |
140 | { | |
141 | 0 | parent.showNews(false); |
142 | } | |
143 | ||
144 | } | |
145 | ||
146 | 0 | @Override |
147 | public void setEnabled(boolean arg0) | |
148 | { | |
149 | ||
150 | } | |
151 | ||
152 | 0 | @Override |
153 | public void removePropertyChangeListener(PropertyChangeListener arg0) | |
154 | { | |
155 | // TODO Auto-generated method stub | |
156 | ||
157 | } | |
158 | ||
159 | 0 | @Override |
160 | public void putValue(String arg0, Object arg1) | |
161 | { | |
162 | // TODO Auto-generated method stub | |
163 | ||
164 | } | |
165 | ||
166 | 0 | @Override |
167 | public boolean isEnabled() | |
168 | { | |
169 | // TODO Auto-generated method stub | |
170 | 0 | return true; |
171 | } | |
172 | ||
173 | 0 | @Override |
174 | public Object getValue(String arg0) | |
175 | { | |
176 | // TODO Auto-generated method stub | |
177 | 0 | return null; |
178 | } | |
179 | ||
180 | 0 | @Override |
181 | public void addPropertyChangeListener(PropertyChangeListener arg0) | |
182 | { | |
183 | // TODO Auto-generated method stub | |
184 | ||
185 | } | |
186 | }; | |
187 | ||
188 | private JFrame xf = null; | |
189 | ||
190 | private JalviewDialog jd = null; | |
191 | ||
192 | 9 | private JalviewDialog createDialog() |
193 | { | |
194 | ||
195 | 9 | return jd = new JalviewDialog() |
196 | { | |
197 | ||
198 | 0 | @Override |
199 | protected void raiseClosed() | |
200 | { | |
201 | 0 | if (parent != null) |
202 | { | |
203 | 0 | Console.debug("News window closed."); |
204 | 0 | jd = null; |
205 | 0 | parent.showNews(false); |
206 | } | |
207 | } | |
208 | ||
209 | 0 | @Override |
210 | protected void okPressed() | |
211 | { | |
212 | // TODO Auto-generated method stub | |
213 | ||
214 | } | |
215 | ||
216 | 0 | @Override |
217 | protected void cancelPressed() | |
218 | { | |
219 | // TODO Auto-generated method stub | |
220 | ||
221 | } | |
222 | }; | |
223 | } | |
224 | ||
225 | private JLabel lblChannels = new JLabel(); | |
226 | ||
227 | private List _updatableActions = new ArrayList(); | |
228 | ||
229 | private ItemReadTimer _itemTimer = null; | |
230 | ||
231 | private JPopupMenu _popupItems = null; | |
232 | ||
233 | private JPopupMenu _popupChannels = null; | |
234 | ||
235 | private String lastm = ""; | |
236 | ||
237 | private boolean newsnew = false; | |
238 | ||
239 | private Desktop parent = null; | |
240 | ||
241 | 0 | BlogReader() |
242 | { | |
243 | 0 | this(null); |
244 | } | |
245 | ||
246 | // should we ignore fake gui events | |
247 | private boolean updating = false; | |
248 | ||
249 | 42 | public BlogReader(Desktop desktop) |
250 | { | |
251 | 42 | Console.debug("Constructing news reader."); |
252 | ||
253 | 42 | parent = desktop; |
254 | 42 | _channelModel = new ChannelListModel(); |
255 | // Construct our jalview news channel | |
256 | 42 | Channel chan = new Channel(); |
257 | 42 | chan.setURL(Cache.getDefault("JALVIEW_NEWS_RSS", |
258 | Cache.getDefault("www.jalview.org", "https://www.jalview.org") | |
259 | + "/feeds/desktop/rss")); | |
260 | 42 | loadLastM(); |
261 | 42 | _channelModel.addChannel(chan); |
262 | 42 | updating = true; |
263 | 42 | try |
264 | { | |
265 | 42 | jbInit(); |
266 | 42 | postInit(); |
267 | } catch (Exception e) | |
268 | { | |
269 | 0 | e.printStackTrace(); |
270 | } | |
271 | ||
272 | 42 | initItems(chan); |
273 | 42 | updating = false; |
274 | 42 | if (!Cache.getDefault("NONEWS", false)) |
275 | { | |
276 | 42 | boolean setvisible = checkForNew(chan, true); |
277 | ||
278 | 42 | if (setvisible) |
279 | { | |
280 | ||
281 | 9 | Console.debug("Will show jalview news automatically"); |
282 | 9 | showNews(); |
283 | } | |
284 | } | |
285 | 42 | Console.debug("Completed construction of reader."); |
286 | ||
287 | } | |
288 | ||
289 | /** | |
290 | * check if the news panel's container is visible | |
291 | */ | |
292 | 511 | @Override |
293 | public boolean isVisible() | |
294 | { | |
295 | 511 | if (parent == null) |
296 | { | |
297 | 0 | return xf != null && xf.isVisible(); |
298 | } | |
299 | 511 | return jd != null && jd.isVisible(); |
300 | } | |
301 | ||
302 | /** | |
303 | * display the container for the news panel | |
304 | */ | |
305 | 9 | public void showNews() |
306 | { | |
307 | 9 | final BlogReader me = this; |
308 | 9 | SwingUtilities.invokeLater(new Runnable() |
309 | { | |
310 | 9 | @Override |
311 | public void run() | |
312 | { | |
313 | 9 | Rectangle bounds = new Rectangle(5, 5, 550, 350); |
314 | 9 | if (parent == null) |
315 | { | |
316 | 0 | xf = new JFrame(); |
317 | 0 | xf.setContentPane(me); |
318 | 0 | xf.addWindowListener(new WindowAdapter() |
319 | { | |
320 | 0 | @Override |
321 | public void windowClosing(WindowEvent e) | |
322 | { | |
323 | 0 | ActionEvent actionEvent = new ActionEvent(this, |
324 | ActionEvent.ACTION_FIRST, | |
325 | (String) exitAction.getValue(Action.NAME)); | |
326 | 0 | exitAction.actionPerformed(actionEvent); |
327 | } | |
328 | ||
329 | 0 | @Override |
330 | public void windowOpened(WindowEvent e) | |
331 | { | |
332 | } | |
333 | }); | |
334 | 0 | me.setSize(new Dimension(550, 350)); |
335 | 0 | xf.setVisible(true); |
336 | } | |
337 | else | |
338 | { | |
339 | 9 | createDialog(); |
340 | 9 | bounds = new Rectangle(5, 5, 550, 350); |
341 | 9 | jd.initDialogFrame(me, false, false, |
342 | MessageManager.getString("label.news_from_jalview"), | |
343 | bounds.width, bounds.height); | |
344 | 9 | jd.frame.setModalExclusionType(ModalExclusionType.NO_EXCLUDE); |
345 | 9 | Console.debug("Displaying news."); |
346 | 9 | jd.waitForInput(); |
347 | } | |
348 | } | |
349 | }); | |
350 | } | |
351 | ||
352 | /** | |
353 | * update hasnew flag and mark all new messages as unread. | |
354 | */ | |
355 | 165 | private boolean checkForNew(Channel chan, boolean updateItems) |
356 | { | |
357 | ||
358 | 165 | if (!updating || updateItems) |
359 | { | |
360 | 165 | newsnew = false; |
361 | } | |
362 | 165 | java.util.Date earliest = null; |
363 | 165 | try |
364 | { | |
365 | 165 | earliest = new SimpleDateFormat("YYYY-MM-DD") |
366 | .parse(chan.getHTTPLastModified()); | |
367 | } catch (Exception x) | |
368 | { | |
369 | } | |
370 | 165 | if (chan != null && chan.getItems() != null) |
371 | { | |
372 | 165 | Console.debug("Scanning news items: newsnew=" + newsnew |
373 | + " and lastDate is " + lastDate); | |
374 | 165 | for (Item i : (List<Item>) chan.getItems()) |
375 | { | |
376 | 4950 | Date published = i.getPublishDate(); |
377 | 4950 | boolean isread = lastDate == null ? false |
378 | : (published != null && !lastDate.before(published)); | |
379 | ||
380 | 4950 | if (!updating || updateItems) |
381 | { | |
382 | 4950 | newsnew |= !isread; |
383 | } | |
384 | 4950 | if (updateItems) |
385 | { | |
386 | 1260 | i.setRead(isread); |
387 | } | |
388 | 4950 | if (published != null && !i.isRead()) |
389 | { | |
390 | 964 | if (earliest == null || earliest.after(published)) |
391 | { | |
392 | 932 | earliest = published; |
393 | } | |
394 | } | |
395 | } | |
396 | } | |
397 | 165 | if (!updateItems && !updating && lastDate == null) |
398 | { | |
399 | 0 | lastDate = earliest; |
400 | } | |
401 | 165 | return newsnew; |
402 | } | |
403 | ||
404 | java.util.Date lastDate = null; | |
405 | ||
406 | 42 | private void loadLastM() |
407 | { | |
408 | 42 | lastDate = Cache.getDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED"); |
409 | } | |
410 | ||
411 | 123 | private void saveLastM(Item item) |
412 | { | |
413 | 123 | if (item != null) |
414 | { | |
415 | 123 | if (item.getPublishDate() != null) |
416 | { | |
417 | 82 | if (lastDate == null || item.getPublishDate().after(lastDate)) |
418 | { | |
419 | 8 | lastDate = item.getPublishDate(); |
420 | } | |
421 | } | |
422 | ||
423 | 123 | if (_channelModel.getElementAt(0) != null) |
424 | { | |
425 | 123 | checkForNew((Channel) _channelModel.getElementAt(0), false); |
426 | } | |
427 | 123 | if (lastDate != null) |
428 | { | |
429 | 123 | String formatted = Cache |
430 | .setDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED", lastDate); | |
431 | 123 | Console.debug("Saved last read date as " + formatted); |
432 | } | |
433 | } | |
434 | } | |
435 | ||
436 | 42 | private void jbInit() throws Exception |
437 | { | |
438 | 42 | setLayout(layoutMain); |
439 | 42 | panelMain.setLayout(borderLayout1); |
440 | 42 | topPanel.setLayout(borderLayout5); |
441 | 42 | bottomPanel.setLayout(borderLayout4); |
442 | 42 | topBottomSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); |
443 | 42 | topBottomSplitPane.setDividerLocation(100); |
444 | 42 | topBottomSplitPane.setTopComponent(topPanel); |
445 | 42 | topBottomSplitPane.setBottomComponent(bottomPanel); |
446 | 42 | JScrollPane spTextDescription = new JScrollPane(textDescription); |
447 | 42 | textDescription.setText(""); |
448 | 42 | statusBar.setText(new StringBuffer("[") |
449 | .append(MessageManager.getString("label.status")).append("]") | |
450 | .toString()); | |
451 | 42 | buttonRefresh.addActionListener(new ActionListener() |
452 | { | |
453 | ||
454 | 0 | @Override |
455 | public void actionPerformed(ActionEvent e) | |
456 | { | |
457 | 0 | refreshNews(); |
458 | } | |
459 | }); | |
460 | 42 | add(statusBar, BorderLayout.SOUTH); |
461 | 42 | toolBar.add(buttonRefresh); |
462 | 42 | toolBar.addSeparator(); |
463 | 42 | JLabel about = new JLabel( |
464 | "brought to you by JSwingReader (jswingreader.sourceforge.net)"); | |
465 | 42 | toolBar.add(about); |
466 | 42 | toolBar.setFloatable(false); |
467 | 42 | add(toolBar, BorderLayout.NORTH); |
468 | 42 | panelMain.add(topBottomSplitPane, BorderLayout.CENTER); |
469 | 42 | add(panelMain, BorderLayout.CENTER); |
470 | 42 | JScrollPane spListItems = new JScrollPane(listItems); |
471 | 42 | listItems |
472 | .setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); | |
473 | 42 | topPanel.add(spListItems, BorderLayout.CENTER); |
474 | 42 | bottomPanel.add(spTextDescription, BorderLayout.CENTER); |
475 | 42 | listChannels.setModel(_channelModel); |
476 | ||
477 | 42 | listItems.addMouseListener(new java.awt.event.MouseAdapter() |
478 | { | |
479 | 0 | @Override |
480 | public void mouseClicked(MouseEvent e) | |
481 | { | |
482 | 0 | listItems_mouseClicked(e); |
483 | } | |
484 | }); | |
485 | 42 | _popupItems = _buildItemsPopupMenu(); |
486 | 42 | _popupChannels = _buildChannelsPopupMenu(); |
487 | 42 | ContextMenuMouseAdapter popupAdapter = new ContextMenuMouseAdapter( |
488 | _popupItems); | |
489 | 42 | ContextMenuMouseAdapter popupChannelsAdapter = new ContextMenuMouseAdapter( |
490 | _popupChannels); | |
491 | 42 | listItems.addMouseListener(popupAdapter); |
492 | 42 | listItems.setCellRenderer(new ItemsRenderer()); |
493 | 42 | lblChannels.setText(MessageManager.getString("label.channels")); |
494 | } | |
495 | ||
496 | 42 | private void postInit() |
497 | { | |
498 | // clear the default hyperlink listener and replace with our own. | |
499 | 42 | for (HyperlinkListener hll : textDescription.getHyperlinkListeners()) |
500 | { | |
501 | 42 | textDescription.removeHyperlinkListener(hll); |
502 | } | |
503 | 42 | textDescription.addHyperlinkListener(new HyperlinkListener() |
504 | { | |
505 | 0 | @Override |
506 | public void hyperlinkUpdate(HyperlinkEvent e) | |
507 | { | |
508 | 0 | if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) |
509 | { | |
510 | 0 | Desktop.showUrl(e.getURL().toExternalForm()); |
511 | } | |
512 | } | |
513 | }); | |
514 | ||
515 | 42 | listItems.addListSelectionListener(new ListSelectionListener() |
516 | { | |
517 | 42 | @Override |
518 | public void valueChanged(ListSelectionEvent e) | |
519 | { | |
520 | 42 | if (e.getValueIsAdjusting() == false) |
521 | { | |
522 | 42 | _itemsValueChanged(listItems); |
523 | } | |
524 | } | |
525 | }); | |
526 | 42 | listChannels.setSelectedIndex(1); |
527 | 42 | _updateAllActions(); |
528 | 42 | _updateToolbarButtons(); |
529 | ||
530 | 42 | _itemTimer = new ItemReadTimer(listChannels, listItems); |
531 | 42 | _itemsValueChanged(listItems); |
532 | } | |
533 | ||
534 | public class LaunchJvBrowserOnItem extends AbstractAction | |
535 | implements UpdatableAction | |
536 | { | |
537 | JList _listItems = null; | |
538 | ||
539 | 42 | public LaunchJvBrowserOnItem(JList listItems) |
540 | { | |
541 | 42 | super("Open in Browser"); |
542 | 42 | this.putValue(MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_O)); |
543 | 42 | this.putValue(Action.LONG_DESCRIPTION, "Open in Browser"); |
544 | 42 | _listItems = listItems; |
545 | } | |
546 | ||
547 | 0 | @Override |
548 | public void actionPerformed(ActionEvent e) | |
549 | { | |
550 | 0 | Object o = _listItems.getSelectedValue(); |
551 | 0 | if (o instanceof Item) |
552 | { | |
553 | 0 | Item item = (Item) o; |
554 | 0 | item.setRead(true); |
555 | 0 | _listItems.repaint(); |
556 | ||
557 | 0 | Desktop.showUrl(item.getLink()); |
558 | } | |
559 | } | |
560 | ||
561 | 0 | @Override |
562 | public void update(Object o) | |
563 | { | |
564 | 0 | setEnabled(true); |
565 | 0 | if (_listItems == null || _listItems.getModel().getSize() == 0) |
566 | { | |
567 | 0 | setEnabled(false); |
568 | } | |
569 | 0 | else if (_listItems.getSelectedIndex() == -1) |
570 | { | |
571 | 0 | setEnabled(false); |
572 | } | |
573 | } | |
574 | ||
575 | } | |
576 | ||
577 | 42 | private JPopupMenu _buildItemsPopupMenu() |
578 | { | |
579 | 42 | JPopupMenu popup = new JPopupMenu(); |
580 | 42 | popup.add(new JMenuItem(new LaunchJvBrowserOnItem(listItems))); |
581 | 42 | popup.addSeparator(); |
582 | 42 | popup.add(new JMenuItem(new MarkItemAsRead(listItems))); |
583 | 42 | popup.add(new JMenuItem(new MarkItemAsUnread(listItems))); |
584 | 42 | return popup; |
585 | } | |
586 | ||
587 | 42 | private JPopupMenu _buildChannelsPopupMenu() |
588 | { | |
589 | 42 | JPopupMenu popup = new JPopupMenu(); |
590 | 42 | popup.add( |
591 | new JMenuItem(new MarkChannelAsRead(listChannels, listItems))); | |
592 | 42 | popup.add(new JMenuItem( |
593 | new MarkChannelAsUnread(listChannels, listItems))); | |
594 | 42 | return popup; |
595 | } | |
596 | ||
597 | 42 | private void initItems(Channel channel) |
598 | { | |
599 | 42 | if (channel == null) |
600 | { | |
601 | 0 | channel = new Channel(); |
602 | } | |
603 | 42 | if (!channel.isOpen() && channel.getURL() != null) |
604 | { | |
605 | 42 | try |
606 | { | |
607 | 42 | SimpleRSSParser.parse(channel); |
608 | } catch (Exception ex) | |
609 | { | |
610 | 0 | ex.printStackTrace(); |
611 | } | |
612 | } | |
613 | 42 | DefaultListModel itemsModel = (DefaultListModel) listItems.getModel(); |
614 | 42 | itemsModel.clear(); |
615 | 42 | Iterator iter = (channel.getItems() != null) |
616 | ? channel.getItems().iterator() | |
617 | : Collections.EMPTY_LIST.iterator(); | |
618 | 1302 | while (iter.hasNext()) |
619 | { | |
620 | 1260 | itemsModel.addElement(iter.next()); |
621 | } | |
622 | 42 | if (itemsModel.getSize() > 0) |
623 | { | |
624 | 42 | listItems.setSelectedIndex(0); |
625 | 42 | _itemsValueChanged(listItems); |
626 | } | |
627 | 42 | setStatusBarText(channel.getURL()); |
628 | 42 | _updateAllActions(); |
629 | } | |
630 | ||
631 | 126 | private void _itemsValueChanged(JList itemList) |
632 | { | |
633 | 126 | Item item = (Item) itemList.getSelectedValue(); |
634 | 126 | if (item == null) |
635 | { | |
636 | 42 | if (itemList.getModel().getSize() > 0) |
637 | { | |
638 | 0 | item = (Item) itemList.getModel().getElementAt(0); |
639 | } | |
640 | 42 | if (item == null) |
641 | { | |
642 | 42 | item = new Item(); |
643 | } | |
644 | else | |
645 | { | |
646 | 0 | itemList.setSelectedIndex(0); |
647 | } | |
648 | } | |
649 | ||
650 | 126 | if (_itemTimer != null) |
651 | { | |
652 | // prefer a shorter delay than 5s | |
653 | 126 | _itemTimer.setDelay(300); |
654 | 126 | _itemTimer.start(); |
655 | 126 | _itemTimer.setLastItem(item); |
656 | 126 | final Item lastitem = item; |
657 | 126 | _itemTimer.addActionListener(new ActionListener() |
658 | { | |
659 | ||
660 | 123 | @Override |
661 | public void actionPerformed(ActionEvent e) | |
662 | { | |
663 | 123 | saveLastM(lastitem); |
664 | } | |
665 | }); | |
666 | } | |
667 | ||
668 | 126 | setStatusBarText(item.getLink()); |
669 | 126 | textDescription.setBlogText(item); |
670 | 126 | _updateAllActions(); |
671 | } | |
672 | ||
673 | 168 | public void setStatusBarText(String text) |
674 | { | |
675 | 168 | statusBar.setText(text); |
676 | } | |
677 | ||
678 | 210 | private void _updateAllActions() |
679 | { | |
680 | 210 | Iterator iter = _updatableActions.iterator(); |
681 | 210 | while (iter.hasNext()) |
682 | { | |
683 | 0 | UpdatableAction action = (UpdatableAction) iter.next(); |
684 | 0 | action.update(this); |
685 | } | |
686 | } | |
687 | ||
688 | 42 | private void _updateToolbarButtons() |
689 | { | |
690 | 42 | Map general = (Map) Main.getPreferences().get("general"); |
691 | 42 | if (general == null) |
692 | { | |
693 | 0 | return; |
694 | } | |
695 | ||
696 | 42 | Component[] components = toolBar.getComponents(); |
697 | 168 | for (int i = 0; i < components.length; i++) |
698 | { | |
699 | 126 | Component component = components[i]; |
700 | 126 | if (component instanceof JButton) |
701 | { | |
702 | 42 | JButton button = (JButton) component; |
703 | 42 | if (Boolean.toString(false).equals(general.get("useToolBarText"))) |
704 | { | |
705 | // Remove the text if preferences state no toolbar text | |
706 | 42 | button.setText(""); |
707 | } | |
708 | 42 | if (Boolean.toString(true).equals(general.get("radioTextBelow"))) |
709 | { | |
710 | 0 | button.setVerticalTextPosition(AbstractButton.BOTTOM); |
711 | 0 | button.setHorizontalTextPosition(AbstractButton.CENTER); |
712 | } | |
713 | 42 | else if (Boolean.toString(true) |
714 | .equals(general.get("radioTextRight"))) | |
715 | { | |
716 | 0 | button.setVerticalTextPosition(AbstractButton.CENTER); |
717 | 0 | button.setHorizontalTextPosition(AbstractButton.RIGHT); |
718 | } | |
719 | } | |
720 | } | |
721 | } | |
722 | ||
723 | 0 | private void listItems_mouseClicked(MouseEvent e) |
724 | { | |
725 | 0 | if (e.getClickCount() == 2 && e.getModifiersEx() == MouseEvent.NOBUTTON) |
726 | { | |
727 | 0 | Item item = (Item) listItems.getSelectedValue(); |
728 | 0 | item.setRead(true); |
729 | 0 | saveLastM(item); |
730 | 0 | if (_itemTimer != null) |
731 | { | |
732 | 0 | _itemTimer.stop(); |
733 | } | |
734 | ||
735 | 0 | Action action = new LaunchJvBrowserOnItem(listItems); |
736 | 0 | ActionEvent event = new ActionEvent(this, |
737 | ActionEvent.ACTION_PERFORMED, "LaunchBrowserOnItem"); | |
738 | 0 | action.actionPerformed(event); |
739 | } | |
740 | } | |
741 | ||
742 | /** | |
743 | * force the news panel to refresh | |
744 | */ | |
745 | 0 | public void refreshNews() |
746 | { | |
747 | 0 | try |
748 | { | |
749 | 0 | initItems((Channel) _channelModel.getElementAt(0)); |
750 | ||
751 | } catch (Exception x) | |
752 | { | |
753 | } | |
754 | } | |
755 | ||
756 | /** | |
757 | * @j2sIgnore | |
758 | * @param args | |
759 | */ | |
760 | 0 | public static void main(String args[]) |
761 | { | |
762 | // this tests the detection of new news based on the last read date stored | |
763 | // in jalview properties | |
764 | 0 | Cache.loadProperties(null); |
765 | 0 | Console.initLogger(); |
766 | // test will advance read date each time | |
767 | 0 | Calendar today = Calendar.getInstance(), |
768 | lastread = Calendar.getInstance(); | |
769 | 0 | lastread.set(1983, 01, 01); |
770 | 0 | while (lastread.before(today)) |
771 | { | |
772 | 0 | String formattedDate = Cache.setDateProperty( |
773 | "JALVIEW_NEWS_RSS_LASTMODIFIED", lastread.getTime()); | |
774 | 0 | BlogReader me = new BlogReader(); |
775 | 0 | jalview.bin.Console.outPrintln("Set last date to " + formattedDate); |
776 | 0 | if (me.isNewsNew()) |
777 | { | |
778 | 0 | Console.debug("There is news to read."); |
779 | } | |
780 | else | |
781 | { | |
782 | 0 | Console.debug("There is no new news."); |
783 | 0 | me.xf.setTitle("Testing : Last read is " + me.lastDate); |
784 | 0 | me.showNews(); |
785 | 0 | me.xf.toFront(); |
786 | } | |
787 | 0 | Console.debug("Waiting for closure."); |
788 | 0 | do |
789 | { | |
790 | 0 | try |
791 | { | |
792 | 0 | Thread.sleep(300); |
793 | } catch (InterruptedException x) | |
794 | { | |
795 | } | |
796 | 0 | } while (me.isVisible()); |
797 | ||
798 | 0 | if (me.isNewsNew()) |
799 | { | |
800 | 0 | Console.debug("Still new news after reader displayed."); |
801 | } | |
802 | 0 | if (lastread.getTime().before(me.lastDate)) |
803 | { | |
804 | 0 | Console.debug("The news was read."); |
805 | 0 | lastread.setTime(me.lastDate); |
806 | } | |
807 | else | |
808 | { | |
809 | 0 | lastread.add(Calendar.MONTH, 1); |
810 | } | |
811 | ||
812 | } | |
813 | } | |
814 | ||
815 | 0 | boolean isNewsNew() |
816 | { | |
817 | 0 | return newsnew; |
818 | } | |
819 | } | |
820 | ||
821 | class ChannelsRenderer extends DefaultListCellRenderer | |
822 | { | |
823 | private final static Icon _icon = new ImageIcon( | |
824 | Main.class.getResource("image/ComposeMail16.gif")); | |
825 | ||
826 | 0 | @Override |
827 | public Component getListCellRendererComponent(JList list, Object value, | |
828 | int index, boolean isSelected, boolean cellHasFocus) | |
829 | { | |
830 | 0 | JLabel component = (JLabel) super.getListCellRendererComponent(list, |
831 | value, index, isSelected, cellHasFocus); | |
832 | 0 | component.setIcon(ChannelsRenderer._icon); |
833 | 0 | if (value instanceof Channel) |
834 | { | |
835 | 0 | Channel channel = (Channel) value; |
836 | 0 | component.setText(MessageManager |
837 | .formatMessage("label.channel_title_item_count", new String[] | |
838 | { channel.getTitle(), Integer | |
839 | .valueOf(channel.getUnreadItemCount()).toString() })); | |
840 | 0 | component.setToolTipText(channel.getURL()); |
841 | } | |
842 | 0 | return component; |
843 | } | |
844 | } | |
845 | ||
846 | class ItemsRenderer extends DefaultListCellRenderer | |
847 | { | |
848 | private final static Icon _icon = new ImageIcon( | |
849 | Main.class.getResource("image/ComposeMail16.gif")); | |
850 | ||
851 | 1755 | @Override |
852 | public Component getListCellRendererComponent(JList list, Object value, | |
853 | int index, boolean isSelected, boolean cellHasFocus) | |
854 | { | |
855 | 1755 | JLabel component = (JLabel) super.getListCellRendererComponent(list, |
856 | value, index, isSelected, cellHasFocus); | |
857 | 1755 | component.setIcon(ItemsRenderer._icon); |
858 | 1755 | if (value instanceof Item) |
859 | { | |
860 | 1755 | Item item = (Item) value; |
861 | 1755 | if (item.getPublishDate() != null) |
862 | { | |
863 | 1755 | component.setText(MessageManager.formatMessage( |
864 | "label.blog_item_published_on_date", new String[] | |
865 | { DateFormat | |
866 | .getDateInstance(DateFormat.LONG, | |
867 | MessageManager.getLocale()) | |
868 | .format(item.getPublishDate()).toString(), | |
869 | item.getTitle() })); | |
870 | } | |
871 | 1755 | component.setToolTipText(item.getLink()); |
872 | 1755 | if (!item.isRead()) |
873 | { | |
874 | 1717 | component.setFont(component.getFont().deriveFont(Font.BOLD)); |
875 | } | |
876 | else | |
877 | { | |
878 | 38 | component.setFont(component.getFont().deriveFont(Font.PLAIN)); |
879 | } | |
880 | } | |
881 | 1755 | return component; |
882 | } | |
883 | } |