* TreeView.cs: Don't draw the selected node when we lose
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Application.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25
26
27 // COMPLETE
28
29 using Microsoft.Win32;
30 using System;
31 using System.Drawing;
32 using System.ComponentModel;
33 using System.Collections;
34 using System.Diagnostics;
35 using System.Globalization;
36 using System.IO;
37 using System.Reflection;
38 using System.Runtime.InteropServices;
39 using System.Threading;
40
41 namespace System.Windows.Forms {
42         public sealed class Application {
43                 private static bool                     browser_embedded        = false;
44                 private static bool                     exiting                 = false;
45                 private static InputLanguage            input_language          = InputLanguage.CurrentInputLanguage;
46                 private static bool                     messageloop_started     = false;
47                 private static string                   safe_caption_format     = "{1} - {0} - {2}";
48                 private static ArrayList                message_filters         = new ArrayList();
49                 private static ApplicationContext       app_context             = null;
50
51                 private Application () {
52                 }
53
54                 #region Private and Internal Methods
55                 internal static void ModalRun(Form form) {
56                         MSG     msg = new MSG();
57                         Queue   toplevels = new Queue();
58                         IEnumerator control = Control.controls.GetEnumerator();
59
60                         if (form == null) {
61                                 return;
62                         }
63
64                         // Both calls are needed, one is for the WM, the other for our focus logic
65                         XplatUI.Activate(form.window.Handle);
66                         form.Activate();
67
68                         while (control.MoveNext()) {
69                                 if ((((Control)control.Current).parent == null) && (((Control)control.Current).is_visible) && (((Control)control.Current).is_enabled)) {
70                                         if ((control.Current is Form)  && (((Form)control.Current)!=form)) {
71                                                 XplatUI.EnableWindow(((Control)control.Current).window.Handle, false);
72                                                 toplevels.Enqueue((Control)control.Current);
73                                         }
74                                 }
75                         }
76
77                         form.CreateControl();
78
79                         while (!exiting && !form.end_modal && XplatUI.GetMessage(ref msg, IntPtr.Zero, 0, 0)) {
80                                 if ((message_filters != null) && (message_filters.Count > 0)) {
81                                         Message m;
82                                         bool    drop;
83
84                                         drop = false;
85                                         m = new Message();
86                                         m.Msg = (int)msg.message;
87                                         m.HWnd = msg.hwnd;
88                                         m.LParam = msg.lParam;
89                                         m.WParam = msg.wParam;
90                                         for (int i = 0; i < message_filters.Count; i++) {
91                                                 if (((IMessageFilter)message_filters[i]).PreFilterMessage(ref m)) {
92                                                         // we're dropping the message
93                                                         drop = true;
94                                                         break;
95                                                 }
96                                         }
97                                         if (drop) {
98                                                 continue;
99                                         }
100                                 }
101
102                                 XplatUI.TranslateMessage(ref msg);
103                                 XplatUI.DispatchMessage(ref msg);
104
105                                 // Handle exit, Form might have received WM_CLOSE and set 'closing' in response
106                                 if (form.closing) {
107                                         form.end_modal = true;
108                                 }
109                         }
110
111                         while (toplevels.Count>0) {
112                                 XplatUI.EnableWindow(((Control)toplevels.Dequeue()).window.Handle, true);
113                         }
114                 }
115                 #endregion      // Private and Internal Methods
116
117                 #region Public Static Properties
118                 public static bool AllowQuit {
119                         get {
120                                 return browser_embedded;
121                         }
122                 }
123
124                 public static string CommonAppDataPath {
125                         get {
126                                 return Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
127                         }
128                 }
129
130                 public static RegistryKey CommonAppDataRegistry {
131                         get {
132                                 RegistryKey     key;
133
134                                 key = Registry.LocalMachine.OpenSubKey("Software\\" + Application.CompanyName + "\\" + Application.ProductName + "\\" + Application.ProductVersion, true);
135
136                                 return key;
137                         }
138                 }
139
140                 public static string CompanyName {
141                         get {
142                                 AssemblyCompanyAttribute[] attrs = (AssemblyCompanyAttribute[]) Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), true);
143                                 
144                                 if ((attrs != null) && attrs.Length>0) {
145                                         return attrs[0].Company;
146                                 }
147
148                                 return Assembly.GetEntryAssembly().GetName().Name;
149                         }
150                 }
151
152                 public static CultureInfo CurrentCulture {
153                         get {
154                                 return Thread.CurrentThread.CurrentUICulture;
155                         }
156
157                         set {
158                                 
159                                 Thread.CurrentThread.CurrentUICulture=value;
160                         }
161                 }
162
163                 public static InputLanguage CurrentInputLanguage {
164                         get {
165                                 return input_language;
166                         }
167
168                         set {
169                                 input_language=value;
170                         }
171                 }
172
173                 public static string ExecutablePath {
174                         get {
175                                 return Assembly.GetEntryAssembly().Location;
176                         }
177                 }
178
179                 public static string LocalUserAppDataPath {
180                         get {
181                                 return Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), CompanyName), ProductName), ProductVersion);
182                         }
183                 }
184
185                 public static bool MessageLoop {
186                         get {
187                                 return messageloop_started;
188                         }
189                 }
190
191                 public static string ProductName {
192                         get {
193                                 AssemblyProductAttribute[] attrs = (AssemblyProductAttribute[]) Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true);
194                                 
195                                 if ((attrs != null) && attrs.Length>0) {
196                                         return attrs[0].Product;
197                                 }
198
199                                 return Assembly.GetEntryAssembly().GetName().Name;
200                         }
201                 }
202
203                 public static string ProductVersion {
204                         get {
205                                 String version;
206
207                                 version = Assembly.GetEntryAssembly().GetName().Version.ToString();
208
209                                 if (version.StartsWith("0.")) {
210                                         version="1." + version.Substring(2);
211                                 }
212                                 return version;
213                         }
214                 }
215
216                 public static string SafeTopLevelCaptionFormat {
217                         get {
218                                 return safe_caption_format;
219                         }
220
221                         set {
222                                 safe_caption_format=value;
223                         }
224                 }
225
226                 public static string StartupPath {
227                         get {
228                                 return Path.GetDirectoryName(Application.ExecutablePath);
229                         }
230                 }
231
232                 public static string UserAppDataPath {
233                         get {
234                                 return Path.Combine(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), CompanyName), ProductName), ProductVersion);
235                         }
236                 }
237
238                 public static RegistryKey UserAppDataRegistry {
239                         get {
240                                 RegistryKey     key;
241
242                                 key = Registry.CurrentUser.OpenSubKey("Software\\" + Application.CompanyName + "\\" + Application.ProductName + "\\" + Application.ProductVersion, true);
243
244                                 return key;
245                         }
246                 }
247                 #endregion
248
249                 #region Public Static Methods
250                 public static void AddMessageFilter(IMessageFilter value) {
251                         message_filters.Add(value);
252                 }
253
254                 public static void DoEvents() {
255                         XplatUI.DoEvents();
256                 }
257
258                 public static void EnableVisualStyles() {
259                         XplatUI.EnableThemes();
260                 }
261
262 #if NET_2_0
263                 public static void EnableRTLMirroring () 
264                 {
265                 }
266 #endif
267
268                 public static void Exit() {
269                         XplatUI.Exit();
270                 }
271
272                 public static void ExitThread() {
273                         exiting=true;
274                 }
275
276                 private static void InternalExit(object sender, EventArgs e) {
277                         Application.Exit();
278                 }
279
280                 public static ApartmentState OleRequired() {
281                         //throw new NotImplementedException("OLE Not supported by this System.Windows.Forms implementation");
282                         return ApartmentState.Unknown;
283                 }
284
285                 public static void OnThreadException(Exception t) {
286                         if (Application.ThreadException != null) {
287                                 Application.ThreadException(null, new ThreadExceptionEventArgs(t));
288                                 return;
289                         }
290 #if !later
291                          else {
292                                 XplatUI.HandleException(t);
293                         }
294 #else
295                         // TODO: Missing implementation
296                         //if (SystemInformation.UserInteractive)
297                         {
298                                 Form form = new ThreadExceptionDialog (t);
299                                 form.ShowDialog ();
300                         }
301                         //else
302                                 Console.WriteLine (t.ToString ());
303 #endif
304                 }
305
306                 public static void RemoveMessageFilter(IMessageFilter filter) {
307                         message_filters.Remove(filter);
308                 }
309
310                 public static void Run() {
311                         MSG     msg = new MSG();
312                         Form    form = null;
313
314                         if (app_context != null) {
315                                 form = app_context.MainForm;
316                         }
317
318                         if (form != null) {
319                                 // Both calls are needed, one is for the WM, the other for our focus logic
320                                 XplatUI.Activate(form.window.Handle);
321                                 form.Activate();
322                         }
323
324                         messageloop_started = true;
325
326                         while (!exiting && XplatUI.GetMessage(ref msg, IntPtr.Zero, 0, 0)) {
327                                 if ((message_filters != null) && (message_filters.Count > 0)) {
328                                         Message m;
329                                         bool    drop;
330
331                                         drop = false;
332                                         m = new Message();
333                                         m.Msg = (int)msg.message;
334                                         m.HWnd = msg.hwnd;
335                                         m.LParam = msg.lParam;
336                                         m.WParam = msg.wParam;
337                                         for (int i = 0; i < message_filters.Count; i++) {
338                                                 if (((IMessageFilter)message_filters[i]).PreFilterMessage(ref m)) {
339                                                         // we're dropping the message
340                                                         drop = true;
341                                                         break;
342                                                 }
343                                         }
344                                         if (drop) {
345                                                 continue;
346                                         }
347                                 }
348
349                                 XplatUI.TranslateMessage(ref msg);
350                                 XplatUI.DispatchMessage(ref msg);
351
352                                 // Handle exit, Form might have received WM_CLOSE and set 'closing' in response
353                                 if ((form != null) && form.closing) {
354                                         exiting = true;
355                                 }
356                         }
357
358                         messageloop_started = false;
359
360                         if (ThreadExit != null) {
361                                 ThreadExit(null, EventArgs.Empty);
362                         }
363
364                         if (ApplicationExit != null) {
365                                 ApplicationExit(null, EventArgs.Empty);
366                         }
367                 }
368
369                 public static void Run(Form mainForm) {
370                         mainForm.CreateControl();
371                         Run(new ApplicationContext(mainForm));
372                 }
373
374                 public static void Run(ApplicationContext context) {
375                         app_context=context;
376                         if (app_context.MainForm!=null) {
377                                 app_context.MainForm.Show();
378                                 app_context.MainForm.PerformLayout();
379                                 app_context.ThreadExit += new EventHandler(InternalExit);
380                         }
381                         Run();
382                 }
383                 #endregion      // Public Static Methods
384
385                 #region Events
386                 public static event EventHandler        ApplicationExit;
387
388                 public static event EventHandler        Idle {
389                         add {
390                                 XplatUI.Idle += value;
391                         }
392                         remove {
393                                 XplatUI.Idle -= value;
394                         }
395                 }
396
397                 public static event EventHandler        ThreadExit;
398                 public static event ThreadExceptionEventHandler ThreadException;
399                 #endregion      // Events
400         }
401 }