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