/* * Copyright (c) 2013, 2015, 2016 Eike Stepper (Berlin, Germany) and others. * 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 * * Contributors: * Christian W. Damus (CEA LIST) - initial API and implementation */ package org.eclipse.emf.cdo.security.internal.ui.editor; import org.eclipse.emf.cdo.security.Directory; import org.eclipse.emf.cdo.security.Realm; import org.eclipse.emf.cdo.security.SecurityFactory; import org.eclipse.emf.cdo.security.SecurityPackage; import org.eclipse.emf.cdo.security.internal.ui.messages.Messages; import org.eclipse.emf.cdo.security.internal.ui.util.ActionBarsHelper; import org.eclipse.emf.cdo.security.internal.ui.util.ObjectExistsConverter.ObjectWritableConverter; import org.eclipse.emf.cdo.security.internal.ui.util.SecurityUIUtil; import org.eclipse.emf.cdo.security.internal.ui.util.TableLabelProvider; import org.eclipse.emf.cdo.ui.shared.SharedIcons; import org.eclipse.net4j.util.ui.UIUtil; import org.eclipse.net4j.util.ui.actions.SelectionListenerAction; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.edit.command.AddCommand; import org.eclipse.emf.edit.command.CommandActionDelegate; import org.eclipse.emf.edit.command.CommandParameter; import org.eclipse.emf.edit.command.CreateChildCommand; import org.eclipse.emf.edit.command.DeleteCommand; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; import org.eclipse.core.databinding.beans.PojoProperties; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.databinding.viewers.ViewersObservables; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.LocalSelectionTransfer; 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.StructuredViewer; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.ViewerDropAdapter; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.dnd.TransferData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; import java.util.Collections; /** * Common framework for section parts of a form that present a list of * similar objects. It presents buttons for adding and deleting * objects in the list. The objects presented are the contents * (of the appropriate type) of some {@link Directory} in the security * realm model. * * @author Christian W. Damus (CEA LIST) */ public abstract class TableSection<T extends EObject> extends AbstractSectionPart<Directory> { private final Class<T> elementType; private final EClass elementEClass; private TableViewer viewer; public TableSection(Class<T> elementType, EClass elementEClass, EditingDomain domain, AdapterFactory adapterFactory) { super(Directory.class, SecurityPackage.Literals.DIRECTORY, domain, adapterFactory); this.elementType = elementType; this.elementEClass = elementEClass; } @Override protected void createContents(Composite parent, FormToolkit toolkit) { parent.setLayout(new GridLayout()); Table table = toolkit.createTable(parent, SWT.H_SCROLL | SWT.V_SCROLL); table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); viewer = new TableViewer(table); viewer.setContentProvider(new AdapterFactoryContentProvider(getAdapterFactory())); viewer.setLabelProvider(new TableLabelProvider(getAdapterFactory())); addFilters(viewer); forwardSelection(viewer); getContext().bindValue(ViewersObservables.observeInput(viewer), getValue()); configureDragSupport(viewer); configureDropSupport(viewer); } @Override public void setFocus() { if (viewer != null) { viewer.getControl().setFocus(); } else { super.setFocus(); } } protected void addFilters(TableViewer viewer) { SecurityUIUtil.applyTypeFilter(viewer, elementEClass); SecurityUIUtil.applySupportedElementFilter(viewer, elementEClass); } @Override public boolean setFormInput(Object input) { if (elementType.isInstance(input)) { viewer.setSelection(new StructuredSelection(input), true); return true; } else if (input instanceof Directory && input == getDirectory(((Directory)input).getRealm())) { // It's my directory boolean result = super.setFormInput(input); checkForUnsupportedModelContent(); return result; } else if (input instanceof Realm) { return setFormInput(getDirectory((Realm)input)); } return false; } protected Directory getDirectory(Realm realm) { return SecurityUIUtil.getDirectory(realm, elementEClass); } @Override protected void createActionToolbar(Section section, FormToolkit toolkit) { ToolBarManager mgr = new ToolBarManager(SWT.FLAT); ToolBar toolbar = mgr.createControl(section); toolbar.setCursor(section.getDisplay().getSystemCursor(SWT.CURSOR_HAND)); mgr.add(createAddNewAction()); IAction deleteAction = createDeleteAction(); mgr.add(deleteAction); if (deleteAction instanceof ISelectionChangedListener) { ISelectionChangedListener scl = (ISelectionChangedListener)deleteAction; viewer.addSelectionChangedListener(scl); scl.selectionChanged(new SelectionChangedEvent(viewer, viewer.getSelection())); } mgr.update(true); section.setTextClient(toolbar); ActionBarsHelper actionBarsHelper = new ActionBarsHelper(getEditorActionBars()); ActionBarsHelper globalAction = actionBarsHelper.addGlobalAction(ActionFactory.DELETE.getId(), deleteAction); globalAction.install(viewer); } @SuppressWarnings("unchecked") protected IAction createAddNewAction() { Command dummy = createCreateNewCommand(); ImageDescriptor image = null; if (dummy instanceof CommandActionDelegate) { image = ExtendedImageRegistry.getInstance().getImageDescriptor(((CommandActionDelegate)dummy).getImage()); } IAction result = new Action(dummy.getLabel(), image) { @Override public void run() { final Command command = createCreateNewCommand(); if (command.canExecute()) { getEditingDomain().getCommandStack().execute(command); viewer.getControl().getDisplay().asyncExec(new Runnable() { public void run() { viewer.getControl().setFocus(); viewer.setSelection(new StructuredSelection(command.getResult().toArray())); } }); } } }; getContext().bindValue(PojoProperties.value("enabled").observe(getContext().getValidationRealm(), result), //$NON-NLS-1$ getValue(), null, ObjectWritableConverter.createUpdateValueStrategy()); return result; } protected Command createCreateNewCommand() { Object input = viewer.getInput(); Directory parent = input instanceof Directory ? (Directory)input : SecurityFactory.eINSTANCE.createDirectory(); Object child = EcoreUtil.create(elementEClass); CommandParameter param = new CommandParameter(parent, SecurityPackage.Literals.DIRECTORY__ITEMS, child); return CreateChildCommand.create(getEditingDomain(), parent, param, Collections.singleton(parent)); } protected IAction createDeleteAction() { Command dummy = createDeleteCommand(EcoreUtil.create(elementEClass)); return new SelectionListenerAction<EObject>(dummy.getLabel(), SharedIcons.getDescriptor("etool16/delete.gif")) //$NON-NLS-1$ { @Override public void run() { Command delete = createDeleteCommand(getSelectedObject()); if (delete.canExecute()) { getEditingDomain().getCommandStack().execute(delete); } } @Override protected boolean updateSelection(IStructuredSelection selection) { return super.updateSelection(selection) && SecurityUIUtil.isEditable(getInput()); } @Override protected Class<EObject> getType() { return EObject.class; } }; } protected Command createDeleteCommand(EObject toDelete) { return DeleteCommand.create(getEditingDomain(), toDelete); } private void forwardSelection(StructuredViewer viewer) { viewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { IManagedForm form = getManagedForm(); if (form != null) { form.fireSelectionChanged(TableSection.this, event.getSelection()); } } }); } protected void configureDragSupport(TableViewer viewer) { UIUtil.addDragSupport(viewer); } protected void configureDropSupport(final TableViewer viewer) { viewer.addDropSupport(DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY, new Transfer[] { LocalSelectionTransfer.getTransfer() }, new ViewerDropAdapter(viewer) { { // We don't want it to look like you can insert new elements, only drop onto existing elements setFeedbackEnabled(false); } @Override public boolean validateDrop(Object target, int operation, TransferData transferType) { boolean result = false; if (target instanceof EObject && LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) { EObject objectToDrop = getObjectToDrop(transferType); if (objectToDrop != null) { result = getDropReference((EObject)target, objectToDrop) != null; if (result && (getCurrentEvent().operations | DND.DROP_COPY) != 0) { overrideOperation(DND.DROP_COPY); } } } return result; } @Override public boolean performDrop(Object data) { IStructuredSelection selection = (IStructuredSelection)data; EObject objectToDrop = UIUtil.getElement(selection, EObject.class); EObject target = (EObject)getCurrentTarget(); Command command = AddCommand.create(getEditingDomain(), target, getDropReference(target, objectToDrop), selection.toList()); boolean result = execute(command); if (result) { viewer.getControl().setFocus(); viewer.setSelection(new StructuredSelection(target)); } return result; } private EObject getObjectToDrop(TransferData transferType) { return UIUtil.getElement(LocalSelectionTransfer.getTransfer().getSelection(), EObject.class); } }); } protected EReference getDropReference(EObject target, EObject objectToDrop) { return null; } protected boolean execute(Command command) { boolean result = command.canExecute(); if (result) { getEditingDomain().getCommandStack().execute(command); } return result; } protected void checkForUnsupportedModelContent() { if (getInput() == null) { getManagedForm().getMessageManager().addMessage(this, Messages.TableSection_2, null, IStatus.WARNING, viewer.getControl()); } else { // Anything not matching filters? if (viewer.getTable().getItemCount() < getInput().getItems().size()) { getManagedForm().getMessageManager().addMessage(this, Messages.TableSection_3, null, IStatus.WARNING, viewer.getControl()); } } } }