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