View Javadoc
1   /*******************************************************************************
2    * jArduino: Arduino C++ Code Generation From Java
3    * Copyright 2020 Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   ******************************************************************************/
17  package net.sourceforge.jarduino.gui;
18  
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import javax.swing.JComponent;
25  import javax.swing.JTable;
26  import javax.swing.table.AbstractTableModel;
27  import javax.swing.table.TableColumn;
28  import javax.swing.table.TableColumnModel;
29  
30  import net.sourceforge.jarduino.gui.ArduinoPanelMeta.ArduinoConfigMode;
31  import net.sourceforge.jarduino.message.ArduinoAttribute;
32  import net.sourceforge.jarduino.message.ArduinoAttribute.ArduinoAttrClass;
33  import net.sourceforge.jarduino.message.ArduinoAttribute.ArduinoAttrObject;
34  import net.sourceforge.jarduino.message.ArduinoMessage;
35  import net.sourceforge.jarduino.message.ArduinoNode;
36  import net.sourceforge.jarduino.message.ArduinoSignal;
37  import net.sourceforge.jarduino.message.ArduinoSystem;
38  
39  /**
40   * Table for Attributes.
41   */
42  public class ArduinoTableAttr {
43      /**
44       * The attributes.
45       */
46      private final List<ArduinoAttribute> theAttributes;
47  
48      /**
49       * The receivers.
50       */
51      private final Map<Integer, ArduinoNode> theReceivers;
52  
53      /**
54       * The values.
55       */
56      private final List<Object> theValues;
57  
58      /**
59       * The Attributes table.
60       */
61      private final JTable theTable;
62  
63      /**
64       * The Attributes table model.
65       */
66      private final ArduinoAttrModel theModel;
67  
68      /**
69       * The Parents column.
70       */
71      private final TableColumn theParentCol;
72  
73      /**
74       * Is the parent column visible?
75       */
76      private boolean parentsVisible;
77  
78      /**
79       * The system.
80       */
81      private ArduinoSystem theSystem;
82  
83      /**
84       * The mode.
85       */
86      private ArduinoConfigMode theMode;
87  
88      /**
89       * The selected Object.
90       */
91      private ArduinoAttrObject theSelected;
92  
93      /**
94       * Constructor.
95       */
96      ArduinoTableAttr() {
97          /* Create lists and maps */
98          theAttributes = new ArrayList<>();
99          theValues = new ArrayList<>();
100         theReceivers = new HashMap<>();
101 
102         /* Create the table */
103         theTable = new JTable();
104         theTable.setAutoCreateRowSorter(true);
105 
106         /* Create the table model */
107         theModel = new ArduinoAttrModel();
108         theTable.setModel(theModel);
109 
110         /* Access the parent column */
111         final TableColumnModel myColModel = theTable.getColumnModel();
112         theParentCol = myColModel.getColumn(ArduinoAttrModel.COL_RECEIVER);
113         parentsVisible = true;
114     }
115 
116     /**
117      * Obtain the component.
118      * @return the component
119      */
120     JComponent getComponent() {
121         return theTable;
122     }
123 
124     /**
125      * Configure the table.
126      *
127      * @param pSystem the system
128      * @param pMode the mode
129      * @param pSelected the selected object
130      */
131     void configureTable(final ArduinoSystem pSystem,
132                         final ArduinoConfigMode pMode,
133                         final ArduinoAttrObject pSelected) {
134         /* store the details */
135         theSystem = pSystem;
136         theMode = pMode;
137         theSelected = pSelected;
138 
139         /* Refresh the table model */
140         theModel.refresh();
141 
142         /* Determine whether parents column should be visible */
143         final boolean bParentsVisible = !theReceivers.isEmpty();
144 
145         /* If we should modify the columns */
146         if (bParentsVisible != parentsVisible) {
147             /* Access the table column model */
148             final TableColumnModel myColModel = theTable.getColumnModel();
149 
150             /* If we need to remove the column */
151             if (parentsVisible) {
152                 myColModel.removeColumn(theParentCol);
153 
154                 /* else restore the column and move to correct position */
155             } else {
156                 myColModel.addColumn(theParentCol);
157                 myColModel.moveColumn(ArduinoAttrModel.COL_VALUE, ArduinoAttrModel.COL_RECEIVER);
158             }
159 
160             /* Flip the flag */
161             parentsVisible = !parentsVisible;
162         }
163     }
164 
165     /**
166      * Table Model.
167      */
168     private class ArduinoAttrModel
169             extends AbstractTableModel {
170         /**
171          * Serial Id.
172          */
173         private static final long serialVersionUID = -7093822082474013905L;
174 
175         /**
176          * The attribute column.
177          */
178         private static final int COL_ATTR = 0;
179 
180         /**
181          * The receiver column.
182          */
183         private static final int COL_RECEIVER = COL_ATTR + 1;
184 
185         /**
186          * The value column.
187          */
188         private static final int COL_VALUE = COL_RECEIVER + 1;
189 
190         /**
191          * Constructor.
192          */
193         ArduinoAttrModel() {
194         }
195 
196         /**
197          * Refresh the model.
198          */
199         void refresh() {
200             /* Clear the lists/maps */
201             theAttributes.clear();
202             theValues.clear();
203             theReceivers.clear();
204 
205             /* Loop through the attributes */
206             for (ArduinoAttribute myAttr : theSystem.getAttributes()) {
207                 /* If the attribute is relevant */
208                 if (isRelevant(myAttr)) {
209                     /* If this is a relation attribute */
210                     if (myAttr.getAttrClass().isRelation()) {
211                         /* Load values associated with it */
212                         loadRelationAttribute(myAttr);
213                     } else {
214                         /* Load values associated with it */
215                         loadAttribute(myAttr);
216                     }
217                 }
218             }
219 
220             /* Refresh the table */
221             fireTableDataChanged();
222         }
223 
224         /**
225          * loadAttribute.
226          * @param pAttr the attribute to load
227          */
228         private void loadAttribute(final ArduinoAttribute pAttr) {
229             /* Add the item and its value to the list */
230             theAttributes.add(pAttr);
231             theValues.add(theSelected.getAttrValue(pAttr));
232         }
233 
234         /**
235          * loadAttribute.
236          * @param pAttr the attribute to load
237          */
238         private void loadRelationAttribute(final ArduinoAttribute pAttr) {
239             /* The index */
240             int myIndex = theAttributes.size();
241 
242             /* Loop through the nodes */
243             for (ArduinoNode myNode : theSystem.getNodes()) {
244                 /* If the node receives the signal/message */
245                 if (nodeReceivesObject(myNode)) {
246                     /* Access the value and store into map */
247                     theAttributes.add(pAttr);
248                     theReceivers.put(myIndex++, myNode);
249                     theValues.add(myNode.getRelationValue(pAttr, theSelected));
250                 }
251             }
252         }
253 
254         /**
255          * is the attribute relevant in this mode?
256          * @param pAttr the attribute to load
257          * @return true/false
258          */
259         private boolean isRelevant(final ArduinoAttribute pAttr) {
260             final ArduinoAttrClass myClass = pAttr.getAttrClass();
261             switch (theMode) {
262                 case SYSTEM:
263                     return myClass == ArduinoAttrClass.SYSTEM;
264                 case NODE:
265                     return myClass == ArduinoAttrClass.NODE;
266                 case MESSAGE:
267                     return myClass == ArduinoAttrClass.MESSAGE
268                             || myClass == ArduinoAttrClass.NODE2MSG;
269                 case SIGNAL:
270                     return myClass == ArduinoAttrClass.SIGNAL
271                             || myClass == ArduinoAttrClass.NODE2SIGNAL;
272                 default:
273                     return false;
274             }
275         }
276 
277         /**
278          * is the node a receiver of the selected object.
279          * @param pNode the node
280          * @return true/false
281          */
282         private boolean nodeReceivesObject(final ArduinoNode pNode) {
283             /* If the object is a message */
284             if (theSelected instanceof ArduinoMessage) {
285                 return pNode.receivesMessage((ArduinoMessage) theSelected);
286             } else if (theSelected instanceof ArduinoSignal) {
287                 return pNode.receivesSignal((ArduinoSignal) theSelected);
288             }
289             return false;
290         }
291 
292         @Override
293         public int getRowCount() {
294             return theAttributes.size();
295         }
296 
297         @Override
298         public String getColumnName(final int pColIndex) {
299             switch (pColIndex) {
300                 case COL_ATTR:
301                     return "Attribute";
302                 case COL_RECEIVER:
303                     return "Receiver";
304                 case COL_VALUE:
305                     return "Value";
306                 default:
307                     return null;
308             }
309         }
310 
311         @Override
312         public int getColumnCount() {
313             return COL_VALUE + 1;
314         }
315 
316         @Override
317         public boolean isCellEditable(final int pRowIndex,
318                                       final int pColIndex) {
319             return false;
320         }
321 
322         @Override
323         public Object getValueAt(final int pRowIndex,
324                                  final int pColIndex) {
325             switch (pColIndex) {
326                 case COL_ATTR:
327                     return theAttributes.get(pRowIndex).getName();
328                 case COL_RECEIVER:
329                     return theReceivers.get(pRowIndex);
330                 case COL_VALUE:
331                     return theValues.get(pRowIndex);
332                 default:
333                     return null;
334             }
335         }
336     }
337 }