001package jmri.jmrit.vsdecoder.swing;
002
003import java.util.HashMap;
004import javax.swing.table.AbstractTableModel;
005import jmri.jmrit.vsdecoder.listener.ListeningSpot;
006import jmri.util.PhysicalLocation;
007
008/**
009 * Table Models for Loading of Reporters, Blocks, Locations and Listener.
010 *
011 * <hr>
012 * This file is part of JMRI.
013 * <p>
014 * JMRI is free software; you can redistribute it and/or modify it under
015 * the terms of version 2 of the GNU General Public License as published
016 * by the Free Software Foundation. See the "COPYING" file for a copy
017 * of this license.
018 * <p>
019 * JMRI is distributed in the hope that it will be useful, but WITHOUT
020 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
021 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
022 * for more details.
023 *
024 * @author Klaus Killinger Copyright (C) 2020
025 */
026class ManageLocationsTableModel {
027
028    // Note: the four tables covered here do not have the same structure
029    static final int SYSNAMECOL     = 0;             // system name
030    static final int NAMECOL        = 0;             // name (special case for Operations Locations)
031    static final int USERNAMECOL    = 1;             // user name
032    static final int USECOL         = 1;             // usage flag for Operations Locations and Listener
033    static final int XCOL           = 2;             // X value
034    static final int YCOL           = 3;             // Y value
035    static final int ZCOL           = 4;             // Z value
036    static final int TUNNELCOL      = 5;             // tunnel flag (not for Listener)
037    static final int BEARINGCOL     = 5;             // bearing attribute (Listener only)
038    static final int AZIMUTHCOL     = 6;             // azimuth attribute (Listener only)
039
040    /**
041     * class to serve as TableModel for Reporters and Blocks
042     */
043    static class ReporterBlockTableModel extends AbstractTableModel {
044
045        // These get internationalized at runtime in the constructor below.
046        private String[] columnNames = new String[7];
047        private Object[][] rowData;
048
049        public ReporterBlockTableModel(Object[][] dataMap) {
050            super();
051            // Use i18n-ized column titles.
052            columnNames[SYSNAMECOL] = Bundle.getMessage("Name");
053            columnNames[USERNAMECOL] = Bundle.getMessage("ColumnUserName");
054            columnNames[USECOL + 1] = Bundle.getMessage("FieldTableUseColumn");
055            columnNames[XCOL + 1] = Bundle.getMessage("FieldTableXColumn");
056            columnNames[YCOL + 1] = Bundle.getMessage("FieldTableYColumn");
057            columnNames[ZCOL + 1] = Bundle.getMessage("FieldTableZColumn");
058            columnNames[TUNNELCOL + 1] = Bundle.getMessage("FieldTableIsTunnelColumn");
059            rowData = dataMap;
060        }
061
062        public HashMap<String, PhysicalLocation> getDataMap() {
063            // Includes only the ones with the checkbox made
064            HashMap<String, PhysicalLocation> retv = new HashMap<>();
065            for (Object[] row : rowData) {
066                if ((Boolean) row[USECOL + 1]) {
067                    if (row[XCOL + 1] == null) {
068                        row[XCOL + 1] = 0.0f;
069                    }
070                    if (row[YCOL + 1] == null) {
071                        row[YCOL + 1] = 0.0f;
072                    }
073                    if (row[ZCOL + 1] == null) {
074                        row[ZCOL + 1] = 0.0f;
075                    }
076                    retv.put((String) row[SYSNAMECOL],
077                            new PhysicalLocation((Float) row[XCOL + 1], (Float) row[YCOL + 1], (Float) row[ZCOL + 1], (Boolean) row[TUNNELCOL + 1]));
078                }
079            }
080            return retv;
081        }
082
083        @Override
084        public String getColumnName(int col) {
085            return columnNames[col];
086        }
087
088        @Override
089        public int getRowCount() {
090            return rowData.length;
091        }
092
093        @Override
094        public int getColumnCount() {
095            return columnNames.length;
096        }
097
098        @Override
099        public Object getValueAt(int row, int col) {
100            return rowData[row][col];
101        }
102
103        @Override
104        public boolean isCellEditable(int row, int col) {
105            return true;
106        }
107
108        @Override
109        public void setValueAt(Object value, int row, int col) {
110            rowData[row][col] = value;
111            fireTableCellUpdated(row, col);
112        }
113
114        @Override
115        public Class<?> getColumnClass(int columnIndex) {
116            switch (columnIndex) {
117                case USECOL + 1:
118                case TUNNELCOL + 1:
119                    return Boolean.class;
120                case ZCOL + 1:
121                case YCOL + 1:
122                case XCOL + 1:
123                    return Float.class;
124                case USERNAMECOL:
125                case SYSNAMECOL:
126                default:
127                    return super.getColumnClass(columnIndex);
128            }
129        }
130    }
131
132    /**
133     * class to serve as TableModel for Ops Locations
134     */
135    static class LocationTableModel extends AbstractTableModel {
136
137        // These get internationalized at runtime in the constructor below.
138        private String[] columnNames = new String[6];
139        private Object[][] rowData;
140
141        public LocationTableModel(Object[][] dataMap) {
142            super();
143            // Use i18n-ized column titles.
144            columnNames[NAMECOL] = Bundle.getMessage("Name");
145            columnNames[USECOL] = Bundle.getMessage("FieldTableUseColumn");
146            columnNames[XCOL] = Bundle.getMessage("FieldTableXColumn");
147            columnNames[YCOL] = Bundle.getMessage("FieldTableYColumn");
148            columnNames[ZCOL] = Bundle.getMessage("FieldTableZColumn");
149            columnNames[TUNNELCOL] = Bundle.getMessage("FieldTableIsTunnelColumn");
150            rowData = dataMap;
151        }
152
153        public HashMap<String, PhysicalLocation> getDataMap() {
154            // Includes only the ones with the checkbox made
155            HashMap<String, PhysicalLocation> retv = new HashMap<>();
156            for (Object[] row : rowData) {
157                if ((Boolean) row[USECOL]) {
158                    if (row[XCOL] == null) {
159                        row[XCOL] = 0.0f;
160                    }
161                    if (row[YCOL] == null) {
162                        row[YCOL] = 0.0f;
163                    }
164                    if (row[ZCOL] == null) {
165                        row[ZCOL] = 0.0f;
166                    }
167                    retv.put((String) row[NAMECOL],
168                            new PhysicalLocation((Float) row[XCOL], (Float) row[YCOL], (Float) row[ZCOL], (Boolean) row[TUNNELCOL]));
169                }
170            }
171            return retv;
172        }
173
174        @Override
175        public String getColumnName(int col) {
176            return columnNames[col];
177        }
178
179        @Override
180        public int getRowCount() {
181            return rowData.length;
182        }
183
184        @Override
185        public int getColumnCount() {
186            return columnNames.length;
187        }
188
189        @Override
190        public Object getValueAt(int row, int col) {
191            return rowData[row][col];
192        }
193
194        @Override
195        public boolean isCellEditable(int row, int col) {
196            return true;
197        }
198
199        @Override
200        public void setValueAt(Object value, int row, int col) {
201            rowData[row][col] = value;
202            fireTableCellUpdated(row, col);
203        }
204
205        @Override
206        public Class<?> getColumnClass(int columnIndex) {
207            switch (columnIndex) {
208                case USECOL:
209                case TUNNELCOL:
210                    return Boolean.class;
211                case ZCOL:
212                case YCOL:
213                case XCOL:
214                    return Float.class;
215                case NAMECOL:
216                default:
217                    return super.getColumnClass(columnIndex);
218            }
219        }
220    }
221
222    /**
223     * class for use as TableModel for Listener Locations
224     */
225    static class ListenerTableModel extends AbstractTableModel {
226
227        // These get internationalized at runtime in the constructor below.
228        private String[] columnNames = new String[7];
229        private Object[][] rowData = null;
230
231        public ListenerTableModel(Object[][] dataMap) {
232            super();
233            // Use i18n-ized column titles.
234            columnNames[NAMECOL] = Bundle.getMessage("Name");
235            columnNames[USECOL] = Bundle.getMessage("FieldTableUseColumn");
236            columnNames[XCOL] = Bundle.getMessage("FieldTableXColumn");
237            columnNames[YCOL] = Bundle.getMessage("FieldTableYColumn");
238            columnNames[ZCOL] = Bundle.getMessage("FieldTableZColumn");
239            columnNames[BEARINGCOL] = Bundle.getMessage("FieldTableBearingColumn");
240            columnNames[AZIMUTHCOL] = Bundle.getMessage("FieldTableAzimuthColumn");
241            rowData = dataMap;
242        }
243
244        public HashMap<String, ListeningSpot> getDataMap() {
245            // Includes only the ones with the checkbox made
246            HashMap<String, ListeningSpot> retv = new HashMap<>();
247            ListeningSpot spot = null;
248            for (Object[] row : rowData) {
249                if ((Boolean) row[USECOL]) {
250                    spot = new ListeningSpot();
251                    spot.setName((String) row[NAMECOL]);
252                    spot.setLocation((Double) row[XCOL], (Double) row[YCOL], (Double) row[ZCOL]);
253                    spot.setOrientation((Double) row[BEARINGCOL], (Double) row[AZIMUTHCOL]);
254                    retv.put((String) row[NAMECOL], spot);
255                }
256            }
257            return retv;
258        }
259
260        @Override
261        public String getColumnName(int col) {
262            return columnNames[col];
263        }
264
265        @Override
266        public int getRowCount() {
267            return rowData.length;
268        }
269
270        @Override
271        public int getColumnCount() {
272            return columnNames.length;
273        }
274
275        @Override
276        public Object getValueAt(int row, int col) {
277            return rowData[row][col];
278        }
279
280        @Override
281        public boolean isCellEditable(int row, int col) {
282            return true;
283        }
284
285        @Override
286        public void setValueAt(Object value, int row, int col) {
287            rowData[row][col] = value;
288            fireTableCellUpdated(row, col);
289        }
290
291        @Override
292        public Class<?> getColumnClass(int columnIndex) {
293            switch (columnIndex) {
294                case USECOL:
295                    return Boolean.class;
296                case AZIMUTHCOL:
297                case BEARINGCOL:
298                case ZCOL:
299                case YCOL:
300                case XCOL:
301                    return Double.class;
302                case NAMECOL:
303                default:
304                    return super.getColumnClass(columnIndex);
305            }
306        }
307    }
308}