001package jmri.jmrit.display; 002 003import java.awt.*; 004import java.awt.datatransfer.DataFlavor; 005import java.awt.event.*; 006import java.awt.geom.Rectangle2D; 007import java.beans.PropertyChangeEvent; 008import java.beans.PropertyVetoException; 009import java.beans.VetoableChangeListener; 010import java.lang.reflect.InvocationTargetException; 011import java.text.MessageFormat; 012import java.util.*; 013import java.util.List; 014 015import javax.annotation.Nonnull; 016import javax.swing.*; 017import javax.swing.Timer; 018import javax.swing.border.Border; 019import javax.swing.border.CompoundBorder; 020import javax.swing.border.LineBorder; 021import javax.swing.event.ListSelectionEvent; 022 023import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 024 025import jmri.*; 026import jmri.jmrit.catalog.CatalogPanel; 027import jmri.jmrit.catalog.DirectorySearcher; 028import jmri.jmrit.catalog.ImageIndexEditor; 029import jmri.jmrit.catalog.NamedIcon; 030import jmri.jmrit.display.controlPanelEditor.shape.PositionableShape; 031import jmri.jmrit.logixng.*; 032import jmri.jmrit.logixng.tools.swing.DeleteBean; 033import jmri.jmrit.logixng.tools.swing.LogixNGEditor; 034import jmri.jmrit.operations.trains.TrainIcon; 035import jmri.jmrit.picker.PickListModel; 036import jmri.jmrit.roster.Roster; 037import jmri.jmrit.roster.RosterEntry; 038import jmri.jmrit.roster.swing.RosterEntrySelectorPanel; 039import jmri.util.DnDStringImportHandler; 040import jmri.util.JmriJFrame; 041import jmri.util.ThreadingUtil; 042import jmri.util.swing.JmriColorChooser; 043import jmri.util.swing.JmriJOptionPane; 044import jmri.util.swing.JmriMouseEvent; 045import jmri.util.swing.JmriMouseListener; 046import jmri.util.swing.JmriMouseMotionListener; 047 048/** 049 * This is the Model and a Controller for panel editor Views. (Panel Editor, 050 * Layout Editor or any subsequent editors) The Model is simply a list of 051 * Positionable objects added to a "target panel". Control of the display 052 * attributes of the Positionable objects is done here. However, control of 053 * mouse events is passed to the editor views, so control is also done by the 054 * editor views. 055 * <p> 056 * The "contents" List keeps track of all the objects added to the target frame 057 * for later manipulation. This class only locates and moves "target panel" 058 * items, and does not control their appearance - that is left for the editor 059 * views. 060 * <p> 061 * The Editor has tri-state "flags" to control the display of Positionable 062 * object attributes globally - i.e. "on" or "off" for all - or as a third 063 * state, permits the display control "locally" by corresponding flags in each 064 * Positionable object 065 * <p> 066 * The title of the target and the editor panel are kept consistent via the 067 * {#setTitle} method. 068 * <p> 069 * Mouse events are initial handled here, rather than in the individual 070 * displayed objects, so that selection boxes for moving multiple objects can be 071 * provided. 072 * <p> 073 * This class also implements an effective ToolTipManager replacement, because 074 * the standard Swing one can't deal with the coordinate changes used to zoom a 075 * panel. It works by controlling the contents of the _tooltip instance 076 * variable, and triggering repaint of the target window when the tooltip 077 * changes. The window painting then explicitly draws the tooltip for the 078 * underlying object. 079 * 080 * @author Bob Jacobsen Copyright: Copyright (c) 2002, 2003, 2007 081 * @author Dennis Miller 2004 082 * @author Howard G. Penny Copyright: Copyright (c) 2005 083 * @author Matthew Harris Copyright: Copyright (c) 2009 084 * @author Pete Cressman Copyright: Copyright (c) 2009, 2010, 2011 085 * 086 */ 087public abstract class Editor extends JmriJFrameWithPermissions 088 implements JmriMouseListener, JmriMouseMotionListener, ActionListener, 089 KeyListener, VetoableChangeListener { 090 091 public static final int BKG = 1; 092 public static final int TEMP = 2; 093 public static final int ICONS = 3; 094 public static final int LABELS = 4; 095 public static final int MEMORIES = 5; 096 public static final int REPORTERS = 5; 097 public static final int SECURITY = 6; 098 public static final int TURNOUTS = 7; 099 public static final int LIGHTS = 8; 100 public static final int SIGNALS = 9; 101 public static final int SENSORS = 10; 102 public static final int CLOCK = 10; 103 public static final int MARKERS = 10; 104 public static final int NUM_LEVELS = 10; 105 106 public static final int SCROLL_NONE = 0; 107 public static final int SCROLL_BOTH = 1; 108 public static final int SCROLL_HORIZONTAL = 2; 109 public static final int SCROLL_VERTICAL = 3; 110 111 public static final Color HIGHLIGHT_COLOR = new Color(204, 207, 88); 112 113 public static final String POSITIONABLE_FLAVOR = DataFlavor.javaJVMLocalObjectMimeType 114 + ";class=jmri.jmrit.display.Positionable"; 115 116 private boolean _loadFailed = false; 117 118 private ArrayList<Positionable> _contents = new ArrayList<>(); 119 private Map<String, Positionable> _idContents = new HashMap<>(); 120 private Map<String, Set<Positionable>> _classContents = new HashMap<>(); 121 protected JLayeredPane _targetPanel; 122 private JFrame _targetFrame; 123 private JScrollPane _panelScrollPane; 124 125 // Option menu items 126 protected int _scrollState = SCROLL_NONE; 127 protected boolean _editable = true; 128 private boolean _positionable = true; 129 private boolean _controlLayout = true; 130 private boolean _showHidden = true; 131 private boolean _showToolTip = true; 132// private boolean _showCoordinates = true; 133 134 final public static int OPTION_POSITION = 1; 135 final public static int OPTION_CONTROLS = 2; 136 final public static int OPTION_HIDDEN = 3; 137 final public static int OPTION_TOOLTIP = 4; 138// final public static int OPTION_COORDS = 5; 139 140 private boolean _globalSetsLocal = true; // pre 2.9.6 behavior 141 private boolean _useGlobalFlag = false; // pre 2.9.6 behavior 142 143 // mouse methods variables 144 protected int _lastX; 145 protected int _lastY; 146 BasicStroke DASHED_LINE = new BasicStroke(1f, BasicStroke.CAP_BUTT, 147 BasicStroke.JOIN_BEVEL, 148 10f, new float[]{10f, 10f}, 0f); 149 150 protected Rectangle _selectRect = null; 151 protected Rectangle _highlightcomponent = null; 152 protected boolean _dragging = false; 153 protected ArrayList<Positionable> _selectionGroup = null; // items gathered inside fence 154 155 protected Positionable _currentSelection; 156 private ToolTip _defaultToolTip; 157 private ToolTip _tooltip = null; 158 159 // Accessible to editor views 160 protected int xLoc = 0; // x coord of selected Positionable 161 protected int yLoc = 0; // y coord of selected Positionable 162 protected int _anchorX; // x coord when mousePressed 163 protected int _anchorY; // y coord when mousePressed 164 165// private boolean delayedPopupTrigger = false; // Used to delay the request of a popup, on a mouse press as this may conflict with a drag event 166 protected double _paintScale = 1.0; // scale for _targetPanel drawing 167 168 protected Color defaultBackgroundColor = Color.lightGray; 169 protected boolean _pastePending = false; 170 171 // map of icon editor frames (incl, icon editor) keyed by name 172 protected HashMap<String, JFrameItem> _iconEditorFrame = new HashMap<>(); 173 174 // store panelMenu state so preference is retained on headless systems 175 private boolean panelMenuIsVisible = true; 176 177 private boolean _inEditInlineLogixNGMode = false; 178 private LogixNGEditor _inlineLogixNGEdit; 179 180 public Editor() { 181 } 182 183 public Editor(String name, boolean saveSize, boolean savePosition) { 184 super(name, saveSize, savePosition); 185 setName(name); 186 _defaultToolTip = new ToolTip(null, 0, 0, null); 187 setVisible(false); 188 InstanceManager.getDefault(SignalHeadManager.class).addVetoableChangeListener(this); 189 InstanceManager.getDefault(SignalMastManager.class).addVetoableChangeListener(this); 190 InstanceManager.turnoutManagerInstance().addVetoableChangeListener(this); 191 InstanceManager.sensorManagerInstance().addVetoableChangeListener(this); 192 InstanceManager.memoryManagerInstance().addVetoableChangeListener(this); 193 InstanceManager.getDefault(BlockManager.class).addVetoableChangeListener(this); 194 InstanceManager.getDefault(EditorManager.class).add(this); 195 } 196 197 public Editor(String name) { 198 this(name, true, true); 199 } 200 201 /** 202 * Set <strong>white</strong> as the default background color for panels created using the <strong>New Panel</strong> menu item. 203 * Overriden by LE to use a different default background color and set other initial defaults. 204 */ 205 public void newPanelDefaults() { 206 setBackgroundColor(Color.WHITE); 207 } 208 209 public void loadFailed() { 210 _loadFailed = true; 211 } 212 213 NamedIcon _newIcon; 214 boolean _ignore = false; 215 boolean _delete; 216 HashMap<String, String> _urlMap = new HashMap<>(); 217 218 public NamedIcon loadFailed(String msg, String url) { 219 log.debug("loadFailed _ignore= {} {}", _ignore, msg); 220 if (_urlMap == null) { 221 _urlMap = new HashMap<>(); 222 } 223 String goodUrl = _urlMap.get(url); 224 if (goodUrl != null) { 225 return NamedIcon.getIconByName(goodUrl); 226 } 227 if (_ignore) { 228 _loadFailed = true; 229 return NamedIcon.getIconByName(url); 230 } 231 _newIcon = null; 232 _delete = false; 233 (new UrlErrorDialog(msg, url)).setVisible(true); 234 235 if (_delete) { 236 return null; 237 } 238 if (_newIcon == null) { 239 _loadFailed = true; 240 _newIcon = NamedIcon.getIconByName(url); 241 } 242 return _newIcon; 243 } 244 245 public class UrlErrorDialog extends JDialog { 246 247 private final JTextField _urlField; 248 private final CatalogPanel _catalog; 249 private final String _badUrl; 250 251 UrlErrorDialog(String msg, String url) { 252 super(_targetFrame, Bundle.getMessage("BadIcon"), true); 253 _badUrl = url; 254 JPanel content = new JPanel(); 255 JPanel panel = new JPanel(); 256 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 257 panel.add(Box.createVerticalStrut(10)); 258 panel.add(new JLabel(MessageFormat.format(Bundle.getMessage("IconUrlError"), msg))); 259 panel.add(new JLabel(Bundle.getMessage("UrlErrorPrompt1"))); 260 panel.add(new JLabel(Bundle.getMessage("UrlErrorPrompt1A"))); 261 panel.add(new JLabel(Bundle.getMessage("UrlErrorPrompt1B"))); 262 panel.add(Box.createVerticalStrut(10)); 263 panel.add(new JLabel(Bundle.getMessage("UrlErrorPrompt2", Bundle.getMessage("ButtonContinue")))); 264 panel.add(new JLabel(Bundle.getMessage("UrlErrorPrompt3", Bundle.getMessage("ButtonDelete")))); 265 panel.add(new JLabel(Bundle.getMessage("UrlErrorPrompt3A"))); 266 panel.add(Box.createVerticalStrut(10)); 267 panel.add(new JLabel(Bundle.getMessage("UrlErrorPrompt4", Bundle.getMessage("ButtonIgnore")))); 268 panel.add(Box.createVerticalStrut(10)); 269 _urlField = new JTextField(url); 270 _urlField.setDragEnabled(true); 271 _urlField.setTransferHandler(new DnDStringImportHandler()); 272 panel.add(_urlField); 273 panel.add(makeDoneButtonPanel()); 274 _urlField.setToolTipText(Bundle.getMessage("TooltipFixUrl")); 275 panel.setToolTipText(Bundle.getMessage("TooltipFixUrl")); 276 _catalog = CatalogPanel.makeDefaultCatalog(); 277 _catalog.setToolTipText(Bundle.getMessage("ToolTipDragIconToText")); 278 panel.add(_catalog); 279 content.add(panel); 280 setContentPane(content); 281 setLocation(200, 100); 282 pack(); 283 } 284 285 private JPanel makeDoneButtonPanel() { 286 JPanel result = new JPanel(); 287 result.setLayout(new FlowLayout()); 288 JButton doneButton = new JButton(Bundle.getMessage("ButtonContinue")); 289 doneButton.addActionListener(a -> { 290 _newIcon = NamedIcon.getIconByName(_urlField.getText()); 291 if (_newIcon != null) { 292 _urlMap.put(_badUrl, _urlField.getText()); 293 } 294 UrlErrorDialog.this.dispose(); 295 }); 296 doneButton.setToolTipText(Bundle.getMessage("TooltipContinue")); 297 result.add(doneButton); 298 299 JButton deleteButton = new JButton(Bundle.getMessage("ButtonDelete")); 300 deleteButton.addActionListener(a -> { 301 _delete = true; 302 UrlErrorDialog.this.dispose(); 303 }); 304 result.add(deleteButton); 305 deleteButton.setToolTipText(Bundle.getMessage("TooltipDelete")); 306 307 JButton cancelButton = new JButton(Bundle.getMessage("ButtonIgnore")); 308 cancelButton.addActionListener(a -> { 309 _ignore = true; 310 UrlErrorDialog.this.dispose(); 311 }); 312 result.add(cancelButton); 313 cancelButton.setToolTipText(Bundle.getMessage("TooltipIgnore")); 314 return result; 315 } 316 } 317 318 public void disposeLoadData() { 319 _urlMap = null; 320 } 321 322 public boolean loadOK() { 323 return !_loadFailed; 324 } 325 326 public List<Positionable> getContents() { 327 return Collections.unmodifiableList(_contents); 328 } 329 330 public Map<String, Positionable> getIdContents() { 331 return Collections.unmodifiableMap(_idContents); 332 } 333 334 public Set<String> getClassNames() { 335 return Collections.unmodifiableSet(_classContents.keySet()); 336 } 337 338 public Set<Positionable> getPositionablesByClassName(String className) { 339 Set<Positionable> set = _classContents.get(className); 340 if (set == null) { 341 return null; 342 } 343 return Collections.unmodifiableSet(set); 344 } 345 346 public void setDefaultToolTip(ToolTip dtt) { 347 _defaultToolTip = dtt; 348 } 349 350 // 351 // *************** setting the main panel and frame *************** 352 // 353 /** 354 * Set the target panel. 355 * <p> 356 * An Editor may or may not choose to use 'this' as its frame or the 357 * interior class 'TargetPane' for its targetPanel. 358 * 359 * @param targetPanel the panel to be edited 360 * @param frame the frame to embed the panel in 361 */ 362 protected void setTargetPanel(JLayeredPane targetPanel, JmriJFrame frame) { 363 if (targetPanel == null) { 364 _targetPanel = new TargetPane(); 365 } else { 366 _targetPanel = targetPanel; 367 } 368 // If on a headless system, set heavyweight components to null 369 // and don't attach mouse and keyboard listeners to the panel 370 if (GraphicsEnvironment.isHeadless()) { 371 _panelScrollPane = null; 372 _targetFrame = null; 373 return; 374 } 375 if (frame == null) { 376 _targetFrame = this; 377 } else { 378 _targetFrame = frame; 379 } 380 _targetFrame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); 381 _panelScrollPane = new JScrollPane(_targetPanel); 382 Container contentPane = _targetFrame.getContentPane(); 383 contentPane.add(_panelScrollPane); 384 _targetFrame.addWindowListener(new WindowAdapter() { 385 @Override 386 public void windowClosing(WindowEvent e) { 387 targetWindowClosingEvent(e); 388 } 389 }); 390 _targetPanel.addMouseListener(JmriMouseListener.adapt(this)); 391 _targetPanel.addMouseMotionListener(JmriMouseMotionListener.adapt(this)); 392 _targetPanel.setFocusable(true); 393 _targetPanel.addKeyListener(this); 394 //_targetFrame.pack(); 395 } 396 397 protected void setTargetPanelSize(int w, int h) { 398// log.debug("setTargetPanelSize now w={}, h={}", w, h); 399 _targetPanel.setSize(w, h); 400 _targetPanel.invalidate(); 401 } 402 403 protected Dimension getTargetPanelSize() { 404 return _targetPanel.getSize(); 405 } 406 407 /** 408 * Allow public access to the target (content) panel for external 409 * modification, particularly from scripts. 410 * 411 * @return the target panel 412 */ 413 public final JComponent getTargetPanel() { 414 return _targetPanel; 415 } 416 417 /** 418 * Allow public access to the scroll pane for external control of position, 419 * particularly from scripts. 420 * 421 * @return the scroll pane containing the target panel 422 */ 423 public final JScrollPane getPanelScrollPane() { 424 return _panelScrollPane; 425 } 426 427 public final JFrame getTargetFrame() { 428 return _targetFrame; 429 } 430 431 public Color getBackgroundColor() { 432 if (_targetPanel instanceof TargetPane) { 433 TargetPane tmp = (TargetPane) _targetPanel; 434 return tmp.getBackgroundColor(); 435 } else { 436 return null; 437 } 438 } 439 440 public void setBackgroundColor(Color col) { 441 if (_targetPanel instanceof TargetPane) { 442 TargetPane tmp = (TargetPane) _targetPanel; 443 tmp.setBackgroundColor(col); 444 } 445 JmriColorChooser.addRecentColor(col); 446 } 447 448 public void clearBackgroundColor() { 449 if (_targetPanel instanceof TargetPane) { 450 TargetPane tmp = (TargetPane) _targetPanel; 451 tmp.clearBackgroundColor(); 452 } 453 } 454 455 /** 456 * Get scale for TargetPane drawing. 457 * 458 * @return the scale 459 */ 460 public final double getPaintScale() { 461 return _paintScale; 462 } 463 464 protected final void setPaintScale(double newScale) { 465 double ratio = newScale / _paintScale; 466 _paintScale = newScale; 467 setScrollbarScale(ratio); 468 } 469 470 private ToolTipTimer _tooltipTimer; 471 472 protected void setToolTip(ToolTip tt) { 473 if (tt != null) { 474 var pos = tt.getPositionable(); 475 if (pos != null) { // LE turnout tooltips do not have a Positionable 476 if (pos.isHidden() && !isEditable()) { 477 // Skip hidden objects 478 return; 479 } 480 } 481 } 482 483 if (tt == null) { 484 _tooltip = null; 485 if (_tooltipTimer != null) { 486 _tooltipTimer.stop(); 487 _tooltipTimer = null; 488 _targetPanel.repaint(); 489 } 490 491 } else if (_tooltip == null && _tooltipTimer == null) { 492 log.debug("start :: tt = {}, tooltip = {}, timer = {}", tt, _tooltip, _tooltipTimer); 493 _tooltipTimer = new ToolTipTimer(TOOLTIPSHOWDELAY, this, tt); 494 _tooltipTimer.setRepeats(false); 495 _tooltipTimer.start(); 496 } 497 } 498 499 static int TOOLTIPSHOWDELAY = 1000; // msec 500 static int TOOLTIPDISMISSDELAY = 4000; // msec 501 502 /* 503 * Wait TOOLTIPSHOWDELAY then show tooltip. Wait TOOLTIPDISMISSDELAY and 504 * disappear. 505 */ 506 @Override 507 public void actionPerformed(ActionEvent event) { 508 //log.debug("_tooltipTimer actionPerformed: Timer on= {}", (_tooltipTimer!=null)); 509 if (_tooltipTimer != null) { 510 _tooltip = _tooltipTimer.getToolTip(); 511 _tooltipTimer.stop(); 512 } 513 if (_tooltip != null) { 514 _tooltipTimer = new ToolTipTimer(TOOLTIPDISMISSDELAY, this, null); 515 _tooltipTimer.setRepeats(false); 516 _tooltipTimer.start(); 517 } else { 518 _tooltipTimer = null; 519 } 520 _targetPanel.repaint(); 521 } 522 523 static class ToolTipTimer extends Timer { 524 525 private final ToolTip tooltip; 526 527 ToolTipTimer(int delay, ActionListener listener, ToolTip tip) { 528 super(delay, listener); 529 tooltip = tip; 530 } 531 532 ToolTip getToolTip() { 533 return tooltip; 534 } 535 } 536 537 /** 538 * Special internal class to allow drawing of layout to a JLayeredPane. This 539 * is the 'target' pane where the layout is displayed. 540 */ 541 public class TargetPane extends JLayeredPane { 542 543 private int h = 100; 544 private int w = 150; 545 546 public TargetPane() { 547 setLayout(null); 548 } 549 550 @Override 551 public void setSize(int width, int height) { 552// log.debug("size now w={}, h={}", width, height); 553 this.h = height; 554 this.w = width; 555 super.setSize(width, height); 556 } 557 558 @Override 559 public Dimension getSize() { 560 return new Dimension(w, h); 561 } 562 563 @Override 564 public Dimension getPreferredSize() { 565 return new Dimension(w, h); 566 } 567 568 @Override 569 public Dimension getMinimumSize() { 570 return getPreferredSize(); 571 } 572 573 @Override 574 public Dimension getMaximumSize() { 575 return getPreferredSize(); 576 } 577 578 @Override 579 public Component add(@Nonnull Component c, int i) { 580 int hnew = Math.max(this.h, c.getLocation().y + c.getSize().height); 581 int wnew = Math.max(this.w, c.getLocation().x + c.getSize().width); 582 if (hnew > h || wnew > w) { 583// log.debug("size was {},{} - i ={}", w, h, i); 584 setSize(wnew, hnew); 585 } 586 return super.add(c, i); 587 } 588 589 @Override 590 public void add(@Nonnull Component c, Object o) { 591 super.add(c, o); 592 int hnew = Math.max(h, c.getLocation().y + c.getSize().height); 593 int wnew = Math.max(w, c.getLocation().x + c.getSize().width); 594 if (hnew > h || wnew > w) { 595 // log.debug("adding of {} with Object - i=", c.getSize(), o); 596 setSize(wnew, hnew); 597 } 598 } 599 600 private Color _highlightColor = HIGHLIGHT_COLOR; 601 private Color _selectGroupColor = HIGHLIGHT_COLOR; 602 private Color _selectRectColor = Color.red; 603 private transient Stroke _selectRectStroke = DASHED_LINE; 604 605 public void setHighlightColor(Color color) { 606 _highlightColor = color; 607 } 608 609 public Color getHighlightColor() { 610 return _highlightColor; 611 } 612 613 public void setSelectGroupColor(Color color) { 614 _selectGroupColor = color; 615 } 616 617 public void setSelectRectColor(Color color) { 618 _selectRectColor = color; 619 } 620 621 public void setSelectRectStroke(Stroke stroke) { 622 _selectRectStroke = stroke; 623 } 624 625 public void setDefaultColors() { 626 _highlightColor = HIGHLIGHT_COLOR; 627 _selectGroupColor = HIGHLIGHT_COLOR; 628 _selectRectColor = Color.red; 629 _selectRectStroke = DASHED_LINE; 630 } 631 632 @Override 633 public void paint(Graphics g) { 634 Graphics2D g2d = null; 635 if (g instanceof Graphics2D) { 636 g2d = (Graphics2D) g; 637 g2d.scale(_paintScale, _paintScale); 638 } 639 super.paint(g); 640 641 Stroke stroke = new BasicStroke(); 642 if (g2d != null) { 643 stroke = g2d.getStroke(); 644 } 645 Color color = g.getColor(); 646 if (_selectRect != null) { 647 //Draw a rectangle on top of the image. 648 if (g2d != null) { 649 g2d.setStroke(_selectRectStroke); 650 } 651 g.setColor(_selectRectColor); 652 g.drawRect(_selectRect.x, _selectRect.y, _selectRect.width, _selectRect.height); 653 } 654 if (_selectionGroup != null) { 655 g.setColor(_selectGroupColor); 656 if (g2d != null) { 657 g2d.setStroke(new BasicStroke(2.0f)); 658 } 659 for (Positionable p : _selectionGroup) { 660 if (p != null) { 661 if (!(p instanceof PositionableShape)) { 662 g.drawRect(p.getX(), p.getY(), p.maxWidth(), p.maxHeight()); 663 } else { 664 PositionableShape s = (PositionableShape) p; 665 s.drawHandles(); 666 } 667 } 668 } 669 } 670 //Draws a border around the highlighted component 671 if (_highlightcomponent != null) { 672 g.setColor(_highlightColor); 673 if (g2d != null) { 674 g2d.setStroke(new BasicStroke(2.0f)); 675 } 676 g.drawRect(_highlightcomponent.x, _highlightcomponent.y, 677 _highlightcomponent.width, _highlightcomponent.height); 678 } 679 paintTargetPanel(g); 680 681 g.setColor(color); 682 if (g2d != null) { 683 g2d.setStroke(stroke); 684 } 685 if (_tooltip != null) { 686 _tooltip.paint(g2d, _paintScale); 687 } 688 } 689 690 public void setBackgroundColor(Color col) { 691 setBackground(col); 692 setOpaque(true); 693 JmriColorChooser.addRecentColor(col); 694 } 695 696 public void clearBackgroundColor() { 697 setOpaque(false); 698 } 699 700 public Color getBackgroundColor() { 701 if (isOpaque()) { 702 return getBackground(); 703 } 704 return null; 705 } 706 } 707 708 private void setScrollbarScale(double ratio) { 709 //resize the panel to reflect scaling 710 Dimension dim = _targetPanel.getSize(); 711 int tpWidth = (int) ((dim.width) * ratio); 712 int tpHeight = (int) ((dim.height) * ratio); 713 _targetPanel.setSize(tpWidth, tpHeight); 714 log.debug("setScrollbarScale: ratio= {}, tpWidth= {}, tpHeight= {}", ratio, tpWidth, tpHeight); 715 // compute new scroll bar positions to keep upper left same 716 JScrollBar horScroll = _panelScrollPane.getHorizontalScrollBar(); 717 JScrollBar vertScroll = _panelScrollPane.getVerticalScrollBar(); 718 int hScroll = (int) (horScroll.getValue() * ratio); 719 int vScroll = (int) (vertScroll.getValue() * ratio); 720 // set scrollbars maximum range (otherwise setValue may fail); 721 horScroll.setMaximum((int) ((horScroll.getMaximum()) * ratio)); 722 vertScroll.setMaximum((int) ((vertScroll.getMaximum()) * ratio)); 723 // set scroll bar positions 724 horScroll.setValue(hScroll); 725 vertScroll.setValue(vScroll); 726 } 727 728 /* 729 * ********************** Options setup ********************* 730 */ 731 /** 732 * Control whether target panel items are editable. Does this by invoke the 733 * {@link Positionable#setEditable(boolean)} function of each item on the 734 * target panel. This also controls the relevant pop-up menu items (which 735 * are the primary way that items are edited). 736 * 737 * @param state true for editable. 738 */ 739 public void setAllEditable(boolean state) { 740 _editable = state; 741 for (Positionable _content : _contents) { 742 _content.setEditable(state); 743 } 744 if (!_editable) { 745 _highlightcomponent = null; 746 deselectSelectionGroup(); 747 } 748 } 749 750 public void deselectSelectionGroup() { 751 if (_selectionGroup == null) { 752 return; 753 } 754 for (Positionable p : _selectionGroup) { 755 if (p instanceof PositionableShape) { 756 PositionableShape s = (PositionableShape) p; 757 s.removeHandles(); 758 } 759 } 760 _selectionGroup = null; 761 } 762 763 // accessor routines for persistent information 764 public boolean isEditable() { 765 return _editable; 766 } 767 768 /** 769 * Set which flag should be used, global or local for Positioning and 770 * Control of individual items. Items call getFlag() to return the 771 * appropriate flag it should use. 772 * 773 * @param set True if global flags should be used for positioning. 774 */ 775 public void setUseGlobalFlag(boolean set) { 776 _useGlobalFlag = set; 777 } 778 779 public boolean useGlobalFlag() { 780 return _useGlobalFlag; 781 } 782 783 /** 784 * Get the setting for the specified option. 785 * 786 * @param whichOption The option to get 787 * @param localFlag is the current setting of the item 788 * @return The setting for the option 789 */ 790 public boolean getFlag(int whichOption, boolean localFlag) { 791 //log.debug("getFlag Option= {}, _useGlobalFlag={} localFlag={}", whichOption, _useGlobalFlag, localFlag); 792 if (_useGlobalFlag) { 793 switch (whichOption) { 794 case OPTION_POSITION: 795 return _positionable; 796 case OPTION_CONTROLS: 797 return _controlLayout; 798 case OPTION_HIDDEN: 799 return _showHidden; 800 case OPTION_TOOLTIP: 801 return _showToolTip; 802// case OPTION_COORDS: 803// return _showCoordinates; 804 default: 805 log.warn("Unhandled which option code: {}", whichOption); 806 break; 807 } 808 } 809 return localFlag; 810 } 811 812 /** 813 * Set if {@link #setAllControlling(boolean)} and 814 * {@link #setAllPositionable(boolean)} are set for existing as well as new 815 * items. 816 * 817 * @param set true if setAllControlling() and setAllPositionable() are set 818 * for existing items 819 */ 820 public void setGlobalSetsLocalFlag(boolean set) { 821 _globalSetsLocal = set; 822 } 823 824 /** 825 * Control whether panel items can be positioned. Markers can always be 826 * positioned. 827 * 828 * @param state true to set all items positionable; false otherwise 829 */ 830 public void setAllPositionable(boolean state) { 831 _positionable = state; 832 if (_globalSetsLocal) { 833 for (Positionable p : _contents) { 834 // don't allow backgrounds to be set positionable by global flag 835 if (!state || p.getDisplayLevel() != BKG) { 836 p.setPositionable(state); 837 } 838 } 839 } 840 } 841 842 public boolean allPositionable() { 843 return _positionable; 844 } 845 846 /** 847 * Control whether target panel items are controlling layout items. 848 * <p> 849 * Does this by invoking the {@link Positionable#setControlling} function of 850 * each item on the target panel. This also controls the relevant pop-up 851 * menu items. 852 * 853 * @param state true for controlling. 854 */ 855 public void setAllControlling(boolean state) { 856 _controlLayout = state; 857 if (_globalSetsLocal) { 858 for (Positionable _content : _contents) { 859 _content.setControlling(state); 860 } 861 } 862 } 863 864 public boolean allControlling() { 865 return _controlLayout; 866 } 867 868 /** 869 * Control whether target panel hidden items are visible or not. Does this 870 * by invoke the {@link Positionable#setHidden} function of each item on the 871 * target panel. 872 * 873 * @param state true for Visible. 874 */ 875 public void setShowHidden(boolean state) { 876 _showHidden = state; 877 if (_showHidden) { 878 for (Positionable _content : _contents) { 879 _content.setVisible(true); 880 } 881 } else { 882 for (Positionable _content : _contents) { 883 _content.showHidden(); 884 } 885 } 886 } 887 888 public boolean showHidden() { 889 return _showHidden; 890 } 891 892 public void setAllShowToolTip(boolean state) { 893 _showToolTip = state; 894 for (Positionable _content : _contents) { 895 _content.setShowToolTip(state); 896 } 897 } 898 899 public boolean showToolTip() { 900 return _showToolTip; 901 } 902 903 /* 904 * Control whether target panel items will show their coordinates in their 905 * popup menu. 906 * 907 * @param state true for show coordinates. 908 */ 909 /* 910 public void setShowCoordinates(boolean state) { 911 _showCoordinates = state; 912 for (int i = 0; i<_contents.size(); i++) { 913 _contents.get(i).setViewCoordinates(state); 914 } 915 } 916 public boolean showCoordinates() { 917 return _showCoordinates; 918 } 919 */ 920 921 /** 922 * Hide or show menus on the target panel. 923 * 924 * @param state true to show menus; false to hide menus 925 * @since 3.9.5 926 */ 927 public void setPanelMenuVisible(boolean state) { 928 this.panelMenuIsVisible = state; 929 if (!GraphicsEnvironment.isHeadless() && this._targetFrame != null) { 930 _targetFrame.getJMenuBar().setVisible(state); 931 this.revalidate(); 932 } 933 } 934 935 /** 936 * Is the menu on the target panel shown? 937 * 938 * @return true if menu is visible 939 * @since 3.9.5 940 */ 941 public boolean isPanelMenuVisible() { 942 if (!GraphicsEnvironment.isHeadless() && this._targetFrame != null) { 943 this.panelMenuIsVisible = _targetFrame.getJMenuBar().isVisible(); 944 } 945 return this.panelMenuIsVisible; 946 } 947 948 protected void setScroll(int state) { 949 log.debug("setScroll {}", state); 950 switch (state) { 951 case SCROLL_NONE: 952 _panelScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 953 _panelScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 954 break; 955 case SCROLL_BOTH: 956 _panelScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 957 _panelScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 958 break; 959 case SCROLL_HORIZONTAL: 960 _panelScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 961 _panelScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 962 break; 963 case SCROLL_VERTICAL: 964 _panelScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 965 _panelScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 966 break; 967 default: 968 log.warn("Unexpected setScroll state of {}", state); 969 break; 970 } 971 _scrollState = state; 972 } 973 974 public void setScroll(String strState) { 975 int state = SCROLL_BOTH; 976 if (strState.equalsIgnoreCase("none") || strState.equalsIgnoreCase("no")) { 977 state = SCROLL_NONE; 978 } else if (strState.equals("horizontal")) { 979 state = SCROLL_HORIZONTAL; 980 } else if (strState.equals("vertical")) { 981 state = SCROLL_VERTICAL; 982 } 983 log.debug("setScroll: strState= {}, state= {}", strState, state); 984 setScroll(state); 985 } 986 987 public String getScrollable() { 988 String value = ""; 989 switch (_scrollState) { 990 case SCROLL_NONE: 991 value = "none"; 992 break; 993 case SCROLL_BOTH: 994 value = "both"; 995 break; 996 case SCROLL_HORIZONTAL: 997 value = "horizontal"; 998 break; 999 case SCROLL_VERTICAL: 1000 value = "vertical"; 1001 break; 1002 default: 1003 log.warn("Unexpected _scrollState of {}", _scrollState); 1004 break; 1005 } 1006 return value; 1007 } 1008 /* 1009 * *********************** end Options setup ********************** 1010 */ 1011 /* 1012 * Handle closing (actually hiding due to HIDE_ON_CLOSE) the target window. 1013 * <p> 1014 * The target window has been requested to close, don't delete it at this 1015 * time. Deletion must be accomplished via the Delete this panel menu item. 1016 */ 1017 protected void targetWindowClosing() { 1018 String name = _targetFrame.getTitle(); 1019 if (!InstanceManager.getDefault(ShutDownManager.class).isShuttingDown()) { 1020 InstanceManager.getDefault(UserPreferencesManager.class).showInfoMessage( 1021 Bundle.getMessage("PanelHideTitle"), Bundle.getMessage("PanelHideNotice", name), // NOI18N 1022 "jmri.jmrit.display.EditorManager", "skipHideDialog"); // NOI18N 1023 InstanceManager.getDefault(UserPreferencesManager.class).setPreferenceItemDetails( 1024 "jmri.jmrit.display.EditorManager", "skipHideDialog", Bundle.getMessage("PanelHideSkip")); // NOI18N 1025 } 1026 } 1027 1028 protected Editor changeView(String className) { 1029 JFrame frame = getTargetFrame(); 1030 1031 try { 1032 Editor ed = (Editor) Class.forName(className).getDeclaredConstructor().newInstance(); 1033 1034 ed.setName(getName()); 1035 ed.init(getName()); 1036 1037 ed._contents = new ArrayList<>(_contents); 1038 ed._idContents = new HashMap<>(_idContents); 1039 ed._classContents = new HashMap<>(_classContents); 1040 1041 for (Positionable p : _contents) { 1042 p.setEditor(ed); 1043 ed.addToTarget(p); 1044 if (log.isDebugEnabled()) { 1045 log.debug("changeView: {} addToTarget class= {}", p.getNameString(), p.getClass().getName()); 1046 } 1047 } 1048 ed.setAllEditable(isEditable()); 1049 //ed.setAllPositionable(allPositionable()); 1050 //ed.setShowCoordinates(showCoordinates()); 1051 ed.setAllShowToolTip(showToolTip()); 1052 //ed.setAllControlling(allControlling()); 1053 ed.setShowHidden(isVisible()); 1054 ed.setPanelMenuVisible(frame.getJMenuBar().isVisible()); 1055 ed.setScroll(getScrollable()); 1056 ed.setTitle(); 1057 ed.setBackgroundColor(getBackgroundColor()); 1058 ed.getTargetFrame().setLocation(frame.getLocation()); 1059 ed.getTargetFrame().setSize(frame.getSize()); 1060 ed.setSize(getSize()); 1061// ed.pack(); 1062 ed.setVisible(true); 1063 dispose(); 1064 InstanceManager.getDefault(EditorManager.class).add(ed); 1065 return ed; 1066 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException cnfe) { 1067 log.error("changeView exception {}", cnfe.toString()); 1068 } 1069 return null; 1070 } 1071 1072 /* 1073 * *********************** Popup Item Methods ********************** 1074 * 1075 * These methods are to be called from the editor view's showPopUp method 1076 */ 1077 /** 1078 * Add a checkbox to lock the position of the Positionable item. 1079 * 1080 * @param p the item 1081 * @param popup the menu to add the lock menu item to 1082 */ 1083 public void setPositionableMenu(Positionable p, JPopupMenu popup) { 1084 JCheckBoxMenuItem lockItem = new JCheckBoxMenuItem(Bundle.getMessage("LockPosition")); 1085 lockItem.setSelected(!p.isPositionable()); 1086 lockItem.addActionListener(new ActionListener() { 1087 private Positionable comp; 1088 private JCheckBoxMenuItem checkBox; 1089 1090 @Override 1091 public void actionPerformed(ActionEvent e) { 1092 comp.setPositionable(!checkBox.isSelected()); 1093 setSelectionsPositionable(!checkBox.isSelected(), comp); 1094 } 1095 1096 ActionListener init(Positionable pos, JCheckBoxMenuItem cb) { 1097 comp = pos; 1098 checkBox = cb; 1099 return this; 1100 } 1101 }.init(p, lockItem)); 1102 popup.add(lockItem); 1103 } 1104 1105 /** 1106 * Display the {@literal X & Y} coordinates of the Positionable item and 1107 * provide a dialog menu item to edit them. 1108 * 1109 * @param p The item to add the menu item to 1110 * @param popup The menu item to add the action to 1111 * @return always returns true 1112 */ 1113 public boolean setShowCoordinatesMenu(Positionable p, JPopupMenu popup) { 1114 1115 JMenuItem edit; 1116 if ((p instanceof MemoryOrGVIcon) && (p.getPopupUtility().getFixedWidth() == 0)) { 1117 MemoryOrGVIcon pm = (MemoryOrGVIcon) p; 1118 1119 edit = new JMenuItem(Bundle.getMessage( 1120 "EditLocationXY", pm.getOriginalX(), pm.getOriginalY())); 1121 1122 edit.addActionListener(MemoryIconCoordinateEdit.getCoordinateEditAction(pm)); 1123 } else { 1124 edit = new JMenuItem(Bundle.getMessage( 1125 "EditLocationXY", p.getX(), p.getY())); 1126 edit.addActionListener(CoordinateEdit.getCoordinateEditAction(p)); 1127 } 1128 popup.add(edit); 1129 return true; 1130 } 1131 1132 /** 1133 * Offer actions to align the selected Positionable items either 1134 * Horizontally (at average y coordinates) or Vertically (at average x 1135 * coordinates). 1136 * 1137 * @param p The positionable item 1138 * @param popup The menu to add entries to 1139 * @return true if entries added to menu 1140 */ 1141 public boolean setShowAlignmentMenu(Positionable p, JPopupMenu popup) { 1142 if (showAlignPopup(p)) { 1143 JMenu edit = new JMenu(Bundle.getMessage("EditAlignment")); 1144 edit.add(new AbstractAction(Bundle.getMessage("AlignX")) { 1145 private int _x; 1146 1147 @Override 1148 public void actionPerformed(ActionEvent e) { 1149 if (_selectionGroup == null) { 1150 return; 1151 } 1152 for (Positionable comp : _selectionGroup) { 1153 if (!getFlag(OPTION_POSITION, comp.isPositionable())) { 1154 continue; 1155 } 1156 comp.setLocation(_x, comp.getY()); 1157 } 1158 } 1159 1160 AbstractAction init(int x) { 1161 _x = x; 1162 return this; 1163 } 1164 }.init(p.getX())); 1165 edit.add(new AbstractAction(Bundle.getMessage("AlignMiddleX")) { 1166 private int _x; 1167 1168 @Override 1169 public void actionPerformed(ActionEvent e) { 1170 if (_selectionGroup == null) { 1171 return; 1172 } 1173 for (Positionable comp : _selectionGroup) { 1174 if (!getFlag(OPTION_POSITION, comp.isPositionable())) { 1175 continue; 1176 } 1177 comp.setLocation(_x - comp.getWidth() / 2, comp.getY()); 1178 } 1179 } 1180 1181 AbstractAction init(int x) { 1182 _x = x; 1183 return this; 1184 } 1185 }.init(p.getX() + p.getWidth() / 2)); 1186 edit.add(new AbstractAction(Bundle.getMessage("AlignOtherX")) { 1187 private int _x; 1188 1189 @Override 1190 public void actionPerformed(ActionEvent e) { 1191 if (_selectionGroup == null) { 1192 return; 1193 } 1194 for (Positionable comp : _selectionGroup) { 1195 if (!getFlag(OPTION_POSITION, comp.isPositionable())) { 1196 continue; 1197 } 1198 comp.setLocation(_x - comp.getWidth(), comp.getY()); 1199 } 1200 } 1201 1202 AbstractAction init(int x) { 1203 _x = x; 1204 return this; 1205 } 1206 }.init(p.getX() + p.getWidth())); 1207 edit.add(new AbstractAction(Bundle.getMessage("AlignY")) { 1208 private int _y; 1209 1210 @Override 1211 public void actionPerformed(ActionEvent e) { 1212 if (_selectionGroup == null) { 1213 return; 1214 } 1215 for (Positionable comp : _selectionGroup) { 1216 if (!getFlag(OPTION_POSITION, comp.isPositionable())) { 1217 continue; 1218 } 1219 comp.setLocation(comp.getX(), _y); 1220 } 1221 } 1222 1223 AbstractAction init(int y) { 1224 _y = y; 1225 return this; 1226 } 1227 }.init(p.getY())); 1228 edit.add(new AbstractAction(Bundle.getMessage("AlignMiddleY")) { 1229 private int _y; 1230 1231 @Override 1232 public void actionPerformed(ActionEvent e) { 1233 if (_selectionGroup == null) { 1234 return; 1235 } 1236 for (Positionable comp : _selectionGroup) { 1237 if (!getFlag(OPTION_POSITION, comp.isPositionable())) { 1238 continue; 1239 } 1240 comp.setLocation(comp.getX(), _y - comp.getHeight() / 2); 1241 } 1242 } 1243 1244 AbstractAction init(int y) { 1245 _y = y; 1246 return this; 1247 } 1248 }.init(p.getY() + p.getHeight() / 2)); 1249 edit.add(new AbstractAction(Bundle.getMessage("AlignOtherY")) { 1250 private int _y; 1251 1252 @Override 1253 public void actionPerformed(ActionEvent e) { 1254 if (_selectionGroup == null) { 1255 return; 1256 } 1257 for (Positionable comp : _selectionGroup) { 1258 if (!getFlag(OPTION_POSITION, comp.isPositionable())) { 1259 continue; 1260 } 1261 comp.setLocation(comp.getX(), _y - comp.getHeight()); 1262 } 1263 } 1264 1265 AbstractAction init(int y) { 1266 _y = y; 1267 return this; 1268 } 1269 }.init(p.getY() + p.getHeight())); 1270 edit.add(new AbstractAction(Bundle.getMessage("AlignXFirst")) { 1271 1272 @Override 1273 public void actionPerformed(ActionEvent e) { 1274 if (_selectionGroup == null) { 1275 return; 1276 } 1277 int x = _selectionGroup.get(0).getX(); 1278 for (int i = 1; i < _selectionGroup.size(); i++) { 1279 Positionable comp = _selectionGroup.get(i); 1280 if (!getFlag(OPTION_POSITION, comp.isPositionable())) { 1281 continue; 1282 } 1283 comp.setLocation(x, comp.getY()); 1284 } 1285 } 1286 }); 1287 edit.add(new AbstractAction(Bundle.getMessage("AlignYFirst")) { 1288 1289 @Override 1290 public void actionPerformed(ActionEvent e) { 1291 if (_selectionGroup == null) { 1292 return; 1293 } 1294 int y = _selectionGroup.get(0).getX(); 1295 for (int i = 1; i < _selectionGroup.size(); i++) { 1296 Positionable comp = _selectionGroup.get(i); 1297 if (!getFlag(OPTION_POSITION, comp.isPositionable())) { 1298 continue; 1299 } 1300 comp.setLocation(comp.getX(), y); 1301 } 1302 } 1303 }); 1304 popup.add(edit); 1305 return true; 1306 } 1307 return false; 1308 } 1309 1310 /** 1311 * Display 'z' level of the Positionable item and provide a dialog 1312 * menu item to edit it. 1313 * 1314 * @param p The item 1315 * @param popup the menu to add entries to 1316 */ 1317 public void setDisplayLevelMenu(Positionable p, JPopupMenu popup) { 1318 JMenuItem edit = new JMenuItem(Bundle.getMessage("EditLevel_", p.getDisplayLevel())); 1319 edit.addActionListener(CoordinateEdit.getLevelEditAction(p)); 1320 popup.add(edit); 1321 } 1322 1323 /** 1324 * Add a menu entry to set visibility of the Positionable item 1325 * 1326 * @param p the item 1327 * @param popup the menu to add the entry to 1328 */ 1329 public void setHiddenMenu(Positionable p, JPopupMenu popup) { 1330 if (p.getDisplayLevel() == BKG) { 1331 return; 1332 } 1333 JCheckBoxMenuItem hideItem = new JCheckBoxMenuItem(Bundle.getMessage("SetHidden")); 1334 hideItem.setSelected(p.isHidden()); 1335 hideItem.addActionListener(new ActionListener() { 1336 private Positionable comp; 1337 private JCheckBoxMenuItem checkBox; 1338 1339 @Override 1340 public void actionPerformed(ActionEvent e) { 1341 comp.setHidden(checkBox.isSelected()); 1342 setSelectionsHidden(checkBox.isSelected(), comp); 1343 } 1344 1345 ActionListener init(Positionable pos, JCheckBoxMenuItem cb) { 1346 comp = pos; 1347 checkBox = cb; 1348 return this; 1349 } 1350 }.init(p, hideItem)); 1351 popup.add(hideItem); 1352 } 1353 1354 /** 1355 * Add a menu entry to set visibility of the Positionable item based on the presence of contents. 1356 * If the value is null or empty, the icon is not visible. 1357 * This is applicable to memory, block content and LogixNG global variable labels. 1358 * 1359 * @param p the item 1360 * @param popup the menu to add the entry to 1361 */ 1362 public void setEmptyHiddenMenu(Positionable p, JPopupMenu popup) { 1363 if (p.getDisplayLevel() == BKG) { 1364 return; 1365 } 1366 if (p instanceof BlockContentsIcon || p instanceof MemoryIcon 1367 || p instanceof GlobalVariableIcon || p instanceof LogixNGTableIcon) { 1368 JCheckBoxMenuItem hideEmptyItem = new JCheckBoxMenuItem(Bundle.getMessage("SetEmptyHidden")); 1369 hideEmptyItem.setSelected(p.isEmptyHidden()); 1370 hideEmptyItem.addActionListener(new ActionListener() { 1371 private Positionable comp; 1372 private JCheckBoxMenuItem checkBox; 1373 1374 @Override 1375 public void actionPerformed(ActionEvent e) { 1376 comp.setEmptyHidden(checkBox.isSelected()); 1377 } 1378 1379 ActionListener init(Positionable pos, JCheckBoxMenuItem cb) { 1380 comp = pos; 1381 checkBox = cb; 1382 return this; 1383 } 1384 }.init(p, hideEmptyItem)); 1385 popup.add(hideEmptyItem); 1386 } 1387 } 1388 1389 /** 1390 * Add a menu entry to disable double click value edits. This applies when not in panel edit mode. 1391 * This is applicable to memory, block content and LogixNG global variable labels. 1392 * 1393 * @param p the item 1394 * @param popup the menu to add the entry to 1395 */ 1396 public void setValueEditDisabledMenu(Positionable p, JPopupMenu popup) { 1397 if (p.getDisplayLevel() == BKG) { 1398 return; 1399 } 1400 if (p instanceof BlockContentsIcon || p instanceof MemoryIcon 1401 || p instanceof GlobalVariableIcon || p instanceof LogixNGTableIcon) { 1402 JCheckBoxMenuItem valueEditDisableItem = new JCheckBoxMenuItem(Bundle.getMessage("SetValueEditDisabled")); 1403 valueEditDisableItem.setSelected(p.isValueEditDisabled()); 1404 valueEditDisableItem.addActionListener(new ActionListener() { 1405 private Positionable comp; 1406 private JCheckBoxMenuItem checkBox; 1407 1408 @Override 1409 public void actionPerformed(ActionEvent e) { 1410 comp.setValueEditDisabled(checkBox.isSelected()); 1411 } 1412 1413 ActionListener init(Positionable pos, JCheckBoxMenuItem cb) { 1414 comp = pos; 1415 checkBox = cb; 1416 return this; 1417 } 1418 }.init(p, valueEditDisableItem)); 1419 popup.add(valueEditDisableItem); 1420 } 1421 } 1422 1423 /** 1424 * Add a menu entry to edit Id of the Positionable item 1425 * 1426 * @param p the item 1427 * @param popup the menu to add the entry to 1428 */ 1429 public void setEditIdMenu(Positionable p, JPopupMenu popup) { 1430 if (p.getDisplayLevel() == BKG) { 1431 return; 1432 } 1433 1434 popup.add(CoordinateEdit.getIdEditAction(p, "EditId", this)); 1435 } 1436 1437 /** 1438 * Add a menu entry to edit Classes of the Positionable item 1439 * 1440 * @param p the item 1441 * @param popup the menu to add the entry to 1442 */ 1443 public void setEditClassesMenu(Positionable p, JPopupMenu popup) { 1444 if (p.getDisplayLevel() == BKG) { 1445 return; 1446 } 1447 1448 popup.add(CoordinateEdit.getClassesEditAction(p, "EditClasses", this)); 1449 } 1450 1451 /** 1452 * Check if edit of a conditional is in progress. 1453 * 1454 * @return true if this is the case, after showing dialog to user 1455 */ 1456 private boolean checkEditConditionalNG() { 1457 if (_inEditInlineLogixNGMode) { 1458 // Already editing a LogixNG, ask for completion of that edit 1459 JmriJOptionPane.showMessageDialog(null, 1460 Bundle.getMessage("Error_InlineLogixNGInEditMode"), // NOI18N 1461 Bundle.getMessage("ErrorTitle"), // NOI18N 1462 JmriJOptionPane.ERROR_MESSAGE); 1463 _inlineLogixNGEdit.bringToFront(); 1464 return true; 1465 } 1466 return false; 1467 } 1468 1469 /** 1470 * Add a menu entry to edit Id of the Positionable item 1471 * 1472 * @param p the item 1473 * @param popup the menu to add the entry to 1474 */ 1475 public void setLogixNGPositionableMenu(Positionable p, JPopupMenu popup) { 1476 if (p.getDisplayLevel() == BKG) { 1477 return; 1478 } 1479 1480 JMenu logixNG_Menu = new JMenu("LogixNG"); 1481 popup.add(logixNG_Menu); 1482 1483 logixNG_Menu.add(new AbstractAction(Bundle.getMessage("LogixNG_Inline")) { 1484 @Override 1485 public void actionPerformed(ActionEvent e) { 1486 if (checkEditConditionalNG()) { 1487 return; 1488 } 1489 1490 if (p.getLogixNG() == null) { 1491 LogixNG logixNG = InstanceManager.getDefault(LogixNG_Manager.class) 1492 .createLogixNG(null, true); 1493 logixNG.setInlineLogixNG(p); 1494 logixNG.activate(); 1495 logixNG.setEnabled(true); 1496 logixNG.clearStartup(); 1497 p.setLogixNG(logixNG); 1498 } 1499 LogixNGEditor logixNGEditor = new LogixNGEditor(null, p.getLogixNG().getSystemName()); 1500 logixNGEditor.addEditorEventListener((HashMap<String, String> data) -> { 1501 _inEditInlineLogixNGMode = false; 1502 data.forEach((key, value) -> { 1503 if (key.equals("Finish")) { // NOI18N 1504 _inlineLogixNGEdit = null; 1505 _inEditInlineLogixNGMode = false; 1506 } else if (key.equals("Delete")) { // NOI18N 1507 _inEditInlineLogixNGMode = false; 1508 deleteLogixNG(p.getLogixNG()); 1509 } else if (key.equals("chgUname")) { // NOI18N 1510 p.getLogixNG().setUserName(value); 1511 } 1512 }); 1513 if (p.getLogixNG() != null && p.getLogixNG().getNumConditionalNGs() == 0) { 1514 deleteLogixNG_Internal(p.getLogixNG()); 1515 } 1516 }); 1517 logixNGEditor.bringToFront(); 1518 _inEditInlineLogixNGMode = true; 1519 _inlineLogixNGEdit = logixNGEditor; 1520 } 1521 }); 1522 } 1523 1524 private void deleteLogixNG(LogixNG logixNG) { 1525 DeleteBean<LogixNG> deleteBean = new DeleteBean<>( 1526 InstanceManager.getDefault(LogixNG_Manager.class)); 1527 1528 boolean hasChildren = logixNG.getNumConditionalNGs() > 0; 1529 1530 deleteBean.delete(logixNG, hasChildren, t -> deleteLogixNG_Internal(t), 1531 (t,list) -> logixNG.getListenerRefsIncludingChildren(list), 1532 jmri.jmrit.logixng.LogixNG_UserPreferences.class.getName()); 1533 } 1534 1535 private void deleteLogixNG_Internal(LogixNG logixNG) { 1536 logixNG.setEnabled(false); 1537 try { 1538 InstanceManager.getDefault(LogixNG_Manager.class).deleteBean(logixNG, "DoDelete"); 1539 logixNG.getInlineLogixNG().setLogixNG(null); 1540 } catch (PropertyVetoException e) { 1541 //At this stage the DoDelete shouldn't fail, as we have already done a can delete, which would trigger a veto 1542 log.error("{} : Could not Delete.", e.getMessage()); 1543 } 1544 } 1545 1546 /** 1547 * Check if it's possible to change the id of the Positionable to the 1548 * desired string. 1549 * @param p the Positionable 1550 * @param newId the desired new id 1551 * @throws jmri.jmrit.display.Positionable.DuplicateIdException if another 1552 * Positionable in the editor already has this id 1553 */ 1554 public void positionalIdChange(Positionable p, String newId) 1555 throws Positionable.DuplicateIdException { 1556 1557 if (Objects.equals(newId, p.getId())) { 1558 return; 1559 } 1560 1561 if ((newId != null) && (_idContents.containsKey(newId))) { 1562 throw new Positionable.DuplicateIdException(); 1563 } 1564 1565 if (p.getId() != null) { 1566 _idContents.remove(p.getId()); 1567 } 1568 if (newId != null) { 1569 _idContents.put(newId, p); 1570 } 1571 } 1572 1573 /** 1574 * Add a class name to the Positionable 1575 * @param p the Positionable 1576 * @param className the class name 1577 * @throws IllegalArgumentException if the name contains a comma 1578 */ 1579 public void positionalAddClass(Positionable p, String className) { 1580 1581 if (className == null) { 1582 throw new IllegalArgumentException("Class name must not be null"); 1583 } 1584 if (className.isBlank()) { 1585 throw new IllegalArgumentException("Class name must not be blank"); 1586 } 1587 if (className.contains(",")) { 1588 throw new IllegalArgumentException("Class name must not contain a comma"); 1589 } 1590 1591 if (p.getClasses().contains(className)) { 1592 return; 1593 } 1594 1595 _classContents.computeIfAbsent(className, o -> new HashSet<>()).add(p); 1596 } 1597 1598 /** 1599 * Removes a class name from the Positionable 1600 * @param p the Positionable 1601 * @param className the class name 1602 */ 1603 public void positionalRemoveClass(Positionable p, String className) { 1604 1605 if (p.getClasses().contains(className)) { 1606 return; 1607 } 1608 _classContents.get(className).remove(p); 1609 } 1610 1611 /** 1612 * Add a checkbox to display a tooltip for the Positionable item and if 1613 * showable, provide a dialog menu to edit it. 1614 * 1615 * @param p the item to set the menu for 1616 * @param popup the menu to add for p 1617 */ 1618 public void setShowToolTipMenu(Positionable p, JPopupMenu popup) { 1619 if (p.getDisplayLevel() == BKG) { 1620 return; 1621 } 1622 1623 JMenu edit = new JMenu(Bundle.getMessage("EditTooltip")); 1624 1625 JCheckBoxMenuItem showToolTipItem = new JCheckBoxMenuItem(Bundle.getMessage("ShowTooltip")); 1626 showToolTipItem.setSelected(p.showToolTip()); 1627 showToolTipItem.addActionListener(new ActionListener() { 1628 private Positionable comp; 1629 private JCheckBoxMenuItem checkBox; 1630 1631 @Override 1632 public void actionPerformed(ActionEvent e) { 1633 comp.setShowToolTip(checkBox.isSelected()); 1634 } 1635 1636 ActionListener init(Positionable pos, JCheckBoxMenuItem cb) { 1637 comp = pos; 1638 checkBox = cb; 1639 return this; 1640 } 1641 }.init(p, showToolTipItem)); 1642 edit.add(showToolTipItem); 1643 1644 edit.add(CoordinateEdit.getToolTipEditAction(p)); 1645 1646 JCheckBoxMenuItem prependToolTipWithDisplayNameItem = 1647 new JCheckBoxMenuItem(Bundle.getMessage("PrependTooltipWithDisplayName")); 1648 prependToolTipWithDisplayNameItem.setSelected(p.getToolTip().getPrependToolTipWithDisplayName()); 1649 prependToolTipWithDisplayNameItem.addActionListener(new ActionListener() { 1650 private Positionable comp; 1651 private JCheckBoxMenuItem checkBox; 1652 1653 @Override 1654 public void actionPerformed(ActionEvent e) { 1655 comp.getToolTip().setPrependToolTipWithDisplayName(checkBox.isSelected()); 1656 } 1657 1658 ActionListener init(Positionable pos, JCheckBoxMenuItem cb) { 1659 comp = pos; 1660 checkBox = cb; 1661 return this; 1662 } 1663 }.init(p, prependToolTipWithDisplayNameItem)); 1664 edit.add(prependToolTipWithDisplayNameItem); 1665 1666 popup.add(edit); 1667 } 1668 1669 /** 1670 * Add an action to remove the Positionable item. 1671 * 1672 * @param p the item to set the menu for 1673 * @param popup the menu to add for p 1674 */ 1675 public void setRemoveMenu(Positionable p, JPopupMenu popup) { 1676 popup.add(new AbstractAction(Bundle.getMessage("Remove")) { 1677 private Positionable comp; 1678 1679 @Override 1680 public void actionPerformed(ActionEvent e) { 1681 comp.remove(); 1682 removeSelections(comp); 1683 } 1684 1685 AbstractAction init(Positionable pos) { 1686 comp = pos; 1687 return this; 1688 } 1689 }.init(p)); 1690 } 1691 1692 /* 1693 * *********************** End Popup Methods ********************** 1694 */ 1695 /* 1696 * ****************** Marker Menu *************************** 1697 */ 1698 protected void locoMarkerFromRoster() { 1699 final JmriJFrame locoRosterFrame = new JmriJFrame(); 1700 locoRosterFrame.getContentPane().setLayout(new FlowLayout()); 1701 locoRosterFrame.setTitle(Bundle.getMessage("LocoFromRoster")); 1702 JLabel mtext = new JLabel(); 1703 mtext.setText(Bundle.getMessage("SelectLoco") + ":"); 1704 locoRosterFrame.getContentPane().add(mtext); 1705 final RosterEntrySelectorPanel rosterBox = new RosterEntrySelectorPanel(); 1706 rosterBox.addPropertyChangeListener("selectedRosterEntries", pce -> { 1707 if (rosterBox.getSelectedRosterEntries().length != 0) { 1708 selectLoco(rosterBox.getSelectedRosterEntries()[0]); 1709 } 1710 }); 1711 locoRosterFrame.getContentPane().add(rosterBox); 1712 locoRosterFrame.addWindowListener(new WindowAdapter() { 1713 @Override 1714 public void windowClosing(WindowEvent e) { 1715 locoRosterFrame.dispose(); 1716 } 1717 }); 1718 locoRosterFrame.pack(); 1719 locoRosterFrame.setVisible(true); 1720 } 1721 1722 protected LocoIcon selectLoco(String rosterEntryTitle) { 1723 if ("".equals(rosterEntryTitle)) { 1724 return null; 1725 } 1726 return selectLoco(Roster.getDefault().entryFromTitle(rosterEntryTitle)); 1727 } 1728 1729 protected LocoIcon selectLoco(RosterEntry entry) { 1730 LocoIcon l = null; 1731 if (entry == null) { 1732 return null; 1733 } 1734 // try getting road number, else use DCC address 1735 String rn = entry.getRoadNumber(); 1736 if ((rn == null) || rn.equals("")) { 1737 rn = entry.getDccAddress(); 1738 } 1739 if (rn != null) { 1740 l = addLocoIcon(rn); 1741 l.setRosterEntry(entry); 1742 } 1743 return l; 1744 } 1745 1746 protected void locoMarkerFromInput() { 1747 final JmriJFrame locoFrame = new JmriJFrame(); 1748 locoFrame.getContentPane().setLayout(new FlowLayout()); 1749 locoFrame.setTitle(Bundle.getMessage("EnterLocoMarker")); 1750 1751 JLabel textId = new JLabel(); 1752 textId.setText(Bundle.getMessage("LocoID") + ":"); 1753 locoFrame.getContentPane().add(textId); 1754 1755 final JTextField locoId = new JTextField(7); 1756 locoFrame.getContentPane().add(locoId); 1757 locoId.setText(""); 1758 locoId.setToolTipText(Bundle.getMessage("EnterLocoID")); 1759 JButton okay = new JButton(); 1760 okay.setText(Bundle.getMessage("ButtonOK")); 1761 okay.addActionListener(e -> { 1762 String nameID = locoId.getText(); 1763 if ((nameID != null) && !(nameID.trim().equals(""))) { 1764 addLocoIcon(nameID.trim()); 1765 } else { 1766 JmriJOptionPane.showMessageDialog(locoFrame, Bundle.getMessage("ErrorEnterLocoID"), 1767 Bundle.getMessage("ErrorTitle"), JmriJOptionPane.ERROR_MESSAGE); 1768 } 1769 }); 1770 locoFrame.getContentPane().add(okay); 1771 locoFrame.addWindowListener(new WindowAdapter() { 1772 @Override 1773 public void windowClosing(WindowEvent e) { 1774 locoFrame.dispose(); 1775 } 1776 }); 1777 locoFrame.pack(); 1778 if (_targetFrame != null) { 1779 locoFrame.setLocation(_targetFrame.getLocation()); 1780 } 1781 locoFrame.setVisible(true); 1782 } 1783 1784 /** 1785 * Remove marker icons from panel 1786 */ 1787 protected void removeMarkers() { 1788 log.debug("Remove markers"); 1789 for (int i = _contents.size() - 1; i >= 0; i--) { 1790 Positionable il = _contents.get(i); 1791 if (il instanceof LocoIcon) { 1792 il.remove(); 1793 if (il.getId() != null) { 1794 _idContents.remove(il.getId()); 1795 } 1796 for (String className : il.getClasses()) { 1797 _classContents.get(className).remove(il); 1798 } 1799 } 1800 } 1801 } 1802 1803 /* 1804 * *********************** End Marker Menu Methods ********************** 1805 */ 1806 /* 1807 * ************ Adding content to the panel ********************** 1808 */ 1809 public PositionableLabel setUpBackground(String name) { 1810 NamedIcon icon = NamedIcon.getIconByName(name); 1811 PositionableLabel l = new PositionableLabel(icon, this); 1812 l.setPopupUtility(null); // no text 1813 l.setPositionable(false); 1814 l.setShowToolTip(false); 1815 l.setSize(icon.getIconWidth(), icon.getIconHeight()); 1816 l.setDisplayLevel(BKG); 1817 l.setLocation(getNextBackgroundLeft(), 0); 1818 try { 1819 putItem(l); 1820 } catch (Positionable.DuplicateIdException e) { 1821 // This should never happen 1822 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 1823 } 1824 return l; 1825 } 1826 1827 protected PositionableLabel addLabel(String text) { 1828 PositionableLabel l = new PositionableLabel(text, this); 1829 l.setSize(l.getPreferredSize().width, l.getPreferredSize().height); 1830 l.setDisplayLevel(LABELS); 1831 setNextLocation(l); 1832 try { 1833 putItem(l); 1834 } catch (Positionable.DuplicateIdException e) { 1835 // This should never happen 1836 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 1837 } 1838 return l; 1839 } 1840 1841 /** 1842 * Determine right side x of furthest right background 1843 */ 1844 private int getNextBackgroundLeft() { 1845 int left = 0; 1846 // place to right of background images, if any 1847 for (Positionable p : _contents) { 1848 if (p instanceof PositionableLabel) { 1849 PositionableLabel l = (PositionableLabel) p; 1850 if (l.isBackground()) { 1851 int test = l.getX() + l.maxWidth(); 1852 if (test > left) { 1853 left = test; 1854 } 1855 } 1856 } 1857 } 1858 return left; 1859 } 1860 1861 /** 1862 * Positionable has set a new level. 1863 * Editor must change it in the target panel. 1864 * @param l the positionable to display. 1865 */ 1866 public void displayLevelChange(Positionable l) { 1867 ThreadingUtil.runOnGUI( () -> { 1868 removeFromTarget(l); 1869 addToTarget(l); 1870 }); 1871 } 1872 1873 public TrainIcon addTrainIcon(String name) { 1874 TrainIcon l = new TrainIcon(this); 1875 putLocoIcon(l, name); 1876 return l; 1877 } 1878 1879 public LocoIcon addLocoIcon(String name) { 1880 LocoIcon l = new LocoIcon(this); 1881 putLocoIcon(l, name); 1882 return l; 1883 } 1884 1885 public void putLocoIcon(LocoIcon l, String name) { 1886 l.setText(name); 1887 l.setHorizontalTextPosition(SwingConstants.CENTER); 1888 l.setSize(l.getPreferredSize().width, l.getPreferredSize().height); 1889 l.setEditable(isEditable()); // match popup mode to editor mode 1890 l.setLocation(75, 75); // fixed location 1891 try { 1892 putItem(l); 1893 } catch (Positionable.DuplicateIdException e) { 1894 // This should never happen 1895 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 1896 } 1897 } 1898 1899 public void putItem(@Nonnull Positionable l) throws Positionable.DuplicateIdException { 1900 ThreadingUtil.runOnGUI( () -> { 1901 l.invalidate(); 1902 l.setPositionable(true); 1903 l.setVisible(true); 1904 if (l.getToolTip() == null) { 1905 l.setToolTip(new ToolTip(_defaultToolTip, l)); 1906 } 1907 addToTarget(l); 1908 }); 1909 if (!_contents.add(l)) { 1910 log.error("Unable to add {} to _contents", l.getNameString()); 1911 } 1912 if (l.getId() != null) { 1913 if (_idContents.containsKey(l.getId())) { 1914 throw new Positionable.DuplicateIdException(); 1915 } 1916 _idContents.put(l.getId(), l); 1917 } 1918 for (String className : l.getClasses()) { 1919 _classContents.get(className).add(l); 1920 } 1921 if (log.isDebugEnabled()) { 1922 log.debug("putItem {} to _contents. level= {}", l.getNameString(), l.getDisplayLevel()); 1923 } 1924 } 1925 1926 protected void addToTarget(Positionable l) { 1927 JComponent c = (JComponent) l; 1928 c.invalidate(); 1929 _targetPanel.remove(c); 1930 _targetPanel.add(c, Integer.valueOf(l.getDisplayLevel())); 1931 _targetPanel.moveToFront(c); 1932 c.repaint(); 1933 _targetPanel.revalidate(); 1934 } 1935 1936 /* 1937 * ************ Icon editors for adding content *********** 1938 */ 1939 static final String[] ICON_EDITORS = {"Sensor", "RightTurnout", "LeftTurnout", 1940 "SlipTOEditor", "SignalHead", "SignalMast", "Memory", "Light", 1941 "Reporter", "Background", "MultiSensor", "Icon", "Text", "Block Contents"}; 1942 1943 /** 1944 * Create editor for a given item type. 1945 * Paths to default icons are fixed in code. Compare to respective icon package, 1946 * eg. {@link #addSensorEditor()} and {@link SensorIcon} 1947 * 1948 * @param name Icon editor's name 1949 * @return a window 1950 */ 1951 public JFrameItem getIconFrame(String name) { 1952 JFrameItem frame = _iconEditorFrame.get(name); 1953 if (frame == null) { 1954 if ("Sensor".equals(name)) { 1955 addSensorEditor(); 1956 } else if ("RightTurnout".equals(name)) { 1957 addRightTOEditor(); 1958 } else if ("LeftTurnout".equals(name)) { 1959 addLeftTOEditor(); 1960 } else if ("SlipTOEditor".equals(name)) { 1961 addSlipTOEditor(); 1962 } else if ("SignalHead".equals(name)) { 1963 addSignalHeadEditor(); 1964 } else if ("SignalMast".equals(name)) { 1965 addSignalMastEditor(); 1966 } else if ("Memory".equals(name)) { 1967 addMemoryEditor(); 1968 } else if ("GlobalVariable".equals(name)) { 1969 addGlobalVariableEditor(); 1970 } else if ("LogixNGTable".equals(name)) { 1971 addLogixNGTableEditor(); 1972 } else if ("Reporter".equals(name)) { 1973 addReporterEditor(); 1974 } else if ("Light".equals(name)) { 1975 addLightEditor(); 1976 } else if ("Background".equals(name)) { 1977 addBackgroundEditor(); 1978 } else if ("MultiSensor".equals(name)) { 1979 addMultiSensorEditor(); 1980 } else if ("Icon".equals(name)) { 1981 addIconEditor(); 1982 } else if ("Text".equals(name)) { 1983 addTextEditor(); 1984 } else if ("BlockLabel".equals(name)) { 1985 addBlockContentsEditor(); 1986 } else if ("Audio".equals(name)) { 1987 addAudioEditor(); 1988 } else if ("LogixNG".equals(name)) { 1989 addLogixNGEditor(); 1990 } else { 1991 // log.error("No such Icon Editor \"{}\"", name); 1992 return null; 1993 } 1994 // frame added in the above switch 1995 frame = _iconEditorFrame.get(name); 1996 1997 if (frame == null) { // addTextEditor does not create a usable frame 1998 return null; 1999 } 2000 //frame.setLocationRelativeTo(this); 2001 frame.setLocation(frameLocationX, frameLocationY); 2002 frameLocationX += DELTA; 2003 frameLocationY += DELTA; 2004 } 2005 frame.setVisible(true); 2006 return frame; 2007 } 2008 public int frameLocationX = 0; 2009 public int frameLocationY = 0; 2010 static final int DELTA = 20; 2011 2012 public IconAdder getIconEditor(String name) { 2013 return _iconEditorFrame.get(name).getEditor(); 2014 } 2015 2016 /** 2017 * Add a label to the target. 2018 */ 2019 protected void addTextEditor() { 2020 String newLabel = JmriJOptionPane.showInputDialog(this, Bundle.getMessage("PromptNewLabel"),""); 2021 if (newLabel == null) { 2022 return; // canceled 2023 } 2024 PositionableLabel l = addLabel(newLabel); 2025 // always allow new items to be moved 2026 l.setPositionable(true); 2027 } 2028 2029 protected void addRightTOEditor() { 2030 IconAdder editor = new IconAdder("RightTurnout"); 2031 editor.setIcon(3, "TurnoutStateClosed", 2032 "resources/icons/smallschematics/tracksegments/os-righthand-west-closed.gif"); 2033 editor.setIcon(2, "TurnoutStateThrown", 2034 "resources/icons/smallschematics/tracksegments/os-righthand-west-thrown.gif"); 2035 editor.setIcon(0, "BeanStateInconsistent", 2036 "resources/icons/smallschematics/tracksegments/os-righthand-west-error.gif"); 2037 editor.setIcon(1, "BeanStateUnknown", 2038 "resources/icons/smallschematics/tracksegments/os-righthand-west-unknown.gif"); 2039 2040 JFrameItem frame = makeAddIconFrame("RightTurnout", true, true, editor); 2041 _iconEditorFrame.put("RightTurnout", frame); 2042 editor.setPickList(PickListModel.turnoutPickModelInstance()); 2043 2044 ActionListener addIconAction = a -> addTurnoutR(); 2045 editor.makeIconPanel(true); 2046 editor.complete(addIconAction, true, true, false); 2047 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2048 } 2049 2050 protected void addLeftTOEditor() { 2051 IconAdder editor = new IconAdder("LeftTurnout"); 2052 editor.setIcon(3, "TurnoutStateClosed", 2053 "resources/icons/smallschematics/tracksegments/os-lefthand-east-closed.gif"); 2054 editor.setIcon(2, "TurnoutStateThrown", 2055 "resources/icons/smallschematics/tracksegments/os-lefthand-east-thrown.gif"); 2056 editor.setIcon(0, "BeanStateInconsistent", 2057 "resources/icons/smallschematics/tracksegments/os-lefthand-east-error.gif"); 2058 editor.setIcon(1, "BeanStateUnknown", 2059 "resources/icons/smallschematics/tracksegments/os-lefthand-east-unknown.gif"); 2060 2061 JFrameItem frame = makeAddIconFrame("LeftTurnout", true, true, editor); 2062 _iconEditorFrame.put("LeftTurnout", frame); 2063 editor.setPickList(PickListModel.turnoutPickModelInstance()); 2064 2065 ActionListener addIconAction = a -> addTurnoutL(); 2066 editor.makeIconPanel(true); 2067 editor.complete(addIconAction, true, true, false); 2068 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2069 } 2070 2071 protected void addSlipTOEditor() { 2072 SlipIconAdder editor = new SlipIconAdder("SlipTOEditor"); 2073 editor.setIcon(3, "LowerWestToUpperEast", 2074 "resources/icons/smallschematics/tracksegments/os-slip-lower-west-upper-east.gif"); 2075 editor.setIcon(2, "UpperWestToLowerEast", 2076 "resources/icons/smallschematics/tracksegments/os-slip-upper-west-lower-east.gif"); 2077 editor.setIcon(4, "LowerWestToLowerEast", 2078 "resources/icons/smallschematics/tracksegments/os-slip-lower-west-lower-east.gif"); 2079 editor.setIcon(5, "UpperWestToUpperEast", 2080 "resources/icons/smallschematics/tracksegments/os-slip-upper-west-upper-east.gif"); 2081 editor.setIcon(0, "BeanStateInconsistent", 2082 "resources/icons/smallschematics/tracksegments/os-slip-error-full.gif"); 2083 editor.setIcon(1, "BeanStateUnknown", 2084 "resources/icons/smallschematics/tracksegments/os-slip-unknown-full.gif"); 2085 editor.setTurnoutType(SlipTurnoutIcon.DOUBLESLIP); 2086 JFrameItem frame = makeAddIconFrame("SlipTOEditor", true, true, editor); 2087 _iconEditorFrame.put("SlipTOEditor", frame); 2088 editor.setPickList(PickListModel.turnoutPickModelInstance()); 2089 2090 ActionListener addIconAction = a -> addSlip(); 2091 editor.makeIconPanel(true); 2092 editor.complete(addIconAction, true, true, false); 2093 frame.addHelpMenu("package.jmri.jmrit.display.SlipTurnoutIcon", true); 2094 } 2095 2096 protected void addSensorEditor() { 2097 IconAdder editor = new IconAdder("Sensor"); 2098 editor.setIcon(3, "SensorStateActive", 2099 "resources/icons/smallschematics/tracksegments/circuit-occupied.gif"); 2100 editor.setIcon(2, "SensorStateInactive", 2101 "resources/icons/smallschematics/tracksegments/circuit-empty.gif"); 2102 editor.setIcon(0, "BeanStateInconsistent", 2103 "resources/icons/smallschematics/tracksegments/circuit-error.gif"); 2104 editor.setIcon(1, "BeanStateUnknown", 2105 "resources/icons/smallschematics/tracksegments/circuit-error.gif"); 2106 2107 JFrameItem frame = makeAddIconFrame("Sensor", true, true, editor); 2108 _iconEditorFrame.put("Sensor", frame); 2109 editor.setPickList(PickListModel.sensorPickModelInstance()); 2110 2111 ActionListener addIconAction = a -> putSensor(); 2112 editor.makeIconPanel(true); 2113 editor.complete(addIconAction, true, true, false); 2114 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2115 } 2116 2117 protected void addSignalHeadEditor() { 2118 IconAdder editor = getSignalHeadEditor(); 2119 JFrameItem frame = makeAddIconFrame("SignalHead", true, true, editor); 2120 _iconEditorFrame.put("SignalHead", frame); 2121 editor.setPickList(PickListModel.signalHeadPickModelInstance()); 2122 2123 ActionListener addIconAction = a -> putSignalHead(); 2124 editor.makeIconPanel(true); 2125 editor.complete(addIconAction, true, false, false); 2126 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2127 } 2128 2129 protected IconAdder getSignalHeadEditor() { 2130 // note that all these icons will be refreshed when user clicks a specific signal head in the table 2131 IconAdder editor = new IconAdder("SignalHead"); 2132 editor.setIcon(0, "SignalHeadStateRed", 2133 "resources/icons/smallschematics/searchlights/left-red-marker.gif"); 2134 editor.setIcon(1, "SignalHeadStateYellow", 2135 "resources/icons/smallschematics/searchlights/left-yellow-marker.gif"); 2136 editor.setIcon(2, "SignalHeadStateGreen", 2137 "resources/icons/smallschematics/searchlights/left-green-marker.gif"); 2138 editor.setIcon(3, "SignalHeadStateDark", 2139 "resources/icons/smallschematics/searchlights/left-dark-marker.gif"); 2140 editor.setIcon(4, "SignalHeadStateHeld", 2141 "resources/icons/smallschematics/searchlights/left-held-marker.gif"); 2142 editor.setIcon(5, "SignalHeadStateLunar", 2143 "resources/icons/smallschematics/searchlights/left-lunar-marker.gif"); 2144 editor.setIcon(6, "SignalHeadStateFlashingRed", 2145 "resources/icons/smallschematics/searchlights/left-flashred-marker.gif"); 2146 editor.setIcon(7, "SignalHeadStateFlashingYellow", 2147 "resources/icons/smallschematics/searchlights/left-flashyellow-marker.gif"); 2148 editor.setIcon(8, "SignalHeadStateFlashingGreen", 2149 "resources/icons/smallschematics/searchlights/left-flashgreen-marker.gif"); 2150 editor.setIcon(9, "SignalHeadStateFlashingLunar", 2151 "resources/icons/smallschematics/searchlights/left-flashlunar-marker.gif"); 2152 return editor; 2153 } 2154 2155 protected void addSignalMastEditor() { 2156 IconAdder editor = new IconAdder("SignalMast"); 2157 2158 JFrameItem frame = makeAddIconFrame("SignalMast", true, true, editor); 2159 _iconEditorFrame.put("SignalMast", frame); 2160 editor.setPickList(PickListModel.signalMastPickModelInstance()); 2161 2162 ActionListener addIconAction = a -> putSignalMast(); 2163 editor.makeIconPanel(true); 2164 editor.complete(addIconAction, true, false, false); 2165 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2166 } 2167 2168 private final SpinnerNumberModel _spinCols = new SpinnerNumberModel(3, 1, 100, 1); 2169 2170 protected void addMemoryEditor() { 2171 IconAdder editor = new IconAdder("Memory") { 2172 final JButton bSpin = new JButton(Bundle.getMessage("AddSpinner")); 2173 final JButton bBox = new JButton(Bundle.getMessage("AddInputBox")); 2174 final JSpinner spinner = new JSpinner(_spinCols); 2175 2176 @Override 2177 protected void addAdditionalButtons(JPanel p) { 2178 bSpin.addActionListener(a -> addMemorySpinner()); 2179 JPanel p1 = new JPanel(); 2180 //p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS)); 2181 bBox.addActionListener(a -> addMemoryInputBox()); 2182 ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField().setColumns(2); 2183 spinner.setMaximumSize(spinner.getPreferredSize()); 2184 JPanel p2 = new JPanel(); 2185 p2.add(new JLabel(Bundle.getMessage("NumColsLabel"))); 2186 p2.add(spinner); 2187 p1.add(p2); 2188 p1.add(bBox); 2189 p.add(p1); 2190 p1 = new JPanel(); 2191 p1.add(bSpin); 2192 p.add(p1); 2193 } 2194 2195 @Override 2196 public void valueChanged(ListSelectionEvent e) { 2197 super.valueChanged(e); 2198 bSpin.setEnabled(addIconIsEnabled()); 2199 bBox.setEnabled(addIconIsEnabled()); 2200 } 2201 }; 2202 ActionListener addIconAction = a -> putMemory(); 2203 JFrameItem frame = makeAddIconFrame("Memory", true, true, editor); 2204 _iconEditorFrame.put("Memory", frame); 2205 editor.setPickList(PickListModel.memoryPickModelInstance()); 2206 editor.makeIconPanel(true); 2207 editor.complete(addIconAction, false, true, false); 2208 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2209 } 2210 2211 protected void addGlobalVariableEditor() { 2212 IconAdder editor = new IconAdder("GlobalVariable") { 2213 final JButton bSpin = new JButton(Bundle.getMessage("AddSpinner")); 2214 final JButton bBox = new JButton(Bundle.getMessage("AddInputBox")); 2215 final JSpinner spinner = new JSpinner(_spinCols); 2216 2217 @Override 2218 protected void addAdditionalButtons(JPanel p) { 2219 bSpin.addActionListener(a -> addGlobalVariableSpinner()); 2220 JPanel p1 = new JPanel(); 2221 //p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS)); 2222 bBox.addActionListener(a -> addGlobalVariableInputBox()); 2223 ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField().setColumns(2); 2224 spinner.setMaximumSize(spinner.getPreferredSize()); 2225 JPanel p2 = new JPanel(); 2226 p2.add(new JLabel(Bundle.getMessage("NumColsLabel"))); 2227 p2.add(spinner); 2228 p1.add(p2); 2229 p1.add(bBox); 2230 p.add(p1); 2231 p1 = new JPanel(); 2232 p1.add(bSpin); 2233 p.add(p1); 2234 } 2235 2236 @Override 2237 public void valueChanged(ListSelectionEvent e) { 2238 super.valueChanged(e); 2239 bSpin.setEnabled(addIconIsEnabled()); 2240 bBox.setEnabled(addIconIsEnabled()); 2241 } 2242 }; 2243 ActionListener addIconAction = a -> putGlobalVariable(); 2244 JFrameItem frame = makeAddIconFrame("GlobalVariable", true, true, editor); 2245 _iconEditorFrame.put("GlobalVariable", frame); 2246 editor.setPickList(PickListModel.globalVariablePickModelInstance()); 2247 editor.makeIconPanel(true); 2248 editor.complete(addIconAction, false, false, false); 2249 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2250 } 2251 2252 protected void addLogixNGTableEditor() { 2253 IconAdder editor = new IconAdder("LogixNGTable"); 2254 ActionListener addIconAction = a -> addLogixNGTable(); 2255 JFrameItem frame = makeAddIconFrame("LogixNGTable", true, true, editor); 2256 _iconEditorFrame.put("LogixNGTable", frame); 2257 editor.setPickList(PickListModel.namedTablePickModelInstance()); 2258 editor.makeIconPanel(true); 2259 editor.complete(addIconAction, false, false, false); 2260 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2261 } 2262 2263 protected void addBlockContentsEditor() { 2264 IconAdder editor = new IconAdder("Block Contents"); 2265 ActionListener addIconAction = a -> putBlockContents(); 2266 JFrameItem frame = makeAddIconFrame("BlockLabel", true, true, editor); 2267 _iconEditorFrame.put("BlockLabel", frame); 2268 editor.setPickList(PickListModel.blockPickModelInstance()); 2269 editor.makeIconPanel(true); 2270 editor.complete(addIconAction, false, true, false); 2271 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2272 } 2273 2274 protected void addReporterEditor() { 2275 IconAdder editor = new IconAdder("Reporter"); 2276 ActionListener addIconAction = a -> addReporter(); 2277 JFrameItem frame = makeAddIconFrame("Reporter", true, true, editor); 2278 _iconEditorFrame.put("Reporter", frame); 2279 editor.setPickList(PickListModel.reporterPickModelInstance()); 2280 editor.makeIconPanel(true); 2281 editor.complete(addIconAction, false, true, false); 2282 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2283 } 2284 2285 protected void addLightEditor() { 2286 IconAdder editor = new IconAdder("Light"); 2287 editor.setIcon(3, "StateOff", 2288 "resources/icons/smallschematics/lights/cross-on.png"); 2289 editor.setIcon(2, "StateOn", 2290 "resources/icons/smallschematics/lights/cross-off.png"); 2291 editor.setIcon(0, "BeanStateInconsistent", 2292 "resources/icons/smallschematics/lights/cross-inconsistent.png"); 2293 editor.setIcon(1, "BeanStateUnknown", 2294 "resources/icons/smallschematics/lights/cross-unknown.png"); 2295 2296 JFrameItem frame = makeAddIconFrame("Light", true, true, editor); 2297 _iconEditorFrame.put("Light", frame); 2298 editor.setPickList(PickListModel.lightPickModelInstance()); 2299 2300 ActionListener addIconAction = a -> addLight(); 2301 editor.makeIconPanel(true); 2302 editor.complete(addIconAction, true, true, false); 2303 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2304 } 2305 2306 protected void addBackgroundEditor() { 2307 IconAdder editor = new IconAdder("Background"); 2308 editor.setIcon(0, "background", "resources/PanelPro.gif"); 2309 2310 JFrameItem frame = makeAddIconFrame("Background", true, false, editor); 2311 _iconEditorFrame.put("Background", frame); 2312 2313 ActionListener addIconAction = a -> putBackground(); 2314 editor.makeIconPanel(true); 2315 editor.complete(addIconAction, true, false, false); 2316 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2317 } 2318 2319 protected JFrameItem addMultiSensorEditor() { 2320 MultiSensorIconAdder editor = new MultiSensorIconAdder("MultiSensor"); 2321 editor.setIcon(0, "BeanStateInconsistent", 2322 "resources/icons/USS/plate/levers/l-inconsistent.gif"); 2323 editor.setIcon(1, "BeanStateUnknown", 2324 "resources/icons/USS/plate/levers/l-unknown.gif"); 2325 editor.setIcon(2, "SensorStateInactive", 2326 "resources/icons/USS/plate/levers/l-inactive.gif"); 2327 editor.setIcon(3, "MultiSensorPosition 0", 2328 "resources/icons/USS/plate/levers/l-left.gif"); 2329 editor.setIcon(4, "MultiSensorPosition 1", 2330 "resources/icons/USS/plate/levers/l-vertical.gif"); 2331 editor.setIcon(5, "MultiSensorPosition 2", 2332 "resources/icons/USS/plate/levers/l-right.gif"); 2333 2334 JFrameItem frame = makeAddIconFrame("MultiSensor", true, false, editor); 2335 _iconEditorFrame.put("MultiSensor", frame); 2336 frame.addHelpMenu("package.jmri.jmrit.display.MultiSensorIconAdder", true); 2337 2338 editor.setPickList(PickListModel.sensorPickModelInstance()); 2339 2340 ActionListener addIconAction = a -> addMultiSensor(); 2341 editor.makeIconPanel(true); 2342 editor.complete(addIconAction, true, true, false); 2343 return frame; 2344 } 2345 2346 protected void addIconEditor() { 2347 IconAdder editor = new IconAdder("Icon"); 2348 editor.setIcon(0, "plainIcon", "resources/icons/smallschematics/tracksegments/block.gif"); 2349 JFrameItem frame = makeAddIconFrame("Icon", true, false, editor); 2350 _iconEditorFrame.put("Icon", frame); 2351 2352 ActionListener addIconAction = a -> putIcon(); 2353 editor.makeIconPanel(true); 2354 editor.complete(addIconAction, true, false, false); 2355 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2356 } 2357 2358 protected void addAudioEditor() { 2359 IconAdder editor = new IconAdder("Audio"); 2360 editor.setIcon(0, "plainIcon", "resources/icons/audio_icon.gif"); 2361 JFrameItem frame = makeAddIconFrame("Audio", true, false, editor); 2362 _iconEditorFrame.put("Audio", frame); 2363 editor.setPickList(PickListModel.audioPickModelInstance()); 2364 2365 ActionListener addIconAction = a -> putAudio(); 2366 editor.makeIconPanel(true); 2367 editor.complete(addIconAction, true, false, false); 2368 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2369 } 2370 2371 protected void addLogixNGEditor() { 2372 IconAdder editor = new IconAdder("LogixNG"); 2373 editor.setIcon(0, "plainIcon", "resources/icons/logixng/logixng_icon.gif"); 2374 JFrameItem frame = makeAddIconFrame("LogixNG", true, false, editor); 2375 _iconEditorFrame.put("LogixNG", frame); 2376 2377 ActionListener addIconAction = a -> putLogixNG(); 2378 editor.makeIconPanel(true); 2379 editor.complete(addIconAction, true, false, false); 2380 frame.addHelpMenu("package.jmri.jmrit.display.IconAdder", true); 2381 } 2382 2383 /* 2384 * ************** add content items from Icon Editors ******************* 2385 */ 2386 /** 2387 * Add a sensor indicator to the target. 2388 * 2389 * @return The sensor that was added to the panel. 2390 */ 2391 protected SensorIcon putSensor() { 2392 SensorIcon result = new SensorIcon(new NamedIcon("resources/icons/smallschematics/tracksegments/circuit-error.gif", 2393 "resources/icons/smallschematics/tracksegments/circuit-error.gif"), this); 2394 IconAdder editor = getIconEditor("Sensor"); 2395 Hashtable<String, NamedIcon> map = editor.getIconMap(); 2396 Enumeration<String> e = map.keys(); 2397 while (e.hasMoreElements()) { 2398 String key = e.nextElement(); 2399 result.setIcon(key, map.get(key)); 2400 } 2401// l.setActiveIcon(editor.getIcon("SensorStateActive")); 2402// l.setInactiveIcon(editor.getIcon("SensorStateInactive")); 2403// l.setInconsistentIcon(editor.getIcon("BeanStateInconsistent")); 2404// l.setUnknownIcon(editor.getIcon("BeanStateUnknown")); 2405 NamedBean b = editor.getTableSelection(); 2406 if (b != null) { 2407 result.setSensor(b.getDisplayName()); 2408 } 2409 result.setDisplayLevel(SENSORS); 2410 setNextLocation(result); 2411 try { 2412 putItem(result); 2413 } catch (Positionable.DuplicateIdException ex) { 2414 // This should never happen 2415 log.error("Editor.putItem() with null id has thrown DuplicateIdException", ex); 2416 } 2417 return result; 2418 } 2419 2420 /** 2421 * Add a turnout indicator to the target 2422 */ 2423 void addTurnoutR() { 2424 IconAdder editor = getIconEditor("RightTurnout"); 2425 addTurnout(editor); 2426 } 2427 2428 void addTurnoutL() { 2429 IconAdder editor = getIconEditor("LeftTurnout"); 2430 addTurnout(editor); 2431 } 2432 2433 protected TurnoutIcon addTurnout(IconAdder editor) { 2434 TurnoutIcon result = new TurnoutIcon(this); 2435 result.setTurnout(editor.getTableSelection().getDisplayName()); 2436 Hashtable<String, NamedIcon> map = editor.getIconMap(); 2437 Enumeration<String> e = map.keys(); 2438 while (e.hasMoreElements()) { 2439 String key = e.nextElement(); 2440 result.setIcon(key, map.get(key)); 2441 } 2442 result.setDisplayLevel(TURNOUTS); 2443 setNextLocation(result); 2444 try { 2445 putItem(result); 2446 } catch (Positionable.DuplicateIdException ex) { 2447 // This should never happen 2448 log.error("Editor.putItem() with null id has thrown DuplicateIdException", ex); 2449 } 2450 return result; 2451 } 2452 2453 @SuppressFBWarnings(value="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", justification="iconEditor requested as exact type") 2454 SlipTurnoutIcon addSlip() { 2455 SlipTurnoutIcon result = new SlipTurnoutIcon(this); 2456 SlipIconAdder editor = (SlipIconAdder) getIconEditor("SlipTOEditor"); 2457 result.setSingleSlipRoute(editor.getSingleSlipRoute()); 2458 2459 switch (editor.getTurnoutType()) { 2460 case SlipTurnoutIcon.DOUBLESLIP: 2461 result.setLowerWestToUpperEastIcon(editor.getIcon("LowerWestToUpperEast")); 2462 result.setUpperWestToLowerEastIcon(editor.getIcon("UpperWestToLowerEast")); 2463 result.setLowerWestToLowerEastIcon(editor.getIcon("LowerWestToLowerEast")); 2464 result.setUpperWestToUpperEastIcon(editor.getIcon("UpperWestToUpperEast")); 2465 break; 2466 case SlipTurnoutIcon.SINGLESLIP: 2467 result.setLowerWestToUpperEastIcon(editor.getIcon("LowerWestToUpperEast")); 2468 result.setUpperWestToLowerEastIcon(editor.getIcon("UpperWestToLowerEast")); 2469 result.setLowerWestToLowerEastIcon(editor.getIcon("Slip")); 2470 result.setSingleSlipRoute(editor.getSingleSlipRoute()); 2471 break; 2472 case SlipTurnoutIcon.THREEWAY: 2473 result.setLowerWestToUpperEastIcon(editor.getIcon("Upper")); 2474 result.setUpperWestToLowerEastIcon(editor.getIcon("Middle")); 2475 result.setLowerWestToLowerEastIcon(editor.getIcon("Lower")); 2476 result.setSingleSlipRoute(editor.getSingleSlipRoute()); 2477 break; 2478 case SlipTurnoutIcon.SCISSOR: //Scissor is the same as a Double for icon storing. 2479 result.setLowerWestToUpperEastIcon(editor.getIcon("LowerWestToUpperEast")); 2480 result.setUpperWestToLowerEastIcon(editor.getIcon("UpperWestToLowerEast")); 2481 result.setLowerWestToLowerEastIcon(editor.getIcon("LowerWestToLowerEast")); 2482 //l.setUpperWestToUpperEastIcon(editor.getIcon("UpperWestToUpperEast")); 2483 break; 2484 default: 2485 log.warn("Unexpected addSlip editor.getTurnoutType() of {}", editor.getTurnoutType()); 2486 break; 2487 } 2488 2489 if ((editor.getTurnoutType() == SlipTurnoutIcon.SCISSOR) && (!editor.getSingleSlipRoute())) { 2490 result.setTurnout(editor.getTurnout("lowerwest").getName(), SlipTurnoutIcon.LOWERWEST); 2491 result.setTurnout(editor.getTurnout("lowereast").getName(), SlipTurnoutIcon.LOWEREAST); 2492 } 2493 result.setInconsistentIcon(editor.getIcon("BeanStateInconsistent")); 2494 result.setUnknownIcon(editor.getIcon("BeanStateUnknown")); 2495 result.setTurnoutType(editor.getTurnoutType()); 2496 result.setTurnout(editor.getTurnout("west").getName(), SlipTurnoutIcon.WEST); 2497 result.setTurnout(editor.getTurnout("east").getName(), SlipTurnoutIcon.EAST); 2498 result.setDisplayLevel(TURNOUTS); 2499 setNextLocation(result); 2500 try { 2501 putItem(result); 2502 } catch (Positionable.DuplicateIdException e) { 2503 // This should never happen 2504 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2505 } 2506 return result; 2507 } 2508 2509 /** 2510 * Add a signal head to the target. 2511 * 2512 * @return The signal head that was added to the target. 2513 */ 2514 protected SignalHeadIcon putSignalHead() { 2515 SignalHeadIcon result = new SignalHeadIcon(this); 2516 IconAdder editor = getIconEditor("SignalHead"); 2517 result.setSignalHead(editor.getTableSelection().getDisplayName()); 2518 Hashtable<String, NamedIcon> map = editor.getIconMap(); 2519 Enumeration<String> e = map.keys(); 2520 while (e.hasMoreElements()) { 2521 String key = e.nextElement(); 2522 result.setIcon(key, map.get(key)); 2523 } 2524 result.setDisplayLevel(SIGNALS); 2525 setNextLocation(result); 2526 try { 2527 putItem(result); 2528 } catch (Positionable.DuplicateIdException ex) { 2529 // This should never happen 2530 log.error("Editor.putItem() with null id has thrown DuplicateIdException", ex); 2531 } 2532 return result; 2533 } 2534 2535 /** 2536 * Add a signal mast to the target. 2537 * 2538 * @return The signal mast that was added to the target. 2539 */ 2540 protected SignalMastIcon putSignalMast() { 2541 SignalMastIcon result = new SignalMastIcon(this); 2542 IconAdder editor = _iconEditorFrame.get("SignalMast").getEditor(); 2543 result.setSignalMast(editor.getTableSelection().getDisplayName()); 2544 result.setDisplayLevel(SIGNALS); 2545 setNextLocation(result); 2546 try { 2547 putItem(result); 2548 } catch (Positionable.DuplicateIdException e) { 2549 // This should never happen 2550 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2551 } 2552 return result; 2553 } 2554 2555 protected MemoryIcon putMemory() { 2556 MemoryIcon result = new MemoryIcon(new NamedIcon("resources/icons/misc/X-red.gif", 2557 "resources/icons/misc/X-red.gif"), this); 2558 IconAdder memoryIconEditor = getIconEditor("Memory"); 2559 result.setMemory(memoryIconEditor.getTableSelection().getDisplayName()); 2560 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2561 result.setDisplayLevel(MEMORIES); 2562 setNextLocation(result); 2563 try { 2564 putItem(result); 2565 } catch (Positionable.DuplicateIdException e) { 2566 // This should never happen 2567 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2568 } 2569 return result; 2570 } 2571 2572 protected MemorySpinnerIcon addMemorySpinner() { 2573 MemorySpinnerIcon result = new MemorySpinnerIcon(this); 2574 IconAdder memoryIconEditor = getIconEditor("Memory"); 2575 result.setMemory(memoryIconEditor.getTableSelection().getDisplayName()); 2576 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2577 result.setDisplayLevel(MEMORIES); 2578 setNextLocation(result); 2579 try { 2580 putItem(result); 2581 } catch (Positionable.DuplicateIdException e) { 2582 // This should never happen 2583 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2584 } 2585 return result; 2586 } 2587 2588 protected MemoryInputIcon addMemoryInputBox() { 2589 MemoryInputIcon result = new MemoryInputIcon(_spinCols.getNumber().intValue(), this); 2590 IconAdder memoryIconEditor = getIconEditor("Memory"); 2591 result.setMemory(memoryIconEditor.getTableSelection().getDisplayName()); 2592 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2593 result.setDisplayLevel(MEMORIES); 2594 setNextLocation(result); 2595 try { 2596 putItem(result); 2597 } catch (Positionable.DuplicateIdException e) { 2598 // This should never happen 2599 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2600 } 2601 return result; 2602 } 2603 2604 protected GlobalVariableIcon putGlobalVariable() { 2605 GlobalVariableIcon result = new GlobalVariableIcon(new NamedIcon("resources/icons/misc/X-red.gif", 2606 "resources/icons/misc/X-red.gif"), this); 2607 IconAdder globalVariableIconEditor = getIconEditor("GlobalVariable"); 2608 result.setGlobalVariable(globalVariableIconEditor.getTableSelection().getDisplayName()); 2609 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2610 result.setDisplayLevel(MEMORIES); 2611 setNextLocation(result); 2612 try { 2613 putItem(result); 2614 } catch (Positionable.DuplicateIdException e) { 2615 // This should never happen 2616 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2617 } 2618 return result; 2619 } 2620 2621 protected GlobalVariableSpinnerIcon addGlobalVariableSpinner() { 2622 GlobalVariableSpinnerIcon result = new GlobalVariableSpinnerIcon(this); 2623 IconAdder globalVariableIconEditor = getIconEditor("GlobalVariable"); 2624 result.setGlobalVariable(globalVariableIconEditor.getTableSelection().getDisplayName()); 2625 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2626 result.setDisplayLevel(MEMORIES); 2627 setNextLocation(result); 2628 try { 2629 putItem(result); 2630 } catch (Positionable.DuplicateIdException e) { 2631 // This should never happen 2632 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2633 } 2634 return result; 2635 } 2636 2637 protected GlobalVariableInputIcon addGlobalVariableInputBox() { 2638 GlobalVariableInputIcon result = new GlobalVariableInputIcon(_spinCols.getNumber().intValue(), this); 2639 IconAdder globalVariableIconEditor = getIconEditor("GlobalVariable"); 2640 result.setGlobalVariable(globalVariableIconEditor.getTableSelection().getDisplayName()); 2641 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2642 result.setDisplayLevel(MEMORIES); 2643 setNextLocation(result); 2644 try { 2645 putItem(result); 2646 } catch (Positionable.DuplicateIdException e) { 2647 // This should never happen 2648 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2649 } 2650 return result; 2651 } 2652 2653 protected LogixNGTableIcon addLogixNGTable() { 2654 IconAdder logixNGTableIconEditor = getIconEditor("LogixNGTable"); 2655 LogixNGTableIcon result = new LogixNGTableIcon(logixNGTableIconEditor.getTableSelection().getDisplayName(), this); 2656 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2657 result.setDisplayLevel(MEMORIES); 2658 setNextLocation(result); 2659 try { 2660 putItem(result); 2661 } catch (Positionable.DuplicateIdException e) { 2662 // This should never happen 2663 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2664 } 2665 return result; 2666 } 2667 2668 protected BlockContentsIcon putBlockContents() { 2669 BlockContentsIcon result = new BlockContentsIcon(new NamedIcon("resources/icons/misc/X-red.gif", 2670 "resources/icons/misc/X-red.gif"), this); 2671 IconAdder blockIconEditor = getIconEditor("BlockLabel"); 2672 result.setBlock(blockIconEditor.getTableSelection().getDisplayName()); 2673 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2674 result.setDisplayLevel(MEMORIES); 2675 setNextLocation(result); 2676 try { 2677 putItem(result); 2678 } catch (Positionable.DuplicateIdException e) { 2679 // This should never happen 2680 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2681 } 2682 return result; 2683 } 2684 2685 /** 2686 * Add a Light indicator to the target 2687 * 2688 * @return The light indicator that was added to the target. 2689 */ 2690 protected LightIcon addLight() { 2691 LightIcon result = new LightIcon(this); 2692 IconAdder editor = getIconEditor("Light"); 2693 result.setOffIcon(editor.getIcon("StateOff")); 2694 result.setOnIcon(editor.getIcon("StateOn")); 2695 result.setInconsistentIcon(editor.getIcon("BeanStateInconsistent")); 2696 result.setUnknownIcon(editor.getIcon("BeanStateUnknown")); 2697 result.setLight((Light) editor.getTableSelection()); 2698 result.setDisplayLevel(LIGHTS); 2699 setNextLocation(result); 2700 try { 2701 putItem(result); 2702 } catch (Positionable.DuplicateIdException e) { 2703 // This should never happen 2704 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2705 } 2706 return result; 2707 } 2708 2709 protected ReporterIcon addReporter() { 2710 ReporterIcon result = new ReporterIcon(this); 2711 IconAdder reporterIconEditor = getIconEditor("Reporter"); 2712 result.setReporter((Reporter) reporterIconEditor.getTableSelection()); 2713 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2714 result.setDisplayLevel(REPORTERS); 2715 setNextLocation(result); 2716 try { 2717 putItem(result); 2718 } catch (Positionable.DuplicateIdException e) { 2719 // This should never happen 2720 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2721 } 2722 return result; 2723 } 2724 2725 /** 2726 * Button pushed, add a background image. Note that a background image 2727 * differs from a regular icon only in the level at which it's presented. 2728 */ 2729 void putBackground() { 2730 // most likely the image is scaled. get full size from URL 2731 IconAdder bkgrndEditor = getIconEditor("Background"); 2732 String url = bkgrndEditor.getIcon("background").getURL(); 2733 setUpBackground(url); 2734 } 2735 2736 /** 2737 * Add an icon to the target. 2738 * 2739 * @return The icon that was added to the target. 2740 */ 2741 protected Positionable putIcon() { 2742 IconAdder iconEditor = getIconEditor("Icon"); 2743 String url = iconEditor.getIcon("plainIcon").getURL(); 2744 NamedIcon icon = NamedIcon.getIconByName(url); 2745 if (log.isDebugEnabled()) { 2746 log.debug("putIcon: {} url= {}", (icon == null ? "null" : "icon"), url); 2747 } 2748 PositionableLabel result = new PositionableLabel(icon, this); 2749// l.setPopupUtility(null); // no text 2750 result.setDisplayLevel(ICONS); 2751 setNextLocation(result); 2752 try { 2753 putItem(result); 2754 } catch (Positionable.DuplicateIdException e) { 2755 // This should never happen 2756 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2757 } 2758 result.updateSize(); 2759 return result; 2760 } 2761 2762 /** 2763 * Add a LogixNG icon to the target. 2764 * 2765 * @return The LogixNG icon that was added to the target. 2766 */ 2767 protected Positionable putAudio() { 2768 IconAdder iconEditor = getIconEditor("Audio"); 2769 String url = iconEditor.getIcon("plainIcon").getURL(); 2770 NamedIcon icon = NamedIcon.getIconByName(url); 2771 if (log.isDebugEnabled()) { 2772 log.debug("putAudio: {} url= {}", (icon == null ? "null" : "icon"), url); 2773 } 2774 AudioIcon result = new AudioIcon(icon, this); 2775 NamedBean b = iconEditor.getTableSelection(); 2776 if (b != null) { 2777 result.setAudio(b.getDisplayName()); 2778 } 2779// l.setPopupUtility(null); // no text 2780 result.setDisplayLevel(ICONS); 2781 setNextLocation(result); 2782 try { 2783 putItem(result); 2784 } catch (Positionable.DuplicateIdException e) { 2785 // This should never happen 2786 log.error("Editor.putAudio() with null id has thrown DuplicateIdException", e); 2787 } 2788 result.updateSize(); 2789 return result; 2790 } 2791 2792 /** 2793 * Add a LogixNG icon to the target. 2794 * 2795 * @return The LogixNG icon that was added to the target. 2796 */ 2797 protected Positionable putLogixNG() { 2798 IconAdder iconEditor = getIconEditor("LogixNG"); 2799 String url = iconEditor.getIcon("plainIcon").getURL(); 2800 NamedIcon icon = NamedIcon.getIconByName(url); 2801 if (log.isDebugEnabled()) { 2802 log.debug("putLogixNG: {} url= {}", (icon == null ? "null" : "icon"), url); 2803 } 2804 LogixNGIcon result = new LogixNGIcon(icon, this); 2805// l.setPopupUtility(null); // no text 2806 result.setDisplayLevel(ICONS); 2807 setNextLocation(result); 2808 try { 2809 putItem(result); 2810 } catch (Positionable.DuplicateIdException e) { 2811 // This should never happen 2812 log.error("Editor.putLogixNG() with null id has thrown DuplicateIdException", e); 2813 } 2814 result.updateSize(); 2815 return result; 2816 } 2817 2818 @SuppressFBWarnings(value="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", justification="iconEditor requested as exact type") 2819 public MultiSensorIcon addMultiSensor() { 2820 MultiSensorIcon result = new MultiSensorIcon(this); 2821 MultiSensorIconAdder editor = (MultiSensorIconAdder) getIconEditor("MultiSensor"); 2822 result.setUnknownIcon(editor.getIcon("BeanStateUnknown")); 2823 result.setInconsistentIcon(editor.getIcon("BeanStateInconsistent")); 2824 result.setInactiveIcon(editor.getIcon("SensorStateInactive")); 2825 int numPositions = editor.getNumIcons(); 2826 for (int i = 3; i < numPositions; i++) { 2827 NamedIcon icon = editor.getIcon(i); 2828 String sensor = editor.getSensor(i).getName(); 2829 result.addEntry(sensor, icon); 2830 } 2831 result.setUpDown(editor.getUpDown()); 2832 result.setDisplayLevel(SENSORS); 2833 setNextLocation(result); 2834 try { 2835 putItem(result); 2836 } catch (Positionable.DuplicateIdException e) { 2837 // This should never happen 2838 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2839 } 2840 return result; 2841 } 2842 2843 protected AnalogClock2Display addClock() { 2844 AnalogClock2Display result = new AnalogClock2Display(this); 2845 result.setOpaque(false); 2846 result.update(); 2847 result.setDisplayLevel(CLOCK); 2848 setNextLocation(result); 2849 try { 2850 putItem(result); 2851 } catch (Positionable.DuplicateIdException e) { 2852 // This should never happen 2853 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2854 } 2855 return result; 2856 } 2857 2858 protected RpsPositionIcon addRpsReporter() { 2859 RpsPositionIcon result = new RpsPositionIcon(this); 2860 result.setSize(result.getPreferredSize().width, result.getPreferredSize().height); 2861 result.setDisplayLevel(SENSORS); 2862 setNextLocation(result); 2863 try { 2864 putItem(result); 2865 } catch (Positionable.DuplicateIdException e) { 2866 // This should never happen 2867 log.error("Editor.putItem() with null id has thrown DuplicateIdException", e); 2868 } 2869 return result; 2870 } 2871 2872 /* 2873 * ****************** end adding content ******************** 2874 */ 2875 /* 2876 * ********************* Icon Editors utils *************************** 2877 */ 2878 public static class JFrameItem extends JmriJFrame { 2879 2880 private final IconAdder _editor; 2881 2882 JFrameItem(String name, IconAdder editor) { 2883 super(name); 2884 _editor = editor; 2885 setName(name); 2886 } 2887 2888 public IconAdder getEditor() { 2889 return _editor; 2890 } 2891 2892 @Override 2893 public String toString() { 2894 return this.getName(); 2895 } 2896 } 2897 2898 public void setTitle() { 2899 String name = _targetFrame.getTitle(); 2900 if (name == null || name.equals("")) { 2901 super.setTitle(Bundle.getMessage("LabelEditor")); 2902 } else { 2903 super.setTitle(name + " " + Bundle.getMessage("LabelEditor")); 2904 } 2905 for (JFrameItem frame : _iconEditorFrame.values()) { 2906 frame.setTitle(frame.getName() + " (" + name + ")"); 2907 } 2908 setName(name); 2909 } 2910 2911 /** 2912 * Create a frame showing all images in the set used for an icon. 2913 * Opened when editItemInPanel button is clicked in the Edit Icon Panel, 2914 * shown after icon's context menu Edit Icon... item is selected. 2915 * 2916 * @param name bean type name 2917 * @param add true when used to add a new item on panel, false when used to edit an item already on the panel 2918 * @param table true for bean types presented as table instead of icons 2919 * @param editor parent frame of the image frame 2920 * @return JFrame connected to the editor, to be filled with icons 2921 */ 2922 protected JFrameItem makeAddIconFrame(String name, boolean add, boolean table, IconAdder editor) { 2923 log.debug("makeAddIconFrame for {}, add= {}, table= {}", name, add, table); 2924 String txt; 2925 String bundleName; 2926 JFrameItem frame = new JFrameItem(name, editor); 2927 // use NamedBeanBundle property for basic beans like "Turnout" I18N 2928 if ("Sensor".equals(name)) { 2929 bundleName = "BeanNameSensor"; 2930 } else if ("SignalHead".equals(name)) { 2931 bundleName = "BeanNameSignalHead"; 2932 } else if ("SignalMast".equals(name)) { 2933 bundleName = "BeanNameSignalMast"; 2934 } else if ("Memory".equals(name)) { 2935 bundleName = "BeanNameMemory"; 2936 } else if ("Reporter".equals(name)) { 2937 bundleName = "BeanNameReporter"; 2938 } else if ("Light".equals(name)) { 2939 bundleName = "BeanNameLight"; 2940 } else if ("Turnout".equals(name)) { 2941 bundleName = "BeanNameTurnout"; // called by RightTurnout and LeftTurnout objects in TurnoutIcon.java edit() method 2942 } else if ("Block".equals(name)) { 2943 bundleName = "BeanNameBlock"; 2944 } else if ("GlobalVariable".equals(name)) { 2945 bundleName = "BeanNameGlobalVariable"; 2946 } else if ("LogixNGTable".equals(name)) { 2947 bundleName = "BeanNameLogixNGTable"; 2948 } else if ("Audio".equals(name)) { 2949 bundleName = "BeanNameAudio"; 2950 } else { 2951 bundleName = name; 2952 } 2953 if (editor != null) { 2954 JPanel p = new JPanel(); 2955 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); 2956 if (add) { 2957 txt = MessageFormat.format(Bundle.getMessage("addItemToPanel"), Bundle.getMessage(bundleName)); 2958 } else { 2959 txt = MessageFormat.format(Bundle.getMessage("editItemInPanel"), Bundle.getMessage(bundleName)); 2960 } 2961 p.add(new JLabel(txt)); 2962 if (table) { 2963 txt = MessageFormat.format(Bundle.getMessage("TableSelect"), Bundle.getMessage(bundleName), 2964 (add ? Bundle.getMessage("ButtonAddIcon") : Bundle.getMessage("ButtonUpdateIcon"))); 2965 } else { 2966 if ("MultiSensor".equals(name)) { 2967 txt = MessageFormat.format(Bundle.getMessage("SelectMultiSensor", Bundle.getMessage("ButtonAddIcon")), 2968 (add ? Bundle.getMessage("ButtonAddIcon") : Bundle.getMessage("ButtonUpdateIcon"))); 2969 } else { 2970 txt = MessageFormat.format(Bundle.getMessage("IconSelect"), Bundle.getMessage(bundleName), 2971 (add ? Bundle.getMessage("ButtonAddIcon") : Bundle.getMessage("ButtonUpdateIcon"))); 2972 } 2973 } 2974 p.add(new JLabel(txt)); 2975 p.add(new JLabel(" ")); // add a bit of space on pane above icons 2976 frame.getContentPane().add(p, BorderLayout.NORTH); 2977 frame.getContentPane().add(editor); 2978 2979 JMenuBar menuBar = new JMenuBar(); 2980 JMenu findIcon = new JMenu(Bundle.getMessage("findIconMenu")); 2981 menuBar.add(findIcon); 2982 2983 JMenuItem editItem = new JMenuItem(Bundle.getMessage("editIndexMenu")); 2984 editItem.addActionListener(e -> { 2985 ImageIndexEditor ii = InstanceManager.getDefault(ImageIndexEditor.class); 2986 ii.pack(); 2987 ii.setVisible(true); 2988 }); 2989 findIcon.add(editItem); 2990 findIcon.addSeparator(); 2991 2992 JMenuItem searchItem = new JMenuItem(Bundle.getMessage("searchFSMenu")); 2993 searchItem.addActionListener(new ActionListener() { 2994 private IconAdder ea; 2995 2996 @Override 2997 public void actionPerformed(ActionEvent e) { 2998 InstanceManager.getDefault(DirectorySearcher.class).searchFS(); 2999 ea.addDirectoryToCatalog(); 3000 } 3001 3002 ActionListener init(IconAdder ed) { 3003 ea = ed; 3004 return this; 3005 } 3006 }.init(editor)); 3007 3008 findIcon.add(searchItem); 3009 frame.setJMenuBar(menuBar); 3010 editor.setParent(frame); 3011 // when this window closes, check for saving 3012 if (add) { 3013 frame.addWindowListener(new WindowAdapter() { 3014 @Override 3015 public void windowClosing(WindowEvent e) { 3016 setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); 3017 if (log.isDebugEnabled()) { 3018 log.debug("windowClosing: HIDE {}", toString()); 3019 } 3020 } 3021 }); 3022 } 3023 } else { 3024 log.error("No icon editor specified for {}", name); // NOI18N 3025 } 3026 if (add) { 3027 txt = MessageFormat.format(Bundle.getMessage("AddItem"), Bundle.getMessage(bundleName)); 3028 _iconEditorFrame.put(name, frame); 3029 } else { 3030 txt = MessageFormat.format(Bundle.getMessage("EditItem"), Bundle.getMessage(bundleName)); 3031 } 3032 frame.setTitle(txt + " (" + getTitle() + ")"); 3033 frame.pack(); 3034 return frame; 3035 } 3036 3037 /* 3038 * ******************* cleanup ************************ 3039 */ 3040 protected void removeFromTarget(@Nonnull Positionable l) { 3041 Point p = l.getLocation(); 3042 _targetPanel.remove((Component) l); 3043 _highlightcomponent = null; 3044 int w = Math.max( l.maxWidth(), l.getWidth()); 3045 int h = Math.max( l.maxHeight(), l.getHeight()); 3046 _targetPanel.revalidate(); 3047 _targetPanel.repaint(p.x, p.y, w, h); 3048 } 3049 3050 public boolean removeFromContents(@Nonnull Positionable l) { 3051 removeFromTarget(l); 3052 //todo check that parent == _targetPanel 3053 //Container parent = this.getParent(); 3054 // force redisplay 3055 if (l.getId() != null) { 3056 _idContents.remove(l.getId()); 3057 } 3058 for (String className : l.getClasses()) { 3059 _classContents.get(className).remove(l); 3060 } 3061 return _contents.remove(l); 3062 } 3063 3064 /** 3065 * Ask user the user to decide what to do with LogixNGs, whether to delete them 3066 * or convert them to normal LogixNGs. Then respond to user's choice. 3067 */ 3068 private void dispositionLogixNGs() { 3069 ArrayList<LogixNG> logixNGArrayList = new ArrayList<>(); 3070 for (Positionable _content : _contents) { 3071 if (_content.getLogixNG() != null) { 3072 LogixNG logixNG = _content.getLogixNG(); 3073 logixNGArrayList.add(logixNG); 3074 } 3075 } 3076 if (!logixNGArrayList.isEmpty()) { 3077 LogixNGDeleteDialog logixNGDeleteDialog = new LogixNGDeleteDialog(this, getTitle(), logixNGArrayList); 3078 logixNGDeleteDialog.setVisible(true); 3079 List<LogixNG> selectedItems = logixNGDeleteDialog.getSelectedItems(); 3080 for (LogixNG logixNG : selectedItems) { 3081 deleteLogixNG_Internal(logixNG); 3082 logixNGArrayList.remove(logixNG); 3083 } 3084 for (LogixNG logixNG : logixNGArrayList) { 3085 logixNG.setInline(false); 3086 logixNG.setEnabled(!logixNGDeleteDialog.isDisableLogixNG()); 3087 } 3088 } 3089 } 3090 3091 /** 3092 * Ask user if panel should be deleted. The caller should dispose the panel 3093 * to delete it. 3094 * 3095 * @return true if panel should be deleted. 3096 */ 3097 public boolean deletePanel() { 3098 log.debug("deletePanel"); 3099 // verify deletion 3100 int selectedValue = JmriJOptionPane.showOptionDialog(_targetPanel, 3101 Bundle.getMessage("QuestionA") + "\n" + Bundle.getMessage("QuestionA2", 3102 Bundle.getMessage("FileMenuItemStore")), 3103 Bundle.getMessage("DeleteVerifyTitle"), JmriJOptionPane.DEFAULT_OPTION, 3104 JmriJOptionPane.QUESTION_MESSAGE, null, 3105 new Object[]{Bundle.getMessage("ButtonYesDelete"), Bundle.getMessage("ButtonCancel")}, 3106 Bundle.getMessage("ButtonCancel")); 3107 // return without deleting if "Cancel" or Cancel Dialog response 3108 if (selectedValue == 0) { 3109 dispositionLogixNGs(); 3110 } 3111 return (selectedValue == 0 ); // array position 0 = Yes, Delete. 3112 } 3113 3114 /** 3115 * Dispose of the editor. 3116 */ 3117 @Override 3118 public void dispose() { 3119 for (JFrameItem frame : _iconEditorFrame.values()) { 3120 frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 3121 frame.dispose(); 3122 } 3123 // delete panel - deregister the panel for saving 3124 ConfigureManager cm = InstanceManager.getNullableDefault(ConfigureManager.class); 3125 if (cm != null) { 3126 cm.deregister(this); 3127 } 3128 InstanceManager.getDefault(EditorManager.class).remove(this); 3129 setVisible(false); 3130 _contents.clear(); 3131 _idContents.clear(); 3132 for (var list : _classContents.values()) { 3133 list.clear(); 3134 } 3135 _classContents.clear(); 3136 removeAll(); 3137 super.dispose(); 3138 } 3139 3140 /* 3141 * **************** Mouse Methods ********************** 3142 */ 3143 public void showToolTip(Positionable selection, JmriMouseEvent event) { 3144 ToolTip tip = selection.getToolTip(); 3145 tip.setLocation(selection.getX() + selection.getWidth() / 2, selection.getY() + selection.getHeight()); 3146 setToolTip(tip); 3147 } 3148 3149 protected int getItemX(Positionable p, int deltaX) { 3150 if ((p instanceof MemoryOrGVIcon) && (p.getPopupUtility().getFixedWidth() == 0)) { 3151 MemoryOrGVIcon pm = (MemoryOrGVIcon) p; 3152 return pm.getOriginalX() + (int) Math.round(deltaX / getPaintScale()); 3153 } else { 3154 return p.getX() + (int) Math.round(deltaX / getPaintScale()); 3155 } 3156 } 3157 3158 protected int getItemY(Positionable p, int deltaY) { 3159 if ((p instanceof MemoryOrGVIcon) && (p.getPopupUtility().getFixedWidth() == 0)) { 3160 MemoryOrGVIcon pm = (MemoryOrGVIcon) p; 3161 return pm.getOriginalY() + (int) Math.round(deltaY / getPaintScale()); 3162 } else { 3163 return p.getY() + (int) Math.round(deltaY / getPaintScale()); 3164 } 3165 } 3166 3167 /** 3168 * Provide a method for external code to add items to context menus. 3169 * 3170 * @param nb The namedBean associated with the postionable item. 3171 * @param item The entry to add to the menu. 3172 * @param menu The menu to add the entry to. 3173 */ 3174 public void addToPopUpMenu(NamedBean nb, JMenuItem item, int menu) { 3175 if (nb == null || item == null) { 3176 return; 3177 } 3178 for (Positionable pos : _contents) { 3179 if (pos.getNamedBean() == nb && pos.getPopupUtility() != null) { 3180 addToPopUpMenu( pos, item, menu); 3181 return; 3182 } else if (pos instanceof SlipTurnoutIcon) { 3183 if (pos.getPopupUtility() != null) { 3184 SlipTurnoutIcon sti = (SlipTurnoutIcon) pos; 3185 if ( sti.getTurnout(SlipTurnoutIcon.EAST) == nb || sti.getTurnout(SlipTurnoutIcon.WEST) == nb 3186 || sti.getTurnout(SlipTurnoutIcon.LOWEREAST) == nb 3187 || sti.getTurnout(SlipTurnoutIcon.LOWERWEST) == nb) { 3188 addToPopUpMenu( pos, item, menu); 3189 return; 3190 } 3191 } 3192 } else if ( pos instanceof MultiSensorIcon && pos.getPopupUtility() != null) { 3193 MultiSensorIcon msi = (MultiSensorIcon) pos; 3194 for (int i = 0; i < msi.getNumEntries(); i++) { 3195 if ( msi.getSensorName(i).equals(nb.getUserName()) 3196 || msi.getSensorName(i).equals(nb.getSystemName())) { 3197 addToPopUpMenu( pos, item, menu); 3198 return; 3199 } 3200 } 3201 } 3202 } 3203 } 3204 3205 private void addToPopUpMenu( Positionable pos, JMenuItem item, int menu ) { 3206 switch (menu) { 3207 case VIEWPOPUPONLY: 3208 pos.getPopupUtility().addViewPopUpMenu(item); 3209 break; 3210 case EDITPOPUPONLY: 3211 pos.getPopupUtility().addEditPopUpMenu(item); 3212 break; 3213 default: 3214 pos.getPopupUtility().addEditPopUpMenu(item); 3215 pos.getPopupUtility().addViewPopUpMenu(item); 3216 } 3217 } 3218 3219 public static final int VIEWPOPUPONLY = 0x00; 3220 public static final int EDITPOPUPONLY = 0x01; 3221 public static final int BOTHPOPUPS = 0x02; 3222 3223 /** 3224 * Relocate item. 3225 * <p> 3226 * Note that items can not be moved past the left or top edges of the panel. 3227 * 3228 * @param p The item to move. 3229 * @param deltaX The horizontal displacement. 3230 * @param deltaY The vertical displacement. 3231 */ 3232 public void moveItem(Positionable p, int deltaX, int deltaY) { 3233 //log.debug("moveItem at ({},{}) delta ({},{})", p.getX(), p.getY(), deltaX, deltaY); 3234 if (getFlag(OPTION_POSITION, p.isPositionable())) { 3235 int xObj = getItemX(p, deltaX); 3236 int yObj = getItemY(p, deltaY); 3237 // don't allow negative placement, icon can become unreachable 3238 if (xObj < 0) { 3239 xObj = 0; 3240 } 3241 if (yObj < 0) { 3242 yObj = 0; 3243 } 3244 p.setLocation(xObj, yObj); 3245 // and show! 3246 p.repaint(); 3247 } 3248 } 3249 3250 /** 3251 * Return a List of all items whose bounding rectangle contain the mouse 3252 * position. ordered from top level to bottom 3253 * 3254 * @param event contains the mouse position. 3255 * @return a list of positionable items or an empty list. 3256 */ 3257 protected List<Positionable> getSelectedItems(JmriMouseEvent event) { 3258 Rectangle rect = new Rectangle(); 3259 ArrayList<Positionable> selections = new ArrayList<>(); 3260 for (Positionable p : _contents) { 3261 double x = event.getX(); 3262 double y = event.getY(); 3263 rect = p.getBounds(rect); 3264 if (p instanceof jmri.jmrit.display.controlPanelEditor.shape.PositionableShape 3265 && p.getDegrees() != 0) { 3266 double rad = p.getDegrees() * Math.PI / 180.0; 3267 java.awt.geom.AffineTransform t = java.awt.geom.AffineTransform.getRotateInstance(-rad); 3268 double[] pt = new double[2]; 3269 // bit shift to avoid SpotBugs paranoia 3270 pt[0] = x - rect.x - (rect.width >>> 1); 3271 pt[1] = y - rect.y - (rect.height >>> 1); 3272 t.transform(pt, 0, pt, 0, 1); 3273 x = pt[0] + rect.x + (rect.width >>> 1); 3274 y = pt[1] + rect.y + (rect.height >>> 1); 3275 } 3276 Rectangle2D.Double rect2D = new Rectangle2D.Double(rect.x * _paintScale, 3277 rect.y * _paintScale, 3278 rect.width * _paintScale, 3279 rect.height * _paintScale); 3280 if (rect2D.contains(x, y) && (p.getDisplayLevel() > BKG || event.isControlDown())) { 3281 boolean added = false; 3282 int level = p.getDisplayLevel(); 3283 for (int k = 0; k < selections.size(); k++) { 3284 if (level >= selections.get(k).getDisplayLevel()) { 3285 selections.add(k, p); 3286 added = true; // OK to lie in the case of background icon 3287 break; 3288 } 3289 } 3290 if (!added) { 3291 selections.add(p); 3292 } 3293 } 3294 } 3295 //log.debug("getSelectedItems at ({},{}) {} found,", x, y, selections.size()); 3296 return selections; 3297 } 3298 3299 /* 3300 * Gather all items inside _selectRect 3301 * Keep old group if Control key is down 3302 */ 3303 protected void makeSelectionGroup(JmriMouseEvent event) { 3304 if (!event.isControlDown() || _selectionGroup == null) { 3305 _selectionGroup = new ArrayList<>(); 3306 } 3307 Rectangle test = new Rectangle(); 3308 List<Positionable> list = getContents(); 3309 if (event.isShiftDown()) { 3310 for (Positionable comp : list) { 3311 if (_selectRect.intersects(comp.getBounds(test)) 3312 && (event.isControlDown() || comp.getDisplayLevel() > BKG)) { 3313 _selectionGroup.add(comp); 3314 //log.debug("makeSelectionGroup: selection: {}, class= {}", comp.getNameString(), comp.getClass().getName()); 3315 } 3316 } 3317 } else { 3318 for (Positionable comp : list) { 3319 if (_selectRect.contains(comp.getBounds(test)) 3320 && (event.isControlDown() || comp.getDisplayLevel() > BKG)) { 3321 _selectionGroup.add(comp); 3322 //log.debug("makeSelectionGroup: selection: {}, class= {}", comp.getNameString(), comp.getClass().getName()); 3323 } 3324 } 3325 } 3326 log.debug("makeSelectionGroup: {} selected.", _selectionGroup.size()); 3327 if (_selectionGroup.size() < 1) { 3328 _selectRect = null; 3329 deselectSelectionGroup(); 3330 } 3331 } 3332 3333 /* 3334 * For the param, selection, Add to or delete from _selectionGroup. 3335 * If not there, add. 3336 * If there, delete. 3337 * make new group if Cntl key is not held down 3338 */ 3339 protected void modifySelectionGroup(Positionable selection, JmriMouseEvent event) { 3340 if (!event.isControlDown() || _selectionGroup == null) { 3341 _selectionGroup = new ArrayList<>(); 3342 } 3343 boolean removed = false; 3344 if (event.isControlDown()) { 3345 if (selection.getDisplayLevel() > BKG) { 3346 if (_selectionGroup.contains(selection)) { 3347 removed = _selectionGroup.remove(selection); 3348 } else { 3349 _selectionGroup.add(selection); 3350 } 3351 } else if (event.isShiftDown()) { 3352 if (_selectionGroup.contains(selection)) { 3353 removed = _selectionGroup.remove(selection); 3354 } else { 3355 _selectionGroup.add(selection); 3356 } 3357 } 3358 } 3359 log.debug("modifySelectionGroup: size= {}, selection {}", 3360 _selectionGroup.size(), (removed ? "removed" : "added")); 3361 } 3362 3363 /** 3364 * Set attributes of a Positionable. 3365 * 3366 * @param newUtil helper from which to get attributes 3367 * @param p the item to set attributes of 3368 * 3369 */ 3370 public void setAttributes(PositionablePopupUtil newUtil, Positionable p) { 3371 p.setPopupUtility(newUtil.clone(p, p.getTextComponent())); 3372 int mar = newUtil.getMargin(); 3373 int bor = newUtil.getBorderSize(); 3374 Border outlineBorder; 3375 if (bor == 0) { 3376 outlineBorder = BorderFactory.createEmptyBorder(0, 0, 0, 0); 3377 } else { 3378 outlineBorder = new LineBorder(newUtil.getBorderColor(), bor); 3379 } 3380 Border borderMargin; 3381 if (newUtil.hasBackground()) { 3382 borderMargin = new LineBorder(p.getBackground(), mar); 3383 } else { 3384 borderMargin = BorderFactory.createEmptyBorder(mar, mar, mar, mar); 3385 } 3386 p.setBorder(new CompoundBorder(outlineBorder, borderMargin)); 3387 3388 if (p instanceof PositionableLabel) { 3389 PositionableLabel pos = (PositionableLabel) p; 3390 if (pos.isText()) { 3391 int deg = pos.getDegrees(); 3392 pos.rotate(0); 3393 if (deg == 0) { 3394 p.setOpaque(newUtil.hasBackground()); 3395 } else { 3396 pos.rotate(deg); 3397 } 3398 } 3399 } else if (p instanceof PositionableJPanel) { 3400 p.setOpaque(newUtil.hasBackground()); 3401 p.getTextComponent().setOpaque(newUtil.hasBackground()); 3402 } 3403 p.updateSize(); 3404 p.repaint(); 3405 if (p instanceof PositionableIcon) { 3406 NamedBean bean = p.getNamedBean(); 3407 if (bean != null) { 3408 ((PositionableIcon) p).displayState(bean.getState()); 3409 } 3410 } 3411 } 3412 3413 protected void setSelectionsAttributes(PositionablePopupUtil util, Positionable pos) { 3414 if (_selectionGroup != null && _selectionGroup.contains(pos)) { 3415 for (Positionable p : _selectionGroup) { 3416 if (p instanceof PositionableLabel) { 3417 setAttributes(util, p); 3418 } 3419 } 3420 } 3421 } 3422 3423 protected void setSelectionsHidden(boolean enabled, Positionable p) { 3424 if (_selectionGroup != null && _selectionGroup.contains(p)) { 3425 for (Positionable comp : _selectionGroup) { 3426 comp.setHidden(enabled); 3427 } 3428 } 3429 } 3430 3431 protected boolean setSelectionsPositionable(boolean enabled, Positionable p) { 3432 if (_selectionGroup != null && _selectionGroup.contains(p)) { 3433 for (Positionable comp : _selectionGroup) { 3434 comp.setPositionable(enabled); 3435 } 3436 return true; 3437 } else { 3438 return false; 3439 } 3440 } 3441 3442 protected void removeSelections(Positionable p) { 3443 if (_selectionGroup != null && _selectionGroup.contains(p)) { 3444 for (Positionable comp : _selectionGroup) { 3445 comp.remove(); 3446 } 3447 deselectSelectionGroup(); 3448 } 3449 } 3450 3451 protected void setSelectionsScale(double s, Positionable p) { 3452 if (_selectionGroup != null && _selectionGroup.contains(p)) { 3453 for (Positionable comp : _selectionGroup) { 3454 comp.setScale(s); 3455 } 3456 } else { 3457 p.setScale(s); 3458 } 3459 } 3460 3461 protected void setSelectionsRotation(int k, Positionable p) { 3462 if (_selectionGroup != null && _selectionGroup.contains(p)) { 3463 for (Positionable comp : _selectionGroup) { 3464 comp.rotate(k); 3465 } 3466 } else { 3467 p.rotate(k); 3468 } 3469 } 3470 3471 protected void setSelectionsDisplayLevel(int k, Positionable p) { 3472 if (_selectionGroup != null && _selectionGroup.contains(p)) { 3473 for (Positionable comp : _selectionGroup) { 3474 comp.setDisplayLevel(k); 3475 } 3476 } else { 3477 p.setDisplayLevel(k); 3478 } 3479 } 3480 3481 protected void setSelectionsDockingLocation(Positionable p) { 3482 if (_selectionGroup != null && _selectionGroup.contains(p)) { 3483 for (Positionable pos : _selectionGroup) { 3484 if (pos instanceof LocoIcon) { 3485 ((LocoIcon) pos).setDockingLocation(pos.getX(), pos.getY()); 3486 } 3487 } 3488 } else if (p instanceof LocoIcon) { 3489 ((LocoIcon) p).setDockingLocation(p.getX(), p.getY()); 3490 } 3491 } 3492 3493 protected void dockSelections(Positionable p) { 3494 if (_selectionGroup != null && _selectionGroup.contains(p)) { 3495 for (Positionable pos : _selectionGroup) { 3496 if (pos instanceof LocoIcon) { 3497 ((LocoIcon) pos).dock(); 3498 } 3499 } 3500 } else if (p instanceof LocoIcon) { 3501 ((LocoIcon) p).dock(); 3502 } 3503 } 3504 3505 protected boolean showAlignPopup(Positionable p) { 3506 return _selectionGroup != null && _selectionGroup.contains(p); 3507 } 3508 3509 public Rectangle getSelectRect() { 3510 return _selectRect; 3511 } 3512 3513 public void drawSelectRect(int x, int y) { 3514 int aX = getAnchorX(); 3515 int aY = getAnchorY(); 3516 int w = x - aX; 3517 int h = y - aY; 3518 if (x < aX) { 3519 aX = x; 3520 w = -w; 3521 } 3522 if (y < aY) { 3523 aY = y; 3524 h = -h; 3525 } 3526 _selectRect = new Rectangle((int) Math.round(aX / _paintScale), (int) Math.round(aY / _paintScale), 3527 (int) Math.round(w / _paintScale), (int) Math.round(h / _paintScale)); 3528 } 3529 3530 public final int getAnchorX() { 3531 return _anchorX; 3532 } 3533 3534 public final int getAnchorY() { 3535 return _anchorY; 3536 } 3537 3538 public final int getLastX() { 3539 return _lastX; 3540 } 3541 3542 public final int getLastY() { 3543 return _lastY; 3544 } 3545 3546 @Override 3547 public void keyTyped(KeyEvent e) { 3548 } 3549 3550 @Override 3551 public void keyPressed(KeyEvent e) { 3552 if (_selectionGroup == null) { 3553 return; 3554 } 3555 int x = 0; 3556 int y = 0; 3557 switch (e.getKeyCode()) { 3558 case KeyEvent.VK_UP: 3559 y = -1; 3560 break; 3561 case KeyEvent.VK_DOWN: 3562 y = 1; 3563 break; 3564 case KeyEvent.VK_LEFT: 3565 x = -1; 3566 break; 3567 case KeyEvent.VK_RIGHT: 3568 x = 1; 3569 break; 3570 default: 3571 log.debug("Unexpected e.getKeyCode() of {}", e.getKeyCode()); 3572 break; 3573 } 3574 //A cheat if the shift key isn't pressed then we move 5 pixels at a time. 3575 if (!e.isShiftDown()) { 3576 y *= 5; 3577 x *= 5; 3578 } 3579 for (Positionable comp : _selectionGroup) { 3580 moveItem(comp, x, y); 3581 } 3582 _targetPanel.repaint(); 3583 } 3584 3585 @Override 3586 public void keyReleased(KeyEvent e) { 3587 } 3588 3589 @Override 3590 public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { 3591 NamedBean nb = (NamedBean) evt.getOldValue(); 3592 if ("CanDelete".equals(evt.getPropertyName())) { // NOI18N 3593 StringBuilder message = new StringBuilder(); 3594 message.append(Bundle.getMessage("VetoInUseEditorHeader", getName())); // NOI18N 3595 message.append("<br>"); 3596 boolean found = false; 3597 int count = 0; 3598 for (Positionable p : _contents) { 3599 if (nb.equals(p.getNamedBean())) { 3600 found = true; 3601 count++; 3602 } 3603 } 3604 if (found) { 3605 message.append(Bundle.getMessage("VetoFoundInPanel", count)); 3606 message.append("<br>"); 3607 message.append(Bundle.getMessage("VetoReferencesWillBeRemoved")); // NOI18N 3608 message.append("<br>"); 3609 throw new PropertyVetoException(message.toString(), evt); 3610 } 3611 } else if ("DoDelete".equals(evt.getPropertyName())) { // NOI18N 3612 ArrayList<Positionable> toDelete = new ArrayList<>(); 3613 for (Positionable p : _contents) { 3614 if (nb.equals(p.getNamedBean())) { 3615 toDelete.add(p); 3616 } 3617 } 3618 for (Positionable p : toDelete) { 3619 removeFromContents(p); 3620 _targetPanel.repaint(); 3621 } 3622 } 3623 } 3624 3625 /* 3626 * ********************* Abstract Methods *********************** 3627 */ 3628 @Override 3629 public abstract void mousePressed(JmriMouseEvent event); 3630 3631 @Override 3632 public abstract void mouseReleased(JmriMouseEvent event); 3633 3634 @Override 3635 public abstract void mouseClicked(JmriMouseEvent event); 3636 3637 @Override 3638 public abstract void mouseDragged(JmriMouseEvent event); 3639 3640 @Override 3641 public abstract void mouseMoved(JmriMouseEvent event); 3642 3643 @Override 3644 public abstract void mouseEntered(JmriMouseEvent event); 3645 3646 @Override 3647 public abstract void mouseExited(JmriMouseEvent event); 3648 3649 /* 3650 * set up target panel, frame etc. 3651 */ 3652 protected abstract void init(String name); 3653 3654 /* 3655 * Closing of Target frame window. 3656 */ 3657 protected abstract void targetWindowClosingEvent(WindowEvent e); 3658 3659 /** 3660 * Called from TargetPanel's paint method for additional drawing by editor 3661 * view. 3662 * 3663 * @param g the context to paint within 3664 */ 3665 protected abstract void paintTargetPanel(Graphics g); 3666 3667 /** 3668 * Set an object's location when it is created. 3669 * 3670 * @param obj the object to locate 3671 */ 3672 protected abstract void setNextLocation(Positionable obj); 3673 3674 /** 3675 * After construction, initialize all the widgets to their saved config 3676 * settings. 3677 */ 3678 protected abstract void initView(); 3679 3680 /** 3681 * Set up item(s) to be copied by paste. 3682 * 3683 * @param p the item to copy 3684 */ 3685 protected abstract void copyItem(Positionable p); 3686 3687 public List<NamedBeanUsageReport> getUsageReport(NamedBean bean) { 3688 List<NamedBeanUsageReport> report = new ArrayList<>(); 3689 if (bean != null) { 3690 getContents().forEach( pos -> { 3691 String data = getUsageData(pos); 3692 if (pos instanceof MultiSensorIcon) { 3693 MultiSensorIcon multi = (MultiSensorIcon) pos; 3694 multi.getSensors().forEach( sensor -> { 3695 if (bean.equals(sensor)) { 3696 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3697 } 3698 }); 3699 3700 } else if (pos instanceof SlipTurnoutIcon) { 3701 SlipTurnoutIcon slip3Scissor = (SlipTurnoutIcon) pos; 3702 if (bean.equals(slip3Scissor.getTurnout(SlipTurnoutIcon.EAST))) { 3703 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3704 } 3705 if (bean.equals(slip3Scissor.getTurnout(SlipTurnoutIcon.WEST))) { 3706 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3707 } 3708 if ( slip3Scissor.getNamedTurnout(SlipTurnoutIcon.LOWEREAST) != null 3709 && bean.equals(slip3Scissor.getTurnout(SlipTurnoutIcon.LOWEREAST))) { 3710 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3711 } 3712 if ( slip3Scissor.getNamedTurnout(SlipTurnoutIcon.LOWERWEST) != null 3713 && bean.equals(slip3Scissor.getTurnout(SlipTurnoutIcon.LOWERWEST))) { 3714 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3715 } 3716 3717 } else if (pos instanceof LightIcon) { 3718 LightIcon icon = (LightIcon) pos; 3719 if (bean.equals(icon.getLight())) { 3720 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3721 } 3722 3723 } else if (pos instanceof ReporterIcon) { 3724 ReporterIcon icon = (ReporterIcon) pos; 3725 if (bean.equals(icon.getReporter())) { 3726 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3727 } 3728 3729 } else if (pos instanceof AudioIcon) { 3730 AudioIcon icon = (AudioIcon) pos; 3731 if (bean.equals(icon.getAudio())) { 3732 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3733 } 3734 3735 } else { 3736 if ( bean.equals(pos.getNamedBean())) { 3737 report.add(new NamedBeanUsageReport("PositionalIcon", data)); 3738 } 3739 } 3740 }); 3741 } 3742 return report; 3743 } 3744 3745 String getUsageData(Positionable pos) { 3746 Point point = pos.getLocation(); 3747 return String.format("%s :: x=%d, y=%d", 3748 pos.getClass().getSimpleName(), 3749 Math.round(point.getX()), 3750 Math.round(point.getY())); 3751 } 3752 3753 // initialize logging 3754 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Editor.class); 3755 3756}