From 2f882866dc620354c72f1ad9c3a1113bf293f637 Mon Sep 17 00:00:00 2001 From: Florian Hoelzl Date: Thu, 7 Nov 2019 13:45:55 +0100 Subject: [PATCH] Kernel: JavaFX editor. Added LayoutedModelElement base controllers. Issue-Ref: 3815 Issue-Url: https://af3-developer.fortiss.org/issues/3815 Signed-off-by: Florian Hoelzl --- .../META-INF/MANIFEST.MF | 1 + .../tooling/base/ui/editor/fx/.ratings | 4 + .../fx/EObjectBasedDiagramControllerBase.java | 111 +++++++++++++ ...angularResizableContentControllerBase.java | 142 ++++++++++++++++ ...lementBasedContentAnchorageController.java | 127 ++++++++++++++ ...lementBasedDiagramAnchorageController.java | 155 ++++++++++++++++++ 6 files changed, 540 insertions(+) create mode 100644 org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/.ratings create mode 100644 org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedDiagramControllerBase.java create mode 100644 org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedRectangularResizableContentControllerBase.java create mode 100644 org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedContentAnchorageController.java create mode 100644 org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedDiagramAnchorageController.java diff --git a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF index 041caa29..38af68c9 100644 --- a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF +++ b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF @@ -24,6 +24,7 @@ Export-Package: org.fortiss.tooling.base.ui, org.fortiss.tooling.base.ui.dnd.jface, org.fortiss.tooling.base.ui.editor, org.fortiss.tooling.base.ui.editor.annotations, + org.fortiss.tooling.base.ui.editor.fx, org.fortiss.tooling.base.ui.editpart, org.fortiss.tooling.base.ui.editpart.allocation, org.fortiss.tooling.base.ui.editpart.command, diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/.ratings b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/.ratings new file mode 100644 index 00000000..41409c8c --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/.ratings @@ -0,0 +1,4 @@ +EObjectBasedDiagramControllerBase.java 1d57b1b031d57ffb5123773c752e3415bacd8f7e RED +EObjectBasedRectangularResizableContentControllerBase.java 6cdf3d430353b79ec8c2ccf1bc20736db2ed102c RED +LayoutedModelElementBasedContentAnchorageController.java abbf310db98983a6e80c4cd339cb34a23c795101 RED +LayoutedModelElementBasedDiagramAnchorageController.java bb4a942f9cca35f032dfe3adee26443654315774 RED diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedDiagramControllerBase.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedDiagramControllerBase.java new file mode 100644 index 00000000..1d57b1b0 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedDiagramControllerBase.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) 2017, 2018 fortiss GmbH. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v2.0 which is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Florian Hoelzl (fortiss GmbH) - initial implementation + * + *******************************************************************************/ +package org.fortiss.tooling.base.ui.editor.fx; + +import static java.lang.Math.max; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramCoordinate; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerFeatures; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.base.ControllerBase; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeListener; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle; +import org.fortiss.tooling.kernel.service.IElementCompositorService; +import org.fortiss.tooling.kernel.ui.service.IContextMenuService; + +import javafx.scene.Node; +import javafx.scene.control.MenuItem; + +/** + * Diagram controller that uses the {@link IElementCompositorService} to create context menu + * entries for prototypes provided by the {@link IContextMenuService}. + */ +public abstract class EObjectBasedDiagramControllerBase extends ControllerBase + implements IModelChangeProvider { + /** Constructor. */ + public EObjectBasedDiagramControllerBase(IMVCBundle mvcb) { + super(mvcb); + if(!(getModel() instanceof EObject)) { + throw new IllegalArgumentException("Model element must be an instance of an EObject."); + } + } + + /** Returns the {@link EObject} model element. */ + protected EObject getEObject() { + // wild cast works: see constructor check with exception + return (EObject)getModel(); + } + + /** {@inheritDoc} */ + @Override + public List contextMenuContributions(Node node, DiagramCoordinate diagramLocation) { + // outer-most grid areas of the diagram are inaccessible + DiagramViewerFeatures features = getViewer().getFeatures(); + double x = max(features.getHorizontalSpacing(), diagramLocation.getX()); + double y = max(features.getVerticalSpacing(), diagramLocation.getY()); + + // wild cast works: see constructor exception + // EObject modelParent = (EObject)getModel(); + // IEclipseContext subContext = + // createSubContextWithCompositionLocation(context, modelParent, x, y); + // IContextMenuService icms = context.get(IContextMenuService.class); + // return icms.createDefaultContextMenu(subContext); + // TODO: + return Collections.emptyList(); + } + + /** The model change listener list. */ + private final List changeListeners = + new LinkedList(); + + /** {@inheritDoc} */ + @Override + public void addListener(IModelChangeListener l) { + if(changeListeners.isEmpty()) { + connectToModel(); + } + if(!changeListeners.contains(l)) { + changeListeners.add(l); + } + } + + /** Called when sub-class should register with the underlying {@link EObject}. */ + protected abstract void connectToModel(); + + /** {@inheritDoc} */ + @Override + public void removeListener(IModelChangeListener l) { + changeListeners.remove(l); + if(changeListeners.isEmpty()) { + disconnectFromModel(); + } + } + + /** Called when sub-class should unregister from the underlying {@link EObject}. */ + protected abstract void disconnectFromModel(); + + /** {@inheritDoc} */ + @Override + public void fireUpdateComplete() { + EObject eo = getEObject(); + for(IModelChangeListener mcl : changeListeners) { + mcl.changed(eo); + } + } +} diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedRectangularResizableContentControllerBase.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedRectangularResizableContentControllerBase.java new file mode 100644 index 00000000..6cdf3d43 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedRectangularResizableContentControllerBase.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (c) 2017, 2018 fortiss GmbH. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v2.0 which is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Florian Hoelzl (fortiss GmbH) - initial implementation + * + *******************************************************************************/ +package org.fortiss.tooling.base.ui.editor.fx; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramCoordinate; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.rectangular.RectangularResizableContentControllerBase; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeListener; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IContentMVCBundle; +import org.fortiss.tooling.base.model.layout.ILayoutedModelElement; +import org.fortiss.tooling.base.utils.LayoutModelElementAdapter; + +import javafx.scene.Node; +import javafx.scene.control.MenuItem; + +/** + * {@link RectangularResizableContentControllerBase} with a listener mechanism connected to + * {@link EObject#eAdapters()}. + */ +public abstract class EObjectBasedRectangularResizableContentControllerBase + extends RectangularResizableContentControllerBase implements IModelChangeProvider { + /** Layout model adapter used for listening to EMF model changes. */ + private final LayoutModelElementAdapter layoutAdapter; + + /** Constructor. */ + public EObjectBasedRectangularResizableContentControllerBase(IContentMVCBundle mvcb) { + super(mvcb); + if(!(mvcb.getModel() instanceof ILayoutedModelElement)) { + throw new IllegalArgumentException("Model element must be an instance of an EObject."); + } + ILayoutedModelElement lme = (ILayoutedModelElement)mvcb.getModel(); + layoutAdapter = new LayoutModelElementAdapter(lme) { + @Override + public void layoutChanged(Notification notification) { + fireUpdateComplete(); + } + }; + } + + /** Returns the {@link ILayoutedModelElement} model element. */ + protected ILayoutedModelElement getLayoutedME() { + // wild cast works: see constructor check with exception + return (ILayoutedModelElement)getModel(); + } + + // /** {@inheritDoc} */ + // @Override + // protected void link(IMVCBundle startBundle, DiagramCoordinate startLocation, + // IMVCBundle endBundle, DiagramCoordinate endLocation) { + // createLinkByCommand(startBundle, startLocation, endBundle, endLocation, + // (EObject)getViewer().getRootElement(), context); + // } + // + // /** {@inheritDoc} */ + // @Override + // public boolean isPossibleLinkTarget() { + // return true; + // } + + /** {@inheritDoc} */ + @Override + public List contextMenuContributions(Node node, DiagramCoordinate diagramLocation) { + // // outer-most grid areas of the diagram are inaccessible + // DiagramViewerFeatures features = getViewer().getFeatures(); + // double x = max(features.getHorizontalSpacing(), diagramLocation.getX()); + // double y = max(features.getVerticalSpacing(), diagramLocation.getY()); + // // wild cast works: see constructor exception + // EObject modelParent = (EObject)getModel(); + // IEclipseContext subContext = + // createSubContextWithCompositionBorderLocation(context, modelParent, x, y); + // + // IContextMenuService icms = context.get(IContextMenuService.class); + // return icms.createDefaultContextMenu(subContext); + return Collections.emptyList(); + } + + /** {@inheritDoc} */ + @Override + public void delete() { + // deleteByService(getEObject(), context); + } + + /** The model change listener list. */ + private final List changeListeners = + new LinkedList(); + + /** {@inheritDoc} */ + @Override + public void addListener(IModelChangeListener l) { + if(changeListeners.isEmpty()) { + connectToModel(); + } + if(!changeListeners.contains(l)) { + changeListeners.add(l); + } + } + + /** Called when sub-class should register with the underlying {@link EObject}. */ + protected void connectToModel() { + getLayoutedME().eAdapters().add(layoutAdapter); + } + + /** {@inheritDoc} */ + @Override + public void removeListener(IModelChangeListener l) { + changeListeners.remove(l); + if(changeListeners.isEmpty()) { + disconnectFromModel(); + } + } + + /** Called when sub-class should unregister from the underlying {@link EObject}. */ + protected void disconnectFromModel() { + getLayoutedME().eAdapters().remove(layoutAdapter); + } + + /** {@inheritDoc} */ + @Override + public void fireUpdateComplete() { + EObject eo = getLayoutedME(); + for(IModelChangeListener mcl : changeListeners) { + mcl.changed(eo); + } + } +} diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedContentAnchorageController.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedContentAnchorageController.java new file mode 100644 index 00000000..abbf310d --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedContentAnchorageController.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2017, 2018 fortiss GmbH. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v2.0 which is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Florian Hoelzl (fortiss GmbH) - initial implementation + * + *******************************************************************************/ +package org.fortiss.tooling.base.ui.editor.fx; + +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.base.DelegatingContentAnchorageController; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeListener; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IContentAnchorageMVCBundle; +import org.fortiss.tooling.base.model.layout.ILayoutedModelElement; +import org.fortiss.tooling.base.utils.LayoutModelElementAdapter; + +/** + * {@link DelegatingContentAnchorageController} for + * {@link org.fortiss.tooling.base.model.layout.ILayoutedModelElement}s. + */ +public class LayoutedModelElementBasedContentAnchorageController + extends DelegatingContentAnchorageController implements IModelChangeProvider { + /** Layout model adapter used for listening to EMF model changes. */ + private final LayoutModelElementAdapter layoutAdapter; + + /** Constructor. */ + public LayoutedModelElementBasedContentAnchorageController(IContentAnchorageMVCBundle mvcb) { + super(mvcb); + if(!(mvcb.getModel() instanceof ILayoutedModelElement)) { + throw new IllegalArgumentException( + "Model element must be an instance of an ILayoutedModelElement."); + } + ILayoutedModelElement lme = (ILayoutedModelElement)mvcb.getModel(); + layoutAdapter = new LayoutModelElementAdapter(lme) { + @Override + public void layoutChanged(Notification notification) { + fireUpdateComplete(); + } + }; + } + + /** Returns the model element. */ + public ILayoutedModelElement getLayoutedME() { + return (ILayoutedModelElement)getModel(); + } + + /** {@inheritDoc} */ + @Override + public void delete() { + // TODO + } + + // /** {@inheritDoc} */ + // @Override + // protected void link(IMVCBundle startBundle, DiagramCoordinate startLocation, + // IMVCBundle endBundle, DiagramCoordinate endLocation) { + // createLinkByCommand(startBundle, startLocation, endBundle, endLocation, + // (EObject)getViewer().getRootElement(), context); + // } + // + // /** {@inheritDoc} */ + // @Override + // public boolean isPossibleLinkTarget() { + // return true; + // } + // + // /** {@inheritDoc} */ + // @Override + // public MVCBundleTag getLinkTargetEffectForNewLinkFrom(IMVCBundle linkStartBundle) { + // return getLinkTargetEffect(linkStartBundle, getLayoutedME(), + // (EObject)getViewer().getRootElement(), context); + // } + + /** The model change listener list. */ + private final List changeListeners = + new LinkedList(); + + /** {@inheritDoc} */ + @Override + public void addListener(IModelChangeListener l) { + if(changeListeners.isEmpty()) { + connectToModel(); + } + if(!changeListeners.contains(l)) { + changeListeners.add(l); + } + } + + /** Called when sub-class should register with the underlying {@link EObject}. */ + protected void connectToModel() { + getLayoutedME().eAdapters().add(layoutAdapter); + } + + /** {@inheritDoc} */ + @Override + public void removeListener(IModelChangeListener l) { + changeListeners.remove(l); + if(changeListeners.isEmpty()) { + disconnectFromModel(); + } + } + + /** Called when sub-class should unregister from the underlying {@link EObject}. */ + protected void disconnectFromModel() { + getLayoutedME().eAdapters().remove(layoutAdapter); + } + + /** {@inheritDoc} */ + @Override + public void fireUpdateComplete() { + EObject eo = getLayoutedME(); + for(IModelChangeListener mcl : changeListeners) { + mcl.changed(eo); + } + } +} diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedDiagramAnchorageController.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedDiagramAnchorageController.java new file mode 100644 index 00000000..bb4a942f --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedDiagramAnchorageController.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2017, 2018 fortiss GmbH. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v2.0 which is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Florian Hoelzl (fortiss GmbH) - initial implementation + * + *******************************************************************************/ +package org.fortiss.tooling.base.ui.editor.fx; + +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.FeedbackChange; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.base.MoveControllerBase; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeListener; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle; +import org.fortiss.tooling.base.model.layout.ILayoutedModelElement; +import org.fortiss.tooling.base.utils.LayoutModelElementAdapter; + +/** {@link MoveControllerBase} for {@link ILayoutedModelElement}s. */ +public class LayoutedModelElementBasedDiagramAnchorageController extends MoveControllerBase + implements IModelChangeProvider { + /** Layout model adapter used for listening to EMF model changes. */ + private final LayoutModelElementAdapter layoutAdapter; + + /** Constructor. */ + public LayoutedModelElementBasedDiagramAnchorageController(IMVCBundle mvcb) { + super(mvcb); + if(!(mvcb.getModel() instanceof ILayoutedModelElement)) { + throw new IllegalArgumentException( + "Model element must be an instance of an ILayoutedModelElement."); + } + ILayoutedModelElement lme = (ILayoutedModelElement)mvcb.getModel(); + layoutAdapter = new LayoutModelElementAdapter(lme) { + @Override + public void layoutChanged(Notification notification) { + fireUpdateComplete(); + } + }; + } + + /** Returns the model element. */ + public ILayoutedModelElement getLayoutedME() { + return (ILayoutedModelElement)getModel(); + } + + /** {@inheritDoc} */ + @Override + public void move(FeedbackChange delta) { + // ILayoutedModelElement model = getLayoutedME(); + // Point pos = getPosition(model); + // int oldX = pos.getX(); + // int oldY = pos.getY(); + // DiagramViewerFeatures features = getViewer().getFeatures(); + // int newX = (int)max(oldX + delta.getDeltaX(), features.getHorizontalSpacing()); + // int newY = (int)max(oldY + delta.getDeltaY(), features.getVerticalSpacing()); + // context.get(IPersistencyService.class).runAsCommand(getModelRoot(model), + // new AbstractCommand() { + // @Override + // public boolean canExecute() { + // return true; + // } + // + // @Override + // public void redo() { + // execute(); + // } + // + // @Override + // public void execute() { + // setPosition(model, newX, newY); + // } + // }); + // setPosition(model, newX, newY); + } + + /** {@inheritDoc} */ + @Override + public void delete() { + // deleteByService(getLayoutedME(), context); + } + + // /** {@inheritDoc} */ + // @Override + // protected void link(IMVCBundle startBundle, DiagramCoordinate startLocation, + // IMVCBundle endBundle, DiagramCoordinate endLocation) { + // createLinkByCommand(startBundle, startLocation, endBundle, endLocation, + // (EObject)getViewer().getRootElement(), context); + // } + // + // /** {@inheritDoc} */ + // @Override + // public boolean isPossibleLinkTarget() { + // return true; + // } + // + // /** {@inheritDoc} */ + // @Override + // public MVCBundleTag getLinkTargetEffectForNewLinkFrom(IMVCBundle linkStartBundle) { + // return getLinkTargetEffect(linkStartBundle, getLayoutedME(), + // (EObject)getViewer().getRootElement(), context); + // } + + /** The model change listener list. */ + private final List changeListeners = + new LinkedList(); + + /** {@inheritDoc} */ + @Override + public void addListener(IModelChangeListener l) { + if(changeListeners.isEmpty()) { + connectToModel(); + } + if(!changeListeners.contains(l)) { + changeListeners.add(l); + } + } + + /** Called when sub-class should register with the underlying {@link EObject}. */ + protected void connectToModel() { + getLayoutedME().eAdapters().add(layoutAdapter); + } + + /** {@inheritDoc} */ + @Override + public void removeListener(IModelChangeListener l) { + changeListeners.remove(l); + if(changeListeners.isEmpty()) { + disconnectFromModel(); + } + } + + /** Called when sub-class should unregister from the underlying {@link EObject}. */ + protected void disconnectFromModel() { + getLayoutedME().eAdapters().remove(layoutAdapter); + } + + /** {@inheritDoc} */ + @Override + public void fireUpdateComplete() { + EObject eo = getLayoutedME(); + for(IModelChangeListener mcl : changeListeners) { + mcl.changed(eo); + } + } +} -- GitLab