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 fileMenu.add(new jmri.configurexml.StoreMenu()); 256 257 JMenuItem printItem = new JMenuItem(Bundle.getMessage("PrintTable")); 258 fileMenu.add(printItem); 259 printItem.addActionListener((ActionEvent e) -> { 260 try { 261 // MessageFormat headerFormat = new MessageFormat(getTitle()); // not used below 262 MessageFormat footerFormat = new MessageFormat(getTitle() + " page {0,number}"); 263 if (item.getStandardTableModel()) { 264 item.getDataTable().print(JTable.PrintMode.FIT_WIDTH, null, footerFormat); 265 } else { 266 item.getAAClass().print(JTable.PrintMode.FIT_WIDTH, null, footerFormat); 267 } 268 } catch (java.awt.print.PrinterException e1) { 269 log.warn("Printing error", e1); 270 } catch (NullPointerException ex) { 271 log.error("Trying to print returned a NPE error"); 272 } 273 }); 274 275 JMenu viewMenu = new JMenu(Bundle.getMessage("MenuView")); 276 menuBar.add(viewMenu); 277 for (final TabbedTableItemListArray itemList : tabbedTableItemListArrayArray) { 278 JMenuItem viewItem = new JMenuItem(itemList.getItemString()); 279 viewMenu.add(viewItem); 280 viewItem.addActionListener((ActionEvent e) -> gotoListItem(itemList.getClassAsString())); 281 } 282 283 this.setJMenuBar(menuBar); 284 try { 285 item.getAAClass().setMenuBar(this); 286 this.addHelpMenu(item.getAAClass().helpTarget(), true); 287 } catch (Exception ex) { 288 log.error("Error when trying to set menu bar for {}", item.getClassAsString(), ex); 289 } 290 this.revalidate(); 291 } 292 293 TabbedTableItem<E> lastSelectedItem = null; 294 295 /* This is a bit of a bodge to add the contents to the bottom box and keep 296 * it backwardly compatible with the original views. When the original views 297 * are deprecated then this can be re-written 298 */ 299 //@TODO Sort out the procedure to add to bottom box 300 @Override 301 protected void addToBottomBox(Component comp, String c) { 302 for (TabbedTableItem<E> tti : tabbedTableArray) { 303 if (tti.getClassAsString().equals(c)) { 304 tti.addToBottomBox(comp); 305 return; 306 } 307 } 308 } 309 310 protected static ArrayList<String> getChoices() { 311 ArrayList<String> choices = new ArrayList<>(); 312 for (TabbedTableItemListArray ttila : tabbedTableItemListArrayArray) { 313 choices.add(ttila.getItemString()); 314 } 315 return choices; 316 } 317 318 public void setDividerLocation(int loc) { 319 if (loc == 0) { 320 return; 321 } 322 cardHolder.setDividerLocation(loc); 323 InstanceManager.getDefault(UserPreferencesManager.class) 324 .setProperty(ListedTableFrame.class.getName(), "dividerLocation", loc); 325 } 326 327 public int getDividerLocation() { 328 try { 329 return Integer.parseInt(InstanceManager.getDefault(UserPreferencesManager.class) 330 .getProperty(ListedTableFrame.class.getName(), "dividerLocation").toString()); 331 } catch (NullPointerException | NumberFormatException ex) { 332 // ignore, this means the divider location has never been saved 333 return 0; 334 } 335 } 336 337 /** 338 * Flag Table initialisation started 339 * @param newVal true when started 340 */ 341 private synchronized static void setInit(boolean newVal) { 342 init = newVal; 343 } 344 345 /** 346 * One tabbed item on the ListedTable containing the table(s) for a NamedBean class. 347 * 348 * @param <E> main class of the table(s) 349 */ 350 public static class TabbedTableItem<E extends NamedBean> { 351 352 AbstractTableAction<E> tableAction; 353 String className; 354 String itemText; 355 BeanTableDataModel<E> dataModel; 356 JTable dataTable; 357 JScrollPane dataScroll; 358 Box bottomBox; 359 int bottomBoxIndex; // index to insert extra stuff 360 static final int bottomStrutWidth = 20; 361 362 boolean standardModel; 363 364 final JPanel dataPanel = new JPanel(); 365 366 @SuppressWarnings("unchecked") // type ensured by reflection 367 TabbedTableItem(String aaClass, String choice, boolean stdModel) { 368 className = aaClass; 369 itemText = choice; 370 standardModel = stdModel; 371 372 bottomBox = Box.createHorizontalBox(); 373 bottomBox.add(Box.createHorizontalGlue()); 374 bottomBoxIndex = 0; 375 376 try { 377 Class<?> cl = Class.forName(aaClass); 378 java.lang.reflect.Constructor<?> co = cl.getConstructor(String.class); 379 tableAction = (AbstractTableAction<E>) co.newInstance(choice); // this cast is handled by reflection 380 } catch (ClassNotFoundException | InstantiationException e1) { 381 log.error("Not a valid class : {}", aaClass); 382 return; 383 } catch (NoSuchMethodException e2) { 384 log.error("Not such method : {}", aaClass); 385 return; 386 } catch (ClassCastException e4) { 387 log.error("Not part of the abstractTableActions : {}", aaClass); 388 return; 389 } catch (IllegalAccessException | IllegalArgumentException | SecurityException | InvocationTargetException e) { 390 log.error("Exception accessing {}: {}", aaClass, e.getMessage()); 391 return; 392 } 393 394 // If a panel model is used, it should really add to the bottom box 395 // but it can be done this way if required. 396 // In this case we "hijack" the TabbedTable for different (non-bean) tables to manage OBlocks. 397 dataPanel.setLayout(new BorderLayout()); 398 399 if (stdModel) { 400 createDataModel(); // first table of a grouped set with the primary manager, see OBlockTable 401 } else { 402 addPanelModel(); // for any additional table using a different manager, see Audio, OBlock 403 } 404 } 405 406 void createDataModel() { 407 dataModel = tableAction.getTableDataModel(); 408 TableRowSorter<BeanTableDataModel<E>> sorter = new TableRowSorter<>(dataModel); 409 dataTable = dataModel.makeJTable(dataModel.getMasterClassName() + ":" + getItemString(), dataModel, sorter); 410 dataScroll = new JScrollPane(dataTable); 411 412 // use NamedBean's built-in Comparator interface for sorting the system name column 413 RowSorterUtil.setSortOrder(sorter, BeanTableDataModel.SYSNAMECOL, SortOrder.ASCENDING); 414 415 sorter.setComparator(BeanTableDataModel.USERNAMECOL, new AlphanumComparator()); 416 RowSorterUtil.setSortOrder(sorter, BeanTableDataModel.USERNAMECOL, SortOrder.ASCENDING); 417 418 dataModel.configureTable(dataTable); 419 420 java.awt.Dimension dataTableSize = dataTable.getPreferredSize(); 421 // width is fine, but if table is empty, it's not high 422 // enough to reserve much space. 423 dataTableSize.height = Math.max(dataTableSize.height, 400); 424 dataScroll.getViewport().setPreferredSize(dataTableSize); 425 426 // set preferred scrolling options 427 dataScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 428 dataScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 429 430 dataPanel.add(dataScroll, BorderLayout.CENTER); 431 432 dataPanel.add(bottomBox, BorderLayout.SOUTH); 433 if (tableAction.includeAddButton()) { 434 JButton addButton = new JButton(Bundle.getMessage("ButtonAdd")); 435 addToBottomBox(addButton); 436 addButton.addActionListener((ActionEvent e) -> tableAction.addPressed(e)); 437 } 438 if (dataModel.getPropertyColumnCount() > 0) { 439 final JCheckBox propertyVisible = new JCheckBox(Bundle.getMessage 440 ("ShowSystemSpecificProperties")); 441 propertyVisible.setToolTipText(Bundle.getMessage 442 ("ShowSystemSpecificPropertiesToolTip")); 443 addToBottomBox(propertyVisible); 444 propertyVisible.addActionListener((ActionEvent e) -> dataModel.setPropertyColumnsVisible(dataTable, propertyVisible.isSelected())); 445 dataModel.setPropertyColumnsVisible(dataTable, false); 446 } 447 tableAction.addToFrame(this); 448 dataModel.persistTable(dataTable); 449 } 450 451 void addPanelModel() { 452 try { 453 dataPanel.add(tableAction.getPanel(), BorderLayout.CENTER); 454 dataPanel.add(bottomBox, BorderLayout.SOUTH); 455 } catch (NullPointerException e) { 456 log.error("An error occurred while trying to create the table for {}", itemText, e); 457 } 458 } 459 460 boolean getStandardTableModel() { 461 return standardModel; 462 } 463 464 String getClassAsString() { 465 return className; 466 } 467 468 String getItemString() { 469 return itemText; 470 } 471 472 AbstractTableAction<E> getAAClass() { 473 return tableAction; 474 } 475 476 JPanel getPanel() { 477 return dataPanel; 478 } 479 480 JTable getDataTable() { 481 return dataTable; 482 } 483 484 public void addToBottomBox(Component comp) { 485 bottomBox.add(Box.createHorizontalStrut(bottomStrutWidth), bottomBoxIndex); 486 ++bottomBoxIndex; 487 bottomBox.add(comp, bottomBoxIndex); 488 ++bottomBoxIndex; 489 } 490 491 void dispose() { 492 if (dataModel != null) { 493 dataModel.stopPersistingTable(dataTable); 494 dataModel.dispose(); 495 } 496 if (tableAction != null) { 497 tableAction.dispose(); 498 } 499 dataModel = null; 500 dataTable = null; 501 dataScroll = null; 502 } 503 } 504 505 static class TabbedTableItemListArray { 506 507 String className; 508 String itemText; 509 boolean standardModel; 510 511 TabbedTableItemListArray(String aaClass, String choice, boolean stdModel) { 512 className = aaClass; 513 itemText = choice; 514 standardModel = stdModel; 515 } 516 517 boolean getStandardTableModel() { 518 return standardModel; 519 } 520 521 String getClassAsString() { 522 return className; 523 } 524 525 String getItemString() { 526 return itemText; 527 } 528 529 } 530 531 /** 532 * ActionJList This deals with handling non-default mouse operations on the 533 * List panel and allows for right click popups and double click to open new 534 * windows of the items we are hovering over. 535 */ 536 class ActionJList extends JmriMouseAdapter { 537 538 JPopupMenu popUp; 539 JMenuItem menuItem; 540 541 protected BeanTableFrame<E> frame; 542 543 ActionJList(BeanTableFrame<E> f) { 544 frame = f; 545 popUp = new JPopupMenu(); 546 menuItem = new JMenuItem(Bundle.getMessage("MenuOpenInNewWindow")); 547 popUp.add(menuItem); 548 menuItem.addActionListener((ActionEvent e) -> openNewTableWindow(mouseItem)); 549 currentItemSelected = 0; 550 } 551 552 private int currentItemSelected; 553 554 @Override 555 public void mousePressed(JmriMouseEvent e) { 556 if (e.isPopupTrigger()) { 557 showPopup(e); 558 } 559 } 560 561 @Override 562 public void mouseReleased(JmriMouseEvent e) { 563 if (e.isPopupTrigger()) { 564 showPopup(e); 565 } 566 } 567 568 // records the original pre-click index 569 private int beforeClickIndex; 570 571 //Records the item index that the mouse is currently over 572 private int mouseItem; 573 574 void showPopup(JmriMouseEvent e) { 575 popUp.show(e.getComponent(), e.getX(), e.getY()); 576 mouseItem = list.locationToIndex(e.getPoint()); 577 } 578 579 void setCurrentItem(int current) { 580 currentItemSelected = current; 581 } 582 583 @Override 584 public void mouseClicked(JmriMouseEvent e) { 585 586 mouseItem = list.locationToIndex(e.getPoint()); 587 if (popUp.isVisible()) { 588 return; 589 } 590 if (e.isPopupTrigger()) { 591 showPopup(e); 592 return; 593 } 594 if (e.getClickCount() == 1) { 595 beforeClickIndex = currentItemSelected; 596 selectListItem(mouseItem); 597 } else if (e.getClickCount() == 2) { 598 list.setSelectedIndex(beforeClickIndex); 599 selectListItem(beforeClickIndex); 600 openNewTableWindow(mouseItem); 601 } 602 } 603 604 void openNewTableWindow(int index) { 605 TabbedTableItem<E> item = tabbedTableArray.get(index); 606 class WindowMaker implements Runnable { 607 608 final TabbedTableItem<E> item; 609 610 WindowMaker(TabbedTableItem<E> tItem) { 611 item = tItem; 612 } 613 614 @Override 615 public void run() { 616 ListedTableAction tmp = new ListedTableAction(item.getItemString(), item.getClassAsString(), cardHolder.getDividerLocation()); 617 tmp.actionPerformed(); 618 } 619 } 620 WindowMaker t = new WindowMaker(item); 621 javax.swing.SwingUtilities.invokeLater(t); 622 } 623 624 void selectListItem(int index) { 625 currentItemSelected = index; 626 TabbedTableItem<E> item = tabbedTableArray.get(index); 627 CardLayout cl = (CardLayout) (detailPanel.getLayout()); 628 cl.show(detailPanel, item.getClassAsString()); 629 frame.setTitle(item.getItemString()); 630 frame.generateWindowRef(); 631 try { 632 item.getAAClass().setFrame(frame); 633 buildMenus(item); 634 } catch (Exception ex) { 635 log.error("Could not build table {}", item, ex); 636 } 637 list.ensureIndexIsVisible(index); 638 list.setSelectedIndex(index); 639 } 640 } 641 642 private final static Logger log = LoggerFactory.getLogger(ListedTableFrame.class); 643 644}