001package jmri.jmrit.beantable; 002 003import java.awt.Component; 004import javax.swing.Box; 005import javax.swing.BoxLayout; 006import javax.swing.JScrollPane; 007import javax.swing.JTable; 008import javax.swing.SortOrder; 009import javax.swing.table.TableRowSorter; 010import jmri.NamedBean; 011import jmri.swing.RowSorterUtil; 012 013/** 014 * Provide a JPanel to display a table of NamedBeans. 015 * <p> 016 * This frame includes the table itself at the top, plus a "bottom area" for 017 * things like an Add... button and checkboxes that control display options. 018 * <p> 019 * The usual menus are also provided here. 020 * <p> 021 * Specific uses are customized via the BeanTableDataModel implementation they 022 * provide, and by providing a {@link #extras} implementation that can in turn 023 * invoke {@link #addToBottomBox} as needed. 024 * 025 * @author Bob Jacobsen Copyright (C) 2003 026 */ 027public class BeanTablePane<E extends NamedBean> extends jmri.util.swing.JmriPanel { 028 029 BeanTableDataModel<E> dataModel; 030 JTable dataTable; 031 JScrollPane dataScroll; 032 Box bottomBox; // panel at bottom for extra buttons etc 033 int bottomBoxIndex; // index to insert extra stuff 034 static final int bottomStrutWidth = 20; 035 036 public void init(BeanTableDataModel<E> model) { 037 038 dataModel = model; 039 040 TableRowSorter<BeanTableDataModel<E>> sorter = new TableRowSorter<>(dataModel); 041 dataTable = dataModel.makeJTable(dataModel.getMasterClassName(), dataModel, sorter); 042 dataScroll = new JScrollPane(dataTable); 043 044 // use NamedBean's built-in Comparator interface for sorting the system name column 045 RowSorterUtil.setSortOrder(sorter, BeanTableDataModel.SYSNAMECOL, SortOrder.ASCENDING); 046 this.dataTable.setRowSorter(sorter); 047 048 // configure items for GUI 049 dataModel.configureTable(dataTable); 050 051 // general GUI config 052 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 053 054 // install items in GUI 055 add(dataScroll); 056 bottomBox = Box.createHorizontalBox(); 057 bottomBox.add(Box.createHorizontalGlue()); // stays at end of box 058 bottomBoxIndex = 0; 059 060 add(bottomBox); 061 062 // add extras, if desired by subclass 063 extras(); 064 065 // set Viewport preferred size from size of table 066 java.awt.Dimension dataTableSize = dataTable.getPreferredSize(); 067 // width is right, but if table is empty, it's not high 068 // enough to reserve much space. 069 dataTableSize.height = Math.max(dataTableSize.height, 400); 070 dataScroll.getViewport().setPreferredSize(dataTableSize); 071 072 // set preferred scrolling options 073 dataScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 074 dataScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 075 } 076 077 /** 078 * Hook to allow sub-types to install more items in GUI. 079 */ 080 void extras() { 081 } 082 083 protected Box getBottomBox() { 084 return bottomBox; 085 } 086 087 /** 088 * Add a component to the bottom box. 089 * <p> 090 * Takes care of organising glue, struts etc. 091 * 092 * @param comp {@link Component} to add 093 */ 094 protected void addToBottomBox(Component comp) { 095 bottomBox.add(Box.createHorizontalStrut(bottomStrutWidth), bottomBoxIndex); 096 ++bottomBoxIndex; 097 bottomBox.add(comp, bottomBoxIndex); 098 ++bottomBoxIndex; 099 } 100 101 @Override 102 public void dispose() { 103 if (dataModel != null) { 104 dataModel.dispose(); 105 } 106 dataModel = null; 107 dataTable = null; 108 dataScroll = null; 109 } 110}