001package jmri.jmrix.can.cbus.swing.cbusslotmonitor;
002
003import java.awt.*;
004import java.awt.event.ActionEvent;
005import java.util.ArrayList;
006import java.util.Arrays;
007import java.util.List;
008
009import javax.swing.*;
010import javax.swing.table.*;
011
012import jmri.InstanceManager;
013import jmri.jmrit.catalog.NamedIcon;
014import jmri.jmrit.throttle.LargePowerManagerButton;
015import jmri.jmrix.can.CanSystemConnectionMemo;
016import jmri.jmrix.can.cbus.swing.CbusCommonSwing;
017import jmri.swing.JmriJTablePersistenceManager;
018import jmri.util.swing.StayOpenCheckBoxItem;
019import jmri.util.swing.XTableColumnModel;
020import jmri.util.table.ButtonEditor;
021import jmri.util.table.ButtonRenderer;
022import jmri.util.table.JTableWithColumnToolTips;
023
024/**
025 * Pane for monitoring and configuring a MERG CBUS Command Station.
026 *
027 * @author Steve Young Copyright (C) 2018
028 * @since 4.13.4
029 */
030public class CbusSlotMonitorPane extends jmri.jmrix.can.swing.CanPanel {
031
032    protected CbusSlotMonitorDataModel slotModel;
033    private JTable slotTable;
034    private final XTableColumnModel tcm = new XTableColumnModel();
035    private final JMenu colMenu = new JMenu((Bundle.getMessage("SessCol")));
036
037    // private JMenu cancmdMenu = new JMenu("CANCMD Setup");
038
039    public CbusSlotMonitorPane() {
040        super();
041    }
042
043    @Override
044    public void initComponents(CanSystemConnectionMemo memo) {
045        super.initComponents(memo);
046        slotModel = memo.get(CbusSlotMonitorDataModel.class);
047        slotTable = new JTableWithColumnToolTips(slotModel,CbusSlotMonitorDataModel.CBUSSLOTMONTOOLTIPS);
048        init();
049    }
050
051    public void init() {
052
053        // Use XTableColumnModel so we can control which columns are visible
054        slotTable.setColumnModel(tcm);
055
056        setupColumnsMenuLinks();
057
058        final TableRowSorter<CbusSlotMonitorDataModel> sorter = new TableRowSorter<>(slotModel);
059        slotTable.setRowSorter(sorter);
060
061        setCellRenderers();
062
063        JScrollPane slotScroll = new JScrollPane(slotTable);
064        slotScroll.setPreferredSize(new Dimension(400, 200));
065
066        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
067
068        JScrollPane scrolltablefeedback = new JScrollPane (slotModel.tablefeedback());
069        scrolltablefeedback.setMinimumSize(new Dimension(150, 20));
070
071        JPanel toppanelcontainer = new JPanel();
072        toppanelcontainer.setLayout(new BoxLayout(toppanelcontainer, BoxLayout.X_AXIS));
073        toppanelcontainer.add(getStopButton());
074        toppanelcontainer.add(new LargePowerManagerButton(true));
075
076        JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
077            slotScroll, scrolltablefeedback);
078        split.setResizeWeight(0.95d);
079        split.setContinuousLayout(true);
080
081        JPanel p1 = new JPanel();
082        p1.setLayout(new BorderLayout());
083
084        p1.add(toppanelcontainer, BorderLayout.PAGE_START);
085        p1.add(split, BorderLayout.CENTER);        
086        add(p1);
087
088        p1.setMinimumSize(new Dimension(450, 200));
089        p1.setVisible(true);
090    }
091
092    private void setCellRenderers(){
093        for (int i = 0; i < CbusSlotMonitorDataModel.MAX_COLUMN; i++) {
094            TableColumn col = tcm.getColumnByModelIndex(i);
095            switch (i) {
096                case CbusSlotMonitorDataModel.LOCO_ID_LONG_COLUMN:
097                    break; // use default CellRenderer for boolean values
098                case CbusSlotMonitorDataModel.ESTOP_COLUMN:
099                    col.setMinWidth(55);
100                    col.setCellRenderer( new ButtonRenderer() );
101                    col.setCellEditor( new ButtonEditor( new JButton() ) );
102                    break;
103                case CbusSlotMonitorDataModel.KILL_SESSION_COLUMN:
104                case CbusSlotMonitorDataModel.LAUNCH_THROTTLE:
105                    col.setCellRenderer( new ButtonRenderer() );
106                    col.setCellEditor( new ButtonEditor( new JButton() ) );
107                    break;
108                default:
109                    col.setCellRenderer( getRenderer());
110                    break;
111            }
112        }
113    }
114
115    private JButton getStopButton(){
116        JButton estopButton = new JButton("Stop All");
117        estopButton.setIcon(new NamedIcon("resources/icons/throttles/estop.png", "resources/icons/throttles/estop.png"));
118        estopButton.setToolTipText(Bundle.getMessage("ThrottleToolBarStopAllToolTip"));
119        estopButton.addActionListener((ActionEvent e) -> slotModel.sendcbusestop() );
120        return estopButton;
121    }
122
123    private void setupColumnsMenuLinks() {
124
125        // configure items for GUI
126        CbusCommonSwing.configureTable(slotTable);
127        slotTable.setName("CbusSlotMonitorPane.5.9.7"); // to reset UI xml when table format changes
128
129        StayOpenCheckBoxItem[] cbArray = new StayOpenCheckBoxItem[slotModel.getColumnCount()];
130
131        // initialise and set default column visibiity
132        for (int i = 0; i < slotModel.getColumnCount(); i++) {
133            StayOpenCheckBoxItem cbi = new StayOpenCheckBoxItem(slotModel.getColumnName(i));
134            cbArray[i] = cbi;
135            TableColumn column  = tcm.getColumnByModelIndex(i);
136            cbi.addActionListener((ActionEvent e) ->
137                tcm.setColumnVisible(column, cbi.isSelected()));
138            final int ii = i;
139            tcm.setColumnVisible(tcm.getColumnByModelIndex(i),
140                Arrays.stream(CbusSlotMonitorDataModel.CBUSSLOTMONINITIALCOLS).anyMatch(j -> j == ii)
141                );
142
143        }
144
145        InstanceManager.getOptionalDefault(JmriJTablePersistenceManager.class).ifPresent( tpm ->
146            tpm.persist(slotTable, true));
147
148        for (int i = 0; i < slotModel.getColumnCount(); i++) {
149            cbArray[i].setSelected(tcm.isColumnVisible(tcm.getColumnByModelIndex(i)));
150            colMenu.add(cbArray[i]); // count columns
151        }
152
153    }
154
155    /**
156     * {@inheritDoc}
157     */
158    @Override
159    public String getTitle() {
160        return prependConnToString(Bundle.getMessage("MenuItemCbusSlotMonitor"));
161    }
162
163    /**
164     * Creates a Menu List.
165     * {@inheritDoc}
166     */
167    @Override
168    public List<JMenu> getMenus() {
169        List<JMenu> menuList = new ArrayList<>();
170        menuList.add(colMenu);
171        return menuList;
172    }
173
174    /**
175     * {@inheritDoc}
176     */
177    @Override
178    public String getHelpTarget() {
179        return "package.jmri.jmrix.can.cbus.swing.cbusslotmonitor.CbusSlotMonitorPane";
180    }    
181
182    private TableCellRenderer getRenderer() {
183        return new TableCellRenderer() {
184            JTextField f = new JTextField();
185
186            @Override
187            public Component getTableCellRendererComponent(
188                JTable table, Object arg1, boolean isSelected, boolean hasFocus,
189                int row, int col) {
190
191                if(arg1 != null){
192                    String string = arg1.toString();
193                    f.setText(string);
194                    f.setHorizontalAlignment(JTextField.CENTER);
195
196                } else {
197                    f.setText("");
198                }
199
200                CbusCommonSwing.setCellBackground(isSelected, f, table,row);
201                CbusCommonSwing.setCellFocus(hasFocus, f, table);
202                return f;
203            }
204        };
205    }
206
207    /**
208     * {@inheritDoc}
209     */
210    @Override
211    public void dispose() {
212        InstanceManager.getOptionalDefault(JmriJTablePersistenceManager.class).ifPresent( tpm ->
213            tpm.stopPersisting(slotTable) );
214        slotTable = null;
215        super.dispose();
216    }
217
218    /**
219     * Nested class to create one of these using old-style defaults
220     */
221    public static class Default extends jmri.jmrix.can.swing.CanNamedPaneAction {
222
223        public Default() {
224            super(Bundle.getMessage("MenuItemCbusSlotMonitor"),
225                    new jmri.util.swing.sdi.JmriJFrameInterface(),
226                    CbusSlotMonitorPane.class.getName(),
227                    InstanceManager.getDefault(CanSystemConnectionMemo.class));
228        }
229    }
230
231    // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusSlotMonitorPane.class);
232
233}