Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 226618 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/mylyn/internal/context/ui/ContextUiPlugin.java (-2 / +74 lines)
Lines 11-16 Link Here
11
11
12
package org.eclipse.mylyn.internal.context.ui;
12
package org.eclipse.mylyn.internal.context.ui;
13
13
14
import java.io.File;
15
import java.io.StringReader;
14
import java.util.ArrayList;
16
import java.util.ArrayList;
15
import java.util.Collections;
17
import java.util.Collections;
16
import java.util.HashMap;
18
import java.util.HashMap;
Lines 27-35 Link Here
27
import org.eclipse.core.runtime.IExtension;
29
import org.eclipse.core.runtime.IExtension;
28
import org.eclipse.core.runtime.IExtensionPoint;
30
import org.eclipse.core.runtime.IExtensionPoint;
29
import org.eclipse.core.runtime.IExtensionRegistry;
31
import org.eclipse.core.runtime.IExtensionRegistry;
32
import org.eclipse.core.runtime.IPath;
30
import org.eclipse.core.runtime.IStatus;
33
import org.eclipse.core.runtime.IStatus;
31
import org.eclipse.core.runtime.Platform;
34
import org.eclipse.core.runtime.Platform;
32
import org.eclipse.core.runtime.Status;
35
import org.eclipse.core.runtime.Status;
36
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
37
import org.eclipse.core.runtime.preferences.InstanceScope;
33
import org.eclipse.jface.dialogs.MessageDialog;
38
import org.eclipse.jface.dialogs.MessageDialog;
34
import org.eclipse.jface.preference.IPreferenceStore;
39
import org.eclipse.jface.preference.IPreferenceStore;
35
import org.eclipse.jface.resource.ImageDescriptor;
40
import org.eclipse.jface.resource.ImageDescriptor;
Lines 47-52 Link Here
47
import org.eclipse.mylyn.context.core.IInteractionRelation;
52
import org.eclipse.mylyn.context.core.IInteractionRelation;
48
import org.eclipse.mylyn.context.ui.AbstractContextUiBridge;
53
import org.eclipse.mylyn.context.ui.AbstractContextUiBridge;
49
import org.eclipse.mylyn.context.ui.IContextUiStartup;
54
import org.eclipse.mylyn.context.ui.IContextUiStartup;
55
import org.eclipse.mylyn.internal.context.core.InteractionContext;
50
import org.eclipse.mylyn.internal.monitor.ui.MonitorUiPlugin;
56
import org.eclipse.mylyn.internal.monitor.ui.MonitorUiPlugin;
51
import org.eclipse.mylyn.monitor.ui.MonitorUi;
57
import org.eclipse.mylyn.monitor.ui.MonitorUi;
52
import org.eclipse.mylyn.tasks.core.ITask;
58
import org.eclipse.mylyn.tasks.core.ITask;
Lines 57-70 Link Here
57
import org.eclipse.swt.graphics.Image;
63
import org.eclipse.swt.graphics.Image;
58
import org.eclipse.ui.IEditorInput;
64
import org.eclipse.ui.IEditorInput;
59
import org.eclipse.ui.IEditorPart;
65
import org.eclipse.ui.IEditorPart;
66
import org.eclipse.ui.IMemento;
60
import org.eclipse.ui.IViewPart;
67
import org.eclipse.ui.IViewPart;
61
import org.eclipse.ui.IViewReference;
68
import org.eclipse.ui.IViewReference;
62
import org.eclipse.ui.IWorkbench;
69
import org.eclipse.ui.IWorkbench;
63
import org.eclipse.ui.IWorkbenchWindow;
70
import org.eclipse.ui.IWorkbenchWindow;
64
import org.eclipse.ui.PlatformUI;
71
import org.eclipse.ui.PlatformUI;
72
import org.eclipse.ui.WorkbenchException;
73
import org.eclipse.ui.XMLMemento;
65
import org.eclipse.ui.internal.WorkbenchPlugin;
74
import org.eclipse.ui.internal.WorkbenchPlugin;
66
import org.eclipse.ui.plugin.AbstractUIPlugin;
75
import org.eclipse.ui.plugin.AbstractUIPlugin;
76
import org.eclipse.ui.preferences.ScopedPreferenceStore;
67
import org.osgi.framework.BundleContext;
77
import org.osgi.framework.BundleContext;
78
import org.osgi.service.prefs.BackingStoreException;
68
79
69
/**
80
/**
70
 * Main entry point for the Context UI.
81
 * Main entry point for the Context UI.
Lines 75-80 Link Here
75
 */
86
 */
