add the Java Client from M0AZM
[spider.git] / SpiderConsole / src / Cluster.java
1 /**
2  * Cluster - Cluster console plugin.
3  * @author Ian Norton
4  * @verison 0.1 - 28/12/00.
5  * @see JPanel
6  * 
7  * RadioConsole.
8  *
9  * Copyright (C) 2001 Ian Norton.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public Licence as published by
13  * the Free Software Foundation; either version 2 of the Licence, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public Licence for more details.
20  *
21  * You should have received a copy of the GNU General Public Licence
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                     *
24  * Contacting the author :
25  * Ian Norton
26  * i.norton@lancaster.ac.uk
27  * http://www.lancs.ac.uk/~norton/
28  **/
29
30 import javax.swing.*;
31 import javax.swing.text.*;
32 import javax.swing.event.*;
33 import java.awt.*;
34 import java.io.*;
35 import java.awt.event.*;
36 import java.util.Hashtable ;
37 import java.util.Enumeration ;
38
39 // public class Cluster extends Plugin implements Runnable
40 class Cluster extends Plugin implements Runnable
41     {
42     // Name and tip used when creating the tabbed pane.
43     public static final String NAME = "Cluster" ;   
44     public static final String TIP = "DX Cluster Console" ;   
45     
46     // Number of commands to buffer.
47     public static final int CMDBUFFERLINES = 30 ;
48
49     // Number of lines of scrollback to buffer.
50     public static final int SCROLLBUFFERLINES = 100 ;
51
52     public static final boolean DEBUG = false ;
53
54     // Input and output streams for the plugin.
55     // private PipedInputStream pin ;
56     private BufferedReader bir ;
57     private PipedOutputStream pos ;
58
59     // User input field.
60     private JTextField tf ;
61
62     private JTextPane jtp ;
63     private Thread t ;
64     private SimpleAttributeSet attr ;
65     private LimitedStyledDocument doc ;
66
67     // Input line scrollback buffer.
68     private CommandBuffer cbuf ;
69
70     private static final String encoding = "latin1"; // "ISO8859_1";
71
72     /**
73      * Class initialiser.
74      **/
75     public Cluster()
76         {
77         super() ;
78         }   
79
80     /**
81      * Plugin initialiser.
82      * @param PipedInputStream i - Stream to read data from
83      * @param PipedOutputStream o - Stream to write data to
84      **/
85     public void init(PipedInputStream i, PipedOutputStream o)
86         {
87         // Initialise the plugin IO.
88         bir = new BufferedReader(new InputStreamReader(i)) ;
89         pos = o ;
90
91         // Initialise the ScrollingTextArea.
92         // ScrollingTextArea sta = new ScrollingTextArea(pin, SCROLLBUFFERLINES, doc) ;
93         // sta.setFont(new Font("Courier", Font.PLAIN, 10)) ;
94         // sta.setFont(new Font("Monospaced", Font.PLAIN, 10)) ;
95         // System.out.println(sta.getFont()) ;
96
97         doc = new LimitedStyledDocument(SCROLLBUFFERLINES) ;
98         jtp = new JTextPane(doc) ;
99         jtp.setEditable(false) ;
100         attr = new SimpleAttributeSet() ;
101         StyleConstants.setFontFamily(attr, "Monospaced") ;
102         StyleConstants.setFontSize(attr, 10) ;
103         jtp.setBackground(Color.black) ;
104
105         doc.addDocumentListener(new DocumentListener() {
106             public void insertUpdate(DocumentEvent e) {
107                 jtp.setCaretPosition(doc.getLength()) ;
108                 // tf.requestFocus() ;
109                 }
110             public void removeUpdate(DocumentEvent e) {
111                 }
112             public void changedUpdate(DocumentEvent e) {
113                 }
114             });
115
116         // Initialise the TextField for user input.
117         tf = new JTextField() ;
118         tf.setFont(new Font("Courier", Font.PLAIN, 10)) ;
119         Insets inset = tf.getMargin() ;
120         inset.top = inset.top + 1 ;
121         inset.bottom = inset.bottom + 1 ;
122         tf.setMargin(inset) ;
123         tf.setForeground(Color.white) ;
124         tf.setBackground(Color.black) ;
125
126         // Set the layout manager.
127         this.setLayout(new BorderLayout()) ;
128
129         // Scrollbars for scrolling text area.
130         // JScrollPane scrollpane = new JScrollPane(sta);
131         JScrollPane scrollpane = new JScrollPane(jtp);
132
133         // Add the bits to the panel.
134         this.add(scrollpane, BorderLayout.CENTER);
135         this.add(tf, BorderLayout.SOUTH);
136
137         // Initialise the command buffer.
138         cbuf = new CommandBuffer(CMDBUFFERLINES) ;
139
140         // Action listener stuff.
141         tf.addKeyListener(new KeyAdapter()
142             {
143             public void keyTyped(KeyEvent e)
144                 {
145                 // Enter key
146                 if((e.getID() == KeyEvent.KEY_TYPED) && (e.getKeyChar() == KeyEvent.VK_ENTER))
147                     {
148                     // System.out.println("Enter Event") ;
149                     send(tf.getText() + '\n') ;
150                     cbuf.addCommand(tf.getText()) ;
151                     tf.setText("") ;
152                     }
153                 }
154             public void keyPressed(KeyEvent e)
155                 {
156                 // UP Arrow
157                 if((e.getID() == KeyEvent.KEY_PRESSED) && (e.getKeyCode() == KeyEvent.VK_UP))
158                     {
159                     // System.out.println("UP Event") ;
160                     tf.setText(cbuf.getPreviousCommand()) ;
161                     tf.setCaretPosition(tf.getText().length()) ;
162                     }
163                 // DOWN Arrow
164                 if((e.getID() == KeyEvent.KEY_PRESSED) && (e.getKeyCode() == KeyEvent.VK_DOWN))
165                     {
166                     // System.out.println("DOWN Event") ;
167                     tf.setText(cbuf.getNextCommand()) ;
168                     tf.setCaretPosition(tf.getText().length()) ;
169                     }
170                 // Escape key
171                 if((e.getID() == KeyEvent.KEY_PRESSED) && (e.getKeyCode() == KeyEvent.VK_ESCAPE))
172                     {
173                     // System.out.println("ESCAPE Event") ;
174                     tf.setText("") ;                                                                }
175                 }
176             }) ;
177  
178         // Add component listener to focus text field.
179         this.addComponentListener(new ComponentAdapter() {
180             public void componentShown(ComponentEvent e) {
181                 tf.setVisible(true) ;
182                 tf.requestFocus() ;
183                 }
184             });
185         
186         // Init the scrolling thread.
187         t = new Thread(this, "Scrolling thread") ;
188         t.start() ;
189         } // End of init
190  
191     /**
192      * getTabName - Get the name that this component should show on it's tab
193      * @returns String s - Tab name
194      **/
195  
196     public String getTabName()
197         {                                                                               return NAME ;
198         }
199  
200     /**
201      * getTabTip - Get the tip that this component should show on it's tab
202      * @returns String s - Tab tip
203      **/
204     public String getTabTip()
205         {
206         return TIP ;
207         }
208  
209     /**
210      * getMenu - get the menu to add to the main menu bar.
211      * @returns JMenu
212      **/
213     public JMenu getMenu()
214         {
215         return null ;
216         }                                                                        
217     /**
218      * send - Helper function to send data out to the PipedOutputMUX
219      * @param String s - data to send.
220      **/
221     private void send(String s)
222         {
223         // System.out.println("Cluster: send got : " + s) ;
224  
225         try
226             {
227             // Write the data to the stream.
228             for(int i=0;i<s.length();i++)
229                 {
230                 pos.write(s.charAt(i)) ;
231                 }
232             }
233         catch(IOException ex)
234             {
235             System.out.println("Cluster: IOException on destination stream.") ;
236             System.out.println(ex) ;
237             }
238         }
239  
240     /**
241      * Loop continually checking to see if anything has been written to the
242      * file that is being monitored.
243      */
244     public void run()
245         {
246         String output = new String() ;
247         // Loop continually reading from the input stream
248         while(true)                                                          
249             {
250             
251             try
252                 {
253                 //while(n >= 0)
254                 //    {
255                 //    n = pin.read(b);
256                 //    if(n > 0)
257                 //        {
258                 //        output = new String(b, 0, n, encoding) ;
259                 //        display(output) ;
260                 //        // System.out.println("Read : " + output) ;
261                 //        }
262                 //    }
263                 output = bir.readLine() ;
264                 if(output != null) display(output) ;
265
266                 if(DEBUG) System.out.println("After reading a line.") ;
267                 }
268             catch(IOException ex)
269                 {
270                 System.out.println("ScrollingTextArea: IOException trying to read.") ;
271                 }
272             } // End of infinate loop.
273         } // End of run.                                                        
274
275     private void display(String s)
276         {
277         // System.out.println(s) ;
278         // Ignore Ctrl-G.
279         // s = s.replace('\r', ' ') ;
280         s = s.replace('\a', ' ') ;                                              
281
282         attr = getAttributes(s) ;
283         doc.append(s + "\n", attr) ;
284         }
285
286     private SimpleAttributeSet getAttributes(String s)
287         {
288         SimpleAttributeSet sas = attr ;
289
290         /**
291          # 0 - $foreground, $background
292          # 1 - RED, $background
293          # 2 - BROWN, $background
294          # 3 - GREEN, $background
295          # 4 - CYAN, $background
296          # 5 - BLUE, $background
297          # 6 - MAGENTA, $background
298
299         VHF DX SPOT
300          [ '^DX de [\-A-Z0-9]+:\s+([57][01]\d\d\d\.|\d\d\d\d\d\d+.)', COLOR_PAIR(1) ],
301         PROMPT
302          [ '^G0VGS de GB7MBC', COLOR_PAIR(6) ],
303         DUNNO!
304          [ '^G0VGS de', A_BOLD|COLOR_PAIR(2) ],
305         HF DX SPOT
306          [ '^DX', COLOR_PAIR(5) ],
307         ANNOUNCE
308          [ '^To', COLOR_PAIR(3) ],
309         WWV SPOT
310          [ '^WWV', COLOR_PAIR(4) ],
311         DUNNO! 
312          [ '^[-A-Z0-9]+ de [-A-Z0-9]+ \d\d-\w\w\w-\d\d\d\d \d\d\d\dZ', COLOR_PAIR(0) ],
313         DUNNO! - PROBABLY A TALK
314          [ '^[-A-Z0-9]+ de [-A-Z0-9]+ ', COLOR_PAIR(6) ],
315         WX SPOT
316          [ '^WX', COLOR_PAIR(3) ],
317         NEW MAIL
318          [ '^New mail', A_BOLD|COLOR_PAIR(4) ],
319         USER LOGIN?
320          [ '^User', COLOR_PAIR(2) ],
321         NODE LOGIN?
322          [ '^Node', COLOR_PAIR(2) ],                                  
323          **/
324
325         Hashtable h = new Hashtable() ;
326         h.put("DX de", Color.red) ;
327         h.put("M0AZM de GB7MBC", Color.magenta) ;
328         h.put("G0VGS de GB7MBC", Color.magenta) ;
329         h.put("G0VGS2 de GB7MBC", Color.magenta) ;
330         // h.put("DX", Color.blue) ;
331         h.put("To", Color.green) ;
332         h.put("WWV", Color.cyan) ;
333         h.put("WCY", Color.cyan) ;
334         // h.put("", Color.) ;
335         // h.put("", Color.) ;
336         h.put("WX", Color.green) ;
337         h.put("New mail", Color.cyan) ;
338         //h.put("User", Color.brown) ;
339         //h.put("Node", Color.brown) ;
340         h.put("User", Color.yellow) ;
341         h.put("Node", Color.orange) ;
342         
343         Enumeration e = h.keys() ;
344         
345         while(e.hasMoreElements())
346             {
347             String prefix = (String)e.nextElement() ;
348             if(s.startsWith(prefix))
349                 {
350                 StyleConstants.setForeground(sas, (Color)h.get(prefix)) ;
351                 return sas ;
352                 }
353             }
354
355         StyleConstants.setForeground(sas, Color.white) ;
356         return sas ;
357         }
358     }