72 73 // -------------- PRIVATE FIELDS ----------------------------------------------------------------------------------- 74 75 private static final int MIN_WIDTH_TO_LEAVE_FOR_CHART_CONTENT = 200; 76 private static final int MIN_HEIGHT_TO_LEAVE_FOR_CHART_CONTENT = 150; 77 78 /** Title Label */ 79 private final Label titleLabel = new Label(); 80 /** 81 * This is the Pane that Chart subclasses use to contain the chart content, 82 * It is sized to be inside the chart area leaving space for the title and legend. 83 */ 84 private final Pane chartContent = new Pane() { 85 @Override protected void layoutChildren() { 86 final double top = snappedTopInset(); 87 final double left = snappedLeftInset(); 88 final double bottom = snappedBottomInset(); 89 final double right = snappedRightInset(); 90 final double width = getWidth(); 91 final double height = getHeight(); 92 final double contentWidth = snapSize(width - (left + right)); 93 final double contentHeight = snapSize(height - (top + bottom)); 94 layoutChartChildren(snapPosition(top), snapPosition(left),contentWidth,contentHeight); 95 } 96 @Override public boolean usesMirroring() { 97 return useChartContentMirroring; 98 } 99 }; 100 // Determines if chart content should be mirrored if node orientation is right-to-left. 101 boolean useChartContentMirroring = true; 102 103 /** Animator for animating stuff on the chart */ 104 private final ChartLayoutAnimator animator = new ChartLayoutAnimator(chartContent); 105 106 // -------------- PUBLIC PROPERTIES -------------------------------------------------------------------------------- 107 108 /** The chart title */ 109 private StringProperty title = new StringPropertyBase() { 110 @Override protected void invalidated() { 111 titleLabel.setText(get()); 112 } 113 114 @Override 320 * @param left The left offset from the origin to account for any padding on the chart content 321 * @param width The width of the area to layout the chart within 322 * @param height The height of the area to layout the chart within 323 */ 324 protected abstract void layoutChartChildren(double top, double left, double width, double height); 325 326 /** 327 * Invoked during the layout pass to layout this chart and all its content. 328 */ 329 @Override protected void layoutChildren() { 330 double top = snappedTopInset(); 331 double left = snappedLeftInset(); 332 double bottom = snappedBottomInset(); 333 double right = snappedRightInset(); 334 final double width = getWidth(); 335 final double height = getHeight(); 336 // layout title 337 if (getTitle() != null) { 338 titleLabel.setVisible(true); 339 if (getTitleSide().equals(Side.TOP)) { 340 final double titleHeight = snapSize(titleLabel.prefHeight(width-left-right)); 341 titleLabel.resizeRelocate(left,top,width-left-right,titleHeight); 342 top += titleHeight; 343 } else if (getTitleSide().equals(Side.BOTTOM)) { 344 final double titleHeight = snapSize(titleLabel.prefHeight(width-left-right)); 345 titleLabel.resizeRelocate(left,height-bottom-titleHeight,width-left-right,titleHeight); 346 bottom += titleHeight; 347 } else if (getTitleSide().equals(Side.LEFT)) { 348 final double titleWidth = snapSize(titleLabel.prefWidth(height-top-bottom)); 349 titleLabel.resizeRelocate(left,top,titleWidth,height-top-bottom); 350 left += titleWidth; 351 } else if (getTitleSide().equals(Side.RIGHT)) { 352 final double titleWidth = snapSize(titleLabel.prefWidth(height-top-bottom)); 353 titleLabel.resizeRelocate(width-right-titleWidth,top,titleWidth,height-top-bottom); 354 right += titleWidth; 355 } 356 } else { 357 titleLabel.setVisible(false); 358 } 359 // layout legend 360 final Node legend = getLegend(); 361 if (legend != null) { 362 boolean shouldShowLegend = isLegendVisible(); 363 if (shouldShowLegend) { 364 if (getLegendSide() == Side.TOP) { 365 final double legendHeight = snapSize(legend.prefHeight(width-left-right)); 366 final double legendWidth = Utils.boundedSize(snapSize(legend.prefWidth(legendHeight)), 0, width - left - right); 367 legend.resizeRelocate(left + (((width - left - right)-legendWidth)/2), top, legendWidth, legendHeight); 368 if ((height - bottom - top - legendHeight) < MIN_HEIGHT_TO_LEAVE_FOR_CHART_CONTENT) { 369 shouldShowLegend = false; 370 } else { 371 top += legendHeight; 372 } 373 } else if (getLegendSide() == Side.BOTTOM) { 374 final double legendHeight = snapSize(legend.prefHeight(width-left-right)); 375 final double legendWidth = Utils.boundedSize(snapSize(legend.prefWidth(legendHeight)), 0, width - left - right); 376 legend.resizeRelocate(left + (((width - left - right)-legendWidth)/2), height-bottom-legendHeight, legendWidth, legendHeight); 377 if ((height - bottom - top - legendHeight) < MIN_HEIGHT_TO_LEAVE_FOR_CHART_CONTENT) { 378 shouldShowLegend = false; 379 } else { 380 bottom += legendHeight; 381 } 382 } else if (getLegendSide() == Side.LEFT) { 383 final double legendWidth = snapSize(legend.prefWidth(height-top-bottom)); 384 final double legendHeight = Utils.boundedSize(snapSize(legend.prefHeight(legendWidth)), 0, height - top - bottom); 385 legend.resizeRelocate(left,top +(((height-top-bottom)-legendHeight)/2),legendWidth,legendHeight); 386 if ((width - left - right - legendWidth) < MIN_WIDTH_TO_LEAVE_FOR_CHART_CONTENT) { 387 shouldShowLegend = false; 388 } else { 389 left += legendWidth; 390 } 391 } else if (getLegendSide() == Side.RIGHT) { 392 final double legendWidth = snapSize(legend.prefWidth(height-top-bottom)); 393 final double legendHeight = Utils.boundedSize(snapSize(legend.prefHeight(legendWidth)), 0, height - top - bottom); 394 legend.resizeRelocate(width-right-legendWidth,top +(((height-top-bottom)-legendHeight)/2),legendWidth,legendHeight); 395 if ((width - left - right - legendWidth) < MIN_WIDTH_TO_LEAVE_FOR_CHART_CONTENT) { 396 shouldShowLegend = false; 397 } else { 398 right += legendWidth; 399 } 400 } 401 } 402 legend.setVisible(shouldShowLegend); 403 } 404 // whats left is for the chart content 405 chartContent.resizeRelocate(left,top,width-left-right,height-top-bottom); 406 } 407 408 /** 409 * Charts are sized outside in, user tells chart how much space it has and chart draws inside that. So minimum 410 * height is a constant 150. 411 */ 412 @Override protected double computeMinHeight(double width) { return 150; } 413 | 72 73 // -------------- PRIVATE FIELDS ----------------------------------------------------------------------------------- 74 75 private static final int MIN_WIDTH_TO_LEAVE_FOR_CHART_CONTENT = 200; 76 private static final int MIN_HEIGHT_TO_LEAVE_FOR_CHART_CONTENT = 150; 77 78 /** Title Label */ 79 private final Label titleLabel = new Label(); 80 /** 81 * This is the Pane that Chart subclasses use to contain the chart content, 82 * It is sized to be inside the chart area leaving space for the title and legend. 83 */ 84 private final Pane chartContent = new Pane() { 85 @Override protected void layoutChildren() { 86 final double top = snappedTopInset(); 87 final double left = snappedLeftInset(); 88 final double bottom = snappedBottomInset(); 89 final double right = snappedRightInset(); 90 final double width = getWidth(); 91 final double height = getHeight(); 92 final double contentWidth = snapSizeX(width - (left + right)); 93 final double contentHeight = snapSizeY(height - (top + bottom)); 94 layoutChartChildren(snapPositionY(top), snapPositionX(left), contentWidth, contentHeight); 95 } 96 @Override public boolean usesMirroring() { 97 return useChartContentMirroring; 98 } 99 }; 100 // Determines if chart content should be mirrored if node orientation is right-to-left. 101 boolean useChartContentMirroring = true; 102 103 /** Animator for animating stuff on the chart */ 104 private final ChartLayoutAnimator animator = new ChartLayoutAnimator(chartContent); 105 106 // -------------- PUBLIC PROPERTIES -------------------------------------------------------------------------------- 107 108 /** The chart title */ 109 private StringProperty title = new StringPropertyBase() { 110 @Override protected void invalidated() { 111 titleLabel.setText(get()); 112 } 113 114 @Override 320 * @param left The left offset from the origin to account for any padding on the chart content 321 * @param width The width of the area to layout the chart within 322 * @param height The height of the area to layout the chart within 323 */ 324 protected abstract void layoutChartChildren(double top, double left, double width, double height); 325 326 /** 327 * Invoked during the layout pass to layout this chart and all its content. 328 */ 329 @Override protected void layoutChildren() { 330 double top = snappedTopInset(); 331 double left = snappedLeftInset(); 332 double bottom = snappedBottomInset(); 333 double right = snappedRightInset(); 334 final double width = getWidth(); 335 final double height = getHeight(); 336 // layout title 337 if (getTitle() != null) { 338 titleLabel.setVisible(true); 339 if (getTitleSide().equals(Side.TOP)) { 340 final double titleHeight = snapSizeY(titleLabel.prefHeight(width-left-right)); 341 titleLabel.resizeRelocate(left,top,width-left-right,titleHeight); 342 top += titleHeight; 343 } else if (getTitleSide().equals(Side.BOTTOM)) { 344 final double titleHeight = snapSizeY(titleLabel.prefHeight(width-left-right)); 345 titleLabel.resizeRelocate(left,height-bottom-titleHeight,width-left-right,titleHeight); 346 bottom += titleHeight; 347 } else if (getTitleSide().equals(Side.LEFT)) { 348 final double titleWidth = snapSizeX(titleLabel.prefWidth(height-top-bottom)); 349 titleLabel.resizeRelocate(left,top,titleWidth,height-top-bottom); 350 left += titleWidth; 351 } else if (getTitleSide().equals(Side.RIGHT)) { 352 final double titleWidth = snapSizeX(titleLabel.prefWidth(height-top-bottom)); 353 titleLabel.resizeRelocate(width-right-titleWidth,top,titleWidth,height-top-bottom); 354 right += titleWidth; 355 } 356 } else { 357 titleLabel.setVisible(false); 358 } 359 // layout legend 360 final Node legend = getLegend(); 361 if (legend != null) { 362 boolean shouldShowLegend = isLegendVisible(); 363 if (shouldShowLegend) { 364 if (getLegendSide() == Side.TOP) { 365 final double legendHeight = snapSizeY(legend.prefHeight(width-left-right)); 366 final double legendWidth = Utils.boundedSize(snapSizeX(legend.prefWidth(legendHeight)), 0, width - left - right); 367 legend.resizeRelocate(left + (((width - left - right)-legendWidth)/2), top, legendWidth, legendHeight); 368 if ((height - bottom - top - legendHeight) < MIN_HEIGHT_TO_LEAVE_FOR_CHART_CONTENT) { 369 shouldShowLegend = false; 370 } else { 371 top += legendHeight; 372 } 373 } else if (getLegendSide() == Side.BOTTOM) { 374 final double legendHeight = snapSizeY(legend.prefHeight(width-left-right)); 375 final double legendWidth = Utils.boundedSize(snapSizeX(legend.prefWidth(legendHeight)), 0, width - left - right); 376 legend.resizeRelocate(left + (((width - left - right)-legendWidth)/2), height-bottom-legendHeight, legendWidth, legendHeight); 377 if ((height - bottom - top - legendHeight) < MIN_HEIGHT_TO_LEAVE_FOR_CHART_CONTENT) { 378 shouldShowLegend = false; 379 } else { 380 bottom += legendHeight; 381 } 382 } else if (getLegendSide() == Side.LEFT) { 383 final double legendWidth = snapSizeX(legend.prefWidth(height-top-bottom)); 384 final double legendHeight = Utils.boundedSize(snapSizeY(legend.prefHeight(legendWidth)), 0, height - top - bottom); 385 legend.resizeRelocate(left,top +(((height-top-bottom)-legendHeight)/2),legendWidth,legendHeight); 386 if ((width - left - right - legendWidth) < MIN_WIDTH_TO_LEAVE_FOR_CHART_CONTENT) { 387 shouldShowLegend = false; 388 } else { 389 left += legendWidth; 390 } 391 } else if (getLegendSide() == Side.RIGHT) { 392 final double legendWidth = snapSizeX(legend.prefWidth(height-top-bottom)); 393 final double legendHeight = Utils.boundedSize(snapSizeY(legend.prefHeight(legendWidth)), 0, height - top - bottom); 394 legend.resizeRelocate(width-right-legendWidth,top +(((height-top-bottom)-legendHeight)/2),legendWidth,legendHeight); 395 if ((width - left - right - legendWidth) < MIN_WIDTH_TO_LEAVE_FOR_CHART_CONTENT) { 396 shouldShowLegend = false; 397 } else { 398 right += legendWidth; 399 } 400 } 401 } 402 legend.setVisible(shouldShowLegend); 403 } 404 // whats left is for the chart content 405 chartContent.resizeRelocate(left,top,width-left-right,height-top-bottom); 406 } 407 408 /** 409 * Charts are sized outside in, user tells chart how much space it has and chart draws inside that. So minimum 410 * height is a constant 150. 411 */ 412 @Override protected double computeMinHeight(double width) { return 150; } 413 |