76
public class ContextUiPlugin extends AbstractUIPlugin {
87
public class ContextUiPlugin extends AbstractUIPlugin {
77
88
89
	private static final String EDITOR_MEMENTO_PREFS_PREFIX = "editors.task."; //$NON-NLS-1$
90
78
	public static final String ID_PLUGIN = "org.eclipse.mylyn.context.ui"; //$NON-NLS-1$
91
	public static final String ID_PLUGIN = "org.eclipse.mylyn.context.ui"; //$NON-NLS-1$
79
92
80
	private class ContextActivationListener extends AbstractContextListener {
93
	private class ContextActivationListener extends AbstractContextListener {
Lines 212-217 Link Here
212
225
213
	private ContextEditorManager editorManager;
226
	private ContextEditorManager editorManager;
214
227
228
	private ContextMementoManager mementoManager;
229
215
	public ContextUiPlugin() {
230
	public ContextUiPlugin() {
216
		INSTANCE = this;
231
		INSTANCE = this;
217
	}
232
	}
Lines 260-267 Link Here
260
			MonitorUi.addWindowPerspectiveListener(perspectiveManager);
275
			MonitorUi.addWindowPerspectiveListener(perspectiveManager);
261
			TasksUi.getTaskActivityManager().addActivationListener(TASK_ACTIVATION_LISTENER);
276
			TasksUi.getTaskActivityManager().addActivationListener(TASK_ACTIVATION_LISTENER);
262
277
278
			mementoManager = new ContextMementoManager(ContextCore.getContextManager(), getContextMementoPath());
279
			mementoManager.start();
280
263
			editorManager = new ContextEditorManager();
281
			editorManager = new ContextEditorManager();
264
			ContextCore.getContextManager().addListener(editorManager);
282
			editorManager.start(ContextCore.getContextManager(), mementoManager);
283
284
			migrateContextMementos(mementoManager);
265
		} catch (Exception e) {
285
		} catch (Exception e) {
266
			StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, "Context UI initialization failed", //$NON-NLS-1$
286
			StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, "Context UI initialization failed", //$NON-NLS-1$
267
					e));
287
					e));
Lines 293-301 Link Here
293
		}
313
		}
294
	}
314
	}
295
315
316
	// XXX verify this works...delete preferences?
317
	private void migrateContextMementos(ContextMementoManager mementoManager) {
318
		ScopedPreferenceStore preferenceStore = new ScopedPreferenceStore(new InstanceScope(),
319
				"org.eclipse.mylyn.resources.ui"); //$NON-NLS-1$
320
321
		IEclipsePreferences[] nodes = preferenceStore.getPreferenceNodes(false);
322
		if (nodes.length > 0) {
323
			String[] keys;
324
			try {
325
				keys = nodes[0].keys();
326
				for (String key : keys) {
327
					if (key.startsWith(EDITOR_MEMENTO_PREFS_PREFIX)) {
328
						String contextHandle = key.substring(EDITOR_MEMENTO_PREFS_PREFIX.length());
329
						String mementoString = preferenceStore.getString(key);
330
						if (mementoString != null && !mementoString.trim().equals("")) { //$NON-NLS-1$
331
							try {
332
								IMemento oldMemento = XMLMemento.createReadRoot(new StringReader(mementoString));
333
								InteractionContext context = new InteractionContext(contextHandle,
334
										ContextCore.getCommonContextScaling());
335
								ContextMemento state = mementoManager.createMemento(context, contextHandle);
336
								IMemento newMemnto = state.createMemento("editors");
337
								newMemnto.putMemento(oldMemento);
338
								mementoManager.write(state);
339
							} catch (WorkbenchException e) {
340
								StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN,
341
										"Migration of editor memento failed", e)); //$NON-NLS-1$
342
							}
343
						}
344
					}
345
				}
346
			} catch (BackingStoreException e) {
347
				StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN,
348
						"Migration of editor mementos failed", e)); //$NON-NLS-1$
349
			}
350
		}
351
	}
