Subversion Repositories Programming Utils

Rev

Rev 50 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
12 rm5248 1
package com.rm5248.terminal;
2
 
3
import java.awt.BorderLayout;
4
import java.awt.Color;
5
import java.awt.Dimension;
6
import java.awt.Font;
16 rm5248 7
import java.awt.FontMetrics;
22 rm5248 8
import java.awt.GridLayout;
19 rm5248 9
import java.awt.event.ActionEvent;
10
import java.awt.event.ActionListener;
11
import java.awt.event.KeyEvent;
12
import java.awt.event.KeyListener;
16 rm5248 13
import java.io.IOException;
12 rm5248 14
import java.io.InputStream;
15
import java.io.OutputStream;
16
 
22 rm5248 17
import javax.swing.BorderFactory;
21 rm5248 18
import javax.swing.ButtonGroup;
41 rm5248 19
import javax.swing.JButton;
21 rm5248 20
import javax.swing.JCheckBoxMenuItem;
22 rm5248 21
import javax.swing.JComboBox;
12 rm5248 22
import javax.swing.JFrame;
23
import javax.swing.JLabel;
19 rm5248 24
import javax.swing.JMenu;
25
import javax.swing.JMenuBar;
26
import javax.swing.JMenuItem;
41 rm5248 27
import javax.swing.JOptionPane;
12 rm5248 28
import javax.swing.JPanel;
21 rm5248 29
import javax.swing.JRadioButtonMenuItem;
16 rm5248 30
import javax.swing.JScrollPane;
21 rm5248 31
import javax.swing.JSeparator;
12 rm5248 32
import javax.swing.JTextArea;
19 rm5248 33
import javax.swing.KeyStroke;
34
import javax.swing.UIManager;
35
import javax.swing.text.BadLocationException;
12 rm5248 36
 
37
import com.rm5248.serial.NoSuchPortException;
38
import com.rm5248.serial.NotASerialPortException;
37 rm5248 39
import com.rm5248.serial.SerialChangeListener;
40
import com.rm5248.serial.SerialLineState;
12 rm5248 41
import com.rm5248.serial.SerialPort;
42
import com.rm5248.serial.SerialPort.BaudRate;
43
import com.rm5248.serial.SerialPort.DataBits;
44
import com.rm5248.serial.SerialPort.FlowControl;
45
import com.rm5248.serial.SerialPort.Parity;
46
import com.rm5248.serial.SerialPort.StopBits;
47
 
48
/**
49
 * JavaTerminal is a Java-based terminal emulator to open serial ports.
50
 * It is designed to be similar to GTKTerm for Linux.
51
 * GTKTerm's webpage is at https://fedorahosted.org/gtkterm/
52
 *
53
 *
54
 */
