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}