352
296
	private void lazyStop() {
353
	private void lazyStop() {
297
		if (editorManager != null) {
354
		if (editorManager != null) {
298
			ContextCore.getContextManager().removeListener(editorManager);
355
			editorManager.stop(ContextCore.getContextManager(), mementoManager);
356
		}
357
358
		if (mementoManager != null) {
359
			mementoManager.stop();
299
		}
360
		}
300
361
301
		ContextCore.getContextManager().removeListener(viewerManager);
362
		ContextCore.getContextManager().removeListener(viewerManager);
Lines 649-652 Link Here
649
	public static ContextPerspectiveManager getPerspectiveManager() {
710
	public static ContextPerspectiveManager getPerspectiveManager() {
650
		return INSTANCE.perspectiveManager;
711
		return INSTANCE.perspectiveManager;
651
	}
712
	}
713
714
	private File getContextMementoPath() {
715
		IPath stateLocation = Platform.getStateLocation(getBundle());
716
		IPath cacheFile = stateLocation.append("workbench"); //$NON-NLS-1$
717
		return cacheFile.toFile();
718
	}
719
720
	public ContextMementoManager getMementoManager() {
721
		return mementoManager;
722
	}
723
652
}
724
}
(-)src/org/eclipse/mylyn/internal/context/ui/ContextEditorManager.java (-74 / +80 lines)
Lines 11-19 Link Here
11
11
12
package org.eclipse.mylyn.internal.context.ui;
12
package org.eclipse.mylyn.internal.context.ui;
13
13
14
import java.io.IOException;
15
import java.io.StringReader;
16
import java.io.StringWriter;
17
import java.util.ArrayList;
14
import java.util.ArrayList;
18
import java.util.Arrays;
15
import java.util.Arrays;
19
import java.util.HashSet;
16
import java.util.HashSet;
Lines 23-36 Link Here
23
import org.eclipse.core.runtime.IStatus;
20
import org.eclipse.core.runtime.IStatus;
24
import org.eclipse.core.runtime.MultiStatus;
21
import org.eclipse.core.runtime.MultiStatus;
25
import org.eclipse.core.runtime.Status;
22
import org.eclipse.core.runtime.Status;
26
import org.eclipse.core.runtime.preferences.InstanceScope;
27
import org.eclipse.jface.preference.IPreferenceStore;
28
import org.eclipse.mylyn.commons.core.StatusHandler;
23
import org.eclipse.mylyn.commons.core.StatusHandler;
29
import org.eclipse.mylyn.context.core.AbstractContextListener;
24
import org.eclipse.mylyn.context.core.AbstractContextListener;
30
import org.eclipse.mylyn.context.core.AbstractContextStructureBridge;
25
import org.eclipse.mylyn.context.core.AbstractContextStructureBridge;
31
import org.eclipse.mylyn.context.core.ContextChangeEvent;
26
import org.eclipse.mylyn.context.core.ContextChangeEvent;
32
import org.eclipse.mylyn.context.core.ContextCore;
27
import org.eclipse.mylyn.context.core.ContextCore;
33
import org.eclipse.mylyn.context.core.IInteractionContext;
28
import org.eclipse.mylyn.context.core.IInteractionContextManager;
34
import org.eclipse.mylyn.context.core.IInteractionElement;
29
import org.eclipse.mylyn.context.core.IInteractionElement;
35
import org.eclipse.mylyn.context.ui.AbstractContextUiBridge;
30
import org.eclipse.mylyn.context.ui.AbstractContextUiBridge;
36
import org.eclipse.mylyn.context.ui.ContextUi;
31
import org.eclipse.mylyn.context.ui.ContextUi;
Lines 48-71 Link Here
48
import org.eclipse.ui.IWorkbenchWindow;
43
import org.eclipse.ui.IWorkbenchWindow;
49
import org.eclipse.ui.PartInitException;
44
import org.eclipse.ui.PartInitException;
50
import org.eclipse.ui.PlatformUI;
45
import org.eclipse.ui.PlatformUI;
51
import org.eclipse.ui.XMLMemento;
52
import org.eclipse.ui.internal.EditorManager;
46
import org.eclipse.ui.internal.EditorManager;
53
import org.eclipse.ui.internal.IPreferenceConstants;
47
import org.eclipse.ui.internal.IPreferenceConstants;
54
import org.eclipse.ui.internal.IWorkbenchConstants;
48
import org.eclipse.ui.internal.IWorkbenchConstants;
55
import org.eclipse.ui.internal.Workbench;
49
import org.eclipse.ui.internal.Workbench;
56
import org.eclipse.ui.internal.WorkbenchPage;
50
import org.eclipse.ui.internal.WorkbenchPage;
57
import org.eclipse.ui.internal.WorkbenchWindow;
51
import org.eclipse.ui.internal.WorkbenchWindow;
58
import org.eclipse.ui.preferences.ScopedPreferenceStore;
59
52
60
/**
53
/**
61
 * @author Mik Kersten
54
 * @author Mik Kersten
62
 * @author Shawn Minto
55
 * @author Shawn Minto
63
 */
56
 */
