26
26
import java .util .ArrayList ;
27
27
import javax .swing .*;
28
28
import javax .swing .border .EmptyBorder ;
29
+ import javax .swing .text .DefaultEditorKit ;
29
30
import java .awt .*;
31
+ import java .awt .event .ActionEvent ;
30
32
import java .awt .event .ActionListener ;
33
+ import java .awt .event .WindowAdapter ;
34
+ import java .awt .event .WindowEvent ;
31
35
import java .awt .geom .AffineTransform ;
32
36
import java .awt .geom .Rectangle2D ;
33
37
@@ -40,6 +44,11 @@ public class SerialPlotter extends AbstractMonitor {
40
44
private Serial serial ;
41
45
private int serialRate , xCount ;
42
46
47
+ private JLabel noLineEndingAlert ;
48
+ private JTextField textField ;
49
+ private JButton sendButton ;
50
+ private JComboBox <String > lineEndings ;
51
+
43
52
private ArrayList <Graph > graphs ;
44
53
private final static int BUFFER_CAPACITY = 500 ;
45
54
@@ -267,10 +276,113 @@ protected void onCreateWindow(Container mainPane) {
267
276
pane .add (serialRates );
268
277
269
278
mainPane .add (pane , BorderLayout .SOUTH );
279
+
280
+ textField = new JTextField (40 );
281
+ // textField is selected every time the window is focused
282
+ addWindowFocusListener (new WindowAdapter () {
283
+ @ Override
284
+ public void windowGainedFocus (WindowEvent e ) {
285
+ textField .requestFocusInWindow ();
286
+ }
287
+ });
288
+
289
+ // Add cut/copy/paste contextual menu to the text input field.
290
+ JPopupMenu menu = new JPopupMenu ();
291
+
292
+ Action cut = new DefaultEditorKit .CutAction ();
293
+ cut .putValue (Action .NAME , tr ("Cut" ));
294
+ menu .add (cut );
295
+
296
+ Action copy = new DefaultEditorKit .CopyAction ();
297
+ copy .putValue (Action .NAME , tr ("Copy" ));
298
+ menu .add (copy );
299
+
300
+ Action paste = new DefaultEditorKit .PasteAction ();
301
+ paste .putValue (Action .NAME , tr ("Paste" ));
302
+ menu .add (paste );
303
+
304
+ textField .setComponentPopupMenu (menu );
305
+
306
+ sendButton = new JButton (tr ("Send" ));
307
+
308
+ JPanel lowerPane = new JPanel ();
309
+ lowerPane .setLayout (new BoxLayout (lowerPane , BoxLayout .X_AXIS ));
310
+ lowerPane .setBorder (new EmptyBorder (4 , 4 , 4 , 4 ));
311
+
312
+ noLineEndingAlert = new JLabel (I18n .format (tr ("You've pressed {0} but nothing was sent. Should you select a line ending?" ), tr ("Send" )));
313
+ noLineEndingAlert .setToolTipText (noLineEndingAlert .getText ());
314
+ noLineEndingAlert .setForeground (pane .getBackground ());
315
+ Dimension minimumSize = new Dimension (noLineEndingAlert .getMinimumSize ());
316
+ minimumSize .setSize (minimumSize .getWidth () / 3 , minimumSize .getHeight ());
317
+ noLineEndingAlert .setMinimumSize (minimumSize );
318
+
319
+
320
+ lineEndings = new JComboBox <String >(new String []{tr ("No line ending" ), tr ("Newline" ), tr ("Carriage return" ), tr ("Both NL & CR" )});
321
+ lineEndings .addActionListener ((ActionEvent event ) -> {
322
+ PreferencesData .setInteger ("serial.line_ending" , lineEndings .getSelectedIndex ());
323
+ noLineEndingAlert .setForeground (pane .getBackground ());
324
+ });
325
+ lineEndings .setMaximumSize (lineEndings .getMinimumSize ());
326
+
327
+ lowerPane .add (textField );
328
+ lowerPane .add (Box .createRigidArea (new Dimension (4 , 0 )));
329
+ lowerPane .add (sendButton );
330
+
331
+ pane .add (lowerPane );
332
+ pane .add (noLineEndingAlert );
333
+ pane .add (Box .createRigidArea (new Dimension (8 , 0 )));
334
+ pane .add (lineEndings );
335
+
336
+ applyPreferences ();
337
+
338
+ onSendCommand ((ActionEvent event ) -> {
339
+ send (textField .getText ());
340
+ textField .setText ("" );
341
+ });
342
+
343
+ }
344
+
345
+ private void send (String string ) {
346
+ String s = string ;
347
+ if (serial != null ) {
348
+ switch (lineEndings .getSelectedIndex ()) {
349
+ case 1 :
350
+ s += "\n " ;
351
+ break ;
352
+ case 2 :
353
+ s += "\r " ;
354
+ break ;
355
+ case 3 :
356
+ s += "\r \n " ;
357
+ break ;
358
+ default :
359
+ break ;
360
+ }
361
+ if ("" .equals (s ) && lineEndings .getSelectedIndex () == 0 && !PreferencesData .has ("runtime.line.ending.alert.notified" )) {
362
+ noLineEndingAlert .setForeground (Color .RED );
363
+ PreferencesData .set ("runtime.line.ending.alert.notified" , "true" );
364
+ }
365
+ serial .write (s );
366
+ }
367
+ }
368
+
369
+ public void onSendCommand (ActionListener listener ) {
370
+ textField .addActionListener (listener );
371
+ sendButton .addActionListener (listener );
372
+ }
373
+
374
+ public void appyPreferences () {
375
+ // Apply line endings.
376
+ if (PreferencesData .get ("serial.line_ending" ) != null ) {
377
+ lineEndings .setSelectedIndex (PreferencesData .getInteger ("serial.line_ending" ));
378
+ }
270
379
}
271
380
272
381
protected void onEnableWindow (boolean enable ) {
273
382
serialRates .setEnabled (enable );
383
+ textField .setEnabled (enable );
384
+ sendButton .setEnabled (enable );
385
+ lineEndings .setEnabled (enable );
274
386
}
275
387
276
388
private void onSerialRateChange (ActionListener listener ) {
0 commit comments