21 rm5248 55
public class JavaTerminal implements KeyListener, Runnable {
17 rm5248 56
 
21 rm5248 57
        private enum NewlineType{
58
                CR,
59
                NL,
60
                CRNL
61
        }
62
 
63
        //SerialPort variables
12 rm5248 64
        private SerialPort thePort;
65
        private InputStream portInput;
66
        private OutputStream portOutput;
17 rm5248 67
        private boolean localEcho;
21 rm5248 68
        private NewlineType newlines;
17 rm5248 69
 
21 rm5248 70
        //GUI variables
12 rm5248 71
        private JFrame theFrame;
72
        private JLabel portInfoLeft;
39 rm5248 73
        private LineIndicatorPanel portStatus;
12 rm5248 74
        private JTextArea text;
22 rm5248 75
        private Font monoFont;
76
        private Font sansFont;
17 rm5248 77
 
21 rm5248 78
        //The newline separator, so that we put the correct one in the GUI so copy/paste will work nicely
19 rm5248 79
        private final static String NEWLINE = System.getProperty("line.separator");
80
 
22 rm5248 81
        public JavaTerminal( String portToOpen, BaudRate baud, DataBits data, StopBits stop, Parity parity, FlowControl flow, boolean localEcho, boolean justOpen ){
17 rm5248 82
                this.localEcho = localEcho;
21 rm5248 83
                newlines = NewlineType.NL;
84
 
19 rm5248 85
                try{
86
                        UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
87
                }catch( Exception e ){}
88
 
50 rm5248 89
                makeGUI();
90
 
12 rm5248 91
                try {
22 rm5248 92
                        if( !justOpen ){
93
                                thePort = new SerialPort( portToOpen, baud, data, stop, parity, flow );
94
                        }else{
95
                                thePort = new SerialPort( portToOpen, justOpen );
96
                        }
12 rm5248 97
                } catch (NoSuchPortException e) {
98
                        System.err.println( "ERROR: No Such Port( " + portToOpen + " )" );
50 rm5248 99
                        System.err.println( "    " + e.getMessage() );
100
                        JOptionPane.showMessageDialog( null, "ERROR: No Such Port( " + portToOpen + ")\n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );
101
                        return;
12 rm5248 102
                } catch (NotASerialPortException e) {
103
                        System.err.println( "ERROR: Not a serial port( " + portToOpen + " )" );
50 rm5248 104
                        System.err.println( "    " + e.getMessage() );
105
                        JOptionPane.showMessageDialog( null, "ERROR: Not a serial port( " + portToOpen + ")", "Error", JOptionPane.ERROR_MESSAGE );
106
                        return;
12 rm5248 107
                }
17 rm5248 108
 
12 rm5248 109
                portInput = thePort.getInputStream();
110
                portOutput = thePort.getOutputStream();
41 rm5248 111
 
22 rm5248 112
                new Thread( this, "Reading Thread" ).start();
41 rm5248 113
 
37 rm5248 114
                thePort.setSerialChangeListener( new SerialChangeListener() {
41 rm5248 115
 
37 rm5248 116
                        @Override
117
                        public void serialStateChanged(SerialLineState state) {
39 rm5248 118
                                portStatus.setLineState( state );
37 rm5248 119
                        }
120
                });
64 rm5248 121
 
122
                SerialLineState newState = new SerialLineState();
123
                newState.dataTerminalReady = true;
124
                newState.requestToSend = true;
125
 
126
                thePort.setSerialLineState( newState );
41 rm5248 127
 
39 rm5248 128
                try {
129
                        portStatus.setLineState( thePort.getSerialLineState() );
130
                } catch (IOException e) {
131
                        // TODO Auto-generated catch block
132
                        e.printStackTrace();
133
                }
41 rm5248 134
 
50 rm5248 135
                updatePortInformation();
64 rm5248 136
 
39 rm5248 137
                /*new Thread( new Runnable() {
41 rm5248 138
 
37 rm5248 139
                        @Override
140
                        public void run() {
141
                                while( true ){
142
                                        try {
143
                                                System.out.println( thePort.getSerialLineState() );
144
                                                Thread.sleep( 1000 );
145
                                        } catch (IOException e) {
146
                                                e.printStackTrace();
147
                                        } catch (InterruptedException e) {
148
                                                // TODO Auto-generated catch block
149
                                                e.printStackTrace();
150
                                        }
151
                                }
152
                        }
153
                }).start();
41 rm5248 154
                 */
12 rm5248 155
        }
17 rm5248 156
 
12 rm5248 157
        private void makeGUI(){
19 rm5248 158
                //First let's get the fonts that we want to use
159
                try {
160
                        InputStream is = this.getClass().getResourceAsStream( "/fonts/LiberationMono-Regular.ttf" );
161
                        monoFont = Font.createFont( Font.TRUETYPE_FONT, is );
162
                        monoFont = monoFont.deriveFont( 18.0f );
163
                } catch ( Exception e ){
164
                        monoFont = new Font( "monospaced", Font.PLAIN, 18 );
165
                }
21 rm5248 166
 
19 rm5248 167
                try{
168
                        InputStream is = this.getClass().getResourceAsStream( "/fonts/LiberationSans-Regular.ttf" );
169
                        sansFont = Font.createFont( Font.TRUETYPE_FONT, is );
170
                        sansFont = sansFont.deriveFont( 12.0f );
171
                }catch( Exception e){
172
                        sansFont = new Font( "serif", Font.PLAIN, 12 );
173
                }
21 rm5248 174
 
12 rm5248 175
                theFrame = new JFrame( "JavaTerminal" );
17 rm5248 176
 
12 rm5248 177
                JPanel mainPanel = new JPanel( new BorderLayout() );
17 rm5248 178
 
12 rm5248 179
                JPanel statusPanel = new JPanel( new BorderLayout() );
19 rm5248 180
                statusPanel.add( portInfoLeft = new JLabel(), BorderLayout.WEST );
39 rm5248 181
                statusPanel.add( portStatus = new LineIndicatorPanel(), BorderLayout.EAST );
12 rm5248 182
                statusPanel.setPreferredSize( new Dimension( 20, 20 ) );
17 rm5248 183
 
19 rm5248 184
                portInfoLeft.setFont( sansFont );
12 rm5248 185
                portInfoLeft.setForeground( Color.DARK_GRAY );
17 rm5248 186
 
12 rm5248 187
                text = new JTextArea();
188
                text.setBackground( Color.BLACK );
189
                text.setForeground( Color.LIGHT_GRAY );
19 rm5248 190
 
191
                text.setFont( monoFont );
17 rm5248 192
                text.setColumns( 80 );
19 rm5248 193
                text.setEditable( false );
194
                text.addKeyListener( this );
16 rm5248 195
 
196
                JScrollPane scrollPane = new JScrollPane( text );
197
                scrollPane.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS );
19 rm5248 198
                scrollPane.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED );
16 rm5248 199
                mainPanel.add( scrollPane );
12 rm5248 200
                mainPanel.add( statusPanel, BorderLayout.SOUTH );
21 rm5248 201
 
19 rm5248 202
                //Make our menus
203
                JMenuBar menuBar = new JMenuBar();
21 rm5248 204
                //Make our file menu
19 rm5248 205
                JMenu fileMenu = new JMenu( "File" );
206
                fileMenu.setMnemonic( KeyEvent.VK_F );
207
                JMenuItem exitItem = new JMenuItem( "Exit" );
208
                exitItem.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_Q, KeyEvent.VK_ALT ) );
209
                exitItem.addActionListener( new ActionListener() {
21 rm5248 210
 
19 rm5248 211
                        @Override
212
                        public void actionPerformed(ActionEvent e) {
213
                                System.exit( 0 );
214
                        }
215
                });
216
                fileMenu.add( exitItem );
217
                menuBar.add( fileMenu );
21 rm5248 218
                //Make config menu
19 rm5248 219
                JMenu configMenu = new JMenu( "Configuration" );
220
                configMenu.setMnemonic( KeyEvent.VK_C );
21 rm5248 221
                JMenuItem port = new JMenuItem( "Port" );
222
                port.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_S, KeyEvent.VK_ALT ) );
