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