001package jmri.jmrit.beantable;
002
003import java.awt.Component;
004
005import javax.swing.*;
006import javax.swing.table.TableRowSorter;
007
008import jmri.NamedBean;
009import jmri.swing.RowSorterUtil;
010
011/**
012 * Provide a JPanel to display a table of NamedBeans.
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 BeanTableDataModel implementation they
020 * provide, and by providing a {@link #extras} implementation that can in turn
021 * invoke {@link #addToBottomBox} as needed.
022 *
023 * @author Bob Jacobsen Copyright (C) 2003
024 * @param <E> the Bean displayed in the Pane.................
025 */
026public class BeanTablePane<E extends NamedBean> extends jmri.util.swing.JmriPanel {
027
028    private BeanTableDataModel<E> dataModel;
029    private JTable dataTable;
030    private JScrollPane dataScroll;
031    private JPanel bottomBox;  // panel at bottom for extra buttons etc
032    static final int bottomStrutWidth = 20;
033
034    public void init(BeanTableDataModel<E> model) {
035
036        dataModel = model;
037
038        TableRowSorter<BeanTableDataModel<E>> sorter = new TableRowSorter<>(dataModel);
039        dataTable = dataModel.makeJTable(dataModel.getMasterClassName(), dataModel, sorter);
040        dataScroll = new JScrollPane(dataTable);
041
042        // use NamedBean's built-in Comparator interface for sorting the system name column
043        RowSorterUtil.setSortOrder(sorter, BeanTableDataModel.SYSNAMECOL, SortOrder.ASCENDING);
044        this.dataTable.setRowSorter(sorter);
045
046        // configure items for GUI
047        dataModel.configureTable(dataTable);
048
049        // general GUI config
050        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
051
052        // install items in GUI
053        add(dataScroll);
054        bottomBox = new JPanel();
055        bottomBox.setLayout(new jmri.util.swing.WrapLayout(jmri.util.swing.WrapLayout.LEFT, bottomStrutWidth, 5));
056
057        add(bottomBox);
058
059        // add extras, if desired by subclass
060        extras();
061
062        // set Viewport preferred size from size of table
063        java.awt.Dimension dataTableSize = dataTable.getPreferredSize();
064        // width is right, but if table is empty, it's not high
065        // enough to reserve much space.
066        dataTableSize.height = Math.max(dataTableSize.height, 400);
067        dataScroll.getViewport().setPreferredSize(dataTableSize);
068
069        // set preferred scrolling options
070        dataScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
071        dataScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
072    }
073
074    /**
075     * Hook to allow sub-types to install more items in GUI.
076     */
077    void extras() {
078    }
079
080    /**
081     * Add a component to the bottom box.
082     * @param comp {@link Component} to add
083     */
084    protected void addToBottomBox(Component comp) {
085        bottomBox.add(comp);
086    }
087
088    @Override
089    public void dispose() {
090        if (dataModel != null) {
091            dataModel.dispose();
092        }
093        dataModel = null;
094        dataTable = null;
095        dataScroll = null;
096    }
097}