1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sourceforge.jarduino.gui;
18
19 import java.awt.BorderLayout;
20 import java.awt.Color;
21 import java.awt.Dimension;
22 import java.awt.Font;
23 import java.awt.GridBagConstraints;
24 import java.awt.GridBagLayout;
25 import java.awt.event.MouseAdapter;
26 import java.awt.event.MouseEvent;
27 import javax.swing.BorderFactory;
28 import javax.swing.Box;
29 import javax.swing.BoxLayout;
30 import javax.swing.JComponent;
31 import javax.swing.JFrame;
32 import javax.swing.JLabel;
33 import javax.swing.JPanel;
34 import javax.swing.JScrollPane;
35 import javax.swing.SwingConstants;
36 import javax.swing.border.Border;
37
38 import net.sourceforge.jarduino.message.ArduinoMessage;
39 import net.sourceforge.jarduino.message.ArduinoSystem;
40 import net.sourceforge.jarduino.util.ArduinoHex;
41
42
43
44
45 public class ArduinoPanelSignal {
46
47
48
49 static final Font FONT = new Font("monospaced", Font.BOLD, 16);
50
51
52
53
54 static final Font FONTX = new Font("SansSerif", Font.BOLD, 16);
55
56
57
58
59 private final JPanel thePanel;
60
61
62
63
64 private final ArduinoTableSignal theTable;
65
66
67
68
69 private final ArduinoScrollButton<ArduinoMessage> theSelect;
70
71
72
73
74 private final JLabel theHex;
75
76
77
78
79 private final JLabel theMsgId;
80
81
82
83
84 private final BinaryData theBinary;
85
86
87
88
89 private byte[] theData;
90
91
92
93
94
95 ArduinoPanelSignal(final JFrame pFrame) {
96
97 theSelect = new ArduinoScrollButton<>(pFrame);
98 theSelect.setFormatter(ArduinoMessage::getName);
99 theSelect.onSelect(this::selectMessage);
100
101
102 theMsgId = new JLabel();
103 theMsgId.setFont(FONTX);
104 final JLabel myIdPrompt = new JLabel("MessageId:");
105 myIdPrompt.setFont(FONTX);
106 final JPanel myIdPanel = new JPanel();
107 myIdPanel.setLayout(new BoxLayout(myIdPanel, BoxLayout.X_AXIS));
108 myIdPanel.add(Box.createHorizontalStrut(ArduinoPanelMain.STRUTSIZE));
109 myIdPanel.add(myIdPrompt);
110 myIdPanel.add(Box.createHorizontalStrut(ArduinoPanelMain.STRUTSIZE));
111 myIdPanel.add(theMsgId);
112 myIdPanel.add(Box.createHorizontalStrut(ArduinoPanelMain.STRUTSIZE));
113
114
115 final JPanel mySelectPanel = new JPanel();
116 mySelectPanel.setLayout(new BoxLayout(mySelectPanel, BoxLayout.X_AXIS));
117 mySelectPanel.add(Box.createHorizontalStrut(ArduinoPanelMain.STRUTSIZE));
118 mySelectPanel.add(theSelect.getComponent());
119 mySelectPanel.add(Box.createHorizontalGlue());
120 mySelectPanel.add(myIdPanel);
121 Border myBorder = BorderFactory.createTitledBorder("Select Message");
122 mySelectPanel.setBorder(myBorder);
123
124
125 theTable = new ArduinoTableSignal(this);
126
127
128 final JPanel myDataPanel = new JPanel(new GridBagLayout());
129 final GridBagConstraints myC = new GridBagConstraints();
130 myBorder = BorderFactory.createTitledBorder("Message Data");
131 myDataPanel.setBorder(myBorder);
132
133
134 myC.gridx = 0;
135 myC.gridy = 0;
136 myC.anchor = GridBagConstraints.LINE_END;
137 myC.weightx = 0.0;
138 myC.fill = GridBagConstraints.NONE;
139 myDataPanel.add(new JLabel("Hex Data: "), myC);
140 myC.gridx = 1;
141 myC.gridy = 0;
142 myC.anchor = GridBagConstraints.CENTER;
143 myC.weightx = 1.0;
144 myC.fill = GridBagConstraints.HORIZONTAL;
145 theHex = new JLabel();
146 theHex.setFont(FONT);
147 myDataPanel.add(theHex, myC);
148
149
150 myC.gridx = 0;
151 myC.gridy = 1;
152 myC.anchor = GridBagConstraints.LINE_END;
153 myC.weightx = 0.0;
154 myC.fill = GridBagConstraints.NONE;
155 myDataPanel.add(new JLabel("Binary Data: "), myC);
156 myC.gridx = 1;
157 myC.gridy = 1;
158 myC.anchor = GridBagConstraints.CENTER;
159 myC.weightx = 1.0;
160 myC.fill = GridBagConstraints.HORIZONTAL;
161 theBinary = new BinaryData();
162 myDataPanel.add(theBinary.getComponent(), myC);
163
164
165
166 final JPanel myMsgPanel = new JPanel(new BorderLayout());
167 myMsgPanel.add(new JScrollPane(theTable.getComponent()), BorderLayout.CENTER);
168 myBorder = BorderFactory.createTitledBorder("Message Signals");
169 myMsgPanel.setBorder(myBorder);
170
171
172 thePanel = new JPanel(new BorderLayout());
173 thePanel.add(mySelectPanel, BorderLayout.PAGE_START);
174 thePanel.add(myMsgPanel, BorderLayout.CENTER);
175 thePanel.add(myDataPanel, BorderLayout.PAGE_END);
176
177
178 thePanel.setPreferredSize(new Dimension(ArduinoPanelMain.WIDTH, ArduinoPanelMain.HEIGHT));
179 }
180
181
182
183
184
185 JComponent getComponent() {
186 return thePanel;
187 }
188
189
190
191
192
193 byte[] getData() {
194 return theData;
195 }
196
197
198
199
200
201 void setSystem(final ArduinoSystem pSystem) {
202
203 theSelect.removeAll();
204 for (ArduinoMessage myMessage : pSystem.getMessages()) {
205 theSelect.add(myMessage);
206 }
207 }
208
209
210
211
212
213 private void selectMessage(final ArduinoMessage pMessage) {
214
215 theData = new byte[pMessage.getLength()];
216
217
218 theTable.configureTable(pMessage);
219
220
221 updateHexAndBinary();
222 updateBitColors();
223 updateMessageId(pMessage);
224 }
225
226
227
228
229
230 void updateMessageId(final ArduinoMessage pMessage) {
231 final int myNum = Integer.parseUnsignedInt(pMessage.getId());
232 theMsgId.setText(pMessage.getId() + String.format(" 0x%08X", myNum));
233 }
234
235
236
237
238 void updateHexAndBinary() {
239 updateHexData();
240 theBinary.refreshData();
241 }
242
243
244
245
246 private void updateHexData() {
247 theHex.setText(ArduinoHex.bytesToHexString(theData));
248 }
249
250
251
252
253 void updateBitColors() {
254
255 theBinary.resetColors();
256
257
258 final int myNumRows = theTable.getNumRows();
259 for (int i = 0; i < myNumRows; i++) {
260
261 final Color myColor = theTable.getColorForRow(i);
262
263
264 if (myColor != null) {
265
266 final byte[] myBitMap = theTable.getBitMapForRow(i);
267
268
269 theBinary.updateColor(myColor, myBitMap);
270 }
271 }
272 }
273
274
275
276
277 private class BinaryData {
278
279
280
281 private final JPanel thePanel;
282
283
284
285
286 private final BinaryBit[] theBits;
287
288
289
290
291 BinaryData() {
292
293 thePanel = new JPanel();
294 thePanel.setLayout(new BoxLayout(thePanel, BoxLayout.X_AXIS));
295
296
297 theBits = new BinaryBit[Long.SIZE];
298
299
300 for (int i = 0; i < Long.SIZE; i++) {
301
302 final BinaryBit myBit = new BinaryBit(i);
303 thePanel.add(myBit.getComponent());
304 theBits[i] = myBit;
305
306
307 if ((i + 1) % Byte.SIZE == 0) {
308 final JLabel mySpacer = new JLabel();
309 mySpacer.setText(" ");
310 thePanel.add(mySpacer);
311 }
312 }
313 }
314
315
316
317
318
319 JComponent getComponent() {
320 return thePanel;
321 }
322
323
324
325
326 void refreshData() {
327
328 final int maxBit = theData.length * Byte.SIZE;
329
330
331 for (int i = 0; i < Long.SIZE; i++) {
332 final boolean visible = i < maxBit;
333 final BinaryBit myBit = theBits[i];
334 myBit.refreshData(visible);
335 }
336 }
337
338
339
340
341 void resetColors() {
342
343 final int maxBit = theData.length * Byte.SIZE;
344
345
346 for (int bitNo = 0; bitNo < maxBit; bitNo++) {
347
348 theBits[bitNo].setColor(thePanel.getBackground());
349 }
350 }
351
352
353
354
355
356
357 void updateColor(final Color pColour,
358 final byte[] pBitMap) {
359
360 final int maxBit = theData.length * Byte.SIZE;
361
362
363 for (int bitNo = 0; bitNo < maxBit; bitNo++) {
364
365 final int myByteNo = bitNo / Byte.SIZE;
366 final int myShift = Byte.SIZE - (bitNo % Byte.SIZE) - 1;
367 final int myMask = 1 << myShift;
368
369
370 if ((pBitMap[myByteNo] & myMask) != 0) {
371
372 theBits[bitNo].setColor(pColour);
373 }
374 }
375 }
376 }
377
378
379
380
381 private class BinaryBit {
382
383
384
385 private final int theIndex;
386
387
388
389
390 private final JLabel theLabel;
391
392
393
394
395
396 BinaryBit(final int pIndex) {
397
398 theIndex = pIndex;
399
400
401 theLabel = new JLabel();
402 theLabel.setFont(FONT);
403 theLabel.setHorizontalAlignment(SwingConstants.CENTER);
404 theLabel.setOpaque(true);
405
406
407 theLabel.addMouseListener(new LabelMouse());
408 }
409
410
411
412
413
414 JComponent getComponent() {
415 return theLabel;
416 }
417
418
419
420
421
422 void setColor(final Color pColour) {
423 theLabel.setForeground(Color.BLACK);
424 theLabel.setBackground(pColour);
425 }
426
427
428
429
430
431 void refreshData(final boolean pVisible) {
432 theLabel.setVisible(pVisible);
433 if (pVisible) {
434 showBitFromData();
435 }
436 }
437
438
439
440
441 void showBitFromData() {
442 final int myByteNo = theIndex / Byte.SIZE;
443 final int myShift = Byte.SIZE - (theIndex % Byte.SIZE) - 1;
444 final int myMask = 1 << myShift;
445 theLabel.setText((theData[myByteNo] & myMask) != 0 ? "1" : "0");
446 }
447
448
449
450
451 void toggleBitInData() {
452
453 final int myByteNo = theIndex / Byte.SIZE;
454 final int myShift = Byte.SIZE - (theIndex % Byte.SIZE) - 1;
455 final int myMask = 1 << myShift;
456 theData[myByteNo] ^= myMask;
457 theLabel.setText((theData[myByteNo] & myMask) != 0 ? "1" : "0");
458 refreshOnToggle();
459 }
460
461
462
463
464 private void refreshOnToggle() {
465 theTable.loadValues();
466 updateHexData();
467 updateBitColors();
468 }
469
470
471
472
473 private final class LabelMouse
474 extends MouseAdapter {
475 @Override
476 public void mouseClicked(final MouseEvent e) {
477 toggleBitInData();
478 }
479 }
480 }
481 }