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
@@ -254,10 +263,113 @@ protected void onCreateWindow(Container mainPane) {
254
263
pane .add (serialRates );
255
264
256
265
mainPane .add (pane , BorderLayout .SOUTH );
266
+
267
+ textField = new JTextField (40 );
268
+ // textField is selected every time the window is focused
269
+ addWindowFocusListener (new WindowAdapter () {
270
+ @ Override
271
+ public void windowGainedFocus (WindowEvent e ) {
272
+ textField .requestFocusInWindow ();
273
+ }
274
+ });
275
+
276
+ // Add cut/copy/paste contextual menu to the text input field.
277
+ JPopupMenu menu = new JPopupMenu ();
278
+
279
+ Action cut = new DefaultEditorKit .CutAction ();
280
+ cut .putValue (Action .NAME , tr ("Cut" ));
281
+ menu .add (cut );
282
+
283
+ Action copy = new DefaultEditorKit .CopyAction ();
284
+ copy .putValue (Action .NAME , tr ("Copy" ));
285
+ menu .add (copy );
286
+
287
+ Action paste = new DefaultEditorKit .PasteAction ();
288
+ paste .putValue (Action .NAME , tr ("Paste" ));
289
+ menu .add (paste );
290
+
291
+ textField .setComponentPopupMenu (menu );
292
+
293
+ sendButton = new JButton (tr ("Send" ));
294
+
295
+ JPanel lowerPane = new JPanel ();
296
+ lowerPane .setLayout (new BoxLayout (lowerPane , BoxLayout .X_AXIS ));
297
+ lowerPane .setBorder (new EmptyBorder (4 , 4 , 4 , 4 ));
298
+
299
+ noLineEndingAlert = new JLabel (I18n .format (tr ("You've pressed {0} but nothing was sent. Should you select a line ending?" ), tr ("Send" )));
300
+ noLineEndingAlert .setToolTipText (noLineEndingAlert .getText ());
301
+ noLineEndingAlert .setForeground (pane .getBackground ());
302
+ Dimension minimumSize = new Dimension (noLineEndingAlert .getMinimumSize ());
303
+ minimumSize .setSize (minimumSize .getWidth () / 3 , minimumSize .getHeight ());
304
+ noLineEndingAlert .setMinimumSize (minimumSize );
305
+
306
+
307
+ lineEndings = new JComboBox <String >(new String []{tr ("No line ending" ), tr ("Newline" ), tr ("Carriage return" ), tr ("Both NL & CR" )});
308
+ lineEndings .addActionListener ((ActionEvent event ) -> {
309
+ PreferencesData .setInteger ("serial.line_ending" , lineEndings .getSelectedIndex ());
310
+ noLineEndingAlert .setForeground (pane .getBackground ());
311
+ });
312
+ lineEndings .setMaximumSize (lineEndings .getMinimumSize ());
313
+
314
+ lowerPane .add (textField );
315
+ lowerPane .add (Box .createRigidArea (new Dimension (4 , 0 )));
316
+ lowerPane .add (sendButton );
317
+
318
+ pane .add (lowerPane );
319
+ pane .add (noLineEndingAlert );
320
+ pane .add (Box .createRigidArea (new Dimension (8 , 0 )));
321
+ pane .add (lineEndings );
322
+
323
+ applyPreferences ();
324
+
325
+ onSendCommand ((ActionEvent event ) -> {
326
+ send (textField .getText ());
327
+ textField .setText ("" );
328
+ });
329
+
330
+ }
331
+
332
+ private void send (String string ) {
333
+ String s = string ;
334
+ if (serial != null ) {
335
+ switch (lineEndings .getSelectedIndex ()) {
336
+ case 1 :
337
+ s += "\n " ;
338
+ break ;
339
+ case 2 :
340
+ s += "\r " ;
341
+ break ;
342
+ case 3 :
343
+ s += "\r \n " ;
344
+ break ;
345
+ default :
346
+ break ;
347
+ }
348
+ if ("" .equals (s ) && lineEndings .getSelectedIndex () == 0 && !PreferencesData .has ("runtime.line.ending.alert.notified" )) {
349
+ noLineEndingAlert .setForeground (Color .RED );
350
+ PreferencesData .set ("runtime.line.ending.alert.notified" , "true" );
351
+ }
352
+ serial .write (s );
353
+ }
354
+ }
355
+
356
+ public void onSendCommand (ActionListener listener ) {
357
+ textField .addActionListener (listener );
358
+ sendButton .addActionListener (listener );
359
+ }
360
+
361
+ public void appyPreferences () {
362
+ // Apply line endings.
363
+ if (PreferencesData .get ("serial.line_ending" ) != null ) {
364
+ lineEndings .setSelectedIndex (PreferencesData .getInteger ("serial.line_ending" ));
365
+ }
257
366
}
258
367
259
368
protected void onEnableWindow (boolean enable ) {
260
369
serialRates .setEnabled (enable );
370
+ textField .setEnabled (enable );
371
+ sendButton .setEnabled (enable );
372
+ lineEndings .setEnabled (enable );
261
373
}
262
374
263
375
private void onSerialRateChange (ActionListener listener ) {
0 commit comments