|
From: <caw...@us...> - 2007-05-11 17:13:56
|
Revision: 2461
http://svn.sourceforge.net/rubyeclipse/?rev=2461&view=rev
Author: cawilliams
Date: 2007-05-11 10:13:55 -0700 (Fri, 11 May 2007)
Log Message:
-----------
add new gem installer/manager view
Modified Paths:
--------------
trunk/com.aptana.rdt/META-INF/MANIFEST.MF
trunk/com.aptana.rdt/plugin.xml
Added Paths:
-----------
trunk/com.aptana.rdt/icons/add.gif
trunk/com.aptana.rdt/icons/nav_refresh.gif
trunk/com.aptana.rdt/icons/remove.gif
trunk/com.aptana.rdt/icons/rubygems.png
trunk/com.aptana.rdt/icons/upgrade.gif
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/Gem.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/GemManager.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/GemManagerContentHandler.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/LogicalGem.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/InstallGemActionDelegate.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/RefreshGemsActionDelegate.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/RemoveGemActionDelegate.java
trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/UpdateGemActionDelegate.java
trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/
trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemContentProvider.java
trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemLabelProvider.java
trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsMessages.java
trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsMessages.properties
trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsView.java
trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/InstallGemDialog.java
Modified: trunk/com.aptana.rdt/META-INF/MANIFEST.MF
===================================================================
--- trunk/com.aptana.rdt/META-INF/MANIFEST.MF 2007-05-10 19:36:12 UTC (rev 2460)
+++ trunk/com.aptana.rdt/META-INF/MANIFEST.MF 2007-05-11 17:13:55 UTC (rev 2461)
@@ -11,11 +11,14 @@
com.aptana.rdt.internal.parser.warnings,
com.aptana.rdt.internal.ui.preferences,
com.aptana.rdt.internal.ui.text.ruby.hover
-Require-Bundle: org.rubypeople.rdt.ui,
- org.eclipse.ui.intro,
+Require-Bundle: org.eclipse.core.resources,
+ org.eclipse.core.runtime,
org.eclipse.jface.text,
org.eclipse.ui,
+ org.eclipse.ui.intro,
+ org.eclipse.debug.core,
+ org.eclipse.debug.ui,
+ org.jruby,
org.rubypeople.rdt.core,
- org.eclipse.core.runtime,
- org.jruby,
- org.eclipse.core.resources
+ org.rubypeople.rdt.launching,
+ org.rubypeople.rdt.ui
Added: trunk/com.aptana.rdt/icons/add.gif
===================================================================
(Binary files differ)
Property changes on: trunk/com.aptana.rdt/icons/add.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/com.aptana.rdt/icons/nav_refresh.gif
===================================================================
(Binary files differ)
Property changes on: trunk/com.aptana.rdt/icons/nav_refresh.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/com.aptana.rdt/icons/remove.gif
===================================================================
(Binary files differ)
Property changes on: trunk/com.aptana.rdt/icons/remove.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/com.aptana.rdt/icons/rubygems.png
===================================================================
(Binary files differ)
Property changes on: trunk/com.aptana.rdt/icons/rubygems.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/com.aptana.rdt/icons/upgrade.gif
===================================================================
(Binary files differ)
Property changes on: trunk/com.aptana.rdt/icons/upgrade.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: trunk/com.aptana.rdt/plugin.xml
===================================================================
--- trunk/com.aptana.rdt/plugin.xml 2007-05-10 19:36:12 UTC (rev 2460)
+++ trunk/com.aptana.rdt/plugin.xml 2007-05-11 17:13:55 UTC (rev 2461)
@@ -64,6 +64,12 @@
class="com.aptana.rdt.internal.ui.infoviews.RubyStdLibAPIView"
id="com.aptana.rdt.ui.views.RubyStdLibAPIView">
</view>
+ <view
+ category="org.rubypeople.rdt.ui.ruby"
+ class="com.aptana.rdt.ui.gems.GemsView"
+ icon="icons/rubygems.png"
+ id="com.aptana.gems.ui.ViewGems"
+ name="RubyGems"/>
</extension>
<extension point="org.eclipse.ui.perspectiveExtensions">
@@ -160,8 +166,47 @@
<argument prefKey="com.aptana.rdt.compiler.problem.maxReturns"/>
</error>
</extension>
+
+ <extension
+ point="org.eclipse.ui.viewActions">
+ <viewContribution
+ id="com.aptana.gems.ui.ViewActions"
+ targetID="com.aptana.gems.ui.ViewGems">
+ <action
+ class="com.aptana.rdt.internal.ui.actions.InstallGemActionDelegate"
+ icon="icons/add.gif"
+ id="com.aptana.gems.ui.ActionInstallGem"
+ label="Install"
+ style="push"
+ toolbarPath="additions"
+ tooltip="Install"/>
+ <action
+ class="com.aptana.rdt.internal.ui.actions.RemoveGemActionDelegate"
+ icon="icons/remove.gif"
+ id="com.aptana.gems.ui.ActionRemoveGem"
+ label="Remove"
+ style="push"
+ toolbarPath="additions"
+ tooltip="Remove"/>
+ <action
+ class="com.aptana.rdt.internal.ui.actions.RefreshGemsActionDelegate"
+ icon="icons/nav_refresh.gif"
+ id="com.aptana.gems.ui.ActionRefreshGems"
+ label="Refresh"
+ style="push"
+ toolbarPath="additions"
+ tooltip="Refresh"/>
+ <action
+ class="com.aptana.rdt.internal.ui.actions.UpdateGemActionDelegate"
+ icon="icons/upgrade.gif"
+ id="com.aptana.gems.ui.ActionUpdateGem"
+ label="Update Gem"
+ style="push"
+ toolbarPath="additions"
+ tooltip="Update Gem"/>
+ </viewContribution>
+ </extension>
-
<!-- =================================================================================== -->
<!-- Extension: Eclipse preferences initializer -->
<!-- =================================================================================== -->
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/Gem.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/Gem.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/Gem.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,63 @@
+package com.aptana.rdt.internal.gems;
+
+public class Gem implements Comparable {
+
+ private String name;
+ private String version;
+ private String description;
+ private String platform;
+
+ public Gem(String name, String version, String description) {
+ this(name, version, description, "ruby");
+ }
+
+ public Gem(String name, String version, String description, String platform) {
+ if (name == null) throw new IllegalArgumentException("A Gem's name must not be null");
+ if (version == null) throw new IllegalArgumentException("A Gem's version must not be null");
+ this.name = name;
+ this.version = version;
+ this.description = description;
+ this.platform = platform;
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getPlatform() {
+ return platform;
+ }
+
+ @Override
+ public boolean equals(Object arg0) {
+ if (!(arg0 instanceof Gem)) return false;
+ Gem other = (Gem) arg0;
+ return getName().equals(other.getName()) && getVersion().equals(other.getVersion()) && getPlatform().equals(other.getPlatform());
+ }
+
+ @Override
+ public int hashCode() {
+ return (getName().hashCode() * 100) + getVersion().hashCode();
+ }
+
+ public int compareTo(Object arg0) {
+ if (!(arg0 instanceof Gem)) return -1;
+ Gem other = (Gem) arg0;
+ return toString().compareTo(other.toString());
+ }
+
+ @Override
+ public String toString() {
+ return getName().toLowerCase() + " " + getVersion() + " " + getPlatform();
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/GemManager.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/GemManager.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/GemManager.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,555 @@
+package com.aptana.rdt.internal.gems;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.IStreamListener;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IStreamMonitor;
+import org.eclipse.debug.core.model.IStreamsProxy;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.osgi.service.environment.Constants;
+import org.rubypeople.rdt.launching.IRubyLaunchConfigurationConstants;
+import org.rubypeople.rdt.launching.IVMInstall;
+import org.rubypeople.rdt.launching.RubyRuntime;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import com.aptana.rdt.AptanaRDTPlugin;
+
+public class GemManager {
+
+ private static final int TIMEOUT = 30000;
+
+ private static final String TIMEOUT_MSG = "Installing gem took more than 30 seconds, intentionally broke out to avoid infinite loop";
+
+ private static final String LOCAL_CACHE_FILE = "remote_gems.xml";
+
+ private static final String GEM_INDEX_URL = "http://gems.rubyforge.org/yaml";
+
+ private static GemManager fgInstance;
+
+ private Set<Gem> gems;
+
+ private Set<Gem> remoteGems;
+
+ private Set<GemListener> listeners;
+
+ private GemManager() {
+ gems = new HashSet<Gem>();
+ // FIXME Somehow allow user to refresh remote gem list
+ // FIXME Do an incremental check for new remote gems somehow?
+ remoteGems = new HashSet<Gem>();
+ listeners = new HashSet<GemListener>();
+ Job job = new Job("Loading remote gem information") {
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ remoteGems = loadLocalCache();
+ if (remoteGems.isEmpty()) {
+ remoteGems = loadRemoteGems();
+ storeGemCache();
+ }
+ return Status.OK_STATUS;
+ }
+
+ };
+ job.schedule();
+ Job job2 = new Job("Loading local gem information") {
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ gems = loadLocalGems();
+ informListeners();
+ return Status.OK_STATUS;
+ }
+
+ };
+ job2.schedule();
+ }
+
+ protected Set<Gem> loadLocalCache() {
+ FileReader fileReader = null;
+ try {
+ fileReader = new FileReader(getConfigFile());
+ XMLReader reader = SAXParserFactory.newInstance().newSAXParser()
+ .getXMLReader();
+ GemManagerContentHandler handler = new GemManagerContentHandler();
+ reader.setContentHandler(handler);
+ reader.parse(new InputSource(fileReader));
+
+ return handler.getGems();
+ } catch (FileNotFoundException e) {
+ // This is okay, will get thrown if no config exists yet
+ } catch (SAXException e) {
+ AptanaRDTPlugin.log(e);
+ } catch (ParserConfigurationException e) {
+ AptanaRDTPlugin.log(e);
+ } catch (FactoryConfigurationError e) {
+ AptanaRDTPlugin.log(e);
+ } catch (IOException e) {
+ AptanaRDTPlugin.log(e);
+ } finally {
+ try {
+ if (fileReader != null)
+ fileReader.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ return new HashSet<Gem>();
+ }
+
+ protected void storeGemCache() {
+ PrintWriter out = null;
+ try {
+ out = new PrintWriter(new FileWriter(getConfigFile()));
+ writeXML(out);
+ } catch (FileNotFoundException e) {
+ AptanaRDTPlugin.log(e);
+ } catch (IOException e) {
+ AptanaRDTPlugin.log(e);
+ } finally {
+ if (out != null)
+ out.close();
+ }
+ }
+
+ /**
+ * Returns the configuration file to use for the servers. The file is
+ * located in the plugin state directory and called
+ * <code>remote_gems.xml</code>.
+ *
+ * @return the config file
+ */
+ private File getConfigFile() {
+ return AptanaRDTPlugin.getDefault().getStateLocation().append(
+ LOCAL_CACHE_FILE).toFile();
+ }
+
+ /**
+ * Writes each server configuration to file in XML format.
+ *
+ * @param out
+ * the writer to use
+ */
+ private void writeXML(PrintWriter out) {
+ out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ out.println("<gems>");
+ for (Gem gem : remoteGems) {
+ out.println("<gem>");
+ out.println("<name>" + gem.getName() + "</name>");
+ out.println("<version>" + gem.getVersion() + "</version>");
+ out.println("<description>" + gem.getDescription()
+ + "</description>");
+ out.println("</gem>");
+ }
+ out.println("</gems>");
+ out.flush();
+ }
+
+ private Set<Gem> loadRemoteGems() {
+ Set<Gem> gems = new HashSet<Gem>();
+ try {
+ URL url = new URL(GEM_INDEX_URL);
+ URLConnection con = url.openConnection();
+ InputStream content = (InputStream) con.getContent();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ content));
+ String line = null;
+ String name = null;
+ String version = null;
+ String description = null;
+ String platform = null;
+ boolean nextIsRealVersion = false;
+ while ((line = reader.readLine()) != null) {
+ if (nextIsRealVersion && line.trim().startsWith("version: ")) {
+ version = line.trim().substring(9);
+ if (version.charAt(0) == '"')
+ version = version.substring(1);
+ if (version.charAt(version.length() - 1) == '"')
+ version = version.substring(0, version.length() - 1);
+ nextIsRealVersion = false;
+ } else if (line.trim().equals(
+ "version: !ruby/object:Gem::Version")) {
+ nextIsRealVersion = true;
+ }
+ // if (line.trim().endsWith(":
+ // !ruby/object:Gem::Specification")) {
+ // // new gem
+ // }
+ if (line.trim().startsWith("name:")) {
+ name = line.trim().substring(6);
+ }
+ if (line.trim().startsWith("platform:")) {
+ platform = line.trim().substring(10);
+ }
+ if (line.trim().startsWith("summary:")) {
+ description = line.trim().substring(9);
+ }
+ if (description != null && name != null && version != null
+ && platform != null) {
+ gems.add(new Gem(name, version, description, platform));
+ description = null;
+ version = null;
+ name = null;
+ platform = null;
+ }
+ }
+ } catch (MalformedURLException e) {
+ AptanaRDTPlugin.log(e);
+ } catch (IOException e) {
+ AptanaRDTPlugin.log(e);
+ }
+ return gems;
+ }
+
+ private Set<Gem> loadLocalGems() {
+ List<String> lines = launchAndRead("list -l");
+ if (lines.size() > 2) {
+ lines.remove(0); // Remove first 3 lines from local list
+ lines.remove(0);
+ lines.remove(0);
+ }
+ return parseOutGems(lines);
+ }
+
+ private List<String> launchAndRead(String command) {
+ try {
+ ILaunchConfiguration config = createGemLaunchConfiguration(command);
+ ILaunch launch = config.launch(ILaunchManager.RUN_MODE, null);
+ IProcess[] processes = launch.getProcesses();
+ IProcess p = processes[0];
+ IStreamsProxy proxy = p.getStreamsProxy();
+ final StringBuffer output = new StringBuffer();
+ IStreamMonitor monitor = proxy.getOutputStreamMonitor();
+ monitor.addListener(new IStreamListener() {
+ public void streamAppended(String text, IStreamMonitor monitor) {
+ output.append(text);
+ }
+
+ });
+ long start = System.currentTimeMillis();
+ String lastOut = null;
+ while (!p.isTerminated() || output.length() == 0) {
+ Thread.yield();
+ if (lastOut != null && !lastOut.equals(output.toString())) {
+ start = System.currentTimeMillis(); // restart timeout if we
+ // have changes in
+ // output
+ }
+ lastOut = output.toString();
+ if (System.currentTimeMillis() > start + TIMEOUT) {
+ AptanaRDTPlugin.log(new Exception(TIMEOUT_MSG));
+ break;
+ }
+ }
+
+ BufferedReader reader = new BufferedReader(new StringReader(output
+ .toString()));
+ String line = null;
+ try {
+ List<String> lines = new ArrayList<String>();
+ while ((line = reader.readLine()) != null) {
+ lines.add(line);
+ }
+ return lines;
+ } catch (IOException e) {
+ AptanaRDTPlugin.log(e);
+ }
+
+ } catch (CoreException e) {
+ AptanaRDTPlugin.log(e);
+ }
+ return new ArrayList<String>();
+ }
+
+ private Set<Gem> parseOutGems(List<String> lines) {
+ Set<Gem> gems = new HashSet<Gem>();
+ for (int i = 0; i < lines.size();) {
+ String nameAndVersion = lines.get(i);
+ String description = lines.get(i + 1);
+ int j = 2;
+ if ((i + 2) < lines.size()) {
+ String nextLine = lines.get(i + 2);
+ while (!nextLine.trim().isEmpty()) {
+ j++;
+ description += " " + nextLine.trim();
+ nextLine = lines.get(i + j);
+ }
+ }
+ int openParen = nameAndVersion.indexOf('(');
+ int closeParen = nameAndVersion.indexOf(')');
+ String name = nameAndVersion.substring(0, openParen);
+ String version = nameAndVersion
+ .substring(openParen + 1, closeParen);
+ gems.add(new Gem(name.trim(), version, description.trim()));
+ i += (j + 1);
+ }
+ return gems;
+ }
+
+ public boolean upgrade(String gemName) {
+ try {
+ String command = "upgrade " + gemName;
+ ILaunchConfiguration config = createGemLaunchConfiguration(command);
+ config.launch(ILaunchManager.RUN_MODE, null);
+ } catch (CoreException e) {
+ AptanaRDTPlugin.log(e);
+ return false;
+ }
+ return true;
+ }
+
+ public boolean installGem(String name) {
+ return installGem(name, null);
+ }
+
+ private ILaunchConfigurationType getRubyApplicationConfigType() {
+ return getLaunchManager().getLaunchConfigurationType(
+ IRubyLaunchConfigurationConstants.ID_RUBY_APPLICATION);
+ }
+
+ private ILaunchManager getLaunchManager() {
+ return DebugPlugin.getDefault().getLaunchManager();
+ }
+
+ private ILaunchConfiguration createGemLaunchConfiguration(String arguments) {
+ String gemPath = getServerScript();
+ ILaunchConfiguration config = null;
+ try {
+ ILaunchConfigurationType configType = getRubyApplicationConfigType();
+ ILaunchConfigurationWorkingCopy wc = configType
+ .newInstance(null, getLaunchManager()
+ .generateUniqueLaunchConfigurationNameFrom(gemPath));
+ wc.setAttribute(IRubyLaunchConfigurationConstants.ATTR_FILE_NAME,
+ gemPath);
+ wc.setAttribute(
+ IRubyLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME,
+ RubyRuntime.getDefaultVMInstall().getName());
+ wc.setAttribute(
+ IRubyLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE,
+ RubyRuntime.getDefaultVMInstall().getVMInstallType()
+ .getId());
+ wc.setAttribute(
+ IRubyLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
+ arguments);
+ wc
+ .setAttribute(
+ IRubyLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
+ "-e STDOUT.sync=true -e STDERR.sync=true -e load(ARGV.shift)");
+ Map<String, String> map = new HashMap<String, String>();
+ map
+ .put(IRubyLaunchConfigurationConstants.ATTR_RUBY_COMMAND,
+ "ruby");
+ wc
+ .setAttribute(
+ IRubyLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE_SPECIFIC_ATTRS_MAP,
+ map);
+ wc.setAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, true);
+ config = wc.doSave();
+ } catch (CoreException ce) {
+ // ignore for now
+ }
+ return config;
+ }
+
+ private String getServerScript() {
+ IVMInstall vm = RubyRuntime.getDefaultVMInstall();
+ File installLocation = vm.getInstallLocation();
+ String path = installLocation.getAbsolutePath();
+ return path + File.separator + "bin" + File.separator + "gem";
+ }
+
+ public boolean installGem(String name, String version) {
+ try {
+ String command = "install " + name;
+ if (version != null && version.trim().length() > 0) {
+ command += " -v " + version;
+ }
+ ILaunchConfiguration config = createGemLaunchConfiguration(command);
+ ILaunch launch = config.launch(ILaunchManager.RUN_MODE, null);
+ IProcess[] processes = launch.getProcesses();
+ IProcess p = processes[0];
+ IStreamMonitor monitor = p.getStreamsProxy()
+ .getOutputStreamMonitor();
+ final StringBuffer buffer = new StringBuffer();
+ monitor.addListener(new IStreamListener() {
+
+ public void streamAppended(String text, IStreamMonitor monitor) {
+ buffer.append(text);
+ }
+
+ });
+ String contents = null;
+ boolean wroteSelection = false;
+ long start = System.currentTimeMillis();
+ String lastOut = null;
+ while (!p.isTerminated()) {
+ contents = buffer.toString();
+ if (contents != null && contents.trim().length() > 0
+ && !wroteSelection) {
+ // System.out.println(contents);
+ if (contents.contains("Select which gem")) {
+ // Parse out options
+ Map<String, String> options = new HashMap<String, String>();
+
+ String[] lines = contents.split("\n");
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i].trim();
+ if (Character.isDigit(line.charAt(0))) {
+ String number = line.substring(0, line
+ .indexOf('.'));
+ int parenIndex = line.indexOf('(');
+ if (parenIndex == -1)
+ continue; // Skip or cancel option
+ String platform = line.substring(
+ parenIndex + 1, line.lastIndexOf(')'));
+ options.put(platform, number);
+ }
+ }
+ // Automatically select the option which matches this
+ // platform.
+ String myPlatform = "ruby";
+ if (Platform.getOS().equals(Constants.OS_WIN32)) {
+ myPlatform = "mswin32";
+ }
+ try {
+ p.getStreamsProxy().write(
+ options.get(myPlatform) + "\r\n");
+ wroteSelection = true;
+ } catch (IOException e) {
+ AptanaRDTPlugin.log(e);
+ }
+ }
+ } else {
+ Thread.yield();
+ if (lastOut != null && !lastOut.equals(buffer.toString())) {
+ start = System.currentTimeMillis(); // restart timeout
+ // if we have
+ // changes in output
+ }
+ if (System.currentTimeMillis() > start + TIMEOUT) {
+ AptanaRDTPlugin.log(new Exception(TIMEOUT_MSG));
+ break;
+ }
+ }
+
+ }
+ } catch (CoreException e) {
+ AptanaRDTPlugin.log(e);
+ return false;
+ }
+ refresh();
+ return true;
+ }
+
+ public boolean removeGem(String name, String version) {
+ try {
+ String command = "uninstall " + name;
+ if (version != null && version.trim().length() > 0) {
+ command += " -v " + version;
+ }
+ ILaunchConfiguration config = createGemLaunchConfiguration(command);
+ config.launch(ILaunchManager.RUN_MODE, null);
+ } catch (CoreException e) {
+ AptanaRDTPlugin.log(e);
+ return false;
+ }
+ refresh(); // FIXME Need to wait until uninstall is finished!
+ return true;
+ }
+
+ public boolean removeGem(String name) {
+ return removeGem(name, null);
+ }
+
+ public Set<Gem> getGems() {
+ return Collections.unmodifiableSortedSet(new TreeSet<Gem>(gems));
+ }
+
+ public static GemManager getInstance() {
+ if (fgInstance == null)
+ fgInstance = new GemManager();
+ return fgInstance;
+ }
+
+ public boolean refresh() {
+ Set<Gem> newGems = loadLocalGems();
+ if (!newGems.isEmpty()) {
+ gems.clear();
+ gems = newGems;
+ informListeners();
+ return true;
+ }
+ return false;
+ }
+
+ private void informListeners() {
+ for (GemListener listener : listeners) {
+ listener.gemsRefreshed();
+ }
+ }
+
+ public void addGemObserver(GemListener listener) {
+ listeners.add(listener);
+ }
+
+ public interface GemListener {
+ public void gemsRefreshed();
+ }
+
+ public Set<Gem> getRemoteGems() {
+ SortedSet<Gem> sorted = new TreeSet<Gem>(remoteGems);
+ SortedSet<Gem> logical = new TreeSet<Gem>();
+ String name = null;
+ Collection<Gem> temp = new HashSet<Gem>();
+ for (Gem gem : sorted) {
+ if (name != null && !gem.getName().equals(name)) {
+ logical.add(LogicalGem.create(temp));
+ temp.clear();
+ }
+ name = gem.getName();
+ temp.add(gem);
+ }
+ return Collections.unmodifiableSortedSet(logical);
+ }
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/GemManagerContentHandler.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/GemManagerContentHandler.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/GemManagerContentHandler.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,87 @@
+package com.aptana.rdt.internal.gems;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+public class GemManagerContentHandler implements ContentHandler {
+
+ private HashSet<Gem> gems;
+ private String name;
+ private String version;
+ private String description;
+
+ private StringBuffer data;
+ private String platform;
+
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ for (int i = start; i < start + length; i++) {
+ data.append(ch[i]);
+ }
+ }
+
+ public void endDocument() throws SAXException {
+ // do nothing
+ }
+
+ public void endElement(String namespaceURI, String localName, String qName)
+ throws SAXException {
+ if (qName.equals("name")) {
+ name = data.toString();
+ } else if (qName.equals("version")) {
+ version = data.toString();
+ } else if (qName.equals("description")) {
+ description = data.toString();
+ } else if (qName.equals("platform")) {
+ platform = data.toString();
+ } else if (qName.equals("gem")) {
+ gems.add(new Gem(name, version, description, platform));
+ }
+ }
+
+ public void endPrefixMapping(String arg0) throws SAXException {
+ // do nothing
+ }
+
+ public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
+ throws SAXException {
+ // do nothing
+ }
+
+ public void processingInstruction(String arg0, String arg1)
+ throws SAXException {
+ // do nothing
+ }
+
+ public void setDocumentLocator(Locator arg0) {
+ // do nothing
+ }
+
+ public void skippedEntity(String arg0) throws SAXException {
+ // do nothing
+ }
+
+ public void startDocument() throws SAXException {
+ gems = new HashSet<Gem>();
+ }
+
+ public void startElement(String namespaceURI, String localName,
+ String qName, Attributes atts) throws SAXException {
+ data = new StringBuffer();
+ }
+
+ public void startPrefixMapping(String arg0, String arg1)
+ throws SAXException {
+ // do nothing
+ }
+
+ public Set<Gem> getGems() {
+ return Collections.unmodifiableSet(gems);
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/LogicalGem.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/LogicalGem.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/gems/LogicalGem.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,40 @@
+package com.aptana.rdt.internal.gems;
+
+import java.util.Collection;
+import java.util.SortedSet;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+
+public class LogicalGem extends Gem {
+
+ private LogicalGem(String name, String version, String description) {
+ super(name, version, description);
+ }
+
+ public static LogicalGem create(Collection<Gem> gems) {
+ if (gems == null || gems.isEmpty()) throw new IllegalArgumentException("Need a non-null, non-empty Collection of Gems");
+ String name = null;
+ String description = null;
+ String version = "(";
+ for (Gem gem : gems) {
+ if (name == null) name = gem.getName();
+ if (description == null) description = gem.getDescription();
+ version += gem.getVersion() + ", ";
+ }
+ version = version.substring(0, version.length() - 2);
+ version += ')';
+ // XXX Need to take platform into account!!!!!!!!
+ return new LogicalGem(name, version, description);
+ }
+
+ public SortedSet<String> getVersions() {
+ String raw = getVersion().substring(1, getVersion().length() - 1);
+ SortedSet<String> version = new TreeSet<String>();
+ StringTokenizer tokenizer = new StringTokenizer(raw, ",");
+ while (tokenizer.hasMoreTokens()) {
+ version.add(tokenizer.nextToken().trim());
+ }
+ return version;
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/InstallGemActionDelegate.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/InstallGemActionDelegate.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/InstallGemActionDelegate.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2005 RadRails.org and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package com.aptana.rdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPart;
+
+import com.aptana.rdt.internal.gems.Gem;
+import com.aptana.rdt.internal.gems.GemManager;
+import com.aptana.rdt.ui.gems.InstallGemDialog;
+
+/**
+ * Install a gem
+ *
+ * @author cwilliams
+ */
+public class InstallGemActionDelegate implements IObjectActionDelegate, IViewActionDelegate {
+
+ /**
+ * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ InstallGemDialog dialog = new InstallGemDialog(Display.getCurrent().getActiveShell());
+ if (dialog.open() == Dialog.OK) {
+ final Gem gem = dialog.getGem();
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ GemManager.getInstance().installGem(gem.getName(), gem.getVersion());
+ }
+ });
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+
+ /**
+ * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart)
+ */
+ public void init(IViewPart view) {
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/RefreshGemsActionDelegate.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/RefreshGemsActionDelegate.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/RefreshGemsActionDelegate.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2005 RadRails.org and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package com.aptana.rdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPart;
+
+import com.aptana.rdt.internal.gems.GemManager;
+
+/**
+ * Install a gem
+ *
+ * @author cwilliams
+ */
+public class RefreshGemsActionDelegate implements IObjectActionDelegate,
+ IViewActionDelegate {
+
+ /**
+ * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ if (!GemManager.getInstance().refresh()) {
+ MessageDialog.openError(Display.getCurrent().getActiveShell(), "Unable to refresh local gems", "Sorry we were unable to refresh the list of local gems.");
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+
+ }
+
+ /**
+ * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart)
+ */
+ public void init(IViewPart view) {
+
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/RemoveGemActionDelegate.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/RemoveGemActionDelegate.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/RemoveGemActionDelegate.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2005 RadRails.org and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package com.aptana.rdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPart;
+
+import com.aptana.rdt.internal.gems.Gem;
+import com.aptana.rdt.internal.gems.GemManager;
+import com.aptana.rdt.ui.gems.GemsView;
+
+/**
+ * Install a gem
+ *
+ * @author cwilliams
+ */
+public class RemoveGemActionDelegate implements IObjectActionDelegate, IViewActionDelegate {
+
+ private IViewPart view;
+ private Gem selectedGem;
+
+ /**
+ * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ Display.getDefault().asyncExec(new Runnable() {
+
+ public void run() {
+ GemManager.getInstance().removeGem(selectedGem.getName());
+ }
+
+ });
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (view instanceof GemsView) {
+ if (selection != null && !selection.isEmpty()) {
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection sel = (IStructuredSelection) selection;
+ Object element = sel.getFirstElement();
+ if (element instanceof Gem) {
+ this.selectedGem = (Gem) element;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart)
+ */
+ public void init(IViewPart view) {
+ this.view = view;
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/UpdateGemActionDelegate.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/UpdateGemActionDelegate.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/internal/ui/actions/UpdateGemActionDelegate.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2005 RadRails.org and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package com.aptana.rdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPart;
+
+import com.aptana.rdt.internal.gems.Gem;
+import com.aptana.rdt.internal.gems.GemManager;
+import com.aptana.rdt.ui.gems.GemsView;
+
+/**
+ * Install a gem
+ *
+ * @author cwilliams
+ */
+public class UpdateGemActionDelegate implements IObjectActionDelegate, IViewActionDelegate {
+
+ private IViewPart view;
+ private Gem selectedGem;
+
+ /**
+ * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ Display.getDefault().asyncExec(new Runnable() {
+
+ public void run() {
+ GemManager.getInstance().upgrade(selectedGem.getName());
+ }
+
+ });
+ }
+
+ /**
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (view instanceof GemsView) {
+ if (selection != null && !selection.isEmpty()) {
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection sel = (IStructuredSelection) selection;
+ Object element = sel.getFirstElement();
+ if (element instanceof Gem) {
+ this.selectedGem = (Gem) element;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.IViewActionDelegate#init(org.eclipse.ui.IViewPart)
+ */
+ public void init(IViewPart view) {
+ this.view = view;
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemContentProvider.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemContentProvider.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemContentProvider.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,25 @@
+package com.aptana.rdt.ui.gems;
+
+import java.util.Collection;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+public class GemContentProvider implements IStructuredContentProvider {
+
+ public Object[] getElements(Object inputElement) {
+ Object[] res = null;
+ if (inputElement instanceof Collection) {
+ res = ((Collection) inputElement).toArray();
+ }
+
+ return res;
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemLabelProvider.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemLabelProvider.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemLabelProvider.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,36 @@
+package com.aptana.rdt.ui.gems;
+
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+import com.aptana.rdt.internal.gems.Gem;
+
+public class GemLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+ private static final int NAME_COLUMN = 0;
+ private static final int VERSION_COLUMN = 1;
+ private static final int DESCRIPTION_COLUMN = 2;
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex) {
+ Gem server = (Gem) element;
+
+ switch (columnIndex) {
+ case NAME_COLUMN:
+ return server.getName();
+ case VERSION_COLUMN:
+ return server.getVersion();
+ case DESCRIPTION_COLUMN:
+ return server.getDescription();
+ default:
+ return "";
+ }
+ }
+
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsMessages.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsMessages.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsMessages.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,20 @@
+package com.aptana.rdt.ui.gems;
+
+import org.eclipse.osgi.util.NLS;
+
+public class GemsMessages extends NLS {
+
+ private static final String BUNDLE_NAME = GemsMessages.class.getName();
+
+ public static String GemsView_NameColumn_label;
+ public static String GemsView_VersionColumn_label;
+ public static String GemsView_DescriptionColumn_label;
+ public static String InstallGemDialog_dialog_title;
+ public static String InstallGemDialog_version_label;
+ public static String InstallGemDialog_name_label;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, GemsMessages.class);
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsMessages.properties
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsMessages.properties (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsMessages.properties 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,7 @@
+GemsView_NameColumn_label=Name
+GemsView_VersionColumn_label=Version
+GemsView_DescriptionColumn_label=Description
+
+InstallGemDialog_dialog_title=Install a gem
+InstallGemDialog_version_label=Version:
+InstallGemDialog_name_label=Gem Name:
\ No newline at end of file
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsView.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsView.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/GemsView.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,104 @@
+package com.aptana.rdt.ui.gems;
+
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.part.ViewPart;
+import org.rubypeople.rdt.ui.TableViewerSorter;
+
+import com.aptana.rdt.internal.gems.GemManager;
+import com.aptana.rdt.internal.gems.GemManager.GemListener;
+
+public class GemsView extends ViewPart implements GemListener {
+
+ private TableViewer gemViewer;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ parent.setLayout(new GridLayout());
+
+ gemViewer = new TableViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION);
+ Table serverTable = gemViewer.getTable();
+ serverTable.setHeaderVisible(true);
+ serverTable.setLinesVisible(false);
+ serverTable.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ TableColumn nameColumn = new TableColumn(serverTable, SWT.LEFT);
+ nameColumn.setText(GemsMessages.GemsView_NameColumn_label);
+ nameColumn.setWidth(150);
+
+ TableColumn versionColumn = new TableColumn(serverTable, SWT.LEFT);
+ versionColumn.setText(GemsMessages.GemsView_VersionColumn_label);
+ versionColumn.setWidth(75);
+
+ TableColumn descriptionColumn = new TableColumn(serverTable, SWT.LEFT);
+ descriptionColumn.setText(GemsMessages.GemsView_DescriptionColumn_label);
+ descriptionColumn.setWidth(275);
+
+
+ gemViewer.setLabelProvider(new GemLabelProvider());
+ gemViewer.setContentProvider(new GemContentProvider());
+ TableViewerSorter.bind(gemViewer);
+ getSite().setSelectionProvider(gemViewer);
+
+ gemViewer.setInput(GemManager.getInstance().getGems());
+ createPopupMenu();
+
+ GemManager.getInstance().addGemObserver(this);
+ }
+
+ @Override
+ public void setFocus() {
+ // do nothing
+ }
+
+ /**
+ * Creates and registers the context menu
+ */
+ private void createPopupMenu() {
+ MenuManager menuMgr = new MenuManager("#PopupMenu");
+ menuMgr.setRemoveAllWhenShown(true);
+
+ menuMgr.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ IContributionItem[] items = getViewSite().getActionBars().getToolBarManager().getItems();
+ for (int i = 0; i < items.length; i++) {
+ if (items[i] instanceof ActionContributionItem) {
+ ActionContributionItem aci = (ActionContributionItem) items[i];
+ manager.add(aci.getAction());
+ }
+ }
+ }
+ });
+ menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); // Allow other plugins to add here
+ Menu menu = menuMgr.createContextMenu(gemViewer.getControl());
+ gemViewer.getControl().setMenu(menu);
+ getSite().registerContextMenu(menuMgr, gemViewer);
+ }
+
+ public void gemsRefreshed() {
+ Display.getDefault().asyncExec(new Runnable() {
+
+ public void run() {
+ gemViewer.setInput(GemManager.getInstance().getGems());
+ gemViewer.refresh();
+ }
+
+ });
+
+ }
+
+}
Added: trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/InstallGemDialog.java
===================================================================
--- trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/InstallGemDialog.java (rev 0)
+++ trunk/com.aptana.rdt/src/com/aptana/rdt/ui/gems/InstallGemDialog.java 2007-05-11 17:13:55 UTC (rev 2461)
@@ -0,0 +1,176 @@
+package com.aptana.rdt.ui.gems;
+
+import java.util.SortedSet;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.rubypeople.rdt.ui.TableViewerSorter;
+
+import com.aptana.rdt.internal.gems.Gem;
+import com.aptana.rdt.internal.gems.GemManager;
+import com.aptana.rdt.internal.gems.LogicalGem;
+
+public class InstallGemDialog extends Dialog {
+
+ private Text nameText;
+ private Combo versionCombo;
+
+ private String name;
+ private String version;
+
+ private boolean filterByText = true;
+
+ private TableViewer gemViewer;
+ private GemContentProvider contentProvider;
+
+ public InstallGemDialog(Shell parentShell) {
+ super(parentShell);
+ contentProvider = new GemContentProvider();
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ getShell().setText(GemsMessages.InstallGemDialog_dialog_title);
+ Composite control = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ control.setLayout(layout);
+
+ Label nameLabel = new Label(control, SWT.LEFT);
+ nameLabel.setText(GemsMessages.InstallGemDialog_name_label);
+
+ nameText = new Text(control, SWT.BORDER);
+ GridData nameTextData = new GridData();
+ nameTextData.widthHint = 150;
+ nameText.setLayoutData(nameTextData);
+ nameText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ if (filterByText) {
+ getShell().getDisplay().syncExec(new Runnable() {
+
+ public void run() {
+ gemViewer.refresh();
+ }
+ });
+ }
+ filterByText = true;
+ }
+
+ });
+
+ Label versionLabel = new Label(control, SWT.LEFT);
+ versionLabel.setText(GemsMessages.InstallGemDialog_version_label);
+
+ versionCombo = new Combo(control, SWT.DROP_DOWN);
+ GridData versionComboData = new GridData();
+ versionComboData.widthHint = 100;
+ versionCombo.setLayoutData(versionComboData);
+
+ gemViewer = new TableViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION);
+ Table serverTable = gemViewer.getTable();
+ serverTable.setHeaderVisible(true);
+ serverTable.setLinesVisible(false);
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ data.heightHint = 400;
+ serverTable.setLayoutData(data);
+
+ TableColumn nameColumn = new TableColumn(serverTable, SWT.LEFT);
+ nameColumn.setText(GemsMessages.GemsView_NameColumn_label);
+ nameColumn.setWidth(150);
+
+ TableColumn versionColumn = new TableColumn(serverTable, SWT.LEFT);
+ versionColumn.setText(GemsMessages.GemsView_VersionColumn_label);
+ versionColumn.setWidth(75);
+
+ TableColumn descriptionColumn = new TableColumn(serverTable, SWT.LEFT);
+ descriptionColumn
+ .setText(GemsMessages.GemsView_DescriptionColumn_label);
+ descriptionColumn.setWidth(275);
+
+ gemViewer.setLabelProvider(new GemLabelProvider());
+ gemViewer.setContentProvider(contentProvider);
+ TableViewerSorter.bind(gemViewer);
+ gemViewer.setInput(GemManager.getInstance().getRemoteGems());
+ gemViewer.addFilter(new MyViewerFilter(nameText));
+
+ gemViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structured = (IStructuredSelection) selection;
+ LogicalGem gem = (LogicalGem) structured.getFirstElement();
+ SortedSet<String> versions = gem.getVersions();
+ filterByText = false; // don't filter list when I programmatically set text
+ nameText.setText(gem.getName());
+ versionCombo.removeAll();
+ String lastVersion = null;
+ for (String version : versions) {
+ versionCombo.add(version);
+ lastVersion = version;
+ }
+ versionCombo.setText(lastVersion);
+ }
+ }
+
+ });
+
+ return control;
+ }
+
+ /**
+ * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
+ */
+ public void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.OK_ID) {
+ name = nameText.getText();
+ version = versionCombo.getText();
+ okPressed();
+ } else if (buttonId == IDialogConstants.CANCEL_ID) {
+ cancelPressed();
+ }
+ }
+
+ public Gem getGem() {
+ return new Gem(name, version, "");
+ }
+
+ private static class MyViewerFilter extends ViewerFilter {
+
+ private Text text;
+
+ public MyViewerFilter(Text text) {
+ this.text = text;
+ }
+
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ Gem gem = (Gem) element;
+ // TODO If there's no text show nothing?
+ return gem.getName().toLowerCase().startsWith(text.getText().toLowerCase());
+ }
+
+ }
+
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|