blob: 5026e4ec842ba3812ff1a8d7a1a9d345eafc5d3e [file] [log] [blame]
/*=============================================================================#
# 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();
}
}