Commit 755c43ce authored by Simon Barner's avatar Simon Barner
Browse files

Improve EReferenceListPropertySectionBase and make list view reusable

* EReferenceListPropertySectionBase
 * Introduce ElementListViewerComposite: Reusable Composite that
   provides a ListViewer & add/remove buttons
 * Usability improvements: enabled state of buttons, auto-select
   next element after "remove" operation
* Introduce IListPropertySection
  * To be implemented by classes that want to embed
    ElementListViewerComposite
  * Provides interface to data model

Issue-Ref: 3470
Issue-Url: https://af3-developer.fortiss.org/issues/3470

Signed-off-by: Simon Barner's avatarSimon Barner <barner@fortiss.org>
parent b8d0fb3a
......@@ -2,9 +2,10 @@ ConstraintUIBases.java 3676a600e0866091db9798763c6eee97eec5b55b GREEN
ContextMenuSubMenuContributorBase.java 6275d96fe8690d9d4744bcbaef3c7d14ba8e30ff GREEN
DialogMessageHandler.java 8714da09a777c8557de0a5c48ff68c340f9fa91d GREEN
EObjectActionBase.java 4ef9f8be59e64d4838acc9e268d418ba5d94fa1a GREEN
EReferenceListPropertySectionBase.java b43469e81cf9f959230e9b2353460c49d8d6a7d3 YELLOW
EReferenceListPropertySectionBase.java bbc5f6851842a9cb0af5e9898d9c6e197a36312a YELLOW
EReferencePropertySectionBase.java 3347e99b2fc135dd4b3117407179900ef757092c GREEN
EditorBase.java 9c09fff92945256bb8680992ae7bb2c78f47b150 GREEN
IListPropertySection.java a093a8a625d291b8adecec5082e32748a2d99f9e YELLOW
ModelEditorBindingBase.java 4c5ac569c0b6e7678fc8191096b26dfd09fdcb98 GREEN
ModelElementHandlerBase.java 384727748f125c9d43f19d9c0eba4ba1be5a7a26 GREEN
MultiEObjectActionBase.java 9e237d8ea640c4194e4877af4a9cfce88698e543 GREEN
......
......@@ -23,7 +23,11 @@ import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
......@@ -34,7 +38,6 @@ import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory;
import org.fortiss.tooling.kernel.ui.extension.base.EReferencePropertySectionBase;
import org.fortiss.tooling.kernel.ui.presentation.ModelElementLabelProvider;
/**
......@@ -43,7 +46,7 @@ import org.fortiss.tooling.kernel.ui.presentation.ModelElementLabelProvider;
* @author barner
*/
public abstract class EReferenceListPropertySectionBase<I extends EObject, R extends EObject>
extends EReferencePropertySectionBase<I, R> {
extends EReferencePropertySectionBase<I, R> implements IListPropertySection<I, R> {
/**
* Element that has been selected the combo box provided by the base class
......@@ -51,8 +54,144 @@ public abstract class EReferenceListPropertySectionBase<I extends EObject, R ext
*/
private R selectedElement;
/** {@link ListViewer} to show edited {@link EReference} list. */
private ListViewer elementListViewer;
/**
* {@link Composite} providing a {@link ListViewer} and an add and a remove {@link Button} to
* edit {@link EReference} list.
*/
public static class ElementListViewerComposite<I extends EObject, R extends EObject>
extends Composite {
/** {@link ListViewer} to show edited {@link EReference} list. */
private ListViewer listViewer;
/** {@link Button} to add an element to the {@link #listViewer}. */
private Button addButton;
/** {@link Button} to remove an element from the {@link #listViewer}. */
private Button removeButton;
/** Underlying {@link IListPropertySection}. */
private IListPropertySection<I, R> section;
/** Constructor. */
public ElementListViewerComposite(Composite parent, int style,
TabbedPropertySheetWidgetFactory wf, IListPropertySection<I, R> section) {
super(parent, style);
this.section = section;
GridLayout layout = new GridLayout(2, false);
layout.marginWidth = 0;
setLayout(layout);
listViewer = new ListViewer(this, SWT.BORDER | SWT.V_SCROLL);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.grabExcessHorizontalSpace = true;
gd.heightHint = 48;
listViewer.getList().setLayoutData(gd);
listViewer.setContentProvider(new ArrayContentProvider());
listViewer.setLabelProvider(new ModelElementLabelProvider());
listViewer.addSelectionChangedListener(new ISelectionChangedListener() {
/** {@inheritDoc} */
@Override
public void selectionChanged(SelectionChangedEvent event) {
// refresh() does not work here. It is based on isRemoveButtonEnabled(), that
// queries the selection of the 'listViewer' has not been updated yet. When this
// listener is triggered, only the 'event' already contains the new selection.
removeButton.setEnabled(getFirstSelectedElement(event.getSelection()) != null);
}
});
Composite buttonComposite = wf.createComposite(this, SWT.NONE);
buttonComposite.setLayout(new FillLayout(SWT.VERTICAL));
addButton = wf.createButton(buttonComposite, "Add", SWT.NONE);
addButton.addSelectionListener(new SelectionAdapter() {
/** {@inheritDoc} */
@Override
public void widgetSelected(SelectionEvent e) {
I input = section.getSectionInput();
runAsCommand(input,
() -> section.addModelListElement(input, section.getSelectedElement()));
section.refresh();
}
});
removeButton = wf.createButton(buttonComposite, "Remove", SWT.NONE);
removeButton.addSelectionListener(new SelectionAdapter() {
/** {@inheritDoc} */
@Override
public void widgetSelected(SelectionEvent e) {
R selectedElement = getFirstSelectedElement(listViewer.getSelection());
if(selectedElement != null) {
I input = section.getSectionInput();
runAsCommand(input,
() -> section.removeModelListElement(input, selectedElement));
section.refresh();
List<R> elements = section.getModelListElements(input);
if(!elements.isEmpty()) {
// Select first element (which has been checked to exist)
listViewer.setSelection(new StructuredSelection(elements.get(0)));
}
}
}
});
}
/** Provides the first selected element of the give {@link ISelection}. */
@SuppressWarnings("unchecked")
private R getFirstSelectedElement(ISelection selection) {
return (R)checkAndPickFirst(selection, EObject.class);
}
/**
* <p>
* Predicate if the {@link #addButton} is currently enabled.
* </p>
* <p>
* <b>NB: </b>Derived classes may override but must return the conjunction of their result
* and this implementation.
* </p>
*/
protected boolean isAddButtonEnabled() {
R selectedElement = section.getSelectedElement();
return selectedElement != null && !section
.getModelListElements(section.getSectionInput()).contains(selectedElement);
}
/**
* <p>
* Predicate if the {@link #removeButton} is currently enabled.
* </p>
* <p>
* <b>NB: </b>Derived classes may override but must return the conjunction of their result
* and this implementation.
* </p>
*/
protected boolean isRemoveButtonEnabled() {
return getFirstSelectedElement(listViewer.getSelection()) != null;
}
/** Refreshes the input and the enabled state of the controls. */
public void refresh() {
addButton.setEnabled(false);
removeButton.setEnabled(false);
I input = section.getSectionInput();
if(input == null) {
return;
}
List<R> elements = section.getModelListElements(input);
listViewer.setInput(elements);
addButton.setEnabled(isAddButtonEnabled());
removeButton.setEnabled(isRemoveButtonEnabled());
}
}
/** {@link Composite} providing a {@link ListViewer} and an add and remove Buttons. */
private ElementListViewerComposite<I, R> listViewerComposite;
/** The edited object (updated in {@link #setSectionInput(Object)}). */
private I input = null;
......@@ -67,60 +206,30 @@ public abstract class EReferenceListPropertySectionBase<I extends EObject, R ext
public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) {
super.createControls(parent, aTabbedPropertySheetPage);
TabbedPropertySheetWidgetFactory wf = getWidgetFactory();
Composite listComposite = wf.createComposite(composite, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.marginWidth = 0;
listComposite.setLayout(layout);
elementListViewer = new ListViewer(listComposite, SWT.BORDER | SWT.V_SCROLL);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.grabExcessHorizontalSpace = true;
gd.heightHint = 48;
elementListViewer.getList().setLayoutData(gd);
elementListViewer.setContentProvider(new ArrayContentProvider());
elementListViewer.setLabelProvider(new ModelElementLabelProvider());
Composite buttonComposite = wf.createComposite(listComposite, SWT.NONE);
buttonComposite.setLayout(new FillLayout(SWT.VERTICAL));
Button addButton = wf.createButton(buttonComposite, "Add", SWT.NONE);
addButton.addSelectionListener(new SelectionAdapter() {
/** {@inheritDoc} */
@Override
public void widgetSelected(SelectionEvent e) {
if(selectedElement != null &&
!getModelListElements(input).contains(selectedElement)) {
runAsCommand(input, () -> addModelListElement(input, selectedElement));
refresh();
}
}
});
Button removeButton = wf.createButton(buttonComposite, "Remove", SWT.NONE);
removeButton.addSelectionListener(new SelectionAdapter() {
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
public void widgetSelected(SelectionEvent e) {
runAsCommand(input, () -> removeModelListElement(input,
(R)checkAndPickFirst(elementListViewer.getSelection(), EObject.class)));
refresh();
}
});
listViewerComposite =
new ElementListViewerComposite<>(composite, SWT.NONE, getWidgetFactory(), this);
createFormEntry(listViewerComposite, "");
}
// Implementation of IListPropertySection
/** {@inheritDoc} */
@Override
public final R getSelectedElement() {
return selectedElement;
}
createFormEntry(listComposite, "");
/** {@inheritDoc} */
@Override
public final I getSectionInput() {
return input;
}
// Implementation of PropertySectionBase
/** {@inheritDoc} */
@Override
public void refresh() {
super.refresh();
if(input == null) {
return;
}
elementListViewer.setInput(getModelListElements(input));
listViewerComposite.refresh();
}
/** {@inheritDoc} */
......@@ -131,6 +240,7 @@ public abstract class EReferenceListPropertySectionBase<I extends EObject, R ext
this.input = (I)input;
}
// Implementation of EReferencePropertySectionBase
/** {@inheritDoc} */
@Override
protected final EObject getModelValue(I input) {
......@@ -149,13 +259,4 @@ public abstract class EReferenceListPropertySectionBase<I extends EObject, R ext
// for possible "add" operation.
selectedElement = newValue;
}
/** Returns the {@link List} of elements in the edited {@link EReference} list. */
protected abstract List<R> getModelListElements(I input);
/** Adds the given {@code element} to the edited {@link EReference} list. */
protected abstract void addModelListElement(I input, R element);
/** Removes the given {@code element} from the edited {@link EReference} list. */
protected abstract void removeModelListElement(I input, R element);
}
/*-------------------------------------------------------------------------+
| Copyright 2018 fortiss GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.ui.extension.base;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
/**
* Interface for property sections in which a list of elements can be edited.
*
* @author barner
*/
public interface IListPropertySection<I extends EObject, R extends EObject> {
/** Returns the {@link List} of elements in the edited {@link EReference} list. */
public List<R> getModelListElements(I input);
/** Adds the given {@code element} to the edited {@link EReference} list. */
public void addModelListElement(I input, R element);
/** Removes the given {@code element} from the edited {@link EReference} list. */
public void removeModelListElement(I input, R element);
/** Returns the currently selected element of the viewer used to edit the element list. */
public R getSelectedElement();
/** Returns the input model that contains the edited list. */
public I getSectionInput();
/** Updates the list viewer and the property section that embeds it. */
public void refresh();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment