001package jmri.jmrit.beantable; 002 003import java.awt.*; 004import java.awt.event.ActionEvent; 005import java.beans.PropertyChangeEvent; 006import java.lang.reflect.InvocationTargetException; 007import java.text.MessageFormat; 008import java.util.ArrayList; 009import java.util.Vector; 010 011import javax.swing.Box; 012import javax.swing.BoxLayout; 013import javax.swing.JButton; 014import javax.swing.JCheckBox; 015import javax.swing.JLabel; 016import javax.swing.JList; 017import javax.swing.JMenu; 018import javax.swing.JMenuBar; 019import javax.swing.JMenuItem; 020import javax.swing.JPanel; 021import javax.swing.JPopupMenu; 022import javax.swing.JScrollPane; 023import javax.swing.JSplitPane; 024import javax.swing.JTable; 025import javax.swing.ListSelectionModel; 026import javax.swing.SortOrder; 027import javax.swing.table.TableRowSorter; 028 029import jmri.*; 030import jmri.swing.RowSorterUtil; 031import jmri.util.AlphanumComparator; 032import jmri.util.gui.GuiLafPreferencesManager; 033import jmri.util.swing.JmriMouseAdapter; 034import jmri.util.swing.JmriMouseEvent; 035import jmri.util.swing.JmriMouseListener; 036 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040/** 041 * Provide access to the various tables in the tabbed Tables interface via a listed pane (normally to the left). 042 * <p> 043 * Based upon the {@link apps.gui3.tabbedpreferences.TabbedPreferences} by Bob Jacobsen 044 * 045 * @author Kevin Dickerson Copyright 2010 046 * @author Bob Jacobsen Copyright 2010 047 */ 048public class ListedTableFrame<E extends NamedBean> extends BeanTableFrame<E> { 049 050 ActionJList actionList; 051 052 public boolean isMultipleInstances() { 053 return true; 054 } 055 056 static ArrayList<TabbedTableItemListArray> tabbedTableItemListArrayArray = new ArrayList<>(); 057 ArrayList<TabbedTableItem<E>> tabbedTableArray = new ArrayList<>(); 058 059 final UserPreferencesManager pref = InstanceManager.getDefault(UserPreferencesManager.class); 060 JSplitPane cardHolder; 061 JList<String> list; 062 JScrollPane listScroller; 063 JPanel listPanel; 064 JPanel detailPanel; 065 static boolean init = false; 066 067 /** 068 * Create a new Listed Table Frame. 069 * Call initTables() before initComponents() 070 */ 071 public ListedTableFrame() { 072 this(Bundle.getMessage("TitleListedTable")); 073 } 074 075 /** 076 * Create a new Listed Table Frame. 077 * Call initTables() before initComponents() 078 * @param s Initial Frame Title 079 */ 080 public ListedTableFrame(String s) { 081 super(s); 082 if (InstanceManager.getNullableDefault(jmri.jmrit.beantable.ListedTableFrame.class) == null) { 083 // We add this to the InstanceManager so that other components can add to the table 084 InstanceManager.store(ListedTableFrame.this, jmri.jmrit.beantable.ListedTableFrame.class); 085 } 086 } 087 088 /** 089 * Initialise all tables to be added to Frame. 090 * Should be called after ListedTableFrame construction and before initComponents() 091 */ 092 public void initTables() { 093 if (!init) { 094 // Add the default tables to the static list array, 095 // this should only be done once on first loading 096 addTable("jmri.jmrit.beantable.TurnoutTableTabAction", Bundle.getMessage("MenuItemTurnoutTable"), false); 097 addTable("jmri.jmrit.beantable.SensorTableTabAction", Bundle.getMessage("MenuItemSensorTable"), false); 098 addTable("jmri.jmrit.beantable.LightTableTabAction", Bundle.getMessage("MenuItemLightTable"), false); 099 addTable("jmri.jmrit.beantable.SignalHeadTableAction", Bundle.getMessage("MenuItemSignalTable"), true); 100 addTable("jmri.jmrit.beantable.SignalMastTableAction", Bundle.getMessage("MenuItemSignalMastTable"), true); 101 addTable("jmri.jmrit.beantable.SignalGroupTableAction", Bundle.getMessage("MenuItemSignalGroupTable"), true); 102 addTable("jmri.jmrit.beantable.SignalMastLogicTableAction", Bundle.getMessage("MenuItemSignalMastLogicTable"), true); 103 addTable("jmri.jmrit.beantable.ReporterTableTabAction", Bundle.getMessage("MenuItemReporterTable"), false); 104 addTable("jmri.jmrit.beantable.MemoryTableAction", Bundle.getMessage("MenuItemMemoryTable"), true); 105 addTable("jmri.jmrit.beantable.RouteTableAction", Bundle.getMessage("MenuItemRouteTable"), true); 106 addTable("jmri.jmrit.beantable.LRouteTableAction", Bundle.getMessage("MenuItemLRouteTable"), true); 107 addTable("jmri.jmrit.beantable.LogixTableAction", Bundle.getMessage("MenuItemLogixTable"), true); 108 addTable("jmri.jmrit.beantable.LogixNGTableAction", Bundle.getMessage("MenuItemLogixNGTable"), true); 109 addTable("jmri.jmrit.beantable.LogixNGModuleTableAction", Bundle.getMessage("MenuItemLogixNGModuleTable"), true); 110 addTable("jmri.jmrit.beantable.LogixNGTableTableAction", Bundle.getMessage("MenuItemLogixNGTableTable"), true); 111 addTable("jmri.jmrit.beantable.LogixNGGlobalVariableTableAction", Bundle.getMessage("MenuItemLogixNGGlobalVariableTableAction"), true); 112 addTable("jmri.jmrit.beantable.BlockTableAction", Bundle.getMessage("MenuItemBlockTable"), true); 113 if (InstanceManager.getDefault(GuiLafPreferencesManager.class).isOblockEditTabbed()) { // select _tabbed in prefs 114 addTable("jmri.jmrit.beantable.OBlockTableAction", Bundle.getMessage("MenuItemOBlockTable"), false); 115 } // requires restart after changing the interface setting (on Display tab) 116 addTable("jmri.jmrit.beantable.SectionTableAction", Bundle.getMessage("MenuItemSectionTable"), true); 117 addTable("jmri.jmrit.beantable.TransitTableAction", Bundle.getMessage("MenuItemTransitTable"), true); 118 addTable("jmri.jmrit.beantable.AudioTableAction", Bundle.getMessage("MenuItemAudioTable"), false); 119 addTable("jmri.jmrit.beantable.IdTagTableTabAction", Bundle.getMessage("MenuItemIdTagTable"), false); 120 addTable("jmri.jmrit.beantable.RailComTableAction", Bundle.getMessage("MenuItemRailComTable"), true); 121 ListedTableFrame.setInit(true); 122 } 123 } 124 125 /** 126 * Initialise Frame Components. 127 * Should be called after initTables() 128 * {@inheritDoc} 129 */ 130 @Override 131 public void initComponents() { 132 if (tabbedTableItemListArrayArray.isEmpty()) { 133 log.error("No tables loaded: {}",this); 134 return; 135 } 136 actionList = new ActionJList(this); 137 138 detailPanel = new JPanel(); 139 detailPanel.setLayout(new CardLayout()); 140 tabbedTableArray = new ArrayList<>(tabbedTableItemListArrayArray.size()); 141 ArrayList<TabbedTableItemListArray> removeItem = new ArrayList<>(5); 142 for (TabbedTableItemListArray item : tabbedTableItemListArrayArray) { 143 // Here we add all the tables into the panel 144 try { 145 TabbedTableItem<E> itemModel = new TabbedTableItem<>(item.getClassAsString(), item.getItemString(), item.getStandardTableModel()); 146 detailPanel.add(itemModel.getPanel(), itemModel.getClassAsString()); 147 tabbedTableArray.add(itemModel); 148 itemModel.getAAClass().addToFrame(this); 149 } catch (Exception ex) { 150 detailPanel.add(errorPanel(item.getItemString()), item.getClassAsString()); 151 log.error("Error when adding {} to display", item.getClassAsString(), ex); 152 removeItem.add(item); 153 } 154 } 155 156 for (TabbedTableItemListArray dead : removeItem) { 157 tabbedTableItemListArrayArray.remove(dead); 158 } 159 160 list = new JList<>(new Vector<>(getChoices())); 161 listScroller = new JScrollPane(list); 162 163 list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 164 list.setLayoutOrientation(JList.VERTICAL); 165 list.addMouseListener(JmriMouseListener.adapt(actionList)); 166 167 listPanel = new JPanel(); 168 listPanel.setLayout(new BorderLayout(5, 0)); 169 listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.Y_AXIS)); 170 listPanel.add(listScroller); 171 listPanel.setMinimumSize(new Dimension(140, 400)); // guarantees minimum width of left divider list 172 173 buildMenus(tabbedTableArray.get(0)); 174 setTitle(tabbedTableArray.get(0).getItemString()); 175 176 cardHolder = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, 177 listPanel, detailPanel); 178 179 cardHolder.setDividerSize(8); 180 if (this.getDividerLocation() != 0) { 181 cardHolder.setDividerLocation(this.getDividerLocation()); 182 } else { // if no specific size has been given we set it to the lists preferred width 183 cardHolder.setDividerLocation(listScroller.getPreferredSize().width); 184 } 185 cardHolder.addPropertyChangeListener((PropertyChangeEvent e) -> { 186 if (e.getPropertyName().equals("dividerLocation")) { 187 InstanceManager.getDefault(UserPreferencesManager.class) 188 .setProperty(ListedTableFrame.class.getName(), "dividerLocation", e.getNewValue()); 189 } 190 }); 191 192 cardHolder.setOneTouchExpandable(true); 193 getContentPane().add(cardHolder); 194 pack(); 195 actionList.selectListItem(0); 196 } 197 198 JPanel errorPanel(String text) { 199 JPanel error = new JPanel(); 200 error.add(new JLabel(Bundle.getMessage("ErrorAddingTable", text))); 201 return error; 202 } 203 204 /* Method allows for the table to go to a specific list item */ 205 public void gotoListItem(String selection) { 206 for (int x = 0; x < tabbedTableArray.size(); x++) { 207 try { 208 if (tabbedTableArray.get(x).getClassAsString().equals(selection)) { 209 actionList.selectListItem(x); 210 return; 211 } 212 } catch (Exception ex) { 213 log.error("An error occurred in the goto list for {}, {}", selection,ex.getMessage()); 214 } 215 } 216 } 217 218 public void addTable(String aaClass, String choice, boolean stdModel) { 219 TabbedTableItemListArray itemToAdd = null; 220 for (TabbedTableItemListArray ttila : tabbedTableItemListArrayArray) { 221 if (ttila.getClassAsString().equals(aaClass)) { 222 log.info("Class {} is already added", aaClass); 223 itemToAdd = ttila; 224 break; 225 } 226 } 227 if (itemToAdd == null) { 228 itemToAdd = new TabbedTableItemListArray(aaClass, choice, stdModel); 229 tabbedTableItemListArrayArray.add(itemToAdd); 230 } 231 } 232 233 @Override 234 public void dispose() { 235 pref.setSaveAllowed(false); 236 for (TabbedTableItem<E> tti : tabbedTableArray) { 237 tti.dispose(); 238 } 239 if (list != null && list.getListSelectionListeners().length > 0) { 240 list.removeListSelectionListener(list.getListSelectionListeners()[0]); 241 } 242 super.dispose(); 243 pref.setSaveAllowed(true); 244 } 245 246 void buildMenus(final TabbedTableItem<E> item) { 247 JMenuBar menuBar = new JMenuBar(); 248 JMenu fileMenu = new JMenu(Bundle.getMessage("MenuFile")); 249 menuBar.add(fileMenu); 250 251 JMenuItem newItem = new JMenuItem(Bundle.getMessage("MenuNewWindow")); 252 fileMenu.add(newItem); 253 newItem.addActionListener((ActionEvent e) -> actionList.openNewTableWindow(list.getSelectedIndex())); 254 255 // do not display Store All Table Content in IdTag Table 256 if (!( item.getAAClass() instanceof IdTagTableAction || 257 item.getAAClass() instanceof IdTagTableTabAction ) ) { 258 fileMenu.add(new jmri.configurexml.StoreMenu()); 259 } 260 261 JMenuItem printItem = new JMenuItem(Bundle.getMessage("PrintTable")); 262 fileMenu.add(printItem); 263 printItem.addActionListener((ActionEvent e) -> { 264 try { 265 // MessageFormat headerFormat = new MessageFormat(getTitle()); // not used below 266 MessageFormat footerFormat = new MessageFormat(getTitle() + " page {0,number}"); 267 if (item.getStandardTableModel()) { 268 item.getDataTable().print(JTable.PrintMode.FIT_WIDTH, null, footerFormat); 269 } else { 270 item.getAAClass().print(JTable.PrintMode.FIT_WIDTH, null, footerFormat); 271 } 272 } catch (java.awt.print.PrinterException e1) { 273 log.warn("Printing error", e1); 274 } catch (NullPointerException ex) { 275 log.error("Trying to print returned a NPE error"); 276 } 277 }); 278 279 JMenu viewMenu = new JMenu(Bundle.getMessage("MenuView")); 280 menuBar.add(viewMenu); 281 for (final TabbedTableItemListArray itemList : tabbedTableItemListArrayArray) { 282 JMenuItem viewItem = new JMenuItem(itemList.getItemString()); 283 viewMenu.add(viewItem); 284 viewItem.addActionListener((ActionEvent e) -> gotoListItem(itemList.getClassAsString())); 285 } 286 287 this.setJMenuBar(menuBar); 288 try { 289 item.getAAClass().setMenuBar(this); 290 this.addHelpMenu(item.getAAClass().helpTarget(), true); 291 } catch (Exception ex) { 292 log.error("Error when trying to set menu bar for {}", item.getClassAsString(), ex); 293 } 294 this.revalidate(); 295 } 296 297 TabbedTableItem<E> lastSelectedItem = null; 298 299 /* This is a bit of a bodge to add the contents to the bottom box and keep 300 * it backwardly compatible with the original views. When the original views 301 * are deprecated then this can be re-written 302 */ 303 //@TODO Sort out the procedure to add to bottom box 304 @Override 305 protected void addToBottomBox(Component comp, String c) { 306 for (TabbedTableItem<E> tti : tabbedTableArray) { 307 if (tti.getClassAsString().equals(c)) { 308 tti.addToBottomBox(comp); 309 return; 310 } 311 } 312 } 313 314 protected static ArrayList<String> getChoices() { 315 ArrayList<String> choices = new ArrayList<>(); 316 for (TabbedTableItemListArray ttila : tabbedTableItemListArrayArray) { 317 choices.add(ttila.getItemString()); 318 } 319 return choices; 320 } 321 322 public void setDividerLocation(int loc) { 323 if (loc == 0) { 324 return; 325 } 326 cardHolder.setDividerLocation(loc); 327 InstanceManager.getDefault(UserPreferencesManager.class) 328 .setProperty(ListedTableFrame.class.getName(), "dividerLocation", loc); 329 } 330 331 public int getDividerLocation() { 332 try { 333 return Integer.parseInt(InstanceManager.getDefault(UserPreferencesManager.class) 334 .getProperty(ListedTableFrame.class.getName(), "dividerLocation").toString()); 335 } catch (NullPointerException | NumberFormatException ex) { 336 // ignore, this means the divider location has never been saved 337 return 0; 338 } 339 } 340 341 /** 342 * Flag Table initialisation started 343 * @param newVal true when started 344 */ 345 private synchronized static void setInit(boolean newVal) { 346 init = newVal; 347 } 348 349 /** 350 * One tabbed item on the ListedTable containing the table(s) for a NamedBean class. 351 * 352 * @param <E> main class of the table(s) 353 */ 354 public static class TabbedTableItem<E extends NamedBean> { 355 356 AbstractTableAction<E> tableAction; 357 String className; 358 String itemText; 359 BeanTableDataModel<E> dataModel; 360 JTable dataTable; 361 JScrollPane dataScroll; 362 Box bottomBox; 363 int bottomBoxIndex; // index to insert extra stuff 364 365 boolean standardModel; 366 367 final JPanel dataPanel = new JPanel(); 368 369 @SuppressWarnings("unchecked") // type ensured by reflection 370 TabbedTableItem(String aaClass, String choice, boolean stdModel) { 371 className = aaClass; 372 itemText = choice; 373 standardModel = stdModel; 374 375 bottomBox = Box.createHorizontalBox(); 376 bottomBox.add(Box.createHorizontalGlue()); 377 bottomBoxIndex = 0; 378 379 try { 380 Class<?> cl = Class.forName(aaClass); 381 java.lang.reflect.Constructor<?> co = cl.getConstructor(String.class); 382 tableAction = (AbstractTableAction<E>) co.newInstance(choice); // this cast is handled by reflection 383 } catch (ClassNotFoundException | InstantiationException e1) { 384 log.error("Not a valid class : {}", aaClass); 385 return; 386 } catch (NoSuchMethodException e2) { 387 log.error("Not such method : {}", aaClass); 388 return; 389 } catch (ClassCastException e4) { 390 log.error("Not part of the abstractTableActions : {}", aaClass); 391 return; 392 } catch (IllegalAccessException | IllegalArgumentException | SecurityException | InvocationTargetException e) { 393 log.error("Exception accessing {}: {}", aaClass, e.getMessage()); 394 return; 395 } 396 397 // If a panel model is used, it should really add to the bottom box 398 // but it can be done this way if required. 399 // In this case we "hijack" the TabbedTable for different (non-bean) tables to manage OBlocks. 400 dataPanel.setLayout(new BorderLayout()); 401 402 if (stdModel) { 403 createDataModel(); // first table of a grouped set with the primary manager, see OBlockTable 404 } else { 405 addPanelModel(); // for any additional table using a different manager, see Audio, OBlock 406 } 407 } 408 409 void createDataModel() { 410 dataModel = tableAction.getTableDataModel(); 411 TableRowSorter<BeanTableDataModel<E>> sorter = new TableRowSorter<>(dataModel); 412 dataTable = dataModel.makeJTable(dataModel.getMasterClassName() + ":" + getItemString(), dataModel, sorter); 413 dataScroll = new JScrollPane(dataTable); 414 415 // use NamedBean's built-in Comparator interface for sorting the system name column 416 RowSorterUtil.setSortOrder(sorter, BeanTableDataModel.SYSNAMECOL, SortOrder.ASCENDING); 417 418 sorter.setComparator(BeanTableDataModel.USERNAMECOL, new AlphanumComparator()); 419 RowSorterUtil.setSortOrder(sorter, BeanTableDataModel.USERNAMECOL, SortOrder.ASCENDING); 420 421 dataModel.configureTable(dataTable); 422 423 java.awt.Dimension dataTableSize = dataTable.getPreferredSize(); 424 // width is fine, but if table is empty, it's not high 425 // enough to reserve much space. 426 dataTableSize.height = Math.max(dataTableSize.height, 400); 427 dataScroll.getViewport().setPreferredSize(dataTableSize); 428 429 // set preferred scrolling options 430 dataScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 431 dataScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 432 433 dataPanel.add(dataScroll, BorderLayout.CENTER); 434 435 dataPanel.add(bottomBox, BorderLayout.SOUTH); 436 if (tableAction.includeAddButton()) { 437 JButton addButton = new JButton(Bundle.getMessage("ButtonAdd")); 438 addToBottomBox(addButton); 439 addButton.addActionListener((ActionEvent e) -> tableAction.addPressed(e)); 440 } 441 if (dataModel.getPropertyColumnCount() > 0) { 442 final JCheckBox propertyVisible = new JCheckBox(Bundle.getMessage 443 ("ShowSystemSpecificProperties")); 444 propertyVisible.setToolTipText(Bundle.getMessage 445 ("ShowSystemSpecificPropertiesToolTip")); 446 addToBottomBox(propertyVisible); 447 propertyVisible.addActionListener((ActionEvent e) -> dataModel.setPropertyColumnsVisible(dataTable, propertyVisible.isSelected())); 448 dataModel.setPropertyColumnsVisible(dataTable, false); 449 } 450 tableAction.addToFrame(this); 451 dataModel.persistTable(dataTable); 452 } 453 454 void addPanelModel() { 455 try { 456 dataPanel.add(tableAction.getPanel(), BorderLayout.CENTER); 457 dataPanel.add(bottomBox, BorderLayout.SOUTH); 458 } catch (NullPointerException e) { 459 log.error("An error occurred while trying to create the table for {}", itemText, e); 460 } 461 } 462 463 boolean getStandardTableModel() { 464 return standardModel; 465 } 466 467 String getClassAsString() { 468 return className; 469 } 470 471 String getItemString() { 472 return itemText; 473 } 474 475 AbstractTableAction<E> getAAClass() { 476 return tableAction; 477 } 478 479 JPanel getPanel() { 480 return dataPanel; 481 } 482 483 JTable getDataTable() { 484 return dataTable; 485 } 486 487 public void addToBottomBox(Component comp) { 488 bottomBox.add(Box.createHorizontalStrut(bottomStrutWidth), bottomBoxIndex); 489 ++bottomBoxIndex; 490 bottomBox.add(comp, bottomBoxIndex); 491 ++bottomBoxIndex; 492 } 493 494 void dispose() { 495 if (dataModel != null) { 496 dataModel.stopPersistingTable(dataTable); 497 dataModel.dispose(); 498 } 499 if (tableAction != null) { 500 tableAction.dispose(); 501 } 502 dataModel = null; 503 dataTable = null; 504 dataScroll = null; 505 } 506 } 507 508 static class TabbedTableItemListArray { 509 510 String className; 511 String itemText; 512 boolean standardModel; 513 514 TabbedTableItemListArray(String aaClass, String choice, boolean stdModel) { 515 className = aaClass; 516 itemText = choice; 517 standardModel = stdModel; 518 } 519 520 boolean getStandardTableModel() { 521 return standardModel; 522 } 523 524 String getClassAsString() { 525 return className; 526 } 527 528 String getItemString() { 529 return itemText; 530 } 531 532 } 533 534 /** 535 * ActionJList This deals with handling non-default mouse operations on the 536 * List panel and allows for right click popups and double click to open new 537 * windows of the items we are hovering over. 538 */ 539 class ActionJList extends JmriMouseAdapter { 540 541 JPopupMenu popUp; 542 JMenuItem menuItem; 543 544 protected BeanTableFrame<E> frame; 545 546 ActionJList(BeanTableFrame<E> f) { 547 frame = f; 548 popUp = new JPopupMenu(); 549 menuItem = new JMenuItem(Bundle.getMessage("MenuOpenInNewWindow")); 550 popUp.add(menuItem); 551 menuItem.addActionListener((ActionEvent e) -> openNewTableWindow(mouseItem)); 552 currentItemSelected = 0; 553 } 554 555 private int currentItemSelected; 556 557 @Override 558 public void mousePressed(JmriMouseEvent e) { 559 if (e.isPopupTrigger()) { 560 showPopup(e); 561 } 562 } 563 564 @Override 565 public void mouseReleased(JmriMouseEvent e) { 566 if (e.isPopupTrigger()) { 567 showPopup(e); 568 } 569 } 570 571 // records the original pre-click index 572 private int beforeClickIndex; 573 574 //Records the item index that the mouse is currently over 575 private int mouseItem; 576 577 void showPopup(JmriMouseEvent e) { 578 popUp.show(e.getComponent(), e.getX(), e.getY()); 579 mouseItem = list.locationToIndex(e.getPoint()); 580 } 581 582 void setCurrentItem(int current) { 583 currentItemSelected = current; 584 } 585 586 @Override 587 public void mouseClicked(JmriMouseEvent e) { 588 589 mouseItem = list.locationToIndex(e.getPoint()); 590 if (popUp.isVisible()) { 591 return; 592 } 593 if (e.isPopupTrigger()) { 594 showPopup(e); 595 return; 596 } 597 if (e.getClickCount() == 1) { 598 beforeClickIndex = currentItemSelected; 599 selectListItem(mouseItem); 600 } else if (e.getClickCount() == 2) { 601 list.setSelectedIndex(beforeClickIndex); 602 selectListItem(beforeClickIndex); 603 openNewTableWindow(mouseItem); 604 } 605 } 606 607 void openNewTableWindow(int index) { 608 TabbedTableItem<E> item = tabbedTableArray.get(index); 609 class WindowMaker implements Runnable { 610 611 final TabbedTableItem<E> item; 612 613 WindowMaker(TabbedTableItem<E> tItem) { 614 item = tItem; 615 } 616 617 @Override 618 public void run() { 619 ListedTableAction tmp = new ListedTableAction(item.getItemString(), item.getClassAsString(), cardHolder.getDividerLocation()); 620 tmp.actionPerformed(); 621 } 622 } 623 WindowMaker t = new WindowMaker(item); 624 javax.swing.SwingUtilities.invokeLater(t); 625 } 626 627 void selectListItem(int index) { 628 currentItemSelected = index; 629 TabbedTableItem<E> item = tabbedTableArray.get(index); 630 CardLayout cl = (CardLayout) (detailPanel.getLayout()); 631 cl.show(detailPanel, item.getClassAsString()); 632 frame.setTitle(item.getItemString()); 633 frame.generateWindowRef(); 634 try { 635 item.getAAClass().setFrame(frame); 636 buildMenus(item); 637 } catch (Exception ex) { 638 log.error("Could not build table {}", item, ex); 639 } 640 list.ensureIndexIsVisible(index); 641 list.setSelectedIndex(index); 642 } 643 } 644 645 private final static Logger log = LoggerFactory.getLogger(ListedTableFrame.class); 646 647}