1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.ComponentModel;
6
using System.Diagnostics;
8
using System.Windows.Forms;
9
using ICSharpCode.Core;
10
using ICSharpCode.Core.WinForms;
12
namespace ICSharpCode.SharpDevelop.Gui
14
public static class WorkbenchSingleton
16
const string uiIconStyle = "IconMenuItem.IconMenuStyle";
17
const string uiLanguageProperty = "CoreProperties.UILanguage";
18
const string workbenchMemento = "WorkbenchMemento";
19
const string activeContentState = "Workbench.ActiveContent";
21
static IWorkbench workbench;
24
/// Gets the main form. Returns null in unit-testing mode.
26
public static IWin32Window MainWin32Window {
28
if (workbench != null) {
29
return workbench.MainWin32Window;
36
/// Gets the main window. Returns null in unit-testing mode.
38
public static Window MainWindow {
40
if (workbench != null) {
41
return workbench.MainWindow;
48
/// Gets the workbench. Returns null in unit-testing mode.
50
public static IWorkbench Workbench {
56
public static IStatusBarService StatusBar {
58
return workbench != null ? workbench.StatusBar : null;
62
public static void InitializeWorkbench(IWorkbench workbench, IWorkbenchLayout layout)
64
WorkbenchSingleton.workbench = workbench;
66
LanguageService.ValidateLanguage();
68
DisplayBindingService.InitializeService();
69
LayoutConfiguration.LoadLayoutConfiguration();
70
FileService.InitializeService();
71
DomHostCallback.Register(); // must be called after StatusBarService.Initialize()
72
ParserService.InitializeParserService();
73
TaskService.Initialize();
74
Bookmarks.BookmarkManager.Initialize();
75
Project.CustomToolsService.Initialize();
76
Project.BuildModifiedProjectsOnlyService.Initialize();
78
var messageService = Core.Services.ServiceManager.Instance.MessageService as IDialogMessageService;
79
if (messageService != null) {
80
messageService.DialogOwner = workbench.MainWin32Window;
81
Debug.Assert(messageService.DialogOwner != null);
82
messageService.DialogSynchronizeInvoke = workbench.SynchronizingObject;
85
workbench.Initialize();
86
workbench.SetMemento(PropertyService.Get(workbenchMemento, new Properties()));
87
workbench.WorkbenchLayout = layout;
89
ApplicationStateInfoService.RegisterStateGetter(activeContentState, delegate { return WorkbenchSingleton.Workbench.ActiveContent; });
93
// initialize workbench-dependent services:
94
Project.ProjectService.InitializeService();
95
NavigationService.InitializeService();
97
workbench.ActiveContentChanged += delegate {
98
Debug.WriteLine("ActiveContentChanged to " + workbench.ActiveContent);
99
LoggingService.Debug("ActiveContentChanged to " + workbench.ActiveContent);
101
workbench.ActiveViewContentChanged += delegate {
102
Debug.WriteLine("ActiveViewContentChanged to " + workbench.ActiveViewContent);
103
LoggingService.Debug("ActiveViewContentChanged to " + workbench.ActiveViewContent);
105
workbench.ActiveWorkbenchWindowChanged += delegate {
106
Debug.WriteLine("ActiveWorkbenchWindowChanged to " + workbench.ActiveWorkbenchWindow);
107
LoggingService.Debug("ActiveWorkbenchWindowChanged to " + workbench.ActiveWorkbenchWindow);
112
/// Runs workbench cleanup.
113
/// Is called by ICSharpCode.SharpDevelop.Sda and should not be called manually!
115
public static void OnWorkbenchUnloaded()
117
if (!Project.ProjectService.IsClosingCanceled()) {
118
Project.ProjectService.CloseSolution();
119
NavigationService.Unload();
121
ApplicationStateInfoService.UnregisterStateGetter(activeContentState);
123
WorkbenchUnloaded(null, EventArgs.Empty);
125
FileService.Unload();
129
#region Safe Thread Caller
130
public static bool InvokeRequired {
132
if (workbench == null)
133
return false; // unit test mode, don't crash
135
return workbench.SynchronizingObject.InvokeRequired;
140
/// Throws an exception if the current thread is not the main thread.
141
/// For performance reasons, the thread check is only done in debug builds.
143
[Conditional("DEBUG")]
144
internal static void DebugAssertMainThread()
150
/// Throws an exception if the current thread is not the main thread.
152
public static void AssertMainThread()
154
if (InvokeRequired) {
155
throw new InvalidOperationException("This operation can be called on the main thread only.");
159
readonly static object[] emptyObjectArray = new object[0];
162
/// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
163
/// operation, which can result in a dead-lock when the main thread waits for a lock
164
/// held by this thread!
166
public static R SafeThreadFunction<R>(Func<R> method)
168
// InvokeRequired test is necessary so that we don't run other actions in the message queue
169
// when we're already running on the main thread (unexpected reentrancy)
170
ISynchronizeInvoke si = workbench.SynchronizingObject;
171
if (si.InvokeRequired)
172
return (R)workbench.SynchronizingObject.Invoke(method, emptyObjectArray);
178
/// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
179
/// operation, which can result in a dead-lock when the main thread waits for a lock
180
/// held by this thread!
182
public static R SafeThreadFunction<A, R>(Func<A, R> method, A arg1)
184
ISynchronizeInvoke si = workbench.SynchronizingObject;
185
if (si.InvokeRequired)
186
return (R)si.Invoke(method, new object[] { arg1 });
192
/// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
193
/// operation, which can result in a dead-lock when the main thread waits for a lock
194
/// held by this thread!
196
public static void SafeThreadCall(Action method)
198
ISynchronizeInvoke si = workbench.SynchronizingObject;
199
if (si.InvokeRequired)
200
si.Invoke(method, emptyObjectArray);
206
/// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
207
/// operation, which can result in a dead-lock when the main thread waits for a lock
208
/// held by this thread!
210
public static void SafeThreadCall<A>(Action<A> method, A arg1)
212
ISynchronizeInvoke si = workbench.SynchronizingObject;
213
if (si.InvokeRequired)
214
si.Invoke(method, new object[] { arg1 });
220
/// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
221
/// operation, which can result in a dead-lock when the main thread waits for a lock
222
/// held by this thread!
224
public static void SafeThreadCall<A, B>(Action<A, B> method, A arg1, B arg2)
226
ISynchronizeInvoke si = workbench.SynchronizingObject;
227
if (si.InvokeRequired)
228
si.Invoke(method, new object[] { arg1, arg2 });
234
/// Makes a call GUI threadsafe. WARNING: This method waits for the result of the
235
/// operation, which can result in a dead-lock when the main thread waits for a lock
236
/// held by this thread!
238
public static void SafeThreadCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3)
240
ISynchronizeInvoke si = workbench.SynchronizingObject;
241
if (si.InvokeRequired)
242
si.Invoke(method, new object[] { arg1, arg2, arg3 });
244
method(arg1, arg2, arg3);
248
/// Makes a call GUI threadsafe without waiting for the returned value.
250
public static void SafeThreadAsyncCall(Action method)
252
workbench.SynchronizingObject.BeginInvoke(method, emptyObjectArray);
256
/// Makes a call GUI threadsafe without waiting for the returned value.
258
public static void SafeThreadAsyncCall<A>(Action<A> method, A arg1)
260
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1 });
264
/// Makes a call GUI threadsafe without waiting for the returned value.
266
public static void SafeThreadAsyncCall<A, B>(Action<A, B> method, A arg1, B arg2)
268
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1, arg2 });
272
/// Makes a call GUI threadsafe without waiting for the returned value.
274
public static void SafeThreadAsyncCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3)
276
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1, arg2, arg3 });
280
/// Calls a method on the GUI thread, but delays the call a bit.
282
public static void CallLater(TimeSpan delay, Action method)
284
int delayMilliseconds = (int)delay.TotalMilliseconds;
285
if (delayMilliseconds < 0)
286
throw new ArgumentOutOfRangeException("delay", delay, "Value must be positive");
288
throw new ArgumentNullException("method");
291
Timer t = new Timer();
292
t.Interval = Math.Max(1, delayMilliseconds);
303
static void OnWorkbenchCreated()
305
WorkbenchCreated(null, EventArgs.Empty);
309
/// Is called, when the workbench is created
311
public static event EventHandler WorkbenchCreated = delegate {};
314
/// Is called, when the workbench is unloaded
316
public static event EventHandler WorkbenchUnloaded = delegate {};