/* ****************************************************************************** * 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.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.ui.IEditorPart; import org.xmind.core.Core; import org.xmind.core.CoreException; import org.xmind.core.IEncryptionHandler; import org.xmind.core.IRevision; import org.xmind.core.IRevisionManager; import org.xmind.core.IRevisionRepository; import org.xmind.core.ISheet; import org.xmind.core.IWorkbook; import org.xmind.core.event.ICoreEventListener; import org.xmind.core.event.ICoreEventRegistration; import org.xmind.core.event.ICoreEventSource; import org.xmind.core.event.ICoreEventSource2; import org.xmind.core.event.ICoreEventSupport; import org.xmind.core.internal.dom.WorkbookImpl; import org.xmind.core.io.DirectoryStorage; import org.xmind.core.io.IStorage; import org.xmind.core.marker.IMarkerSheet; import org.xmind.gef.command.ICommandStack; import org.xmind.ui.internal.MindMapMessages; import org.xmind.ui.internal.MindMapUIPlugin; import org.xmind.ui.mindmap.IWorkbookRef; import org.xmind.ui.mindmap.MindMapUI; import org.xmind.ui.prefs.PrefConstants; import org.xmind.ui.util.Logger; /** * @author Frank Shaka * */ public class WorkbookRef implements IWorkbookRef, IPropertyChangeListener { private static final List<IWorkbookReferrer> EMPTY_LIST = Collections .emptyList(); private static final List<IEditorPart> EMPTY_EDITORS = Collections .emptyList(); private static final String SUBDIR_WORKBOOK = "workbooks"; //$NON-NLS-1$ private Object key; private List<IWorkbookReferrer> referrers; private IWorkbook workbook; private ICommandStack commandStack; private IWorkbookLoader workbookLoader; private IWorkbookSaver workbookSaver; private ICoreEventRegistration forceDirtyReg; private boolean previewOutdated = false; public WorkbookRef() { MindMapUIPlugin.getDefault().getPreferenceStore() .addPropertyChangeListener(this); } public void setKey(Object key) { this.key = key; } public IWorkbookLoader getWorkbookLoader() { return workbookLoader; } public IWorkbookSaver getWorkbookSaver() { return workbookSaver; } public void setWorkbookLoader(IWorkbookLoader workbookLoader) { this.workbookLoader = workbookLoader; } public void setWorkbookSaver(IWorkbookSaver workbookSaver) { this.workbookSaver = workbookSaver; } public boolean isReady() { return workbook != null || workbookLoader != null; } public void setPreviewOutdated(boolean previewOutdated) { this.previewOutdated = previewOutdated; } public boolean isPreviewOutdated() { return previewOutdated; } public void setWorkbook(IWorkbook workbook) { if (workbook == this.workbook) return; this.workbook = workbook; if (workbook != null) { IMarkerSheet markerSheet = workbook.getMarkerSheet(); if (markerSheet != null) { markerSheet.setParentSheet(MindMapUI.getResourceManager() .getUserMarkerSheet()); } } } public void setCommandStack(ICommandStack commandStack) { this.commandStack = commandStack; if (commandStack != null) { commandStack.setUndoLimit(Math.max(MindMapUIPlugin.getDefault() .getPreferenceStore().getInt(PrefConstants.UNDO_LIMIT), 1)); } } public Object getKey() { return key; } /* * (non-Javadoc) * * @see org.xmind.ui.internal.editor.IWorkbookReference#getCommandStack() */ public ICommandStack getCommandStack() { return commandStack; } /* * (non-Javadoc) * * @see org.xmind.ui.internal.editor.IWorkbookReference#getWorkbook() */ public IWorkbook getWorkbook() { return workbook; } // public void setSelection(ISelection selection, boolean reveal, // boolean forceFocus) { // IWorkbookReferrer referrer = getPrimaryReferrer(); // if (referrer != null) { // referrer.setSelection(selection, reveal, forceFocus); // } // } /* * (non-Javadoc) * * @see org.xmind.ui.internal.editor.IWorkbookReference#refresh() */ public void refresh() { //not implemented yet } /* * (non-Javadoc) * * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ public Object getAdapter(Class adapter) { if (adapter == IWorkbook.class) return getWorkbook(); if (adapter == ICommandStack.class) return getCommandStack(); return null; } public void dispose(boolean closeWorkbook) { MindMapUIPlugin.getDefault().getPreferenceStore() .removePropertyChangeListener(this); if (commandStack != null) { commandStack.dispose(); commandStack = null; } key = null; referrers = null; if (workbook != null && closeWorkbook) { closeWorkbook(workbook); } workbook = null; } private void closeWorkbook(IWorkbook workbook) { ICoreEventSupport support = (ICoreEventSupport) workbook .getAdapter(ICoreEventSupport.class); if (support != null) { support.dispatchTargetChange((ICoreEventSource) workbook, MindMapUI.WorkbookClose, this); } IStorage storage = workbook.getTempStorage(); if (storage != null) { storage.clear(); } } public void addReferrer(IWorkbookReferrer referrer) { if (referrers == null) referrers = new ArrayList<IWorkbookReferrer>(2); referrers.add(0, referrer); } public List<IWorkbookReferrer> getReferrers() { return referrers == null ? EMPTY_LIST : referrers; } public IWorkbookReferrer getPrimaryReferrer() { return referrers == null || referrers.isEmpty() ? null : referrers .get(0); } public int getNumReferrers() { return referrers == null ? 0 : referrers.size(); } public boolean isReferred() { return referrers != null && !referrers.isEmpty(); } public void removeReferrer(IWorkbookReferrer referrer) { if (referrers == null) return; referrers.remove(referrer); if (referrers.isEmpty()) referrers = null; } public boolean isContentDirty() { if (workbook == null) return false; if (getCommandStack() != null && getCommandStack().isDirty()) return true; return workbook instanceof ICoreEventSource2 && ((ICoreEventSource2) workbook) .hasOnceListeners(Core.WorkbookPreSaveOnce); } public boolean isDirty() { return isContentDirty() || isPreviewOutdated(); } /** * @deprecated */ public List<IEditorPart> getOpenedEditors() { if (referrers != null && !referrers.isEmpty()) { List<IEditorPart> editors = new ArrayList<IEditorPart>( referrers.size()); for (IWorkbookReferrer r : referrers) { if (r instanceof IEditorPart) { editors.add((IEditorPart) r); } } return editors; } return EMPTY_EDITORS; } /** * @deprecated */ public void forceDirty() { if (forceDirtyReg == null || !forceDirtyReg.isValid()) { if (workbook instanceof ICoreEventSource2) { forceDirtyReg = ((ICoreEventSource2) workbook) .registerOnceCoreEventListener( Core.WorkbookPreSaveOnce, ICoreEventListener.NULL); } else { forceDirtyReg = null; } } } /** * @deprecated */ public boolean isForceDirty() { return forceDirtyReg != null && forceDirtyReg.isValid(); } public void loadWorkbook(IEncryptionHandler encryptionHandler, IProgressMonitor monitor) throws IOException, CoreException, org.eclipse.core.runtime.CoreException { loadWorkbook(createStorage(), encryptionHandler, monitor); } public void loadWorkbook(IStorage storage, IEncryptionHandler encryptionHandler, IProgressMonitor monitor) throws IOException, CoreException, org.eclipse.core.runtime.CoreException { if (workbook != null) return; if (workbookLoader == null) throw new org.eclipse.core.runtime.CoreException(new Status( IStatus.ERROR, MindMapUIPlugin.PLUGIN_ID, "No workbook loader is set.")); //$NON-NLS-1$ setWorkbook(workbookLoader.loadWorkbook(storage, encryptionHandler, monitor)); } static IStorage createStorage() { String tempFile = Core.getIdFactory().createId() + MindMapUI.FILE_EXT_XMIND_TEMP; String tempLocation = Core.getWorkspace().getTempDir( SUBDIR_WORKBOOK + "/" + tempFile); //$NON-NLS-1$ File tempDir = new File(tempLocation); IStorage storage = new DirectoryStorage(tempDir); return storage; } public boolean isSaveable() { return workbook != null && workbookSaver != null; } public boolean canSaveToTarget() { return workbook != null && workbookSaver != null && workbookSaver.canSaveToTarget(); } public void saveWorkbook(IProgressMonitor monitor, IWorkbookReferrer previewSaver, boolean skipNewRevisions) throws IOException, CoreException, org.eclipse.core.runtime.CoreException { monitor.beginTask(null, 100); if (workbook == null) throw new org.eclipse.core.runtime.CoreException(new Status( IStatus.ERROR, MindMapUIPlugin.PLUGIN_ID, "No workbook to save.")); //$NON-NLS-1$ if (workbookSaver == null) throw new org.eclipse.core.runtime.CoreException(new Status( IStatus.ERROR, MindMapUIPlugin.PLUGIN_ID, "No workbook saver has been set.")); //$NON-NLS-1$ // Leave 1 tick for finalizing work: int mainWorkTicks = 99; if (!skipNewRevisions) { monitor.subTask(MindMapMessages.WorkbookSaver_CreateRevisions_taskName); saveRevisions(monitor); } monitor.worked(10); mainWorkTicks -= 10; if (previewSaver != null) { monitor.subTask(MindMapMessages.WorkbookSaver_SavePreviewImage_taskName); savePreview(monitor); } else { setPreviewOutdated(true); } monitor.worked(10); mainWorkTicks -= 10; monitor.subTask(MindMapMessages.WorkbookSaver_SaveWorkbookContent_taskName); workbookSaver.save(monitor, workbook); monitor.worked(mainWorkTicks); monitor.subTask(MindMapMessages.WorkbookSaver_Finalize_taskName); for (IWorkbookReferrer referrer : getReferrers()) { referrer.postSave(monitor); } monitor.done(); } public void saveWorkbookAs(Object newKey, IProgressMonitor monitor, IWorkbookReferrer previewSaver, boolean skipNewRevisions) throws IOException, CoreException, org.eclipse.core.runtime.CoreException { monitor.beginTask(null, 100); if (workbook == null) throw new org.eclipse.core.runtime.CoreException(new Status( IStatus.ERROR, MindMapUIPlugin.PLUGIN_ID, "No workbook to save.")); //$NON-NLS-1$ monitor.subTask(MindMapMessages.WorkbookSaver_PrepareNewSaveTarget_taskName); Object oldKey = getKey(); setKey(newKey); setWorkbookLoader(null); setWorkbookSaver(null); WorkbookRefInitializer.getInstance().initialize(this, newKey, getPrimaryReferrer()); if (workbookSaver == null) throw new org.eclipse.core.runtime.CoreException(new Status( IStatus.ERROR, MindMapUIPlugin.PLUGIN_ID, "No workbook saver has been set.")); //$NON-NLS-1$ // Leave 1 tick for finalizing work: int mainWorkTicks = 99; WorkbookRefManager.getInstance().changeKey(this, oldKey, newKey); monitor.worked(10); mainWorkTicks -= 10; if (!skipNewRevisions) { monitor.subTask(MindMapMessages.WorkbookSaver_CreateRevisions_taskName); saveRevisions(monitor); } monitor.worked(10); mainWorkTicks -= 10; monitor.subTask(MindMapMessages.WorkbookSaver_SavePreviewImage_taskName); savePreview(monitor); monitor.worked(10); mainWorkTicks -= 10; monitor.subTask(MindMapMessages.WorkbookSaver_SaveWorkbookContent_taskName); workbookSaver.save(monitor, workbook); monitor.worked(mainWorkTicks); monitor.subTask(MindMapMessages.WorkbookSaver_Finalize_taskName); for (IWorkbookReferrer referrer : getReferrers()) { referrer.postSaveAs(newKey, monitor); } monitor.done(); } private void saveRevisions(IProgressMonitor monitor) throws IOException, CoreException { if (!isContentDirty() || ((WorkbookImpl) workbook).isSkipRevisionsWhenSaving()) return; IRevisionRepository repo = workbook.getRevisionRepository(); for (ISheet sheet : workbook.getSheets()) { IRevisionManager manager = repo.getRevisionManager(sheet.getId(), IRevision.SHEET); IRevision latestRevision = manager.getLatestRevision(); if (latestRevision == null || sheet.getModifiedTime() == 0 || sheet.getModifiedTime() > latestRevision.getTimestamp()) { manager.addRevision(sheet); } } } private void savePreview(IProgressMonitor monitor) { IWorkbookReferrer referrer = getPrimaryReferrer(); if (referrer != null) { try { referrer.savePreivew(workbook, monitor); setPreviewOutdated(false); } catch (Throwable e) { Logger.log(e, "Failed to save preview picture."); //$NON-NLS-1$ } } } public void propertyChange(PropertyChangeEvent event) { if (commandStack != null) { if (PrefConstants.UNDO_LIMIT.equals(event.getProperty())) { commandStack.setUndoLimit(Math.max( (Integer) event.getNewValue(), 1)); } } } public void setPrimaryReferrer(IWorkbookReferrer referrer) { if (referrers != null && referrers.remove(referrer)) { referrers.add(0, referrer); } } }