Switch to compiler-tester
[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 Button close_button;
18                 private Button maximize_button;
19                 private Button minimize_button;
20                 
21                 // moving windows
22                 private Point start;
23                 private State state;
24                 private FormPos sizing_edge;
25                 private Rectangle virtual_position;
26                 private Rectangle prev_bounds;
27                 private bool maximized;
28                 
29                 
30                 private enum State {
31                         Idle,
32                         Moving,
33                         Sizing,
34                 }
35
36                 [Flags]
37                 private enum FormPos {
38                         None,
39
40                         TitleBar = 1,
41
42                         Top = 2,
43                         Left = 4,
44                         Right = 8,
45                         Bottom = 16,
46
47                         TopLeft = Top | Left,
48                         TopRight = Top | Right,
49
50                         BottomLeft = Bottom | Left,
51                         BottomRight = Bottom | Right,
52
53                         AnyEdge = Top | Left | Right | Bottom,
54                 }
55
56                 public MdiChildContext (Form form)
57                 {
58                         titlebar_color = Color.FromArgb (255, 0, 0, 255);
59                         this.form = form;
60
61                         form.Paint += new PaintEventHandler (PaintWindowDecorations);
62
63                         minimize_button = new Button ();
64                         minimize_button.Bounds = new Rectangle (form.Width - 62,
65                                         BorderWidth + 2, 18, 22);
66                         minimize_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
67                         minimize_button.Paint += new PaintEventHandler (PaintButtonHandler);
68                         minimize_button.Click += new EventHandler (OnMinimizeHandler);
69                         
70                         maximize_button = new Button ();
71                         maximize_button.Bounds = new Rectangle (form.Width - 44,
72                                         BorderWidth + 2, 18, 22);
73                         maximize_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
74                         maximize_button.Paint += new PaintEventHandler (PaintButtonHandler);
75                         maximize_button.Click += new EventHandler (OnMaximizeHandler);
76                         
77                         close_button = new Button ();
78                         close_button.Bounds = new Rectangle (form.Width - 24,
79                                         BorderWidth + 2, 18, 22);
80                         close_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
81                         close_button.Paint += new PaintEventHandler (PaintButtonHandler);
82                         close_button.Click += new EventHandler (CloseButtonClicked);
83
84                         
85                         form.Controls.Add (close_button);
86                         form.Controls.Add (maximize_button);
87                         form.Controls.Add (minimize_button);
88                 }
89
90                 public bool HandleMessage (ref Message m)
91                 {
92                         switch ((Msg)m.Msg) {
93                                 //case Msg.WM_PAINT:
94                                 //DrawWindowDecorations (form.CreateGraphics ());
95                                 //break;
96
97                         case Msg.WM_LBUTTONDOWN:
98                                 return HandleLButtonDown (form, ref m);
99
100                         case Msg.WM_MOUSEMOVE:
101                                 return HandleMouseMove (form, ref m);
102                                  
103                         case Msg.WM_LBUTTONUP:
104                                 HandleLButtonUp (ref m);
105                                 break;
106                         }
107                         return false;
108                 }
109
110                 
111                 private bool HandleLButtonDown (Form form, ref Message m)
112                 {
113                         form.BringToFront ();
114
115                         int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
116                         int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
117                         FormPos pos = FormPosForCoords (x, y);
118
119                         start = new Point (x, y);
120                         virtual_position = form.Bounds;
121
122                         if (pos == FormPos.TitleBar) {
123                                 HandleTitleBarDown (x, y);
124                                 return true;
125                         }
126
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
136                         return true;
137                 }
138
139                 private void HandleTitleBarDown (int x, int y)
140                 {
141                         state = State.Moving;                        
142                         form.Capture = true;
143                 }
144
145                 private bool HandleMouseMove (Form form, ref Message m)
146                 {
147                         switch (state) {
148                         case State.Moving:
149                                 HandleWindowMove (m);
150                                 return true;
151                         case State.Sizing:
152                                 HandleSizing (m);
153                                 return true;
154                         }
155
156                         int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
157                         int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
158                         FormPos pos = FormPosForCoords (x, y);
159
160                         SetCursorForPos (pos);
161
162                         state = State.Idle;
163                         return false;
164                 }
165         
166                 private void SetCursorForPos (FormPos pos)
167                 {
168                         switch (pos) {
169                         case FormPos.TopLeft:
170                         case FormPos.BottomRight:
171                                 form.Cursor = Cursors.SizeNWSE;
172                                 break;
173                         case FormPos.TopRight:
174                         case FormPos.BottomLeft:
175                                 form.Cursor = Cursors.SizeNESW;
176                                 break;
177                         case FormPos.Top:
178                         case FormPos.Bottom:
179                                 form.Cursor = Cursors.SizeNS;
180                                 break;
181                         case FormPos.Left:
182                         case FormPos.Right:
183                                 form.Cursor = Cursors.SizeWE;
184                                 break;
185                         default:
186                                 form.Cursor = Cursors.Default;
187                                 break;
188                         }
189                 }
190         
191                 private void HandleWindowMove (Message m)
192                 {
193                         Point move = MouseMove (m);
194
195                         virtual_position.X = form.Left + move.X;
196                         virtual_position.Y = form.Top + move.Y;
197                         virtual_position.Width = form.Width;
198                         virtual_position.Height = form.Height;
199
200                         Graphics g = form.Parent.CreateGraphics ();
201                         DrawVirtualPosition (g);
202                 }
203
204                 private void HandleSizing (Message m)
205                 {
206                         Point move = MouseMove (m);
207                         Rectangle pos = virtual_position;
208                         int mw = MinTitleBarSize.Width + (BorderWidth * 2);
209                         int mh = MinTitleBarSize.Height + (BorderWidth * 2);
210                         
211                         if ((sizing_edge & FormPos.Top) != 0) {
212                                 int height = form.Height - move.Y;
213                                 if (height <= mh) {
214                                         move.Y += height - mh;
215                                         height = mh;
216                                 }
217                                 pos.Y = form.Top + move.Y;
218                                 pos.Height = height;
219                         } else if ((sizing_edge & FormPos.Bottom) != 0) {
220                                 int height = form.Height + move.Y;
221                                 if (height <= mh)
222                                         move.Y -= height - mh;
223                                 pos.Height = form.Height + move.Y;
224                         }
225
226                         if ((sizing_edge & FormPos.Left) != 0) {
227                                 int width = form.Width - move.X;
228                                 if (width <= mw) {
229                                         move.X += width - mw;
230                                         width = mw;
231                                 }
232                                 pos.X = form.Left + move.X;
233                                 pos.Width = width;
234                         } else if ((sizing_edge & FormPos.Right) != 0) {
235                                 int width = form.Width + move.X;
236                                 if (width <= mw)
237                                         move.X -= width - mw;
238                                 pos.Width = form.Width + move.X;
239                         }
240
241                         UpdateVP (pos);
242                 }
243
244                 private void UpdateVP (Rectangle r)
245                 {
246                         UpdateVP (r.X, r.Y, r.Width, r.Height);
247                 }
248
249                 private void UpdateVP (Point loc, int w, int h)
250                 {
251                         UpdateVP (loc.X, loc.Y, w, h);
252                 }
253
254                 private void UpdateVP (int x, int y, int w, int h)
255                 {
256                         virtual_position.X = x;
257                         virtual_position.Y = y;
258                         virtual_position.Width = w;
259                         virtual_position.Height = h;
260
261                         Graphics g = form.Parent.CreateGraphics ();
262                         DrawVirtualPosition (g);
263                 }
264
265                 private void HandleLButtonUp (ref Message m)
266                 {
267                         if (state == State.Idle)
268                                 return;
269
270                         form.Capture = false;
271
272                         // Clear the virtual position
273                         Graphics g = form.Parent.CreateGraphics ();
274                         g.Clear (form.Parent.BackColor);
275
276                         form.Bounds = virtual_position;
277                         state = State.Idle;
278                 }
279
280                 private void PaintWindowDecorations (object sender, PaintEventArgs pe)
281                 {
282                         Color color = titlebar_color;
283                         if (maximized)
284                                 color = ThemeEngine.Current.ColorButtonFace;
285                         pe.Graphics.FillRectangle (new SolidBrush (color),
286                                                 BorderWidth, BorderWidth,
287                                                 form.Width - BorderWidth, TitleBarHeight);
288
289                         if (form.Icon != null) {
290                                 pe.Graphics.DrawIcon (form.Icon, BorderWidth, BorderWidth);
291                         }
292
293                         Pen bp = new Pen (ThemeEngine.Current.ColorButtonFace,
294                                         BorderWidth);
295
296                         // HACK: kludge the borders around
297                         Rectangle border = form.ClientRectangle;
298                         border.X++;
299                         border.Y++;
300                         border.Width -= 4;
301                         border.Height -= 4;
302                         pe.Graphics.DrawRectangle (bp, border);
303
304                         Border3DStyle style = Border3DStyle.Raised | Border3DStyle.Bump;
305                         border = form.ClientRectangle;
306
307                         if (maximized) {
308                                 style = Border3DStyle.SunkenInner;
309                                 border.Y = TitleBarHeight + BorderWidth * 2;
310                                 border.Height -= TitleBarHeight;
311                         }
312                         
313                         ControlPaint.DrawBorder3D (pe.Graphics, border,
314                                         style,
315                                         Border3DSide.Left | Border3DSide.Right |
316                                         Border3DSide.Top | Border3DSide.Bottom);
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                 // For now just use a solid pen as it is 10 billion times
389                 // faster then using the hatch, and what we really need is invert
390                 private void DrawVirtualPosition (Graphics graphics)
391                 {                       
392                         Pen pen = new Pen (Color.Black, 3);
393
394                         graphics.Clear (form.Parent.BackColor);
395                         graphics.DrawRectangle (pen, virtual_position);
396                         pen.Dispose ();
397                 }
398
399                 private FormPos FormPosForCoords (int x, int y)
400                 {
401                         if (y < TitleBarHeight + BorderWidth) {
402
403                                 if (y > BorderWidth && x > BorderWidth &&
404                                                 x < form.Width - BorderWidth)
405                                         return FormPos.TitleBar;
406
407                                 if (x < BorderWidth || (x < 20 && y < BorderWidth))
408                                         return FormPos.TopLeft;
409
410                                 if (x > form.Width - BorderWidth ||
411                                         (x > form.Width - 20 && y < BorderWidth))
412                                         return FormPos.TopRight;
413
414                                 if (y < BorderWidth)
415                                         return FormPos.Top;
416
417                         } else if (y > form.Height - 20) {
418
419                                 if (x < BorderWidth ||
420                                                 (x < 20 && y > form.Height - BorderWidth))
421                                         return FormPos.BottomLeft;
422
423                                 if (x > form.Width - BorderWidth ||
424                                                 (x > form.Width - 20 &&
425                                                  y > form.Height - BorderWidth))
426                                         return FormPos.BottomRight;
427
428                                 if (y > form.Height - BorderWidth)
429                                         return FormPos.Bottom;
430
431
432                         } else if (x < BorderWidth) {
433                                 return FormPos.Left;
434                         } else if (x > form.Width - BorderWidth) {
435                                 return FormPos.Right;
436                         }
437
438                         return FormPos.None;
439                 }
440         }
441
442 }
443