From: jprocter Date: Thu, 22 Sep 2011 15:50:56 +0000 (+0100) Subject: jalview rss reader based on jswingreader (JAL-943) X-Git-Tag: Release_2_7~29 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=3be300f0d9107885e183ae7c86b081c8e6c6780f;p=jalview.git jalview rss reader based on jswingreader (JAL-943) --- diff --git a/THIRDPARTYLIBS b/THIRDPARTYLIBS index 2671d8c..5918fc2 100644 --- a/THIRDPARTYLIBS +++ b/THIRDPARTYLIBS @@ -19,6 +19,7 @@ httpcore-4.0.1.jar httpmime-4.0.3.jar jaxrpc.jar jhall.jar +jswingreader-0.3.jar : Apache license - built from http://jswingreader.sourceforge.net/ svn/trunk v12 log4j-1.2.8.jar mail.jar miglayout-4.0-swing.jar BSD http://www.migcalendar.com/miglayout/versions/4.0/license.txt diff --git a/lib/jswingreader-0.3.jar b/lib/jswingreader-0.3.jar new file mode 100644 index 0000000..c8a4fff Binary files /dev/null and b/lib/jswingreader-0.3.jar differ diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index ab08140..fab075e 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -19,6 +19,8 @@ package jalview.bin; import java.awt.Color; import java.io.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.*; import org.apache.log4j.*; @@ -767,4 +769,36 @@ public class Cache setProperty(property, jalview.util.Format .getHexString(colour)); } + + public static final DateFormat date_format = SimpleDateFormat.getDateTimeInstance(); + + /** + * store a date in a jalview property + * @param string + * @param time + */ + public static void setDateProperty(String property, Date time) + { + setProperty(property, date_format.format(time)); + } + /** + * read a date stored in a jalview property + * @param property + * @return valid date as stored by setDateProperty, or null + * + */ + public static Date getDateProperty(String property) + { + String val = getProperty(property); + if (val!=null) + { + try { + return date_format.parse(val); + } catch (Exception ex) + { + System.err.println("Invalid or corrupt date in property '"+property+"' : value was '"+val+"'"); + } + } + return null; + } } diff --git a/src/jalview/gui/BlogReader.java b/src/jalview/gui/BlogReader.java new file mode 100644 index 0000000..3b7df48 --- /dev/null +++ b/src/jalview/gui/BlogReader.java @@ -0,0 +1,754 @@ +package jalview.gui; + +import jalview.bin.Cache; +import jalview.jbgui.GBlogReader; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.beans.PropertyChangeListener; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.text.DateFormatter; + +import org.robsite.jswingreader.action.AboutAction; +import org.robsite.jswingreader.action.MarkChannelAsRead; +import org.robsite.jswingreader.action.MarkChannelAsUnread; +import org.robsite.jswingreader.action.MarkItemAsRead; +import org.robsite.jswingreader.action.MarkItemAsUnread; +import org.robsite.jswingreader.action.RefreshChannelAction; +import org.robsite.jswingreader.action.UpdatableAction; +import org.robsite.jswingreader.model.Channel; +import org.robsite.jswingreader.model.ChannelListModel; +import org.robsite.jswingreader.model.Item; +import org.robsite.jswingreader.model.SimpleRSSParser; +import org.robsite.jswingreader.ui.BlogContentPane; +import org.robsite.jswingreader.ui.ItemReadTimer; +import org.robsite.jswingreader.ui.Main; +import org.robsite.jswingreader.ui.util.ContextMenuMouseAdapter; +import org.robsite.jswingreader.util.BrowserUtils; + +import quicktime.std.movies.media.TextDescription; + +/** + * Blog reading window, adapted from JSwingReader's + * org.robsite.jswingreader.ui.MainWindow class + */ + +public class BlogReader extends GBlogReader +{ + private JButton buttonAbout = new JButton(); + + private JButton buttonRefresh = new JButton(); + + private JToolBar toolBar = new JToolBar(); + + private JLabel statusBar = new JLabel(); + + private JPanel panelMain = new JPanel(); + + private BorderLayout layoutMain = new BorderLayout(); + + private BorderLayout borderLayout1 = new BorderLayout(); + + private JPanel topPanel = new JPanel(); + + private JPanel bottomPanel = new JPanel(); + + private BorderLayout borderLayout2 = new BorderLayout(); + + private BorderLayout borderLayout3 = new BorderLayout(); + + private JSplitPane topBottomSplitPane = new JSplitPane(); + + private JList listItems = new JList(new DefaultListModel()); + + // SWITCH IN JALVIEW HTML VIEWER PANE HERE + private BlogContentPane textDescription = new BlogContentPane(); + + // ADD IN JALVIEW BANNER FOR PRETTINESS + private BorderLayout borderLayout4 = new BorderLayout(); + + private BorderLayout borderLayout5 = new BorderLayout(); + + private ChannelListModel _channelModel = null; + + private JList listChannels = new JList(); + + private Action exitAction = new Action() + { + + @Override + public void actionPerformed(ActionEvent arg0) + { + setVisible(false); + if (parent != null) + { + parent.showNews(false); + } + + } + + @Override + public void setEnabled(boolean arg0) + { + + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener arg0) + { + // TODO Auto-generated method stub + + } + + @Override + public void putValue(String arg0, Object arg1) + { + // TODO Auto-generated method stub + + } + + @Override + public boolean isEnabled() + { + // TODO Auto-generated method stub + return true; + } + + @Override + public Object getValue(String arg0) + { + // TODO Auto-generated method stub + return null; + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener arg0) + { + // TODO Auto-generated method stub + + } + }; + + private JLabel lblChannels = new JLabel(); + + private List _updatableActions = new ArrayList(); + + private ItemReadTimer _itemTimer = null; + + private JPopupMenu _popupItems = null; + + private JPopupMenu _popupChannels = null; + + private String lastm = ""; + + private boolean newsnew = false; + + private Desktop parent = null; + + BlogReader() + { + this(null); + } + + // should we ignore fake gui events + private boolean updating = false; + + public BlogReader(Desktop desktop) + { + parent = desktop; + if (parent == null) + { + this.setSize(new Dimension(550, 350)); + } + else + { + Rectangle bounds = parent + .getLastKnownDimensions("JALVIEW_RSS_WINDOW_"); + if (bounds == null) + { + setBounds(parent.getX(), parent.getY(), 550, 350); + } + else + { + setBounds(bounds.x, bounds.y, bounds.width, bounds.height); + } + } + _channelModel = new ChannelListModel(); + // Construct our jalview news channel + Channel chan = new Channel(); + chan.setURL(jalview.bin.Cache.getDefault( + "JALVIEW_NEWS_RSS", + jalview.bin.Cache.getDefault("www.jalview.org", + "http://www.jalview.org") + "/feeds/desktop/rss")); + loadLastM(); + _channelModel.addChannel(chan); + updating = true; + try + { + jbInit(); + postInit(); + } catch (Exception e) + { + e.printStackTrace(); + } + + initItems(chan); + updating = false; + boolean setvisible = checkForNew(chan, true); + if (setvisible) + { + Cache.log.info("Will show jalview news automatically"); + SwingUtilities.invokeLater(new Runnable() + { + @Override + public void run() + { + if (parent != null) + { + parent.showNews(true); + } + else + { + setVisible(true); + } + } + }); + } + } + + /** + * update hasnew flag and mark all new messages as unread. + */ + private boolean checkForNew(Channel chan, boolean updateItems) + { + if (!updating || updateItems) + { + newsnew = false; + } + if (chan != null && chan.getItems() != null) + { + for (Item i : (List) chan.getItems()) + { + boolean isread = (lastDate != null && i.getPublishDate() != null && !lastDate + .before(i.getPublishDate())); + + if (i.getPublishDate() != null && (!updating || updateItems)) + { + newsnew |= !isread; + } + if (updateItems) + { + i.setRead(isread); + } + } + } + return newsnew; + } + + java.util.Date lastDate = null; + + private void loadLastM() + { + lastDate = Cache.getDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED"); + } + + private void saveLastM(Item item) + { + if (item != null && item.getPublishDate() != null + && (lastDate == null || item.getPublishDate().after(lastDate))) + { + lastDate = item.getPublishDate(); + if (lastDate != null) + { + jalview.bin.Cache.setDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED", + lastDate); + jalview.bin.Cache.log.info("Saved last read date as " + + jalview.bin.Cache.date_format.format(lastDate)); + + } + if (_channelModel.getElementAt(0) != null) + { + checkForNew((Channel) _channelModel.getElementAt(0), false); + } + } + } + + private void jbInit() throws Exception + { + this.setTitle("News from www.jalview.org"); + this.getContentPane().setLayout(layoutMain); + panelMain.setLayout(borderLayout1); + topPanel.setLayout(borderLayout5); + bottomPanel.setLayout(borderLayout4); + topBottomSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); + topBottomSplitPane.setDividerLocation(100); + topBottomSplitPane.setTopComponent(topPanel); + topBottomSplitPane.setBottomComponent(bottomPanel); + JScrollPane spTextDescription = new JScrollPane(textDescription); + textDescription.setText(""); + statusBar.setText(" [Status] "); + buttonRefresh.addActionListener(new ActionListener() + { + + @Override + public void actionPerformed(ActionEvent e) + { + refreshNews(); + } + }); + this.getContentPane().add(statusBar, BorderLayout.SOUTH); + toolBar.add(buttonRefresh); + toolBar.addSeparator(); + JLabel about=new JLabel("brought to you by JSwingReader (jswingreader.sourceforge.net)"); + toolBar.add(about); + toolBar.setFloatable(false); + this.getContentPane().add(toolBar, BorderLayout.NORTH); + panelMain.add(topBottomSplitPane, BorderLayout.CENTER); + this.getContentPane().add(panelMain, BorderLayout.CENTER); + JScrollPane spListItems = new JScrollPane(listItems); + listItems + .setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + topPanel.add(spListItems, BorderLayout.CENTER); + bottomPanel.add(spTextDescription, BorderLayout.CENTER); + listChannels.setModel(_channelModel); + + listItems.addMouseListener(new java.awt.event.MouseAdapter() + { + public void mouseClicked(MouseEvent e) + { + listItems_mouseClicked(e); + } + }); + _popupItems = _buildItemsPopupMenu(); + _popupChannels = _buildChannelsPopupMenu(); + ContextMenuMouseAdapter popupAdapter = new ContextMenuMouseAdapter( + _popupItems); + ContextMenuMouseAdapter popupChannelsAdapter = new ContextMenuMouseAdapter( + _popupChannels); + listItems.addMouseListener(popupAdapter); + listItems.setCellRenderer(new ItemsRenderer()); + lblChannels.setText("Channels"); + } + + private void postInit() + { + // clear the default hyperlink listener and replace with our own. + for (HyperlinkListener hll : textDescription.getHyperlinkListeners()) + { + textDescription.removeHyperlinkListener(hll); + } + textDescription.addHyperlinkListener(new HyperlinkListener() + { + public void hyperlinkUpdate(HyperlinkEvent e) + { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) + { + Desktop.showUrl(e.getURL().toExternalForm()); + } + } + }); + + this.addWindowListener(new WindowAdapter() + { + public void windowClosing(WindowEvent e) + { + ActionEvent actionEvent = new ActionEvent(this, + ActionEvent.ACTION_FIRST, (String) exitAction + .getValue(Action.NAME)); + exitAction.actionPerformed(actionEvent); + } + + public void windowOpened(WindowEvent e) + { + } + }); + + listItems.addListSelectionListener(new ListSelectionListener() + { + public void valueChanged(ListSelectionEvent e) + { + if (e.getValueIsAdjusting() == false) + { + _itemsValueChanged(listItems); + } + } + }); + listChannels.setSelectedIndex(1); + _updateAllActions(); + _updateToolbarButtons(); + + _itemTimer = new ItemReadTimer(listChannels, listItems); + _itemsValueChanged(listItems); + } + + public class LaunchJvBrowserOnItem extends AbstractAction implements + UpdatableAction + { + JList _listItems = null; + + public LaunchJvBrowserOnItem(JList listItems) + { + super("Open in Browser"); + this.putValue(MNEMONIC_KEY, new Integer(KeyEvent.VK_O)); + this.putValue(Action.LONG_DESCRIPTION, "Open in Browser"); + _listItems = listItems; + } + + public void actionPerformed(ActionEvent e) + { + Object o = _listItems.getSelectedValue(); + if (o instanceof Item) + { + Item item = (Item) o; + item.setRead(true); + _listItems.repaint(); + + Desktop.showUrl(item.getLink()); + } + } + + public void update(Object o) + { + setEnabled(true); + if (_listItems == null || _listItems.getModel().getSize() == 0) + { + setEnabled(false); + } + else if (_listItems.getSelectedIndex() == -1) + { + setEnabled(false); + } + } + + } + + private JPopupMenu _buildItemsPopupMenu() + { + JPopupMenu popup = new JPopupMenu(); + popup.add(new JMenuItem(new LaunchJvBrowserOnItem(listItems))); + popup.addSeparator(); + popup.add(new JMenuItem(new MarkItemAsRead(listItems))); + popup.add(new JMenuItem(new MarkItemAsUnread(listItems))); + return popup; + } + + private JPopupMenu _buildChannelsPopupMenu() + { + JPopupMenu popup = new JPopupMenu(); + popup.add(new JMenuItem(new MarkChannelAsRead(listChannels, listItems))); + popup.add(new JMenuItem( + new MarkChannelAsUnread(listChannels, listItems))); + return popup; + } + + private void initItems(Channel channel) + { + if (channel == null) + { + channel = new Channel(); + } + if (!channel.isOpen() && channel.getURL() != null) + { + try + { + SimpleRSSParser.parse(channel); + } catch (Exception ex) + { + ex.printStackTrace(); + } + } + DefaultListModel itemsModel = (DefaultListModel) listItems.getModel(); + itemsModel.clear(); + Iterator iter = (channel.getItems() != null) ? channel.getItems() + .iterator() : Collections.EMPTY_LIST.iterator(); + while (iter.hasNext()) + { + itemsModel.addElement(iter.next()); + } + if (itemsModel.getSize() > 0) + { + listItems.setSelectedIndex(0); + _itemsValueChanged(listItems); + } + setStatusBarText(channel.getURL()); + _updateAllActions(); + } + + private void _itemsValueChanged(JList itemList) + { + Item item = (Item) itemList.getSelectedValue(); + if (item == null) + { + if (itemList.getModel().getSize() > 0) + { + item = (Item) itemList.getModel().getElementAt(0); + } + if (item == null) + { + item = new Item(); + } + else + { + itemList.setSelectedIndex(0); + } + } + + if (_itemTimer != null) + { + // prefer a shorter delay than 5s + _itemTimer.setDelay(300); + _itemTimer.start(); + _itemTimer.setLastItem(item); + final Item lastitem = item; + _itemTimer.addActionListener(new ActionListener() + { + + @Override + public void actionPerformed(ActionEvent e) + { + saveLastM(lastitem); + } + }); + } + + setStatusBarText(item.getLink()); + textDescription.setBlogText(item); + _updateAllActions(); + } + + public void setStatusBarText(String text) + { + statusBar.setText(text); + } + + private void _updateAllActions() + { + Iterator iter = _updatableActions.iterator(); + while (iter.hasNext()) + { + UpdatableAction action = (UpdatableAction) iter.next(); + action.update(this); + } + } + + private void _updateToolbarButtons() + { + Map general = (Map) Main.getPreferences().get("general"); + if (general == null) + { + return; + } + + Component[] components = toolBar.getComponents(); + for (int i = 0; i < components.length; i++) + { + Component component = components[i]; + if (component instanceof JButton) + { + JButton button = (JButton) component; + if (Boolean.toString(false).equals(general.get("useToolBarText"))) + { + // Remove the text if preferences state no toolbar text + button.setText(""); + } + if (Boolean.toString(true).equals(general.get("radioTextBelow"))) + { + button.setVerticalTextPosition(AbstractButton.BOTTOM); + button.setHorizontalTextPosition(AbstractButton.CENTER); + } + else if (Boolean.toString(true).equals( + general.get("radioTextRight"))) + { + button.setVerticalTextPosition(AbstractButton.CENTER); + button.setHorizontalTextPosition(AbstractButton.RIGHT); + } + } + } + } + + private void listItems_mouseClicked(MouseEvent e) + { + if (e.getClickCount() == 2 && e.getModifiersEx() == MouseEvent.NOBUTTON) + { + Item item = (Item) listItems.getSelectedValue(); + item.setRead(true); + saveLastM(item); + if (_itemTimer != null) + { + _itemTimer.stop(); + } + + Action action = new LaunchJvBrowserOnItem(listItems); + ActionEvent event = new ActionEvent(this, + ActionEvent.ACTION_PERFORMED, "LaunchBrowserOnItem"); + action.actionPerformed(event); + } + } + + /** + * force the news panel to refresh + */ + public void refreshNews() + { + try { + initItems((Channel)_channelModel.getElementAt(0)); + + } catch (Exception x) + {} + } + + public static void main(String args[]) + { + // this tests the detection of new news based on the last read date stored + // in jalview properties + jalview.bin.Cache.loadProperties(null); + jalview.bin.Cache.initLogger(); + // test will advance read date each time + Calendar today = Calendar.getInstance(), lastread = Calendar + .getInstance(); + lastread.set(1983, 01, 01); + while (lastread.before(today)) + { + Cache.setDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED", + lastread.getTime()); + BlogReader me = new BlogReader(); + System.out.println("Set last date to " + + jalview.bin.Cache.date_format.format(lastread.getTime())); + if (me.isNewsNew()) + { + Cache.log.info("There is news to read."); + } + else + { + Cache.log.info("There is no new news."); + } + me.setTitle("Testing : Last read is " + me.lastDate); + me.setVisible(true); + me.toFront(); + while (me.isVisible()) + { + try + { + Thread.sleep(100); + } catch (InterruptedException x) + { + } + ; + } + if (me.isNewsNew()) + { + Cache.log.info("Still new news after reader displayed."); + } + if (lastread.getTime().before(me.lastDate)) + { + Cache.log.info("The news was read."); + lastread.setTime(me.lastDate); + } + else + { + lastread.add(Calendar.MONTH, 1); + } + me.dispose(); + } + } + + boolean isNewsNew() + { + return newsnew; + } +} + +class ChannelsRenderer extends DefaultListCellRenderer +{ + private final static Icon _icon = new ImageIcon( + Main.class.getResource("image/ComposeMail16.gif")); + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) + { + JLabel component = (JLabel) super.getListCellRendererComponent(list, + value, index, isSelected, cellHasFocus); + component.setIcon(ChannelsRenderer._icon); + if (value instanceof Channel) + { + Channel channel = (Channel) value; + component.setText(channel.getTitle() + " (" + + channel.getUnreadItemCount() + ")"); + component.setToolTipText(channel.getURL()); + } + return component; + } +} + +class ItemsRenderer extends DefaultListCellRenderer +{ + private final static Icon _icon = new ImageIcon( + Main.class.getResource("image/ComposeMail16.gif")); + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) + { + JLabel component = (JLabel) super.getListCellRendererComponent(list, + value, index, isSelected, cellHasFocus); + component.setIcon(ItemsRenderer._icon); + if (value instanceof Item) + { + Item item = (Item) value; + if (item.getPublishDate() != null) + { + component.setText(DateFormat.getDateInstance().format( + item.getPublishDate()) + + " " + item.getTitle()); + } + component.setToolTipText(item.getLink()); + if (!item.isRead()) + { + component.setFont(component.getFont().deriveFont(Font.BOLD)); + } + else + { + component.setFont(component.getFont().deriveFont(Font.PLAIN)); + } + } + return component; + } +} diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index 3796b08..a5778a7 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -57,6 +57,11 @@ public class Desktop extends jalview.jbgui.GDesktop implements private JalviewChangeSupport changeSupport = new JalviewChangeSupport(); /** + * news reader - null if it was never started. + */ + private BlogReader jvnews=null; + + /** * @param listener * @see jalview.gui.JalviewChangeSupport#addJalviewPropertyChangeListener(java.beans.PropertyChangeListener) */ @@ -267,6 +272,18 @@ public class Desktop extends jalview.jbgui.GDesktop implements showConsole(showjconsole); + showNews.setVisible(false); + final Desktop me = this; + // Thread off the news reader, in case there are connection problems. + new Thread( new Runnable() { + @Override + public void run() + { + jvnews = new BlogReader(me); + showNews.setVisible(true); + } + }).start(); + this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) @@ -328,6 +345,22 @@ public class Desktop extends jalview.jbgui.GDesktop implements }); } + protected void showNews_actionPerformed(ActionEvent e) + { + showNews(showNews.isSelected()); + } + void showNews(boolean default1) + { + { + jvnews.setVisible(default1); + if (default1) + { + jvnews.refreshNews(); + jvnews.toFront(); + } + } + } + /** * recover the last known dimensions for a jalview window * @@ -914,6 +947,12 @@ public class Desktop extends jalview.jbgui.GDesktop implements storeLastKnownDimensions("JAVA_CONSOLE_", jconsole.getBounds()); jconsole.stopConsole(); } + if (jvnews!=null) + { + storeLastKnownDimensions("JALVIEW_RSS_WINDOW_", jvnews.getBounds()); + + } + System.exit(0); } diff --git a/src/jalview/jbgui/GBlogReader.java b/src/jalview/jbgui/GBlogReader.java new file mode 100644 index 0000000..c27f4b1 --- /dev/null +++ b/src/jalview/jbgui/GBlogReader.java @@ -0,0 +1,8 @@ +package jalview.jbgui; + +import javax.swing.JFrame; + +public class GBlogReader extends JFrame +{ + +} diff --git a/src/jalview/jbgui/GDesktop.java b/src/jalview/jbgui/GDesktop.java index 5effdbd..fc3f358 100755 --- a/src/jalview/jbgui/GDesktop.java +++ b/src/jalview/jbgui/GDesktop.java @@ -88,6 +88,8 @@ public class GDesktop extends JFrame protected JCheckBoxMenuItem showConsole = new JCheckBoxMenuItem(); + protected JCheckBoxMenuItem showNews = new JCheckBoxMenuItem(); + /** * Creates a new GDesktop object. */ @@ -306,6 +308,14 @@ public class GDesktop extends JFrame showConsole_actionPerformed(e); } }); + showNews.setText("Show Jalview News"); + showNews.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + showNews_actionPerformed(e); + } + }); desktopMenubar.add(FileMenu); desktopMenubar.add(toolsMenu); VamsasMenu.setVisible(false); @@ -330,6 +340,7 @@ public class GDesktop extends JFrame toolsMenu.add(preferences); toolsMenu.add(showMemusage); toolsMenu.add(showConsole); + toolsMenu.add(showNews); toolsMenu.add(garbageCollect); inputMenu.add(inputLocalFileMenuItem); inputMenu.add(inputURLMenuItem); @@ -346,7 +357,11 @@ public class GDesktop extends JFrame // TODO Auto-generated method stub } + protected void showNews_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + } protected void showMemusage_actionPerformed(ActionEvent e) { // TODO Auto-generated method stub