1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
13 package org.simantics.workbench.splashHandlers;
\r
15 import java.util.Timer;
\r
16 import java.util.TimerTask;
\r
18 import org.eclipse.jface.dialogs.MessageDialog;
\r
19 import org.eclipse.jface.resource.ImageDescriptor;
\r
20 import org.eclipse.swt.SWT;
\r
21 import org.eclipse.swt.events.SelectionAdapter;
\r
22 import org.eclipse.swt.events.SelectionEvent;
\r
23 import org.eclipse.swt.graphics.GC;
\r
24 import org.eclipse.swt.graphics.Image;
\r
25 import org.eclipse.swt.graphics.ImageData;
\r
26 import org.eclipse.swt.graphics.Point;
\r
27 import org.eclipse.swt.graphics.Rectangle;
\r
28 import org.eclipse.swt.graphics.Region;
\r
29 import org.eclipse.swt.layout.FillLayout;
\r
30 import org.eclipse.swt.layout.GridData;
\r
31 import org.eclipse.swt.layout.GridLayout;
\r
32 import org.eclipse.swt.widgets.Button;
\r
33 import org.eclipse.swt.widgets.Canvas;
\r
34 import org.eclipse.swt.widgets.Composite;
\r
35 import org.eclipse.swt.widgets.Event;
\r
36 import org.eclipse.swt.widgets.Label;
\r
37 import org.eclipse.swt.widgets.Listener;
\r
38 import org.eclipse.swt.widgets.Shell;
\r
39 import org.eclipse.swt.widgets.Text;
\r
40 import org.eclipse.ui.splash.AbstractSplashHandler;
\r
41 import org.simantics.workbench.internal.Activator;
\r
47 @SuppressWarnings("unused")
\r
48 public class InteractiveSplashHandler extends AbstractSplashHandler {
\r
50 private static final String SPLASH_IMAGE = "simantics.png";
\r
52 private final static int FADE_TIME_MS = 250;
\r
54 private final static int F_LABEL_HORIZONTAL_INDENT = 10;
\r
56 private final static int F_BUTTON_WIDTH_HINT = 80;
\r
58 private final static int F_TEXT_WIDTH_HINT = 175;
\r
60 private final static int F_COLUMN_COUNT = 3;
\r
62 private Composite fCompositeLogin;
\r
64 private Text fTextUsername;
\r
66 private Text fTextPassword;
\r
68 private Button fButtonOK;
\r
70 private Button fButtonCancel;
\r
72 private boolean fAuthenticated;
\r
74 private Image splashImage;
\r
76 private Image currentBackground;
\r
78 private long fadeStartTime = 0;
\r
80 private boolean fadeComplete = false;
\r
82 private Timer watchdogTimer = new Timer("splash-watchdog");
\r
91 // System.out.println(this + " -> " + OK);
\r
95 // System.out.println(this + " -> " + DIRTY);
\r
99 // if (this != DIRTY) {
\r
100 // System.err.println("ERROR: transition from " + this + " to " + DIRTY);
\r
102 // System.out.println(this + " -> " + UPDATED);
\r
107 private State state = State.INIT;
\r
112 public InteractiveSplashHandler() {
\r
113 fCompositeLogin = null;
\r
114 fTextUsername = null;
\r
115 fTextPassword = null;
\r
117 fButtonCancel = null;
\r
118 fAuthenticated = false;
\r
122 * Takes a screenshot of the desktop and blends the splash screen PNG image
\r
123 * on top of it. The blended result is then set as currentBackground.
\r
127 private void updateBackground1(Shell splash) {
\r
128 // System.out.println("Screenshotting");
\r
129 Point size = splash.getSize();
\r
130 Point pt = splash.getLocation();
\r
131 //System.out.println("location: " + pt + ", size: " + size);
\r
133 splash.setRegion(new Region());
\r
135 // Get screenshot into backgroundImage
\r
136 Rectangle clientArea = splash.getDisplay().getClientArea();
\r
137 //System.out.println("client area: " + clientArea);
\r
138 final Image backgroundImage = new Image(splash.getDisplay(), clientArea.width, clientArea.height);
\r
139 GC gc = new GC(splash.getDisplay());
\r
140 gc.copyArea(backgroundImage, 0, 0);
\r
143 // Combine the splash screen with the background
\r
144 final Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);
\r
145 GC gc2 = new GC(newSplashBackground);
\r
146 gc2.drawImage(backgroundImage, pt.x, pt.y, size.x, size.y, 0, 0, size.x, size.y);
\r
147 gc2.drawImage(splashImage, 0, 0);
\r
150 // Screenshot no longer needed
\r
151 backgroundImage.dispose();
\r
153 Region r = new Region();
\r
154 Rectangle r2 = splashImage.getBounds();
\r
156 splash.setRegion(r);
\r
158 // Switch shell background image, dispose the old one.
\r
159 Image old = splash.getBackgroundImage();
\r
160 splash.setBackgroundImage(newSplashBackground);
\r
161 currentBackground = newSplashBackground;
\r
167 * Takes a screenshot of the desktop and uses that as the background of the
\r
168 * splash as currentBackground.
\r
172 private void updateBackground2(Shell splash) {
\r
173 //System.out.println("Screenshotting");
\r
174 Point size = splash.getSize();
\r
175 Point pt = splash.getLocation();
\r
176 //System.out.println("location: " + pt + ", size: " + size);
\r
178 splash.setRegion(new Region());
\r
180 // Get screenshot into backgroundImage
\r
181 Rectangle clientArea = splash.getDisplay().getClientArea();
\r
182 //System.out.println("client area: " + clientArea);
\r
183 final Image backgroundImage = new Image(splash.getDisplay(), clientArea.width, clientArea.height);
\r
184 GC gc = new GC(splash.getDisplay());
\r
185 gc.copyArea(backgroundImage, 0, 0);
\r
188 // Combine the splash screen with the background
\r
189 final Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);
\r
190 GC gc2 = new GC(newSplashBackground);
\r
191 gc2.drawImage(backgroundImage, pt.x, pt.y, size.x, size.y, 0, 0, size.x, size.y);
\r
194 // Screenshot no longer needed
\r
195 backgroundImage.dispose();
\r
197 Region r = new Region();
\r
198 Rectangle r2 = newSplashBackground.getBounds();
\r
200 splash.setRegion(r);
\r
202 // Switch shell background image, dispose the old one.
\r
203 Image old = splash.getBackgroundImage();
\r
204 splash.setBackgroundImage(newSplashBackground);
\r
205 currentBackground = newSplashBackground;
\r
210 private void initializeBackground(Shell splash) {
\r
211 Point size = splash.getSize();
\r
212 Point pt = splash.getLocation();
\r
213 //System.out.println("location: " + pt + ", size: " + size);
\r
215 // Combine the splash screen with the background
\r
216 Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);
\r
217 ImageData imgData = newSplashBackground.getImageData();
\r
220 Region r = new Region();
\r
221 Rectangle r2 = splashImage.getBounds();
\r
222 Rectangle r3 = new Rectangle(r2.x, r2.y, r2.width, r2.height);
\r
224 splash.setRegion(r);
\r
226 // Switch shell background image, dispose the old one.
\r
227 splash.setBackgroundImage(newSplashBackground);
\r
228 currentBackground = newSplashBackground;
\r
232 public void dispose() {
\r
236 if (splashImage != null)
\r
237 splashImage.dispose();
\r
238 if (currentBackground != null)
\r
239 currentBackground.dispose();
\r
245 * @see org.eclipse.ui.splash.AbstractSplashHandler#init(org.eclipse.swt.widgets.Shell)
\r
247 public void init(final Shell splash) {
\r
249 super.init(splash);
\r
251 ImageDescriptor splashDesc = Activator.getImageDescriptor(SPLASH_IMAGE);
\r
252 if (splashDesc == null) {
\r
253 // If splash-image is not available, do nothing.
\r
256 splashImage = splashDesc.createImage();
\r
257 // System.out.println("logo bounds: " + i.getBounds());
\r
259 splash.setSize(splashImage.getBounds().width, splashImage.getBounds().height);
\r
260 // splash.setRegion(new Region());
\r
262 Point pt = splash.getLocation();
\r
263 pt.x -= splashImage.getBounds().width/2;
\r
264 pt.y -= splashImage.getBounds().height/2;
\r
265 splash.setLocation(pt);
\r
267 // updateSplashImage(splash);
\r
268 updateBackground2(splash);
\r
269 //initializeSplash(splash);
\r
270 state = state.ok();
\r
272 // Configure the shell layout
\r
273 configureUISplash();
\r
276 // Create UI listeners
\r
277 createUIListeners();
\r
278 // Force the splash screen to layout
\r
279 splash.layout(true);
\r
280 // Keep the splash screen visible and prevent the RCP application from
\r
281 // loading until the close button is clicked.
\r
288 private void doEventLoop() {
\r
289 final Shell splash = getSplash();
\r
290 // while (fAuthenticated == false) {
\r
292 // Make sure that the splash doesn't block program startup when it is
\r
294 watchdogTimer.schedule(new TimerTask() {
\r
296 public void run() {
\r
297 // Terminate the timer and complete the fade.
\r
298 // System.out.println("watchdog");
\r
299 watchdogTimer.cancel();
\r
300 fadeComplete = true;
\r
302 }, FADE_TIME_MS + 50);
\r
304 while (!fadeComplete) {
\r
305 if (splash.getDisplay().readAndDispatch() == false) {
\r
306 // Cannot use Display.sleep because it may not wake up until the
\r
307 // window receives events which will not happen if the window is
\r
309 // splash.getDisplay().sleep();
\r
312 } catch (InterruptedException e) {
\r
313 e.printStackTrace();
\r
318 while (splash.getDisplay().readAndDispatch());
\r
320 // System.out.println("ENDING EVENT LOOP");
\r
326 private void createUIListeners() {
\r
327 // Update the translucency
\r
329 for (int in : new int[] { SWT.Activate, SWT.Deactivate, SWT.Show, SWT.Hide, SWT.Iconify, SWT.Deiconify }) {
\r
330 getSplash().addListener(in, new Listener() {
\r
332 public void handleEvent(Event event) {
\r
333 int type = event.type;
\r
334 // System.out.println("[" + state + "][" + event.time + "] event: " + type);
\r
335 // System.out.flush();
\r
337 // switch (state) {
\r
339 // if (type == SWT.Deactivate) {
\r
340 // state = state.dirty();
\r
345 // if (type == SWT.Activate) {
\r
346 // state = state.updated();
\r
347 // updateSplashImage(getSplash());
\r
351 // if (type == SWT.Activate) {
\r
352 // state = state.ok();
\r
362 fCompositeLogin.addListener(SWT.Paint, new Listener() {
\r
364 public void handleEvent(Event event) {
\r
365 // Time elapsed in milliseconds from the beginning of the fade.
\r
366 float timeElapsed = 0;
\r
367 if (fadeStartTime == 0) {
\r
368 fadeStartTime = System.currentTimeMillis();
\r
370 timeElapsed = (System.currentTimeMillis() - fadeStartTime);
\r
372 int fade = Math.min(255, (int) Math.round(255f * timeElapsed / (float) FADE_TIME_MS));
\r
374 fadeComplete = true;
\r
378 gc.drawImage(currentBackground, 0, 0);
\r
380 gc.drawImage(splashImage, 0, 0);
\r
382 if (!fadeComplete) {
\r
383 getSplash().getDisplay().timerExec(25, new Runnable() {
\r
385 public void run() {
\r
386 Shell s = getSplash();
\r
387 if (s != null && !s.isDisposed()) {
\r
388 Point size = s.getSize();
\r
389 s.redraw(0,0, size.x, size.y, true);
\r
397 // Create the OK button listeners
\r
398 // createUIListenersButtonOK();
\r
399 // Create the cancel button listeners
\r
400 // createUIListenersButtonCancel();
\r
406 private void createUIListenersButtonCancel() {
\r
407 fButtonCancel.addSelectionListener(new SelectionAdapter() {
\r
408 public void widgetSelected(SelectionEvent e) {
\r
409 handleButtonCancelWidgetSelected();
\r
417 private void handleButtonCancelWidgetSelected() {
\r
418 // Abort the loading of the RCP application
\r
419 getSplash().getDisplay().close();
\r
424 * configureUISplash
\r
426 private void createUIListenersButtonOK() {
\r
427 fButtonOK.addSelectionListener(new SelectionAdapter() {
\r
428 public void widgetSelected(SelectionEvent e) {
\r
429 handleButtonOKWidgetSelected();
\r
437 private void handleButtonOKWidgetSelected() {
\r
438 String username = fTextUsername.getText();
\r
439 String password = fTextPassword.getText();
\r
440 // Aunthentication is successful if a user provides any username and
\r
442 if ((username.length() > 0) &&
\r
443 (password.length() > 0)) {
\r
444 fAuthenticated = true;
\r
446 MessageDialog.openError(
\r
448 "Authentication Failed", //NON-NLS-1
\r
449 "A username and password must be specified to login."); //NON-NLS-1
\r
456 private void createUI() {
\r
457 // Create the login panel
\r
458 createUICompositeLogin();
\r
459 // Create the blank spanner
\r
460 //createUICompositeBlank();
\r
461 // Create the user name label
\r
462 //createUILabelUserName();
\r
463 // Create the user name text widget
\r
464 //createUITextUserName();
\r
465 // Create the password label
\r
466 //createUILabelPassword();
\r
467 // Create the password text widget
\r
468 //createUITextPassword();
\r
469 // Create the blank label
\r
470 //createUILabelBlank();
\r
471 // Create the OK button
\r
472 //createUIButtonOK();
\r
473 // Create the cancel button
\r
474 //createUIButtonCancel();
\r
480 private void createUIButtonCancel() {
\r
481 // Create the button
\r
482 fButtonCancel = new Button(fCompositeLogin, SWT.PUSH);
\r
483 fButtonCancel.setText("Cancel"); //NON-NLS-1
\r
484 // Configure layout data
\r
485 GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);
\r
486 data.widthHint = F_BUTTON_WIDTH_HINT;
\r
487 data.verticalIndent = 10;
\r
488 fButtonCancel.setLayoutData(data);
\r
494 private void createUIButtonOK() {
\r
495 // Create the button
\r
496 fButtonOK = new Button(fCompositeLogin, SWT.PUSH);
\r
497 fButtonOK.setText("OK"); //NON-NLS-1
\r
498 // Configure layout data
\r
499 GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);
\r
500 data.widthHint = F_BUTTON_WIDTH_HINT;
\r
501 data.verticalIndent = 10;
\r
502 fButtonOK.setLayoutData(data);
\r
508 private void createUILabelBlank() {
\r
509 Label label = new Label(fCompositeLogin, SWT.NONE);
\r
510 label.setVisible(false);
\r
516 private void createUITextPassword() {
\r
517 // Create the text widget
\r
518 int style = SWT.PASSWORD | SWT.BORDER;
\r
519 fTextPassword = new Text(fCompositeLogin, style);
\r
520 // Configure layout data
\r
521 GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);
\r
522 data.widthHint = F_TEXT_WIDTH_HINT;
\r
523 data.horizontalSpan = 2;
\r
524 fTextPassword.setLayoutData(data);
\r
530 private void createUILabelPassword() {
\r
531 // Create the label
\r
532 Label label = new Label(fCompositeLogin, SWT.NONE);
\r
533 label.setText("&Password:"); //NON-NLS-1
\r
534 // Configure layout data
\r
535 GridData data = new GridData();
\r
536 data.horizontalIndent = F_LABEL_HORIZONTAL_INDENT;
\r
537 label.setLayoutData(data);
\r
543 private void createUITextUserName() {
\r
544 // Create the text widget
\r
545 fTextUsername = new Text(fCompositeLogin, SWT.BORDER);
\r
546 // Configure layout data
\r
547 GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);
\r
548 data.widthHint = F_TEXT_WIDTH_HINT;
\r
549 data.horizontalSpan = 2;
\r
550 fTextUsername.setLayoutData(data);
\r
556 private void createUILabelUserName() {
\r
557 // Create the label
\r
558 Label label = new Label(fCompositeLogin, SWT.NONE);
\r
559 label.setText("&User Name:"); //NON-NLS-1
\r
560 // Configure layout data
\r
561 GridData data = new GridData();
\r
562 data.horizontalIndent = F_LABEL_HORIZONTAL_INDENT;
\r
563 label.setLayoutData(data);
\r
569 private void createUICompositeBlank() {
\r
570 Composite spanner = new Composite(fCompositeLogin, SWT.NONE);
\r
571 GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
\r
572 data.horizontalSpan = F_COLUMN_COUNT;
\r
573 spanner.setLayoutData(data);
\r
579 private void createUICompositeLogin() {
\r
580 // Create the composite
\r
581 // fCompositeLogin = new Composite(getSplash(), SWT.NONE);
\r
582 fCompositeLogin = new Canvas(getSplash(), SWT.DOUBLE_BUFFERED);
\r
583 GridLayout layout = new GridLayout(F_COLUMN_COUNT, false);
\r
584 fCompositeLogin.setLayout(layout);
\r
590 private void configureUISplash() {
\r
591 // Configure layout
\r
592 FillLayout layout = new FillLayout();
\r
593 getSplash().setLayout(layout);
\r
594 // Force shell to inherit the splash background
\r
595 getSplash().setBackgroundMode(SWT.INHERIT_DEFAULT);
\r