22 rm5248 223
                port.addActionListener( new ActionListener() {
41 rm5248 224
 
22 rm5248 225
                        @Override
226
                        public void actionPerformed(ActionEvent arg0) {
227
                                JFrame settingFrame = new JFrame( "Configuration" );
64 rm5248 228
 
41 rm5248 229
                                JPanel mainPanel = new JPanel();
230
 
22 rm5248 231
                                JPanel configPanel = new JPanel( new GridLayout( 4, 3 ) );
232
                                configPanel.setBorder( BorderFactory.createTitledBorder( "Serial port") );
233
                                configPanel.add( createDialogLabel( "Port:" ) );
234
                                configPanel.add( createDialogLabel( "Speed:" ) );
235
                                configPanel.add( createDialogLabel( "Parity:" ) );
41 rm5248 236
                                final JComboBox port = new JComboBox();
22 rm5248 237
                                port.setEditable( true );
64 rm5248 238
                                if( thePort != null ){
239
                                        port.addItem( thePort.getPortName() );
240
                                }
22 rm5248 241
                                configPanel.add( port );
41 rm5248 242
                                final JComboBox speed = new JComboBox();
22 rm5248 243
                                BaudRate[] values = BaudRate.values();
244
                                for( int x = 0; x < values.length; x++ ){
245
                                        speed.addItem( values[ x ] );
64 rm5248 246
                                        if( thePort != null ){
247
                                                if( thePort.getBaudRate() == values[ x ] ){
248
                                                        speed.setSelectedIndex( x );
249
                                                }
22 rm5248 250
                                        }
251
                                }
252
                                speed.setEditable( false );
253
                                configPanel.add( speed );
41 rm5248 254
                                final JComboBox parity = new JComboBox();
22 rm5248 255
                                Parity[] parityValues = Parity.values();
256
                                for( int x = 0; x < parityValues.length; x++ ){
257
                                        parity.addItem( parityValues[ x ] );
64 rm5248 258
                                        if( thePort != null ){
259
                                                if( thePort.getParity() == parityValues[ x ] ){
260
                                                        parity.setSelectedIndex( x );
261
                                                }
22 rm5248 262
                                        }
263
                                }
264
                                parity.setEditable( false );
265
                                configPanel.add( parity );
266
                                configPanel.add( createDialogLabel( "Bits:" ) );
267
                                configPanel.add( createDialogLabel( "Stopbits:" ) );
268
                                configPanel.add( createDialogLabel( "Flow control:" ) );
41 rm5248 269
                                final JComboBox bits = new JComboBox();
22 rm5248 270
                                DataBits[] dataValues = DataBits.values();
271
                                for( int x = 0; x < dataValues.length; x++ ){
272
                                        bits.addItem( dataValues[ x ] );
64 rm5248 273
                                        if( thePort != null ){
274
                                                if( thePort.getDataBits() == dataValues[ x ] ){
275
                                                        bits.setSelectedIndex( x );
276
                                                }
22 rm5248 277
                                        }
278
                                }
279
                                configPanel.add( bits );
41 rm5248 280
                                final JComboBox stopbits = new JComboBox();
22 rm5248 281
                                StopBits[] stopValues = StopBits.values();
282
                                for( int x = 0; x < stopValues.length; x++ ){
283
                                        stopbits.addItem( stopValues[ x ] );
64 rm5248 284
                                        if( thePort != null ){
285
                                                if( thePort.getStopBits() == stopValues[ x ] ){
286
                                                        stopbits.setSelectedIndex( x );
287
                                                }
22 rm5248 288
                                        }
289
                                }
290
                                configPanel.add( stopbits );
41 rm5248 291
                                final JComboBox flow = new JComboBox();
22 rm5248 292
                                FlowControl[] flowValues = FlowControl.values();
293
                                for( int x = 0; x < flowValues.length; x++ ){
294
                                        flow.addItem( flowValues[ x ] );
64 rm5248 295
                                        if( thePort != null ){
296
                                                if( thePort.getFlowControl() == flowValues[ x ] ){
297
                                                        flow.setSelectedIndex( x );
298
                                                }
22 rm5248 299
                                        }
300
                                }
301
                                configPanel.add( flow );
64 rm5248 302
 
41 rm5248 303
                                JPanel bottomPanel = new JPanel();
304
                                JButton applyButton = new JButton( "Apply" );
305
                                applyButton.addActionListener( new ActionListener() {
64 rm5248 306
 
41 rm5248 307
                                        @Override
308
                                        public void actionPerformed(ActionEvent e) {
64 rm5248 309
                                                if( thePort == null || !thePort.getPortName().equals( port.getSelectedItem().toString() ) ){
310
                                                        if( thePort != null ){
311
                                                                thePort.close();
312
                                                        }
313
 
41 rm5248 314
                                                        try {
315
                                                                thePort = new SerialPort( port.getName(), true );
316
                                                        } catch (NoSuchPortException e1) {
317
                                                                JOptionPane.showMessageDialog( null, "ERROR: " + port.getName() + " does not exist!", "Error", JOptionPane.ERROR_MESSAGE );
318
                                                                return;
319
                                                        } catch (NotASerialPortException e1) {
320
                                                                JOptionPane.showMessageDialog( null, "ERROR: " + port.getName() + " is not a serial port!", "Error", JOptionPane.ERROR_MESSAGE );
321
                                                                return;
322
                                                        }
64 rm5248 323
 
41 rm5248 324
                                                        portInput = thePort.getInputStream();
325
                                                        portOutput = thePort.getOutputStream();
326
 
327
                                                        try {
328
                                                                portStatus.setLineState( thePort.getSerialLineState() );
329
                                                        } catch (IOException ex) {
330
                                                                // TODO Auto-generated catch block
331
                                                                ex.printStackTrace();
332
                                                        }
333
                                                }
64 rm5248 334
 
41 rm5248 335
                                                BaudRate[] values = BaudRate.values();
336
                                                for( int x = 0; x < values.length; x++ ){
337
                                                        if( values[ x ].toString().equals( speed.getSelectedItem().toString() ) ){
338
                                                                thePort.setBaudRate( values[ x ] );
339
                                                        }
340
                                                }
64 rm5248 341
 
41 rm5248 342
                                                Parity[] parityValues = Parity.values();
343
                                                for( int x = 0; x < parityValues.length; x++ ){
344
                                                        if( parityValues[ x ].toString().equals( parity.getSelectedItem().toString() ) ){
345
                                                                thePort.setParity( parityValues[ x ] );
346
                                                        }
347
                                                }
64 rm5248 348
 
41 rm5248 349
                                                DataBits[] dataValues = DataBits.values();
350
                                                for( int x = 0; x < dataValues.length; x++ ){
351
                                                        if( dataValues[ x ].equals( bits.getSelectedItem() ) ){
352
                                                                thePort.setDataSize( dataValues[ x ] );
353
                                                        }
354
                                                }
64 rm5248 355
 
41 rm5248 356
                                                StopBits[] stopValues = StopBits.values();
357
                                                for( int x = 0; x < stopValues.length; x++ ){
358
                                                        if( stopValues[ x ].equals( stopbits.getSelectedItem() ) ){
359
                                                                thePort.setStopBits( stopValues[ x ] );
360
                                                        }
361
                                                }
64 rm5248 362
 
41 rm5248 363
                                                FlowControl[] flowValues = FlowControl.values();
364
                                                for( int x = 0; x < flowValues.length; x++ ){
365
                                                        if( flowValues[ x ].equals( flow.getSelectedItem() ) ){
366
                                                                thePort.setFlowControl( flowValues[ x ] );
367
                                                        }
368
                                                }
64 rm5248 369
 
41 rm5248 370
                                                updatePortInformation();
371
                                        }
372
                                });
373
                                bottomPanel.add( applyButton );
374
 
375
                                mainPanel.add( configPanel );
376
                                mainPanel.add( bottomPanel );
377
                                settingFrame.add( mainPanel );
378
 
22 rm5248 379
                                settingFrame.setSize( 500, 300 );
380
                                settingFrame.setVisible( true );
41 rm5248 381
                                settingFrame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
22 rm5248 382
                        }
383
                });
