001package jmri.jmrit.throttle; 002 003import java.awt.*; 004import java.awt.event.*; 005import java.beans.PropertyChangeListener; 006import java.beans.PropertyVetoException; 007import java.io.File; 008import java.net.URI; 009import java.util.HashMap; 010import java.util.List; 011 012import javax.swing.*; 013 014import jmri.*; 015import jmri.jmrit.catalog.NamedIcon; 016import jmri.jmrit.jython.Jynstrument; 017import jmri.jmrit.jython.JynstrumentFactory; 018import jmri.util.FileUtil; 019import jmri.util.JmriJFrame; 020import jmri.util.iharder.dnd.URIDrop; 021 022import org.jdom2.Element; 023import org.jdom2.Attribute; 024 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027 028// Should be named ThrottleFrame, but ThrottleFrame already exit, hence ThrottleWindow 029public class ThrottleWindow extends JmriJFrame { 030 031 private final jmri.jmrix.ConnectionConfig connectionConfig; 032 private final ThrottleManager throttleManager; 033 034 private JPanel throttlesPanel; 035 private ThrottleFrame currentThrottleFrame; 036 private CardLayout throttlesLayout; 037 038 private JCheckBoxMenuItem viewControlPanel; 039 private JCheckBoxMenuItem viewFunctionPanel; 040 private JCheckBoxMenuItem viewAddressPanel; 041 private JCheckBoxMenuItem viewSpeedPanel; 042 private JMenuItem viewAllButtons; 043 private JMenuItem fileMenuSave; 044 private JMenuItem editMenuExportRoster; 045 046 private JButton jbPrevious = null; 047 private JButton jbNext = null; 048 private JButton jbPreviousRunning = null; 049 private JButton jbNextRunning = null; 050 private JButton jbThrottleList = null; 051 private JButton jbNew = null; 052 private JButton jbClose = null; 053 private JButton jbMode = null; 054 private JToolBar throttleToolBar; 055 056 private String titleText = ""; 057 private String titleTextType = "rosterID"; 058 private boolean isEditMode = true; 059 060 private final PowerManager powerMgr; 061 private SmallPowerManagerButton smallPowerMgmtButton; 062 063 private final ThrottleWindowActionsFactory myActionFactory; 064 065 private HashMap<String, ThrottleFrame> throttleFrames = new HashMap<>(5); 066 private int cardCounterID = 0; // to generate unique names for each card 067 private int cardCounterNB = 1; // real counter 068 069 java.beans.PropertyChangeSupport pcs = new java.beans.PropertyChangeSupport(this); 070 071 /** 072 * Default constructor 073 */ 074 public ThrottleWindow() { 075 this((jmri.jmrix.ConnectionConfig) null); 076 } 077 078 /** 079 * Constructor 080 * @param connectionConfig the connection config 081 */ 082 public ThrottleWindow(jmri.jmrix.ConnectionConfig connectionConfig) { 083 super(); 084 this.connectionConfig = connectionConfig; 085 if (connectionConfig != null) { 086 this.throttleManager = connectionConfig.getAdapter().getSystemConnectionMemo().get(jmri.ThrottleManager.class); 087 } else { 088 this.throttleManager = InstanceManager.getDefault(jmri.ThrottleManager.class); 089 } 090 091 myActionFactory = new ThrottleWindowActionsFactory(this); 092 powerMgr = InstanceManager.getNullableDefault(PowerManager.class); 093 if (powerMgr == null) { 094 log.info("No power manager instance found, panel not active"); 095 } 096 pcs.addPropertyChangeListener(InstanceManager.getDefault(ThrottleFrameManager.class).getThrottlesListPanel().getTableModel()); 097 initGUI(); 098 applyPreferences(); 099 } 100 101 /** 102 * Create a ThrottleWindow 103 * @param e the xml element for the throttle window 104 * @return the throttle window 105 */ 106 public static ThrottleWindow createThrottleWindow(Element e) { 107 jmri.jmrix.ConnectionConfig connectionConfig = null; 108 109 Attribute systemPrefixAttr = e.getAttribute("systemPrefix"); 110 if (systemPrefixAttr != null) { 111 String systemPrefix = systemPrefixAttr.getValue(); 112 // Set connectionConfig to null in case the systemPrefix 113 // points to a connection that doesn't exist anymore. 114 115 for (jmri.jmrix.ConnectionConfig c : InstanceManager.getDefault(jmri.jmrix.ConnectionConfigManager.class)) { 116 if (c.getAdapter().getSystemPrefix().equals(systemPrefix)) { 117 connectionConfig = c; 118 } 119 } 120 } 121 122 ThrottleWindow tw = new ThrottleWindow(connectionConfig); 123 tw.setXml(e); 124 return tw; 125 } 126 127 private void initGUI() { 128 setTitle(Bundle.getMessage("ThrottleTitle")); 129 setLayout(new BorderLayout()); 130 throttlesLayout = new CardLayout(); 131 throttlesPanel = new JPanel(throttlesLayout); 132 throttlesPanel.setDoubleBuffered(true); 133 134 initializeToolbar(); 135 initializeMenu(); 136 137 setCurrentThrottleFrame(new ThrottleFrame(this, throttleManager)); 138 getCurrentThrottleFrame().setTitle("default"); 139 throttlesPanel.add(getCurrentThrottleFrame(), "default"); 140 throttleFrames.put("default", getCurrentThrottleFrame()); 141 add(throttlesPanel, BorderLayout.CENTER); 142 143 installInputsListenerOnAllComponents(this); 144 // to get something to put focus on 145 getRootPane().setFocusable(true); 146 147 ActionMap am = myActionFactory.buildActionMap(); 148 for (Object k : am.allKeys()) { 149 getRootPane().getActionMap().put(k, am.get(k)); 150 } 151 152 addMouseWheelListener( new ThrottleWindowInputsListener(this) ); 153 154 this.addWindowListener(new WindowAdapter() { 155 @Override 156 public void windowClosing(WindowEvent e) { 157 ThrottleWindow me = (ThrottleWindow) e.getSource(); 158 InstanceManager.getDefault(ThrottleFrameManager.class).requestThrottleWindowDestruction(me); 159 if (throttleToolBar != null) { 160 Component[] cmps = throttleToolBar.getComponents(); 161 if (cmps != null) { 162 for (Component cmp : cmps) { 163 if (cmp instanceof Jynstrument) { 164 ((Jynstrument) cmp).exit(); 165 } 166 } 167 } 168 } 169 } 170 171 @Override 172 public void windowOpened(WindowEvent e) { 173 try { // on initial open, force selection of address panel 174 getCurrentThrottleFrame().getAddressPanel().setSelected(true); 175 } catch (PropertyVetoException ex) { 176 log.warn("Unable to force selection of address panel", ex); 177 } 178 } 179 }); 180 updateGUI(); 181 } 182 183 public void updateGUI() { 184 if (getCurrentThrottleFrame() == null) { 185 return; 186 } 187 // title bar 188 getCurrentThrottleFrame().setFrameTitle(); 189 // menu items 190 viewAddressPanel.setEnabled(isEditMode); 191 viewControlPanel.setEnabled(isEditMode); 192 viewFunctionPanel.setEnabled(isEditMode); 193 viewSpeedPanel.setEnabled(isEditMode); 194 if (isEditMode) { 195 viewAddressPanel.setSelected(getCurrentThrottleFrame().getAddressPanel().isVisible()); 196 viewControlPanel.setSelected(getCurrentThrottleFrame().getControlPanel().isVisible()); 197 viewFunctionPanel.setSelected(getCurrentThrottleFrame().getFunctionPanel().isVisible()); 198 viewSpeedPanel.setSelected(getCurrentThrottleFrame().getSpeedPanel().isVisible()); 199 } 200 fileMenuSave.setEnabled(getCurrentThrottleFrame().getLastUsedSaveFile() != null || getCurrentThrottleFrame().getRosterEntry() != null); 201 editMenuExportRoster.setEnabled(getCurrentThrottleFrame().getRosterEntry() != null); 202 // toolbar items 203 if (jbPrevious != null) // means toolbar enabled 204 { 205 if (cardCounterNB > 1) { 206 jbPrevious.setEnabled(true); 207 jbNext.setEnabled(true); 208 jbClose.setEnabled(true); 209 jbPreviousRunning.setEnabled(true); 210 jbNextRunning.setEnabled(true); 211 } else { 212 jbPrevious.setEnabled(false); 213 jbNext.setEnabled(false); 214 jbClose.setEnabled(false); 215 jbPreviousRunning.setEnabled(false); 216 jbNextRunning.setEnabled(false); 217 } 218 } 219 getRootPane().requestFocusInWindow(); 220 } 221 222 private void initializeToolbar() { 223 throttleToolBar = new JToolBar("Throttles toolbar"); 224 225 jbNew = new JButton(); 226 // nouveau.setText(Bundle.getMessage("ThrottleToolBarNew")); 227 jbNew.setIcon(new NamedIcon("resources/icons/throttles/add.png", "resources/icons/throttles/add.png")); 228 jbNew.setToolTipText(Bundle.getMessage("ThrottleToolBarNewToolTip")); 229 jbNew.setVerticalTextPosition(JButton.BOTTOM); 230 jbNew.setHorizontalTextPosition(JButton.CENTER); 231 jbNew.addActionListener(e -> addThrottleFrame()); 232 throttleToolBar.add(jbNew); 233 234 jbClose = new JButton(); 235// close.setText(Bundle.getMessage("ThrottleToolBarClose")); 236 jbClose.setIcon(new NamedIcon("resources/icons/throttles/remove.png", "resources/icons/throttles/remove.png")); 237 jbClose.setToolTipText(Bundle.getMessage("ThrottleToolBarCloseToolTip")); 238 jbClose.setVerticalTextPosition(JButton.BOTTOM); 239 jbClose.setHorizontalTextPosition(JButton.CENTER); 240 jbClose.addActionListener(e -> removeThrottleFrame()); 241 throttleToolBar.add(jbClose); 242 243 throttleToolBar.addSeparator(); 244 245 jbPreviousRunning = new JButton(); 246 jbPreviousRunning.setIcon(new NamedIcon("resources/icons/throttles/previous-jump.png", "resources/icons/throttles/previous-jump.png")); 247 jbPreviousRunning.setVerticalTextPosition(JButton.BOTTOM); 248 jbPreviousRunning.setHorizontalTextPosition(JButton.CENTER); 249 jbPreviousRunning.setToolTipText(Bundle.getMessage("ThrottleToolBarPrevRunToolTip")); 250 jbPreviousRunning.addActionListener(e -> previousRunningThrottleFrame()); 251 throttleToolBar.add(jbPreviousRunning); 252 253 jbPrevious = new JButton(); 254 jbPrevious.setIcon(new NamedIcon("resources/icons/throttles/previous.png", "resources/icons/throttles/previous.png")); 255 jbPrevious.setVerticalTextPosition(JButton.BOTTOM); 256 jbPrevious.setHorizontalTextPosition(JButton.CENTER); 257 jbPrevious.setToolTipText(Bundle.getMessage("ThrottleToolBarPrevToolTip")); 258 jbPrevious.addActionListener(e -> previousThrottleFrame()); 259 throttleToolBar.add(jbPrevious); 260 261 jbNext = new JButton(); 262 // next.setText(Bundle.getMessage("ThrottleToolBarNext")); 263 jbNext.setIcon(new NamedIcon("resources/icons/throttles/next.png", "resources/icons/throttles/next.png")); 264 jbNext.setToolTipText(Bundle.getMessage("ThrottleToolBarNextToolTip")); 265 jbNext.setVerticalTextPosition(JButton.BOTTOM); 266 jbNext.setHorizontalTextPosition(JButton.CENTER); 267 jbNext.addActionListener(e -> nextThrottleFrame()); 268 throttleToolBar.add(jbNext); 269 270 jbNextRunning = new JButton(); 271 jbNextRunning.setIcon(new NamedIcon("resources/icons/throttles/next-jump.png", "resources/icons/throttles/next-jump.png")); 272 jbNextRunning.setToolTipText(Bundle.getMessage("ThrottleToolBarNextRunToolTip")); 273 jbNextRunning.setVerticalTextPosition(JButton.BOTTOM); 274 jbNextRunning.setHorizontalTextPosition(JButton.CENTER); 275 jbNextRunning.addActionListener(e -> nextRunningThrottleFrame()); 276 throttleToolBar.add(jbNextRunning); 277 278 throttleToolBar.addSeparator(); 279 280 throttleToolBar.add(new StopAllButton()); 281 282 if (powerMgr != null) { 283 throttleToolBar.add(new LargePowerManagerButton(false)); 284 } 285 286 throttleToolBar.addSeparator(); 287 288 jbMode = new JButton(); 289 jbMode.setIcon(new NamedIcon("resources/icons/throttles/edit-view.png", "resources/icons/throttles/edit-view.png")); 290 jbMode.setToolTipText(Bundle.getMessage("ThrottleToolBarEditToolTip")); 291 jbMode.setVerticalTextPosition(JButton.BOTTOM); 292 jbMode.setHorizontalTextPosition(JButton.CENTER); 293 jbMode.addActionListener(e -> setEditMode( !isEditMode )); 294 throttleToolBar.add(jbMode); 295 296 throttleToolBar.addSeparator(); 297 298 jbThrottleList = new JButton(); 299 jbThrottleList.setIcon(new NamedIcon("resources/icons/throttles/list.png", "resources/icons/throttles/list.png")); 300 jbThrottleList.setToolTipText(Bundle.getMessage("ThrottleToolBarOpenThrottleListToolTip")); 301 jbThrottleList.setVerticalTextPosition(JButton.BOTTOM); 302 jbThrottleList.setHorizontalTextPosition(JButton.CENTER); 303 jbThrottleList.addActionListener(new ThrottlesListAction()); 304 throttleToolBar.add(jbThrottleList); 305 306 // Receptacle for Jynstruments 307 new URIDrop(throttleToolBar, uris -> { 308 for (URI uri : uris ) { 309 ynstrument(new File(uri).getPath()); 310 } 311 }); 312 313 add(throttleToolBar, BorderLayout.PAGE_START); 314 } 315 316 /** {@inheritDoc} */ 317 @Override 318 public void setTitle(String title) { 319 if (connectionConfig != null) { 320 super.setTitle(Bundle.getMessage("ThrottleTitleWithConnection", title, connectionConfig.getConnectionName())); 321 } else { 322 super.setTitle(title); 323 } 324 } 325 326 public void setEditMode(boolean mode) { 327 if (mode == isEditMode) 328 return; 329 isEditMode = mode; 330 if (!throttleFrames.isEmpty()) { 331 throttleFrames.values().forEach((throttleFrame) -> { 332 throttleFrame.setEditMode(isEditMode); 333 }); 334 } 335 updateGUI(); 336 } 337 338 public boolean isEditMode() { 339 return isEditMode; 340 } 341 342 public Jynstrument ynstrument(String path) { 343 Jynstrument it = JynstrumentFactory.createInstrument(path, this); 344 if (it == null) { 345 log.error("Error while creating Jynstrument {}", path); 346 return null; 347 } 348 ThrottleFrame.setTransparent(it, true); 349 it.setVisible(true); 350 throttleToolBar.add(it); 351 throttleToolBar.repaint(); 352 return it; 353 } 354 355 /** 356 * Set up View, Edit and Power Menus 357 */ 358 private void initializeMenu() { 359 JMenu fileMenu = new JMenu(Bundle.getMessage("MenuFile")); 360 361 JMenuItem fileMenuLoad = new JMenuItem(Bundle.getMessage("ThrottleFileMenuLoadThrottle")); 362 fileMenuLoad.addActionListener(new AbstractAction() { 363 364 @Override 365 public void actionPerformed(ActionEvent e) { 366 getCurrentThrottleFrame().loadThrottle(); 367 } 368 }); 369 fileMenuSave = new JMenuItem(Bundle.getMessage("ThrottleFileMenuSaveThrottle")); 370 fileMenuSave.addActionListener(new AbstractAction() { 371 372 @Override 373 public void actionPerformed(ActionEvent e) { 374 getCurrentThrottleFrame().saveThrottle(); 375 } 376 }); 377 JMenuItem fileMenuSaveAs = new JMenuItem(Bundle.getMessage("ThrottleFileMenuSaveAsThrottle")); 378 fileMenuSaveAs.addActionListener(new AbstractAction() { 379 380 @Override 381 public void actionPerformed(ActionEvent e) { 382 getCurrentThrottleFrame().saveThrottleAs(); 383 } 384 }); 385 386 jmri.jmrit.throttle.ThrottleCreationAction.addNewThrottleItemsToThrottleMenu(fileMenu); 387 fileMenu.add(fileMenuLoad); 388 fileMenu.add(fileMenuSave); 389 fileMenu.add(fileMenuSaveAs); 390 fileMenu.addSeparator(); 391 392 fileMenu.add(new jmri.jmrit.throttle.LoadXmlThrottlesLayoutAction(Bundle.getMessage("MenuItemLoadThrottleLayout"))); 393 fileMenu.add(new jmri.jmrit.throttle.StoreXmlThrottlesLayoutAction(Bundle.getMessage("MenuItemSaveThrottleLayout"))); 394 fileMenu.addSeparator(); 395 fileMenu.add(new jmri.jmrit.throttle.LoadDefaultXmlThrottlesLayoutAction(Bundle.getMessage("MenuItemLoadDefaultThrottleLayout"))); 396 fileMenu.add(new jmri.jmrit.throttle.StoreDefaultXmlThrottlesLayoutAction(Bundle.getMessage("MenuItemSaveAsDefaultThrottleLayout"))); 397 fileMenu.addSeparator(); 398 fileMenu.add(new jmri.jmrit.withrottle.WiThrottleCreationAction(Bundle.getMessage("MenuItemStartWiThrottle"))); 399 400 JMenu viewMenu = new JMenu(Bundle.getMessage("ThrottleMenuView")); 401 viewAddressPanel = new JCheckBoxMenuItem(Bundle.getMessage("ThrottleMenuViewAddressPanel")); 402 viewAddressPanel.setSelected(true); 403 viewAddressPanel.addItemListener(e -> getCurrentThrottleFrame().getAddressPanel().setVisible(e.getStateChange() == ItemEvent.SELECTED)); 404 405 viewControlPanel = new JCheckBoxMenuItem(Bundle.getMessage("ThrottleMenuViewControlPanel")); 406 viewControlPanel.setSelected(true); 407 viewControlPanel.addItemListener(e -> getCurrentThrottleFrame().getControlPanel().setVisible(e.getStateChange() == ItemEvent.SELECTED)); 408 viewFunctionPanel = new JCheckBoxMenuItem(Bundle.getMessage("ThrottleMenuViewFunctionPanel")); 409 viewFunctionPanel.setSelected(true); 410 viewFunctionPanel.addItemListener(e -> getCurrentThrottleFrame().getFunctionPanel().setVisible(e.getStateChange() == ItemEvent.SELECTED)); 411 viewSpeedPanel = new JCheckBoxMenuItem(Bundle.getMessage("ThrottleMenuViewSpeedPanel")); 412 viewSpeedPanel.setSelected(false); 413 viewSpeedPanel.addItemListener(e -> getCurrentThrottleFrame().getSpeedPanel().setVisible(e.getStateChange() == ItemEvent.SELECTED)); 414 415 viewAllButtons = new JMenuItem(Bundle.getMessage("ThrottleMenuViewAllFunctionButtons")); 416 viewAllButtons.addActionListener(new AbstractAction() { 417 418 @Override 419 public void actionPerformed(ActionEvent ev) { 420 getCurrentThrottleFrame().getFunctionPanel().resetFnButtons(); 421 getCurrentThrottleFrame().getFunctionPanel().setEnabled(); 422 } 423 }); 424 425 JMenuItem makeAllComponentsInBounds = new JMenuItem(Bundle.getMessage("ThrottleMenuViewMakeAllComponentsInBounds")); 426 makeAllComponentsInBounds.addActionListener(new AbstractAction() { 427 428 @Override 429 public void actionPerformed(ActionEvent ev) { 430 getCurrentThrottleFrame().makeAllComponentsInBounds(); 431 } 432 }); 433 434 JMenuItem switchViewMode = new JMenuItem(Bundle.getMessage("ThrottleMenuViewSwitchMode")); 435 switchViewMode.addActionListener(new AbstractAction() { 436 437 @Override 438 public void actionPerformed(ActionEvent ev) { 439 setEditMode(!isEditMode); 440 } 441 }); 442 JMenuItem viewThrottlesList = new JMenuItem(Bundle.getMessage("ThrottleMenuViewViewThrottleList")); 443 viewThrottlesList.addActionListener(new ThrottlesListAction()); 444 445 viewMenu.add(viewAddressPanel); 446 viewMenu.add(viewControlPanel); 447 viewMenu.add(viewFunctionPanel); 448 viewMenu.add(viewSpeedPanel); 449 viewMenu.addSeparator(); 450 viewMenu.add(viewAllButtons); 451 viewMenu.add(makeAllComponentsInBounds); 452 viewMenu.addSeparator(); 453 viewMenu.add(switchViewMode); 454 viewMenu.add(viewThrottlesList); 455 456 JMenu editMenu = new JMenu(Bundle.getMessage("MenuEdit")); 457 JMenuItem preferencesItem = new JMenuItem(Bundle.getMessage("ThrottleMenuEditFrameProperties")); 458 editMenu.add(preferencesItem); 459 preferencesItem.addActionListener(e -> editPreferences()); 460 editMenuExportRoster = new JMenuItem(Bundle.getMessage("ThrottleMenuEditSaveCustoms")); 461 editMenu.add(editMenuExportRoster); 462 editMenuExportRoster.addActionListener(e -> getCurrentThrottleFrame().saveRosterChanges()); 463 editMenu.addSeparator(); 464 editMenu.add(new jmri.jmrit.throttle.ThrottlesPreferencesAction(Bundle.getMessage("MenuItemThrottlesPreferences"))); // now in tabbed preferences 465 466 this.setJMenuBar(new JMenuBar()); 467 this.getJMenuBar().add(fileMenu); 468 this.getJMenuBar().add(editMenu); 469 this.getJMenuBar().add(viewMenu); 470 471 if (powerMgr != null) { 472 JMenu powerMenu = new JMenu(Bundle.getMessage("ThrottleMenuPower")); 473 JMenuItem powerOn = new JMenuItem(Bundle.getMessage("ThrottleMenuPowerOn")); 474 powerMenu.add(powerOn); 475 powerOn.addActionListener(e -> { 476 try { 477 powerMgr.setPower(PowerManager.ON); 478 } catch (JmriException e1) { 479 log.error("Error when setting power: ", e1); 480 } 481 }); 482 483 JMenuItem powerOff = new JMenuItem(Bundle.getMessage("ThrottleMenuPowerOff")); 484 powerMenu.add(powerOff); 485 powerOff.addActionListener(e -> { 486 try { 487 powerMgr.setPower(PowerManager.OFF); 488 } catch (JmriException e1) { 489 log.error("Error when setting power: ", e1); 490 } 491 }); 492 493 this.getJMenuBar().add(powerMenu); 494 495 smallPowerMgmtButton = new SmallPowerManagerButton(); 496 this.getJMenuBar().add(smallPowerMgmtButton); 497 } 498 499 // add help selection 500 addHelpMenu("package.jmri.jmrit.throttle.ThrottleFrame", true); 501 } 502 503 private void editPreferences() { 504 ThrottleFramePropertyEditor editor = new ThrottleFramePropertyEditor(this); 505 editor.setVisible(true); 506 } 507 508 /** 509 * Handle my own destruction. 510 * <ol> 511 * <li> dispose of sub windows. 512 * <li> notify my manager of my demise. 513 * </ol> 514 * 515 */ 516 @Override 517 public void dispose() { 518 URIDrop.remove(throttleToolBar); 519 if ((throttleFrames != null) && (!throttleFrames.isEmpty())) { 520 throttleFrames.values().forEach((throttleFrame) -> { 521 throttleFrame.dispose(); 522 }); 523 throttleFrames.clear(); 524 } 525 throttleFrames = null; 526 currentThrottleFrame = null; 527 for (PropertyChangeListener pcl : pcs.getPropertyChangeListeners()) { 528 pcs.removePropertyChangeListener(pcl); 529 } 530 for (MouseWheelListener mwl : getMouseWheelListeners()) { 531 removeMouseWheelListener(mwl); 532 } 533 getRootPane().getActionMap().clear(); 534 throttlesPanel.removeAll(); 535 removeAll(); 536 super.dispose(); 537 } 538 539 public JCheckBoxMenuItem getViewControlPanel() { 540 return viewControlPanel; 541 } 542 543 public JCheckBoxMenuItem getViewFunctionPanel() { 544 return viewFunctionPanel; 545 } 546 547 public JCheckBoxMenuItem getViewAddressPanel() { 548 return viewAddressPanel; 549 } 550 551 public JCheckBoxMenuItem getViewSpeedPanel() { 552 return viewSpeedPanel; 553 } 554 555 private void updateCurentThrottleFrame() { 556 for (Component comp : throttlesPanel.getComponents()) { 557 if (comp instanceof ThrottleFrame && comp.isVisible()) { 558 currentThrottleFrame = (ThrottleFrame) comp; 559 } 560 } 561 } 562 563 public ThrottleFrame getCurrentThrottleFrame() { 564 return currentThrottleFrame; 565 } 566 567 public void setCurrentThrottleFrame(ThrottleFrame tf) { 568 if (getCurrentThrottleFrame() != null) { 569 log.debug("setCurrentThrottleFrame from {} to {}", getCurrentThrottleFrame().getAddressPanel().getCurrentAddress(), tf.getAddressPanel().getCurrentAddress()); 570 } 571 pcs.firePropertyChange("ThrottleFrame", getCurrentThrottleFrame(), tf); 572 currentThrottleFrame = tf; 573 } 574 575 public void removeThrottleFrame(ThrottleFrame tf) { 576 if (cardCounterNB > 1) // we don't like empty ThrottleWindow 577 { 578 cardCounterNB--; 579 if (getCurrentThrottleFrame() == tf) { 580 log.debug("Closing last created"); 581 } 582 throttlesPanel.remove(tf); 583 throttleFrames.remove(tf.getTitle()); 584 tf.dispose(); 585 throttlesLayout.invalidateLayout(throttlesPanel); 586 } 587 updateGUI(); 588 updateCurentThrottleFrame(); 589 pcs.firePropertyChange("ThrottleFrame", tf, getCurrentThrottleFrame()); 590 } 591 592 public void nextThrottleFrame() { 593 ThrottleFrame otf = getCurrentThrottleFrame(); 594 throttlesLayout.next(throttlesPanel); 595 updateCurentThrottleFrame(); 596 updateGUI(); 597 pcs.firePropertyChange("ThrottleFrame", otf, getCurrentThrottleFrame()); 598 } 599 600 public void previousThrottleFrame() { 601 ThrottleFrame otf = getCurrentThrottleFrame(); 602 throttlesLayout.previous(throttlesPanel); 603 updateCurentThrottleFrame(); 604 updateGUI(); 605 pcs.firePropertyChange("ThrottleFrame", otf, getCurrentThrottleFrame()); 606 } 607 608 public void nextRunningThrottleFrame() { 609 if (!throttleFrames.isEmpty()) { 610 ThrottleFrame cf = this.getCurrentThrottleFrame(); 611 ThrottleFrame nf = null; 612 boolean passed = false; 613 for (ThrottleFrame tf : throttleFrames.values()) { 614 if (tf != cf) { 615 if ((tf.getAddressPanel() != null) && (tf.getAddressPanel().getThrottle() != null) && (tf.getAddressPanel().getThrottle().getSpeedSetting() > 0)) { 616 if (passed) { // if we passed the curent one, and found something then return it 617 nf = tf; 618 break; 619 } else if (nf == null) { 620 nf = tf; 621 } 622 } 623 } else { 624 passed = true; 625 } 626 } 627 if (nf != null) { 628 nf.toFront(); 629 updateCurentThrottleFrame(); 630 pcs.firePropertyChange("ThrottleFrame", cf, nf); 631 } 632 } 633 } 634 635 public void previousRunningThrottleFrame() { 636 if (!throttleFrames.isEmpty()) { 637 ThrottleFrame cf = this.getCurrentThrottleFrame(); 638 ThrottleFrame nf = null; 639 for (ThrottleFrame tf : throttleFrames.values()) { 640 if ((tf != cf) && (tf.getAddressPanel() != null) && (tf.getAddressPanel().getThrottle() != null) && (tf.getAddressPanel().getThrottle().getSpeedSetting() > 0)) { 641 nf = tf; 642 } 643 if ((tf == cf) && (nf != null)) { // return the last one found before the curent one 644 break; 645 } 646 } 647 if (nf != null) { 648 nf.toFront(); 649 updateCurentThrottleFrame(); 650 pcs.firePropertyChange("ThrottleFrame", cf, nf); 651 } 652 } 653 } 654 655 public void removeThrottleFrame() { 656 removeThrottleFrame(getCurrentThrottleFrame()); 657 } 658 659 public void addThrottleFrame(ThrottleFrame tp) { 660 ThrottleFrame otf = getCurrentThrottleFrame(); 661 cardCounterID++; 662 cardCounterNB++; 663 String txt = "Card-" + cardCounterID; 664 tp.setTitle(txt); 665 throttleFrames.put(txt, tp); 666 throttlesPanel.add(tp, txt); 667 throttlesLayout.show(throttlesPanel, txt); 668 if (!isEditMode) { 669 tp.setEditMode(isEditMode); 670 } 671 updateCurentThrottleFrame(); 672 updateGUI(); 673 pcs.firePropertyChange("ThrottleFrame", otf, tp); 674 } 675 676 public ThrottleFrame addThrottleFrame() { 677 setCurrentThrottleFrame(new ThrottleFrame(this, throttleManager)); 678 installInputsListenerOnAllComponents(getCurrentThrottleFrame()); 679 addThrottleFrame(getCurrentThrottleFrame()); 680 return getCurrentThrottleFrame(); 681 } 682 683 public void toFront(String throttleFrameTitle) { 684 ThrottleFrame otf = getCurrentThrottleFrame(); 685 throttlesLayout.show(throttlesPanel, throttleFrameTitle); 686 updateCurentThrottleFrame(); 687 setVisible(true); 688 requestFocus(); 689 toFront(); 690 pcs.firePropertyChange("ThrottleFrame", otf, getCurrentThrottleFrame()); 691 } 692 693 public String getTitleTextType() { 694 return titleTextType; 695 } 696 697 public String getTitleText() { 698 return titleText; 699 } 700 701 public void setTitleText(String titleText) { 702 this.titleText = titleText; 703 } 704 705 public void setTitleTextType(String titleTextType) { 706 this.titleTextType = titleTextType; 707 } 708 709 public Element getXml() { 710 Element me = new Element("ThrottleWindow"); 711 if (connectionConfig != null) { 712 me.setAttribute("systemPrefix", connectionConfig.getAdapter().getSystemPrefix()); 713 } 714 me.setAttribute("title", titleText); 715 me.setAttribute("titleType", titleTextType); 716 me.setAttribute("isEditMode", String.valueOf(isEditMode)); 717 718 java.util.ArrayList<Element> children = new java.util.ArrayList<>(1); 719 children.add(WindowPreferences.getPreferences(this)); 720 if (!throttleFrames.isEmpty()) { 721 ThrottleFrame cf = this.getCurrentThrottleFrame(); 722 for (ThrottleFrame tf : throttleFrames.values()) { 723 if ((InstanceManager.getDefault(ThrottlesPreferences.class).isUsingExThrottle()) && (InstanceManager.getDefault(ThrottlesPreferences.class).isSavingThrottleOnLayoutSave())) { 724 tf.toFront(); 725 tf.saveThrottle(); 726 } 727 Element tfe = tf.getXmlFile(); 728 if (tfe == null) { 729 tfe = tf.getXml(); 730 } 731 children.add(tfe); 732 } 733 if (cf != null) { 734 cf.toFront(); 735 } 736 } 737 738 // Save Jynstruments 739 if (throttleToolBar != null) { 740 Component[] cmps = throttleToolBar.getComponents(); 741 if (cmps != null) { 742 for (Component cmp : cmps) { 743 try { 744 if (cmp instanceof Jynstrument) { 745 Jynstrument jyn = (Jynstrument) cmp; 746 Element elt = new Element("Jynstrument"); 747 elt.setAttribute("JynstrumentFolder", FileUtil.getPortableFilename(jyn.getFolder())); 748 Element je = jyn.getXml(); 749 if (je != null) { 750 java.util.ArrayList<Element> jychildren = new java.util.ArrayList<>(1); 751 jychildren.add(je); 752 elt.setContent(jychildren); 753 } 754 children.add(elt); 755 } 756 757 } catch (Exception ex) { 758 log.debug("Got exception (no panic): ", ex); 759 } 760 } 761 } 762 } 763 me.setContent(children); 764 return me; 765 } 766 767 private void setXml(Element e) { 768 if (e.getAttribute("title") != null) { 769 setTitle(e.getAttribute("title").getValue()); 770 } 771 if (e.getAttribute("title") != null) { 772 setTitleText(e.getAttribute("title").getValue()); 773 } 774 if (e.getAttribute("titleType") != null) { 775 setTitleTextType(e.getAttribute("titleType").getValue()); 776 } 777 if (e.getAttribute("isEditMode") != null) { 778 isEditMode = Boolean.parseBoolean(e.getAttribute("isEditMode").getValue()); 779 } 780 781 Element window = e.getChild("window"); 782 if (window != null) { 783 WindowPreferences.setPreferences(this, window); 784 } 785 786 List<Element> tfes = e.getChildren("ThrottleFrame"); 787 if ((tfes != null) && (tfes.size() > 0)) { 788 for (int i = 0; i < tfes.size(); i++) { 789 ThrottleFrame tf; 790 if (i == 0) { 791 tf = getCurrentThrottleFrame(); 792 } else { 793 tf = addThrottleFrame(); 794 } 795 tf.setXml(tfes.get(i)); 796 tf.setEditMode(isEditMode); 797 } 798 } 799 800 List<Element> jinsts = e.getChildren("Jynstrument"); 801 if ((jinsts != null) && (jinsts.size() > 0)) { 802 jinsts.forEach((jinst) -> { 803 Jynstrument jyn = ynstrument(FileUtil.getExternalFilename(jinst.getAttributeValue("JynstrumentFolder"))); 804 if (jyn != null) { 805 jyn.setXml(jinst); 806 } 807 }); 808 } 809 810 updateGUI(); 811 } 812 813 @Override 814 public synchronized void addPropertyChangeListener(java.beans.PropertyChangeListener l) { 815 pcs.addPropertyChangeListener(l); 816 } 817 818 @Override 819 public synchronized void removePropertyChangeListener(java.beans.PropertyChangeListener l) { 820 pcs.removePropertyChangeListener(l); 821 } 822 823 private void installInputsListenerOnAllComponents(Container c) { 824 c.setFocusTraversalKeysEnabled(false); // make tab and shift tab available 825 if (! ( c instanceof JTextField)) { 826 c.setFocusable(false); 827 } 828 for (Component component : c.getComponents()) { 829 if (component instanceof Container) { 830 installInputsListenerOnAllComponents( (Container) component); 831 } else { 832 if (! ( component instanceof JTextField)) { 833 component.setFocusable(false); 834 } 835 } 836 } 837 } 838 839 public void applyPreferences() { 840 ThrottlesPreferences preferences = InstanceManager.getDefault(ThrottlesPreferences.class); 841 842 ComponentInputMap im = new ComponentInputMap(getRootPane()); 843 for (Object k : this.getRootPane().getActionMap().allKeys()) { 844 KeyStroke[] kss = preferences.getThrottlesKeyboardControls().getKeyStrokes((String)k); 845 if (kss !=null) { 846 for (KeyStroke keystroke : kss) { 847 if (keystroke != null) { 848 im.put(keystroke, k); 849 } 850 } 851 } 852 } 853 getRootPane().setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW,im); 854 855 throttleToolBar.setVisible ( preferences.isUsingExThrottle() && preferences.isUsingToolBar() ); 856 857 if (smallPowerMgmtButton != null) { 858 smallPowerMgmtButton.setVisible( (!preferences.isUsingExThrottle()) || (!preferences.isUsingToolBar()) ); 859 } 860 861 throttleFrames.values().forEach(tf -> { 862 tf.applyPreferences(); 863 }); 864 } 865 866 private final static Logger log = LoggerFactory.getLogger(ThrottleWindow.class); 867}