diff --git a/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF b/org.fortiss.tooling.base.ui/META-INF/MANIFEST.MF index 041caa29dacb8317ea1c625e61a3f2bd1e628da7..38af68c9e3784c683c32ff42abd70cc77ba447ad 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 0000000000000000000000000000000000000000..e653166242491b3ca417726ed14323d4c8283f2b --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/.ratings @@ -0,0 +1,9 @@ +ContextMenuUtil.java 3e04dbd52ee99a59735d39b4087c55b07fb91076 GREEN +EObjectBasedDiagramControllerBase.java b25bbbaa6eef3878b9aea73ca67d66de9beebb18 GREEN +EObjectBasedRectangularResizableContentControllerBase.java a263a6c123ee96015e0a5c37b6e3c13ebd0e8a75 GREEN +HierarchicModelElementModelChangeProvider.java 05217577a99d78038763bbcd841a032bb84f0553 GREEN +KernelServiceBasedModelChangeProviderBase.java 7c30347fb0c7cc4aacc79aeaf85167872afc1958 GREEN +LayoutModelElementModelChangeProvider.java 70c50b789c0088a7e5363bf662bc707a5b5ddf10 GREEN +LayoutedModelElementBasedContentAnchorageController.java c4dfb9dbcd16078c63321d5dec13a902e4088949 GREEN +LayoutedModelElementBasedDiagramAnchorageController.java 8e66f7d8207d2b6a03abaa151f94b51449ad66c7 GREEN +LayoutedModelElementBasedLinkBendPointController.java eb00b6119c02199b53b1a8e3cee2687f835b727c GREEN diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/ContextMenuUtil.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/ContextMenuUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..3e04dbd52ee99a59735d39b4087c55b07fb91076 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/ContextMenuUtil.java @@ -0,0 +1,111 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2019 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.editor.fx; + +import static org.fortiss.tooling.base.utils.LayoutModelElementFactory.createPoint; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewer; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerFeatures; +import org.fortiss.tooling.base.dnd.ElementDropContext; +import org.fortiss.tooling.base.model.layout.Point; +import org.fortiss.tooling.kernel.extension.data.IElementCompositionContext; +import org.fortiss.tooling.kernel.extension.data.Prototype; +import org.fortiss.tooling.kernel.service.ICommandStackService; +import org.fortiss.tooling.kernel.service.IElementCompositorService; +import org.fortiss.tooling.kernel.service.IPrototypeService; + +import javafx.scene.control.Menu; +import javafx.scene.control.MenuItem; + +/** + * Helper class for creating context menus. + * + * @author hoelzl + */ +final class ContextMenuUtil { + /** Creates the menu populated with composable prototypes. */ + public static List<MenuItem> createPrototypeMenu(EObject target, + IElementCompositionContext context) { + IPrototypeService pers = IPrototypeService.getInstance(); + IElementCompositorService ecs = IElementCompositorService.getInstance(); + ICommandStackService css = ICommandStackService.getInstance(); + List<MenuItem> result = new ArrayList<>(); + Menu newMenu = new Menu("New ..."); + List<Prototype> protos = pers.getComposablePrototypes(target.getClass()); + for(Prototype p : protos) { + EObject prototypeCopy = p.getPrototypeCopy(); + if(ecs.canCompose(target, prototypeCopy, context)) { + MenuItem mi = new MenuItem(p.getName()); + mi.setOnAction(evt -> { + css.runAsCommand(target, () -> { + ecs.compose(target, prototypeCopy, context); + }); + }); + newMenu.getItems().add(mi); + } + } + if(!newMenu.getItems().isEmpty()) { + result.add(newMenu); + } + return result; + } + + /** Creates the element composition context. */ + public static IElementCompositionContext createElementCompositionContext(EObject target, + double x, double y, boolean isRoot, double zoom) { + Point loc = createPoint((int)x, (int)y, "CompositionPoint"); + return new ElementDropContext(target, loc, isRoot, zoom); + } + + /** Returns the default display menu for interaction with diagram viewer features. */ + public static Menu createDisplayMenu(DiagramViewer viewer) { + Menu menu = new Menu("Display ..."); + DiagramViewerFeatures features = viewer.getFeatures(); + // link highlighting + if(features.isLinkHighlightingEnabled()) { + MenuItem disableLinkHighlighting = new MenuItem("Disable Link Highlighting"); + disableLinkHighlighting.setOnAction(evt -> { + features.setLinkHighlightingEnabled(false); + }); + menu.getItems().add(disableLinkHighlighting); + } else { + MenuItem enableLinkHighlighting = new MenuItem("Enable Link Highlighting"); + enableLinkHighlighting.setOnAction(evt -> { + features.setLinkHighlightingEnabled(true); + }); + menu.getItems().add(enableLinkHighlighting); + } + // interaction area shading + if(features.isInteractionAreaShadingEnabled()) { + MenuItem disableInteractionShading = new MenuItem("Disable Interactive Area Shading"); + disableInteractionShading.setOnAction(evt -> { + features.setInteractionAreaShadingEnabled(false); + }); + menu.getItems().add(disableInteractionShading); + } else { + MenuItem enableInteractionShading = new MenuItem("Enable Interactive Area Shading"); + enableInteractionShading.setOnAction(evt -> { + features.setInteractionAreaShadingEnabled(true); + }); + menu.getItems().add(enableInteractionShading); + } + return menu; + } +} 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 0000000000000000000000000000000000000000..b25bbbaa6eef3878b9aea73ca67d66de9beebb18 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedDiagramControllerBase.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * 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 static org.fortiss.tooling.base.ui.editor.fx.ContextMenuUtil.createDisplayMenu; +import static org.fortiss.tooling.base.ui.editor.fx.ContextMenuUtil.createElementCompositionContext; +import static org.fortiss.tooling.base.ui.editor.fx.ContextMenuUtil.createPrototypeMenu; + +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.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle; +import org.fortiss.tooling.base.model.element.IHierarchicElement; +import org.fortiss.tooling.kernel.extension.data.IElementCompositionContext; +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}. + * + * @author hoelzl + */ +public abstract class EObjectBasedDiagramControllerBase extends ControllerBase { + /** The model change provider. */ + private final HierarchicModelElementModelChangeProvider modelChangeProvider; + + /** Constructor. */ + public EObjectBasedDiagramControllerBase(IMVCBundle mvcb) { + super(mvcb); + if(!(getModel() instanceof IHierarchicElement)) { + throw new IllegalArgumentException( + "Model element must be an instance of an IHierarchicElement."); + } + this.modelChangeProvider = + new HierarchicModelElementModelChangeProvider(getHierarchicElement()); + } + + /** {@inheritDoc} */ + @Override + public IModelChangeProvider getModelChangeProvider() { + return modelChangeProvider; + } + + /** Returns the {@link IHierarchicElement} model element. */ + protected IHierarchicElement getHierarchicElement() { + // wild cast works: see constructor check with exception + return (IHierarchicElement)getModel(); + } + + /** {@inheritDoc} */ + @Override + public List<MenuItem> 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 = getHierarchicElement(); + IElementCompositionContext edc = createElementCompositionContext(modelParent, x, y, true, + getViewer().getFeatures().getCurrentZoomFactor()); + List<MenuItem> result = createPrototypeMenu(modelParent, edc); + result.add(createDisplayMenu(getViewer())); + return result; + } +} 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 0000000000000000000000000000000000000000..a263a6c123ee96015e0a5c37b6e3c13ebd0e8a75 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/EObjectBasedRectangularResizableContentControllerBase.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * 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 static org.fortiss.tooling.base.ui.editor.fx.ContextMenuUtil.createElementCompositionContext; +import static org.fortiss.tooling.base.ui.editor.fx.ContextMenuUtil.createPrototypeMenu; + +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.DiagramViewerFeatures; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.change.Change; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.IClickController; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.base.ClickControllerBase; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.rectangular.RectangularResizableContentControllerBase; +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.element.ElementPackage; +import org.fortiss.tooling.base.model.layout.ILayoutedModelElement; +import org.fortiss.tooling.kernel.extension.data.IElementCompositionContext; +import org.fortiss.tooling.kernel.service.IElementCompositorService; +import org.fortiss.tooling.kernel.ui.extension.IModelElementHandler; +import org.fortiss.tooling.kernel.ui.service.IModelEditorBindingService; +import org.fortiss.tooling.kernel.ui.service.IModelElementHandlerService; + +import javafx.scene.Node; +import javafx.scene.control.MenuItem; +import javafx.scene.input.MouseEvent; + +/** + * {@link RectangularResizableContentControllerBase} with a listener mechanism for the layout of the + * connected {@link EObject model element}. + * + * @author hoelzl + */ +public abstract class EObjectBasedRectangularResizableContentControllerBase + extends RectangularResizableContentControllerBase { + /** {@link IModelChangeProvider} for this controller */ + private final LayoutModelElementModelChangeProvider layoutModelChangeProvider; + /** The click controller handling double-click to open editor. */ + private final IClickController openEditorDoubleClickController = new ClickControllerBase() { + @Override + public Change singleClick(MouseEvent event, Node node, DiagramCoordinate diagramLocation) { + return EObjectBasedRectangularResizableContentControllerBase.super.getClickController( + node, diagramLocation).singleClick(event, node, diagramLocation); + } + + @Override + public Change secondaryClick(MouseEvent event, Node node, + DiagramCoordinate diagramLocation) { + return EObjectBasedRectangularResizableContentControllerBase.super.getClickController( + node, diagramLocation).secondaryClick(event, node, diagramLocation); + } + + @Override + public Change doubleClick(MouseEvent event, Node node, DiagramCoordinate diagramLocation) { + EObject eo = getLayoutedME(); + IModelElementHandler<EObject> handler = + IModelElementHandlerService.getInstance().getModelElementHandler(eo); + if(handler != null) { + eo = handler.handleOpenModelElementRequest(eo); + } + IModelEditorBindingService.getInstance().openInEditor(eo); + return null; // no changes to model + } + }; + + /** Constructor. */ + public EObjectBasedRectangularResizableContentControllerBase(IContentMVCBundle 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(); + this.layoutModelChangeProvider = new LayoutModelElementModelChangeProvider(lme) { + /** {@inheritDoc} */ + @Override + protected boolean acceptNotification(Notification notification) { + if(notification.getNotifier() != getLayoutedME()) { + return false; + } + return isAnchorageFeature(notification.getFeature()); + } + }; + } + + /** Returns the {@link ILayoutedModelElement} model element. */ + protected ILayoutedModelElement getLayoutedME() { + // wild cast works: see constructor check with exception + return (ILayoutedModelElement)getModel(); + } + + /** {@inheritDoc} */ + @Override + public IModelChangeProvider getModelChangeProvider() { + return layoutModelChangeProvider; + } + + /** {@inheritDoc} */ + @Override + public List<MenuItem> 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(); + IElementCompositionContext edc = createElementCompositionContext(modelParent, x, y, false, + getViewer().getFeatures().getCurrentZoomFactor()); + return createPrototypeMenu(modelParent, edc); + } + + /** {@inheritDoc} */ + @Override + public void delete() { + IElementCompositorService.getInstance().decompose(getLayoutedME()); + } + + /** Checks whether the given feature corresponds to an anchorage model element. */ + protected boolean isAnchorageFeature(Object feature) { + return feature == ElementPackage.Literals.IHIERARCHIC_ELEMENT__CONNECTORS; + } + + /** {@inheritDoc} */ + @Override + public IClickController getClickController(Node node, DiagramCoordinate diagramLocation) { + return openEditorDoubleClickController; + } +} diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/HierarchicModelElementModelChangeProvider.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/HierarchicModelElementModelChangeProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..05217577a99d78038763bbcd841a032bb84f0553 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/HierarchicModelElementModelChangeProvider.java @@ -0,0 +1,61 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2019 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.editor.fx; + +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.notify.impl.AdapterImpl; +import org.fortiss.tooling.base.model.element.IHierarchicElement; + +/** + * An {@link KernelServiceBasedModelChangeProviderBase} for {@link IHierarchicElement}s. + * + * @author hoelzl + */ +final class HierarchicModelElementModelChangeProvider + extends KernelServiceBasedModelChangeProviderBase<IHierarchicElement> { + /** The model element. */ + private final IHierarchicElement modelElement; + /** The EMF notification listener. */ + private final HierarchicElementAdapter notificationListener; + + /** Constructor. */ + public HierarchicModelElementModelChangeProvider(IHierarchicElement modelElement) { + this.modelElement = modelElement; + this.notificationListener = new HierarchicElementAdapter(); + } + + /** {@inheritDoc} */ + @Override + protected IHierarchicElement getModelElement() { + return modelElement; + } + + /** {@inheritDoc} */ + @Override + protected Adapter getNotificationListener() { + return notificationListener; + } + + /** Specialized adapter listening to model changes of {@link IHierarchicElement}. */ + private class HierarchicElementAdapter extends AdapterImpl { + /** {@inheritDoc} */ + @Override + public void notifyChanged(Notification event) { + addNotification(event); + } + } +} diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/KernelServiceBasedModelChangeProviderBase.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/KernelServiceBasedModelChangeProviderBase.java new file mode 100644 index 0000000000000000000000000000000000000000..7c30347fb0c7cc4aacc79aeaf85167872afc1958 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/KernelServiceBasedModelChangeProviderBase.java @@ -0,0 +1,89 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2019 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.editor.fx; + +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; + +import org.eclipse.emf.common.command.CommandStackListener; +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.ModelChangeProviderBase; +import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; +import org.fortiss.tooling.kernel.service.ICommandStackService; +import org.fortiss.tooling.kernel.service.IPersistencyService; + +/** + * Base class for {@link IModelChangeProvider}s using kernel services. + * + * @author hoelzl + */ +abstract class KernelServiceBasedModelChangeProviderBase<T extends EObject> + extends ModelChangeProviderBase implements CommandStackListener { + /** The persistency service reference. */ + private static final IPersistencyService persistencyService = IPersistencyService.getInstance(); + /** The command stack service. */ + private static final ICommandStackService commandStackService = + ICommandStackService.getInstance(); + /** List of relevant {@link Notification}s recorded during a change transaction. */ + private final List<Notification> notifications = new ArrayList<>(); + + /** Returns the model element. */ + protected abstract T getModelElement(); + + /** Returns the EMF notification listener. */ + protected abstract Adapter getNotificationListener(); + + /** Adds the given {@link Notification} to list of notifications. */ + protected final void addNotification(Notification event) { + notifications.add(event); + } + + /** {@inheritDoc} */ + @Override + protected final void connectToModel() { + notifications.clear(); + T modelElement = getModelElement(); + Adapter notificationListener = getNotificationListener(); + ITopLevelElement root = persistencyService.getTopLevelElementFor(modelElement); + commandStackService.addCommandStackListener(root, this); + modelElement.eAdapters().add(notificationListener); + } + + /** {@inheritDoc} */ + @Override + protected final void disconnectFromModel() { + T modelElement = getModelElement(); + Adapter notificationListener = getNotificationListener(); + modelElement.eAdapters().remove(notificationListener); + ITopLevelElement root = persistencyService.getTopLevelElementFor(modelElement); + commandStackService.removeCommandStackListener(root, this); + notifications.clear(); + } + + /** {@inheritDoc} */ + @Override + public void commandStackChanged(EventObject event) { + if(notifications.isEmpty()) { + return; + } + fireUpdateComplete(); + notifications.clear(); + } +} diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutModelElementModelChangeProvider.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutModelElementModelChangeProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..70c50b789c0088a7e5363bf662bc707a5b5ddf10 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutModelElementModelChangeProvider.java @@ -0,0 +1,127 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2019 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.editor.fx; + +import static org.fortiss.tooling.base.model.layout.LayoutPackage.ILAYOUTED_MODEL_ELEMENT__LAYOUT_DATA; + +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EContentAdapter; +import org.fortiss.tooling.base.model.layout.ILayoutData; +import org.fortiss.tooling.base.model.layout.ILayoutedModelElement; +import org.fortiss.tooling.base.model.layout.LayoutPackage; + +/** + * An {@link KernelServiceBasedModelChangeProviderBase} for {@link ILayoutedModelElement}s. + * + * @author hoelzl + */ +class LayoutModelElementModelChangeProvider + extends KernelServiceBasedModelChangeProviderBase<ILayoutedModelElement> { + /** The layouted model element. */ + private final ILayoutedModelElement modelElement; + /** The layout EMF notification listener. */ + private final LayoutModelElementAdapter notificationListener; + + /** Constructor. */ + public LayoutModelElementModelChangeProvider(ILayoutedModelElement modelElement) { + this.modelElement = modelElement; + this.notificationListener = new LayoutModelElementAdapter(); + } + + /** {@inheritDoc} */ + @Override + protected ILayoutedModelElement getModelElement() { + return modelElement; + } + + /** {@inheritDoc} */ + @Override + protected Adapter getNotificationListener() { + return notificationListener; + } + + /** + * Checks whether the given notification should be accepted. + * + * @param notification + * the notification + * @return whether the notification should be accepted + */ + protected boolean acceptNotification(Notification notification) { + return false; + } + + /** Specific {@link EContentAdapter} listening to layout data changes. */ + public class LayoutModelElementAdapter extends EContentAdapter { + /** {@inheritDoc} */ + @Override + public void notifyChanged(Notification notification) { + if(acceptNotification(notification)) { + addNotification(notification); + return; + } + Object notifier = notification.getNotifier(); + if(notifier == modelElement) { + Object feature = notification.getFeature(); + if(feature == LayoutPackage.Literals.ILAYOUTED_MODEL_ELEMENT__LAYOUT_DATA) { + // self adapt to layout data + super.notifyChanged(notification); + addNotification(notification); + return; + } + } else if(notifier instanceof ILayoutData) { + // self adapt to layout data + super.notifyChanged(notification); + addNotification(notification); + return; + } + // prevent self-adapt for all other cases + } + + /** Called when layout data of the underlying model element changed. */ + protected void layoutChanged() { + // default does nothing + } + + /** {@inheritDoc} */ + @Override + protected void selfAdapt(Notification notification) { + // ignore resources and resource sets + if(notification.getNotifier() instanceof EObject) { + super.selfAdapt(notification); + } + } + + /** {@inheritDoc} */ + @Override + protected void handleContainment(Notification notification) { + // only adapt to layout data + if(notification.getNotifier() instanceof ILayoutData) { + super.handleContainment(notification); + return; + } + + Class<?> instanceClass = + LayoutPackage.Literals.ILAYOUTED_MODEL_ELEMENT.getInstanceClass(); + // only adapt to layout data + if(notification.getFeatureID(instanceClass) == ILAYOUTED_MODEL_ELEMENT__LAYOUT_DATA) { + super.handleContainment(notification); + } + } + } +} 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 0000000000000000000000000000000000000000..c4dfb9dbcd16078c63321d5dec13a902e4088949 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedContentAnchorageController.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * 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 org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags.LINK_TARGET_ALLOWED_TAG; +import static org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags.LINK_TARGET_DENIED_TAG; + +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.base.DelegatingContentAnchorageController; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IContentAnchorageMVCBundle; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.MVCBundleTag; +import org.fortiss.tooling.base.model.element.IConnector; +import org.fortiss.tooling.base.model.layout.ILayoutedModelElement; +import org.fortiss.tooling.kernel.service.IConnectionCompositorService; +import org.fortiss.tooling.kernel.service.IElementCompositorService; + +/** + * {@link DelegatingContentAnchorageController} for + * {@link org.fortiss.tooling.base.model.layout.ILayoutedModelElement}s. + * + * @author hoelzl + */ +public class LayoutedModelElementBasedContentAnchorageController + extends DelegatingContentAnchorageController { + /** {@link IModelChangeProvider} for this controller */ + private final LayoutModelElementModelChangeProvider layoutModelChangeProvider; + + /** 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(); + this.layoutModelChangeProvider = new LayoutModelElementModelChangeProvider(lme); + } + + /** Returns the model element. */ + public ILayoutedModelElement getLayoutedME() { + return (ILayoutedModelElement)getModel(); + } + + /** {@inheritDoc} */ + @Override + public IModelChangeProvider getModelChangeProvider() { + return layoutModelChangeProvider; + } + + /** {@inheritDoc} */ + @Override + public void delete() { + IElementCompositorService.getInstance().decompose(getLayoutedME()); + } + + /** {@inheritDoc} */ + @Override + protected boolean canLink(IMVCBundle startBundle, DiagramCoordinate startLocation, + IMVCBundle endBundle, DiagramCoordinate endLocation) { + IConnectionCompositorService ccs = IConnectionCompositorService.getInstance(); + EObject start = (EObject)startBundle.getModel(); + EObject end = (EObject)endBundle.getModel(); + EObject root = (EObject)getViewer().getRootElement(); + return ccs.canConnect(start, end, root, null); + } + + /** {@inheritDoc} */ + @Override + protected void link(IMVCBundle startBundle, DiagramCoordinate startLocation, + IMVCBundle endBundle, DiagramCoordinate endLocation) { + EObject start = (EObject)startBundle.getModel(); + EObject end = (EObject)endBundle.getModel(); + EObject root = (EObject)getViewer().getRootElement(); + IConnectionCompositorService.getInstance().connect(start, end, root, null); + } + + /** {@inheritDoc} */ + @Override + public boolean isPossibleLinkTarget() { + return true; + } + + /** {@inheritDoc} */ + @Override + public MVCBundleTag getLinkTargetEffectForNewLinkFrom(IMVCBundle linkSourceBundle) { + Object srcModel = linkSourceBundle.getModel(); + if(srcModel instanceof ILayoutedModelElement && srcModel instanceof IConnector) { + EObject startModel = (EObject)srcModel; + ILayoutedModelElement endModel = getLayoutedME(); + EObject root = (EObject)getViewer().getRootElement(); + IConnectionCompositorService srv = IConnectionCompositorService.getInstance(); + if(srv.canConnect(startModel, endModel, root, null)) { + return LINK_TARGET_ALLOWED_TAG; + } + } + return LINK_TARGET_DENIED_TAG; + } +} 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 0000000000000000000000000000000000000000..8e66f7d8207d2b6a03abaa151f94b51449ad66c7 --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedDiagramAnchorageController.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * 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 org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags.LINK_TARGET_ALLOWED_TAG; +import static org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags.LINK_TARGET_DENIED_TAG; +import static org.fortiss.tooling.base.utils.LayoutDataUtils.moveNode; + +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.FeedbackChange; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.base.MoveControllerBase; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.MVCBundleTag; +import org.fortiss.tooling.base.model.element.IConnector; +import org.fortiss.tooling.base.model.layout.ILayoutedModelElement; +import org.fortiss.tooling.kernel.service.IConnectionCompositorService; +import org.fortiss.tooling.kernel.service.IElementCompositorService; + +/** + * {@link MoveControllerBase} for {@link ILayoutedModelElement}s. + * + * @author hoelzl + */ +public class LayoutedModelElementBasedDiagramAnchorageController extends MoveControllerBase { + /** {@link IModelChangeProvider} for this controller */ + private final LayoutModelElementModelChangeProvider layoutModelChangeProvider; + + /** 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(); + this.layoutModelChangeProvider = new LayoutModelElementModelChangeProvider(lme); + } + + /** Returns the model element. */ + public ILayoutedModelElement getLayoutedME() { + return (ILayoutedModelElement)getModel(); + } + + /** {@inheritDoc} */ + @Override + public IModelChangeProvider getModelChangeProvider() { + return layoutModelChangeProvider; + } + + /** {@inheritDoc} */ + @Override + public void move(FeedbackChange delta) { + ILayoutedModelElement model = getLayoutedME(); + int dx = (int)delta.getDeltaX(); + int dy = (int)delta.getDeltaY(); + moveNode(model, dx, dy); + } + + /** {@inheritDoc} */ + @Override + public void delete() { + IElementCompositorService.getInstance().decompose(getLayoutedME()); + } + + /** {@inheritDoc} */ + @Override + protected boolean canLink(IMVCBundle startBundle, DiagramCoordinate startLocation, + IMVCBundle endBundle, DiagramCoordinate endLocation) { + IConnectionCompositorService ccs = IConnectionCompositorService.getInstance(); + EObject start = (EObject)startBundle.getModel(); + EObject end = (EObject)endBundle.getModel(); + EObject root = (EObject)getViewer().getRootElement(); + return ccs.canConnect(start, end, root, null); + } + + /** {@inheritDoc} */ + @Override + protected void link(IMVCBundle startBundle, DiagramCoordinate startLocation, + IMVCBundle endBundle, DiagramCoordinate endLocation) { + EObject start = (EObject)startBundle.getModel(); + EObject end = (EObject)endBundle.getModel(); + EObject root = (EObject)getViewer().getRootElement(); + IConnectionCompositorService.getInstance().connect(start, end, root, null); + } + + /** {@inheritDoc} */ + @Override + public boolean isPossibleLinkTarget() { + return true; + } + + /** {@inheritDoc} */ + @Override + public MVCBundleTag getLinkTargetEffectForNewLinkFrom(IMVCBundle linkSourceBundle) { + Object srcModel = linkSourceBundle.getModel(); + if(srcModel instanceof ILayoutedModelElement && srcModel instanceof IConnector) { + EObject startModel = (EObject)srcModel; + ILayoutedModelElement endModel = getLayoutedME(); + EObject root = (EObject)getViewer().getRootElement(); + IConnectionCompositorService srv = IConnectionCompositorService.getInstance(); + if(srv.canConnect(startModel, endModel, root, null)) { + return LINK_TARGET_ALLOWED_TAG; + } + } + return LINK_TARGET_DENIED_TAG; + } +} diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedLinkBendPointController.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedLinkBendPointController.java new file mode 100644 index 0000000000000000000000000000000000000000..eb00b6119c02199b53b1a8e3cee2687f835b727c --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/editor/fx/LayoutedModelElementBasedLinkBendPointController.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * 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 org.fortiss.tooling.base.ui.utils.LayoutDataUIUtils.addConnectionPoint; +import static org.fortiss.tooling.base.ui.utils.LayoutDataUIUtils.getConnectionPoints; +import static org.fortiss.tooling.base.ui.utils.LayoutDataUIUtils.removeConnectionPoint; + +import java.util.List; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramCoordinate; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewer; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.IController; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.base.LinkControllerBase; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelChangeProvider; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.ILinkMVCBundle; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle; +import org.fortiss.tooling.base.model.layout.ILayoutedModelElement; +import org.fortiss.tooling.base.model.layout.Point; +import org.fortiss.tooling.kernel.service.IConnectionCompositorService; + +/** + * {@link IController} for {@link ILayoutedModelElement}s representing links and connections in a + * {@link DiagramViewer}. + * + * @author hoelzl + */ +public class LayoutedModelElementBasedLinkBendPointController extends LinkControllerBase { + /** {@link IModelChangeProvider} for this controller */ + private final LayoutModelElementModelChangeProvider layoutModelChangeProvider; + + /** Constructor. */ + public LayoutedModelElementBasedLinkBendPointController(ILinkMVCBundle 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(); + this.layoutModelChangeProvider = new LayoutModelElementModelChangeProvider(lme); + } + + /** Returns the model element. */ + public ILayoutedModelElement getLayoutedME() { + return (ILayoutedModelElement)getModel(); + } + + /** {@inheritDoc} */ + @Override + public IModelChangeProvider getModelChangeProvider() { + return layoutModelChangeProvider; + } + + /** {@inheritDoc} */ + @Override + protected int getNumerOfBendPoints() { + return getBendPointList(getLayoutedME()).size(); + } + + /** Returns the list of bend-points. */ + private EList<Point> getBendPointList(ILayoutedModelElement modelElement) { + return getConnectionPoints(modelElement).getPoints(); + } + + /** {@inheritDoc} */ + @Override + protected void createBendPointAt(int bpIndex, DiagramCoordinate location) { + int x = (int)location.getX(); + int y = (int)location.getY(); + addConnectionPoint(getLayoutedME(), bpIndex, x, y); + } + + /** {@inheritDoc} */ + @Override + protected void updateModelAfterBendPointMove(int bpIndex, double dx, double dy) { + List<Point> oldPoints = getBendPointList(getLayoutedME()); + Point point = oldPoints.get(bpIndex); + int oldX = point.getX(); + int oldY = point.getY(); + int newX = oldX + (int)dx; + int newY = oldY + (int)dy; + point.setX(newX); + point.setY(newY); + } + + /** {@inheritDoc} */ + @Override + protected void deleteBendPoint(int bpIndex) { + removeConnectionPoint(getLayoutedME(), bpIndex); + } + + /** {@inheritDoc} */ + @Override + protected void updateModelAfterLinkMove(ILinkMVCBundle linkBundle, IMVCBundle startBundle, + IMVCBundle endBundle) { + // ignored + } + + /** {@inheritDoc} */ + @Override + protected void deleteLink() { + IConnectionCompositorService.getInstance().disconnect(getLayoutedME()); + } + + /** {@inheritDoc} */ + @Override + public void delete() { + deleteLink(); + } +} diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/.ratings b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/.ratings index ab3f586d361cb743224e07bc27672ca45bdef584..27fbc6fb9f974296b2e91d4738b5ba7289852c08 100644 --- a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/.ratings +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/.ratings @@ -5,6 +5,7 @@ DragAndDropBaseUtils.java d375377f9124f6113b2a295e6b0e09ac8966e564 GREEN EllipseLayoutUIUtils.java 4dd9dbd96a45e8c455c019caa19e4a50f18336af GREEN FontUtils.java a167a05bdaa8da9853705cc5134f30f6d81bc9f2 GREEN GCStateManager.java 983973a92376b5c757c1253b32e33d0666ccdf7b GREEN +LWFXEditorUtils.java c628e79fa43c1be8a7b87ee90db6e7264904eafc GREEN LayoutDataUIUtils.java c85886ac313a6efb122532218eb134047ffd6631 GREEN PropertiesViewUtils.java d345b4501c4092228edf1c98e0189317d53aaf22 GREEN RectangleLayoutUIUtils.java ef4b872bb5b4a51174e9a29d9ef05e7cb3bff3a1 GREEN diff --git a/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/LWFXEditorUtils.java b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/LWFXEditorUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..c628e79fa43c1be8a7b87ee90db6e7264904eafc --- /dev/null +++ b/org.fortiss.tooling.base.ui/src/org/fortiss/tooling/base/ui/utils/LWFXEditorUtils.java @@ -0,0 +1,106 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2019 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.utils; + +import static java.lang.Math.atan2; +import static java.lang.Math.cos; +import static java.lang.Math.sin; + +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramCoordinate; +import org.fortiss.tooling.base.model.layout.EOrientation; + +import javafx.geometry.Point2D; +import javafx.geometry.Rectangle2D; +import javafx.geometry.Side; + +/** + * Utility methods for the JavaFX-based graphical LWFXEF editors. + * + * @author hoelzl + */ +public final class LWFXEditorUtils { + /** Computes the location of the link w.r.t. the given anchor bounds and target position. */ + public static DiagramCoordinate computeLinkToAnchorLocation(Rectangle2D anchorBounds, + DiagramCoordinate target) { + double x = 0; + if(target.getX() < anchorBounds.getMinX()) { + x = -1.0; + } else if(target.getX() > anchorBounds.getMaxX()) { + x = 1.0; + } + double y = 0; + if(target.getY() < anchorBounds.getMinY()) { + y = -1.0; + } else if(target.getY() > anchorBounds.getMaxY()) { + y = 1.0; + } + double w2 = anchorBounds.getWidth() / 2; + double h2 = anchorBounds.getHeight() / 2; + x = anchorBounds.getMinX() + w2 + x * w2; + y = anchorBounds.getMinY() + h2 + y * h2; + return new DiagramCoordinate(x, y); + } + + /** Returns the {@link EOrientation} for the given {@link Side}. */ + public static EOrientation convertSideToEOrientation(Side s) { + switch(s) { + case TOP: + return EOrientation.NORTH; + case BOTTOM: + return EOrientation.SOUTH; + case LEFT: + return EOrientation.WEST; + case RIGHT: + return EOrientation.EAST; + } + return null; + } + + /** Returns the {@link Side} for the given {@link EOrientation}. */ + public static Side convertEOrientationToSide(EOrientation eo) { + switch(eo) { + case NORTH: + return Side.TOP; + case SOUTH: + return Side.BOTTOM; + case WEST: + return Side.LEFT; + case EAST: + return Side.RIGHT; + } + return null; + } + + /** + * Returns the point on a circle centered in the current bounds intersecting with a line between + * the center point and the given point. + */ + public static DiagramCoordinate computeLinkToCircleLocation(Rectangle2D bounds, + Point2D target) { + double sx = bounds.getMinX() + bounds.getWidth() / 2; + double sy = bounds.getMinY() + bounds.getHeight() / 2; + + double a = atan2(target.getY() - sy, target.getX() - sx); + double nx = sx + cos(a) * (bounds.getWidth() / 2 - 1); + double ny = sy + sin(a) * (bounds.getHeight() / 2 - 1); + return new DiagramCoordinate(nx, ny); + } + + /** Constructor. */ + private LWFXEditorUtils() { + // prevent instantiation + } +} diff --git a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/utils/.ratings b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/utils/.ratings index b628d001a439891e6b134468fc023f1bda0d0f2a..cb56cc2420509be5d99ef48a902127aa8fbb84b5 100644 --- a/org.fortiss.tooling.base/src/org/fortiss/tooling/base/utils/.ratings +++ b/org.fortiss.tooling.base/src/org/fortiss/tooling/base/utils/.ratings @@ -6,6 +6,7 @@ ConstraintsBaseUtils.java bba938b43756ce6f35c338f6cef21c3ab5d49a9d GREEN DimensionUtils.java 0dc67f9de11a84e6e4c6e1eb627817dee91ff30a GREEN EllipseLayoutUtils.java 5c3a0126fdca5d5b4fb441694747e1cb0f49cd9f GREEN LayoutDataUtils.java 5739dd16f0212e8f94927c0a0f51503390f2be69 GREEN +LayoutModelElementAdapter.java d81dfc551baa832f2761b4804760dcd8f57b7c5b YELLOW LayoutModelElementFactory.java c49fca2de5a8cb7502fb28cc2b7e64a272df11b0 GREEN MigrationUtils.java ab9d8682233313c21c6a52b8b03e1c796aacd29c GREEN OffsetOrientationUtils.java 913cebbac2a5628bdd08b4df669b9412d6e07d94 GREEN diff --git a/org.fortiss.tooling.common.ui/.classpath b/org.fortiss.tooling.common.ui/.classpath index 0920a6fed0bb5a3313c4f46b95ea1fcb99101429..bcb5e0f03a41ae289fd0381df83ec7357ced92d2 100644 --- a/org.fortiss.tooling.common.ui/.classpath +++ b/org.fortiss.tooling.common.ui/.classpath @@ -3,6 +3,8 @@ <classpathentry kind="src" path="src"/> <classpathentry kind="src" path="external-src"/> <classpathentry kind="src" path="res"/> + <classpathentry exported="true" kind="lib" path="lib/org.eclipse.systemfocus.kernel.common_0.0.4.20191111.jar"/> + <classpathentry exported="true" kind="lib" path="lib/org.eclipse.systemfocus.kernel.common.ui_0.0.4.20191111.jar"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"> <attributes> <attribute name="module" value="true"/> diff --git a/org.fortiss.tooling.common.ui/META-INF/MANIFEST.MF b/org.fortiss.tooling.common.ui/META-INF/MANIFEST.MF index dcf60fe7c7d2231ee36c7eb97df43e40ad59e350..9de211b109b7cb768aa4006cfe89bb2944315aa8 100644 --- a/org.fortiss.tooling.common.ui/META-INF/MANIFEST.MF +++ b/org.fortiss.tooling.common.ui/META-INF/MANIFEST.MF @@ -24,8 +24,13 @@ Require-Bundle: org.fortiss.tooling.common;visibility:=reexport, Bundle-ClassPath: ., lib/org.conqat.ide.commons.gef.jar, lib/org.conqat.ide.commons.ui.jar, - lib/swt-grouplayout.jar -Export-Package: org.conqat.ide.commons.gef, + lib/swt-grouplayout.jar, + lib/org.eclipse.systemfocus.kernel.common_0.0.4.20191111.jar, + lib/org.eclipse.systemfocus.kernel.common.ui_0.0.4.20191111.jar +Export-Package: aerofx, + aquafx, + jfxtras, + org.conqat.ide.commons.gef, org.conqat.ide.commons.gef.directediting, org.conqat.ide.commons.gef.draw2d, org.conqat.ide.commons.gef.editor, @@ -69,6 +74,25 @@ Export-Package: org.conqat.ide.commons.gef, org.eclipse.gmf.runtime.draw2d.ui.figures, org.eclipse.gmf.runtime.draw2d.ui.geometry, org.eclipse.jface.viewers, + org.eclipse.systemfocus.kernel.common.ui.javafx.control.treetableview, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.change, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.base, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.elliptic, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.rectangular, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.layout, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.impl, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.base, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.elliptic, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.rectangular, + org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.widgets, + org.eclipse.systemfocus.kernel.common.ui.javafx.mesh, + org.eclipse.systemfocus.kernel.common.ui.javafx.style, + org.eclipse.systemfocus.kernel.common.ui.javafx.util, org.eclipse.ui.actions, org.eclipse.wb.swt, org.eclipse.wb.swt.layout.grouplayout, diff --git a/org.fortiss.tooling.common.ui/build.properties b/org.fortiss.tooling.common.ui/build.properties index ab1e37fb1bbf7fdb879ccf70079b428aacb1e8ff..809b922c3605b1753b73f7f3906f7a9bd53d1aa2 100644 --- a/org.fortiss.tooling.common.ui/build.properties +++ b/org.fortiss.tooling.common.ui/build.properties @@ -5,7 +5,9 @@ bin.includes = .,\ lib/org.conqat.ide.commons.gef.jar,\ lib/org.conqat.ide.commons.ui.jar,\ lib/swt-grouplayout.jar,\ - res/ + res/,\ + lib/org.eclipse.systemfocus.kernel.common_0.0.4.20191111.jar,\ + lib/org.eclipse.systemfocus.kernel.common.ui_0.0.4.20191111.jar jars.compile.order = . source.. = src/,\ res/,\ diff --git a/org.fortiss.tooling.common.ui/lib/org.eclipse.systemfocus.kernel.common.ui_0.0.4.20191111.jar b/org.fortiss.tooling.common.ui/lib/org.eclipse.systemfocus.kernel.common.ui_0.0.4.20191111.jar new file mode 100644 index 0000000000000000000000000000000000000000..f3931238bae4d485625ffda3a204fef1d1b64ece Binary files /dev/null and b/org.fortiss.tooling.common.ui/lib/org.eclipse.systemfocus.kernel.common.ui_0.0.4.20191111.jar differ diff --git a/org.fortiss.tooling.common.ui/lib/org.eclipse.systemfocus.kernel.common_0.0.4.20191111.jar b/org.fortiss.tooling.common.ui/lib/org.eclipse.systemfocus.kernel.common_0.0.4.20191111.jar new file mode 100644 index 0000000000000000000000000000000000000000..2d172810cb6ebac59ebfaef25c3283e6729cc099 Binary files /dev/null and b/org.fortiss.tooling.common.ui/lib/org.eclipse.systemfocus.kernel.common_0.0.4.20191111.jar differ diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/.ratings b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/.ratings index 0dc4ea3d0c7cc3b78179d5bf38f965a7c79702a3..976ba3f728d9b735717c8a0d137b2c2c1da9e672 100644 --- a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/.ratings +++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/.ratings @@ -5,7 +5,9 @@ EObjectActionBase.java 4ef9f8be59e64d4838acc9e268d418ba5d94fa1a GREEN EReferenceListPropertySectionBase.java 7390dd7bfdc979e8ff0c5c30c67ab7b6c9d70c92 GREEN EReferencePropertySectionBase.java 0548da6778516003257f59d0b4c2b60d458be3b6 GREEN EditorBase.java 9c09fff92945256bb8680992ae7bb2c78f47b150 GREEN +FXEditorBase.java 2e520be0bbae7d0aebdff70218a124dbe0896ce2 GREEN IListPropertySection.java 8bb00fe7959583e794ff9437b7a77404c9a9e70f GREEN +LWFXEFEditorBase.java 0b8e6af85d83d0542dcd908974e52c618bc22a08 GREEN ModelEditorBindingBase.java 4c5ac569c0b6e7678fc8191096b26dfd09fdcb98 GREEN ModelElementHandlerBase.java 384727748f125c9d43f19d9c0eba4ba1be5a7a26 GREEN MultiEObjectActionBase.java 9e237d8ea640c4194e4877af4a9cfce88698e543 GREEN diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/FXEditorBase.java b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/FXEditorBase.java new file mode 100644 index 0000000000000000000000000000000000000000..2e520be0bbae7d0aebdff70218a124dbe0896ce2 --- /dev/null +++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/FXEditorBase.java @@ -0,0 +1,42 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2011 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 org.eclipse.emf.ecore.EObject; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; + +import javafx.embed.swt.FXCanvas; +import javafx.scene.Parent; +import javafx.scene.Scene; + +/** + * Base implementation of model element editors which are using JavaFX. + * + * @author hoelzlf + */ +public abstract class FXEditorBase<T extends EObject> extends EditorBase<T> { + /** {@inheritDoc} */ + @Override + public final void createPartControl(Composite parent) { + FXCanvas canvas = new FXCanvas(parent, SWT.NONE); + Scene scene = new Scene(createSceneRoot()); + canvas.setScene(scene); + } + + /** Creates the root node of the scene. */ + protected abstract Parent createSceneRoot(); +} diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/LWFXEFEditorBase.java b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/LWFXEFEditorBase.java new file mode 100644 index 0000000000000000000000000000000000000000..0b8e6af85d83d0542dcd908974e52c618bc22a08 --- /dev/null +++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/extension/base/LWFXEFEditorBase.java @@ -0,0 +1,127 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2019 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.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewer; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerSelection; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.change.Change; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.IControllerFactory; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.model.IModelFactory; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle; +import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.IVisualFactory; +import org.fortiss.tooling.kernel.service.ICommandStackService; + +import javafx.scene.Parent; + +/** + * Base implementation of model element editors which are using LWFXEF DiaViewer. + * + * @author hoelzlf + */ +public abstract class LWFXEFEditorBase<T extends EObject> extends FXEditorBase<T> + implements ISelectionProvider { + /** The diagram viewer. */ + protected DiagramViewer viewer; + /** The list of {@link ISelectionChangedListener}s. */ + private final List<ISelectionChangedListener> selectionListeners = new ArrayList<>(); + + /** {@inheritDoc} */ + @Override + protected final Parent createSceneRoot() { + viewer = new DiagramViewer(createModelFactory(), createVisualFactory(), + createControllerFactory(), cb -> modelSelected(), chg -> applyModelChange(chg)); + customizeViewer(); + getSite().setSelectionProvider(this); + return viewer.getVisualNode(); + } + + /** Customize the viewer after it is created. The default implementation changes nothing. */ + protected void customizeViewer() { + // the default does nothing + } + + /** Create the {@link IModelFactory}. */ + protected abstract IModelFactory createModelFactory(); + + /** Create the {@link IVisualFactory}. */ + protected abstract IVisualFactory createVisualFactory(); + + /** Create the {@link IControllerFactory}. */ + protected abstract IControllerFactory createControllerFactory(); + + /** Called when a model element is selected in the diagram viewer. */ + protected void modelSelected() { + getSite().getSelectionProvider().setSelection(createSelection()); + } + + /** Called when some change to the model happens. */ + protected void applyModelChange(Change chg) { + ICommandStackService.getInstance().runAsCommand(editedObject, () -> chg.applyChange()); + } + + /** {@inheritDoc} */ + @Override + public void addSelectionChangedListener(ISelectionChangedListener listener) { + if(!selectionListeners.contains(listener)) { + selectionListeners.add(listener); + } + } + + /** {@inheritDoc} */ + @Override + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + selectionListeners.remove(listener); + } + + /** {@inheritDoc} */ + @Override + public void setSelection(ISelection selection) { + SelectionChangedEvent evt = new SelectionChangedEvent(this, selection); + for(ISelectionChangedListener scl : selectionListeners) { + scl.selectionChanged(evt); + } + } + + /** {@inheritDoc} */ + @Override + public ISelection getSelection() { + return createSelection(); + } + + /** Creates an {@link IStructuredSelection} from {@link DiagramViewerSelection}. */ + private IStructuredSelection createSelection() { + DiagramViewerSelection vsel = viewer.getSelection(); + if(vsel.isEmpty()) { + return StructuredSelection.EMPTY; + } + List<Object> selList = new ArrayList<>(vsel.getSecondarySelections().size() + 1); + selList.add(vsel.getPrimarySelection().getModel()); + for(IMVCBundle sec : vsel.getSecondarySelections()) { + selList.add(sec.getModel()); + } + return new StructuredSelection(selList); + } +}