21 rm5248 384
                configMenu.add( port );
385
                JMenuItem window = new JMenuItem( "Main Window" );
386
                configMenu.add( window );
387
                final JCheckBoxMenuItem localEchoBox = new JCheckBoxMenuItem( "Local Echo" );
388
                localEchoBox.addActionListener( new ActionListener() {
389
                        @Override
390
                        public void actionPerformed(ActionEvent e) {
391
                                localEcho = localEchoBox.isSelected();
392
                        }
393
                });
394
                localEchoBox.setSelected( localEcho );
395
                configMenu.add( localEchoBox );
396
                configMenu.add( new JSeparator() );
397
                configMenu.add( new JMenuItem( "ENTER sends: " ) );
398
                ButtonGroup newlineGroup = new ButtonGroup();
399
                JRadioButtonMenuItem crButton = new JRadioButtonMenuItem( "CR (\\r)" );
400
                JRadioButtonMenuItem nlButton = new JRadioButtonMenuItem( "NL (\\n)" );
401
                JRadioButtonMenuItem crnlButton = new JRadioButtonMenuItem( "CR NL (\\r\\n)" );
402
                newlineGroup.add( crButton );
403
                newlineGroup.add( nlButton );
404
                newlineGroup.add( crnlButton );
405
                nlButton.setSelected( true );
406
                crButton.addActionListener( new ActionListener() {
407
                        @Override
408
                        public void actionPerformed(ActionEvent arg0) {
409
                                newlines = NewlineType.CR;
410
                        }
411
                });
412
                nlButton.addActionListener( new ActionListener() {
413
                        @Override
414
                        public void actionPerformed(ActionEvent arg0) {
415
                                newlines = NewlineType.NL;
416
                        }
417
                });
418
                crnlButton.addActionListener( new ActionListener() {
419
                        @Override
420
                        public void actionPerformed(ActionEvent arg0) {
421
                                newlines = NewlineType.CRNL;
422
                        }
423
                });
424
                configMenu.add( crButton );
425
                configMenu.add( nlButton );
426
                configMenu.add( crnlButton );
427
                configMenu.add( new JSeparator() );
428
                menuBar.add( configMenu );
429
 
22 rm5248 430
                JMenu controlSigs = new JMenu( "Control Signals" );
431
                controlSigs.setMnemonic( KeyEvent.VK_S );
432
                JMenuItem sendBreak = new JMenuItem( "Send Break" );
433
                sendBreak.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_B, KeyEvent.VK_ALT ) );
434
                controlSigs.add( sendBreak );
435
                JMenuItem toggleDTR = new JMenuItem( "Toggle DTR" );
436
                toggleDTR.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_F7, KeyEvent.ALT_DOWN_MASK & KeyEvent.CTRL_DOWN_MASK ) );
437
                toggleDTR.addActionListener( new ActionListener() {
41 rm5248 438
 
22 rm5248 439
                        @Override
440
                        public void actionPerformed(ActionEvent arg0) {
41 rm5248 441
                                try{
442
                                        SerialLineState s = thePort.getSerialLineState();
443
                                        s.dataTerminalReady = !s.dataTerminalReady;
444
                                        thePort.setSerialLineState( s );
445
                                }catch( IOException e ){}
22 rm5248 446
                        }
447
                });