64
public class ContextEditorManager extends AbstractContextListener {
57
public class ContextEditorManager {
65
58
66
	private static final String PREFS_PREFIX = "editors.task."; //$NON-NLS-1$
59
	private class MementoListener extends ContextMementoListener {
67
60
68
	private static final String KEY_CONTEXT_EDITORS = "ContextOpenEditors"; //$NON-NLS-1$
61
		@Override
62
		public void clearState(String contextHandle, boolean isActiveContext) {
63
			ContextEditorManager.this.clearState(contextHandle, isActiveContext);
64
		};
65
66
		@Override
67
		public void restoreState(ContextMemento memento) {
68
			ContextEditorManager.this.restoreState(memento);
69
		}
70
71
		@Override
72
		public void saveState(ContextMemento memento) {
73
			ContextEditorManager.this.saveState(memento);
74
		}
75
76
	}
77
78
	private class ContextListener extends AbstractContextListener {
79
80
		@Override
81
		public void contextChanged(ContextChangeEvent event) {
82
			switch (event.getEventKind()) {
83
			case INTEREST_CHANGED:
84
				for (IInteractionElement element : event.getElements()) {
85
					closeEditor(element, false);
86
				}
87
				break;
88
			case ELEMENTS_DELETED:
89
				for (IInteractionElement element : event.getElements()) {
90
					closeEditor(element, true);
91
				}
92
				break;
93
			}
94
		}
95
	}
69
96
70
	private static final String KEY_MONITORED_WINDOW_OPEN_EDITORS = "MonitoredWindowOpenEditors"; //$NON-NLS-1$
97
	private static final String KEY_MONITORED_WINDOW_OPEN_EDITORS = "MonitoredWindowOpenEditors"; //$NON-NLS-1$
71
98
Lines 80-120 Link Here
80
	private boolean previousCloseEditorsSetting = Workbench.getInstance().getPreferenceStore().getBoolean(
107
	private boolean previousCloseEditorsSetting = Workbench.getInstance().getPreferenceStore().getBoolean(
81
			IPreferenceConstants.REUSE_EDITORS_BOOLEAN);
108
			IPreferenceConstants.REUSE_EDITORS_BOOLEAN);
82
109
83
	private final IPreferenceStore preferenceStore;
110
	private final MementoListener mementoListener;
111
112
	private final ContextListener contextListener;
113
114
	//private final IPreferenceStore preferenceStore;
84
115
85
	public ContextEditorManager() {
116
	public ContextEditorManager() {
86
		preferenceStore = new ScopedPreferenceStore(new InstanceScope(), "org.eclipse.mylyn.resources.ui"); //$NON-NLS-1$
117
		//preferenceStore = new ScopedPreferenceStore(new InstanceScope(), "org.eclipse.mylyn.resources.ui"); //$NON-NLS-1$
118
		this.mementoListener = new MementoListener();
119
		this.contextListener = new ContextListener();
87
	}
120
	}
88
121
89
	@Override
122
	public void start(IInteractionContextManager contextManager, ContextMementoManager mementoManager) {
90
	public void contextChanged(ContextChangeEvent event) {
123
		contextManager.addListener(contextListener);
91
		switch (event.getEventKind()) {
124
		mementoManager.addMementoListener(mementoListener);
92
		case ACTIVATED:
125
	}
93
			openEditorsFromMemento(event.getContext());
94
			break;
95
		case DEACTIVATED:
96
			closeEditorsAndSaveMemento(event.getContext());
97
			break;
98
		case INTEREST_CHANGED:
99
			for (IInteractionElement element : event.getElements()) {
100
				closeEditor(element, false);
101
			}
102
			break;
103
		case ELEMENTS_DELETED:
104
			for (IInteractionElement element : event.getElements()) {
105
				closeEditor(element, true);
106
			}
107
			break;
108
		case CLEARED:
109
			// use the handle since the context is null when it is cleared
110
			// bug 255588
111
			clearEditorMemento(event.getContextHandle(), event.isActiveContext());
112
			break;
113
126
114
		}
127
	public void stop(IInteractionContextManager contextManager, ContextMementoManager mementoManager) {
128
		contextManager.removeListener(contextListener);
129
		mementoManager.removeMementoListener(mementoListener);
115
	}
130
	}
116
131
117
	public void openEditorsFromMemento(IInteractionContext context) {
132
	public void restoreState(ContextMemento state) {
118
		if (!Workbench.getInstance().isStarting()
133
		if (!Workbench.getInstance().isStarting()
119
				&& ContextUiPlugin.getDefault().getPreferenceStore().getBoolean(
134
				&& ContextUiPlugin.getDefault().getPreferenceStore().getBoolean(
120
						IContextUiPreferenceContstants.AUTO_MANAGE_EDITORS) && !TaskMigrator.isActive()) {
135
						IContextUiPreferenceContstants.AUTO_MANAGE_EDITORS) && !TaskMigrator.isActive()) {
Lines 131-139 Link Here
131
				// TODO change where memento is stored
146
				// TODO change where memento is stored
132
				IWorkbenchWindow activeWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
147
				IWorkbenchWindow activeWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
133
				try {
148
				try {
134
					mementoString = readEditorMemento(context);
149
					//mementoString = readEditorMemento(context);
135
					if (mementoString != null && !mementoString.trim().equals("")) { //$NON-NLS-1$
150
//					if (mementoString != null && !mementoString.trim().equals("")) { //$NON-NLS-1$
136
						IMemento memento = XMLMemento.createReadRoot(new StringReader(mementoString));
151
//						IMemento memento = XMLMemento.createReadRoot(new StringReader(mementoString));
152
					IMemento memento = state.getMemento("editors");
153
					if (memento != null) {
137
						IMemento[] children = memento.getChildren(KEY_MONITORED_WINDOW_OPEN_EDITORS);
154
						IMemento[] children = memento.getChildren(KEY_MONITORED_WINDOW_OPEN_EDITORS);
138
						if (children.length > 0) {
155
						if (children.length > 0) {
139
							// This code supports restore from multiple windows
156
							// This code supports restore from multiple windows
Lines 156-162 Link Here
156
							"Could not restore all editors, memento: \"" + mementoString + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$
173
							"Could not restore all editors, memento: \"" + mementoString + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$
157
				}
174
				}
158
				activeWindow.setActivePage(activeWindow.getActivePage());
175
				activeWindow.setActivePage(activeWindow.getActivePage());
159
				IInteractionElement activeNode = context.getActiveNode();
176
				IInteractionElement activeNode = state.getContext().getActiveNode();
160
				if (activeNode != null) {
177
				if (activeNode != null) {
161
					ContextUi.getUiBridge(activeNode.getContentType()).open(activeNode);
178
					ContextUi.getUiBridge(activeNode.getContentType()).open(activeNode);
162
				}
179
				}
Lines 170-176 Link Here
170
	}
187
	}
171
188
172
	private WorkbenchPage getWorkbenchPageForMemento(IMemento memento, IWorkbenchWindow activeWindow) {
189
	private WorkbenchPage getWorkbenchPageForMemento(IMemento memento, IWorkbenchWindow activeWindow) {
173
174
		String windowToRestoreClassName = memento.getString(ATTRIBUTE_CLASS);
190
		String windowToRestoreClassName = memento.getString(ATTRIBUTE_CLASS);
175
		if (windowToRestoreClassName == null) {
191
		if (windowToRestoreClassName == null) {
176
			windowToRestoreClassName = ""; //$NON-NLS-1$
192
			windowToRestoreClassName = ""; //$NON-NLS-1$
Lines 224-245 Link Here
224
		return null;
240
		return null;
225
	}
241
	}
226
242
227
	private String readEditorMemento(IInteractionContext context) {
243
//	private String readEditorMemento(IInteractionContext context) {
228
		return preferenceStore.getString(PREFS_PREFIX + context.getHandleIdentifier());
244
//		return preferenceStore.getString(PREFS_PREFIX + context.getHandleIdentifier());
229
	}
245
//	}
230
246
231
	public void closeEditorsAndSaveMemento(IInteractionContext context) {
247
	public void saveState(ContextMemento state) {
232
		if (!PlatformUI.getWorkbench().isClosing()
248
		if (!PlatformUI.getWorkbench().isClosing()
233
				&& ContextUiPlugin.getDefault().getPreferenceStore().getBoolean(
249
				&& ContextUiPlugin.getDefault().getPreferenceStore().getBoolean(
234
						IContextUiPreferenceContstants.AUTO_MANAGE_EDITORS) && !TaskMigrator.isActive()) {
250
						IContextUiPreferenceContstants.AUTO_MANAGE_EDITORS) && !TaskMigrator.isActive()) {
235
			closeAllButActiveTaskEditor(context.getHandleIdentifier());
251
			closeAllButActiveTaskEditor(state.getContextHandle());
236
252
237
			XMLMemento rootMemento = XMLMemento.createWriteRoot(KEY_CONTEXT_EDITORS);
253
//			XMLMemento rootMemento = XMLMemento.createWriteRoot(KEY_CONTEXT_EDITORS);
238
254
239
			IWorkbenchWindow activeWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
255
			IWorkbenchWindow activeWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
240
			IWorkbenchWindow launchingWindow = MonitorUi.getLaunchingWorkbenchWindow();
256
			IWorkbenchWindow launchingWindow = MonitorUi.getLaunchingWorkbenchWindow();
241
			Set<IWorkbenchWindow> monitoredWindows = MonitorUi.getMonitoredWindows();
257
			Set<IWorkbenchWindow> monitoredWindows = MonitorUi.getMonitoredWindows();
242
258
259
			IMemento rootMemento = state.createMemento("editors");
243
			for (IWorkbenchWindow window : monitoredWindows) {
260
			for (IWorkbenchWindow window : monitoredWindows) {
244
				IMemento memento = rootMemento.createChild(KEY_MONITORED_WINDOW_OPEN_EDITORS);
261
				IMemento memento = rootMemento.createChild(KEY_MONITORED_WINDOW_OPEN_EDITORS);
245
262
Lines 254-268 Link Here
254
				memento.putString(ATTRIBUTE_IS_ACTIVE, (window == activeWindow) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
271
				memento.putString(ATTRIBUTE_IS_ACTIVE, (window == activeWindow) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
255
				((WorkbenchPage) window.getActivePage()).getEditorManager().saveState(memento);
272
				((WorkbenchPage) window.getActivePage()).getEditorManager().saveState(memento);
256
			}
273
			}
257
			// TODO: avoid storing with preferences due to bloat?
274
//			// TODO: avoid storing with preferences due to bloat?
258
			StringWriter writer = new StringWriter();
275
//			StringWriter writer = new StringWriter();
259
			try {
276
//			try {
260
				rootMemento.save(writer);
277
//				rootMemento.save(writer);
261
				writeEditorMemento(context.getHandleIdentifier(), writer.getBuffer().toString());
278
//				writeEditorMemento(context, writer.getBuffer().toString());
262
			} catch (IOException e) {
279
//			} catch (IOException e) {
263
				StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, "Could not store editor state", //$NON-NLS-1$
280
//				StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, "Could not store editor state", //$NON-NLS-1$
264
						e));
281
//						e));
265
			}
282
//			}
266
283
267
			Workbench.getInstance().getPreferenceStore().setValue(IPreferenceConstants.REUSE_EDITORS_BOOLEAN,
284
			Workbench.getInstance().getPreferenceStore().setValue(IPreferenceConstants.REUSE_EDITORS_BOOLEAN,
268
					previousCloseEditorsSetting);
285
					previousCloseEditorsSetting);
Lines 270-296 Link Here
270
		}
287
		}
271
	}
288
	}
272
289
273
	public void writeEditorMemento(String contextHandle, String memento) {
290
//	public void writeEditorMemento(IInteractionContext context, String memento) {
274
		preferenceStore.setValue(PREFS_PREFIX + contextHandle, memento);
291
//		preferenceStore.setValue(PREFS_PREFIX + context.getHandleIdentifier(), memento);
275
	}
292
//	}
276
293
277
	public void clearEditorMemento(String contextHandle, boolean closeEditors) {
294
	public void clearState(String contextHandle, boolean closeEditors) {
278
295
279
		if (closeEditors) {
296
		if (closeEditors) {
280
			closeAllButActiveTaskEditor(contextHandle);
297
			closeAllButActiveTaskEditor(contextHandle);
281
		}
298
		}
282
299
283
		XMLMemento memento = XMLMemento.createWriteRoot(KEY_CONTEXT_EDITORS);
284
285
		// TODO: avoid storing with preferences due to bloat?
286
		StringWriter writer = new StringWriter();
287
		try {
288
			memento.save(writer);
289
			writeEditorMemento(contextHandle, writer.getBuffer().toString());
290
		} catch (IOException e) {
291
			StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, "Could not store editor state", e)); //$NON-NLS-1$
292
		}
293
294
		Workbench.getInstance().getPreferenceStore().setValue(IPreferenceConstants.REUSE_EDITORS_BOOLEAN,
300
		Workbench.getInstance().getPreferenceStore().setValue(IPreferenceConstants.REUSE_EDITORS_BOOLEAN,
295
				previousCloseEditorsSetting);
301
				previousCloseEditorsSetting);
296
		if (closeEditors) {
302
		if (closeEditors) {
(-)src/org/eclipse/mylyn/internal/context/ui/ContextMementoManager.java (+281 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2008 Tasktop Technologies and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Tasktop Technologies - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylyn.internal.context.ui;
13
14
import java.io.BufferedReader;
15
import java.io.BufferedWriter;
16
import java.io.File;
17
import java.io.FileInputStream;
18
import java.io.FileOutputStream;
19
import java.io.IOException;
20
import java.io.InputStreamReader;
21
import java.io.OutputStreamWriter;
22
import java.util.HashMap;
23
import java.util.List;
24
import java.util.Map;
25
import java.util.concurrent.CopyOnWriteArrayList;
26
27
import org.eclipse.core.runtime.Assert;
28
import org.eclipse.core.runtime.IProgressMonitor;
29
import org.eclipse.core.runtime.IStatus;
30
import org.eclipse.core.runtime.MultiStatus;
31
import org.eclipse.core.runtime.SafeRunner;
32
import org.eclipse.core.runtime.Status;
33
import org.eclipse.core.runtime.jobs.Job;
34
import org.eclipse.jface.util.SafeRunnable;
35
import org.eclipse.mylyn.commons.core.StatusHandler;
36
import org.eclipse.mylyn.context.core.AbstractContextListener;
37
import org.eclipse.mylyn.context.core.ContextChangeEvent;
38
import org.eclipse.mylyn.context.core.IInteractionContext;
39
import org.eclipse.mylyn.context.core.IInteractionContextManager;
40
import org.eclipse.mylyn.internal.provisional.tasks.core.TasksUtil;
41
import org.eclipse.osgi.util.NLS;
42
import org.eclipse.ui.WorkbenchException;
43
import org.eclipse.ui.XMLMemento;
44
45
/**
46
 * @author Steffen Pingel
47
 */
48
public class ContextMementoManager {
49
50
	private class ContextListener extends AbstractContextListener {
51
52
		@Override
53
		public void contextChanged(ContextChangeEvent event) {
54
55
			switch (event.getEventKind()) {
56
			case ACTIVATED:
57
				restoreState(event.getContext());
58
				break;
59
			case DEACTIVATED:
60
				saveState(event.getContext());
61
				break;
62
			case CLEARED:
63
				// use the handle since the context is null when it is cleared
64
				// bug 255588
65
				clearState(event.getContextHandle(), event.isActiveContext());
66
				break;
67
68
			}
69
		}
70
71
	}
72
73
	private class FlushJob extends Job {
74
75
		public FlushJob() {
76
			super("Flush context mementos"); //$NON-NLS-1$
77
		}
78
79
		@Override
80
		protected IStatus run(IProgressMonitor monitor) {
81
			ContextMementoManager.this.flushPending();
82
			return Status.OK_STATUS;
83
		}
84
85
	}
86
87
	private static final String TAG_CONTEXT_STATE = "ContextState"; //$NON-NLS-1$
88
89
	private static final long FLUSH_DELAY = 500;
90
91
	private static final String CHARSET = "UTF-8"; //$NON-NLS-1$
92
93
	private final Map<String, ContextMemento> pending;
94
95
	private final File location;
96
97
	private FlushJob flushJob;
98
99
	private boolean scheduled;
100
101
	private final IInteractionContextManager contextManager;
102
103
	private final ContextListener contextListener;
104
105
	private final List<ContextMementoListener> listeners;
106
107
	public ContextMementoManager(IInteractionContextManager contextManager, File location) {
108
		Assert.isNotNull(contextManager);
109
		Assert.isNotNull(location);
110
		this.contextManager = contextManager;
111
		this.location = location;
112
		this.contextListener = new ContextListener();
113
		this.pending = new HashMap<String, ContextMemento>();
114
		this.listeners = new CopyOnWriteArrayList<ContextMementoListener>();
115
	}
116
117
	public void addMementoListener(ContextMementoListener listener) {
118
		if (listeners.contains(listener)) {
119
			throw new IllegalStateException("listener already added"); //$NON-NLS-1$
120
		}
121
		listeners.add(listener);
122
	}
123
124
	public void removeMementoListener(ContextMementoListener listener) {
125
		listeners.remove(listener);
126
	}
127
128
	public void clearState(final String contextHandle, final boolean isActiveContext) {
129
		final ContextMemento memento = createMemento(null, contextHandle);
130
		for (final ContextMementoListener listener : listeners) {
131
			SafeRunner.run(new SafeRunnable() {
132
				public void run() throws Exception {
133
					listener.clearState(contextHandle, isActiveContext);
134
				}
135
136
				@Override
137
				public void handleException(Throwable e) {
138
					StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN,
139
							"Unexpected error processing context event", e)); //$NON-NLS-1$
140
					removeMementoListener(listener);
141
				}
142
			});
143
		}
144
		delete(memento);
145
	}
146
147
	public void saveState(IInteractionContext context) {
148
		final ContextMemento memento = createMemento(context, context.getHandleIdentifier());
149
		for (final ContextMementoListener listener : listeners) {
150
			SafeRunner.run(new SafeRunnable() {
151
				public void run() throws Exception {
152
					listener.saveState(memento);
153
				}
154
155
				@Override
156
				public void handleException(Throwable e) {
157
					StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN,
158
							"Unexpected error processing context event", e)); //$NON-NLS-1$
159
					removeMementoListener(listener);
160
				}
161
			});
162
		}
163
		if (memento.isChanged()) {
164
			writeLater(memento);
165
		}
166
	}
167
168
	ContextMemento createMemento(IInteractionContext context, String contextHandle) {
169
		return new ContextMemento(context, contextHandle, XMLMemento.createWriteRoot(TAG_CONTEXT_STATE));
170
	}
171
172
	public void restoreState(IInteractionContext context) {
173
		final ContextMemento memento = read(context);
174
		for (final ContextMementoListener listener : listeners) {
175
			SafeRunner.run(new SafeRunnable() {
176
				public void run() throws Exception {
177
					listener.restoreState(memento);
178
				}
179
180
				@Override
181
				public void handleException(Throwable e) {
182
					StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN,
183
							"Unexpected error processing context event", e)); //$NON-NLS-1$
184
					removeMementoListener(listener);
185
				}
186
			});
187
		}
188
	}
189
190
	public synchronized void start() {
191
		contextManager.addListener(contextListener);
192
	}
193
194
	public synchronized void stop() {
195
		contextManager.removeListener(contextListener);
196
	}
197
198
	public synchronized void flushPending() {
199
		MultiStatus status = new MultiStatus(ContextUiPlugin.ID_PLUGIN, 0,
200
				"Failed to save context workbench state", null); //$NON-NLS-1$
201
		for (ContextMemento memento : pending.values()) {
202
			if (memento.isChanged()) {
203
				IStatus result = write(memento);
204
				status.add(result);
205
			}
206
		}
207
		pending.clear();
208
		if (!status.isOK()) {
209
			StatusHandler.log(status);
210
		}
211
	}
212
213
	private ContextMemento read(IInteractionContext context) {
214
		File file = getFile(context.getHandleIdentifier());
215
		if (file.exists()) {
216
			try {
217
				BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), CHARSET));
218
				XMLMemento memento = XMLMemento.createReadRoot(reader);
219
				return new ContextMemento(context, context.getHandleIdentifier(), memento);
220
			} catch (IOException e) {
221
				StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind(
222
						"Failed to read context memento from \"{0}\"", file.getAbsolutePath()), e)); //$NON-NLS-1$
223
			} catch (WorkbenchException e) {
224
				StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind(
225
						"Failed to read context memento from \"{0}\"", file.getAbsolutePath()), e)); //$NON-NLS-1$
226
			}
227
		}
228
		return createMemento(context, context.getHandleIdentifier());
229
	}
230
231
	IStatus write(ContextMemento memento) {
232
		File file = getFile(memento.getContextHandle());
233
		if (!file.getParentFile().exists()) {
234
			file.getParentFile().mkdirs();
235
		}
236
		try {
237
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), CHARSET));
238
			try {
239
				(memento.getMemento()).save(writer);
240
			} finally {
241
				writer.close();
242
			}
