/* ******************************************************************************
* Copyright (c) 2006-2016 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.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.eclipse.ui.internal.IWorkbenchConstants;
import org.xmind.ui.util.Cancelable;
import org.xmind.ui.util.ICancelable;
/**
* @author Frank Shaka
*
*/
public class EditorStatePersistance {
private static final String PATH_SESSION = "editorstates.xml"; //$NON-NLS-1$
private class EditorStateLabelProvider extends LabelProvider {
private LocalResourceManager resources;
/**
*
*/
public EditorStateLabelProvider() {
this.resources = new LocalResourceManager(
JFaceResources.getResources());
}
public String getText(Object element) {
if (element instanceof IMemento) {
IMemento state = (IMemento) element;
String name = state.getString(IWorkbenchConstants.TAG_TITLE);
if (name == null) {
name = state.getString(IWorkbenchConstants.TAG_NAME);
}
if (name == null) {
name = state.getString(IWorkbenchConstants.TAG_PART_NAME);
}
if (name == null) {
String editorId = state
.getString(IWorkbenchConstants.TAG_ID);
if (editorId != null) {
IEditorDescriptor editor = workbench.getEditorRegistry()
.findEditor(editorId);
if (editor != null) {
name = editor.getLabel();
}
}
}
if (name == null) {
name = ""; //$NON-NLS-1$
}
return name;
}
return super.getText(element);
}
public Image getImage(Object element) {
if (element instanceof IMemento) {
IMemento state = (IMemento) element;
String editorId = state.getString(IWorkbenchConstants.TAG_ID);
if (editorId != null) {
IEditorDescriptor editor = workbench.getEditorRegistry()
.findEditor(editorId);
if (editor != null) {
ImageDescriptor icon = editor.getImageDescriptor();
if (icon != null)
return (Image) resources.get(icon);
}
}
}
return super.getImage(element);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.BaseLabelProvider#dispose()
*/
@Override
public void dispose() {
resources.dispose();
super.dispose();
}
}
private final IWorkbench workbench;
private final IPath basePath;
private final ILogger logger;
private final int autoSaveIntervals;
private ICancelable autoSaveTask;
/**
*
*/
public EditorStatePersistance(IWorkbench workbench, IPath basePath,
ILogger logger, int autoSaveIntervals) {
this.workbench = workbench;
this.basePath = basePath;
this.logger = logger == null ? ILogger.DEFAULT : logger;
this.autoSaveIntervals = autoSaveIntervals;
this.autoSaveTask = null;
}
/**
* Must be called within the UI thread.
*
* @throws WorkbenchException
*/
public void startUp() throws WorkbenchException {
final Display display = workbench.getDisplay();
Assert.isNotNull(display);
Assert.isTrue(display == Display.getCurrent());
try {
recoverLastSession();
} finally {
schedule(display);
workbench.addWorkbenchListener(new IWorkbenchListener() {
public boolean preShutdown(IWorkbench workbench,
boolean forced) {
return true;
}
public void postShutdown(IWorkbench workbench) {
shutDown();
}
});
}
}
/**
* @return
*/
private File getSessionFile() {
return basePath.append(PATH_SESSION).toFile();
}
/**
* @throws WorkbenchException
*/
private void recoverLastSession() throws WorkbenchException {
File sessionFile = getSessionFile();
if (sessionFile == null || !sessionFile.exists())
return;
XMLMemento root;
try {
Reader reader = new BufferedReader(new FileReader(sessionFile));
root = XMLMemento.createReadRoot(reader);
} catch (IOException e) {
logger.logError(null, e);
return;
} finally {
sessionFile.delete();
}
IMemento[] states = root.getChildren(IWorkbenchConstants.TAG_EDITOR);
if (states.length == 0)
return;
ListSelectionDialog dialog = new ListSelectionDialog(null, states,
new ArrayContentProvider(), new EditorStateLabelProvider(),
WorkbenchMessages.appWindow_ListSelectionDialog_Text);
dialog.setTitle(WorkbenchMessages.appWindow_ListSelectionDialog_Title);
dialog.setInitialSelections(states);
int ret = dialog.open();
if (ret == ListSelectionDialog.CANCEL)
return;
Object[] result = dialog.getResult();
if (result == null)
return;
states = new IMemento[result.length];
System.arraycopy(result, 0, states, 0, result.length);
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
if (window == null) {
window = workbench.openWorkbenchWindow(null);
}
IWorkbenchPage page = window.getActivePage();
if (page == null) {
page = window.openPage(null);
}
page.openEditors(null, null, states, 0, 0);
}
public void shutDown() {
ICancelable task = this.autoSaveTask;
this.autoSaveTask = null;
if (task != null) {
task.cancel();
}
File sessionFile = getSessionFile();
if (sessionFile != null) {
sessionFile.delete();
}
}
private void schedule(final Display display) {
ICancelable oldTask = this.autoSaveTask;
ICancelable task = new Cancelable() {
@Override
protected void doJob() {
autoSave(display);
}
};
this.autoSaveTask = task;
display.timerExec(autoSaveIntervals, task);
if (oldTask != null) {
oldTask.cancel();
}
}
private void autoSave(final Display display) {
try {
save();
} catch (Throwable e) {
logger.logError(null, e);
}
schedule(display);
}
/**
*
*/
private void save() throws IOException {
File sessionFile = getSessionFile();
if (sessionFile == null)
return;
List<IMemento> states = new ArrayList<IMemento>();
for (IWorkbenchWindow window : workbench.getWorkbenchWindows()) {
IWorkbenchPage page = window.getActivePage();
if (page == null)
continue;
IMemento[] editorState = page
.getEditorState(page.getEditorReferences(), true);
states.addAll(Arrays.asList(editorState));
}
XMLMemento root = XMLMemento
.createWriteRoot(IWorkbenchConstants.TAG_EDITORS);
for (IMemento state : states) {
IMemento st = root.createChild(state.getType());
st.putMemento(state);
}
File dir = sessionFile.getParentFile();
if (dir != null && !dir.exists()) {
dir.mkdirs();
}
BufferedWriter writer = new BufferedWriter(new FileWriter(sessionFile));
try {
root.save(writer);
} finally {
writer.close();
}
}
}