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