From 8c85e7351c3b67d2f64694a2c68c94939c414d66 Mon Sep 17 00:00:00 2001 From: bancika Date: Wed, 26 Oct 2016 18:04:52 +0200 Subject: [PATCH] add announcements --- .../org/diylc/announcements/Announcement.java | 73 ++++++++++++++ .../announcements/AnnouncementProvider.java | 64 +++++++++++++ .../announcements/IAnnouncementService.java | 8 ++ .../cloud/presenter/CloudPresenter.java | 3 +- .../src/org/diylc/images/IconLoader.java | 2 +- .../src/org/diylc/images/megaphone.png | Bin 0 -> 854 bytes .../view/browser/ResultsScrollPanel.java | 18 +++- .../swing/plugins/statusbar/StatusBar.java | 90 +++++++++++++++++- 8 files changed, 249 insertions(+), 9 deletions(-) create mode 100644 diylc/diylc-core/src/org/diylc/announcements/Announcement.java create mode 100644 diylc/diylc-core/src/org/diylc/announcements/AnnouncementProvider.java create mode 100644 diylc/diylc-core/src/org/diylc/announcements/IAnnouncementService.java create mode 100644 diylc/diylc-swing/src/org/diylc/images/megaphone.png diff --git a/diylc/diylc-core/src/org/diylc/announcements/Announcement.java b/diylc/diylc-core/src/org/diylc/announcements/Announcement.java new file mode 100644 index 00000000..2e9d9793 --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/announcements/Announcement.java @@ -0,0 +1,73 @@ +package org.diylc.announcements; + +import java.io.Serializable; + +public class Announcement implements Serializable { + + private static final long serialVersionUID = 1L; + + private String title; + private String text; + private String date; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((date == null) ? 0 : date.hashCode()); + result = prime * result + ((text == null) ? 0 : text.hashCode()); + result = prime * result + ((title == null) ? 0 : title.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Announcement other = (Announcement) obj; + if (date == null) { + if (other.date != null) + return false; + } else if (!date.equals(other.date)) + return false; + if (text == null) { + if (other.text != null) + return false; + } else if (!text.equals(other.text)) + return false; + if (title == null) { + if (other.title != null) + return false; + } else if (!title.equals(other.title)) + return false; + return true; + } +} diff --git a/diylc/diylc-core/src/org/diylc/announcements/AnnouncementProvider.java b/diylc/diylc-core/src/org/diylc/announcements/AnnouncementProvider.java new file mode 100644 index 00000000..7d680d98 --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/announcements/AnnouncementProvider.java @@ -0,0 +1,64 @@ +package org.diylc.announcements; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import org.diylc.appframework.miscutils.ConfigurationManager; +import org.diylc.plugins.cloud.model.IServiceAPI; + +import com.diyfever.httpproxy.PhpFlatProxy; +import com.diyfever.httpproxy.ProxyFactory; + +public class AnnouncementProvider { + + private String serviceUrl = "http://www.diy-fever.com/diylc/api/v1/announcements.html"; + private String LAST_READ_KEY = "announcement.lastReadDate"; + + private IAnnouncementService service; + + private Date lastDate; + private List announcements; + + private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + public AnnouncementProvider() { + String lastDateStr = ConfigurationManager.getInstance().readString(LAST_READ_KEY, null); + try { + this.lastDate = lastDateStr == null ? null : dateFormat.parse(lastDateStr); + } catch (ParseException e) { + } + serviceUrl = + ConfigurationManager.getInstance().readString(IServiceAPI.URL_KEY, "http://www.diy-fever.com/diylc/api/v1"); + ProxyFactory factory = new ProxyFactory(new PhpFlatProxy()); + service = factory.createProxy(IAnnouncementService.class, serviceUrl); + } + + public String getCurrentAnnouncements() throws ParseException { + announcements = service.getAnnouncements(); + boolean hasUnread = false; + StringBuilder sb = new StringBuilder(""); + for (int i = 0; i < announcements.size(); i++) { + Date date = dateFormat.parse(announcements.get(i).getDate()); + if (lastDate == null || lastDate.before(date)) { + sb.append("").append(announcements.get(i).getTitle()).append(" on ") + .append(announcements.get(i).getDate()).append("").append("

") + .append(announcements.get(i).getText()).append("

"); + hasUnread = true; + } + } + if (!hasUnread) + return ""; + sb.append("
Click OK to dismiss and mark these announcements as read."); + sb.append(""); + return sb.toString(); + } + + public void dismissed() { + Date date = new Date(); + ConfigurationManager.getInstance().writeValue(LAST_READ_KEY, dateFormat.format(date)); + } +} diff --git a/diylc/diylc-core/src/org/diylc/announcements/IAnnouncementService.java b/diylc/diylc-core/src/org/diylc/announcements/IAnnouncementService.java new file mode 100644 index 00000000..4ee2795f --- /dev/null +++ b/diylc/diylc-core/src/org/diylc/announcements/IAnnouncementService.java @@ -0,0 +1,8 @@ +package org.diylc.announcements; + +import java.util.List; + +public interface IAnnouncementService { + + public List getAnnouncements(); +} diff --git a/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java b/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java index a31b1c10..087ccf00 100644 --- a/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java +++ b/diylc/diylc-core/src/org/diylc/plugins/cloud/presenter/CloudPresenter.java @@ -224,7 +224,7 @@ public class CloudPresenter { if (res instanceof List) { @SuppressWarnings("unchecked") List projects = (List) res; - LOG.info("Received " + projects.size() + " results"); + LOG.info("Received " + projects.size() + " results. Downloading thumbnails..."); // Download thumbnails and replace urls with local paths to speed up loading in the main thread for (int i = 0; i < projects.size(); i++) { String url = projects.get(i).getThumbnailUrl(); @@ -236,6 +236,7 @@ public class CloudPresenter { projects.get(i).setThumbnailUrl(temp.getAbsolutePath()); fos.close(); } + LOG.info("Finished downloading thumbnails."); return projects; } throw new CloudException("Unexpected server response received for search results: " + res.getClass().getName()); diff --git a/diylc/diylc-swing/src/org/diylc/images/IconLoader.java b/diylc/diylc-swing/src/org/diylc/images/IconLoader.java index 3337a053..0a0ec1d1 100644 --- a/diylc/diylc-swing/src/org/diylc/images/IconLoader.java +++ b/diylc/diylc-swing/src/org/diylc/images/IconLoader.java @@ -34,7 +34,7 @@ public enum IconLoader { "id_card_edit.png"), KeyEdit("key_edit.png"), Find("find.png"), Dashboard("dashboard.png"), DataFind( "data_find.png"), CloudDownload("cloud-download.png"), NavLeftBlue("nav_left_blue.png"), NavRightBlue( "nav_right_blue.png"), MissingImage("missing_image.png"), CloudBg("cloud_bg.png"), CloudBig("cloud_big.png"), CloudWait( - "cloud_wait.png"), Spinning("spinning.gif"); + "cloud_wait.png"), Spinning("spinning.gif"), Megaphone("megaphone.png"); protected String name; diff --git a/diylc/diylc-swing/src/org/diylc/images/megaphone.png b/diylc/diylc-swing/src/org/diylc/images/megaphone.png new file mode 100644 index 0000000000000000000000000000000000000000..e712c9cfb01d48ebbf4e98bbe424d9e87514243e GIT binary patch literal 854 zcmV-c1F8IpP)WdKBPATc!{O<`#uGB7YRATc;PFf%$ZG$1Q5F)%Q<;O7vOH*MO$DjA?>{r{+ZFGjiA_>wUh9n`oHerb5A7Gbu71~Wom%H%Zi}0eW zQP_owV#Pp^E+S1GQLRMUXr5Nn>GABBo7>Jg+k1N6wZgKX9{9j}-uHdJ@AK;r_;(|} zed~YPJY~bf!`FO1-)%tK=v!G?d5Ho!9(Fd@=I`I^=@Ja5!qCySqHm$y+eTWPPB59wh>3J` zbadkJCFC{lvBA|YfkL&SHmX7h0gmGu0tUSX^V=F3xa@>hyA3##1uPZ|*zI;B9=j1U zckq5|PL}gfu9QL3G*A=;DwPUossfUnBM*{oWZd1E7a?C_7)T2xU`1mEK7dN-TdQo?*N@C%aS{kGg2t@aI#b? zWie$CMG>miDn?WV!Cr^xqyQhrTS3w4K&jp+;>N~C9G#Dm8cSA1L~Pe9kH^z^VPRnb zBuRqfiUR3u2{J_$1(k+yCX<2X<>e&$NJy1y7F=CJGa8Lx!#vaJ^#1JZ?B`mo1{j%M zC=^&bSz7wy;-ZLi!3JoDMZy2*7#8LT!($bO?(S}3Y;5cirqnk$IM|LkvyK7^DZyZH z4c8+2d}0DWo9}kJ<@NP-=j!UJ91e%y#9}ci8jU`ql$x;b7ZQm?YIJloEX(pfUVnka zSPCcq1=g1HNDtyd*u`z6rMY(wDYD@~-XU4miIW0sZ9*JPF_veE%@fj!oMBaGV!Z literal 0 HcmV?d00001 diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java index d31c48b3..16f944b8 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/browser/ResultsScrollPanel.java @@ -6,6 +6,8 @@ import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; @@ -28,7 +30,9 @@ import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import javax.swing.text.DefaultCaret; import org.apache.log4j.Logger; import org.diylc.common.IPlugInPort; @@ -139,11 +143,21 @@ public class ResultsScrollPanel extends JScrollPane { JLabel thumbnailLabel = new JLabel(loadImage(project.getThumbnailUrl())); JLabel nameLabel = new JLabel("" + project.getName() + ""); nameLabel.setFont(nameLabel.getFont().deriveFont(12f)); + + // JLabel descriptionArea = new JLabel("

" + project.getDescription() + + // "

"); JTextArea descriptionArea = new JTextArea(project.getDescription().replace("
", "\n")); descriptionArea.setEditable(false); descriptionArea.setFont(thumbnailLabel.getFont()); descriptionArea.setLineWrap(true); descriptionArea.setWrapStyleWord(true); + descriptionArea.setFocusable(false); + descriptionArea.setRequestFocusEnabled(false); + DefaultCaret caret = (DefaultCaret) descriptionArea.getCaret(); + caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); + descriptionArea.setEnabled(false); + // descriptionArea.setDisabledTextColor(descriptionArea.getSelectionColor()); + JLabel categoryLabel = new JLabel("Category: " + project.getCategory() + ""); JLabel authorLabel = new JLabel("Author: " + project.getOwner() + ""); JLabel updatedLabel = new JLabel("Last updated: " + project.getUpdated() + ""); @@ -271,9 +285,7 @@ public class ResultsScrollPanel extends JScrollPane { gbc.insets = new Insets(2, 2, 2, 2); getResultsPanel().add(new JSeparator(), gbc); - getResultsPanel().invalidate(); - - return thumbnailLabel; + return nameLabel; } private JLabel getLoadMoreLabel() { diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/statusbar/StatusBar.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/statusbar/StatusBar.java index b8e4bba2..3c9bd3e4 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/statusbar/StatusBar.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/statusbar/StatusBar.java @@ -1,14 +1,17 @@ package org.diylc.swing.plugins.statusbar; import java.awt.BorderLayout; +import java.awt.Cursor; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.Insets; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Point2D; +import java.io.IOException; import java.text.DecimalFormat; import java.text.Format; import java.util.ArrayList; @@ -27,6 +30,8 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; import org.apache.log4j.Logger; +import org.diylc.announcements.Announcement; +import org.diylc.announcements.AnnouncementProvider; import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.appframework.miscutils.Utils; import org.diylc.common.BadPositionException; @@ -34,7 +39,9 @@ import org.diylc.common.ComponentType; import org.diylc.common.EventType; import org.diylc.common.IPlugIn; import org.diylc.common.IPlugInPort; +import org.diylc.common.ITask; import org.diylc.core.IDIYComponent; +import org.diylc.core.IView; import org.diylc.images.IconLoader; import org.diylc.presenter.Presenter; import org.diylc.swing.ISwingUI; @@ -53,11 +60,13 @@ public class StatusBar extends JPanel implements IPlugIn { private JComboBox zoomBox; private UpdateLabel updateLabel; + private JLabel announcementLabel; private MemoryBar memoryPanel; private JLabel statusLabel; private JLabel sizeLabel; private IPlugInPort plugInPort; + private ISwingUI swingUI; // State variables private ComponentType componentSlot; @@ -67,8 +76,13 @@ public class StatusBar extends JPanel implements IPlugIn { private List stuckComponentNames; private String statusMessage; + private AnnouncementProvider announcementProvider; + public StatusBar(ISwingUI swingUI) { super(); + this.swingUI = swingUI; + + this.announcementProvider = new AnnouncementProvider(); setLayout(new GridBagLayout()); @@ -77,6 +91,29 @@ public class StatusBar extends JPanel implements IPlugIn { } catch (BadPositionException e) { LOG.error("Could not install status bar", e); } + + swingUI.executeBackgroundTask(new ITask() { + + @Override + public String doInBackground() throws Exception { + Thread.sleep(1000); + return announcementProvider.getCurrentAnnouncements(); + } + + @Override + public void failed(Exception e) { + LOG.error("Error while fetching announcements", e); + } + + @Override + public void complete(String result) { + if (result != null && result.length() > 0) { + StatusBar.this.swingUI.showMessage(result, "Public Announcements", IView.INFORMATION_MESSAGE); + announcementProvider.dismissed(); + } + } + + }); } private JComboBox getZoomBox() { @@ -107,6 +144,45 @@ public class StatusBar extends JPanel implements IPlugIn { return updateLabel; } + public JLabel getAnnouncementLabel() { + if (announcementLabel == null) { + announcementLabel = new JLabel(IconLoader.Megaphone.getIcon()); + announcementLabel.setToolTipText("Check for public announcements"); + announcementLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + announcementLabel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + swingUI.executeBackgroundTask(new ITask() { + + @Override + public String doInBackground() throws Exception { + return announcementProvider.getCurrentAnnouncements(); + } + + @Override + public void failed(Exception e) { + LOG.error("Error while fetching announcements", e); + swingUI.showMessage("Could not fetch public announcements.", "Error", IView.ERROR_MESSAGE); + } + + @Override + public void complete(String result) { + if (result != null && result.length() > 0) { + swingUI.showMessage(result, "Public Announcements", IView.INFORMATION_MESSAGE); + announcementProvider.dismissed(); + } else + swingUI.showMessage("No new public announcements available.", "Public Announcements", + IView.INFORMATION_MESSAGE); + } + + }); + } + }); + } + return announcementLabel; + } + private MemoryBar getMemoryPanel() { if (memoryPanel == null) { memoryPanel = new MemoryBar(false); @@ -165,19 +241,25 @@ public class StatusBar extends JPanel implements IPlugIn { // 4))); zoomPanel.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4)); - gbc.gridx = 1; + gbc.gridx++; gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 0; add(zoomPanel, gbc); - gbc.gridx = 2; + gbc.gridx++; + gbc.insets = new Insets(0, 2, 0, 2); add(getSizeLabel(), gbc); - gbc.gridx = 3; + gbc.gridx++; + add(getAnnouncementLabel(), gbc); + + gbc.gridx++; + gbc.insets = new Insets(0, 0, 0, 0); add(getUpdateLabel(), gbc); - gbc.gridx = 4; + gbc.gridx++; gbc.fill = GridBagConstraints.NONE; + gbc.insets = new Insets(0, 0, 0, 4); add(getMemoryPanel(), gbc); gbc.gridx = 5;