001package conexp.fx.gui.graph;
002
003/*
004 * #%L
005 * Concept Explorer FX
006 * %%
007 * Copyright (C) 2010 - 2023 Francesco Kriegel
008 * %%
009 * This program is free software: you can redistribute it and/or modify
010 * it under the terms of the GNU General Public License as
011 * published by the Free Software Foundation, either version 3 of the
012 * License, or (at your option) any later version.
013 * 
014 * This program is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 * 
019 * You should have received a copy of the GNU General Public
020 * License along with this program.  If not, see
021 * <http://www.gnu.org/licenses/gpl-3.0.html>.
022 * #L%
023 */
024
025
026import javafx.scene.Group;
027import javafx.scene.paint.Color;
028import javafx.scene.paint.Paint;
029import javafx.scene.shape.Arc;
030import javafx.scene.shape.ArcBuilder;
031import javafx.scene.shape.ArcType;
032import javafx.scene.shape.Circle;
033import javafx.scene.shape.CircleBuilder;
034import javafx.scene.shape.Rectangle;
035import javafx.scene.shape.RectangleBuilder;
036import javafx.scene.shape.Shape;
037import javafx.scene.shape.StrokeType;
038
039public class SuperNode extends Group {
040
041  public enum State {
042    CIRCLE,
043    ARC;
044  }
045
046  private State state;
047
048  public final State getState() {
049    return state;
050  }
051
052  public SuperNode(final double radius, final Paint fill) {
053    toCircle(radius, fill);
054  }
055
056  public SuperNode(
057      final double innerRadius,
058      final double outerRadius,
059      final double startAngle,
060      final double length,
061      final Paint fill) {
062    toArc(innerRadius, outerRadius, startAngle, length, fill);
063  }
064
065  public void toCircle(final double radius, final Paint fill) {
066    getChildren().clear();
067    getChildren().add(
068        CircleBuilder
069            .create()
070            .radius(radius)
071            .fill(fill)
072            .strokeType(StrokeType.OUTSIDE)
073            .stroke(Color.BLACK)
074            .strokeWidth(1d)
075            .build());
076    state = State.CIRCLE;
077  }
078
079  public void toArc(
080      final double innerRadius,
081      final double outerRadius,
082      final double startAngle,
083      final double length,
084      final Paint fill) {
085    getChildren().clear();
086    getChildren().add(newBackRectangle(2 * outerRadius));
087    getChildren().add(newCircularSegment(innerRadius, outerRadius, startAngle, length, fill));
088    state = State.ARC;
089  }
090
091  private final Rectangle newBackRectangle(final double size) {
092    final Rectangle back = RectangleBuilder.create().build();
093    back.setWidth(size);
094    back.setHeight(size);
095    back.setFill(Color.TRANSPARENT);
096    return back;
097  }
098
099  private final Shape newCircularSegment(
100      final double innerRadius,
101      final double outerRadius,
102      final double startAngle,
103      final double length,
104      final Paint fill) {
105    final Circle inner = CircleBuilder.create().centerX(outerRadius).centerY(outerRadius).radius(innerRadius).build();
106    final Arc outer =
107        ArcBuilder
108            .create()
109            .centerX(outerRadius)
110            .centerY(outerRadius)
111            .radiusX(outerRadius)
112            .radiusY(outerRadius)
113            .startAngle(startAngle)
114            .type(ArcType.ROUND)
115            .length(length)
116            .build();
117    final Shape segmentArc = Shape.subtract(outer, inner);
118    segmentArc.setFill(fill);
119    segmentArc.setStrokeType(StrokeType.CENTERED);
120    segmentArc.setStroke(Color.BLACK);
121    segmentArc.setStrokeWidth(0.5d);
122    return segmentArc;
123  }
124}