| /*=============================================================================# |
| # Copyright (c) 2012, 2019 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.emf.ui.forms; |
| |
| import java.util.Collection; |
| import java.util.Iterator; |
| |
| import org.eclipse.core.databinding.observable.IObserving; |
| import org.eclipse.core.databinding.observable.list.IObservableList; |
| import org.eclipse.core.databinding.observable.value.IObservableValue; |
| import org.eclipse.emf.common.notify.AdapterFactory; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.databinding.edit.EMFEditProperties; |
| import org.eclipse.emf.databinding.edit.IEMFEditListProperty; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.edit.command.CommandParameter; |
| import org.eclipse.emf.edit.domain.EditingDomain; |
| import org.eclipse.emf.edit.provider.IViewerNotification; |
| import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter; |
| import org.eclipse.emf.edit.ui.dnd.LocalTransfer; |
| import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter; |
| import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; |
| import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; |
| import org.eclipse.jface.action.IContributionItem; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; |
| import org.eclipse.jface.databinding.viewers.typed.ViewerProperties; |
| import org.eclipse.jface.viewers.ISelectionProvider; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.TableViewer; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Menu; |
| |
| import org.eclipse.statet.ecommons.emf.core.databinding.IEMFEditContext; |
| import org.eclipse.statet.ecommons.ui.components.ButtonGroup; |
| import org.eclipse.statet.ecommons.ui.content.ElementSourceSelectionProvider; |
| import org.eclipse.statet.ecommons.ui.util.MenuUtils; |
| import org.eclipse.statet.ecommons.ui.viewers.ViewerUtils; |
| import org.eclipse.statet.ecommons.ui.viewers.ViewerUtils.TableComposite; |
| |
| |
| public class EObjectListProperty<TProperty extends EObject> extends EFProperty { |
| |
| |
| private class LabelProvider extends AdapterFactoryLabelProvider { |
| |
| protected Viewer viewer; |
| protected AdapterFactoryContentProvider.ViewerRefresh viewerRefresh; |
| |
| public LabelProvider(final AdapterFactory adapterFactory, final Viewer viewer) { |
| super(adapterFactory); |
| |
| this.viewer= viewer; |
| } |
| |
| @Override |
| public void notifyChanged(final Notification notification) { |
| if (this.viewer != null && this.viewer.getControl() != null && !this.viewer.getControl().isDisposed() |
| && notification instanceof IViewerNotification) { |
| final IViewerNotification viewerNotification= (IViewerNotification) notification; |
| if (viewerNotification.isLabelUpdate()) { |
| if (this.viewerRefresh == null) { |
| this.viewerRefresh= new AdapterFactoryContentProvider.ViewerRefresh(this.viewer); |
| } |
| if (this.viewerRefresh.addNotification(viewerNotification)) { |
| this.viewer.getControl().getDisplay().asyncExec(this.viewerRefresh); |
| } |
| } |
| } |
| super.notifyChanged(notification); |
| } |
| |
| } |
| |
| private class AddHandler extends ButtonGroup.AddHandler { |
| |
| |
| private MenuManager menuManager; |
| |
| |
| public AddHandler() { |
| } |
| |
| |
| @Override |
| public boolean run(final IStructuredSelection selection) { |
| if (this.menuManager == null) { |
| this.menuManager= new MenuManager(); |
| } |
| else { |
| this.menuManager.removeAll(); |
| } |
| fillMenu(this.menuManager); |
| |
| final Menu menu= this.menuManager.createContextMenu(getControl()); |
| MenuUtils.setPullDownPosition(menu, getControl()); |
| menu.setVisible(true); |
| return false; |
| } |
| |
| protected void fillMenu(final MenuManager menuManager) { |
| final EditingDomain editingDomain= getEditingDomain(); |
| final EObject base= (EObject) getBaseObservable().getValue(); |
| if (base == null) { |
| return; |
| } |
| final Collection<?> descriptors= editingDomain.getNewChildDescriptors(base, null); |
| for (final Object descriptor : descriptors) { |
| if (!(descriptor instanceof CommandParameter)) { |
| continue; |
| } |
| final CommandParameter parameter= (CommandParameter) descriptor; |
| if (parameter.getEStructuralFeature() != getEFeature()) { |
| continue; |
| } |
| final IContributionItem item= new EditCommandContributionItem(parameter, |
| editingDomain, getBaseObservable() ) { |
| @Override |
| protected void executed(final Collection<?> result) { |
| final Iterator<?> iter= result.iterator(); |
| if (iter.hasNext()) { |
| final TProperty value= (TProperty) iter.next(); |
| if (EObjectListProperty.this.modelObservable.contains(value)) { |
| EObjectListProperty.this.singleSelectionObservable.setValue(value); |
| } |
| } |
| } |
| }; |
| menuManager.add(item); |
| } |
| } |
| |
| @Override |
| public void widgetDisposed(final DisposeEvent e) { |
| if (this.menuManager != null) { |
| this.menuManager.dispose(); |
| } |
| } |
| |
| } |
| |
| |
| private TableComposite widget; |
| private ButtonGroup<TProperty> buttonGroup; |
| |
| private IObservableList<TProperty> modelObservable; |
| |
| private ElementSourceSelectionProvider selectionProvider; |
| private IObservableValue<TProperty> singleSelectionObservable; |
| |
| |
| public EObjectListProperty(final String label, final String tooltip, |
| final EClass eClass, final EStructuralFeature eFeature) { |
| super(label, tooltip, eClass, eFeature); |
| } |
| |
| |
| @Override |
| public void create(final Composite parent, final IEFFormPage page) { |
| this.widget= page.getToolkit().createPropSingleColumnTable(parent, 10, 25); |
| |
| this.widget.viewer.setContentProvider(new ObservableListContentProvider()); |
| this.widget.viewer.setLabelProvider(new LabelProvider( |
| page.getEditor().getAdapterFactory(), this.widget.viewer )); |
| |
| this.buttonGroup= new ButtonGroup<>(parent); |
| this.buttonGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); |
| |
| customizeButtonGroup(this.buttonGroup); |
| } |
| |
| protected void customizeButtonGroup(final ButtonGroup<TProperty> buttonGroup) { |
| buttonGroup.addAddButton(new AddHandler()); |
| buttonGroup.addDeleteButton(null); |
| buttonGroup.addSeparator(); |
| buttonGroup.addUpButton(null); |
| buttonGroup.addDownButton(null); |
| } |
| |
| @Override |
| public Control getControl() { |
| return this.widget; |
| } |
| |
| public TableViewer getViewer() { |
| return this.widget.viewer; |
| } |
| |
| @Override |
| public void bind(final IEMFEditContext context) { |
| super.bind(context); |
| |
| final IEMFEditListProperty emfProperty= EMFEditProperties.list(getEditingDomain(), |
| getEFeature() ); |
| this.modelObservable= emfProperty.observeDetail(getBaseObservable()); |
| ((IObserving) this.modelObservable).getObserved(); |
| |
| this.widget.viewer.setInput(this.modelObservable); |
| this.buttonGroup.connectTo(this.widget.viewer, this.modelObservable, null); |
| |
| register(this.widget.table, IEFPropertyExpressions.EOBJECT_LIST_ID); |
| this.selectionProvider= new ElementSourceSelectionProvider(this.widget.viewer, this); |
| ViewerUtils.setSelectionProvider(this.widget.table, this.selectionProvider); |
| |
| { final int operations= (DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_MOVE); |
| final Transfer[] transfers= new Transfer[] { LocalTransfer.getInstance() }; |
| this.widget.viewer.addDragSupport(operations, transfers, new ViewerDragAdapter(this.widget.viewer)); |
| this.widget.viewer.addDropSupport(operations, transfers, new EditingDomainViewerDropAdapter( |
| getEditingDomain(), this.widget.viewer )); |
| } |
| |
| this.singleSelectionObservable= |
| ViewerProperties.singlePostSelection((Class<TProperty>)this.modelObservable.getElementType()) |
| .observe(this.widget.viewer); |
| |
| this.buttonGroup.updateState(); |
| } |
| |
| @Override |
| public IObservableList<TProperty> getPropertyObservable() { |
| return this.modelObservable; |
| } |
| |
| public IObservableValue<TProperty> getSingleSelectionObservable() { |
| return this.singleSelectionObservable; |
| } |
| |
| public ISelectionProvider getSelectionProvider() { |
| return this.selectionProvider; |
| } |
| |
| } |