Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  2. Package jalview.gui

File BlogReader.java

 

Coverage histogram

../../img/srcFileCovDistChart6.png
37% of files have more coverage

Code metrics

104
266
44
4
883
723
112
0.42
6.05
11
2.55

Classes

Class Line # Actions
BlogReader 93 233 99
0.616022161.6%
BlogReader.LaunchJvBrowserOnItem 534 15 7
0.2083333320.8%
ChannelsRenderer 821 7 2
0.00%
ItemsRenderer 846 11 4
0.888888988.9%
 

Contributing tests

This file is covered by 54 tests. .

Source view

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 toggle @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 toggle @Override
147    public void setEnabled(boolean arg0)
148    {
149   
150    }
151   
 
152  0 toggle @Override
153    public void removePropertyChangeListener(PropertyChangeListener arg0)
154    {
155    // TODO Auto-generated method stub
156   
157    }
158   
 
159  0 toggle @Override
160    public void putValue(String arg0, Object arg1)
161    {
162    // TODO Auto-generated method stub
163   
164    }
165   
 
166  0 toggle @Override
167    public boolean isEnabled()
168    {
169    // TODO Auto-generated method stub
170  0 return true;
171    }
172   
 
173  0 toggle @Override
174    public Object getValue(String arg0)
175    {
176    // TODO Auto-generated method stub
177  0 return null;
178    }
179   
 
180  0 toggle @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 toggle private JalviewDialog createDialog()
193    {
194   
195  9 return jd = new JalviewDialog()
196    {
197   
 
198  0 toggle @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 toggle @Override
210    protected void okPressed()
211    {
212    // TODO Auto-generated method stub
213   
214    }
215   
 
216  0 toggle @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 toggle BlogReader()
242    {
243  0 this(null);
244    }
245   
246    // should we ignore fake gui events
247    private boolean updating = false;
248   
 
249  42 toggle 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  503 toggle @Override
293    public boolean isVisible()
294    {
295  503 if (parent == null)
296    {
297  0 return xf != null && xf.isVisible();
298    }
299  503 return jd != null && jd.isVisible();
300    }
301   
302    /**
303    * display the container for the news panel
304    */
 
305  9 toggle public void showNews()
306    {
307  9 final BlogReader me = this;
308  9 SwingUtilities.invokeLater(new Runnable()
309    {
 
310  9 toggle @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 toggle @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 toggle @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 toggle 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  961 if (earliest == null || earliest.after(published))
391    {
392  929 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 toggle private void loadLastM()
407    {
408  42 lastDate = Cache.getDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED");
409    }
410   
 
411  123 toggle 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 toggle 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 toggle @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 toggle @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 toggle 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 toggle @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 toggle @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 toggle 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 toggle @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 toggle @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 toggle 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 toggle 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 toggle 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 toggle 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 toggle @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 toggle public void setStatusBarText(String text)
674    {
675  168 statusBar.setText(text);
676    }
677   
 
678  210 toggle 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 toggle 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 toggle 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 toggle 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 toggle 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 toggle 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 toggle @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  1710 toggle @Override
852    public Component getListCellRendererComponent(JList list, Object value,
853    int index, boolean isSelected, boolean cellHasFocus)
854    {
855  1710 JLabel component = (JLabel) super.getListCellRendererComponent(list,
856    value, index, isSelected, cellHasFocus);
857  1710 component.setIcon(ItemsRenderer._icon);
858  1710 if (value instanceof Item)
859    {
860  1710 Item item = (Item) value;
861  1710 if (item.getPublishDate() != null)
862    {
863  1710 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  1710 component.setToolTipText(item.getLink());
872  1710 if (!item.isRead())
873    {
874  1657 component.setFont(component.getFont().deriveFont(Font.BOLD));
875    }
876    else
877    {
878  53 component.setFont(component.getFont().deriveFont(Font.PLAIN));
879    }
880    }
881  1710 return component;
882    }
883    }