001package jmri.jmrit.display.layoutEditor; 002 003import java.awt.*; 004import java.awt.geom.Line2D; 005import java.awt.geom.Point2D; 006import java.awt.geom.Rectangle2D; 007 008import javax.annotation.Nonnull; 009import javax.swing.*; 010 011import jmri.util.*; 012 013/* 014* This is an intermediate component used to put the Layout Editor 015* into the component layers hierarchy so that objects can be drawn 016* in front of or behind layout editor objects. 017* 018* @author George Warner Copyright (c) 2017-2018 019 */ 020class LayoutEditorComponent extends JComponent { 021 022 private final LayoutEditor layoutEditor; 023 024 // Antialiasing rendering 025 protected static final RenderingHints antialiasing = new RenderingHints( 026 RenderingHints.KEY_ANTIALIASING, 027 RenderingHints.VALUE_ANTIALIAS_ON); 028 029 protected LayoutEditorComponent(@Nonnull final LayoutEditor LayoutEditor) { 030 super(); 031 this.layoutEditor = LayoutEditor; 032 } 033 034 /* 035 * {@inheritDoc} 036 */ 037 @Override 038 public void paint(Graphics g) { 039 if (g instanceof Graphics2D) { 040 // layoutEditor.draw((Graphics2D) g); 041 042 Graphics2D g2 = (Graphics2D) g; 043 044 if (clipBounds != null) { 045 if (!clipBounds.isEmpty()) { 046 if ((clipBounds.getWidth() > 0) && (clipBounds.getHeight() > 0)) { 047 if (!clipBounds.equals(g2.getClipBounds())) { 048 //log.debug("LEComponent.paint(); clipBounds: {}, oldClipBounds: {}", 049 // clipBounds, g2.getClipBounds()); 050 // intersect, never replace: clipBounds is the visible part of 051 // the panel, used here to cull drawing, while the incoming clip 052 // is the area Swing actually asked for. Replacing it would draw 053 // track outside the dirty region, on top of higher level icons 054 // that are not being repainted, as the target panel is a 055 // JLayeredPane and so is not paint-optimized. 056 g2.clip(clipBounds); 057 } 058 } 059 } 060 } 061 // Optional antialising, to eliminate (reduce) staircase on diagonal lines 062 if (layoutEditor.getAntialiasingOn()) { 063 g2.setRenderingHints(antialiasing); 064 } 065 066 // drawPositionableLabelBorder(g2); 067 // things that only get drawn in edit mode 068 if (layoutEditor.isEditable()) { 069 if (layoutEditor.getDrawGrid()) { 070 drawPanelGrid(g2); 071 } 072 drawLayoutTracksHidden(g2); 073 } 074 075 drawShapes(g2, true); 076 drawTrackSegmentsDashed(g2); 077 drawLayoutTracksBallast(g2); 078 drawLayoutTracksTies(g2); 079 drawLayoutTracksRails(g2); 080 drawLayoutTracksBlockLines(g2); 081 082 drawPositionablePoints(g2, false); 083 drawPositionablePoints(g2, true); 084 085 drawShapes(g2, false); 086 087 drawDecorations(g2); 088 089 // things that only get drawn in edit mode 090 if (layoutEditor.isEditable()) { 091 drawLayoutTrackEditControls(g2); 092 drawShapeEditControls(g2); 093 094 drawMemoryRects(g2); 095 drawGlobalVariableRects(g2); 096 drawBlockContentsRects(g2); 097 098 if (layoutEditor.allControlling()) { 099 drawTurnoutControls(g2); 100 } 101 drawSelectionRect(g2); 102 highLightSelection(g2); 103 104 drawTrackSegmentInProgress(g2); 105 drawShapeInProgress(g2); 106 107 if (layoutEditor.isDrawLayoutTracksLabel()) { 108 drawLayoutTracksLabel(g2); 109 } 110 } else if (layoutEditor.getTurnoutCircles()) { 111 if (layoutEditor.allControlling()) { 112 drawTurnoutControls(g2); 113 } 114 } 115 } else { 116 log.error("LayoutEditor drawing requires Graphics2D"); 117 } 118 } 119 120 private void drawPanelGrid(Graphics2D g2) { 121 int wideMod = layoutEditor.gContext.getGridSize() * layoutEditor.gContext.getGridSize2nd(); 122 int wideMin = layoutEditor.gContext.getGridSize() / 2; 123 124 // granulize puts these on getGridSize() increments 125 int minX = 0; 126 int minY = 0; 127 int maxX = (int) MathUtil.granulize(layoutEditor.gContext.getLayoutWidth(), layoutEditor.gContext.getGridSize()); 128 int maxY = (int) MathUtil.granulize(layoutEditor.gContext.getLayoutHeight(), layoutEditor.gContext.getGridSize()); 129 130 log.debug("drawPanelGrid: minX: {}, minY: {}, maxX: {}, maxY: {}", minX, minY, maxX, maxY); 131 132 Point2D startPt, stopPt; 133 BasicStroke narrow = new BasicStroke(1.0F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 134 BasicStroke wide = new BasicStroke(2.0F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 135 136 g2.setColor(Color.gray); 137 g2.setStroke(narrow); 138 139 // draw horizontal lines 140 for (int y = minY; y <= maxY; y += layoutEditor.gContext.getGridSize()) { 141 startPt = new Point2D.Double(minX, y); 142 stopPt = new Point2D.Double(maxX, y); 143 144 if ((y % wideMod) < wideMin) { 145 g2.setStroke(wide); 146 g2.draw(new Line2D.Double(startPt, stopPt)); 147 g2.setStroke(narrow); 148 } else { 149 g2.draw(new Line2D.Double(startPt, stopPt)); 150 } 151 } 152 153 // draw vertical lines 154 for (int x = minX; x <= maxX; x += layoutEditor.gContext.getGridSize()) { 155 startPt = new Point2D.Double(x, minY); 156 stopPt = new Point2D.Double(x, maxY); 157 158 if ((x % wideMod) < wideMin) { 159 g2.setStroke(wide); 160 g2.draw(new Line2D.Double(startPt, stopPt)); 161 g2.setStroke(narrow); 162 } else { 163 g2.draw(new Line2D.Double(startPt, stopPt)); 164 } 165 } 166 } 167 168 // 169 // draw hidden layout tracks 170 // 171 private void drawLayoutTracksHidden(Graphics2D g2) { 172 LayoutTrackDrawingOptions ltdo = layoutEditor.getLayoutTrackDrawingOptions(); 173 Stroke stroke = new BasicStroke(1.F); 174 Stroke dashedStroke = new BasicStroke(1.F, 175 BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10.F, 176 new float[]{6.F, 4.F}, 0); 177 178 // setup for drawing hidden sideline rails 179 g2.setColor(ltdo.getSideRailColor()); 180 g2.setStroke(stroke); 181 boolean main = false, block = false, hidden = true, dashed = false; 182 draw1(g2, main, block, hidden, dashed); 183 g2.setStroke(dashedStroke); 184 draw1(g2, main, block, hidden, dashed = true); 185 186 // setup for drawing mainline rails 187 main = true; 188 g2.setColor(ltdo.getMainRailColor()); 189 g2.setStroke(stroke); 190 draw1(g2, main, block, hidden, dashed = false); 191 g2.setStroke(dashedStroke); 192 dashed = true; 193 draw1(g2, main, block, hidden, dashed); 194 } 195 196 // 197 // draw dashed track segments 198 // 199 private void drawTrackSegmentsDashed(Graphics2D g2) { 200 LayoutTrackDrawingOptions ltdo = layoutEditor.getLayoutTrackDrawingOptions(); 201 boolean main = false, block = false, hidden = false, dashed = true; 202 203 if (ltdo.getSideRailCount() > 0) { 204 // setup for drawing dashed sideline rails 205 int railWidth = ltdo.getSideRailWidth(); 206 float[] dashArray = new float[]{6.F + railWidth, 4.F + railWidth}; 207 g2.setStroke(new BasicStroke( 208 railWidth, 209 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 210 10.F, dashArray, 0)); 211 g2.setColor(ltdo.getSideRailColor()); 212 if ((ltdo.getSideRailCount() & 1) == 1) { 213 draw1(g2, main, block, hidden, dashed); 214 } 215 if (ltdo.getSideRailCount() >= 2) { 216 float railDisplacement = railWidth + (ltdo.getSideRailGap() / 2.F); 217 draw2(g2, main, railDisplacement, dashed); 218 } 219 } 220 221 if (ltdo.getMainRailCount() > 0) { 222 // setup for drawing dashed mainline rails 223 main = true; 224 int railWidth = ltdo.getMainRailWidth(); 225 float[] dashArray = new float[]{6.F + railWidth, 4.F + railWidth}; 226 g2.setStroke(new BasicStroke( 227 railWidth, 228 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 229 10.F, dashArray, 0)); 230 g2.setColor(ltdo.getMainRailColor()); 231 if ((ltdo.getMainRailCount() & 1) == 1) { 232 draw1(g2, main, block, hidden, dashed); 233 } 234 if (ltdo.getMainRailCount() >= 2) { 235 float railDisplacement = railWidth + (ltdo.getSideRailGap() / 2.F); 236 draw2(g2, main, railDisplacement, dashed); 237 } 238 } 239 } // drawTrackSegmentsDashed 240 241 // 242 // draw layout track ballast 243 // 244 private void drawLayoutTracksBallast(Graphics2D g2) { 245 LayoutTrackDrawingOptions ltdo = layoutEditor.getLayoutTrackDrawingOptions(); 246 boolean main = false, block = false, hidden = false, dashed = false; 247 248 // setup for drawing sideline ballast 249 int ballastWidth = ltdo.getSideBallastWidth(); 250 if (ballastWidth > 0) { 251 g2.setStroke(new BasicStroke(ballastWidth, 252 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 253 g2.setColor(ltdo.getSideBallastColor()); 254 draw1(g2, main, block, hidden, dashed); 255 } 256 257 // setup for drawing mainline ballast 258 ballastWidth = ltdo.getMainBallastWidth(); 259 if (ballastWidth > 0) { 260 g2.setStroke(new BasicStroke(ballastWidth, 261 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 262 g2.setColor(ltdo.getMainBallastColor()); 263 main = true; 264 draw1(g2, main, block, hidden, dashed); 265 } 266 } 267 268 // 269 // draw layout track ties 270 // 271 private void drawLayoutTracksTies(Graphics2D g2) { 272 LayoutTrackDrawingOptions ltdo = layoutEditor.getLayoutTrackDrawingOptions(); 273 274 // setup for drawing sideline ties 275 int tieLength = ltdo.getSideTieLength(); 276 int tieWidth = ltdo.getSideTieWidth(); 277 int tieGap = ltdo.getSideTieGap(); 278 if ((tieLength > 0) && (tieWidth > 0) && (tieGap > 0)) { 279 g2.setStroke(new BasicStroke(tieLength, 280 BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10.F, 281 new float[]{tieWidth, tieGap}, 0)); 282 g2.setColor(ltdo.getSideTieColor()); 283 draw1(g2, false); // main = false 284 } 285 286 // setup for drawing mainline ties 287 tieLength = ltdo.getMainTieLength(); 288 tieWidth = ltdo.getMainTieWidth(); 289 tieGap = ltdo.getMainTieGap(); 290 if ((tieLength > 0) && (tieWidth > 0) && (tieGap > 0)) { 291 g2.setStroke(new BasicStroke(tieLength, 292 BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10.F, 293 new float[]{tieWidth, tieGap}, 0)); 294 g2.setColor(ltdo.getMainTieColor()); 295 draw1(g2, true); // main = true 296 } 297 } 298 299 // 300 // draw layout track rails 301 // 302 private void drawLayoutTracksRails(Graphics2D g2) { 303 LayoutTrackDrawingOptions ltdo = layoutEditor.getLayoutTrackDrawingOptions(); 304 int railWidth = ltdo.getSideRailWidth(); 305 Color railColor = ltdo.getSideRailColor(); 306 307 boolean main = false, block = false, hidden = false, dashed = false; 308 309 if (ltdo.getSideRailCount() > 1) { 310 // setup for drawing sideline rails 311 float railDisplacement = railWidth + (ltdo.getSideRailGap() / 2.F); 312 g2.setStroke(new BasicStroke(railWidth, 313 BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 314 g2.setColor(railColor); 315 draw2(g2, main, railDisplacement); 316 } 317 318 if ((ltdo.getSideRailCount() & 1) == 1) { 319 // setup for drawing sideline rails 320 g2.setStroke(new BasicStroke( 321 railWidth, 322 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 323 g2.setColor(railColor); 324 draw1(g2, main, block, hidden, dashed); 325 } 326 327 main = true; 328 329 railWidth = ltdo.getMainRailWidth(); 330 railColor = ltdo.getMainRailColor(); 331 if (ltdo.getMainRailCount() > 1) { 332 // setup for drawing mainline rails 333 float railDisplacement = railWidth + (ltdo.getMainRailGap() / 2.F); 334 g2.setStroke(new BasicStroke(railWidth, 335 BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 336 g2.setColor(railColor); 337 draw2(g2, main, railDisplacement); 338 } 339 if ((ltdo.getMainRailCount() & 1) == 1) { 340 // setup for drawing mainline rails 341 g2.setStroke(new BasicStroke( 342 railWidth, 343 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 344 g2.setColor(railColor); 345 dashed = false; 346 draw1(g2, main, block, hidden, dashed); 347 } 348 } // drawLayoutTracksRails 349 350 // 351 // draw layout track block lines 352 // 353 private void drawLayoutTracksBlockLines(Graphics2D g2) { 354 LayoutTrackDrawingOptions ltdo = layoutEditor.getLayoutTrackDrawingOptions(); 355 356 // setup for drawing sideline block lines 357 int blockLineWidth = ltdo.getSideBlockLineWidth(); 358 float[] dashArray = new float[]{6.F + blockLineWidth, 4.F + blockLineWidth}; 359 360 Stroke blockLineStroke; 361 int dashPercentageX10 = ltdo.getSideBlockLineDashPercentageX10(); 362 if (dashPercentageX10 > 0) { 363 float[] blockLineDashArray = new float[]{ 364 dashPercentageX10 + blockLineWidth, 365 10.F - dashPercentageX10 + blockLineWidth}; 366 blockLineStroke = new BasicStroke( 367 blockLineWidth, 368 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 369 10.F, blockLineDashArray, 0); 370 g2.setStroke(blockLineStroke); 371 } else { 372 blockLineStroke = new BasicStroke( 373 blockLineWidth, 374 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 375 g2.setStroke(new BasicStroke( 376 blockLineWidth, 377 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 378 10.F, dashArray, 0)); 379 } 380 381 // note: color is set in layout track's draw1 when isBlock is true 382 boolean main = false, block = true, hidden = false, dashed = true; 383 draw1(g2, main, block, hidden, dashed); 384 g2.setStroke(blockLineStroke); 385 draw1(g2, main, block, hidden, dashed = false); 386 387 // setup for drawing mainline block lines 388 blockLineWidth = ltdo.getMainBlockLineWidth(); 389 dashArray = new float[]{6.F + blockLineWidth, 4.F + blockLineWidth}; 390 391 dashPercentageX10 = ltdo.getMainBlockLineDashPercentageX10(); 392 if (dashPercentageX10 > 0) { 393 float[] blockLineDashArray = new float[]{ 394 dashPercentageX10 + blockLineWidth, 395 10 - dashPercentageX10 + blockLineWidth}; 396 blockLineStroke = new BasicStroke( 397 blockLineWidth, 398 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 399 10.F, blockLineDashArray, 0); 400 g2.setStroke(blockLineStroke); 401 } else { 402 blockLineStroke = new BasicStroke( 403 blockLineWidth, 404 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); 405 g2.setStroke(new BasicStroke( 406 blockLineWidth, 407 BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 408 10.F, dashArray, 0)); 409 } 410 // note: color is set in layout track's draw1 when isBlock is true 411 draw1(g2, main = true, block, hidden, dashed = true); 412 g2.setStroke(blockLineStroke); 413 dashed = false; 414 draw1(g2, main, block, hidden, dashed); 415 } 416 417 // isDashed defaults to false 418 private void draw1(Graphics2D g2, 419 boolean isMain, 420 boolean isBlock, 421 boolean isHidden) { 422 draw1(g2, isMain, isBlock, isHidden, false); 423 } 424 425 // isHidden defaults to false 426 private void draw1(Graphics2D g2, 427 boolean isMain, 428 boolean isBlock) { 429 draw1(g2, isMain, isBlock, false); 430 } 431 432 // isBlock defaults to false 433 private void draw1(Graphics2D g2, boolean isMain) { 434 draw1(g2, isMain, false); 435 } 436 437 // draw single line (ballast, ties & block lines) 438 private void draw1(Graphics2D g2, 439 boolean isMain, 440 boolean isBlock, 441 boolean isHidden, 442 boolean isDashed) { 443 for (LayoutTrackView layoutTrackView : layoutEditor.getLayoutTrackViews()) { 444 if (!(layoutTrackView instanceof PositionablePointView)) { 445 if (isHidden == layoutTrackView.isHidden()) { 446 if ((layoutTrackView instanceof TrackSegmentView)) { 447 if (((TrackSegmentView) layoutTrackView).isDashed() == isDashed) { 448 layoutTrackView.draw1(g2, isMain, isBlock); 449 } 450 } else if (!isDashed) { 451 layoutTrackView.draw1(g2, isMain, isBlock); 452 } 453 } 454 } 455 } 456 } 457 458 // draw positionable points 459 private void drawPositionablePoints(Graphics2D g2, boolean isMain) { 460 for (PositionablePointView positionablePointView : layoutEditor.getPositionablePointViews()) { 461 positionablePointView.draw1(g2, isMain, false); 462 } 463 } 464 465 // isDashed defaults to false 466 private void draw2(Graphics2D g2, boolean isMain, float railDisplacement) { 467 draw2(g2, isMain, railDisplacement, false); 468 } 469 470 // draw parallel lines (rails) 471 private void draw2(Graphics2D g2, boolean isMain, 472 float railDisplacement, boolean isDashed) { 473 for (LayoutTrackView layoutTrackView : layoutEditor.getLayoutTrackViews()) { 474 if ((layoutTrackView instanceof TrackSegmentView)) { 475 if (((TrackSegmentView) layoutTrackView).isDashed() == isDashed) { 476 layoutTrackView.draw2(g2, isMain, railDisplacement); 477 } 478 } else if (!isDashed) { 479 layoutTrackView.draw2(g2, isMain, railDisplacement); 480 } 481 } 482 } 483 484 // draw decorations 485 private void drawDecorations(Graphics2D g2) { 486 layoutEditor.getLayoutTrackViews().forEach((tr) -> tr.drawDecorations(g2)); 487 } 488 489 // draw shapes 490 private void drawShapes(Graphics2D g2, boolean isBackground) { 491 layoutEditor.getLayoutShapes().forEach((s) -> { 492 if (isBackground == (s.getLevel() < 3)) { 493 s.draw(g2); 494 } 495 }); 496 } 497 498 // draw track segment (in progress) 499 private void drawTrackSegmentInProgress(Graphics2D g2) { 500 // check for segment in progress 501 if (layoutEditor.isEditable() && (layoutEditor.beginTrack != null) && layoutEditor.getLayoutEditorToolBarPanel().trackButton.isSelected()) { 502 g2.setColor(layoutEditor.defaultTrackColor); 503 g2.setStroke(new BasicStroke(layoutEditor.gContext.getSidelineTrackWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 504 g2.draw(new Line2D.Double(layoutEditor.beginLocation, layoutEditor.currentLocation)); 505 506 // highlight unconnected endpoints of all tracks 507 Color highlightColor = ColorUtil.setAlpha(Color.red, 0.25); 508 Color connectColor = ColorUtil.setAlpha(Color.green, 0.5); 509 g2.setColor(highlightColor); 510 g2.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 511 for (LayoutTrack lt : layoutEditor.getLayoutTracks()) { 512 if (lt != layoutEditor.beginTrack) { 513 LayoutTrackView ltv = layoutEditor.getLayoutTrackView(lt); 514 if (lt == layoutEditor.foundTrack) { 515 ltv.highlightUnconnected(g2); 516 g2.setColor(connectColor); 517 ltv.highlightUnconnected(g2, layoutEditor.foundHitPointType); 518 g2.setColor(highlightColor); 519 } else { 520 ltv.highlightUnconnected(g2); 521 } 522 } 523 } 524 } 525 } 526 527 // draw shape (in progress) 528 private void drawShapeInProgress(Graphics2D g2) { 529 // check for segment in progress 530 if (layoutEditor.getLayoutEditorToolBarPanel().shapeButton.isSelected()) { 531 // log.warn("drawShapeInProgress: selectedObject: " + selectedObject); 532 if ((layoutEditor.selectedObject != null)) { 533 g2.setColor(Color.DARK_GRAY); 534 g2.setStroke(new BasicStroke(3.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 535 g2.draw(new Line2D.Double(layoutEditor.beginLocation, layoutEditor.currentLocation)); 536 } 537 } 538 } 539 540 // draw layout track edit controls 541 private void drawLayoutTrackEditControls(Graphics2D g2) { 542 g2.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 543 544 layoutEditor.getLayoutTrackViews().forEach((tr) -> tr.drawEditControls(g2)); 545 } 546 547 private void drawShapeEditControls(Graphics2D g2) { 548 g2.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 549 layoutEditor.getLayoutShapes().forEach((s) -> s.drawEditControls(g2)); 550 } 551 552 // draw layout turnout controls 553 private void drawTurnoutControls(Graphics2D g2) { 554 g2.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 555 g2.setColor(layoutEditor.turnoutCircleColor); 556 g2.setBackground(layoutEditor.turnoutCircleThrownColor); 557 558 // loop over all turnouts 559 boolean editable = layoutEditor.isEditable(); 560 layoutEditor.getLayoutTrackViews().forEach((tr) -> { 561 if (tr instanceof LayoutTurnoutView) { //<== this includes LayoutSlips 562 LayoutTurnoutView lt = (LayoutTurnoutView) tr; 563 if (editable || !(lt.isHidden() || lt.isDisabled())) { 564 lt.drawTurnoutControls(g2); 565 } 566 } else if (tr instanceof LayoutTurntableView) { 567 LayoutTurntableView lt = (LayoutTurntableView) tr; 568 if (editable || !lt.isHidden()) { 569 lt.drawTurnoutControls(g2); 570 } 571 }else if (tr instanceof LayoutTraverserView) { 572 LayoutTraverserView lt = (LayoutTraverserView) tr; 573 if (editable || !lt.isHidden()) { 574 lt.drawTurnoutControls(g2); 575 } 576 } 577 }); 578 579 } 580 581 private void drawSelectionRect(Graphics2D g2) { 582 if (layoutEditor.selectionActive && (layoutEditor.selectionWidth != 0.0) && (layoutEditor.selectionHeight != 0.0)) { 583 // The Editor super class draws a dashed red selection rectangle... 584 // We're going to also draw a non-dashed yellow selection rectangle... 585 // This could be code stripped if the super-class implementation is "good enough" 586 Stroke stroke = g2.getStroke(); 587 Color color = g2.getColor(); 588 589 g2.setColor(new Color(204, 207, 88)); 590 g2.setStroke(new BasicStroke(3.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 591 592 g2.draw(layoutEditor.getSelectionRect()); // this sets _selectRect also 593 594 g2.setColor(color); 595 g2.setStroke(stroke); 596 } else { 597 layoutEditor.setSelectRect(null); // and clear it to turn it off 598 } 599 } 600 601 private void drawMemoryRects(Graphics2D g2) { 602 g2.setColor(layoutEditor.defaultTrackColor); 603 g2.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 604 605 layoutEditor.getMemoryLabelList().forEach((l) -> g2.draw(new Rectangle2D.Double(l.getX(), l.getY(), l.getSize().width, l.getSize().height))); 606 } 607 608 private void drawGlobalVariableRects(Graphics2D g2) { 609 g2.setColor(layoutEditor.defaultTrackColor); 610 g2.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 611 612 layoutEditor.getGlobalVariableLabelList().forEach((l) -> g2.draw(new Rectangle2D.Double(l.getX(), l.getY(), l.getSize().width, l.getSize().height))); 613 } 614 615 private void drawBlockContentsRects(Graphics2D g2) { 616 g2.setColor(layoutEditor.defaultTrackColor); 617 g2.setStroke(new BasicStroke(1.0F, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); 618 619 layoutEditor.getBlockContentsLabelList().forEach((l) -> g2.draw(new Rectangle2D.Double(l.getX(), l.getY(), l.getSize().width, l.getSize().height))); 620 } 621 622 private void highLightSelection(Graphics2D g) { 623 Stroke stroke = g.getStroke(); 624 Color color = g.getColor(); 625 g.setColor(new Color(204, 207, 88)); 626 g.setStroke(new BasicStroke(2.0f)); 627 628 layoutEditor.getPositionalSelection().forEach((c) -> g.drawRect(c.getX(), c.getY(), c.maxWidth(), c.maxHeight())); 629 630 layoutEditor._layoutTrackSelection.stream().map((lt) -> { 631 LayoutTrackView ltv = layoutEditor.getLayoutTrackView(lt); 632 Rectangle2D r = ltv.getBounds(); 633 if (r.isEmpty()) { 634 r = MathUtil.inset(r, -4.0); 635 } 636 //r = MathUtil.centerRectangleOnPoint(r, ltv.getCoordsCenter()); 637 return r; 638 }).forEachOrdered(g::draw); 639 640 layoutEditor._layoutShapeSelection.stream().map((ls) -> { 641 Rectangle2D r = ls.getBounds(); 642 if (r.isEmpty()) { 643 r = MathUtil.inset(r, -4.0); 644 } 645 //r = MathUtil.centerRectangleOnPoint(r, ls.getCoordsCenter()); 646 return r; 647 }).forEachOrdered(g::draw); 648 649 g.setColor(color); 650 g.setStroke(stroke); 651 } 652 653 private void drawLayoutTracksLabel(Graphics2D g) { 654 g.setFont(new Font(Font.MONOSPACED, Font.BOLD, 12)); 655 g.setColor(Color.red); 656 for (LayoutTrackView layoutTrackView : layoutEditor.getLayoutTrackViews()) { 657 layoutTrackView.drawLayoutTrackText(g); 658 } 659 } 660 661 /* 662 * {@inheritDoc} 663 */ 664 @Override 665 public Rectangle getBounds() { 666 JComponent targetPanel = layoutEditor.getTargetPanel(); 667 Rectangle2D targetBounds = targetPanel.getBounds(); 668 Container parent = getParent(); 669 if (parent != null) { // if there is a parent... 670 Rectangle2D parentBounds = parent.getBounds(); 671 672 // convert our origin to parent coordinates 673 Point2D origin = new Point2D.Double( 674 targetBounds.getX() - parentBounds.getX(), 675 targetBounds.getY() - parentBounds.getY()); 676 677 return new Rectangle((int) origin.getX(), (int) origin.getY(), 678 (int) targetBounds.getWidth(), (int) targetBounds.getHeight()); 679 } else { 680 return MathUtil.rectangle2DToRectangle(targetBounds); 681 } 682 } 683 684 /* 685 * {@inheritDoc} 686 */ 687 @Override 688 public Rectangle getBounds(Rectangle rv) { 689 rv.setBounds(getBounds()); 690 return rv; 691 } 692 693 /* 694 * {@inheritDoc} 695 */ 696 @Override 697 public int getX() { 698 Rectangle bounds = getBounds(); 699 return (int) bounds.getX(); 700 } 701 702 /* 703 * {@inheritDoc} 704 */ 705 @Override 706 public int getY() { 707 Rectangle bounds = getBounds(); 708 return (int) bounds.getY(); 709 } 710 711 /* 712 * {@inheritDoc} 713 */ 714 @Override 715 public int getWidth() { 716 Rectangle bounds = getBounds(); 717 return (int) bounds.getWidth(); 718 } 719 720 /* 721 * {@inheritDoc} 722 */ 723 @Override 724 public int getHeight() { 725 Rectangle bounds = getBounds(); 726 return (int) bounds.getHeight(); 727 } 728 729 private Rectangle2D clipBounds = null; 730 731 public void setClip(Rectangle2D clipBounds) { 732 this.clipBounds = clipBounds; 733 } 734 735 // initialize logging 736 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LayoutEditorComponent.class); 737}