[Mono-winforms-list] [Fwd: new Control.Autosize Patch]

Jonathan Pobst monkey at jpobst.com
Mon Apr 9 15:33:08 EDT 2007


Hey Noah, sorry this didn't go out quicker.  Dunno why the list is 
eating it (or if it's just me that isn't getting it).

It's good work, but there's some things that need to be fixed up before 
I can commit it.

We have to match the MS public API, so the following things are issues:
- Control.GetAutoSizeMode must be protected.
- We can't have the overrides: Button.AutoSize, Button.GetPreferredSize, 
GroupBox.GetPreferredSize, or UserControl.GetPreferredSize.
(Check out the ButtonBase class.)

Other issues:
- Don't call the DefaultLayout.LayoutAutoSizedChildren method on 
!NET_2_0.  (Since there doesn't seem to be any work done in there for 1.1.)
- Remove the MonoTODO on Control.AutoSize.  Since it's implemented now, 
there's no real reason to have it.
- In DefaultLayout.LayoutAutoSizedChildren, use BoundsSpecified.None in 
your SetBounds call. 
(http://jpobst.blogspot.com/2007/04/setboundscore.html)
- What is the purpose for Control.GetPreferredSizeCore?
- Please write a ChangeLog entry summarizes the changes.

I think most of the patch is fine.  No old tests broke, and your new 
tests pass.  It just needs a little cleaning to make sure we match MS's 
public API.  :-)

Thanks!
Jon



Jackson Harper wrote:
> Since this didn't get delivered to everyone on the list.  Just
> re-posting.
> 
> Love,
> Jackson
> 
> 
> -------- Forwarded Message --------
> From: Stefan Noack <noackstefan at googlemail.com>
> To: mono-winforms-list <mono-winforms-list at lists.ximian.com>
> Subject: [Mono-winforms-list] new Control.Autosize Patch
> Date: Mon, 9 Apr 2007 18:02:27 +0200
> 
> hi
> 
> here it is. related to a newer revision and without non-autosize stuff.
> (let me recheck this .... yes it is ok :) it also contains a new
> testcase.
> 
> best, noah
> _______________________________________________
> Mono-winforms-list maillist  -  Mono-winforms-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-winforms-list
> 
> 
> ------------------------------------------------------------------------
> 
> Index: mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs
> ===================================================================
> --- mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs	(Revision 75536)
> +++ mcs/class/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs	(Arbeitskopie)
> @@ -3,6 +3,7 @@
>  //
>  // Authors:
>  //      Ritvik Mayank (mritvik at novell.com)
> +//		Stefan Noack (noackstefan at googlemail.com)
>  //
>  
>  using System;
> @@ -24,7 +25,137 @@
>  	[TestFixture]
>  	public class ControlTest
>  	{
> +		
> +#if NET_2_0
>  		[Test]
> +		public void AutoSizeTest ()
> +		{
> +			ControlAutoSizeTester c = new ControlAutoSizeTester (new Size (23, 17), AutoSizeMode.GrowAndShrink);
> +			
> +			Form f = new Form();
> +			f.Size = new Size (200, 200);
> +			c.Parent = f;
> +			f.Show();
> +			
> +			Size s = new Size (42, 42);
> +			c.Size = s;
> +			
> +			Point l = new Point (10, 10);
> +			c.Location = l;
> +			
> +			//Check wether normal size setting is OK
> +			Assert.AreEqual (s, c.Size, "#S1");
> +			
> +			//Check wether size remains without GetPreferredSize implemented even when AutoSize turned on.
> +			c.AutoSize = true;
> +			f.PerformLayout();
> +			Assert.AreEqual (s, c.Size, "#S2");
> +			
> +			//Simulate a Control implementing GetPreferredSize
> +			c.UseCustomPrefSize = true;
> +			f.PerformLayout();
> +			
> +			//Check wether size shrinks to preferred size
> +			Assert.AreEqual (c.CustomPrefSize, c.Size, "#S3");
> +			//Check wether Location stays constant
> +			Assert.AreEqual (l, c.Location, "#L1");
> +			
> +			//Check wether Dock is respected
> +			c.Dock = DockStyle.Bottom;
> +			Assert.AreEqual (f.ClientSize.Width, c.Width, "#D1");
> +			
> +			//Check wether size shrinks to preferred size again
> +			c.Dock = DockStyle.None;
> +			Assert.AreEqual (c.CustomPrefSize, c.Size, "#S4");
> +			
> +			//Check wether Anchor is respected for adjusting Locatioon
> +			c.Anchor = AnchorStyles.Bottom;
> +			f.Height += 50;
> +			Assert.AreEqual (l.Y + 50, c.Top, "#A1");
> +			//Check wether size is still OK
> +			Assert.AreEqual (c.CustomPrefSize, c.Size, "#S5");
> +			
> +			
> +			//just tidy up
> +			c.Anchor = AnchorStyles.Top | AnchorStyles.Left;
> +			c.Location = l;
> +			
> +			//Check wether shrinking to zero is possible 
> +			c.CustomPrefSize = new Size (0, 0);
> +			f.PerformLayout();
> +			Assert.AreEqual (c.CustomPrefSize, c.Size, "#S6");
> +			
> +			//Check wether MinimumSize is honored
> +			c.MinimumSize = new Size (10, 12);
> +			c.CustomPrefSize = new Size (5, 5);
> +			f.PerformLayout();
> +			Assert.AreEqual (c.MinimumSize, c.Size, "#S7");
> +			c.MinimumSize = new Size (0, 0);
> +			
> +			//Check wether MaximumSize is honored
> +			c.MaximumSize = new Size (100, 120); 
> +			c.CustomPrefSize = new Size (500, 500);
> +			f.PerformLayout();
> +			Assert.AreEqual (c.MaximumSize, c.Size, "#S8");
> +			
> +			//Check wether shrinking does not happen when GrowOnly
> +			c.AutoSize = false;
> +			s = new Size (23, 23);
> +			c.Size = s;
> +			c.CustomPrefSize = new Size (5, 5);
> +			c.AutoSizeMode = AutoSizeMode.GrowOnly;
> +			c.AutoSize = true;
> +			f.PerformLayout();
> +			Assert.AreEqual (s, c.Size, "#S9");
> +		}
> +		
> +		public class ControlAutoSizeTester : Control {
> +			
> +
> +			public ControlAutoSizeTester (Size customPrefSize, AutoSizeMode autoSizeMode)
> +			{
> +				custom_prefsize = customPrefSize;
> +				AutoSizeMode = autoSizeMode;
> +			}
> +			
> +			public AutoSizeMode AutoSizeMode {
> +				set {
> +					base.SetAutoSizeMode (value);
> +				}
> +			}
> +
> +			private bool use_custom_prefsize = false;
> +			public bool UseCustomPrefSize {
> +				set {
> +					use_custom_prefsize = value;
> +				}
> +			}
> +			
> +			private Size custom_prefsize;
> +			
> +			public Size CustomPrefSize {
> +				get {
> +					return custom_prefsize;
> +				}
> +				set {
> +					custom_prefsize = value;
> +				}
> +			}
> +			
> +			
> +			public override Size GetPreferredSize (Size proposedSize)
> +			{
> +				if (use_custom_prefsize) {
> +					return custom_prefsize;
> +				} else {	
> +					return base.GetPreferredSize(proposedSize);
> +				}
> +			}
> +			
> +		}
> +#endif
> +		
> +		[Test]
>  		public void InvokeTestParentHandle ()
>  		{
>  			Control child, parent;
> Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs
> ===================================================================
> --- mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs	(Revision 75536)
> +++ mcs/class/Managed.Windows.Forms/System.Windows.Forms/Button.cs	(Arbeitskopie)
> @@ -94,6 +94,30 @@
>  				dialog_result = value;
>  			}
>  		}
> +		
> +#if NET_2_0
> +
> +		//Propagate that we can AutoSize 
> +		public override bool AutoSize {
> +			get {
> +				return base.AutoSize;
> +			}
> +			set {
> +				base.AutoSize = value;
> +			}
> +		}
> +		
> +		public System.Windows.Forms.AutoSizeMode AutoSizeMode {
> +			set {
> +				base.SetAutoSizeMode (value);
> +			}
> +			get {
> +				return base.GetAutoSizeMode();
> +			}
> +		}
> +		
> +#endif 
> +		
>  		#endregion	// Public Instance Properties
>  
>  		#region Protected Instance Properties
> @@ -117,6 +141,28 @@
>  		public override string ToString() {
>  			return base.ToString() + ", Text: " + this.Text;
>  		}
> +		
> +#if NET_2_0
> +		public override Size GetPreferredSize (Size proposedSize)
> +		{
> +			
> +			Size retsize = new Size (0, 0);
> +			
> +			// Figure out where our text and image should go
> +			Rectangle text_rectangle;
> +			Rectangle image_rectangle;
> +
> +			ThemeEngine.Current.CalculateButtonTextAndImageLayout (this, out text_rectangle, out image_rectangle);
> +
> +			// FIXME: Image should also be respected of course - not only text - depending on how they are put together
> +			retsize.Width += text_rectangle.Width;
> +			retsize.Height += text_rectangle.Height;
> +			
> +			return retsize;
> +		}
> +		
> +#endif 
> +		
>  		#endregion	// Public Instance Methods
>  
>  		#region	Protected Instance Methods
> Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms/GroupBox.cs
> ===================================================================
> --- mcs/class/Managed.Windows.Forms/System.Windows.Forms/GroupBox.cs	(Revision 75536)
> +++ mcs/class/Managed.Windows.Forms/System.Windows.Forms/GroupBox.cs	(Arbeitskopie)
> @@ -196,9 +196,63 @@
>  			}
>  		}
>  
> -		#endregion //Public Properties
> +#if NET_2_0
>  
> +		//Propagate that we can AutoSize 
> +		public override bool AutoSize {
> +			get {
> +				return base.AutoSize;
> +			}
> +			set {
> +				base.AutoSize = value;
> +			}
> +		}
> +		
> +		public System.Windows.Forms.AutoSizeMode AutoSizeMode {
> +			set {
> +				base.SetAutoSizeMode (value);
> +			}
> +			get {
> +				return base.GetAutoSizeMode();
> +			}
> +		}
> +		
> +#endif 
> +		
> +		#endregion	// Public Instance Properties
> +
>  		#region Public Methods
> +		
> +#if NET_2_0
> +		public override Size GetPreferredSize (Size proposedSize)
> +		{
> +			Size retsize = new Size (0, 0);
> +			
> +			for (int i = Controls.Count - 1; i >= 0; i--) {
> +				Control child = Controls[i];
> +				
> +				if (child.Dock != DockStyle.Top 
> +				&& child.Dock != DockStyle.Bottom 
> +				&& child.Bounds.Right > retsize.Width)
> +					retsize.Width=child.Bounds.Right;
> +				
> +				if (child.Dock != DockStyle.Left 
> +				&& child.Dock != DockStyle.Right 
> +				&& child.Bounds.Bottom > retsize.Height)
> +					retsize.Height=child.Bounds.Bottom;
> +					
> +			}
> +			
> +			Rectangle display_r = DisplayRectangle;
> +			retsize.Width += Width - display_r.Width;
> +			retsize.Height += Height - display_r.Height;
> +			
> +			return retsize;
> +		}
> +		
> +#endif 
> +
> +		
>  		protected override void OnFontChanged (EventArgs e)
>  		{
>  			base.OnFontChanged (e);
> Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs
> ===================================================================
> --- mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs	(Revision 75536)
> +++ mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs	(Arbeitskopie)
> @@ -881,7 +881,7 @@
>  					owner.PerformLayout(ctrl, "Parent");
>  				}
>  			}
> -
> +			
>  			bool IList.IsFixedSize {
>  				get {
>  					return false;
> @@ -2028,7 +2028,6 @@
>  			}
>  		}
>  			
> -		// XXX: Implement me!
>  		bool auto_size;
>  		
>  		[RefreshProperties (RefreshProperties.All)]
> @@ -2037,7 +2036,7 @@
>  		[Browsable (false)]
>  		[EditorBrowsable (EditorBrowsableState.Never)]
>  		[DefaultValue (false)]
> -		[MonoTODO("This method currently does nothing")]
> +		[MonoTODO("This method now works. (Done by the LayoutEngine.) However, derived classes supposed to provide AutoSize must implement their AutoSize habits by overriding GetPreferredSize to complete this functionality")]
>  		public virtual bool AutoSize {
>  			get { return auto_size; }
>  			set {
> @@ -2048,6 +2047,18 @@
>  			}
>  		}
>  		
> +		private AutoSizeMode auto_size_mode = AutoSizeMode.GrowOnly;
> +		
> +		protected void SetAutoSizeMode (AutoSizeMode mode)
> +		{
> +			auto_size_mode = mode;
> +		}
> +		
> +		internal AutoSizeMode GetAutoSizeMode () 
> +		{
> +			return auto_size_mode;
> +		}
> +		
>  #if NET_2_0
>  		[AmbientValue ("{Width=0, Height=0}")]
>  #else
> @@ -3485,7 +3496,7 @@
>  #if NET_2_0
>  		[EditorBrowsable (EditorBrowsableState.Advanced)]
>  		public virtual Size GetPreferredSize (Size proposedSize) {
> -			Size retsize = this.explicit_bounds.Size;
> +			Size retsize = GetPreferredSizeCore(proposedSize);
>  			
>  			// If we're bigger than the MaximumSize, fix that
>  			if (this.maximum_size.Width != 0 && retsize.Width > this.maximum_size.Width)
> @@ -3501,6 +3512,11 @@
>  				
>  			return retsize;
>  		}
> +		
> +		internal virtual Size GetPreferredSizeCore (Size proposedSize) {
> +			return this.explicit_bounds.Size;
> +		}
> +		
>  #endif
>  
>  		public void Hide() {
> Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms/UserControl.cs
> ===================================================================
> --- mcs/class/Managed.Windows.Forms/System.Windows.Forms/UserControl.cs	(Revision 75536)
> +++ mcs/class/Managed.Windows.Forms/System.Windows.Forms/UserControl.cs	(Arbeitskopie)
> @@ -68,8 +68,56 @@
>  				base.Text = value;
>  			}
>  		}
> +
> +#if NET_2_0
> +
> +		//Propagate that we can AutoSize 
> +		public override bool AutoSize {
> +			get {
> +				return base.AutoSize;
> +			}
> +			set {
> +				base.AutoSize = value;
> +			}
> +		}
> +		
> +		public System.Windows.Forms.AutoSizeMode AutoSizeMode {
> +			set {
> +				base.SetAutoSizeMode (value);
> +			}
> +			get {
> +				return base.GetAutoSizeMode();
> +			}
> +		}
> +		
> +#endif 
> +		
>  		#endregion	// Public Instance Properties
>  
> +#if NET_2_0
> +		public override Size GetPreferredSize (Size proposedSize)
> +		{
> +			Size retsize = new Size (0, 0);
> +			
> +			for (int i = Controls.Count - 1; i >= 0; i--) {
> +				Control child = Controls[i];
> +				
> +				if (child.Dock != DockStyle.Top 
> +				&& child.Dock != DockStyle.Bottom 
> +				&& child.Bounds.Right > retsize.Width)
> +					retsize.Width=child.Bounds.Right;
> +				
> +				if (child.Dock != DockStyle.Left 
> +				&& child.Dock != DockStyle.Right 
> +				&& child.Bounds.Bottom > retsize.Height)
> +					retsize.Height=child.Bounds.Bottom;
> +					
> +			}
> +			return retsize;
> +		}
> +		
> +#endif 
> +
>  		#region Protected Instance Methods
>  		[EditorBrowsable(EditorBrowsableState.Advanced)]
>  		protected override void OnCreateControl() {
> @@ -96,6 +144,7 @@
>  		protected override void WndProc(ref Message m) {
>  			base.WndProc(ref m);
>  		}
> +		
>  		#endregion	// Protected Instance Methods
>  
>  		#region Protected Properties
> @@ -110,6 +159,7 @@
>  		}
>  #endif
>  		#endregion
> +
>  		#region Events
>  		static object LoadEvent = new object ();
>  
> Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms/ContainerControl.cs
> ===================================================================
> --- mcs/class/Managed.Windows.Forms/System.Windows.Forms/ContainerControl.cs	(Revision 75536)
> +++ mcs/class/Managed.Windows.Forms/System.Windows.Forms/ContainerControl.cs	(Arbeitskopie)
> @@ -334,15 +334,19 @@
>  				return null;
>  			}
>  		}
> +
> +		
>  		#endregion	// Public Instance Properties
>  
> +				
> +
>  		#region Protected Instance Methods
>  		protected override CreateParams CreateParams {
>  			get {
>  				return base.CreateParams;
>  			}
>  		}
> -		#endregion	// Public Instance Methods
> +		#endregion	// Protected Instance Methods
>  
>  		#region Public Instance Methods
>  		[MonoTODO]
> @@ -359,6 +363,7 @@
>  		bool IContainerControl.ActivateControl(Control control) {
>  			return Select(control);
>  		}
> +		
>  		#endregion	// Public Instance Methods
>  
>  		#region Protected Instance Methods
> 
> Index: mcs/class/Managed.Windows.Forms/System.Windows.Forms.Layout/DefaultLayout.cs
> ===================================================================
> --- mcs/class/Managed.Windows.Forms/System.Windows.Forms.Layout/DefaultLayout.cs	(Revision 75536)
> +++ mcs/class/Managed.Windows.Forms/System.Windows.Forms.Layout/DefaultLayout.cs	(Arbeitskopie)
> @@ -24,6 +24,7 @@
>  //
>  // Authors:
>  //	Jonathan Pobst (monkey at jpobst.com)
> +//  Stefan Noack (noackstefan at googlemail.com)
>  //
>  
>  using System;
> @@ -111,14 +112,14 @@
>  				left = child.Left;
>  				top = child.Top;
>  				
> -#if NET_2_0
> -				Size preferredsize = child.PreferredSize;
> -				width = preferredsize.Width;
> -				height = preferredsize.Height;
> -#else
> +//#if NET_2_0
> +//				Size preferredsize = child.PreferredSize;
> +//				width = preferredsize.Width;
> +//				height = preferredsize.Height;							
> +//#else
>  				width = child.Width;
>  				height = child.Height;
> -#endif
> +//#endif
>  
>  				if ((anchor & AnchorStyles.Right) != 0) {
>  					if ((anchor & AnchorStyles.Left) != 0)
> @@ -154,7 +155,65 @@
>  				child.SetBounds (left, top, width, height, BoundsSpecified.None);
>  			}
>  		}
> +		
> +		void LayoutAutoSizedChildren (Control parent, Control[] controls)
> +		{
> +			
> +			for (int i = 0; i < controls.Length; i++) {
> +				int left;
> +				int top;
> +				int width;
> +				int height;
>  
> +				Control child = controls[i];
> +#if NET_2_0
> +				if (!child.VisibleInternal
> +				    || child.ControlLayoutType == Control.LayoutType.Dock
> +				    || !child.AutoSize)
> +					continue;
> +
> +
> +				left = child.Left;
> +				top = child.Top;
> +				
> +
> +				Size preferredsize = child.PreferredSize;
> +				
> +				if (child.GetAutoSizeMode() == AutoSizeMode.GrowAndShrink) {
> +					width = preferredsize.Width;
> +					height = preferredsize.Height;
> +				} else {
> +					width = child.Width;
> +					height = child.Height;
> +					if (preferredsize.Width > width)
> +						width = preferredsize.Width;
> +					if (preferredsize.Height > height)
> +						height = preferredsize.Height;
> +						
> +				}
> +			
> +				
> +				
> +				// Sanity
> +				if (width < child.MinimumSize.Width)
> +					width = child.MinimumSize.Width;
> +
> +				if (height < child.MinimumSize.Height)
> +					height = child.MinimumSize.Height;
> +
> +				
> +				if (child.MaximumSize.Width != 0 && width > child.MaximumSize.Width)
> +					width = child.MaximumSize.Width;
> +
> +				if (child.MaximumSize.Height != 0 && height > child.MaximumSize.Height)
> +					height = child.MaximumSize.Height;
> +
> +				child.SetBounds (left, top, width, height);
> +#endif
> +
> +			}
> +		}
> +
>  		public override bool Layout (object container, LayoutEventArgs args)
>  		{
>  			Control parent = container as Control;
> @@ -163,6 +222,7 @@
>  
>  			LayoutDockedChildren (parent, controls);
>  			LayoutAnchoredChildren (parent, controls);
> +			LayoutAutoSizedChildren (parent, controls);
>  
>  			return false;
>  		}
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Mono-winforms-list maillist  -  Mono-winforms-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-winforms-list



More information about the Mono-winforms-list mailing list