KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > intro > impl > parts > StandbyPart


1 /*******************************************************************************
2  * Copyright (c) 2004, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.intro.impl.parts;
12
13 import java.util.Enumeration JavaDoc;
14 import java.util.Hashtable JavaDoc;
15
16 import org.eclipse.osgi.util.NLS;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.custom.StackLayout;
19 import org.eclipse.swt.graphics.Point;
20 import org.eclipse.swt.graphics.Rectangle;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Control;
23 import org.eclipse.swt.widgets.Layout;
24 import org.eclipse.ui.IMemento;
25 import org.eclipse.ui.forms.events.HyperlinkAdapter;
26 import org.eclipse.ui.forms.events.HyperlinkEvent;
27 import org.eclipse.ui.forms.widgets.FormToolkit;
28 import org.eclipse.ui.forms.widgets.ImageHyperlink;
29 import org.eclipse.ui.internal.intro.impl.IIntroConstants;
30 import org.eclipse.ui.internal.intro.impl.IntroPlugin;
31 import org.eclipse.ui.internal.intro.impl.Messages;
32 import org.eclipse.ui.internal.intro.impl.model.AbstractIntroPage;
33 import org.eclipse.ui.internal.intro.impl.model.IntroModelRoot;
34 import org.eclipse.ui.internal.intro.impl.model.IntroStandbyContentPart;
35 import org.eclipse.ui.internal.intro.impl.model.loader.ExtensionPointManager;
36 import org.eclipse.ui.internal.intro.impl.model.loader.ModelLoaderUtil;
37 import org.eclipse.ui.internal.intro.impl.util.ImageUtil;
38 import org.eclipse.ui.internal.intro.impl.util.Log;
39 import org.eclipse.ui.internal.intro.impl.util.StringUtil;
40 import org.eclipse.ui.intro.IIntroPart;
41 import org.eclipse.ui.intro.config.CustomizableIntroPart;
42 import org.eclipse.ui.intro.config.IStandbyContentPart;
43
44 /**
45  * Standby part is responsible for managing and creating IStandbycontent parts.
46  * It knows how to create and cache content parts. It also handles saving and
47  * restoring its own state. It does that by caching the id of the last content
48  * part viewed and recreating that part on startup. It also manages the life
49  * cycle of content parts by creating and initializing them at the right
50  * moments. It also passes the momento at appropriate times to these content
51  * parts to enable storing and retrieving of state by content parts. Content
52  * parts are responsible for recreating there own state, including input, from
53  * the passed momemnto. When the Return to Introduction link is clicked, the
54  * Intro goes out of standby content mode, and the standby content parts are not
55  * shown anymore until the user explicitly asks for a part again. This is
56  * accomplished through a data flag on the CustomizableIntroPart control.
57  *
58  */

