Snapshot before changing swt list to comboviewer
[FinalKeyGui.git] / src / fkgui / MainWin.java
1 package fkgui;
2
3
4 import java.util.Iterator;
5 import java.util.concurrent.CountDownLatch;
6 import  java.util.prefs.*;
7 import java.awt.*;
8 import java.awt.event.ActionEvent;
9 import java.awt.event.ActionListener;
10 import java.beans.PropertyChangeEvent;
11 import java.beans.PropertyChangeListener;
12
13 import javax.swing.UIManager;
14 import javax.swing.UnsupportedLookAndFeelException;
15
16 import org.eclipse.swt.widgets.Display;
17 import org.eclipse.swt.widgets.Event;
18 import org.eclipse.swt.widgets.Listener;
19 import org.eclipse.swt.widgets.MessageBox;
20 import org.eclipse.swt.widgets.Shell;
21 import org.eclipse.swt.widgets.Button;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.events.ModifyEvent;
24 import org.eclipse.swt.events.ModifyListener;
25 import org.eclipse.swt.events.SelectionAdapter;
26 import org.eclipse.swt.events.SelectionEvent;
27 import org.eclipse.swt.events.SelectionListener;
28 import org.eclipse.swt.events.ShellEvent;
29 import org.eclipse.swt.events.ShellListener;
30 import org.eclipse.swt.widgets.Text;
31 import org.eclipse.swt.widgets.Label;
32 import org.eclipse.swt.widgets.Control;
33 import org.eclipse.wb.swt.SWTResourceManager;
34
35 import fkgui.SerialWorker.SerialState;
36 import fkgui.UpdateChecker.AutoUpdaterResultListener;
37
38 import org.eclipse.swt.widgets.TabFolder;
39 import org.eclipse.swt.widgets.TabItem;
40 import org.eclipse.swt.widgets.Composite;
41 import org.eclipse.swt.layout.FillLayout;
42 import org.eclipse.swt.layout.GridLayout;
43 import org.eclipse.swt.layout.FormLayout;
44 import org.eclipse.swt.layout.FormData;
45 import org.eclipse.swt.layout.FormAttachment;
46 import org.eclipse.swt.widgets.List;
47
48
49 public class MainWin implements ConsoleMsg, AutoUpdaterResultListener {
50
51         protected Shell shell;
52         private Text txtPsw;
53         public TrayIcon trayIcon;
54         public PopupMenu popup;
55         public MenuItem showMain;
56         public MenuItem hideMain;
57
58         public Text txtLog;
59         public Button btnConnect;
60         public Button chkAutoHide;
61         public Label lblPort;
62         public Label lblPassword;
63         
64         public Animation animation;
65         
66         public TabFolder tabFolder;
67
68         private Text txtDev;
69         Preferences prefs;
70         MainWin mySelf;
71         private SerialState lastState = SerialState.Disconnected;
72         
73         SerialWorker fkSerial;
74         private boolean sysTrayIconVisible;
75
76         
77         static final String PREF_PORT ="lastUsedPortPref";
78         static final String DEFAULT_DEVICE = "/dev/FinalKey";
79         static final String PREF_AUTOHIDE = "hideMainWinAfterConnect";
80         public Composite cmpConnect;
81         private Composite cmpAccounts;
82         List lstAccounts;
83  
84         
85         /**
86          * Launch the application.
87          * @param args
88          */
89         public static void main(String[] args) {
90
91                 try {
92                         MainWin window = new MainWin();
93                         window.open();
94                 } catch (Exception e) {
95                         e.printStackTrace();
96                 }
97                 
98         }
99
100         /**
101          * Open the window.
102          */
103         public void open() {
104                 Display display = Display.getDefault();
105                 createContents();
106                 shell.open();
107                 shell.layout();
108                 createSysTrayIcon();
109                 serialEvent(SerialState.Disconnected);
110                 new Thread(new UpdateChecker(this)).start();
111
112                 while (!shell.isDisposed()) {
113                         if (!display.readAndDispatch()) {
114                                 display.sleep();                                
115                         }
116                 }
117         }
118         
119         public void log( String str )
120         {
121                 txtLog.append(str+"\n");
122                 txtLog.redraw();
123                 shell.redraw();
124                 System.out.println(str);
125         }
126
127         /**
128          * Create a systemTray icon
129          */
130         private void createSysTrayIcon()
131         {
132                 sysTrayIconVisible=true;
133         //Check the SystemTray is supported
134         if (!SystemTray.isSupported()) {
135             log("SystemTray is not supported, app is useless");
136             return;
137         }
138         
139         try {
140                         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
141                 } catch (ClassNotFoundException e1) {
142                         // TODO Auto-generated catch block
143                         e1.printStackTrace();
144                 } catch (InstantiationException e1) {
145                         // TODO Auto-generated catch block
146                         e1.printStackTrace();
147                 } catch (IllegalAccessException e1) {
148                         // TODO Auto-generated catch block
149                         e1.printStackTrace();
150                 } catch (UnsupportedLookAndFeelException e1) {
151                         // TODO Auto-generated catch block
152                         e1.printStackTrace();
153                 }
154
155         popup = new PopupMenu();
156         trayIcon =
157                 new TrayIcon(Toolkit.getDefaultToolkit().createImage(getClass().getResource("finalkey.png")));
158         trayIcon.setToolTip("The Final Key - Hardware password manager");
159         trayIcon.setImageAutoSize(true);
160         final SystemTray tray = SystemTray.getSystemTray();
161        
162         // Create a pop-up menu components
163         showMain = new MenuItem("Show FinalKey");
164         hideMain = new MenuItem("Hide FinalKey");
165
166         showMain.addActionListener(new ActionListener() {
167                         @Override
168                         public void actionPerformed(ActionEvent e) {
169                                 Display.getDefault().syncExec( new Runnable(){
170                                         
171                                         public void run()
172                                         {
173                                                 showFromTray();
174                                         }
175                                 } );
176                         }
177                                 
178                 });
179         
180         hideMain.addActionListener(new ActionListener() {
181                         @Override
182                         public void actionPerformed(ActionEvent e) {
183                                 Display.getDefault().syncExec( new Runnable(){
184                                         
185                                         public void run()
186                                         {
187                                                 hideToTray();
188                                         }
189                                 } );
190                         }
191                                 
192                 });
193
194         clearSystray();
195
196
197         trayIcon.setPopupMenu(popup);
198        
199         try {
200             tray.add(trayIcon);
201         } catch (AWTException e) {
202                 log("TrayIcon could not be added.");
203         }       
204         
205         }
206         
207         private void hideToTray()
208         {
209                 popup.remove(0);
210                 popup.insert(showMain, 0);
211                 shell.setVisible(false);
212         }
213         
214         private void showFromTray()
215         {
216                 popup.remove(0);
217                 popup.insert(hideMain, 0);
218                 shell.setVisible(true);
219                 shell.forceActive();
220         }
221         
222         private void destroySysTrayIcon()
223         {
224                 sysTrayIconVisible=false;
225                 SystemTray.getSystemTray().remove(trayIcon);
226         }
227         
228         private void clearSystray() {
229                         popup.removeAll();
230                 //Add components to pop-up menu
231                         if(shell.isVisible()==true)
232                         {
233                                 popup.add(hideMain);
234                         } else {
235                                 popup.add(showMain);
236                         }
237                 popup.addSeparator();
238         }
239
240         public void shutDownApp()
241         {
242                 if(fkSerial != null)
243                 {
244                         fkSerial.disconnect();
245                 }
246                 if(sysTrayIconVisible == true)
247                 {
248                         destroySysTrayIcon();
249                 }
250                 System.exit(0);
251         }
252         
253         /**
254          * Create contents of the window.
255          */
256         protected void createContents() {
257                 shell = new Shell();
258                 shell.setImage(SWTResourceManager.getImage(MainWin.class, "/fkgui/finalkey.png"));
259                 shell.setSize(711, 655);
260                 shell.setText("Final Key (Not connected)");
261
262                 
263                 prefs = Preferences.userNodeForPackage(this.getClass());
264                 
265
266                 mySelf = this;
267                 shell.setLayout(new FormLayout());
268                 
269                 tabFolder = new TabFolder(shell, SWT.NONE);
270                 FormData fd_tabFolder = new FormData();
271                 fd_tabFolder.bottom = new FormAttachment(0, 627);
272                 fd_tabFolder.right = new FormAttachment(0, 709);
273                 fd_tabFolder.top = new FormAttachment(0);
274                 fd_tabFolder.left = new FormAttachment(0);
275                 tabFolder.setLayoutData(fd_tabFolder);
276                 tabFolder.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
277                 
278                 TabItem tbtmConnection = new TabItem(tabFolder, SWT.NONE);
279                 tbtmConnection.setText("Connection");
280                 
281                 cmpConnect = new Composite(tabFolder, SWT.BORDER);
282                 tbtmConnection.setControl(cmpConnect);
283                 cmpConnect.setLayout(new FormLayout());
284                 
285
286                 btnConnect = new Button(cmpConnect, SWT.CENTER);
287                 btnConnect.setImage(SWTResourceManager.getImage("/home/dusted/Downloads/lightning.png"));
288                 FormData fd_btnConnect = new FormData();
289                 fd_btnConnect.left = new FormAttachment(100, -125);
290                 fd_btnConnect.right = new FormAttachment(100, -10);
291                 btnConnect.setLayoutData(fd_btnConnect);
292
293                 btnConnect.addSelectionListener(new SelectionAdapter() {
294                         public void widgetSelected(SelectionEvent e) {
295                                 
296                                 if( fkSerial!=null && fkSerial.state == SerialState.Connected )
297                                 {
298                                         fkSerial.disconnect();
299                                 } else {
300                                         
301                                         prefs.putBoolean(PREF_AUTOHIDE, chkAutoHide.getSelection() );
302
303                                         fkSerial = new SerialWorker(mySelf);
304                                         prefs.put(PREF_PORT, txtDev.getText() );
305                                         fkSerial.connect(txtDev.getText(),txtPsw.getText());
306                                         txtPsw.setText("");
307                                 }
308                         }
309                 });
310                 btnConnect.setText("Connect");
311                 
312                 txtPsw = new Text(cmpConnect, SWT.BORDER | SWT.PASSWORD);
313                 fd_btnConnect.bottom = new FormAttachment(txtPsw, 0, SWT.BOTTOM);
314                 FormData fd_txtPsw = new FormData();
315                 fd_txtPsw.bottom = new FormAttachment(0, 52);
316                 fd_txtPsw.right = new FormAttachment(0, 501);
317                 fd_txtPsw.top = new FormAttachment(0, 29);
318                 fd_txtPsw.left = new FormAttachment(0, 102);
319                 txtPsw.setLayoutData(fd_txtPsw);
320                 
321                 txtLog = new Text(cmpConnect, SWT.BORDER | SWT.V_SCROLL | SWT.MULTI);
322                 FormData fd_txtLog = new FormData();
323                 fd_txtLog.left = new FormAttachment(0, 10);
324                 fd_txtLog.right = new FormAttachment(100, -10);
325                 fd_txtLog.bottom = new FormAttachment(100, -10);
326                 fd_txtLog.top = new FormAttachment(0, 58);
327                 txtLog.setLayoutData(fd_txtLog);
328                 txtLog.setEditable(false);
329                 
330                 lblPort = new Label(cmpConnect, SWT.NONE);
331                 fd_btnConnect.top = new FormAttachment(lblPort, 0, SWT.TOP);
332                 FormData fd_lblPort = new FormData();
333                 fd_lblPort.right = new FormAttachment(0, 86);
334                 fd_lblPort.top = new FormAttachment(0);
335                 fd_lblPort.left = new FormAttachment(0, 10);
336                 lblPort.setLayoutData(fd_lblPort);
337                 lblPort.setText("Port");
338                 
339                 txtDev = new Text(cmpConnect, SWT.BORDER);
340                 FormData fd_txtDev = new FormData();
341                 fd_txtDev.bottom = new FormAttachment(0, 23);
342                 fd_txtDev.right = new FormAttachment(0, 256);
343                 fd_txtDev.top = new FormAttachment(0);
344                 fd_txtDev.left = new FormAttachment(0, 102);
345                 txtDev.setLayoutData(fd_txtDev);
346                 txtDev.setFont(SWTResourceManager.getFont("Cantarell", 9, SWT.NORMAL));
347                 txtDev.setText( prefs.get(PREF_PORT, DEFAULT_DEVICE));
348                 lblPassword = new Label(cmpConnect, SWT.NONE);
349                 FormData fd_lblPassword = new FormData();
350                 fd_lblPassword.right = new FormAttachment(0, 95);
351                 fd_lblPassword.top = new FormAttachment(0, 29);
352                 fd_lblPassword.left = new FormAttachment(0, 10);
353                 lblPassword.setLayoutData(fd_lblPassword);
354                 lblPassword.setText("Password");
355                 
356                 chkAutoHide = new Button(cmpConnect, SWT.CHECK);
357                 FormData fd_chkAutoHide = new FormData();
358                 fd_chkAutoHide.right = new FormAttachment(0, 501);
359                 fd_chkAutoHide.top = new FormAttachment(0);
360                 fd_chkAutoHide.left = new FormAttachment(0, 262);
361                 chkAutoHide.setLayoutData(fd_chkAutoHide);
362                 chkAutoHide.setText("Hide after connection");
363                 
364                 chkAutoHide.setSelection( prefs.getBoolean(PREF_AUTOHIDE, false)) ;
365                 
366                 animation = new Animation(cmpConnect, SWT.NONE, 4);
367
368                 FormData fd_animation = new FormData();
369                 fd_animation.right = new FormAttachment(0, 86);
370                 fd_animation.top = new FormAttachment(0);
371                 fd_animation.left = new FormAttachment(0, 10);          
372                 
373                 animation.setLayoutData(fd_animation);
374
375
376                 
377                 
378
379                 
380                 animation.setVisible(false);
381                 animation.addFrame( SWTResourceManager.getImage("/home/dusted/Downloads/finalkey1.png") );
382                 animation.addFrame( SWTResourceManager.getImage("/home/dusted/Downloads/finalkey2.png") );
383                 animation.setPlaying(false);
384                 cmpConnect.setTabList(new Control[]{txtPsw, btnConnect});
385                 
386         
387                 
388                 log("Type your password and press connect.\n----------\n");
389
390
391                 shell.addShellListener( new ShellListener() {
392                         
393                         public void shellIconified(ShellEvent e) {
394
395                         }
396
397                         public void shellDeiconified(ShellEvent e) {
398                                 // TODO Auto-generated method stub
399                                 
400                         }
401                         
402                         public void shellDeactivated(ShellEvent e) {
403                                 // TODO Auto-generated method stub
404                                 
405                         }
406                         
407                         public void shellClosed(ShellEvent e) {
408                                 shutDownApp();
409                         }
410                         
411                         public void shellActivated(ShellEvent e) {
412                                 // TODO Auto-generated method stub
413                                 
414                         }
415                 } );
416                 
417
418
419         }
420
421
422         @Override
423         public void serialEvent(SerialState state) {
424                 switch(state)
425                 {
426                 case Connected:
427                         shell.setText("Final Key (Connected)");
428                         
429                         animation.setVisible(false);
430                         animation.setPlaying(false);
431
432
433                         btnConnect.setText("Disconnect");
434                         btnConnect.setVisible(true);
435                         
436                         //Should we hide?
437                         if( prefs.getBoolean(PREF_AUTOHIDE, false) == true)
438                         {
439                                 hideToTray();
440                         }
441                         
442                         addAccountsTab();
443                         
444                         
445                         tabFolder.setSelection(1);
446                         
447                         for( FkManager.Account a : FkManager.getInstance().getList() )
448                         {
449                                 lstAccounts.add(a.name);
450                                 
451                                 Menu menu = new Menu(a.name+" ["+a.num+"]");
452                                 MenuItem both = new MenuItem("User + Pass");
453                                 MenuItem usr = new MenuItem("User");
454                                 MenuItem psw = new MenuItem("Pass");
455                                 menu.add(both);
456                                 menu.add(usr);
457                                 menu.add(psw);
458
459
460                                 both.addActionListener(FkManager.getInstance());
461                                 both.setActionCommand( "%"+a.num );
462
463
464
465                                 psw.addActionListener(FkManager.getInstance()); 
466                                 psw.setActionCommand( "p"+a.num);
467
468
469                                 usr.addActionListener(FkManager.getInstance()); 
470                                 usr.setActionCommand( "u"+a.num );
471
472                                 popup.add(menu);                                
473                                 
474                                 
475                         }
476                         
477                         if( lstAccounts.getItemCount() > 0 )
478                         {
479                                 trayIcon.displayMessage("FinalKey", lstAccounts.getItemCount() + " account"+(( lstAccounts.getItemCount()>1)?"s":"")+" ready.", 
480                                     TrayIcon.MessageType.INFO);
481                         }
482
483                         
484                         log("* Connected *");
485                         break;
486                 case Connecting:
487                         shell.setText("Final Key (Connecting...)");
488                         animation.setVisible(true);
489                         animation.setPlaying(true);
490
491                         txtPsw.setVisible(false);
492                         txtDev.setVisible(false);
493                         btnConnect.setVisible(false);
494                         lblPort.setVisible(false);
495                         lblPassword.setVisible(false);
496                         chkAutoHide.setVisible(false);
497                         break;
498                 case Disconnected:
499                         fkSerial=null;
500                         animation.setVisible(false);
501                         animation.setPlaying(false);
502
503                         remAccountsTab();
504                         
505                         tabFolder.setSelection(0);
506
507                         shell.setText("Final Key (Not connected)");
508                         txtPsw.setVisible(true);
509                         txtDev.setVisible(true);
510                         btnConnect.setText("Connect");
511                         btnConnect.setVisible(true);
512                         lblPort.setVisible(true);
513                         lblPassword.setVisible(true);
514                         chkAutoHide.setVisible(true);
515                         clearSystray();
516                         if(lastState != state)
517                         {
518                                 log("* Disconnected *");
519                         }
520                         break;
521                 
522                 case Working:
523                         animation.setPlaying(false);
524                         animation.setVisible(false);
525                         break;
526                         
527                 default:
528                         break;
529                 }
530                 lastState=state;
531                 cmpConnect.layout();
532         }
533
534         private void remAccountsTab() {
535                 if( tabFolder.getItemCount() > 1 )
536                 {
537                         tabFolder.getItem(1).dispose();
538                 }
539                 
540         }
541
542         private void addAccountsTab() {
543                 TabItem tbtmAccounts = new TabItem(tabFolder, SWT.NONE);
544                 tbtmAccounts.setText("Accounts");
545                 
546                 cmpAccounts = new Composite(tabFolder, SWT.BORDER);
547                 tbtmAccounts.setControl(cmpAccounts);
548                 cmpAccounts.setLayout(new FormLayout());
549                 
550                 Button btnNewAccoount = new Button(cmpAccounts, SWT.NONE);
551                 btnNewAccoount.setImage(SWTResourceManager.getImage("/home/dusted/Downloads/Button New-01.png"));
552                 btnNewAccoount.addSelectionListener(new SelectionAdapter() {
553                         @Override
554                         public void widgetSelected(SelectionEvent e) {
555                         }
556                 });
557                 FormData fd_btnNewAccoount = new FormData();
558                 fd_btnNewAccoount.left = new FormAttachment(0, 530);
559                 fd_btnNewAccoount.right = new FormAttachment(100, -10);
560                 fd_btnNewAccoount.bottom = new FormAttachment(100, -10);
561                 btnNewAccoount.setLayoutData(fd_btnNewAccoount);
562                 btnNewAccoount.setText("New Account");
563                 
564                 lstAccounts = new List(cmpAccounts, SWT.BORDER | SWT.V_SCROLL);
565                 FormData fd_lstAccounts = new FormData();
566                 fd_lstAccounts.bottom = new FormAttachment(btnNewAccoount, -6);
567                 fd_lstAccounts.top = new FormAttachment(0, 10);
568                 fd_lstAccounts.left = new FormAttachment(0, 10);
569                 fd_lstAccounts.right = new FormAttachment(100, -10);
570
571                 lstAccounts.setLayoutData(fd_lstAccounts);
572                                 
573                 lstAccounts.addListener(SWT.Selection, new Listener()
574                 {
575
576                         @Override
577                         public void handleEvent(Event event) {
578                                 System.out.println( "Selected Idx:"+lstAccounts.getSelectionIndex() );
579                                 TriggerDialog diag = new TriggerDialog(shell, shell.getStyle(), FkManager.getInstance().getList().get(lstAccounts.getSelectionIndex()) );
580
581                                 shell.setMinimized(true);
582                                 shell.setEnabled(false);
583                                 if( !((Boolean)diag.open()) )
584                                 {
585                                         shell.setMinimized(false);
586                                 }
587                                 
588                                 shell.setEnabled(true);
589                         }
590                         
591                 });
592         }
593
594
595         @Override
596         public void updateCheckFinished(AutoUpdaterResultEvent event) {
597                 switch(event.result)
598                 {
599                 case CHECK_FAILED:
600                         System.out.println("Trouble checking for updates.");
601                         break;
602                 case NO_UPDATE:
603                         System.out.println("No update avaiable at this time.");
604                         break;
605                 case UPDATE_AVAILABLE:
606                         MessageBox dialog = new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
607                         dialog.setText("FinalKey GUI Version "+event.version+" available.");
608                         dialog.setMessage("There's a new version of FinalKey GUI available.\nGo to http://cyberstalker.dk/finalkey/gui/ to download.\n\nNews:\n"+event.message);
609                         dialog.open();  
610                         break;
611                 }
612                 
613         }
614 }