448
                controlSigs.add( toggleDTR );
449
                JMenuItem toggleRTS = new JMenuItem( "Toggle RTS" );
450
                toggleRTS.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_F8, KeyEvent.ALT_DOWN_MASK & KeyEvent.CTRL_DOWN_MASK ) );
41 rm5248 451
                toggleRTS.addActionListener( new ActionListener() {
64 rm5248 452
 
41 rm5248 453
                        @Override
454
                        public void actionPerformed(ActionEvent evt) {
455
                                try{
456
                                        SerialLineState s = thePort.getSerialLineState();
457
                                        s.requestToSend = !s.requestToSend;
458
                                        thePort.setSerialLineState( s );
459
                                }catch( IOException e ){}
460
                        }
461
                });
22 rm5248 462
                controlSigs.add( toggleRTS );
463
                menuBar.add( controlSigs );
41 rm5248 464
 
22 rm5248 465
                JMenu view = new JMenu( "View" );
466
                view.setMnemonic( KeyEvent.VK_V );
467
                ButtonGroup asciiHexGroup = new ButtonGroup();
468
                JRadioButtonMenuItem ascii = new JRadioButtonMenuItem( "ASCII" );
469
                ascii.setSelected( true );
470
                asciiHexGroup.add( ascii );
471
                view.add( ascii );
472
                JRadioButtonMenuItem hex = new JRadioButtonMenuItem( "Hex" );
473
                asciiHexGroup.add( hex );
474
                view.add( hex );
475
                JMenu hexCharsSubMenu = new JMenu( "Hexadecimal chars" );
476
                hexCharsSubMenu.setEnabled( false );
477
                JMenuItem eightChars = new JMenuItem( "8" );
478
                hexCharsSubMenu.add( eightChars );
479
                JMenuItem tenChars = new JMenuItem( "10" );
480
                hexCharsSubMenu.add( tenChars );
481
                JMenuItem sixteenChars = new JMenuItem( "16" );
482
                hexCharsSubMenu.add( sixteenChars );
483
                JMenuItem twentyFourChars = new JMenuItem( "24" );
484
                hexCharsSubMenu.add( twentyFourChars );
485
                JMenuItem thirtyTwooChars = new JMenuItem( "32" );
486
                hexCharsSubMenu.add( thirtyTwooChars );
487
                view.add( hexCharsSubMenu );
488
                JMenuItem showIndex = new JMenuItem( "Show Index" );
489
                showIndex.setEnabled( false );
490
                view.add( showIndex );
491
                view.addSeparator();
492
                JMenuItem sendHexData = new JMenuItem( "Send Hex Data" );
493
                view.add( sendHexData );
494
                menuBar.add( view );
21 rm5248 495
 
64 rm5248 496
                JMenu help = new JMenu( "Help" );
497
                help.setMnemonic( KeyEvent.VK_H );
498
                JMenuItem about = new JMenuItem( "About" );
499
                about.addActionListener( new ActionListener() {
500
 
501
                        @Override
502
                        public void actionPerformed(ActionEvent e) {
503
                                JOptionPane.showMessageDialog( null, "JavaTerminal 0.X\n" +
504
                                                "From programming.rm5248.com\n\n\n" +
505
                                                "Java Serial version: " + String.format( "%d.%d", SerialPort.getMajorVersion(), SerialPort.getMinorVersion() ) + "\n"+
506
                                                "Java Serial Native Version: " + String.format( "%d.%d", SerialPort.getMajorNativeVersion(), SerialPort.getMinorNativeVersion() ) + "\n", "About", JOptionPane.INFORMATION_MESSAGE );
507
                        }
508
                });
509
                help.add( about );
510
                menuBar.add( help );
511
 
19 rm5248 512
                //add everything to the frame
513
                theFrame.setJMenuBar( menuBar );
12 rm5248 514
                theFrame.add( mainPanel );
515
                theFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
516
                theFrame.setVisible( true );
17 rm5248 517
 
16 rm5248 518
                //Let's figure out how wide we should be in order to be 80 characters wide
519
                //We can only do this after the frame is visible.
520
                //85 characters wide because of the width of the window and scroll bar
521
                int width = 0;
19 rm5248 522
                FontMetrics font = text.getGraphics().getFontMetrics( monoFont );
16 rm5248 523
                width = font.charWidth( 'a' ) * 85;
17 rm5248 524
 
16 rm5248 525
                theFrame.setSize( width, 600 );
64 rm5248 526
 
19 rm5248 527
                updatePortInformation();
12 rm5248 528
        }
529
 
530
        /**
531
         * @param args
532
         */
