Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 319ee63acc55479a9f715482d3bc750c9c2b8855 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
/*******************************************************************************
 * Copyright (c) 2004, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui.internal.intro.impl.model;

import java.util.Vector;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IRegistryChangeEvent;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.internal.intro.impl.model.loader.ModelLoaderUtil;
import org.eclipse.ui.internal.intro.impl.presentations.BrowserIntroPartImplementation;
import org.eclipse.ui.internal.intro.impl.presentations.FormIntroPartImplementation;
import org.eclipse.ui.internal.intro.impl.presentations.TextIntroPartImplementation;
import org.eclipse.ui.internal.intro.impl.util.Log;
import org.eclipse.ui.intro.IIntroPart;

/**
 * This class models the presentation element contributed to a config extension
 * point. The Presentation class delegates UI creation to the actual
 * Implementation class, and passes the IntroPart along to this implementation
 * class. Also, dynamic awarness is honored here.
 * <p>
 * Rules:
 * <ul>
 * <li>There is no model class for the "implementation" markup element. This
 * presentation class inherits information from the implementation class that is
 * picked (based on OS, ...).</li>
 * <li>ID attribute of this model class is the id of the picked implementation
 * element.</li>
 * <li>Style attribute in this model class is the style of the picked
 * implementation element.</li>
 * <li>HTMLHeadContent in this model class is the HEAD element under the picked
 * implementation element, only if the implementation element is a Browser
 * implmenetation.</li>
 * <li>The UI model class, AbstractIntroPartImplementation, that represents the
 * IntroPart implementation is cached here for quick access. It is used by intro
 * url actions for manipulation of UI.<br>
 * INTRO:This really should be in a UI model class.
 * <ul>
 */
public class IntroPartPresentation extends AbstractIntroElement {

    protected static final String TAG_PRESENTATION = "presentation"; //$NON-NLS-1$
    private static final String TAG_IMPLEMENTATION = "implementation"; //$NON-NLS-1$
    private static final String TAG_LAUNCH_BAR = "launchBar"; //$NON-NLS-1$    

    private static final String ATT_KIND = "kind"; //$NON-NLS-1$
    private static final String ATT_STYLE = "style"; //$NON-NLS-1$
    private static final String ATT_OS = "os"; //$NON-NLS-1$
    private static final String ATT_WS = "ws"; //$NON-NLS-1$
    protected static final String ATT_HOME_PAGE_ID = "home-page-id"; //$NON-NLS-1$
    protected static final String ATT_STANDBY_PAGE_ID = "standby-page-id"; //$NON-NLS-1$

    protected static final String BROWSER_IMPL_KIND = "html"; //$NON-NLS-1$
    protected static final String FORMS_IMPL_KIND = "swt"; //$NON-NLS-1$
    // this implementation kind if not public api. Only used internally for
    // debugging.
    private static final String TEXT_IMPL_KIND = "text"; //$NON-NLS-1$


    // private String title;
    private String implementationStyle;
    private String implementationKind;
    private String homePageId;
    private String standbyPageId;

    // The Head contributions to this preentation (inherited from child
    // implementation).
    private IntroHead head;

    private AbstractIntroPartImplementation implementation;

    private LaunchBarElement launchBar;

    // CustomizableIntroPart and memento instances. Passed to the Implementation
    // classes.
    private IIntroPart introPart;
    private IMemento memento;

    /**
     * 
     */
    IntroPartPresentation(IConfigurationElement element) {
        super(element);
        homePageId = element.getAttribute(ATT_HOME_PAGE_ID);
        standbyPageId = element.getAttribute(ATT_STANDBY_PAGE_ID);
    }

    private void updatePresentationAttributes(IConfigurationElement element) {
        if (element != null) {
            // reset (ie: inherit) type and style to be implementation type and
            // style. Then handle HEAD content for the case of HTML Browser.
            implementationStyle = element.getAttribute(ATT_STYLE);
            implementationKind = element.getAttribute(ATT_KIND);
            // get Head contribution, regardless of implementation class.
            // Implementation class is created lazily by UI.
            head = getHead(element);
            // Resolve.
            implementationStyle = ModelUtil.resolveURL(implementationStyle,
                element);
        }
    }

    /**
     * Returns the style associated with the Presentation. May be null if no
     * shared presentation style is needed, or in the case of static HTML OOBE.
     * 
     * @return Returns the style.
     */
    public String getImplementationStyle() {
        return implementationStyle;
    }

    /**
     * Returns the type attribute of the implementation picked by this
     * presentation.
     * 
     * @return Returns the implementationKind.
     */
    public String getImplementationKind() {
        return implementationKind;
    }

    public AbstractIntroPartImplementation getIntroParttImplementation() {
        return implementation;
    }


