/******************************************************************************* * Copyright (c) 2009 David Green 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: * David Green - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.wikitext.ui.editor; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.IOpenListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.OpenEvent; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.window.ToolTip; import org.eclipse.mylyn.wikitext.parser.outline.OutlineItem; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.model.BaseWorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.part.IShowInSource; import org.eclipse.ui.part.IShowInTarget; import org.eclipse.ui.part.ShowInContext; import org.eclipse.ui.texteditor.ITextEditorActionConstants; /** * a default source editor outline view that presents a structured outline in a tree view based on the * {@link OutlineItem heading-based outline}. * * @author David Green * @since 1.3 */ public class DefaultWikiTextSourceEditorOutline extends AbstractWikiTextSourceEditorOutline implements IShowInSource, IShowInTarget { private boolean disableReveal; @Override public void createControl(Composite parent) { super.createControl(parent); TreeViewer viewer = getTreeViewer(); viewer.setUseHashlookup(true); viewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); viewer.setContentProvider(new BaseWorkbenchContentProvider()); viewer.setLabelProvider(WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider()); viewer.setInput(getEditor().getAdapter(OutlineItem.class)); viewer.addOpenListener(new IOpenListener() { public void open(OpenEvent event) { revealInEditor(event.getSelection()); } }); viewer.addPostSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { revealInEditor(event.getSelection()); } }); viewer.expandAll(); updateSelectionToMatchEditor(); new ToolTip(viewer.getControl(), ToolTip.RECREATE, false) { @Override protected Composite createToolTipContentArea(Event event, Composite parent) { Composite comp = new Composite(parent, SWT.NONE); comp.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); GridLayout gl = new GridLayout(1, false); gl.marginBottom = 2; gl.marginTop = 2; gl.marginHeight = 0; gl.marginWidth = 0; gl.marginLeft = 2; gl.marginRight = 2; gl.verticalSpacing = 1; comp.setLayout(gl); Object tipItem = getToolTipItem(new Point(event.x, event.y)); if (tipItem instanceof OutlineItem) { OutlineItem outlineItem = (OutlineItem) tipItem; Label label = new Label(comp, SWT.WRAP); label.setBackground(comp.getBackground()); label.setText(outlineItem.getTooltip()); } return comp; } @Override protected boolean shouldCreateToolTip(Event event) { final Object eventItem = getToolTipItem(new Point(event.x, event.y)); boolean shouldCreate = eventItem != null && eventItem instanceof OutlineItem && super.shouldCreateToolTip(event); if (!shouldCreate) { hide(); } return shouldCreate; } protected Object getToolTipItem(Point point) { TreeItem item = ((Tree) getTreeViewer().getControl()).getItem(point); if (item != null) { return item.getData(); } return null; } }; MenuManager manager = new MenuManager("#PopUp"); //$NON-NLS-1$ manager.setRemoveAllWhenShown(true); manager.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager menuManager) { contextMenuAboutToShow(menuManager); } }); viewer.getTree().setMenu(manager.createContextMenu(viewer.getTree())); } private void contextMenuAboutToShow(IMenuManager menuManager) { menuManager.add(new Separator(ITextEditorActionConstants.GROUP_UNDO)); menuManager.add(new GroupMarker(ITextEditorActionConstants.GROUP_SAVE)); menuManager.add(new Separator(ITextEditorActionConstants.GROUP_COPY)); menuManager.add(new Separator(ITextEditorActionConstants.GROUP_PRINT)); menuManager.add(new Separator(ITextEditorActionConstants.GROUP_EDIT)); menuManager.add(new Separator(ITextEditorActionConstants.GROUP_FIND)); menuManager.add(new Separator(IWorkbenchActionConstants.GROUP_ADD)); menuManager.add(new Separator(IWorkbenchActionConstants.GROUP_SHOW_IN)); menuManager.add(new Separator(IWorkbenchActionConstants.GROUP_REORGANIZE)); menuManager.add(new Separator(ITextEditorActionConstants.GROUP_REST)); menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } private void revealInEditor(ISelection selection) { if (disableReveal) { return; } if (selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; Object firstElement = structuredSelection.getFirstElement(); if (firstElement instanceof OutlineItem) { OutlineItem item = (OutlineItem) firstElement; if (getEditor() != null) { IShowInTarget target = (IShowInTarget) getEditor().getAdapter(IShowInTarget.class); if (target != null) { target.show(new ShowInContext(null, new StructuredSelection(item))); } } } } } private void refresh() { getTreeViewer().getTree().setRedraw(false); try { getTreeViewer().refresh(); getTreeViewer().expandAll(); } finally { getTreeViewer().getTree().setRedraw(true); } } public ShowInContext getShowInContext() { if (getEditor() != null) { IShowInSource source = (IShowInSource) getEditor().getAdapter(IShowInSource.class); if (source != null) { return source.getShowInContext(); } } return null; } public boolean show(ShowInContext context) { if (getEditor() != null) { IShowInTarget target = (IShowInTarget) getEditor().getAdapter(IShowInTarget.class); if (target != null) { return target.show(context); } } return false; } @Override protected void editorPropertyChanged(Object source, int propId) { super.editorPropertyChanged(source, propId); if (getControl() != null && !getControl().isDisposed()) { if (propId == WikiTextSourceEditor.PROP_OUTLINE) { refresh(); // update the outline selection from the editor getControl().getDisplay().asyncExec(new Runnable() { public void run() { if (getControl() != null && !getControl().isDisposed() && getEditor() != null) { updateSelectionToMatchEditor(); } } }); } else if (propId == WikiTextSourceEditor.PROP_OUTLINE_LOCATION) { updateSelectionToMatchEditor(); } } } @Override public void setSelection(ISelection selection) { disableReveal = true; try { super.setSelection(selection); } finally { disableReveal = false; } } private void updateSelectionToMatchEditor() { if (getEditor() == null) { return; } IShowInSource source = (IShowInSource) getEditor().getAdapter(IShowInSource.class); if (source != null) { ShowInContext showInContext = source.getShowInContext(); if (showInContext != null) { if (showInContext.getSelection() instanceof IStructuredSelection) { Object firstElement = ((IStructuredSelection) showInContext.getSelection()).getFirstElement(); if (firstElement instanceof OutlineItem) { setSelection(new StructuredSelection(firstElement)); } } } } } }