| /******************************************************************************* |
| * Copyright (c) 2002, 2019 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Tom Hofmann, Perspectix AG - https://bugs.eclipse.org/bugs/show_bug.cgi?id=291750 |
| * Asma Smaoui - CEA LIST - https://bugs.eclipse.org/bugs/show_bug.cgi?id=517379 |
| * Christoph Läubrich - Bug 552773 - Simplify logging in platform code base |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.cheatsheets.views; |
| |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.ListIterator; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.core.runtime.FileLocator; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.help.ui.internal.views.HelpTray; |
| import org.eclipse.help.ui.internal.views.IHelpPartPage; |
| import org.eclipse.help.ui.internal.views.ReusableHelpPart; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.dialogs.TrayDialog; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Cursor; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Widget; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.cheatsheets.CheatSheetListener; |
| import org.eclipse.ui.cheatsheets.ICheatSheetEvent; |
| import org.eclipse.ui.cheatsheets.ICheatSheetViewer; |
| import org.eclipse.ui.forms.widgets.FormToolkit; |
| import org.eclipse.ui.forms.widgets.ImageHyperlink; |
| import org.eclipse.ui.internal.cheatsheets.CheatSheetPlugin; |
| import org.eclipse.ui.internal.cheatsheets.CheatSheetStopWatch; |
| import org.eclipse.ui.internal.cheatsheets.ICheatSheetResource; |
| import org.eclipse.ui.internal.cheatsheets.Messages; |
| import org.eclipse.ui.internal.cheatsheets.actions.IMenuContributor; |
| import org.eclipse.ui.internal.cheatsheets.composite.model.CompositeCheatSheetModel; |
| import org.eclipse.ui.internal.cheatsheets.composite.views.CompositeCheatSheetPage; |
| import org.eclipse.ui.internal.cheatsheets.data.CheatSheet; |
| import org.eclipse.ui.internal.cheatsheets.data.CheatSheetParser; |
| import org.eclipse.ui.internal.cheatsheets.data.CheatSheetSaveHelper; |
| import org.eclipse.ui.internal.cheatsheets.data.ICheatSheet; |
| import org.eclipse.ui.internal.cheatsheets.data.IParserTags; |
| import org.eclipse.ui.internal.cheatsheets.data.ParserInput; |
| import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetElement; |
| import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetRegistryReader; |
| import org.eclipse.ui.internal.cheatsheets.state.DefaultStateManager; |
| import org.eclipse.ui.internal.cheatsheets.state.ICheatSheetStateManager; |
| import org.eclipse.ui.internal.cheatsheets.state.NoSaveStateManager; |
| import org.eclipse.ui.internal.cheatsheets.state.TrayStateManager; |
| import org.osgi.framework.Bundle; |
| |
| public class CheatSheetViewer implements ICheatSheetViewer, IMenuContributor { |
| |
| //CS Elements |
| private CheatSheetElement contentElement; |
| private ParserInput parserInput; |
| private String currentID; |
| private int currentItemNum; |
| // Used to indicate if an invalid cheat sheet id was specified via setInput. |
| private boolean invalidCheatSheetId = false; |
| // Used to indicate if a null cheat sheet id was specified via setInput. |
| private boolean nullCheatSheetId = false; |
| |
| private CheatSheetParser parser; |
| private ICheatSheet model; |
| private CheatSheetManager manager; |
| private CheatSheetSaveHelper saveHelper; |
| |
| private CheatSheetExpandRestoreAction expandRestoreAction; |
| private Action copyAction; |
| |
| //ITEMS |
| private ViewItem currentItem; |
| |
| //Lists |
| private ArrayList<String> expandRestoreList = new ArrayList<>(); |
| private ArrayList<ViewItem> viewItemList = new ArrayList<>(); |
| |
| //Composites |
| protected Composite control; |
| |
| private Cursor busyCursor; |
| |
| // The page currently displayed, may be a CheatSheetPage, CompositeCheatSheetPage |
| // or ErrorPage |
| private Page currentPage; |
| private Label howToBegin; |
| private boolean inDialog; |
| private Listener listener; |
| |
| private ICheatSheetStateManager stateManager; // The state manager to use when saving |
| private ICheatSheetStateManager preTrayManager; // The state manager in use before a tray was opened |
| private String restorePath; |
| |
| private int dialogReturnCode; |
| private boolean isRestricted; |
| |
| /** |
| * The constructor. |
| * |
| * @param inDialog whether or not this viewer will be placed in a modal dialog |
| */ |
| public CheatSheetViewer(boolean inDialog) { |
| currentItemNum = -1; |
| this.inDialog = inDialog; |
| saveHelper = new CheatSheetSaveHelper(); |
| } |
| |
| public void advanceIntroItem() { |
| if (getViewItemAtIndex(0) == null) { |
| return; // Cheat Sheet has no items or was not opened correctly |
| } |
| resetItemState(); |
| /* LP-item event */ |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_DEACTIVATED, introItem); |
| |
| currentItemNum = 1; |
| ViewItem nextItem = getViewItemAtIndex(currentItemNum); |
| if (nextItem.item.isDynamic()) { |
| nextItem.handleButtons(); |
| } |
| nextItem.setAsCurrentActiveItem(); |
| /* LP-item event */ |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, nextItem); |
| collapseAllButCurrent(false); |
| |
| saveCurrentSheet(); |
| } |
| |
| /** |
| * Reset the state of all the items in this cheatsheet |
| */ |
| private void resetItemState() { |
| IntroItem introItem = (IntroItem) getViewItemAtIndex(0); |
| boolean isStarted = introItem.isCompleted(); |
| |
| expandRestoreList = new ArrayList<>(); |
| if(expandRestoreAction != null) |
| expandRestoreAction.setCollapsed(false); |
| |
| clearBackgrounds(); |
| clearIcons(); |
| collapseAllButtons(); |
| if(isStarted) |
| initManager(); |
| |
| for (ViewItem item : viewItemList) { |
| if (item instanceof CoreItem) { |
| CoreItem c = (CoreItem) item; |
| ArrayList<SubItemCompositeHolder> l = c.getListOfSubItemCompositeHolders(); |
| if (l != null) |
| for (int j = 0; j < l.size(); j++) { |
| l.get(j).setSkipped(false); |
| l.get(j).setCompleted(false); |
| } |
| } |
| } |
| |
| if (isStarted) |
| getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_RESTARTED); |
| else |
| getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_STARTED); |
| |
| isStarted = true; |
| introItem.setAsNormalCollapsed(); |
| introItem.setComplete(); |
| introItem.setRestartImage(); |
| } |
| |
| /*package*/ |
| /* |
| * This function can do one of three things |
| * 1. If this item has a completion message which has not been displayed, display it |
| * 2. Otherwise if this is the final item return to the introduction |
| * 3. If neither condition 1 or 2 is satisfied move to the next item |
| */ |
| public void advanceItem(ImageHyperlink link, boolean markAsCompleted) { |
| currentItem = (ViewItem) link.getData(); |
| int indexNextItem = getIndexOfItem(currentItem) +1; |
| boolean isFinalItem = indexNextItem >= viewItemList.size(); |
| |
| if (markAsCompleted |
| && currentItem.hasCompletionMessage() |
| && !currentItem.isCompletionMessageExpanded()) { |
| currentItem.setCompletionMessageExpanded(isFinalItem); |
| currentItem.setComplete(); |
| if (isFinalItem) { |
| getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_COMPLETED); |
| } |
| saveCurrentSheet(); |
| return; |
| } |
| |
| if (indexNextItem < currentItemNum) { |
| ViewItem vi = getViewItemAtIndex(currentItemNum); |
| vi.setAsNormalNonCollapsed(); |
| } |
| if (currentItem != null) { |
| //set that item to it's original color. |
| currentItem.setAsNormalCollapsed(); |
| //set that item as complete. |
| if (markAsCompleted) { |
| if (!currentItem.isCompleted()) { |
| currentItem.setComplete(); |
| } |
| /* LP-item event */ |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_COMPLETED, currentItem); |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_DEACTIVATED, currentItem); |
| } else { |
| currentItem.setSkipped(); |
| /* LP-item event */ |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_SKIPPED, currentItem); |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_DEACTIVATED, currentItem); |
| } |
| } |
| if (!isFinalItem) { |
| ViewItem nextItem = getViewItemAtIndex(indexNextItem); |
| currentItemNum = indexNextItem; |
| if (nextItem != null) { |
| //Handle lazy button instantiation here. |
| if (nextItem.item.isDynamic()) { |
| ((CoreItem) nextItem).handleButtons(); |
| } |
| nextItem.setAsCurrentActiveItem(); |
| /* LP-item event */ |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, nextItem); |
| currentItem = nextItem; |
| } |
| |
| FormToolkit.ensureVisible(currentItem.getMainItemComposite()); |
| } else if (indexNextItem == viewItemList.size()) { |
| if (!currentItem.isCompletionMessageExpanded()) { // The event will already have been fired |
| getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_COMPLETED); |
| } |
| showIntroItem(); |
| } |
| |
| saveCurrentSheet(); |
| } |
| |
| private void showIntroItem() { |
| ViewItem item = getViewItemAtIndex(0); |
| item.setAsCurrentActiveItem(); |
| } |
| |
| public void advanceSubItem(ImageHyperlink link, boolean markAsCompleted, int subItemIndex) { |
| Label l = null; |
| ArrayList<SubItemCompositeHolder> list = null; |
| SubItemCompositeHolder sich = null; |
| CoreItem ciws = null; |
| |
| currentItem = (ViewItem) link.getData(); |
| |
| if (currentItem instanceof CoreItem) |
| ciws = (CoreItem) currentItem; |
| |
| if (ciws != null) { |
| list = ciws.getListOfSubItemCompositeHolders(); |
| sich = list.get(subItemIndex); |
| l = sich.getCheckDoneLabel(); |
| } |
| |
| if (l != null) { |
| if (markAsCompleted) { |
| sich.setCompleted(true); |
| sich.setSkipped(false); |
| /* LP-subitem event */ |
| // fireManagerSubItemEvent(ICheatSheetItemEvent.ITEM_COMPLETED, ciws, subItemID); |
| } else { |
| sich.setSkipped(true); |
| sich.setCompleted(false); |
| /* LP-subitem event */ |
| // fireManagerSubItemEvent(ICheatSheetItemEvent.ITEM_SKIPPED, ciws, subItemID); |
| } |
| ciws.refreshItem(); |
| } |
| |
| boolean allAttempted = checkAllAttempted(list); |
| boolean anySkipped = checkContainsSkipped(list); |
| |
| if (allAttempted && !anySkipped) { |
| advanceItem(link, true); |
| return; |
| } else if (allAttempted && anySkipped) { |
| advanceItem(link, false); |
| return; |
| } |
| |
| setFocus(); |
| saveCurrentSheet(); |
| } |
| |
| private boolean checkAllAttempted(ArrayList<SubItemCompositeHolder> list) { |
| for (int i = 0; i < list.size(); i++) { |
| SubItemCompositeHolder s = list.get(i); |
| if (s.isCompleted() || s.isSkipped()) { |
| continue; |
| } |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean checkContainsSkipped(ArrayList<SubItemCompositeHolder> list) { |
| for (int i = 0; i < list.size(); i++) { |
| SubItemCompositeHolder s = list.get(i); |
| if (s.isSkipped()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @SuppressWarnings({ "rawtypes", "unchecked" }) |
| private boolean loadState() { |
| try { |
| Properties props = stateManager.getProperties(); |
| |
| manager = stateManager.getCheatSheetManager(); |
| |
| // There is a bug which causes the background of the buttons to |
| // remain white, even though the color is set. So instead of calling |
| // clearBackgrounds() only the following line should be needed. D'oh! |
| // ((ViewItem) viewItemList.get(0)).setOriginalColor(); |
| clearBackgrounds(); |
| |
| if (props == null) { |
| getViewItemAtIndex(0).setAsCurrentActiveItem(); |
| /* LP-item event */ |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, items[0]); |
| return true; |
| } |
| |
| boolean buttonIsDown = (Integer.parseInt((String) props.get(IParserTags.BUTTON)) == 0) ? false : true; |
| int itemNum = Integer.parseInt((String) props.get(IParserTags.CURRENT)); |
| ArrayList completedStatesList = (ArrayList) props.get(IParserTags.COMPLETED); |
| ArrayList expandedStatesList = (ArrayList) props.get(IParserTags.EXPANDED); |
| expandRestoreList = (ArrayList<String>) props.get(IParserTags.EXPANDRESTORE); |
| String cid = (String) props.get(IParserTags.ID); |
| Hashtable completedSubItems = (Hashtable) props.get(IParserTags.SUBITEMCOMPLETED); |
| Hashtable<String, String> skippedSubItems = (Hashtable<String, String>) props |
| .get(IParserTags.SUBITEMSKIPPED); |
| |
| ArrayList completedSubItemsItemList = new ArrayList<>(); |
| ArrayList skippedSubItemsItemList = new ArrayList<>(); |
| |
| Enumeration e = completedSubItems.keys(); |
| while (e.hasMoreElements()) |
| completedSubItemsItemList.add(e.nextElement()); |
| |
| Enumeration e2 = skippedSubItems.keys(); |
| while (e2.hasMoreElements()) |
| skippedSubItemsItemList.add(e2.nextElement()); |
| |
| if (cid != null) |
| currentID = cid; |
| |
| if (itemNum >= 0) { |
| currentItemNum = itemNum; |
| |
| currentItem = getViewItemAtIndex(itemNum); |
| |
| CheatSheetStopWatch.startStopWatch("CheatSheetViewer.checkSavedState()"); //$NON-NLS-1$ |
| for (int i = 0; i < viewItemList.size(); i++) { |
| |
| ViewItem item = getViewItemAtIndex(i); |
| if (i > 0 && item.item.isDynamic() && i <= currentItemNum) { |
| item.handleButtons(); |
| item.setOriginalColor(); |
| } |
| |
| if (completedStatesList.contains(Integer.toString(i))) { |
| item.setComplete(); |
| item.setRestartImage(); |
| } else { |
| if (i < currentItemNum) { |
| item.setSkipped(); |
| } |
| } |
| if (expandedStatesList.contains(Integer.toString(i))) { |
| item.setExpanded(); |
| } else { |
| item.setCollapsed(); |
| } |
| if (i > currentItemNum) { |
| item.setButtonsVisible(false); |
| item.setCompletionMessageCollapsed(); |
| } else { |
| item.setButtonsVisible(true); |
| if (i >currentItemNum || item.isCompleted()) { |
| item.setCompletionMessageExpanded(i + 1 >= viewItemList.size()); |
| } else { |
| item.setCompletionMessageCollapsed(); |
| } |
| } |
| if (expandRestoreList.contains(Integer.toString(i))) { |
| item.setCollapsed(); |
| } |
| if (completedSubItemsItemList.contains(Integer.toString(i))) { |
| String subItemNumbers = (String) completedSubItems.get(Integer.toString(i)); |
| StringTokenizer st = new StringTokenizer(subItemNumbers, ","); //$NON-NLS-1$ |
| if (item instanceof CoreItem) { |
| CoreItem coreitemws = (CoreItem) item; |
| ArrayList<SubItemCompositeHolder> subItemCompositeHolders = coreitemws |
| .getListOfSubItemCompositeHolders(); |
| if (subItemCompositeHolders != null) { |
| while (st.hasMoreTokens()) { |
| String token = st.nextToken(); |
| subItemCompositeHolders.get(Integer.parseInt(token)).setCompleted(true); |
| ArrayList<SubItemCompositeHolder> l = subItemCompositeHolders; |
| SubItemCompositeHolder s = l.get(Integer.parseInt(token)); |
| if (s != null && s.getStartButton() != null) { |
| s.getStartButton().setImage(CheatSheetPlugin.getPlugin().getImage(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_RESTART)); |
| s.getStartButton().setToolTipText(Messages.RESTART_TASK_TOOLTIP); |
| } |
| |
| } |
| } |
| } |
| } |
| if (skippedSubItemsItemList.contains(Integer.toString(i))) { |
| String subItemNumbers = skippedSubItems.get(Integer.toString(i)); |
| StringTokenizer st = new StringTokenizer(subItemNumbers, ","); //$NON-NLS-1$ |
| if (item instanceof CoreItem) { |
| CoreItem coreitemws = (CoreItem) item; |
| while (st.hasMoreTokens()) { |
| String token = st.nextToken(); |
| coreitemws.getListOfSubItemCompositeHolders().get(Integer.parseInt(token)) |
| .setSkipped(true); |
| } |
| } |
| } |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.checkSavedState()", "Time in CheatSheetViewer.checkSavedState() after loop #"+i+": "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.checkSavedState()", "Time in CheatSheetViewer.checkSavedState() after loop: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| if (buttonIsDown) { |
| if(expandRestoreAction != null) |
| expandRestoreAction.setCollapsed(true); |
| } |
| |
| // If the last item is the current one and it is complete then |
| // we should collapse the last item and set the focus on intro. |
| // For all other cases, set the current item as the active item. |
| if(viewItemList.size()-1 == itemNum && currentItem.isCompleted()) { |
| currentItem.setCollapsed(); |
| getViewItemAtIndex(0).getMainItemComposite().setFocus(); |
| |
| // The cheat sheet has been restored but is also completed so fire both events |
| getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_RESTORED); |
| getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_COMPLETED); |
| } else { |
| currentItem.setAsCurrentActiveItem(); |
| |
| // If the intro item is completed, than the cheat sheet has been restored. |
| if(getViewItemAtIndex(0).isCompleted()) |
| getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_RESTORED); |
| } |
| |
| /* LP-item event */ |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, currentItem); |
| } else { |
| getViewItemAtIndex(0).setAsCurrentActiveItem(); |
| /* LP-item event */ |
| // fireManagerItemEvent(ICheatSheetItemEvent.ITEM_ACTIVATED, items[0]); |
| } |
| |
| return true; |
| } catch(Exception e) { |
| // An exception while restoring the saved state data usually only occurs if |
| // the cheat sheet has been modified since this previous execution. This most |
| // often occurs during development of cheat sheets and as such an end user is |
| // not as likely to encounter this. |
| |
| boolean reset = MessageDialog.openConfirm(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), |
| Messages.CHEATSHEET_STATE_RESTORE_FAIL_TITLE, |
| Messages.CHEATSHEET_STATE_RESET_CONFIRM); |
| |
| if (reset) { |
| restart(); |
| return true; |
| } |
| |
| // Log the exception |
| String stateFile = saveHelper.getStateFile(currentID).toOSString(); |
| String message = NLS.bind(Messages.ERROR_APPLYING_STATE_DATA_LOG, (new Object[] {stateFile, currentID})); |
| CheatSheetPlugin.getPlugin().getLog().error(message, e); |
| |
| // Set the currentID to null so it is not saved during internalDispose() |
| currentID = null; |
| |
| internalDispose(); |
| |
| // Reinitialize a few variables because there is no currentItem or currentPage now |
| parserInput = null; |
| currentItem = null; |
| currentItemNum = -1; |
| currentPage = null; |
| expandRestoreList = new ArrayList<>(); |
| viewItemList = new ArrayList<>(); |
| |
| // Create the errorpage to show the user |
| createErrorPage(Messages.ERROR_APPLYING_STATE_DATA); |
| |
| return false; |
| } |
| } |
| |
| private void clearBackgrounds() { |
| for (ViewItem item : viewItemList) { |
| item.setOriginalColor(); |
| } |
| } |
| |
| private void clearIcons() { |
| for (ViewItem item : viewItemList) { |
| item.setOriginalColor(); |
| if (item.isCompleted() || item.isExpanded() || item.isSkipped()) |
| item.setIncomplete(); |
| } |
| } |
| |
| private void collapseAllButCurrent(boolean fromAction) { |
| expandRestoreList = new ArrayList<>(); |
| try { |
| ViewItem current = getViewItemAtIndex(currentItemNum); |
| for (ListIterator<ViewItem> iter = viewItemList.listIterator(viewItemList.size()); iter.hasPrevious();) { |
| ViewItem item = iter.previous(); |
| if (item != current && item.isExpanded()) { |
| item.setCollapsed(); |
| if (fromAction) |
| expandRestoreList.add(Integer.toString(getIndexOfItem(item))); |
| } |
| } |
| } catch (Exception e) { |
| } |
| } |
| |
| private void collapseAllButtons() { |
| for (Iterator<ViewItem> iter = viewItemList.listIterator(1); iter.hasNext();) { |
| ViewItem item = iter.next(); |
| item.setButtonsVisible(false); |
| item.setCompletionMessageCollapsed(); |
| } |
| } |
| |
| private void createErrorPage(String message) { |
| setCollapseExpandButtonEnabled(false); |
| if(message != null) { |
| currentPage = new ErrorPage(message); |
| } else { |
| currentPage = new ErrorPage(); |
| } |
| currentPage.createPart(control); |
| control.layout(true); |
| } |
| |
| private void showStartPage() { |
| setCollapseExpandButtonEnabled(false); |
| internalDispose(); |
| |
| howToBegin = new Label(control, SWT.WRAP); |
| howToBegin.setText(Messages.INITIAL_VIEW_DIRECTIONS); |
| howToBegin.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| currentPage = null; |
| control.layout(true); |
| } |
| |
| private void createErrorPage(IStatus status) { |
| setCollapseExpandButtonEnabled(false); |
| currentPage = new ErrorPage(status); |
| currentPage.createPart(control); |
| control.layout(true); |
| } |
| |
| /** |
| * Creates the SWT controls for this workbench part. |
| * <p> |
| * Clients should not call this method (the workbench calls this method at |
| * appropriate times). |
| * </p> |
| * <p> |
| * For implementors this is a multi-step process: |
| * </p> |
| * <ol> |
| * <li>Create one or more controls within the parent.</li> |
| * <li>Set the parent layout as needed.</li> |
| * <li>Register any global actions with the <code>IActionService</code>.</li> |
| * <li>Register any popup menus with the <code>IActionService</code>.</li> |
| * <li>Register a selection provider with the <code>ISelectionService</code> |
| * (optional). </li> |
| * </ol> |
| * |
| * @param parent the parent control |
| */ |
| @Override |
| public void createPartControl(Composite parent) { |
| control = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| layout.verticalSpacing = 0; |
| layout.horizontalSpacing = 0; |
| layout.numColumns = 1; |
| control.setLayout(layout); |
| |
| control.addDisposeListener(e -> dispose()); |
| |
| showStartPage(); |
| |
| Display display = parent.getDisplay(); |
| |
| busyCursor = display.getSystemCursor(SWT.CURSOR_WAIT); |
| |
| if(contentElement != null) { |
| initCheatSheetView(); |
| } |
| } |
| |
| /** |
| * Called when any TrayDialog is opened. The viewer must react by disabling |
| * itself and moving the cheat sheet to the dialog's tray if the current item |
| * was flagged as one that opens a modal dialog. |
| * |
| * @param dialog the dialog that was opened |
| */ |
| private void dialogOpened(final TrayDialog dialog) { |
| if (isActive()) { |
| HelpTray tray = (HelpTray)dialog.getTray(); |
| if (tray == null) { |
| tray = new HelpTray(); |
| dialog.openTray(tray); |
| } |
| ReusableHelpPart helpPart = tray.getHelpPart(); |
| IHelpPartPage page = helpPart.createPage(CheatSheetHelpPart.ID, null, null); |
| page.setVerticalSpacing(0); |
| page.setHorizontalMargin(0); |
| ICheatSheetStateManager trayManager = new TrayStateManager(); |
| preTrayManager = stateManager; |
| stateManager = trayManager; |
| saveCurrentSheet(); // Save the state into the tray manager |
| helpPart.addPart(CheatSheetHelpPart.ID, new CheatSheetHelpPart(helpPart.getForm().getForm().getBody(), helpPart.getForm().getToolkit(), page.getToolBarManager(), contentElement, trayManager)); |
| page.addPart(CheatSheetHelpPart.ID, true); |
| helpPart.addPage(page); |
| helpPart.showPage(CheatSheetHelpPart.ID); |
| |
| /* |
| * Disable the viewer until the tray is closed, then show it again. |
| */ |
| control.setVisible(false); |
| Display.getCurrent().removeFilter(SWT.Show, listener); |
| |
| helpPart.getControl().addListener(SWT.Dispose, event -> { |
| control.setVisible(true); |
| Display.getCurrent().addFilter(SWT.Show, listener); |
| if (preTrayManager != null) { |
| loadState(); // Load from the tray manager |
| stateManager = preTrayManager; |
| preTrayManager = null; |
| } |
| dialogReturnCode = dialog.getReturnCode(); |
| }); |
| } |
| } |
| |
| /** |
| * Disposes of this cheat sheet viewer. |
| */ |
| private void dispose() { |
| internalDispose(); |
| } |
| |
| /* |
| * Returns the cheat sheet being viewed. |
| */ |
| public ICheatSheet getCheatSheet() { |
| return model; |
| } |
| |
| @Override |
| public String getCheatSheetID() { |
| if(getContent() != null) { |
| return getContent().getID(); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the current content. |
| * |
| * @return CheatSheetElement |
| */ |
| /*package*/ CheatSheetElement getContent() { |
| return contentElement; |
| } |
| |
| @Override |
| public Control getControl() { |
| return control; |
| } |
| |
| private int getIndexOfItem(ViewItem item) { |
| int index = viewItemList.indexOf(item); |
| if(index != -1) { |
| return index; |
| } |
| return 0; |
| } |
| |
| /*package*/ CheatSheetManager getManager() { |
| if (manager == null) { |
| getNewManager(); |
| } |
| return manager; |
| } |
| |
| private CheatSheetManager getNewManager(){ |
| manager = new CheatSheetManager(contentElement); |
| return manager; |
| } |
| |
| private CheatSheetManager initManager(){ |
| CheatSheetManager csManager = getManager(); |
| csManager.setData(new Hashtable<>()); |
| return csManager; |
| } |
| |
| private ViewItem getViewItemAtIndex(int index) { |
| if (viewItemList != null && !viewItemList.isEmpty()) { |
| return viewItemList.get(index); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns whether or not this viewer contains the given Control, which |
| * is currently in focus. |
| * |
| * @param control the Control currently in focus |
| * @return whether this viewer contains the given Control or not |
| */ |
| public boolean hasFocusControl(Control control) { |
| return (control == this.control) || (currentPage.getControl() == control); |
| } |
| |
| /** |
| * If in a dialog-opening step, will add the appropriate listener for |
| * the cheatsheet to jump into the dialog's tray once opened. |
| * |
| * Should be called before executing any action. |
| */ |
| private void hookDialogListener() { |
| /* |
| * org.eclipse.help.ui is an optional dependency; only perform this |
| * step is this plugin is present. |
| */ |
| if (!inDialog && isInDialogItem() && (Platform.getBundle("org.eclipse.help.ui") != null)) { //$NON-NLS-1$ |
| listener = event -> { |
| if (isTrayDialog(event.widget)) { |
| dialogOpened((TrayDialog) ((Shell) event.widget).getData()); |
| } |
| }; |
| Display.getCurrent().addFilter(SWT.Show, listener); |
| } |
| } |
| |
| /** |
| * Removes the dialog-opening listener, if it was added. |
| * |
| * Should be called after executing any action. |
| */ |
| private void unhookDialogListener() { |
| if (listener != null) { |
| Display.getCurrent().removeFilter(SWT.Show, listener); |
| } |
| } |
| |
| /* |
| * return true if a cheat sheet was opened successfully |
| */ |
| private boolean initCheatSheetView() { |
| CheatSheetStopWatch.startStopWatch("CheatSheetViewer.initCheatSheetView()"); //$NON-NLS-1$ |
| //Re-initialize list to store items collapsed by expand/restore action on c.s. toolbar. |
| expandRestoreList = new ArrayList<>(); |
| |
| // re set that action to turned off. |
| if(expandRestoreAction != null) |
| expandRestoreAction.setCollapsed(false); |
| |
| //reset current item to be null; next item too. |
| currentItem = null; |
| currentItemNum = 0; |
| viewItemList = new ArrayList<>(); |
| |
| // Reset the page variable |
| currentPage = null; |
| |
| if(howToBegin != null) { |
| howToBegin.dispose(); |
| howToBegin = null; |
| } |
| |
| // If a null cheat sheet id was specified, return leaving the cheat sheet empty. |
| if(nullCheatSheetId) { |
| return false; |
| } |
| |
| if(invalidCheatSheetId) { |
| createErrorPage(Messages.ERROR_CHEATSHEET_DOESNOT_EXIST); |
| return false; |
| } |
| |
| // read our contents, if there are problems reading the file an error page should be created. |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() before readFile() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| IStatus parseStatus = readFile(); |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after readFile() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (!parseStatus.isOK()) { |
| CheatSheetPlugin.getPlugin().getLog().log(parseStatus); |
| } |
| if(parseStatus.getSeverity() == Status.ERROR){ |
| |
| // Error during parsing. |
| // Something is wrong with the Cheat sheet content file at the xml level. |
| |
| createErrorPage(parseStatus); |
| return false; |
| } |
| |
| control.setRedraw(false); |
| if (model instanceof CheatSheet) { |
| CheatSheet cheatSheetModel = (CheatSheet)model; |
| |
| if (isRestricted && cheatSheetModel.isContainsCommandOrAction()) { |
| boolean isOK = MessageDialog.openConfirm(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), |
| Messages.CHEATSHEET_FROM_URL_WITH_EXEC_TITLE, |
| Messages.CHEATSHEET_FROM_URL_WITH_EXEC); |
| |
| if (!isOK) { |
| control.setRedraw(true); |
| showStartPage(); |
| return true; |
| } |
| } |
| |
| currentPage = new CheatSheetPage(cheatSheetModel, viewItemList, this); |
| setCollapseExpandButtonEnabled(true); |
| } else if (model instanceof CompositeCheatSheetModel) { |
| CompositeCheatSheetModel compositeCheatSheetModel = ((CompositeCheatSheetModel)model); |
| compositeCheatSheetModel.setId(currentID); |
| currentPage = new CompositeCheatSheetPage(compositeCheatSheetModel, stateManager); |
| compositeCheatSheetModel.setCheatSheetManager(initManager()); |
| setCollapseExpandButtonEnabled(false); |
| } |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after CheatSheetPage() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| currentPage.createPart(control); |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after CheatSheetPage.createPart() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| if (model instanceof CheatSheet) { |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after fireEvent() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| if(!loadState()) { |
| // An error occurred when apply the saved state data. |
| control.setRedraw(true); |
| control.layout(); |
| return true; |
| } |
| |
| getManager().fireEvent(ICheatSheetEvent.CHEATSHEET_OPENED); |
| } |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after checkSavedState() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| currentPage.initialized(); |
| control.setRedraw(true); |
| control.layout(); |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() after layout() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| if (currentItem != null && !currentItem.isCompleted()) |
| currentItem.setFocus(); |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.initCheatSheetView()", "Time in CheatSheetViewer.initCheatSheetView() at end of method: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| return true; |
| } |
| |
| private void internalDispose() { |
| if(manager != null) |
| manager.fireEvent(ICheatSheetEvent.CHEATSHEET_CLOSED); |
| |
| saveCurrentSheet(); |
| |
| for (Iterator<ViewItem> iter = viewItemList.iterator(); iter.hasNext();) { |
| ViewItem item = iter.next(); |
| item.dispose(); |
| } |
| |
| if(currentPage != null) { |
| currentPage.dispose(); |
| } |
| manager = null; |
| } |
| |
| /** |
| * Returns whether or not the cheat sheet viewer is currently active. This |
| * means it is visible to the user and enabled. |
| * |
| * @return whether or not this viewer is active |
| */ |
| private boolean isActive() { |
| Control control = getControl(); |
| if (control != null && !control.isDisposed()) { |
| Control parent = control.getParent(); |
| return (parent != null && !parent.isDisposed() && parent.isVisible() && parent.isEnabled()); |
| } |
| return false; |
| } |
| |
| /* |
| * Show the collapse/expand button if we have access to the toolbar |
| */ |
| private void setCollapseExpandButtonEnabled(boolean enable) { |
| if (expandRestoreAction != null) { |
| expandRestoreAction.setEnabled(enable); |
| } |
| } |
| |
| /** |
| * Returns whether or not the currently active item requires opening a |
| * modal dialog. |
| * |
| * @return whether the current item opens a modal dialog |
| */ |
| private boolean isInDialogItem() { |
| if (currentItem != null) { |
| return currentItem.getItem().isDialog(); |
| } |
| return false; |
| } |
| |
| /** |
| * Returns whether or not this cheat sheet viewer is inside a modal |
| * dialog. |
| * |
| * @return whether this viewer is inside a modal dialog |
| */ |
| public boolean isInDialogMode() { |
| return inDialog; |
| } |
| |
| /** |
| * Returns whether the given widget is a TrayDialog. |
| * |
| * @param widget the widget to check |
| * @return whether or not the widget is a TrayDialog |
| */ |
| private boolean isTrayDialog(Widget widget) { |
| return (widget instanceof Shell && ((Shell)widget).getData() instanceof TrayDialog); |
| } |
| |
| /** |
| * Read the contents of the cheat sheet file |
| * @return true if the file was read and parsed without error |
| */ |
| private IStatus readFile() { |
| if(parser == null) |
| parser = new CheatSheetParser(); |
| // If the cheat sheet was registered then |
| // search for a specific type - composite or simple |
| int cheatSheetKind = CheatSheetParser.ANY; |
| if (contentElement.isRegistered()) { |
| if (contentElement.isComposite()) { |
| cheatSheetKind = CheatSheetParser.COMPOSITE_ONLY; |
| } else { |
| cheatSheetKind = CheatSheetParser.SIMPLE_ONLY; |
| } |
| } |
| |
| model = parser.parse(parserInput, cheatSheetKind); |
| return parser.getStatus(); |
| } |
| |
| private void restoreExpandStates() { |
| try { |
| for (int i = 0; i < expandRestoreList.size(); i++) { |
| int index = Integer.parseInt((expandRestoreList.get(i))); |
| ViewItem item = getViewItemAtIndex(index); |
| if (!item.isExpanded()) { |
| item.setExpanded(); |
| } |
| } |
| expandRestoreList = null; |
| } catch (Exception e) { |
| } |
| } |
| |
| /*package*/ void runPerformExecutable(ImageHyperlink link) { |
| link.setCursor(busyCursor); |
| currentItem = (ViewItem) link.getData(); |
| CoreItem coreItem = (CoreItem) currentItem; |
| Page page= currentPage; |
| |
| if (coreItem != null) { |
| try { |
| hookDialogListener(); |
| dialogReturnCode = -1; |
| IStatus status = coreItem.runExecutable(getManager()); |
| if ( status.getSeverity() == IStatus.ERROR) { |
| CheatSheetPlugin.getPlugin().getLog().log(status); |
| org.eclipse.jface.dialogs.ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), null, null, status); |
| } |
| if (page != currentPage) { |
| // action closed the cheatsheet view or changed the cheatsheet |
| return; |
| } |
| if (status.isOK() && dialogReturnCode != Window.CANCEL) { |
| coreItem.setRestartImage(); |
| if (!coreItem.hasConfirm()) { |
| //set that item as complete. |
| advanceItem(link, true); |
| saveCurrentSheet(); |
| } |
| } |
| } |
| finally { |
| unhookDialogListener(); |
| } |
| } |
| |
| link.setCursor(null); |
| } |
| |
| /*package*/ void runSubItemPerformExecutable(ImageHyperlink link, int subItemIndex) { |
| CoreItem coreItem = null; |
| link.setCursor(busyCursor); |
| currentItem = (ViewItem) link.getData(); |
| coreItem = (CoreItem) currentItem; |
| |
| try { |
| if (coreItem != null) { |
| hookDialogListener(); |
| if (coreItem.runSubItemExecutable(getManager(), subItemIndex) == ViewItem.VIEWITEM_ADVANCE && !coreItem.hasConfirm(subItemIndex)) { |
| ArrayList<SubItemCompositeHolder> l = coreItem.getListOfSubItemCompositeHolders(); |
| SubItemCompositeHolder s = l.get(subItemIndex); |
| s.getStartButton().setImage(CheatSheetPlugin.getPlugin().getImage(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_RESTART)); |
| s.getStartButton().setToolTipText(Messages.RESTART_TASK_TOOLTIP); |
| advanceSubItem(link, true, subItemIndex); |
| saveCurrentSheet(); |
| } |
| } |
| } catch (RuntimeException e) { |
| IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, Messages.ERROR_RUNNING_ACTION, e); |
| CheatSheetPlugin.getPlugin().getLog().log(status); |
| org.eclipse.jface.dialogs.ErrorDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), null, null, status); |
| } finally { |
| unhookDialogListener(); |
| link.setCursor(null); |
| } |
| } |
| |
| public void saveCurrentSheet() { |
| if(currentID != null) { |
| if (currentPage instanceof CheatSheetPage) { |
| Properties properties = saveHelper.createProperties(currentItemNum, viewItemList, getExpandRestoreActionState(), expandRestoreList, currentID, restorePath); |
| IStatus status = stateManager.saveState(properties, getManager()); |
| if (!status.isOK()) { |
| CheatSheetPlugin.getPlugin().getLog().log(status); |
| } |
| } else if (currentPage instanceof CompositeCheatSheetPage) { |
| ((CompositeCheatSheetPage)currentPage).saveState(); |
| } |
| } |
| } |
| |
| private boolean getExpandRestoreActionState() { |
| boolean expandRestoreActionState = false; |
| if(expandRestoreAction != null) |
| expandRestoreActionState = expandRestoreAction.isCollapsed(); |
| return expandRestoreActionState; |
| } |
| |
| /*package*/ void setContent(CheatSheetElement element, ICheatSheetStateManager inputStateManager) { |
| CheatSheetStopWatch.startStopWatch("CheatSheetViewer.setContent(CheatSheetElement element)"); //$NON-NLS-1$ |
| |
| // Cleanup previous contents |
| internalDispose(); |
| |
| // Set the current content to new content |
| contentElement = element; |
| stateManager = inputStateManager; |
| stateManager.setElement(element); |
| |
| currentID = null; |
| parserInput = null; |
| if (element != null) { |
| initInputFields(element); |
| } |
| |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.setContent(CheatSheetElement element)", "Time in CheatSheetViewer.setContent() before initCheatSheetView() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| // Initialize the view with the new contents |
| boolean cheatSheetOpened = false; |
| if (control != null) { |
| cheatSheetOpened = initCheatSheetView(); |
| } |
| if (!cheatSheetOpened) { |
| contentElement = null; |
| stateManager = null; |
| } |
| // If the cheat sheet failed to open clear the content element so we don't see an |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.setContent(CheatSheetElement element)", "Time in CheatSheetViewer.setContent() after initCheatSheetView() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| private void initInputFields(CheatSheetElement element) { |
| currentID = element.getID(); |
| String contentXml = element.getContentXml(); |
| URL contentURL = null; |
| restorePath = element.getRestorePath(); |
| String errorMessage = null; |
| |
| if (contentXml != null) { |
| parserInput = new ParserInput(contentXml, element.getHref()); |
| return; |
| } |
| |
| // The input was not an XML string, find the content URL |
| Bundle bundle = null; |
| if(element != null && element.getConfigurationElement() != null) |
| try{ |
| String pluginId = element.getConfigurationElement().getContributor().getName(); |
| bundle = Platform.getBundle(pluginId); |
| } catch (Exception e) { |
| // do nothing |
| } |
| if (bundle != null) { |
| contentURL = FileLocator.find(bundle, new Path(element.getContentFile()), null); |
| if (contentURL == null && element.getContentFile() != null) { |
| errorMessage = NLS.bind(Messages.ERROR_OPENING_FILE_IN_PARSER, (new Object[] {element.getContentFile()})); |
| } |
| } |
| |
| if (contentURL == null) { |
| try { |
| contentURL = new URL(element.getHref()); |
| } catch (MalformedURLException mue) { |
| } |
| if (contentURL == null && element.getHref() != null) { |
| errorMessage = NLS.bind(Messages.ERROR_OPENING_FILE_IN_PARSER, (new Object[] {element.getHref()})); |
| } |
| } |
| String pluginId = bundle != null ? bundle.getSymbolicName() : null; |
| parserInput = new ParserInput(contentURL, pluginId, errorMessage); |
| } |
| |
| |
| /*package*/ void setExpandRestoreAction(CheatSheetExpandRestoreAction action) { |
| expandRestoreAction = action; |
| } |
| |
| /** |
| * Passing the focus request to the viewer's control. |
| */ |
| @Override |
| public void setFocus() { |
| //need this to have current item selected. (Assumes that when you reactivate the view you will work with current item.) |
| if (currentItem != null) { |
| currentItem.setFocus(); |
| } else { |
| getControl().setFocus(); |
| } |
| } |
| |
| |
| @Override |
| public void setInput(String id) { |
| setInput(id, new DefaultStateManager()); |
| } |
| |
| public void setInput(String id, ICheatSheetStateManager inputStateManager) { |
| CheatSheetStopWatch.startStopWatch("CheatSheetViewer.setInput(String id)"); //$NON-NLS-1$ |
| |
| CheatSheetElement element = null; |
| |
| if(id == null) { |
| nullCheatSheetId = true; |
| } else { |
| nullCheatSheetId = false; |
| |
| element = CheatSheetRegistryReader.getInstance().findCheatSheet(id); |
| if(element == null) { |
| String message = NLS.bind(Messages.ERROR_INVALID_CHEATSHEET_ID, (new Object[] {id})); |
| IStatus status = new Status(IStatus.ERROR, ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID, IStatus.OK, message, null); |
| CheatSheetPlugin.getPlugin().getLog().log(status); |
| invalidCheatSheetId = true; |
| } else { |
| invalidCheatSheetId = false; |
| this.isRestricted = false; |
| } |
| } |
| |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.setInput(String id)", "Time in CheatSheetViewer.setInput(String id) before setContent() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| setContent(element, inputStateManager); |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.setInput(String id)", "Time in CheatSheetViewer.setInput(String id) after setContent() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| // Update most recently used cheat sheets list. |
| CheatSheetPlugin.getPlugin().getCheatSheetHistory().add(element); |
| CheatSheetStopWatch.printLapTime("CheatSheetViewer.setInput(String id)", "Time in CheatSheetViewer.setInput(String id) after getCheatSheetHistory() call: "); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| @Override |
| public void setInput(String id, String name, URL url) { |
| setInput(id, name, url, new DefaultStateManager(), false); |
| } |
| |
| public void setInputFromXml(String id, String name, String xml, String basePath) { |
| if (id == null || name == null || xml == null) { |
| throw new IllegalArgumentException(); |
| } |
| CheatSheetElement element = new CheatSheetElement(name); |
| element.setID(id); |
| element.setContentXml(xml); |
| element.setHref(basePath); |
| |
| nullCheatSheetId = false; |
| invalidCheatSheetId = false; |
| isRestricted = false; |
| setContent(element, new NoSaveStateManager()); |
| } |
| |
| public void setInput(String id, String name, URL url, |
| ICheatSheetStateManager inputStateManager, boolean isRestricted) { |
| if (id == null || name == null || url == null) { |
| throw new IllegalArgumentException(); |
| } |
| CheatSheetElement element = new CheatSheetElement(name); |
| element.setID(id); |
| element.setHref(url.toString()); |
| |
| nullCheatSheetId = false; |
| invalidCheatSheetId = false; |
| this.isRestricted = isRestricted; |
| setContent(element, inputStateManager); |
| } |
| |
| /*package*/ void toggleExpandRestore() { |
| if(expandRestoreAction == null) |
| return; |
| |
| if (expandRestoreAction.isCollapsed()) { |
| restoreExpandStates(); |
| expandRestoreAction.setCollapsed(false); |
| } else { |
| collapseAllButCurrent(true); |
| expandRestoreAction.setCollapsed(true); |
| } |
| |
| } |
| |
| public Action getCopyAction() { |
| return copyAction; |
| } |
| |
| public void setCopyAction(Action copyAction) { |
| this.copyAction = copyAction; |
| } |
| |
| public void copy() { |
| if (currentItem!=null) |
| currentItem.copy(); |
| } |
| |
| public void addListener(CheatSheetListener listener) { |
| if (contentElement != null ) { |
| getManager().addListener(listener); |
| } |
| } |
| |
| @Override |
| public int contributeToViewMenu(Menu menu, int index) { |
| if (currentPage instanceof IMenuContributor) { |
| return ((IMenuContributor)currentPage).contributeToViewMenu(menu, index); |
| } |
| return index; |
| } |
| |
| public void restart() { |
| resetItemState(); |
| currentItemNum = 0; |
| collapseAllButCurrent(false); |
| IntroItem introItem = (IntroItem) getViewItemAtIndex(0); |
| introItem.setIncomplete(); |
| showIntroItem(); |
| } |
| |
| public void saveState(IMemento memento) { |
| if (currentPage instanceof CheatSheetPage) { |
| Properties properties = saveHelper.createProperties(currentItemNum, viewItemList, getExpandRestoreActionState(), expandRestoreList, currentID, restorePath); |
| saveHelper.saveToMemento(properties, getManager(), memento); |
| } |
| } |
| |
| @Override |
| public void reset(Map<String, String> cheatSheetData) { |
| if (currentPage instanceof CheatSheetPage) { |
| restart(); |
| getManager().setData(cheatSheetData); |
| } else if (currentPage instanceof CompositeCheatSheetPage) { |
| ((CompositeCheatSheetPage)currentPage).restart(cheatSheetData); |
| } |
| } |
| |
| public void showError(String message) { |
| internalDispose(); |
| if(howToBegin != null) { |
| howToBegin.dispose(); |
| howToBegin = null; |
| } |
| createErrorPage(message); |
| } |
| |
| } |