    /**
     * Returns the model class for the Head element under an implementation.
     * Returns null if there is no head contribution.
     * 
     * @param element
     * @return
     */
    private IntroHead getHead(IConfigurationElement element) {
        try {
            // There should only be one head element. Since elements where
            // obtained by name, no point validating name.
            IConfigurationElement[] headElements = element
                .getChildren(IntroHead.TAG_HEAD);
            if (headElements.length == 0)
                // no contributions. done.
                return null;
            IntroHead head = new IntroHead(headElements[0]);
            head.setParent(this);
            return head;
        } catch (Exception e) {
            Log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * Returns the launch bar element if defined in this presentation, or
     * <code>null</code> otherwise.
     * 
     * @since 3.1
     * @return
     */

    public LaunchBarElement getLaunchBar() {
        if (launchBar != null)
            return launchBar;
        IConfigurationElement[] children = getCfgElement().getChildren(
            TAG_LAUNCH_BAR);
        if (children.length > 0) {
            launchBar = new LaunchBarElement(children[0]);
        }
        return launchBar;
    }

    /**
     * @param introPart
     */
    public void init(IIntroPart introPart, IMemento memento) {
        // REVISIT: Called when the actual UI needs to be created. Incomplete
        // separation of model / UI. Will change later. should not get here if
        // there is no valid implementation.
        this.introPart = introPart;
        this.memento = memento;
    }

    /**
     * Creates the UI based on the implementation class.
     * 
     * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
     */
    public void createPartControl(Composite parent) {
        Vector validImplementations = getValidImplementationElements(getCfgElement());
        IConfigurationElement implementationElement = null;
        for (int i = 0; i < validImplementations.size(); i++) {
            implementationElement = (IConfigurationElement) validImplementations
                .elementAt(i);
            // you want to pass primed model.
            updatePresentationAttributes(implementationElement);
            try {
                implementation = createIntroPartImplementation(getImplementationKind());
                if (implementation == null)
                    // failed to create executable.
                    continue;

                implementation.init(introPart, memento);
                implementation.createPartControl(parent);
                if (Log.logInfo)
                    Log.info("Loaded config implementation from: " //$NON-NLS-1$
                            + ModelLoaderUtil.getLogString(
                                implementationElement, "class")); //$NON-NLS-1$
                break;
            } catch (SWTError e) {
                Log.error("Failed to create implementation from: " //$NON-NLS-1$
                        + ModelLoaderUtil.getLogString(implementationElement,
                            "class"), e); //$NON-NLS-1$
                implementation = null;
                implementationElement = null;
            } catch (Exception e) {
                Log.error("Failed to create implementation from: " //$NON-NLS-1$
                        + ModelLoaderUtil.getLogString(implementationElement,
                            "class"), e); //$NON-NLS-1$
                implementation = null;
                implementationElement = null;
            }
        }

        if (implementationElement == null) {
            // worst case scenario. We failed in all cases.
            implementation = new FormIntroPartImplementation();
            try {
                implementation.init(introPart, memento);
            } catch (Exception e) {
                // should never be here.
                Log.error(e.getMessage(), e);
                return;
            }
            implementation.createPartControl(parent);
            Log.warning("Loaded UI Forms implementation as a default Welcome."); //$NON-NLS-1$
        }
    }

    /**
     * Retruns a list of valid implementation elements of the config. Choose
     * correct implementation element based on os atrributes. Rules: get current
     * OS, choose first contributrion, with os that matches OS. Otherwise,
     * choose first contribution with no os. Returns null if no valid
     * implementation is found.
     */
    private Vector getValidImplementationElements(
            IConfigurationElement configElement) {

        Vector validList = new Vector();

        // There can be more than one implementation contribution. Add each
        // valid one. First start with OS, then WS then no OS.
        IConfigurationElement[] implementationElements = configElement
            .getChildren(TAG_IMPLEMENTATION);
        // IConfigurationElement implementationElement = null;

        if (implementationElements.length == 0)
            // no contributions. done.
            return validList;

        String currentOS = Platform.getOS();
        String currentWS = Platform.getWS();

        // first loop through all to find one with matching OS, with or
        // without WS.
        for (int i = 0; i < implementationElements.length; i++) {
            String os = implementationElements[i].getAttribute(ATT_OS);
            if (os == null)
                // no os, no match.
                continue;

            if (listValueHasValue(os, currentOS)) {
                // found implementation with correct OS. Now try if WS
                // matches.
                String ws = implementationElements[i].getAttribute(ATT_WS);
                if (ws == null) {
                    // good OS, and they do not care about WS. we have a
                    // match.
                    validList.add(implementationElements[i]);
                } else {
                    // good OS, and we have WS.
                    if (listValueHasValue(ws, currentWS))
                        validList.add(implementationElements[i]);
                }
            }
        }

        // now loop through all to find one with no OS defined, but with a
        // matching WS.
        for (int i = 0; i < implementationElements.length; i++) {
            String os = implementationElements[i].getAttribute(ATT_OS);
            if (os == null) {
                // found implementation with no OS. Now try if WS
                // matches.
                String ws = implementationElements[i].getAttribute(ATT_WS);
                if (ws == null) {
                    // no OS, and they do not care about WS. we have a
                    // match.
                    validList.add(implementationElements[i]);
                } else {
                    // no OS, and we have WS.
                    if (listValueHasValue(ws, currentWS))
                        validList.add(implementationElements[i]);
                }

            }
        }

        return validList;

    }

    /**
     * Util method that searches for the given value in a comma separated list
     * of values. The list is retrieved as an attribute value of OS, WS.
     * 
     */
    private boolean listValueHasValue(String stringValue, String value) {
        String[] attributeValues = stringValue.split(","); //$NON-NLS-1$
        for (int i = 0; i < attributeValues.length; i++) {
            if (attributeValues[i].equalsIgnoreCase(value))
                return true;
        }
        return false;
    }

    /**
     * Util method to load shared style from given kind.
     */
    public String getSharedStyle(String kind) {

        // There can be more than one implementation contribution.
        IConfigurationElement[] implementationElements = getCfgElement()
            .getChildren(TAG_IMPLEMENTATION);
        // IConfigurationElement implementationElement = null;

        if (implementationElements.length == 0)
            // no implementations. done.
            return null;

        // loop through all to find one with matching kind.
        for (int i = 0; i < implementationElements.length; i++) {
            String aKind = implementationElements[i].getAttribute(ATT_KIND);
            if (aKind.equals(kind)) {
                // found implementation with matching kind.
                String style = implementationElements[i]
                    .getAttribute(ATT_STYLE);
                return ModelUtil.resolveURL(style, getCfgElement());
            }
        }
        return null;
    }


    /**
     * Creates the actual implementation class. Returns null on failure.
     * 
     */
    private AbstractIntroPartImplementation createIntroPartImplementation(
            String implementationType) {
        // quick exits
        if (implementationType == null)
            return null;
        if (!implementationType.equals(BROWSER_IMPL_KIND)
                && !implementationType.equals(FORMS_IMPL_KIND)
                && !implementationType.equals(TEXT_IMPL_KIND))
            return null;

        AbstractIntroPartImplementation implementation = null;
        try {
            if (implementationType.equals(BROWSER_IMPL_KIND))
                implementation = new BrowserIntroPartImplementation();
            else if (implementationType.equals(FORMS_IMPL_KIND))
                implementation = new FormIntroPartImplementation();
            else
                implementation = new TextIntroPartImplementation();
        } catch (Exception e) {
            Log.error("Could not instantiate implementation " //$NON-NLS-1$
                    + implementationType, e);
        }
        return implementation;
    }

    /**
     * Returns the the Customizable Intro Part. may return null if init() has
     * not been called yet on the presentation.
     * 
     * @return Returns the introPart.
     */
    public IIntroPart getIntroPart() {
        return introPart;
    }

    /**
     * Save the current state of the intro. Delegate to the implementation to do
     * the work, as different implementations may have different requirements.
     * 
     * @param memento
     *            the memento in which to store state information
     */
    public void saveState(IMemento memento) {
        if (implementation != null)
            implementation.saveState(memento);
    }


    public void setFocus() {
        if (implementation != null)
            implementation.setFocus();
    }

    public void standbyStateChanged(boolean standby, boolean isStandbyPartNeeded) {
        if (implementation != null)
            implementation.standbyStateChanged(standby, isStandbyPartNeeded);
    }

    public void updateHistory(String location) {
        if (implementation != null)
            implementation.updateHistory(location);
    }

    public boolean navigateForward() {
        if (implementation != null)
            return implementation.navigateForward();
        return false;
    }

    public boolean navigateBackward() {
        if (implementation != null)
            return implementation.navigateBackward();
        return false;
    }

    public boolean navigateHome() {
        if (implementation != null)
            return implementation.navigateHome();
        return false;
    }


    /**
     * Called when the IntroPart is disposed. Forwards the call to the
     * implementation class.
     */
    public void dispose() {
        if (implementation != null)
            implementation.dispose();
    }

    /**
     * Support dynamic awarness. Clear cached models first, then update UI by
     * delegating to implementation.
     * 
     * @see org.eclipse.core.runtime.IRegistryChangeListener#registryChanged(org.eclipse.core.runtime.IRegistryChangeEvent)
     */
    public void registryChanged(IRegistryChangeEvent event) {
        if (implementation != null)
            implementation.registryChanged(event);
    }

    /**
     * @return Returns the homePageId.
     */
    public String getHomePageId() {
        return homePageId;
    }

    /**
     * @return Returns the homePageId.
     */
    public String getStandbyPageId() {
        return standbyPageId;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.internal.intro.impl.model.IntroElement#getType()
     */
    public int getType() {
        return AbstractIntroElement.PRESENTATION;
    }

    /**
     * @return Returns the HTML head conttent to be added to each dynamic html
     *         page in this presentation..
     */
    public IntroHead getHead() {
        return head;
    }




}

Back to the top