001: /*******************************************************************************
002: * Copyright (c) 2004, 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.internal.intro.impl.model;
011:
012: import org.eclipse.core.runtime.IRegistryChangeEvent;
013: import org.eclipse.core.runtime.PerformanceStats;
014: import org.eclipse.jface.action.Action;
015: import org.eclipse.jface.action.IToolBarManager;
016: import org.eclipse.swt.widgets.Composite;
017: import org.eclipse.ui.IActionBars;
018: import org.eclipse.ui.IMemento;
019: import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
020: import org.eclipse.ui.internal.intro.impl.IIntroConstants;
021: import org.eclipse.ui.internal.intro.impl.IntroPlugin;
022: import org.eclipse.ui.internal.intro.impl.Messages;
023: import org.eclipse.ui.internal.intro.impl.model.viewer.IntroModelContentProvider;
024: import org.eclipse.ui.internal.intro.impl.model.viewer.IntroModelLabelProvider;
025: import org.eclipse.ui.internal.intro.impl.util.ImageUtil;
026: import org.eclipse.ui.internal.intro.impl.util.Log;
027: import org.eclipse.ui.internal.intro.impl.util.Util;
028: import org.eclipse.ui.intro.IIntroPart;
029: import org.eclipse.ui.intro.config.CustomizableIntroPart;
030:
031: /**
032: * UI Implementation class that represents a Presentation Part. This class is
033: * instantiated from plugin markup and so we need a default constructor,
034: * including in subclasses. It has some base methods, including maintaining a
035: * history of navigation locations. Also, dynamic awarness is honored here.
036: *
037: */
038: public abstract class AbstractIntroPartImplementation {
039:
040: // CustomizableIntroPart instance.
041: private CustomizableIntroPart introPart = null;
042:
043: // IMemento for restoring state.
044: private IMemento memento;
045:
046: protected History history = new History();
047:
048: // flag used to enable logging of perf data for full UI creation only once.
049: // Since standbyStateChanged is called several times, flag is used in method
050: // to filter out all subsequent calls.
051: boolean logUIcreationTime = true;
052:
053: // Global actions
054: protected Action backAction = new Action() {
055:
056: {
057: setToolTipText(Messages.Browser_backwardButton_tooltip);
058: setImageDescriptor(ImageUtil
059: .createImageDescriptor("full/elcl16/backward_nav.gif")); //$NON-NLS-1$
060: setDisabledImageDescriptor(ImageUtil
061: .createImageDescriptor("full/dlcl16/backward_nav.gif")); //$NON-NLS-1$
062: }
063:
064: public void run() {
065: navigateBackward();
066: }
067: };
068:
069: protected Action forwardAction = new Action() {
070:
071: {
072: setToolTipText(Messages.Browser_forwardButton_tooltip);
073: setImageDescriptor(ImageUtil
074: .createImageDescriptor("full/elcl16/forward_nav.gif")); //$NON-NLS-1$
075: setDisabledImageDescriptor(ImageUtil
076: .createImageDescriptor("full/dlcl16/forward_nav.gif")); //$NON-NLS-1$
077: }
078:
079: public void run() {
080: navigateForward();
081: }
082: };
083:
084: protected Action homeAction = new Action() {
085:
086: {
087: setToolTipText(Messages.Browser_homeButton_tooltip);
088: setImageDescriptor(ImageUtil
089: .createImageDescriptor("full/elcl16/home_nav.gif")); //$NON-NLS-1$
090: setDisabledImageDescriptor(ImageUtil
091: .createImageDescriptor("full/dlcl16/home_nav.gif")); //$NON-NLS-1$
092: }
093:
094: public void run() {
095: navigateHome();
096: }
097: };
098:
099: protected Action viewIntroModelAction = new Action() {
100:
101: {
102: setToolTipText(Messages.IntroPart_showContentButton_tooltip);
103: setImageDescriptor(ImageUtil
104: .createImageDescriptor("contents_view.gif")); //$NON-NLS-1$
105: }
106:
107: public void run() {
108: ElementTreeSelectionDialog treeViewer = new ElementTreeSelectionDialog(
109: getIntroPart().getIntroSite().getShell(),
110: new IntroModelLabelProvider(),
111: new IntroModelContentProvider());
112: treeViewer.setInput(getModel());
113: treeViewer.open();
114: }
115: };
116:
117: /**
118: * Creates the UI based on this implementation class. .
119: *
120: * @param parent
121: */
122: public abstract void createPartControl(Composite parent);
123:
124: /**
125: * Called when the init method is called in the IIntroPart. Subclasses may
126: * extend, for example to get the passed Memento. When extending, make sure
127: * you include a call to super.
128: *
129: * @param introPart
130: */
131: public void init(IIntroPart introPart, IMemento memento) {
132: // we know the class type to cast to.
133: this .introPart = (CustomizableIntroPart) introPart;
134: this .memento = memento;
135: }
136:
137: /**
138: * @return
139: */
140: public IntroModelRoot getModel() {
141: return IntroPlugin.getDefault().getIntroModelRoot();
142: }
143:
144: /**
145: * @return Returns the introPart.
146: */
147: public CustomizableIntroPart getIntroPart() {
148: return introPart;
149: }
150:
151: /**
152: * Updates the UI navigation history with either a real URL.
153: *
154: * @param location
155: */
156: public void updateHistory(String location) {
157: history.updateHistory(location);
158: updateNavigationActionsState();
159: }
160:
161: /**
162: * Updates the UI navigation history with a page ID.
163: *
164: * @param pageId
165: */
166: public void updateHistory(AbstractIntroPage page) {
167: history.updateHistory(page);
168: updateNavigationActionsState();
169: }
170:
171: /**
172: * Subclasses must implement to set the state of the navigation actions in
173: * the toolbar.
174: *
175: */
176: public abstract void setFocus();
177:
178: /**
179: * Subclasses must implement to update the intro view actions when history
180: * is updated.
181: *
182: */
183: protected abstract void updateNavigationActionsState();
184:
185: public abstract boolean navigateBackward();
186:
187: public abstract boolean navigateForward();
188:
189: public abstract boolean navigateHome();
190:
191: /**
192: * Called when the IntroPart is disposed. Subclasses should override to
193: * dispose of resources. By default, this implementation does nothing.
194: */
195: public void dispose() {
196: // no-op
197: }
198:
199: /*
200: * Add the Intro Model Viewer as an action to all implementations.
201: */
202: protected void addToolBarActions() {
203: // Handle menus:
204: IActionBars actionBars = getIntroPart().getIntroSite()
205: .getActionBars();
206: IToolBarManager toolBarManager = actionBars.getToolBarManager();
207: toolBarManager.add(viewIntroModelAction);
208: toolBarManager.update(true);
209: actionBars.updateActionBars();
210: }
211:
212: /**
213: * Called when the Intro changes state. This method should not be
214: * subclassed. It adds performance logging calls. Subclasses must implement
215: * doStandbyStateChanged instead.
216: *
217: * @param standby
218: */
219: public void standbyStateChanged(boolean standby,
220: boolean isStandbyPartNeeded) {
221: PerformanceStats setStandbyStateStats = null;
222: long start = 0;
223: if (Log.logPerformance) {
224: if (logUIcreationTime && PerformanceStats.ENABLED) {
225: PerformanceStats stats = PerformanceStats.getStats(
226: IIntroConstants.PERF_UI_ZOOM,
227: IIntroConstants.INTRO);
228: stats.endRun();
229: Util
230: .logPerformanceMessage(
231: "(perf stats) time spent in UI code before content is displayed (standbyStateChanged event is fired) ", //$NON-NLS-1$
232: stats.getRunningTime());
233: stats.reset();
234: }
235:
236: // standby time.
237: setStandbyStateStats = PerformanceStats.getStats(
238: IIntroConstants.PERF_SET_STANDBY_STATE,
239: IIntroConstants.INTRO);
240: setStandbyStateStats.startRun();
241: start = System.currentTimeMillis();
242: }
243:
244: doStandbyStateChanged(standby, isStandbyPartNeeded);
245:
246: // now log performance
247: if (Log.logPerformance) {
248: if (PerformanceStats.ENABLED) {
249: setStandbyStateStats.endRun();
250: Util
251: .logPerformanceMessage(
252: "(perf stats) setting standby state (zooming, displaying content) took:", //$NON-NLS-1$
253: +setStandbyStateStats.getRunningTime());
254: setStandbyStateStats.reset();
255: } else
256: Util
257: .logPerformanceTime(
258: "setting standby state (zooming, generating content, setText() ) took:", //$NON-NLS-1$
259: +start);
260:
261: if (logUIcreationTime) {
262: if (PerformanceStats.ENABLED) {
263: PerformanceStats stats = PerformanceStats.getStats(
264: IIntroConstants.PERF_VIEW_CREATION_TIME,
265: IIntroConstants.INTRO);
266: stats.endRun();
267: Util
268: .logPerformanceMessage(
269: "END - (perf stats): creating CustomizableIntroPart view took:", //$NON-NLS-1$
270: +stats.getRunningTime());
271: stats.reset();
272: } else
273: Util
274: .logPerformanceTime(
275: "END: creating CustomizableIntroPart view took:", //$NON-NLS-1$
276: +IntroPlugin.getDefault()
277: .gettUICreationStartTime());
278:
279: // prevent further logging of UI creation time.
280: logUIcreationTime = false;
281: }
282:
283: }
284: }
285:
286: /*
287: * Subclasses must implement the actual logic for the method.
288: */
289: protected abstract void doStandbyStateChanged(boolean standby,
290: boolean isStandbyPartNeeded);
291:
292: /**
293: * Save the current state of the intro. Currently, we only store information
294: * about the most recently visited intro page. In static case, the last HTML
295: * page is remembered. In dynamic case, the last UI page or HTML page is
296: * remembered.
297: *
298: * Note: This method saves the last visited intro page in a dynamic case.
299: * Subclasses need to extend to get the desired behavior relavent to the
300: * specific implementation. Broswer implementation needs to cache an http
301: * web page, if it happens to be the last page visited.
302: *
303: * @param memento
304: */
305: public void saveState(IMemento memento) {
306: saveCurrentPage(memento);
307: }
308:
309: /**
310: * This method saves the most recently visited dynamic intro page in the
311: * memento. If a given implementation requires saving alternative
312: * information (e.g., information about the most recently visited static
313: * page) it should override this method.
314: *
315: * @param memento
316: */
317: protected void saveCurrentPage(IMemento memento) {
318: IntroModelRoot model = getModel();
319:
320: if (memento == null || model == null)
321: return;
322: String currentPage = model.getCurrentPageId();
323: if (currentPage != null && currentPage.length() > 0) {
324: memento.putString(IIntroConstants.MEMENTO_CURRENT_PAGE_ATT,
325: currentPage);
326: }
327: }
328:
329: /**
330: * get the last page if it was stored in memento. This page is the last
331: * visited intro page. It can be a intro page id, in the case of dynamic
332: * intro. Or it can be an http in the case of static intro. It can also be
333: * an http in the case of dynamic intro where the last visited page is a
334: * url.
335: */
336: protected String getCachedCurrentPage() {
337: // Check to see if the start page has been overriden because
338: // content
339: String newContentPage = ExtensionMap.getInstance()
340: .getStartPage();
341: if (newContentPage != null) {
342: return newContentPage;
343: }
344: IMemento memento = getMemento();
345: if (memento == null)
346: return null;
347: return memento
348: .getString(IIntroConstants.MEMENTO_CURRENT_PAGE_ATT);
349: }
350:
351: /**
352: * @return Returns the memento passed on creation.
353: */
354: public IMemento getMemento() {
355: return memento;
356: }
357:
358: /**
359: * Support dynamic awarness. Clear cached models first, then update UI by
360: * delegating to implementation.
361: *
362: * @see org.eclipse.core.runtime.IRegistryChangeListener#registryChanged(org.eclipse.core.runtime.IRegistryChangeEvent)
363: */
364: public void registryChanged(IRegistryChangeEvent event) {
365: history.clear();
366: // give implementation a chance to react to change.
367: handleRegistryChanged(event);
368: }
369:
370: /*
371: * Handle reacting to plugin registry changes. This method will only be
372: * called when regitry changes pertaining to Intro extension points is
373: * detected.
374: */
375: protected abstract void handleRegistryChanged(
376: IRegistryChangeEvent event);
377:
378: public History getHistory() {
379: return history;
380: }
381:
382: }
|