blob: e0917726b3a7da0b8b94b4d68dc6c9b5af2a5909 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013, 2017 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* CEA LIST - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.cdo.internal.ui.dialogs;
import org.eclipse.emf.cdo.eresource.CDOResourceFolder;
import org.eclipse.emf.cdo.eresource.CDOResourceNode;
import org.eclipse.emf.cdo.eresource.EresourcePackage;
import org.eclipse.emf.cdo.explorer.CDOExplorerUtil;
import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout;
import org.eclipse.emf.cdo.util.CDOURIUtil;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewInvalidationEvent;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.ui.views.IElementFilter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.papyrus.cdo.internal.core.CDOUtils;
import org.eclipse.papyrus.cdo.internal.ui.l10n.Messages;
import org.eclipse.papyrus.cdo.internal.ui.util.UIUtil;
import org.eclipse.papyrus.cdo.internal.ui.views.CheckoutItemProvider;
import org.eclipse.papyrus.cdo.internal.ui.widgets.ActionButton;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.CreateFolderAction;
import com.google.common.base.Strings;
/**
* This is the CheckoutBrowseDialog type. Enjoy.
*/
public class CheckoutBrowseDialog extends TitleAreaDialog {
private final String windowTitle;
private final String title;
private final String message;
private final int style;
private final CDOCheckout checkout;
private boolean allowOverwrite = false;
private EClass nodeTypeFilter = EresourcePackage.Literals.CDO_RESOURCE_NODE;
private TreeViewer tree;
private Text nameText;
private URI initialURI;
private CDOResourceNode selection;
private String name;
private IListener viewerRefresh;
/**
* @param style
* one of {@link SWT#OPEN} or {@link SWT#SAVE}
*/
public CheckoutBrowseDialog(Shell parentShell, String title, String message, CDOView view, int style) {
this(parentShell, Messages.CheckoutBrowseDialog_windowTitle, title, message, view, style);
}
/**
* @param style
* one of {@link SWT#OPEN} or {@link SWT#SAVE}
*/
public CheckoutBrowseDialog(Shell parentShell, String windowTitle, String title, String message, CDOView view, int style) {
super(parentShell);
this.windowTitle = windowTitle;
this.title = title;
this.message = message;
this.style = checkStyle(style);
this.checkout = (view == null) ? null : CDOExplorerUtil.getCheckout(view);
setHelpAvailable(false);
}
int checkStyle(int style) {
setShellStyle(getShellStyle() | (style & ~(SWT.OPEN | SWT.SAVE)));
return style & (SWT.OPEN | SWT.SAVE);
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(windowTitle);
newShell.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
shellDisposed();
}
});
}
private void shellDisposed() {
if (viewerRefresh != null) {
for (CDOCheckout next : CDOExplorerUtil.getCheckoutManager().getCheckouts()) {
if (next.isOpen()) {
next.getView().removeListener(viewerRefresh);
}
}
}
}
public boolean isAllowOverwrite() {
return allowOverwrite;
}
public void setAllowOverwrite(boolean allowOverwrite) {
this.allowOverwrite = allowOverwrite;
}
public EClass getNodeTypeFilter() {
return nodeTypeFilter;
}
public void setNodeTypeFilter(EClass nodeTypeFilter) {
boolean defaulted = (nodeTypeFilter == null) || !EresourcePackage.Literals.CDO_RESOURCE_NODE.isSuperTypeOf(nodeTypeFilter);
this.nodeTypeFilter = defaulted ? EresourcePackage.Literals.CDO_RESOURCE_NODE : nodeTypeFilter;
}
public URI getInitialURI() {
return initialURI;
}
public void setInitialURI(URI initialURI) {
this.initialURI = initialURI;
}
public URI getSelectedURI() {
return (getReturnCode() != Window.OK) ? null : basicGetSelectedURI();
}
private URI basicGetSelectedURI() {
URI result = null;
if (selection != null) {
result = selection.getURI();
if (name != null) {
String resourceName = Strings.emptyToNull(name);
if (resourceName != null) {
if (!(selection instanceof CDOResourceFolder)) {
// append the name to the parent folder
result = result.trimSegments(1);
}
result = result.appendSegment(resourceName);
}
}
}
return result;
}
boolean isOpenStyle() {
return (style & SWT.OPEN) != 0;
}
boolean isSaveStyle() {
return (style & SWT.SAVE) != 0;
}
CDOCheckout getCheckout() {
return checkout;
}
@Override
protected Control createDialogArea(Composite parent) {
setTitle(title);
setMessage(message);
Composite main = (Composite) super.createDialogArea(parent);
Composite result = new Composite(main, SWT.NONE);
result.setLayout(new GridLayout(isSaveStyle() ? 3 : 1, false));
result.setLayoutData(new GridData(GridData.FILL_BOTH));
tree = new TreeViewer(result, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
tree.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, isSaveStyle() ? 2 : 1, 1));
CheckoutItemProvider itemProvider = (getCheckout() == null) ? new CheckoutItemProvider(null, showConnectedRepositories()) : new CheckoutItemProvider(null, getCheckout());
tree.setContentProvider(itemProvider);
tree.setLabelProvider(new DecoratingLabelProvider(itemProvider, PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()));
tree.setSorter(itemProvider);
tree.setInput(CDOExplorerUtil.getCheckoutManager());
for (CDOCheckout next : CDOExplorerUtil.getCheckoutManager().getCheckouts()) {
if (next.isOpen()) {
next.getView().addListener(getViewerRefresh());
}
}
if (isSaveStyle()) {
// don't need to create new folders when opening an existing resource
Composite actionButtons = new Composite(result, SWT.NONE);
actionButtons.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
actionButtons.setLayout(new RowLayout(SWT.VERTICAL));
ActionButton newFolderButton = new ActionButton(Messages.CheckoutBrowseDialog_newFolderAction, new CreateFolderAction(this), SWT.PUSH);
newFolderButton.attach(tree);
newFolderButton.createControl(actionButtons);
// don't need to type in names of non-existent resources when opening an existing resource
Label label = new Label(result, SWT.NONE);
label.setText(Messages.CheckoutBrowseDialog_nameLabel);
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.verticalIndent = convertVerticalDLUsToPixels(8);
label.setLayoutData(gd);
nameText = new Text(result, SWT.BORDER);
gd = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1);
gd.verticalIndent = convertVerticalDLUsToPixels(8);
nameText.setLayoutData(gd);
}
if (getInitialURI() != null) {
initializeSelection();
} else if (getCheckout() != null) {
selection = getCheckout().getView().getRootResource();
}
tree.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection sel = (IStructuredSelection) event.getSelection();
if (sel.isEmpty()) {
if (getCheckout() != null) {
selection = getCheckout().getView().getRootResource();
} else {
selection = null;
}
} else {
selection = CDOUtils.adapt(sel.getFirstElement(), CDOResourceNode.class);
}
validateSelection();
}
});
if (nameText != null) {
nameText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
name = Strings.emptyToNull(nameText.getText().trim());
validateSelection();
}
});
}
return result;
}
private IElementFilter showConnectedRepositories() {
return new IElementFilter() {
@Override
public boolean filter(Object element) {
boolean result = false;
if (element instanceof CDOCheckout) {
result = ((CDOCheckout) element).isOpen();
}
return result;
}
};
}
private void initializeSelection() {
URI uri = getInitialURI();
CDOView view = getCheckout().getView();
String path = CDOURIUtil.extractResourcePath(uri);
if (view.hasResource(path)) {
selection = view.getResourceNode(path);
tree.setSelection(new StructuredSelection(selection));
tree.expandToLevel(selection, 1);
if (nameText != null) {
name = selection.getName();
nameText.setText(name);
}
} else if (uri.segmentCount() > 0) {
// try the containing folder, then
URI parent = uri.trimSegments(1);
path = CDOURIUtil.extractResourcePath(parent);
if (view.hasResource(path)) {
// if the root resource, it is represented by the checkout
selection = view.getResourceNode(path);
Object treeSelection = selection.isRoot() ? getCheckout() : selection;
tree.setSelection(new StructuredSelection(treeSelection), true);
tree.expandToLevel(treeSelection, 1);
if (nameText != null) {
name = uri.lastSegment();
nameText.setText(name);
}
}
} else {
// select the checkout (representing the root resource)
selection = view.getRootResource();
Object treeSelection = getCheckout();
tree.setSelection(new StructuredSelection(treeSelection), true);
tree.expandToLevel(treeSelection, 1);
}
}
private void validateSelection() {
String error = null;
String warning = null;
String info = null;
boolean disable = false;
if (name != null) {
if (!URI.validSegment(name)) {
error = Messages.CheckoutBrowseDialog_invalidURISeg;
}
}
if (error == null) {
if (selection == null) {
disable = true;
} else {
String path = CDOURIUtil.extractResourcePath(basicGetSelectedURI());
CDOView view = selection.cdoView();
if (isOpenStyle() && !view.hasResource(path)) {
error = Messages.CheckoutBrowseDialog_noSuchResource;
} else if (isOpenStyle()) {
// then the resource exists. Is it the kind we want?
CDOResourceNode node = view.getResourceNode(path);
if (!getNodeTypeFilter().isInstance(node)) {
disable = true;
info = NLS.bind(Messages.CheckoutBrowseDialog_wrongSelection, getNodeType(getNodeTypeFilter()));
}
} else if (isSaveStyle() && view.hasResource(path)) {
if (isAllowOverwrite()) {
warning = Messages.CheckoutBrowseDialog_existsWarning;
} else {
error = Messages.CheckoutBrowseDialog_existsError;
}
}
}
}
getButton(IDialogConstants.OK_ID).setEnabled(!disable && (error == null));
if (error != null) {
setMessage(error, IMessageProvider.ERROR);
} else if (warning != null) {
setMessage(warning, IMessageProvider.WARNING);
} else if (info != null) {
setMessage(info, IMessageProvider.INFORMATION);
} else {
setMessage(message);
}
}
private String getNodeType(EClass nodeClass) {
String result = Messages.CheckoutBrowseDialog_anyNode;
if (nodeClass.getEPackage() == EresourcePackage.eINSTANCE) {
switch (nodeClass.getClassifierID()) {
case EresourcePackage.CDO_RESOURCE:
result = Messages.CheckoutBrowseDialog_modelKind;
break;
case EresourcePackage.CDO_RESOURCE_FOLDER:
result = Messages.CheckoutBrowseDialog_folderKind;
break;
case EresourcePackage.CDO_TEXT_RESOURCE:
result = Messages.CheckoutBrowseDialog_textKind;
break;
case EresourcePackage.CDO_BINARY_RESOURCE:
result = Messages.CheckoutBrowseDialog_binKind;
break;
case EresourcePackage.CDO_FILE_RESOURCE:
result = Messages.CheckoutBrowseDialog_fileKind;
break;
case EresourcePackage.CDO_RESOURCE_LEAF:
result = Messages.CheckoutBrowseDialog_leafKind;
break;
}
}
return result;
}
private IListener getViewerRefresh() {
if (viewerRefresh == null) {
viewerRefresh = new IListener() {
@Override
public void notifyEvent(IEvent event) {
if (event instanceof CDOViewInvalidationEvent) {
if ((getContents() != null) && !getContents().isDisposed()) {
if (UIUtil.ensureUIThread(this, event)) {
tree.refresh();
}
}
}
}
};
}
return viewerRefresh;
}
}