001package jmri.jmrit.display.controlPanelEditor; 002 003import java.awt.Dimension; 004import java.awt.FlowLayout; 005import java.awt.datatransfer.DataFlavor; 006import java.awt.datatransfer.UnsupportedFlavorException; 007import java.awt.dnd.DragSourceDropEvent; 008import java.awt.event.ActionEvent; 009import java.io.IOException; 010import java.util.ArrayList; 011import java.util.Enumeration; 012import java.util.HashMap; 013import java.util.List; 014import java.util.Map.Entry; 015 016import javax.annotation.Nonnull; 017import javax.swing.BorderFactory; 018import javax.swing.Box; 019import javax.swing.BoxLayout; 020import javax.swing.JButton; 021import javax.swing.JComponent; 022import javax.swing.JLabel; 023import javax.swing.JPanel; 024import javax.swing.JScrollPane; 025import javax.swing.JTextField; 026import javax.swing.event.ListSelectionEvent; 027import javax.swing.event.ListSelectionListener; 028 029import jmri.InstanceManager; 030import jmri.NamedBean; 031import jmri.SignalAppearanceMap; 032import jmri.SignalHead; 033import jmri.SignalMast; 034import jmri.SignalHeadManager; 035import jmri.SignalMastManager; 036import jmri.NamedBean.DisplayOptions; 037import jmri.jmrit.beantable.AbstractTableAction; 038import jmri.jmrit.beantable.BeanTableFrame; 039import jmri.jmrit.beantable.SignalHeadTableAction; 040import jmri.jmrit.beantable.SignalMastTableAction; 041import jmri.jmrit.catalog.DragJLabel; 042import jmri.jmrit.catalog.NamedIcon; 043import jmri.jmrit.display.Editor; 044import jmri.jmrit.display.PositionableIcon; 045import jmri.jmrit.display.SignalHeadIcon; 046import jmri.jmrit.display.SignalMastIcon; 047import jmri.jmrit.display.palette.ItemPalette; 048import jmri.jmrit.logix.OBlock; 049import jmri.jmrit.logix.Portal; 050import jmri.jmrit.picker.PickListModel; 051import jmri.util.swing.JmriJOptionPane; 052 053/** 054 * 055 * @author Pete Cressman Copyright: Copyright (c) 2019 056 * 057 */ 058public class EditSignalFrame extends EditFrame { 059 060 private PortalIcon _portalIcon; 061 062 private JTextField _mastName; 063 private PortalList _portalList; 064 private SignalList _signalList; 065 private LengthPanel _lengthPanel; 066 private Portal _currentPortal; 067 OpenPickListButton<SignalMast> _pickMast; 068 OpenPickListButton<SignalHead> _pickHead; 069 AbstractTableAction<SignalMast> _mastTableAction; 070 AbstractTableAction<SignalHead> _headTableAction; 071 JPanel _dndPanel; 072 private IconDragJLabel _dragLabel; 073 074 public EditSignalFrame(String title, CircuitBuilder parent, OBlock block) { 075 super(title, parent, block); 076 checkCircuitIcons("BlockSignal"); 077 pack(); 078 } 079 080 @Override 081 protected JPanel makeContentPanel() { 082 JPanel signalPanel = new JPanel(); 083 signalPanel.setLayout(new BoxLayout(signalPanel, BoxLayout.Y_AXIS)); 084 085 JPanel panel = new JPanel(); 086 panel.add(new JLabel(Bundle.getMessage("PortalTitle", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME)))); 087 signalPanel.add(panel); 088 089 _portalList = new PortalList(_homeBlock, this); 090 _portalList.addListSelectionListener(new PortalListListener(this)); 091 signalPanel.add(new JScrollPane(_portalList)); 092 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE / 2)); 093 094 panel = new JPanel(); 095 panel.add(new JLabel(Bundle.getMessage("SignalTitle", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME)))); 096 signalPanel.add(panel); 097 098 _signalList = new SignalList(_homeBlock, this); 099 _signalList.addListSelectionListener(new SignalListListener(this)); 100 signalPanel.add(new JScrollPane(_signalList)); 101 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE / 2)); 102 103 JButton clearButton = new JButton(Bundle.getMessage("buttonClearSelection")); 104 clearButton.addActionListener(a -> { 105 _portalList.clearSelection(); 106 _signalList.clearSelection(); 107 _parent._editor.highlight(null); 108 _mastName.setText(null); 109 }); 110 111 panel = new JPanel(); 112 panel.add(clearButton); 113 signalPanel.add(panel); 114 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE / 2)); 115 116 JPanel framingPanel = new JPanel(); 117 JPanel mastConfigPanel = new JPanel(); 118 // set border to group items in UI 119 mastConfigPanel.setBorder(BorderFactory.createEtchedBorder()); 120 mastConfigPanel.setLayout(new BoxLayout(mastConfigPanel, BoxLayout.Y_AXIS)); 121 122 panel = new JPanel(); 123 _mastName = new JTextField(); 124 panel.add(CircuitBuilder.makeTextBoxPanel(false, _mastName, "mastName", true, null)); 125 _mastName.setPreferredSize(new Dimension(300, _mastName.getPreferredSize().height)); 126 _mastName.setToolTipText(Bundle.getMessage("ToolTipMastName", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME))); 127 mastConfigPanel.add(panel); 128 129 _lengthPanel = new LengthPanel(_homeBlock, LengthPanel.ENTRANCE_SPACE, "OffsetToolTip"); 130 _lengthPanel.changeUnits(); 131 mastConfigPanel.add(_lengthPanel); 132 133 JPanel buttonPanel = new JPanel(); 134 JButton addButton = new JButton(Bundle.getMessage("ButtonAddMast")); 135 addButton.addActionListener((ActionEvent a) -> addMast()); 136 addButton.setToolTipText(Bundle.getMessage("ToolTipAddMast", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME))); 137 buttonPanel.add(addButton); 138/* 139 JButton button = new JButton(Bundle.getMessage("buttonChangeName")); 140 button.addActionListener((ActionEvent a) -> changeName(null)); 141 button.setToolTipText(Bundle.getMessage("ToolTipChangeName", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME))); 142 panel.add(button);*/ 143 144 JButton buttonRemove = new JButton(Bundle.getMessage("ButtonRemoveMast")); 145 buttonRemove.addActionListener((ActionEvent a) -> removeMast()); 146 buttonRemove.setToolTipText(Bundle.getMessage("ToolTipRemoveMast", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME))); 147 buttonPanel.add(buttonRemove); 148 149 mastConfigPanel.add(buttonPanel); 150 // border up to here 151 framingPanel.add(mastConfigPanel); 152 signalPanel.add(framingPanel); 153 154 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE)); 155 156 panel = new JPanel(); 157 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 158 JLabel l = new JLabel(Bundle.getMessage("addSignalConfig")); 159 l.setAlignmentX(JComponent.LEFT_ALIGNMENT); 160 panel.add(l); 161 l = new JLabel(Bundle.getMessage("selectSignalMast")); 162 l.setAlignmentX(JComponent.LEFT_ALIGNMENT); 163 panel.add(l); 164 l = new JLabel(Bundle.getMessage("pressConfigure", Bundle.getMessage("ButtonAddMast"))); 165 l.setAlignmentX(JComponent.LEFT_ALIGNMENT); 166 panel.add(l); 167 panel.add(Box.createVerticalStrut(STRUT_SIZE / 2)); 168 l = new JLabel(Bundle.getMessage("addSignalIcon")); 169 l.setAlignmentX(JComponent.LEFT_ALIGNMENT); 170 panel.add(l); 171 l = new JLabel(Bundle.getMessage("positionMast")); 172 l.setAlignmentX(JComponent.LEFT_ALIGNMENT); 173 panel.add(l); 174 JPanel p = new JPanel(); 175 p.add(panel); 176 signalPanel.add(p); 177 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE / 2)); 178 179 panel = new JPanel(); 180 l = new JLabel(Bundle.getMessage("recommendMasts")); 181 panel.add(l); 182 signalPanel.add(panel); 183 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE / 2)); 184 185 String[] blurbLines = {Bundle.getMessage("DragMast", Bundle.getMessage("mastName"))}; 186 187 panel = new JPanel(); 188 panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); 189 _pickMast = new OpenPickListButton<>(blurbLines, PickListModel.signalMastPickModelInstance(), 190 this, Bundle.getMessage("OpenPicklist", Bundle.getMessage("BeanNameSignalMast"))); 191 _mastTableAction = new SignalMastTableAction(Bundle.getMessage("ButtonCreateMast")); 192 p = new JPanel(); 193 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); 194 p.add(_pickMast.getButtonPanel()); 195 JPanel pp = new JPanel(); 196 pp.setLayout(new FlowLayout()); 197 JButton buttonCreate = new JButton(Bundle.getMessage("ButtonCreateMast")); 198 buttonCreate.addActionListener(_mastTableAction); 199 buttonCreate.setToolTipText(Bundle.getMessage("ToolTipAddToTable")); 200 pp.add(buttonCreate); 201 p.add(pp); 202 panel.add(p); 203 204 _pickHead = new OpenPickListButton<>(blurbLines, PickListModel.signalHeadPickModelInstance(), 205 this, Bundle.getMessage("OpenPicklist", Bundle.getMessage("BeanNameSignalHead"))); 206 _headTableAction = new SignalHeadTableAction(Bundle.getMessage("ButtonCreateHead")); 207 p = new JPanel(); 208 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); 209 p.add(_pickHead.getButtonPanel()); 210 pp = new JPanel(); 211 pp.setLayout(new FlowLayout()); 212 buttonCreate = new JButton(Bundle.getMessage("ButtonCreateHead")); 213 buttonCreate.addActionListener(_headTableAction); 214 buttonCreate.setToolTipText(Bundle.getMessage("ToolTipAddToTable")); 215 pp.add(buttonCreate); 216 p.add(pp); 217 panel.add(p); 218 signalPanel.add(panel); 219 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE)); 220 221 panel = new JPanel(); 222 l = new JLabel(Bundle.getMessage("modifySignal")); 223 panel.add(l); 224 signalPanel.add(panel); 225 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE)); 226 227 _dndPanel = makeDndIconPanel(); 228 signalPanel.add(_dndPanel); 229 signalPanel.add(Box.createVerticalStrut(STRUT_SIZE)); 230 signalPanel.add(makeDoneButtonPanel()); 231 return signalPanel; 232 } 233 234 protected void setSelected(PositionableIcon icon) { 235 if (!canEdit()) { 236 return; 237 } 238 NamedBean mast = null; 239 Portal portal = null; 240 if (icon instanceof PortalIcon) { 241 portal = ((PortalIcon)icon).getPortal(); 242 } else if (icon instanceof SignalMastIcon) { 243 mast = ((SignalMastIcon)icon).getSignalMast(); 244 } else if (icon instanceof SignalHeadIcon) { 245 mast = ((SignalHeadIcon)icon).getSignalHead(); 246 } else { 247 return; 248 } 249 if (log.isDebugEnabled()) { 250 log.debug("setSelected portal= \"{}\" mast ={}", (portal!=null?portal.getName():"null"),(mast!=null?mast.getDisplayName():"null")); 251 } 252 _portalIcon = null; 253 if (portal != null) { 254 mast = portal.getSignalProtectingBlock(_homeBlock); 255 if (mast !=null) { 256 setMastNameAndIcon(mast, portal); 257 } 258 } else if (mast !=null) { 259 portal =_parent.getSignalPortal(mast); 260 if (portal != null) { 261 OBlock protectedBlock = portal.getProtectedBlock(mast); 262 if (_homeBlock.equals(protectedBlock)) { 263 setMastNameAndIcon(mast, portal); 264 } 265 } 266 _portalList.setSelected(portal); 267 _signalList.setSelected(portal); 268 _parent._editor.highlight(icon); 269 } 270 } 271 272 private void setMastNameAndIcon(NamedBean mast, Portal portal) { 273 _mastName.setText(mast.getDisplayName(DisplayOptions.DISPLAYNAME)); 274 _parent._editor.highlight(null); 275 List<PositionableIcon> siArray = _parent.getSignalIconMap(mast); 276 for (PositionableIcon si : siArray) { 277 _parent._editor.highlight(si); 278 } 279 List<PortalIcon> piArray = _parent.getPortalIcons(portal); 280 for (PortalIcon pi : piArray) { 281 _parent._editor.highlight(pi); 282 } 283 } 284 285 /** 286 * *********************** end setup ************************* 287 */ 288 289 class PortalListListener implements ListSelectionListener { 290 EditFrame _frame; 291 PortalListListener(EditFrame parent) { 292 _frame = parent; 293 } 294 @Override 295 public void valueChanged(ListSelectionEvent e) { 296 Portal portal = _portalList.getSelectedValue(); 297 if (log.isDebugEnabled()) { 298 log.debug("PortalList: valueChanged: portal = {}, _currentPortal = {}", (portal==null?"null":portal.getName()), 299 (_currentPortal==null?"null":_currentPortal.getName())); 300 } 301 NamedBean mast = null; 302 if (portal != null) { 303 mast = portal.getSignalProtectingBlock(_homeBlock); 304 if (!portal.equals(_currentPortal)) { 305 String msg = checkMastForSave(); 306 if (msg.length() > 0) { 307 StringBuffer sb = new StringBuffer(msg); 308 NamedBean bean = getSignal(); 309// if (bean != null) { 310 sb.append("\n"); 311 sb.append(Bundle.getMessage("saveChanges")); 312// } 313 int answer = JmriJOptionPane.showConfirmDialog(_frame, sb.toString(), Bundle.getMessage("configureSignal"), 314 JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE); 315 if (answer == JmriJOptionPane.YES_OPTION) { 316 if (bean != null) { 317 addMast(_currentPortal, bean); 318// } else { 319// changeName(_currentPortal); 320 } 321 return; 322 } 323 } 324 } 325 } 326 if (_portalIcon == null) { 327 _parent._editor.highlight(null); 328 } 329 _currentPortal = portal; 330 if (portal != null) { 331 _lengthPanel.setLength(portal.getEntranceSpaceForBlock(_homeBlock)); 332 List<PortalIcon> piArray = _parent.getPortalIcons(portal); 333 if (!piArray.isEmpty()) { 334 _portalIcon = piArray.get(0); 335 } 336 } 337 338 if (mast != null) { 339 setMastNameAndIcon(mast, portal); 340 } else { 341 _parent._editor.highlight(null); 342 _mastName.setText(null); 343 if (portal != null) { 344 _parent._editor.highlight(_portalIcon); 345 } 346 _lengthPanel.setLength(0); 347 } 348 _signalList.setSelected(portal); 349 setDragIcon(mast); 350 } 351 352 } 353 354 class SignalListListener implements ListSelectionListener { 355 EditFrame _frame; 356 SignalListListener(EditFrame parent) { 357 _frame = parent; 358 } 359 @Override 360 public void valueChanged(ListSelectionEvent e) { 361 SignalPair sp = _signalList.getSelectedValue(); 362 if (log.isDebugEnabled()) { 363 if (sp != null) { 364 log.debug("SignalList: valueChanged: portal = {}, signal = {}", 365 sp._portal.getName(), sp._signal.getDisplayName()); 366 } else { 367 log.debug("SignalList: valueChanged: signalPair null"); 368 } 369 } 370 NamedBean signal; 371 if (sp != null) { 372 _portalList.setSelected(sp._portal); 373 signal = sp._signal; 374 } else { 375 signal = null; 376 } 377 setDragIcon(signal); 378 } 379 } 380 381 // Called from ButtonAddMast 382 private boolean replaceQuestion(@Nonnull NamedBean mast, @Nonnull Portal homePortal) { 383 StringBuffer sb = new StringBuffer(); 384 Portal portal = _parent.getSignalPortal(mast); 385 OBlock blk = null; 386 if (portal != null) { 387 blk = portal.getProtectedBlock(mast); 388 if (blk != null && !blk.equals(_homeBlock)) { 389 sb.append(Bundle.getMessage("mastProtectsPortal", 390 mast.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME), 391 blk.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME), 392 portal.getName())); 393 sb.append("\n"); 394 } 395 } 396 NamedBean homeMast = homePortal.getSignalProtectingBlock(_homeBlock); 397 String mastName = mast.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME); 398 String homeName = _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME); 399 if (homeMast != null) { 400 if (homeMast.equals(mast)) { 401 // no changes needed except for length. So do it now and skip the rest of AddMast() 402 homePortal.setEntranceSpaceForBlock(_homeBlock, _lengthPanel.getLength()); 403 return false; 404 } else { 405 String homeMastName = homeMast.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME); 406 sb.append(Bundle.getMessage("mastProtectsPortal", homeMastName, homeName, homePortal.getName())); 407 sb.append("\n"); 408 sb.append(Bundle.getMessage("replaceSignalMast", homeMast.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME), 409 mastName, homePortal.getName())); 410 } 411 } else if (sb.length() > 0) { 412 sb.append(Bundle.getMessage("noMast", homePortal.getName(), homeName)); 413 sb.append("\n"); 414 sb.append(Bundle.getMessage("setSignal", mastName)); 415 sb.append("\n"); 416 sb.append(Bundle.getMessage("attachMast", mastName, homeName, homePortal.getName())); 417 } 418 if (sb.length() > 0) { 419 int answer = JmriJOptionPane.showConfirmDialog(this, sb.toString(), 420 Bundle.getMessage("configureSignal"), JmriJOptionPane.YES_NO_OPTION, JmriJOptionPane.QUESTION_MESSAGE); 421 if (answer != JmriJOptionPane.YES_OPTION) { 422 return false; // Skip the rest 423 } 424 } 425 if (homeMast != null) { 426 homePortal.setProtectSignal(null, 0, blk); 427 } 428 _parent.putSignalPortal(mast, null); 429 return true; 430 } 431 432 private NamedBean getSignal() { 433 String name = _mastName.getText(); 434 if (name.trim().length() == 0) { 435 return null; 436 } 437 NamedBean signal = InstanceManager.getDefault(SignalMastManager.class).getSignalMast(name); 438 if (signal == null) { 439 signal = InstanceManager.getDefault(SignalHeadManager.class).getSignalHead(name); 440 } 441 return signal; 442 } 443 444 // Called from: 445 // ConfigureButton - addMast(portal, mast); portal from portal list, mast from name field 446 private void addMast(@Nonnull Portal portal, @Nonnull NamedBean newMast) { 447 if (log.isDebugEnabled()) { 448 log.debug("addMast \"{}\"", newMast.getDisplayName()); 449 } 450 if (newMast instanceof SignalMast) { 451 SignalMast mast = (SignalMast)newMast; 452 if (mast.getAspect() == null) { 453 mast.setAspect(mast.getValidAspects().get(0)); 454 } 455 } 456 portal.setProtectSignal(newMast, _lengthPanel.getLength(), _homeBlock); 457 _parent.putSignalPortal(newMast, portal); 458 setDragIcon(newMast); 459 } 460 461 private boolean addMast() { 462 Portal portal = _portalList.getSelectedValue(); 463 String msg = null; 464 if (portal != null) { 465 NamedBean signal = getSignal(); 466 if (signal != null) { 467 if (replaceQuestion(signal, portal)) { 468 addMast(portal, signal); 469 } 470 } else { 471 String name = _mastName.getText().trim(); 472 if ( name.length()==0) { 473 msg = Bundle.getMessage("selectSignalMast"); 474 } else { 475 msg = Bundle.getMessage("NotFound", name); 476 } 477 } 478 } else { 479 msg = Bundle.getMessage("selectPortalProtection", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME)); 480 } 481 if (msg != null) { 482 JmriJOptionPane.showMessageDialog(this, msg, 483 Bundle.getMessage("configureSignal"), JmriJOptionPane.INFORMATION_MESSAGE); 484 return false; 485 } 486 return true; 487 } 488/* 489 private void changeName(Portal portal) { 490 if (portal == null) { 491 portal = _portalList.getSelectedValue(); 492 } 493 String msg = null; 494 if (portal != null) { 495 NamedBean signal = portal.getSignalProtectingBlock(_homeBlock); 496 if (signal != null) { 497 String name = _mastName.getText().trim(); 498 if ( name.length()==0) { 499 msg = Bundle.getMessage("selectSignalMast", Bundle.getMessage("mastName")); 500 } else { 501 NamedBean nb; 502 if (signal instanceof SignalMast) { 503 nb = InstanceManager.getDefault(SignalMastManager.class).getByUserName(name); 504 } else { 505 nb = InstanceManager.getDefault(SignalHeadManager.class).getByUserName(name); 506 } 507 if (nb != null) { 508 msg = Bundle.getMessage("signalExists", name, signal.getDisplayName()); 509 } else { 510 // TODO!!!! patch up references to name change! 511 signal.setUserName(name); 512 } 513 } 514 } else { 515 msg = Bundle.getMessage("noMast", portal.getName(), 516 _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME)); 517 } 518 } else { 519 msg = Bundle.getMessage("selectPortalProtection", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME)); 520 } 521 if (msg != null) { 522 JmriJOptionPane.showMessageDialog(this, msg, 523 Bundle.getMessage("configureSignal"), JmriJOptionPane.INFORMATION_MESSAGE); 524 } 525 }*/ 526 527 private void removeMast() { 528 Portal portal = _portalList.getSelectedValue(); 529 NamedBean oldMast = null; 530 if (portal != null) { 531 oldMast = portal.getSignalProtectingBlock(_homeBlock); 532 } else { 533 _mastName.setText(null); 534 return; 535 } 536 if (oldMast != null) { 537 _mastName.setText(null); // do before portal triggers propertyChange 538 portal.setProtectSignal(null, 0, _homeBlock); 539 _parent.putSignalPortal(oldMast, null); 540 } else { 541 JmriJOptionPane.showMessageDialog(this, 542 Bundle.getMessage("noPortalProtection", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME), 543 portal.getName()), 544 Bundle.getMessage("configureSignal"), JmriJOptionPane.INFORMATION_MESSAGE); 545 } 546 _mastName.setText(null); 547 } 548 549 /** 550 * Check for questions about configuring this signal 551 * @return message of any concerns. But ALWAYS non-null. 552 */ 553 private String checkMastForSave() { 554 if (_currentPortal == null) { 555 return ""; 556 } 557 StringBuffer sb = new StringBuffer(); 558 NamedBean selectedMast = getSignal(); 559 NamedBean currentMast = _currentPortal.getSignalProtectingBlock(_homeBlock); 560 561 if (selectedMast == null) { 562 if (currentMast != null) { 563 String curMastName = currentMast.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME); 564 String curPortalName = _currentPortal.getName(); 565 sb.append(Bundle.getMessage("mastProtectsPortal", curMastName, 566 _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME), curPortalName)); 567 sb.append("\n"); 568 String name = _mastName.getText(); 569 if (name.trim().length() > 0) { 570 sb.append(Bundle.getMessage("NotFound", name)); 571 sb.append("\n"); 572 String type; 573 if (currentMast instanceof SignalMast) { 574 type = Bundle.getMessage("BeanNameSignalMast"); 575 } else { 576 type = Bundle.getMessage("BeanNameSignalHead"); 577 } 578 sb.append(Bundle.getMessage("changeOrCancel", curMastName, name, type)); 579 } else { 580 sb.append(Bundle.getMessage("removeSignalMast", curMastName, curPortalName)); 581 } 582 } 583 } else { 584 String selMastName = selectedMast.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME); 585 String curPortalName = _currentPortal.getName(); 586 String homeName = _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME); 587 if (!selectedMast.equals(currentMast)) { 588 if (currentMast != null) { 589 Portal selectedPortal = _parent.getSignalPortal(selectedMast); 590 if (selectedPortal != null) { 591 OBlock blk = selectedPortal.getProtectedBlock(selectedMast); 592 if (blk != null) { 593 sb.append(Bundle.getMessage("mastProtectsPortal", selMastName, 594 blk.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME), selectedPortal.getName())); 595 sb.append("\n"); 596 } 597 } 598 String curMastName = currentMast.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME); 599 sb.append(Bundle.getMessage("mastProtectsPortal", curMastName, homeName, curPortalName)); 600 sb.append("\n"); 601 sb.append(Bundle.getMessage("replaceSignalMast", curMastName, selMastName, curPortalName)); 602 sb.append("\n"); 603 if (_lengthPanel.isChanged(_currentPortal.getEntranceSpaceForBlock(_homeBlock))) { 604 sb.append(Bundle.getMessage("spaceChanged", selMastName, _currentPortal.getName())); 605 } 606 } else { 607 sb.append(Bundle.getMessage("noMast", curPortalName, homeName)); 608 sb.append("\n"); 609 sb.append(Bundle.getMessage("setSignal", selMastName)); 610 sb.append("\n"); 611 sb.append(Bundle.getMessage("attachMast", selMastName, 612 homeName, _currentPortal.getName())); 613 } 614 } 615 } 616 return sb.toString(); 617 } 618 619 @Override 620 protected void closingEvent(boolean close) { 621 StringBuffer sb = new StringBuffer(); 622 String msg = _parent.checkForPortals(_homeBlock, "ItemTypeSignalMast"); 623 if (msg.length() > 0) { 624 sb.append(msg); 625 sb.append("\n"); 626 } 627 msg = checkMastForSave(); 628 if (msg.length() > 0) { 629 sb.append(msg); 630 sb.append("\n"); 631 } 632 closingEvent(close, sb.toString()); 633 if (_pickMast != null) { 634 _pickMast.closePickList(); 635 } 636 if (_pickHead != null) { 637 _pickHead.closePickList(); 638 } 639 if (_mastTableAction != null) { 640 _mastTableAction.dispose(); 641 BeanTableFrame<SignalMast> frame = _mastTableAction.getFrame(); 642 if (frame != null) { 643 frame.dispose(); 644 } 645 } 646 if (_headTableAction != null) { 647 _headTableAction.dispose(); 648 BeanTableFrame<SignalHead> frame = _headTableAction.getFrame(); 649 if (frame != null) { 650 frame.dispose(); 651 } 652 } 653 } 654 655 private void setDragIcon(NamedBean signal) { 656 NamedIcon icon = null; 657 if (signal != null) { 658 if (signal instanceof SignalMast) { 659 icon = setDragMastIcon((SignalMast)signal); 660 } else if (signal instanceof SignalHead) { 661 icon = setDragHeadIcon((SignalHead)signal); 662 } 663 } 664 if (icon == null) { 665 _dragLabel.setText(Bundle.getMessage("noIcon")); 666 } else { 667 _dragLabel.setText(null); 668 } 669 _dragLabel.setIcon(icon); 670 _dndPanel.invalidate(); 671 invalidate(); 672 pack(); 673 } 674 675 private NamedIcon setDragMastIcon(SignalMast mast) { 676 String family = mast.getSignalSystem().getSystemName(); 677 SignalAppearanceMap appMap = mast.getAppearanceMap(); 678 Enumeration<String> e = mast.getAppearanceMap().getAspects(); 679 String s = appMap.getImageLink("Clear", family); 680 if ( s == null || s.equals("")) { 681 s = appMap.getImageLink("Stop", family); 682 } 683 if ( s == null || s.equals("")) { 684 s = appMap.getImageLink(e.nextElement(), family); 685 } 686 if (s !=null && !s.equals("")) { 687 if (!s.contains("preference:")) { 688 s = s.substring(s.indexOf("resources")); 689 } 690 return new NamedIcon(s, s); 691 } 692 log.error("SignalMast icon cannot be found for {}", mast.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME)); 693 return null; 694 } 695 696 private NamedIcon setDragHeadIcon(SignalHead mast) { 697 _dragHeadIcon = null; 698 // find icon from other icons displaying this head, if any 699 List<PositionableIcon> iArray = _parent.getSignalIconMap(mast); 700 if (!iArray.isEmpty()) { 701 PositionableIcon pos = iArray.get(0); 702 if (pos instanceof SignalHeadIcon) { 703 _dragHeadIcon = (SignalHeadIcon)pos; 704 } 705 } 706 if (_dragHeadIcon == null) { // find icon from icons of other heads on this panel 707 HashMap<NamedBean, ArrayList<PositionableIcon>> icons = _parent.getSignalIconMap(); 708 if (icons != null && !icons.isEmpty()) { 709 for (List<PositionableIcon> ia : icons.values()) { 710 if (!ia.isEmpty()) { 711 PositionableIcon pos = ia.get(0); 712 if (pos instanceof SignalHeadIcon) { 713 _dragHeadIcon = (SignalHeadIcon)pos; 714 break; 715 } 716 } 717 } 718 } 719 } 720 if (_dragHeadIcon == null) { // find icon from any set in ItemPalette 721 _dragHeadIcon = new SignalHeadIcon(_parent._editor); 722 _dragHeadIcon.setSignalHead(mast.getDisplayName()); 723 HashMap<String, HashMap<String, NamedIcon>> maps = ItemPalette.getFamilyMaps("SignalHead"); 724 if (maps.isEmpty()) { 725 log.error("SignalHead icon cannot be found for {}", mast.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME)); 726 } else { 727 for (Entry<String, HashMap<String, NamedIcon>> entry : maps.entrySet()) { 728 HashMap<String, NamedIcon> map = entry.getValue(); 729 for (Entry<String, NamedIcon> ent : map.entrySet()) { 730 _dragHeadIcon.setIcon(ent.getKey(), new NamedIcon(ent.getValue())); 731 } 732 _dragHeadIcon.setFamily(entry.getKey()); 733 break; 734 } 735 } 736 } else { 737 _dragHeadIcon = (SignalHeadIcon)_dragHeadIcon.deepClone(); 738 } 739 _dragHeadIcon.setDisplayLevel(SignalHead.RED); 740 return (NamedIcon)_dragHeadIcon.getIcon(); 741 } 742 743 SignalHeadIcon _dragHeadIcon; 744 745 //////////////////////////// DnD //////////////////////////// 746 protected JPanel makeDndIconPanel() { 747 JPanel dndPanel = new JPanel(); 748 dndPanel.setLayout(new BoxLayout(dndPanel, BoxLayout.Y_AXIS)); 749 750 JPanel p = new JPanel(); 751 JLabel l = new JLabel(Bundle.getMessage("dragIcon")); 752 p.add(l); 753 dndPanel.add(p); 754 755 JPanel panel = new JPanel(); 756 panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), 757 Bundle.getMessage("signal"))); 758 try { 759 _dragLabel = new IconDragJLabel(new DataFlavor(Editor.POSITIONABLE_FLAVOR)); 760 _dragLabel.setIcon(null); 761 _dragLabel.setText(Bundle.getMessage("noIcon")); 762 _dragLabel.setName(Bundle.getMessage("signal")); 763 panel.add(_dragLabel); 764 } catch (java.lang.ClassNotFoundException cnfe) { 765 log.error("Unable to find class supporting {}", Editor.POSITIONABLE_FLAVOR, cnfe); 766 } 767 dndPanel.add(panel); 768 dndPanel.setVisible(true); 769 return dndPanel; 770 } 771 772 public class IconDragJLabel extends DragJLabel { 773 774 NamedBean signal; 775 776 public IconDragJLabel(DataFlavor flavor) { 777 super(flavor); 778 } 779 780 @Override 781 protected boolean okToDrag() { 782 String msg; 783 if (_currentPortal == null) { 784 msg = Bundle.getMessage("selectPortalProtection", _homeBlock.getDisplayName(DisplayOptions.QUOTED_DISPLAYNAME)); 785 } else { 786 signal = getSignal(); 787 if (signal != null) { 788 msg = checkMastForSave(); 789 } else { 790 String name = _mastName.getText().trim(); 791 if ( name.length()==0) { 792 msg = Bundle.getMessage("selectSignalMast"); 793 } else { 794 msg = Bundle.getMessage("NotFound", name); 795 } 796 } 797 } 798 if (msg.length() > 0) { 799 JmriJOptionPane.showMessageDialog(this, msg, 800 Bundle.getMessage("configureSignal"), JmriJOptionPane.INFORMATION_MESSAGE); 801 return false; 802 } 803 return true; 804 } 805 806 @Override 807 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { 808 if (!isDataFlavorSupported(flavor)) { 809 return null; 810 } 811 if (DataFlavor.stringFlavor.equals(flavor)) { 812 return null; 813 } 814 815 if (signal == null || _currentPortal == null) { 816 return null; 817 } 818 PositionableIcon icon; 819 if (signal instanceof SignalMast) { 820 icon = new SignalMastIcon(_parent._editor); 821 ((SignalMastIcon)icon).setSignalMast(signal.getDisplayName()); 822 } else if (signal instanceof SignalHead) { 823 icon = _dragHeadIcon; 824 } else { 825 log.error("Signal icon cannot be created for {}", signal.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME)); 826 return null; 827 } 828 _parent.getCircuitIcons(_homeBlock).add(icon); 829 List<PositionableIcon> siArray = _parent.getSignalIconMap(signal); 830 siArray.add(icon); 831 _parent._editor.highlight(icon); 832 icon.setLevel(Editor.SIGNALS); 833 log.debug("getTransferData for {}", signal.getDisplayName(DisplayOptions.USERNAME_SYSTEMNAME)); 834 return icon; 835 } 836 837 @Override 838 public void dragDropEnd(DragSourceDropEvent e) { 839 setMastNameAndIcon(signal, _currentPortal); 840 log.debug("DragJLabel.dragDropEnd "); 841 } 842 } 843 844 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EditSignalFrame.class); 845 846}