uidate: fix newsfeed images
[scilab.git] / scilab / modules / ui_data / src / java / org / scilab / modules / ui_data / newsfeed / NewsFeedWidget.java
1 /*\r
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab\r
3  * Copyright (C) 2015-2016 - Scilab Enterprises - Simon Marchetto\r
4  * Copyright (C) 2016 - Scilab Enterprises - Clement David\r
5  *\r
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises\r
7  *\r
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,\r
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.\r
10  * This file was originally licensed under the terms of the CeCILL v2.1,\r
11  * and continues to be available under such terms.\r
12  * For more information, see the COPYING file which you should have received\r
13  * along with this program.\r
14  *\r
15  */\r
16 \r
17 package org.scilab.modules.ui_data.newsfeed;\r
18 \r
19 import org.scilab.modules.commons.ScilabConstants;\r
20 import org.scilab.modules.commons.gui.FindIconHelper;\r
21 import org.scilab.modules.gui.utils.WebBrowser;\r
22 \r
23 import javax.swing.JPanel;\r
24 import javax.swing.JEditorPane;\r
25 import javax.swing.JScrollPane;\r
26 import javax.swing.text.html.HTMLEditorKit;\r
27 import javax.swing.text.Document;\r
28 import javax.swing.event.HyperlinkEvent;\r
29 import javax.swing.event.HyperlinkListener;\r
30 import javax.swing.SwingUtilities;\r
31 import javax.swing.UIManager;\r
32 \r
33 import java.awt.BorderLayout;\r
34 import java.awt.Font;\r
35 import java.awt.Point;\r
36 import java.awt.event.ActionEvent;\r
37 import java.io.File;\r
38 import java.text.SimpleDateFormat;\r
39 \r
40 import java.net.MalformedURLException;\r
41 import java.net.URL;\r
42 import java.util.logging.Level;\r
43 import java.util.logging.Logger;\r
44 import javax.swing.AbstractAction;\r
45 import javax.swing.Action;\r
46 import javax.swing.ImageIcon;\r
47 import javax.swing.JButton;\r
48 \r
49 /**\r
50  * News feed widget Displays one news at a time.\r
51  * Controlled by NewsFeedController\r
52  * Displays news in HTML format (JEditorPane/HTMLEditorKit)\r
53  * Loads styles from CSS newsfeed.css (in directory ui_data/etc or SCIHOME)\r
54  */\r
55 public class NewsFeedWidget extends JPanel implements NewsFeedEventListener, HyperlinkListener {\r
56     private static final String NEWS_DATE_HTML_ID = "news_date";\r
57     private static final String NEWS_CONTENT_HTML_ID = "news_content";\r
58     private static final String NEWS_LINK_HTML_ID = "news_link";\r
59     private static final String NEWS_MEDIA_CONTENT_HTML_ID = "news_media_content";\r
60     private static final String NEWS_DESCRIPTION_HTML_ID = "news_description";\r
61 \r
62     private final NewsFeedController newsFeedController;\r
63     private final JEditorPane editorPane;\r
64     private final JScrollPane scrollPane;\r
65     private final JPanel headerPane;\r
66     private final JButton headerButton;\r
67 \r
68     public NewsFeedWidget(NewsFeedController newsFeedController) {\r
69         this.newsFeedController = newsFeedController;\r
70 \r
71         editorPane = new JEditorPane();\r
72         editorPane.setEditable(false);\r
73         editorPane.setContentType("text/html");\r
74 \r
75         // use current look & feel font\r
76         editorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);\r
77         Font font = UIManager.getFont("Label.font");\r
78         editorPane.setFont(font);\r
79 \r
80         HTMLEditorKit htmlEditorKit = new HTMLEditorKit();\r
81         editorPane.setEditorKit(htmlEditorKit);\r
82         Document doc = htmlEditorKit.createDefaultDocument();\r
83         editorPane.setDocument(doc);\r
84 \r
85         htmlEditorKit.getStyleSheet().importStyleSheet(getStyleSheetURL());\r
86 \r
87         editorPane.addHyperlinkListener(this);\r
88 \r
89         headerButton = new JButton();\r
90         headerPane = new JPanel(new BorderLayout());\r
91         headerPane.add(new JButton(new AbstractAction(null, new ImageIcon(FindIconHelper.findIcon("go-previous"))) {\r
92             @Override\r
93             public void actionPerformed(ActionEvent e) {\r
94                 newsFeedController.previousNews();\r
95             }\r
96         }), BorderLayout.WEST);\r
97         headerPane.add(headerButton, BorderLayout.CENTER);\r
98         headerPane.add(new JButton(new AbstractAction(null, new ImageIcon(FindIconHelper.findIcon("go-next"))) {\r
99             @Override\r
100             public void actionPerformed(ActionEvent e) {\r
101                 newsFeedController.nextNews();\r
102             }\r
103         }), BorderLayout.EAST);\r
104 \r
105         scrollPane = new JScrollPane(editorPane);\r
106 \r
107         setLayout(new BorderLayout());\r
108         add(headerPane, BorderLayout.NORTH);\r
109         add(scrollPane, BorderLayout.CENTER);\r
110     }\r
111 \r
112     public void newsFeedEventReceived(NewsFeedEvent evt) {\r
113         switch (evt.getEventType()) {\r
114             case NewsFeedEvent.NEWS_CHANGED: {\r
115                 displayNews(newsFeedController.getCurrentNews());\r
116                 break;\r
117             }\r
118             case NewsFeedEvent.NEWSFEED_ERROR: {\r
119                 displayError(((NewsFeedErrorEvent) evt).getErrorMessage());\r
120                 break;\r
121             }\r
122         }\r
123     }\r
124 \r
125     public void hyperlinkUpdate(HyperlinkEvent event) {\r
126         if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {\r
127             URL url = event.getURL();\r
128             if (url != null) {\r
129                 WebBrowser.openUrl(url, event.getDescription());\r
130             }\r
131         }\r
132     }\r
133 \r
134     private void displayNews(News news) {\r
135         StringBuilder newsHtmlBuilder = new StringBuilder();\r
136 \r
137         if (news.getContent() != null) {\r
138             // if given, use RSS item content\r
139             newsHtmlBuilder.append(getDivHtml(news.getContent(), NEWS_CONTENT_HTML_ID));\r
140         } else {\r
141             // otherwise get content : date, description\r
142             SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE dd MMM yyyy HH:mm");\r
143             String dateStr = simpleDateFormat.format(news.getDate());\r
144             String newsDateHtml = getSpanHtml(dateStr, NEWS_DATE_HTML_ID);\r
145             newsHtmlBuilder.append(getDivHtml(newsDateHtml));\r
146             newsHtmlBuilder.append(getDivHtml(news.getDescription(), NEWS_DESCRIPTION_HTML_ID));\r
147         }\r
148 \r
149         // Add media content (image) if exist\r
150         NewsMediaContent mediaContent = news.getMediaContent();\r
151         if (mediaContent != null) {\r
152             newsHtmlBuilder.append(getDivHtml(getImageHtml(mediaContent.getURL(), mediaContent.getWidth(), mediaContent.getHeight()), NEWS_MEDIA_CONTENT_HTML_ID));\r
153         }\r
154 \r
155         // Add news link if exist\r
156         if (news.getLink() != null) {\r
157             newsHtmlBuilder.append(getDivHtml(getLinkHtml(news.getLink(), news.getLink()), NEWS_LINK_HTML_ID));\r
158         }\r
159 \r
160         display(new AbstractAction(news.getTitle()) {\r
161             @Override\r
162             public void actionPerformed(ActionEvent e) {\r
163                 try {\r
164                     WebBrowser.openUrl(new URL(news.getLink()), news.getLink());\r
165                 } catch (MalformedURLException ex) {\r
166                     Logger.getLogger(NewsFeedWidget.class.getName()).log(Level.SEVERE, null, ex);\r
167                 }\r
168             }\r
169         }, getHTML(newsHtmlBuilder));\r
170     }\r
171 \r
172     private String getImageHtml(String url, String width, String height) {\r
173         // Cannot setup border with CSS, limitation of CSS support of HTMLEditorKit\r
174         return String.format("<img src='%s' border='0' width='%s', height='%s'/>", url, width, height);\r
175     }\r
176 \r
177     private String getLinkHtml(String url, String description) {\r
178         return String.format("<a href='%s'>%s</a>", url, description);\r
179     }\r
180 \r
181     private String getSpanHtml(String spanContent, String spanId) {\r
182         return String.format("<span id='%s'>%s</span>", spanId, spanContent);\r
183     }\r
184 \r
185     private String getDivHtml(String divContent, String divId) {\r
186         return String.format("<div id='%s'>%s</div>", divId, divContent);\r
187     }\r
188 \r
189     private String getDivHtml(String divContent) {\r
190         return String.format("<div>%s</div>", divContent);\r
191     }\r
192 \r
193     private void displayError(String errorMessage) {\r
194         StringBuilder errMsgHtmlBuilder = new StringBuilder(errorMessage);\r
195         display(new AbstractAction() {\r
196             @Override\r
197             public void actionPerformed(ActionEvent e) {\r
198                 URL url = newsFeedController.getNewsFetcher().getURL();\r
199                 WebBrowser.openUrl(url, url.toString());\r
200             }\r
201         }, getHTML(errMsgHtmlBuilder));\r
202     }\r
203 \r
204     private String getHTML(StringBuilder htmlBuilder) {\r
205         htmlBuilder.insert(0, "<html><body>");\r
206         htmlBuilder.append("</body></html>");\r
207         return htmlBuilder.toString();\r
208     }\r
209 \r
210     private void display(final Action titleAction, final String htmlContent) {\r
211         try     {\r
212             SwingUtilities.invokeLater(new Runnable() {\r
213                 public void run() {\r
214                     headerButton.setAction(titleAction);\r
215                     headerButton.setToolTipText(titleAction.getValue(Action.NAME).toString());\r
216 \r
217                     editorPane.setText(htmlContent);\r
218                     // reset position to the upper left\r
219                     editorPane.setCaretPosition(0);\r
220                 }\r
221             });\r
222         } catch (Exception e) {\r
223             e.printStackTrace();\r
224         }\r
225     }\r
226 \r
227     private URL getStyleSheetURL() {\r
228         File settingsFile = new File(ScilabConstants.SCIHOME + "/newsfeed.css");\r
229         if (!settingsFile.exists()) {\r
230             settingsFile = new File(ScilabConstants.SCI + "/modules/ui_data/etc/newsfeed.css");\r
231         }\r
232         if (settingsFile.exists()) {\r
233             try {\r
234                 return settingsFile.toURI().toURL();\r
235             } catch (MalformedURLException e) {\r
236                 e.printStackTrace();\r
237                 return null;\r
238             }\r
239         } else {\r
240             return null;\r
241         }\r
242     }\r
243 }\r