001: /*******************************************************************************
002: * Copyright (c) 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.splash;
011:
012: import org.eclipse.core.runtime.IProgressMonitor;
013: import org.eclipse.jface.dialogs.ProgressIndicator;
014: import org.eclipse.jface.window.Window;
015: import org.eclipse.jface.wizard.ProgressMonitorPart;
016: import org.eclipse.swt.SWT;
017: import org.eclipse.swt.graphics.Color;
018: import org.eclipse.swt.graphics.Font;
019: import org.eclipse.swt.graphics.Point;
020: import org.eclipse.swt.graphics.RGB;
021: import org.eclipse.swt.graphics.Rectangle;
022: import org.eclipse.swt.widgets.Composite;
023: import org.eclipse.swt.widgets.Display;
024: import org.eclipse.swt.widgets.Label;
025: import org.eclipse.swt.widgets.Shell;
026: import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
027:
028: /**
029: * Basic splash implementation that provides an absolute positioned progress bar
030: * and message string that is hooked up to a progress monitor.
031: *
032: * @since 3.3
033: */
034: public abstract class BasicSplashHandler extends AbstractSplashHandler {
035:
036: /**
037: * Hacks the progress monitor to have absolute positioning for its controls.
038: * In addition, all methods that access the controls will be wrapped in an
039: * asynchExec().
040: */
041: class AbsolutePositionProgressMonitorPart extends
042: ProgressMonitorPart {
043: public AbsolutePositionProgressMonitorPart(Composite parent) {
044: super (parent, null);
045: setLayout(null);
046: }
047:
048: public ProgressIndicator getProgressIndicator() {
049: return fProgressIndicator;
050: }
051:
052: public Label getProgressText() {
053: return fLabel;
054: }
055:
056: /* (non-Javadoc)
057: * @see org.eclipse.jface.wizard.ProgressMonitorPart#beginTask(java.lang.String, int)
058: */
059: public void beginTask(final String name, final int totalWork) {
060:
061: updateUI(new Runnable() {
062:
063: public void run() {
064: if (isDisposed())
065: return;
066: AbsolutePositionProgressMonitorPart.super
067: .beginTask(name, totalWork);
068: }
069: });
070:
071: }
072:
073: /*
074: * (non-Javadoc)
075: *
076: * @see org.eclipse.jface.wizard.ProgressMonitorPart#done()
077: */
078: public void done() {
079:
080: updateUI(new Runnable() {
081:
082: public void run() {
083: if (isDisposed())
084: return;
085: AbsolutePositionProgressMonitorPart.super .done();
086: }
087: });
088:
089: }
090:
091: /*
092: * (non-Javadoc)
093: *
094: * @see org.eclipse.jface.wizard.ProgressMonitorPart#internalWorked(double)
095: */
096: public void internalWorked(final double work) {
097:
098: updateUI(new Runnable() {
099:
100: public void run() {
101: if (isDisposed())
102: return;
103: AbsolutePositionProgressMonitorPart.super
104: .internalWorked(work);
105: }
106: });
107:
108: }
109:
110: /*
111: * (non-Javadoc)
112: *
113: * @see org.eclipse.jface.wizard.ProgressMonitorPart#setFont(org.eclipse.swt.graphics.Font)
114: */
115: public void setFont(final Font font) {
116:
117: updateUI(new Runnable() {
118:
119: public void run() {
120: if (isDisposed())
121: return;
122: AbsolutePositionProgressMonitorPart.super
123: .setFont(font);
124: }
125: });
126:
127: }
128:
129: /*
130: * (non-Javadoc)
131: *
132: * @see org.eclipse.jface.wizard.ProgressMonitorPart#updateLabel()
133: */
134: protected void updateLabel() {
135:
136: updateUI(new Runnable() {
137:
138: public void run() {
139: if (isDisposed())
140: return;
141: AbsolutePositionProgressMonitorPart.super
142: .updateLabel();
143: }
144: });
145:
146: }
147: }
148:
149: private Color foreground = null;
150: private AbsolutePositionProgressMonitorPart monitor;
151: private Rectangle messageRect;
152: private Rectangle progressRect;
153:
154: /*
155: * (non-Javadoc)
156: *
157: * @see org.eclipse.ui.splash.AbstractSplashHandler#getBundleProgressMonitor()
158: */
159: public IProgressMonitor getBundleProgressMonitor() {
160: if (monitor == null) {
161: Composite parent = new Composite(getSplash(), Window
162: .getDefaultOrientation());
163: Point size = getSplash().getSize();
164: parent.setBounds(new Rectangle(0, 0, size.x, size.y));
165: monitor = new AbsolutePositionProgressMonitorPart(parent);
166: monitor.setSize(size);
167: if (progressRect != null)
168: monitor.getProgressIndicator().setBounds(progressRect);
169: else
170: monitor.getProgressIndicator().setVisible(false);
171:
172: if (messageRect != null)
173: monitor.getProgressText().setBounds(messageRect);
174: else
175: monitor.getProgressText().setVisible(false);
176:
177: if (foreground != null)
178: monitor.getProgressText().setForeground(foreground);
179: monitor.setBackgroundMode(SWT.INHERIT_FORCE);
180: monitor.setBackgroundImage(getSplash().getShell()
181: .getBackgroundImage());
182: }
183: return monitor;
184: }
185:
186: /*
187: * (non-Javadoc)
188: *
189: * @see org.eclipse.ui.splash.AbstractSplashHandler#dispose()
190: */
191: public void dispose() {
192: super .dispose();
193: if (foreground != null)
194: foreground.dispose();
195: }
196:
197: /**
198: * Set the foreground text color. This method has no effect after
199: * {@link #getBundleProgressMonitor()} has been invoked.
200: *
201: * @param foregroundRGB
202: * the color
203: */
204: protected void setForeground(RGB foregroundRGB) {
205: if (monitor != null)
206: return;
207: if (this .foreground != null)
208: this .foreground.dispose();
209: this .foreground = new Color(
210: getSplash().getShell().getDisplay(), foregroundRGB);
211: }
212:
213: /**
214: * Get the foreground text color. This color should not be disposed by
215: * callers.
216: *
217: * @return the foreground color
218: */
219: protected Color getForeground() {
220: return foreground;
221: }
222:
223: /**
224: * Set the location of the message text in the splash. This method has no
225: * effect after {@link #getBundleProgressMonitor()} has been invoked.
226: *
227: * @param messageRect
228: * the location of the message text
229: */
230: protected void setMessageRect(Rectangle messageRect) {
231: this .messageRect = messageRect;
232: }
233:
234: /**
235: * Set the location of the progress bar in the splash. This method has no
236: * effect after {@link #getBundleProgressMonitor()} has been invoked.
237: *
238: * @param progressRect
239: * the location of the progress bar
240: */
241: protected void setProgressRect(Rectangle progressRect) {
242: this .progressRect = progressRect;
243: }
244:
245: /**
246: * Get the composite on which any supplemental controls should be drawn.
247: * This will not have a layout set and clients are responsible for setting
248: * the location of child controls manually.
249: *
250: * <p>
251: * This method must be called in the
252: * {@link #init(org.eclipse.swt.widgets.Shell)} method of a subclasses to
253: * ensure proper creation of controls
254: * </p>
255: *
256: * <p>
257: * Please note that the default implementation of this method assumes that
258: * the {@link IProgressMonitor} returned from
259: * {@link #getBundleProgressMonitor()} can be safely casted to a
260: * {@link Composite}. If this is not the case this method must be
261: * reimplemented to reflect the new progress controls.
262: * </p>
263: *
264: * @see #init(org.eclipse.swt.widgets.Shell)
265: * @return the composite
266: */
267: protected Composite getContent() {
268: return (Composite) getBundleProgressMonitor();
269: }
270:
271: /**
272: * Perform some update on the splash. If called from a non-UI thread it will
273: * be wrapped by a runnable that may be run before the workbench has been
274: * fully realized.
275: *
276: * @param r
277: * the update runnable
278: * @throws Throwable
279: */
280: private void updateUI(final Runnable r) {
281: Shell splashShell = getSplash();
282: if (splashShell == null || splashShell.isDisposed())
283: return;
284:
285: Display display = splashShell.getDisplay();
286:
287: if (Thread.currentThread() == display.getThread())
288: r.run(); // run immediatley if we're on the UI thread
289: else {
290: // wrapper with a StartupRunnable to ensure that it will run before
291: // the UI is fully initialized
292: StartupRunnable startupRunnable = new StartupRunnable() {
293:
294: public void runWithException() throws Throwable {
295: r.run();
296: }
297: };
298: display.asyncExec(startupRunnable);
299: }
300: }
301: }
|