2007-03-19 Chris Toshok <toshok@ximian.com>
[mono-project.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / SizeGrip.cs
blobafbdc5a242628d4c448c4945a6565edb9205929d
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.
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.
20 // Copyright (c) 2005 Novell, Inc.
22 // Authors:
23 // Jackson Harper (jackson@ximian.com)
25 using System;
26 using System.Drawing;
28 namespace System.Windows.Forms {
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
44 #region Constructors
45 public SizeGrip (Control CapturedControl)
47 this.Cursor = Cursors.SizeNWSE;
48 enabled = true;
49 fill_background = true;
50 this.Size = GetDefaultSize ();
51 this.CapturedControl = CapturedControl;
53 #endregion // Constructors
55 #region Properties
56 public bool FillBackground {
57 get {
58 return fill_background;
60 set {
61 fill_background = value;
65 public bool Virtual {
66 get {
67 return is_virtual;
69 set {
70 if (is_virtual == value)
71 return;
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);
90 public Control CapturedControl {
91 get {
92 return captured_control;
94 set {
95 captured_control = value;
99 #endregion // Properties
101 #region Methods
102 static internal Size GetDefaultSize () {
103 return new Size (SystemInformation.VerticalScrollBarWidth, SystemInformation.HorizontalScrollBarHeight);
106 static internal Rectangle GetDefaultRectangle (Control Parent)
108 Size size = GetDefaultSize ();
109 return new Rectangle (Parent.ClientSize.Width - size.Width, Parent.ClientSize.Height - size.Height, size.Width, size.Height);
112 private void HandleResize (object sender, EventArgs e)
114 Control ctrl = (Control) sender;
115 ctrl.Invalidate (last_painted_area);
118 private void HandleEnabledChanged (object sender, EventArgs e)
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;
128 if (is_virtual) {
129 if (CapturedControl != null)
130 CapturedControl.Cursor = cursor;
131 } else {
132 this.Cursor = cursor;
134 ctrl.Invalidate (GetDefaultRectangle (ctrl));
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)
142 if (Visible) {
143 Control destination = (Control) sender;
144 Graphics gr = e.Graphics;
145 Rectangle rect = GetDefaultRectangle (destination);
147 if (!is_virtual || fill_background) {
148 gr.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorControl), rect);
150 if (enabled) {
151 ControlPaint.DrawSizeGrip (gr, BackColor, rect);
153 last_painted_area = rect;
157 private void HandleMouseCaptureChanged (object sender, EventArgs e)
159 Control ctrl = (Control) sender;
160 if (captured && !ctrl.Capture) {
161 captured = false;
162 CapturedControl.Size = new Size (window_w, window_h);
166 internal void HandleMouseDown (object sender, MouseEventArgs e)
168 if (enabled) {
169 Control ctrl = (Control)sender;
170 if (!GetDefaultRectangle (ctrl).Contains (e.X, e.Y)) {
171 return;
174 ctrl.Capture = true;
175 captured = true;
176 capture_point = Control.MousePosition;
178 window_w = CapturedControl.Width;
179 window_h = CapturedControl.Height;
183 internal void HandleMouseMove (object sender, MouseEventArgs e)
185 Control ctrl = (Control) sender;
186 Rectangle rect = GetDefaultRectangle (ctrl);
188 if (rect.Contains (e.X, e.Y)) {
189 ctrl.Cursor = Cursors.SizeNWSE;
190 } else {
191 ctrl.Cursor = Cursors.Default;
194 if (captured) {
195 int delta_x;
196 int delta_y;
197 Point current_point;
199 current_point = Control.MousePosition;
201 delta_x = current_point.X - capture_point.X;
202 delta_y = current_point.Y - capture_point.Y;
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;
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;
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;
220 if (new_size != parent.Size) {
221 parent.Size = new_size;
226 internal void HandleMouseUp (object sender, MouseEventArgs e)
228 if (captured) {
229 Control ctrl = (Control) sender;
230 captured = false;
231 ctrl.Capture = false;
232 ctrl.Invalidate (last_painted_area);
234 if (Parent is ScrollableControl) {
235 ((ScrollableControl)Parent).UpdateSizeGripVisible ();
237 if (hide_pending) {
238 Hide();
239 hide_pending = false;
245 protected override void SetVisibleCore(bool value) {
246 if (Capture) {
247 if (value == false) {
248 hide_pending = true;
249 } else {
250 hide_pending = false;
252 return;
254 base.SetVisibleCore (value);
257 protected override void OnPaint (PaintEventArgs pe)
259 HandlePaint (this, pe);
260 base.OnPaint (pe);
263 #if NET_2_0
264 protected override void OnMouseCaptureChanged (EventArgs e)
265 #else
266 internal override void OnMouseCaptureChanged (EventArgs e)
267 #endif
269 base.OnMouseCaptureChanged (e);
270 HandleMouseCaptureChanged (this, e);
273 protected override void OnEnabledChanged (EventArgs e)
275 base.OnEnabledChanged (e);
276 HandleEnabledChanged (this, e);
279 protected override void OnMouseDown (MouseEventArgs e)
281 HandleMouseDown (this, e);
284 protected override void OnMouseMove(MouseEventArgs e)
286 HandleMouseMove (this, e);
289 protected override void OnMouseUp (MouseEventArgs e)
291 HandleMouseUp (this, e);
293 #endregion // Methods