533
        public static void main(String[] args) {
534
                //Make defaults, then parse our arguments
535
                BaudRate baud = BaudRate.B9600;
536
                DataBits data = DataBits.DATABITS_8;
537
                StopBits stop = StopBits.STOPBITS_1;
538
                Parity parity = Parity.NONE;
539
                FlowControl flow = FlowControl.NONE;
540
                String portToOpen;
17 rm5248 541
                boolean echo = false;
22 rm5248 542
                boolean justOpen = false;
17 rm5248 543
 
12 rm5248 544
                if( System.getProperty( "os.name" ).toLowerCase().indexOf( "win" ) >= 0 ){
545
                        portToOpen = "COM1";
546
                }else{
547
                        portToOpen = "/dev/ttyS0";
548
                }
17 rm5248 549
 
12 rm5248 550
                for( int x = 0; x < args.length; x++ ){
551
                        if( args[ x ].equals( "--help" ) ||
552
                                        args[ x ].equals( "-h" ) ){
553
                                //Print out help
554
                                System.out.println( "JavaTerminal" );
555
                                System.out.println();
556
                                System.out.println( "Program Homepage: http://www.rm5248.com/JavaSerial" );
557
                                System.out.println();
558
                                System.out.println( "Command Line Options: " );
559
                                System.out.println( "--help or -h : This help screen" );
560
                                System.out.println( "--port=<port> or -p : Device to open (Default: " + portToOpen + ")" );
561
                                System.out.println( "--speed=<speed> or -s : Port Speed (Default: 9600)" );
562
                                System.out.println( "--bits=<bits> or -b : Number of bits (Default: 8)" );
563
                                System.out.println( "--stopbits=<bits> or -t : Number of stop bits (Defaults: 1)" );
17 rm5248 564
                                System.out.println( "--parity=<odd|even|none> or -a : Parity (Default: None)" );
565
                                System.out.println( "--flow=<xon|cts|none> or -w : Flow Control (Default: None)" );
12 rm5248 566
                                System.out.println( "--echo or -e : Switch on local echo" );
22 rm5248 567
                                System.out.println( "--open or -o : Open the serial port, do not change settings" );
568
                                System.exit( 0 );
17 rm5248 569
                        }else if( args[ x ].startsWith( "--port=" ) ){
570
                                portToOpen = args[ x ].substring( args[ x ].indexOf( '=' ) + 1 );
571
                        }else if( args[ x ].equals( "-p" ) && x < args.length ){
572
                                portToOpen = args[ ++x ];
573
                        }else if( args[ x ].startsWith( "--speed=" ) ){
574
                                int speed = 9600;
575
 
576
                                try{
577
                                        speed = Integer.parseInt( args[ x ].substring( args[ x ].indexOf( '=' ) + 1 ) );
578
                                }catch( Exception e ){
579
                                        System.err.println( "ERROR: Speed was incorrect, assuming 9600" );
580
                                        speed = 9600;
581
                                }
582
 
583
                                switch( speed ){
584
                                case 0     :  baud = BaudRate.B0     ; break;
585
                                case 50    :  baud = BaudRate.B50    ; break;
586
                                case 75    :  baud = BaudRate.B75    ; break;
587
                                case 110   :  baud = BaudRate.B110   ; break;
588
                                case 134   :  baud = BaudRate.B134   ; break;
589
                                case 150   :  baud = BaudRate.B150   ; break;
590
                                case 200   :  baud = BaudRate.B200   ; break;
591
                                case 300   :  baud = BaudRate.B300   ; break;
592
                                case 600   :  baud = BaudRate.B600   ; break;
593
                                case 1200  :  baud = BaudRate.B1200  ; break;
594
                                case 1800  :  baud = BaudRate.B1800  ; break;
595
                                case 2400  :  baud = BaudRate.B2400  ; break;
596
                                case 4800  :  baud = BaudRate.B4800  ; break;
597
                                case 9600  :  baud = BaudRate.B9600  ; break;
598
                                case 38400 :  baud = BaudRate.B38400 ; break;
599
                                case 115200:  baud = BaudRate.B115200; break;
600
                                default:
601
                                        System.err.println( "ERROR: Speed was incorrect, assuming 9600" );
602
                                        baud = BaudRate.B9600;
603
                                }
604
                        }else if( args[ x ].equals( "-s" ) ){
605
                                int speed = 9600;
606
 
607
                                try{
608
                                        speed = Integer.parseInt( args[ ++x ] );
609
                                }catch( Exception e ){
610
                                        System.err.println( "ERROR: Speed was incorrect, assuming 9600" );
611
                                        speed = 9600;
612
                                }
613
 
614
                                switch( speed ){
615
                                case 0     :  baud = BaudRate.B0     ; break;
616
                                case 50    :  baud = BaudRate.B50    ; break;
617
                                case 75    :  baud = BaudRate.B75    ; break;
618
                                case 110   :  baud = BaudRate.B110   ; break;
619
                                case 134   :  baud = BaudRate.B134   ; break;
620
                                case 150   :  baud = BaudRate.B150   ; break;
621
                                case 200   :  baud = BaudRate.B200   ; break;
622
                                case 300   :  baud = BaudRate.B300   ; break;
623
                                case 600   :  baud = BaudRate.B600   ; break;
624
                                case 1200  :  baud = BaudRate.B1200  ; break;
625
                                case 1800  :  baud = BaudRate.B1800  ; break;
626
                                case 2400  :  baud = BaudRate.B2400  ; break;
627
                                case 4800  :  baud = BaudRate.B4800  ; break;
628
                                case 9600  :  baud = BaudRate.B9600  ; break;
629
                                case 38400 :  baud = BaudRate.B38400 ; break;
630
                                case 115200:  baud = BaudRate.B115200; break;
631
                                default:
632
                                        System.err.println( "ERROR: Speed was incorrect, assuming 9600" );
633
                                        baud = BaudRate.B9600;
634
                                }
635
                        }else if( args[ x ].startsWith( "--bits=" ) ){
636
                                int bits = 8;
637
 
638
                                try{
639
                                        bits = Integer.parseInt( args[ x ].substring( args[ x ].indexOf( '=' ) + 1 ) );
640
                                }catch( Exception e ){
641
                                        System.err.println( "ERROR: Bits were incorrect, assuming 8" );
642
                                        bits = 8;
643
                                }
644
 
645
                                switch( bits ){
646
                                case 8:
647
                                        data = DataBits.DATABITS_8; break;
648
                                case 7:
649
                                        data = DataBits.DATABITS_7; break;
650
                                case 6:
651
                                        data = DataBits.DATABITS_6; break;
652
                                case 5:
653
                                        data = DataBits.DATABITS_5; break;
654
                                default:
655
                                        data = DataBits.DATABITS_8;
656
                                }
657
 
658
                        }else if( args[ x ].equals( "-b" ) ){
659
                                int bits = 8;
660
 
661
                                try{
662
                                        bits = Integer.parseInt( args[ ++x ] );
663
                                }catch( Exception e ){
664
                                        System.err.println( "ERROR: Bits were incorrect, assuming 8" );
665
                                        bits = 8;
666
                                }
667
 
668
                                switch( bits ){
669
                                case 8:
670
                                        data = DataBits.DATABITS_8; break;
671
                                case 7:
672
                                        data = DataBits.DATABITS_7; break;
673
                                case 6:
674
                                        data = DataBits.DATABITS_6; break;
675
                                case 5:
676
                                        data = DataBits.DATABITS_5; break;
677
                                default:
678
                                        data = DataBits.DATABITS_8;
679
                                }
680
                        }else if( args[ x ].startsWith( "--stopbits=" ) ){
681
                                int stopBits = 1;
682
 
683
                                try{
684
                                        stopBits = Integer.parseInt( args[ x ].substring( args[ x ].indexOf( '=' ) + 1 ) );
685
                                }catch( Exception e ){
686
                                        System.err.println( "ERROR: StopBits were incorrect, assuming 1" );
687
                                        stopBits = 1;
688
                                }
689
 
690
                                switch( stopBits ){
691
                                case 2:
692
                                        stop = StopBits.STOPBITS_2; break;
693
                                case 1:
694
                                        stop = StopBits.STOPBITS_1; break;
695
                                default:
696
                                        stop = StopBits.STOPBITS_1;
697
                                        System.err.println( "ERROR: StopBits were incorrect, assuming 1" );
698
                                }
699
                        }else if( args[ x ].equals( "-t" ) ){
700
                                int stopBits = 1;
701
 
702
                                try{
703
                                        stopBits = Integer.parseInt( args[ ++x ] );
704
                                }catch( Exception e ){
705
                                        System.err.println( "ERROR: StopBits were incorrect, assuming 1" );
706
                                        stopBits = 1;
707
                                }
708
 
709
                                switch( stopBits ){
710
                                case 2:
711
                                        stop = StopBits.STOPBITS_2; break;
712
                                case 1:
713
                                        stop = StopBits.STOPBITS_1; break;
714
                                default:
715
                                        stop = StopBits.STOPBITS_1;
716
                                        System.err.println( "ERROR: StopBits were incorrect, assuming 1" );
717
                                }
718
                        }else if( args[ x ].startsWith( "--parity=" ) ){
33 rm5248 719
                                String parityName = args[ x ].substring( args[ x ].indexOf( '=' ) + 1 );
19 rm5248 720
 
17 rm5248 721
                                if( parityName.equals( "odd" ) ){
722
                                        parity = Parity.ODD;
723
                                }else if( parityName.equals( "none" ) ){
724
                                        parity = Parity.NONE;
725
                                }else if( parityName.equals( "even" ) ){
726
                                        parity = Parity.EVEN;
727
                                }else{
728
                                        System.err.println( "ERROR: Parity was incorrect, assuming none" );
729
                                }
730
                        }else if( args[ x ].equals( "-a" ) ){
731
                                String parityName = args[ ++x ];
19 rm5248 732
 
17 rm5248 733
                                if( parityName.equals( "odd" ) ){
734
                                        parity = Parity.ODD;
735
                                }else if( parityName.equals( "none" ) ){
736
                                        parity = Parity.NONE;
737
                                }else if( parityName.equals( "even" ) ){
738
                                        parity = Parity.EVEN;
739
                                }else{
740
                                        System.err.println( "ERROR: Parity was incorrect, assuming none" );
741
                                }
742
                        }else if( args[ x ].startsWith( "--flow=" ) ){
33 rm5248 743
                                String flowName = args[ x ].substring( args[ x ].indexOf( '=' ) + 1 );
19 rm5248 744
 
17 rm5248 745
                                if( flowName.equals( "xon" ) ){
746
                                        flow = FlowControl.SOFTWARE;
747
                                }else if( flowName.equals( "cts" ) ){
748
                                        flow = FlowControl.HARDWARE;
749
                                }else if( flowName.equals( "none" ) ){
750
                                        flow = FlowControl.NONE;
751
                                }else{
752
                                        System.err.println( "ERROR: Flow Control was incorrect, assuming none" );
753
                                }
754
                        }else if( args[ x ].equals( "-w" ) ){
755
                                String flowName = args[ ++x ];
19 rm5248 756
 
17 rm5248 757
                                if( flowName.equals( "xon" ) ){
758
                                        flow = FlowControl.SOFTWARE;
759
                                }else if( flowName.equals( "cts" ) ){
760
                                        flow = FlowControl.HARDWARE;
761
                                }else if( flowName.equals( "none" ) ){
762
                                        flow = FlowControl.NONE;
763
                                }else{
764
                                        System.err.println( "ERROR: Flow Control was incorrect, assuming none" );
765
                                }
766
                        }else if( args[ x ].equals( "--echo" ) || args[ x ].equals( "-e" ) ){
767
                                echo = true;
22 rm5248 768
                        }else if( args[ x ].equals( "--open" ) || args[ x ].equals( "-o" ) ){
769
                                justOpen = true;
12 rm5248 770
                        }
17 rm5248 771
                } // end for loop
12 rm5248 772
 
22 rm5248 773
                new JavaTerminal( portToOpen, baud, data, stop, parity, flow, echo, justOpen );
12 rm5248 774
        }
