From cb17c98c5be01b932909158e1709459076e104f8 Mon Sep 17 00:00:00 2001 From: Akarshit Wal Date: Thu, 18 Jun 2015 01:33:05 +0530 Subject: [PATCH] initial phase --- app/src/processing/app/Base.java | 29 +- app/src/processing/app/UpdateCheck.java | 10 +- .../app/contrib/ContributionListPanel.java | 6 +- .../app/contrib/ContributionListing.java | 3 + .../contrib/ContributionManagerDialog.java | 1059 +++++++++-------- .../app/contrib/ContributionPanel.java | 40 +- .../app/contrib/ContributionTab.java | 616 ++++++++++ 7 files changed, 1195 insertions(+), 568 deletions(-) create mode 100644 app/src/processing/app/contrib/ContributionTab.java diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 2765505dc..4bf83df73 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -105,12 +105,9 @@ public class Base { PreferencesFrame preferencesFrame; // A single instance of the library manager window - ContributionManagerDialog libraryManagerFrame; - ContributionManagerDialog toolManagerFrame; - ContributionManagerDialog modeManagerFrame; - ContributionManagerDialog exampleManagerFrame; - ContributionManagerDialog updateManagerFrame; + ContributionManagerDialog contributionManagerFrame; + // Location for untitled items static File untitledFolder; @@ -391,16 +388,8 @@ public class Base { } } - libraryManagerFrame = - new ContributionManagerDialog(ContributionType.LIBRARY); - toolManagerFrame = - new ContributionManagerDialog(ContributionType.TOOL); - modeManagerFrame = - new ContributionManagerDialog(ContributionType.MODE); - exampleManagerFrame = - new ContributionManagerDialog(ContributionType.EXAMPLES); - updateManagerFrame = - new ContributionManagerDialog(null); + contributionManagerFrame = + new ContributionManagerDialog(); // Make sure ThinkDifferent has library examples too nextMode.rebuildLibraryList(); @@ -1394,7 +1383,7 @@ public class Base { * Show the library installer window. */ public void handleOpenLibraryManager() { - libraryManagerFrame.showFrame(activeEditor); + contributionManagerFrame.showFrame(activeEditor); } @@ -1402,7 +1391,7 @@ public class Base { * Show the tool installer window. */ public void handleOpenToolManager() { - toolManagerFrame.showFrame(activeEditor); + contributionManagerFrame.showFrame(activeEditor); } @@ -1410,7 +1399,7 @@ public class Base { * Show the mode installer window. */ public void handleOpenModeManager() { - modeManagerFrame.showFrame(activeEditor); + contributionManagerFrame.showFrame(activeEditor); } @@ -1418,12 +1407,12 @@ public class Base { * Show the examples installer window. */ public void handleOpenExampleManager() { - exampleManagerFrame.showFrame(activeEditor); + contributionManagerFrame.showFrame(activeEditor); } public void handleShowUpdates() { - updateManagerFrame.showFrame(activeEditor); + contributionManagerFrame.showFrame(activeEditor); } diff --git a/app/src/processing/app/UpdateCheck.java b/app/src/processing/app/UpdateCheck.java index 098eda1c2..e25a775cc 100644 --- a/app/src/processing/app/UpdateCheck.java +++ b/app/src/processing/app/UpdateCheck.java @@ -122,14 +122,8 @@ public class UpdateCheck { // Wait for xml file to be downloaded and updates to come in. // (this should really be handled better). Thread.sleep(5 * 1000); - if ((!base.libraryManagerFrame.hasAlreadyBeenOpened() - && !base.toolManagerFrame.hasAlreadyBeenOpened() - && !base.modeManagerFrame.hasAlreadyBeenOpened() - && !base.exampleManagerFrame.hasAlreadyBeenOpened()) - && (base.libraryManagerFrame.hasUpdates(base) - || base.toolManagerFrame.hasUpdates(base) - || base.modeManagerFrame.hasUpdates(base) - || base.exampleManagerFrame.hasUpdates(base))) { + if ((!base.contributionManagerFrame.hasAlreadyBeenOpened() + && (base.contributionManagerFrame.hasUpdates(base)))){ promptToOpenContributionManager(); } } diff --git a/app/src/processing/app/contrib/ContributionListPanel.java b/app/src/processing/app/contrib/ContributionListPanel.java index 4e01060c6..01c1d52c5 100644 --- a/app/src/processing/app/contrib/ContributionListPanel.java +++ b/app/src/processing/app/contrib/ContributionListPanel.java @@ -41,7 +41,7 @@ import processing.app.Base; public class ContributionListPanel extends JPanel implements Scrollable, ContributionChangeListener { - ContributionManagerDialog contribManager; + ContributionTab contributionTab; TreeMap panelByContribution; static HyperlinkListener nullHyperlinkListener = new HyperlinkListener() { @@ -56,10 +56,10 @@ public class ContributionListPanel extends JPanel implements Scrollable, Contrib private ContributionListing contribListing = ContributionListing.getInstance(); - public ContributionListPanel(ContributionManagerDialog libraryManager, + public ContributionListPanel(ContributionTab contributionTab, ContributionFilter filter) { super(); - this.contribManager = libraryManager; + this.contributionTab = contributionTab; this.filter = filter; // contribListing = ContributionListing.getInstance(); diff --git a/app/src/processing/app/contrib/ContributionListing.java b/app/src/processing/app/contrib/ContributionListing.java index 7f50575de..2d7403f9f 100644 --- a/app/src/processing/app/contrib/ContributionListing.java +++ b/app/src/processing/app/contrib/ContributionListing.java @@ -396,6 +396,9 @@ public class ContributionListing { new Thread(new Runnable() { public void run() { downloadingListingLock.lock(); +// if(hasDownloadedLatestList == true){ +// return; +// } URL url = null; try { diff --git a/app/src/processing/app/contrib/ContributionManagerDialog.java b/app/src/processing/app/contrib/ContributionManagerDialog.java index 273f2bc60..9e18c20d8 100644 --- a/app/src/processing/app/contrib/ContributionManagerDialog.java +++ b/app/src/processing/app/contrib/ContributionManagerDialog.java @@ -1,394 +1,423 @@ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* - Part of the Processing project - http://processing.org + Part of the Processing project - http://processing.org - Copyright (c) 2013 The Processing Foundation - Copyright (c) 2011-12 Ben Fry and Casey Reas + Copyright (c) 2013 The Processing Foundation + Copyright (c) 2011-12 Ben Fry and Casey Reas - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ package processing.app.contrib; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.Font; -import java.awt.event.*; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.SocketTimeoutException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; -import javax.swing.*; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.ScrollPaneConstants; +import javax.swing.UIManager; import javax.swing.border.EmptyBorder; -import javax.swing.event.*; - -import processing.app.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import processing.app.Base; +import processing.app.Editor; +import processing.app.Language; +import processing.app.Library; +import processing.app.Toolkit; public class ContributionManagerDialog { static final String ANY_CATEGORY = Language.text("contrib.all"); JFrame dialog; + String title; - ContributionFilter filter; - JComboBox categoryChooser; - JScrollPane scrollPane; - ContributionListPanel contributionListPanel; - StatusPanel status; - FilterField filterField; + JButton restartButton; - JButton retryConnectingButton; - JProgressBar progressBar; // the calling editor, so updates can be applied Editor editor; - String category; - String compatibleCheckboxLabel; - boolean isCompatibilityFilter; - ContributionListing contribListing; + ContributionTab toolsContributionTab; - public ContributionManagerDialog(ContributionType type) { - if (type == null) { - title = Language.text("contrib.manager_title.update"); - filter = ContributionType.createUpdateFilter(); - compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.update"); - } else { - if (type == ContributionType.MODE) { - title = Language.text("contrib.manager_title.mode"); - compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.mode"); - } - else if (type == ContributionType.TOOL) { - title = Language.text("contrib.manager_title.tool"); - compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.tool"); - } - else if (type == ContributionType.LIBRARY) { - title = Language.text("contrib.manager_title.library"); - compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.library"); - } - else if (type == ContributionType.EXAMPLES) { - title = Language.text("contrib.manager_title.examples"); - compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.examples"); - } + ContributionTab librariesContributionTab; - filter = type.createFilter(); - } - contribListing = ContributionListing.getInstance(); - contributionListPanel = new ContributionListPanel(this, filter); - contribListing.addContributionListener(contributionListPanel); + ContributionTab examplesContributionTab; + + ContributionTab modesContributionTab; + + ContributionTab updatesContributionTab; + + public ContributionManagerDialog() { + toolsContributionTab = new ContributionTab(ContributionType.TOOL); + librariesContributionTab = new ContributionTab(ContributionType.LIBRARY); + modesContributionTab = new ContributionTab(ContributionType.MODE); + examplesContributionTab = new ContributionTab(ContributionType.EXAMPLES); + updatesContributionTab = new ContributionTab(null); } - public boolean hasUpdates() { - return contribListing.hasUpdates(); + return toolsContributionTab.hasUpdates() + || librariesContributionTab.hasUpdates() + || examplesContributionTab.hasUpdates() + || modesContributionTab.hasUpdates(); } - public boolean hasUpdates(Base base) { - return contribListing.hasUpdates(base); + return toolsContributionTab.hasUpdates(base) + || modesContributionTab.hasUpdates(base) + || librariesContributionTab.hasUpdates(base) + || examplesContributionTab.hasUpdates(base); + } + + protected JPanel makeTextPanel(String text) { + JPanel panel = new JPanel(false); + JLabel filler = new JLabel(text); + filler.setHorizontalAlignment(JLabel.CENTER); + panel.setLayout(new GridLayout(1, 1)); + panel.add(filler); + return panel; } public void showFrame(final Editor editor) { this.editor = editor; if (dialog == null) { - dialog = new JFrame(title); - - restartButton = new JButton(Language.text("contrib.restart")); - restartButton.setVisible(false); - restartButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent arg0) { - - Iterator iter = editor.getBase().getEditors().iterator(); - while (iter.hasNext()) { - Editor ed = iter.next(); - if (ed.getSketch().isModified()) { - int option = Base - .showYesNoQuestion(editor, title, - Language.text("contrib.unsaved_changes"), - Language.text("contrib.unsaved_changes.prompt")); - - if (option == JOptionPane.NO_OPTION) - return; - else - break; - } - } - - // Thanks to http://stackoverflow.com/a/4160543 - StringBuilder cmd = new StringBuilder(); - cmd.append(System.getProperty("java.home") + File.separator + "bin" - + File.separator + "java "); - for (String jvmArg : ManagementFactory.getRuntimeMXBean() - .getInputArguments()) { - cmd.append(jvmArg + " "); - } - cmd.append("-cp ") - .append(ManagementFactory.getRuntimeMXBean().getClassPath()) - .append(" "); - cmd.append(Base.class.getName()); - - try { - Runtime.getRuntime().exec(cmd.toString()); - System.exit(0); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - }); - - retryConnectingButton = new JButton("Retry"); - retryConnectingButton.setVisible(false); - retryConnectingButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent arg0) { - // The message is set to null so that every time the retry button is hit - // no previous error is displayed in the status - status.setMessage(null); - downloadAndUpdateContributionListing(); - } - }); - - progressBar = new JProgressBar(); - progressBar.setVisible(true); - - Toolkit.setIcon(dialog); - createComponents(); - registerDisposeListeners(); - - dialog.pack(); - dialog.setLocationRelativeTo(null); + makeFrame(editor); } dialog.setVisible(true); - contributionListPanel.grabFocus(); - - if (contribListing.hasDownloadedLatestList()) { - updateContributionListing(); - - } else { - downloadAndUpdateContributionListing(); - } } + public void makeFrame(final Editor editor) { + dialog = new JFrame(title); + JTabbedPane tabbedPane = new JTabbedPane(); + + toolsContributionTab.showFrame(editor); + + tabbedPane + .addTab("Tools", null, toolsContributionTab.panel, "Does nothing"); + tabbedPane.setMnemonicAt(0, KeyEvent.VK_1); + + librariesContributionTab.showFrame(editor); + tabbedPane.addTab("Libraries", null, librariesContributionTab.panel, + "Does twice as much nothing"); + tabbedPane.setMnemonicAt(1, KeyEvent.VK_2); + + modesContributionTab.showFrame(editor); + tabbedPane.addTab("Modes", null, modesContributionTab.panel, + "Still does nothing"); + tabbedPane.setMnemonicAt(2, KeyEvent.VK_3); + + examplesContributionTab.showFrame(editor); + examplesContributionTab.panel.setPreferredSize(new Dimension(410, 50)); + tabbedPane.addTab("Examples", null, examplesContributionTab.panel, + "Does nothing at all"); + tabbedPane.setMnemonicAt(3, KeyEvent.VK_4); + + dialog.add(tabbedPane); + + restartButton = new JButton(Language.text("contrib.restart")); + restartButton.setVisible(false); + restartButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + + Iterator iter = editor.getBase().getEditors().iterator(); + while (iter.hasNext()) { + Editor ed = iter.next(); + if (ed.getSketch().isModified()) { + int option = Base.showYesNoQuestion(editor, title, Language + .text("contrib.unsaved_changes"), Language + .text("contrib.unsaved_changes.prompt")); + + if (option == JOptionPane.NO_OPTION) + return; + else + break; + } + } + + // Thanks to http://stackoverflow.com/a/4160543 + StringBuilder cmd = new StringBuilder(); + cmd.append(System.getProperty("java.home") + File.separator + "bin" + + File.separator + "java "); + for (String jvmArg : ManagementFactory.getRuntimeMXBean() + .getInputArguments()) { + cmd.append(jvmArg + " "); + } + cmd.append("-cp ") + .append(ManagementFactory.getRuntimeMXBean().getClassPath()) + .append(" "); + cmd.append(Base.class.getName()); + + try { + Runtime.getRuntime().exec(cmd.toString()); + System.exit(0); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + }); + + Toolkit.setIcon(dialog); + registerDisposeListeners(); + + dialog.pack(); + dialog.setLocationRelativeTo(null); + } /** * Close the window after an OK or Cancel. */ protected void disposeFrame() { - status.clear(); dialog.dispose(); editor = null; } - - /** Creates and arranges the Swing components in the dialog. */ - private void createComponents() { - dialog.setResizable(true); - - Container pane = dialog.getContentPane(); -// pane.setLayout(new GridBagLayout()); +// /** +// * Creates and arranges the Swing components in the dialog. +// * +// * @param panel1 +// */ +// private void createComponents(JPanel panel1) { +// dialog.setResizable(true); // -// { // Shows "Filter by Category" and the combo box for selecting a category -// GridBagConstraints c = new GridBagConstraints(); -// c.gridx = 0; -// c.gridy = 0; - pane.setLayout(new BorderLayout()); - - JPanel filterPanel = new JPanel(); - filterPanel.setLayout(new BoxLayout(filterPanel, BoxLayout.X_AXIS)); -// pane.add(filterPanel, c); - pane.add(filterPanel, BorderLayout.NORTH); - - filterPanel.add(Box.createHorizontalStrut(6)); - - JLabel categoryLabel = new JLabel(Language.text("contrib.category")); - filterPanel.add(categoryLabel); - - filterPanel.add(Box.createHorizontalStrut(5)); - - categoryChooser = new JComboBox(); - categoryChooser.setMaximumRowCount(20); - updateCategoryChooser(); -// filterPanel.add(categoryChooser, c); - filterPanel.add(categoryChooser); - categoryChooser.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - category = (String) categoryChooser.getSelectedItem(); - if (ContributionManagerDialog.ANY_CATEGORY.equals(category)) { - category = null; - } - filterLibraries(category, filterField.filters, isCompatibilityFilter); - contributionListPanel.updateColors(); - } - }); - - filterPanel.add(Box.createHorizontalStrut(5)); -// filterPanel.add(Box.createHorizontalGlue()); - filterField = new FilterField(); - filterPanel.add(filterField); - - filterPanel.add(Box.createHorizontalStrut(5)); - - final JCheckBox compatibleContrib = new JCheckBox(compatibleCheckboxLabel); - compatibleContrib.addItemListener(new ItemListener() { - - @Override - public void itemStateChanged(ItemEvent arg0) { - isCompatibilityFilter = compatibleContrib.isSelected(); - filterLibraries(category, filterField.filters, isCompatibilityFilter); - contributionListPanel.updateColors(); - } - }); - filterPanel.add(compatibleContrib); -// filterPanel.add(Box.createHorizontalGlue()); -// } - //filterPanel.setBorder(new EmptyBorder(13, 13, 13, 13)); - filterPanel.setBorder(new EmptyBorder(7, 7, 7, 7)); - -// { // The scroll area containing the contribution listing and the status bar. -// GridBagConstraints c = new GridBagConstraints(); -// c.fill = GridBagConstraints.BOTH; -// c.gridx = 0; -// c.gridy = 1; -// c.gridwidth = 2; -// c.weighty = 1; -// c.weightx = 1; - - scrollPane = new JScrollPane(); - scrollPane.setPreferredSize(new Dimension(300, 300)); - scrollPane.setViewportView(contributionListPanel); -// scrollPane.getViewport().setOpaque(true); -// scrollPane.getViewport().setBackground(contributionListPanel.getBackground()); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); -// scrollPane.setBorder(new EmptyBorder(0, 7, 0, 7)); - pane.add(scrollPane, BorderLayout.CENTER); - - pane.add(Box.createHorizontalStrut(10), BorderLayout.WEST); - pane.add(Box.createHorizontalStrut(10), BorderLayout.EAST); - - status = new StatusPanel(); -// status.setBorder(new EmptyBorder(7, 7, 7, 7)); - - JPanel statusRestartPane = new JPanel(); - statusRestartPane.setLayout(new BorderLayout()); - - statusRestartPane.setBorder(new EmptyBorder(7, 7, 7, 7)); - statusRestartPane.setOpaque(false); - - statusRestartPane.add(status, BorderLayout.WEST); - statusRestartPane.add(progressBar, BorderLayout.LINE_END); - - // Adding both of these to EAST shouldn't pose too much of a problem, - // since they can never get added together. - statusRestartPane.add(restartButton, BorderLayout.EAST); - statusRestartPane.add(retryConnectingButton, BorderLayout.EAST); - - pane.add(statusRestartPane, BorderLayout.SOUTH); - - -// status = new StatusPanel(); -// status.setBorder(BorderFactory.createEtchedBorder()); - -// final JLayeredPane layeredPane = new JLayeredPane(); -// layeredPane.add(scrollPane, JLayeredPane.DEFAULT_LAYER); -// layeredPane.add(status, JLayeredPane.PALETTE_LAYER); +// Container pane = panel1; +//// pane.setLayout(new GridBagLayout()); +//// +//// { // Shows "Filter by Category" and the combo box for selecting a category +//// GridBagConstraints c = new GridBagConstraints(); +//// c.gridx = 0; +//// c.gridy = 0; +// pane.setLayout(new BorderLayout()); // -// layeredPane.addComponentListener(new ComponentAdapter() { +// JPanel filterPanel = new JPanel(); +// filterPanel.setLayout(new BoxLayout(filterPanel, BoxLayout.X_AXIS)); +//// pane.add(filterPanel, c); +// pane.add(filterPanel, BorderLayout.NORTH); // -// void resizeLayers() { -// scrollPane.setSize(layeredPane.getSize()); -// scrollPane.updateUI(); +// filterPanel.add(Box.createHorizontalStrut(6)); +// +// JLabel categoryLabel = new JLabel(Language.text("contrib.category")); +// filterPanel.add(categoryLabel); +// +// filterPanel.add(Box.createHorizontalStrut(5)); +// +// categoryChooser = new JComboBox(); +// categoryChooser.setMaximumRowCount(20); +// updateCategoryChooser(); +//// filterPanel.add(categoryChooser, c); +// filterPanel.add(categoryChooser); +// categoryChooser.addItemListener(new ItemListener() { +// public void itemStateChanged(ItemEvent e) { +// category = (String) categoryChooser.getSelectedItem(); +// if (ContributionManagerDialog.ANY_CATEGORY.equals(category)) { +// category = null; // } -// -// public void componentShown(ComponentEvent e) { -// resizeLayers(); -// } -// -// public void componentResized(ComponentEvent arg0) { -// resizeLayers(); -// } -// }); -// -// final JViewport viewport = scrollPane.getViewport(); -// viewport.addComponentListener(new ComponentAdapter() { -// void resizeLayers() { -// status.setLocation(0, viewport.getHeight() - 18); -// -// Dimension d = viewport.getSize(); -// d.height = 20; -// d.width += 3; -// status.setSize(d); -// } -// public void componentShown(ComponentEvent e) { -// resizeLayers(); -// } -// public void componentResized(ComponentEvent e) { -// resizeLayers(); -// } -// }); -// -// pane.add(layeredPane, c); -// } - -// { // The filter text area -// GridBagConstraints c = new GridBagConstraints(); -// c.gridx = 0; -// c.gridy = 2; -// c.gridwidth = 2; -// c.weightx = 1; -// c.fill = GridBagConstraints.HORIZONTAL; -// filterField = new FilterField(); -// -// pane.add(filterField, c); -// } - - dialog.setMinimumSize(new Dimension(450, 400)); - } - - - private void updateCategoryChooser() { - if (categoryChooser != null) { - ArrayList categories; - categoryChooser.removeAllItems(); - categories = new ArrayList(contribListing.getCategories(filter)); -// for (int i = 0; i < categories.size(); i++) { -// System.out.println(i + " category: " + categories.get(i)); +// filterLibraries(category, filterField.filters, isCompatibilityFilter); +// contributionListPanel.updateColors(); // } - Collections.sort(categories); -// categories.add(0, ContributionManagerDialog.ANY_CATEGORY); - boolean categoriesFound = false; - categoryChooser.addItem(ContributionManagerDialog.ANY_CATEGORY); - for (String s : categories) { - categoryChooser.addItem(s); - if (!s.equals("Unknown")) { - categoriesFound = true; - } - } - categoryChooser.setEnabled(categoriesFound); - } - } +// }); +// +// filterPanel.add(Box.createHorizontalStrut(5)); +//// filterPanel.add(Box.createHorizontalGlue()); +// filterField = new FilterField(); +// filterPanel.add(filterField); +// +// filterPanel.add(Box.createHorizontalStrut(5)); +// +// final JCheckBox compatibleContrib = new JCheckBox(compatibleCheckboxLabel); +// compatibleContrib.addItemListener(new ItemListener() { +// +// @Override +// public void itemStateChanged(ItemEvent arg0) { +// isCompatibilityFilter = compatibleContrib.isSelected(); +// filterLibraries(category, filterField.filters, isCompatibilityFilter); +// contributionListPanel.updateColors(); +// } +// }); +// filterPanel.add(compatibleContrib); +//// filterPanel.add(Box.createHorizontalGlue()); +//// } +// //filterPanel.setBorder(new EmptyBorder(13, 13, 13, 13)); +// filterPanel.setBorder(new EmptyBorder(7, 7, 7, 7)); +// +//// { // The scroll area containing the contribution listing and the status bar. +//// GridBagConstraints c = new GridBagConstraints(); +//// c.fill = GridBagConstraints.BOTH; +//// c.gridx = 0; +//// c.gridy = 1; +//// c.gridwidth = 2; +//// c.weighty = 1; +//// c.weightx = 1; +// +// scrollPane = new JScrollPane(); +// scrollPane.setPreferredSize(new Dimension(300, 300)); +// scrollPane.setViewportView(contributionListPanel); +//// scrollPane.getViewport().setOpaque(true); +//// scrollPane.getViewport().setBackground(contributionListPanel.getBackground()); +// scrollPane +// .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); +// scrollPane +// .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); +//// scrollPane.setBorder(new EmptyBorder(0, 7, 0, 7)); +// pane.add(scrollPane, BorderLayout.CENTER); +// +// pane.add(Box.createHorizontalStrut(10), BorderLayout.WEST); +// pane.add(Box.createHorizontalStrut(10), BorderLayout.EAST); +// +// status = new StatusPanel(); +//// status.setBorder(new EmptyBorder(7, 7, 7, 7)); +// +// JPanel statusRestartPane = new JPanel(); +// statusRestartPane.setLayout(new BorderLayout()); +// +// statusRestartPane.setBorder(new EmptyBorder(7, 7, 7, 7)); +// statusRestartPane.setOpaque(false); +// +// statusRestartPane.add(status, BorderLayout.WEST); +// statusRestartPane.add(progressBar, BorderLayout.LINE_END); +// +// // Adding both of these to EAST shouldn't pose too much of a problem, +// // since they can never get added together. +// statusRestartPane.add(restartButton, BorderLayout.EAST); +// statusRestartPane.add(retryConnectingButton, BorderLayout.EAST); +// +// pane.add(statusRestartPane, BorderLayout.SOUTH); +// +//// status = new StatusPanel(); +//// status.setBorder(BorderFactory.createEtchedBorder()); +// +//// final JLayeredPane layeredPane = new JLayeredPane(); +//// layeredPane.add(scrollPane, JLayeredPane.DEFAULT_LAYER); +//// layeredPane.add(status, JLayeredPane.PALETTE_LAYER); +//// +//// layeredPane.addComponentListener(new ComponentAdapter() { +//// +//// void resizeLayers() { +//// scrollPane.setSize(layeredPane.getSize()); +//// scrollPane.updateUI(); +//// } +//// +//// public void componentShown(ComponentEvent e) { +//// resizeLayers(); +//// } +//// +//// public void componentResized(ComponentEvent arg0) { +//// resizeLayers(); +//// } +//// }); +//// +//// final JViewport viewport = scrollPane.getViewport(); +//// viewport.addComponentListener(new ComponentAdapter() { +//// void resizeLayers() { +//// status.setLocation(0, viewport.getHeight() - 18); +//// +//// Dimension d = viewport.getSize(); +//// d.height = 20; +//// d.width += 3; +//// status.setSize(d); +//// } +//// public void componentShown(ComponentEvent e) { +//// resizeLayers(); +//// } +//// public void componentResized(ComponentEvent e) { +//// resizeLayers(); +//// } +//// }); +//// +//// pane.add(layeredPane, c); +//// } +// +//// { // The filter text area +//// GridBagConstraints c = new GridBagConstraints(); +//// c.gridx = 0; +//// c.gridy = 2; +//// c.gridwidth = 2; +//// c.weightx = 1; +//// c.fill = GridBagConstraints.HORIZONTAL; +//// filterField = new FilterField(); +//// +//// pane.add(filterField, c); +//// } +// +// dialog.setMinimumSize(new Dimension(450, 400)); +// } +// private void updateCategoryChooser() { +// if (categoryChooser != null) { +// ArrayList categories; +// categoryChooser.removeAllItems(); +// categories = new ArrayList(contribListing.getCategories(filter)); +//// for (int i = 0; i < categories.size(); i++) { +//// System.out.println(i + " category: " + categories.get(i)); +//// } +// Collections.sort(categories); +//// categories.add(0, ContributionManagerDialog.ANY_CATEGORY); +// boolean categoriesFound = false; +// categoryChooser.addItem(ContributionManagerDialog.ANY_CATEGORY); +// for (String s : categories) { +// categoryChooser.addItem(s); +// if (!s.equals("Unknown")) { +// categoriesFound = true; +// } +// } +// categoryChooser.setEnabled(categoriesFound); +// } +// } private void registerDisposeListeners() { dialog.addWindowListener(new WindowAdapter() { @@ -407,207 +436,203 @@ public class ContributionManagerDialog { public void keyPressed(KeyEvent e) { //System.out.println(e); KeyStroke wc = Toolkit.WINDOW_CLOSE_KEYSTROKE; - if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) || - (KeyStroke.getKeyStrokeForEvent(e).equals(wc))) { + if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) + || (KeyStroke.getKeyStrokeForEvent(e).equals(wc))) { disposeFrame(); } } }); } - - protected void filterLibraries(String category, List filters) { - List filteredLibraries = - contribListing.getFilteredLibraryList(category, filters); - contributionListPanel.filterLibraries(filteredLibraries); - } - - - protected void filterLibraries(String category, List filters, boolean isCompatibilityFilter) { - List filteredLibraries = - contribListing.getFilteredLibraryList(category, filters); - filteredLibraries = contribListing.getCompatibleContributionList(filteredLibraries, isCompatibilityFilter); - contributionListPanel.filterLibraries(filteredLibraries); - } - - - protected void updateContributionListing() { - if (editor != null) { - ArrayList contributions = new ArrayList(); - - ArrayList libraries = - new ArrayList(editor.getMode().contribLibraries); - contributions.addAll(libraries); - - //ArrayList tools = editor.contribTools; - List tools = editor.getToolContribs(); - contributions.addAll(tools); - - List modes = editor.getBase().getModeContribs(); - contributions.addAll(modes); - - List examples = editor.getBase().getExampleContribs(); - contributions.addAll(examples); - -// ArrayList compilations = LibraryCompilation.list(libraries); +// protected void filterLibraries(String category, List filters) { +// List filteredLibraries = contribListing +// .getFilteredLibraryList(category, filters); +// contributionListPanel.filterLibraries(filteredLibraries); +// } // -// // Remove libraries from the list that are part of a compilations -// for (LibraryCompilation compilation : compilations) { -// Iterator it = libraries.iterator(); -// while (it.hasNext()) { -// Library current = it.next(); -// if (compilation.getFolder().equals(current.getFolder().getParentFile())) { -// it.remove(); +// protected void filterLibraries(String category, List filters, +// boolean isCompatibilityFilter) { +// List filteredLibraries = contribListing +// .getFilteredLibraryList(category, filters); +// filteredLibraries = contribListing +// .getCompatibleContributionList(filteredLibraries, isCompatibilityFilter); +// contributionListPanel.filterLibraries(filteredLibraries); +// } +// +// protected void updateContributionListing() { +// if (editor != null) { +// ArrayList contributions = new ArrayList(); +// +// ArrayList libraries = new ArrayList( +// editor.getMode().contribLibraries); +// contributions.addAll(libraries); +// +// //ArrayList tools = editor.contribTools; +// List tools = editor.getToolContribs(); +// contributions.addAll(tools); +// +// List modes = editor.getBase().getModeContribs(); +// contributions.addAll(modes); +// +// List examples = editor.getBase() +// .getExampleContribs(); +// contributions.addAll(examples); +// +//// ArrayList compilations = LibraryCompilation.list(libraries); +//// +//// // Remove libraries from the list that are part of a compilations +//// for (LibraryCompilation compilation : compilations) { +//// Iterator it = libraries.iterator(); +//// while (it.hasNext()) { +//// Library current = it.next(); +//// if (compilation.getFolder().equals(current.getFolder().getParentFile())) { +//// it.remove(); +//// } +//// } +//// } +// +// contribListing.updateInstalledList(contributions); +// } +// } +// +// protected void downloadAndUpdateContributionListing() { +// retryConnectingButton.setEnabled(false); +// status.setMessage(Language.text("contrib.status.downloading_list")); +// contribListing.downloadAvailableList(new ContribProgressBar(progressBar) { +// +// @Override +// public void startTask(String name, int maxValue) { +// super.startTask(name, maxValue); +// progressBar.setString(null); +// } +// +// @Override +// public void setProgress(int value) { +// super.setProgress(value); +//// int percent = 100 * value / this.max; +// progressBar.setValue(value); +// progressBar.setStringPainted(true); +// status.setMessage(Language.text("contrib.status.downloading_list")); +// } +// +// @Override +// public void finishedAction() { +// progressBar.setVisible(false); +// +// updateContributionListing(); +// updateCategoryChooser(); +// +// retryConnectingButton.setEnabled(true); +// +// if (error) { +// if (exception instanceof SocketTimeoutException) { +// status.setErrorMessage(Language +// .text("contrib.errors.list_download.timeout")); +// } else { +// status.setErrorMessage(Language +// .text("contrib.errors.list_download")); +// } +// exception.printStackTrace(); +// retryConnectingButton.setVisible(true); +// +// } else { +// status.setMessage(Language.text("contrib.status.done")); +// retryConnectingButton.setVisible(false); // } // } -// } - - contribListing.updateInstalledList(contributions); - } - } - - - protected void downloadAndUpdateContributionListing() { - retryConnectingButton.setEnabled(false); - status.setMessage(Language.text("contrib.status.downloading_list")); - contribListing.downloadAvailableList(new ContribProgressBar(progressBar) { - - - @Override - public void startTask(String name, int maxValue) { - super.startTask(name, maxValue); - progressBar.setString(null); - } - - @Override - public void setProgress(int value) { - super.setProgress(value); -// int percent = 100 * value / this.max; - progressBar.setValue(value); - progressBar.setStringPainted(true); - status.setMessage(Language.text("contrib.status.downloading_list")); - } - - @Override - public void finishedAction() { - progressBar.setVisible(false); - - updateContributionListing(); - updateCategoryChooser(); - - retryConnectingButton.setEnabled(true); - - if (error) { - if (exception instanceof SocketTimeoutException) { - status.setErrorMessage(Language - .text("contrib.errors.list_download.timeout")); - } else { - status.setErrorMessage(Language - .text("contrib.errors.list_download")); - } - exception.printStackTrace(); - retryConnectingButton.setVisible(true); - - } else { - status.setMessage(Language.text("contrib.status.done")); - retryConnectingButton.setVisible(false); - } - } - }); - } - - - protected void setFilterText(String filter) { - if (filter == null || filter.isEmpty()) { - filterField.setText(""); - filterField.showingHint = true; - } else { - filterField.setText(filter); - filterField.showingHint = false; - } - filterField.applyFilter(); - } - - -// private JPanel getPlaceholder() { -// return contributionListPanel.statusPlaceholder; +// }); +// } +// +// protected void setFilterText(String filter) { +// if (filter == null || filter.isEmpty()) { +// filterField.setText(""); +// filterField.showingHint = true; +// } else { +// filterField.setText(filter); +// filterField.showingHint = false; +// } +// filterField.applyFilter(); +// } +// +//// private JPanel getPlaceholder() { +//// return contributionListPanel.statusPlaceholder; +//// } +// +// class FilterField extends JTextField { +// String filterHint; +// +// boolean showingHint; +// +// List filters; +// +// public FilterField() { +// super(Language.text("contrib.filter_your_search")); +// filterHint = Language.text("contrib.filter_your_search"); +// +// showingHint = true; +// filters = new ArrayList(); +// updateStyle(); +// +// addFocusListener(new FocusListener() { +// public void focusLost(FocusEvent focusEvent) { +// if (filterField.getText().isEmpty()) { +// showingHint = true; +// } +// updateStyle(); +// } +// +// public void focusGained(FocusEvent focusEvent) { +// if (showingHint) { +// showingHint = false; +// filterField.setText(""); +// } +// updateStyle(); +// } +// }); +// +// getDocument().addDocumentListener(new DocumentListener() { +// public void removeUpdate(DocumentEvent e) { +// applyFilter(); +// } +// +// public void insertUpdate(DocumentEvent e) { +// applyFilter(); +// } +// +// public void changedUpdate(DocumentEvent e) { +// applyFilter(); +// } +// }); +// } +// +// public void applyFilter() { +// String filter = filterField.getFilterText(); +// filter = filter.toLowerCase(); +// +// // Replace anything but 0-9, a-z, or : with a space +// filter = filter.replaceAll("[^\\x30-\\x39^\\x61-\\x7a^\\x3a]", " "); +// filters = Arrays.asList(filter.split(" ")); +// filterLibraries(category, filters, isCompatibilityFilter); +// +// contributionListPanel.updateColors(); +// } +// +// public String getFilterText() { +// return showingHint ? "" : getText(); +// } +// +// public void updateStyle() { +// if (showingHint) { +// setText(filterHint); +// // setForeground(UIManager.getColor("TextField.light")); // too light +// setForeground(Color.gray); +// setFont(getFont().deriveFont(Font.ITALIC)); +// } else { +// setForeground(UIManager.getColor("TextField.foreground")); +// setFont(getFont().deriveFont(Font.PLAIN)); +// } +// } // } - - - class FilterField extends JTextField { - String filterHint; - boolean showingHint; - List filters; - - public FilterField () { - super(Language.text("contrib.filter_your_search")); - filterHint = Language.text("contrib.filter_your_search"); - - showingHint = true; - filters = new ArrayList(); - updateStyle(); - - addFocusListener(new FocusListener() { - public void focusLost(FocusEvent focusEvent) { - if (filterField.getText().isEmpty()) { - showingHint = true; - } - updateStyle(); - } - - public void focusGained(FocusEvent focusEvent) { - if (showingHint) { - showingHint = false; - filterField.setText(""); - } - updateStyle(); - } - }); - - getDocument().addDocumentListener(new DocumentListener() { - public void removeUpdate(DocumentEvent e) { - applyFilter(); - } - - public void insertUpdate(DocumentEvent e) { - applyFilter(); - } - - public void changedUpdate(DocumentEvent e) { - applyFilter(); - } - }); - } - - public void applyFilter() { - String filter = filterField.getFilterText(); - filter = filter.toLowerCase(); - - // Replace anything but 0-9, a-z, or : with a space - filter = filter.replaceAll("[^\\x30-\\x39^\\x61-\\x7a^\\x3a]", " "); - filters = Arrays.asList(filter.split(" ")); - filterLibraries(category, filters, isCompatibilityFilter); - - contributionListPanel.updateColors(); - } - - public String getFilterText() { - return showingHint ? "" : getText(); - } - - public void updateStyle() { - if (showingHint) { - setText(filterHint); - // setForeground(UIManager.getColor("TextField.light")); // too light - setForeground(Color.gray); - setFont(getFont().deriveFont(Font.ITALIC)); - } else { - setForeground(UIManager.getColor("TextField.foreground")); - setFont(getFont().deriveFont(Font.PLAIN)); - } - } - } - public boolean hasAlreadyBeenOpened() { return dialog != null; diff --git a/app/src/processing/app/contrib/ContributionPanel.java b/app/src/processing/app/contrib/ContributionPanel.java index 3d937fd15..2110a3321 100644 --- a/app/src/processing/app/contrib/ContributionPanel.java +++ b/app/src/processing/app/contrib/ContributionPanel.java @@ -128,7 +128,7 @@ class ContributionPanel extends JPanel { installActionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { - listPanel.contribManager.status.clear(); + listPanel.contributionTab.status.clear(); isInstallInProgress = true; ((CardLayout) barButtonCardPane.getLayout()).show(barButtonCardPane, PROGRESS_BAR_CONSTRAINT); if (contrib instanceof AvailableContribution) { @@ -140,7 +140,7 @@ class ContributionPanel extends JPanel { undoActionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { - listPanel.contribManager.status.clear(); + listPanel.contributionTab.status.clear(); if (contrib instanceof LocalContribution) { LocalContribution installed = (LocalContribution) contrib; installed.setDeletionFlag(false); @@ -157,14 +157,14 @@ class ContributionPanel extends JPanel { } } } - listPanel.contribManager.restartButton.setVisible(toBeRestarted); + listPanel.contributionTab.restartButton.setVisible(toBeRestarted); } } }; removeActionListener = new ActionListener() { public void actionPerformed(ActionEvent arg) { - listPanel.contribManager.status.clear(); + listPanel.contributionTab.status.clear(); if (contrib.isInstalled() && contrib instanceof LocalContribution) { isRemoveInProgress = true; ((CardLayout) barButtonCardPane.getLayout()).show(barButtonCardPane, PROGRESS_BAR_CONSTRAINT); @@ -193,12 +193,12 @@ class ContributionPanel extends JPanel { reorganizePaneComponents(); setSelected(true); - ContributionManagerDialog manager = listPanel.contribManager; + ContributionTab contributionTab = listPanel.contributionTab; boolean isModeActive = false; if (contrib.getType() == ContributionType.MODE) { ModeContribution m = (ModeContribution) contrib; // TODO there's gotta be a cleaner way to do this accessor - for (Editor e : manager.editor.getBase().getEditors()) { + for (Editor e : contributionTab.editor.getBase().getEditors()) { //Iterator iter = listPanel.contribManager.editor.getBase().getEditors().iterator(); //while (iter.hasNext()) { //Editor e = iter.next(); @@ -211,13 +211,13 @@ class ContributionPanel extends JPanel { if (isModeActive) { updateButton.setEnabled(true); } else { - manager.restartButton.setVisible(true); + contributionTab.restartButton.setVisible(true); } } }; - ContributionManagerDialog manager = listPanel.contribManager; + ContributionTab contributionTab = listPanel.contributionTab; LocalContribution localContrib = (LocalContribution) contrib; - localContrib.removeContribution(manager.editor, monitor, manager.status); + localContrib.removeContribution(contributionTab.editor, monitor, contributionTab.status); } } }; @@ -248,7 +248,7 @@ class ContributionPanel extends JPanel { } else { final String msg = contrib.getName() + " is not compatible with this version of Processing"; - listPanel.contribManager.status.setErrorMessage(msg); + listPanel.contributionTab.status.setErrorMessage(msg); } } }); @@ -306,7 +306,7 @@ class ContributionPanel extends JPanel { updateButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - listPanel.contribManager.status.clear(); + listPanel.contributionTab.status.clear(); isUpdateInProgress = true; if (contrib.getType().requiresRestart()) { installRemoveButton.setEnabled(false); @@ -328,7 +328,7 @@ class ContributionPanel extends JPanel { public void cancel() { super.cancel(); resetInstallProgressBarState(); - listPanel.contribManager.status.setMessage(""); + listPanel.contributionTab.status.setMessage(""); isUpdateInProgress = false; installRemoveButton.setEnabled(true); if (contrib.isDeletionFlagged()) { @@ -343,7 +343,7 @@ class ContributionPanel extends JPanel { //Iterator iter = listPanel.contribManager.editor.getBase().getEditors().iterator(); //while (iter.hasNext()) { // TODO there's gotta be a cleaner way to do this accessor - Base base = listPanel.contribManager.editor.getBase(); + Base base = listPanel.contributionTab.editor.getBase(); for (Editor e : base.getEditors()) { //Editor e = iter.next(); if (e.getMode().equals(m.getMode())) { @@ -355,13 +355,13 @@ class ContributionPanel extends JPanel { if (isModeActive) { updateButton.setEnabled(true); } else { - listPanel.contribManager.restartButton.setVisible(true); + listPanel.contributionTab.restartButton.setVisible(true); } } }; ((LocalContribution) contrib) - .removeContribution(listPanel.contribManager.editor, - progress, listPanel.contribManager.status); + .removeContribution(listPanel.contributionTab.editor, + progress, listPanel.contributionTab.status); } else { updateButton.setEnabled(false); installRemoveButton.setEnabled(false); @@ -689,7 +689,7 @@ class ContributionPanel extends JPanel { private void installContribution(AvailableContribution info) { if (info.link == null) { - listPanel.contribManager.status.setErrorMessage(Language.interpolate("contrib.unsupported_operating_system", info.getType())); + listPanel.contributionTab.status.setErrorMessage(Language.interpolate("contrib.unsupported_operating_system", info.getType())); } else { installContribution(info, info.link); } @@ -729,7 +729,7 @@ class ContributionPanel extends JPanel { installRemoveButton.setEnabled(!contrib.isUpdateFlagged()); if (isError()) { - listPanel.contribManager.status.setErrorMessage(Language.text("contrib.download_error")); + listPanel.contributionTab.status.setErrorMessage(Language.text("contrib.download_error")); } ((CardLayout) barButtonCardPane.getLayout()).show(barButtonCardPane, BUTTON_CONSTRAINT); isInstallInProgress = false; @@ -744,10 +744,10 @@ class ContributionPanel extends JPanel { } }; - ContributionManager.downloadAndInstall(listPanel.contribManager.editor, + ContributionManager.downloadAndInstall(listPanel.contributionTab.editor, downloadUrl, ad, downloadProgress, installProgress, - listPanel.contribManager.status); + listPanel.contributionTab.status); } catch (MalformedURLException e) { Base.showWarning(Language.text("contrib.errors.install_failed"), diff --git a/app/src/processing/app/contrib/ContributionTab.java b/app/src/processing/app/contrib/ContributionTab.java new file mode 100644 index 000000000..a1de0c65a --- /dev/null +++ b/app/src/processing/app/contrib/ContributionTab.java @@ -0,0 +1,616 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2013 The Processing Foundation + Copyright (c) 2011-12 Ben Fry and Casey Reas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +package processing.app.contrib; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.File; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.ScrollPaneConstants; +import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +import processing.app.Base; +import processing.app.Editor; +import processing.app.Language; +import processing.app.Library; + + +public class ContributionTab { + static final String ANY_CATEGORY = Language.text("contrib.all"); + + JPanel panel; + ContributionType contributionType; + String title; + ContributionFilter filter; + JComboBox categoryChooser; + JScrollPane scrollPane; + ContributionListPanel contributionListPanel; + StatusPanel status; + FilterField filterField; + JButton restartButton; + JButton retryConnectingButton; + JProgressBar progressBar; + + // the calling editor, so updates can be applied + Editor editor; + String category; + String compatibleCheckboxLabel; + boolean isCompatibilityFilter; + ContributionListing contribListing; + + + public ContributionTab(ContributionType type) { + if (type == null) { + title = Language.text("contrib.manager_title.update"); + filter = ContributionType.createUpdateFilter(); + compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.update"); + } else { + if (type == ContributionType.MODE) { + title = Language.text("contrib.manager_title.mode"); + compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.mode"); + } + else if (type == ContributionType.TOOL) { + title = Language.text("contrib.manager_title.tool"); + compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.tool"); + } + else if (type == ContributionType.LIBRARY) { + title = Language.text("contrib.manager_title.library"); + compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.library"); + } + else if (type == ContributionType.EXAMPLES) { + title = Language.text("contrib.manager_title.examples"); + compatibleCheckboxLabel = Language.text("contrib.show_only_compatible.examples"); + } + + filter = type.createFilter(); + } + contribListing = ContributionListing.getInstance(); + contributionListPanel = new ContributionListPanel(this, filter); + contribListing.addContributionListener(contributionListPanel); + } + + + public boolean hasUpdates() { + return contribListing.hasUpdates(); + } + + + public boolean hasUpdates(Base base) { + return contribListing.hasUpdates(base); + } + + protected JPanel makeTextPanel(String text) { + JPanel panel = new JPanel(false); + JLabel filler = new JLabel(text); + filler.setHorizontalAlignment(JLabel.CENTER); + panel.setLayout(new GridLayout(1, 1)); + panel.add(filler); + return panel; + } + public void showFrame(final Editor editor) { + this.editor = editor; + + if (panel == null) { + makePanel(editor); + } + panel.setVisible(true); + contributionListPanel.grabFocus(); + + if (!contribListing.hasDownloadedLatestList() && contributionType == ContributionType.TOOL) { +// updateContributionListing(); + + } else { + downloadAndUpdateContributionListing(); + } + } + + + public JPanel makePanel(final Editor editor) { + panel = makeTextPanel("Panel #1"); + + restartButton = new JButton(Language.text("contrib.restart")); + restartButton.setVisible(false); + restartButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + + Iterator iter = editor.getBase().getEditors().iterator(); + while (iter.hasNext()) { + Editor ed = iter.next(); + if (ed.getSketch().isModified()) { + int option = Base + .showYesNoQuestion(editor, title, + Language.text("contrib.unsaved_changes"), + Language.text("contrib.unsaved_changes.prompt")); + + if (option == JOptionPane.NO_OPTION) + return; + else + break; + } + } + + // Thanks to http://stackoverflow.com/a/4160543 + StringBuilder cmd = new StringBuilder(); + cmd.append(System.getProperty("java.home") + File.separator + "bin" + + File.separator + "java "); + for (String jvmArg : ManagementFactory.getRuntimeMXBean() + .getInputArguments()) { + cmd.append(jvmArg + " "); + } + cmd.append("-cp ") + .append(ManagementFactory.getRuntimeMXBean().getClassPath()) + .append(" "); + cmd.append(Base.class.getName()); + + try { + Runtime.getRuntime().exec(cmd.toString()); + System.exit(0); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + }); + + retryConnectingButton = new JButton("Retry"); + retryConnectingButton.setVisible(false); + retryConnectingButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + // The message is set to null so that every time the retry button is hit + // no previous error is displayed in the status + status.setMessage(null); + downloadAndUpdateContributionListing(); + } + }); + + progressBar = new JProgressBar(); + progressBar.setVisible(true); + + createComponents(); + + return panel; + } + + + /** Creates and arranges the Swing components in the dialog. + * @param panel1 */ + private void createComponents() { + + Container pane = panel; +// pane.setLayout(new GridBagLayout()); +// +// { // Shows "Filter by Category" and the combo box for selecting a category +// GridBagConstraints c = new GridBagConstraints(); +// c.gridx = 0; +// c.gridy = 0; + pane.setLayout(new BorderLayout()); + + JPanel filterPanel = new JPanel(); + filterPanel.setLayout(new BoxLayout(filterPanel, BoxLayout.X_AXIS)); +// pane.add(filterPanel, c); + pane.add(filterPanel, BorderLayout.NORTH); + + filterPanel.add(Box.createHorizontalStrut(6)); + + JLabel categoryLabel = new JLabel(Language.text("contrib.category")); + filterPanel.add(categoryLabel); + + filterPanel.add(Box.createHorizontalStrut(5)); + + categoryChooser = new JComboBox(); + categoryChooser.setMaximumRowCount(20); + updateCategoryChooser(); +// filterPanel.add(categoryChooser, c); + filterPanel.add(categoryChooser); + categoryChooser.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + category = (String) categoryChooser.getSelectedItem(); + if (ContributionManagerDialog.ANY_CATEGORY.equals(category)) { + category = null; + } + filterLibraries(category, filterField.filters, isCompatibilityFilter); + contributionListPanel.updateColors(); + } + }); + + filterPanel.add(Box.createHorizontalStrut(5)); +// filterPanel.add(Box.createHorizontalGlue()); + filterField = new FilterField(); + filterPanel.add(filterField); + + filterPanel.add(Box.createHorizontalStrut(5)); + + final JCheckBox compatibleContrib = new JCheckBox(compatibleCheckboxLabel); + compatibleContrib.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent arg0) { + isCompatibilityFilter = compatibleContrib.isSelected(); + filterLibraries(category, filterField.filters, isCompatibilityFilter); + contributionListPanel.updateColors(); + } + }); + filterPanel.add(compatibleContrib); +// filterPanel.add(Box.createHorizontalGlue()); +// } + //filterPanel.setBorder(new EmptyBorder(13, 13, 13, 13)); + filterPanel.setBorder(new EmptyBorder(7, 7, 7, 7)); + +// { // The scroll area containing the contribution listing and the status bar. +// GridBagConstraints c = new GridBagConstraints(); +// c.fill = GridBagConstraints.BOTH; +// c.gridx = 0; +// c.gridy = 1; +// c.gridwidth = 2; +// c.weighty = 1; +// c.weightx = 1; + + scrollPane = new JScrollPane(); + scrollPane.setPreferredSize(new Dimension(300, 300)); + scrollPane.setViewportView(contributionListPanel); +// scrollPane.getViewport().setOpaque(true); +// scrollPane.getViewport().setBackground(contributionListPanel.getBackground()); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); +// scrollPane.setBorder(new EmptyBorder(0, 7, 0, 7)); + pane.add(scrollPane, BorderLayout.CENTER); + + pane.add(Box.createHorizontalStrut(10), BorderLayout.WEST); + pane.add(Box.createHorizontalStrut(10), BorderLayout.EAST); + + status = new StatusPanel(); +// status.setBorder(new EmptyBorder(7, 7, 7, 7)); + + JPanel statusRestartPane = new JPanel(); + statusRestartPane.setLayout(new BorderLayout()); + + statusRestartPane.setBorder(new EmptyBorder(7, 7, 7, 7)); + statusRestartPane.setOpaque(false); + + statusRestartPane.add(status, BorderLayout.WEST); + statusRestartPane.add(progressBar, BorderLayout.LINE_END); + + // Adding both of these to EAST shouldn't pose too much of a problem, + // since they can never get added together. + statusRestartPane.add(restartButton, BorderLayout.EAST); + statusRestartPane.add(retryConnectingButton, BorderLayout.EAST); + + pane.add(statusRestartPane, BorderLayout.SOUTH); + + +// status = new StatusPanel(); +// status.setBorder(BorderFactory.createEtchedBorder()); + +// final JLayeredPane layeredPane = new JLayeredPane(); +// layeredPane.add(scrollPane, JLayeredPane.DEFAULT_LAYER); +// layeredPane.add(status, JLayeredPane.PALETTE_LAYER); +// +// layeredPane.addComponentListener(new ComponentAdapter() { +// +// void resizeLayers() { +// scrollPane.setSize(layeredPane.getSize()); +// scrollPane.updateUI(); +// } +// +// public void componentShown(ComponentEvent e) { +// resizeLayers(); +// } +// +// public void componentResized(ComponentEvent arg0) { +// resizeLayers(); +// } +// }); +// +// final JViewport viewport = scrollPane.getViewport(); +// viewport.addComponentListener(new ComponentAdapter() { +// void resizeLayers() { +// status.setLocation(0, viewport.getHeight() - 18); +// +// Dimension d = viewport.getSize(); +// d.height = 20; +// d.width += 3; +// status.setSize(d); +// } +// public void componentShown(ComponentEvent e) { +// resizeLayers(); +// } +// public void componentResized(ComponentEvent e) { +// resizeLayers(); +// } +// }); +// +// pane.add(layeredPane, c); +// } + +// { // The filter text area +// GridBagConstraints c = new GridBagConstraints(); +// c.gridx = 0; +// c.gridy = 2; +// c.gridwidth = 2; +// c.weightx = 1; +// c.fill = GridBagConstraints.HORIZONTAL; +// filterField = new FilterField(); +// +// pane.add(filterField, c); +// } + + panel.setMinimumSize(new Dimension(450, 400)); + } + + + private void updateCategoryChooser() { + if (categoryChooser != null) { + ArrayList categories; + categoryChooser.removeAllItems(); + categories = new ArrayList(contribListing.getCategories(filter)); +// for (int i = 0; i < categories.size(); i++) { +// System.out.println(i + " category: " + categories.get(i)); +// } + Collections.sort(categories); +// categories.add(0, ContributionManagerDialog.ANY_CATEGORY); + boolean categoriesFound = false; + categoryChooser.addItem(ContributionManagerDialog.ANY_CATEGORY); + for (String s : categories) { + categoryChooser.addItem(s); + if (!s.equals("Unknown")) { + categoriesFound = true; + } + } + categoryChooser.setEnabled(categoriesFound); + } + } + + + protected void filterLibraries(String category, List filters) { + List filteredLibraries = + contribListing.getFilteredLibraryList(category, filters); + contributionListPanel.filterLibraries(filteredLibraries); + } + + + protected void filterLibraries(String category, List filters, boolean isCompatibilityFilter) { + List filteredLibraries = + contribListing.getFilteredLibraryList(category, filters); + filteredLibraries = contribListing.getCompatibleContributionList(filteredLibraries, isCompatibilityFilter); + contributionListPanel.filterLibraries(filteredLibraries); + } + + + protected void updateContributionListing() { + if (editor != null) { + ArrayList contributions = new ArrayList(); + + ArrayList libraries = + new ArrayList(editor.getMode().contribLibraries); + contributions.addAll(libraries); + + //ArrayList tools = editor.contribTools; + List tools = editor.getToolContribs(); + contributions.addAll(tools); + + List modes = editor.getBase().getModeContribs(); + contributions.addAll(modes); + + List examples = editor.getBase().getExampleContribs(); + contributions.addAll(examples); + +// ArrayList compilations = LibraryCompilation.list(libraries); +// +// // Remove libraries from the list that are part of a compilations +// for (LibraryCompilation compilation : compilations) { +// Iterator it = libraries.iterator(); +// while (it.hasNext()) { +// Library current = it.next(); +// if (compilation.getFolder().equals(current.getFolder().getParentFile())) { +// it.remove(); +// } +// } +// } + + contribListing.updateInstalledList(contributions); + } + } + + + protected void downloadAndUpdateContributionListing() { + retryConnectingButton.setEnabled(false); + status.setMessage(Language.text("contrib.status.downloading_list")); + contribListing.downloadAvailableList(new ContribProgressBar(progressBar) { + + + @Override + public void startTask(String name, int maxValue) { + super.startTask(name, maxValue); + progressBar.setString(null); + } + + @Override + public void setProgress(int value) { + super.setProgress(value); +// int percent = 100 * value / this.max; + progressBar.setValue(value); + progressBar.setStringPainted(true); + status.setMessage(Language.text("contrib.status.downloading_list")); + } + + @Override + public void finishedAction() { + progressBar.setVisible(false); + + updateContributionListing(); + updateCategoryChooser(); + + retryConnectingButton.setEnabled(true); + + if (error) { + if (exception instanceof SocketTimeoutException) { + status.setErrorMessage(Language + .text("contrib.errors.list_download.timeout")); + } else { + status.setErrorMessage(Language + .text("contrib.errors.list_download")); + } + exception.printStackTrace(); + retryConnectingButton.setVisible(true); + + } else { + status.setMessage(Language.text("contrib.status.done")); + retryConnectingButton.setVisible(false); + } + } + }); + } + + + protected void setFilterText(String filter) { + if (filter == null || filter.isEmpty()) { + filterField.setText(""); + filterField.showingHint = true; + } else { + filterField.setText(filter); + filterField.showingHint = false; + } + filterField.applyFilter(); + } + + +// private JPanel getPlaceholder() { +// return contributionListPanel.statusPlaceholder; +// } + + + class FilterField extends JTextField { + String filterHint; + boolean showingHint; + List filters; + + public FilterField () { + super(Language.text("contrib.filter_your_search")); + filterHint = Language.text("contrib.filter_your_search"); + + showingHint = true; + filters = new ArrayList(); + updateStyle(); + + addFocusListener(new FocusListener() { + public void focusLost(FocusEvent focusEvent) { + if (filterField.getText().isEmpty()) { + showingHint = true; + } + updateStyle(); + } + + public void focusGained(FocusEvent focusEvent) { + if (showingHint) { + showingHint = false; + filterField.setText(""); + } + updateStyle(); + } + }); + + getDocument().addDocumentListener(new DocumentListener() { + public void removeUpdate(DocumentEvent e) { + applyFilter(); + } + + public void insertUpdate(DocumentEvent e) { + applyFilter(); + } + + public void changedUpdate(DocumentEvent e) { + applyFilter(); + } + }); + } + + public void applyFilter() { + String filter = filterField.getFilterText(); + filter = filter.toLowerCase(); + + // Replace anything but 0-9, a-z, or : with a space + filter = filter.replaceAll("[^\\x30-\\x39^\\x61-\\x7a^\\x3a]", " "); + filters = Arrays.asList(filter.split(" ")); + filterLibraries(category, filters, isCompatibilityFilter); + + contributionListPanel.updateColors(); + } + + public String getFilterText() { + return showingHint ? "" : getText(); + } + + public void updateStyle() { + if (showingHint) { + setText(filterHint); + // setForeground(UIManager.getColor("TextField.light")); // too light + setForeground(Color.gray); + setFont(getFont().deriveFont(Font.ITALIC)); + } else { + setForeground(UIManager.getColor("TextField.foreground")); + setFont(getFont().deriveFont(Font.PLAIN)); + } + } + } + + + public boolean hasAlreadyBeenOpened() { + return panel != null; + } +}