From 8ca82855778c664420cd7352f251d05de793899a Mon Sep 17 00:00:00 2001
From: Andreas Bayha <bayha@fortiss.org>
Date: Tue, 9 Jun 2020 18:04:48 +0200
Subject: [PATCH] Annotations: AnnotationFxView table

First Durchstich to display annotations according to the current
selection.

Issue-Ref: 4014
Issue-Url: https://af3-developer.fortiss.org/issues/4014
Signed-off-by: Andreas Bayha <bayha@fortiss.org>
---
 org.fortiss.tooling.base.ui/.classpath        |   3 +-
 .../META-INF/MANIFEST.MF                      |   3 +-
 org.fortiss.tooling.base.ui/plugin.xml        |   7 +
 .../annotation/view/fx/AnnotationViewFx.fxml  |  15 ++
 .../view/fx/AnnotationFxViewPart.java         |  49 ++++
 .../view/fx/AnnotationViewFXController.java   | 240 ++++++++++++++++++
 .../base/annotation/AnnotationEntry.java      |   2 +-
 7 files changed, 316 insertions(+), 3 deletions(-)
 create mode 100644 org.fortiss.tooling.base.ui/res/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFx.fxml
 create mode 100644 org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationFxViewPart.java
 create mode 100644 org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java

diff --git a/org.fortiss.tooling.base.ui/.classpath b/org.fortiss.tooling.base.ui/.classpath
index f3432614c..180930d41 100644
--- a/org.fortiss.tooling.base.ui/.classpath
+++ b/org.fortiss.tooling.base.ui/.classpath
@@ -7,7 +7,7 @@
 	</classpathentry>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="output" path="build"/>
+	<classpathentry kind="src" path="res"/>
 	<classpathentry kind="lib" path="lib/opal-1.0.4.jar" sourcepath="lib/opal-1.0.4-src.zip"/>
 	<classpathentry exported="true" kind="lib" path="lib/com.google.guava-15.0.0.v201403281430.jar" sourcepath="lib/klay-layouters-2016-02-src.zip"/>
 	<classpathentry exported="true" kind="lib" path="lib/de.cau.cs.kieler.core-0.15.0.201602160301.jar" sourcepath="lib/klay-layouters-2016-02-src.zip"/>
@@ -16,4 +16,5 @@
 	<classpathentry exported="true" kind="lib" path="lib/de.cau.cs.kieler.klay.force-0.4.0.201602160301.jar" sourcepath="lib/klay-layouters-2016-02-src.zip"/>
 	<classpathentry exported="true" kind="lib" path="lib/de.cau.cs.kieler.klay.layered-0.13.0.201602160301.jar" sourcepath="lib/klay-layouters-2016-02-src.zip"/>
 	<classpathentry exported="true" kind="lib" path="lib/de.cau.cs.kieler.klay.tree-0.4.0.201602160301.jar" sourcepath="lib/klay-layouters-2016-02-src.zip"/>
+	<classpathentry kind="output" path="build"/>
 </classpath>
diff --git a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF
index 171e250f8..5fe281bb2 100644
--- a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF
+++ b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF
@@ -6,7 +6,8 @@ Bundle-Version: 2.17.0.qualifier
 Bundle-Activator: org.fortiss.tooling.base.ui.ToolingBaseUIActivator
 Require-Bundle: org.fortiss.tooling.base;bundle-version="2.17.0";visibility:=reexport,
  org.fortiss.tooling.kernel.ui;bundle-version="2.17.0";visibility:=reexport,
- org.eclipse.swt
+ org.eclipse.swt,
+ org.fortiss.tooling.common.ui
 Bundle-ActivationPolicy: lazy
 Bundle-RequiredExecutionEnvironment: JavaSE-11
 Bundle-Vendor: fortiss GmbH
diff --git a/org.fortiss.tooling.base.ui/plugin.xml b/org.fortiss.tooling.base.ui/plugin.xml
index 6fd4666af..231f48481 100644
--- a/org.fortiss.tooling.base.ui/plugin.xml
+++ b/org.fortiss.tooling.base.ui/plugin.xml
@@ -20,6 +20,13 @@
             name="Annotations"
             restorable="true">
       </view>
+      <view
+            class="org.fortiss.tooling.base.ui.annotation.view.fx.AnnotationFxViewPart"
+            icon="icons/annotation.gif"
+            id="org.fortiss.tooling.base.ui.annotationFxView"
+            name="Annotations FX"
+            restorable="true">
+      </view>
    </extension>
    <extension point="org.fortiss.tooling.kernel.uiMessageHandler">
       <uiMessageHandler
