| /*=============================================================================# |
| # Copyright (c) 2017, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ecommons.ui.workbench.workspace; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jface.viewers.DoubleClickEvent; |
| import org.eclipse.jface.viewers.IDoubleClickListener; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.ui.dialogs.SelectionStatusDialog; |
| |
| import org.eclipse.statet.jcommons.collections.ImCollections; |
| |
| |
| public abstract class AbstractResourceSelectionDialog<TResource extends IResource> extends SelectionStatusDialog { |
| |
| |
| public static IResource findExistingResource(final IPath path, final IContainer base) { |
| IResource initialElement= null; |
| if (path != null) { |
| IContainer container= base; |
| final int nSegments= path.segmentCount(); |
| for (int i= 0; i < nSegments; i++) { |
| final IResource elem= container.findMember(path.segment(i)); |
| if (elem != null) { |
| initialElement= elem; |
| } |
| if (elem instanceof IContainer) { |
| container= (IContainer) elem; |
| } |
| else { |
| break; |
| } |
| } |
| } |
| return initialElement; |
| } |
| |
| |
| /* the root element to populate the viewer with */ |
| private IContainer rootContainer; |
| |
| private boolean allowNew; |
| |
| private TResource selectedResource; |
| |
| private Text textField; |
| private boolean ignoreTextFieldModifications= false; |
| |
| |
| public AbstractResourceSelectionDialog(final Shell parent) { |
| super(parent); |
| |
| setHelpAvailable(false); |
| setShellStyle(getShellStyle() | SWT.RESIZE); |
| } |
| |
| |
| protected abstract String getDefaultMessage(); |
| |
| protected abstract int getResourceTypes(); |
| |
| |
| public void setRootElement(final IContainer container) { |
| this.rootContainer= container; |
| } |
| |
| protected IContainer getRootElement() { |
| return this.rootContainer; |
| } |
| |
| public void setAllowNewResources(final boolean allowNew) { |
| this.allowNew= allowNew; |
| } |
| |
| protected boolean isAllowNewResources() { |
| return this.allowNew; |
| } |
| |
| public void setInitialElementSelection(final IResource resource) { |
| setInitialElementSelections((resource != null) ? ImCollections.newList(resource) : null); |
| } |
| |
| protected TResource getSelectedResource() { |
| return this.selectedResource; |
| } |
| |
| |
| @Override |
| public void create() { |
| // check settings |
| if (this.rootContainer == null) { |
| setRootElement(ResourcesPlugin.getWorkspace().getRoot()); |
| } |
| if (getMessage() == null) { |
| setMessage(getDefaultMessage()); |
| } |
| |
| super.create(); |
| |
| initDialog(); |
| } |
| |
| protected ISelectionChangedListener createSelectionChangeListener() { |
| return new ISelectionChangedListener() { |
| @Override |
| public void selectionChanged(final SelectionChangedEvent event) { |
| final IResource selection= (IResource) |
| ((IStructuredSelection) event.getSelection()).getFirstElement(); |
| if (selection != null) { |
| onResourceSelected(selection); |
| validate(); |
| } |
| } |
| }; |
| } |
| |
| protected IDoubleClickListener createSelectionDoubleClickListener() { |
| return new IDoubleClickListener() { |
| @Override |
| public void doubleClick(final DoubleClickEvent event) { |
| if (getOkButton().isEnabled()) { |
| okPressed(); |
| } |
| } |
| }; |
| } |
| |
| protected void createTextField(final Composite composite) { |
| this.textField= new Text(composite, SWT.BORDER | SWT.SINGLE); |
| this.textField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| this.textField.addModifyListener((final ModifyEvent e) -> { |
| if (!AbstractResourceSelectionDialog.this.ignoreTextFieldModifications) { |
| onTextChanged(AbstractResourceSelectionDialog.this.textField.getText()); |
| validate(); |
| } |
| }); |
| } |
| |
| protected void initSelection(final List<IResource> checkedResources) { |
| } |
| |
| |
| protected IResource checkSelectionElement(final Object o) { |
| if (o instanceof IResource) { |
| final IResource resource= (IResource) o; |
| final IPath fullPath= resource.getFullPath(); |
| final IPath rootPath= this.rootContainer.getFullPath(); |
| if (rootPath.isPrefixOf(fullPath)) { |
| return findExistingResource(fullPath.makeRelativeTo(rootPath), this.rootContainer); |
| } |
| } |
| return null; |
| } |
| |
| protected void initDialog() { |
| { // init selection |
| final List elements= getInitialElementSelections(); |
| if (!elements.isEmpty()) { |
| final List<IResource> checkedResources= new ArrayList<>(); |
| for (final Object o : elements) { |
| final IResource resource= checkSelectionElement(o); |
| if (resource != null) { |
| checkedResources.add(resource); |
| } |
| } |
| if (!checkedResources.isEmpty()) { |
| initSelection(checkedResources); |
| } |
| } |
| } |
| |
| validate(); |
| } |
| |
| |
| private void setSelectedResource0(final IResource resource) { |
| this.selectedResource= ((resource.getType() & getResourceTypes()) != 0) ? |
| (TResource) resource : null; |
| } |
| |
| protected void onTextChanged(String pathText) { |
| pathText= pathText.trim(); |
| |
| IResource resource= null; |
| try { |
| final IPath path= new Path(pathText).makeRelative(); |
| resource= this.rootContainer.findMember(path); |
| if (resource == null) { |
| resource= (path.hasTrailingSeparator() |
| || ((getResourceTypes() & IResource.FILE) == 0)) ? |
| this.rootContainer.getFolder(path) : |
| this.rootContainer.getFile(path); |
| } |
| } |
| catch (final IllegalArgumentException e) {} |
| |
| setSelectedResource0(resource); |
| } |
| |
| protected void onResourceSelected(final IResource resource) { |
| setSelectedResource0(resource); |
| |
| this.ignoreTextFieldModifications= true; |
| try { |
| final String pathText= (resource != null) ? |
| resource.getFullPath().makeRelativeTo( |
| this.rootContainer.getFullPath()).toString() : |
| ""; //$NON-NLS-1$ |
| this.textField.setText(pathText); |
| } |
| finally { |
| this.ignoreTextFieldModifications= false; |
| } |
| } |
| |
| protected void validate() { |
| boolean isValid= false; |
| final IResource selectedResource= getSelectedResource(); |
| if (selectedResource != null) { |
| final IPath path= selectedResource.getFullPath(); |
| final IStatus test= ResourcesPlugin.getWorkspace().validatePath(path.toString(), IResource.FILE); |
| isValid= (test.getCode() == IStatus.OK && this.rootContainer.getFullPath().isPrefixOf(path) |
| && (isAllowNewResources() || selectedResource.exists()) ); |
| } |
| getOkButton().setEnabled(isValid); |
| } |
| |
| |
| @Override |
| protected void computeResult() { |
| setSelectionResult(new IResource[] { getSelectedResource() }); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public TResource getFirstResult() { |
| return (TResource) super.getFirstResult(); |
| } |
| |
| } |