PK !ye0M *= = WorkbenchPlugin.txtIndex: WorkbenchPlugin.java =================================================================== retrieving revision 1.62 diff -u -r1.62 WorkbenchPlugin.java --- WorkbenchPlugin.java 1 Mar 2004 20:05:42 -0000 1.62 +++ WorkbenchPlugin.java 5 Mar 2004 20:07:38 -0000 @@ -32,7 +32,9 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.widgets.Decorations; import org.eclipse.jface.preference.IPreferenceNode; import org.eclipse.jface.preference.IPreferenceStore; @@ -620,63 +622,12 @@ } public void startup() throws CoreException { - /* The plugin org.eclipse.ui has being separed in - several plugins. Copy the state files from - org.eclipse.ui to org.eclipse.ui.workbench */ - - IPath locationPath = getStateLocation(); - File newLocation = locationPath.toFile(); - File oldLocation = new File(newLocation,"..//org.eclipse.ui"); //$NON-NLS-1$ - try { - oldLocation = oldLocation.getCanonicalFile(); - } catch (IOException e) { - // ignore - } - String markerFileName = ".copiedStateFiles_Marker"; //$NON-NLS-1$ - File markerFile = new File(oldLocation,markerFileName); - if(markerFile.exists()) - return; - - try { - String list[] = newLocation.list(); - if(list != null && list.length != 0) - return; - - String oldList[] = oldLocation.list(); - if(oldList == null || oldList.length == 0) - return; - - byte b[] = new byte[1024]; - for (int i = 0; i < oldList.length; i++) { - String string = oldList[i]; - try { - File oldFile = new File(oldLocation,string); - FileInputStream in = new FileInputStream(oldFile); - FileOutputStream out = new FileOutputStream(new File(newLocation,string)); - int read = in.read(b); - while(read >= 0) { - out.write(b,0,read); - read = in.read(b); - } - in.close(); - out.close(); - // Don't delete the old file since the public preferences and some - // dialog settings are still read from org.eclipse.ui. - // See bug 33334. - // oldFile.delete(); - } catch (IOException e) { - new File(newLocation,string).delete(); - } - } - } finally { - try { - new FileOutputStream(markerFile).close(); - } catch (IOException e) { - // ignore - } - } + // Previously this impl. managed migration from 2.0 to 2.1, which is no longer + // required. However, that previous impl. didn't call the parent method, so + // this empty impl. has been left to continue to prevent the parent behaviour + // from being invoked. } - + /** * Initializes product-specific information that comes from the * about.ini file of the primary feature. PK xe0:ʭ#v#vorg.eclipse.ui.internal.ide.txtIndex: IDEApplication.java =================================================================== retrieving revision 1.9 diff -u -r1.9 IDEApplication.java --- IDEApplication.java 1 Mar 2004 20:05:57 -0000 1.9 +++ IDEApplication.java 5 Mar 2004 20:05:38 -0000 @@ -8,14 +8,30 @@ * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ - package org.eclipse.ui.internal.ide; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Properties; + import org.eclipse.core.boot.IPlatformRunnable; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.osgi.service.datalocation.Location; +import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; /** @@ -25,37 +41,51 @@ */ public final class IDEApplication implements IPlatformRunnable, IExecutableExtension { + private static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$ + private static final String VERSION_FILENAME = "version.ini"; //$NON-NLS-1$ + private static final String WORKSPACE_VERSION_KEY = "org.eclipse.core.runtime"; //$NON-NLS-1$ + private static final String WORKSPACE_VERSION_VALUE = "1"; //$NON-NLS-1$ + /** * Creates a new IDE application. */ public IDEApplication() { // There is nothing to do for IDEApplication } - + /* (non-Javadoc) * @see org.eclipse.core.boot.IPlatformRunnable#run(java.lang.Object) */ public Object run(Object args) throws Exception { - // create and startup the display for the workbench Display display = PlatformUI.createDisplay(); try { + Shell shell = new Shell(display); + try { + if (!checkInstanceLocation(shell)) { + Platform.endSplash(); + return EXIT_OK; + } + } finally { + if (shell != null) + shell.dispose(); + } + // create the workbench with this advisor and run it until it exits - // N.B. createWorkbench remembers the advisor, and also registers the - // workbench globally so that all UI plug-ins can find it using + // N.B. createWorkbench remembers the advisor, and also registers + // the workbench globally so that all UI plug-ins can find it using // PlatformUI.getWorkbench() or AbstractUIPlugin.getWorkbench() - int returnCode = PlatformUI.createAndRunWorkbench(display, new IDEWorkbenchAdvisor()); + int returnCode = PlatformUI.createAndRunWorkbench(display, + new IDEWorkbenchAdvisor()); // exit the application with an appropriate return code - if (returnCode == PlatformUI.RETURN_RESTART) { - return IPlatformRunnable.EXIT_RESTART; - } else { - return IPlatformRunnable.EXIT_OK; - } - } - finally { - display.dispose(); + return returnCode == PlatformUI.RETURN_RESTART + ? EXIT_RESTART + : EXIT_OK; + } finally { + if (display != null) + display.dispose(); } } @@ -64,5 +94,248 @@ */ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { // There is nothing to do for IDEApplication + } + + /** + * Return true if a valid workspace path has been set and false otherwise. + * Prompt for and set the path if possible and required. + * + * @return true if a valid instance location has been set and false + * otherwise + */ + private boolean checkInstanceLocation(Shell shell) { + // -data @none was specified but an ide requires workspace + Location instanceLoc = Platform.getInstanceLocation(); + if (instanceLoc == null) { + MessageDialog + .openError( + shell, + IDEWorkbenchMessages + .getString("IDEApplication.workspaceMandatoryTitle"), //$NON-NLS-1$ + IDEWorkbenchMessages + .getString("IDEApplication.workspaceMandatoryMessage")); //$NON-NLS-1$ + return false; + } + + // -data "/valid/path", workspace already set + if (instanceLoc.isSet()) + return true; + + // -data @noDefault or -data not specified, prompt and set + URL defaultUrl = instanceLoc.getDefault(); + String initialDefault = defaultUrl == null ? null : defaultUrl + .getFile(); + ChooseWorkspaceData launchData = new ChooseWorkspaceData( + initialDefault); + + while (true) { + URL workspaceUrl = promptForWorkspace(shell, launchData); + if (workspaceUrl == null) + return false; + + try { + // the operation will fail if the url is not a valid + // instance data area, so other checking is unneeded + if (instanceLoc.setURL(workspaceUrl, true)) { + launchData.writePersistedData(); + writeWorkspaceVersion(); + return true; + } + } catch (IllegalStateException e) { + MessageDialog + .openError( + shell, + IDEWorkbenchMessages + .getString("IDEApplication.workspaceCannotBeSetTitle"), //$NON-NLS-1$ + IDEWorkbenchMessages + .getString("IDEApplication.workspaceCannotBeSetMessage")); //$NON-NLS-1$ + return false; + } + + // by this point it has been determined that the workspace is already + // in use -- force the user to choose again + MessageDialog + .openError( + shell, + IDEWorkbenchMessages + .getString("IDEApplication.workspaceInUseTitle"), //$NON-NLS-1$ + IDEWorkbenchMessages + .getString("IDEApplication.workspaceInUseMessage")); //$NON-NLS-1$ + } + } + + /** + * Open a workspace selection dialog on the argument shell, populating the + * argument data with the user's selection. Perform first level validation + * on the selection by comparing the version information. This method does + * not examine the runtime state (e.g., is the workspace already locked?). + * + * @param shell + * @param launchData + * @return An URL storing the selected workspace or null if the user has + * canceled the launch operation. + */ + private URL promptForWorkspace(Shell shell, ChooseWorkspaceData launchData) { + URL url = null; + do { + new ChooseWorkspaceDialog(shell, launchData).open(); + String instancePath = launchData.getSelection(); + if (instancePath == null) + return null; + + try { + url = new File(instancePath).toURL(); + } catch (MalformedURLException e) { + MessageDialog + .openError( + shell, + IDEWorkbenchMessages + .getString("IDEApplication.workspaceInvalidTitle"), //$NON-NLS-1$ + IDEWorkbenchMessages + .getString("IDEApplication.workspaceInvalidMessage")); //$NON-NLS-1$ + continue; + } + } while (!isValidWorkspace(shell, url)); + + return url; + } + + /** + * Return true if the argument directory is ok to use as a workspace and + * false otherwise. A version check will be performed, and a confirmation + * box may be displayed on the argument shell if an older version is + * detected. + */ + private boolean isValidWorkspace(Shell shell, URL url) { + String version = readWorkspaceVersion(url); + + // if the version could not be read, then there is not any existing + // workspace data to trample, e.g., perhaps its a new directory that + // is just starting to be used as a workspace + if (version == null) + return true; + + final int ide_version = Integer.parseInt(WORKSPACE_VERSION_VALUE); + int workspace_version = Integer.parseInt(version); + + // equality test is required since any version difference (newer + // or older) may result in data being trampled + if (workspace_version == ide_version) + return true; + + // At this point workspace has been detected to be from a version + // other than the current ide version -- find out if the user wants + // to use it anyhow. + String title = IDEWorkbenchMessages + .getString("IDEApplication.versionTitle"); //$NON-NLS-1$ + String message = IDEWorkbenchMessages.format( + "IDEApplication.versionMessage", //$NON-NLS-1$ + new Object[]{url.getFile()}); + + MessageBox mbox = new MessageBox(shell, SWT.OK | SWT.CANCEL + | SWT.ICON_WARNING | SWT.APPLICATION_MODAL); + mbox.setText(title); + mbox.setMessage(message); + return mbox.open() == SWT.OK; + } + + /** + * Look at the argument URL for the workspace's version information. Return + * that version if found and null otherwise. + */ + private static String readWorkspaceVersion(URL workspace) { + File versionFile = getVersionFile(workspace, false); + if (versionFile == null || !versionFile.exists()) + return null; + + try { + // Although the version file is not spec'ed to be a Java properties + // file, it happens to follow the same format currently, so using + // Properties to read it is convenient. + Properties props = new Properties(); + FileInputStream is = new FileInputStream(versionFile); + try { + props.load(is); + } finally { + is.close(); + } + + return props.getProperty(WORKSPACE_VERSION_KEY); + } catch (IOException e) { + IDEWorkbenchPlugin.log("Could not read version file", new Status( //$NON-NLS-1$ + IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, + IStatus.ERROR, e.getMessage(), e)); + return null; + } + } + + /** + * Write the version of the metadata into a known file overwriting any + * existing file contents. Writing the version file isn't really crucial, + * so the function is silent about failure + */ + private static void writeWorkspaceVersion() { + Location instanceLoc = Platform.getInstanceLocation(); + if (instanceLoc == null || instanceLoc.isReadOnly()) + return; + + File versionFile = getVersionFile(instanceLoc.getURL(), true); + if (versionFile == null) + return; + + OutputStream output = null; + try { + String versionLine = WORKSPACE_VERSION_KEY + '=' + WORKSPACE_VERSION_VALUE; + + output = new FileOutputStream(versionFile); + output.write(versionLine.getBytes("UTF-8")); //$NON-NLS-1$ + } catch (IOException e) { + IDEWorkbenchPlugin.log("Could not write version file", new Status( //$NON-NLS-1$ + IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, + IStatus.ERROR, e.getMessage(), e)); + } finally { + try { + if (output != null) + output.close(); + } catch (IOException e) { + // do nothing + } + } + } + + /** + * The version file is stored in the metadata area of the workspace. This + * method returns an URL to the file or null if the directory or file does + * not exist (and the create parameter is false). + * + * @param create + * If the directory and file does not exist this parameter + * controls whether it will be created. + * @return An url to the file or null if the version file does not exist or + * could not be created. + */ + private static File getVersionFile(URL workspaceUrl, boolean create) { + if (workspaceUrl == null) + return null; + + try { + // make sure the directory exists + URL metaUrl = new URL(workspaceUrl, METADATA_FOLDER); + File metaDir = new File(metaUrl.getFile()); + if (!metaDir.exists() && (!create || !metaDir.mkdir())) + return null; + + // make sure the file exists + URL versionUrl = new URL(metaDir.toURL(), VERSION_FILENAME); + File versionFile = new File(versionUrl.getFile()); + if (!versionFile.exists() + && (!create || !versionFile.createNewFile())) + return null; + + return versionFile; + } catch (IOException e) { + // cannot log because instance area has not been set + return null; + } } } Index: src/org/eclipse/ui/internal/ide/ChooseWorkspaceData.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/ChooseWorkspaceData.java diff -N src/org/eclipse/ui/internal/ide/ChooseWorkspaceData.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/ChooseWorkspaceData.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,294 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation 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/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.net.URL; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.service.datalocation.Location; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.XMLMemento; + +/** + * This class stores the information behind the "Launch Workspace" dialog. The + * class is able to read and write itself to a well known configuration file. + */ +public class ChooseWorkspaceData { + /** + * The default max length of the recent workspace mru list. The values + * stored in xml (both the max-length parameter and actual size of the + * list) will supersede this value. + */ + private static final int RECENT_MAX_LENGTH = 5; + + /** + * The directory within the config area that will be used for the + * receiver's persisted data. + */ + private static final String PERS_FOLDER = "org.eclipse.ui.ide"; //$NON-NLS-1$ + + /** + * The name of the file within the config area that will be used for + * the recever's persisted data. + * @see PERS_FOLDER + */ + private static final String PERS_FILENAME = "recentWorkspaces.xml"; //$NON-NLS-1$ + private static final int PERS_ENCODING_VERSION = 1; + + private String initialDefault; + private String selection; + private String[] recentWorkspaces; + + // xml tags + private static interface XML { + public static final String PROTOCOL = "protocol"; //$NON-NLS-1$ + public static final String VERSION = "version"; //$NON-NLS-1$ + public static final String WORKSPACE = "workspace"; //$NON-NLS-1$ + public static final String RECENT_WORKSPACES = "recentWorkspaces"; //$NON-NLS-1$ + public static final String MAX_LENGTH = "maxLength"; //$NON-NLS-1$ + public static final String PATH = "path"; //$NON-NLS-1$ + } + + /** + * Creates a new instance, loading persistent data if its found. + */ + public ChooseWorkspaceData(String initialDefault) { + readPersistedData(); + this.initialDefault = initialDefault; + } + + /** + * Return the folder to be used as a default if no other information + * exists. Does not return null. + */ + public String getInitialDefault() { + if (initialDefault == null) + initialDefault = System.getProperty("user.dir") + + File.separator + "workspace"; + return initialDefault; + } + + /** + * Return the currently selected workspace or null if nothing is selected. + */ + public String getSelection() { + return selection; + } + + /** + * Return an array of recent workspaces sorted with the most recently used at + * the start. + */ + public String[] getRecentWorkspaces() { + return recentWorkspaces; + } + + /** + * The argument workspace has been selected, update the receiver. Does not + * persist the new values. + */ + public void workspaceSelected(String dir) { + // this just stores the selection, it is not inserted and persisted + // until the workspace is actually selected + selection = dir; + } + + /** + * Update the persistent store. Call this function after the currently selected + * value has been found to be ok. + */ + public void writePersistedData() { + Location configLoc = Platform.getConfigurationLocation(); + if (configLoc == null || configLoc.isReadOnly()) + return; + + URL persUrl = getPersistenceUrl(configLoc.getURL(), true); + if (persUrl == null) + return; + + // move the new selection to the front of the list + if(selection != null) { + String oldEntry = recentWorkspaces[0]; + recentWorkspaces[0] = selection; + for (int i = 1; i < recentWorkspaces.length && oldEntry != null; ++i) { + if (selection.equals(oldEntry)) + return; + String tmp = recentWorkspaces[i]; + recentWorkspaces[i] = oldEntry; + oldEntry = tmp; + } + } + + Writer writer = null; + try { + writer = new FileWriter(persUrl.getFile()); + + // E.g., + // + // + // + // + // + // + // + + XMLMemento memento = XMLMemento.createWriteRoot("launchWorkspaceData"); + + memento.createChild(XML.PROTOCOL) + .putInteger(XML.VERSION, PERS_ENCODING_VERSION); + + IMemento recentMemento = memento.createChild(XML.RECENT_WORKSPACES); + recentMemento.putInteger(XML.MAX_LENGTH, recentWorkspaces.length); + for(int i = 0; i < recentWorkspaces.length; ++i) { + if(recentWorkspaces[i] == null) + break; + recentMemento.createChild(XML.WORKSPACE).putString(XML.PATH, recentWorkspaces[i]); + } + memento.save(writer); + } catch (IOException e) { + IDEWorkbenchPlugin.log("Unable to write recent workspace data", new Status( //$NON-NLS-1$ + IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, + IStatus.ERROR, e.getMessage(), e)); + } + finally { + if(writer != null) + try { + writer.close(); + } catch (IOException e1) { + // do nothing + } + } + } + + /** + * Look for and read data that might have been persisted from some previous + * run. Leave the receiver in a default state if no persistent data is + * found. + */ + private void readPersistedData() { + URL persUrl = null; + + Location configLoc = Platform.getConfigurationLocation(); + if(configLoc != null) + persUrl = getPersistenceUrl(configLoc.getURL(), false); + + try { + // inside try to get the safe default creation in the finally + // clause + if (persUrl == null) + return; + + // E.g., + // + // + // + // + // + // + // + + Reader reader = new FileReader(persUrl.getFile()); + XMLMemento memento = XMLMemento.createReadRoot(reader); + if (memento == null || !compatibleProtocol(memento)) + return; + + IMemento recent = memento.getChild(XML.RECENT_WORKSPACES); + if(recent == null) + return; + + Integer maxLength = recent.getInteger(XML.MAX_LENGTH); + int max = RECENT_MAX_LENGTH; + if(maxLength != null) + max = maxLength.intValue(); + + IMemento indices[] = recent.getChildren(XML.WORKSPACE); + if(indices == null || indices.length <= 0) + return; + + // if a user has edited maxLength to be shorter than the listed + // indices, accept the list (its tougher for them to retype a long + // list of paths than to update a max number) + max = Math.max(max, indices.length); + + recentWorkspaces = new String[max]; + for(int i = 0; i < indices.length; ++i) { + String path = indices[i].getString(XML.PATH); + if(path == null) + break; + recentWorkspaces[i] = path; + } + return; + } catch (IOException e) { + // do nothing -- cannot log because instance area has not been set + } catch (WorkbenchException e) { + // do nothing -- cannot log because instance area has not been set + } + finally { + // create safe default if needed + if(recentWorkspaces == null) + recentWorkspaces = new String[RECENT_MAX_LENGTH]; + } + } + + /** + * Return true if the protocol used to encode the argument memento is compatible + * with the receiver's implementation and false otherwise. + */ + private static boolean compatibleProtocol(IMemento memento) { + IMemento protocolMemento = memento.getChild(XML.PROTOCOL); + if(protocolMemento == null) + return false; + + Integer version = protocolMemento.getInteger(XML.VERSION); + return version != null && version.intValue() == PERS_ENCODING_VERSION; + } + + /** + * The workspace data is stored in the well known file pointed to by the result + * of this method. + * @param create If the directory and file does not exist this parameter + * controls whether it will be created. + * @return An url to the file and null if it does not exist or could not + * be created. + */ + private static URL getPersistenceUrl(URL baseUrl, boolean create) { + if(baseUrl == null) + return null; + + try { + // make sure the directory exists + URL url = new URL(baseUrl, PERS_FOLDER); + File dir = new File(url.getFile()); + if (!dir.exists() && (!create || !dir.mkdir())) + return null; + + // make sure the file exists + url = new URL(dir.toURL(), PERS_FILENAME); + File persFile = new File(url.getFile()); + if (!persFile.exists() && (!create || !persFile.createNewFile())) + return null; + + return persFile.toURL(); + } catch (IOException e) { + // cannot log because instance area has not been set + return null; + } + } +} Index: src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java diff -N src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation 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/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +/** + * A dialog that prompts for a directory to use as a workspace. + */ +public class ChooseWorkspaceDialog extends TitleAreaDialog { + private ChooseWorkspaceData launchData; + private String currentSelection; + + /** + * Create a modal dialog on the arugment shell, using and updating the argument + * data object. + */ + public ChooseWorkspaceDialog(Shell parentShell, ChooseWorkspaceData launchData) { + super(parentShell); + this.launchData = launchData; + } + + /** + * Creates and returns the contents of the upper part of this dialog (above + * the button bar). + *

+ * The Dialog implementation of this framework method creates + * and returns a new Composite with no margins and spacing. + *

+ * + * @param the parent composite to contain the dialog area + * @return the dialog area control + */ + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + setTitle(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.dialogTitle")); //$NON-NLS-1$ + setMessage(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.dialogMessage")); //$NON-NLS-1$ + setTitleImage(); + + createWorkspaceBrowseRow(composite); + return composite; + } + + /** + * Configures the given shell in preparation for opening this window + * in it. + *

