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}