0001: /*******************************************************************************
0002: * Copyright (c) 2002, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.internal.cheatsheets.views;
0011:
0012: import java.net.MalformedURLException;
0013: import java.net.URL;
0014: import java.util.ArrayList;
0015: import java.util.Enumeration;
0016: import java.util.Hashtable;
0017: import java.util.Iterator;
0018: import java.util.ListIterator;
0019: import java.util.Map;
0020: import java.util.Properties;
0021: import java.util.StringTokenizer;
0022:
0023: import org.eclipse.core.runtime.FileLocator;
0024: import org.eclipse.core.runtime.IStatus;
0025: import org.eclipse.core.runtime.Path;
0026: import org.eclipse.core.runtime.Platform;
0027: import org.eclipse.core.runtime.Status;
0028: import org.eclipse.help.ui.internal.views.HelpTray;
0029: import org.eclipse.help.ui.internal.views.IHelpPartPage;
0030: import org.eclipse.help.ui.internal.views.ReusableHelpPart;
0031: import org.eclipse.jface.action.Action;
0032: import org.eclipse.jface.dialogs.MessageDialog;
0033: import org.eclipse.jface.dialogs.TrayDialog;
0034: import org.eclipse.jface.window.Window;
0035: import org.eclipse.osgi.util.NLS;
0036: import org.eclipse.swt.SWT;
0037: import org.eclipse.swt.events.DisposeEvent;
0038: import org.eclipse.swt.events.DisposeListener;
0039: import org.eclipse.swt.graphics.Cursor;
0040: import org.eclipse.swt.layout.GridData;
0041: import org.eclipse.swt.layout.GridLayout;
0042: import org.eclipse.swt.widgets.Composite;
0043: import org.eclipse.swt.widgets.Control;
0044: import org.eclipse.swt.widgets.Display;
0045: import org.eclipse.swt.widgets.Event;
0046: import org.eclipse.swt.widgets.Label;
0047: import org.eclipse.swt.widgets.Listener;
0048: import org.eclipse.swt.widgets.Menu;
0049: import org.eclipse.swt.widgets.Shell;
0050: import org.eclipse.swt.widgets.Widget;
0051: import org.eclipse.ui.IMemento;
0052: import org.eclipse.ui.PlatformUI;
0053: import org.eclipse.ui.cheatsheets.CheatSheetListener;
0054: import org.eclipse.ui.cheatsheets.ICheatSheetEvent;
0055: import org.eclipse.ui.cheatsheets.ICheatSheetViewer;
0056: import org.eclipse.ui.forms.widgets.FormToolkit;
0057: import org.eclipse.ui.forms.widgets.ImageHyperlink;
0058: import org.eclipse.ui.internal.cheatsheets.CheatSheetPlugin;
0059: import org.eclipse.ui.internal.cheatsheets.CheatSheetStopWatch;
0060: import org.eclipse.ui.internal.cheatsheets.ICheatSheetResource;
0061: import org.eclipse.ui.internal.cheatsheets.Messages;
0062: import org.eclipse.ui.internal.cheatsheets.actions.IMenuContributor;
0063: import org.eclipse.ui.internal.cheatsheets.composite.model.CompositeCheatSheetModel;
0064: import org.eclipse.ui.internal.cheatsheets.composite.views.CompositeCheatSheetPage;
0065: import org.eclipse.ui.internal.cheatsheets.data.CheatSheet;
0066: import org.eclipse.ui.internal.cheatsheets.data.CheatSheetParser;
0067: import org.eclipse.ui.internal.cheatsheets.data.CheatSheetSaveHelper;
0068: import org.eclipse.ui.internal.cheatsheets.data.ICheatSheet;
0069: import org.eclipse.ui.internal.cheatsheets.data.IParserTags;
0070: import org.eclipse.ui.internal.cheatsheets.data.ParserInput;
0071: import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetElement;
0072: import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetRegistryReader;
0073: import org.eclipse.ui.internal.cheatsheets.state.DefaultStateManager;
0074: import org.eclipse.ui.internal.cheatsheets.state.ICheatSheetStateManager;
0075: import org.eclipse.ui.internal.cheatsheets.state.NoSaveStateManager;
0076: import org.eclipse.ui.internal.cheatsheets.state.TrayStateManager;
0077: import org.osgi.framework.Bundle;
0078:
0079: public class CheatSheetViewer implements ICheatSheetViewer,
0080: IMenuContributor {
0081:
0082: //CS Elements
0083: private CheatSheetElement contentElement;
0084: private ParserInput parserInput;
0085: private String currentID;
0086: private int currentItemNum;
0087: // Used to indicate if an invalid cheat sheet id was specified via setInput.
0088: private boolean invalidCheatSheetId = false;
0089: // Used to indicate if a null cheat sheet id was specified via setInput.
0090: private boolean nullCheatSheetId = false;
0091:
0092: private CheatSheetParser parser;
0093: private ICheatSheet model;
0094: private CheatSheetManager manager;
0095: private CheatSheetSaveHelper saveHelper;
0096:
0097: private CheatSheetExpandRestoreAction expandRestoreAction;
0098: private Action copyAction;
0099:
0100: //ITEMS
0101: private ViewItem currentItem;
0102:
0103: //Lists
0104: private ArrayList expandRestoreList = new ArrayList();
0105: private ArrayList viewItemList = new ArrayList();
0106:
0107: //Composites
0108: protected Composite control;
0109:
0110: private Cursor busyCursor;
0111:
0112: // The page currently displayed, may be a CheatSheetPage, CompositeCheatSheetPage
0113: // or ErrorPage
0114: private Page currentPage;
0115: private Label howToBegin;
0116: private boolean inDialog;
0117: private Listener listener;
0118:
0119: private ICheatSheetStateManager stateManager; // The state manager to use when saving
0120: private ICheatSheetStateManager preTrayManager; // The state manager in use before a tray was opened
0121: private String restorePath;
0122:
0123: private int dialogReturnCode;
0124: private boolean isRestricted;
0125:
0126: /**
0127: * The constructor.
0128: *
0129: * @param inDialog whether or not this viewer will be placed in a modal dialog
0130: */
0131: public CheatSheetViewer(boolean inDialog) {
0132: currentItemNum = -1;
0133: this .inDialog = inDialog;
0134: saveHelper = new CheatSheetSaveHelper();
0135: }
0136:
0137: public void advanceIntroItem() {
0138: resetItemState();
0139: /* LP-item event */
0140: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_DEACTIVATED, introItem);
0141: currentItemNum = 1;
0142: ViewItem nextItem = getViewItemAtIndex(currentItemNum);
0143: if (nextItem.item.isDynamic()) {
0144: nextItem.handleButtons();
0145: }
0146: nextItem.setAsCurrentActiveItem();
0147: /* LP-item event */
0148: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, nextItem);
0149: collapseAllButCurrent(false);
0150:
0151: saveCurrentSheet();
0152: }
0153:
0154: /**
0155: * Reset the state of all the items in this cheatsheet
0156: */
0157: private void resetItemState() {
0158: IntroItem introItem = (IntroItem) getViewItemAtIndex(0);
0159: boolean isStarted = introItem.isCompleted();
0160:
0161: expandRestoreList = new ArrayList();
0162: if (expandRestoreAction != null)
0163: expandRestoreAction.setCollapsed(false);
0164:
0165: clearBackgrounds();
0166: clearIcons();
0167: collapseAllButtons();
0168: if (isStarted)
0169: initManager();
0170:
0171: for (Iterator iter = viewItemList.iterator(); iter.hasNext();) {
0172: ViewItem item = (ViewItem) iter.next();
0173: if (item instanceof CoreItem) {
0174: CoreItem c = (CoreItem) item;
0175: ArrayList l = c.getListOfSubItemCompositeHolders();
0176: if (l != null)
0177: for (int j = 0; j < l.size(); j++) {
0178: ((SubItemCompositeHolder) l.get(j))
0179: .setSkipped(false);
0180: ((SubItemCompositeHolder) l.get(j))
0181: .setCompleted(false);
0182: }
0183: }
0184: }
0185:
0186: if (isStarted)
0187: getManager().fireEvent(
0188: ICheatSheetEvent.CHEATSHEET_RESTARTED);
0189: else
0190: getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_STARTED);
0191:
0192: isStarted = true;
0193: introItem.setAsNormalCollapsed();
0194: introItem.setComplete();
0195: introItem.setRestartImage();
0196: }
0197:
0198: /*package*/
0199: /*
0200: * This function can do one of three things
0201: * 1. If this item has a completion message which has not been displayed, display it
0202: * 2. Otherwise if this is the final item return to the introduction
0203: * 3. If neither condition 1 or 2 is satisfied move to the next item
0204: */
0205: void advanceItem(ImageHyperlink link, boolean markAsCompleted) {
0206: currentItem = (ViewItem) link.getData();
0207: int indexNextItem = getIndexOfItem(currentItem) + 1;
0208: boolean isFinalItem = indexNextItem >= viewItemList.size();
0209:
0210: if (markAsCompleted && currentItem.hasCompletionMessage()
0211: && !currentItem.isCompletionMessageExpanded()) {
0212: currentItem.setCompletionMessageExpanded(isFinalItem);
0213: currentItem.setComplete();
0214: if (isFinalItem) {
0215: getManager().fireEvent(
0216: ICheatSheetEvent.CHEATSHEET_COMPLETED);
0217: }
0218: saveCurrentSheet();
0219: return;
0220: }
0221:
0222: if (indexNextItem < currentItemNum) {
0223: ViewItem vi = getViewItemAtIndex(currentItemNum);
0224: vi.setAsNormalNonCollapsed();
0225: }
0226: if (currentItem != null) {
0227: //set that item to it's original color.
0228: currentItem.setAsNormalCollapsed();
0229: //set that item as complete.
0230: if (markAsCompleted) {
0231: if (!currentItem.isCompleted()) {
0232: currentItem.setComplete();
0233: }
0234: /* LP-item event */
0235: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_COMPLETED, currentItem);
0236: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_DEACTIVATED, currentItem);
0237: } else {
0238: currentItem.setSkipped();
0239: /* LP-item event */
0240: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_SKIPPED, currentItem);
0241: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_DEACTIVATED, currentItem);
0242: }
0243: }
0244: if (!isFinalItem) {
0245: ViewItem nextItem = getViewItemAtIndex(indexNextItem);
0246: currentItemNum = indexNextItem;
0247: if (nextItem != null) {
0248: //Handle lazy button instantiation here.
0249: if (nextItem.item.isDynamic()) {
0250: ((CoreItem) nextItem).handleButtons();
0251: }
0252: nextItem.setAsCurrentActiveItem();
0253: /* LP-item event */
0254: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, nextItem);
0255: currentItem = nextItem;
0256: }
0257:
0258: FormToolkit.ensureVisible(currentItem
0259: .getMainItemComposite());
0260: } else if (indexNextItem == viewItemList.size()) {
0261: if (!currentItem.isCompletionMessageExpanded()) { // The event will already have been fired
0262: getManager().fireEvent(
0263: ICheatSheetEvent.CHEATSHEET_COMPLETED);
0264: }
0265: showIntroItem();
0266: }
0267:
0268: saveCurrentSheet();
0269: }
0270:
0271: private void showIntroItem() {
0272: ViewItem item = getViewItemAtIndex(0);
0273: item.setAsCurrentActiveItem();
0274: }
0275:
0276: /*package*/void advanceSubItem(ImageHyperlink link,
0277: boolean markAsCompleted, int subItemIndex) {
0278: Label l = null;
0279: ArrayList list = null;
0280: SubItemCompositeHolder sich = null;
0281: CoreItem ciws = null;
0282:
0283: currentItem = (ViewItem) link.getData();
0284:
0285: if (currentItem instanceof CoreItem)
0286: ciws = (CoreItem) currentItem;
0287:
0288: if (ciws != null) {
0289: list = ciws.getListOfSubItemCompositeHolders();
0290: sich = (SubItemCompositeHolder) list.get(subItemIndex);
0291: l = sich.getCheckDoneLabel();
0292: }
0293:
0294: if (l != null) {
0295: if (markAsCompleted) {
0296: sich.setCompleted(true);
0297: sich.setSkipped(false);
0298: /* LP-subitem event */
0299: // fireManagerSubItemEvent(ICheatSheetItemEvent.ITEM_COMPLETED, ciws, subItemID);
0300: } else {
0301: sich.setSkipped(true);
0302: sich.setCompleted(false);
0303: /* LP-subitem event */
0304: // fireManagerSubItemEvent(ICheatSheetItemEvent.ITEM_SKIPPED, ciws, subItemID);
0305: }
0306: ciws.refreshItem();
0307: }
0308:
0309: boolean allAttempted = checkAllAttempted(list);
0310: boolean anySkipped = checkContainsSkipped(list);
0311:
0312: if (allAttempted && !anySkipped) {
0313: advanceItem(link, true);
0314: return;
0315: } else if (allAttempted && anySkipped) {
0316: advanceItem(link, false);
0317: return;
0318: }
0319:
0320: setFocus();
0321: saveCurrentSheet();
0322: }
0323:
0324: private boolean checkAllAttempted(ArrayList list) {
0325: for (int i = 0; i < list.size(); i++) {
0326: SubItemCompositeHolder s = (SubItemCompositeHolder) list
0327: .get(i);
0328: if (s.isCompleted() || s.isSkipped()) {
0329: continue;
0330: }
0331: return false;
0332: }
0333: return true;
0334: }
0335:
0336: private boolean checkContainsSkipped(ArrayList list) {
0337: for (int i = 0; i < list.size(); i++) {
0338: SubItemCompositeHolder s = (SubItemCompositeHolder) list
0339: .get(i);
0340: if (s.isSkipped()) {
0341: return true;
0342: }
0343: }
0344: return false;
0345: }
0346:
0347: private boolean loadState() {
0348: try {
0349: Properties props = stateManager.getProperties();
0350:
0351: manager = stateManager.getCheatSheetManager();
0352:
0353: // There is a bug which causes the background of the buttons to
0354: // remain white, even though the color is set. So instead of calling
0355: // clearBackgrounds() only the following line should be needed. D'oh!
0356: // ((ViewItem) viewItemList.get(0)).setOriginalColor();
0357: clearBackgrounds();
0358:
0359: if (props == null) {
0360: getViewItemAtIndex(0).setAsCurrentActiveItem();
0361: /* LP-item event */
0362: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, items[0]);
0363: return true;
0364: }
0365:
0366: boolean buttonIsDown = (Integer.parseInt((String) props
0367: .get(IParserTags.BUTTON)) == 0) ? false : true;
0368: int itemNum = Integer.parseInt((String) props
0369: .get(IParserTags.CURRENT));
0370: ArrayList completedStatesList = (ArrayList) props
0371: .get(IParserTags.COMPLETED);
0372: ArrayList expandedStatesList = (ArrayList) props
0373: .get(IParserTags.EXPANDED);
0374: expandRestoreList = (ArrayList) props
0375: .get(IParserTags.EXPANDRESTORE);
0376: String cid = (String) props.get(IParserTags.ID);
0377: Hashtable completedSubItems = (Hashtable) props
0378: .get(IParserTags.SUBITEMCOMPLETED);
0379: Hashtable skippedSubItems = (Hashtable) props
0380: .get(IParserTags.SUBITEMSKIPPED);
0381:
0382: ArrayList completedSubItemsItemList = new ArrayList();
0383: ArrayList skippedSubItemsItemList = new ArrayList();
0384:
0385: Enumeration e = completedSubItems.keys();
0386: while (e.hasMoreElements())
0387: completedSubItemsItemList.add(e.nextElement());
0388:
0389: Enumeration e2 = skippedSubItems.keys();
0390: while (e2.hasMoreElements())
0391: skippedSubItemsItemList.add(e2.nextElement());
0392:
0393: if (cid != null)
0394: currentID = cid;
0395:
0396: if (itemNum >= 0) {
0397: currentItemNum = itemNum;
0398:
0399: currentItem = getViewItemAtIndex(itemNum);
0400:
0401: CheatSheetStopWatch
0402: .startStopWatch("CheatSheetViewer.checkSavedState()"); //$NON-NLS-1$
0403: for (int i = 0; i < viewItemList.size(); i++) {
0404:
0405: ViewItem item = getViewItemAtIndex(i);
0406: if (i > 0 && item.item.isDynamic()
0407: && i <= currentItemNum) {
0408: item.handleButtons();
0409: item.setOriginalColor();
0410: }
0411:
0412: if (completedStatesList.contains(Integer
0413: .toString(i))) {
0414: item.setComplete();
0415: item.setRestartImage();
0416: } else {
0417: if (i < currentItemNum) {
0418: item.setSkipped();
0419: }
0420: }
0421: if (expandedStatesList
0422: .contains(Integer.toString(i))) {
0423: item.setExpanded();
0424: } else {
0425: item.setCollapsed();
0426: }
0427: if (i > currentItemNum) {
0428: item.setButtonsVisible(false);
0429: item.setCompletionMessageCollapsed();
0430: } else {
0431: item.setButtonsVisible(true);
0432: if (i > currentItemNum || item.isCompleted()) {
0433: item
0434: .setCompletionMessageExpanded(i + 1 >= viewItemList
0435: .size());
0436: } else {
0437: item.setCompletionMessageCollapsed();
0438: }
0439: }
0440: if (expandRestoreList.contains(Integer.toString(i))) {
0441: item.setCollapsed();
0442: }
0443: if (completedSubItemsItemList.contains(Integer
0444: .toString(i))) {
0445: String subItemNumbers = (String) completedSubItems
0446: .get(Integer.toString(i));
0447: StringTokenizer st = new StringTokenizer(
0448: subItemNumbers, ","); //$NON-NLS-1$
0449: if (item instanceof CoreItem) {
0450: CoreItem coreitemws = (CoreItem) item;
0451: ArrayList subItemCompositeHolders = coreitemws
0452: .getListOfSubItemCompositeHolders();
0453: if (subItemCompositeHolders != null) {
0454: while (st.hasMoreTokens()) {
0455: String token = st.nextToken();
0456: ((SubItemCompositeHolder) subItemCompositeHolders
0457: .get(Integer
0458: .parseInt(token)))
0459: .setCompleted(true);
0460: ArrayList l = subItemCompositeHolders;
0461: SubItemCompositeHolder s = (SubItemCompositeHolder) l
0462: .get(Integer
0463: .parseInt(token));
0464: if (s != null
0465: && s.getStartButton() != null) {
0466: s
0467: .getStartButton()
0468: .setImage(
0469: CheatSheetPlugin
0470: .getPlugin()
0471: .getImage(
0472: ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_RESTART));
0473: s
0474: .getStartButton()
0475: .setToolTipText(
0476: Messages.RESTART_TASK_TOOLTIP);
0477: }
0478:
0479: }
0480: }
0481: }
0482: }
0483: if (skippedSubItemsItemList.contains(Integer
0484: .toString(i))) {
0485: String subItemNumbers = (String) skippedSubItems
0486: .get(Integer.toString(i));
0487: StringTokenizer st = new StringTokenizer(
0488: subItemNumbers, ","); //$NON-NLS-1$
0489: if (item instanceof CoreItem) {
0490: CoreItem coreitemws = (CoreItem) item;
0491: while (st.hasMoreTokens()) {
0492: String token = st.nextToken();
0493: ((SubItemCompositeHolder) coreitemws
0494: .getListOfSubItemCompositeHolders()
0495: .get(Integer.parseInt(token)))
0496: .setSkipped(true);
0497: }
0498: }
0499: }
0500: CheatSheetStopWatch
0501: .printLapTime(
0502: "CheatSheetViewer.checkSavedState()", "Time in CheatSheetViewer.checkSavedState() after loop #" + i + ": "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0503: }
0504: CheatSheetStopWatch
0505: .printLapTime(
0506: "CheatSheetViewer.checkSavedState()", "Time in CheatSheetViewer.checkSavedState() after loop: "); //$NON-NLS-1$ //$NON-NLS-2$
0507:
0508: if (buttonIsDown) {
0509: if (expandRestoreAction != null)
0510: expandRestoreAction.setCollapsed(true);
0511: }
0512:
0513: // If the last item is the current one and it is complete then
0514: // we should collapse the last item and set the focus on intro.
0515: // For all other cases, set the current item as the active item.
0516: if (viewItemList.size() - 1 == itemNum
0517: && currentItem.isCompleted()) {
0518: currentItem.setCollapsed();
0519: getViewItemAtIndex(0).getMainItemComposite()
0520: .setFocus();
0521:
0522: // The cheat sheet has been restored but is also completed so fire both events
0523: getManager().fireEvent(
0524: ICheatSheetEvent.CHEATSHEET_RESTORED);
0525: getManager().fireEvent(
0526: ICheatSheetEvent.CHEATSHEET_COMPLETED);
0527: } else {
0528: currentItem.setAsCurrentActiveItem();
0529:
0530: // If the intro item is completed, than the cheat sheet has been restored.
0531: if (getViewItemAtIndex(0).isCompleted())
0532: getManager().fireEvent(
0533: ICheatSheetEvent.CHEATSHEET_RESTORED);
0534: }
0535:
0536: /* LP-item event */
0537: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, currentItem);
0538: } else {
0539: getViewItemAtIndex(0).setAsCurrentActiveItem();
0540: /* LP-item event */
0541: // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, items[0]);
0542: }
0543:
0544: return true;
0545: } catch (Exception e) {
0546: // An exception while restoring the saved state data usually only occurs if
0547: // the cheat sheet has been modified since this previous execution. This most
0548: // often occurs during development of cheat sheets and as such an end user is
0549: // not as likely to encounter this.
0550:
0551: boolean reset = MessageDialog.openConfirm(PlatformUI
0552: .getWorkbench().getActiveWorkbenchWindow()
0553: .getShell(),
0554: Messages.CHEATSHEET_STATE_RESTORE_FAIL_TITLE,
0555: Messages.CHEATSHEET_STATE_RESET_CONFIRM);
0556:
0557: if (reset) {
0558: restart();
0559: return true;
0560: }
0561:
0562: // Log the exception
0563: String stateFile = saveHelper.getStateFile(currentID)
0564: .toOSString();
0565: String message = NLS.bind(
0566: Messages.ERROR_APPLYING_STATE_DATA_LOG,
0567: (new Object[] { stateFile, currentID }));
0568: IStatus status = new Status(IStatus.ERROR,
0569: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
0570: IStatus.OK, message, e);
0571: CheatSheetPlugin.getPlugin().getLog().log(status);
0572:
0573: // Set the currentID to null so it is not saved during internalDispose()
0574: currentID = null;
0575:
0576: internalDispose();
0577:
0578: // Reinitialize a few variables because there is no currentItem or currentPage now
0579: parserInput = null;
0580: currentItem = null;
0581: currentItemNum = -1;
0582: currentPage = null;
0583: expandRestoreList = new ArrayList();
0584: viewItemList = new ArrayList();
0585:
0586: // Create the errorpage to show the user
0587: createErrorPage(Messages.ERROR_APPLYING_STATE_DATA);
0588:
0589: return false;
0590: }
0591: }
0592:
0593: private void clearBackgrounds() {
0594: for (Iterator iter = viewItemList.iterator(); iter.hasNext();) {
0595: ViewItem item = (ViewItem) iter.next();
0596: item.setOriginalColor();
0597: }
0598: }
0599:
0600: private void clearIcons() {
0601: for (Iterator iter = viewItemList.iterator(); iter.hasNext();) {
0602: ViewItem item = (ViewItem) iter.next();
0603: item.setOriginalColor();
0604: if (item.isCompleted() || item.isExpanded()
0605: || item.isSkipped())
0606: item.setIncomplete();
0607: }
0608: }
0609:
0610: private void collapseAllButCurrent(boolean fromAction) {
0611: expandRestoreList = new ArrayList();
0612: try {
0613: ViewItem current = getViewItemAtIndex(currentItemNum);
0614: for (ListIterator iter = viewItemList
0615: .listIterator(viewItemList.size()); iter
0616: .hasPrevious();) {
0617: ViewItem item = (ViewItem) iter.previous();
0618: if (item != current && item.isExpanded()) {
0619: item.setCollapsed();
0620: if (fromAction)
0621: expandRestoreList.add(Integer
0622: .toString(getIndexOfItem(item)));
0623: }
0624: }
0625: } catch (Exception e) {
0626: }
0627: }
0628:
0629: private void collapseAllButtons() {
0630: for (Iterator iter = viewItemList.listIterator(1); iter
0631: .hasNext();) {
0632: ViewItem item = (ViewItem) iter.next();
0633: item.setButtonsVisible(false);
0634: item.setCompletionMessageCollapsed();
0635: }
0636: }
0637:
0638: private void createErrorPage(String message) {
0639: setCollapseExpandButtonEnabled(false);
0640: if (message != null) {
0641: currentPage = new ErrorPage(message);
0642: } else {
0643: currentPage = new ErrorPage();
0644: }
0645: currentPage.createPart(control);
0646: control.layout(true);
0647: }
0648:
0649: private void showStartPage() {
0650: setCollapseExpandButtonEnabled(false);
0651: internalDispose();
0652:
0653: howToBegin = new Label(control, SWT.WRAP);
0654: howToBegin.setText(Messages.INITIAL_VIEW_DIRECTIONS);
0655: howToBegin.setLayoutData(new GridData(GridData.FILL_BOTH));
0656: currentPage = null;
0657: control.layout(true);
0658: }
0659:
0660: private void createErrorPage(IStatus status) {
0661: setCollapseExpandButtonEnabled(false);
0662: currentPage = new ErrorPage(status);
0663: currentPage.createPart(control);
0664: control.layout(true);
0665: }
0666:
0667: /**
0668: * Creates the SWT controls for this workbench part.
0669: * <p>
0670: * Clients should not call this method (the workbench calls this method at
0671: * appropriate times).
0672: * </p>
0673: * <p>
0674: * For implementors this is a multi-step process:
0675: * <ol>
0676: * <li>Create one or more controls within the parent.</li>
0677: * <li>Set the parent layout as needed.</li>
0678: * <li>Register any global actions with the <code>IActionService</code>.</li>
0679: * <li>Register any popup menus with the <code>IActionService</code>.</li>
0680: * <li>Register a selection provider with the <code>ISelectionService</code>
0681: * (optional). </li>
0682: * </ol>
0683: * </p>
0684: *
0685: * @param parent the parent control
0686: */
0687: public void createPartControl(Composite parent) {
0688: control = new Composite(parent, SWT.NONE);
0689: GridLayout layout = new GridLayout();
0690: layout.marginHeight = 0;
0691: layout.marginWidth = 0;
0692: layout.verticalSpacing = 0;
0693: layout.horizontalSpacing = 0;
0694: layout.numColumns = 1;
0695: control.setLayout(layout);
0696:
0697: control.addDisposeListener(new DisposeListener() {
0698: public void widgetDisposed(DisposeEvent e) {
0699: dispose();
0700: }
0701: });
0702:
0703: showStartPage();
0704:
0705: Display display = parent.getDisplay();
0706:
0707: busyCursor = new Cursor(display, SWT.CURSOR_WAIT);
0708:
0709: if (contentElement != null) {
0710: initCheatSheetView();
0711: }
0712: }
0713:
0714: /**
0715: * Called when any TrayDialog is opened. The viewer must react by disabling
0716: * itself and moving the cheat sheet to the dialog's tray if the current item
0717: * was flagged as one that opens a modal dialog.
0718: *
0719: * @param dialog the dialog that was opened
0720: */
0721: private void dialogOpened(final TrayDialog dialog) {
0722: if (isActive()) {
0723: HelpTray tray = (HelpTray) dialog.getTray();
0724: if (tray == null) {
0725: tray = new HelpTray();
0726: dialog.openTray(tray);
0727: }
0728: ReusableHelpPart helpPart = tray.getHelpPart();
0729: IHelpPartPage page = helpPart.createPage(
0730: CheatSheetHelpPart.ID, null, null);
0731: page.setVerticalSpacing(0);
0732: page.setHorizontalMargin(0);
0733: ICheatSheetStateManager trayManager = new TrayStateManager();
0734: preTrayManager = stateManager;
0735: stateManager = trayManager;
0736: saveCurrentSheet(); // Save the state into the tray manager
0737: helpPart.addPart(CheatSheetHelpPart.ID,
0738: new CheatSheetHelpPart(helpPart.getForm().getForm()
0739: .getBody(),
0740: helpPart.getForm().getToolkit(), page
0741: .getToolBarManager(),
0742: contentElement, trayManager));
0743: page.addPart(CheatSheetHelpPart.ID, true);
0744: helpPart.addPage(page);
0745: helpPart.showPage(CheatSheetHelpPart.ID);
0746:
0747: /*
0748: * Disable the viewer until the tray is closed, then show it again.
0749: */
0750: control.setVisible(false);
0751: Display.getCurrent().removeFilter(SWT.Show, listener);
0752:
0753: helpPart.getControl().addListener(SWT.Dispose,
0754: new Listener() {
0755: public void handleEvent(Event event) {
0756: control.setVisible(true);
0757: Display.getCurrent().addFilter(SWT.Show,
0758: listener);
0759: if (preTrayManager != null) {
0760: loadState(); // Load from the tray manager
0761: stateManager = preTrayManager;
0762: preTrayManager = null;
0763: }
0764: dialogReturnCode = dialog.getReturnCode();
0765: }
0766: });
0767: }
0768: }
0769:
0770: /**
0771: * Disposes of this cheat sheet viewer.
0772: */
0773: private void dispose() {
0774: internalDispose();
0775: if (busyCursor != null)
0776: busyCursor.dispose();
0777: }
0778:
0779: /*
0780: * Returns the cheat sheet being viewed.
0781: */
0782: public ICheatSheet getCheatSheet() {
0783: return model;
0784: }
0785:
0786: /* (non-Javadoc)
0787: * @see org.eclipse.ui.cheatsheets.ICheatSheetViewer#getCheatSheetID()
0788: */
0789: public String getCheatSheetID() {
0790: if (getContent() != null) {
0791: return getContent().getID();
0792: }
0793:
0794: return null;
0795: }
0796:
0797: /**
0798: * Returns the current content.
0799: *
0800: * @return CheatSheetElement
0801: */
0802: /*package*/CheatSheetElement getContent() {
0803: return contentElement;
0804: }
0805:
0806: /* (non-Javadoc)
0807: * @see org.eclipse.ui.cheatsheets.ICheatSheetViewer#getControl()
0808: */
0809: public Control getControl() {
0810: return control;
0811: }
0812:
0813: private int getIndexOfItem(ViewItem item) {
0814: int index = viewItemList.indexOf(item);
0815: if (index != -1) {
0816: return index;
0817: }
0818: return 0;
0819: }
0820:
0821: /*package*/CheatSheetManager getManager() {
0822: if (manager == null) {
0823: getNewManager();
0824: }
0825: return manager;
0826: }
0827:
0828: private CheatSheetManager getNewManager() {
0829: manager = new CheatSheetManager(contentElement);
0830: return manager;
0831: }
0832:
0833: private CheatSheetManager initManager() {
0834: CheatSheetManager csManager = getManager();
0835: csManager.setData(new Hashtable());
0836: return csManager;
0837: }
0838:
0839: private ViewItem getViewItemAtIndex(int index) {
0840: if (viewItemList != null && !viewItemList.isEmpty()) {
0841: return (ViewItem) viewItemList.get(index);
0842: }
0843: return null;
0844: }
0845:
0846: /**
0847: * Returns whether or not this viewer contains the given Control, which
0848: * is currently in focus.
0849: *
0850: * @param control the Control currently in focus
0851: * @return whether this viewer contains the given Control or not
0852: */
0853: public boolean hasFocusControl(Control control) {
0854: return (control == this .control)
0855: || (currentPage.getControl() == control);
0856: }
0857:
0858: /**
0859: * If in a dialog-opening step, will add the appropriate listener for
0860: * the cheatsheet to jump into the dialog's tray once opened.
0861: *
0862: * Should be called before executing any action.
0863: */
0864: private void hookDialogListener() {
0865: /*
0866: * org.eclipse.help.ui is an optional dependency; only perform this
0867: * step is this plugin is present.
0868: */
0869: if (!inDialog && isInDialogItem()
0870: && (Platform.getBundle("org.eclipse.help.ui") != null)) { //$NON-NLS-1$
0871: listener = new Listener() {
0872: public void handleEvent(Event event) {
0873: if (isTrayDialog(event.widget)) {
0874: dialogOpened((TrayDialog) ((Shell) event.widget)
0875: .getData());
0876: }
0877: }
0878: };
0879: Display.getCurrent().addFilter(SWT.Show, listener);
0880: }
0881: }
0882:
0883: /**
0884: * Removes the dialog-opening listener, if it was added.
0885: *
0886: * Should be called after executing any action.
0887: */
0888: private void unhookDialogListener() {
0889: if (listener != null) {
0890: Display.getCurrent().removeFilter(SWT.Show, listener);
0891: }
0892: }
0893:
0894: /*
0895: * return true if a cheat sheet was opened successfully
0896: */
0897: private boolean initCheatSheetView() {
0898: CheatSheetStopWatch
0899: .startStopWatch("CheatSheetViewer.initCheatSheetView()"); //$NON-NLS-1$
0900: //Re-initialize list to store items collapsed by expand/restore action on c.s. toolbar.
0901: expandRestoreList = new ArrayList();
0902:
0903: // re set that action to turned off.
0904: if (expandRestoreAction != null)
0905: expandRestoreAction.setCollapsed(false);
0906:
0907: //reset current item to be null; next item too.
0908: currentItem = null;
0909: currentItemNum = 0;
0910: viewItemList = new ArrayList();
0911:
0912: // Reset the page variable
0913: currentPage = null;
0914:
0915: if (howToBegin != null) {
0916: howToBegin.dispose();
0917: howToBegin = null;
0918: }
0919:
0920: // If a null cheat sheet id was specified, return leaving the cheat sheet empty.
0921: if (nullCheatSheetId) {
0922: return false;
0923: }
0924:
0925: if (invalidCheatSheetId) {
0926: createErrorPage(Messages.ERROR_CHEATSHEET_DOESNOT_EXIST);
0927: return false;
0928: }
0929:
0930: // read our contents, if there are problems reading the file an error page should be created.
0931: CheatSheetStopWatch
0932: .printLapTime(
0933: "CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() before readFile() call: "); //$NON-NLS-1$ //$NON-NLS-2$
0934: IStatus parseStatus = readFile();
0935: CheatSheetStopWatch
0936: .printLapTime(
0937: "CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after readFile() call: "); //$NON-NLS-1$ //$NON-NLS-2$
0938: if (!parseStatus.isOK()) {
0939: CheatSheetPlugin.getPlugin().getLog().log(parseStatus);
0940: }
0941: if (parseStatus.getSeverity() == Status.ERROR) {
0942:
0943: // Error during parsing.
0944: // Something is wrong with the Cheat sheet content file at the xml level.
0945:
0946: createErrorPage(parseStatus);
0947: return false;
0948: }
0949:
0950: control.setRedraw(false);
0951: if (model instanceof CheatSheet) {
0952: CheatSheet cheatSheetModel = (CheatSheet) model;
0953:
0954: if (isRestricted
0955: && cheatSheetModel.isContainsCommandOrAction()) {
0956: boolean isOK = MessageDialog.openConfirm(PlatformUI
0957: .getWorkbench().getActiveWorkbenchWindow()
0958: .getShell(),
0959: Messages.CHEATSHEET_FROM_URL_WITH_EXEC_TITLE,
0960: Messages.CHEATSHEET_FROM_URL_WITH_EXEC);
0961:
0962: if (!isOK) {
0963: control.setRedraw(true);
0964: showStartPage();
0965: return true;
0966: }
0967: }
0968:
0969: currentPage = new CheatSheetPage(cheatSheetModel,
0970: viewItemList, this );
0971: setCollapseExpandButtonEnabled(true);
0972: } else if (model instanceof CompositeCheatSheetModel) {
0973: CompositeCheatSheetModel compositeCheatSheetModel = ((CompositeCheatSheetModel) model);
0974: compositeCheatSheetModel.setId(currentID);
0975: currentPage = new CompositeCheatSheetPage(
0976: compositeCheatSheetModel, stateManager);
0977: compositeCheatSheetModel
0978: .setCheatSheetManager(initManager());
0979: setCollapseExpandButtonEnabled(false);
0980: }
0981: CheatSheetStopWatch
0982: .printLapTime(
0983: "CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after CheatSheetPage() call: "); //$NON-NLS-1$ //$NON-NLS-2$
0984: currentPage.createPart(control);
0985: CheatSheetStopWatch
0986: .printLapTime(
0987: "CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after CheatSheetPage.createPart() call: "); //$NON-NLS-1$ //$NON-NLS-2$
0988:
0989: if (model instanceof CheatSheet) {
0990: CheatSheetStopWatch
0991: .printLapTime(
0992: "CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after fireEvent() call: "); //$NON-NLS-1$ //$NON-NLS-2$
0993:
0994: if (!loadState()) {
0995: // An error occurred when apply the saved state data.
0996: control.setRedraw(true);
0997: control.layout();
0998: return true;
0999: }
1000:
1001: getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_OPENED);
1002: }
1003: CheatSheetStopWatch
1004: .printLapTime(
1005: "CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after checkSavedState() call: "); //$NON-NLS-1$ //$NON-NLS-2$
1006:
1007: currentPage.initialized();
1008: control.setRedraw(true);
1009: control.layout();
1010: CheatSheetStopWatch
1011: .printLapTime(
1012: "CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after layout() call: "); //$NON-NLS-1$ //$NON-NLS-2$
1013:
1014: if (currentItem != null && !currentItem.isCompleted())
1015: currentItem.setFocus();
1016: CheatSheetStopWatch
1017: .printLapTime(
1018: "CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() at end of method: "); //$NON-NLS-1$ //$NON-NLS-2$
1019: return true;
1020: }
1021:
1022: private void internalDispose() {
1023: if (manager != null)
1024: manager.fireEvent(ICheatSheetEvent.CHEATSHEET_CLOSED);
1025:
1026: saveCurrentSheet();
1027:
1028: for (Iterator iter = viewItemList.iterator(); iter.hasNext();) {
1029: ViewItem item = (ViewItem) iter.next();
1030: item.dispose();
1031: }
1032:
1033: if (currentPage != null) {
1034: currentPage.dispose();
1035: }
1036: }
1037:
1038: /**
1039: * Returns whether or not the cheat sheet viewer is currently active. This
1040: * means it is visible to the user and enabled.
1041: *
1042: * @return whether or not this viewer is active
1043: */
1044: private boolean isActive() {
1045: Control control = getControl();
1046: if (control != null && !control.isDisposed()) {
1047: Control parent = control.getParent();
1048: return (parent != null && !parent.isDisposed()
1049: && parent.isVisible() && parent.isEnabled());
1050: }
1051: return false;
1052: }
1053:
1054: /*
1055: * Show the collapse/expand button if we have access to the toolbar
1056: */
1057: private void setCollapseExpandButtonEnabled(boolean enable) {
1058: if (expandRestoreAction != null) {
1059: expandRestoreAction.setEnabled(enable);
1060: }
1061: }
1062:
1063: /**
1064: * Returns whether or not the currently active item requires opening a
1065: * modal dialog.
1066: *
1067: * @return whether the current item opens a modal dialog
1068: */
1069: private boolean isInDialogItem() {
1070: ViewItem item = getViewItemAtIndex(currentItemNum);
1071: if (item != null) {
1072: return item.getItem().isDialog();
1073: }
1074: return false;
1075: }
1076:
1077: /**
1078: * Returns whether or not this cheat sheet viewer is inside a modal
1079: * dialog.
1080: *
1081: * @return whether this viewer is inside a modal dialog
1082: */
1083: public boolean isInDialogMode() {
1084: return inDialog;
1085: }
1086:
1087: /**
1088: * Returns whether the given widget is a TrayDialog.
1089: *
1090: * @param widget the widget to check
1091: * @return whether or not the widget is a TrayDialog
1092: */
1093: private boolean isTrayDialog(Widget widget) {
1094: return (widget instanceof Shell && ((Shell) widget).getData() instanceof TrayDialog);
1095: }
1096:
1097: /**
1098: * Read the contents of the cheat sheet file
1099: * @return true if the file was read and parsed without error
1100: */
1101: private IStatus readFile() {
1102: if (parser == null)
1103: parser = new CheatSheetParser();
1104: // If the cheat sheet was registered then
1105: // search for a specific type - composite or simple
1106: int cheatSheetKind = CheatSheetParser.ANY;
1107: if (contentElement.isRegistered()) {
1108: if (contentElement.isComposite()) {
1109: cheatSheetKind = CheatSheetParser.COMPOSITE_ONLY;
1110: } else {
1111: cheatSheetKind = CheatSheetParser.SIMPLE_ONLY;
1112: }
1113: }
1114:
1115: model = parser.parse(parserInput, cheatSheetKind);
1116: return parser.getStatus();
1117: }
1118:
1119: private void restoreExpandStates() {
1120: try {
1121: for (int i = 0; i < expandRestoreList.size(); i++) {
1122: int index = Integer
1123: .parseInt(((String) expandRestoreList.get(i)));
1124: ViewItem item = getViewItemAtIndex(index);
1125: if (!item.isExpanded()) {
1126: item.setExpanded();
1127: }
1128: }
1129: expandRestoreList = null;
1130: } catch (Exception e) {
1131: }
1132: }
1133:
1134: /*package*/void runPerformExecutable(ImageHyperlink link) {
1135: link.setCursor(busyCursor);
1136: currentItem = (ViewItem) link.getData();
1137: CoreItem coreItem = (CoreItem) currentItem;
1138:
1139: if (coreItem != null) {
1140: try {
1141: hookDialogListener();
1142: dialogReturnCode = -1;
1143: IStatus status = coreItem.runExecutable(getManager());
1144: if (status.isOK() && dialogReturnCode != Window.CANCEL) {
1145: coreItem.setRestartImage();
1146: if (!coreItem.hasConfirm()) {
1147: //set that item as complete.
1148: advanceItem(link, true);
1149: saveCurrentSheet();
1150: }
1151: }
1152: if (status.getSeverity() == IStatus.ERROR) {
1153: CheatSheetPlugin.getPlugin().getLog().log(status);
1154: org.eclipse.jface.dialogs.ErrorDialog.openError(
1155: PlatformUI.getWorkbench()
1156: .getActiveWorkbenchWindow()
1157: .getShell(), null, null, status);
1158: }
1159: } finally {
1160: unhookDialogListener();
1161: }
1162: }
1163:
1164: link.setCursor(null);
1165: }
1166:
1167: /*package*/void runSubItemPerformExecutable(ImageHyperlink link,
1168: int subItemIndex) {
1169: CoreItem coreItem = null;
1170: link.setCursor(busyCursor);
1171: currentItem = (ViewItem) link.getData();
1172: coreItem = (CoreItem) currentItem;
1173:
1174: try {
1175: if (coreItem != null) {
1176: hookDialogListener();
1177: if (coreItem.runSubItemExecutable(getManager(),
1178: subItemIndex) == ViewItem.VIEWITEM_ADVANCE
1179: && !coreItem.hasConfirm(subItemIndex)) {
1180: ArrayList l = coreItem
1181: .getListOfSubItemCompositeHolders();
1182: SubItemCompositeHolder s = (SubItemCompositeHolder) l
1183: .get(subItemIndex);
1184: s
1185: .getStartButton()
1186: .setImage(
1187: CheatSheetPlugin
1188: .getPlugin()
1189: .getImage(
1190: ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_RESTART));
1191: s.getStartButton().setToolTipText(
1192: Messages.RESTART_TASK_TOOLTIP);
1193: advanceSubItem(link, true, subItemIndex);
1194: saveCurrentSheet();
1195: }
1196: }
1197: } catch (RuntimeException e) {
1198: IStatus status = new Status(IStatus.ERROR,
1199: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
1200: IStatus.OK, Messages.ERROR_RUNNING_ACTION, e);
1201: CheatSheetPlugin.getPlugin().getLog().log(status);
1202: org.eclipse.jface.dialogs.ErrorDialog.openError(PlatformUI
1203: .getWorkbench().getActiveWorkbenchWindow()
1204: .getShell(), null, null, status);
1205: } finally {
1206: unhookDialogListener();
1207: link.setCursor(null);
1208: }
1209: }
1210:
1211: /*package*/void saveCurrentSheet() {
1212: if (currentID != null) {
1213: if (currentPage instanceof CheatSheetPage) {
1214: Properties properties = saveHelper.createProperties(
1215: currentItemNum, viewItemList,
1216: getExpandRestoreActionState(),
1217: expandRestoreList, currentID, restorePath);
1218: IStatus status = stateManager.saveState(properties,
1219: getManager());
1220: if (!status.isOK()) {
1221: CheatSheetPlugin.getPlugin().getLog().log(status);
1222: }
1223: } else if (currentPage instanceof CompositeCheatSheetPage) {
1224: ((CompositeCheatSheetPage) currentPage).saveState();
1225: }
1226: }
1227: }
1228:
1229: private boolean getExpandRestoreActionState() {
1230: boolean expandRestoreActionState = false;
1231: if (expandRestoreAction != null)
1232: expandRestoreActionState = expandRestoreAction
1233: .isCollapsed();
1234: return expandRestoreActionState;
1235: }
1236:
1237: /*package*/void setContent(CheatSheetElement element,
1238: ICheatSheetStateManager inputStateManager) {
1239: CheatSheetStopWatch
1240: .startStopWatch("CheatSheetViewer.setContent(CheatSheetElement element)"); //$NON-NLS-1$
1241:
1242: // Cleanup previous contents
1243: internalDispose();
1244:
1245: // Set the current content to new content
1246: contentElement = element;
1247: stateManager = inputStateManager;
1248: stateManager.setElement(element);
1249:
1250: currentID = null;
1251: parserInput = null;
1252: if (element != null) {
1253: initInputFields(element);
1254: }
1255:
1256: CheatSheetStopWatch
1257: .printLapTime(
1258: "CheatSheetViewer.setContent(CheatSheetElement element)", "Time in CheatSheetViewer.setContent() before initCheatSheetView() call: "); //$NON-NLS-1$ //$NON-NLS-2$
1259: // Initialize the view with the new contents
1260: boolean cheatSheetOpened = false;
1261: if (control != null) {
1262: cheatSheetOpened = initCheatSheetView();
1263: }
1264: if (!cheatSheetOpened) {
1265: contentElement = null;
1266: stateManager = null;
1267: }
1268: // If the cheat sheet failed to open clear the content element so we don't see an
1269: CheatSheetStopWatch
1270: .printLapTime(
1271: "CheatSheetViewer.setContent(CheatSheetElement element)", "Time in CheatSheetViewer.setContent() after initCheatSheetView() call: "); //$NON-NLS-1$ //$NON-NLS-2$
1272: }
1273:
1274: private void initInputFields(CheatSheetElement element) {
1275: currentID = element.getID();
1276: String contentXml = element.getContentXml();
1277: URL contentURL = null;
1278: restorePath = element.getRestorePath();
1279:
1280: if (contentXml != null) {
1281: parserInput = new ParserInput(contentXml, element.getHref());
1282: return;
1283: }
1284:
1285: // The input was not an XML string, find the content URL
1286: Bundle bundle = null;
1287: if (element != null
1288: && element.getConfigurationElement() != null)
1289: try {
1290: String pluginId = element.getConfigurationElement()
1291: .getContributor().getName();
1292: bundle = Platform.getBundle(pluginId);
1293: } catch (Exception e) {
1294: // do nothing
1295: }
1296: if (bundle != null) {
1297: contentURL = FileLocator.find(bundle, new Path(element
1298: .getContentFile()), null);
1299: }
1300:
1301: if (contentURL == null) {
1302: try {
1303: contentURL = new URL(element.getHref());
1304: } catch (MalformedURLException mue) {
1305: }
1306: }
1307: parserInput = new ParserInput(contentURL,
1308: bundle != null ? bundle.getSymbolicName() : null);
1309: }
1310:
1311: /*package*/void setExpandRestoreAction(
1312: CheatSheetExpandRestoreAction action) {
1313: expandRestoreAction = action;
1314: }
1315:
1316: /**
1317: * Passing the focus request to the viewer's control.
1318: */
1319: public void setFocus() {
1320: //need this to have current item selected. (Assumes that when you reactivate the view you will work with current item.)
1321: if (currentItem != null) {
1322: currentItem.setFocus();
1323: } else {
1324: getControl().setFocus();
1325: }
1326: }
1327:
1328: /* (non-Javadoc)
1329: * @see org.eclipse.ui.cheatsheets.ICheatSheetViewer#setInput(java.lang.String)
1330: */
1331: public void setInput(String id) {
1332: setInput(id, new DefaultStateManager());
1333: }
1334:
1335: public void setInput(String id,
1336: ICheatSheetStateManager inputStateManager) {
1337: CheatSheetStopWatch
1338: .startStopWatch("CheatSheetViewer.setInput(String id)"); //$NON-NLS-1$
1339:
1340: CheatSheetElement element = null;
1341:
1342: if (id == null) {
1343: nullCheatSheetId = true;
1344: } else {
1345: nullCheatSheetId = false;
1346:
1347: element = CheatSheetRegistryReader.getInstance()
1348: .findCheatSheet(id);
1349: if (element == null) {
1350: String message = NLS.bind(
1351: Messages.ERROR_INVALID_CHEATSHEET_ID,
1352: (new Object[] { id }));
1353: IStatus status = new Status(IStatus.ERROR,
1354: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
1355: IStatus.OK, message, null);
1356: CheatSheetPlugin.getPlugin().getLog().log(status);
1357: invalidCheatSheetId = true;
1358: } else {
1359: invalidCheatSheetId = false;
1360: this .isRestricted = false;
1361: }
1362: }
1363:
1364: CheatSheetStopWatch
1365: .printLapTime(
1366: "CheatSheetViewer.setInput(String id)", "Time in CheatSheetViewer.setInput(String id) before setContent() call: "); //$NON-NLS-1$ //$NON-NLS-2$
1367: setContent(element, inputStateManager);
1368: CheatSheetStopWatch
1369: .printLapTime(
1370: "CheatSheetViewer.setInput(String id)", "Time in CheatSheetViewer.setInput(String id) after setContent() call: "); //$NON-NLS-1$ //$NON-NLS-2$
1371:
1372: // Update most recently used cheat sheets list.
1373: CheatSheetPlugin.getPlugin().getCheatSheetHistory()
1374: .add(element);
1375: CheatSheetStopWatch
1376: .printLapTime(
1377: "CheatSheetViewer.setInput(String id)", "Time in CheatSheetViewer.setInput(String id) after getCheatSheetHistory() call: "); //$NON-NLS-1$ //$NON-NLS-2$
1378: }
1379:
1380: /* (non-Javadoc)
1381: * @see org.eclipse.ui.cheatsheets.ICheatSheetViewer#setInput(java.lang.String, java.lang.String, java.net.URL)
1382: */
1383: public void setInput(String id, String name, URL url) {
1384: setInput(id, name, url, new DefaultStateManager(), false);
1385: }
1386:
1387: public void setInputFromXml(String id, String name, String xml,
1388: String basePath) {
1389: if (id == null || name == null || xml == null) {
1390: throw new IllegalArgumentException();
1391: }
1392: CheatSheetElement element = new CheatSheetElement(name);
1393: element.setID(id);
1394: element.setContentXml(xml);
1395: element.setHref(basePath);
1396:
1397: nullCheatSheetId = false;
1398: invalidCheatSheetId = false;
1399: isRestricted = false;
1400: setContent(element, new NoSaveStateManager());
1401: }
1402:
1403: public void setInput(String id, String name, URL url,
1404: ICheatSheetStateManager inputStateManager,
1405: boolean isRestricted) {
1406: if (id == null || name == null || url == null) {
1407: throw new IllegalArgumentException();
1408: }
1409: CheatSheetElement element = new CheatSheetElement(name);
1410: element.setID(id);
1411: element.setHref(url.toString());
1412:
1413: nullCheatSheetId = false;
1414: invalidCheatSheetId = false;
1415: this .isRestricted = isRestricted;
1416: setContent(element, inputStateManager);
1417: }
1418:
1419: /*package*/void toggleExpandRestore() {
1420: if (expandRestoreAction == null)
1421: return;
1422:
1423: if (expandRestoreAction.isCollapsed()) {
1424: restoreExpandStates();
1425: expandRestoreAction.setCollapsed(false);
1426: } else {
1427: collapseAllButCurrent(true);
1428: expandRestoreAction.setCollapsed(true);
1429: }
1430:
1431: }
1432:
1433: public Action getCopyAction() {
1434: return copyAction;
1435: }
1436:
1437: public void setCopyAction(Action copyAction) {
1438: this .copyAction = copyAction;
1439: }
1440:
1441: public void copy() {
1442: if (currentItem != null)
1443: currentItem.copy();
1444: }
1445:
1446: public void addListener(CheatSheetListener listener) {
1447: if (contentElement != null) {
1448: getManager().addListener(listener);
1449: }
1450: }
1451:
1452: public int contributeToViewMenu(Menu menu, int index) {
1453: if (currentPage instanceof IMenuContributor) {
1454: return ((IMenuContributor) currentPage)
1455: .contributeToViewMenu(menu, index);
1456: }
1457: return index;
1458: }
1459:
1460: public void restart() {
1461: resetItemState();
1462: currentItemNum = 0;
1463: collapseAllButCurrent(false);
1464: IntroItem introItem = (IntroItem) getViewItemAtIndex(0);
1465: introItem.setIncomplete();
1466: showIntroItem();
1467: }
1468:
1469: public void saveState(IMemento memento) {
1470: if (currentPage instanceof CheatSheetPage) {
1471: Properties properties = saveHelper.createProperties(
1472: currentItemNum, viewItemList,
1473: getExpandRestoreActionState(), expandRestoreList,
1474: currentID, restorePath);
1475: saveHelper.saveToMemento(properties, getManager(), memento);
1476: }
1477: }
1478:
1479: public void reset(Map cheatSheetData) {
1480: if (currentPage instanceof CheatSheetPage) {
1481: restart();
1482: getManager().setData(cheatSheetData);
1483: } else if (currentPage instanceof CompositeCheatSheetPage) {
1484: ((CompositeCheatSheetPage) currentPage)
1485: .restart(cheatSheetData);
1486: }
1487: }
1488:
1489: public void showError(String message) {
1490: internalDispose();
1491: if (howToBegin != null) {
1492: howToBegin.dispose();
1493: howToBegin = null;
1494: }
1495: createErrorPage(message);
1496: }
1497:
1498: }
|