Fix bug #395
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStripManager.cs
1 //
2 // ToolStripManager.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 //
25 // Authors:
26 //      Jonathan Pobst (monkey@jpobst.com)
27 //
28
29 using System.Drawing;
30 using System.Runtime.InteropServices;
31 using System.ComponentModel;
32 using System.Collections.Generic;
33
34 namespace System.Windows.Forms
35 {
36         public sealed class ToolStripManager
37         {
38                 private static ToolStripRenderer renderer = new ToolStripProfessionalRenderer ();
39                 private static ToolStripManagerRenderMode render_mode = ToolStripManagerRenderMode.Professional;
40                 private static bool visual_styles_enabled = Application.RenderWithVisualStyles;
41                 private static List<WeakReference> toolstrips = new List<WeakReference> ();
42                 private static List<ToolStripMenuItem> menu_items = new List<ToolStripMenuItem> ();
43                 private static bool activated_by_keyboard;
44                 
45                 #region Private Constructor
46                 private ToolStripManager ()
47                 {
48                 }
49                 #endregion
50
51                 #region Public Properties
52                 public static ToolStripRenderer Renderer {
53                         get { return ToolStripManager.renderer; }
54                         set {
55                                 if (ToolStripManager.Renderer != value) {
56                                         ToolStripManager.renderer = value;
57                                         ToolStripManager.OnRendererChanged (EventArgs.Empty);
58                                 }
59                         }
60                 }
61
62                 public static ToolStripManagerRenderMode RenderMode {
63                         get { return ToolStripManager.render_mode; }
64                         set {
65                                 if (!Enum.IsDefined (typeof (ToolStripManagerRenderMode), value))
66                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripManagerRenderMode", value));
67
68                                 if (ToolStripManager.render_mode != value) {
69                                         ToolStripManager.render_mode = value;
70
71                                         switch (value) {
72                                                 case ToolStripManagerRenderMode.Custom:
73                                                         throw new NotSupportedException ();
74                                                 case ToolStripManagerRenderMode.System:
75                                                         ToolStripManager.Renderer = new ToolStripSystemRenderer ();
76                                                         break;
77                                                 case ToolStripManagerRenderMode.Professional:
78                                                         ToolStripManager.Renderer = new ToolStripProfessionalRenderer ();
79                                                         break;
80                                         }
81                                 }
82                         }
83                 }
84
85                 public static bool VisualStylesEnabled {
86                         get { return ToolStripManager.visual_styles_enabled; }
87                         set {
88                                 if (ToolStripManager.visual_styles_enabled != value) {
89                                         ToolStripManager.visual_styles_enabled = value;
90
91                                         if (ToolStripManager.render_mode == ToolStripManagerRenderMode.Professional) {
92                                                 (ToolStripManager.renderer as ToolStripProfessionalRenderer).ColorTable.UseSystemColors = !value;
93                                                 ToolStripManager.OnRendererChanged (EventArgs.Empty);
94                                         }
95                                 }
96                         }
97                 }
98                 #endregion
99
100                 #region Public Methods
101                 public static ToolStrip FindToolStrip (string toolStripName)
102                 {
103                         lock (toolstrips)
104                                 foreach (WeakReference wr in toolstrips) {
105                                         ToolStrip ts = (ToolStrip)wr.Target;
106                                         
107                                         if (ts == null)
108                                                 continue;
109                                 
110                                         if (ts.Name == toolStripName)
111                                                 return ts;
112                                 }
113                                                 
114                         return null;
115                 }
116                 
117                 public static bool IsShortcutDefined (Keys shortcut)
118                 {
119                         lock (menu_items)
120                                 foreach (ToolStripMenuItem tsmi in menu_items)
121                                         if (tsmi.ShortcutKeys == shortcut)
122                                                 return true;
123
124                         return false;
125                 }
126                 
127                 public static bool IsValidShortcut (Keys shortcut)
128                 {
129                         // Anything with an F1 - F12 is a shortcut
130                         if ((shortcut & Keys.F1) == Keys.F1)
131                                 return true;
132                         else if ((shortcut & Keys.F2) == Keys.F2)
133                                 return true;
134                         else if ((shortcut & Keys.F3) == Keys.F3)
135                                 return true;
136                         else if ((shortcut & Keys.F4) == Keys.F4)
137                                 return true;
138                         else if ((shortcut & Keys.F5) == Keys.F5)
139                                 return true;
140                         else if ((shortcut & Keys.F6) == Keys.F6)
141                                 return true;
142                         else if ((shortcut & Keys.F7) == Keys.F7)
143                                 return true;
144                         else if ((shortcut & Keys.F8) == Keys.F8)
145                                 return true;
146                         else if ((shortcut & Keys.F9) == Keys.F9)
147                                 return true;
148                         else if ((shortcut & Keys.F10) == Keys.F10)
149                                 return true;
150                         else if ((shortcut & Keys.F11) == Keys.F11)
151                                 return true;
152                         else if ((shortcut & Keys.F12) == Keys.F12)
153                                 return true;
154                                 
155                         // Modifier keys alone are not shortcuts
156                         switch (shortcut) {
157                                 case Keys.Alt:
158                                 case Keys.Control:
159                                 case Keys.Shift:
160                                 case Keys.Alt | Keys.Control:
161                                 case Keys.Alt | Keys.Shift:
162                                 case Keys.Control | Keys.Shift:
163                                 case Keys.Alt | Keys.Control | Keys.Shift:
164                                         return false;
165                         }
166         
167                         // Anything else with a modifier key is a shortcut
168                         if ((shortcut & Keys.Alt) == Keys.Alt)
169                                 return true;
170                         else if ((shortcut & Keys.Control) == Keys.Control)
171                                 return true;
172                         else if ((shortcut & Keys.Shift) == Keys.Shift)
173                                 return true;
174
175                         // Anything else is not a shortcut
176                         return false;
177                 }
178
179                 [MonoTODO ("Stub, does nothing")]
180                 public static void LoadSettings (Form targetForm)
181                 {
182                         if (targetForm == null)
183                                 throw new ArgumentNullException ("targetForm");
184                 }
185
186                 [MonoTODO ("Stub, does nothing")]
187                 public static void LoadSettings (Form targetForm, string key)
188                 {
189                         if (targetForm == null)
190                                 throw new ArgumentNullException ("targetForm");
191                         if (string.IsNullOrEmpty (key))
192                                 throw new ArgumentNullException ("key");
193                 }
194                 
195                 [MonoLimitation ("Only supports one level of merging, cannot merge the same ToolStrip multiple times")]
196                 public static bool Merge (ToolStrip sourceToolStrip, string targetName)
197                 {
198                         if (string.IsNullOrEmpty (targetName))
199                                 throw new ArgumentNullException ("targetName");
200                                 
201                         return Merge (sourceToolStrip, FindToolStrip (targetName));
202                 }
203                 
204                 [MonoLimitation ("Only supports one level of merging, cannot merge the same ToolStrip multiple times")]
205                 public static bool Merge (ToolStrip sourceToolStrip, ToolStrip targetToolStrip)
206                 {
207                         // Check for exceptions
208                         if (sourceToolStrip == null)
209                                 throw new ArgumentNullException ("sourceToolStrip");
210                                 
211                         if (targetToolStrip == null)
212                                 throw new ArgumentNullException ("targetName");
213                                 
214                         if (targetToolStrip == sourceToolStrip)
215                                 throw new ArgumentException ("Source and target ToolStrip must be different.");
216                         
217                         // If the toolstrips don't allow merging, don't merge them
218                         if (!sourceToolStrip.AllowMerge || !targetToolStrip.AllowMerge)
219                                 return false;
220                         
221                         // We currently can't support merging multiple times
222                         if (sourceToolStrip.IsCurrentlyMerged || targetToolStrip.IsCurrentlyMerged)
223                                 return false;
224                                 
225                         // What I wouldn't give to be able to modify a collection
226                         // while enumerating through it...
227
228                         List<ToolStripItem> items_to_move = new List<ToolStripItem> ();
229                         
230                         // Create a list of every ToolStripItem we plan on moving
231                         foreach (ToolStripItem tsi in sourceToolStrip.Items) {
232                                 switch (tsi.MergeAction) {
233                                         case MergeAction.Append:
234                                         default:
235                                                 items_to_move.Add (tsi);
236                                                 break;
237                                         case MergeAction.Insert:
238                                                 if (tsi.MergeIndex >= 0)
239                                                         items_to_move.Add (tsi);
240                                                 break;
241                                         case MergeAction.Replace:
242                                         case MergeAction.Remove:
243                                         case MergeAction.MatchOnly:
244                                                 foreach (ToolStripItem target_tsi in targetToolStrip.Items)
245                                                         if (tsi.Text == target_tsi.Text) {
246                                                                 items_to_move.Add (tsi);
247                                                                 break;
248                                                         }
249                                                 break;
250                                 }
251                         }
252
253                         // If there was nothing valid to merge, return false
254                         if (items_to_move.Count == 0)
255                                 return false;
256                                 
257                         // Set some state so we can unmerge later
258                         sourceToolStrip.BeginMerge ();
259                         targetToolStrip.BeginMerge ();                  
260
261                         sourceToolStrip.SuspendLayout ();
262                         targetToolStrip.SuspendLayout ();
263         
264                         while (items_to_move.Count > 0) {
265                                 ToolStripItem tsi = items_to_move[0];
266                                 items_to_move.Remove (tsi);
267                                 
268                                 switch (tsi.MergeAction) {
269                                         case MergeAction.Append:
270                                         default:
271                                                 // Just changing the parent will append it to the target
272                                                 // and remove it from the source
273                                                 ToolStrip.SetItemParent (tsi, targetToolStrip);
274                                                 
275                                                 break;
276                                         case MergeAction.Insert:
277                                                 // Do the same work as Append, except Insert it into the
278                                                 // location specified by the MergeIndex
279                                                 RemoveItemFromParentToolStrip (tsi);
280
281                                                 if (tsi.MergeIndex == -1)
282                                                         continue;
283                                                 else if (tsi.MergeIndex >= CountRealToolStripItems (targetToolStrip))
284                                                         targetToolStrip.Items.AddNoOwnerOrLayout (tsi);                                         
285                                                 else
286                                                         targetToolStrip.Items.InsertNoOwnerOrLayout (AdjustItemMergeIndex (targetToolStrip, tsi), tsi);
287
288                                                 tsi.Parent = targetToolStrip;
289                                                 
290                                                 break;
291                                         case MergeAction.Replace:
292                                                 // Find a target ToolStripItem with the same Text, remove it
293                                                 // and replace it with the source one
294                                                 foreach (ToolStripItem target_tsi in targetToolStrip.Items)
295                                                         if (tsi.Text == target_tsi.Text) {
296                                                                 RemoveItemFromParentToolStrip (tsi);
297
298                                                                 // Insert where the old one is, then remove the old one
299                                                                 targetToolStrip.Items.InsertNoOwnerOrLayout (targetToolStrip.Items.IndexOf (target_tsi), tsi);
300                                                                 targetToolStrip.Items.RemoveNoOwnerOrLayout (target_tsi);
301
302                                                                 // Store the replaced one so we can get it back in unmerge
303                                                                 targetToolStrip.HiddenMergedItems.Add (target_tsi);
304                                                                 break;
305                                                         }
306
307                                                 break;
308                                         case MergeAction.Remove:
309                                                 // Find a target ToolStripItem with the same Text, and remove
310                                                 // it from the target, nothing else
311                                                 foreach (ToolStripItem target_tsi in targetToolStrip.Items)
312                                                         if (tsi.Text == target_tsi.Text) {
313                                                                 targetToolStrip.Items.RemoveNoOwnerOrLayout (target_tsi);
314                                                                 
315                                                                 // Store the removed one so we can get it back in unmerge
316                                                                 targetToolStrip.HiddenMergedItems.Add (target_tsi);
317                                                                 break;
318                                                         }
319
320                                                 break;
321                                         case MergeAction.MatchOnly:
322                                                 // Ugh, find the target ToolStripItem with the same Text, and take
323                                                 // all the subitems from the source one, and append it to the target one
324                                                 foreach (ToolStripItem target_tsi in targetToolStrip.Items)
325                                                         if (tsi.Text == target_tsi.Text) {
326                                                                 if (target_tsi is ToolStripMenuItem && tsi is ToolStripMenuItem) {
327                                                                         ToolStripMenuItem source = (ToolStripMenuItem)tsi;
328                                                                         ToolStripMenuItem target = (ToolStripMenuItem)target_tsi;
329                                                                         
330                                                                         ToolStripManager.Merge (source.DropDown, target.DropDown);
331                                                                 }
332                                                                 
333                                                                 break;
334                                                         }
335                                                 
336                                                 break;
337                                 }
338                         }
339                         
340                         sourceToolStrip.ResumeLayout ();
341                         targetToolStrip.ResumeLayout ();
342                         
343                         // Store who we merged with, so we can unmerge when only given the target toolstrip
344                         sourceToolStrip.CurrentlyMergedWith = targetToolStrip;
345                         targetToolStrip.CurrentlyMergedWith = sourceToolStrip;
346                         
347                         return true;
348                 }
349
350                 public static bool RevertMerge (string targetName)
351                 {
352                         return RevertMerge (FindToolStrip (targetName));
353                 }
354                 
355                 public static bool RevertMerge (ToolStrip targetToolStrip)
356                 {
357                         return RevertMerge (targetToolStrip, targetToolStrip.CurrentlyMergedWith);                      
358                 }
359                 
360                 public static bool RevertMerge (ToolStrip targetToolStrip, ToolStrip sourceToolStrip)
361                 {
362                         if (sourceToolStrip == null)
363                                 throw new ArgumentNullException ("sourceToolStrip");
364                                 
365                         List<ToolStripItem> items_to_move = new List<ToolStripItem> ();
366                         
367                         // Find every ToolStripItem who's Owner is the source toolstrip
368                         // - If it's a TSMI, see if any of the subitems need to be moved back
369                         foreach (ToolStripItem tsi in targetToolStrip.Items) {
370                                 if (tsi.Owner == sourceToolStrip)
371                                         items_to_move.Add (tsi);
372                                 else if (tsi is ToolStripMenuItem)
373                                         foreach (ToolStripItem menuitem in (tsi as ToolStripMenuItem).DropDownItems)
374                                                 foreach (ToolStripMenuItem tsmi in sourceToolStrip.Items)
375                                                         if (menuitem.Owner == tsmi.DropDown)
376                                                                 items_to_move.Add (menuitem);   
377                         }
378
379                         // If we didn't find anything, return false
380                         if (items_to_move.Count == 0 && targetToolStrip.HiddenMergedItems.Count == 0)
381                                 return false;
382
383                         // Put back all the target's items removed in the merge
384                         while (targetToolStrip.HiddenMergedItems.Count > 0) {
385                                 targetToolStrip.RevertMergeItem (targetToolStrip.HiddenMergedItems[0]);
386                                 targetToolStrip.HiddenMergedItems.RemoveAt (0);
387                         }
388                                 
389                         sourceToolStrip.SuspendLayout ();
390                         targetToolStrip.SuspendLayout ();
391                         
392                         // Revert everything
393                         while (items_to_move.Count > 0) {
394                                 sourceToolStrip.RevertMergeItem (items_to_move[0]);
395                                 items_to_move.Remove (items_to_move[0]);
396                         }
397
398                         sourceToolStrip.ResumeLayout ();
399                         targetToolStrip.ResumeLayout ();
400                         
401                         sourceToolStrip.IsCurrentlyMerged = false;
402                         targetToolStrip.IsCurrentlyMerged = false;
403
404                         sourceToolStrip.CurrentlyMergedWith = null;
405                         targetToolStrip.CurrentlyMergedWith = null;
406
407                         return true;
408                 }
409
410                 public static void SaveSettings (Form sourceForm)
411                 {
412                         if (sourceForm == null)
413                                 throw new ArgumentNullException ("sourceForm");
414                 }
415
416                 public static void SaveSettings (Form sourceForm, string key)
417                 {
418                         if (sourceForm == null)
419                                 throw new ArgumentNullException ("sourceForm");
420                         if (string.IsNullOrEmpty (key))
421                                 throw new ArgumentNullException ("key");
422                 }
423                 #endregion
424                 
425                 #region Public Events
426                 public static event EventHandler RendererChanged;
427                 #endregion
428
429                 #region Private/Internal Methods
430                 internal static bool ActivatedByKeyboard {
431                         get { return activated_by_keyboard; }
432                         set { activated_by_keyboard = value; }
433                 }
434                 
435                 internal static void AddToolStrip (ToolStrip ts)
436                 {
437                         lock (toolstrips)
438                                 toolstrips.Add (new WeakReference (ts));
439                 }
440
441                 // When we have merged in MDI items like the min/max/close buttons, we
442                 // can't count them for the sake of menu merging or it will mess up
443                 // where people are trying to put them
444                 private static int AdjustItemMergeIndex (ToolStrip ts, ToolStripItem tsi)
445                 {                       
446                         if (ts.Items[0] is MdiControlStrip.SystemMenuItem)
447                                 return tsi.MergeIndex + 1;
448                                 
449                         return tsi.MergeIndex;
450                 }
451                 
452                 private static int CountRealToolStripItems (ToolStrip ts)
453                 {
454                         int count = 0;
455                         
456                         foreach (ToolStripItem tsi in ts.Items)
457                                 if (!(tsi is MdiControlStrip.ControlBoxMenuItem) && !(tsi is MdiControlStrip.SystemMenuItem))
458                                         count++;
459                                         
460                         return count; 
461                 }
462                 
463                 internal static ToolStrip GetNextToolStrip (ToolStrip ts, bool forward)
464                 {
465                         lock (toolstrips) {
466                                 List<ToolStrip> tools = new List<ToolStrip> ();
467                                 
468                                 foreach (WeakReference wr in toolstrips) {
469                                         ToolStrip t = (ToolStrip)wr.Target;
470                                         
471                                         if (t != null)
472                                                 tools.Add (t);
473                                 }
474                                 
475                                 int index = tools.IndexOf (ts);
476
477                                 if (forward) {
478                                         // Look for any toolstrip after this one in the collection
479                                         for (int i = index + 1; i < tools.Count; i++)
480                                                 if (tools[i].TopLevelControl == ts.TopLevelControl && !(tools[i] is StatusStrip))
481                                                         return tools[i];
482
483                                         // Look for any toolstrip before this one in the collection
484                                         for (int i = 0; i < index; i++)
485                                                 if (tools[i].TopLevelControl == ts.TopLevelControl && !(tools[i] is StatusStrip))
486                                                         return tools[i];
487                                 } else {
488                                         // Look for any toolstrip before this one in the collection
489                                         for (int i = index - 1; i >= 0; i--)
490                                                 if (tools[i].TopLevelControl == ts.TopLevelControl && !(tools[i] is StatusStrip))
491                                                         return tools[i];
492
493                                         // Look for any toolstrip after this one in the collection
494                                         for (int i = tools.Count - 1; i > index; i--)
495                                                 if (tools[i].TopLevelControl == ts.TopLevelControl && !(tools[i] is StatusStrip))
496                                                         return tools[i];
497                                 }
498                         }
499                         
500                         return null;
501                 }
502                 
503                 internal static bool ProcessCmdKey (ref Message m, Keys keyData)
504                 {
505                         lock (menu_items)
506                                 foreach (ToolStripMenuItem tsmi in menu_items)
507                                         if (tsmi.ProcessCmdKey (ref m, keyData) == true)
508                                                 return true;
509                         
510                         return false;
511                 }
512                 
513                 internal static bool ProcessMenuKey (ref Message m)
514                 {
515                         // If we have a currently active menu, deactivate it
516                         if (Application.KeyboardCapture != null) {
517                                 if (Application.KeyboardCapture.OnMenuKey ())
518                                         return true;
519                         }
520                         
521                         // Get the parent form of this message
522                         Form f = (Form)Control.FromHandle (m.HWnd).TopLevelControl;
523
524                         // If there isn't a Form with this, there isn't much we can do
525                         if (f == null)
526                                 return false;
527                                 
528                         // Check the MainMenuStrip property first
529                         if (f.MainMenuStrip != null)
530                                 if (f.MainMenuStrip.OnMenuKey ())
531                                         return true;
532                                         
533                         // Look for any MenuStrip in the form
534                         lock (toolstrips)
535                                 foreach (WeakReference wr in toolstrips) {
536                                         ToolStrip ts = (ToolStrip)wr.Target;
537
538                                         if (ts == null)
539                                                 continue;
540                                 
541                                         if (ts.TopLevelControl == f)
542                                                 if (ts.OnMenuKey ())
543                                                         return true;
544                                 }
545
546                         return false;
547                 }
548                 
549                 internal static void SetActiveToolStrip (ToolStrip toolStrip, bool keyboard)
550                 {
551                         if (Application.KeyboardCapture != null)
552                                 Application.KeyboardCapture.KeyboardActive = false;
553                                 
554                         if (toolStrip == null) {
555                                 activated_by_keyboard = false;
556                                 return;
557                         }
558                         
559                         activated_by_keyboard = keyboard;
560                                 
561                         toolStrip.KeyboardActive = true;
562                 }
563                 
564                 internal static void AddToolStripMenuItem (ToolStripMenuItem tsmi)
565                 {
566                         lock (menu_items)
567                                 menu_items.Add (tsmi);
568                 }
569                 
570                 internal static void RemoveToolStrip (ToolStrip ts)
571                 {
572                         lock (toolstrips) {
573                                 foreach (WeakReference wr in toolstrips)
574                                         if (wr.Target == ts) {
575                                                 toolstrips.Remove (wr);
576                                                 return;
577                                         }
578                         }
579                 }
580
581                 internal static void RemoveToolStripMenuItem (ToolStripMenuItem tsmi)
582                 {
583                         lock (menu_items)
584                                 menu_items.Remove (tsmi);
585                 }
586
587                 internal static void FireAppClicked ()
588                 {
589                         if (AppClicked != null) AppClicked (null, EventArgs.Empty);
590                         
591                         if (Application.KeyboardCapture != null)
592                                 Application.KeyboardCapture.Dismiss (ToolStripDropDownCloseReason.AppClicked);
593                 }
594
595                 internal static void FireAppFocusChanged (Form form)
596                 {
597                         if (AppFocusChange != null) AppFocusChange (form, EventArgs.Empty);
598
599                         if (Application.KeyboardCapture != null)
600                                 Application.KeyboardCapture.Dismiss (ToolStripDropDownCloseReason.AppFocusChange);
601                 }
602
603                 internal static void FireAppFocusChanged (object sender)
604                 {
605                         if (AppFocusChange != null) AppFocusChange (sender, EventArgs.Empty);
606
607                         if (Application.KeyboardCapture != null)
608                                 Application.KeyboardCapture.Dismiss (ToolStripDropDownCloseReason.AppFocusChange);
609                 }
610                 
611                 private static void OnRendererChanged (EventArgs e)
612                 {
613                         if (RendererChanged != null) RendererChanged (null, e);
614                 }
615
616                 private static void RemoveItemFromParentToolStrip (ToolStripItem tsi)
617                 {
618                         if (tsi.Owner != null) {
619                                 tsi.Owner.Items.RemoveNoOwnerOrLayout (tsi);
620
621                                 if (tsi.Owner is ToolStripOverflow)
622                                         (tsi.Owner as ToolStripOverflow).ParentToolStrip.Items.RemoveNoOwnerOrLayout (tsi);
623                         }
624                 }
625                 
626                 internal static event EventHandler AppClicked;
627                 internal static event EventHandler AppFocusChange;
628                 #endregion
629         }
630 }