In progress: [ Issue 40 ] Add support for import resolution across multiple folders
https://code.google.com/p/protobuf-dt/issues/detail?id=40
Adding support for using both workspace and file system paths for resolution of imports.
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryNamesEditor.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryNamesEditor.java
index a829057..7815410 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryNamesEditor.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/DirectoryNamesEditor.java
@@ -11,18 +11,16 @@
import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.*;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;
-import static org.eclipse.jface.window.Window.OK;
-import static org.eclipse.xtext.util.Strings.isEmpty;
import java.util.Collection;
-import org.eclipse.jface.dialogs.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
-import org.eclipse.swt.layout.*;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
-import com.google.eclipse.protobuf.ui.util.*;
+import com.google.eclipse.protobuf.ui.util.SwtEventListeners;
/**
* Editor where users can add/remove the directories to be used for URI resolution.
@@ -31,7 +29,6 @@
*/
public class DirectoryNamesEditor extends Composite {
- private final DirectoryNameValidator directoryNameValidator;
private final SwtEventListeners eventListeners;
private List lstDirectoryNames;
@@ -42,12 +39,10 @@
private SelectionListener onChangeListener;
- public DirectoryNamesEditor(Composite parent, DirectoryNameValidator directoryNameValidator,
- SwtEventListeners eventListeners) {
+ public DirectoryNamesEditor(Composite parent, SwtEventListeners eventListeners) {
super(parent, SWT.NONE);
// generated by WindowBuilder
- this.directoryNameValidator = directoryNameValidator;
this.eventListeners = eventListeners;
setLayout(new GridLayout(3, false));
@@ -93,16 +88,9 @@
});
btnAdd.addSelectionListener(new SelectionAdapter() {
@Override public void widgetSelected(SelectionEvent e) {
- IInputValidator validator = new IInputValidator() {
- public String isValid(String newText) {
- String text = (newText == null) ? null : newText.trim();
- if (isEmpty(text)) return errorEmptyDirectoryName;
- return directoryNameValidator.validateDirectoryName(text);
- }
- };
- InputDialog input = new InputDialog(getShell(), directoryNameInputTitle, directoryNameInputMessage, null, validator);
- if (input.open() == OK) {
- lstDirectoryNames.add(input.getValue().trim());
+ IncludeDialog dialog = new IncludeDialog(getShell(), includeDirectoryTitle);
+ if (dialog.open()) {
+ lstDirectoryNames.add(dialog.getEnteredPath());
}
}
});
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/IncludeDialog.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/IncludeDialog.java
new file mode 100644
index 0000000..8c879f8
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/IncludeDialog.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.ui.preferences.paths;
+
+import static com.google.eclipse.protobuf.ui.preferences.paths.Messages.*;
+import static com.google.eclipse.protobuf.ui.swt.BrowseWorkspaceDialogLauncher.showSelectWorkspaceDirectoryDialog;
+import static org.eclipse.xtext.util.Strings.isEmpty;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Dialog where users can enter/select a path (in the workspace or file system) to be included in resolution of imports.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class IncludeDialog extends Dialog {
+
+ private final Shell parent;
+
+ private Shell shell;
+ private boolean result;
+
+ private String enteredPath;
+ private boolean isWorkspacePath;
+
+ private Text txtPath;
+ private Button btnWorkspace;
+ private Button btnIsWorkspacePath;
+ private Button btnFileSystem;
+ private Button btnCancel;
+ private Button btnOk;
+
+ /**
+ * Creates a new </code>{@link IncludeDialog}</code>.
+ * @param parent a shell which will be the parent of the new instance.
+ * @param title the title of this dialog.
+ */
+ public IncludeDialog(Shell parent, String title) {
+ super(parent, SWT.NONE);
+ this.parent = parent;
+ getStyle();
+ setText(title);
+ }
+
+ /**
+ * Opens this dialog.
+ * @return {@code true} if the user made a selection and pressed "OK" or {@code false} if the user pressed "Cancel."
+ */
+ public boolean open() {
+ result = false;
+ shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.RESIZE);
+ shell.setText(getText());
+ createAndCenterContent();
+ shell.open();
+ Display display = parent.getDisplay();
+ while (!shell.isDisposed())
+ if (!display.readAndDispatch()) display.sleep();
+ return result;
+ }
+
+ private void createAndCenterContent() {
+ shell.setLayout(new GridLayout(2, false));
+
+ Label label = new Label(shell, SWT.NONE);
+ label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ label.setText(includeDirectoryPrompt);
+
+ txtPath = new Text(shell, SWT.BORDER);
+ txtPath.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+
+ btnIsWorkspacePath = new Button(shell, SWT.CHECK);
+ btnIsWorkspacePath.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false, 1, 1));
+ btnIsWorkspacePath.setText(isWorkspacePathCheck);
+
+ Composite composite = new Composite(shell, SWT.NONE);
+ composite.setLayout(new GridLayout(2, true));
+ new Label(composite, SWT.NONE);
+
+ btnWorkspace = new Button(composite, SWT.NONE);
+ btnWorkspace.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+ btnWorkspace.setText(browseWorkspace);
+ new Label(composite, SWT.NONE);
+
+ btnFileSystem = new Button(composite, SWT.NONE);
+ btnFileSystem.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+ btnFileSystem.setText(browseFileSystem);
+
+ btnOk = new Button(composite, SWT.NONE);
+ btnOk.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+ btnOk.setEnabled(false);
+ btnOk.setText(ok);
+
+ btnCancel = new Button(composite, SWT.NONE);
+ btnCancel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+ btnCancel.setText(cancel);
+
+ addEventListeners();
+
+ shell.setDefaultButton(btnOk);
+ shell.pack();
+
+ centerWindow();
+ }
+
+ private void addEventListeners() {
+ btnWorkspace.addSelectionListener(new SelectionAdapter() {
+ @Override public void widgetSelected(SelectionEvent e) {
+ String path = showSelectWorkspaceDirectoryDialog(shell, txtPath.getText(), null);
+ if (path != null) {
+ txtPath.setText(path.trim());
+ btnIsWorkspacePath.setSelection(true);
+ }
+ }
+ });
+ btnOk.addSelectionListener(new SelectionAdapter() {
+ @Override public void widgetSelected(SelectionEvent e) {
+ enteredPath = txtPath.getText().trim();
+ isWorkspacePath = btnIsWorkspacePath.getSelection();
+ result = true;
+ shell.dispose();
+ }
+ });
+ btnCancel.addSelectionListener(new SelectionAdapter() {
+ @Override public void widgetSelected(SelectionEvent e) {
+ shell.dispose();
+ }
+ });
+ txtPath.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ boolean hasText = !isEmpty(txtPath.getText().trim());
+ btnOk.setEnabled(hasText);
+ }
+ });
+ }
+
+ private void centerWindow() {
+ Rectangle parentRect = parent.getBounds();
+ Rectangle shellRect = shell.getBounds();
+ int x = parentRect.x + (parentRect.width - shellRect.width) / 2;
+ int y = parentRect.y + (parentRect.height - shellRect.height) / 2;
+ shell.setBounds(x, y, shellRect.width, shellRect.height);
+ }
+
+ /**
+ * Returns the path entered/selected by the user.
+ * @return the path entered/selected by the user.
+ */
+ public String getEnteredPath() {
+ return enteredPath;
+ }
+
+ /**
+ * Indicates whether the path returned by <code>{@link #getEnteredPath()}</code> is a workspace path.
+ * @return {@code true} if the entered path is a workspace path; {@code false} otherwise.
+ */
+ public boolean isWorkspacePath() {
+ return isWorkspacePath;
+ }
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java
index ef56359..a51464b 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.java
@@ -16,6 +16,9 @@
public class Messages extends NLS {
public static String add;
+ public static String browseFileSystem;
+ public static String browseWorkspace;
+ public static String cancel;
public static String directoryNameInputMessage;
public static String directoryNameInputTitle;
public static String down;
@@ -24,6 +27,10 @@
public static String filesInMultipleDirectories;
public static String filesInOneDirectoryOnly;
public static String importedFilesPathResolution;
+ public static String includeDirectoryPrompt;
+ public static String includeDirectoryTitle;
+ public static String isWorkspacePathCheck;
+ public static String ok;
public static String remove;
public static String up;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties
index 0322aa3..fd8966b 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/Messages.properties
@@ -1,4 +1,7 @@
add=&Add
+browseFileSystem=File system...
+browseWorkspace=Workspace...
+cancel=Cancel
directoryNameInputMessage=Enter directory name:
directoryNameInputTitle=Path Resolution
down=&Down
@@ -7,5 +10,9 @@
filesInMultipleDirectories=Look for imported files in directories:
filesInOneDirectoryOnly=One directory for all .proto files
importedFilesPathResolution=Path resolution of imported files
+includeDirectoryPrompt=Directory:
+includeDirectoryTitle=Add directory path
+isWorkspacePathCheck=Is a workspace path
+ok=OK
remove=&Remove
up=&Up
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java
index d1c3807..d1cd8c5 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/paths/PathsPreferencePage.java
@@ -64,7 +64,7 @@
btnMultipleFolders.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
btnMultipleFolders.setText(filesInMultipleDirectories);
- directoryNamesEditor = new DirectoryNamesEditor(grpResolutionOfImported, directoryNameValidator, eventListeners);
+ directoryNamesEditor = new DirectoryNamesEditor(grpResolutionOfImported, eventListeners);
directoryNamesEditor.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
new Label(contents, SWT.NONE);
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/BrowseWorkspaceDialogLauncher.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/BrowseWorkspaceDialogLauncher.java
new file mode 100644
index 0000000..53c492a
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/BrowseWorkspaceDialogLauncher.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.ui.swt;
+
+import static com.google.eclipse.protobuf.ui.swt.Messages.*;
+import static org.eclipse.core.runtime.IStatus.ERROR;
+import static org.eclipse.core.runtime.Status.OK_STATUS;
+import static org.eclipse.jface.window.Window.OK;
+import static org.eclipse.ui.views.navigator.ResourceComparator.NAME;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
+import org.eclipse.ui.dialogs.ISelectionStatusValidator;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.views.navigator.ResourceComparator;
+
+/**
+ * Launches a dialog where users can browse a workspace.
+ *
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class BrowseWorkspaceDialogLauncher {
+
+ private static final String PLUGIN_ID = "com.google.eclipse.protobuf.ui";
+
+ public static String showSelectWorkspaceDirectoryDialog(Shell shell, String text, IProject project) {
+ String currentPathText = text.replaceAll("\"", "");
+ IPath path = new Path(currentPathText);
+ ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(shell, new WorkbenchLabelProvider(),
+ new WorkbenchContentProvider());
+ dialog.setInput(project == null ? workspaceRoot() : project);
+ dialog.setComparator(new ResourceComparator(NAME));
+ IResource container = null;
+ if (path.isAbsolute()) {
+ IContainer containers[] = workspaceRoot().findContainersForLocation(path);
+ if (containers != null && containers.length > 0) container = containers[0];
+ }
+ dialog.setInitialSelection(container);
+ dialog.setValidator(new ISelectionStatusValidator() {
+ public IStatus validate(Object[] selection) {
+ if (selection != null && selection.length > 0 && selection[0] instanceof IFile)
+ return new Status(ERROR, PLUGIN_ID, errorElementIsNotDirectory);
+ return OK_STATUS;
+ }
+ });
+ dialog.setTitle(browseWorkspaceFolderTitle);
+ dialog.setMessage(browseWorkspaceFolderPrompt);
+ if (dialog.open() != OK) return null;
+ IResource resource = (IResource) dialog.getFirstResult();
+ if (resource == null) return null;
+ StringBuilder b = new StringBuilder();
+ return b.append("${").append("workspace_loc:").append(resource.getFullPath()).append("}").toString();
+ }
+
+ private static IWorkspaceRoot workspaceRoot() {
+ return ResourcesPlugin.getWorkspace().getRoot();
+ }
+
+ private BrowseWorkspaceDialogLauncher() {}
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/Messages.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/Messages.java
new file mode 100644
index 0000000..699b0cc
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/Messages.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.ui.swt;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class Messages extends NLS {
+
+ public static String browseWorkspaceFolderPrompt;
+ public static String browseWorkspaceFolderTitle;
+ public static String errorElementIsNotDirectory;
+
+ static {
+ Class<Messages> targetType = Messages.class;
+ NLS.initializeMessages(targetType.getName(), targetType);
+ }
+
+ private Messages() {}
+}
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/Messages.properties b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/Messages.properties
new file mode 100644
index 0000000..b65ca74
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/swt/Messages.properties
@@ -0,0 +1,3 @@
+browseWorkspaceFolderPrompt=Select a folder from workspace:
+browseWorkspaceFolderTitle=Folder selection
+errorElementIsNotDirectory=The selected element is not a directory.