+ * The default implementation of this framework method + * sets the shell's image and gives it a grid layout. + * Subclasses may extend or reimplement. + *

+ * + * @param shell the shell + */ + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.dialogName")); //$NON-NLS-1$ + } + + /** + * Notifies that the ok button of this dialog has been pressed. + *

+ * The Dialog implementation of this framework method sets + * this dialog's return code to Window.OK + * and closes the dialog. Subclasses may override. + *

+ */ + protected void okPressed() { + launchData.workspaceSelected(currentSelection); + super.okPressed(); + } + + /** + * Notifies that the cancel button of this dialog has been pressed. + *

+ * The Dialog implementation of this framework method sets + * this dialog's return code to Window.CANCEL + * and closes the dialog. Subclasses may override if desired. + *

+ */ + protected void cancelPressed() { + currentSelection = null; + launchData.workspaceSelected(currentSelection); + super.cancelPressed(); + } + + private void setTitleImage() { + try { + URL installURL = Platform.getPlugin( + IDEWorkbenchPlugin.IDE_WORKBENCH).getDescriptor() + .getInstallURL(); + URL url = new URL(installURL, "icons/full/wizban/newfolder_wiz.gif");//$NON-NLS-1$ + + ImageDescriptor desc = ImageDescriptor.createFromURL(url); + Image image = desc.createImage(); + if (image != null) + setTitleImage(image); + } catch (MalformedURLException e) { + // do nothing + } + } + + /** + * The main area of the dialog is just a row with the current selection + * information and a drop-down of the most recently used workspaces. + */ + private void createWorkspaceBrowseRow(Composite parent) { + Composite panel = new Composite(parent, SWT.NONE); + + GridLayout layout = new GridLayout(3, false); + layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + panel.setLayout(layout); + panel.setLayoutData(new GridData(GridData.FILL_BOTH)); + panel.setFont(parent.getFont()); + + Label label = new Label(panel, SWT.NONE); + label.setText(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.workspaceEntryLabel")); //$NON-NLS-1$ + + final Combo text = new Combo(panel, SWT.BORDER | SWT.LEAD + | SWT.DROP_DOWN); + text.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL + | GridData.FILL_HORIZONTAL)); + setInitialTextValues(text); + text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + currentSelection = text.getText(); + } + }); + + Button browseButton = new Button(panel, SWT.PUSH); + browseButton.setText(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.browseLabel")); //$NON-NLS-1$ + setButtonLayoutData(browseButton); + GridData data = (GridData) browseButton.getLayoutData(); + data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_END; + browseButton.setLayoutData(data); + browseButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + DirectoryDialog dialog = new DirectoryDialog(getShell()); + dialog.setText(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.directoryBrowserTitle")); //$NON-NLS-1$ + dialog.setMessage(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.directoryBrowserMessage")); //$NON-NLS-1$ + dialog.setFilterPath(currentSelection); + String dir = dialog.open(); + if (dir != null) + text.setText(dir); + } + }); + } + + private void setInitialTextValues(Combo text) { + String[] recentWorkspaces = launchData.getRecentWorkspaces(); + for(int i = 0; i < recentWorkspaces.length; ++i) + if(recentWorkspaces[i] != null) + text.add(recentWorkspaces[i]); + + currentSelection = text.getItemCount() > 0 + ? text.getItem(0) + : launchData.getInitialDefault(); + text.setText(currentSelection); + } +} PK xe0Cq8OOmessages.properties.txtIndex: messages.properties =================================================================== retrieving revision 1.15 diff -u -r1.15 messages.properties --- messages.properties 1 Mar 2004 20:37:50 -0000 1.15 +++ messages.properties 5 Mar 2004 20:07:11 -0000 @@ -1568,5 +1568,33 @@ DecorationScheduler.UpdatingTask=Updating DecorationScheduler.CalculatingTask=Calculating DecorationScheduler.DecoratingSubtask=Decorating {0} +ChooseWorkspaceDialog.dialogName=Workspace Launcher +ChooseWorkspaceDialog.dialogTitle=Select a workspace +ChooseWorkspaceDialog.dialogMessage=The workspace is where resources such as files and directories are stored. +ChooseWorkspaceDialog.workspaceEntryLabel=&Workspace: +ChooseWorkspaceDialog.browseLabel=&Browse... +ChooseWorkspaceDialog.directoryBrowserTitle=Select Workspace Directory +ChooseWorkspaceDialog.directoryBrowserMessage=Select the workspace directory to use. +IDEApplication.workspaceMandatoryTitle=Workspace is Mandatory +IDEApplication.workspaceMandatoryMessage=IDEs need a valid workspace; restart without the @none option. +IDEApplication.workspaceInUseTitle=Workspace in Use +IDEApplication.workspaceInUseMessage=Workspace in use, choose a different one. +IDEApplication.workspaceInvalidTitle=Invalid Workspace +IDEApplication.workspaceInvalidMessage=Selected workspace is not valid; choose a different one. +IDEApplication.workspaceCannotBeSetTitle=Workspace Cannot be Set +IDEApplication.workspaceCannotBeSetMessage=Error in runtime; workspace could not be set. Exiting. +IDEApplication.versionTitle = Different Workspace Version +IDEApplication.versionMessage = \ + This workspace was written with a different version of the product and needs to be updated.\n\n\ + {0}\n\n\ + Updating the workspace may make it incompatible with other versions of the product.\n\ + Press OK to update the workspace and open it. Press Cancel to select a different workspace. +ChooseWorkspaceData.launchWorkspaceTag=launchWorkspaceData +ChooseWorkspaceData.protocolTag=protocol +ChooseWorkspaceData.versionTag=version +ChooseWorkspaceData.pathTag=path +ChooseWorkspaceData.recentWorkspacesTag=recentWorkspaces +ChooseWorkspaceData.maxLengthTag=maxLength +ChooseWorkspaceData.workspaceTag=workspace GlobalBuildAction.BuildRunningTitle=Build Is Running GlobalBuildAction.BuildRunningMessage=A build is currently running. Do you wish to cancel it? Index: src/org/eclipse/ui/internal/ide/ChooseWorkspaceData.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/ChooseWorkspaceData.java diff -N src/org/eclipse/ui/internal/ide/ChooseWorkspaceData.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/ChooseWorkspaceData.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,294 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation 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/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.net.URL; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.service.datalocation.Location; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.XMLMemento; + +/** + * This class stores the information behind the "Launch Workspace" dialog. The + * class is able to read and write itself to a well known configuration file. + */ +public class ChooseWorkspaceData { + /** + * The default max length of the recent workspace mru list. The values + * stored in xml (both the max-length parameter and actual size of the + * list) will supersede this value. + */ + private static final int RECENT_MAX_LENGTH = 5; + + /** + * The directory within the config area that will be used for the + * receiver's persisted data. + */ + private static final String PERS_FOLDER = "org.eclipse.ui.ide"; //$NON-NLS-1$ + + /** + * The name of the file within the config area that will be used for + * the recever's persisted data. + * @see PERS_FOLDER + */ + private static final String PERS_FILENAME = "recentWorkspaces.xml"; //$NON-NLS-1$ + private static final int PERS_ENCODING_VERSION = 1; + + private String initialDefault; + private String selection; + private String[] recentWorkspaces; + + // xml tags + private static interface XML { + public static final String PROTOCOL = "protocol"; //$NON-NLS-1$ + public static final String VERSION = "version"; //$NON-NLS-1$ + public static final String WORKSPACE = "workspace"; //$NON-NLS-1$ + public static final String RECENT_WORKSPACES = "recentWorkspaces"; //$NON-NLS-1$ + public static final String MAX_LENGTH = "maxLength"; //$NON-NLS-1$ + public static final String PATH = "path"; //$NON-NLS-1$ + } + + /** + * Creates a new instance, loading persistent data if its found. + */ + public ChooseWorkspaceData(String initialDefault) { + readPersistedData(); + this.initialDefault = initialDefault; + } + + /** + * Return the folder to be used as a default if no other information + * exists. Does not return null. + */ + public String getInitialDefault() { + if (initialDefault == null) + initialDefault = System.getProperty("user.dir") + + File.separator + "workspace"; + return initialDefault; + } + + /** + * Return the currently selected workspace or null if nothing is selected. + */ + public String getSelection() { + return selection; + } + + /** + * Return an array of recent workspaces sorted with the most recently used at + * the start. + */ + public String[] getRecentWorkspaces() { + return recentWorkspaces; + } + + /** + * The argument workspace has been selected, update the receiver. Does not + * persist the new values. + */ + public void workspaceSelected(String dir) { + // this just stores the selection, it is not inserted and persisted + // until the workspace is actually selected + selection = dir; + } + + /** + * Update the persistent store. Call this function after the currently selected + * value has been found to be ok. + */ + public void writePersistedData() { + Location configLoc = Platform.getConfigurationLocation(); + if (configLoc == null || configLoc.isReadOnly()) + return; + + URL persUrl = getPersistenceUrl(configLoc.getURL(), true); + if (persUrl == null) + return; + + // move the new selection to the front of the list + if(selection != null) { + String oldEntry = recentWorkspaces[0]; + recentWorkspaces[0] = selection; + for (int i = 1; i < recentWorkspaces.length && oldEntry != null; ++i) { + if (selection.equals(oldEntry)) + return; + String tmp = recentWorkspaces[i]; + recentWorkspaces[i] = oldEntry; + oldEntry = tmp; + } + } + + Writer writer = null; + try { + writer = new FileWriter(persUrl.getFile()); + + // E.g., + // + // + // + // + // + // + // + + XMLMemento memento = XMLMemento.createWriteRoot("launchWorkspaceData"); + + memento.createChild(XML.PROTOCOL) + .putInteger(XML.VERSION, PERS_ENCODING_VERSION); + + IMemento recentMemento = memento.createChild(XML.RECENT_WORKSPACES); + recentMemento.putInteger(XML.MAX_LENGTH, recentWorkspaces.length); + for(int i = 0; i < recentWorkspaces.length; ++i) { + if(recentWorkspaces[i] == null) + break; + recentMemento.createChild(XML.WORKSPACE).putString(XML.PATH, recentWorkspaces[i]); + } + memento.save(writer); + } catch (IOException e) { + IDEWorkbenchPlugin.log("Unable to write recent workspace data", new Status( //$NON-NLS-1$ + IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH, + IStatus.ERROR, e.getMessage(), e)); + } + finally { + if(writer != null) + try { + writer.close(); + } catch (IOException e1) { + // do nothing + } + } + } + + /** + * Look for and read data that might have been persisted from some previous + * run. Leave the receiver in a default state if no persistent data is + * found. + */ + private void readPersistedData() { + URL persUrl = null; + + Location configLoc = Platform.getConfigurationLocation(); + if(configLoc != null) + persUrl = getPersistenceUrl(configLoc.getURL(), false); + + try { + // inside try to get the safe default creation in the finally + // clause + if (persUrl == null) + return; + + // E.g., + // + // + // + // + // + // + // + + Reader reader = new FileReader(persUrl.getFile()); + XMLMemento memento = XMLMemento.createReadRoot(reader); + if (memento == null || !compatibleProtocol(memento)) + return; + + IMemento recent = memento.getChild(XML.RECENT_WORKSPACES); + if(recent == null) + return; + + Integer maxLength = recent.getInteger(XML.MAX_LENGTH); + int max = RECENT_MAX_LENGTH; + if(maxLength != null) + max = maxLength.intValue(); + + IMemento indices[] = recent.getChildren(XML.WORKSPACE); + if(indices == null || indices.length <= 0) + return; + + // if a user has edited maxLength to be shorter than the listed + // indices, accept the list (its tougher for them to retype a long + // list of paths than to update a max number) + max = Math.max(max, indices.length); + + recentWorkspaces = new String[max]; + for(int i = 0; i < indices.length; ++i) { + String path = indices[i].getString(XML.PATH); + if(path == null) + break; + recentWorkspaces[i] = path; + } + return; + } catch (IOException e) { + // do nothing -- cannot log because instance area has not been set + } catch (WorkbenchException e) { + // do nothing -- cannot log because instance area has not been set + } + finally { + // create safe default if needed + if(recentWorkspaces == null) + recentWorkspaces = new String[RECENT_MAX_LENGTH]; + } + } + + /** + * Return true if the protocol used to encode the argument memento is compatible + * with the receiver's implementation and false otherwise. + */ + private static boolean compatibleProtocol(IMemento memento) { + IMemento protocolMemento = memento.getChild(XML.PROTOCOL); + if(protocolMemento == null) + return false; + + Integer version = protocolMemento.getInteger(XML.VERSION); + return version != null && version.intValue() == PERS_ENCODING_VERSION; + } + + /** + * The workspace data is stored in the well known file pointed to by the result + * of this method. + * @param create If the directory and file does not exist this parameter + * controls whether it will be created. + * @return An url to the file and null if it does not exist or could not + * be created. + */ + private static URL getPersistenceUrl(URL baseUrl, boolean create) { + if(baseUrl == null) + return null; + + try { + // make sure the directory exists + URL url = new URL(baseUrl, PERS_FOLDER); + File dir = new File(url.getFile()); + if (!dir.exists() && (!create || !dir.mkdir())) + return null; + + // make sure the file exists + url = new URL(dir.toURL(), PERS_FILENAME); + File persFile = new File(url.getFile()); + if (!persFile.exists() && (!create || !persFile.createNewFile())) + return null; + + return persFile.toURL(); + } catch (IOException e) { + // cannot log because instance area has not been set + return null; + } + } +} Index: src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java =================================================================== RCS file: src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java diff -N src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation 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/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.ide; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +/** + * A dialog that prompts for a directory to use as a workspace. + */ +public class ChooseWorkspaceDialog extends TitleAreaDialog { + private ChooseWorkspaceData launchData; + private String currentSelection; + + /** + * Create a modal dialog on the arugment shell, using and updating the argument + * data object. + */ + public ChooseWorkspaceDialog(Shell parentShell, ChooseWorkspaceData launchData) { + super(parentShell); + this.launchData = launchData; + } + + /** + * Creates and returns the contents of the upper part of this dialog (above + * the button bar). + *

+ * The Dialog implementation of this framework method creates + * and returns a new Composite with no margins and spacing. + *

+ * + * @param the parent composite to contain the dialog area + * @return the dialog area control + */ + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + setTitle(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.dialogTitle")); //$NON-NLS-1$ + setMessage(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.dialogMessage")); //$NON-NLS-1$ + setTitleImage(); + + createWorkspaceBrowseRow(composite); + return composite; + } + + /** + * Configures the given shell in preparation for opening this window + * in it. + *

+ * The default implementation of this framework method + * sets the shell's image and gives it a grid layout. + * Subclasses may extend or reimplement. + *

+ * + * @param shell the shell + */ + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.dialogName")); //$NON-NLS-1$ + } + + /** + * Notifies that the ok button of this dialog has been pressed. + *

+ * The Dialog implementation of this framework method sets + * this dialog's return code to Window.OK + * and closes the dialog. Subclasses may override. + *

+ */ + protected void okPressed() { + launchData.workspaceSelected(currentSelection); + super.okPressed(); + } + + /** + * Notifies that the cancel button of this dialog has been pressed. + *

+ * The Dialog implementation of this framework method sets + * this dialog's return code to Window.CANCEL + * and closes the dialog. Subclasses may override if desired. + *

+ */ + protected void cancelPressed() { + currentSelection = null; + launchData.workspaceSelected(currentSelection); + super.cancelPressed(); + } + + private void setTitleImage() { + try { + URL installURL = Platform.getPlugin( + IDEWorkbenchPlugin.IDE_WORKBENCH).getDescriptor() + .getInstallURL(); + URL url = new URL(installURL, "icons/full/wizban/newfolder_wiz.gif");//$NON-NLS-1$ + + ImageDescriptor desc = ImageDescriptor.createFromURL(url); + Image image = desc.createImage(); + if (image != null) + setTitleImage(image); + } catch (MalformedURLException e) { + // do nothing + } + } + + /** + * The main area of the dialog is just a row with the current selection + * information and a drop-down of the most recently used workspaces. + */ + private void createWorkspaceBrowseRow(Composite parent) { + Composite panel = new Composite(parent, SWT.NONE); + + GridLayout layout = new GridLayout(3, false); + layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + panel.setLayout(layout); + panel.setLayoutData(new GridData(GridData.FILL_BOTH)); + panel.setFont(parent.getFont()); + + Label label = new Label(panel, SWT.NONE); + label.setText(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.workspaceEntryLabel")); //$NON-NLS-1$ + + final Combo text = new Combo(panel, SWT.BORDER | SWT.LEAD + | SWT.DROP_DOWN); + text.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL + | GridData.FILL_HORIZONTAL)); + setInitialTextValues(text); + text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + currentSelection = text.getText(); + } + }); + + Button browseButton = new Button(panel, SWT.PUSH); + browseButton.setText(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.browseLabel")); //$NON-NLS-1$ + setButtonLayoutData(browseButton); + GridData data = (GridData) browseButton.getLayoutData(); + data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_END; + browseButton.setLayoutData(data); + browseButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + DirectoryDialog dialog = new DirectoryDialog(getShell()); + dialog.setText(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.directoryBrowserTitle")); //$NON-NLS-1$ + dialog.setMessage(IDEWorkbenchMessages + .getString("ChooseWorkspaceDialog.directoryBrowserMessage")); //$NON-NLS-1$ + dialog.setFilterPath(currentSelection); + String dir = dialog.open(); + if (dir != null) + text.setText(dir); + } + }); + } + + private void setInitialTextValues(Combo text) { + String[] recentWorkspaces = launchData.getRecentWorkspaces(); + for(int i = 0; i < recentWorkspaces.length; ++i) + if(recentWorkspaces[i] != null) + text.add(recentWorkspaces[i]); + + currentSelection = text.getItemCount() > 0 + ? text.getItem(0) + : launchData.getInitialDefault(); + text.setText(currentSelection); + } +} PK !ye0M *= =  WorkbenchPlugin.txtPK xe0:ʭ#v#v n org.eclipse.ui.internal.ide.txtPK xe0Cq8OO ΁messages.properties.txtPK