d1736aa38f539fc1041bb77278c07c9ee3b59bea
[FinalKeyGui.git] / src / fkgui / MainWin.java
1 package fkgui;
2
3
4 import java.net.URI;
5 import java.util.Map;
6 import java.util.Vector;
7 import  java.util.prefs.*;
8 import java.awt.*;
9 import java.awt.event.ActionEvent;
10 import java.awt.event.ActionListener;
11
12 import javax.swing.UIManager;
13
14 import org.eclipse.jface.viewers.DoubleClickEvent;
15 import org.eclipse.jface.viewers.IDoubleClickListener;
16 import org.eclipse.jface.viewers.ISelectionChangedListener;
17 import org.eclipse.jface.viewers.ListViewer;
18 import org.eclipse.jface.viewers.SelectionChangedEvent;
19 import org.eclipse.jface.viewers.StructuredSelection;
20 import org.eclipse.swt.widgets.Display;
21 import org.eclipse.swt.widgets.Event;
22 import org.eclipse.swt.widgets.Listener;
23 import org.eclipse.swt.widgets.MessageBox;
24 import org.eclipse.swt.widgets.Shell;
25 import org.eclipse.swt.widgets.Button;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.events.FocusEvent;
28 import org.eclipse.swt.events.FocusListener;
29 import org.eclipse.swt.events.KeyEvent;
30 import org.eclipse.swt.events.KeyListener;
31 import org.eclipse.swt.events.SelectionAdapter;
32 import org.eclipse.swt.events.SelectionEvent;
33 import org.eclipse.swt.events.SelectionListener;
34 import org.eclipse.swt.events.ShellEvent;
35 import org.eclipse.swt.events.ShellListener;
36 import org.eclipse.swt.graphics.Color;
37 import org.eclipse.swt.graphics.Device;
38 import org.eclipse.swt.widgets.Text;
39 import org.eclipse.swt.widgets.Label;
40 import org.eclipse.swt.widgets.Control;
41 import org.eclipse.wb.swt.SWTResourceManager;
42
43 import fkgui.FkManager.Account;
44 import fkgui.SerialWorker.SerialState;
45 import fkgui.UpdateChecker.UpdateCheckResultListener;
46
47 import org.eclipse.swt.widgets.TabFolder;
48 import org.eclipse.swt.widgets.TabItem;
49 import org.eclipse.swt.widgets.Composite;
50 import org.eclipse.swt.layout.FormLayout;
51 import org.eclipse.swt.layout.FormData;
52 import org.eclipse.swt.layout.FormAttachment;
53 import org.eclipse.swt.layout.FillLayout;
54 import org.eclipse.swt.widgets.List;
55
56 public class MainWin implements ConsoleMsg, UpdateCheckResultListener {
57
58         protected Shell shell;
59         private Text txtPsw;
60         public TrayIcon trayIcon;
61         public PopupMenu popup;
62         public MenuItem showMain;
63         public MenuItem hideMain;
64
65         public Text txtLog;
66         public Button btnConnect;
67         public Label lblPort;
68         public Label lblPassword;
69         
70         public Animation animation;
71         
72         public TabFolder tabFolder;
73
74         private Text txtDev;
75         Preferences prefs;
76         MainWin mySelf;
77         
78         SerialWorker fkSerial;
79         private boolean sysTrayIconVisible;
80         
81         Button btnOpenAccount;
82         private Color blackColor;
83         private Color grayColor;
84         private Color defaultBgColor;
85         private Color greenColor;
86         private Color redColor;
87         
88         private static final String PREF_PORT ="lastUsedPortPref"; //$NON-NLS-1$
89         private static final String PREF_DEFAULT_DEVICE = "/dev/FinalKey"; //$NON-NLS-1$
90         private static final String PREF_AUTOHIDE = "hideMainWinAfterConnect"; //$NON-NLS-1$
91         private static final String PREF_SORT_BY_ID_KEY = "sortAccountListById"; //$NON-NLS-1$
92         private static final String PREF_SHOW_ACCOUNT_ID_IN_NAME_KEY = "showAccountIdInName"; //$NON-NLS-1$
93         private static final String PREF_ALLOW_UPDATE_CHECK = "allowUpdateCheck"; //$NON-NLS-1$
94         private static final String PREF_SHOW_ACCOUNTS_READY_NOTICE = "showAccountsReadyNotice"; //$NON-NLS-1$
95
96         public Composite cmpConnect;
97         private Composite cmpAccounts;
98         ListViewer lstAccounts;
99         private List lstAccountsControl;
100         Label lblNumFree;
101         Button btnNewAccount;
102         Button chkCheckForUpdates;
103         Boolean hiddenAtStart=false;
104         Button btnShowaccountsReady;
105  
106         //Icons
107         private org.eclipse.swt.graphics.Image iconProgramOnline  = SWTResourceManager.getImage(MainWin.class, "/fkgui/gfx/finalkey.png");  //$NON-NLS-1$
108         private org.eclipse.swt.graphics.Image iconProgramOffline  = SWTResourceManager.getImage(MainWin.class, "/fkgui/gfx/finalkey-big-offline.png");  //$NON-NLS-1$
109         private Image iconSystrayOnline = Toolkit.getDefaultToolkit().createImage(getClass().getResource("gfx/systray-color.png"));  //$NON-NLS-1$
110         private Image iconSystrayOffline= Toolkit.getDefaultToolkit().createImage(getClass().getResource("gfx/systray-offline.png"));  //$NON-NLS-1$
111
112         private TabItem tbtmAccounts;
113         private TabItem tbtmSettings;
114         private Composite cmpSettings;
115         private Button chkAutoHide;
116         private Button chkSortByAccountId;
117         private Button chkShowAccountId;
118         private Thread updateCheckThread;
119         private Text txtFilter;
120
121         
122         
123         /**
124          * Launch the application.
125          * @param args
126          */
127         public static void main(String[] args) {
128
129                 try {
130                         MainWin window = new MainWin();
131
132                         for(String s : args )
133                         {
134                                 if( s.compareTo("--hide") == 0 ) //$NON-NLS-1$
135                                 {
136                                         window.hiddenAtStart=true;
137                                 }
138                         }
139
140                         window.open();
141                 } catch (Exception e) {
142                         e.printStackTrace();
143                 }
144                 
145         }
146
147         /**
148          * Open the window.
149          */
150         public void open() {
151                 Display display = Display.getDefault();
152                 createContents();
153                 addAccountsTab();
154                 addSettingsTab();
155                 createSysTrayIcon();
156
157                 serialEvent(SerialState.Disconnected);
158                 
159                 shell.getDisplay().addFilter(SWT.KeyDown, new Listener() {
160                         
161                         @Override
162                         public void handleEvent(Event arg0) {
163                                 if( ( (arg0.stateMask&SWT.CTRL) == SWT.CTRL) && arg0.keyCode == 'f'  )
164                                 {
165                                         if( tabFolder.getItemCount() == 3 && !txtFilter.isFocusControl() )
166                                         {
167                                                 tabFolder.setSelection(1);
168                                                 txtFilter.setFocus();
169                                         }
170                                 }
171                                 
172                         }
173                 });
174
175
176                 checkForUpdates();
177
178                 if( hiddenAtStart )
179                 {
180                         hideToTray();
181                 } else {
182                         shell.open();
183                         shell.layout();
184                 }
185
186                 while (!shell.isDisposed()) {
187                         if (!display.readAndDispatch()) {
188                                 display.sleep();                                
189                         }
190                 }
191         }
192         
193         private void checkForUpdates() {
194                 if( prefs.getBoolean(PREF_ALLOW_UPDATE_CHECK, true) )
195                 {
196                         if( updateCheckThread == null )
197                         {
198                                 updateCheckThread = new Thread(new UpdateChecker(this));
199                                 updateCheckThread.start();
200                         } else {
201                                 System.out.println(Messages.MainWin_0);
202                         }
203                 } else {
204                         System.out.println(Messages.MainWin_3);
205                 }
206         }
207
208         public void log( String str )
209         {
210                 txtLog.append(str+"\n"); //$NON-NLS-1$
211                 if( tabFolder.getSelectionIndex() == 0 )
212                 {
213                         txtLog.redraw();
214                         shell.redraw();
215                 }
216                 System.out.println(str);
217
218         }
219
220         /**
221          * Create a systemTray icon
222          */
223         private void createSysTrayIcon()
224         {
225                 sysTrayIconVisible=true;
226                 //Check the SystemTray is supported
227                 if (!SystemTray.isSupported()) {
228                         log("SystemTray is not supported, app is useless"); //$NON-NLS-1$
229                         return;
230                 }
231
232                 try {
233                         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
234                 } catch (Exception e1) {
235                         e1.printStackTrace();
236                 } 
237
238                 popup = new PopupMenu();
239                 trayIcon = new TrayIcon( iconSystrayOffline ); //$NON-NLS-1$
240                 trayIcon.setToolTip("The Final Key - Hardware password manager"); //$NON-NLS-1$
241                 trayIcon.setImageAutoSize(true);
242                 final SystemTray tray = SystemTray.getSystemTray();
243
244                 // Create a pop-up menu components
245                 showMain = new MenuItem(Messages.MainWin_7);
246                 hideMain = new MenuItem(Messages.MainWin_8);
247
248                 showMain.addActionListener(new ActionListener() {
249                         @Override
250                         public void actionPerformed(ActionEvent e) {
251                                 Display.getDefault().syncExec( new Runnable(){
252
253                                         public void run()
254                                         {
255                                                 showFromTray();
256                                         }
257                                 } );
258                         }
259
260                 });
261
262                 hideMain.addActionListener(new ActionListener() {
263                         @Override
264                         public void actionPerformed(ActionEvent e) {
265                                 Display.getDefault().syncExec( new Runnable(){
266
267                                         public void run()
268                                         {
269                                                 hideToTray();
270                                         }
271                                 } );
272                         }
273                 });
274
275                 clearSystray();
276
277
278                 trayIcon.setPopupMenu(popup);
279
280                 try {
281                         tray.add(trayIcon);
282                 } catch (AWTException e) {
283                         log("TrayIcon could not be added."); //$NON-NLS-1$
284                 }
285
286         }
287
288         private void hideToTray()
289         {
290                 popup.remove(0);
291                 popup.insert(showMain, 0);
292                 shell.setVisible(false);
293         }
294
295         private void showFromTray()
296         {
297                 popup.remove(0);
298                 popup.insert(hideMain, 0);
299                 shell.setVisible(true);
300                 shell.forceActive();
301         }
302
303         private void destroySysTrayIcon()
304         {
305                 sysTrayIconVisible=false;
306                 SystemTray.getSystemTray().remove(trayIcon);
307         }
308
309         private void clearSystray() {
310                         popup.removeAll();
311                         //Add components to pop-up menu
312                         if(shell.isVisible()==true)
313                         {
314                                 popup.add(hideMain);
315                         } else {
316                                 popup.add(showMain);
317                         }
318                         popup.addSeparator();
319         }
320
321         public void shutDownApp()
322         {
323                 if(fkSerial != null)
324                 {
325                         fkSerial.disconnect();
326                 }
327                 if(sysTrayIconVisible == true)
328                 {
329                         destroySysTrayIcon();
330                 }
331                 System.exit(0);
332         }
333
334         /**
335          * Create contents of the window.
336          */
337         protected void createContents() {
338
339
340                 shell = new Shell();
341                 shell.setImage( iconProgramOffline ); //$NON-NLS-1$
342                 shell.setSize(711, 655);
343
344
345                 prefs = Preferences.userNodeForPackage(this.getClass());
346
347                 FkManager.getInstance().sortById( prefs.getBoolean(PREF_SORT_BY_ID_KEY, false) );
348
349                 mySelf = this;
350                 shell.setLayout(new FillLayout(SWT.HORIZONTAL));
351
352                 tabFolder = new TabFolder(shell, SWT.NONE);
353                 tabFolder.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
354
355                 TabItem tbtmConnection = new TabItem(tabFolder, SWT.NONE);
356                 tbtmConnection.setText(Messages.MainWin_12);
357
358                 cmpConnect = new Composite(tabFolder, SWT.BORDER);
359                 tbtmConnection.setControl(cmpConnect);
360                 cmpConnect.setLayout(new FormLayout());
361
362                 btnConnect = new Button(cmpConnect, SWT.CENTER);
363                 btnConnect.setImage( SWTResourceManager.getImage(MainWin.class, "/fkgui/gfx/lightning.png") ); //$NON-NLS-1$
364                 FormData fd_btnConnect = new FormData();
365                 fd_btnConnect.top = new FormAttachment(0, 8);
366                 fd_btnConnect.left = new FormAttachment(100, -125);
367                 fd_btnConnect.right = new FormAttachment(100, -10);
368
369                 btnConnect.setLayoutData(fd_btnConnect);
370
371                 btnConnect.addSelectionListener(new SelectionAdapter() {
372                         public void widgetSelected(SelectionEvent e) {
373
374                                 if( fkSerial!=null && fkSerial.state == SerialState.Connected )
375                                 {
376                                         fkSerial.disconnect();
377                                 } else {
378                                         connect();
379                                 }
380                         }
381
382                 });
383                 btnConnect.setText(Messages.MainWin_15);
384                 txtPsw = new Text(cmpConnect, SWT.BORDER | SWT.PASSWORD);
385                 FormData fd_txtPsw = new FormData();
386
387                 fd_txtPsw.left = new FormAttachment(0, 102);
388                 txtPsw.setLayoutData(fd_txtPsw);
389                 txtPsw.setFocus();
390                 txtPsw.addKeyListener( new KeyListener() {
391                         @Override
392                         public void keyReleased(KeyEvent arg0) { }
393
394                         @Override
395                         public void keyPressed(KeyEvent arg0) {
396                                 if( arg0.character==SWT.CR )
397                                 {
398                                         connect();
399                                 }
400                         }
401                 });
402
403                 txtLog = new Text(cmpConnect, SWT.BORDER | SWT.V_SCROLL | SWT.MULTI | SWT.WRAP);
404                 fd_btnConnect.bottom = new FormAttachment(txtPsw, 0, SWT.BOTTOM);
405                 FormData fd_txtLog = new FormData();
406                 fd_txtLog.bottom = new FormAttachment(100, -8);
407                 fd_txtLog.top = new FormAttachment(btnConnect, 8, SWT.BOTTOM);
408                 fd_txtLog.left = new FormAttachment(0, 8);
409                 fd_txtLog.right = new FormAttachment(btnConnect,0, SWT.RIGHT);
410                 txtLog.setLayoutData(fd_txtLog);
411                 txtLog.setEditable(false);
412
413                 lblPort = new Label(cmpConnect, SWT.NONE);
414                 lblPort.setAlignment(SWT.RIGHT);
415                 FormData fd_lblPort = new FormData();
416                 fd_lblPort.left = new FormAttachment(0, 10);
417                 lblPort.setLayoutData(fd_lblPort);
418                 lblPort.setText(Messages.MainWin_4);
419
420                 txtDev = new Text(cmpConnect, SWT.BORDER);
421                 fd_txtPsw.top = new FormAttachment(txtDev,4, SWT.BOTTOM);
422                 fd_lblPort.top = new FormAttachment(txtDev,0,SWT.CENTER);
423                 fd_lblPort.right = new FormAttachment(txtDev, -7);
424                 FormData fd_txtDev = new FormData();
425                 fd_txtDev.top = new FormAttachment(btnConnect,0,SWT.TOP);
426                 fd_txtDev.left = new FormAttachment(0, 102);
427                 txtDev.setLayoutData(fd_txtDev);
428                 txtDev.setText( prefs.get(PREF_PORT, PREF_DEFAULT_DEVICE));
429                 lblPassword = new Label(cmpConnect, SWT.NONE);
430                 lblPassword.setAlignment(SWT.RIGHT);
431                 FormData fd_lblPassword = new FormData();
432                 fd_lblPassword.right = new FormAttachment(0, 95);
433                 fd_lblPassword.top = new FormAttachment(txtPsw, 0, SWT.CENTER);
434                 fd_lblPassword.left = new FormAttachment(0, 10);
435                 lblPassword.setLayoutData(fd_lblPassword);
436                 lblPassword.setText(Messages.MainWin_18);
437
438                 animation = new Animation(cmpConnect, SWT.NONE, 4);
439                 fd_txtDev.right = new FormAttachment(animation,-16, SWT.LEFT );
440                 fd_txtPsw.right = new FormAttachment(animation,-16, SWT.LEFT );
441
442                 FormData fd_animation = new FormData();
443                 fd_animation.right = new FormAttachment(btnConnect, -16);
444                 fd_animation.top = new FormAttachment(0, 10);
445
446                 animation.setLayoutData(fd_animation);
447
448                 animation.setVisible(false);
449                 animation.setPlaying(false);
450                 cmpConnect.setTabList(new Control[]{txtPsw, btnConnect, txtDev});
451
452                 log(Messages.MainWin_22);
453
454
455                 shell.addShellListener( new ShellListener() {
456
457                         public void shellIconified(ShellEvent e) {
458                         }
459
460                         public void shellDeiconified(ShellEvent e) {
461                         }
462
463                         public void shellDeactivated(ShellEvent e) {
464                         }
465
466                         public void shellClosed(ShellEvent e) {
467                                 shutDownApp();
468                         }
469
470                         public void shellActivated(ShellEvent e) {
471
472                         }
473                 } );
474
475
476                 if( System.getProperty("os.name").compareTo("Linux") == 0 ) //$NON-NLS-1$ //$NON-NLS-2$
477                 {
478                         Boolean gtkOk=false;
479                         Map<String, String> env = System.getenv();
480                         for (String envName : env.keySet()) {
481                                 if( envName.compareTo("SWT_GTK3") == 0 && env.get(envName).compareTo("0") == 0 ) //$NON-NLS-1$ //$NON-NLS-2$
482                                 {
483                                         gtkOk=true;
484                                 }
485                         }
486
487                         if( !gtkOk )
488                         {
489                                 log("Warning: Enviroment variable SWT_GTK3 is not set to 0, if FinalKey GUI looks weird or crashes after connecting, try export GTK_SWT3=0 before running."); //$NON-NLS-1$
490                         }
491                 }
492
493                 Device display = Display.getCurrent();
494                 blackColor = display.getSystemColor(SWT.COLOR_BLACK );
495                 grayColor = display.getSystemColor(SWT.COLOR_GRAY );
496                 defaultBgColor = display.getSystemColor(SWT.COLOR_LIST_BACKGROUND );
497                 greenColor = display.getSystemColor(SWT.COLOR_DARK_GREEN );
498                 redColor = display.getSystemColor(SWT.COLOR_RED );
499
500         }
501
502
503         private void connect() {
504                 fkSerial = new SerialWorker(mySelf);
505                 prefs.put(PREF_PORT, txtDev.getText() );
506                 fkSerial.connect(txtDev.getText(),txtPsw.getText());
507                 txtPsw.setText(""); //$NON-NLS-1$
508         }
509
510         @Override
511         public void updateAccountList()
512         {
513                 int free=256;
514                 clearSystray();
515                 lstAccounts.getList().removeAll();
516
517                 Boolean showAccountId = prefs.getBoolean( PREF_SHOW_ACCOUNT_ID_IN_NAME_KEY, false);
518
519                 for( FkManager.Account a : FkManager.getInstance().getList() )
520                 {
521                         free--;
522                         lstAccounts.add( a.showNumInName( showAccountId ) );
523
524                         Menu menu = new Menu(a.toString());
525                         MenuItem both = new MenuItem(Messages.MainWin_25);
526                         MenuItem usr = new MenuItem(Messages.MainWin_26);
527                         MenuItem psw = new MenuItem(Messages.MainWin_27);
528                         menu.add(both);
529                         menu.add(usr);
530                         menu.add(psw);
531
532
533                         both.addActionListener(FkManager.getInstance());
534                         both.setActionCommand( "%"+a.num ); //$NON-NLS-1$
535
536
537
538                         psw.addActionListener(FkManager.getInstance()); 
539                         psw.setActionCommand( "p"+a.num); //$NON-NLS-1$
540
541
542                         usr.addActionListener(FkManager.getInstance()); 
543                         usr.setActionCommand( "u"+a.num ); //$NON-NLS-1$
544
545                         popup.add(menu);
546                 }
547
548                 lblNumFree.setText(" "+free+Messages.MainWin_32); //$NON-NLS-1$
549                 lblNumFree.pack();
550                 lblNumFree.getParent().layout();
551
552                 if( free == 0 )
553                 {
554                         btnNewAccount.setVisible(false);
555                 } else {
556                         btnNewAccount.setVisible(true);
557                 }
558
559         }
560
561         @Override
562         public void serialEvent(SerialState state) {
563                 switch(state)
564                 {
565                 case Connected:
566                         shell.setText(Messages.MainWin_33 + FkManager.getInstance().getBanner());
567
568                         animation.setVisible(false);
569                         animation.setPlaying(false);
570
571                         btnConnect.setText(Messages.MainWin_34);
572                         btnConnect.setEnabled(true);
573
574                         //Should we hide?
575                         if( prefs.getBoolean(PREF_AUTOHIDE, false) == true)
576                         {
577                                 hideToTray();
578                         }
579
580                         addAccountsTab();
581
582                         tabFolder.setSelection(1);
583
584                         updateAccountList();
585                         txtFilter.setFocus();
586
587                         //Update icons for systray and window
588                         shell.setImage( iconProgramOnline );
589                         trayIcon.setImage( iconSystrayOnline );
590
591                         int numAccounts=FkManager.getInstance().getList().size();
592                         if( numAccounts>0 && prefs.getBoolean( PREF_SHOW_ACCOUNTS_READY_NOTICE, true) )
593                         {
594                                 trayIcon.displayMessage("FinalKey", numAccounts +" "+ (( numAccounts >1)?Messages.MainWin_1:Messages.MainWin_2), //$NON-NLS-1$ //$NON-NLS-2$
595                                                 TrayIcon.MessageType.INFO);
596                         }
597
598                 //      log(Messages.MainWin_40);
599
600                         break;
601                 case Connecting:
602                         shell.setText(Messages.MainWin_41);
603                         animation.setVisible(true);
604                         animation.setPlaying(true);
605
606                         txtPsw.setEnabled(false);
607                         txtDev.setEnabled(false);
608                         btnConnect.setEnabled(false);
609
610                         lblPort.setEnabled(false);
611                         lblPassword.setEnabled(false);
612                         break;
613                 case Disconnected:
614                         fkSerial=null;
615                         animation.setVisible(false);
616                         animation.setPlaying(false);
617
618                         remAccountsTab();
619
620                         tabFolder.setSelection(0);
621
622                         shell.setText(Messages.MainWin_42);
623                         btnConnect.setText(Messages.MainWin_43);
624
625                         btnConnect.setEnabled(true);
626
627                         lblPort.setEnabled(true);
628                         lblPassword.setEnabled(true);
629                         txtPsw.setEnabled(true);
630                         txtPsw.setFocus();
631                         txtDev.setEnabled(true);
632
633                         cmpConnect.update();
634
635                         clearSystray();
636
637                         //Update icons for systray and window
638                         shell.setImage( iconProgramOffline );
639                         trayIcon.setImage( iconSystrayOffline );
640                         break;
641
642                 case Working:
643                         animation.setPlaying(false);
644                         animation.setVisible(false);
645                         break;
646
647                 default:
648                         break;
649                 }
650                 cmpConnect.layout();
651         }
652
653         private void remAccountsTab() {
654                 if( tabFolder.getItemCount() > 1 )
655                 {
656                         tabFolder.getItem(1).dispose();
657                 }
658
659         }
660
661         void updateFilteredList(Vector<Account> source)
662         {
663                 lstAccounts.getList().removeAll();
664
665                 Boolean showAccountId = prefs.getBoolean( PREF_SHOW_ACCOUNT_ID_IN_NAME_KEY, false);
666
667                 for( FkManager.Account a : source )
668                 {
669                         lstAccounts.add( a.showNumInName( showAccountId ) );
670                 }
671         }
672
673         private void addAccountsTab() {
674
675                 tbtmAccounts = new TabItem(tabFolder, SWT.NONE, 1);//TabItem(tabFolder, SWT.NONE);
676                 tbtmAccounts.setText(Messages.MainWin_45);
677
678                 cmpAccounts = new Composite(tabFolder, SWT.BORDER);
679                 tbtmAccounts.setControl(cmpAccounts);
680                 cmpAccounts.setLayout(new FormLayout());
681
682                 btnNewAccount = new Button(cmpAccounts, SWT.NONE);
683                 btnNewAccount.setImage(SWTResourceManager.getImage(MainWin.class, "/fkgui/gfx/new.png")); //$NON-NLS-1$
684                 btnNewAccount.addSelectionListener(new SelectionAdapter() {
685                         @Override
686                         public void widgetSelected(SelectionEvent e) {
687                                 NewAccountDialog dialog = new NewAccountDialog(shell, shell.getStyle() );
688                                 btnOpenAccount.setEnabled(false);
689                                 shell.setEnabled(false);
690                                 dialog.open();
691                                 shell.setEnabled(true);
692                                 updateAccountList();
693                         }
694                 });
695                 FormData fd_btnNewAccoount = new FormData();
696                 fd_btnNewAccoount.right = new FormAttachment(100, -10);
697                 fd_btnNewAccoount.top = new FormAttachment(100, -40);
698                 fd_btnNewAccoount.bottom = new FormAttachment(100, -6);
699                 fd_btnNewAccoount.left = new FormAttachment(100, -200);
700
701                 btnNewAccount.setLayoutData(fd_btnNewAccoount);
702                 btnNewAccount.setText(Messages.MainWin_47);
703
704                 lstAccounts = new ListViewer(cmpAccounts, SWT.BORDER | SWT.V_SCROLL);
705                 lstAccountsControl = lstAccounts.getList();
706                 lstAccountsControl.setLayoutData(new FormData());
707
708                 lblNumFree = new Label(cmpAccounts, SWT.NONE);
709                 //lblNumFree.setText("Hello World!"); //$NON-NLS-1$
710                 FormData fd_lblNumFree = new FormData();
711                 fd_lblNumFree.left = new FormAttachment(lstAccountsControl,0,SWT.LEFT);
712                 fd_lblNumFree.bottom = new FormAttachment(btnNewAccount, 0, SWT.CENTER);
713                 lblNumFree.setLayoutData(fd_lblNumFree);
714
715                 btnOpenAccount = new Button(cmpAccounts, SWT.NONE);
716                 //fd_lblNumFree.right = new FormAttachment(btnOpenAccount, -224);
717                 btnOpenAccount.setImage(SWTResourceManager.getImage(MainWin.class, "/fkgui/gfx/lightbulb.png")); //$NON-NLS-1$
718                 FormData fd_btnOpenAccount = new FormData();
719                 fd_btnOpenAccount.top = new FormAttachment(btnNewAccount, 0, SWT.TOP);
720                 fd_btnOpenAccount.bottom = new FormAttachment(btnNewAccount, 0, SWT.BOTTOM);
721                 fd_btnOpenAccount.right = new FormAttachment(btnNewAccount, -8, SWT.LEFT );
722                 btnOpenAccount.setLayoutData(fd_btnOpenAccount);
723                 btnOpenAccount.setText(Messages.MainWin_5);
724                 btnOpenAccount.getShell().layout();
725                 btnOpenAccount.setEnabled(false);
726
727
728                 FormData fd_lstAccounts = new FormData();
729                 fd_lstAccounts.top = new FormAttachment(0, 8);
730                 fd_lstAccounts.bottom = new FormAttachment(btnNewAccount, -6);
731
732                 txtFilter = new Text(cmpAccounts, SWT.BORDER);
733                 txtFilter.setText(Messages.MainWin_10);
734                 FormData fd_txtFilter = new FormData();
735                 fd_txtFilter.left = new FormAttachment(lblNumFree, 8, SWT.RIGHT);
736                 fd_txtFilter.bottom = new FormAttachment(btnOpenAccount,0, SWT.CENTER);
737                 fd_txtFilter.right = new FormAttachment(btnOpenAccount, -8, SWT.LEFT);
738                 txtFilter.setLayoutData(fd_txtFilter);
739                 txtFilter.setForeground( grayColor );
740                 txtFilter.addFocusListener( new FocusListener() {
741                         @Override
742                         public void focusLost(FocusEvent arg0) {
743                                 txtFilter.setText(Messages.MainWin_10);
744                                 txtFilter.setForeground( grayColor );
745                                 txtFilter.setBackground( defaultBgColor );
746                         }
747
748                         @Override
749                         public void focusGained(FocusEvent arg0) {
750                                 updateFilteredList( FkManager.getInstance().getList() );
751                                 txtFilter.setForeground( blackColor );
752                                 txtFilter.setText(""); //$NON-NLS-1$
753                                 btnOpenAccount.setEnabled(false);
754                         }
755                 });
756
757                 txtFilter.addKeyListener( new KeyListener() {
758
759                         @Override
760                         public void keyReleased(KeyEvent arg0) {
761                                 if( arg0.keyCode == SWT.ESC )
762                                 {
763                                         txtFilter.setText(""); //$NON-NLS-1$
764                                 }
765
766                                 txtFilterKeyPressEvent(arg0);
767                         }
768
769                         @Override
770                         public void keyPressed(KeyEvent arg0) {
771
772                         }
773                 });
774
775                 fd_lstAccounts.left = new FormAttachment(0, 10);
776                 fd_lstAccounts.right = new FormAttachment(100, -10);
777
778                 lstAccounts.getControl().setLayoutData(fd_lstAccounts);
779                 lstAccounts.addDoubleClickListener( new IDoubleClickListener() {
780
781                         @Override
782                         public void doubleClick(DoubleClickEvent arg0) {
783                                 StructuredSelection selection = (StructuredSelection) arg0.getSelection();
784                                 if( !selection.isEmpty() )
785                                 {
786                                         Account acc = (Account)selection.getFirstElement();
787                                         showTrigDialog(acc);
788                                 }
789                         }
790
791
792                 });
793
794                 lstAccounts.addSelectionChangedListener( new ISelectionChangedListener() {
795
796                         @Override
797                         public void selectionChanged(SelectionChangedEvent arg0) {
798                                 StructuredSelection selection = (StructuredSelection) arg0.getSelection();
799                                 if( !selection.isEmpty() )
800                                 {
801                                         btnOpenAccount.setEnabled(true);
802
803                                         //Remove any listeners
804                                         for( Listener s :btnOpenAccount.getListeners(SWT.Selection) )
805                                         {
806                                                 btnOpenAccount.removeListener(SWT.Selection, s);
807                                         }
808
809                                         btnOpenAccount.addSelectionListener( new SelectionListener() {
810
811                                                 @Override
812                                                 public void widgetSelected(SelectionEvent arg0) {
813                                                         StructuredSelection selection = (StructuredSelection) lstAccounts.getSelection();
814                                                         Account acc = (Account)selection.getFirstElement();
815                                                         showTrigDialog(acc);
816                                                 }
817
818                                                 @Override
819                                                 public void widgetDefaultSelected(SelectionEvent arg0) {
820                                                         // TODO Auto-generated method stub
821                                                 }
822                                         });
823                                 }
824                         }
825                 });
826
827
828                 lstAccountsControl.addKeyListener( new KeyListener() {
829                         @Override
830                         public void keyReleased(KeyEvent arg0) {
831                         }
832
833                         @Override
834                         public void keyPressed(KeyEvent arg0) {
835                                 if( arg0.keyCode > 31 && arg0.keyCode < 126 && (arg0.stateMask&SWT.CTRL)!=SWT.CTRL )
836                                 {
837                                         txtFilter.setFocus();
838                                         txtFilter.setText( ""+(char)arg0.keyCode ); //$NON-NLS-1$
839                                         txtFilterKeyPressEvent(arg0);
840                                         txtFilter.setSelection(1);
841                                 } else if( arg0.keyCode == SWT.ARROW_UP)
842                                 {
843                                         //If selectionIndex is already 0, that means that the previous event caused that, so this time, it's changing nothing
844                                         //and we can use it to wrap
845                                         if( lstAccountsControl.getSelectionIndex() == 0)
846                                         {
847                                                 lstAccountsControl.setSelection( lstAccountsControl.getItemCount()-1 );
848                                                 arg0.doit=false;
849                                         }
850                                 } else if( arg0.keyCode == SWT.ARROW_DOWN)
851                                 {
852                                         if( lstAccountsControl.getSelectionIndex() == lstAccountsControl.getItemCount()-1 )
853                                         {
854                                                 lstAccountsControl.setSelection(0);
855                                                 arg0.doit=false;
856                                         }
857                                 }
858                         }
859                 });
860
861                 lstAccountsControl.addFocusListener( new FocusListener() {
862
863                         @Override
864                         public void focusLost(FocusEvent arg0) {
865
866                         }
867
868                         @Override
869                         public void focusGained(FocusEvent arg0) {
870                                 if( lstAccountsControl.getItemCount() == 0 )
871                                 {
872                                         updateFilteredList(FkManager.getInstance().getList());
873                                 }
874
875                         }
876                 });
877
878                 cmpAccounts.setTabList(new Control[]{txtFilter,lstAccountsControl, btnOpenAccount, btnNewAccount});
879         }
880
881         protected void txtFilterKeyPressEvent(KeyEvent arg0) {
882                 Vector<Account> res = null;
883
884                 if( txtFilter.getText().length() == 0 )
885                 {
886                         res=FkManager.getInstance().getList();
887                         txtFilter.setBackground( defaultBgColor );
888                 } else {
889                         res = FkManager.getInstance().getList(txtFilter.getText());
890                         if( res.size() < 1 )
891                         {
892                                 txtFilter.setBackground( redColor );
893                         } else if( res.size() == 1 )
894                         {
895                                 txtFilter.setBackground( greenColor );
896                                 if( arg0.character== SWT.CR)
897                                 {
898                                         showTrigDialog(res.get(0));
899                                 }
900                         } else {
901                                 txtFilter.setBackground( defaultBgColor );
902                         }
903                 }
904
905
906                 if( res != null )
907                 {
908                         updateFilteredList( res );
909                         if( res.size() > 0 )
910                         {
911                                 if( arg0.keyCode == SWT.ARROW_UP )
912                                 {
913                                         lstAccountsControl.setFocus();
914                                         lstAccountsControl.setSelection( res.size()-1 );
915                                 }
916
917                                 if( arg0.keyCode == SWT.ARROW_DOWN )
918                                 {
919                                         lstAccountsControl.setFocus();
920                                         lstAccountsControl.setSelection( 0 );
921                                 }
922                         }
923                 }
924         }
925
926         private void addSettingsTab()
927         {
928                 tbtmSettings = new TabItem(tabFolder, SWT.NONE);
929                 tbtmSettings.setText(Messages.MainWin_tbtmSettings_text);
930
931                 cmpSettings = new Composite(tabFolder, SWT.BORDER);
932                 tbtmSettings.setControl(cmpSettings);
933                 cmpSettings.setLayout(new FormLayout());
934
935                 chkAutoHide = new Button(cmpSettings, SWT.CHECK);
936                 chkAutoHide.setText(Messages.MainWin_6);
937                 chkAutoHide.setSelection( prefs.getBoolean( PREF_AUTOHIDE, false ) );
938                 FormData fd_chkAutoHide = new FormData();
939                 fd_chkAutoHide.top = new FormAttachment(0, 10);
940                 fd_chkAutoHide.left = new FormAttachment(0, 10);
941                 chkAutoHide.setLayoutData(fd_chkAutoHide);
942                 chkAutoHide.addSelectionListener( new SelectionAdapter() {
943                         public void widgetSelected(SelectionEvent e) {
944                                 prefs.putBoolean(PREF_AUTOHIDE, chkAutoHide.getSelection() );
945                         }
946                 });
947
948                 chkSortByAccountId = new Button(cmpSettings, SWT.CHECK);
949                 chkSortByAccountId.setText(Messages.MainWin_9);
950                 chkSortByAccountId.setSelection( prefs.getBoolean( PREF_SORT_BY_ID_KEY, false) );
951                 FormData fd_btnSortByAccountId = new FormData();
952                 fd_btnSortByAccountId.top = new FormAttachment(chkAutoHide, 6);
953                 fd_btnSortByAccountId.left = new FormAttachment(chkAutoHide, 0, SWT.LEFT);
954                 chkSortByAccountId.setLayoutData(fd_btnSortByAccountId);
955                 chkSortByAccountId.addSelectionListener( new SelectionAdapter() {
956                         public void widgetSelected(SelectionEvent e) {
957                                 prefs.putBoolean( PREF_SORT_BY_ID_KEY, chkSortByAccountId.getSelection() );
958                                 FkManager.getInstance().sortById( chkSortByAccountId.getSelection() );
959                                 updateAccountList();
960                         }
961                 });
962
963                 chkShowAccountId = new Button(cmpSettings, SWT.CHECK);
964                 FormData fd_chkShowAccountId = new FormData();
965                 fd_chkShowAccountId.top = new FormAttachment(chkSortByAccountId, 6);
966                 fd_chkShowAccountId.left = new FormAttachment(chkAutoHide, 0, SWT.LEFT);
967                 chkShowAccountId.setLayoutData(fd_chkShowAccountId);
968                 chkShowAccountId.setText(Messages.MainWin_btnShowAccountId_text);
969                 chkShowAccountId.setSelection( prefs.getBoolean(PREF_SHOW_ACCOUNT_ID_IN_NAME_KEY, false) );
970                 chkShowAccountId.addSelectionListener( new SelectionAdapter() {
971                         public void widgetSelected(SelectionEvent e) {
972                                 prefs.putBoolean( PREF_SHOW_ACCOUNT_ID_IN_NAME_KEY, chkShowAccountId.getSelection() );
973                                 updateAccountList();
974                         }
975                 });
976
977                 chkCheckForUpdates = new Button(cmpSettings, SWT.CHECK);
978                 FormData fd_chkCheckForUpdates = new FormData();
979                 fd_chkCheckForUpdates.left = new FormAttachment(chkAutoHide, 0, SWT.LEFT);
980                 chkCheckForUpdates.setLayoutData(fd_chkCheckForUpdates);
981                 chkCheckForUpdates.setText(Messages.MainWin_btnCheckForUpdates_text);
982                 chkCheckForUpdates.setSelection( prefs.getBoolean( PREF_ALLOW_UPDATE_CHECK, true) );
983                 chkCheckForUpdates.addSelectionListener( new SelectionAdapter() {
984                         public void widgetSelected(SelectionEvent e) {
985                                 prefs.putBoolean( PREF_ALLOW_UPDATE_CHECK, chkCheckForUpdates.getSelection() );
986                                 checkForUpdates();
987                         }
988                 });
989                 fd_chkCheckForUpdates.top = new FormAttachment(chkShowAccountId, 6);
990
991                 btnShowaccountsReady = new Button(cmpSettings, SWT.CHECK);
992                 btnShowaccountsReady.setSelection( prefs.getBoolean( PREF_SHOW_ACCOUNTS_READY_NOTICE, true) );
993                 FormData fd_btnShowaccountsReady = new FormData();
994                 fd_btnShowaccountsReady.top = new FormAttachment(chkCheckForUpdates, 6);
995                 fd_btnShowaccountsReady.left = new FormAttachment(chkAutoHide, 0, SWT.LEFT);
996                 btnShowaccountsReady.setLayoutData(fd_btnShowaccountsReady);
997
998                 btnShowaccountsReady.setText(Messages.MainWin_btnShowaccountsReady_text);
999                 btnShowaccountsReady.addSelectionListener( new SelectionAdapter() {
1000                 public void widgetSelected(SelectionEvent e) {
1001                                 prefs.putBoolean( PREF_SHOW_ACCOUNTS_READY_NOTICE, btnShowaccountsReady.getSelection() );
1002                         }
1003                 });
1004
1005         }
1006
1007         private void showTrigDialog(Account acc) {
1008                 Account selectedAccount = acc;
1009                 TriggerDialog diag = new TriggerDialog(shell, shell.getStyle(), acc,
1010                                 mySelf);
1011
1012                 shell.setEnabled(false);
1013                 diag.open();
1014
1015                 // Check if the account still exists
1016                 Boolean deleted = true;
1017                 for (Account a : FkManager.getInstance().getList()) {
1018                         if (a.equals(selectedAccount)) {
1019                                 deleted = false;
1020                                 break;
1021                         }
1022                 }
1023
1024                 if (deleted) {
1025                         btnOpenAccount.setEnabled(false);
1026                 }
1027
1028                 txtFilter.setFocus();
1029                 shell.setEnabled(true);
1030         }
1031
1032         @Override
1033         public void updateCheckFinished(UpdateResultEvent event) {
1034                 updateCheckThread=null;
1035                 switch(event.result)
1036                 {
1037                 case CHECK_FAILED:
1038                         System.out.println("Trouble checking for updates."); //$NON-NLS-1$
1039                         break;
1040                 case NO_UPDATE:
1041                         System.out.println("No update avaiable at this time."); //$NON-NLS-1$
1042                         break;
1043                 case UPDATE_AVAILABLE:
1044                         String title =Messages.MainWin_52+event.version+Messages.MainWin_53;
1045                         String text = Messages.MainWin_54+event.message;
1046                         log(title);
1047                         log(text);
1048
1049                         MessageBox dialog = new MessageBox(shell, SWT.ICON_INFORMATION |SWT.YES | SWT.NO);
1050                         dialog.setText(title);
1051                         dialog.setMessage(text+"\n\n\n"+Messages.MainWin_13); //$NON-NLS-1$
1052                         int res = dialog.open();
1053
1054                         if( res == SWT.YES )
1055                         {
1056                                 if(Desktop.isDesktopSupported())
1057                                 {
1058                                         try {
1059                                                 URI uri = new URI("http://finalkey.net/gui/"); //$NON-NLS-1$
1060                                                 log(Messages.MainWin_16+uri.toString());
1061                                                 //FIXME: For whichever reason, this causes busy-cursor on the application, even though ui works fine.
1062                                                 Desktop.getDesktop().browse(uri);
1063                                                 log(Messages.MainWin_17);
1064                                         } catch (Exception e) {
1065                                                 log(Messages.MainWin_20);
1066                                                 log(Messages.MainWin_21);
1067                                                 log(e.getLocalizedMessage());
1068                                         }
1069                                 }
1070                         } else {
1071                                 log(Messages.MainWin_11);
1072                         }
1073
1074                         break;
1075                 }
1076
1077         }
1078 }