Scilab news feed -- re-committed into its own branch, to make specific builds.
Simon Marchetto [Fri, 30 Oct 2015 16:46:37 +0000 (17:46 +0100)]
- integrated in GUI as flexdock panel
- displays RSS feed from scilab.org (configurable)
- displays one news at a time
- use HTML (JEditorPane/HtmlEditorKit) for display
- previous/next buttons
- possibility to change news automatically (time interval configurable).
- uses an external CSS stylesheet (ui_data/etc/newsfeed.css or SCIHOME/newsfeed.css)
- manages link opening in an external browser
- application & user settings in ui_data/etc/newsfeed.xml and SCIHOME/newsfeed.xml

Change-Id: I6cffceb77e0f0d7f6aed2cbece9c4ac2ea57d605

19 files changed:
scilab/modules/gui/etc/integratedConfiguration.xml
scilab/modules/gui/etc/main_menubar.xml
scilab/modules/ui_data/etc/newsfeed.css [new file with mode: 0644]
scilab/modules/ui_data/etc/newsfeed.xml [new file with mode: 0644]
scilab/modules/ui_data/help/en_US/newsfeed.xml [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/News.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedController.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedErrorEvent.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedEvent.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedEventListener.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedSettings.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedTab.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedTabFactory.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedUIMessages.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedWidget.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFetcher.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/CloseAction.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/HelpAction.java [new file with mode: 0644]
scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/UpdateAction.java [new file with mode: 0644]

index 64bdb18..0f139bf 100644 (file)
                             <DockableNode dockableId="00000000-0000-0000-0000-000000000000"/>
                         </DockingPortNode>
                         <DockingPortNode>
-                            <SplitNode dockingRegion="north" orientation="vertical" percentage="0.5" region="left">
+                            <SplitNode dockingRegion="north" orientation="vertical" percentage="0.30" region="left">
                                 <DockingPortNode>
                                     <DockableNode dockableId="3b649047-6a71-4998-bd8e-00d367a4793c"/>
                                 </DockingPortNode>
                                 <DockingPortNode>
-                                    <DockableNode dockableId="856207f6-0a60-47a0-b9f4-232feedd4bf4"/>
+                                    <SplitNode dockingRegion="south" orientation="vertical" percentage="0.50" region="left">
+                                        <DockingPortNode>
+                                            <DockableNode dockableId="856207f6-0a60-47a0-b9f4-232feedd4bf4"/>
+                                        </DockingPortNode>
+                                        <DockingPortNode>
+                                            <DockableNode dockableId="DC0957B3-81DA-4E39-B0B5-E93B35412162"/>
+                                        </DockingPortNode>
+                                    </SplitNode>
                                 </DockingPortNode>
                             </SplitNode>
                         </DockingPortNode>
             </SplitNode>
         </DockingPortNode>
     </Window>
+    <NewsFeed depends="00000000-0000-0000-0000-000000000000" factory="org.scilab.modules.ui_data.newsfeed.NewsFeedTabFactory" height="500" load="" uuid="DC0957B3-81DA-4E39-B0B5-E93B35412162" width="200" winuuid="5171ff0a-e5e6-4ea9-8525-8d9a5434b881"/>
     <Console factory="org.scilab.modules.core.ConsoleTabFactory" height="769" load="Console" uuid="00000000-0000-0000-0000-000000000000" width="576" winuuid="5171ff0a-e5e6-4ea9-8525-8d9a5434b881"/>
     <VariableBrowser depends="00000000-0000-0000-0000-000000000000" factory="org.scilab.modules.ui_data.tabfactory.VariableBrowserTabFactory" height="383" load="" uuid="3b649047-6a71-4998-bd8e-00d367a4793c" width="308" winuuid="5171ff0a-e5e6-4ea9-8525-8d9a5434b881"/>
     <CommandHistory depends="00000000-0000-0000-0000-000000000000" factory="org.scilab.modules.history_browser.CommandHistoryTabFactory" height="383" load="" uuid="856207f6-0a60-47a0-b9f4-232feedd4bf4" width="308" winuuid="5171ff0a-e5e6-4ea9-8525-8d9a5434b881"/>
     <FileBrowser depends="00000000-0000-0000-0000-000000000000" factory="org.scilab.modules.ui_data.tabfactory.FileBrowserTabFactory" height="769" load="" uuid="3b649047-6a71-4998-bd8e-00d367a4793d" width="329" winuuid="5171ff0a-e5e6-4ea9-8525-8d9a5434b881"/>
-    <!-- Xcos default configuration -->
+<!-- Xcos default configuration -->
     <Window height="500" uuid="xcos-palette-default-window" width="500" x="0" y="0" state="0">
         <DockingPortNode>
             <DockableNode dockableId="org.scilab.modules.xcos.palette.model"/>
index 9cf4aaf..51e87f4 100644 (file)
         <submenu label="&amp;File Browser">
             <callback instruction="filebrowser()" type="0"/>
         </submenu>
+        <separator/>
+        <submenu label="&amp;News feed">
+            <callback instruction="org.scilab.modules.ui_data.newsfeed.NewsFeedTab.displayTab" type="3"/>
+        </submenu>
     </menu>
     <!-- Help menu -->
     <menu label="&amp;?" enabled="true">
diff --git a/scilab/modules/ui_data/etc/newsfeed.css b/scilab/modules/ui_data/etc/newsfeed.css
new file mode 100644 (file)
index 0000000..6e78371
--- /dev/null
@@ -0,0 +1,15 @@
+#navigation {
+    margin-bottom: 10px
+}
+
+#news_title {
+    font-weight: bold
+}
+
+#news_date {
+    font-weight: bold
+}
+
+#news_link {
+    margin-top: 10px
+}
diff --git a/scilab/modules/ui_data/etc/newsfeed.xml b/scilab/modules/ui_data/etc/newsfeed.xml
new file mode 100644 (file)
index 0000000..33ec1c2
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<newsfeed>
+   <!-- RSS Feed URL -->
+   <url>http://www.scilab.org/rss/feed/news</url>
+   <!-- automatic news change interval time (in ms), set to -1 to disable -->
+   <newsChangeTimeInterval>-1</newsChangeTimeInterval>
+   <!-- periodic feed update interval time (in ms), set to -1 to disable -->
+   <feedUpdateTimeInterval>14400</feedUpdateTimeInterval>
+</newsfeed>
diff --git a/scilab/modules/ui_data/help/en_US/newsfeed.xml b/scilab/modules/ui_data/help/en_US/newsfeed.xml
new file mode 100644 (file)
index 0000000..e19526d
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2015 - Scilab Enterprises
+ *
+ * This file must be used under the terms of the CeCILL.
+ * This source file is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at
+ * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+ *
+ -->
+<refentry xmlns="http://docbook.org/ns/docbook"
+        xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:svg="http://www.w3.org/2000/svg"
+        xmlns:mml="http://www.w3.org/1998/Math/MathML"
+        xmlns:db="http://docbook.org/ns/docbook"
+        xmlns:scilab="http://www.scilab.org"
+        xml:lang="en"
+        xml:id="newsfeed">
+    <refnamediv>
+        <refname>News feed</refname>
+        <refpurpose>Displays news about Scilab</refpurpose>
+    </refnamediv>
+    <refsection>
+        <title>Description</title>
+        <para>
+            The Scilab news feed is an embedded component that displays news about the Scilab product and Scilab Enterprises company. The same news can be found on the <ulink url="http://www.scilab.org">Scilab</ulink> web site.
+        </para>
+    </refsection>
+</refentry>
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/News.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/News.java
new file mode 100644 (file)
index 0000000..f394c43
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import java.util.Date;
+
+/**
+ * News data
+ */
+public class News {
+
+    private String title;
+    private Date date;
+    private String description;
+    private String link;
+
+    public News(String title, Date date, String description, String link) {
+        this.title = title;
+        this.date = date;
+        this.description = description;
+        this.link = link;
+    }
+
+    String getTitle() {
+        return title;
+    }
+
+    Date getDate() {
+        return date;
+    }
+
+    String getDescription() {
+        return description;
+    }
+
+    String getLink() {
+        return link;
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedController.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedController.java
new file mode 100644 (file)
index 0000000..e7d6d6f
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Timer;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * News feed controller
+ * Updates news periodically & manages news rolling
+ * Communicates through NewsFeedEvent event class
+ * URL and other settings loaded from a settings file
+ */
+public class NewsFeedController implements ActionListener {
+
+    private List<News> news;
+    private ListIterator<News> newsIterator = null;
+    private News currentNews;
+
+    // by default do not change news automatically
+    private Timer newsChangeTimer;
+    private int newsChangeTimeInterval = -1;
+
+    // by default update feed every 4 hours
+    private Timer feedUpdateTimer;
+    private int feedUpdateTimeInterval = 4 * 60 * 60 * 1000;
+
+    private NewsFetcher newsFetcher;
+
+    private ArrayList<NewsFeedEventListener> listeners;
+
+    public NewsFeedController() {
+        newsFetcher = new NewsFetcher();
+
+        news = new ArrayList<News>();
+        listeners = new ArrayList<NewsFeedEventListener>();
+
+        readSettings();
+
+        if (newsChangeTimeInterval != -1) {
+            newsChangeTimer = new Timer(newsChangeTimeInterval, this);
+            newsChangeTimer.setRepeats(true);
+        } else {
+            newsChangeTimer = new Timer(1000, this);
+            newsChangeTimer.setRepeats(false);
+        }
+        newsChangeTimer.setInitialDelay(1000);
+
+        if (feedUpdateTimeInterval != -1) {
+            feedUpdateTimer = new Timer(feedUpdateTimeInterval, this);
+            feedUpdateTimer.setInitialDelay(0);
+            feedUpdateTimer.setRepeats(true);
+        } else {
+            feedUpdateTimer = new Timer(0, this);
+            feedUpdateTimer.setRepeats(false);
+        }
+    }
+
+    public void start() {
+        currentNews = null;
+        newsChangeTimer.start();
+        feedUpdateTimer.start();
+    }
+
+    public void stop() {
+        newsChangeTimer.stop();
+        feedUpdateTimer.stop();
+        currentNews = null;
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        if (e.getSource() == newsChangeTimer) {
+            if (isOK()) {
+                nextNews();
+            }
+        } else if (e.getSource() == feedUpdateTimer) {
+            updateNewsFeed();
+        }
+    }
+
+    public News getCurrentNews() {
+        return currentNews;
+    }
+
+    public void addNewsFeedEventListener(NewsFeedEventListener listener) {
+        listeners.add(listener);
+    }
+
+    public void removeNewsFeedEventListener(NewsFeedEventListener listener) {
+        listeners.remove(listener);
+    }
+
+    public void previousNews() {
+        currentNews = getIterator().previous();
+        fireNewsFeedEvent(NewsFeedEvent.NEWS_CHANGED);
+    }
+
+    public void nextNews() {
+        currentNews = getIterator().next();
+        fireNewsFeedEvent(NewsFeedEvent.NEWS_CHANGED);
+    }
+
+    public ListIterator<News> getIterator() {
+        if ((newsIterator == null) || !newsIterator.hasNext()) {
+            newsIterator = news.listIterator();
+        }
+        return newsIterator;
+    }
+
+    private boolean isOK() {
+        return (news != null && !news.isEmpty());
+    }
+
+    public void updateNewsFeed() {
+        news = null;
+
+        try {
+            newsFetcher.readSettings();
+
+            if (!newsFetcher.isOK()) {
+                return;
+            }
+
+            // TODO : update only if RSS feed has new news
+            news = newsFetcher.fetchNews();
+        } catch (Exception e) {
+            System.err.println(e);
+            e.printStackTrace();
+            fireNewsFeedErrorEvent(NewsFeedUIMessages.NEWS_FEED_UNAVAILABLE_ERROR);
+        }
+
+        newsIterator = null;
+    }
+
+    private void readSettings() {
+        try {
+            newsFetcher.readSettings();
+            newsChangeTimeInterval = NewsFeedSettings.getIntSetting("newsChangeTimeInterval");
+            if (newsChangeTimeInterval != -1) {
+                newsChangeTimeInterval *= 1000;
+            }
+            feedUpdateTimeInterval = NewsFeedSettings.getIntSetting("feedUpdateTimeInterval");
+            if (feedUpdateTimeInterval != -1) {
+                feedUpdateTimeInterval *= 1000;
+            }
+        } catch (Exception e) {
+            System.err.println(e);
+            e.printStackTrace();
+            fireNewsFeedErrorEvent(NewsFeedUIMessages.NEWS_FEED_CONFIGURATION_ERROR);
+        }
+    }
+
+    private void fireNewsFeedEvent(int eventType) {
+        NewsFeedEvent event = new NewsFeedEvent(this, eventType);
+        Iterator<NewsFeedEventListener> iterator = listeners.iterator();
+        while (iterator.hasNext()) {
+            iterator.next().newsFeedEventReceived(event);
+        }
+    }
+
+    private void fireNewsFeedErrorEvent(String errorMessage) {
+        NewsFeedErrorEvent errorEvent = new NewsFeedErrorEvent(this, errorMessage);
+        Iterator<NewsFeedEventListener> iterator = listeners.iterator();
+        while (iterator.hasNext()) {
+            iterator.next().newsFeedEventReceived(errorEvent);
+        }
+    }
+
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedErrorEvent.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedErrorEvent.java
new file mode 100644 (file)
index 0000000..f353fa1
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+/**
+ * News feed error event
+ */
+public class NewsFeedErrorEvent extends NewsFeedEvent {
+    private String errorMessage;
+
+    public NewsFeedErrorEvent(Object source, String errorMessage) {
+        super(source, NewsFeedEvent.NEWSFEED_ERROR);
+        this.errorMessage = errorMessage;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedEvent.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedEvent.java
new file mode 100644 (file)
index 0000000..7cda3d2
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import java.util.EventObject;
+
+/**
+ * News feed event
+ */
+public class NewsFeedEvent extends EventObject {
+    public static final int NEWS_CHANGED = 1;
+    public static final int NEWSFEED_UPDATED = 2;
+    public static final int NEWSFEED_ERROR = 3;
+
+    private int eventType;
+
+    public NewsFeedEvent(Object source, int eventType) {
+        super(source);
+        this.eventType = eventType;
+    }
+
+    public int getEventType() {
+        return eventType;
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedEventListener.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedEventListener.java
new file mode 100644 (file)
index 0000000..9579ecf
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+/**
+ * Interface for news feed event listener
+ */
+public interface NewsFeedEventListener {
+    public void newsFeedEventReceived(NewsFeedEvent e);
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedSettings.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedSettings.java
new file mode 100644 (file)
index 0000000..e39da5f
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import org.scilab.modules.commons.ScilabConstants;
+
+import java.io.File;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * Loads news feed settings like URL or update interval time
+ * Settings stored in newsfeed.xml (in directory ui_data/etc or SCIHOME)
+ */
+public class NewsFeedSettings {
+
+    public static String getStringSetting(String settingName) throws Exception {
+        File settingsFile = getSettingsFile();
+
+        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        Document doc = builder.parse(settingsFile);
+        NodeList newsfeedNodes = doc.getElementsByTagName("newsfeed");
+        return getItemValue((Element) (newsfeedNodes.item(0)), settingName);
+    }
+
+    public static int getIntSetting(String settingName) throws Exception {
+        String strSetting = getStringSetting(settingName);
+        return Integer.parseInt(strSetting);
+    }
+
+    private static File getSettingsFile() {
+        File settingsFile = new File(ScilabConstants.SCIHOME + "/newsfeed.xml");
+        if (!settingsFile.exists()) {
+            settingsFile = new File(ScilabConstants.SCI + "/modules/ui_data/etc/newsfeed.xml");
+        }
+        if (settingsFile.exists()) {
+            return settingsFile;
+        } else {
+            return null;
+        }
+    }
+
+    private static String getItemValue(Element item, String nodeName) {
+        NodeList nodeList = item.getElementsByTagName(nodeName);
+        if (nodeList.getLength() > 0) {
+            return nodeList.item(0).getFirstChild().getNodeValue();
+        } else {
+            return null;
+        }
+    }
+
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedTab.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedTab.java
new file mode 100644 (file)
index 0000000..93b682a
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import org.scilab.modules.ui_data.newsfeed.actions.CloseAction;
+import org.scilab.modules.ui_data.newsfeed.actions.HelpAction;
+import org.scilab.modules.ui_data.newsfeed.actions.UpdateAction;
+
+import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel;
+import org.scilab.modules.gui.bridge.toolbar.SwingScilabToolBar;
+import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
+import org.scilab.modules.gui.textbox.TextBox;
+import org.scilab.modules.gui.toolbar.ScilabToolBar;
+import org.scilab.modules.gui.toolbar.ToolBar;
+import org.scilab.modules.gui.menu.Menu;
+import org.scilab.modules.gui.menu.ScilabMenu;
+import org.scilab.modules.gui.menubar.MenuBar;
+import org.scilab.modules.gui.menubar.ScilabMenuBar;
+import org.scilab.modules.gui.tab.SimpleTab;
+import org.scilab.modules.gui.utils.ClosingOperationsManager;
+import org.scilab.modules.gui.utils.WindowsConfigurationManager;
+
+import org.scilab.modules.ui_data.utils.UiDataMessages;
+
+import java.util.List;
+import java.util.ListIterator;
+
+
+/**
+ * Main class to display a news feed in a tab Dockable panel (jflexdock) For
+ * now, manages one tab only
+ */
+public class NewsFeedTab extends SwingScilabDockablePanel implements SimpleTab {
+
+    public static final String NEWSFEED_UUID = "DC0957B3-81DA-4E39-B0B5-E93B35412162";
+    public static final String NEWSFEED_HELP_ID = "newsfeed";
+
+    private static NewsFeedTab instance = null;
+
+    private NewsFeedWidget newsFeedWidget;
+    private NewsFeedController newsFeedController;
+
+    public static NewsFeedTab getInstance() {
+        if (instance == null) {
+            instance = new NewsFeedTab();
+        }
+        return instance;
+    }
+
+    private NewsFeedTab() {
+        super(NewsFeedUIMessages.NEWS_FEED, NEWSFEED_UUID);
+
+        newsFeedController = new NewsFeedController();
+        newsFeedWidget = new NewsFeedWidget(newsFeedController);
+        newsFeedController.addNewsFeedEventListener(newsFeedWidget);
+
+        setContentPane(newsFeedWidget);
+
+        addMenuBar(createMenuBar());
+        addToolBar(createToolBar());
+
+        registerClosingOperation();
+        WindowsConfigurationManager.restorationFinished(this);
+
+        setAssociatedXMLIDForHelp(NEWSFEED_HELP_ID);
+
+        startNewsFeed();
+    }
+
+    public static void displayTab() {
+        if (instance == null) {
+            if (!WindowsConfigurationManager.restoreUUID(NEWSFEED_UUID)) {
+                NewsFeedTabFactory.getInstance().getTab(NEWSFEED_UUID);
+                instance.createTabWindow();
+            }
+        }
+        instance.setVisible(true);
+    }
+
+    public void startNewsFeed() {
+        newsFeedController.start();
+    }
+
+    public void updateNewsFeed() {
+        newsFeedController.updateNewsFeed();
+    }
+
+    public void closeTab() {
+        stopNewsFeed();
+        instance = null;
+    }
+
+    public void addInfoBar(TextBox infoBar) {
+        //setInfoBar(infoBarToAdd);
+    }
+
+    public void addToolBar(ToolBar toolBar) {
+        setToolBar(toolBar);
+    }
+
+    public void addMenuBar(MenuBar menuBar) {
+        setMenuBar(menuBar);
+    }
+
+    public SwingScilabWindow getParentWindow() {
+        return SwingScilabWindow.allScilabWindows.get(getParentWindowId());
+    }
+
+    public SimpleTab getAsSimpleTab() {
+        return this;
+    }
+
+    private MenuBar createMenuBar() {
+        MenuBar menuBar = ScilabMenuBar.createMenuBar();
+
+        Menu fileMenu = ScilabMenu.createMenu();
+        fileMenu.setText(UiDataMessages.FILE);
+        fileMenu.setMnemonic('F');
+        fileMenu.add(CloseAction.createMenuItem());
+        fileMenu.add(UpdateAction.createMenuItem());
+        menuBar.add(fileMenu);
+
+        Menu helpMenu = ScilabMenu.createMenu();
+        helpMenu.setText(NewsFeedUIMessages.NEWS_FEED_HELP_LABEL);
+        helpMenu.setMnemonic('?');
+        helpMenu.add(HelpAction.createMenuItem());
+        menuBar.add(helpMenu);
+
+        return menuBar;
+    }
+
+    private ToolBar createToolBar() {
+        ToolBar toolBar = ScilabToolBar.createToolBar();
+        SwingScilabToolBar swingScilabToolBar = (SwingScilabToolBar) toolBar.getAsSimpleToolBar();
+        swingScilabToolBar.add(UpdateAction.createPushButton());
+        swingScilabToolBar.addSeparator();
+        swingScilabToolBar.add(HelpAction.createPushButton());
+        return toolBar;
+    }
+
+    private SwingScilabWindow createTabWindow() {
+        SwingScilabWindow window = SwingScilabWindow.createWindow(true);
+        window.addTab(this);
+        window.setVisible(true);
+        return window;
+    }
+
+    private void registerClosingOperation() {
+        ClosingOperationsManager.registerClosingOperation(this, new ClosingOperationsManager.ClosingOperation() {
+
+            @Override
+            public int canClose() {
+                return 1;
+            }
+
+            @Override
+            public void destroy() {
+                closeTab();
+            }
+
+            @Override
+            public String askForClosing(final List<SwingScilabDockablePanel> list) {
+                return null;
+            }
+
+            @Override
+            public void updateDependencies(List<SwingScilabDockablePanel> list,
+                                           ListIterator<SwingScilabDockablePanel> it) {
+            }
+        });
+    }
+
+    private void stopNewsFeed() {
+        newsFeedController.stop();
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedTabFactory.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedTabFactory.java
new file mode 100644 (file)
index 0000000..628ab3e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel;
+import org.scilab.modules.gui.tabfactory.AbstractScilabTabFactory;
+import org.scilab.modules.gui.tabfactory.ScilabTabFactory;
+
+/**
+ * Factory to create news feed tabs For now, manages one tab only
+ */
+public class NewsFeedTabFactory extends AbstractScilabTabFactory {
+
+    public static final String APPLICATION = "NewsFeed";
+    public static final String PACKAGE = "";
+    public static final String CLASS = "org.scilab.modules.ui_data.newsfeed.NewsFeedTabFactory";
+
+    static {
+        ScilabTabFactory.getInstance().addTabFactory(NewsFeedTabFactory.getInstance());
+    }
+
+    private static NewsFeedTabFactory instance = null;
+
+    public NewsFeedTabFactory() {
+        if (instance == null) {
+            instance = this;
+        }
+    }
+
+    public SwingScilabDockablePanel getTab(String uuid) {
+        NewsFeedTab newsFeedTab = NewsFeedTab.getInstance();
+        ScilabTabFactory.getInstance().addToCache(newsFeedTab);
+        return newsFeedTab;
+    }
+
+    public String getPackage() {
+        return PACKAGE;
+    }
+
+    public String getClassName() {
+        return CLASS;
+    }
+
+    public String getApplication() {
+        return APPLICATION;
+    }
+
+
+    public boolean isAValidUUID(String uuid) {
+        return NewsFeedTab.NEWSFEED_UUID.equals(uuid);
+    }
+
+    public static NewsFeedTabFactory getInstance() {
+        if (instance == null) {
+            instance = new NewsFeedTabFactory();
+        }
+        return instance;
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedUIMessages.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedUIMessages.java
new file mode 100644 (file)
index 0000000..d15d9e5
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import org.scilab.modules.localization.Messages;
+
+/**
+ * Localized messages, menus labels, etc... used by news feed
+ */
+public class NewsFeedUIMessages {
+    public static final String NEWS_FEED = Messages.gettext("News feed");
+
+    public static final String NEWS_FEED_UNAVAILABLE_ERROR = Messages.gettext("News feed unavailable.");
+    public static final String NEWS_FEED_CONFIGURATION_ERROR = Messages.gettext("News feed configuration error.");
+
+    public static final String NEWS_FEED_HELP_LABEL = Messages.gettext("Help");
+    public static final String NEWS_FEED_UPDATE_LABEL = Messages.gettext("Update feed");
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedWidget.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFeedWidget.java
new file mode 100644 (file)
index 0000000..d2fa383
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import org.scilab.modules.commons.ScilabConstants;
+import org.scilab.modules.gui.utils.WebBrowser;
+
+import javax.swing.JPanel;
+import javax.swing.JEditorPane;
+import javax.swing.JScrollPane;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.Document;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+import javax.swing.text.Element;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.html.HTML;
+
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.io.File;
+import java.text.SimpleDateFormat;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * News feed widget Displays one news at a time.
+ * Controlled by NewsFeedController
+ * Displays news in HTML format (JEditorPane/HTMLEditorKit)
+ * Loads styles from CSS newsfeed.css (in directory ui_data/etc or SCIHOME)
+ */
+public class NewsFeedWidget extends JPanel implements NewsFeedEventListener, HyperlinkListener {
+    private static final String NAVIGATION_HTML_ID = "navigation";
+    private static final String PREVIOUS_HTML_ID = "previous";
+    private static final String NEXT_HTML_ID = "next";
+    private static final String NEWS_TITLE_HTML_ID = "news_title";
+    private static final String NEWS_DATE_HTML_ID = "news_date";
+    private static final String NEWS_LINK_HTML_ID = "news_link";
+    private static final String NEWS_DESCRIPTION_HTML_ID = "news_description";
+
+    private NewsFeedController newsFeedController;
+    private JEditorPane editorPane;
+    private JScrollPane scrollPane;
+
+    public NewsFeedWidget(NewsFeedController newsFeedController) {
+        this.newsFeedController = newsFeedController;
+
+        editorPane = new JEditorPane();
+        editorPane.setEditable(false);
+        editorPane.setContentType("text/html");
+
+        // use current look & feel font
+        editorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
+        Font font = UIManager.getFont("Label.font");
+        editorPane.setFont(font);
+
+        HTMLEditorKit htmlEditorKit = new HTMLEditorKit();
+        editorPane.setEditorKit(htmlEditorKit);
+        Document doc = htmlEditorKit.createDefaultDocument();
+        editorPane.setDocument(doc);
+
+        htmlEditorKit.getStyleSheet().importStyleSheet(getStyleSheetURL());
+
+        editorPane.addHyperlinkListener(this);
+
+        scrollPane = new JScrollPane(editorPane);
+        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+
+        setLayout(new BorderLayout());
+        add(scrollPane, BorderLayout.CENTER);
+    }
+
+    public void newsFeedEventReceived(NewsFeedEvent evt) {
+        switch (evt.getEventType()) {
+            case NewsFeedEvent.NEWS_CHANGED: {
+                displayNews(newsFeedController.getCurrentNews());
+                break;
+            }
+            case NewsFeedEvent.NEWSFEED_ERROR: {
+                displayError(((NewsFeedErrorEvent) evt).getErrorMessage());
+                break;
+            }
+        }
+    }
+
+    public void hyperlinkUpdate(HyperlinkEvent event) {
+        if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+            String name = null;
+            Element element = event.getSourceElement();
+            AttributeSet atts = element.getAttributes();
+            AttributeSet linkAtts = (AttributeSet)atts.getAttribute(HTML.Tag.A);
+            if (linkAtts != null) {
+                name = (String)linkAtts.getAttribute(HTML.Attribute.NAME);
+            }
+            if (name != null) {
+                if (name.equals("previous")) {
+                    newsFeedController.previousNews();
+                } else if (name.equals("next")) {
+                    newsFeedController.nextNews();
+                }
+            } else {
+                URL url = event.getURL();
+                if (url != null) {
+                    WebBrowser.openUrl(url, event.getDescription());
+                }
+            }
+        }
+    }
+
+    private void displayNews(News news) {
+        StringBuilder newsHtmlBuilder = new StringBuilder();
+
+        // Add navigation links
+        String previousLinkHtml = getSpanHtml(getLinkHtml("previous", "", "previous"), PREVIOUS_HTML_ID);
+        String nextLinkHtml = getSpanHtml(getLinkHtml("next", "", "next"), NEXT_HTML_ID);
+        newsHtmlBuilder.append(getDivHtml(String.format("%s %s", previousLinkHtml, nextLinkHtml), NAVIGATION_HTML_ID));
+
+        // Add news title & date
+        String newsTitleHtml = getSpanHtml(news.getTitle(), NEWS_TITLE_HTML_ID);
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE dd MMM yyyy HH:mm");
+        String dateStr = simpleDateFormat.format(news.getDate());
+        String newsDateHtml = getSpanHtml(dateStr, NEWS_DATE_HTML_ID);
+        newsHtmlBuilder.append(getDivHtml(String.format("%s - %s", newsTitleHtml, newsDateHtml)));
+
+        newsHtmlBuilder.append(getDivHtml(news.getDescription(), NEWS_DESCRIPTION_HTML_ID));
+
+        // Add news link if exist
+        if (news.getLink() != null) {
+            newsHtmlBuilder.append(getDivHtml(getLinkHtml(news.getLink(), news.getLink()), NEWS_LINK_HTML_ID));
+        }
+
+        display(getHTML(newsHtmlBuilder));
+    }
+
+    private String getLinkHtml(String name, String url, String description) {
+        return String.format("<a name='%s' href='%s'>%s</a>", name, url, description);
+    }
+
+    private String getLinkHtml(String url, String description) {
+        return String.format("<a href='%s'>%s</a>", url, description);
+    }
+
+    private String getSpanHtml(String spanContent, String spanId) {
+        return String.format("<span id='%s'>%s</span>", spanId, spanContent);
+    }
+
+    private String getDivHtml(String divContent, String divId) {
+        return String.format("<div id='%s'>%s</div>", divId, divContent);
+    }
+
+    private String getDivHtml(String divContent) {
+        return String.format("<div>%s</div>", divContent);
+    }
+
+    private void displayError(String errorMessage) {
+        StringBuilder errMsgHtmlBuilder = new StringBuilder(errorMessage);
+        display(getHTML(errMsgHtmlBuilder));
+    }
+
+    private String getHTML(StringBuilder htmlBuilder) {
+        htmlBuilder.insert(0, "<html><body>");
+        htmlBuilder.append("</body></html>");
+        return htmlBuilder.toString();
+    }
+
+    private void display(String htmlContent) {
+        editorPane.setText(htmlContent);
+        try    {
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    scrollPane.getHorizontalScrollBar().setValue(0);
+                    scrollPane.getVerticalScrollBar().setValue(0);
+                    repaint();
+                }
+            });
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static URL getStyleSheetURL() {
+        File settingsFile = new File(ScilabConstants.SCIHOME + "/newsfeed.css");
+        if (!settingsFile.exists()) {
+            settingsFile = new File(ScilabConstants.SCI + "/modules/ui_data/etc/newsfeed.css");
+        }
+        if (settingsFile.exists()) {
+            try {
+                return settingsFile.toURI().toURL();
+            } catch (MalformedURLException e) {
+                e.printStackTrace();
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFetcher.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/NewsFetcher.java
new file mode 100644 (file)
index 0000000..bb9382e
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+* Copyright (C) 2015 - Scilab Enterprises
+*
+* This file must be used under the terms of the CeCILL.
+* This source file is licensed as described in the file COPYING, which
+* you should have received as part of this distribution.  The terms
+* are also available at
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+*
+*/
+
+package org.scilab.modules.ui_data.newsfeed;
+
+import java.net.URL;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Fetches news through a RSS feed
+ * The RSS URL is configurable in the settings file
+ */
+public class NewsFetcher {
+    private URL rssURL = null;
+
+    public NewsFetcher() {
+    }
+
+    public void readSettings() throws Exception {
+        rssURL = null;
+        String urlSetting = NewsFeedSettings.getStringSetting("url");
+        rssURL = new URL(urlSetting);
+    }
+
+    public boolean isOK() {
+        return rssURL != null;
+    }
+
+    public List<News> fetchNews() throws Exception {
+        List<News> newsList = new ArrayList<News>();
+        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        Document doc = builder.parse(rssURL.openStream());
+        NodeList items = doc.getElementsByTagName("item");
+
+        SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
+
+        for (int i = 0; i < items.getLength(); i++) {
+            Element item = (Element) items.item(i);
+            String title = getItemValue(item, "title");
+            String dateStr = getItemValue(item, "pubDate");
+            Date date = formatter.parse(dateStr);
+            String description = getItemValue(item, "description");
+            String link = getItemValue(item, "link");
+            newsList.add(new News(title, date, description, link));
+        }
+        return newsList;
+    }
+
+    private String getItemValue(Element item, String nodeName) {
+        NodeList nodeList = item.getElementsByTagName(nodeName);
+        if (nodeList.getLength() > 0) {
+            return nodeList.item(0).getFirstChild().getNodeValue();
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/CloseAction.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/CloseAction.java
new file mode 100644 (file)
index 0000000..d9c5fad
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2015 - Scilab Enterprises
+ *
+ * This file must be used under the terms of the CeCILL.
+ * This source file is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at
+ * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+ *
+ */
+
+package org.scilab.modules.ui_data.newsfeed.actions;
+
+import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem;
+import org.scilab.modules.gui.events.callback.CommonCallBack;
+import org.scilab.modules.gui.menuitem.MenuItem;
+import org.scilab.modules.gui.menuitem.ScilabMenuItem;
+import org.scilab.modules.gui.utils.ClosingOperationsManager;
+
+import org.scilab.modules.ui_data.utils.UiDataMessages;
+import org.scilab.modules.ui_data.newsfeed.NewsFeedTab;
+
+import org.scilab.modules.commons.gui.ScilabKeyStroke;
+
+public class CloseAction extends CommonCallBack {
+
+    private static final String LABEL = UiDataMessages.CLOSE;
+    private static final String ICON = null;
+    private static final char MNEMONIC = 'F';
+    private static final String KEY = "OSSCKEY W";
+
+    public CloseAction() {
+        super("");
+    }
+
+    public static MenuItem createMenuItem() {
+        MenuItem menuItem = ScilabMenuItem.createMenuItem();
+        menuItem.setText(LABEL);
+        menuItem.setMnemonic(MNEMONIC);
+        menuItem.setCallback(getCallBack());
+        ((SwingScilabMenuItem) menuItem.getAsSimpleMenuItem()).setAccelerator(ScilabKeyStroke.getKeyStroke(KEY));
+        return menuItem;
+    }
+
+    public static CommonCallBack getCallBack() {
+        CommonCallBack callback = null;
+        try {
+            callback = CloseAction.class.getConstructor().newInstance();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return callback;
+    }
+
+    public void callBack() {
+        ClosingOperationsManager.startClosingOperation(NewsFeedTab.getInstance());
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/HelpAction.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/HelpAction.java
new file mode 100644 (file)
index 0000000..c71a898
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2015 - Scilab Enterprises
+ *
+ * This file must be used under the terms of the CeCILL.
+ * This source file is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at
+ * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+ *
+ */
+
+package org.scilab.modules.ui_data.newsfeed.actions;
+
+import org.scilab.modules.ui_data.utils.UiDataMessages;
+import org.scilab.modules.ui_data.newsfeed.NewsFeedUIMessages;
+import org.scilab.modules.ui_data.newsfeed.NewsFeedTab;
+
+import org.scilab.modules.commons.gui.FindIconHelper;
+import org.scilab.modules.commons.gui.ScilabKeyStroke;
+import org.scilab.modules.commons.gui.ScilabLAF;
+
+import org.scilab.modules.gui.bridge.CallScilabBridge;
+import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem;
+import org.scilab.modules.gui.events.callback.CommonCallBack;
+import org.scilab.modules.gui.menuitem.MenuItem;
+import org.scilab.modules.gui.menuitem.ScilabMenuItem;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+
+public class HelpAction extends CommonCallBack  {
+
+    private static final String LABEL = NewsFeedUIMessages.NEWS_FEED_HELP_LABEL;
+    private static final String ICON = FindIconHelper.findIcon("help-browser");
+    private static final char MNEMONIC = 'H';
+    private static final String KEY = "OSSCKEY F1";
+
+    public HelpAction() {
+        super("");
+    }
+
+    public static MenuItem createMenuItem() {
+        MenuItem menuItem = ScilabMenuItem.createMenuItem();
+        menuItem.setText(LABEL);
+        menuItem.setMnemonic(MNEMONIC);
+        menuItem.setCallback(getCallBack());
+        ((SwingScilabMenuItem) menuItem.getAsSimpleMenuItem()).setAccelerator(ScilabKeyStroke.getKeyStroke(KEY));
+        return menuItem;
+    }
+
+    public static JButton createPushButton() {
+        JButton pushButton = new JButton();
+        ScilabLAF.setDefaultProperties(pushButton);
+        pushButton.setIcon(new ImageIcon(ICON));
+        pushButton.setToolTipText(LABEL);
+        pushButton.addActionListener(getCallBack());
+        return pushButton;
+    }
+
+    public static CommonCallBack getCallBack() {
+        CommonCallBack callback = null;
+        try {
+            callback = HelpAction.class.getConstructor().newInstance();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return callback;
+    }
+
+    public void callBack() {
+        CallScilabBridge.openHelp(NewsFeedTab.NEWSFEED_HELP_ID);
+    }
+}
diff --git a/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/UpdateAction.java b/scilab/modules/ui_data/src/java/org/scilab/modules/ui_data/newsfeed/actions/UpdateAction.java
new file mode 100644 (file)
index 0000000..bec3313
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2015 - Scilab Enterprises
+ *
+ * This file must be used under the terms of the CeCILL.
+ * This source file is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at
+ * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
+ *
+ */
+
+package org.scilab.modules.ui_data.newsfeed.actions;
+
+import org.scilab.modules.ui_data.newsfeed.NewsFeedTab;
+import org.scilab.modules.ui_data.newsfeed.NewsFeedUIMessages;
+
+import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem;
+import org.scilab.modules.gui.events.callback.CommonCallBack;
+import org.scilab.modules.gui.menuitem.MenuItem;
+import org.scilab.modules.gui.menuitem.ScilabMenuItem;
+
+import org.scilab.modules.commons.gui.FindIconHelper;
+import org.scilab.modules.commons.gui.ScilabKeyStroke;
+import org.scilab.modules.commons.gui.ScilabLAF;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+
+public class UpdateAction extends CommonCallBack {
+
+    private static final String LABEL = NewsFeedUIMessages.NEWS_FEED_UPDATE_LABEL;
+    private static final String ICON = FindIconHelper.findIcon("view-refresh");
+    private static final char MNEMONIC = 'R';
+    private static final String KEY = "OSSCKEY R";
+
+
+    public UpdateAction() {
+        super("");
+    }
+
+    public static MenuItem createMenuItem() {
+        MenuItem menuItem = ScilabMenuItem.createMenuItem();
+        menuItem.setText(LABEL);
+        menuItem.setMnemonic(MNEMONIC);
+        menuItem.setCallback(getCallBack());
+        ((SwingScilabMenuItem) menuItem.getAsSimpleMenuItem()).setAccelerator(ScilabKeyStroke.getKeyStroke(KEY));
+        return menuItem;
+    }
+
+    public static JButton createPushButton() {
+        JButton pushButton = new JButton();
+        ScilabLAF.setDefaultProperties(pushButton);
+        pushButton.setIcon(new ImageIcon(ICON));
+        pushButton.setToolTipText(LABEL);
+        pushButton.addActionListener(getCallBack());
+        return pushButton;
+    }
+
+    public static CommonCallBack getCallBack() {
+        CommonCallBack callback = null;
+        try {
+            callback = UpdateAction.class.getConstructor().newInstance();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return callback;
+    }
+
+    public void callBack() {
+        NewsFeedTab.getInstance().updateNewsFeed();
+    }
+}