001package jmri.jmrit.beantable;
002
003import java.awt.BorderLayout;
004import java.awt.event.ActionEvent;
005import java.util.ArrayList;
006
007import javax.annotation.Nonnull;
008import javax.swing.*;
009import javax.swing.event.*;
010import javax.swing.table.*;
011
012import jmri.*;
013import jmri.swing.RowSorterUtil;
014import jmri.util.AlphanumComparator;
015
016public abstract class AbstractTableTabAction<E extends NamedBean> extends AbstractTableAction<E> {
017
018    protected JTabbedPane dataTabs;
019    protected boolean init = false;
020
021    public AbstractTableTabAction(String s) {
022        super(s);
023    }
024
025    @Override
026    protected void createModel() {
027        dataTabs = new JTabbedPane();
028        Manager<E> mgr = getManager();
029        if (mgr instanceof jmri.managers.AbstractProxyManager) {
030            // build the list, with default at start and internal at end (if present)
031            jmri.managers.AbstractProxyManager<E> proxy = (jmri.managers.AbstractProxyManager<E>) mgr;
032
033            tabbedTableArray.add(new TabbedTableItem<>(
034                Bundle.getMessage("All"), true, mgr, getNewTableAction("All"))); // NOI18N
035
036            proxy.getDisplayOrderManagerList().stream().map(manager -> {
037                String manuName = manager.getMemo().getUserName();
038                return new TabbedTableItem<>(
039                    manuName, true, manager, getNewTableAction(manuName)); // connection name to display in Tab
040            }).forEachOrdered(itemModel -> tabbedTableArray.add(itemModel));
041
042        } else {
043            Manager<E> man = getManager();
044            String manuName = ( man!=null ? man.getMemo().getUserName() : "Unknown Manager");
045            tabbedTableArray.add(new TabbedTableItem<>(manuName, true, getManager(), getNewTableAction(manuName)));
046        }
047        for (int x = 0; x < tabbedTableArray.size(); x++) {
048            AbstractTableAction<E> table = tabbedTableArray.get(x).getAAClass();
049            table.addToPanel(this);
050            dataTabs.addTab(tabbedTableArray.get(x).getItemString(),  tabbedTableArray.get(x).getPanel());
051        }
052        dataTabs.addChangeListener((ChangeEvent evt) -> setMenuBar(f));
053        init = true;
054    }
055
056    @Override
057    protected abstract Manager<E> getManager();
058
059    protected abstract AbstractTableAction<E> getNewTableAction(String choice);
060
061    @Override
062    public JComponent getPanel() {
063        if (!init) {
064            createModel();
065        }
066        return dataTabs;
067    }
068
069    protected ArrayList<TabbedTableItem<E>> tabbedTableArray = new ArrayList<>();
070
071    @Override
072    protected void setTitle() {
073        //atf.setTitle("multiple sensors");
074    }
075
076    @Override
077    protected abstract String helpTarget();
078
079    @Override
080    protected void addPressed(ActionEvent e) {
081        log.warn("This should not have happened");
082    }
083
084    @Override
085    public void addToFrame(BeanTableFrame<E> f) {
086        try {
087            TabbedTableItem<E> table = tabbedTableArray.get(dataTabs.getSelectedIndex());
088            if (table != null) {
089                table.getAAClass().addToFrame(f);
090            }
091        } catch (ArrayIndexOutOfBoundsException ex) {
092            log.error("{} in add to Frame {} {}", ex.toString(), dataTabs.getSelectedIndex(), dataTabs.getSelectedComponent());
093        }
094    }
095
096    @Override
097    public void setMenuBar(BeanTableFrame<E> f) {
098        try {
099            tabbedTableArray.get(dataTabs.getSelectedIndex()).getAAClass().setMenuBar(f);
100        } catch (ArrayIndexOutOfBoundsException ex) {
101            log.error("{} in add to Menu {} {}", ex.toString(), dataTabs.getSelectedIndex(), dataTabs.getSelectedComponent());
102        }
103    }
104
105    public void addToBottomBox(JComponent c, String str) {
106        tabbedTableArray.forEach( table -> {
107            String item = table.getItemString();
108            if (item != null && item.equals(str)) {
109                table.addToBottomBox(c);
110            }
111        });
112    }
113
114    @Override
115    public void print(javax.swing.JTable.PrintMode mode, java.text.MessageFormat headerFormat, java.text.MessageFormat footerFormat) {
116        try {
117            tabbedTableArray.get(dataTabs.getSelectedIndex()).getDataTable().print(mode, headerFormat, footerFormat);
118        } catch (java.awt.print.PrinterException e1) {
119            log.warn("error printing", e1);
120        } catch (NullPointerException ex) {
121            log.error("Trying to print returned a NPE error");
122        }
123    }
124
125    @Override
126    public void dispose() {
127        for (int x = 0; x < tabbedTableArray.size(); x++) {
128            tabbedTableArray.get(x).dispose();
129        }
130        super.dispose();
131    }
132
133    protected static class TabbedTableItem<E extends NamedBean> extends AbstractTableAction.TableItem<E> {  // E comes from the parent
134
135        final String itemText;
136
137        final JPanel bottomBox;
138        private boolean addToFrameRan = false;
139        final Manager<E> manager;
140
141        private boolean standardModel = true;
142
143        private final JPanel tabPanel;
144
145        @SuppressWarnings("unchecked")
146        public TabbedTableItem(String choice, boolean stdModel, Manager<E> manager, @Nonnull AbstractTableAction<E> tableAction) {
147
148            super(tableAction);
149
150            itemText = choice;
151            standardModel = stdModel;
152            this.manager = manager;
153
154            //If a panel model is used, it should really add to the bottom box
155            //but it can be done this way if required.
156            tabPanel = new JPanel();
157            tabPanel.setLayout(new BorderLayout());
158
159            bottomBox = new JPanel();
160            bottomBox.setLayout(new jmri.util.swing.WrapLayout(jmri.util.swing.WrapLayout.LEFT,20,5));
161
162            if (stdModel) {
163                createDataModel();
164            } else {
165                addPanelModel();
166            }
167        }
168
169        @SuppressWarnings("unchecked")
170        final void createDataModel() {
171            tableAction.setManager(manager);
172            dataModel = tableAction.getTableDataModel();
173            TableRowSorter<BeanTableDataModel<E>> sorter = new TableRowSorter<>(dataModel);
174            dataTable = dataModel.makeJTable(dataModel.getMasterClassName() + ":" + getItemString(), dataModel, sorter);
175            JScrollPane dataScroll = new JScrollPane(dataTable);
176
177            RowSorterUtil.setSortOrder(sorter, BeanTableDataModel.SYSNAMECOL, SortOrder.ASCENDING);
178
179            sorter.setComparator(BeanTableDataModel.USERNAMECOL, new AlphanumComparator());
180            RowSorterUtil.setSortOrder(sorter, BeanTableDataModel.USERNAMECOL, SortOrder.ASCENDING);
181
182            dataModel.configureTable(dataTable);
183            tableAction.configureTable(dataTable);
184
185            java.awt.Dimension dataTableSize = dataTable.getPreferredSize();
186            // width is right, but if table is empty, it's not high
187            // enough to reserve much space.
188            dataTableSize.height = Math.max(dataTableSize.height, 400);
189            dataScroll.getViewport().setPreferredSize(dataTableSize);
190
191            // set preferred scrolling options
192            dataScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
193            dataScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
194
195            tabPanel.add(dataScroll, BorderLayout.CENTER);
196            tabPanel.add(bottomBox, BorderLayout.SOUTH);
197
198            includeAddButton(tableAction.includeAddButton());
199
200            includePropertyCheckBox();
201
202        }
203
204        final void addPanelModel() {
205            tabPanel.add(tableAction.getPanel(), BorderLayout.CENTER);
206            tabPanel.add(bottomBox, BorderLayout.SOUTH);
207        }
208
209        public boolean getStandardTableModel() {
210            return standardModel;
211        }
212
213        public String getItemString() {
214            return itemText;
215        }
216
217        public JComponent getPanel() {
218            return tabPanel;
219        }
220
221        public boolean getAdditionsToFrameDone() {
222            return addToFrameRan;
223        }
224
225        public void setAddToFrameRan() {
226            addToFrameRan = true;
227        }
228
229        @Override
230        protected void addToBottomBox(JComponent comp) {
231            bottomBox.add(comp);
232        }
233
234    }
235
236    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractTableTabAction.class);
237
238}