From d5626a8e01bf8bb04eb16c066dc9c9ca31c06ffd Mon Sep 17 00:00:00 2001 From: pesckal Date: Sun, 17 Jul 2011 22:22:45 +0000 Subject: [PATCH] Added link for updating contributions --- app/src/processing/app/Contribution.java | 6 + .../processing/app/ContributionListPanel.java | 224 +++++++++++------- .../processing/app/ContributionListing.java | 77 +++--- .../processing/app/ContributionManager.java | 40 ++-- 4 files changed, 209 insertions(+), 138 deletions(-) diff --git a/app/src/processing/app/Contribution.java b/app/src/processing/app/Contribution.java index f28641473..b54753126 100644 --- a/app/src/processing/app/Contribution.java +++ b/app/src/processing/app/Contribution.java @@ -57,6 +57,8 @@ public abstract class Contribution { protected String link = ""; + protected ContributionInfo latestVersion; + public static class Author { public String name; @@ -81,6 +83,10 @@ public abstract class Contribution { * installed */ public abstract Contribution getContribution(); + + public void setLatestVersion(ContributionInfo advertisedInfo) { + latestVersion = advertisedInfo; + } } diff --git a/app/src/processing/app/ContributionListPanel.java b/app/src/processing/app/ContributionListPanel.java index bed9ad38c..7b7f9f2b4 100644 --- a/app/src/processing/app/ContributionListPanel.java +++ b/app/src/processing/app/ContributionListPanel.java @@ -53,6 +53,8 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib + "You can still intall this library manually by visiting\n" + "the library's website."; + private static String UPDATE_LINK = "http://update/"; + ContributionManager contributionManager; JProgressBar setupProgressBar; @@ -82,7 +84,7 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib libraryInstaller = new ContributionInstaller() { public Contribution installContribution(File f) { - return contributionManager.installLibrary(f); + return contributionManager.installLibrary(f, false); } }; @@ -471,6 +473,8 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib JTextPane headerLabel; + JTextPane versionLabel; + JLabel categoryLabel; JTextPane descriptionText; @@ -480,6 +484,8 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib JButton installOrRemove; boolean isSelected; + + private ArrayList htmlPanes; private ContributionPanel(ContributionInfo contributionInfo, ContributionInstaller contributionInstaller) { @@ -487,13 +493,19 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib this.info = contributionInfo; this.installer = contributionInstaller; + htmlPanes = new ArrayList(); + okayToOpenHyperLink = false; conditionalHyperlinkOpener = new HyperlinkListener() { public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { if (okayToOpenHyperLink) { - Base.openURL(e.getURL().toString()); + if (UPDATE_LINK.equals(e.getURL().toString())) { + installContribution(info.latestVersion.link); + } else { + Base.openURL(e.getURL().toString()); + } } } } @@ -501,8 +513,6 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - createAuthorString(); - installAction = createInstallAction(); removeAction = createRemoveAction(); @@ -535,15 +545,27 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib getParent().requestFocusInWindow(); } } - + }; addMouseListener(expandPanelMouseListener); - stripListeners(headerLabel); - stripListeners(descriptionText); - headerLabel.addMouseListener(expandPanelMouseListener); - categoryLabel.addMouseListener(expandPanelMouseListener); - descriptionText.addMouseListener(expandPanelMouseListener); + stripListener(expandPanelMouseListener, this); + } + + private void stripListener(MouseAdapter expandPanelMouseListener, + Container con) { + + for (Component c : con.getComponents()) { + if (c instanceof Container) { + stripListener(expandPanelMouseListener, (Container) c); + } + if (c instanceof JTextPane) { + stripListeners((JTextPane) c); + } + if (c instanceof JComponent) { + ((JComponent) c).addMouseListener(expandPanelMouseListener); + } + } } /** @@ -579,49 +601,74 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib } public void updateState() { + if (info.isInstalled()) { + // Display the version number and upgrade link + StringBuilder versionText = new StringBuilder(); + versionText.append(""); + versionText.append("Version "); + versionText.append(info.prettyVersion); + versionText.append(" installed."); + if (info.latestVersion != null + && info.latestVersion.version > info.version) { + versionText.append(" "); + versionText.append("Click here to update to latest version."); + } + versionText.append(""); + versionLabel.setText(versionText.toString()); + versionLabel.setMargin(new Insets(0, 25, 10, 5)); + versionLabel.setVisible(true); + useRemoveAction(); } else { useInstalledAction(); + versionLabel.setVisible(false); } + } protected ActionListener createInstallAction() { return new ActionListener() { public void actionPerformed(ActionEvent arg) { - installOrRemove.setEnabled(false); - - try { - URL url = new URL(info.link); - - installProgressBar.setVisible(true); - - contributionManager.downloadAndInstall(url, info, installer, - new JProgressMonitor(installProgressBar) { - - public void finishedAction() { - // Finished downloading library - } - }, - new JProgressMonitor(installProgressBar) { - - public void finishedAction() { - // Finished installing library - resetInstallProgressBarState(); - installOrRemove.setEnabled(true); - } - } - ); - - } catch (MalformedURLException e) { - Base.showWarning(INSTALL_FAILURE_TITLE, MALFORMED_URL_MESSAGE, e); - installOrRemove.setEnabled(true); - } + installContribution(info.link); } }; } + + private void installContribution(String url) { + installOrRemove.setEnabled(false); + + try { + URL downloadUrl = new URL(url); + + installProgressBar.setVisible(true); + + contributionManager.downloadAndInstall(downloadUrl, info, installer, + new JProgressMonitor(installProgressBar) { + public void finishedAction() { + // Finished downloading library + } + }, + new JProgressMonitor(installProgressBar) { + + public void finishedAction() { + // Finished installing library + resetInstallProgressBarState(); + installOrRemove.setEnabled(true); + } + } + ); + + } catch (MalformedURLException e) { + Base.showWarning(INSTALL_FAILURE_TITLE, MALFORMED_URL_MESSAGE, e); + installOrRemove.setEnabled(true); + } + } + protected ActionListener createRemoveAction() { return new ActionListener() { @@ -664,7 +711,11 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib if (author.url == null) { authors.append(author.name); } else { - authors.append("" + author.name + ""); + authors.append(""); + authors.append(author.name); + authors.append(""); } if (i + 2 < info.authorList.size()) { authors.append(", "); @@ -708,11 +759,13 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib } updateHyperLinkStyle(textPane); + htmlPanes.add(textPane); } void updateHyperLinkStyles() { - updateHyperLinkStyle(headerLabel); - updateHyperLinkStyle(descriptionText); + for (JTextPane textPane : htmlPanes) { + updateHyperLinkStyle(textPane); + } } private void updateHyperLinkStyle(JTextPane textPane) { @@ -745,6 +798,9 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib * Create the widgets for the header panel which is visible when the library * panel is not clicked */ + /** + * + */ private void addPaneComponents() { setFocusable(true); setLayout(new GridBagLayout()); @@ -761,46 +817,35 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib // nameLabel.getDocument(). // ((HTMLDocument)nameLabel.getDocument()).getStyleSheet().addRule("a {font-family:"+font.getFamily()+";}"); - StringBuilder header = new StringBuilder(); - header.append(""); - header.append(""); + StringBuilder nameText = new StringBuilder(); + nameText.append(""); if (info.url == null) { - header.append(info.name); + nameText.append(info.name); } else { - header.append("" + info.name + ""); + nameText.append("" + info.name + ""); } - header.append(""); - header.append(createAuthorString()); - header.append(""); - headerLabel.setText(header.toString()); + nameText.append(""); + nameText.append(createAuthorString()); + nameText.append(""); + headerLabel.setText(nameText.toString()); setHtmlTextStyle(headerLabel, false); - headerLabel.addHyperlinkListener(nullHyperlinkListener); add(headerLabel, c); c = new GridBagConstraints(); c.gridx = 1; c.gridy = 0; - c.anchor = GridBagConstraints.EAST; + c.anchor = GridBagConstraints.WEST; + categoryLabel = new JLabel("[" + info.category + "]"); categoryLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 7)); add(categoryLabel, c); -// c = new GridBagConstraints(); -// c.gridx = 2; -// c.gridy = 0; -// c.anchor = GridBagConstraints.NORTHEAST; -// JLabel categoryLabel = new JLabel(libInfo.categoryName + " "); -// font = categoryLabel.getFont(); -// font = font.deriveFont(font.getSize() * 0.7f); -// categoryLabel.setFont(font); -// headerPanel.add(categoryLabel, c); - c = new GridBagConstraints(); c.gridx = 0; c.gridy = 1; c.weightx = 1; - c.gridwidth = 3; + c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.WEST; @@ -820,18 +865,31 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib description.append(""); descriptionText.setText(description.toString()); - descriptionText.addHyperlinkListener(nullHyperlinkListener); descriptionText.setMargin(new Insets(0, 25, 10, 5)); setHtmlTextStyle(descriptionText, true); add(descriptionText, c); + + c = new GridBagConstraints(); + c.gridx = 0; + c.gridy = 2; + c.weightx = 1; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + + versionLabel = new JTextPane(); + versionLabel.setContentType("text/html"); + setHtmlTextStyle(versionLabel, false); + versionLabel.setVisible(false); + add(versionLabel, c); } public void addProgressBarAndButton() { GridBagConstraints c = new GridBagConstraints(); - c.gridx = 3; + c.gridx = 4; c.gridy = 0; c.weighty = 1; - c.gridheight = 2; + c.gridheight = 3; c.fill = GridBagConstraints.VERTICAL; c.anchor = GridBagConstraints.NORTH; JPanel rightPane = new JPanel(); @@ -882,24 +940,23 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib installProgressBar.setVisible(false); } - public void setSelected(boolean doShow) { - isSelected = doShow; - installOrRemove.setVisible(doShow); - - updateLiseners(headerLabel); - updateLiseners(descriptionText); - - } + public void setSelected(boolean isSelected) { + this.isSelected = isSelected; + installOrRemove.setVisible(isSelected); - private void updateLiseners(JEditorPane editorPane) { - if (isSelected) { - editorPane.removeHyperlinkListener(nullHyperlinkListener); - editorPane.addHyperlinkListener(conditionalHyperlinkOpener); - editorPane.setEditable(false); - } else { - editorPane.removeHyperlinkListener(conditionalHyperlinkOpener); - editorPane.addHyperlinkListener(nullHyperlinkListener); - editorPane.setEditable(true); + for (JTextPane textPane : htmlPanes) { + if (textPane instanceof JEditorPane) { + JEditorPane editorPane = (JEditorPane) textPane; + if (isSelected) { + editorPane.removeHyperlinkListener(nullHyperlinkListener); + editorPane.addHyperlinkListener(conditionalHyperlinkOpener); + editorPane.setEditable(false); + } else { + editorPane.removeHyperlinkListener(conditionalHyperlinkOpener); + editorPane.addHyperlinkListener(nullHyperlinkListener); + editorPane.setEditable(true); + } + } } } @@ -923,5 +980,4 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib } } - } diff --git a/app/src/processing/app/ContributionListing.java b/app/src/processing/app/ContributionListing.java index 2f365bfcd..740e008f4 100644 --- a/app/src/processing/app/ContributionListing.java +++ b/app/src/processing/app/ContributionListing.java @@ -48,69 +48,68 @@ public class ContributionListing { ArrayList allLibraries; - boolean hasDownloadedList; - public ContributionListing() { listeners = new ArrayList(); librariesByCategory = new HashMap>(); allLibraries = new ArrayList(); - hasDownloadedList = false; } - public void updateList(File xmlFile) { - - hasDownloadedList = true; + public void setAdvertisedList(File xmlFile) { ContributionXmlParser xmlParser = new ContributionXmlParser(xmlFile); advertisedContributions = xmlParser.getLibraries(); - updateList(advertisedContributions); + for (ContributionInfo info : advertisedContributions) { + addContribution(info); + } Collections.sort(allLibraries); } + /** + * If a the given contribution has a version of it which is advertised. This + * method sets the latestVersion and category for the contribution. + */ + public void getInformationFromAdvertised(ContributionInfo contribution) { + + ContributionInfo advertised = getAdvertisedContribution(contribution.name, + contribution.getType()); + contribution.setLatestVersion(advertised); + + if (advertised != null) { + // Merge information from the advertised and local versions. + if (advertised.category != null) { + contribution.category = advertised.category; + } + } + } + /** * Adds the installed libraries to the listing of libraries, replacing any * pre-existing libraries by the same name as one in the list. */ - public void updateList(List contributions) { + public void updateInstalledList(List installedContributions) { - // First, record the names of all the libraries in installedLibraries - HashSet installedContributionNames = new HashSet(); - for (ContributionInfo libInfo : contributions) { - installedContributionNames.add(libInfo.name); - } - - // We also want to remember categories of libraries that happen to already - // exist since there is no 'category' attribute in export.txt. For this, we - // use a mapping of contributions names to category names. - HashMap categoriesByName = new HashMap(); - - Iterator it = allLibraries.iterator(); - while (it.hasNext()) { - ContributionInfo libInfo = it.next(); - if (installedContributionNames.contains(libInfo.name)) { - if (librariesByCategory.containsKey(libInfo.category)) { - librariesByCategory.get(libInfo.category).remove(libInfo); + for (ContributionInfo contribution : installedContributions) { + + getInformationFromAdvertised(contribution); + + boolean found= false; + for (ContributionInfo existing : allLibraries) { + if (existing.name.equals(contribution.name) && existing.getType() == contribution.getType()) { + replaceContribution(existing, contribution); + found = true; + break; } - it.remove(); - notifyRemove(libInfo); - categoriesByName.put(libInfo.name, libInfo.category); + } + + if (!found) { + addContribution(contribution); } } - for (ContributionInfo libInfo : contributions) { - String category = categoriesByName.get(libInfo.name); - if (category != null) { - libInfo.category = category; - } - addContribution(libInfo); - } - - Collections.sort(allLibraries); - } @@ -326,7 +325,7 @@ public class ContributionListing { File xmlFile = downloader.getFile(); if (xmlFile != null) { - libListing.updateList(xmlFile); + libListing.setAdvertisedList(xmlFile); } } }); diff --git a/app/src/processing/app/ContributionManager.java b/app/src/processing/app/ContributionManager.java index 1b251af4a..3e4f95a6c 100644 --- a/app/src/processing/app/ContributionManager.java +++ b/app/src/processing/app/ContributionManager.java @@ -279,7 +279,7 @@ public class ContributionManager { infoList.add(compilation.info); } - contributionListing.updateList(infoList); + contributionListing.updateInstalledList(infoList); } public void removeContribution(final Contribution contribution, @@ -332,6 +332,7 @@ public class ContributionManager { Contribution contribution = installOperation.installContribution(libFile); if (contribution != null) { + contributionListing.getInformationFromAdvertised(contribution.getInfo()); contributionListing.replaceContribution(info, contribution.getInfo()); refreshInstalled(); } @@ -391,7 +392,7 @@ public class ContributionManager { DRAG_AND_DROP_SECONDARY); if (result == JOptionPane.YES_OPTION) { - return installLibrary(libFile); + return installLibrary(libFile, true); } return null; @@ -473,7 +474,7 @@ public class ContributionManager { return fileName; } - protected Library installLibrary(File libFile) { + protected Library installLibrary(File libFile, boolean confirmReplace) { File tempDir = unzipFileToTemp(libFile); try { @@ -488,7 +489,7 @@ public class ContributionManager { if (discoveredLibs != null && discoveredLibs.size() == 1) { Library discoveredLib = discoveredLibs.get(0); - if (installLibrary(discoveredLib)) { + if (installLibrary(discoveredLib, confirmReplace)) { return discoveredLib; } else { return null; @@ -515,8 +516,15 @@ public class ContributionManager { return null; } - - protected boolean installLibrary(Library newLib) { + + /** + * + * @param confirmReplace + * if true and the library is already installed, opens a prompt to + * ask the user if it's okay to replace the library. If false, the + * library is always replaced with the new copy. + */ + protected boolean installLibrary(Library newLib, boolean confirmReplace) { ArrayList oldLibs = editor.getMode().contribLibraries; @@ -532,16 +540,18 @@ public class ContributionManager { // XXX: Handle other cases when installing libraries. // -What if a library by the same name is already installed? // -What if newLibDest exists, but isn't used by an existing library? - if (oldLib.libraryFolder.exists() && oldLib.equals(newLibDest)) { + if (oldLib.folder.exists() && oldLib.folder.equals(newLibDest)) { - int result = Base.showYesNoQuestion(editor, "Replace", - "Replace existing \"" + oldLib.getName() + "\" library?", - "An existing copy of the \"" + oldLib.getName() + "\" library
"+ - "has been found in your sketchbook. Clicking “Yes”
"+ - "will move the existing library to a backup folder
" + - " in libraries/old before replacing it."); - - if (result == JOptionPane.YES_OPTION) { + int result = 0; + if (confirmReplace) { + result = Base.showYesNoQuestion(editor, "Replace", + "Replace existing \"" + oldLib.getName() + "\" library?", + "An existing copy of the \"" + oldLib.getName() + "\" library
"+ + "has been found in your sketchbook. Clicking “Yes”
"+ + "will move the existing library to a backup folder
" + + " in libraries/old before replacing it."); + } + if (!confirmReplace || result == JOptionPane.YES_OPTION) { if (!backupContribution(oldLib)) { return false; }