/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.internal.editor;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Layer;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.internal.util.BundleUtility;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.osgi.framework.Bundle;
import org.xmind.core.Core;
import org.xmind.core.CoreException;
import org.xmind.core.IFileEntry;
import org.xmind.core.IMeta;
import org.xmind.core.ISheet;
import org.xmind.core.ISheetComponent;
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.ICoreEventRegister;
import org.xmind.core.event.ICoreEventSource;
import org.xmind.core.event.ICoreEventSource2;
import org.xmind.core.internal.dom.WorkbookImpl;
import org.xmind.core.util.FileUtils;
import org.xmind.gef.EditDomain;
import org.xmind.gef.GEF;
import org.xmind.gef.IGraphicalViewer;
import org.xmind.gef.command.Command;
import org.xmind.gef.command.ICommandStack;
import org.xmind.gef.ui.actions.IActionRegistry;
import org.xmind.gef.ui.actions.RedoAction;
import org.xmind.gef.ui.actions.UndoAction;
import org.xmind.gef.ui.editor.GraphicalEditor;
import org.xmind.gef.ui.editor.GraphicalEditorPagePopupPreviewHelper;
import org.xmind.gef.ui.editor.IGraphicalEditor;
import org.xmind.gef.ui.editor.IGraphicalEditorPage;
import org.xmind.ui.IWordContextProvider;
import org.xmind.ui.actions.MindMapActionFactory;
import org.xmind.ui.commands.ModifyTitleTextCommand;
import org.xmind.ui.commands.MoveSheetCommand;
import org.xmind.ui.dialogs.SimpleInfoPopupDialog;
import org.xmind.ui.internal.MindMapMessages;
import org.xmind.ui.internal.MindMapUIPlugin;
import org.xmind.ui.internal.MindMapWordContextProvider;
import org.xmind.ui.internal.actions.CreateSheetAction;
import org.xmind.ui.internal.actions.DeleteOtherSheetsAction;
import org.xmind.ui.internal.actions.DeleteSheetAction;
import org.xmind.ui.internal.actions.ShowPropertiesAction;
import org.xmind.ui.internal.dialogs.DialogMessages;
import org.xmind.ui.internal.dialogs.DialogUtils;
import org.xmind.ui.internal.findreplace.IFindReplaceOperationProvider;
import org.xmind.ui.internal.mindmap.MindMapEditDomain;
import org.xmind.ui.internal.outline.MindMapOutlinePage;
import org.xmind.ui.internal.properties.MindMapPropertySheetPage;
import org.xmind.ui.mindmap.IMindMap;
import org.xmind.ui.mindmap.IMindMapImages;
import org.xmind.ui.mindmap.IWorkbookRef;
import org.xmind.ui.mindmap.MindMapImageExporter;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.prefs.PrefConstants;
import org.xmind.ui.resources.ColorUtils;
import org.xmind.ui.tabfolder.IPageMoveListener;
import org.xmind.ui.tabfolder.IPageTitleChangedListener;
import org.xmind.ui.tabfolder.PageMoveHelper;
import org.xmind.ui.tabfolder.PageTitleEditor;
import org.xmind.ui.util.MindMapUtils;
public class MindMapEditor extends GraphicalEditor implements ISaveablePart2,
ICoreEventListener, IPageMoveListener, IPageTitleChangedListener,
IWorkbookReferrer {
private static boolean PROMPT_COMPATIBILITY_WARNING = false;
private static class MindMapEditorPagePopupPreviewHelper extends
GraphicalEditorPagePopupPreviewHelper {
private static final int MIN_PREVIEW_WIDTH = 600;
private static final int MIN_PREVIEW_HEIGHT = 600;
public MindMapEditorPagePopupPreviewHelper(IGraphicalEditor editor,
CTabFolder tabFolder) {
super(editor, tabFolder);
}
protected Rectangle calcContentsBounds(IFigure contents,
IGraphicalViewer viewer) {
Rectangle bounds = super.calcContentsBounds(contents, viewer);
int max = Math.max(bounds.width, bounds.height) + 50;
int newWidth = bounds.width;
if (newWidth < MIN_PREVIEW_WIDTH) {
newWidth = MIN_PREVIEW_WIDTH;
}
if (newWidth < max) {
newWidth = max;
}
if (newWidth != bounds.width) {
int ex = (newWidth - bounds.width) / 2;
Rectangle b = contents.getBounds();
int right = bounds.x + bounds.width;
bounds.x = Math.max(b.x, bounds.x - ex);
bounds.width = Math.min(b.x + b.width, right + ex) - bounds.x;
}
int newHeight = bounds.height;
if (newHeight < MIN_PREVIEW_HEIGHT) {
newHeight = MIN_PREVIEW_HEIGHT;
}
if (newHeight < max) {
newHeight = max;
}
if (newHeight != bounds.height) {
int ex = (newHeight - bounds.height) / 2;
Rectangle b = contents.getBounds();
int bottom = bounds.y + bounds.height;
bounds.y = Math.max(b.y, bounds.y - ex);
bounds.height = Math.min(b.y + b.height, bottom + ex)
- bounds.y;
}
return bounds;
}
}
protected class MindMapEditorBackCover extends DialogPaneContainer {
private Font bigFont;
@Override
public void createControl(Composite parent) {
super.createControl(parent);
createBigFont(parent.getDisplay());
}
private void createBigFont(Display display) {
Font base = display.getSystemFont();
FontData[] fontData = base.getFontData();
int increment;
if ((Util.isMac())
&& System
.getProperty("org.eclipse.swt.internal.carbon.smallFonts") != null) { //$NON-NLS-1$
increment = 3;
} else {
increment = 1;
}
for (FontData fd : fontData) {
fd.setHeight(fd.getHeight() + increment);
}
this.bigFont = new Font(display, fontData);
}
@Override
protected void handleDispose() {
if (bigFont != null) {
bigFont.dispose();
bigFont = null;
}
super.handleDispose();
}
/*
* (non-Javadoc)
*
* @see org.xmind.ui.internal.editor.DialogPaneContainer#close()
*/
@Override
public boolean close() {
boolean ret = super.close();
if (ret) {
if (pageBook != null && !pageBook.isDisposed()) {
pageBook.showPage(pageContainer);
if (isEditorActive()) {
MindMapEditor.this.setFocus();
}
}
}
return ret;
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.ui.internal.editor.DialogPaneContainer#showDialog(org.xmind
* .ui.internal.editor.IDialogPane)
*/
@Override
protected void showDialog(IDialogPane dialog) {
pageBook.showPage(getControl());
if (isEditorActive()) {
MindMapEditor.this.setFocus();
}
super.showDialog(dialog);
}
}
private WorkbookRef workbookRef = null;
private ICoreEventRegister eventRegister = null;
private PageTitleEditor pageTitleEditor = null;
private PageMoveHelper pageMoveHelper = null;
// private IContentOutlinePage outlinePage = null;
// private IPropertySheetPage propertyPage = null;
private MindMapFindReplaceOperationProvider findReplaceOperationProvider = null;
private EditorInputMonitor inputMonitor = null;
private PageBook pageBook = null;
private Composite pageContainer = null;
private LoadWorkbookJob loadWorkbookJob = null;
private MindMapEditorBackCover backCover = null;
private IWordContextProvider wordContextProvider = null;
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
if (this.workbookRef == null) {
try {
this.workbookRef = WorkbookRefManager.getInstance()
.addReferrer(input, this);
} catch (org.eclipse.core.runtime.CoreException e) {
throw new PartInitException(
NLS.bind(
MindMapMessages.MindMapEditor_partInitException_message,
input), e);
}
}
super.init(site, input);
setMiniBarContributor(new MindMapMiniBarContributor());
}
protected ICommandStack createCommandStack() {
return workbookRef.getCommandStack();
}
protected void disposeCommandStack(ICommandStack commandStack) {
// No need to dispose command stack here, because the workbook reference
// manager will dispose unused command stacks automatically.
}
public void dispose() {
uninstallModelListener();
WorkbookRefManager.getInstance().removeReferrer(getEditorInput(), this);
if (inputMonitor != null) {
inputMonitor.dispose();
inputMonitor = null;
}
// if (propertyPage != null) {
// propertyPage.dispose();
// propertyPage = null;
// }
// if (outlinePage != null) {
// outlinePage.dispose();
// outlinePage = null;
// }
if (loadWorkbookJob != null) {
loadWorkbookJob.cancel();
loadWorkbookJob = null;
}
if (backCover != null) {
backCover.dispose();
backCover = null;
}
super.dispose();
eventRegister = null;
pageTitleEditor = null;
pageMoveHelper = null;
findReplaceOperationProvider = null;
workbookRef = null;
pageBook = null;
pageContainer = null;
}
protected Composite createContainerParent(Composite parent) {
StackLayout layout = new StackLayout();
parent.setLayout(layout);
pageBook = new PageBook(parent, SWT.NONE);
layout.topControl = pageBook;
backCover = new MindMapEditorBackCover();
backCover.init(getSite());
backCover.createControl(pageBook);
pageContainer = new Composite(pageBook, SWT.NONE);
return pageContainer;
}
@Override
protected void createEditorContents() {
super.createEditorContents();
// Make editor actions:
createActions(getActionRegistry());
// Update editor pane title:
updateNames();
// Add helpers to handle moving pages, editing page title, showing
// page popup preview, creating new page, etc.:
if (getContainer() instanceof CTabFolder) {
final CTabFolder tabFolder = (CTabFolder) getContainer();
pageMoveHelper = new PageMoveHelper(tabFolder);
pageMoveHelper.addListener(this);
pageTitleEditor = new PageTitleEditor(tabFolder);
pageTitleEditor.addPageTitleChangedListener(this);
pageTitleEditor.setContextId(getSite(),
"org.xmind.ui.context.mindmap.textEdit"); //$NON-NLS-1$
new MindMapEditorPagePopupPreviewHelper(this, tabFolder);
tabFolder.addListener(SWT.MouseDoubleClick, new Listener() {
public void handleEvent(Event event) {
CTabItem item = tabFolder.getItem(new Point(event.x,
event.y));
if (item == null)
createSheet();
}
});
}
// Let 3rd-party plugins configure this editor:
MindMapEditorConfigurerManager.getInstance().configureEditor(this);
// Start monitoring changes to this editor's input source:
inputMonitor = new EditorInputMonitor(this);
// Try loading workbook:
if (getWorkbook() != null) {
workbookLoaded();
} else if (loadWorkbookJob == null) {
loadWorkbookJob = new LoadWorkbookJob(getEditorInput().getName(),
workbookRef, backCover, pageBook.getDisplay());
loadWorkbookJob.addJobChangeListener(new JobChangeAdapter() {
public void done(IJobChangeEvent event) {
loadWorkbookJob = null;
if (pageBook == null || pageBook.isDisposed())
return;
IStatus result = event.getResult();
if (result.getSeverity() == IStatus.OK) {
pageBook.getDisplay().asyncExec(new Runnable() {
public void run() {
workbookLoaded();
}
});
} else if (result.getSeverity() == IStatus.CANCEL) {
pageBook.getDisplay().asyncExec(new Runnable() {
public void run() {
closeEditor();
}
});
} else {
Throwable error = result.getException();
if (error == null) {
try {
throw new org.eclipse.core.runtime.CoreException(
new Status(
IStatus.ERROR,
MindMapUI.PLUGIN_ID,
MindMapMessages.UnexpectedWorkbookLoadFailure_error));
} catch (Throwable e) {
error = e;
}
}
final Throwable err = error;
pageBook.getDisplay().asyncExec(new Runnable() {
public void run() {
showError(err);
}
});
}
}
});
loadWorkbookJob.schedule();
fireDirty();
}
}
private void closeEditor() {
getSite().getPage().closeEditor(this, false);
}
private void showError(Throwable error) {
ErrorDialogPane pane = new ErrorDialogPane();
pane.setContent(error,
MindMapMessages.LoadWorkbookJob_errorDialog_title,
MindMapMessages.LoadWorkbookJob_errorDialog_message,
System.currentTimeMillis());
backCover.open(pane);
closeEditor();
}
protected void createActions(IActionRegistry actionRegistry) {
UndoAction undoAction = new UndoAction(this);
actionRegistry.addAction(undoAction);
addCommandStackAction(undoAction);
RedoAction redoAction = new RedoAction(this);
actionRegistry.addAction(redoAction);
addCommandStackAction(redoAction);
CreateSheetAction createSheetAction = new CreateSheetAction(this);
actionRegistry.addAction(createSheetAction);
DeleteSheetAction deleteSheetAction = new DeleteSheetAction(this);
actionRegistry.addAction(deleteSheetAction);
DeleteOtherSheetsAction deleteOtherSheetAction = new DeleteOtherSheetsAction(
this);
actionRegistry.addAction(deleteOtherSheetAction);
ShowPropertiesAction showPropertiesAction = new ShowPropertiesAction(
getSite().getWorkbenchWindow());
actionRegistry.addAction(showPropertiesAction);
}
private void configurePage(IGraphicalEditorPage page) {
MindMapEditorConfigurerManager.getInstance().configurePage(page);
}
protected void createPages() {
if (getWorkbook() == null)
return;
for (ISheet sheet : getWorkbook().getSheets()) {
IGraphicalEditorPage page = createSheetPage(sheet, -1);
configurePage(page);
}
if (getPageCount() > 0) {
setActivePage(0);
}
checkWorkbookVersion();
}
private void checkWorkbookVersion() {
if (!PROMPT_COMPATIBILITY_WARNING)
return;
String version = getWorkbook().getVersion();
if (Core.getCurrentVersion().equals(version))
return;
final SimpleInfoPopupDialog popup = new SimpleInfoPopupDialog(getSite()
.getShell(), "", //$NON-NLS-1$
"", //$NON-NLS-1$
SWT.ICON_INFORMATION);
popup.popUp(getContainer());
getContainer().addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
popup.close();
}
});
}
protected IGraphicalEditorPage createSheetPage(ISheet sheet, int index) {
IGraphicalEditorPage page = new MindMapEditorPage();
page.init(this, sheet);
addPage(page);
if (index >= 0 && index < getPageCount()) {
movePageTo(findPage(page), index);
}
index = findPage(page);
if (getActivePage() != index) {
setActivePage(index);
}
page.updatePageTitle();
return page;
}
protected EditDomain createEditDomain(IGraphicalEditorPage page) {
MindMapEditDomain domain = new MindMapEditDomain();
domain.setCommandStack(getCommandStack());
return domain;
}
protected void updateNames() {
setPartName(getEditorInput().getName());
setTitleToolTip(getEditorInput().getToolTipText());
}
public int promptToSaveOnClose() {
if (BackgroundWorkbookSaver.getInstance().isRunning()
&& workbookRef != null && workbookRef.canSaveToTarget()) {
NullProgressMonitor monitor = new NullProgressMonitor();
doSave(monitor, true);
if (monitor.isCanceled())
return CANCEL;
return NO;
}
return DEFAULT;
}
private void saveWorkbook(IProgressMonitor monitor,
boolean useProgressDialog, final boolean skipNewRevisions) {
runWithProgress(new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
workbookRef.saveWorkbook(monitor, MindMapEditor.this,
skipNewRevisions);
} catch (Exception e) {
throw new InvocationTargetException(e);
}
}
}, monitor, useProgressDialog);
}
private void saveWorkbookAs(final IEditorInput newInput,
IProgressMonitor monitor, boolean useProgressDialog,
final boolean skipNewRevisions) {
runWithProgress(new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
try {
workbookRef.saveWorkbookAs(newInput, monitor, null,
skipNewRevisions);
} catch (Exception e) {
throw new InvocationTargetException(e);
}
}
}, monitor, useProgressDialog);
}
private void runWithProgress(final IRunnableWithProgress runnable,
final IProgressMonitor monitor, final boolean useProgressDialog) {
if (useProgressDialog) {
final ProgressMonitorDialog dialog = new ProgressMonitorDialog(
getSite().getShell());
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
dialog.run(true, true, runnable);
}
});
} else {
BusyIndicator.showWhile(getSite().getShell().getDisplay(),
new Runnable() {
public void run() {
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
runnable.run(monitor);
}
@Override
public void handleException(Throwable e) {
if (e instanceof InvocationTargetException) {
e = ((InvocationTargetException) e)
.getCause();
}
super.handleException(e);
}
});
}
});
}
}
/**
*
* @param fileName
* @return 0 for Save As, 1 for Cancel, -1 for Save
*/
private int promptWorkbookVersion(String fileName) {
IWorkbook workbook = getWorkbook();
if (Core.getCurrentVersion().equals(workbook.getVersion()))
return -1;
String messages = NLS.bind("", fileName); //$NON-NLS-1$
MessageDialog dialog = new MessageDialog(getSite().getShell(),
"", null, messages, //$NON-NLS-1$
MessageDialog.QUESTION, new String[] { "", //$NON-NLS-1$
IDialogConstants.CANCEL_LABEL }, 0);
return dialog.open();
}
public void doSave(final IProgressMonitor monitor) {
doSave(monitor, false);
}
private void doSave(IProgressMonitor monitor, boolean useProgressDialog) {
if (!workbookRef.canSaveToTarget()) {
doSaveAs(monitor, useProgressDialog);
} else {
int ret = promptWorkbookVersion(getPartName());
if (ret == 1)
return;
if (ret == 0) {
doSaveAs(monitor, useProgressDialog);
} else {
saveWorkbook(monitor, useProgressDialog, false);
}
}
}
public void doSaveAs(IProgressMonitor monitor, String filterExtension,
String filterName) {
doSaveAs(monitor, false, filterExtension, filterName);
}
public void doSaveAs(final IProgressMonitor monitor,
final boolean useProgressDialog, final String filterExtension,
final String filterName) {
if (getWorkbook() == null)
return;
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
final IEditorInput newInput = createNewEditorInput(monitor,
filterExtension, filterName);
if (newInput == null || monitor.isCanceled())
return;
boolean isTemplate = MindMapUI.FILE_EXT_TEMPLATE
.equals(filterExtension);
((WorkbookImpl) getWorkbook())
.setSkipRevisionsWhenSaving(isTemplate);
saveWorkbookAs(newInput, monitor, useProgressDialog, isTemplate);
}
});
}
protected IEditorInput createNewEditorInput(final IProgressMonitor monitor,
String filterExtension, String filterName)
throws org.eclipse.core.runtime.CoreException {
final IEditorInput newInput;
Bundle ide = Platform.getBundle("org.eclipse.ui.ide"); //$NON-NLS-1$
if (ide != null) {
newInput = saveAsResource(ide, monitor, filterExtension, filterName);
} else {
newInput = saveAsFile(monitor, filterExtension, filterName);
}
return newInput;
}
private IEditorInput saveAsFile(final IProgressMonitor monitor,
String filterExtension, String filterName)
throws org.eclipse.core.runtime.CoreException {
String path;
String extension = filterExtension;
String proposalName;
File oldFile = MME.getFile(getEditorInput());
if (oldFile != null) {
proposalName = FileUtils.getNoExtensionFileName(oldFile.getName());
path = oldFile.getParent();
} else {
String name = getWorkbook().getPrimarySheet().getRootTopic()
.getTitleText();
proposalName = MindMapUtils.trimFileName(name);
path = null;
}
// Hide busy cursor
Display display = getSite().getShell().getDisplay();
Shell[] shells = display.getShells();
Cursor cursor = display.getSystemCursor(SWT.CURSOR_WAIT);
for (Shell shell : shells) {
Cursor cursor2 = shell.getCursor();
if (cursor2 != null && cursor2.equals(cursor)) {
shell.setCursor(null);
}
}
// Show save dialog
String extensionFullName = "*" + extension; //$NON-NLS-1$
String filterFullName;
if ("macosx".equals(Platform.getOS())) { //$NON-NLS-1$
filterFullName = NLS.bind(
"{0} ({1})", filterName, extensionFullName); //$NON-NLS-1$
} else {
filterFullName = filterName;
}
String result = DialogUtils.save(getSite().getShell(), proposalName,
new String[] { extensionFullName },
new String[] { filterFullName }, 0, path);
if (result == null) {
monitor.setCanceled(true);
return null;
}
if ("win32".equals(SWT.getPlatform())) { //$NON-NLS-1$
if (!result.endsWith(filterExtension)) {
result = result + filterExtension;
}
}
return MME.createFileEditorInput(result);
}
private IEditorInput saveAsResource(Bundle ide, IProgressMonitor monitor,
String filterExtension, String filterName)
throws org.eclipse.core.runtime.CoreException {
// TODO
return null;
}
protected void doSaveAs(final IProgressMonitor monitor,
boolean useProgressDialog) {
doSaveAs(monitor, useProgressDialog, MindMapUI.FILE_EXT_XMIND,
DialogMessages.WorkbookFilterName);
}
public void doSaveAs() {
doSaveAs(new NullProgressMonitor(), false);
}
public boolean isSaveAsAllowed() {
return getWorkbook() != null;
}
public IWorkbookRef getWorkbookRef() {
return workbookRef;
}
public IWorkbook getWorkbook() {
if (workbookRef == null)
return null;
return workbookRef.getWorkbook();
}
public Object getAdapter(Class adapter) {
if (adapter == IContentOutlinePage.class) {
return new MindMapOutlinePage(this, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
// if (outlinePage == null) {
// outlinePage = new MindMapOutlinePage(this, SWT.MULTI
// | SWT.H_SCROLL | SWT.V_SCROLL);
// }
// return outlinePage;
} else if (adapter == IPropertySheetPage.class) {
return new MindMapPropertySheetPage(this);
// if (propertyPage == null) {
// propertyPage = new MindMapPropertySheetPage(this);
// }
// return propertyPage;
} else if (adapter == IWorkbookRef.class) {
return getWorkbookRef();
} else if (adapter == IWorkbook.class) {
return getWorkbook();
} else if (adapter == PageTitleEditor.class) {
return pageTitleEditor;
} else if (adapter == PageMoveHelper.class) {
return pageMoveHelper;
} else if (adapter == IFindReplaceOperationProvider.class) {
if (findReplaceOperationProvider == null) {
findReplaceOperationProvider = new MindMapFindReplaceOperationProvider(
this);
}
return findReplaceOperationProvider;
} else if (adapter == IWordContextProvider.class) {
if (wordContextProvider == null) {
wordContextProvider = new MindMapWordContextProvider(this);
}
return wordContextProvider;
} else if (adapter == IDialogPaneContainer.class) {
return backCover;
} else if (adapter == LoadWorkbookJob.class) {
return loadWorkbookJob;
}
return super.getAdapter(adapter);
}
protected void installModelListener() {
IWorkbook workbook = getWorkbook();
if (workbook instanceof ICoreEventSource) {
eventRegister = new CoreEventRegister((ICoreEventSource) workbook,
this);
eventRegister.register(Core.SheetAdd);
eventRegister.register(Core.SheetRemove);
eventRegister.register(Core.SheetMove);
eventRegister.register(Core.PasswordChange);
eventRegister.register(Core.WorkbookPreSaveOnce);
}
}
protected void uninstallModelListener() {
if (eventRegister != null) {
eventRegister.unregisterAll();
eventRegister = null;
}
}
public void handleCoreEvent(CoreEvent event) {
String type = event.getType();
if (Core.WorkbookPreSaveOnce.equals(type)) {
getSite().getShell().getDisplay().syncExec(new Runnable() {
public void run() {
fireDirty();
firePropertyChange(PROP_INPUT);
}
});
} else if (Core.SheetAdd.equals(type)) {
ISheet sheet = (ISheet) event.getTarget();
int index = event.getIndex();
IGraphicalEditorPage page = createSheetPage(sheet, index);
configurePage(page);
} else if (Core.SheetRemove.equals(type)) {
ISheet sheet = (ISheet) event.getTarget();
IGraphicalEditorPage page = findPage(sheet);
if (page != null) {
removePage(page);
}
} else if (Core.SheetMove.equals(type)) {
int oldIndex = event.getIndex();
int newIndex = ((ISheet) event.getTarget()).getIndex();
movePageTo(oldIndex, newIndex);
} else if (Core.PasswordChange.equals(type)) {
IWorkbook workbook = getWorkbook();
if (workbook instanceof ICoreEventSource2) {
((ICoreEventSource2) workbook).registerOnceCoreEventListener(
Core.WorkbookPreSaveOnce, ICoreEventListener.NULL);
}
}
}
public boolean isDirty() {
return workbookRef != null && workbookRef.isDirty();
}
protected void saveAndRun(Command command) {
ICommandStack cs = getCommandStack();
if (cs != null)
cs.execute(command);
}
public void pageMoved(int fromIndex, int toIndex) {
IWorkbook workbook = getWorkbook();
MoveSheetCommand command = new MoveSheetCommand(workbook, fromIndex,
toIndex);
command.setLabel(""); //$NON-NLS-1$
saveAndRun(command);
}
public void pageTitleChanged(int pageIndex, String newValue) {
IGraphicalEditorPage page = getPage(pageIndex);
if (page != null) {
Object pageInput = page.getInput();
if (pageInput instanceof ISheet) {
ModifyTitleTextCommand command = new ModifyTitleTextCommand(
(ISheet) pageInput, newValue);
command.setLabel(""); //$NON-NLS-1$
saveAndRun(command);
}
}
}
protected void createSheet() {
IAction action = getActionRegistry().getAction(
MindMapActionFactory.NEW_SHEET.getId());
if (action != null && action.isEnabled()) {
action.run();
}
}
@Override
public void setFocus() {
if (workbookRef != null) {
workbookRef.setPrimaryReferrer(this);
}
if (backCover != null && backCover.isOpen()) {
backCover.setFocus();
} else {
super.setFocus();
}
}
public void openEncryptionDialog() {
if (pageBook == null || pageBook.isDisposed())
return;
backCover.open(new EncryptionDailogPane(getWorkbookRef()));
}
public ISelectionProvider getSelectionProvider() {
return getSite().getSelectionProvider();
}
public void reveal() {
getSite().getPage().activate(this);
setFocus();
}
public void savePreivew(final IWorkbook workbook,
final IProgressMonitor monitor) throws IOException, CoreException {
if (workbook == null)
throw new IllegalArgumentException();
if (workbook.getPassword() != null) {
URL url = BundleUtility.find(MindMapUI.PLUGIN_ID,
IMindMapImages.ENCRYPTED_THUMBNAIL);
if (url != null) {
savePreviewFromURL(url, workbook);
}
} else if (getPageCount() <= 0
|| MindMapUIPlugin.getDefault().getPreferenceStore()
.getBoolean(PrefConstants.PREVIEW_SKIPPED)) {
URL url = BundleUtility.find(MindMapUI.PLUGIN_ID,
IMindMapImages.DEFAULT_THUMBNAIL);
if (url != null) {
savePreviewFromURL(url, workbook);
}
} else {
MindMapImageExporter exporter = new MindMapImageExporter(getSite()
.getShell().getDisplay());
IGraphicalViewer sourceViewer = getPage(0).getViewer();
exporter.setSource(sourceViewer.getInput(), null, null);
exporter.setTargetWorkbook(workbook);
exporter.export();
org.eclipse.draw2d.geometry.Point origin = exporter
.calcRelativeOrigin();
workbook.getMeta().setValue(IMeta.ORIGIN_X,
String.valueOf(origin.x));
workbook.getMeta().setValue(IMeta.ORIGIN_Y,
String.valueOf(origin.y));
workbook.getMeta().setValue(IMeta.BACKGROUND_COLOR,
getBackgroundColor(sourceViewer));
// Delete old preview file entry:
String oldPreview = "Thumbnails/thumbnail.jpg"; //$NON-NLS-1$
IFileEntry oldPreviewEntry = workbook.getManifest().getFileEntry(
oldPreview);
if (oldPreviewEntry != null) {
oldPreviewEntry.increaseReference();
oldPreviewEntry.decreaseReference();
oldPreviewEntry.decreaseReference();
oldPreviewEntry.decreaseReference();
}
}
}
private String getBackgroundColor(IGraphicalViewer sourceViewer) {
Layer layer = sourceViewer.getLayer(GEF.LAYER_BACKGROUND);
if (layer != null) {
Color color = layer.getBackgroundColor();
if (color != null)
return ColorUtils.toString(color);
}
return "#ffffff"; //$NON-NLS-1$
}
/**
* @param url
*/
private void savePreviewFromURL(URL url, IWorkbook workbook)
throws IOException {
MindMapImageExporter exporter = new MindMapImageExporter(getSite()
.getShell().getDisplay());
InputStream stream = url.openStream();
exporter.setTargetWorkbook(workbook);
exporter.export(stream);
}
public void postSave(final IProgressMonitor monitor) {
getSite().getShell().getDisplay().syncExec(new Runnable() {
public void run() {
superDoSave(monitor);
}
});
}
private void superDoSave(IProgressMonitor monitor) {
super.doSave(monitor);
}
public void postSaveAs(final Object newKey, final IProgressMonitor monitor) {
getSite().getShell().getDisplay().syncExec(new Runnable() {
public void run() {
if (newKey instanceof IEditorInput) {
setInput((IEditorInput) newKey);
firePropertyChange(PROP_INPUT);
}
superDoSave(monitor);
updateNames();
}
});
}
public void setSelection(ISelection selection, boolean reveal,
boolean forceFocus) {
ISelectionProvider selectionProvider = getSite().getSelectionProvider();
if (selectionProvider != null) {
selectionProvider.setSelection(selection);
}
if (forceFocus) {
getSite().getPage().activate(this);
Shell shell = getSite().getShell();
if (shell != null && !shell.isDisposed()) {
shell.setActive();
}
} else if (reveal) {
getSite().getPage().bringToTop(this);
}
}
public IGraphicalEditorPage findPage(Object input) {
if (input instanceof IMindMap) {
input = ((IMindMap) input).getSheet();
}
return super.findPage(input);
}
private void workbookLoaded() {
if (pageBook == null || pageBook.isDisposed())
return;
backCover.close();
Assert.isTrue(getWorkbook() != null);
createPages();
if (isEditorActive()) {
setFocus();
}
installModelListener();
firePropertyChange(PROP_INPUT);
fireDirty();
WorkbookRefManager.getInstance().hibernateAll();
}
private boolean isEditorActive() {
return getSite().getPage().getActiveEditor() == this;
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.gef.ui.editor.GraphicalEditor#findOwnedInput(org.eclipse.jface
* .viewers.ISelection)
*/
@Override
protected Object findOwnedInput(ISelection selection) {
if (selection instanceof IStructuredSelection) {
Object[] elements = ((IStructuredSelection) selection).toArray();
for (Object element : elements) {
if (element instanceof ISheetComponent)
return ((ISheetComponent) element).getOwnedSheet();
if (element instanceof ISheet)
return (ISheet) element;
}
}
return super.findOwnedInput(selection);
}
}