diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/Bundle.properties --- a/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/Bundle.properties Fri Jul 04 17:07:19 2008 +0200 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/Bundle.properties Tue Jul 08 16:11:03 2008 +0200 @@ -1,6 +1,9 @@ CTL_CreateViewAction=Create view LBL_process_problem=There was a problem creating the grails process: CTL_GenerateAllAction=Generate all +CTL_ManagePluginsAction=Grails Plugins +CTL_Close=Close +CTL_PluginTitle=Grails Plugins MSG_Runtime_Not_Configured=The Grails Home has not been set.
\ Use menu Tools/Options/Groovy to set the environment. \ No newline at end of file diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/ManagePluginsAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/ManagePluginsAction.java Tue Jul 08 16:11:03 2008 +0200 @@ -0,0 +1,94 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.groovy.grailsproject.actions; + +import java.awt.Dialog; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import org.netbeans.api.project.Project; +import org.netbeans.modules.groovy.grailsproject.GrailsProject; +import org.netbeans.modules.groovy.grailsproject.ui.GrailsPluginsPanel; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.nodes.Node; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; + +/** + * + * @author David Calavera + */ +public class ManagePluginsAction extends AbstractAction { + + GrailsProject project; + + public ManagePluginsAction(Project project) { + super(NbBundle.getMessage(ManagePluginsAction.class, "CTL_ManagePluginsAction")); + this.project = (GrailsProject) project; + } + + public boolean isEnabled() { + return true; + } + + public void actionPerformed(ActionEvent arg0) { + GrailsPluginsPanel panel = new GrailsPluginsPanel(project); + javax.swing.JButton close = + new javax.swing.JButton(NbBundle.getMessage(ManagePluginsAction.class, "CTL_Close")); + close.getAccessibleContext() + .setAccessibleDescription(NbBundle.getMessage(ManagePluginsAction.class, "CTL_Close")); + + DialogDescriptor descriptor = + new DialogDescriptor(panel, NbBundle.getMessage(ManagePluginsAction.class, "CTL_PluginTitle"), + true, new Object[] { close }, close, DialogDescriptor.DEFAULT_ALIGN, + new HelpCtx(GrailsPluginsPanel.class), null); // NOI18N + Dialog dlg = null; + + try { + dlg = DialogDisplayer.getDefault().createDialog(descriptor); + dlg.setVisible(true); + } finally { + if (dlg != null) { + dlg.dispose(); + } + } + } + +} diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/Bundle.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/Bundle.properties Tue Jul 08 16:11:03 2008 +0200 @@ -0,0 +1,4 @@ +PluginPleaseWait=Installing {0} plugin +Installation=Installing plugins +CTL_Close=Close +CTL_Cancel=Cancel \ No newline at end of file diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/GrailsPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/GrailsPlugin.java Tue Jul 08 16:11:03 2008 +0200 @@ -0,0 +1,109 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.groovy.grailsproject.plugins; + +/** + * plugin pojo class + * + * @author David Calavera + */ +public class GrailsPlugin implements Comparable { + private final String name; + private final String version; + private final String description; + + public GrailsPlugin(String name, String version, String description) { + this.name = name; + this.version = version; + this.description = description; + } + + public String getName() { + return name; + } + + public String getVersion() { + return version; + } + + public String getDescription() { + return description; + } + + @Override + public String toString() { + String toS = getName(); + if (getVersion() != null && getVersion().trim().length() > 0) { + toS += "(" + getVersion().trim() + ")"; + } + if (getDescription() != null && getDescription().trim().length() > 0 + && !getDescription().trim().equals("No description available")) { + toS += " -- " + getDescription().trim(); + } + return toS; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final GrailsPlugin other = (GrailsPlugin) obj; + if (this.name != other.name && (this.name == null || !this.name.equalsIgnoreCase(other.name))) { + return false; + } + return true; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 97 * hash + (this.name != null ? this.name.toUpperCase().hashCode() : 0); + return hash; + } + + public int compareTo(GrailsPlugin o) { + return name.compareToIgnoreCase(o.name); + } + +} diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/GrailsPluginsManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/GrailsPluginsManager.java Tue Jul 08 16:11:03 2008 +0200 @@ -0,0 +1,304 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.groovy.grailsproject.plugins; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.Dialog; +import java.lang.String; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JButton; +import javax.swing.SwingUtilities; +import org.netbeans.api.project.ProjectInformation; +import org.netbeans.modules.extexecution.api.ExecutionDescriptor; +import org.netbeans.modules.extexecution.api.ExecutionService; +import org.netbeans.modules.extexecution.api.input.InputProcessor; +import org.netbeans.modules.extexecution.api.input.InputProcessors; +import org.netbeans.modules.extexecution.api.input.LineProcessor; +import org.netbeans.modules.groovy.grails.api.ExecutionSupport; +import org.netbeans.modules.groovy.grails.api.GrailsProjectConfig; +import org.netbeans.modules.groovy.grailsproject.GrailsProject; +import org.netbeans.modules.groovy.grailsproject.actions.RefreshProjectRunnable; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.filesystems.FileObject; +import org.openide.util.Exceptions; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.RequestProcessor; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * + * @author David Calavera + */ +public class GrailsPluginsManager { + + private final GrailsProject project; + + private GrailsPluginsManager(GrailsProject project) { + this.project = project; + } + + public static GrailsPluginsManager getInstance(GrailsProject project) { + return new GrailsPluginsManager(project); + } + + public List refreshAvailablePlugins() { + String command = "list-plugins"; // NOI18N + + ProjectInformation inf = project.getLookup().lookup(ProjectInformation.class); + String displayName = inf.getDisplayName() + " (" + command + ")"; // NOI18N + + Callable callable = ExecutionSupport.getInstance().createSimpleCommand( + command, GrailsProjectConfig.forProject(project)); + + final PluginProcessor processor = new PluginProcessor(); + ExecutionDescriptor.Builder builder = new ExecutionDescriptor.Builder(); + builder.frontWindow(true); + builder.outProcessorFactory(new ExecutionDescriptor.InputProcessorFactory() { + public InputProcessor newInputProcessor() { + return InputProcessors.bridge(processor); + } + }); + + ExecutionService service = ExecutionService.newService(callable, builder.create(), displayName); + try { + service.run().get(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex.getCause()); + } + + return processor.getPlugins(); + } + + public List refreshInstalledPlugins() { + List plugins = new ArrayList(); + try { + FileObject pluginsDir = project.getProjectDirectory().getFileObject("plugins"); //NOI18N + if (pluginsDir != null && pluginsDir.isFolder()) { + pluginsDir.refresh(); + for (FileObject child : pluginsDir.getChildren()) { + if (child.isFolder()) { + FileObject descriptor = child.getFileObject("plugin.xml"); //NOI18N + if (descriptor != null && descriptor.canRead()) { + Document doc = XMLUtil.parse(new InputSource(descriptor.getInputStream()), + false, false, null, null); + Node root = doc.getFirstChild(); + String name = root.getAttributes().getNamedItem("name").getTextContent(); //NOI18N + String version = null; + String description = null; + if (root.getAttributes().getNamedItem("version") != null) { //NOI18N + version = root.getAttributes().getNamedItem("version").getTextContent(); //NOI18N + } + if (doc.getElementsByTagName("title") != null + && doc.getElementsByTagName("title").getLength() > 0) { //NOI18N + description = doc.getElementsByTagName("title") + .item(0).getTextContent(); //NOI18N + } + + plugins.add(new GrailsPlugin(name, version, description)); + } + } + } + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + Collections.sort(plugins); + return plugins; + } + + public boolean uninstallPlugins(Object[] selectedPlugins) { + if (selectedPlugins != null && selectedPlugins.length > 0) { + FileObject pluginsDir = project.getProjectDirectory().getFileObject("plugins"); //NO I18N + if (pluginsDir != null && pluginsDir.isFolder() && pluginsDir.canWrite()) { + pluginsDir.refresh(); + try { + for (Object obj : selectedPlugins) { + GrailsPlugin plugin = (GrailsPlugin) obj; + String pluginName = plugin.getName() + "-" + plugin.getVersion(); + FileObject pluginDir = pluginsDir.getFileObject(pluginName); + if (pluginDir != null && pluginDir.isValid()) { + pluginDir.delete(); + } + FileObject pluginZipFile = pluginsDir.getFileObject("grails-" + pluginName + ".zip"); + if (pluginZipFile != null && pluginZipFile.isValid()) { + pluginZipFile.delete(); + } + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + } + return true; + } + + public boolean installPlugins(final Object[] selectedPlugins) { + boolean installed = true; + if (selectedPlugins != null && selectedPlugins.length > 0) { + final JButton closeButton = new JButton(NbBundle.getMessage(GrailsPluginsManager.class, "CTL_Close")); + final JButton cancelButton = + new JButton(NbBundle.getMessage(GrailsPluginsManager.class, "CTL_Cancel")); + closeButton.getAccessibleContext() + .setAccessibleDescription(NbBundle.getMessage(GrailsPluginsManager.class, "CTL_Close")); + + Object[] options = new Object[] { closeButton, cancelButton }; + closeButton.setEnabled(false); + + String title = NbBundle.getMessage(GrailsPluginsManager.class, "Installation"); + + for (Object obj : selectedPlugins) { + final GrailsPlugin plugin = (GrailsPlugin) obj; + + final InstallingPluginPanel progress = new InstallingPluginPanel(NbBundle.getMessage(GrailsPluginsManager.class, "PluginPleaseWait", plugin.getName())); + DialogDescriptor descriptor = new DialogDescriptor(progress, title, true, options, closeButton, + DialogDescriptor.DEFAULT_ALIGN, new HelpCtx(InstallingPluginPanel.class), null); // NOI18N + descriptor.setModal(true); + final Dialog dlg = DialogDisplayer.getDefault().createDialog(descriptor); + + closeButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + dlg.setVisible(false); + dlg.dispose(); + } + }); + + final String command = "install-plugin"; // NOI18N + + Runnable runner = new Runnable() { + public void run() { + ProjectInformation inf = project.getLookup().lookup(ProjectInformation.class); + String displayName = inf.getDisplayName() + " (" + command + ")"; // NOI18N + + Callable callable = ExecutionSupport.getInstance().createSimpleCommand( + command, GrailsProjectConfig.forProject(project), plugin.getName(), plugin.getVersion()); + + ExecutionDescriptor.Builder builder = new ExecutionDescriptor.Builder(); + builder.frontWindow(true); + builder.postExecution(new RefreshProjectRunnable(project)); + + ExecutionService service = ExecutionService.newService(callable, builder.create(), displayName); + final Future future = service.run(); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ev) { + future.cancel(true); + } + }); + + try { + future.get(); + } catch (InterruptedException ex) { + //do nothing + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } catch (CancellationException ex) { + //do nothing + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + dlg.setVisible(false); + dlg.dispose(); + } + }); + } + }; + RequestProcessor.getDefault().post(runner, 10); + dlg.setVisible(true); + + if (descriptor.getValue() == cancelButton) { + cleanUninstalledPlugin(dlg, plugin); + installed = false; + } + } + } + return installed; + } + + private void cleanUninstalledPlugin(Dialog dlg, GrailsPlugin plugin) { + uninstallPlugins(new Object[]{plugin}); + dlg.setVisible(false); + dlg.dispose(); + } + + private static class PluginProcessor implements LineProcessor { + + private final List plugins = Collections.synchronizedList(new ArrayList()); + + private static final Pattern PLUGIN_PATTERN = Pattern.compile("(.+)[\\s]+<([\\w\\s.-]+)>[\\s]+--(.+)"); + public void processLine(String line) { + GrailsPlugin plugin = null; + Matcher matcher = PLUGIN_PATTERN.matcher(line); + if (matcher.matches()) { + if (!"no releases".equals(matcher.group(2))) { //NO I18N + plugin = new GrailsPlugin(matcher.group(1).trim(), matcher.group(2), matcher.group(3)); + } + } + if (plugin != null) { + plugins.add(plugin); + } + } + + public void reset() { + // noop + } + + public List getPlugins() { + return plugins; + } + + } +} diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/InstallingPluginPanel.form --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/InstallingPluginPanel.form Tue Jul 08 16:11:03 2008 +0200 @@ -0,0 +1,55 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/InstallingPluginPanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/InstallingPluginPanel.java Tue Jul 08 16:11:03 2008 +0200 @@ -0,0 +1,66 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.netbeans.modules.groovy.grailsproject.plugins; + +/** + * @author David Calavera + */ +public class InstallingPluginPanel extends javax.swing.JPanel { + + public InstallingPluginPanel(String message) { + initComponents(); + jLabel1.setText(message); + } + + public void done(String message) { + progressBar.setIndeterminate(false); + progressBar.getModel().setValue(progressBar.getModel().getMaximum()); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the FormEditor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + progressBar = new javax.swing.JProgressBar(); + jLabel1 = new javax.swing.JLabel(); + + progressBar.setIndeterminate(true); + + jLabel1.setText("Plugin"); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(progressBar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE) + .add(jLabel1)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .add(12, 12, 12) + .add(jLabel1) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(progressBar, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addContainerGap(36, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JProgressBar progressBar; + // End of variables declaration//GEN-END:variables + +} diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/Bundle.properties --- a/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/Bundle.properties Fri Jul 04 17:07:19 2008 +0200 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/Bundle.properties Tue Jul 08 16:11:03 2008 +0200 @@ -1,3 +1,4 @@ +FetchingPlugins=Please Wait... Fetching list of plugins from server GeneralCustomizerPanel.projectFolderLabel.text=Project Directory: GeneralCustomizerPanel.projectFolderTextField.text= GeneralCustomizerPanel.activeGrailsEnvironmentLabel.text=Active Grails Enviroment: diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsLogicalViewProvider.java --- a/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsLogicalViewProvider.java Fri Jul 04 17:07:19 2008 +0200 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsLogicalViewProvider.java Tue Jul 08 16:11:03 2008 +0200 @@ -51,6 +51,7 @@ import org.netbeans.modules.groovy.grailsproject.GrailsActionProvider; import org.netbeans.modules.groovy.grailsproject.GrailsProject; import org.netbeans.modules.groovy.grailsproject.actions.GrailsCommandAction; +import org.netbeans.modules.groovy.grailsproject.actions.ManagePluginsAction; import org.netbeans.spi.project.ActionProvider; import org.netbeans.spi.project.ui.LogicalViewProvider; import org.netbeans.spi.project.ui.support.CommonProjectActions; @@ -130,6 +131,8 @@ actions.add(null); actions.add(ProjectSensitiveActions.projectCommandAction(GrailsActionProvider.COMMAND_GRAILS_SHELL, NbBundle.getMessage(GrailsLogicalViewProvider.class, "LBL_ShellAction_Name"), null)); + actions.add(null); + actions.add(new ManagePluginsAction(project)); actions.add(null); actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_RUN, NbBundle.getMessage(GrailsLogicalViewProvider.class, "LBL_RunAction_Name"), null)); diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsPluginsPanel.form --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsPluginsPanel.form Tue Jul 08 16:11:03 2008 +0200 @@ -0,0 +1,207 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsPluginsPanel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsPluginsPanel.java Tue Jul 08 16:11:03 2008 +0200 @@ -0,0 +1,353 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.netbeans.modules.groovy.grailsproject.ui; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.DefaultListModel; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import org.netbeans.api.project.Project; +import org.netbeans.modules.groovy.grailsproject.GrailsProject; +import org.netbeans.modules.groovy.grailsproject.plugins.GrailsPlugin; +import org.netbeans.modules.groovy.grailsproject.plugins.GrailsPluginsManager; +import org.openide.util.NbBundle; +import org.openide.util.RequestProcessor; + +/** + * @author David Calavera + */ +public class GrailsPluginsPanel extends javax.swing.JPanel { + + private GrailsProject project; + private GrailsPluginsManager pluginsManager; + + private boolean installedInitialized; + private boolean installedModified; + private boolean availablePluginsInitialized; + private boolean availableModified; + private List installedPluginsList = new ArrayList(); + private List availablePluginsList = new ArrayList(); + + /** Creates new customizer GrailsPluginsPanel */ + public GrailsPluginsPanel(Project project) { + initComponents(); + this.project = (GrailsProject) project; + this.pluginsManager = GrailsPluginsManager.getInstance(this.project); + } + + /** Refresh the installed plugin list */ + private void refreshInstalled() { + assert SwingUtilities.isEventDispatchThread(); + final DefaultListModel model = new DefaultListModel(); + reloadInstalledButton.setEnabled(false); + installedPluginsList = pluginsManager.refreshInstalledPlugins(); + for (GrailsPlugin plugin : installedPluginsList) { + model.addElement(plugin); + } + + installedPlugins.clearSelection(); + installedPlugins.setModel(model); + installedPlugins.invalidate(); + installedPlugins.repaint(); + reloadInstalledButton.setEnabled(true); + } + + private void refreshAvailable() { + assert SwingUtilities.isEventDispatchThread(); + + Runnable runner = new Runnable() { + + public void run() { + synchronized(GrailsPluginsPanel.this) { + final DefaultListModel model = new DefaultListModel(); + availablePluginsList = pluginsManager.refreshAvailablePlugins(); + + for (GrailsPlugin plugin : availablePluginsList) { + if (!installedPluginsList.contains(plugin)) { + model.addElement(plugin); + } + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + availablePlugins.clearSelection(); + availablePlugins.setModel(model); + availablePlugins.invalidate(); + availablePlugins.repaint(); + reloadAvailableButton.setEnabled(true); + } + }); + } + } + }; + + reloadAvailableButton.setEnabled(false); + DefaultListModel model = new DefaultListModel(); + model.addElement(NbBundle.getMessage(GrailsPluginsPanel.class, "FetchingPlugins")); + availablePlugins.setModel(model); + + RequestProcessor.getDefault().post(runner); + } + + private void uninstallPlugins() { + Object[] selected = installedPlugins.getSelectedValues(); + pluginsManager.uninstallPlugins(selected); + + refreshInstalled(); + availableModified = true; + } + + private void installPlugins() { + installButton.setEnabled(false); + + Object[] selected = availablePlugins.getSelectedValues(); + availableModified = pluginsManager.installPlugins(selected); + + refreshInstalled(); + + pluginsPanel.setSelectedComponent(installedPanel); + pluginsPanel.invalidate(); + pluginsPanel.repaint(); + + installButton.setEnabled(true); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the FormEditor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + pluginsPanel = new javax.swing.JTabbedPane(); + installedPanel = new javax.swing.JPanel(); + reloadInstalledButton = new javax.swing.JButton(); + jScrollPane1 = new javax.swing.JScrollPane(); + installedPlugins = new javax.swing.JList(); + uninstallButton = new javax.swing.JButton(); + newPluginPanel = new javax.swing.JPanel(); + jScrollPane2 = new javax.swing.JScrollPane(); + availablePlugins = new javax.swing.JList(); + installButton = new javax.swing.JButton(); + reloadAvailableButton = new javax.swing.JButton(); + + installedPanel.addComponentListener(new java.awt.event.ComponentAdapter() { + public void componentShown(java.awt.event.ComponentEvent evt) { + installedPanelComponentShown(evt); + } + }); + + reloadInstalledButton.setText("Reload Plugins"); + reloadInstalledButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + reloadInstalledButtonActionPerformed(evt); + } + }); + + installedPlugins.setModel(new javax.swing.AbstractListModel() { + public int getSize() { return installedPluginsList.size(); } + public Object getElementAt(int arg0) { return installedPluginsList.get(arg0); } + }); + installedPlugins.addListSelectionListener(new javax.swing.event.ListSelectionListener() { + public void valueChanged(javax.swing.event.ListSelectionEvent evt) { + installedPluginsValueChanged(evt); + } + }); + jScrollPane1.setViewportView(installedPlugins); + + uninstallButton.setText("Uninstall"); + uninstallButton.setEnabled(false); + uninstallButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + uninstallButtonActionPerformed(evt); + } + }); + + org.jdesktop.layout.GroupLayout installedPanelLayout = new org.jdesktop.layout.GroupLayout(installedPanel); + installedPanel.setLayout(installedPanelLayout); + installedPanelLayout.setHorizontalGroup( + installedPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(installedPanelLayout.createSequentialGroup() + .addContainerGap() + .add(installedPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(uninstallButton) + .add(reloadInstalledButton) + .add(org.jdesktop.layout.GroupLayout.TRAILING, installedPanelLayout.createSequentialGroup() + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 728, Short.MAX_VALUE))) + .addContainerGap()) + ); + installedPanelLayout.setVerticalGroup( + installedPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(installedPanelLayout.createSequentialGroup() + .addContainerGap() + .add(reloadInstalledButton) + .add(17, 17, 17) + .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 355, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 35, Short.MAX_VALUE) + .add(uninstallButton) + .addContainerGap()) + ); + + pluginsPanel.addTab("Installed", installedPanel); + + newPluginPanel.addComponentListener(new java.awt.event.ComponentAdapter() { + public void componentShown(java.awt.event.ComponentEvent evt) { + newPluginPanelComponentShown(evt); + } + }); + + availablePlugins.setModel(new javax.swing.AbstractListModel() { + public int getSize() { return availablePluginsList.size(); } + public Object getElementAt(int arg0) { return availablePluginsList.get(arg0); } + }); + availablePlugins.addListSelectionListener(new javax.swing.event.ListSelectionListener() { + public void valueChanged(javax.swing.event.ListSelectionEvent evt) { + availablePluginsValueChanged(evt); + } + }); + jScrollPane2.setViewportView(availablePlugins); + + installButton.setText("Install"); + installButton.setEnabled(false); + installButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + installButtonActionPerformed(evt); + } + }); + + reloadAvailableButton.setText("Reload Plugins"); + reloadAvailableButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + reloadAvailableButtonActionPerformed(evt); + } + }); + + org.jdesktop.layout.GroupLayout newPluginPanelLayout = new org.jdesktop.layout.GroupLayout(newPluginPanel); + newPluginPanel.setLayout(newPluginPanelLayout); + newPluginPanelLayout.setHorizontalGroup( + newPluginPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(newPluginPanelLayout.createSequentialGroup() + .addContainerGap() + .add(newPluginPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 728, Short.MAX_VALUE) + .add(installButton) + .add(reloadAvailableButton)) + .addContainerGap()) + ); + newPluginPanelLayout.setVerticalGroup( + newPluginPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(org.jdesktop.layout.GroupLayout.TRAILING, newPluginPanelLayout.createSequentialGroup() + .addContainerGap() + .add(reloadAvailableButton) + .add(17, 17, 17) + .add(jScrollPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 355, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 35, Short.MAX_VALUE) + .add(installButton) + .addContainerGap()) + ); + + pluginsPanel.addTab("New plugins", newPluginPanel); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(pluginsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 757, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .addContainerGap() + .add(pluginsPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 508, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + +private void uninstallButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_uninstallButtonActionPerformed + uninstallPlugins(); +}//GEN-LAST:event_uninstallButtonActionPerformed + +private void reloadAvailableButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reloadAvailableButtonActionPerformed + refreshAvailable(); +}//GEN-LAST:event_reloadAvailableButtonActionPerformed + +private void reloadInstalledButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reloadInstalledButtonActionPerformed + refreshInstalled(); +}//GEN-LAST:event_reloadInstalledButtonActionPerformed + +private void installButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_installButtonActionPerformed + installPlugins(); +}//GEN-LAST:event_installButtonActionPerformed + +private void installedPluginsValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_installedPluginsValueChanged + uninstallButton.setEnabled(installedPlugins.getSelectedIndices() != null + && installedPlugins.getSelectedIndices().length > 0); +}//GEN-LAST:event_installedPluginsValueChanged + +private void availablePluginsValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_availablePluginsValueChanged + installButton.setEnabled(availablePlugins.getSelectedIndices() != null + && availablePlugins.getSelectedIndices().length > 0); + //waiting the plugin list from the server + if (availablePlugins.getSelectedIndices().length == 1 && + availablePlugins.getSelectedValue().equals( + NbBundle.getMessage(GrailsPluginsPanel.class, "FetchingPlugins"))) { + installButton.setEnabled(false); + } +}//GEN-LAST:event_availablePluginsValueChanged + +private void installedPanelComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_installedPanelComponentShown + assert SwingUtilities.isEventDispatchThread(); + + if (!installedInitialized) { + installedInitialized = true; + installedPlugins.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + + installedModified = true; + } else installedModified = false; + + if (installedModified) { + refreshInstalled(); + } +}//GEN-LAST:event_installedPanelComponentShown + +private void newPluginPanelComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_newPluginPanelComponentShown + assert SwingUtilities.isEventDispatchThread(); + + if (!availablePluginsInitialized) { + availablePluginsInitialized = true; + availablePlugins.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + + availableModified = true; + } + + if (availableModified) { + refreshAvailable(); + availableModified = false; + } +}//GEN-LAST:event_newPluginPanelComponentShown + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JList availablePlugins; + private javax.swing.JButton installButton; + private javax.swing.JPanel installedPanel; + private javax.swing.JList installedPlugins; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JPanel newPluginPanel; + private javax.swing.JTabbedPane pluginsPanel; + private javax.swing.JButton reloadAvailableButton; + private javax.swing.JButton reloadInstalledButton; + private javax.swing.JButton uninstallButton; + // End of variables declaration//GEN-END:variables + +}