001package jmri.jmrit.withrottle;
002
003import java.awt.BorderLayout;
004import java.awt.Color;
005import java.awt.event.ActionEvent;
006import java.beans.PropertyChangeListener;
007import java.util.List;
008import javax.swing.*;
009import javax.swing.event.TableModelEvent;
010import javax.swing.event.TableModelListener;
011import javax.swing.table.AbstractTableModel;
012import javax.swing.table.TableColumn;
013import javax.swing.table.TableColumnModel;
014import jmri.*;
015import jmri.util.JmriJFrame;
016import org.slf4j.Logger;
017import org.slf4j.LoggerFactory;
018
019/**
020 * @author Brett Hoffman Copyright (C) 2010
021 */
022public class ControllerFilterFrame extends JmriJFrame implements TableModelListener {
023
024    private static final String[] COLUMN_NAMES = {Bundle.getMessage("ColumnSystemName"),
025        Bundle.getMessage("ColumnUserName"),
026        Bundle.getMessage("Include")};
027
028    public ControllerFilterFrame() {
029        super(Bundle.getMessage("TitleControlsFilter"), true, true);
030    }
031
032    @Override
033    public void initComponents() {
034        JTabbedPane tabbedPane = new JTabbedPane();
035        if (InstanceManager.getNullableDefault(jmri.TurnoutManager.class) != null) {
036
037            tabbedPane.addTab(Bundle.getMessage("Turnouts"), null, addTurnoutPanel(), Bundle.getMessage("ToolTipTurnoutTab"));
038        }
039
040        if (InstanceManager.getNullableDefault(jmri.RouteManager.class) != null) {
041
042            tabbedPane.addTab(Bundle.getMessage("LabelRoute"), null, addRoutePanel(), Bundle.getMessage("ToolTipRouteTab"));
043        }
044
045        add(tabbedPane);
046
047        pack();
048
049        addHelpMenu("package.jmri.jmrit.withrottle.UserInterface", true);
050    }
051
052    private JPanel addTurnoutPanel() {
053        JPanel tPanel = new JPanel(new BorderLayout());
054        JLabel label = new JLabel(Bundle.getMessage("LabelTurnoutTab"), SwingConstants.CENTER);
055        tPanel.add(label, BorderLayout.NORTH);
056        tPanel.add(addCancelSavePanel(), BorderLayout.WEST);
057
058        final TurnoutFilterModel filterModel = new TurnoutFilterModel();
059        JTable table = new JTable(filterModel);
060        buildTable(table);
061
062        JScrollPane scrollPane = new JScrollPane(table);
063        tPanel.add(scrollPane, BorderLayout.CENTER);
064
065        tPanel.add(getIncludeButtonsPanel(filterModel), BorderLayout.SOUTH);
066
067        return tPanel;
068    }
069
070    private JPanel addRoutePanel() {
071        JPanel tPanel = new JPanel(new BorderLayout());
072        JLabel label = new JLabel(Bundle.getMessage("LabelRouteTab"), SwingConstants.CENTER);
073        tPanel.add(label, BorderLayout.NORTH);
074        tPanel.add(addCancelSavePanel(), BorderLayout.WEST);
075
076        final RouteFilterModel filterModel = new RouteFilterModel();
077        JTable table = new JTable(filterModel);
078        buildTable(table);
079
080        JScrollPane scrollPane = new JScrollPane(table);
081        tPanel.add(scrollPane, BorderLayout.CENTER);
082
083        tPanel.add(getIncludeButtonsPanel(filterModel), BorderLayout.SOUTH);
084
085        return tPanel;
086    }
087
088    private void buildTable(JTable table) {
089        table.getModel().addTableModelListener(this);
090
091        table.setRowSelectionAllowed(false);
092        table.setPreferredScrollableViewportSize(new java.awt.Dimension(580, 240));
093
094        //table.getTableHeader().setBackground(Color.lightGray);
095        table.setShowGrid(false);
096        table.setShowHorizontalLines(true);
097        table.setGridColor(Color.gray);
098        table.setRowHeight(30);
099
100        TableColumnModel columnModel = table.getColumnModel();
101
102        TableColumn include = columnModel.getColumn(AbstractFilterModel.INCLUDECOL);
103        include.setResizable(false);
104        include.setMinWidth(60);
105        include.setMaxWidth(70);
106
107        TableColumn sName = columnModel.getColumn(AbstractFilterModel.SNAMECOL);
108        sName.setResizable(true);
109        sName.setMinWidth(80);
110        sName.setPreferredWidth(80);
111        sName.setMaxWidth(340);
112
113        TableColumn uName = columnModel.getColumn(AbstractFilterModel.UNAMECOL);
114        uName.setResizable(true);
115        uName.setMinWidth(180);
116        uName.setPreferredWidth(300);
117        uName.setMaxWidth(440);
118    }
119
120    private JPanel getIncludeButtonsPanel(final AbstractFilterModel fm) {
121        JPanel pane = new JPanel();
122        pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
123        pane.add(Box.createHorizontalGlue());
124
125        JButton selectAllButton = new JButton(Bundle.getMessage("ButtonSelectAll"));
126        selectAllButton.addActionListener((ActionEvent event) -> {
127            fm.setIncludeColToValue(true);
128        });
129        pane.add(selectAllButton);
130
131        JButton deselectAllButton = new JButton(Bundle.getMessage("ButtonDeselectAll"));
132        deselectAllButton.addActionListener((ActionEvent event) -> {
133            fm.setIncludeColToValue(false);
134        });
135        pane.add(deselectAllButton);
136
137        JButton selectUserNamedButton = new JButton(Bundle.getMessage("ButtonSelectByUserName"));
138        selectUserNamedButton.addActionListener((ActionEvent event) -> {
139            fm.setIncludeToUserNamed();
140        });
141        pane.add(selectUserNamedButton);
142
143        return pane;
144    }
145
146    private JPanel addCancelSavePanel() {
147        JPanel p = new JPanel();
148        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
149        p.add(Box.createVerticalGlue());
150
151        JButton cancelButton = new JButton(Bundle.getMessage("ButtonCancel"));
152        cancelButton.setAlignmentX(CENTER_ALIGNMENT);
153        cancelButton.setToolTipText(Bundle.getMessage("ToolTipCancel"));
154        cancelButton.addActionListener((ActionEvent event) -> {
155            dispose();
156        });
157        p.add(cancelButton);
158
159        JButton saveButton = new JButton(Bundle.getMessage("ButtonSave"));
160        saveButton.setAlignmentX(CENTER_ALIGNMENT);
161        saveButton.setToolTipText(Bundle.getMessage("ToolTipSave"));
162        saveButton.addActionListener((ActionEvent event) -> {
163            storeValues();
164            dispose();
165        });
166        p.add(saveButton);
167
168        return p;
169    }
170
171    @Override
172    protected void storeValues() {
173        new jmri.configurexml.StoreXmlUserAction().actionPerformed(null);
174    }
175
176    @Override
177    public void tableChanged(TableModelEvent e) {
178        if (log.isDebugEnabled()) {
179            log.debug("Set mod flag true for: {}", getTitle());
180        }
181        this.setModifiedFlag(true);
182    }
183
184    public abstract class AbstractFilterModel extends AbstractTableModel implements PropertyChangeListener {
185
186        List<String> sysNameList = null;
187        boolean isDirty;
188
189        @Override
190        public Class<?> getColumnClass(int c) {
191            if (c == INCLUDECOL) {
192                return Boolean.class;
193            } else {
194                return String.class;
195            }
196        }
197
198        @Override
199        public void propertyChange(java.beans.PropertyChangeEvent e) {
200            if (e.getPropertyName().equals("length")) {
201                fireTableDataChanged();
202            }
203        }
204
205        public void dispose() {
206            InstanceManager.turnoutManagerInstance().removePropertyChangeListener(this);
207            InstanceManager.getDefault(jmri.RouteManager.class).removePropertyChangeListener(this);
208        }
209
210        @Override
211        public String getColumnName(int c) {
212            return COLUMN_NAMES[c];
213        }
214
215        @Override
216        public int getColumnCount() {
217            return 3;
218        }
219
220        @Override
221        public int getRowCount() {
222            return sysNameList.size();
223        }
224
225        @Override
226        public boolean isCellEditable(int r, int c) {
227            return (c == INCLUDECOL);
228        }
229
230        abstract void setIncludeColToValue(boolean value);
231
232        abstract void setIncludeToUserNamed();
233
234        public static final int SNAMECOL = 0;
235        public static final int UNAMECOL = 1;
236        public static final int INCLUDECOL = 2;
237    }
238
239    class TurnoutFilterModel extends AbstractFilterModel {
240
241        TurnoutManager mgr = InstanceManager.turnoutManagerInstance();
242
243        TurnoutFilterModel() {
244            sysNameList = new java.util.ArrayList<>(mgr.getNamedBeanSet().size());
245            mgr.getNamedBeanSet().forEach(bean -> {
246                sysNameList.add(bean.getSystemName());
247            });
248            mgr.addPropertyChangeListener(this);
249        }
250
251        @Override
252        public Object getValueAt(int r, int c) {
253
254            // some error checking
255            if (r >= sysNameList.size()) {
256                log.debug("row is greater than turnout list size");
257                return null;
258            }
259            Turnout t = mgr.getBySystemName(sysNameList.get(r));
260            switch (c) {
261                case INCLUDECOL:
262                    if (t != null) {
263                        Object o = t.getProperty("WifiControllable");
264                        if (o != null) {
265                            return Boolean.valueOf(o.toString());
266                        }
267                    }
268                    return true;
269                case SNAMECOL:
270                    return sysNameList.get(r);
271                case UNAMECOL:
272                    return t != null ? t.getUserName() : null;
273                default:
274                    return null;
275            }
276        }
277
278        @Override
279        public void setValueAt(Object type, int r, int c) {
280            Turnout t = mgr.getBySystemName(sysNameList.get(r));
281            if (t != null) {
282                switch (c) {
283                    case INCLUDECOL:
284                        t.setProperty("WifiControllable", type);
285                        if (!isDirty) {
286                            this.fireTableChanged(new TableModelEvent(this));
287                            isDirty = true;
288                        }
289                        break;
290                    default:
291                        log.warn("Unhandled col: {}", c);
292                        break;
293                }
294            }
295        }
296
297        @Override
298        public void setIncludeColToValue(boolean value) {
299            for (String sysName : sysNameList) {
300                Turnout t = mgr.getBySystemName(sysName);
301                if (t != null) {
302                    t.setProperty("WifiControllable", value);
303                }
304            }
305            fireTableDataChanged();
306        }
307
308        @Override
309        public void setIncludeToUserNamed() {
310            for (String sysName : sysNameList) {
311                Turnout t = mgr.getBySystemName(sysName);
312                if (t != null) {
313                    String uname = t.getUserName();
314                    if ((uname != null) && (uname.length() > 0)) {
315                        t.setProperty("WifiControllable", true);
316                    } else {
317                        t.setProperty("WifiControllable", false);
318                    }
319                }
320            }
321            fireTableDataChanged();
322        }
323    }
324
325    class RouteFilterModel extends AbstractFilterModel {
326
327        RouteManager mgr = InstanceManager.getDefault(jmri.RouteManager.class);
328
329        RouteFilterModel() {
330            sysNameList = new java.util.ArrayList<>(mgr.getNamedBeanSet().size());
331            mgr.getNamedBeanSet().forEach(bean -> {
332                sysNameList.add(bean.getSystemName());
333            });
334            mgr.addPropertyChangeListener(this);
335        }
336
337        @Override
338        public Object getValueAt(int r, int c) {
339
340            // some error checking
341            if (r >= sysNameList.size()) {
342                log.debug("row is greater than turnout list size");
343                return null;
344            }
345            Route rt = mgr.getBySystemName(sysNameList.get(r));
346            switch (c) {
347                case INCLUDECOL:
348                    if (rt == null) {
349                        return null;
350                    }
351                    Object o = rt.getProperty("WifiControllable");
352                    if (o != null) {
353                        return Boolean.valueOf(o.toString());
354                    }
355                    return true;
356                case SNAMECOL:
357                    return sysNameList.get(r);
358                case UNAMECOL:
359                    if (rt == null) {
360                        return null;
361                    }
362                    return rt.getUserName();
363                default:
364                    return null;
365            }
366        }
367
368        @Override
369        public void setValueAt(Object type, int r, int c) {
370
371            switch (c) {
372                case INCLUDECOL:
373                    Route rt = mgr.getBySystemName(sysNameList.get(r));
374                    if (rt != null) {
375                        rt.setProperty("WifiControllable", type);
376                        if (!isDirty) {
377                            this.fireTableChanged(new TableModelEvent(this));
378                            isDirty = true;
379                        }
380                    }
381                    break;
382                default:
383                    log.warn("Unhandled col: {}", c);
384                    break;
385            }
386        }
387
388        @Override
389        public void setIncludeColToValue(boolean value) {
390            for (String sysName : sysNameList) {
391                Route rt = mgr.getBySystemName(sysName);
392                if (rt != null) {
393                    rt.setProperty("WifiControllable", value);
394                }
395            }
396            fireTableDataChanged();
397        }
398
399        @Override
400        public void setIncludeToUserNamed() {
401            for (String sysName : sysNameList) {
402                NamedBean bean = mgr.getBySystemName(sysName);
403                if (bean != null) {
404                    String uname = bean.getUserName();
405                    if ((uname != null) && (uname.length() > 0)) {
406                        bean.setProperty("WifiControllable", true);
407                    } else {
408                        bean.setProperty("WifiControllable", false);
409                    }
410                } else {
411                    log.error("Failed to get bean from getBySystemName {}", sysName);
412                }
413            }
414            fireTableDataChanged();
415        }
416    }
417
418    private final static Logger log = LoggerFactory.getLogger(ControllerFilterFrame.class);
419
420}