001package jmri.jmrit.roster.swing.rostergroup;
002
003import java.awt.Component;
004import javax.swing.Box;
005import javax.swing.BoxLayout;
006import javax.swing.JMenuBar;
007import javax.swing.JScrollPane;
008import javax.swing.JTable;
009import javax.swing.table.TableRowSorter;
010
011/**
012 * Provide a JFrame to display the Roster Data Based upon BeanTableFrame.
013 * <p>
014 * This frame includes the table itself at the top, plus a "bottom area" for
015 * things like an Add... button and checkboxes that control display options.
016 * <p>
017 * The usual menus are also provided here.
018 * <p>
019 * Specific uses are customized via the RosterGroupTableDataModel implementation
020 * they provide, and by providing a {@link #extras} implementation that can in
021 * turn invoke {@link #addToBottomBox} as needed.
022 *
023 * @author Bob Jacobsen Copyright (C) 2003
024 * @author Kevin Dickerson Copyright (C) 2009
025 */
026public class RosterGroupTableFrame extends jmri.util.JmriJFrame {
027
028    RosterGroupTableModel dataModel;
029    JTable dataTable;
030    JScrollPane dataScroll;
031    Box bottomBox;  // panel at bottom for extra buttons etc
032    int bottomBoxIndex; // index to insert extra stuff
033    static final int bottomStrutWidth = 20;
034    Box topBox;  // panel at bottom for extra buttons etc
035    int topBoxIndex; // index to insert extra stuff
036    static final int topStrutWidth = 20;
037
038    public RosterGroupTableFrame(RosterGroupTableModel model, String helpTarget) {
039
040        super();
041        dataModel = model;
042
043        dataTable = new JTable(dataModel);
044        
045        dataTable.setAutoCreateRowSorter(true);  // user can pick sort column
046        
047        TableRowSorter<RosterGroupTableModel> sorter = new TableRowSorter<>(dataModel);
048        dataTable.setRowSorter(sorter);
049
050        sorter.setComparator(RosterGroupTableModel.IDCOL, new jmri.util.AlphanumComparator());
051        sorter.toggleSortOrder(RosterGroupTableModel.IDCOL);
052        
053        dataScroll = new JScrollPane(dataTable);
054
055        // configure items for GUI
056        dataModel.configureTable(dataTable);
057
058        // general GUI config
059        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
060
061        // add save menu item
062        JMenuBar menuBar = new JMenuBar();
063
064        setJMenuBar(menuBar);
065
066        addHelpMenu(helpTarget, true);
067
068        // install items in GUI
069        topBox = Box.createHorizontalBox();
070        topBox.add(Box.createHorizontalGlue()); // stays at beginning of box
071        topBoxIndex = 0;
072        getContentPane().add(topBox);
073        getContentPane().add(dataScroll);
074
075        bottomBox = Box.createHorizontalBox();
076        bottomBox.add(Box.createHorizontalGlue()); // stays at end of box
077        bottomBoxIndex = 0;
078
079        getContentPane().add(bottomBox);
080
081        // add extras, if desired by subclass
082        extras();
083
084        // set Viewport preferred size from size of table
085        java.awt.Dimension dataTableSize = dataTable.getPreferredSize();
086        // width is right, but if table is empty, it's not high
087        // enough to reserve much space.
088        dataTableSize.height = Math.max(dataTableSize.height, 400);
089        dataScroll.getViewport().setPreferredSize(dataTableSize);
090
091        // set preferred scrolling options
092        dataScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
093        dataScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
094    }
095
096    /**
097     * Hook to allow sub-types to install more items in GUI.
098     */
099    void extras() {
100    }
101
102    protected Box getBottomBox() {
103        return bottomBox;
104    }
105
106    /**
107     * Add a component to the bottom box. Takes care of organising glue, struts
108     * etc
109     *
110     * @param comp Component to add to the bottom box
111     */
112    protected void addToBottomBox(Component comp) {
113        bottomBox.add(Box.createHorizontalStrut(bottomStrutWidth), bottomBoxIndex);
114        ++bottomBoxIndex;
115        bottomBox.add(comp, bottomBoxIndex);
116        ++bottomBoxIndex;
117    }
118
119    protected Box getTopBox() {
120        return topBox;
121    }
122
123    /**
124     * Add a component to the top box. Takes care of organising glue, struts
125     * etc.
126     * @param comp Component to add to the top box
127     */
128    protected void addToTopBox(Component comp) {
129        topBox.add(Box.createHorizontalStrut(topStrutWidth), topBoxIndex);
130        ++topBoxIndex;
131        topBox.add(comp, topBoxIndex);
132        ++topBoxIndex;
133    }
134
135    @Override
136    public void dispose() {
137        if (dataModel != null) {
138            dataModel.dispose();
139        }
140        dataModel = null;
141        dataTable = null;
142        dataScroll = null;
143        super.dispose();
144    }
145
146}