下面列出了怎么用javafx.scene.shape.StrokeLineCap的API类实例代码及写法,或者点击链接到github查看源代码。
/** @param color Color to display */
public void setColor(final WidgetColor color)
{
final GraphicsContext gc = blob.getGraphicsContext2D();
gc.setFill(JFXUtil.convert(color));
gc.fillRect(0, 0, 16, 16);
gc.setLineCap(StrokeLineCap.SQUARE);
gc.setLineJoin(StrokeLineJoin.MITER);
gc.setLineWidth(1.75);
gc.setStroke(Color.BLACK);
gc.strokeRect(0, 0, 16, 16);
button.setText(String.valueOf(color));
}
private void initGraphics() {
if (Double.compare(getPrefWidth(), 0.0) <= 0 || Double.compare(getPrefHeight(), 0.0) <= 0 || Double.compare(getWidth(), 0.0) <= 0 ||
Double.compare(getHeight(), 0.0) <= 0) {
if (getPrefWidth() > 0 && getPrefHeight() > 0) {
setPrefSize(getPrefWidth(), getPrefHeight());
} else {
setPrefSize(PREFERRED_WIDTH, PREFERRED_HEIGHT);
}
}
canvas = new Canvas(PREFERRED_WIDTH, PREFERRED_HEIGHT);
ctx = canvas.getGraphicsContext2D();
ctx.setLineCap(StrokeLineCap.BUTT);
tooltip = new Tooltip();
tooltip.setAutoHide(true);
getChildren().setAll(canvas);
}
private void drawGradientBar() {
double xy = TickLabelLocation.OUTSIDE == tickLabelLocation ? 0.115 * size : 0.0515 * size;
double wh = TickLabelLocation.OUTSIDE == tickLabelLocation ? size * 0.77 : size * 0.897;
double offset = 90 - startAngle;
List<Stop> stops = getSkinnable().getGradientBarStops();
Map<Double, Color> stopAngleMap = new HashMap<>(stops.size());
for (Stop stop : stops) { stopAngleMap.put(stop.getOffset() * angleRange, stop.getColor()); }
double offsetFactor = ScaleDirection.CLOCKWISE == scaleDirection ? (startAngle - 90) : (startAngle + 180);
AngleConicalGradient gradient = new AngleConicalGradient(size * 0.5, size * 0.5, offsetFactor, stopAngleMap, getSkinnable().getScaleDirection());
double barStartAngle = ScaleDirection.CLOCKWISE == scaleDirection ? -minValue * angleStep : minValue * angleStep;
double barAngleExtend = ScaleDirection.CLOCKWISE == scaleDirection ? getSkinnable().getRange() * angleStep : -getSkinnable().getRange() * angleStep;
tickMarkCtx.save();
tickMarkCtx.setStroke(gradient.getImagePattern(new Rectangle(xy - 0.026 * size, xy - 0.026 * size, wh + 0.052 * size, wh + 0.052 * size)));
tickMarkCtx.setLineWidth(size * 0.052);
tickMarkCtx.setLineCap(StrokeLineCap.BUTT);
tickMarkCtx.strokeArc(xy, xy, wh, wh, -(offset + barStartAngle), -barAngleExtend, ArcType.OPEN);
tickMarkCtx.restore();
}
private void drawHours(final ZonedDateTime TIME) {
int hourCounter = 1;
int hour = TIME.getHour();
double strokeWidth = size * 0.06;
hoursCtx.setLineCap(StrokeLineCap.BUTT);
hoursCtx.clearRect(0, 0, size, size);
for (int i = 450 ; i >= 90 ; i--) {
hoursCtx.save();
if (i % 30 == 0) {
//draw hours
hoursCtx.setStroke(hourColor);
hoursCtx.setLineWidth(strokeWidth);
if (hour == 0 || hour == 12) {
hoursCtx.strokeArc(strokeWidth * 0.5, strokeWidth * 0.5, size - strokeWidth, size - strokeWidth, i + 1 - 30, 28, ArcType.OPEN);
} else if (hourCounter <= (TIME.get(ChronoField.AMPM_OF_DAY) == 1 ? hour - 12 : hour)) {
hoursCtx.strokeArc(strokeWidth * 0.5, strokeWidth * 0.5, size - strokeWidth, size - strokeWidth, i + 1 - 30, 28, ArcType.OPEN);
hourCounter++;
}
}
hoursCtx.restore();
}
}
private void drawMinutes(final ZonedDateTime TIME) {
int minCounter = 1;
double strokeWidth = size * 0.06;
minutesCtx.clearRect(0, 0, size, size);
minutesCtx.setLineCap(StrokeLineCap.BUTT);
for (int i = 450 ; i >= 90 ; i--) {
minutesCtx.save();
if (i % 6 == 0) {
// draw minutes
if (minCounter <= TIME.getMinute()) {
minutesCtx.setStroke(minCounter % 5 == 0 ? fiveMinuteColor : minuteColor);
minutesCtx.setLineWidth(strokeWidth);
minutesCtx.strokeArc(strokeWidth * 0.5 + strokeWidth * 1.1, strokeWidth * 0.5 + strokeWidth * 1.1, size - strokeWidth - strokeWidth * 2.2, size - strokeWidth - strokeWidth * 2.2, i + 1 - 6, 4, ArcType.OPEN);
minCounter++;
}
}
minutesCtx.restore();
}
}
private void drawSeconds(final ZonedDateTime TIME) {
int secCounter = 1;
double strokeWidth = size * 0.06;
secondsCtx.setLineCap(StrokeLineCap.BUTT);
secondsCtx.clearRect(0, 0, size, size);
for (int i = 450 ; i >= 90 ; i--) {
secondsCtx.save();
if (i % 6 == 0) {
// draw seconds
if (secCounter <= TIME.getSecond() + 1) {
secondsCtx.setStroke(secondColor);
secondsCtx.setLineWidth(strokeWidth * 0.25);
secondsCtx.strokeArc(strokeWidth * 0.5 + strokeWidth * 1.8, strokeWidth * 0.5 + strokeWidth * 1.8, size - strokeWidth - strokeWidth * 3.6, size - strokeWidth - strokeWidth * 3.6, i + 1 - 6, 4, ArcType.OPEN);
secCounter++;
}
}
secondsCtx.restore();
}
}
private void drawGradientBar() {
Pos knobPosition = gauge.getKnobPosition();
TickLabelLocation tickLabelLocation = gauge.getTickLabelLocation();
double scaledSize = size * 1.9;
double xy = TickLabelLocation.OUTSIDE == tickLabelLocation ? 0.105 * scaledSize : 0.03875 * scaledSize;
double wh = TickLabelLocation.OUTSIDE == tickLabelLocation ? scaledSize * 0.79 : scaledSize * 0.925;
double offsetX = Pos.TOP_LEFT == knobPosition || Pos.BOTTOM_LEFT == knobPosition ? -scaledSize * 0.475 : 0;
double offsetY = Pos.TOP_LEFT == knobPosition || Pos.TOP_RIGHT == knobPosition ? -scaledSize * 0.475 : 0;
double offset = 90 - startAngle;
ScaleDirection scaleDirection = gauge.getScaleDirection();
List<Stop> stops = gauge.getGradientBarStops();
Map<Double, Color> stopAngleMap = new HashMap<>(stops.size());
for (Stop stop : stops) { stopAngleMap.put(stop.getOffset() * ANGLE_RANGE, stop.getColor()); }
double offsetFactor = ScaleDirection.CLOCKWISE == scaleDirection ? (Pos.TOP_LEFT == knobPosition || Pos.BOTTOM_RIGHT == knobPosition ? startAngle : 180 - startAngle) : (startAngle + 180);
AngleConicalGradient gradient = new AngleConicalGradient(scaledSize * 0.5, scaledSize * 0.5, offsetFactor, stopAngleMap, gauge.getScaleDirection());
double barStartAngle = ScaleDirection.CLOCKWISE == scaleDirection ? -minValue * angleStep : minValue * angleStep;
double barAngleExtend = ScaleDirection.CLOCKWISE == scaleDirection ? gauge.getRange() * angleStep : -gauge.getRange() * angleStep;
tickMarkCtx.save();
tickMarkCtx.setStroke(gradient.getImagePattern(new Rectangle(xy - 0.026 * scaledSize + offsetX, xy - 0.026 * scaledSize + offsetY, wh + 0.052 * scaledSize, wh + 0.052 * scaledSize)));
tickMarkCtx.setLineWidth(scaledSize * 0.052);
tickMarkCtx.setLineCap(StrokeLineCap.BUTT);
tickMarkCtx.strokeArc(xy + offsetX, xy + offsetY, wh, wh, -(offset + barStartAngle), -barAngleExtend, ArcType.OPEN);
tickMarkCtx.restore();
}
private void drawSections() {
if (sections.isEmpty()) return;
sectionLayer.getChildren().clear();
double centerX = width * 0.5;
double centerY = height * 0.85;
double barRadius = height * 0.54210526;
double barWidth = width * 0.28472222;
List<Arc> sectionBars = new ArrayList<>(sections.size());
for (Section section : sections) {
Arc sectionBar = new Arc(centerX, centerY, barRadius, barRadius, angleRange * 0.5 + 90 - (section.getStart() * angleStep), -((section.getStop() - section.getStart()) - minValue) * angleStep);
sectionBar.setType(ArcType.OPEN);
sectionBar.setStroke(section.getColor());
sectionBar.setStrokeWidth(barWidth);
sectionBar.setStrokeLineCap(StrokeLineCap.BUTT);
sectionBar.setFill(null);
Tooltip sectionTooltip = new Tooltip(new StringBuilder(section.getText()).append("\n").append(String.format(Locale.US, "%.2f", section.getStart())).append(" - ").append(String.format(Locale.US, "%.2f", section.getStop())).toString());
sectionTooltip.setTextAlignment(TextAlignment.CENTER);
Tooltip.install(sectionBar, sectionTooltip);
sectionBars.add(sectionBar);
}
sectionLayer.getChildren().addAll(sectionBars);
}
/**
* Maps a line cap code from AWT to the corresponding JavaFX StrokeLineCap
* enum value.
*
* @param c the line cap code.
*
* @return A JavaFX line cap value.
*/
private StrokeLineCap awtToJavaFXLineCap(int c) {
if (c == BasicStroke.CAP_BUTT) {
return StrokeLineCap.BUTT;
} else if (c == BasicStroke.CAP_ROUND) {
return StrokeLineCap.ROUND;
} else if (c == BasicStroke.CAP_SQUARE) {
return StrokeLineCap.SQUARE;
} else {
throw new IllegalArgumentException("Unrecognised cap code: " + c);
}
}
@Override
public ObjectProperty<StrokeLineCap> strokeLineCapProperty() {
if (strokeLineCap == null) {
strokeLineCap = new SimpleObjectProperty<>(this, "strokeLineCap", DEFAULT_STROKE_LINE_CAP);
strokeLineCap.addListener((v, o, n) -> forwardShapeProperty(s -> s.setStrokeLineCap(n)));
}
return strokeLineCap;
}
private void initializeParts() {
double cx = ARTBOARD_WIDTH * 0.5;
separator = new Line(25, 15, 225, 15);
separator.getStyleClass().add("separator");
separator.setStrokeLineCap(StrokeLineCap.ROUND);
titleLabel = createCenteredText(cx, 19, "title");
titleLabel.setTextOrigin(VPos.TOP);
valueLabel = createCenteredText(cx, 150, "value");
unitLabel = createCenteredText(cx, 188, "unit");
unitLabel.setTextOrigin(VPos.TOP);
barBackground = new Circle(CIRCLE_CENTER_X, CIRCLE_CENTER_Y, RADIUS);
barBackground.getStyleClass().add("barBackground");
bar = new Arc(CIRCLE_CENTER_X, CIRCLE_CENTER_Y, RADIUS, RADIUS, START_ANGLE, 0);
bar.getStyleClass().add("bar");
bar.setType(ArcType.OPEN);
thumb = new Circle(7);
thumb.getStyleClass().add("thumb");
// always needed
drawingPane = new Pane();
drawingPane.setMaxSize(ARTBOARD_WIDTH, ARTBOARD_HEIGHT);
drawingPane.setMinSize(ARTBOARD_WIDTH, ARTBOARD_HEIGHT);
drawingPane.setPrefSize(ARTBOARD_WIDTH, ARTBOARD_HEIGHT);
}
private final void drawSections(final GraphicsContext CTX) {
final double xy = (size - 0.87 * size) * 0.5;
final double wh = size * 0.87;
final double MIN_VALUE = getSkinnable().getMinValue();
final double OFFSET = 90 - getSkinnable().getStartAngle();
for (int i = 0 ; i < getSkinnable().getSections().size() ; i++) {
final Section SECTION = getSkinnable().getSections().get(i);
final double ANGLE_START = (SECTION.getStart() - MIN_VALUE) * angleStep;
final double ANGLE_EXTEND = (SECTION.getStop() - SECTION.getStart()) * angleStep;
CTX.save();
switch(i) {
case 0: CTX.setStroke(getSkinnable().getSectionFill0()); break;
case 1: CTX.setStroke(getSkinnable().getSectionFill1()); break;
case 2: CTX.setStroke(getSkinnable().getSectionFill2()); break;
case 3: CTX.setStroke(getSkinnable().getSectionFill3()); break;
case 4: CTX.setStroke(getSkinnable().getSectionFill4()); break;
case 5: CTX.setStroke(getSkinnable().getSectionFill5()); break;
case 6: CTX.setStroke(getSkinnable().getSectionFill6()); break;
case 7: CTX.setStroke(getSkinnable().getSectionFill7()); break;
case 8: CTX.setStroke(getSkinnable().getSectionFill8()); break;
case 9: CTX.setStroke(getSkinnable().getSectionFill9()); break;
}
CTX.setLineWidth(size * 0.1);
CTX.setLineCap(StrokeLineCap.BUTT);
CTX.strokeArc(xy, xy, wh, wh, -(OFFSET + ANGLE_START), -ANGLE_EXTEND, ArcType.OPEN);
CTX.restore();
}
}
/**
* Maps a line cap code from AWT to the corresponding JavaFX StrokeLineCap
* enum value.
*
* @param c the line cap code.
*
* @return A JavaFX line cap value.
*/
private StrokeLineCap awtToJavaFXLineCap(int c) {
if (c == BasicStroke.CAP_BUTT) {
return StrokeLineCap.BUTT;
} else if (c == BasicStroke.CAP_ROUND) {
return StrokeLineCap.ROUND;
} else if (c == BasicStroke.CAP_SQUARE) {
return StrokeLineCap.SQUARE;
} else {
throw new IllegalArgumentException("Unrecognised cap code: " + c);
}
}
private Line createLine(final Point p1, final Point p2) {
final Line line = new Line();
line.startXProperty().bind(p1.xProperty());
line.startYProperty().bind(p1.yProperty());
line.endXProperty().bind(p2.xProperty());
line.endYProperty().bind(p2.yProperty());
line.strokeWidthProperty().bind(Bindings.createDoubleBinding(() -> model.getFullThickness() / 2d, model.thicknessProperty(),
model.dbleBordSepProperty(), model.dbleBordProperty()));
line.strokeProperty().bind(Bindings.createObjectBinding(() -> model.getLineColour().toJFX(), model.lineColourProperty()));
line.setStrokeLineCap(StrokeLineCap.BUTT);
line.getStrokeDashArray().clear();
line.getStrokeDashArray().addAll(model.getDashSepBlack(), model.getDashSepWhite());
return line;
}
@Override
public Group createJFXNode() throws Exception
{
final Polyline polyline = new Polyline();
polyline.setStrokeLineJoin(StrokeLineJoin.MITER);
polyline.setStrokeLineCap(StrokeLineCap.BUTT);
return new Group(polyline, new Arrow(), new Arrow());
}
@Override
public Polygon createJFXNode() throws Exception
{
final Polygon polygon = new Polygon();
polygon.setStrokeLineJoin(StrokeLineJoin.ROUND);
polygon.setStrokeLineCap(StrokeLineCap.BUTT);
return polygon;
}
@Test
void testLineStylePlainLineCap() {
assumeTrue(model.isLineStylable());
model.setLineStyle(LineStyle.SOLID);
WaitForAsyncUtils.waitForFxEvents();
assertEquals(StrokeLineCap.BUTT, border.getStrokeLineCap());
}
public static String toValue(StrokeLineCap x)
{
switch(x)
{
case BUTT: return "butt";
case ROUND: return "round";
case SQUARE: return "square";
}
throw new Error("?" + x);
}
private void drawHighLightSections(final double VALUE) {
highlightSectionCtx.setLineCap(StrokeLineCap.BUTT);
highlightSectionCtx.clearRect(0, 0, width, height);
if (tile.getSectionsVisible() && !sections.isEmpty()) {
double x = (width - size * 0.7) * 0.5;
double y = (height - size * 0.7) * 0.5;
double wh = size * 0.7;
double minValue = tile.getMinValue();
double maxValue = tile.getMaxValue();
double angleStep = tile.getAngleStep();
highlightSectionCtx.setLineWidth(size * 0.01);
highlightSectionCtx.setLineCap(StrokeLineCap.BUTT);
for (int i = 0; i < sections.size(); i++) {
Section section = sections.get(i);
double sectionStartAngle;
if (Double.compare(section.getStart(), maxValue) <= 0 && Double.compare(section.getStop(), minValue) >= 0) {
if (Double.compare(section.getStart(), minValue) < 0 && Double.compare(section.getStop(), maxValue) < 0) {
sectionStartAngle = 15;
} else {
sectionStartAngle = (section.getStart() - minValue) * angleStep + 15;
}
double sectionAngleExtend;
if (Double.compare(section.getStop(), maxValue) > 0) {
sectionAngleExtend = (maxValue - section.getStart()) * angleStep;
} else if (Double.compare(section.getStart(), minValue) < 0) {
sectionAngleExtend = (section.getStop() - minValue) * tile.getAngleStep();
} else {
sectionAngleExtend = (section.getStop() - section.getStart()) * angleStep;
}
highlightSectionCtx.save();
highlightSectionCtx.setStroke(section.contains(VALUE) ? section.getColor() : section.getColor().darker().darker());
highlightSectionCtx.strokeArc(x, y, wh, wh, -(120 + sectionStartAngle), -sectionAngleExtend, ArcType.OPEN);
highlightSectionCtx.restore();
}
}
}
}
@Test
void testChangeSubGridDots() {
model.setSubGridDots(21);
WaitForAsyncUtils.waitForFxEvents();
assertNotEquals(subGridBefore, view.getSubgrid().getElements());
assertEquals(StrokeLineCap.ROUND, view.getSubgrid().getStrokeLineCap());
assertEquals(mainGridBefore, view.getMaingrid().getElements());
}
@Test
void testLineStyleDashedLineCap() {
assumeTrue(model.isLineStylable());
model.setLineStyle(LineStyle.DASHED);
WaitForAsyncUtils.waitForFxEvents();
assertEquals(StrokeLineCap.BUTT, border.getStrokeLineCap());
}
private void drawTicks() {
double sinValue;
double cosValue;
double startAngle = 180;
double angleStep = 360 / 60;
Point2D center = new Point2D(size * 0.5, size * 0.5);
Color hourTickMarkColor = getSkinnable().getHourTickMarkColor();
Color minuteTickMarkColor = getSkinnable().getMinuteTickMarkColor();
boolean hourTickMarksVisible = getSkinnable().isHourTickMarksVisible();
boolean minuteTickMarksVisible = getSkinnable().isMinuteTickMarksVisible();
tickCtx.clearRect(0, 0, size, size);
tickCtx.setLineCap(StrokeLineCap.ROUND);
for (double angle = 0, counter = 0 ; Double.compare(counter, 59) <= 0 ; angle -= angleStep, counter++) {
sinValue = Math.sin(Math.toRadians(angle + startAngle));
cosValue = Math.cos(Math.toRadians(angle + startAngle));
Point2D innerPoint = new Point2D(center.getX() + size * 0.405 * sinValue, center.getY() + size * 0.405 * cosValue);
Point2D innerMinutePoint = new Point2D(center.getX() + size * 0.435 * sinValue, center.getY() + size * 0.435 * cosValue);
Point2D outerPoint = new Point2D(center.getX() + size * 0.465 * sinValue, center.getY() + size * 0.465 * cosValue);
if (counter % 5 == 0) {
// Draw hour tickmark
tickCtx.setStroke(hourTickMarkColor);
if (hourTickMarksVisible) {
tickCtx.setLineWidth(size * 0.01);
tickCtx.strokeLine(innerPoint.getX(), innerPoint.getY(), outerPoint.getX(), outerPoint.getY());
} else if (minuteTickMarksVisible) {
tickCtx.setLineWidth(size * 0.005);
tickCtx.strokeLine(innerMinutePoint.getX(), innerMinutePoint.getY(), outerPoint.getX(), outerPoint.getY());
}
} else if (counter % 1 == 0 && minuteTickMarksVisible) {
// Draw minute tickmark
tickCtx.setLineWidth(size * 0.005);
tickCtx.setStroke(minuteTickMarkColor);
tickCtx.strokeLine(innerMinutePoint.getX(), innerMinutePoint.getY(), outerPoint.getX(), outerPoint.getY());
}
}
}
public static Node createLoadingNode () {
Circle c0 = new Circle(65);
c0.setFill(Color.TRANSPARENT);
c0.setStrokeWidth(0.0);
Circle c1 = new Circle(50);
c1.setFill(Color.TRANSPARENT);
c1.setStrokeType(StrokeType.INSIDE);
c1.setStrokeLineCap(StrokeLineCap.BUTT);
c1.getStrokeDashArray().addAll(78.54); // 50 * 2 * 3.1416 / 4
c1.setCache(true);
c1.setCacheHint(CacheHint.ROTATE);
c1.getStyleClass().add("loading-circle");
setRotate(c1, true, 440.0, 10);
Circle c2 = new Circle(40);
c2.setFill(Color.TRANSPARENT);
c2.setStrokeType(StrokeType.INSIDE);
c2.setStrokeLineCap(StrokeLineCap.BUTT);
c2.getStrokeDashArray().addAll(41.89); // 40 * 2 * 3.1416 / 6
c2.setCache(true);
c2.setCacheHint(CacheHint.ROTATE);
c2.getStyleClass().add("loading-circle");
setRotate(c2, true, 360.0, 14);
Circle c3 = new Circle(30);
c3.setFill(Color.TRANSPARENT);
c3.setStrokeType(StrokeType.INSIDE);
c3.setStrokeLineCap(StrokeLineCap.BUTT);
c3.getStyleClass().add("loading-circle");
Group g = new Group(c0, c1, c2, c3);
g.getStylesheets().add(Dialogs.class.getResource("/com/adr/helloiot/styles/loading.css").toExternalForm());
return g;
}
@Test
void testChangeGridDots() {
model.setGridDots(23);
WaitForAsyncUtils.waitForFxEvents();
assertNotEquals(mainGridBefore, view.getMaingrid().getElements());
assertEquals(StrokeLineCap.ROUND, view.getMaingrid().getStrokeLineCap());
assertEquals(subGridBefore, view.getSubgrid().getElements());
}
public HamburgerIcon(double sz)
{
super(sz);
double gapx = sz * 0.2;
double gapy = sz * 0.25;
double th = sz * 0.075;
double x0 = gapx;
double xm = sz - gapx;
double y0 = gapy;
double y1 = sz / 2;
double ym = sz - gapy;
FxPath p = new FxPath();
p.setStroke(Color.BLACK);
p.setStrokeWidth(th);
p.setStrokeLineCap(StrokeLineCap.ROUND);
p.moveto(x0, y0);
p.lineto(xm, y0);
p.moveto(x0, y1);
p.lineto(xm, y1);
p.moveto(x0, ym);
p.lineto(xm, ym);
add(p);
}
/**
* Maps a line cap code from AWT to the corresponding JavaFX StrokeLineCap
* enum value.
*
* @param c the line cap code.
*
* @return A JavaFX line cap value.
*/
private StrokeLineCap awtToJavaFXLineCap(int c) {
if (c == BasicStroke.CAP_BUTT) {
return StrokeLineCap.BUTT;
} else if (c == BasicStroke.CAP_ROUND) {
return StrokeLineCap.ROUND;
} else if (c == BasicStroke.CAP_SQUARE) {
return StrokeLineCap.SQUARE;
} else {
throw new IllegalArgumentException("Unrecognised cap code: " + c);
}
}
/**
* The constructor by default.
* @param border The selection border.
*/
public RotationHandler(final @NotNull Rectangle border) {
super();
final Arc arc = new Arc();
arc.setCenterX(DEFAULT_SIZE / 2d);
arc.setRadiusX(DEFAULT_SIZE / 2d);
arc.setRadiusY(DEFAULT_SIZE / 2d);
arc.setType(ArcType.OPEN);
arc.setLength(270d);
arc.setStroke(DEFAULT_COLOR);
arc.setStrokeWidth(2.5d);
arc.setStrokeLineCap(StrokeLineCap.BUTT);
arc.setFill(new Color(1d, 1d, 1d, 0d));
getChildren().add(arc);
final Path arrows = new Path();
arrows.setStroke(null);
arrows.setFill(new Color(0d, 0d, 0d, 0.4));
arrows.getElements().add(new MoveTo(DEFAULT_SIZE + DEFAULT_SIZE / 4d, 0d));
arrows.getElements().add(new LineTo(DEFAULT_SIZE, DEFAULT_SIZE / 2d));
arrows.getElements().add(new LineTo(DEFAULT_SIZE - DEFAULT_SIZE / 4d, 0d));
arrows.getElements().add(new ClosePath());
getChildren().add(arrows);
translateXProperty().bind(Bindings.createDoubleBinding(() -> border.getLayoutX() + border.getWidth(), border.xProperty(),
border.widthProperty(), border.layoutXProperty()));
translateYProperty().bind(Bindings.createDoubleBinding(() -> border.getLayoutY() + DEFAULT_SIZE, border.yProperty(),
border.heightProperty(), border.layoutYProperty()));
}
/**
* Maps a line cap code from AWT to the corresponding JavaFX StrokeLineCap
* enum value.
*
* @param c the line cap code.
*
* @return A JavaFX line cap value.
*/
private StrokeLineCap awtToJavaFXLineCap(int c) {
if (c == BasicStroke.CAP_BUTT) {
return StrokeLineCap.BUTT;
} else if (c == BasicStroke.CAP_ROUND) {
return StrokeLineCap.ROUND;
} else if (c == BasicStroke.CAP_SQUARE) {
return StrokeLineCap.SQUARE;
} else {
throw new IllegalArgumentException("Unrecognised cap code: " + c);
}
}
private String strokeLineCapToSVGLineCap(final StrokeLineCap cap) {
return switch(cap) {
case SQUARE -> SVGAttributes.SVG_LINECAP_VALUE_SQUARE;
case BUTT -> SVGAttributes.SVG_LINECAP_VALUE_BUTT;
case ROUND -> SVGAttributes.SVG_LINECAP_VALUE_ROUND;
};
}
private void drawTicks() {
double sinValue;
double cosValue;
double startAngle = 180;
double angleStep = 360 / 60;
Point2D center = new Point2D(size * 0.5, size * 0.5);
Color hourTickMarkColor = clock.getHourTickMarkColor();
Color minuteTickMarkColor = clock.getMinuteTickMarkColor();
boolean hourTickMarksVisible = clock.isHourTickMarksVisible();
boolean minuteTickMarksVisible = clock.isMinuteTickMarksVisible();
tickCtx.clearRect(0, 0, size, size);
tickCtx.setLineCap(StrokeLineCap.BUTT);
tickCtx.setLineWidth(size * 0.00539811);
for (double angle = 0, counter = 0 ; Double.compare(counter, 59) <= 0 ; angle -= angleStep, counter++) {
sinValue = Math.sin(Math.toRadians(angle + startAngle));
cosValue = Math.cos(Math.toRadians(angle + startAngle));
Point2D innerPoint = new Point2D(center.getX() + size * 0.40350877 * sinValue, center.getY() + size * 0.40350877 * cosValue);
Point2D innerMinutePoint = new Point2D(center.getX() + size * 0.451417 * sinValue, center.getY() + size * 0.451417 * cosValue);
Point2D outerPoint = new Point2D(center.getX() + size * 0.47435897 * sinValue, center.getY() + size * 0.47435897 * cosValue);
if (counter % 5 == 0) {
tickCtx.setStroke(hourTickMarkColor);
if (hourTickMarksVisible) {
tickCtx.strokeLine(innerPoint.getX(), innerPoint.getY(), outerPoint.getX(), outerPoint.getY());
} else if (minuteTickMarksVisible) {
tickCtx.strokeLine(innerMinutePoint.getX(), innerMinutePoint.getY(), outerPoint.getX(), outerPoint.getY());
}
} else if (counter % 1 == 0 && minuteTickMarksVisible) {
tickCtx.setStroke(minuteTickMarkColor);
tickCtx.strokeLine(innerMinutePoint.getX(), innerMinutePoint.getY(), outerPoint.getX(), outerPoint.getY());
}
}
}