775
 
19 rm5248 776
        @Override
777
        public void keyPressed(KeyEvent arg0) {}
778
 
779
        @Override
780
        public void keyReleased(KeyEvent arg0) {}
781
 
782
        @Override
21 rm5248 783
        public void keyTyped(KeyEvent event) {
784
                String toWrite = "";
64 rm5248 785
 
50 rm5248 786
                if( portOutput == null ){
787
                        return;
788
                }
21 rm5248 789
 
19 rm5248 790
                if( localEcho ){
21 rm5248 791
                        appendCharacter( event.getKeyChar() );
19 rm5248 792
                }
21 rm5248 793
 
794
                if( event.getKeyCode() == KeyEvent.VK_ENTER ){
795
                        if( newlines == NewlineType.NL ){
796
                                toWrite = "\n";
797
                        }else if( newlines == NewlineType.CR ){
798
                                toWrite = "\r";
799
                        }else if( newlines == NewlineType.CRNL ){
800
                                toWrite = "\r\n";
801
                        }
802
                }else{
803
                        toWrite = new String( event.getKeyChar() + "" );
804
                }
41 rm5248 805
 
19 rm5248 806
                try {
21 rm5248 807
                        portOutput.write( toWrite.getBytes() );
19 rm5248 808
                } catch (IOException e) {
809
                        e.printStackTrace();
810
                }
811
        }
