package org.xmind.ui.internal.outline;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.IPageChangedListener;
import org.eclipse.jface.dialogs.PageChangedEvent;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
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.TreeEditor;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.part.IContributedContentsView;
import org.eclipse.ui.part.PageBook;
import org.xmind.core.Core;
import org.xmind.core.ISheet;
import org.xmind.core.ITopic;
import org.xmind.core.IWorkbook;
import org.xmind.core.event.CoreEvent;
import org.xmind.core.event.CoreEventRegister;
import org.xmind.core.event.ICoreEventListener;
import org.xmind.core.event.ICoreEventSource;
import org.xmind.gef.EditDomain;
import org.xmind.gef.GEF;
import org.xmind.gef.IGraphicalViewer;
import org.xmind.gef.IViewer;
import org.xmind.gef.Request;
import org.xmind.gef.dnd.IDndClient;
import org.xmind.gef.part.IGraphicalPart;
import org.xmind.gef.part.IPart;
import org.xmind.gef.service.IRevealService;
import org.xmind.gef.service.IRevealServiceListener;
import org.xmind.gef.service.RevealEvent;
import org.xmind.gef.service.ZoomingAndPanningRevealService;
import org.xmind.gef.tree.ITreeViewer;
import org.xmind.gef.tree.TreeRootPart;
import org.xmind.gef.tree.TreeSelectTool;
import org.xmind.gef.tree.TreeViewer;
import org.xmind.gef.ui.editor.IGraphicalEditor;
import org.xmind.gef.ui.editor.IGraphicalEditorPage;
import org.xmind.ui.internal.MindMapMessages;
import org.xmind.ui.internal.dnd.MindMapElementTransfer;
import org.xmind.ui.internal.e4models.ViewModelPart;
import org.xmind.ui.internal.editpolicies.ModifiablePolicy;
import org.xmind.ui.internal.outline.resource.OutlineResources;
import org.xmind.ui.mindmap.IMindMapImages;
import org.xmind.ui.mindmap.ITopicPart;
import org.xmind.ui.mindmap.IWorkbookRef;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.tabfolder.IPageClosedListener;
import org.xmind.ui.util.MindMapUtils;
public class OutlineIndexModelPart extends ViewModelPart
implements IPartListener, IPageChangedListener,
IContributedContentsView, IPageClosedListener, ICoreEventListener {
private class CenteredRevealHelper implements IRevealServiceListener {
private ZoomingAndPanningRevealService service;
private boolean oldCentered;
/**
*
*/
public CenteredRevealHelper(IViewer viewer) {
Object service = viewer.getService(IRevealService.class);
if (service != null
&& service instanceof ZoomingAndPanningRevealService) {
this.service = (ZoomingAndPanningRevealService) service;
this.oldCentered = this.service.isCentered();
} else {
this.service = null;
this.oldCentered = false;
}
}
public void start(IGraphicalPart part) {
if (this.service != null) {
this.service.setCentered(true);
this.service.reveal(new StructuredSelection(part));
this.service.addRevealServiceListener(this);
}
}
/*
* (non-Javadoc)
* @see
* org.xmind.gef.service.IRevealServiceListener#revealingStarted(org
* .xmind.gef.service.RevealEvent)
*/
public void revealingStarted(RevealEvent event) {
}
/*
* (non-Javadoc)
* @see
* org.xmind.gef.service.IRevealServiceListener#revealingCanceled(org
* .xmind.gef.service.RevealEvent)
*/
public void revealingCanceled(RevealEvent event) {
restore();
}
/*
* (non-Javadoc)
* @see
* org.xmind.gef.service.IRevealServiceListener#revealingFinished(org
* .xmind.gef.service.RevealEvent)
*/
public void revealingFinished(RevealEvent event) {
restore();
}
void restore() {
this.service.removeRevealServiceListener(this);
this.service.setCentered(this.oldCentered);
}
}
private class ShowWorkbookAction extends Action {
public ShowWorkbookAction() {
super(MindMapMessages.OutlineIndexPart_ShowWorkbookAction_text,
AS_RADIO_BUTTON);
setId("org.xmind.ui.showWorkbook"); //$NON-NLS-1$
setToolTipText(
MindMapMessages.OutlineIndexPart_ShowWorkbookAction_toolTip);
setImageDescriptor(
MindMapUI.getImages().get(IMindMapImages.WORKBOOK, true));
setDisabledImageDescriptor(
MindMapUI.getImages().get(IMindMapImages.WORKBOOK, false));
}
public void run() {
showCurrentPage = false;
showCurrentSheetAction.setChecked(showCurrentPage);
showWorkbookAction.setChecked(!showCurrentPage);
if (sourceEditor == null)
return;
IWorkbookRef workbookRef = sourceEditor
.getAdapter(IWorkbookRef.class);
if (workbookRef == null)
return;
if (outlineType == OUTLINE_TYPE_NONE) {
showEditorTreeViewer();
} else {
OutlineViewer currentViewer = getOutlineViewer(sourceEditor,
parseOutlineTypeToViewerType(outlineType));
if (currentViewer != null
&& !currentViewer.getControl().isDisposed()) {
currentViewer.setInput(
outlineResources.getResourceForWorkbook(workbookRef,
outlineType, false));
viewerStack.showPage(currentViewer.getControl());
}
}
}
}
private class ShowCurrentSheetAction extends Action {
public ShowCurrentSheetAction() {
super(MindMapMessages.OutlineIndexPart_ShowCurrentSheetAction_text);
setId("org.xmind.ui.showCurrentSheet"); //$NON-NLS-1$
setToolTipText(
MindMapMessages.OutlineIndexPart_ShowCurrentSheetAction_toolTip);
setImageDescriptor(
MindMapUI.getImages().get(IMindMapImages.SHEET, true));
setDisabledImageDescriptor(
MindMapUI.getImages().get(IMindMapImages.SHEET, false));
}
public void run() {
showCurrentPage = true;
showCurrentSheetAction.setChecked(showCurrentPage);
showWorkbookAction.setChecked(!showCurrentPage);
if (sourcePage == null)
return;
ISheet sheet = (ISheet) sourcePage.getAdapter(ISheet.class);
if (sheet == null)
return;
if (outlineType == OUTLINE_TYPE_NONE) {
showCurrentPageViewer();
} else {
OutlineViewer currentViewer = getOutlineViewer(sourceEditor,
parseOutlineTypeToViewerType(outlineType));
if (currentViewer != null
&& !currentViewer.getControl().isDisposed()) {
currentViewer.setInput(outlineResources
.getResourceForSheet(sheet, outlineType, false));
viewerStack.showPage(currentViewer.getControl());
}
}
}
}
private class IndexTypeAction extends Action {
IndexTypeAction(String name) {
super(name, IAction.AS_CHECK_BOX);
}
@Override
public void run() {
if (indexTypeToolItem != null && !indexTypeToolItem.isDisposed()) {
setOutlineType(OutlineType.findByName(getText()).getType());
indexTypeToolItem.setText(getText());
if (topComposite != null && !topComposite.isDisposed()) {
topComposite.pack(true);
topComposite.getParent().layout(true, true);
}
}
}
}
public static final int OUTLINE_TYPE_NONE = 0;
public static final int OUTLINE_TYPE_BY_MARKERS = 1;
public static final int OUTLINE_TYPE_BY_LABELS = 2;
public static final int OUTLINE_TYPE_BY_STARTDATE = 3;
public static final int OUTLINE_TYPE_BY_ENDDATE = 4;
public static final int OUTLINE_TYPE_BY_ASSIGNEE = 5;
public static final int OUTLINE_TYPE_BY_AZ = 6;
public static final int OUTLINE_TYPE_BY_ZA = 7;
private static final String VIEWMENU_ID_FOR_OUTLINEPART = "org.eclipse.ui.views.ContentOutline"; //$NON-NLS-1$
private CoreEventRegister coreEventRegister = new CoreEventRegister(this);
private Composite parentComposite;
private IGraphicalEditor sourceEditor;
private OutlineResources outlineResources;
private IGraphicalEditorPage sourcePage;
private PageBook viewerStack;
private Control defaultPage;
private ITreeViewer editorTreeViewer;
private Map<Object, ITreeViewer> pageViewers = new HashMap<Object, ITreeViewer>();
private Map<IGraphicalEditor, Collection<IGraphicalEditorPage>> pages = new HashMap<IGraphicalEditor, Collection<IGraphicalEditorPage>>();
private boolean showCurrentPage = false;
private int outlineType = OUTLINE_TYPE_NONE;
private Map<IGraphicalEditor, Map<String, OutlineViewer>> outlineViewers = new HashMap<IGraphicalEditor, Map<String, OutlineViewer>>();
private EditDomain domain;
private IAction showWorkbookAction;
private IAction showCurrentSheetAction;
private MenuManager dropDownMenuManager;
private Composite topComposite;
private ToolItem indexTypeToolItem;
protected void init() {
super.init();
registerViewMenu(VIEWMENU_ID_FOR_OUTLINEPART);
}
protected Control doCreateContent(Composite parent) {
this.parentComposite = parent;
Composite composite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.verticalSpacing = 0;
layout.horizontalSpacing = 0;
composite.setLayout(layout);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
topComposite = createTopComposite(composite);
new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL)
.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
Composite contentComposite = new Composite(composite, SWT.NONE);
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
gridLayout.verticalSpacing = 0;
gridLayout.horizontalSpacing = 0;
contentComposite.setLayout(gridLayout);
contentComposite
.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
viewerStack = new PageBook(contentComposite, SWT.NONE);
viewerStack.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
defaultPage = createDefaultPage(viewerStack);
viewerStack.showPage(defaultPage);
IWorkbenchWindow window = getAdapter(IWorkbenchWindow.class);
if (window != null) {
IWorkbenchPage activePage = window.getActivePage();
if (activePage != null) {
partActivated(activePage.getActiveEditor());
activePage.addPartListener(this);
}
}
return composite;
}
private Composite createTopComposite(Composite composite) {
Composite topComposite = new Composite(composite, SWT.RIGHT);
topComposite.setBackground(
topComposite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
GridLayout layout = new GridLayout(2, false);
layout.marginWidth = 2;
layout.marginHeight = 0;
layout.verticalSpacing = 0;
layout.horizontalSpacing = 0;
topComposite.setLayout(layout);
topComposite
.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
showWorkbookAction = new ShowWorkbookAction();
showCurrentSheetAction = new ShowCurrentSheetAction();
showWorkbookAction.setChecked(!isShowCurrentPage());
showCurrentSheetAction.setChecked(isShowCurrentPage());
ToolBarManager toolBarManager = new ToolBarManager();
toolBarManager.add(showWorkbookAction);
toolBarManager.add(showCurrentSheetAction);
ToolBar leftToolBar = toolBarManager.createControl(topComposite);
leftToolBar.setLayoutData(
new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
ToolBar rightToolBar = new ToolBar(topComposite, SWT.NONE);
rightToolBar
.setLayoutData(new GridData(SWT.END, SWT.CENTER, true, false));
indexTypeToolItem = new ToolItem(rightToolBar, SWT.DROP_DOWN);
indexTypeToolItem.setText(OutlineType.None.getName());
indexTypeToolItem.addListener(SWT.Dispose, getToolItemListener());
indexTypeToolItem.addListener(SWT.Selection, getToolItemListener());
return topComposite;
}
private Listener getToolItemListener() {
return new Listener() {
public void handleEvent(Event event) {
switch (event.type) {
case SWT.Dispose:
handleWidgetDispose(event);
break;
case SWT.Selection:
Widget ew = event.widget;
if (ew != null) {
handleWidgetSelection(event,
((ToolItem) ew).getSelection());
}
break;
}
}
};
}
private void handleWidgetSelection(Event event, boolean selection) {
if (event.widget instanceof ToolItem) {
ToolItem item = (ToolItem) event.widget;
MenuManager menuMan = getDropDownMenuManager();
Menu menu = menuMan.createContextMenu(item.getParent());
if (menu != null) {
Rectangle b = item.getBounds();
Point p = item.getParent().toDisplay(b.x, b.y + b.height);
menu.setLocation(p.x, p.y);
menu.setVisible(true);
}
}
}
private MenuManager getDropDownMenuManager() {
if (dropDownMenuManager == null) {
dropDownMenuManager = new MenuManager();
dropDownMenuManager.setRemoveAllWhenShown(true);
dropDownMenuManager.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
for (String name : OutlineType.getNames()) {
manager.add(new IndexTypeAction(name));
}
}
});
}
return dropDownMenuManager;
}
private void handleWidgetDispose(Event event) {
if (event.widget instanceof ToolItem) {
if (dropDownMenuManager != null) {
dropDownMenuManager.dispose();
dropDownMenuManager = null;
}
}
}
private OutlineViewer getOutlineViewer(IGraphicalEditor editor,
String viewerType) {
Map<String, OutlineViewer> typeToViewers = outlineViewers.get(editor);
if (typeToViewers == null)
return null;
return typeToViewers.get(viewerType);
}
private String parseOutlineTypeToViewerType(int outlineType) {
if (outlineType == OUTLINE_TYPE_BY_STARTDATE
|| outlineType == OUTLINE_TYPE_BY_ENDDATE)
return OutlineViewer.VIEWERTYPE_MULITCOLUMN;
if (outlineType == OUTLINE_TYPE_BY_MARKERS
|| outlineType == OUTLINE_TYPE_BY_LABELS
|| outlineType == OUTLINE_TYPE_BY_ASSIGNEE
|| outlineType == OUTLINE_TYPE_BY_AZ
|| outlineType == OUTLINE_TYPE_BY_ZA)
return OutlineViewer.VIEWERTYPE_SINGLECOLUMN;
return null;
}
private void registerCoreEventForEditor() {
if (sourceEditor != null) {
IWorkbook workbook = (IWorkbook) sourceEditor
.getAdapter(IWorkbook.class);
if (workbook instanceof ICoreEventSource) {
coreEventRegister = new CoreEventRegister(
(ICoreEventSource) workbook, this);
coreEventRegister.register(Core.ModifyTime);
coreEventRegister.register(Core.WorkbookSave);
}
}
}
public OutlineResources getOutlineResources() {
return outlineResources;
}
public boolean isShowCurrentPage() {
return showCurrentPage;
}
public void setOutlineType(int type) {
if (type == OUTLINE_TYPE_NONE) {
outlineType = type;
if (isShowCurrentPage()) {
showCurrentPageViewer();
} else {
showEditorTreeViewer();
}
} else {
String oldViewerType = parseOutlineTypeToViewerType(outlineType);
OutlineViewer oldViewer = getOutlineViewer(sourceEditor,
oldViewerType);
this.outlineType = type;
String viewerType = parseOutlineTypeToViewerType(type);
OutlineViewer newViewer = getOutlineViewer(sourceEditor,
viewerType);
if (newViewer == null) {
newViewer = createOutlineViewer(viewerStack, viewerType);
Map<String, OutlineViewer> typeToViewer = outlineViewers
.get(sourceEditor);
typeToViewer.put(viewerType, newViewer);
}
outlineViewerChanged(oldViewer, newViewer);
}
}
protected void dispose() {
setEditor(null);
IWorkbenchWindow window = getAdapter(IWorkbenchWindow.class);
if (window != null) {
window.getActivePage().removePartListener(this);
}
for (Object editor : pages.keySet().toArray()) {
partClosed((IGraphicalEditor) editor);
}
coreEventRegister.unregisterAll();
super.dispose();
}
private Composite createDefaultPage(Composite parent) {
Composite page = new Composite(parent, SWT.NONE);
page.setLayout(new GridLayout(1, false));
Label label = new Label(page, SWT.LEFT | SWT.WRAP);
label.setText(MindMapMessages.OutlineIndexPart_DefaultPage_message);
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
return page;
}
protected void setFocus() {
OutlineViewer outlineViewer = getOutlineViewer(sourceEditor,
parseOutlineTypeToViewerType(outlineType));
if (outlineViewer != null && !outlineViewer.getControl().isDisposed()) {
outlineViewer.setFocus();
} else if (viewerStack != null && !viewerStack.isDisposed()) {
viewerStack.setFocus();
} else if (parentComposite != null && !parentComposite.isDisposed()) {
parentComposite.setFocus();
}
}
public IWorkbenchPart getContributingPart() {
return sourceEditor;
}
public void pageClosed(Object pageObject) {
if (pageObject instanceof IGraphicalEditorPage) {
IGraphicalEditorPage page = (IGraphicalEditorPage) pageObject;
unregisterSourcePage(page);
}
}
public void pageChanged(PageChangedEvent event) {
final IGraphicalEditorPage page = (IGraphicalEditorPage) event
.getSelectedPage();
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
if (page.isDisposed() || page.getControl() == null
|| page.getControl().isDisposed())
return;
setSourcePage(page);
}
});
}
public void partActivated(final IWorkbenchPart part) {
if (!(part instanceof IGraphicalEditor))
return;
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
setEditor((IGraphicalEditor) part);
}
});
}
private void setEditor(IGraphicalEditor editor) {
if (editor == this.sourceEditor)
return;
if (this.sourceEditor != null) {
this.sourceEditor.removePageChangedListener(this);
}
this.sourceEditor = editor;
this.outlineResources = editor == null ? null : new OutlineResources();
registerCoreEventForEditor();
if (editor != null && domain == null) {
domain = new EditDomain();
domain.installTool(GEF.TOOL_SELECT, new TreeSelectTool());
domain.setCommandStack(sourceEditor.getCommandStack());
domain.installEditPolicy(MindMapUI.POLICY_MODIFIABLE,
new ModifiablePolicy());
}
if (this.sourceEditor != null) {
if (!outlineViewers.containsKey(sourceEditor)) {
outlineViewers.put(sourceEditor,
new HashMap<String, OutlineViewer>());
}
this.sourceEditor.addPageChangedListener(this);
setSourcePage(this.sourceEditor.getActivePageInstance());
} else {
setSourcePage(null);
viewerStack.showPage(defaultPage);
}
}
private void setSourcePage(IGraphicalEditorPage page) {
if (page == this.sourcePage)
return;
this.sourcePage = page;
if (viewerStack != null && !viewerStack.isDisposed()) {
Control pageToShow = defaultPage;
if (this.sourcePage != null) {
if (outlineType == OUTLINE_TYPE_NONE) {
if (isShowCurrentPage())
showCurrentPageViewer();
else
showEditorTreeViewer();
} else {
OutlineViewer viewer = ensureOutlineViewer(this.sourcePage);
if (viewer != null && !viewer.getControl().isDisposed()) {
pageToShow = viewer.getControl();
}
viewerStack.showPage(pageToShow);
}
}
}
}
private void showEditorTreeViewer() {
if (editorTreeViewer == null || editorTreeViewer.getControl() == null
|| editorTreeViewer.getControl().isDisposed()) {
editorTreeViewer = createEditorTreeViewer();
if (editorTreeViewer != null) {
configureEditorTreeViewer(editorTreeViewer);
createEditorTreeViewerControl(editorTreeViewer, viewerStack);
editorTreeViewer
.setInput(sourceEditor.getAdapter(IWorkbook.class));
}
}
if (editorTreeViewer != null) {
Object newInput = sourceEditor.getAdapter(IWorkbook.class);
if (newInput != editorTreeViewer.getInput()) {
editorTreeViewer.setInput(newInput);
}
viewerStack.showPage(editorTreeViewer.getControl());
}
}
private void showCurrentPageViewer() {
IGraphicalEditorPage page = sourceEditor.getActivePageInstance();
if (page == null) {
viewerStack.showPage(defaultPage);
return;
}
Object pageInput = page.getInput();
ITreeViewer pageTreeViewer = pageViewers.get(pageInput);
if (pageTreeViewer == null || pageTreeViewer.getControl() == null
|| pageTreeViewer.getControl().isDisposed()) {
pageTreeViewer = createPageTreeViewer();
if (pageTreeViewer != null) {
configurePageTreeViewer(pageTreeViewer);
createPageTreeViewerControl(pageTreeViewer, viewerStack);
pageTreeViewer.setInput(pageInput);
}
}
if (pageTreeViewer != null) {
Object newInput = pageInput;
if (newInput != pageTreeViewer.getInput()) {
pageTreeViewer.setInput(newInput);
}
viewerStack.showPage(pageTreeViewer.getControl());
}
}
private TreeViewer createEditorTreeViewer() {
MindMapTreeViewer viewer = new MindMapTreeViewer();
viewer.getProperties().set(ITreeViewer.PROP_HEADER_VISIBLE, false);
return viewer;
}
private ITreeViewer createPageTreeViewer() {
MindMapTreeViewer viewer = new MindMapTreeViewer();
viewer.getProperties().set(ITreeViewer.PROP_HEADER_VISIBLE, false);
return viewer;
}
private Control createEditorTreeViewerControl(ITreeViewer viewer,
Composite parent) {
Control control = ((TreeViewer) viewer).createControl(parent,
SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
hookViewerControl(viewer, control);
return control;
}
private Control createPageTreeViewerControl(ITreeViewer viewer,
Composite parent) {
Control control = ((TreeViewer) viewer).createControl(parent,
SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
hookViewerControl(viewer, control);
return control;
}
private void configureEditorTreeViewer(ITreeViewer viewer) {
configureTreeViewer(viewer);
}
private void configurePageTreeViewer(ITreeViewer viewer) {
configureTreeViewer(viewer);
}
protected void configureTreeViewer(ITreeViewer viewer) {
// viewer.addSelectionChangedListener(this);
viewer.setEditDomain(domain);
viewer.setPartFactory(MindMapUI.getMindMapTreePartFactory());
viewer.setRootPart(new TreeRootPart());
}
private void outlineViewerChanged(OutlineViewer oldViewer,
OutlineViewer newViewer) {
if (newViewer != null && !newViewer.getControl().isDisposed()
&& sourceEditor != null && sourcePage != null) {
IWorkbookRef workbookRef = sourceEditor
.getAdapter(IWorkbookRef.class);
Object resourceForWorkbook = outlineResources
.getResourceForWorkbook(workbookRef, outlineType, true);
ISheet sheet = (ISheet) sourcePage.getAdapter(ISheet.class);
Object resourceForSheet = outlineResources
.getResourceForSheet(sheet, outlineType, true);
if (showCurrentPage) {
newViewer.setInput(resourceForSheet);
} else {
newViewer.setInput(resourceForWorkbook);
}
if (oldViewer != newViewer) {
// IWorkbenchPartSite site = getViewSite();
// if (site != null)
// site.setSelectionProvider(newViewer);
if (viewerStack != null && !viewerStack.isDisposed()) {
viewerStack.showPage(newViewer.getControl());
}
}
}
}
private OutlineViewer ensureOutlineViewer(IGraphicalEditorPage page) {
String viewerType = parseOutlineTypeToViewerType(outlineType);
OutlineViewer viewer = getOutlineViewer(sourceEditor, viewerType);
if (viewer == null) {
if (sourceEditor != null) {
viewer = createOutlineViewer(viewerStack, viewerType);
registerSourcePage(page);
Map<String, OutlineViewer> typeToViewer = outlineViewers
.get(sourceEditor);
typeToViewer.put(viewerType, viewer);
}
}
if (viewer != null) {
if (showCurrentPage) {
ISheet sheet = (ISheet) page.getAdapter(ISheet.class);
if (sheet != null && viewer.getInput() != outlineResources
.getResourceForSheet(sheet, outlineType, true))
viewer.setInput(outlineResources.getResourceForSheet(sheet,
outlineType, true));
} else {
IWorkbookRef workbookRef = page.getParentEditor()
.getAdapter(IWorkbookRef.class);
Object newInput = outlineResources
.getResourceForWorkbook(workbookRef, outlineType, true);
if (workbookRef != null && viewer.getInput() != newInput)
viewer.setInput(newInput);
}
}
return viewer;
}
private void registerSourcePage(IGraphicalEditorPage page) {
IGraphicalEditor editor = page.getParentEditor();
Collection<IGraphicalEditorPage> list = pages.get(editor);
if (list == null) {
list = new HashSet<IGraphicalEditorPage>();
pages.put(editor, list);
}
list.add(page);
}
private void unregisterSourcePage(IGraphicalEditorPage page) {
IGraphicalEditor editor = page.getParentEditor();
Collection<IGraphicalEditorPage> list = pages.get(editor);
if (list != null) {
list.remove(page);
if (list.isEmpty()) {
pages.remove(editor);
}
}
}
private OutlineViewer createOutlineViewer(PageBook parent,
String viewerType) {
final OutlineViewer viewer = new OutlineViewer(parent, viewerType);
viewer.setAutoExpandLevel(4);
viewer.getTree().setLinesVisible(true);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
Object element = ss.getFirstElement();
if (element instanceof ITopic) {
reveal((ITopic) element);
}
}
}
});
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
// handleDoubleClick(viewer.getTree());
ISelection selection = event.getSelection();
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
Object element = ss.getFirstElement();
if (element instanceof ITopic) {
handleDoubleClick(viewer.getTree(),
MindMapUtils.findTopicPart(
sourceEditor.getAdapter(
IGraphicalViewer.class),
(ITopic) element));
}
}
}
});
viewer.getControl()
.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
return viewer;
}
private void reveal(ITopic topic) {
if (sourceEditor == null)
return;
sourceEditor.getSite().getPage().activate(sourceEditor);
if (topic != null) {
ISelectionProvider selectionProvider = sourceEditor.getSite()
.getSelectionProvider();
if (selectionProvider != null) {
selectionProvider.setSelection(new StructuredSelection(topic));
}
Object selectedPage = sourceEditor.getSelectedPage();
if (selectedPage instanceof IGraphicalEditorPage) {
IGraphicalEditorPage page = (IGraphicalEditorPage) selectedPage;
IGraphicalViewer viewer = page.getViewer();
if (viewer == null)
return;
IPart selectedPart = viewer.getFocusedPart();
if (selectedPart instanceof IGraphicalPart) {
IGraphicalPart part = (IGraphicalPart) selectedPart;
new CenteredRevealHelper(viewer).start(part);
}
}
}
}
private void disposeOutlineViewer(OutlineViewer viewer) {
if (viewer != null && viewer.getControl() != null) {
viewer.getControl().dispose();
viewer = null;
}
}
public void partBroughtToTop(IWorkbenchPart part) {
}
public void partClosed(IWorkbenchPart part) {
if (!(part instanceof IGraphicalEditor))
return;
Collection<IGraphicalEditorPage> oldPages = pages.remove(part);
if (part == this.sourceEditor) {
setEditor(null);
}
if (oldPages != null) {
for (Object page : oldPages.toArray()) {
pageClosed(page);
}
}
Map<String, OutlineViewer> typeToViewer = outlineViewers.remove(part);
if (typeToViewer != null)
for (OutlineViewer viewer : typeToViewer.values()) {
disposeOutlineViewer(viewer);
}
}
public void partDeactivated(IWorkbenchPart part) {
}
public void partOpened(IWorkbenchPart part) {
}
public void handleCoreEvent(CoreEvent event) {
if (sourceEditor == null)
return;
final String type = event.getType();
if (viewerStack != null && !viewerStack.isDisposed())
viewerStack.getDisplay().asyncExec(new Runnable() {
public void run() {
if (Core.WorkbookSave.equals(type)) {
OutlineViewer currentViewer = getOutlineViewer(
sourceEditor,
parseOutlineTypeToViewerType(outlineType));
if (currentViewer != null) {
currentViewer.refresh();
}
} else if (Core.ModifyTime.equals(type)) {
if (sourceEditor != null) {
IWorkbookRef workbookRef = sourceEditor
.getAdapter(IWorkbookRef.class);
Object resourceForWorkbook = outlineResources
.getResourceForWorkbook(workbookRef,
outlineType, true);
Object resourceForSheet = null;
if (sourcePage != null) {
ISheet sheet = (ISheet) sourcePage
.getAdapter(ISheet.class);
resourceForSheet = outlineResources
.getResourceForSheet(sheet, outlineType,
true);
}
OutlineViewer currentViewer = getOutlineViewer(
sourceEditor,
parseOutlineTypeToViewerType(outlineType));
if (currentViewer != null) {
Control control = currentViewer.getControl();
if (control != null && !control.isDisposed()) {
if (!showCurrentPage) {
if (resourceForWorkbook != null)
currentViewer.setInput(
resourceForWorkbook);
} else {
if (resourceForSheet != null)
currentViewer
.setInput(resourceForSheet);
}
}
}
}
}
}
});
}
private void hookViewerControl(final IViewer viewer,
final Control control) {
final DragSource dragSource = new DragSource(control,
DND.DROP_COPY | DND.DROP_MOVE);
dragSource.setTransfer(
new Transfer[] { MindMapElementTransfer.getInstance(),
TextTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
Object[] elements;
String text;
public void dragStart(DragSourceEvent event) {
elements = getElements();
if (elements == null || elements.length == 0)
event.doit = false;
else
text = createText(elements);
}
private Object[] getElements() {
if (control instanceof Tree) {
TreeItem[] selection = ((Tree) control).getSelection();
if (selection.length > 0) {
Object[] elements = new Object[selection.length];
for (int i = 0; i < selection.length; i++) {
TreeItem item = selection[i];
Object data = item.getData();
if (data instanceof IPart) {
data = ((IPart) data).getModel();
}
elements[i] = data;
}
return elements;
}
}
return null;
}
public void dragSetData(DragSourceEvent event) {
if (MindMapElementTransfer.getInstance()
.isSupportedType(event.dataType)) {
event.data = elements;
} else if (TextTransfer.getInstance()
.isSupportedType(event.dataType)) {
event.data = text;
}
}
private String createText(Object[] elements) {
IDndClient textClient = MindMapUI.getMindMapDndSupport()
.getDndClient(MindMapUI.DND_TEXT);
if (textClient == null)
return null;
Object data = textClient.toTransferData(elements, viewer);
return data instanceof String ? (String) data : null;
}
public void dragFinished(DragSourceEvent event) {
}
});
control.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
dragSource.dispose();
}
});
control.addListener(SWT.MouseDown, new Listener() {
@Override
public void handleEvent(Event event) {
Tree tree = (Tree) control;
TreeItem[] selection = tree.getSelection();
if (selection.length == 0)
return;
TreeItem item = selection[0];
if (!(item.getData() instanceof TopicTreePart))
return;
TopicTreePart part = (TopicTreePart) item.getData();
reveal(part.getTopic());
}
});
control.addListener(SWT.MouseDoubleClick, new Listener() {
public void handleEvent(Event event) {
handleDoubleClick(control, null);
event.doit = false;
}
});
}
private void handleDoubleClick(Control control, ITopicPart topicPart) {
startEditing(control, topicPart);
}
private void startEditing(Control control, final ITopicPart topicPart) {
Tree tree = (Tree) control;
TreeItem[] selection = tree.getSelection();
if (selection.length == 0)
return;
final TreeItem item = selection[0];
if (!(item.getData() instanceof TopicTreePart) && topicPart == null) {
return;
}
TreeEditor editor = new TreeEditor(tree) {
@Override
public void layout() {
super.layout();
Control editor = getEditor();
if (editor == null || editor.isDisposed())
return;
Rectangle bounds = editor.getBounds();
Point prefSize = editor.computeSize(SWT.DEFAULT, SWT.DEFAULT);
if (prefSize.y > bounds.height) {
bounds.y += (bounds.height - prefSize.y - 1) / 2;
bounds.height = prefSize.y;
}
editor.setBounds(bounds);
}
};
editor.horizontalAlignment = SWT.LEFT;
editor.grabHorizontal = true;
editor.minimumWidth = 50;
final Text text = new Text(tree, SWT.SINGLE | SWT.BORDER);
text.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_IBEAM));
editor.setEditor(text, item);
final String oldValue = item.getText();
text.setText(oldValue);
text.setFocus();
text.selectAll();
text.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
if (item != null && !item.isDisposed()) {
item.setText(
text.getText() == null ? oldValue : text.getText());
modifyTreeItem(item, topicPart);
}
// This async process fixes a bug on Leopard:
// Whole workbench crashes
e.display.asyncExec(new Runnable() {
public void run() {
text.dispose();
}
});
}
});
text.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
switch (e.character) {
case SWT.ESC:
item.setText(oldValue);
// This async process fixes a bug on Leopard:
// Whole workbench crashes
e.display.asyncExec(new Runnable() {
public void run() {
text.dispose();
}
});
break;
case SWT.CR:
if (item != null && !item.isDisposed()) {
item.setText(text.getText() == null ? oldValue
: text.getText());
modifyTreeItem(item, topicPart);
}
// This async process fixes a bug on Leopard:
// Whole workbench crashes
e.display.asyncExec(new Runnable() {
public void run() {
text.dispose();
}
});
break;
}
}
});
item.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (text != null && !text.isDisposed())
text.dispose();
}
});
}
private void modifyTreeItem(TreeItem item, ITopicPart topicPart) {
if (topicPart != null) {
topicPart.handleRequest(
new Request(GEF.REQ_MODIFY)
.setViewer(topicPart.getSite().getViewer())
.setParameter(GEF.PARAM_TEXT, item.getText())
.setPrimaryTarget(topicPart),
GEF.ROLE_MODIFIABLE);
}
Object o = item.getData();
if (o instanceof IPart) {
IPart part = (IPart) o;
part.handleRequest(new Request(GEF.REQ_MODIFY)
.setViewer(part.getSite().getViewer())
.setParameter(GEF.PARAM_TEXT, item.getText())
.setPrimaryTarget(part), GEF.ROLE_MODIFIABLE);
}
}
}