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}