diff --git a/org.fortiss.tooling.base.ui/res/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFx.fxml b/org.fortiss.tooling.base.ui/res/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFx.fxml
new file mode 100644
index 000000000..a37630e2e
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/res/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFx.fxml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.SplitPane?>
+<?import javafx.scene.control.TreeTableView?>
+<?import javafx.scene.layout.AnchorPane?>
+
+<SplitPane fx:id="annotationSplitPane" dividerPositions="0.6105527638190955" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" orientation="VERTICAL" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
+  <items>
+    <AnchorPane fx:id="annotationTablePane" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
+         <children>
+            <TreeTableView fx:id="annotationTreeTableView" layoutX="328.0" layoutY="20.0" prefHeight="239.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
+         </children></AnchorPane>
+    <AnchorPane fx:id="filterPane" minHeight="0.0" minWidth="0.0" prefHeight="219.0" prefWidth="598.0" />
+  </items>
+</SplitPane>
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationFxViewPart.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationFxViewPart.java
new file mode 100644
index 000000000..f7ea5e728
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationFxViewPart.java
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2020 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.base.ui.annotation.view.fx;
+
+import org.fortiss.tooling.common.ui.javafx.AF3FXViewPart;
+
+import javafx.scene.Scene;
+
+/**
+ * 
+ * @author bayha
+ */
+public class AnnotationFxViewPart extends AF3FXViewPart {
+
+	private static final AnnotationViewFXController VIEW_CONTROLLER =
+			new AnnotationViewFXController();
+
+	/**
+	 * @param controller
+	 * @param cssLocation
+	 * @throws Exception
+	 */
+	public AnnotationFxViewPart() throws Exception {
+		super(VIEW_CONTROLLER, null);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	protected Scene createFxScene() {
+		Scene scene = super.createFxScene();
+
+		getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(VIEW_CONTROLLER);
+
+		return scene;
+	}
+}
diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java
new file mode 100644
index 000000000..3165397eb
--- /dev/null
+++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/annotation/view/fx/AnnotationViewFXController.java
@@ -0,0 +1,240 @@
+/*-------------------------------------------------------------------------+
+| Copyright 2020 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.base.ui.annotation.view.fx;
+
+import static java.util.Collections.emptyList;
+import static org.fortiss.tooling.base.utils.AnnotationUtils.getAnnotationValueProvider;
+import static org.fortiss.tooling.kernel.ui.util.SelectionUtils.checkAndPickFirst;
+import static org.fortiss.tooling.kernel.utils.EcoreUtils.getChildrenWithType;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.fortiss.tooling.base.annotation.AnnotationEntry;
+import org.fortiss.tooling.base.annotation.AnnotationValueService;
+import org.fortiss.tooling.base.annotation.IAnnotationValueService;
+import org.fortiss.tooling.base.annotation.valueprovider.IAnnotationValueProvider;
+import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
+import org.fortiss.tooling.base.model.element.IModelElement;
+import org.fortiss.tooling.base.ui.annotation.view.generic.ColumnHandle;
+import org.fortiss.tooling.common.ui.javafx.control.treetableview.DynamicTreeContentProviderBase;
+import org.fortiss.tooling.common.ui.javafx.control.treetableview.DynamicTreeTableUIProviderBase;
+import org.fortiss.tooling.common.ui.javafx.control.treetableview.DynamicTreeTableViewer;
+import org.fortiss.tooling.common.ui.javafx.layout.CompositeFXControllerBase;
+import org.fortiss.tooling.kernel.model.INamedCommentedElement;
+
+import javafx.fxml.FXML;
+import javafx.scene.Node;
+import javafx.scene.control.SplitPane;
+import javafx.scene.control.TreeTableView;
+
+/**
+ * 
+ * @author bayha
+ */
+@SuppressWarnings("unchecked")
+public class AnnotationViewFXController extends CompositeFXControllerBase<SplitPane, Node>
+		implements ISelectionListener {
+
+	/**  */
+	@FXML
+	private SplitPane annotationSplitPane;
+
+	/**  */
+	@FXML
+	private TreeTableView<AnnotationEntry> annotationTreeTableView;
+
+	/**  */
+	private DynamicTreeTableViewer<AnnotationEntry> annotationTreeViewer;
+
+	/**  */
+	private IModelElement selectedElement;
+
+	/**  */
+	private DynamicTreeContentProviderBase<AnnotationEntry> contentProvider =
+			new AnnotationTableContentProvider();
+
+	/**  */
+	private DynamicTreeTableUIProviderBase<AnnotationEntry> uiProvider =
+			new AnnotationTreeTableUIProvider();
+
+	/**
+	 * Associates the handles of the annotations with their ordered column indexes. Used for the UI
+	 * providers of cell items.
+	 */
+	Map<Integer, ColumnHandle<IAnnotatedSpecification>> colIdxAnnotationMap = new HashMap<>();
+
+	/** {@inheritDoc} */
+	@Override
+	public String getFXMLLocation() {
+		return "AnnotationViewFx.fxml";
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void initialize() {
+		// EMPTY
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
+		selectedElement = checkAndPickFirst(selection, IModelElement.class);
+
+		updateAnnotationTree();
+	}
+
+	/**
+	 * 
+	 */
+	private void updateAnnotationTree() {
+		if(selectedElement == null) {
+			return;
+		}
+
+		EList<IModelElement> childElements =
+				getChildrenWithType(selectedElement, IModelElement.class);
+
+		ArtificialRoot root = new ArtificialRoot(selectedElement);
+
+		for(IModelElement elem : childElements) {
+			AnnotationEntry entry = IAnnotationValueService.getInstance().getAnnotationEntry(elem);
+
+			if(entry != null) {
+				root.elements.add(entry);
+			}
+		}
+
+		// Sorted set of {@link ColumnHandle} used to instantiate this {@link
+		// GenericAnnotationView}'s columns in the right order.
+		Set<ColumnHandle<IAnnotatedSpecification>> sortedColumnHandles = new TreeSet<>();
+		Set<AnnotationEntry> annotationEntries = new HashSet<>();
+		childElements.forEach(e -> annotationEntries
+				.add(AnnotationValueService.getInstance().getAnnotationEntry(e)));
+
+		// Aggregate required columns. Column order is defined by ColumnHandle.compareTo().
+		for(AnnotationEntry entry : annotationEntries) {
+			for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
+				ColumnHandle<IAnnotatedSpecification> columnHandle =
+						new ColumnHandle<IAnnotatedSpecification>(entry, spec);
+				sortedColumnHandles.add(columnHandle);
+			}
+		}
+
+		annotationTreeTableView.getColumns().clear();
+
+		boolean showRoot = false;
+		int revealLevel = 1;
+		annotationTreeViewer = new DynamicTreeTableViewer<AnnotationEntry>(annotationTreeTableView,
+				root, showRoot, revealLevel, contentProvider, uiProvider);
+
+		annotationTreeViewer.addColumn("Model Element", 200);
+		annotationTreeViewer.addColumn("Comment", 250);
+
+		int columnIdx = 2;
+		for(ColumnHandle<IAnnotatedSpecification> handle : sortedColumnHandles) {
+			annotationTreeViewer.addColumn(handle.getColumnName(), 150);
+			colIdxAnnotationMap.put(columnIdx++, handle);
+		}
+	}
+
+	/**
+	 * 
+	 * @author bayha
+	 */
+	protected class AnnotationTreeTableUIProvider
+			extends DynamicTreeTableUIProviderBase<AnnotationEntry> {
+
+		/** {@inheritDoc} */
+		@Override
+		public String getLabel(AnnotationEntry entry, int column) {
+			IModelElement element = entry.getModelElement();
+
+			switch(column) {
+				case 0:
+					if(element instanceof INamedCommentedElement) {
+						return ((INamedCommentedElement)element).getName();
+					}
+					return "";
+				case 1:
+					if(element instanceof INamedCommentedElement) {
+						return ((INamedCommentedElement)element).getComment();
+					}
+					return "";
+				default:
+					ColumnHandle<IAnnotatedSpecification> colHandle =
+							colIdxAnnotationMap.get(column);
+					IAnnotationValueProvider<IAnnotatedSpecification> valProvider =
+							getAnnotationValueProvider(element,
+									colHandle.getAnnotatedSpecificationType());
+					try {
+						return valProvider.getAnnotationValue(colHandle.getAnnotatedSpecification())
+								.toString();
+					} catch(Exception e) {
+						// For this demo class, it is expected that direct conversions to
+						// strings will fail for some annotations. Simple don't show anything in
+						// this case.
+						return "";
+					}
+			}
+		}
+	}
+
+	/**
+	 * 
+	 * @author bayha
+	 */
+	protected class AnnotationTableContentProvider
+			extends DynamicTreeContentProviderBase<AnnotationEntry> {
+
+		/** {@inheritDoc} */
+		@Override
+		protected Collection<? extends AnnotationEntry> getChildren(AnnotationEntry parent) {
+			if(parent instanceof ArtificialRoot) {
+				return ((ArtificialRoot)parent).elements;
+			}
+
+			return emptyList();
+		}
+	}
+
+	/**
+	 * 
+	 * @author bayha
+	 */
+	protected class ArtificialRoot extends AnnotationEntry {
+
+		/**
+		 * @param modelElement
+		 */
+		public ArtificialRoot(IModelElement modelElement) {
+			super(modelElement);
+		}
+
+		/**  */
+		List<AnnotationEntry> elements = new ArrayList<AnnotationEntry>();
+	}
+}
diff --git a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/annotation/AnnotationEntry.java b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/annotation/AnnotationEntry.java
index 928240a72..97a9d45cf 100644
--- a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/annotation/AnnotationEntry.java
+++ b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/annotation/AnnotationEntry.java
@@ -43,7 +43,7 @@ import org.fortiss.tooling.kernel.service.types.EMFTypeMap;
  * 
  * @author eder, barner
  */
-public final class AnnotationEntry {
+public class AnnotationEntry {
 
 	/**
 	 * Model element for which the set of relevant {@link IAnnotatedSpecification}s is managed by
-- 
GitLab