Scilab news feed 87/17387/6
Simon Marchetto [Thu, 14 Jan 2016 15:47:45 +0000 (16:47 +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: I34d306655d153f29a6159af9951adb3ca396788d

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..a82b712
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+* 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;
+
+    private static final int NO_TIME_INTERVAL = -1;
+    private static final int ONE_SECOND = 1000;
+
+    // by default do not change news automatically
+    private Timer newsChangeTimer;
+    private int newsChangeTimeInterval = NO_TIME_INTERVAL;
+
+    // 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 != NO_TIME_INTERVAL) {
+            newsChangeTimer = new Timer(newsChangeTimeInterval, this);
+            newsChangeTimer.setRepeats(true);
+        } else {
+            newsChangeTimer = new Timer(ONE_SECOND, this);
+            newsChangeTimer.setRepeats(false);
+        }
+        newsChangeTimer.setInitialDelay(ONE_SECOND);
+
+        if (feedUpdateTimeInterval != NO_TIME_INTERVAL) {
+            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 != NO_TIME_INTERVAL) {
+                newsChangeTimeInterval *= ONE_SECOND;
+            }
+            feedUpdateTimeInterval = NewsFeedSettings.getIntSetting("feedUpdateTimeInterval");
+            if (feedUpdateTimeInterval != NO_TIME_INTERVAL) {
+                feedUpdateTimeInterval *= ONE_SECOND;
+            }
+        } 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..8b49d36
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab\r
+* Copyright (C) 2015 - Scilab Enterprises\r
+*\r
+* This file must be used under the terms of the CeCILL.\r
+* This source file is licensed as described in the file COPYING, which\r
+* you should have received as part of this distribution.  The terms\r
+* are also available at\r
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt\r
+*\r
+*/\r
+\r
+package org.scilab.modules.ui_data.newsfeed;\r
+\r
+import org.scilab.modules.commons.ScilabConstants;\r
+\r
+import java.io.File;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.NodeList;\r
+import org.w3c.dom.Node;\r
+\r
+/**\r
+ * Loads news feed settings like URL or update interval time\r
+ * Settings stored in newsfeed.xml (in directory ui_data/etc or SCIHOME)\r
+ */\r
+public class NewsFeedSettings {\r
+\r
+    public static String getStringSetting(String settingName) throws Exception {\r
+        File settingsFile = getSettingsFile();\r
+\r
+        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();\r
+        Document doc = builder.parse(settingsFile);\r
+        NodeList newsfeedNodes = doc.getElementsByTagName("newsfeed");\r
+        return getItemValue((Element) (newsfeedNodes.item(0)), settingName);\r
+    }\r
+\r
+    public static int getIntSetting(String settingName) throws Exception {\r
+        String strSetting = getStringSetting(settingName);\r
+        return Integer.parseInt(strSetting);\r
+    }\r
+\r
+    private static File getSettingsFile() {\r
+        File settingsFile = new File(ScilabConstants.SCIHOME + "/newsfeed.xml");\r
+        if (!settingsFile.exists()) {\r
+            settingsFile = new File(ScilabConstants.SCI + "/modules/ui_data/etc/newsfeed.xml");\r
+        }\r
+        if (settingsFile.exists()) {\r
+            return settingsFile;\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+\r
+    private static String getItemValue(Element item, String nodeName) {\r
+        NodeList nodeList = item.getElementsByTagName(nodeName);\r
+        if (nodeList.getLength() > 0) {\r
+            Node node = nodeList.item(0);\r
+            if (node.hasChildNodes()) {\r
+                return node.getFirstChild().getNodeValue();\r
+            } else {\r
+                return null;\r
+            }\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+\r
+}\r
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..6ea0bb9
--- /dev/null
@@ -0,0 +1,239 @@
+/*\r
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab\r
+* Copyright (C) 2015 - Scilab Enterprises\r
+*\r
+* This file must be used under the terms of the CeCILL.\r
+* This source file is licensed as described in the file COPYING, which\r
+* you should have received as part of this distribution.  The terms\r
+* are also available at\r
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt\r
+*\r
+*/\r
+\r
+package org.scilab.modules.ui_data.newsfeed;\r
+\r
+import org.scilab.modules.commons.ScilabConstants;\r
+import org.scilab.modules.commons.gui.FindIconHelper;\r
+import org.scilab.modules.gui.utils.WebBrowser;\r
+\r
+import javax.swing.JPanel;\r
+import javax.swing.JEditorPane;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.text.html.HTMLEditorKit;\r
+import javax.swing.text.Document;\r
+import javax.swing.event.HyperlinkEvent;\r
+import javax.swing.event.HyperlinkListener;\r
+import javax.swing.SwingUtilities;\r
+import javax.swing.UIManager;\r
+\r
+import javax.swing.text.Element;\r
+import javax.swing.text.AttributeSet;\r
+import javax.swing.text.html.HTML;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Font;\r
+import java.io.File;\r
+import java.text.SimpleDateFormat;\r
+\r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+\r
+/**\r
+ * News feed widget Displays one news at a time.\r
+ * Controlled by NewsFeedController\r
+ * Displays news in HTML format (JEditorPane/HTMLEditorKit)\r
+ * Loads styles from CSS newsfeed.css (in directory ui_data/etc or SCIHOME)\r
+ */\r
+public class NewsFeedWidget extends JPanel implements NewsFeedEventListener, HyperlinkListener {\r
+    private static final String NAVIGATION_HTML_ID = "navigation";\r
+    private static final String PREVIOUS_HTML_ID = "previous";\r
+    private static final String NEXT_HTML_ID = "next";\r
+    private static final String NEWS_TITLE_HTML_ID = "news_title";\r
+    private static final String NEWS_DATE_HTML_ID = "news_date";\r
+    private static final String NEWS_LINK_HTML_ID = "news_link";\r
+    private static final String NEWS_DESCRIPTION_HTML_ID = "news_description";\r
+\r
+    private NewsFeedController newsFeedController;\r
+    private JEditorPane editorPane;\r
+    private JScrollPane scrollPane;\r
+\r
+    public NewsFeedWidget(NewsFeedController newsFeedController) {\r
+        this.newsFeedController = newsFeedController;\r
+\r
+        editorPane = new JEditorPane();\r
+        editorPane.setEditable(false);\r
+        editorPane.setContentType("text/html");\r
+\r
+        // use current look & feel font\r
+        editorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);\r
+        Font font = UIManager.getFont("Label.font");\r
+        editorPane.setFont(font);\r
+\r
+        HTMLEditorKit htmlEditorKit = new HTMLEditorKit();\r
+        editorPane.setEditorKit(htmlEditorKit);\r
+        Document doc = htmlEditorKit.createDefaultDocument();\r
+        editorPane.setDocument(doc);\r
+\r
+        htmlEditorKit.getStyleSheet().importStyleSheet(getStyleSheetURL());\r
+\r
+        editorPane.addHyperlinkListener(this);\r
+\r
+        scrollPane = new JScrollPane(editorPane);\r
+        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);\r
+        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);\r
+\r
+        setLayout(new BorderLayout());\r
+        add(scrollPane, BorderLayout.CENTER);\r
+    }\r
+\r
+    public void newsFeedEventReceived(NewsFeedEvent evt) {\r
+        switch (evt.getEventType()) {\r
+            case NewsFeedEvent.NEWS_CHANGED: {\r
+                displayNews(newsFeedController.getCurrentNews());\r
+                break;\r
+            }\r
+            case NewsFeedEvent.NEWSFEED_ERROR: {\r
+                displayError(((NewsFeedErrorEvent) evt).getErrorMessage());\r
+                break;\r
+            }\r
+        }\r
+    }\r
+\r
+    public void hyperlinkUpdate(HyperlinkEvent event) {\r
+        if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {\r
+            String name = null;\r
+            Element element = event.getSourceElement();\r
+            AttributeSet atts = element.getAttributes();\r
+            AttributeSet linkAtts = (AttributeSet)atts.getAttribute(HTML.Tag.A);\r
+            if (linkAtts != null) {\r
+                name = (String)linkAtts.getAttribute(HTML.Attribute.NAME);\r
+            }\r
+            if (name != null) {\r
+                if (name.equals("previous")) {\r
+                    newsFeedController.previousNews();\r
+                } else if (name.equals("next")) {\r
+                    newsFeedController.nextNews();\r
+                }\r
+            } else {\r
+                URL url = event.getURL();\r
+                if (url != null) {\r
+                    WebBrowser.openUrl(url, event.getDescription());\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    private void displayNews(News news) {\r
+        StringBuilder newsHtmlBuilder = new StringBuilder();\r
+\r
+        // Add navigation links\r
+        // Previous news icon link\r
+        String previousIconUrl = getIconURL("go-previous");\r
+        String previousIconHtml = getImageHtml("previous", previousIconUrl);\r
+        String previousLinkHtml = getSpanHtml(getLinkHtml("previous", "previous", previousIconHtml), PREVIOUS_HTML_ID);\r
+        // Next news icon link\r
+        String nextIconUrl = getIconURL("go-next");\r
+        String nextIconHtml = getImageHtml("next", nextIconUrl);\r
+        String nextLinkHtml = getSpanHtml(getLinkHtml("next", "next", nextIconHtml), NEXT_HTML_ID);\r
+        newsHtmlBuilder.append(getDivHtml(String.format("%s %s", previousLinkHtml, nextLinkHtml), NAVIGATION_HTML_ID));\r
+\r
+        // Add news title & date\r
+        String newsTitleHtml = getSpanHtml(news.getTitle(), NEWS_TITLE_HTML_ID);\r
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE dd MMM yyyy HH:mm");\r
+        String dateStr = simpleDateFormat.format(news.getDate());\r
+        String newsDateHtml = getSpanHtml(dateStr, NEWS_DATE_HTML_ID);\r
+        newsHtmlBuilder.append(getDivHtml(String.format("%s - %s", newsTitleHtml, newsDateHtml)));\r
+\r
+        newsHtmlBuilder.append(getDivHtml(news.getDescription(), NEWS_DESCRIPTION_HTML_ID));\r
+\r
+        // Add news link if exist\r
+        if (news.getLink() != null) {\r
+            newsHtmlBuilder.append(getDivHtml(getLinkHtml(news.getLink(), news.getLink()), NEWS_LINK_HTML_ID));\r
+        }\r
+\r
+        display(getHTML(newsHtmlBuilder));\r
+        System.out.println(getHTML(newsHtmlBuilder));\r
+    }\r
+\r
+    private String getLinkHtml(String name, String url, String description) {\r
+        return String.format("<a name='%s' href='%s'>%s</a>", name, url, description);\r
+    }\r
+\r
+    private String getLinkHtml(String url, String description) {\r
+        return String.format("<a href='%s'>%s</a>", url, description);\r
+    }\r
+\r
+    private String getImageHtml(String name, String url) {\r
+        // Cannot setup margin and border with CSS, bugs of HTMLEditorKit ?\r
+        return String.format("<img name='%s' src='%s' hspace=2 border='0'/>", name, url);\r
+    }\r
+\r
+    private String getSpanHtml(String spanContent, String spanId) {\r
+        return String.format("<span id='%s'>%s</span>", spanId, spanContent);\r
+    }\r
+\r
+    private String getDivHtml(String divContent, String divId) {\r
+        return String.format("<div id='%s'>%s</div>", divId, divContent);\r
+    }\r
+\r
+    private String getDivHtml(String divContent) {\r
+        return String.format("<div>%s</div>", divContent);\r
+    }\r
+\r
+    private void displayError(String errorMessage) {\r
+        StringBuilder errMsgHtmlBuilder = new StringBuilder(errorMessage);\r
+        display(getHTML(errMsgHtmlBuilder));\r
+    }\r
+\r
+    private String getHTML(StringBuilder htmlBuilder) {\r
+        htmlBuilder.insert(0, "<html><body>");\r
+        htmlBuilder.append("</body></html>");\r
+        return htmlBuilder.toString();\r
+    }\r
+\r
+    private void display(String htmlContent) {\r
+        editorPane.setText(htmlContent);\r
+        try    {\r
+            SwingUtilities.invokeLater(new Runnable() {\r
+                public void run() {\r
+                    scrollPane.getHorizontalScrollBar().setValue(0);\r
+                    scrollPane.getVerticalScrollBar().setValue(0);\r
+                    repaint();\r
+                }\r
+            });\r
+        } catch (Exception e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+\r
+    private URL getStyleSheetURL() {\r
+        File settingsFile = new File(ScilabConstants.SCIHOME + "/newsfeed.css");\r
+        if (!settingsFile.exists()) {\r
+            settingsFile = new File(ScilabConstants.SCI + "/modules/ui_data/etc/newsfeed.css");\r
+        }\r
+        if (settingsFile.exists()) {\r
+            try {\r
+                return settingsFile.toURI().toURL();\r
+            } catch (MalformedURLException e) {\r
+                e.printStackTrace();\r
+                return null;\r
+            }\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+\r
+    private String getIconURL(String iconName) {\r
+        String iconFilePath = FindIconHelper.findIcon(iconName);\r
+        File iconFile = new File(iconFilePath);\r
+        if (iconFile.exists()) {\r
+            try {\r
+                return iconFile.toURI().toURL().toString();\r
+            } catch (MalformedURLException e) {\r
+                return null;\r
+            }\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+}\r
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..cc71688
--- /dev/null
@@ -0,0 +1,88 @@
+/*\r
+* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab\r
+* Copyright (C) 2015 - Scilab Enterprises\r
+*\r
+* This file must be used under the terms of the CeCILL.\r
+* This source file is licensed as described in the file COPYING, which\r
+* you should have received as part of this distribution.  The terms\r
+* are also available at\r
+* http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt\r
+*\r
+*/\r
+\r
+package org.scilab.modules.ui_data.newsfeed;\r
+\r
+import java.net.URL;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.NodeList;\r
+import org.w3c.dom.Node;\r
+\r
+import java.util.Date;\r
+import java.text.SimpleDateFormat;\r
+import java.util.Locale;\r
+\r
+import java.util.List;\r
+import java.util.ArrayList;\r
+\r
+/**\r
+ * Fetches news through a RSS feed\r
+ * The RSS URL is configurable in the settings file\r
+ */\r
+public class NewsFetcher {\r
+    private URL rssURL = null;\r
+\r
+    public NewsFetcher() {\r
+    }\r
+\r
+    public void readSettings() throws Exception {\r
+        rssURL = null;\r
+        String urlSetting = NewsFeedSettings.getStringSetting("url");\r
+        rssURL = new URL(urlSetting);\r
+    }\r
+\r
+    public boolean isOK() {\r
+        return rssURL != null;\r
+    }\r
+\r
+    public List<News> fetchNews() throws Exception {\r
+        List<News> newsList = new ArrayList<News>();\r
+        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();\r
+        Document doc = builder.parse(rssURL.openStream());\r
+\r
+        NodeList items = doc.getElementsByTagName("item");\r
+        if ((items == null) || (items.getLength() == 0)) {\r
+            throw new Exception("The fetched document has no 'item' element, please check it is a RSS feed.");\r
+        }\r
+\r
+        SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);\r
+\r
+        for (int i = 0; i < items.getLength(); i++) {\r
+            Element item = (Element) items.item(i);\r
+            String title = getItemValue(item, "title");\r
+            String dateStr = getItemValue(item, "pubDate");\r
+            Date date = formatter.parse(dateStr);\r
+            String description = getItemValue(item, "description");\r
+            String link = getItemValue(item, "link");\r
+            newsList.add(new News(title, date, description, link));\r
+        }\r
+        return newsList;\r
+    }\r
+\r
+    private String getItemValue(Element item, String nodeName) {\r
+        NodeList nodeList = item.getElementsByTagName(nodeName);\r
+        if (nodeList.getLength() > 0) {\r
+            Node node = nodeList.item(0);\r
+            if (node.hasChildNodes()) {\r
+                return node.getFirstChild().getNodeValue();\r
+            } else {\r
+                return null;\r
+            }\r
+        } else {\r
+            return null;\r
+        }\r
+    }\r
+}\r
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();
+    }
+}