243
		} catch (IOException e) {
244
			return new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind(
245
					"Failed to write context memento to \"{0}\"", file.getAbsolutePath()), e); //$NON-NLS-1$
246
		}
247
		return Status.OK_STATUS;
248
	}
249
250
	private File getFile(String contextHandle) {
251
		return new File(location, TasksUtil.encode(contextHandle));
252
	}
253
254
	public synchronized void delete(ContextMemento memento) {
255
		String contextHandle = memento.getContextHandle();
256
		pending.remove(contextHandle);
257
		File file = getFile(contextHandle);
258
		if (file != null && file.exists()) {
259
			boolean succeeded = file.delete();
260
			if (!succeeded) {
261
				StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, NLS.bind(
262
						"Unable to remove the editor memento \"{0}\"", file.getAbsolutePath()))); //$NON-NLS-1$
263
			}
264
		}
265
	}
266
267
	public synchronized void writeLater(ContextMemento memento) {
268
		pending.put(memento.getContextHandle(), memento);
269
		schedule();
270
	}
271
272
	private synchronized void schedule() {
273
		if (!scheduled) {
274
			if (flushJob == null) {
275
				flushJob = new FlushJob();
276
			}
277
			flushJob.schedule(FLUSH_DELAY);
278
		}
279
	}