812
 
813
        private void appendCharacter( char c ){
814
                try {
815
                        String lastLine = text.getText().substring( text.getLineStartOffset( text.getLineCount() - 1 ) );
816
                        if( lastLine.length() == 80 ){
817
                                text.append( NEWLINE );
818
                        }
819
                } catch (BadLocationException e) {}
820
 
41 rm5248 821
 
22 rm5248 822
                if( c == '\n' || c == '\r' ){
823
                        text.append( NEWLINE );
824
                }else{
825
                        text.append( c + "" );
826
                }
19 rm5248 827
        }
21 rm5248 828
 
19 rm5248 829
        /**
830
         * Update the information in the lower left corner.
831
         */
832
        private void updatePortInformation(){
21 rm5248 833
                int myRate = 0;
834
                int dataBits = 0;
835
                char parity = 'N';
836
                int stop = 0;
64 rm5248 837
 
50 rm5248 838
                if( thePort == null ){
839
                        portInfoLeft.setText( "No open port" );
840
                        return;
841
                }
21 rm5248 842
                String txt = thePort.getPortName() + " : ";
41 rm5248 843
 
21 rm5248 844
                switch( thePort.getBaudRate() ){
845
                case B0     :  myRate = 0; break;
846
                case B50    :  myRate = 50; break;
847
                case B75    :  myRate = 75; break;
848
                case B110   :  myRate = 110; break;
849
                case B134   :  myRate = 134; break;
850
                case B150   :  myRate = 150; break;
851
                case B200   :  myRate = 200; break;
852
                case B300   :  myRate = 300; break;
853
                case B600   :  myRate = 600; break;
854
                case B1200  :  myRate = 1200; break;
855
                case B1800  :  myRate = 1800; break;
856
                case B2400  :  myRate = 2400; break;
857
                case B4800  :  myRate = 4800; break;
858
                case B9600  :  myRate = 9600; break;
859
                case B38400 :  myRate = 38400; break;
860
                case B115200:  myRate = 115200; break;
861
                }
41 rm5248 862
 
21 rm5248 863
                switch( thePort.getDataBits() ){
864
                case DATABITS_5: dataBits = 5; break;
865
                case DATABITS_6: dataBits = 6; break;
866
                case DATABITS_7: dataBits = 7; break;
867
                case DATABITS_8: dataBits = 8; break;
868
                }
41 rm5248 869
 
21 rm5248 870
                switch( thePort.getParity() ){
871
                case NONE: parity = 'N'; break;
872
                case ODD: parity = 'O'; break;
873
                case EVEN: parity = 'E'; break;
874
                }
41 rm5248 875
 
21 rm5248 876
                switch( thePort.getStopBits() ){
877
                case STOPBITS_1: stop = 1; break;
878
                case STOPBITS_2: stop = 2; break;
879
                }
41 rm5248 880
 
21 rm5248 881
                txt += myRate + ",";
882
                txt += dataBits + ",";
883
                txt += parity + ",";
884
                txt += stop;
885
 
19 rm5248 886
                portInfoLeft.setText( txt );
887
        }
888
 
21 rm5248 889
        @Override
890
        public void run() {
891
                while( true ){
892
                        try {
893
                                appendCharacter( (char)portInput.read() );
894
                        } catch (IOException e) {
895
                                e.printStackTrace();
896
                        }
897
                }
41 rm5248 898
 
21 rm5248 899
        }
41 rm5248 900
 
22 rm5248 901
        private JLabel createDialogLabel( String title ){
902
                JLabel lbl = new JLabel( title );
903
                lbl.setFont( this.sansFont );
904
                lbl.setAlignmentY( JLabel.CENTER_ALIGNMENT );
905
                return lbl;
906
        }
21 rm5248 907
 
12 rm5248 908
}