/* ******************************************************************************
* 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.cathy.internal;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPersistable;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.application.IWorkbenchConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.eclipse.ui.internal.IWorkbenchConstants;
import org.eclipse.ui.internal.UIPlugin;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.xmind.cathy.internal.jobs.OpenFilesJob;
import org.xmind.core.internal.InternalCore;
import org.xmind.core.licensing.ILicenseAgent;
import org.xmind.core.licensing.ILicenseChangedListener;
import org.xmind.core.licensing.ILicenseKeyHeader;
import org.xmind.gef.ui.editor.IEditingContext;
import org.xmind.ui.internal.PasswordProvider;
import org.xmind.ui.internal.dialogs.DialogMessages;
import org.xmind.ui.internal.editor.AbstractWorkbookRef;
import org.xmind.ui.internal.editor.DefaultMindMapPreviewGenerator;
import org.xmind.ui.internal.editor.IMindMapPreviewGenerator;
import org.xmind.ui.internal.editor.IPasswordProvider;
import org.xmind.ui.mindmap.MindMapUI;
public class CathyWorkbenchAdvisor extends WorkbenchAdvisor
implements ILicenseChangedListener {
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
IWorkbenchWindowConfigurer configurer) {
return new CathyWorkbenchWindowAdvisor(configurer);
}
public String getInitialWindowPerspectiveId() {
return MindMapUI.PERSPECTIVE_ID;
}
@Override
public String getMainPreferencePageId() {
return "org.xmind.ui.prefPage.General"; //$NON-NLS-1$
}
public void initialize(IWorkbenchConfigurer configurer) {
super.initialize(configurer);
configurer.setSaveAndRestore(true);
configurer.setExitOnLastWindowClose(true);
}
@Override
public void preStartup() {
super.preStartup();
CathyPlugin.getDefault().getLicenseAgent()
.addLicenseChangedListener(this);
licenseChanged(CathyPlugin.getDefault().getLicenseAgent());
/**
* This hack requires workbench to exist. See
* {@link org.eclipse.ui.internal.PlatformUIPreferenceListener}.
*/
UIPlugin.getDefault().getPreferenceStore().setValue(
IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS,
true);
}
@Override
public void postStartup() {
super.postStartup();
IWorkbench workbench = getWorkbenchConfigurer().getWorkbench();
AbstractWorkbookRef.setDefaultEditingContext(
createDefaultEditingContext(workbench));
new StartUpProcess(workbench).startUp();
}
private IEditingContext createDefaultEditingContext(
final IWorkbench workbench) {
final IMindMapPreviewGenerator previewGenerator = new DefaultMindMapPreviewGenerator(
workbench.getDisplay());
final IPasswordProvider passwordProvider = new PasswordProvider();
return new IEditingContext() {
public <T> T getAdapter(Class<T> adapter) {
if (IMindMapPreviewGenerator.class.equals(adapter))
return adapter.cast(previewGenerator);
if (IPasswordProvider.class.equals(adapter))
return adapter.cast(passwordProvider);
T result;
result = workbench.getService(adapter);
if (result != null)
return result;
result = workbench.getAdapter(adapter);
if (result != null)
return result;
return result;
}
};
}
@Override
public void postShutdown() {
CathyPlugin.getDefault().getLicenseAgent()
.removeLicenseChangedListener(this);
AbstractWorkbookRef.setDefaultEditingContext(null);
super.postShutdown();
}
public boolean preShutdown() {
boolean readyToShutdown = super.preShutdown();
if (readyToShutdown) {
readyToShutdown = saveAllEditorsOnClose();
}
return readyToShutdown;
}
private boolean saveAllEditorsOnClose() {
IWorkbench workbench = getWorkbenchConfigurer().getWorkbench();
final ArrayList<IEditorReference> unClosedEditorRefs = new ArrayList<IEditorReference>();
IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
for (IWorkbenchWindow window : windows) {
IWorkbenchPage page = window.getActivePage();
for (IEditorReference editorRef : page.getEditorReferences()) {
unClosedEditorRefs.add(editorRef);
final IEditorPart editor = editorRef.getEditor(false);
if (editor != null && editor.isDirty()) {
int answer = promptToSaveOnClose(window, page, editor);
if (answer == ISaveablePart2.CANCEL)
return false;
if (answer == ISaveablePart2.YES) {
if (!doSaveEditor(window, editor)) {
return false;
}
}
}
}
}
SafeRunner.run(new SafeRunnable() {
public void run() {
XMLMemento mem = recordEditorsState(unClosedEditorRefs);
saveMementoToFile(mem);
}
});
return closeAllEditors();
}
private XMLMemento recordEditorsState(
ArrayList<IEditorReference> editorRefs) {
XMLMemento memento = XMLMemento.createWriteRoot("xmind"); //$NON-NLS-1$
saveEditorsState(memento, editorRefs);
return memento;
}
private void saveEditorsState(IMemento memento,
ArrayList<IEditorReference> editorRefs) {
IWorkbenchPage activePage = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
IEditorPart activeEditor = activePage.getActiveEditor();
IMemento childrenMemento = memento
.createChild(IWorkbenchConstants.TAG_EDITORS);
if (!editorRefs.isEmpty())
for (IEditorReference ref : editorRefs) {
IEditorPart editor = ref.getEditor(false);
IMemento editorMemento = childrenMemento
.createChild(IWorkbenchConstants.TAG_EDITOR);
editorMemento.putBoolean(IWorkbenchConstants.TAG_ACTIVE_PART,
editor == activeEditor);
IPersistable editorPersistable = CathyPlugin.getAdapter(editor,
IPersistable.class);
if (editorPersistable != null) {
editorPersistable.saveState(editorMemento);
}
IEditorInput input = editor.getEditorInput();
IMemento inputMemento = editorMemento
.createChild(IWorkbenchConstants.TAG_INPUT);
IPersistableElement inputPersistable = CathyPlugin
.getAdapter(input, IPersistableElement.class);
if (inputPersistable != null) {
inputMemento.putString(IWorkbenchConstants.TAG_FACTORY_ID,
inputPersistable.getFactoryId());
inputPersistable.saveState(inputMemento);
}
}
}
private boolean saveMementoToFile(XMLMemento memento) {
// Save it to a file.
File stateFile = getEditorsStateFile();
if (stateFile == null) {
return false;
}
try {
FileOutputStream stream = new FileOutputStream(stateFile);
OutputStreamWriter writer = new OutputStreamWriter(stream, "utf-8"); //$NON-NLS-1$
memento.save(writer);
writer.close();
} catch (IOException e) {
stateFile.delete();
return false;
}
// Success !
return true;
}
private File getEditorsStateFile() {
IPath path = WorkbenchPlugin.getDefault().getDataLocation();
if (path == null) {
return null;
}
path = path.append("XMind_Editors.xml"); //$NON-NLS-1$
return path.toFile();
}
private int promptToSaveOnClose(IWorkbenchWindow window,
IWorkbenchPage page, IEditorPart editor) {
if (editor instanceof ISaveablePart2) {
int answer = ((ISaveablePart2) editor).promptToSaveOnClose();
if (answer != ISaveablePart2.DEFAULT)
return answer;
}
page.activate(editor);
MessageDialog dialog = new MessageDialog(window.getShell(),
DialogMessages.Save_title, null,
NLS.bind(WorkbenchMessages.PromptSaveEditorOnClosing_message,
editor.getTitle()),
MessageDialog.QUESTION,
new String[] { IDialogConstants.YES_LABEL,
IDialogConstants.NO_LABEL,
IDialogConstants.CANCEL_LABEL },
0);
int answerIndex = dialog.open();
switch (answerIndex) {
case 0:
return ISaveablePart2.YES;
case 1:
return ISaveablePart2.NO;
default:
return ISaveablePart2.CANCEL;
}
}
private boolean doSaveEditor(final IWorkbenchWindow window,
final IEditorPart editor) {
final boolean[] saved = new boolean[1];
saved[0] = false;
window.getShell().getDisplay().syncExec(new Runnable() {
public void run() {
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
final IProgressMonitor monitor = new NullProgressMonitor();
if (InternalCore.DEBUG_WORKBOOK_SAVE)
CathyPlugin.log(
"CathyWorkbenchAdvisor: About to save workbook on workbench close: " //$NON-NLS-1$
+ editor.getEditorInput()
.toString());
editor.doSave(monitor);
if (!monitor.isCanceled()) {
saved[0] = true;
} else {
if (InternalCore.DEBUG_WORKBOOK_SAVE)
CathyPlugin.log(
"CathyWorkbenchAdvisor: Finished saving workbook on workbench close: " //$NON-NLS-1$
+ editor.getEditorInput()
.toString());
}
}
});
}
});
return saved[0];
}
private boolean closeAllEditors() {
boolean closed = false;
IWorkbench workbench = getWorkbenchConfigurer().getWorkbench();
for (IWorkbenchWindow window : workbench.getWorkbenchWindows()) {
closed |= window.getActivePage().closeAllEditors(false);
}
return closed;
}
public void licenseChanged(ILicenseAgent agent) {
int type = agent.getLicenseType();
ILicenseKeyHeader header = agent.getLicenseKeyHeader();
String brandingVersion = System
.getProperty("org.xmind.product.brandingVersion", ""); //$NON-NLS-1$ //$NON-NLS-2$
String licenseType;
if ((type & ILicenseAgent.PRO_LICENSE_KEY) != 0) {
licenseType = NLS.bind(WorkbenchMessages.About_ProTitle,
brandingVersion);
} else if ((type & ILicenseAgent.PLUS_LICENSE_KEY) != 0) {
licenseType = NLS.bind(WorkbenchMessages.About_PlusTitle,
brandingVersion);
} else if ((type & ILicenseAgent.PRO_SUBSCRIPTION) != 0) {
licenseType = WorkbenchMessages.About_ProSubscriptionTitle;
} else {
licenseType = null;
}
if (header != null && ((type & ILicenseAgent.PLUS_LICENSE_KEY) != 0
|| (type & ILicenseAgent.PRO_LICENSE_KEY) != 0)) {
String licenseeType = header.getLicenseeType();
if (ILicenseKeyHeader.LICENSEE_FAMILY.equals(licenseeType)) {
licenseType = NLS.bind("{0} (Family License)", licenseType); //$NON-NLS-1$
} else if (ILicenseKeyHeader.LICENSEE_EDU.equals(licenseeType)) {
licenseType = NLS.bind("{0} (Academia License)", licenseType); //$NON-NLS-1$
} else if (ILicenseKeyHeader.LICENSEE_GOV.equals(licenseeType)) {
licenseType = NLS.bind("{0} (Gov/NPO License)", licenseType); //$NON-NLS-1$
} else if (ILicenseKeyHeader.LICENSEE_TEAM_5U.equals(licenseeType)
|| ILicenseKeyHeader.LICENSEE_TEAM_10U.equals(licenseeType)
|| ILicenseKeyHeader.LICENSEE_TEAM_20U
.equals(licenseeType)) {
licenseType = NLS.bind("{0} (Team License)", licenseType); //$NON-NLS-1$
} else if (ILicenseKeyHeader.LICENSEE_VLE.equals(licenseeType)) {
licenseType = NLS.bind("{0} (Volume License)", licenseType); //$NON-NLS-1$
}
}
if (licenseType == null) {
licenseType = WorkbenchMessages.About_LicenseType_Unactivated;
} else {
licenseType = NLS.bind(WorkbenchMessages.About_LicenseTypePattern,
licenseType);
}
System.setProperty("org.xmind.product.license.type", //$NON-NLS-1$
licenseType);
String name = agent.getLicenseeName();
if (name != null && !"".equals(name)) { //$NON-NLS-1$
name = NLS.bind(WorkbenchMessages.About_LicensedTo, name);
} else {
name = ""; //$NON-NLS-1$
}
System.setProperty("org.xmind.product.license.licensee", name); //$NON-NLS-1$
}
@Override
public void eventLoopIdle(Display display) {
String[] paths = OpenDocumentQueue.getInstance().drain();
if (paths.length > 0) {
CathyPlugin.log("Ready to open files: " + Arrays.toString(paths)); //$NON-NLS-1$
openFiles(paths);
IWorkbenchWindow window = getWorkbenchConfigurer().getWorkbench()
.getActiveWorkbenchWindow();
if (window != null) {
Shell shell = window.getShell();
if (shell != null && !shell.isDisposed()) {
shell.forceActive();
}
}
} else {
super.eventLoopIdle(display);
}
}
private void openFiles(String[] paths) {
OpenFilesJob job = new OpenFilesJob(
getWorkbenchConfigurer().getWorkbench(),
WorkbenchMessages.CheckOpenFilesJob_CheckFiles_name,
Arrays.asList(paths));
job.setRule(Log.get(Log.OPENING));
job.schedule();
}
}