]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.workbench/src/org/simantics/workbench/splashHandlers/InteractiveSplashHandler.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.workbench / src / org / simantics / workbench / splashHandlers / InteractiveSplashHandler.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12
13 package org.simantics.workbench.splashHandlers;
14
15 import java.util.Timer;
16 import java.util.TimerTask;
17
18 import org.eclipse.jface.dialogs.MessageDialog;
19 import org.eclipse.jface.resource.ImageDescriptor;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.SelectionAdapter;
22 import org.eclipse.swt.events.SelectionEvent;
23 import org.eclipse.swt.graphics.GC;
24 import org.eclipse.swt.graphics.Image;
25 import org.eclipse.swt.graphics.ImageData;
26 import org.eclipse.swt.graphics.Point;
27 import org.eclipse.swt.graphics.Rectangle;
28 import org.eclipse.swt.graphics.Region;
29 import org.eclipse.swt.layout.FillLayout;
30 import org.eclipse.swt.layout.GridData;
31 import org.eclipse.swt.layout.GridLayout;
32 import org.eclipse.swt.widgets.Button;
33 import org.eclipse.swt.widgets.Canvas;
34 import org.eclipse.swt.widgets.Composite;
35 import org.eclipse.swt.widgets.Event;
36 import org.eclipse.swt.widgets.Label;
37 import org.eclipse.swt.widgets.Listener;
38 import org.eclipse.swt.widgets.Shell;
39 import org.eclipse.swt.widgets.Text;
40 import org.eclipse.ui.splash.AbstractSplashHandler;
41 import org.simantics.workbench.internal.Activator;
42
43
44 /**
45  * @since 3.3
46  */
47 @SuppressWarnings("unused")
48 public class InteractiveSplashHandler extends AbstractSplashHandler {
49
50     private static final String SPLASH_IMAGE              = "simantics.png";
51
52     private final static int    FADE_TIME_MS              = 250;
53
54     private final static int    F_LABEL_HORIZONTAL_INDENT = 10;
55
56     private final static int    F_BUTTON_WIDTH_HINT       = 80;
57
58     private final static int    F_TEXT_WIDTH_HINT         = 175;
59
60     private final static int    F_COLUMN_COUNT            = 3;
61
62     private Composite           fCompositeLogin;
63
64     private Text                fTextUsername;
65
66     private Text                fTextPassword;
67
68     private Button              fButtonOK;
69
70     private Button              fButtonCancel;
71
72     private boolean             fAuthenticated;
73
74     private Image               splashImage;
75
76     private Image               currentBackground;
77
78     private long                fadeStartTime             = 0;
79
80     private boolean             fadeComplete              = false;
81
82     private Timer               watchdogTimer             = new Timer("splash-watchdog");
83
84     enum State {
85         INIT,
86         OK,
87         DIRTY,
88         UPDATED,
89         ;
90         State ok() {
91 //            System.out.println(this + " -> " + OK);
92             return OK;
93         }
94         State dirty() {
95 //            System.out.println(this + " -> " + DIRTY);
96             return DIRTY;
97         }
98         State updated() {
99 //            if (this != DIRTY) {
100 //                System.err.println("ERROR: transition from " + this + " to " + DIRTY);
101 //            }
102 //            System.out.println(this + " -> " + UPDATED);
103             return UPDATED;
104         }
105     }
106
107     private State state = State.INIT;
108
109     /**
110      * 
111      */
112     public InteractiveSplashHandler() {
113         fCompositeLogin = null;
114         fTextUsername = null;
115         fTextPassword = null;
116         fButtonOK = null;
117         fButtonCancel = null;
118         fAuthenticated = false;
119     }
120
121     /**
122      * Takes a screenshot of the desktop and blends the splash screen PNG image
123      * on top of it. The blended result is then set as currentBackground.
124      * 
125      * @param splash
126      */
127     private void updateBackground1(Shell splash) {
128 //        System.out.println("Screenshotting");
129         Point size = splash.getSize();
130         Point pt = splash.getLocation();
131         //System.out.println("location: " + pt + ", size: " + size);
132
133         splash.setRegion(new Region());
134
135         // Get screenshot into backgroundImage
136         Rectangle clientArea = splash.getDisplay().getClientArea();
137         //System.out.println("client area: " + clientArea);
138         final Image backgroundImage = new Image(splash.getDisplay(), clientArea.width, clientArea.height);
139         GC gc = new GC(splash.getDisplay());
140         gc.copyArea(backgroundImage, 0, 0);
141         gc.dispose();
142
143         // Combine the splash screen with the background
144         final Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);
145         GC gc2 = new GC(newSplashBackground);
146         gc2.drawImage(backgroundImage, pt.x, pt.y, size.x, size.y, 0, 0, size.x, size.y);
147         gc2.drawImage(splashImage, 0, 0);
148         gc2.dispose();
149
150         // Screenshot no longer needed
151         backgroundImage.dispose();
152
153         Region r = new Region();
154         Rectangle r2 = splashImage.getBounds();
155         r.add(r2);
156         splash.setRegion(r);
157
158         // Switch shell background image, dispose the old one.
159         Image old = splash.getBackgroundImage();
160         splash.setBackgroundImage(newSplashBackground);
161         currentBackground = newSplashBackground;
162         if (old != null)
163             old.dispose();
164     }
165
166     /**
167      * Takes a screenshot of the desktop and uses that as the background of the
168      * splash as currentBackground.
169      * 
170      * @param splash
171      */
172     private void updateBackground2(Shell splash) {
173         //System.out.println("Screenshotting");
174         Point size = splash.getSize();
175         Point pt = splash.getLocation();
176         //System.out.println("location: " + pt + ", size: " + size);
177
178         splash.setRegion(new Region());
179
180         // Get screenshot into backgroundImage
181         Rectangle clientArea = splash.getDisplay().getClientArea();
182         //System.out.println("client area: " + clientArea);
183         final Image backgroundImage = new Image(splash.getDisplay(), clientArea.width, clientArea.height);
184         GC gc = new GC(splash.getDisplay());
185         gc.copyArea(backgroundImage, 0, 0);
186         gc.dispose();
187
188         // Combine the splash screen with the background
189         final Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);
190         GC gc2 = new GC(newSplashBackground);
191         gc2.drawImage(backgroundImage, pt.x, pt.y, size.x, size.y, 0, 0, size.x, size.y);
192         gc2.dispose();
193
194         // Screenshot no longer needed
195         backgroundImage.dispose();
196
197         Region r = new Region();
198         Rectangle r2 = newSplashBackground.getBounds();
199         r.add(r2);
200         splash.setRegion(r);
201
202         // Switch shell background image, dispose the old one.
203         Image old = splash.getBackgroundImage();
204         splash.setBackgroundImage(newSplashBackground);
205         currentBackground = newSplashBackground;
206         if (old != null)
207             old.dispose();
208     }
209
210     private void initializeBackground(Shell splash) {
211         Point size = splash.getSize();
212         Point pt = splash.getLocation();
213         //System.out.println("location: " + pt + ", size: " + size);
214
215         // Combine the splash screen with the background
216         Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);
217         ImageData imgData = newSplashBackground.getImageData();
218         imgData.alpha = 0;
219
220         Region r = new Region();
221         Rectangle r2 = splashImage.getBounds();
222         Rectangle r3 = new Rectangle(r2.x, r2.y, r2.width, r2.height);
223         r.add(r3);
224         splash.setRegion(r);
225
226         // Switch shell background image, dispose the old one.
227         splash.setBackgroundImage(newSplashBackground);
228         currentBackground = newSplashBackground;
229     }
230
231     @Override
232     public void dispose() {
233         super.dispose();
234
235         // Destroy images
236         if (splashImage != null)
237             splashImage.dispose();
238         if (currentBackground != null)
239             currentBackground.dispose();
240     }
241
242     /*
243      * (non-Javadoc)
244      * 
245      * @see org.eclipse.ui.splash.AbstractSplashHandler#init(org.eclipse.swt.widgets.Shell)
246      */
247     public void init(final Shell splash) {
248
249         super.init(splash);
250
251         ImageDescriptor splashDesc = Activator.getImageDescriptor(SPLASH_IMAGE);
252         if (splashDesc == null) {
253             // If splash-image is not available, do nothing.
254             return;
255         }
256         splashImage  = splashDesc.createImage();
257 //        System.out.println("logo bounds: " + i.getBounds());
258
259         splash.setSize(splashImage.getBounds().width, splashImage.getBounds().height);
260 //        splash.setRegion(new Region());
261
262         Point pt = splash.getLocation();
263         pt.x -= splashImage.getBounds().width/2;
264         pt.y -= splashImage.getBounds().height/2;
265         splash.setLocation(pt);
266
267 //        updateSplashImage(splash);
268         updateBackground2(splash);
269         //initializeSplash(splash);
270         state = state.ok();
271
272 //      Configure the shell layout
273         configureUISplash();
274 //      Create UI
275         createUI();
276 //      Create UI listeners
277         createUIListeners();
278 //      Force the splash screen to layout
279         splash.layout(true);
280 //      Keep the splash screen visible and prevent the RCP application from 
281 //      loading until the close button is clicked.
282         doEventLoop();
283     }
284
285     /**
286      * 
287      */
288     private void doEventLoop() {
289         final Shell splash = getSplash();
290 //        while (fAuthenticated == false) {
291         
292         // Make sure that the splash doesn't block program startup when it is
293         // hidden.
294         watchdogTimer.schedule(new TimerTask() {
295             @Override
296             public void run() {
297                 // Terminate the timer and complete the fade.
298 //                System.out.println("watchdog");
299                 watchdogTimer.cancel();
300                 fadeComplete = true;
301             }
302         }, FADE_TIME_MS + 50);
303
304         while (!fadeComplete) {
305             if (splash.getDisplay().readAndDispatch() == false) {
306                 // Cannot use Display.sleep because it may not wake up until the
307                 // window receives events which will not happen if the window is
308                 // not visible.
309 //                splash.getDisplay().sleep();
310                 try {
311                     Thread.sleep(5);
312                 } catch (InterruptedException e) {
313                     e.printStackTrace();
314                 }
315             }
316         }
317         splash.redraw();
318         while (splash.getDisplay().readAndDispatch());
319
320 //        System.out.println("ENDING EVENT LOOP");
321     }
322
323     /**
324      * 
325      */
326     private void createUIListeners() {
327         // Update the translucency
328         /*
329         for (int in : new int[] { SWT.Activate, SWT.Deactivate, SWT.Show, SWT.Hide, SWT.Iconify, SWT.Deiconify }) {
330             getSplash().addListener(in, new Listener() {
331                 @Override
332                 public void handleEvent(Event event) {
333                     int type = event.type;
334 //                    System.out.println("[" + state + "][" + event.time + "] event: " + type);
335 //                    System.out.flush();
336                     
337 //                    switch (state) {
338 //                        case OK:
339 //                            if (type == SWT.Deactivate) {
340 //                                state = state.dirty();
341 //                            }
342 //                            break;
343 //                            
344 //                        case DIRTY:
345 //                            if (type == SWT.Activate) {
346 //                                state = state.updated();
347 //                                updateSplashImage(getSplash());
348 //                            }
349 //                            break;
350 //                        case UPDATED:
351 //                            if (type == SWT.Activate) {
352 //                                state = state.ok();
353 //                            }
354 //                            break;
355 //                        default:
356 //                    }
357                 }
358             });
359         }
360         */
361
362         fCompositeLogin.addListener(SWT.Paint, new Listener() {
363             @Override
364             public void handleEvent(Event event) {
365                 // Time elapsed in milliseconds from the beginning of the fade.
366                 float timeElapsed = 0;
367                 if (fadeStartTime == 0) {
368                     fadeStartTime = System.currentTimeMillis();
369                 } else {
370                     timeElapsed = (System.currentTimeMillis() - fadeStartTime);
371                 }
372                 int fade = Math.min(255, (int) Math.round(255f * timeElapsed / (float) FADE_TIME_MS));
373                 if (fade >= 255) {
374                     fadeComplete = true;
375                 }
376                 
377                 GC gc = event.gc;
378                 gc.drawImage(currentBackground, 0, 0);
379                 gc.setAlpha(fade);
380                 gc.drawImage(splashImage, 0, 0);
381                 
382                 if (!fadeComplete) {
383                     getSplash().getDisplay().timerExec(25, new Runnable() {
384                         @Override
385                         public void run() {
386                             Shell s = getSplash();
387                             if (s != null && !s.isDisposed()) {
388                                 Point size = s.getSize();
389                                 s.redraw(0,0, size.x, size.y, true);
390                             }
391                         }
392                     });
393                 }
394             }
395         });
396
397         // Create the OK button listeners
398 //        createUIListenersButtonOK();
399         // Create the cancel button listeners
400 //        createUIListenersButtonCancel();
401     }
402
403     /**
404      * 
405      */
406     private void createUIListenersButtonCancel() {
407         fButtonCancel.addSelectionListener(new SelectionAdapter() {
408             public void widgetSelected(SelectionEvent e) {
409                 handleButtonCancelWidgetSelected();
410             }
411         });
412     }
413
414     /**
415      * 
416      */
417     private void handleButtonCancelWidgetSelected() {
418         // Abort the loading of the RCP application
419         getSplash().getDisplay().close();
420         System.exit(0);
421     }
422
423     /**
424      * configureUISplash
425      */
426     private void createUIListenersButtonOK() {
427         fButtonOK.addSelectionListener(new SelectionAdapter() {
428             public void widgetSelected(SelectionEvent e) {
429                 handleButtonOKWidgetSelected();
430             }
431         });
432     }
433
434     /**
435      * 
436      */
437     private void handleButtonOKWidgetSelected() {
438         String username = fTextUsername.getText();
439         String password = fTextPassword.getText();
440         // Aunthentication is successful if a user provides any username and
441         // any password
442         if ((username.length() > 0) &&
443                 (password.length() > 0)) {
444             fAuthenticated = true;
445         } else {
446             MessageDialog.openError(
447                     getSplash(),
448                     "Authentication Failed",  //NON-NLS-1
449             "A username and password must be specified to login.");  //NON-NLS-1
450         }
451     }
452
453     /**
454      * 
455      */
456     private void createUI() {
457         // Create the login panel
458         createUICompositeLogin();
459         // Create the blank spanner
460         //createUICompositeBlank();
461         // Create the user name label
462         //createUILabelUserName();
463         // Create the user name text widget
464         //createUITextUserName();
465         // Create the password label
466         //createUILabelPassword();
467         // Create the password text widget
468         //createUITextPassword();
469         // Create the blank label
470         //createUILabelBlank();
471         // Create the OK button
472         //createUIButtonOK();
473         // Create the cancel button
474         //createUIButtonCancel();
475     }
476
477     /**
478      * 
479      */
480     private void createUIButtonCancel() {
481         // Create the button
482         fButtonCancel = new Button(fCompositeLogin, SWT.PUSH);
483         fButtonCancel.setText("Cancel"); //NON-NLS-1
484         // Configure layout data
485         GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);
486         data.widthHint = F_BUTTON_WIDTH_HINT;   
487         data.verticalIndent = 10;
488         fButtonCancel.setLayoutData(data);
489     }
490
491     /**
492      * 
493      */
494     private void createUIButtonOK() {
495         // Create the button
496         fButtonOK = new Button(fCompositeLogin, SWT.PUSH);
497         fButtonOK.setText("OK"); //NON-NLS-1
498         // Configure layout data
499         GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);
500         data.widthHint = F_BUTTON_WIDTH_HINT;
501         data.verticalIndent = 10;
502         fButtonOK.setLayoutData(data);
503     }
504
505     /**
506      * 
507      */
508     private void createUILabelBlank() {
509         Label label = new Label(fCompositeLogin, SWT.NONE);
510         label.setVisible(false);
511     }
512
513     /**
514      * 
515      */
516     private void createUITextPassword() {
517         // Create the text widget
518         int style = SWT.PASSWORD | SWT.BORDER;
519         fTextPassword = new Text(fCompositeLogin, style);
520         // Configure layout data
521         GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);
522         data.widthHint = F_TEXT_WIDTH_HINT;
523         data.horizontalSpan = 2;
524         fTextPassword.setLayoutData(data);
525     }
526
527     /**
528      * 
529      */
530     private void createUILabelPassword() {
531         // Create the label
532         Label label = new Label(fCompositeLogin, SWT.NONE);
533         label.setText("&Password:"); //NON-NLS-1
534         // Configure layout data
535         GridData data = new GridData();
536         data.horizontalIndent = F_LABEL_HORIZONTAL_INDENT;
537         label.setLayoutData(data);
538     }
539
540     /**
541      * 
542      */
543     private void createUITextUserName() {
544         // Create the text widget
545         fTextUsername = new Text(fCompositeLogin, SWT.BORDER);
546         // Configure layout data
547         GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);
548         data.widthHint = F_TEXT_WIDTH_HINT;
549         data.horizontalSpan = 2;
550         fTextUsername.setLayoutData(data);
551     }
552
553     /**
554      * 
555      */
556     private void createUILabelUserName() {
557         // Create the label
558         Label label = new Label(fCompositeLogin, SWT.NONE);
559         label.setText("&User Name:"); //NON-NLS-1
560         // Configure layout data
561         GridData data = new GridData();
562         data.horizontalIndent = F_LABEL_HORIZONTAL_INDENT;
563         label.setLayoutData(data);              
564     }
565
566     /**
567      * 
568      */
569     private void createUICompositeBlank() {
570         Composite spanner = new Composite(fCompositeLogin, SWT.NONE);
571         GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
572         data.horizontalSpan = F_COLUMN_COUNT;
573         spanner.setLayoutData(data);
574     }
575
576     /**
577      * 
578      */
579     private void createUICompositeLogin() {
580         // Create the composite
581 //        fCompositeLogin = new Composite(getSplash(), SWT.NONE);
582         fCompositeLogin = new Canvas(getSplash(), SWT.DOUBLE_BUFFERED);
583         GridLayout layout = new GridLayout(F_COLUMN_COUNT, false);
584         fCompositeLogin.setLayout(layout);
585     }
586
587     /**
588      * 
589      */
590     private void configureUISplash() {
591         // Configure layout
592         FillLayout layout = new FillLayout(); 
593         getSplash().setLayout(layout);
594         // Force shell to inherit the splash background
595         getSplash().setBackgroundMode(SWT.INHERIT_DEFAULT);
596     }
597
598 }