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