Skip to content
Snippets Groups Projects
Commit d5ef2178 authored by Simon Barner's avatar Simon Barner
Browse files

- Sort columns alphabetically using a TreeSet of the newly introduced ColumnHandles.

- Ensure that "Create" columns for dynamic multi-instance annotations are right to the corresponding instances.
- Simplify column handling. Merge updateSingleInstanceAnnotationColumns() / updateMultiInstanceAnnotationColumns() into update()
refs 1841
parent 793757ed
No related branches found
No related tags found
No related merge requests found
......@@ -19,9 +19,9 @@ package org.fortiss.tooling.base.ui.annotation.view;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.EditingSupport;
......@@ -55,10 +55,6 @@ import org.fortiss.tooling.base.ui.annotation.valueprovider.IAnnotationValueProv
*/
public class GenericAnnotationView extends AnnotationViewPartBase {
/** mapping of {@link IAnnotatedSpecification} -> TableViewerColumn */
protected HashMap<Class<? extends IAnnotatedSpecification>, TableViewerColumn> annotationSpecColumns =
new HashMap<Class<? extends IAnnotatedSpecification>, TableViewerColumn>();
/**
* List containing the columns that are responsible for creating new keys. Required for
* disposing when updating the view.
......@@ -66,104 +62,185 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
private List<CreateAnnotationInstanceColumn> createColumns =
new ArrayList<CreateAnnotationInstanceColumn>();
/** The table viewer */
protected TableViewer tableViewer;
/**
* Map for associating those specifications that allow multiple values with their according
* AnnotationEntries.
* Character used to separte the annotation name from the instance name for multi-instance
* annotations.
*/
private Map<IAnnotatedSpecification, AnnotationEntry> specsAllowingMultipleValues =
new HashMap<IAnnotatedSpecification, AnnotationEntry>();
private final static String MULTIINSTANCE_NAME_SEPARATOR = ":";
/** The table viewer */
protected TableViewer tableViewer;
/**
* Data required to identify a column displaying a particular {@link IAnnotatedSpecification} in
* a column of the {@link GenericAnnotationView}. Used to sort columns (see
* {@link #compareTo(ColumnHandle)}).
*/
private class ColumnHandle implements Comparable<ColumnHandle> {
/**
* {@link AnnotationEntry} from which a particular {@link IAnnotatedSpecification} is to be
* displayed in the column represented by this {@link ColumnHandle}.
*/
private AnnotationEntry entry;
/**
* {@link IAnnotatedSpecification} from {@code entry} to be displayed in the column
* represented by this {@link ColumnHandle}.
*/
private IAnnotatedSpecification annotatedSpecification;
/**
* Instance key identifying the particular instance of an {@link IAnnotatedSpecification}
* from {@code entry} to be displayed in the column represented by this {@link ColumnHandle}
* .
*/
private String instanceKey;
/** Flag if this {@link ColumnHandle} represents a {@link CreateAnnotationInstanceColumn}. */
private boolean isCreateColumn;
/** Constructs a new {@link ColumnHandle}. */
public ColumnHandle(AnnotationEntry entry, IAnnotatedSpecification annotatedSpecification,
String instanceKey, boolean isCreateColumn) {
this.entry = entry;
this.annotatedSpecification = annotatedSpecification;
this.instanceKey = instanceKey;
this.isCreateColumn = isCreateColumn;
}
/**
* Returns the {@link AnnotationEntry} from which a particular
* {@link IAnnotatedSpecification} is to be
* displayed in the column represented by this {@link ColumnHandle}.
*/
public AnnotationEntry getEntry() {
return entry;
}
/**
* Returns the {@link IAnnotatedSpecification} from {@code entry} to be displayed in the
* column represented by this {@link ColumnHandle}.
*/
public IAnnotatedSpecification getAnnotatedSpecification() {
return annotatedSpecification;
}
/**
* Returns the instance key identifying the particular instance of an
* {@link IAnnotatedSpecification} from {@code entry} to be displayed in the column
* represented by this {@link ColumnHandle} .
*/
public String getInstanceKey() {
return instanceKey;
}
/**
* Returns a flag if this {@link ColumnHandle} represents a
* {@link CreateAnnotationInstanceColumn}.
*/
public boolean isCreateColumn() {
return isCreateColumn;
}
/** {@inheritDoc} */
@Override
public int compareTo(ColumnHandle other) {
String columnName = getColumnName(this);
String annotationName;
int columnNameSeparatorIndex = columnName.indexOf(MULTIINSTANCE_NAME_SEPARATOR);
if(columnNameSeparatorIndex != -1) {
annotationName = columnName.substring(0, columnNameSeparatorIndex);
} else {
annotationName = columnName;
}
String otherColumnName = getColumnName(other);
String otherAnnotationName;
int otherColumnNameSeparatorIndex =
otherColumnName.indexOf(MULTIINSTANCE_NAME_SEPARATOR);
if(otherColumnNameSeparatorIndex != -1) {
otherAnnotationName = otherColumnName.substring(0, otherColumnNameSeparatorIndex);
} else {
otherAnnotationName = otherColumnName;
}
// Place "create" columns (label: "<specification name>") after their instances
// (which are labeled "<specification name>: <instance name>").
if(annotationName.equals(otherAnnotationName)) {
// Ensure uniqueness of "create" columns"
if(isCreateColumn && other.isCreateColumn) {
return 0;
}
if(isCreateColumn) {
return 1;
}
if(other.isCreateColumn) {
return -1;
}
}
// Sort alphabetically by specification column label
return columnName.compareTo(otherColumnName);
}
}
/** {@inheritDoc} */
@Override
protected void update(Collection<AnnotationEntry> annotationEntries) {
updateSingleInstanceAnnotationColumns(annotationEntries);
updateMultiInstanceAnnotationColumns(annotationEntries);
}
/*
* Sorted set of {@link ColumnHandle} used to instantiate this {@link
* GenericAnnotationView}'s columns in the right order.
*/
Set<ColumnHandle> sortedColumnHandles = new TreeSet<ColumnHandle>();
/** Create columns for ordinary (single instance) {@link IAnnotatedSpecification}s */
private void
updateSingleInstanceAnnotationColumns(Collection<AnnotationEntry> annotationEntries) {
/*
* disposes all columns of the table viewer, except the first column, which holds the names
* Dispose all columns of the table viewer, except the first column, which holds the names
* of the model elements
*/
while(tableViewer.getTable().getColumnCount() > 1) {
tableViewer.getTable().getColumn(1).dispose();
}
annotationSpecColumns.clear();
/*
* Create a column for each annotation specification provided by any AnnotationEntry. There
* is no additional columns created for those specification which already have an associated
* column or provide complex values.
*/
for(AnnotationEntry entry : annotationEntries) {
for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
if(!isExistingColumn(spec) &&
!entry.allowsDynamicAnnotationInstances(spec.getClass()) &&
entry.getInstanceKeys(spec.getClass()).isEmpty()) {
createAnnotationColumn(entry, spec, null);
}
}
}
if(!tableViewer.getTable().isDisposed())
tableViewer.setInput(annotationEntries);
}
/** Create columns for multi-instance {@link IAnnotatedSpecification}s */
private void
updateMultiInstanceAnnotationColumns(Collection<AnnotationEntry> annotationEntries) {
for(CreateAnnotationInstanceColumn col : createColumns) {
col.dispose();
}
specsAllowingMultipleValues.clear();
/*
* Iterate over all available specifications in the model. Columns for specifications
* with simple values have already been created by the superclass 'GenericAnnotationView',
* others are stored in the map 'specsAllowingMultipleValues'.
* Each annotation specification type may exist only once in the table view or the map
* 'code specsAllowingMultipleValues'.
*/
List<String> specClassNamesMult = new ArrayList<String>();
// Aggregate required columns. Column order is defined by ColumnHandle.compareTo().
for(AnnotationEntry entry : annotationEntries) {
for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
if((!entry.getInstanceKeys(spec.getClass()).isEmpty() || entry
.allowsDynamicAnnotationInstances(spec.getClass())) &&
!specClassNamesMult.contains(spec.getClass().getSimpleName())) {
specsAllowingMultipleValues.put(spec, entry);
specClassNamesMult.add(spec.getClass().getSimpleName());
}
}
}
// Create new column for each instance of the current multi-instance annotation
if((entry.allowsDynamicAnnotationInstances(spec.getClass())) ||
!entry.getInstanceKeys(spec.getClass()).isEmpty()) {
// Iterate over all specification supporting multiple values.
for(IAnnotatedSpecification spec : specsAllowingMultipleValues.keySet().toArray(
new IAnnotatedSpecification[specsAllowingMultipleValues.keySet().size()])) {
AnnotationEntry entry = specsAllowingMultipleValues.get(spec);
for(String instanceKey : entry.getInstanceKeys(spec.getClass())) {
sortedColumnHandles.add(new ColumnHandle(entry, spec, instanceKey, false));
}
}
// Create new column for each instance of the current multi-instance annotation
for(String key : entry.getInstanceKeys(spec.getClass())) {
createAnnotationColumn(entry, spec, key);
}
// Create a new column for
// - ordinary (single-instance) annotations
// - "create" column for multi-instance annotations for which instances can be
// created dynamically
if(entry.getInstanceKeys(spec.getClass()).isEmpty() ||
entry.allowsDynamicAnnotationInstances(spec.getClass())) {
sortedColumnHandles.add(new ColumnHandle(entry, spec, null, entry
.allowsDynamicAnnotationInstances(spec.getClass())));
if(entry.allowsDynamicAnnotationInstances(spec.getClass())) {
// Create column that contains a button for adding new instances of the
// current annotation type.
createColumns.add(new CreateAnnotationInstanceColumn(tableViewer, SWT.NONE, spec,
entry));
(createColumns.get(createColumns.size() - 1)).getColumn().setWidth(125);
}
}
}
// Instantiate columns
for(ColumnHandle columnHandle : sortedColumnHandles) {
createAnnotationColumn(columnHandle);
}
// Refresh table to trigger the update method of the create columns in order to actually
// instantiate the "Create" buttons
// Register content provider
if(!tableViewer.getTable().isDisposed()) {
tableViewer.setInput(annotationEntries);
}
tableViewer.refresh();
}
......@@ -195,42 +272,58 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
}
/** Creates a column in tableViewer that displays the annotation given in spec */
protected void createAnnotationColumn(AnnotationEntry entry, IAnnotatedSpecification spec,
String instanceKey) {
// Determine column name
String specName = entry.getSpecificationAnnotationName(spec.getClass());
if(specName == null || specName.isEmpty()) {
specName = "<Unnamed Annotation>";
protected void createAnnotationColumn(ColumnHandle columnHandle) {
if(columnHandle.isCreateColumn()) {
// Create column that contains a button for adding new instances of the
// current annotation type.
createColumns.add(new CreateAnnotationInstanceColumn(tableViewer, SWT.NONE,
columnHandle.getAnnotatedSpecification(), columnHandle.getEntry()));
(createColumns.get(createColumns.size() - 1)).getColumn().setWidth(125);
return;
}
if(instanceKey != null) {
specName += ": " + instanceKey;
}
String specName = getColumnName(columnHandle);
// Add new new column
TableViewerColumn column = new TableViewerColumn(tableViewer, SWT.NONE);
column.getColumn().setText(specName);
Class<? extends IAnnotatedSpecification> annotationClass =
columnHandle.getAnnotatedSpecification().getClass();
column.getColumn().setWidth(125);
annotationSpecColumns.put(spec.getClass(), column);
// Have the matching EditingSupport created for the current annotated specification
// (work is delegated to respective IAnnotationValueProvider implementation)
EditingSupport editingSupport =
entry.createSpecificationEditElement(tableViewer, spec.getClass(), instanceKey);
columnHandle.getEntry().createSpecificationEditElement(tableViewer,
annotationClass, columnHandle.getInstanceKey());
// Add column label provider, and set EditingSupport
column.setLabelProvider(new AnnotationLabelProvider(spec.getClass(), this, instanceKey));
column.setLabelProvider(new AnnotationLabelProvider(annotationClass, this, columnHandle
.getInstanceKey()));
column.setEditingSupport(editingSupport);
}
/** Checks if column for given specification already exists */
protected boolean isExistingColumn(IAnnotatedSpecification specification) {
if(annotationSpecColumns.containsKey(specification.getClass()))
return true;
return false;
/**
* Returns the name of a column for a given {@link IAnnotatedSpecification} represented by the
* given {@link ColumnHandle}.
*/
protected String getColumnName(ColumnHandle columnHandle) {
// Determine column name
String specName =
columnHandle.getEntry().getSpecificationAnnotationName(
columnHandle.getAnnotatedSpecification().getClass());
if(specName == null || specName.isEmpty()) {
specName = "<Unnamed Annotation>";
}
if(columnHandle.getInstanceKey() != null) {
specName += MULTIINSTANCE_NAME_SEPARATOR + " " + columnHandle.getInstanceKey();
}
return specName;
}
/** {@inheritDoc} */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment