2007-01-16 Rolf Bjarne Kvinge <RKvinge@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / InternalWindowManager.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) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Jackson Harper (jackson@ximian.com)
24 //
25 //
26
27
28 using System;
29 using System.Drawing;
30 using System.Runtime.InteropServices;
31
32
33 namespace System.Windows.Forms {
34
35         internal class InternalWindowManager {
36                 private Size MinTitleBarSize = new Size (115, 25);
37
38                 internal Form form;
39
40                 internal TitleButton close_button;
41                 internal TitleButton maximize_button;
42                 internal TitleButton minimize_button;
43                 
44                 private ToolTip.ToolTipWindow tooltip;
45                 private Timer tooltip_timer;
46                 private TitleButton tooltip_hovered_button;
47                 private TitleButton tooltip_hidden_button;
48                 private const int tooltip_hide_interval = 3000;
49                 private const int tooltip_show_interval = 1000;
50                 private TitleButton [] title_buttons = new TitleButton [3];
51                 
52                 // moving windows
53                 internal Point start;
54                 internal State state;
55                 protected Point clicked_point;
56                 private FormPos sizing_edge;
57                 internal Rectangle virtual_position;
58                 
59                 public class TitleButton {
60                         public Rectangle Rectangle;
61                         public ButtonState State;
62                         public CaptionButton Caption;
63                         public EventHandler Clicked;
64
65                         public TitleButton (CaptionButton caption, EventHandler clicked)
66                         {
67                                 Caption = caption;
68                                 Clicked = clicked;
69                         }
70                 }
71
72                 public enum State {
73                         Idle,
74                         Moving,
75                         Sizing,
76                 }
77
78                 [Flags]
79                 public enum FormPos {
80                         None,
81
82                         TitleBar = 1,
83
84                         Top = 2,
85                         Left = 4,
86                         Right = 8,
87                         Bottom = 16,
88
89                         TopLeft = Top | Left,
90                         TopRight = Top | Right,
91
92                         BottomLeft = Bottom | Left,
93                         BottomRight = Bottom | Right,
94
95                         AnyEdge = Top | Left | Right | Bottom,
96                 }
97
98                 public InternalWindowManager (Form form)
99                 {
100                         this.form = form;
101
102                         form.SizeChanged += new EventHandler (FormSizeChangedHandler);
103
104                         CreateButtons ();
105                 }
106
107                 public Form Form {
108                         get { return form; }
109                 }
110
111                 public bool AnyPushedTitleButtons {
112                         get {
113                                 return (minimize_button != null && minimize_button.State == ButtonState.Pushed) ||
114                                         (maximize_button != null && maximize_button.State == ButtonState.Pushed) ||
115                                         (close_button != null && close_button.State == ButtonState.Pushed);
116                         }
117                 }
118                 
119                 public int IconWidth {
120                         get { return TitleBarHeight - 5; }
121                 }
122
123                 public virtual bool HandleMessage (ref Message m)
124                 {
125                         switch ((Msg)m.Msg) {
126
127
128                                 // The mouse handling messages are actually
129                                 // not WM_NC* messages except for the first button and NCMOVEs
130                                 // down because we capture on the form
131
132                         case Msg.WM_MOUSEMOVE:
133                                 return HandleMouseMove (form, ref m);
134
135                         case Msg.WM_LBUTTONUP:
136                                 HandleLButtonUp (ref m);
137                                 break;
138
139                         case Msg.WM_RBUTTONDOWN:
140                                 return HandleRButtonDown (ref m);
141                                 
142                         case Msg.WM_LBUTTONDOWN:
143                                 return HandleLButtonDown (ref m);
144                                 
145                         case Msg.WM_LBUTTONDBLCLK:
146                                 return HandleLButtonDblClick (ref m);
147                                 
148                         case Msg.WM_PARENTNOTIFY:
149                                 if (Control.LowOrder(m.WParam.ToInt32()) == (int) Msg.WM_LBUTTONDOWN) 
150                                         Activate ();
151                                 break;
152
153                         case Msg.WM_NCHITTEST: 
154                                 return HandleNCHitTest (ref m);
155
156                                 // Return true from these guys, otherwise win32 will mess up z-order
157                         case Msg.WM_NCLBUTTONUP:
158                                 HandleNCLButtonUp (ref m);
159                                 return true;
160
161                         case Msg.WM_NCLBUTTONDOWN:
162                                 HandleNCLButtonDown (ref m);
163                                 return true;
164
165                         case Msg.WM_NCMOUSEMOVE:
166                                 HandleNCMouseMove (ref m);
167                                 return true;
168                                 
169                         case Msg.WM_NCLBUTTONDBLCLK:
170                                 HandleNCLButtonDblClick (ref m);
171                                 break;
172
173                         case Msg.WM_NCMOUSELEAVE:
174                                 HandleNCMouseLeave (ref m);
175                                 break;
176                         
177                         case Msg.WM_MOUSE_LEAVE:
178                                 HandleMouseLeave (ref m);
179                                 break;
180
181                         case Msg.WM_NCCALCSIZE:
182                                 HandleNCCalcSize (ref m);
183                                 break;
184
185                         case Msg.WM_NCPAINT:
186                                 return HandleNCPaint ();
187                         }
188
189                         return false;
190                 }
191
192                 protected virtual bool HandleNCPaint ()
193                 {
194                         PaintEventArgs pe = XplatUI.PaintEventStart (form.Handle, false);
195
196                         Rectangle clip;
197                         // clip region is not correct on win32.
198                         // if (m.WParam.ToInt32 () > 1) {
199                         //      Region r = Region.FromHrgn (m.WParam);
200                         //      RectangleF rf = r.GetBounds (pe.Graphics);
201                         //      clip = new Rectangle ((int) rf.X, (int) rf.Y, (int) rf.Width, (int) rf.Height);
202                         //} else {      
203                         clip = new Rectangle (0, 0, form.Width, form.Height);
204                         //}
205
206                         ThemeEngine.Current.DrawManagedWindowDecorations (pe.Graphics, clip, this);
207                         XplatUI.PaintEventEnd (form.Handle, false);
208                         return true;
209                 }
210
211                 protected virtual void HandleNCCalcSize (ref Message m)
212                 {
213                         XplatUIWin32.NCCALCSIZE_PARAMS ncp;
214
215                         if (m.WParam == (IntPtr)1) {
216                                 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (m.LParam,
217                                                 typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
218
219                                 int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
220
221                                 if (HasBorders) {
222                                         ncp.rgrc1.top += TitleBarHeight + bw;
223                                         ncp.rgrc1.bottom -= bw;
224                                         ncp.rgrc1.left += bw;
225                                         ncp.rgrc1.right -= bw;
226                                 }
227
228                                 Marshal.StructureToPtr (ncp, m.LParam, true);
229                         }
230                 }
231
232                 protected virtual bool HandleNCHitTest (ref Message m)
233                 {
234
235                         int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
236                         int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
237
238                         NCPointToClient (ref x, ref y);
239
240                         FormPos pos = FormPosForCoords (x, y);
241
242                         if (pos == FormPos.TitleBar) {
243                                 m.Result = new IntPtr ((int)HitTest.HTCAPTION);
244                                 return true;
245                         }
246
247                         if (!IsSizable)
248                                 return false;
249
250                         switch (pos) {
251                         case FormPos.Top:
252                                 m.Result = new IntPtr ((int)HitTest.HTTOP);
253                                 break;
254                         case FormPos.Left:
255                                 m.Result = new IntPtr ((int)HitTest.HTLEFT);
256                                 break;
257                         case FormPos.Right:
258                                 m.Result = new IntPtr ((int)HitTest.HTRIGHT);
259                                 break;
260                         case FormPos.Bottom:
261                                 m.Result = new IntPtr ((int)HitTest.HTBOTTOM);
262                                 break;
263                         case FormPos.TopLeft:
264                                 m.Result = new IntPtr ((int)HitTest.HTTOPLEFT);
265                                 break;
266                         case FormPos.TopRight:
267                                 m.Result = new IntPtr ((int)HitTest.HTTOPRIGHT);
268                                 break;
269                         case FormPos.BottomLeft:
270                                 m.Result = new IntPtr ((int)HitTest.HTBOTTOMLEFT);
271                                 break;
272                         case FormPos.BottomRight:
273                                 m.Result = new IntPtr ((int)HitTest.HTBOTTOMRIGHT);
274                                 break;
275                         default:
276                                 // We return false so that DefWndProc handles things
277                                 return false;
278                         }
279                         return true;
280                 }
281
282                 public virtual void UpdateBorderStyle (FormBorderStyle border_style)
283                 {
284                         XplatUI.SetBorderStyle (form.Handle, border_style);
285
286                         if (ShouldRemoveWindowManager (border_style)) {
287                                 form.RemoveWindowManager ();
288                                 return;
289                         }
290                                 
291                         CreateButtons ();
292                 }
293
294                 #region ToolTip helpers
295                 // Called from MouseMove if mouse is over a button
296                 private void ToolTipStart (TitleButton button)
297                 {
298                         tooltip_hovered_button = button;
299                         
300                         if (tooltip_hovered_button == tooltip_hidden_button)
301                                 return;
302                         tooltip_hidden_button = null;
303                         
304                         if (tooltip != null && tooltip.Visible)
305                                 ToolTipShow (true);
306                                 
307                         if (tooltip_timer == null) {
308                                         
309                                 tooltip_timer = new Timer ();
310                                 tooltip_timer.Tick += new EventHandler (ToolTipTimerTick);
311                         }
312                                 
313                         tooltip_timer.Interval = tooltip_show_interval;
314                         tooltip_timer.Start ();
315                         tooltip_hovered_button = button;
316                 }
317                 
318                 private void ToolTipTimerTick (object sender, EventArgs e)
319                 {
320                         if (tooltip_timer.Interval == tooltip_hide_interval) {
321                                 tooltip_hidden_button = tooltip_hovered_button;
322                                 ToolTipHide (false);
323                         } else {
324                                 ToolTipShow (false);
325                         }
326                 }
327                 // Called from timer (with only_refresh = false)
328                 // Called from ToolTipStart if tooltip is already shown (with only_refresh = true)
329                 private void ToolTipShow (bool only_refresh)
330                 {
331                         string text = Locale.GetText (tooltip_hovered_button.Caption.ToString ());
332                         
333                         tooltip_timer.Interval = tooltip_hide_interval;
334                         tooltip_timer.Enabled = true;
335                         
336                         if (only_refresh && (tooltip == null || !tooltip.Visible )) {
337                                 return;
338                         }
339                                 
340                         if (tooltip == null)
341                                 tooltip = new ToolTip.ToolTipWindow ();
342                         else if (tooltip.Text == text && tooltip.Visible)
343                                 return;
344                         else if (tooltip.Visible)
345                                 tooltip.Visible = false;
346
347                         if (form.WindowState == FormWindowState.Maximized)
348                                 tooltip.Present (form.MdiParent, text);
349                         else
350                                 tooltip.Present (form, text);
351                         
352                 }
353                 
354                 // Called from MouseLeave (with reset_hidden_button = true)
355                 // Called from MouseDown  (with reset_hidden_button = false)
356                 // Called from MouseMove if mouse isn't over any button (with reset_hidden_button = false)
357                 // Called from Timer if hiding (with reset_hidden_button = false)
358                 private void ToolTipHide (bool reset_hidden_button)
359                 {
360                         if (tooltip_timer != null)
361                                 tooltip_timer.Enabled = false;
362                         if (tooltip != null && tooltip.Visible)
363                                 tooltip.Visible = false;
364                         if (reset_hidden_button)
365                                 tooltip_hidden_button = null;
366                 }
367                 #endregion
368                 
369                 public virtual void SetWindowState (FormWindowState old_state, FormWindowState window_state)
370                 {
371                 }
372
373                 public virtual FormWindowState GetWindowState ()
374                 {
375                         return form.window_state;
376                 }
377
378                 public virtual void PointToClient (ref int x, ref int y)
379                 {
380                         // toolwindows stay in screencoords we just have to make sure
381                         // they obey the working area
382                         Rectangle working = SystemInformation.WorkingArea;
383
384                         if (x > working.Right)
385                                 x = working.Right;
386                         if (x < working.Left)
387                                 x = working.Left;
388
389                         if (y < working.Top)
390                                 y = working.Top;
391                         if (y > working.Bottom)
392                                 y = working.Bottom;
393                 }
394
395                 public virtual void PointToScreen (ref int x, ref int y)
396                 {
397                         XplatUI.ClientToScreen (form.Handle, ref x, ref y);
398                 }
399
400                 protected virtual bool ShouldRemoveWindowManager (FormBorderStyle style)
401                 {
402                         return style != FormBorderStyle.FixedToolWindow && style != FormBorderStyle.SizableToolWindow;
403                 }
404
405                 protected virtual void Activate ()
406                 {
407                         form.Refresh ();
408                 }
409
410                 public virtual bool IsActive ()
411                 {
412                         return true;
413                 }
414
415
416                 private void FormSizeChangedHandler (object sender, EventArgs e)
417                 {
418                         ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
419                         XplatUI.InvalidateNC (form.Handle);
420                 }
421
422                 protected void CreateButtons ()
423                 {
424                         switch (form.FormBorderStyle) {
425                         case FormBorderStyle.None:
426                                 close_button = null;
427                                 minimize_button = null;
428                                 maximize_button = null;
429                                 if (IsMaximized || IsMinimized)
430                                         goto case FormBorderStyle.Sizable;
431                                 break;
432                         case FormBorderStyle.FixedToolWindow:
433                         case FormBorderStyle.SizableToolWindow:
434                                 close_button = new TitleButton (CaptionButton.Close, new EventHandler (CloseClicked));
435                                 if (IsMaximized || IsMinimized)
436                                         goto case FormBorderStyle.Sizable;
437                                 break;
438                         case FormBorderStyle.FixedSingle:
439                         case FormBorderStyle.Fixed3D:
440                         case FormBorderStyle.FixedDialog:
441                         case FormBorderStyle.Sizable:
442                                 close_button = new TitleButton (CaptionButton.Close, new EventHandler (CloseClicked));
443                                 minimize_button = new TitleButton (CaptionButton.Minimize, new EventHandler (MinimizeClicked));
444                                 maximize_button = new TitleButton (CaptionButton.Maximize, new EventHandler (MaximizeClicked));
445                                 break;
446                         }
447
448                         title_buttons [0] = close_button;
449                         title_buttons [1] = minimize_button;
450                         title_buttons [2] = maximize_button;
451
452                         ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
453                 }
454
455                 protected virtual bool HandleRButtonDown (ref Message m)
456                 {
457                         Activate ();
458                         return false;
459                 }
460                 
461                 protected virtual bool HandleLButtonDown (ref Message m)
462                 {
463                         Activate ();
464                         return false;
465                 }
466
467                 protected virtual bool HandleLButtonDblClick(ref Message m)
468                 {
469                         return false;
470                 }
471                 
472                 protected virtual bool HandleNCMouseLeave (ref Message m)
473                 {
474                         int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
475                         int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
476
477                         NCPointToClient (ref x, ref y);
478                         FormPos pos = FormPosForCoords (x, y);
479
480                         if (pos != FormPos.TitleBar) {
481                                 HandleTitleBarLeave (x, y);
482                                 return true;
483                         }
484
485                         return true;
486                 }
487                 
488                 protected virtual bool HandleNCMouseMove (ref Message m)
489                 {
490                         int x = Control.LowOrder((int)m.LParam.ToInt32( ));
491                         int y = Control.HighOrder((int)m.LParam.ToInt32( ));
492
493                         NCPointToClient (ref x, ref y);
494                         FormPos pos = FormPosForCoords (x, y);
495
496                         if (pos == FormPos.TitleBar) {
497                                 HandleTitleBarMouseMove (x, y);
498                                 return true;
499                         }
500
501                         return true;
502                         
503                 }
504                 
505                 protected virtual bool HandleNCLButtonDown (ref Message m)
506                 {
507                         Activate ();
508
509                         start = Cursor.Position;
510                         virtual_position = form.Bounds;
511                         
512                         int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
513                         int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
514                         
515                         // Need to adjust because we are in NC land
516                         NCPointToClient (ref x, ref y);
517                         FormPos pos = FormPosForCoords (x, y);
518                         
519                         if (pos == FormPos.TitleBar) {
520                                 HandleTitleBarDown (x, y);
521                                 return true;
522                         }
523
524                         if (IsSizable) {
525                                 if ((pos & FormPos.AnyEdge) == 0)
526                                         return false;
527
528                                 virtual_position = form.Bounds;
529                                 state = State.Sizing;
530                                 sizing_edge = pos;
531                                 form.Capture = true;
532                                 return true;
533                         }
534
535                         return false;
536                 }
537
538                 protected virtual void HandleNCLButtonDblClick (ref Message m)
539                 {
540                         int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
541                         int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
542
543                         // Need to adjust because we are in NC land
544                         NCPointToClient (ref x, ref y);
545
546                         FormPos pos = FormPosForCoords (x, y);
547                         if (pos == FormPos.TitleBar || pos == FormPos.Top)
548                                 HandleTitleBarDoubleClick (x, y);
549
550                 }
551                 
552                 protected virtual void HandleTitleBarDoubleClick (int x, int y)
553                 {
554                 
555                 }
556                 
557                 protected virtual void HandleTitleBarLeave (int x, int y)
558                 {
559                         foreach (TitleButton button in title_buttons) {
560                                 if (button != null) {
561                                         button.State = ButtonState.Normal;
562                                 }
563                         }
564                         ToolTipHide (true);
565                         return;
566                 }
567                 
568                 protected virtual void HandleTitleBarMouseMove (int x, int y)
569                 {
570                         bool any_change = false;
571                         bool any_tooltip = false;
572                         bool any_pushed_buttons = AnyPushedTitleButtons;
573                         
574                         foreach (TitleButton button in title_buttons) {
575                                 if (button == null)
576                                         continue;
577                                 
578                                 if (button.Rectangle.Contains (x, y)) {
579                                         if (any_pushed_buttons) {
580                                                 any_change |= button.State != ButtonState.Pushed;
581                                                 button.State = ButtonState.Pushed;
582                                         }
583                                         ToolTipStart (button);
584                                         any_tooltip = true;
585                                 } else {
586                                         if (any_pushed_buttons) {
587                                                 any_change |= button.State != ButtonState.Normal;
588                                                 button.State = ButtonState.Normal;
589                                         }
590                                 }
591                         }
592                         if (any_change) {
593                                 if (IsMaximized && form.IsMdiChild)
594                                         XplatUI.InvalidateNC (form.MdiParent.Handle);
595                                 else
596                                         XplatUI.InvalidateNC (form.Handle);
597                         }
598                         if (!any_tooltip)
599                                 ToolTipHide (false);
600                 }
601                 
602                 protected virtual void HandleTitleBarUp (int x, int y)
603                 {
604                         foreach (TitleButton button in title_buttons) {
605                                 if (button == null)
606                                         continue;
607                                         
608                                 button.State = ButtonState.Normal;
609                                 if (button.Rectangle.Contains (x, y)) {
610                                         button.Clicked (this, EventArgs.Empty);
611                                 } 
612                         }
613
614                         return;
615                 }
616                 
617                 protected virtual void HandleTitleBarDown (int x, int y)
618                 {
619                         ToolTipHide (false);
620                         
621                         foreach (TitleButton button in title_buttons) {
622                                 if (button != null) {
623                                         if (button.Rectangle.Contains (x, y)) {
624                                                 button.State = ButtonState.Pushed;
625                                         } else {
626                                                 button.State = ButtonState.Normal;
627                                         }
628                                 }
629                         }
630                         
631                         if (!AnyPushedTitleButtons && !IsMaximized){
632                                 state = State.Moving;
633                                 clicked_point = new Point (x, y);
634                                 if (form.IsMdiChild) {
635                                         form.CaptureWithConfine (form.Parent);
636                                 } else {
637                                         form.Capture = true;
638                                 }
639                         }
640                         
641                         XplatUI.InvalidateNC (form.Handle);
642                 }
643
644                 private bool HandleMouseMove (Form form, ref Message m)
645                 {
646                         switch (state) {
647                         case State.Moving:
648                                 HandleWindowMove (m);
649                                 return true;
650                         case State.Sizing:
651                                 HandleSizing (m);
652                                 return true;
653                         }
654                         
655                         return false;
656                 }
657
658                 private void HandleMouseLeave (ref Message m)
659                 {
660                         form.ResetCursor ();
661                 }
662         
663                 protected virtual void HandleWindowMove (Message m)
664                 {
665                         Point move = MouseMove (m);
666
667                         UpdateVP (virtual_position.X + move.X, virtual_position.Y + move.Y,
668                                         virtual_position.Width, virtual_position.Height);
669                 }
670
671                 private void HandleSizing (Message m)
672                 {
673                         Rectangle pos = virtual_position;
674                         int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
675                         int mw = MinTitleBarSize.Width + (bw * 2);
676                         int mh = MinTitleBarSize.Height + (bw * 2);
677                         int x = Cursor.Position.X;
678                         int y = Cursor.Position.Y;
679
680                         PointToClient (ref x, ref y);
681
682                         if ((sizing_edge & FormPos.Top) != 0) {
683                                 if (pos.Bottom - y < mh)
684                                         y = pos.Bottom - mh;
685                                 pos.Height = pos.Bottom - y;
686                                 pos.Y = y;
687                         } else if ((sizing_edge & FormPos.Bottom) != 0) {
688                                 int height = y - pos.Top;
689                                 if (height <= mh)
690                                         height = mh;
691                                 pos.Height = height;
692                         }
693
694                         if ((sizing_edge & FormPos.Left) != 0) {
695                                 if (pos.Right - x < mw)
696                                         x = pos.Right - mw;
697                                 pos.Width = pos.Right - x;
698                                 pos.X = x;
699                         } else if ((sizing_edge & FormPos.Right) != 0) {
700                                 int width = x - form.Left;
701                                 if (width <= mw)
702                                         width = mw;
703                                 pos.Width = width;
704                         }
705
706                         UpdateVP (pos);
707                 }
708
709                 public bool IsMaximized {
710                         get { return GetWindowState () == FormWindowState.Maximized; }
711                 }
712
713                 public bool IsMinimized {
714                         get { return GetWindowState () == FormWindowState.Minimized; }
715                 }
716
717                 public bool IsSizable {
718                         get {
719                                 switch (form.FormBorderStyle) {
720                                 case FormBorderStyle.Sizable:
721                                 case FormBorderStyle.SizableToolWindow:
722                                         return (form.window_state != FormWindowState.Minimized);
723                                 default:
724                                         return false;
725                                 }
726                         }
727                 }
728
729                 public bool HasBorders {
730                         get {
731                                 return form.FormBorderStyle != FormBorderStyle.None;
732                         }
733                 }
734
735                 public bool IsToolWindow {
736                         get {
737                                 if (form.FormBorderStyle == FormBorderStyle.SizableToolWindow ||
738                                                 form.FormBorderStyle == FormBorderStyle.FixedToolWindow)
739                                         return true;
740                                 return false;
741                         }
742                 }
743
744                 public int TitleBarHeight {
745                         get {
746                                 return ThemeEngine.Current.ManagedWindowTitleBarHeight (this);
747                         }
748                 }
749
750                 protected void UpdateVP (Rectangle r)
751                 {
752                         UpdateVP (r.X, r.Y, r.Width, r.Height);
753                 }
754
755                 protected void UpdateVP (Point loc, int w, int h)
756                 {
757                         UpdateVP (loc.X, loc.Y, w, h);
758                 }
759
760                 protected void UpdateVP (int x, int y, int w, int h)
761                 {
762                         virtual_position.X = x;
763                         virtual_position.Y = y;
764                         virtual_position.Width = w;
765                         virtual_position.Height = h;
766
767                         DrawVirtualPosition (virtual_position);
768                 }
769
770                 protected virtual void HandleLButtonUp (ref Message m)
771                 {
772                         if (state == State.Idle)
773                                 return;
774
775                         ClearVirtualPosition ();
776
777                         form.Capture = false;
778                         if (state == State.Moving && form.Location != virtual_position.Location) 
779                                 form.Location = virtual_position.Location;
780                         else if (state == State.Sizing && form.Bounds != virtual_position)
781                                 form.Bounds = virtual_position;
782                         state = State.Idle;
783
784                         OnWindowFinishedMoving ();
785                 }
786
787                 private bool HandleNCLButtonUp (ref Message m)
788                 {
789                         if (form.Capture) {
790                                 ClearVirtualPosition ();
791
792                                 form.Capture = false;
793                                 state = State.Idle;
794                                 if (form.MdiContainer != null)
795                                         form.MdiContainer.SizeScrollBars();
796                         }
797                                 
798                         int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
799                         int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
800
801                         NCPointToClient (ref x, ref y);
802                         FormPos pos = FormPosForCoords (x, y);
803
804                         if (pos == FormPos.TitleBar) {
805                                 HandleTitleBarUp (x, y);
806                                 return true;
807                         }
808                         
809                         return true;
810                 }
811                 
812                 protected void DrawTitleButton (Graphics dc, TitleButton button, Rectangle clip)
813                 {
814                         if (!button.Rectangle.IntersectsWith (clip))
815                                 return;
816
817                         dc.FillRectangle (SystemBrushes.Control, button.Rectangle);
818                         ControlPaint.DrawCaptionButton (dc, button.Rectangle,
819                                         button.Caption, button.State);
820                 }
821
822                 public virtual void DrawMaximizedButtons (object sender, PaintEventArgs pe)
823                 {
824                 }
825
826                 protected virtual void CloseClicked (object sender, EventArgs e)
827                 {
828                         form.Close ();
829                 }
830
831                 private void MinimizeClicked (object sender, EventArgs e)
832                 {
833                         if (GetWindowState () != FormWindowState.Minimized) {
834                                 form.WindowState = FormWindowState.Minimized;
835                         } else {
836                                 form.WindowState = FormWindowState.Normal;
837                         }
838                 }
839
840                 private void MaximizeClicked (object sender, EventArgs e)
841                 {
842                         if (GetWindowState () != FormWindowState.Maximized) {
843                                 form.WindowState = FormWindowState.Maximized;
844                         } else {
845                                 form.WindowState = FormWindowState.Normal;
846                         }
847                 }
848
849                 protected Point MouseMove (Message m)
850                 {
851                         Point cp = Cursor.Position;
852                         return new Point (cp.X - start.X, cp.Y - start.Y);
853                 }
854
855                 protected virtual void DrawVirtualPosition (Rectangle virtual_position)
856                 {
857                         form.Bounds = virtual_position;
858                         start = Cursor.Position;
859                 }
860
861                 protected virtual void ClearVirtualPosition ()
862                 {
863                         
864                 }
865
866                 protected virtual void OnWindowFinishedMoving ()
867                 {
868                 }
869
870                 protected virtual void NCPointToClient(ref int x, ref int y) {
871                         form.PointToClient(ref x, ref y);
872                         NCClientToNC (ref x, ref y);
873                 }
874
875                 protected virtual void NCClientToNC (ref int x, ref int y) {
876                         y += TitleBarHeight;
877                         y += ThemeEngine.Current.ManagedWindowBorderWidth (this);
878                 }
879                 
880                 protected FormPos FormPosForCoords (int x, int y)
881                 {
882                         int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
883                         if (y < TitleBarHeight + bw) {
884                                 //      Console.WriteLine ("A");
885                                 if (y > bw && x > bw &&
886                                                 x < form.Width - bw)
887                                         return FormPos.TitleBar;
888
889                                 if (x < bw || (x < 20 && y < bw))
890                                         return FormPos.TopLeft;
891
892                                 if (x > form.Width - bw ||
893                                         (x > form.Width - 20 && y < bw))
894                                         return FormPos.TopRight;
895
896                                 if (y < bw)
897                                         return FormPos.Top;
898
899                         } else if (y > form.Height - 20) {
900                                 //      Console.WriteLine ("B");
901                                 if (x < bw ||
902                                                 (x < 20 && y > form.Height - bw))
903                                         return FormPos.BottomLeft;
904
905                                 if (x > form.Width - (bw * 2) ||
906                                                 (x > form.Width - 20 &&
907                                                  y > form.Height - bw))
908                                         return FormPos.BottomRight;
909
910                                 if (y > form.Height - (bw * 2))
911                                         return FormPos.Bottom;
912
913
914                         } else if (x < bw) {
915                                 //      Console.WriteLine ("C");
916                                 return FormPos.Left;
917                         } else if (x > form.Width - (bw * 2)) {
918 //                              Console.WriteLine ("D");
919                                 return FormPos.Right;
920                         } else {
921                                 //                      Console.WriteLine ("E   {0}", form.Width - bw);
922                         }
923                         
924                         return FormPos.None;
925                 }
926         }
927 }
928
929