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.