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 a0bb772d..2ce4af25 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 @@ -2,9 +2,13 @@ package org.diylc.plugins.cloud.presenter; import java.awt.Image; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.net.InetAddress; import java.net.NetworkInterface; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; import java.util.List; import org.apache.log4j.Logger; @@ -212,12 +216,25 @@ public class CloudPresenter { LOG.info(String.format("search(%1$s,%2$s,%3$s,%4$d,%5$d)", criteria, category, sortOrder, pageNumber, itemsPerPage)); try { Object res = service.search(criteria, category, "json", pageNumber, itemsPerPage, sortOrder); + // Thread.sleep(2000); if (res == null) throw new CloudException("Failed to retreive search results."); if (res instanceof String) throw new CloudException(res.toString()); - if (res instanceof List) - return (List) res; + if (res instanceof List) { + List projects = (List) res; + // Download thumbnails and replace urls with local paths + for (int i = 0; i < projects.size(); i++) { + String url = projects.get(i).getThumbnailUrl(); + URL website = new URL(url); + ReadableByteChannel rbc = Channels.newChannel(website.openStream()); + File temp = File.createTempFile("thumbnail", ".png"); + FileOutputStream fos = new FileOutputStream(temp); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + projects.get(i).setThumbnailUrl(temp.getAbsolutePath()); + } + return projects; + } throw new CloudException("Unexpected server response received for search results: " + res.getClass().getName()); } catch (Exception e) { throw new CloudException(e); diff --git a/diylc/diylc-swing/src/org/diylc/images/IconLoader.java b/diylc/diylc-swing/src/org/diylc/images/IconLoader.java index 669756c9..a7a55879 100644 --- a/diylc/diylc-swing/src/org/diylc/images/IconLoader.java +++ b/diylc/diylc-swing/src/org/diylc/images/IconLoader.java @@ -33,7 +33,7 @@ public enum IconLoader { "arrow.png"), Cloud("cloud.png"), CloudUp("cloud_up.png"), CloudGear("cloud_gear.png"), IdCardEdit( "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"); + "nav_right_blue.png"), MissingImage("missing_image.png"), CloudBg("cloud_bg.png"); protected String name; diff --git a/diylc/diylc-swing/src/org/diylc/images/cloud_bg.png b/diylc/diylc-swing/src/org/diylc/images/cloud_bg.png new file mode 100644 index 00000000..43d0a040 Binary files /dev/null and b/diylc/diylc-swing/src/org/diylc/images/cloud_bg.png differ diff --git a/diylc/diylc-swing/src/org/diylc/images/missing_image.png b/diylc/diylc-swing/src/org/diylc/images/missing_image.png new file mode 100644 index 00000000..6f3e2a8a Binary files /dev/null and b/diylc/diylc-swing/src/org/diylc/images/missing_image.png differ diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CloudBrowserFrame.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CloudBrowserFrame.java index b8d5b2ae..d4e12165 100644 --- a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CloudBrowserFrame.java +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CloudBrowserFrame.java @@ -5,13 +5,12 @@ import java.awt.Cursor; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; -import java.awt.Image; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; -import java.io.IOException; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; @@ -28,11 +27,13 @@ import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JRootPane; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -46,7 +47,6 @@ import org.diylc.plugins.cloud.model.ProjectEntity; import org.diylc.plugins.cloud.presenter.CloudException; import org.diylc.plugins.cloud.presenter.CloudPresenter; import org.diylc.swing.ISwingUI; -import org.diylc.swing.gui.CustomGlassPane; import org.diylc.swing.gui.DialogFactory; import org.diylc.swing.plugins.file.FileFilterEnum; @@ -73,6 +73,12 @@ public class CloudBrowserFrame extends JFrame { private IPlugInPort plugInPort; private CloudPresenter cloudPresenter; + private JPanel navigationPanel; + private JButton prevPageButton; + private JButton nextPageButton; + private JLabel pageLabel; + private List currentResults; + // search criteria private String searchFor; private String category; @@ -90,7 +96,10 @@ public class CloudBrowserFrame extends JFrame { setContentPane(getMainPanel()); this.pack(); this.setLocationRelativeTo(owner); - this.setGlassPane(new CustomGlassPane()); + this.setGlassPane(new CloudGlassPane()); + + JRootPane rootPane = SwingUtilities.getRootPane(getGoButton()); + rootPane.setDefaultButton(getGoButton()); } public JPanel getMainPanel() { @@ -155,6 +164,15 @@ public class CloudBrowserFrame extends JFrame { gbc.weighty = 1; gbc.fill = GridBagConstraints.BOTH; browsePanel.add(getResultsScrollPane(), gbc); + + gbc.anchor = GridBagConstraints.NORTHWEST; + gbc.insets = new Insets(2, 2, 2, 2); + gbc.gridx = 0; + gbc.gridy++; + gbc.fill = GridBagConstraints.BOTH; + gbc.weighty = 0; + gbc.gridwidth = 3; + browsePanel.add(getNavigationPanel(), gbc); } return browsePanel; } @@ -253,7 +271,7 @@ public class CloudBrowserFrame extends JFrame { @Override public void actionPerformed(ActionEvent e) { - CloudBrowserFrame.this.pageNumber = 1; + setPageNumber(1); CloudBrowserFrame.this.searchFor = getSearchField().getText(); CloudBrowserFrame.this.category = getCategoryBox().getSelectedItem() == null ? "" : getCategoryBox().getSelectedItem().toString(); @@ -283,6 +301,7 @@ public class CloudBrowserFrame extends JFrame { @Override public void complete(List result) { + CloudBrowserFrame.this.currentResults = result; getResultsPanel().removeAll(); int count = 0; for (Iterator i = result.iterator(); i.hasNext();) { @@ -293,7 +312,7 @@ public class CloudBrowserFrame extends JFrame { showNoMatches(); count++; } - addNavigationPanel(count); + // addNavigationPanel(count); } }); } @@ -443,65 +462,100 @@ public class CloudBrowserFrame extends JFrame { getResultsPanel().add(new JSeparator(), gbc); } - private void addNavigationPanel(int location) { - JPanel navigationPanel = new JPanel(new GridBagLayout()); - navigationPanel.setBackground(Color.white); + private JPanel getNavigationPanel() { + if (navigationPanel == null) { + navigationPanel = new JPanel(new GridBagLayout()); + navigationPanel.setBackground(Color.white); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.SOUTHWEST; + gbc.insets = new Insets(2, 2, 2, 2); + gbc.gridx = 0; + gbc.weightx = 0; + gbc.fill = GridBagConstraints.NONE; + navigationPanel.add(getPrevPageButton(), gbc); - JButton prevPageButton = new JButton(IconLoader.NavLeftBlue.getIcon()); - prevPageButton.setBorderPainted(false); - prevPageButton.setContentAreaFilled(false); - prevPageButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - prevPageButton.addActionListener(new ActionListener() { + gbc.gridx++; + gbc.weightx = 1; + gbc.anchor = GridBagConstraints.LINE_START; + gbc.fill = GridBagConstraints.HORIZONTAL; + navigationPanel.add(getPageLabel(), gbc); - @Override - public void actionPerformed(ActionEvent e) { - if (CloudBrowserFrame.this.pageNumber > 1) { - CloudBrowserFrame.this.pageNumber--; - CloudBrowserFrame.this.search(); - } - } - }); + gbc.gridx++; + gbc.weightx = 0; + gbc.anchor = GridBagConstraints.SOUTHWEST; + gbc.fill = GridBagConstraints.NONE; + navigationPanel.add(getNextPageButton(), gbc); - JButton nextPageButton = new JButton(IconLoader.NavRightBlue.getIcon()); - nextPageButton.setBorderPainted(false); - nextPageButton.setContentAreaFilled(false); - nextPageButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - nextPageButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - CloudBrowserFrame.this.pageNumber++; - CloudBrowserFrame.this.search(); - } - }); - - GridBagConstraints gbc = new GridBagConstraints(); - gbc.anchor = GridBagConstraints.SOUTHWEST; - gbc.insets = new Insets(2, 2, 2, 2); - gbc.gridx = 0; - gbc.weightx = 0; - gbc.fill = GridBagConstraints.NONE; - navigationPanel.add(prevPageButton, gbc); - - gbc.gridx++; - gbc.weightx = 1; - navigationPanel.add(new JLabel(), gbc); - - gbc.gridx++; - gbc.weightx = 0; - navigationPanel.add(nextPageButton, gbc); - - gbc = new GridBagConstraints(); - gbc.anchor = GridBagConstraints.NORTHWEST; - gbc.insets = new Insets(2, 2, 2, 2); - gbc.gridx = 0; - gbc.gridy = location * 6; - gbc.fill = GridBagConstraints.BOTH; - gbc.weighty = 100; - gbc.gridwidth = 3; - getResultsPanel().add(navigationPanel, gbc); + } + return navigationPanel; } + private JButton getPrevPageButton() { + if (prevPageButton == null) { + prevPageButton = new JButton(IconLoader.NavLeftBlue.getIcon()); + prevPageButton.setBorderPainted(false); + prevPageButton.setContentAreaFilled(false); + prevPageButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + prevPageButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (CloudBrowserFrame.this.pageNumber > 1) { + setPageNumber(CloudBrowserFrame.this.pageNumber - 1); + CloudBrowserFrame.this.search(); + } + } + }); + } + return prevPageButton; + } + + private JButton getNextPageButton() { + if (nextPageButton == null) { + nextPageButton = new JButton(IconLoader.NavRightBlue.getIcon()); + nextPageButton.setBorderPainted(false); + nextPageButton.setContentAreaFilled(false); + nextPageButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + nextPageButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (CloudBrowserFrame.this.currentResults != null && !CloudBrowserFrame.this.currentResults.isEmpty()) { + setPageNumber(CloudBrowserFrame.this.pageNumber + 1); + CloudBrowserFrame.this.search(); + } + } + }); + } + return nextPageButton; + } + + private void setPageNumber(int pageNumber) { + this.pageNumber = pageNumber; + getPageLabel().setText("Page " + pageNumber); + } + + private JLabel getPageLabel() { + if (pageLabel == null) { + pageLabel = new JLabel(); + pageLabel.setFont(pageLabel.getFont().deriveFont(12f)); + pageLabel.setHorizontalAlignment(SwingConstants.CENTER); + } + return pageLabel; + } + + // private void addNavigationPanel(int location) { + // GridBagConstraints gbc = new GridBagConstraints(); + // gbc.anchor = GridBagConstraints.NORTHWEST; + // gbc.insets = new Insets(2, 2, 2, 2); + // gbc.gridx = 0; + // gbc.gridy = location * 6; + // gbc.fill = GridBagConstraints.BOTH; + // gbc.weighty = 100; + // gbc.gridwidth = 3; + // getResultsPanel().add(getNavigationPanel(), gbc); + // } + public void executeBackgroundTask(final ITask task) { getGlassPane().setVisible(true); SwingWorker worker = new SwingWorker() { @@ -513,16 +567,14 @@ public class CloudBrowserFrame extends JFrame { @Override protected void done() { + getGlassPane().setVisible(false); try { T result = get(); task.complete(result); - getGlassPane().setVisible(false); } catch (ExecutionException e) { LOG.error("Background task execution failed", e); - getGlassPane().setVisible(false); task.failed(e); } catch (InterruptedException e) { - getGlassPane().setVisible(false); LOG.error("Background task execution interrupted", e); task.failed(e); } @@ -539,13 +591,19 @@ public class CloudBrowserFrame extends JFrame { return JOptionPane.showConfirmDialog(this, message, title, optionType, messageType); } - private Icon downloadImage(String imageUrl) { - Image image = null; + private Icon downloadImage(String imageFile) { + // Image image = null; + // try { + // URL url = new URL(imageUrl); + // image = ImageIO.read(url); + // } catch (IOException e) { + // } + // return image == null ? IconLoader.MissingImage.getIcon() : new ImageIcon(image); try { - URL url = new URL(imageUrl); - image = ImageIO.read(url); - } catch (IOException e) { + BufferedImage img = ImageIO.read(new File(imageFile)); + return new ImageIcon(img); + } catch (Exception e) { + return IconLoader.MissingImage.getIcon(); } - return new ImageIcon(image); } } diff --git a/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CloudGlassPane.java b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CloudGlassPane.java new file mode 100644 index 00000000..fa5e3c37 --- /dev/null +++ b/diylc/diylc-swing/src/org/diylc/swing/plugins/cloud/view/CloudGlassPane.java @@ -0,0 +1,111 @@ +package org.diylc.swing.plugins.cloud.view; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.JPanel; +import javax.swing.Timer; + +import org.diylc.images.IconLoader; + +public class CloudGlassPane extends JPanel implements MouseListener, KeyListener { + + public static final CloudGlassPane GLASS_PANE = new CloudGlassPane(); + + private static final long serialVersionUID = -5344758920442881290L; + + private long startTime; + private final int msPerPx = 5; + + private Timer animationTimer; + + public CloudGlassPane() { + addKeyListener(this); + addMouseListener(this); + setCursor(new Cursor(Cursor.WAIT_CURSOR)); + setOpaque(false); + setBackground(new Color(192, 222, 237)); + + animationTimer = new Timer(20, new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + repaint(); + } + }); + } + + @Override + public void setVisible(boolean aFlag) { + if (aFlag) { + startTime = System.currentTimeMillis(); + animationTimer.start(); + } else + animationTimer.stop(); + super.setVisible(aFlag); + }; + + @Override + public void paint(java.awt.Graphics g) { + Graphics2D g2d = (Graphics2D) g; + // g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f)); + + Image cloud = IconLoader.CloudBg.getImage(); + + g2d.setColor(new Color(192, 222, 237)); + g2d.fillRect(0, cloud.getHeight(null), getWidth(), getHeight()); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + long ellapsed = System.currentTimeMillis() - startTime; + long dx = (ellapsed / msPerPx) % cloud.getWidth(null); + g2d.drawImage(cloud, -(int) dx, 0, null); + if (cloud.getWidth(null) - dx < getWidth()) { + g2d.drawImage(cloud, (int) (cloud.getWidth(null) - dx), 0, null); + } + + g2d.setColor(Color.white); + g2d.setFont(g2d.getFont().deriveFont(22f)); + String text = "Querying the cloud, please hold on..."; + FontMetrics metrics = g.getFontMetrics(g2d.getFont()); + Rectangle rect = new Rectangle(getSize()); + int x = (rect.width - metrics.stringWidth(text)) / 2; + int y = ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent(); + g.drawString(text, x, y); + }; + + @Override + public void mouseClicked(final MouseEvent pArg0) {} + + @Override + public void mouseEntered(final MouseEvent pArg0) {} + + @Override + public void mouseExited(final MouseEvent pArg0) {} + + @Override + public void mousePressed(final MouseEvent pArg0) {} + + @Override + public void mouseReleased(final MouseEvent pArg0) {} + + @Override + public void keyPressed(KeyEvent e) {} + + @Override + public void keyReleased(KeyEvent e) {} + + @Override + public void keyTyped(KeyEvent e) {} +}