/******************************************************************************* * Copyright (c) 2005, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ui.internal.cheatsheets.composite.views; import java.util.HashMap; import java.util.Map; import java.util.Observable; import java.util.Observer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Point; 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.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.ui.forms.FormColors; import org.eclipse.ui.forms.HyperlinkSettings; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.ManagedForm; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.FormText; import org.eclipse.ui.internal.cheatsheets.CheatSheetPlugin; 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.explorer.RestartAllAction; import org.eclipse.ui.internal.cheatsheets.composite.explorer.TreeExplorerMenu; import org.eclipse.ui.internal.cheatsheets.composite.model.AbstractTask; import org.eclipse.ui.internal.cheatsheets.composite.model.CompositeCheatSheetModel; import org.eclipse.ui.internal.cheatsheets.composite.model.CompositeCheatSheetSaveHelper; import org.eclipse.ui.internal.cheatsheets.composite.model.EditableTask; import org.eclipse.ui.internal.cheatsheets.composite.parser.ICompositeCheatsheetTags; import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetRegistryReader; import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetRegistryReader.TaskExplorerNode; import org.eclipse.ui.internal.cheatsheets.state.ICheatSheetStateManager; import org.eclipse.ui.internal.cheatsheets.views.Page; import org.eclipse.ui.internal.cheatsheets.views.ViewUtilities; import org.eclipse.ui.internal.provisional.cheatsheets.ICompositeCheatSheetTask; import org.eclipse.ui.internal.provisional.cheatsheets.TaskEditor; import org.eclipse.ui.internal.provisional.cheatsheets.TaskExplorer; import org.eclipse.ui.part.PageBook; /** * A page which represents a composite cheat sheet */ public class CompositeCheatSheetPage extends Page implements ISelectionChangedListener, IMenuContributor { public static final String REVIEW_TAG = "__review__"; //$NON-NLS-1$ public static final String END_REVIEW_TAG = "__endReview__"; //$NON-NLS-1$ public static final String GOTO_TASK_TAG = "__goto__"; //$NON-NLS-1$ public static final String START_HREF = "__start__"; //$NON-NLS-1$ public static final String SKIP_HREF = "__skip__"; //$NON-NLS-1$ private ManagedForm mform; private PageBook explorerContainer; private PageBook taskEditorContainer; private CompositeCheatSheetModel model; private TaskExplorer currentExplorer; private DescriptionPanel descriptionPanel; private CompositeCheatSheetSaveHelper saveHelper; private ICompositeCheatSheetTask selectedTask; private boolean initialized = false;; public CompositeCheatSheetPage(CompositeCheatSheetModel model, ICheatSheetStateManager stateManager) { this.model = model; saveHelper = new CompositeCheatSheetSaveHelper(stateManager); } public void createPart(Composite parent) { init(parent.getDisplay()); toolkit.getHyperlinkGroup().setHyperlinkUnderlineMode(HyperlinkSettings.UNDERLINE_HOVER); form = toolkit.createScrolledForm(parent); form.setLayoutData(new GridData(GridData.FILL_BOTH)); FormColors colors = toolkit.getColors(); /* colors.initializeSectionToolBarColors(); Color gbg = colors.getColor(FormColors.TB_GBG); Color bg = colors.getBackground(); form.getForm().setTextBackground(new Color[]{bg, gbg}, new int [] {100}, true); form.getForm().setSeparatorColor(colors.getColor(FormColors.TB_BORDER)); form.getForm().setSeparatorVisible(true); */ toolkit.decorateFormHeading(form.getForm()); mform = new ManagedForm(toolkit, form); GridLayout glayout = new GridLayout(); glayout.marginHeight = 0; glayout.marginWidth = 0; form.getBody().setLayout(glayout); final SashForm sash = new SashForm(form.getBody(), SWT.NULL); GridData gd = new GridData(GridData.FILL_BOTH); gd.widthHint = 10; gd.heightHint = 10; sash.setLayoutData(gd); sash.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { Point size = sash.getSize(); if (size.x>size.y) sash.setOrientation(SWT.HORIZONTAL); else sash.setOrientation(SWT.VERTICAL); updateSashPanelMargins(sash); } }); sash.setBackground(colors.getColor(IFormColors.TB_BG)); Composite explorerPanel = new Composite(sash, SWT.NULL); explorerPanel.setBackground(colors.getColor(IFormColors.TB_BORDER)); GridLayout playout = new GridLayout(); playout.marginWidth = 0; playout.marginTop = 2; playout.marginBottom = 0; explorerPanel.setLayout(playout); toolkit.adapt(explorerPanel); explorerContainer = new PageBook(explorerPanel, SWT.NULL); explorerContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); Composite editorPanel = new Composite(sash, SWT.NULL); playout = new GridLayout(); playout.marginWidth = 0; playout.marginHeight = 0; editorPanel.setLayout(playout); editorPanel.setBackground(colors.getColor(IFormColors.TB_BORDER)); taskEditorContainer = new PageBook(editorPanel, SWT.NULL); toolkit.adapt(taskEditorContainer); taskEditorContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); } private void updateSashPanelMargins(SashForm sash) { Control [] children = sash.getChildren(); int orientation = sash.getOrientation(); // update task explorer panel GridLayout layout = (GridLayout)((Composite)children[0]).getLayout(); if (orientation==SWT.HORIZONTAL) { layout.marginBottom = 0; layout.marginRight = 1; } else { layout.marginBottom = 1; layout.marginRight = 0; } // update task editor panel layout = (GridLayout)((Composite)children[1]).getLayout(); if (orientation==SWT.HORIZONTAL) { layout.marginTop = 0; layout.marginLeft = 1; } else { layout.marginTop = 1; layout.marginLeft = 0; } ((Composite)children[0]).layout(); ((Composite)children[1]).layout(); } public void dispose() { mform.dispose(); super.dispose(); } private void setInputModel(CompositeCheatSheetModel model, Map layout) { this.model = model; mform.getForm().setText(ViewUtilities.escapeForLabel(model.getName())); String explorerId = model.getTaskExplorerId(); setCurrentExplorerFromId(explorerId); String selectedTaskId = (String) layout.get(ICompositeCheatsheetTags.SELECTED_TASK); ICompositeCheatSheetTask selectedTask= null; if (selectedTaskId != null) { selectedTask = model.getDependencies().getTask(selectedTaskId); if (selectedTask != null) { currentExplorer.setSelection(new StructuredSelection(selectedTask), true); } } if (selectedTask != null) { updateSelectedTask(selectedTask); } else { updateSelectedTask(model.getRootTask()); } model.addObserver(new Observer() { public void update(Observable o, Object arg) { ICompositeCheatSheetTask task = (ICompositeCheatSheetTask)arg; if (currentExplorer!=null) currentExplorer.taskUpdated(task); updateTask(task); } }); } private void setCurrentExplorerFromId(String explorerId) { TaskExplorer explorer = getTaskExplorer(explorerId); if (explorer!=null) { explorer.setCompositeCheatSheet(this.model); explorer.setFocus(); setExplorerVisible(explorerId); } } private void setExplorerVisible(String id) { Control [] excontrols = explorerContainer.getChildren(); TaskExplorer explorer=null; for (int i=0; i<excontrols.length; i++) { Control excontrol = excontrols[i]; explorer = (TaskExplorer)excontrol.getData(ICompositeCheatsheetTags.EXPLORER); if (explorer.getId().equals(id)) { explorerContainer.showPage(excontrol); setCurrentExplorer(explorer); return; } } } private void setCurrentExplorer(TaskExplorer explorer) { if (currentExplorer!=null) { currentExplorer.getSelectionProvider().removeSelectionChangedListener(this); } currentExplorer = explorer; currentExplorer.getSelectionProvider().addSelectionChangedListener(this); updateForSelection(currentExplorer.getSelectionProvider().getSelection()); } private TaskExplorer getTaskExplorer(String id) { Control [] excontrols = explorerContainer.getChildren(); TaskExplorer explorer=null; for (int i=0; i<excontrols.length; i++) { Control excontrol = excontrols[i]; Object data = excontrol.getData(ICompositeCheatsheetTags.EXPLORER); if (data instanceof TaskExplorer) { explorer = (TaskExplorer)data; if (explorer.getId().equals(id)) { return explorer; } } } // Load the explorer from an extension point TaskExplorerManager explorerManager = TaskExplorerManager.getInstance(); explorer = explorerManager.getExplorer(id); if (explorer != null) { explorer.createControl(explorerContainer, mform.getToolkit()); explorer.getControl().setData(ICompositeCheatsheetTags.EXPLORER, explorer); new TreeExplorerMenu(explorer); } return explorer; } public void selectionChanged(SelectionChangedEvent event) { updateForSelection(event.getSelection()); } private void updateForSelection(ISelection selection) { Object selectedElement = ((IStructuredSelection)selection).getFirstElement(); if (selectedElement instanceof ICompositeCheatSheetTask) { updateSelectedTask((ICompositeCheatSheetTask)selectedElement); } } private void updateSelectedTask(ICompositeCheatSheetTask task) { selectedTask = task; updateTask(selectedTask); } /* * Update can be called as a result of a selection change or a state change * If this is not the selected task wait till it is selected to display it */ private void updateTask(ICompositeCheatSheetTask task) { if (task==null || task != selectedTask) return; if ( task instanceof EditableTask) { EditableTask editable = (EditableTask)task; if (editable.getState() == ICompositeCheatSheetTask.IN_PROGRESS) { showEditor(editable); return; } else if (editable.isUnderReview()) { if (editable.getState() == ICompositeCheatSheetTask.COMPLETED) { showEditor(editable); } else { endReview(editable); } return; } } showDescription(task); } public void saveState() { Map layout = new HashMap(); if (selectedTask != null) { layout.put(ICompositeCheatsheetTags.SELECTED_TASK, selectedTask.getId()); } saveHelper.saveCompositeState(model, layout); } private void showDescription(final ICompositeCheatSheetTask task) { if (descriptionPanel==null) { createDescriptionPanel(); } descriptionPanel.showDescription(task); setCurrentEditor(descriptionPanel.getControl()); } private void createDescriptionPanel() { descriptionPanel = new DescriptionPanel(mform, taskEditorContainer); descriptionPanel.addHyperlinkListener(new DescriptionLinkListener()); } /* * Ensure that if this task is visible and in a runnable state that it has been started */ private void showEditor(EditableTask task) { if (task == selectedTask) { TaskEditor editor = getTaskEditor(task); if (editor!= null) { if (!task.isEditorInitialized()) { task.setInput(model.getTaskMemento(task.getId())); } setCurrentEditor(editor.getControl().getParent()); } } } private void addHyperlink(StringBuffer buf, String href, String imageRef, String message) { buf.append("<p><a href=\""); //$NON-NLS-1$ buf.append(href); buf.append("\">"); //$NON-NLS-1$ buf.append("<img href=\""); //$NON-NLS-1$ buf.append(imageRef); buf.append("\"/> "); //$NON-NLS-1$ buf.append(message); buf.append("</a></p>"); //$NON-NLS-1$ } private void reviewTask(EditableTask task) { TaskEditor taskEditor = getTaskEditor(task); Composite container = taskEditor.getControl().getParent(); Composite separator = toolkit.createCompositeSeparator(container); GridData data = new GridData(); data.heightHint = 1; data.horizontalAlignment = SWT.FILL; separator.setLayoutData(data); FormText text = toolkit.createFormText(container, false); text.setImage(DescriptionPanel.REVIEW_IMAGE, CheatSheetPlugin.getPlugin().getImage(ICheatSheetResource.COMPOSITE_TASK_REVIEW)); text.addHyperlinkListener(getEndReviewListener()); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); StringBuffer buf = new StringBuffer(); buf.append("<form>"); //$NON-NLS-1$ addHyperlink(buf, END_REVIEW_TAG + task.getId(), DescriptionPanel.REVIEW_IMAGE, Messages.get().COMPOSITE_PAGE_END_REVIEW ); buf.append("</form>"); //$NON-NLS-1$ text.setText(buf.toString(), true, false); task.setUnderReview(true); container.layout(true); showEditor(task); } private void endReview(EditableTask task) { TaskEditor taskEditor = getTaskEditor(task); Control editorControl = taskEditor.getControl(); Composite container = editorControl.getParent(); Control[] children = container.getChildren(); for (int i = children.length -2; i < children.length; i++) { children[i].dispose(); } task.setUnderReview(false); showDescription(task); container.layout(); } private void setCurrentEditor(Control c) { taskEditorContainer.showPage(c); } /** * Class which responds to hyperlink events originating from the * description panel. */ private final class DescriptionLinkListener extends HyperlinkAdapter { public void linkActivated(HyperlinkEvent e) { String ref = (String)e.getHref(); if (ref.equals(START_HREF)) { Object data = descriptionPanel.getControl().getData(ICompositeCheatsheetTags.TASK); if (data instanceof EditableTask) { EditableTask task = (EditableTask)data; task.setStarted(); } } if (ref.equals(SKIP_HREF)) { Object data = descriptionPanel.getControl().getData(ICompositeCheatsheetTags.TASK); if (data instanceof AbstractTask) { AbstractTask task = (AbstractTask)data; task.setState(ICompositeCheatSheetTask.SKIPPED); } } if (ref.equals(REVIEW_TAG)) { Object data = descriptionPanel.getControl().getData(ICompositeCheatsheetTags.TASK); if (data instanceof EditableTask) { reviewTask((EditableTask) data); } } if (ref.startsWith(GOTO_TASK_TAG)) { String next = ref.substring(GOTO_TASK_TAG.length()); AbstractTask nextTask = model.getDependencies().getTask(next); currentExplorer.setSelection (new StructuredSelection(nextTask), true); } } } /** * Class which responds to hyperlink events originating from the * end review panel */ private final class EndReviewListener extends HyperlinkAdapter { public void linkActivated(HyperlinkEvent e) { String ref = (String)e.getHref(); if (ref.startsWith(END_REVIEW_TAG)) { String next = ref.substring(END_REVIEW_TAG.length()); AbstractTask task = model.getDependencies().getTask(next); endReview((EditableTask)task); } } } private EndReviewListener endReviewListener; private EndReviewListener getEndReviewListener() { if (endReviewListener == null) { endReviewListener = new EndReviewListener(); } return endReviewListener; } /* * Get the task editor for this task. If no editor exists create one */ private TaskEditor getTaskEditor(EditableTask editable) { if (editable.getEditor() == null) { // Create a new editor using the extension point data TaskEditor editor = TaskEditorManager.getInstance().getEditor(editable.getKind()); if (editor != null) { Composite editorPanel = new Composite(taskEditorContainer, SWT.NULL); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; editorPanel.setLayout(layout); mform.getToolkit().adapt(editorPanel); editor.createControl(editorPanel, mform.getToolkit()); editable.setEditor(editor); GridData gridData = new GridData(GridData.FILL_BOTH); editor.getControl().setLayoutData(gridData); } } return editable.getEditor(); } public Control getControl() { return form; } protected String getTitle() { return model.getName(); } public void initialized() { // Open the model model.setSaveHelper(saveHelper); Map layout = new HashMap(); model.loadState(layout); setInputModel(model, layout); initialized = true; } public int contributeToViewMenu(Menu menu, int index) { if (!initialized) { return index; } index = contributeExplorerMenuItem(menu, index); return contributeRestartMenuItem(menu, index); } private int contributeRestartMenuItem(Menu menu, int index) { MenuItem item = new MenuItem(menu, SWT.PUSH, index++); item.setText(Messages.get().RESTART_ALL_MENU); item.setImage(CheatSheetPlugin.getPlugin().getImage(ICheatSheetResource.COMPOSITE_RESTART_ALL)); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { if (model != null) { if (RestartAllAction.confirmRestart()) { restart(null); } } } }); return index; } private int contributeExplorerMenuItem(Menu menu, int index) { String[] explorerIds = CheatSheetRegistryReader.getInstance().getExplorerIds(); if (explorerIds.length == 1) { return index; // no other explorer to chosse from } MenuItem menuItem = new MenuItem(menu, SWT.CASCADE, index++); menuItem.setText(Messages.get().EXPLORER_PULLDOWN_MENU); Menu subMenu = new Menu(menu); menuItem.setMenu(subMenu); for (int i = 0; i < explorerIds.length; i++) { final String id = explorerIds[i]; TaskExplorerNode node = CheatSheetRegistryReader.getInstance().findTaskExplorer(id); boolean isCurrentExplorer = id.equals(currentExplorer.getId()); int style = isCurrentExplorer ? SWT.RADIO: SWT.PUSH; MenuItem item = new MenuItem(subMenu, style); item.setText(node.getName()); item.setSelection(isCurrentExplorer); item.setImage(TaskExplorerManager.getInstance().getImage(id)); item.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setCurrentExplorerFromId(id); } }); } return index; } public void restart(Map cheatSheetData) { model.resetAllTasks(cheatSheetData); currentExplorer.setSelection (new StructuredSelection(model.getRootTask()), true); } }