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