280
281
}
(-)src/org/eclipse/mylyn/internal/context/ui/ContextMemento.java (+84 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2008 Tasktop Technologies and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Tasktop Technologies - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylyn.internal.context.ui;
13
14
import org.eclipse.core.runtime.Assert;
15
import org.eclipse.mylyn.context.core.IInteractionContext;
16
import org.eclipse.ui.IMemento;
17
import org.eclipse.ui.XMLMemento;
18
19
/**
20
 * Stores workspace specific settings for a context.
21
 * 
22
 * @author Steffen Pingel
23
 */
24
public class ContextMemento {
25
26
	private boolean changed;
27
28
	private final IInteractionContext context;
29
30
	private final String contextHandle;
31
32
	private final XMLMemento memento;
33
34
	public ContextMemento(IInteractionContext context, String contextHandle, XMLMemento memento) {
35
		Assert.isNotNull(memento);
36
		this.context = context;
37
		this.memento = memento;
38
		this.contextHandle = contextHandle;
39
	}
40
41
	// XXX equals and hashcode should probably use the handle to determine equality
42
	@Override
43
	public boolean equals(Object obj) {
44
		if (!(obj instanceof ContextMemento)) {
45
			return false;
46
		}
47
		return context.equals(((ContextMemento) obj).context);
48
	}
49
50
	@Override
51
	public int hashCode() {
52
		return context.hashCode();
53
	}
54
55
	public String getContextHandle() {
56
		return contextHandle;
57
	}
58
59
	public IInteractionContext getContext() {
60
		return context;
61
	}
62
63
	XMLMemento getMemento() {
64
		return memento;
65
	}
66
67
	public IMemento getMemento(String type) {
68
		return memento.getChild(type);
69
	}
70
71
	public IMemento createMemento(String type) {
72
		changed = true;
73
		return memento.createChild(type);
74
	}
75
76
	public boolean isChanged() {
77
		return changed;
78
	}
79
80
	public void removeMemento(String type) {
81
		memento.createChild(type);
82
	}
83
84
}
(-)src/org/eclipse/mylyn/internal/context/ui/ContextMementoListener.java (+25 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004, 2008 Tasktop Technologies and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Tasktop Technologies - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.mylyn.internal.context.ui;
13
14
/**
15
 * @author Steffen Pingel
16
 */
17
public abstract class ContextMementoListener {
18
19
	public abstract void clearState(String contextHandle, boolean isActiveContext);
20
21
	public abstract void restoreState(ContextMemento memento);
22
23
	public abstract void saveState(ContextMemento memento);
24
25
}

Return to bug 226618