59 public class StandbyPart implements IIntroConstants {
60
61     private FormToolkit toolkit;
62     private IntroModelRoot model;
63     protected ImageHyperlink returnLink;
64     protected Control separator;
65     private Composite container;
66     protected Composite content;
67     private IIntroPart introPart;
68     private EmptyStandbyContentPart emptyPart;
69     private IMemento memento;
70
71     // hastable has partIds as keys, and ControlKeys are values.
72
private Hashtable JavaDoc cachedContentParts = new Hashtable JavaDoc();
73
74     private ControlKey cachedControlKey;
75
76     class StandbyLayout extends Layout {
77
78         private int VGAP = 9;
79         private int VMARGIN = 5;
80         private int HMARGIN = 5;
81         private int SEPARATOR_HEIGHT = 1;
82
83         /*
84          * (non-Javadoc)
85          *
86          * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite,
87          * int, int, boolean)
88          */

89         protected Point computeSize(Composite composite, int wHint, int hHint,
90                 boolean flushCache) {
91             Point lsize = returnLink.computeSize(SWT.DEFAULT, SWT.DEFAULT,
92                 flushCache);
93             Point csize = content.computeSize(SWT.DEFAULT, SWT.DEFAULT,
94                 flushCache);
95             int width = Math.max(lsize.x + 2 * HMARGIN, csize.x);
96             int height = VMARGIN + lsize.y + VGAP + SEPARATOR_HEIGHT + csize.y;
97             return new Point(width, height);
98         }
99
100         /*
101          * (non-Javadoc)
102          *
103          * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite,
104          * boolean)
105          */

106         protected void layout(Composite composite, boolean flushCache) {
107             Rectangle carea = composite.getClientArea();
108             int lwidth = carea.width - HMARGIN * 2;
109             Point lsize = returnLink.computeSize(lwidth, SWT.DEFAULT,
110                 flushCache);
111             int x = HMARGIN;
112             int y = VMARGIN;
113             returnLink.setBounds(x, y, lsize.x, lsize.y);
114             x = 0;
115             y += lsize.y + VGAP;
116             separator.setBounds(x, y, carea.width, SEPARATOR_HEIGHT);
117             y += SEPARATOR_HEIGHT;
118             content.setBounds(x, y, carea.width, carea.height - VMARGIN
119                     - lsize.y - VGAP - SEPARATOR_HEIGHT);
120         }
121     }
122
123     /**
124      * @param parent
125      */

126     public StandbyPart(IntroModelRoot model) {
127         this.model = model;
128     }
129
130
131     public void init(IIntroPart introPart, IMemento memento) {
132         this.introPart = introPart;
133         this.memento = memento;
134     }
135
136     /*
137      * (non-Javadoc)
138      *
139      * @see org.eclipse.ui.intro.IIntroPart#saveState(org.eclipse.ui.IMemento)
140      */

141     private IMemento getMemento(IMemento memento, String JavaDoc key) {
142         if (memento == null)
143             return null;
144         return memento.getChild(key);
145     }
146
147     public void createPartControl(Composite parent) {
148         toolkit = new FormToolkit(parent.getDisplay());
149         // parent container. Has custom layout. Has return link and content
150
// stack composite.
151
container = toolkit.createComposite(parent);
152         container.setLayout(new StandbyLayout());
153
154         // return hyper link.
155
ImageUtil.registerImage(ImageUtil.BACK, "full/elcl16/home_nav.gif"); //$NON-NLS-1$
156
returnLink = toolkit.createImageHyperlink(container, SWT.WRAP
157                 | SWT.CENTER);
158         returnLink.setImage(ImageUtil.getImage(ImageUtil.BACK));
159         returnLink.addHyperlinkListener(new HyperlinkAdapter() {
160
161             public void linkActivated(HyperlinkEvent e) {
162                 doReturn();
163             }
164         });
165
166         // create horizontal separator
167
separator = toolkit.createCompositeSeparator(container);
168         // content stack container
169
content = toolkit.createComposite(container);
170         StackLayout slayout = new StackLayout();
171         slayout.marginWidth = slayout.marginHeight = 0;
172         content.setLayout(slayout);
173
174         boolean success = false;
175         if (memento != null) {
176             success = restoreState(memento);
177             if (!success)
178                 // add empty standby content.
179
addAndShowEmptyPart(Messages.StandbyPart_canNotRestore);
180         }
181
182         updateReturnLinkLabel();
183     }
184
185     /**
186      * Empty content part used as backup for failures.
187      *
188      */

189     private void addAndShowEmptyPart(String JavaDoc message) {
190         if (emptyPart == null)
191             emptyPart = new EmptyStandbyContentPart();
192         addStandbyContentPart(EMPTY_STANDBY_CONTENT_PART, emptyPart);
193         emptyPart.setMessage(message);
194         setTopControl(EMPTY_STANDBY_CONTENT_PART);
195     }
196
197     /**
198      * Tries to create the last content part viewed, based on content part id..
199      *
200      * @param memento
201      * @return
202      */

203     private boolean restoreState(IMemento memento) {
204         String JavaDoc contentPartId = memento
205             .getString(MEMENTO_STANDBY_CONTENT_PART_ID_ATT);
206         if (contentPartId == null)
207             return false;
208         // create the cached content part. Content parts are responsible for
209
// storing and reading their input state.
210
return showContentPart(contentPartId, null);
211     }
212
213
214     /**
215      * Sets the into part to standby, and shows the passed standby part, with
216      * the given input.
217      *
218      * @param partId
219      * @param input
220      */

221     public boolean showContentPart(String JavaDoc partId, String JavaDoc input) {
222         // Get the IntroStandbyContentPart that maps to the given partId.
223
IntroStandbyContentPart standbyPartContent = ExtensionPointManager
224             .getInst().getSharedConfigExtensionsManager()
225             .getStandbyPart(partId);
226
227         if (standbyPartContent != null) {
228             String JavaDoc standbyContentClassName = standbyPartContent.getClassName();
229             String JavaDoc pluginId = standbyPartContent.getPluginId();
230
231             Object JavaDoc standbyContentObject = ModelLoaderUtil.createClassInstance(
232                 pluginId, standbyContentClassName);
233             if (standbyContentObject instanceof IStandbyContentPart) {
234                 IStandbyContentPart contentPart = (IStandbyContentPart) standbyContentObject;
235                 Control c = addStandbyContentPart(partId, contentPart);
236                 if (c != null) {
237                     try {
238                         setTopControl(partId);
239                         setInput(input);
240                         return true;
241                     } catch (Exception JavaDoc e) {
242                         Log.error("Failed to set the input: " + input //$NON-NLS-1$
243
+ " on standby part: " + partId, e); //$NON-NLS-1$
244
}
245                 }
246
247                 // failed to create the standby part, show empty part and signal
248
// failure.
249
String JavaDoc message = NLS.bind(Messages.StandbyPart_failedToCreate,
250                     partId);
251                 addAndShowEmptyPart(message);
252                 return false;
253
254             }
255         }
256
257         // no content part defined with the passed partId, show empty part and
258
// signal failure.
259
String JavaDoc message = NLS.bind(Messages.StandbyPart_nonDefined, partId);
260         addAndShowEmptyPart(message);
261         return false;
262     }
263
264     /**
265      * Creates a standbyContent part in the stack only if one is not already
266      * created. The partId is used as tke key in the cache. The value is an
267      * instance of ControlKey that wraps a control/StandbyPart pair along with
268      * the corresponding part id. This is needed to retrive the control of a
269      * given standby part. The IMemento should be passed to the StandbyPart when
270      * it is initialized.
271      *
272      * @param standbyContent
273      */

274     public Control addStandbyContentPart(String JavaDoc partId,
275             IStandbyContentPart standbyContent) {
276
277         ControlKey controlKey = getCachedContent(partId);
278         if (controlKey == null) {
279
280             try {
281                 standbyContent.init(introPart, getMemento(memento,
282                     MEMENTO_STANDBY_CONTENT_PART_TAG));
283                 standbyContent.createPartControl(content, toolkit);
284             } catch (Exception JavaDoc e) {
285                 // a standby content part throws a PartInitException, log fact.
286
Log.error(
287                     "Failed to create part for standby part: " + partId, e); //$NON-NLS-1$
288
return null;
289             }
290
291             Control control = standbyContent.getControl();
292             controlKey = new ControlKey(control, standbyContent, partId);
293             cachedContentParts.put(partId, controlKey);
294             if (partId.equals(EMPTY_STANDBY_CONTENT_PART))
295                 // just in case it was created explicity, reuse it.
296
emptyPart = (EmptyStandbyContentPart) standbyContent;
297
298             if (controlKey.getControl() == null) {
299                 // control is null. This means that interface was not
300
// implemented properly. log fact.
301
String JavaDoc message = StringUtil
302                     .concat("Standby Content part: ", partId, //$NON-NLS-1$
303
" has a null Control defined. This prevents the part from being displayed.") //$NON-NLS-1$
304
.toString();
305                 Log.error(message, null);
306                 return null;
307             }
308         }
309
310         return controlKey.getControl();
311     }
312
313
314
315     public void setInput(Object JavaDoc input) {
316         IStandbyContentPart standbyContent = cachedControlKey.getContentPart();
317         standbyContent.setInput(input);
318         updateReturnLinkLabel();
319         container.layout();
320     }
321
322
323     public void setTopControl(String JavaDoc key) {
324         cachedControlKey = getCachedContent(key);
325         if (cachedControlKey != null) {
326             setTopControl(cachedControlKey.getControl());
327         }
328     }
329
330     private void setTopControl(Control c) {
331         StackLayout layout = (StackLayout) content.getLayout();
332         layout.topControl = c;
333         if (c instanceof Composite)
334             ((Composite) c).layout();
335         content.layout();
336         container.layout();
337     }
338
339     private void updateReturnLinkLabel() {
340         String JavaDoc linkText = Messages.StandbyPart_returnToIntro;
341         returnLink.setText(linkText);
342         AbstractIntroPage page = model.getCurrentPage();
343         if (page == null)
344             // page will be null in static intro.
345
return;
346
347         String JavaDoc toolTip = Messages.StandbyPart_returnTo;
348         if (page.getTitle() != null)
349             toolTip += " " + page.getTitle(); //$NON-NLS-1$
350

351         returnLink.setToolTipText(toolTip);
352     }
353
354     protected void doReturn() {
355         // remove the flag to indicate that standbypart is no longer needed.
356
((CustomizableIntroPart) introPart).getControl().setData(
357             IIntroConstants.SHOW_STANDBY_PART, null);
358         IntroPlugin.setIntroStandby(false);
359     }
360
361     /**
362      * Calls dispose on all cached IStandbyContentParts.
363      *
364      */

365     public void dispose() {
366         Enumeration JavaDoc values = cachedContentParts.elements();
367         while (values.hasMoreElements()) {
368             ControlKey controlKey = (ControlKey) values.nextElement();
369             controlKey.getContentPart().dispose();
370         }
371         toolkit.dispose();
372     }
373
374     /**
375      * Save the current state of the standby part. It stores the cached content
376      * part id for later creating it on restart. It also creates another
377      * subclass momento to also give the standby content part its own name
378      * space. This was momentos saved by different content parts will not
379      * conflict.
380      *
381      * @param memento
382      * the memento in which to store state information
383      */

384     public void saveState(IMemento memento) {
385         // save cached content part id.
386
if (cachedControlKey != null) {
387             String JavaDoc contentPartId = cachedControlKey.getContentPartId();
388             if (contentPartId == EMPTY_STANDBY_CONTENT_PART)
389                 // do not create memento for empty standby.
390
return;
391             memento.putString(MEMENTO_STANDBY_CONTENT_PART_ID_ATT,
392                 contentPartId);
393             // give standby part its own child to create a name space for
394
// IStandbyPartContent contribution momentos.
395
IMemento standbyContentPartMemento = memento
396                 .createChild(MEMENTO_STANDBY_CONTENT_PART_TAG);
397             // pass new memento to correct standby part.
398
IStandbyContentPart standbyContentpart = cachedControlKey
399                 .getContentPart();
400             if (standbyContentpart != null)
401                 standbyContentpart.saveState(standbyContentPartMemento);
402         }
403     }
404
405
406     /*
407      * Set focus on the IStandbyContentPart that corresponds to the top control
408      * in the stack.
409      *
410      * @see org.eclipse.ui.internal.intro.impl.parts.IStandbyContentPart#setFocus()
411      */

412     public void setFocus() {
413         // grab foxus first, then delegate. This way if content part does
414
// nothing on focus, part still works.
415
returnLink.setFocus();
416         if (cachedControlKey != null)
417             cachedControlKey.getContentPart().setFocus();
418     }
419
420
421
422     /**
423      * Checks the standby cache stack if we have already created a similar
424      * IStandbyContentPart. If not, returns null.
425      *
426      * @param standbyContent
427      * @return
428      */

429     private ControlKey getCachedContent(String JavaDoc key) {
430         if (cachedContentParts.containsKey(key))
431             return (ControlKey) cachedContentParts.get(key);
432         return null;
433     }
434
435     /*
436      * Model class to wrap Control and IStandbyContentPart pairs, along with the
437      * representing ID..
438      */

439     class ControlKey {
440
441         Control c;
442         IStandbyContentPart part;
443         String JavaDoc contentPartId;
444
445         ControlKey(Control c, IStandbyContentPart part, String JavaDoc contentPartId) {
446             this.c = c;
447             this.part = part;
448             this.contentPartId = contentPartId;
449         }
450
451         /**
452          * @return Returns the c.
453          */

454         public Control getControl() {
455             return c;
456         }
457
458         /**
459          * @return Returns the content part.
460          */

461         public IStandbyContentPart getContentPart() {
462             return part;
463         }
464
465         /**
466          * @return Returns the part id.
467          */

468         public String JavaDoc getContentPartId() {
469             return contentPartId;
470         }
471     }
472
473
474 }
475
Popular Tags