Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » GEF » Realizing simple bendable connections
Realizing simple bendable connections [message #1794270] Tue, 28 August 2018 11:18 Go to next message
Robert Stelzmann is currently offline Robert StelzmannFriend
Messages: 3
Registered: July 2018
Junior Member
Hey guys,

I'm currently building a really simple diagram editor allowing the user to create nodes and connect them with edges. Now, I want to allow my users to create new bend points on edges and drag them around to enable them to do some simple kind of layouting. The resulting connection should be rendered as a list of straight lines connecting these bend points. Hence, nothing special so far. I investigated the logo example but the example is already quite complex and it's hard to extract the relevant code/configuration.

My connection visual derives from Connection and does nothing interesting. My connection part implements IBendableContentPart and thus get/setContentBendPoints. Furthermore, my doRefreshVisual implementation is straightforward:
    @Override
    protected void doRefreshVisual(final ConnectionVisual visual) {
        getVisual().setControlPoints(getContent().getWaypoints());
        super.doRefreshVisual(visual);
    }

    @Override
    public List<BendPoint> getContentBendPoints() {
        return getContent().getWaypoints().stream()
                .map(waypoint -> new BendPoint(waypoint))
                .collect(Collectors.toList());
    }

    @Override
    public void setContentBendPoints(final List<BendPoint> bendPoints) {
        getContent().setWaypoints(bendPoints.stream()
				.map(BendPoint::getPosition)
				.collect(Collectors.toList()));
    }


Finally, I tried to configure the Module likewise in the logo example. Here is the connection-related part:
    protected void bindConnectionPartAdapters(final MapBinder<AdapterKey<?>, Object> adapterMapBinder) {
        // geometry provider for selection feedback
        adapterMapBinder
                .addBinding(AdapterKey.role(DefaultSelectionFeedbackPartFactory.SELECTION_FEEDBACK_GEOMETRY_PROVIDER))
                .to(GeometricOutlineProvider.class);
        // geometry provider for selection handles
        adapterMapBinder
                .addBinding(AdapterKey.role(DefaultSelectionHandlePartFactory.SELECTION_HANDLES_GEOMETRY_PROVIDER))
                .to(GeometricOutlineProvider.class);
        adapterMapBinder
                .addBinding(
                        AdapterKey.role(DefaultSelectionFeedbackPartFactory.SELECTION_LINK_FEEDBACK_GEOMETRY_PROVIDER))
                .to(GeometricOutlineProvider.class);
        // geometry provider for hover feedback
        adapterMapBinder.addBinding(AdapterKey.role(DefaultHoverFeedbackPartFactory.HOVER_FEEDBACK_GEOMETRY_PROVIDER))
                .to(GeometricOutlineProvider.class);
        // geometry provider for focus feedback
        adapterMapBinder.addBinding(AdapterKey.role(DefaultFocusFeedbackPartFactory.FOCUS_FEEDBACK_GEOMETRY_PROVIDER))
                .to(GeometricOutlineProvider.class);

        // transaction policy for resize + transform
        adapterMapBinder.addBinding(AdapterKey.defaultRole()).to(ResizePolicy.class);

        adapterMapBinder.addBinding(AdapterKey.defaultRole()).to(BendConnectionPolicy.class);

        // interaction handler to relocate on drag
        adapterMapBinder.addBinding(AdapterKey.defaultRole()).to(TranslateSelectedOnDragHandler.class);

        // drag individual segments
        adapterMapBinder.addBinding(AdapterKey.defaultRole()).to(BendOnSegmentDragHandler.class);

        adapterMapBinder.addBinding(AdapterKey.defaultRole()).to(TransformPolicy.class);

        // clickable area resizing
        adapterMapBinder.addBinding(AdapterKey.defaultRole()).to(ConnectionClickableAreaBehavior.class);
    }


I'm absolutely not sure which Policies/Handlers/Behaviours I do need. By the way, some more documentation explaining their relations and interdependencies would be really helpful!

So, the whole stuff isn't working very well. At least, the edges get correctly displayed and hovered and I see a circle bend point in the middle. But the bend point is neither draggable nor is it possible to create new bend points. Can you guys give me a hint how to realize the described behaviour? Which Handlers/Policies/Behaviours do I need on the connection part? Do I have to configure the CircleSegmentHandlePart (like in the example)?
Re: Realizing simple bendable connections [message #1801048 is a reply to message #1794270] Fri, 11 January 2019 16:40 Go to previous message
Matthias Wienand is currently offline Matthias WienandFriend
Messages: 230
Registered: March 2015
Senior Member
Hi Robert,

unfortunately, the loose-coupling via the adapter mechanism requires some knowledge about the individual adapters (i.e. parts, policies, handlers, supports, behaviours, factories, etc.).

1) The doRefreshVisual() method should set the visual bend points as follows: setVisualBendPoints(getContentBendPoints())

This is the general pattern that should be applied in doRefreshVisual(), i.e. adjust the visualisation to match the contents. Also, the GEF defaults will work nicely with GEF Connection, so you spare custom code (although Connection has some performance issues in comparison to "low-level" JavaFX Line or similar when used extensively).

2) The BendOnSegmentDragHandler bound to your connection part is only applicable for IVisualPart<Connection> with an OrthogonalRouter being configured for the connection visual. This is not immediately obvious and should probably be enhanced in the documentation. You can see this in o.e.gef.mvc.fx.handlers.BendOnSegmentDragHandler:

https://github.com/eclipse/gef/blob/eb158dd82e9ccac54f943df7364f930d12544430/org.eclipse.gef.mvc.fx/src/org/eclipse/gef/mvc/fx/handlers/BendOnSegmentDragHandler.java#L149
	protected boolean isBend(MouseEvent event) {
		boolean isInvalid = false;
		if (!(getHost().getVisual().getRouter() instanceof OrthogonalRouter)) {
			// abort if non-orthogonal
			isInvalid = true;
		} else {
			IVisualPart<? extends Node> host = getHost();
			ObservableList<IContentPart<? extends Node>> selection = host
					.getRoot().getViewer().getAdapter(SelectionModel.class)
					.getSelectionUnmodifiable();
			if (selection.size() > 1 && selection.contains(host)) {
				// abort if part of multiple selection
				isInvalid = true;
			} else if (!getHost().getVisual().isStartConnected()
					&& !getHost().getVisual().isEndConnected()) {
				// abort if unconnected
				isInvalid = true;
			}
		}
		return !isInvalid;
	}


Hence, you either need to configure your connection visual to have an OrthogonalRouter, or you need to setup different handlers for the interaction.

The MVC Logo example does contain the necessary setup to enable manipulation of bend points, i.e. generation of circular segment handle parts when a connection is selected, and binding of BendOnSegmentHandleDragHandler for the corresponding handle parts.

So, yeah, you kind of figured this out: A handle part is needed for the default interactions w.r.t. connection bend points provided by GEF to be usable.

Best regards,
Matthias
Previous Topic:cannot load icons for Hi-DPI displays in GEF application
Next Topic:Update not drawn
Goto Forum:
  


Current Time: Tue Sep 27 16:42:21 GMT 2022

Powered by FUDForum. Page generated in 0.01844 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top