All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modeler.anchors.CustomRectangularAnchor Maven / Gradle / Ivy

Go to download

Jeddict is an open source Jakarta EE application development platform that accelerates developers productivity and simplifies development tasks of creating complex entity relationship models.

There is a newer version: 6.5.0
Show newest version
/**
 * Copyright 2013-2022 Gaurav Gupta
 *
 * 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.netbeans.modeler.anchors;

import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import org.netbeans.api.visual.anchor.Anchor;
import org.netbeans.api.visual.widget.Widget;
import org.netbeans.modeler.specification.model.document.IModelerScene;
import org.netbeans.modeler.specification.model.document.widget.IFlowEdgeWidget;
import org.netbeans.modeler.widget.node.INodeWidget;
import org.netbeans.modeler.widget.node.NodeWidget;
import org.netbeans.modeler.svg.SvgNodeWidget;
import org.netbeans.modeler.svg.ResizeType;
import test.ClosestSegment;
import test.GeometryClosestPointManager;

public class CustomRectangularAnchor extends Anchor {

    private final boolean includeBorders;
    private final int margin;
    private String type = "NONE";
    private final IModelerScene modelerScene;

    public CustomRectangularAnchor(INodeWidget nodeWidget, int margin, boolean includeBorders) {
        super(nodeWidget instanceof NodeWidget ? ((NodeWidget) nodeWidget).getNodeImageWidget() : (Widget) nodeWidget);
        this.modelerScene = nodeWidget.getModelerScene();
        this.margin = margin;
        this.includeBorders = includeBorders;
    }

    @Override
    public boolean allowsArbitraryConnectionPlacement() {
        return false;
    }

    //this is used by the Orthogonal Router. This router routes to the center of
    //of the anchors and then allows the anchor to adjust the end points.
    @Override
    public List compute(List points) {

        ArrayList bestPoints = new ArrayList(points);
        Point relatedLocation = getRelatedSceneLocation();

        int direction = 1;
        int index = 0;

        //the related location is the center of this anchor. It is possible that
        //the list of points started at the opposite anchor (other end of connection).
        Point endPoint = bestPoints.get(index);
        if (!endPoint.equals(relatedLocation)) {
            index = bestPoints.size() - 1;
            endPoint = bestPoints.get(index);
            direction = -1;
        }

        Widget widget = getRelatedWidget();
        Rectangle bounds = widget.getBounds();
        bounds = widget.convertLocalToScene(bounds);

        Point neighbor = bestPoints.get(index + direction);

        //moving the end point to the end of the anchor from the interior
        while (bounds.contains(neighbor)) {
            bestPoints.remove(index);
            endPoint = bestPoints.get(index);
            neighbor = bestPoints.get(index + direction);
        }

        Result intersection = this.computeBoundaryIntersectionPoint(endPoint, neighbor);

        bestPoints.remove(index);
        bestPoints.add(index, intersection.getAnchorSceneLocation());

        return bestPoints;
    }

    @Override
    public Result compute(Entry entry) {
//           NodeWidget nodeWidget = (NodeWidget)getRelatedWidget().getParentWidget();
        Point relatedLocation = getRelatedSceneLocation();
        Point oppositeLocation = null;
        List points = entry.getAttachedConnectionWidget().getControlPoints();

        if (entry.getAttachedConnectionWidget() instanceof IFlowEdgeWidget) {
            IFlowEdgeWidget flowEdgeWidget = (IFlowEdgeWidget) entry.getAttachedConnectionWidget();
            INodeWidget sourceNodeWidget = (INodeWidget) flowEdgeWidget.getSourceWidget();
            INodeWidget targetNodeWidget = (INodeWidget) flowEdgeWidget.getTargetWidget();
            if (sourceNodeWidget != null && targetNodeWidget != null && !sourceNodeWidget.isAnchorEnable() && !targetNodeWidget.isAnchorEnable() && !points.isEmpty()) {        //if edge both nodes anchor not enabled (if any one is allowed then calculated[means this if condition failed])
                if (entry.isAttachedToConnectionSource()) {
                    return new Anchor.Result(points.get(0), Anchor.DIRECTION_ANY); //return current
                } else {
                    return new Anchor.Result(points.get(points.size() - 1), Anchor.DIRECTION_ANY); //return current
                }
            }
        }
        if (points.size() > 2) {
            if (entry.isAttachedToConnectionSource()) {
                oppositeLocation = points.get(1);
                type = "SOURCE";
            } else {
                oppositeLocation = points.get(points.size() - 2);
                type = "TARGET";
            }
        } else {
            oppositeLocation = getOppositeSceneLocation(entry);
            type = "NONE";
        }

        Result boundaryIntersection
                = computeBoundaryIntersectionPoint(relatedLocation, oppositeLocation);

        if (boundaryIntersection == null) {
            return new Anchor.Result(relatedLocation, Anchor.DIRECTION_ANY);
        }

        return boundaryIntersection;
    }

    private Result computeBoundaryIntersectionPoint(Point relatedLocation, Point oppositeLocation) {

        Widget widget = getRelatedWidget();
        Rectangle bounds = widget.getBounds();
        if (!includeBorders) {
            Insets insets = widget.getBorder().getInsets();
            bounds.x += insets.left;
            bounds.y += insets.top;
            bounds.width -= insets.left + insets.right;
            bounds.height -= insets.top + insets.bottom;
        }
        bounds = widget.convertLocalToScene(bounds);

        if (bounds.isEmpty() || relatedLocation.equals(oppositeLocation)) {
            return null;
        }
        float dx = oppositeLocation.x - relatedLocation.x;
        float dy = oppositeLocation.y - relatedLocation.y;

        float ddx = Math.abs(dx) / (float) bounds.width;
        float ddy = Math.abs(dy) / (float) bounds.height;

        Anchor.Direction direction;

        if (ddx >= ddy) {
            direction = dx >= 0.0f ? Direction.RIGHT : Direction.LEFT;
        } else {
            direction = dy >= 0.0f ? Direction.BOTTOM : Direction.TOP;
        }

        float scale = 0.5f / Math.max(ddx, ddy);

        Point point = new Point(Math.round(relatedLocation.x + scale * dx),
                Math.round(relatedLocation.y + scale * dy));

        switch (direction) {
            case BOTTOM:
                point.y = point.y - margin;
                break;
            case TOP:
                point.y = point.y + margin;
                break;
            case LEFT:
                point.x = point.x + margin;
                break;
            case RIGHT:
                point.x = point.x - margin;
                break;
            default:
                break;
        }

        Point movePo;
        if (widget instanceof SvgNodeWidget) {
            SvgNodeWidget imageWidget = (SvgNodeWidget) widget;

            if (imageWidget.getTransform() != null) {
                Shape shape;

                if (imageWidget.getResizeType() == ResizeType.OUTER) {
                    shape = imageWidget.getOutlineShape();
                } else {
                    shape = imageWidget.getTransform().createTransformedShape(imageWidget.getOutlineShape());
                }
                Point widgetLoc = imageWidget.convertLocalToScene(imageWidget.getLocation());
                ClosestSegment cs = GeometryClosestPointManager.getClosetsPoint(shape, new Point2D.Double(point.x - widgetLoc.x, point.y - widgetLoc.y));
                int padX = 0;//padding
                int padY = 0;
                if (direction == Direction.TOP) {
                    padY = - 2;
                } else if (direction == Direction.RIGHT) {
                    padX = +2;
                } else if (direction == Direction.BOTTOM) {
                    padY = +2;
                } else if (direction == Direction.LEFT) {
                    padX = - 2;
                }

                movePo = new Point(widgetLoc.x + (int) cs.getBestPoint().getX() + padX, widgetLoc.y + (int) cs.getBestPoint().getY() + padY);

//        Point left_top = new Point((int) bounds.getX(), (int) bounds.getY());
//        Point top_mid = new Point((int) bounds.getX() + (int) (bounds.getWidth() / 2), (int) bounds.getY());
//        Point top_right = new Point((int) bounds.getX() + (int) bounds.getWidth(), (int) bounds.getY());
//        Point left_mid = new Point((int) bounds.getX(), (int) bounds.getY() + (int) (bounds.getHeight() / 2));
//        Point right_mid = new Point((int) bounds.getX() + (int) bounds.getWidth(), (int) bounds.getY() + (int) (bounds.getHeight() / 2));
//        Point left_bottom = new Point((int) bounds.getX(), (int) bounds.getY() + (int) bounds.getHeight());
//        Point bottom_mid = new Point((int) bounds.getX() + (int) (bounds.getWidth() / 2), (int) bounds.getY() + (int) bounds.getHeight());
//        Point bottom_right = new Point((int) bounds.getX() + (int) bounds.getWidth(), (int) bounds.getY() + (int) bounds.getHeight());

                /* Widget Central Gravity Logic Start */
                Point startXY = new Point((int) bounds.getX(), (int) bounds.getY());
                Point endX = new Point((int) bounds.getX() + (int) bounds.getWidth(), (int) bounds.getY());
                Point endY = new Point((int) bounds.getX(), (int) bounds.getY() + (int) bounds.getHeight());
                int substitutePadX = (int) ((endX.x - startXY.x) / 2.222);
                int substitutePadY = (int) ((endY.y - startXY.y) / 2.222);

                if (!type.equals("NONE")) {
                    if (direction == Direction.BOTTOM || direction == Direction.TOP) {
                        if (startXY.x + substitutePadX < oppositeLocation.x & oppositeLocation.x < endX.x - substitutePadX) {
                            movePo = new Point(oppositeLocation.x, movePo.y);
                        }
                    } else if (direction == Direction.LEFT || direction == Direction.RIGHT) {
                        if (startXY.y + substitutePadY < oppositeLocation.y & oppositeLocation.y < endY.y - substitutePadY) {
                            movePo = new Point(movePo.x, oppositeLocation.y);
                        }
                    }
                }

            } else {
                movePo = point;
            }
        } else {
            movePo = point;
        }
        type = "NONE";
        return new Anchor.Result(movePo, direction);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy