* X11Keyboard.cs: Detect and use the num lock mask.
[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 // $Revision: 1.8 $
27 // $Modtime: $
28 // $Log: Application.cs,v $
29 // Revision 1.8  2004/10/20 03:33:33  pbartok
30 // - Fixed to deal with new Form subclasses for menus
31 //
32 // Revision 1.7  2004/10/18 04:14:14  pbartok
33 // - Added code to simulate modal dialogs on Win32
34 //
35 // Revision 1.6  2004/09/22 20:05:41  pbartok
36 // - Added message loop for modal dialogs
37 //
38 // Revision 1.5  2004/09/21 00:54:15  jackson
39 // New message loop that uses poll so we don't get a busy loop
40 //
41 // Revision 1.4  2004/08/23 22:45:19  pbartok
42 // - Removed debug output
43 // - Simplifications
44 //
45 // Revision 1.3  2004/08/23 22:09:29  pbartok
46 // - Added handling of Idle event
47 // - Added handling of form closing
48 // - Fixed reporting of MessageLoop property
49 // - Removed some unneeded code, should provide a bit of a speedup
50 //
51 // Revision 1.2  2004/08/11 22:16:50  pbartok
52 // - Fixed Signature
53 // - Added .Net 1.1 method
54 //
55 // Revision 1.1  2004/07/09 05:21:25  pbartok
56 // - Initial check-in
57 //
58 //
59
60 // COMPLETE
61
62 using Microsoft.Win32;
63 using System;
64 using System.Drawing;
65 using System.ComponentModel;
66 using System.Collections;
67 using System.Diagnostics;
68 using System.Globalization;
69 using System.IO;
70 using System.Reflection;
71 using System.Runtime.InteropServices;
72 using System.Threading;
73
74 namespace System.Windows.Forms {
75         public sealed class Application {
76                 private static bool                     browser_embedded;
77                 private static bool                     exiting;
78                 private static InputLanguage            input_language;
79                 private static bool                     messageloop_started;
80                 private static string                   safe_caption_format;
81                 private static ArrayList                message_filters;
82                 private static ApplicationContext       app_context;
83                 private static Form                     main_form;
84
85                 private Application () {
86                         input_language  = InputLanguage.CurrentInputLanguage;
87                         message_filters = new ArrayList();
88                         app_context     = null;
89                         browser_embedded= false;
90                         exiting         = false;
91                         messageloop_started = false;
92                         safe_caption_format = "{1} - {0} - {2}";
93                 }
94
95                 #region Private and Internal Methods
96                 internal static void ModalRun(Form form) {
97                         MSG     msg = new MSG();
98                         Queue   toplevels = new Queue();
99                         IEnumerator control = Control.controls.GetEnumerator();
100
101                         if (form == null) {
102                                 return;
103                         }
104
105                         while (control.MoveNext()) {
106                                 if ((((Control)control.Current).parent == null) && (((Control)control.Current).is_visible) && (((Control)control.Current).is_enabled)) {
107                                         if ((control.Current is Form.FormParentWindow)  && (((Form.FormParentWindow)control.Current)!=form.form_parent_window)) {
108                                                 XplatUI.EnableWindow(((Control)control.Current).window.Handle, false);
109                                                 toplevels.Enqueue((Control)control.Current);
110                                         }
111                                 }
112                         }
113
114                         while (!exiting && !form.end_modal && XplatUI.GetMessage(ref msg, IntPtr.Zero, 0, 0)) {
115                                 XplatUI.TranslateMessage(ref msg);
116                                 XplatUI.DispatchMessage(ref msg);
117
118                                 // Handle exit, Form might have received WM_CLOSE and set 'closing' in response
119                                 if (form.closing) {
120                                         form.end_modal = true;
121                                 }
122                         }
123
124                         while (toplevels.Count>0) {
125                                 XplatUI.EnableWindow(((Control)toplevels.Dequeue()).window.Handle, true);
126                         }
127                 }
128                 #endregion      // Private and Internal Methods
129
130                 #region Public Static Properties
131                 public static bool AllowQuit {
132                         get {
133                                 return browser_embedded;
134                         }
135                 }
136
137                 public static string CommonAppDataPath {
138                         get {
139                                 return Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
140                         }
141                 }
142
143                 public static RegistryKey CommonAppDataRegistry {
144                         get {
145                                 RegistryKey     key;
146
147                                 key = Registry.LocalMachine.OpenSubKey("Software\\" + Application.CompanyName + "\\" + Application.ProductName + "\\" + Application.ProductVersion, true);
148
149                                 return key;
150                         }
151                 }
152
153                 public static string CompanyName {
154                         get {
155                                 StackTrace      st;
156
157                                 if (Environment.OSVersion.Platform != (PlatformID)128) {
158                                         RegistryKey     key;
159                                         String          ret;
160
161                                         key=Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion", false);
162                                         ret=(String)key.GetValue("RegisteredOrganization");
163
164                                         return ret;
165                                         
166                                 }
167
168                                 st=new StackTrace();
169                                 return st.GetFrame(st.FrameCount-1).GetMethod().DeclaringType.Namespace;
170                         }
171                 }
172
173                 public static CultureInfo CurrentCulture {
174                         get {
175                                 return Thread.CurrentThread.CurrentUICulture;
176                         }
177
178                         set {
179                                 
180                                 Thread.CurrentThread.CurrentUICulture=value;
181                         }
182                 }
183
184                 public static InputLanguage CurrentInputLanguage {
185                         get {
186                                 return input_language;
187                         }
188
189                         set {
190                                 input_language=value;
191                         }
192                 }
193
194                 public static string ExecutablePath {
195                         get {
196                                 return Assembly.GetEntryAssembly().Location;
197                         }
198                 }
199
200                 public static string LocalUserAppDataPath {
201                         get {
202                                 return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
203                         }
204                 }
205
206                 public static bool MessageLoop {
207                         get {
208                                 return messageloop_started;
209                         }
210                 }
211
212                 public static string ProductName {
213                         get {
214                                 AssemblyProductAttribute[] attrs = (AssemblyProductAttribute[]) Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true);
215                                 
216                                 if ((attrs != null) && attrs.Length>0) {
217                                         return attrs[0].Product;
218                                 }
219
220                                 return Assembly.GetEntryAssembly().GetName().Name;
221                         }
222                 }
223
224                 public static string ProductVersion {
225                         get {
226                                 String version;
227
228                                 version = Assembly.GetEntryAssembly().GetName().Version.ToString();
229
230                                 if (version.StartsWith("0.")) {
231                                         version="1." + version.Substring(2);
232                                 }
233                                 return version;
234                         }
235                 }
236
237                 public static string SafeTopLevelCaptionFormat {
238                         get {
239                                 return safe_caption_format;
240                         }
241
242                         set {
243                                 safe_caption_format=value;
244                         }
245                 }
246
247                 public static string StartupPath {
248                         get {
249                                 return Path.GetDirectoryName(Application.ExecutablePath);
250                         }
251                 }
252
253                 public static string UserAppDataPath {
254                         get {
255                                 return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
256                         }
257                 }
258
259                 public static RegistryKey UserAppDataRegistry {
260                         get {
261                                 RegistryKey     key;
262
263                                 key = Registry.CurrentUser.OpenSubKey("Software\\" + Application.CompanyName + "\\" + Application.ProductName + "\\" + Application.ProductVersion, true);
264
265                                 return key;
266                         }
267                 }
268                 #endregion
269
270                 #region Public Static Methods
271                 public static void AddMessageFilter(IMessageFilter value) {
272                         message_filters.Add(value);
273                 }
274
275                 public static void DoEvents() {
276                         XplatUI.DoEvents();
277                 }
278
279                 public static void EnableVisualStyles() {
280                         XplatUI.EnableThemes();
281                 }
282
283                 public static void Exit() {
284                         XplatUI.Exit();
285                 }
286
287                 public static void ExitThread() {
288                         exiting=true;
289                 }
290
291                 private static void InternalExit(object sender, EventArgs e) {
292                         Application.Exit();
293                 }
294
295                 public static ApartmentState OleRequired() {
296                         //throw new NotImplementedException("OLE Not supported by this System.Windows.Forms implementation");
297                         return ApartmentState.Unknown;
298                 }
299
300                 public static void OnThreadException(Exception t) {
301                         if (Application.ThreadException != null) {
302                                 Application.ThreadException(null, new ThreadExceptionEventArgs(t));
303                                 return;
304                         }
305 #if !later
306                          else {
307                                 XplatUI.HandleException(t);
308                         }
309 #else
310                         // TODO: Missing implementation
311                         //if (SystemInformation.UserInteractive)
312                         {
313                                 Form form = new ThreadExceptionDialog (t);
314                                 form.ShowDialog ();
315                         }
316                         //else
317                                 Console.WriteLine (t.ToString ());
318 #endif
319                 }
320
321                 public static void RemoveMessageFilter(IMessageFilter filter) {
322                         message_filters.Remove(filter);
323                 }
324
325                 public static void Run() {
326                         MSG     msg = new MSG();
327                         Form    form = null;
328
329                         if (app_context != null) {
330                                 form = app_context.MainForm;
331                         }
332
333                         messageloop_started = true;
334
335                         while (!exiting && XplatUI.GetMessage(ref msg, IntPtr.Zero, 0, 0)) {
336                                 XplatUI.TranslateMessage(ref msg);
337                                 XplatUI.DispatchMessage(ref msg);
338
339                                 // Handle exit, Form might have received WM_CLOSE and set 'closing' in response
340                                 if ((form != null) && form.closing) {
341                                         exiting = true;
342                                 }
343                         }
344
345                         messageloop_started = false;
346
347                         if (ApplicationExit != null) {
348                                 ApplicationExit(null, EventArgs.Empty);
349                         }
350                 }
351
352                 public static void Run(Form mainForm) {
353                         mainForm.CreateControl();
354                         Run(new ApplicationContext(mainForm));
355                 }
356
357                 public static void Run(ApplicationContext context) {
358                         app_context=context;
359                         if (app_context.MainForm!=null) {
360                                 app_context.MainForm.Show();
361                                 app_context.ThreadExit += new EventHandler(InternalExit);
362                         }
363                         Run();
364                 }
365                 #endregion      // Public Static Methods
366
367                 #region Events
368                 public static event EventHandler        ApplicationExit;
369
370                 public static event EventHandler        Idle {
371                         add {
372                                 XplatUI.Idle += value;
373                         }
374                         remove {
375                                 XplatUI.Idle -= value;
376                         }
377                 }
378
379                 public static event EventHandler        ThreadExit;
380                 public static event ThreadExceptionEventHandler ThreadException;
381                 #endregion      // Events
382         }
383 }