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 // title bar 185 getCurrentThrottleFrame().setFrameTitle(); 186 // menu items 187 viewAddressPanel.setEnabled(isEditMode); 188 viewControlPanel.setEnabled(isEditMode); 189 viewFunctionPanel.setEnabled(isEditMode); 190 viewSpeedPanel.setEnabled(isEditMode); 191 if (isEditMode) { 192 viewAddressPanel.setSelected(getCurrentThrottleFrame().getAddressPanel().isVisible()); 193 viewControlPanel.setSelected(getCurrentThrottleFrame().getControlPanel().isVisible()); 194 viewFunctionPanel.setSelected(getCurrentThrottleFrame().getFunctionPanel().isVisible()); 195 viewSpeedPanel.setSelected(getCurrentThrottleFrame().getSpeedPanel().isVisible()); 196 } 197 fileMenuSave.setEnabled(getCurrentThrottleFrame().getLastUsedSaveFile() != null || getCurrentThrottleFrame().getRosterEntry() != null); 198 editMenuExportRoster.setEnabled(getCurrentThrottleFrame().getRosterEntry() != null); 199 // toolbar items 200 if (jbPrevious != null) // means toolbar enabled 201 { 202 if (cardCounterNB > 1) { 203 jbPrevious.setEnabled(true); 204 jbNext.setEnabled(true); 205 jbClose.setEnabled(true); 206 jbPreviousRunning.setEnabled(true); 207 jbNextRunning.setEnabled(true); 208 } else { 209 jbPrevious.setEnabled(false); 210 jbNext.setEnabled(false); 211 jbClose.setEnabled(false); 212 jbPreviousRunning.setEnabled(false); 213 jbNextRunning.setEnabled(false); 214 } 215 } 216 getRootPane().requestFocusInWindow(); 217 } 218 219 private void initializeToolbar() { 220 throttleToolBar = new JToolBar("Throttles toolbar"); 221 222 jbNew = new JButton(); 223 // nouveau.setText(Bundle.getMessage("ThrottleToolBarNew")); 224 jbNew.setIcon(new NamedIcon("resources/icons/throttles/add.png", "resources/icons/throttles/add.png")); 225 jbNew.setToolTipText(Bundle.getMessage("ThrottleToolBarNewToolTip")); 226 jbNew.setVerticalTextPosition(JButton.BOTTOM); 227 jbNew.setHorizontalTextPosition(JButton.CENTER); 228 jbNew.addActionListener(e -> addThrottleFrame()); 229 throttleToolBar.add(jbNew); 230 231 jbClose = new JButton(); 232// close.setText(Bundle.getMessage("ThrottleToolBarClose")); 233 jbClose.setIcon(new NamedIcon("resources/icons/throttles/remove.png", "resources/icons/throttles/remove.png")); 234 jbClose.setToolTipText(Bundle.getMessage("ThrottleToolBarCloseToolTip")); 235 jbClose.setVerticalTextPosition(JButton.BOTTOM); 236 jbClose.setHorizontalTextPosition(JButton.CENTER); 237 jbClose.addActionListener(e -> removeThrottleFrame()); 238 throttleToolBar.add(jbClose); 239 240 throttleToolBar.addSeparator(); 241 242 jbPreviousRunning = new JButton(); 243 jbPreviousRunning.setIcon(new NamedIcon("resources/icons/throttles/previous-jump.png", "resources/icons/throttles/previous-jump.png")); 244 jbPreviousRunning.setVerticalTextPosition(JButton.BOTTOM); 245 jbPreviousRunning.setHorizontalTextPosition(JButton.CENTER); 246 jbPreviousRunning.setToolTipText(Bundle.getMessage("ThrottleToolBarPrevRunToolTip")); 247 jbPreviousRunning.addActionListener(e -> previousRunningThrottleFrame()); 248 throttleToolBar.add(jbPreviousRunning); 249 250 jbPrevious = new JButton(); 251 jbPrevious.setIcon(new NamedIcon("resources/icons/throttles/previous.png", "resources/icons/throttles/previous.png")); 252 jbPrevious.setVerticalTextPosition(JButton.BOTTOM); 253 jbPrevious.setHorizontalTextPosition(JButton.CENTER); 254 jbPrevious.setToolTipText(Bundle.getMessage("ThrottleToolBarPrevToolTip")); 255 jbPrevious.addActionListener(e -> previousThrottleFrame()); 256 throttleToolBar.add(jbPrevious); 257 258 jbNext = new JButton(); 259 // next.setText(Bundle.getMessage("ThrottleToolBarNext")); 260 jbNext.setIcon(new NamedIcon("resources/icons/throttles/next.png", "resources/icons/throttles/next.png")); 261 jbNext.setToolTipText(Bundle.getMessage("ThrottleToolBarNextToolTip")); 262 jbNext.setVerticalTextPosition(JButton.BOTTOM); 263 jbNext.setHorizontalTextPosition(JButton.CENTER); 264 jbNext.addActionListener(e -> nextThrottleFrame()); 265 throttleToolBar.add(jbNext); 266 267 jbNextRunning = new JButton(); 268 jbNextRunning.setIcon(new NamedIcon("resources/icons/throttles/next-jump.png", "resources/icons/throttles/next-jump.png")); 269 jbNextRunning.setToolTipText(Bundle.getMessage("ThrottleToolBarNextRunToolTip")); 270 jbNextRunning.setVerticalTextPosition(JButton.BOTTOM); 271 jbNextRunning.setHorizontalTextPosition(JButton.CENTER); 272 jbNextRunning.addActionListener(e -> nextRunningThrottleFrame()); 273 throttleToolBar.add(jbNextRunning); 274 275 throttleToolBar.addSeparator(); 276 277 throttleToolBar.add(new StopAllButton()); 278 279 if (powerMgr != null) { 280 throttleToolBar.add(new LargePowerManagerButton(false)); 281 } 282 283 throttleToolBar.addSeparator(); 284 285 jbMode = new JButton(); 286 jbMode.setIcon(new NamedIcon("resources/icons/throttles/edit-view.png", "resources/icons/throttles/edit-view.png")); 287 jbMode.setToolTipText(Bundle.getMessage("ThrottleToolBarEditToolTip")); 288 jbMode.setVerticalTextPosition(JButton.BOTTOM); 289 jbMode.setHorizontalTextPosition(JButton.CENTER); 290 jbMode.addActionListener(e -> setEditMode( !isEditMode )); 291 throttleToolBar.add(jbMode); 292 293 throttleToolBar.addSeparator(); 294 295 jbThrottleList = new JButton(); 296 jbThrottleList.setIcon(new NamedIcon("resources/icons/throttles/list.png", "resources/icons/throttles/list.png")); 297 jbThrottleList.setToolTipText(Bundle.getMessage("ThrottleToolBarOpenThrottleListToolTip")); 298 jbThrottleList.setVerticalTextPosition(JButton.BOTTOM); 299 jbThrottleList.setHorizontalTextPosition(JButton.CENTER); 300 jbThrottleList.addActionListener(new ThrottlesListAction()); 301 throttleToolBar.add(jbThrottleList); 302 303 // Receptacle for Jynstruments 304 new URIDrop(throttleToolBar, uris -> { 305 for (URI uri : uris ) { 306 ynstrument(new File(uri).getPath()); 307 } 308 }); 309 310 add(throttleToolBar, BorderLayout.PAGE_START); 311 } 312 313 /** {@inheritDoc} */ 314 @Override 315 public void setTitle(String title) { 316 if (connectionConfig != null) { 317 super.setTitle(Bundle.getMessage("ThrottleTitleWithConnection", title, connectionConfig.getConnectionName())); 318 } else { 319 super.setTitle(title); 320 } 321 } 322 323 public void setEditMode(boolean mode) { 324 if (mode == isEditMode) 325 return; 326 isEditMode = mode; 327 if (!throttleFrames.isEmpty()) { 328 throttleFrames.values().forEach((throttleFrame) -> { 329 throttleFrame.setEditMode(isEditMode); 330 }); 331 } 332 updateGUI(); 333 } 334 335 public boolean isEditMode() { 336 return isEditMode; 337 } 338 339 public Jynstrument ynstrument(String path) { 340 Jynstrument it = JynstrumentFactory.createInstrument(path, this); 341 if (it == null) { 342 log.error("Error while creating Jynstrument {}", path); 343 return null; 344 } 345 ThrottleFrame.setTransparent(it, true); 346 it.setVisible(true); 347 throttleToolBar.add(it); 348 throttleToolBar.repaint(); 349 return it; 350 } 351 352 /** 353 * Set up View, Edit and Power Menus 354 */ 355 private void initializeMenu() { 356 JMenu fileMenu = new JMenu(Bundle.getMessage("MenuFile")); 357 358 JMenuItem fileMenuLoad = new JMenuItem(Bundle.getMessage("ThrottleFileMenuLoadThrottle")); 359 fileMenuLoad.addActionListener(new AbstractAction() { 360 361 @Override 362 public void actionPerformed(ActionEvent e) { 363 getCurrentThrottleFrame().loadThrottle(); 364 } 365 }); 366 fileMenuSave = new JMenuItem(Bundle.getMessage("ThrottleFileMenuSaveThrottle")); 367 fileMenuSave.addActionListener(new AbstractAction() { 368 369 @Override 370 public void actionPerformed(ActionEvent e) { 371 getCurrentThrottleFrame().saveThrottle(); 372 } 373 }); 374 JMenuItem fileMenuSaveAs = new JMenuItem(Bundle.getMessage("ThrottleFileMenuSaveAsThrottle")); 375 fileMenuSaveAs.addActionListener(new AbstractAction() { 376 377 @Override 378 public void actionPerformed(ActionEvent e) { 379 getCurrentThrottleFrame().saveThrottleAs(); 380 } 381 }); 382 383 jmri.jmrit.throttle.ThrottleCreationAction.addNewThrottleItemsToThrottleMenu(fileMenu); 384 fileMenu.add(fileMenuLoad); 385 fileMenu.add(fileMenuSave); 386 fileMenu.add(fileMenuSaveAs); 387 fileMenu.addSeparator(); 388 389 fileMenu.add(new jmri.jmrit.throttle.LoadXmlThrottlesLayoutAction(Bundle.getMessage("MenuItemLoadThrottleLayout"))); 390 fileMenu.add(new jmri.jmrit.throttle.StoreXmlThrottlesLayoutAction(Bundle.getMessage("MenuItemSaveThrottleLayout"))); 391 fileMenu.addSeparator(); 392 fileMenu.add(new jmri.jmrit.throttle.LoadDefaultXmlThrottlesLayoutAction(Bundle.getMessage("MenuItemLoadDefaultThrottleLayout"))); 393 fileMenu.add(new jmri.jmrit.throttle.StoreDefaultXmlThrottlesLayoutAction(Bundle.getMessage("MenuItemSaveAsDefaultThrottleLayout"))); 394 fileMenu.addSeparator(); 395 fileMenu.add(new jmri.jmrit.withrottle.WiThrottleCreationAction(Bundle.getMessage("MenuItemStartWiThrottle"))); 396 397 JMenu viewMenu = new JMenu(Bundle.getMessage("ThrottleMenuView")); 398 viewAddressPanel = new JCheckBoxMenuItem(Bundle.getMessage("ThrottleMenuViewAddressPanel")); 399 viewAddressPanel.setSelected(true); 400 viewAddressPanel.addItemListener(e -> getCurrentThrottleFrame().getAddressPanel().setVisible(e.getStateChange() == ItemEvent.SELECTED)); 401 402 viewControlPanel = new JCheckBoxMenuItem(Bundle.getMessage("ThrottleMenuViewControlPanel")); 403 viewControlPanel.setSelected(true); 404 viewControlPanel.addItemListener(e -> getCurrentThrottleFrame().getControlPanel().setVisible(e.getStateChange() == ItemEvent.SELECTED)); 405 viewFunctionPanel = new JCheckBoxMenuItem(Bundle.getMessage("ThrottleMenuViewFunctionPanel")); 406 viewFunctionPanel.setSelected(true); 407 viewFunctionPanel.addItemListener(e -> getCurrentThrottleFrame().getFunctionPanel().setVisible(e.getStateChange() == ItemEvent.SELECTED)); 408 viewSpeedPanel = new JCheckBoxMenuItem(Bundle.getMessage("ThrottleMenuViewSpeedPanel")); 409 viewSpeedPanel.setSelected(false); 410 viewSpeedPanel.addItemListener(e -> getCurrentThrottleFrame().getSpeedPanel().setVisible(e.getStateChange() == ItemEvent.SELECTED)); 411 412 viewAllButtons = new JMenuItem(Bundle.getMessage("ThrottleMenuViewAllFunctionButtons")); 413 viewAllButtons.addActionListener(new AbstractAction() { 414 415 @Override 416 public void actionPerformed(ActionEvent ev) { 417 getCurrentThrottleFrame().getFunctionPanel().resetFnButtons(); 418 getCurrentThrottleFrame().getFunctionPanel().setEnabled(); 419 } 420 }); 421 422 JMenuItem makeAllComponentsInBounds = new JMenuItem(Bundle.getMessage("ThrottleMenuViewMakeAllComponentsInBounds")); 423 makeAllComponentsInBounds.addActionListener(new AbstractAction() { 424 425 @Override 426 public void actionPerformed(ActionEvent ev) { 427 getCurrentThrottleFrame().makeAllComponentsInBounds(); 428 } 429 }); 430 431 JMenuItem switchViewMode = new JMenuItem(Bundle.getMessage("ThrottleMenuViewSwitchMode")); 432 switchViewMode.addActionListener(new AbstractAction() { 433 434 @Override 435 public void actionPerformed(ActionEvent ev) { 436 setEditMode(!isEditMode); 437 } 438 }); 439 JMenuItem viewThrottlesList = new JMenuItem(Bundle.getMessage("ThrottleMenuViewViewThrottleList")); 440 viewThrottlesList.addActionListener(new ThrottlesListAction()); 441 442 viewMenu.add(viewAddressPanel); 443 viewMenu.add(viewControlPanel); 444 viewMenu.add(viewFunctionPanel); 445 viewMenu.add(viewSpeedPanel); 446 viewMenu.addSeparator(); 447 viewMenu.add(viewAllButtons); 448 viewMenu.add(makeAllComponentsInBounds); 449 viewMenu.addSeparator(); 450 viewMenu.add(switchViewMode); 451 viewMenu.add(viewThrottlesList); 452 453 JMenu editMenu = new JMenu(Bundle.getMessage("MenuEdit")); 454 JMenuItem preferencesItem = new JMenuItem(Bundle.getMessage("ThrottleMenuEditFrameProperties")); 455 editMenu.add(preferencesItem); 456 preferencesItem.addActionListener(e -> editPreferences()); 457 editMenuExportRoster = new JMenuItem(Bundle.getMessage("ThrottleMenuEditSaveCustoms")); 458 editMenu.add(editMenuExportRoster); 459 editMenuExportRoster.addActionListener(e -> getCurrentThrottleFrame().saveRosterChanges()); 460 editMenu.addSeparator(); 461 editMenu.add(new jmri.jmrit.throttle.ThrottlesPreferencesAction(Bundle.getMessage("MenuItemThrottlesPreferences"))); // now in tabbed preferences 462 463 this.setJMenuBar(new JMenuBar()); 464 this.getJMenuBar().add(fileMenu); 465 this.getJMenuBar().add(editMenu); 466 this.getJMenuBar().add(viewMenu); 467 468 if (powerMgr != null) { 469 JMenu powerMenu = new JMenu(Bundle.getMessage("ThrottleMenuPower")); 470 JMenuItem powerOn = new JMenuItem(Bundle.getMessage("ThrottleMenuPowerOn")); 471 powerMenu.add(powerOn); 472 powerOn.addActionListener(e -> { 473 try { 474 powerMgr.setPower(PowerManager.ON); 475 } catch (JmriException e1) { 476 log.error("Error when setting power: ", e1); 477 } 478 }); 479 480 JMenuItem powerOff = new JMenuItem(Bundle.getMessage("ThrottleMenuPowerOff")); 481 powerMenu.add(powerOff); 482 powerOff.addActionListener(e -> { 483 try { 484 powerMgr.setPower(PowerManager.OFF); 485 } catch (JmriException e1) { 486 log.error("Error when setting power: ", e1); 487 } 488 }); 489 490 this.getJMenuBar().add(powerMenu); 491 492 smallPowerMgmtButton = new SmallPowerManagerButton(); 493 this.getJMenuBar().add(smallPowerMgmtButton); 494 } 495 496 // add help selection 497 addHelpMenu("package.jmri.jmrit.throttle.ThrottleFrame", true); 498 } 499 500 private void editPreferences() { 501 ThrottleFramePropertyEditor editor = new ThrottleFramePropertyEditor(this); 502 editor.setVisible(true); 503 } 504 505 /** 506 * Handle my own destruction. 507 * <ol> 508 * <li> dispose of sub windows. 509 * <li> notify my manager of my demise. 510 * </ol> 511 * 512 */ 513 @Override 514 public void dispose() { 515 URIDrop.remove(throttleToolBar); 516 if ((throttleFrames != null) && (!throttleFrames.isEmpty())) { 517 throttleFrames.values().forEach((throttleFrame) -> { 518 throttleFrame.dispose(); 519 }); 520 throttleFrames.clear(); 521 } 522 throttleFrames = null; 523 currentThrottleFrame = null; 524 for (PropertyChangeListener pcl : pcs.getPropertyChangeListeners()) { 525 pcs.removePropertyChangeListener(pcl); 526 } 527 for (MouseWheelListener mwl : getMouseWheelListeners()) { 528 removeMouseWheelListener(mwl); 529 } 530 getRootPane().getActionMap().clear(); 531 throttlesPanel.removeAll(); 532 removeAll(); 533 super.dispose(); 534 } 535 536 public JCheckBoxMenuItem getViewControlPanel() { 537 return viewControlPanel; 538 } 539 540 public JCheckBoxMenuItem getViewFunctionPanel() { 541 return viewFunctionPanel; 542 } 543 544 public JCheckBoxMenuItem getViewAddressPanel() { 545 return viewAddressPanel; 546 } 547 548 public JCheckBoxMenuItem getViewSpeedPanel() { 549 return viewSpeedPanel; 550 } 551 552 private void updateCurentThrottleFrame() { 553 for (Component comp : throttlesPanel.getComponents()) { 554 if (comp instanceof ThrottleFrame && comp.isVisible()) { 555 currentThrottleFrame = (ThrottleFrame) comp; 556 } 557 } 558 } 559 560 public ThrottleFrame getCurrentThrottleFrame() { 561 return currentThrottleFrame; 562 } 563 564 public void setCurrentThrottleFrame(ThrottleFrame tf) { 565 if (getCurrentThrottleFrame() != null) { 566 log.debug("setCurrentThrottleFrame from {} to {}", getCurrentThrottleFrame().getAddressPanel().getCurrentAddress(), tf.getAddressPanel().getCurrentAddress()); 567 } 568 pcs.firePropertyChange("ThrottleFrame", getCurrentThrottleFrame(), tf); 569 currentThrottleFrame = tf; 570 } 571 572 public void removeThrottleFrame(ThrottleFrame tf) { 573 if (cardCounterNB > 1) // we don't like empty ThrottleWindow 574 { 575 cardCounterNB--; 576 if (getCurrentThrottleFrame() == tf) { 577 log.debug("Closing last created"); 578 } 579 throttlesPanel.remove(tf); 580 throttleFrames.remove(tf.getTitle()); 581 tf.dispose(); 582 throttlesLayout.invalidateLayout(throttlesPanel); 583 } 584 updateGUI(); 585 updateCurentThrottleFrame(); 586 pcs.firePropertyChange("ThrottleFrame", tf, getCurrentThrottleFrame()); 587 } 588 589 public void nextThrottleFrame() { 590 ThrottleFrame otf = getCurrentThrottleFrame(); 591 throttlesLayout.next(throttlesPanel); 592 updateCurentThrottleFrame(); 593 updateGUI(); 594 pcs.firePropertyChange("ThrottleFrame", otf, getCurrentThrottleFrame()); 595 } 596 597 public void previousThrottleFrame() { 598 ThrottleFrame otf = getCurrentThrottleFrame(); 599 throttlesLayout.previous(throttlesPanel); 600 updateCurentThrottleFrame(); 601 updateGUI(); 602 pcs.firePropertyChange("ThrottleFrame", otf, getCurrentThrottleFrame()); 603 } 604 605 public void nextRunningThrottleFrame() { 606 if (!throttleFrames.isEmpty()) { 607 ThrottleFrame cf = this.getCurrentThrottleFrame(); 608 ThrottleFrame nf = null; 609 boolean passed = false; 610 for (ThrottleFrame tf : throttleFrames.values()) { 611 if (tf != cf) { 612 if ((tf.getAddressPanel() != null) && (tf.getAddressPanel().getThrottle() != null) && (tf.getAddressPanel().getThrottle().getSpeedSetting() > 0)) { 613 if (passed) { // if we passed the curent one, and found something then return it 614 nf = tf; 615 break; 616 } else if (nf == null) { 617 nf = tf; 618 } 619 } 620 } else { 621 passed = true; 622 } 623 } 624 if (nf != null) { 625 nf.toFront(); 626 updateCurentThrottleFrame(); 627 pcs.firePropertyChange("ThrottleFrame", cf, nf); 628 } 629 } 630 } 631 632 public void previousRunningThrottleFrame() { 633 if (!throttleFrames.isEmpty()) { 634 ThrottleFrame cf = this.getCurrentThrottleFrame(); 635 ThrottleFrame nf = null; 636 for (ThrottleFrame tf : throttleFrames.values()) { 637 if ((tf != cf) && (tf.getAddressPanel() != null) && (tf.getAddressPanel().getThrottle() != null) && (tf.getAddressPanel().getThrottle().getSpeedSetting() > 0)) { 638 nf = tf; 639 } 640 if ((tf == cf) && (nf != null)) { // return the last one found before the curent one 641 break; 642 } 643 } 644 if (nf != null) { 645 nf.toFront(); 646 updateCurentThrottleFrame(); 647 pcs.firePropertyChange("ThrottleFrame", cf, nf); 648 } 649 } 650 } 651 652 public void removeThrottleFrame() { 653 removeThrottleFrame(getCurrentThrottleFrame()); 654 } 655 656 public void addThrottleFrame(ThrottleFrame tp) { 657 ThrottleFrame otf = getCurrentThrottleFrame(); 658 cardCounterID++; 659 cardCounterNB++; 660 String txt = "Card-" + cardCounterID; 661 tp.setTitle(txt); 662 throttleFrames.put(txt, tp); 663 throttlesPanel.add(tp, txt); 664 throttlesLayout.show(throttlesPanel, txt); 665 if (!isEditMode) { 666 tp.setEditMode(isEditMode); 667 } 668 updateCurentThrottleFrame(); 669 updateGUI(); 670 pcs.firePropertyChange("ThrottleFrame", otf, tp); 671 } 672 673 public ThrottleFrame addThrottleFrame() { 674 setCurrentThrottleFrame(new ThrottleFrame(this, throttleManager)); 675 installInputsListenerOnAllComponents(getCurrentThrottleFrame()); 676 addThrottleFrame(getCurrentThrottleFrame()); 677 return getCurrentThrottleFrame(); 678 } 679 680 public void toFront(String throttleFrameTitle) { 681 ThrottleFrame otf = getCurrentThrottleFrame(); 682 throttlesLayout.show(throttlesPanel, throttleFrameTitle); 683 updateCurentThrottleFrame(); 684 setVisible(true); 685 requestFocus(); 686 toFront(); 687 pcs.firePropertyChange("ThrottleFrame", otf, getCurrentThrottleFrame()); 688 } 689 690 public String getTitleTextType() { 691 return titleTextType; 692 } 693 694 public String getTitleText() { 695 return titleText; 696 } 697 698 public void setTitleText(String titleText) { 699 this.titleText = titleText; 700 } 701 702 public void setTitleTextType(String titleTextType) { 703 this.titleTextType = titleTextType; 704 } 705 706 public Element getXml() { 707 Element me = new Element("ThrottleWindow"); 708 if (connectionConfig != null) { 709 me.setAttribute("systemPrefix", connectionConfig.getAdapter().getSystemPrefix()); 710 } 711 me.setAttribute("title", titleText); 712 me.setAttribute("titleType", titleTextType); 713 me.setAttribute("isEditMode", String.valueOf(isEditMode)); 714 715 java.util.ArrayList<Element> children = new java.util.ArrayList<>(1); 716 children.add(WindowPreferences.getPreferences(this)); 717 if (!throttleFrames.isEmpty()) { 718 ThrottleFrame cf = this.getCurrentThrottleFrame(); 719 for (ThrottleFrame tf : throttleFrames.values()) { 720 if ((InstanceManager.getDefault(ThrottlesPreferences.class).isUsingExThrottle()) && (InstanceManager.getDefault(ThrottlesPreferences.class).isSavingThrottleOnLayoutSave())) { 721 tf.toFront(); 722 tf.saveThrottle(); 723 } 724 Element tfe = tf.getXmlFile(); 725 if (tfe == null) { 726 tfe = tf.getXml(); 727 } 728 children.add(tfe); 729 } 730 if (cf != null) { 731 cf.toFront(); 732 } 733 } 734 735 // Save Jynstruments 736 if (throttleToolBar != null) { 737 Component[] cmps = throttleToolBar.getComponents(); 738 if (cmps != null) { 739 for (Component cmp : cmps) { 740 try { 741 if (cmp instanceof Jynstrument) { 742 Jynstrument jyn = (Jynstrument) cmp; 743 Element elt = new Element("Jynstrument"); 744 elt.setAttribute("JynstrumentFolder", FileUtil.getPortableFilename(jyn.getFolder())); 745 Element je = jyn.getXml(); 746 if (je != null) { 747 java.util.ArrayList<Element> jychildren = new java.util.ArrayList<>(1); 748 jychildren.add(je); 749 elt.setContent(jychildren); 750 } 751 children.add(elt); 752 } 753 754 } catch (Exception ex) { 755 log.debug("Got exception (no panic): ", ex); 756 } 757 } 758 } 759 } 760 me.setContent(children); 761 return me; 762 } 763 764 private void setXml(Element e) { 765 if (e.getAttribute("title") != null) { 766 setTitle(e.getAttribute("title").getValue()); 767 } 768 if (e.getAttribute("title") != null) { 769 setTitleText(e.getAttribute("title").getValue()); 770 } 771 if (e.getAttribute("titleType") != null) { 772 setTitleTextType(e.getAttribute("titleType").getValue()); 773 } 774 if (e.getAttribute("isEditMode") != null) { 775 isEditMode = Boolean.parseBoolean(e.getAttribute("isEditMode").getValue()); 776 } 777 778 Element window = e.getChild("window"); 779 if (window != null) { 780 WindowPreferences.setPreferences(this, window); 781 } 782 783 List<Element> tfes = e.getChildren("ThrottleFrame"); 784 if ((tfes != null) && (tfes.size() > 0)) { 785 for (int i = 0; i < tfes.size(); i++) { 786 ThrottleFrame tf; 787 if (i == 0) { 788 tf = getCurrentThrottleFrame(); 789 } else { 790 tf = addThrottleFrame(); 791 } 792 tf.setXml(tfes.get(i)); 793 tf.setEditMode(isEditMode); 794 } 795 } 796 797 List<Element> jinsts = e.getChildren("Jynstrument"); 798 if ((jinsts != null) && (jinsts.size() > 0)) { 799 jinsts.forEach((jinst) -> { 800 Jynstrument jyn = ynstrument(FileUtil.getExternalFilename(jinst.getAttributeValue("JynstrumentFolder"))); 801 if (jyn != null) { 802 jyn.setXml(jinst); 803 } 804 }); 805 } 806 807 updateGUI(); 808 } 809 810 @Override 811 public synchronized void addPropertyChangeListener(java.beans.PropertyChangeListener l) { 812 pcs.addPropertyChangeListener(l); 813 } 814 815 @Override 816 public synchronized void removePropertyChangeListener(java.beans.PropertyChangeListener l) { 817 pcs.removePropertyChangeListener(l); 818 } 819 820 private void installInputsListenerOnAllComponents(Container c) { 821 c.setFocusTraversalKeysEnabled(false); // make tab and shift tab available 822 if (! ( c instanceof JTextField)) { 823 c.setFocusable(false); 824 } 825 for (Component component : c.getComponents()) { 826 if (component instanceof Container) { 827 installInputsListenerOnAllComponents( (Container) component); 828 } else { 829 if (! ( component instanceof JTextField)) { 830 component.setFocusable(false); 831 } 832 } 833 } 834 } 835 836 public void applyPreferences() { 837 ThrottlesPreferences preferences = InstanceManager.getDefault(ThrottlesPreferences.class); 838 839 ComponentInputMap im = new ComponentInputMap(getRootPane()); 840 for (Object k : this.getRootPane().getActionMap().allKeys()) { 841 KeyStroke[] kss = preferences.getThrottlesKeyboardControls().getKeyStrokes((String)k); 842 if (kss !=null) { 843 for (KeyStroke keystroke : kss) { 844 if (keystroke != null) { 845 im.put(keystroke, k); 846 } 847 } 848 } 849 } 850 getRootPane().setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW,im); 851 852 throttleToolBar.setVisible ( preferences.isUsingExThrottle() && preferences.isUsingToolBar() ); 853 854 if (smallPowerMgmtButton != null) { 855 smallPowerMgmtButton.setVisible( (!preferences.isUsingExThrottle()) || (!preferences.isUsingToolBar()) ); 856 } 857 858 throttleFrames.values().forEach(tf -> { 859 tf.applyPreferences(); 860 }); 861 } 862 863 private final static Logger log = LoggerFactory.getLogger(ThrottleWindow.class); 864}