Merge pull request #1275 from ranma42/fix-lib64
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / SizeGrip.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.
21 //
22 // Authors:
23 //      Jackson Harper (jackson@ximian.com)
24
25 using System;
26 using System.Drawing;
27
28 namespace System.Windows.Forms {
29
30         internal class SizeGrip : Control {
31                 #region Local Variables
32                 private Point   capture_point;
33                 private Control captured_control;
34                 private int     window_w;
35                 private int     window_h;
36                 private bool    hide_pending;
37                 private bool    captured;
38                 private bool    is_virtual; // If virtual the size grip is painted directly on the captured controls' surface.
39                 private bool    enabled;
40                 private bool    fill_background;
41                 private Rectangle       last_painted_area; // The last area that was painted (to know which area to invalidate when resizing).
42                 #endregion      // Local Variables
43
44                 #region Constructors
45                 public SizeGrip (Control CapturedControl)
46                 {
47                         this.Cursor = Cursors.SizeNWSE;
48                         enabled = true;
49                         fill_background = true;
50                         this.Size = GetDefaultSize ();
51                         this.CapturedControl = CapturedControl;
52                 }
53                 #endregion      // Constructors
54
55                 #region Properties
56                 public bool FillBackground {
57                         get {
58                                 return fill_background;
59                         }
60                         set {
61                                 fill_background = value;
62                         }
63                 }
64                 
65                 public bool Virtual {
66                         get { 
67                                 return is_virtual;
68                         }
69                         set {
70                                 if (is_virtual == value)        
71                                         return;
72                                         
73                                 is_virtual = value;
74                                 if (is_virtual) {
75                                         CapturedControl.MouseMove += new MouseEventHandler(HandleMouseMove);
76                                         CapturedControl.MouseUp += new MouseEventHandler(HandleMouseUp);
77                                         CapturedControl.MouseDown += new MouseEventHandler(HandleMouseDown);
78                                         CapturedControl.EnabledChanged += new EventHandler(HandleEnabledChanged);
79                                         CapturedControl.Resize += new EventHandler(HandleResize);
80                                 } else {
81                                         CapturedControl.MouseMove -= new MouseEventHandler (HandleMouseMove);
82                                         CapturedControl.MouseUp -= new MouseEventHandler (HandleMouseUp);
83                                         CapturedControl.MouseDown -= new MouseEventHandler (HandleMouseDown);
84                                         CapturedControl.EnabledChanged -= new EventHandler (HandleEnabledChanged);
85                                         CapturedControl.Resize -= new EventHandler (HandleResize);
86                                 }
87                         }
88                 }
89                 
90                 public Control CapturedControl {
91                         get {
92                                 return captured_control;
93                         }
94                         set {
95                                 captured_control = value;
96                         }
97                 }
98                 
99                 #endregion      // Properties
100
101                 #region Methods
102                 static internal Size GetDefaultSize () {
103                         return new Size (SystemInformation.VerticalScrollBarWidth, SystemInformation.HorizontalScrollBarHeight);
104                 }
105                 
106                 static internal Rectangle GetDefaultRectangle (Control Parent)
107                 {
108                         Size size = GetDefaultSize ();
109                         return new Rectangle (Parent.ClientSize.Width - size.Width, Parent.ClientSize.Height - size.Height, size.Width, size.Height);
110                 }
111                 
112                 private void HandleResize (object sender, EventArgs e)
113                 {
114                         Control ctrl = (Control) sender;
115                         ctrl.Invalidate (last_painted_area);
116                 }
117
118                 private void HandleEnabledChanged (object sender, EventArgs e)
119                 {
120                         Control ctrl = (Control) sender;
121                         enabled = ctrl.Enabled;
122                         Cursor cursor;
123                         if (enabled) {
124                                 cursor = Cursors.SizeNWSE;
125                         } else {
126                                 cursor = Cursors.Default;
127                         }
128                         if (is_virtual) {
129                                 if (CapturedControl != null)
130                                         CapturedControl.Cursor = cursor;
131                         } else {
132                                 this.Cursor = cursor;
133                         }
134                         ctrl.Invalidate (GetDefaultRectangle (ctrl));
135                         
136                 }
137
138                 // This method needs to be internal, since the captured control must be able to call
139                 // it. We can't use events to hook it up, since then the paint ordering won't be correct
140                 internal void HandlePaint (object sender, PaintEventArgs e)
141                 {
142                         if (Visible) {
143                                 Control destination = (Control) sender;
144                                 Graphics gr = e.Graphics;
145                                 Rectangle rect = GetDefaultRectangle (destination);
146                         
147                                 if (!is_virtual || fill_background) {
148                                         gr.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorControl), rect);
149                                 }
150                                 if (enabled) {
151                                         ControlPaint.DrawSizeGrip (gr, BackColor, rect);
152                                 }
153                                 last_painted_area = rect;
154                         }
155                 }
156
157                 private void HandleMouseCaptureChanged (object sender, EventArgs e)
158                 {
159                         Control ctrl = (Control) sender;
160                         if (captured && !ctrl.Capture) {
161                                 captured = false;
162                                 CapturedControl.Size = new Size (window_w, window_h);
163                         }
164                 }
165
166                 internal void HandleMouseDown (object sender, MouseEventArgs e)
167                 {
168                         if (enabled) {
169                                 Control ctrl = (Control)sender;
170                                 if (!GetDefaultRectangle (ctrl).Contains (e.X, e.Y)) {
171                                         return;
172                                 }
173                                 
174                                 ctrl.Capture = true;
175                                 captured = true;
176                                 capture_point = Control.MousePosition;
177
178                                 window_w = CapturedControl.Width;
179                                 window_h = CapturedControl.Height;
180                         }
181                 }
182
183                 internal void HandleMouseMove (object sender, MouseEventArgs e)
184                 {
185                         Control ctrl = (Control) sender;
186                         Rectangle rect = GetDefaultRectangle (ctrl);
187                         
188                         if (rect.Contains (e.X, e.Y)) {
189                                 ctrl.Cursor = Cursors.SizeNWSE;
190                         } else {
191                                 ctrl.Cursor = Cursors.Default;
192                         }
193                         
194                         if (captured) {
195                                 int     delta_x;
196                                 int     delta_y;
197                                 Point   current_point;
198
199                                 current_point = Control.MousePosition;
200
201                                 delta_x = current_point.X - capture_point.X;
202                                 delta_y = current_point.Y - capture_point.Y;
203
204                                 Control parent = CapturedControl;
205                                 Form form_parent = parent as Form;
206                                 Size new_size = new Size (window_w + delta_x, window_h + delta_y);
207                                 Size max_size = form_parent != null ? form_parent.MaximumSize : Size.Empty;
208                                 Size min_size = form_parent != null ? form_parent.MinimumSize : Size.Empty;
209                                 
210                                 if (new_size.Width > max_size.Width && max_size.Width > 0)
211                                         new_size.Width = max_size.Width;
212                                 else if (new_size.Width < min_size.Width)
213                                         new_size.Width = min_size.Width;
214                                 
215                                 if (new_size.Height > max_size.Height && max_size.Height > 0)
216                                         new_size.Height = max_size.Height;
217                                 else if (new_size.Height < min_size.Height)
218                                         new_size.Height = min_size.Height;
219
220                                 if (new_size != parent.Size) {
221                                         parent.Size = new_size;
222                                 }
223                         }
224                 }
225
226                 internal void HandleMouseUp (object sender, MouseEventArgs e)
227                 {
228                         if (captured) {
229                                 Control ctrl = (Control) sender;
230                                 captured = false;
231                                 ctrl.Capture = false;
232                                 ctrl.Invalidate (last_painted_area);
233                                 
234                                 if (Parent is ScrollableControl) {
235                                         ((ScrollableControl)Parent).UpdateSizeGripVisible ();
236                                 }
237                                 if (hide_pending) {
238                                         Hide();
239                                         hide_pending = false;
240                                 }
241                         }
242                 }
243
244
245                 protected override void SetVisibleCore(bool value) {
246                         if (Capture) {
247                                 if (value == false) {
248                                         hide_pending = true;
249                                 } else {
250                                         hide_pending = false;
251                                 }
252                                 return;
253                         }
254                         base.SetVisibleCore (value);
255                 }
256
257                 protected override void OnPaint (PaintEventArgs pe)
258                 {
259                         HandlePaint (this, pe);
260                         base.OnPaint (pe);
261                 }
262
263                 protected override void OnMouseCaptureChanged (EventArgs e)
264                 {
265                         base.OnMouseCaptureChanged (e);
266                         HandleMouseCaptureChanged (this, e);
267                 }
268
269                 protected override void OnEnabledChanged (EventArgs e)
270                 {
271                         base.OnEnabledChanged (e);
272                         HandleEnabledChanged (this, e);
273                 }
274                 
275                 protected override void OnMouseDown (MouseEventArgs e)
276                 {
277                         HandleMouseDown (this, e);
278                 }
279                 
280                 protected override void OnMouseMove(MouseEventArgs e)
281                 {
282                         HandleMouseMove (this, e);
283                 }
284
285                 protected override void OnMouseUp (MouseEventArgs e)
286                 {
287                         HandleMouseUp (this, e);
288                 }
289                 #endregion      // Methods
290         }
291 }
292
293