* TreeView.cs: Don't draw the selected node when we lose
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / MdiChildContext.cs
1
2 using System;
3 using System.Drawing;
4 using System.Drawing.Drawing2D;
5
6 namespace System.Windows.Forms {
7
8         internal class MdiChildContext {
9
10                 private static Color titlebar_color;
11
12                 private int BorderWidth = 3;
13                 private int TitleBarHeight = 25;
14                 private Size MinTitleBarSize = new Size (115, 25);
15                 
16                 private Form form;
17                 private MdiClient mdi_container;
18                 private Button close_button;
19                 private Button maximize_button;
20                 private Button minimize_button;
21                 
22                 // moving windows
23                 private Point start;
24                 private State state;
25                 private FormPos sizing_edge;
26                 private Rectangle virtual_position;
27                 private Rectangle prev_virtual_position;
28                 private Rectangle prev_bounds;
29                 private bool maximized;
30                 
31                 private enum State {
32                         Idle,
33                         Moving,
34                         Sizing,
35                 }
36
37                 [Flags]
38                 private enum FormPos {
39                         None,
40
41                         TitleBar = 1,
42
43                         Top = 2,
44                         Left = 4,
45                         Right = 8,
46                         Bottom = 16,
47
48                         TopLeft = Top | Left,
49                         TopRight = Top | Right,
50
51                         BottomLeft = Bottom | Left,
52                         BottomRight = Bottom | Right,
53
54                         AnyEdge = Top | Left | Right | Bottom,
55                 }
56
57                 public MdiChildContext (Form form, MdiClient mdi_container)
58                 {
59                         titlebar_color = Color.FromArgb (255, 0, 0, 255);
60                         this.form = form;
61                         this.mdi_container = mdi_container;
62
63                         form.Paint += new PaintEventHandler (PaintWindowDecorations);
64
65                         minimize_button = new Button ();
66                         minimize_button.Bounds = new Rectangle (form.Width - 62,
67                                         BorderWidth + 2, 18, 22);
68                         minimize_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
69                         minimize_button.Paint += new PaintEventHandler (PaintButtonHandler);
70                         minimize_button.Click += new EventHandler (OnMinimizeHandler);
71                         
72                         maximize_button = new Button ();
73                         maximize_button.Bounds = new Rectangle (form.Width - 44,
74                                         BorderWidth + 2, 18, 22);
75                         maximize_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
76                         maximize_button.Paint += new PaintEventHandler (PaintButtonHandler);
77                         maximize_button.Click += new EventHandler (OnMaximizeHandler);
78                         
79                         close_button = new Button ();
80                         close_button.Bounds = new Rectangle (form.Width - 24,
81                                         BorderWidth + 2, 18, 22);
82                         close_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
83                         close_button.Paint += new PaintEventHandler (PaintButtonHandler);
84                         close_button.Click += new EventHandler (CloseButtonClicked);
85
86                         form.Controls.AddImplicit (close_button);
87                         form.Controls.AddImplicit (maximize_button);
88                         form.Controls.AddImplicit (minimize_button);
89                 }
90
91                 public bool HandleMessage (ref Message m)
92                 {
93                         switch ((Msg)m.Msg) {
94
95                         case Msg.WM_LBUTTONDOWN:
96                                 return HandleLButtonDown (form, ref m);
97
98                         case Msg.WM_MOUSEMOVE:
99                                 return HandleMouseMove (form, ref m);
100                                  
101                         case Msg.WM_LBUTTONUP:
102                                 HandleLButtonUp (ref m);
103                                 break;
104                         }
105                         return false;
106                 }
107
108                 
109                 private bool HandleLButtonDown (Form form, ref Message m)
110                 {
111                         form.BringToFront ();
112                         mdi_container.ActiveMdiChild = form;
113
114                         int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
115                         int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
116                         FormPos pos = FormPosForCoords (x, y);
117
118                         start = new Point (x, y);
119                         virtual_position = form.Bounds;
120
121                         if (pos == FormPos.TitleBar) {
122                                 HandleTitleBarDown (x, y);
123                                 return true;
124                         }
125
126                         if (IsSizable) {
127                                 SetCursorForPos (pos);
128                         
129                                 if ((pos & FormPos.AnyEdge) == 0)
130                                         return false;
131
132                                 state = State.Sizing;
133                                 sizing_edge = pos;
134                                 form.Capture = true;
135                                 return true;
136                         }
137
138                         return false;
139                 }
140
141                 private void HandleTitleBarDown (int x, int y)
142                 {
143                         state = State.Moving;                        
144                         form.Capture = true;
145                 }
146
147                 private bool HandleMouseMove (Form form, ref Message m)
148                 {
149                         switch (state) {
150                         case State.Moving:
151                                 HandleWindowMove (m);
152                                 return true;
153                         case State.Sizing:
154                                 HandleSizing (m);
155                                 return true;
156                         }
157
158                         if (IsSizable) {
159                                 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
160                                 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
161                                 FormPos pos = FormPosForCoords (x, y);
162
163                                 SetCursorForPos (pos);
164
165                                 ClearVirtualPosition ();
166                                 state = State.Idle;
167                         }
168
169                         return false;
170                 }
171         
172                 private void SetCursorForPos (FormPos pos)
173                 {
174                         switch (pos) {
175                         case FormPos.TopLeft:
176                         case FormPos.BottomRight:
177                                 form.Cursor = Cursors.SizeNWSE;
178                                 break;
179                         case FormPos.TopRight:
180                         case FormPos.BottomLeft:
181                                 form.Cursor = Cursors.SizeNESW;
182                                 break;
183                         case FormPos.Top:
184                         case FormPos.Bottom:
185                                 form.Cursor = Cursors.SizeNS;
186                                 break;
187                         case FormPos.Left:
188                         case FormPos.Right:
189                                 form.Cursor = Cursors.SizeWE;
190                                 break;
191                         default:
192                                 form.Cursor = Cursors.Default;
193                                 break;
194                         }
195                 }
196         
197                 private void HandleWindowMove (Message m)
198                 {
199                         Point move = MouseMove (m);
200
201                         virtual_position.X = form.Left + move.X;
202                         virtual_position.Y = form.Top + move.Y;
203                         virtual_position.Width = form.Width;
204                         virtual_position.Height = form.Height;
205
206                         DrawVirtualPosition ();
207                 }
208
209                 private void HandleSizing (Message m)
210                 {
211                         Point move = MouseMove (m);
212                         Rectangle pos = virtual_position;
213                         int mw = MinTitleBarSize.Width + (BorderWidth * 2);
214                         int mh = MinTitleBarSize.Height + (BorderWidth * 2);
215                         
216                         if ((sizing_edge & FormPos.Top) != 0) {
217                                 int height = form.Height - move.Y;
218                                 if (height <= mh) {
219                                         move.Y += height - mh;
220                                         height = mh;
221                                 }
222                                 pos.Y = form.Top + move.Y;
223                                 pos.Height = height;
224                         } else if ((sizing_edge & FormPos.Bottom) != 0) {
225                                 int height = form.Height + move.Y;
226                                 if (height <= mh)
227                                         move.Y -= height - mh;
228                                 pos.Height = form.Height + move.Y;
229                         }
230
231                         if ((sizing_edge & FormPos.Left) != 0) {
232                                 int width = form.Width - move.X;
233                                 if (width <= mw) {
234                                         move.X += width - mw;
235                                         width = mw;
236                                 }
237                                 pos.X = form.Left + move.X;
238                                 pos.Width = width;
239                         } else if ((sizing_edge & FormPos.Right) != 0) {
240                                 int width = form.Width + move.X;
241                                 if (width <= mw)
242                                         move.X -= width - mw;
243                                 pos.Width = form.Width + move.X;
244                         }
245
246                         UpdateVP (pos);
247                 }
248
249                 private bool IsSizable {
250                         get {
251                                 switch (form.FormBorderStyle) {
252                                 case FormBorderStyle.Sizable:
253                                 case FormBorderStyle.SizableToolWindow:
254                                         return true;
255                                 default:
256                                         return false;
257                                 }
258                         }
259                 }
260
261                 private void UpdateVP (Rectangle r)
262                 {
263                         UpdateVP (r.X, r.Y, r.Width, r.Height);
264                 }
265
266                 private void UpdateVP (Point loc, int w, int h)
267                 {
268                         UpdateVP (loc.X, loc.Y, w, h);
269                 }
270
271                 private void UpdateVP (int x, int y, int w, int h)
272                 {
273                         virtual_position.X = x;
274                         virtual_position.Y = y;
275                         virtual_position.Width = w;
276                         virtual_position.Height = h;
277
278                         DrawVirtualPosition ();
279                 }
280
281                 private void HandleLButtonUp (ref Message m)
282                 {
283                         if (state == State.Idle)
284                                 return;
285
286                         ClearVirtualPosition ();
287
288                         form.Capture = false;
289                         form.Bounds = virtual_position;
290                         state = State.Idle;
291                 }
292
293                 private void PaintWindowDecorations (object sender, PaintEventArgs pe)
294                 {
295                         Color color = titlebar_color;
296                         if (maximized)
297                                 color = ThemeEngine.Current.ColorControl;
298                         Rectangle tb = new Rectangle (BorderWidth, BorderWidth,
299                                         form.Width - BorderWidth, TitleBarHeight);
300
301                         pe.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (color),
302                                                 BorderWidth, BorderWidth,
303                                                 form.Width - BorderWidth, TitleBarHeight);
304
305                         tb.X += 18; // Room for the icon
306                         if (form.Text != null) {
307                                 StringFormat format = new StringFormat ();
308                                 format.LineAlignment = StringAlignment.Center;
309                                 pe.Graphics.DrawString (form.Text, form.Font,
310                                                 ThemeEngine.Current.ResPool.GetSolidBrush (form.ForeColor),
311                                                 tb, format);
312                         }
313
314                         if (form.Icon != null) {
315                                 pe.Graphics.DrawIcon (form.Icon, new Rectangle (BorderWidth + 2,
316                                                                       BorderWidth + 2, 16, 16));
317                         }
318                 }
319
320                 private void PaintButtonHandler (object sender, PaintEventArgs pe)
321                 {
322                         if (sender == close_button) {
323                                 ControlPaint.DrawCaptionButton (pe.Graphics,
324                                                 close_button.ClientRectangle,
325                                                 CaptionButton.Close,
326                                                 close_button.ButtonState);
327                         } else if (sender == maximize_button) {
328                                 ControlPaint.DrawCaptionButton (pe.Graphics,
329                                                 maximize_button.ClientRectangle,
330                                                 CaptionButton.Maximize,
331                                                 maximize_button.ButtonState);
332                         } else if (sender == minimize_button) {
333                                 ControlPaint.DrawCaptionButton (pe.Graphics,
334                                                 minimize_button.ClientRectangle,
335                                                 CaptionButton.Minimize,
336                                                 minimize_button.ButtonState);
337                         }
338                 }
339
340                 private void CloseButtonClicked (object sender, EventArgs e)
341                 {
342                         form.Close ();
343                         // form.Close should set visibility to false somewhere
344                         // in it's closing chain but currently does not.
345                         form.Visible = false;
346                 }
347
348                 private void OnMinimizeHandler (object sender, EventArgs e)
349                 {
350                         form.SuspendLayout ();
351                         form.Width = MinTitleBarSize.Width + (BorderWidth * 2);
352                         form.Height = MinTitleBarSize.Height + (BorderWidth * 2);
353                         form.ResumeLayout ();
354                 }
355
356                 private void OnMaximizeHandler (object sender, EventArgs e)
357                 {
358                         if (maximized) {
359                                 form.Bounds = prev_bounds;
360                                 maximized = false;
361                         } else {
362                                 prev_bounds = form.Bounds;
363                                 form.Bounds = form.Parent.Bounds;
364                                 maximized = true;
365                         }
366                 }
367
368                 private Point NewLocation (Message m)
369                 {
370                         int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
371                         int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
372                         int x_move = x - start.X;
373                         int y_move = y - start.Y;
374
375                         return new Point (form.Left + x_move, form.Top + y_move);
376                 }
377
378                 private Point MouseMove (Message m)
379                 {
380                         int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
381                         int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
382                         int x_move = x - start.X;
383                         int y_move = y - start.Y;
384
385                         return new Point (x_move, y_move);
386                 }
387
388                 private void DrawVirtualPosition ()
389                 {
390                         ClearVirtualPosition ();
391
392                         XplatUI.DrawReversibleRectangle (mdi_container.Handle, virtual_position, 2);
393                         prev_virtual_position = virtual_position;
394                 }
395
396                 private void ClearVirtualPosition ()
397                 {
398                         if (prev_virtual_position != Rectangle.Empty)
399                                 XplatUI.DrawReversibleRectangle (mdi_container.Handle,
400                                                 prev_virtual_position, 2);
401                         prev_virtual_position = Rectangle.Empty;
402                 }
403
404                 private FormPos FormPosForCoords (int x, int y)
405                 {
406                         if (y < TitleBarHeight + BorderWidth) {
407
408                                 if (y > BorderWidth && x > BorderWidth &&
409                                                 x < form.Width - BorderWidth)
410                                         return FormPos.TitleBar;
411
412                                 if (x < BorderWidth || (x < 20 && y < BorderWidth))
413                                         return FormPos.TopLeft;
414
415                                 if (x > form.Width - BorderWidth ||
416                                         (x > form.Width - 20 && y < BorderWidth))
417                                         return FormPos.TopRight;
418
419                                 if (y < BorderWidth)
420                                         return FormPos.Top;
421
422                         } else if (y > form.Height - 20) {
423
424                                 if (x < BorderWidth ||
425                                                 (x < 20 && y > form.Height - BorderWidth))
426                                         return FormPos.BottomLeft;
427
428                                 if (x > form.Width - BorderWidth ||
429                                                 (x > form.Width - 20 &&
430                                                  y > form.Height - BorderWidth))
431                                         return FormPos.BottomRight;
432
433                                 if (y > form.Height - BorderWidth)
434                                         return FormPos.Bottom;
435
436
437                         } else if (x < BorderWidth) {
438                                 return FormPos.Left;
439                         } else if (x > form.Width - BorderWidth) {
440                                 return FormPos.Right;
441                         }
442
443                         return FormPos.None;
444                 }
445         }
446
447 }
448