hi

i'm just sending this again because it seems like it wasn't posted to the
list (i didn't receive it). sorry if i'm wrong. can someone review the patch
then? ;-)

thanks noah

---------- Forwarded message ----------
From: Stefan Noack <[EMAIL PROTECTED]>
Date: 28.03.2007 20:08
Subject: Fwd: [Patch] Control.AutoSize
To: mono-winforms-list <[email protected]>

hi there

i have created this patch providing baisc autosize features. the default
layout engine has been extended to layouting autosized controls according to
their GetPreferredSize() return value. however the controls must override
this function to produce correct behaviour. UserControl currently tries to
provide enough space for all children, GroupBox should do the same
respecting its border and Button currently is producing rubbish when asked
for its preferred size. i have written a NUnit test for Control to ensure
that the layout engine correctly uses the preferred size honoring dock,
anchor, minimum and maximum sizes. this test passes under microsofts runtime
and under mono. tests for each control's autosize behaviour are still
missing. i hope this patch is helpful. it also contains minor extensions of
TabControl to provide accessing the tab pages by key.
the patch is attached after this message

greetz to all code monkeys :-(|)
noah
Index: class/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs
===================================================================
--- class/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs	(Revision 74926)
+++ class/Managed.Windows.Forms/Test/System.Windows.Forms/ControlTest.cs	(Arbeitskopie)
@@ -3,6 +3,7 @@
 //
 // Authors:
 //      Ritvik Mayank ([EMAIL PROTECTED])
+//		Stefan Noack ([EMAIL PROTECTED])
 //
 
 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: class/Managed.Windows.Forms/System.Windows.Forms/Button.cs
===================================================================
--- class/Managed.Windows.Forms/System.Windows.Forms/Button.cs	(Revision 74926)
+++ 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: class/Managed.Windows.Forms/System.Windows.Forms/GroupBox.cs
===================================================================
--- class/Managed.Windows.Forms/System.Windows.Forms/GroupBox.cs	(Revision 74926)
+++ 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: class/Managed.Windows.Forms/System.Windows.Forms/Control.cs
===================================================================
--- class/Managed.Windows.Forms/System.Windows.Forms/Control.cs	(Revision 74926)
+++ class/Managed.Windows.Forms/System.Windows.Forms/Control.cs	(Arbeitskopie)
@@ -874,7 +874,7 @@
 					owner.PerformLayout(ctrl, "Parent");
 				}
 			}
-
+			
 			bool IList.IsFixedSize {
 				get {
 					return false;
@@ -2014,7 +2014,6 @@
 			}
 		}
 			
-		// XXX: Implement me!
 		bool auto_size;
 		
 		[RefreshProperties (RefreshProperties.All)]
@@ -2023,7 +2022,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 {
@@ -2034,6 +2033,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
@@ -3446,7 +3457,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)
@@ -3462,6 +3473,11 @@
 				
 			return retsize;
 		}
+		
+		internal virtual Size GetPreferredSizeCore (Size proposedSize) {
+			return this.explicit_bounds.Size;
+		}
+		
 #endif
 
 		public void Hide() {
Index: class/Managed.Windows.Forms/System.Windows.Forms/UserControl.cs
===================================================================
--- class/Managed.Windows.Forms/System.Windows.Forms/UserControl.cs	(Revision 74926)
+++ 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,8 +144,10 @@
 		protected override void WndProc(ref Message m) {
 			base.WndProc(ref m);
 		}
+		
 		#endregion	// Protected Instance Methods
 
+		
 		#region Events
 		static object LoadEvent = new object ();
 
Index: class/Managed.Windows.Forms/System.Windows.Forms/ContainerControl.cs
===================================================================
--- class/Managed.Windows.Forms/System.Windows.Forms/ContainerControl.cs	(Revision 74926)
+++ 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: class/Managed.Windows.Forms/System.Windows.Forms/TabControl.cs
===================================================================
--- class/Managed.Windows.Forms/System.Windows.Forms/TabControl.cs	(Revision 74926)
+++ class/Managed.Windows.Forms/System.Windows.Forms/TabControl.cs	(Arbeitskopie)
@@ -1202,7 +1202,7 @@
 		#endregion	// Events
 
 
-		#region Class TaControl.ControlCollection
+		#region Class TabControl.ControlCollection
 		public new class ControlCollection : System.Windows.Forms.Control.ControlCollection {
 
 			private TabControl owner;
@@ -1240,7 +1240,7 @@
 		}
 		#endregion	// Class TabControl.ControlCollection
 
-		#region Class TabPage.TabPageCollection
+		#region Class TabControl.TabPageCollection
 		public class TabPageCollection	: IList, ICollection, IEnumerable {
 
 			private TabControl owner;
@@ -1290,6 +1290,21 @@
 					owner.SetTab (index, (TabPage) value);
 				}
 			}
+			
+#if NET_2_0
+			public virtual TabPage this [string key] {
+				get {
+					if (key != "") {
+						int index = IndexOfKey (key);
+						if (index >= 0) {
+							return owner.GetTab (index);
+						}
+					}
+					return null;							
+				}
+			}
+			
+#endif 
 
 			public void Add (TabPage page)
 			{
@@ -1297,6 +1312,21 @@
 					throw new ArgumentNullException ("Value cannot be null.");
 				owner.Controls.Add (page);
 			}
+			
+			public void Add (string text)
+			{
+				TabPage page = new TabPage();
+				page.Text = text;
+				Add (page);
+			}
+			
+			public void Add (string key, string text)
+			{
+				TabPage page = new TabPage();
+				page.Name = key;
+				page.Text = text;
+				Add (page);
+			}
 
 			public void AddRange (TabPage [] pages)
 			{
@@ -1327,6 +1357,18 @@
 				return owner.Controls.IndexOf (page);
 			}
 
+#if NET_2_0	
+			public int IndexOfKey (string key)
+			{
+				return owner.Controls.IndexOfKey (key);
+			}
+			
+			public bool ContainsKey (string key)
+			{
+				return owner.Controls.ContainsKey (key);
+			}
+#endif
+			
 			public void Remove (TabPage page)
 			{
 				owner.Controls.Remove (page);
@@ -1380,7 +1422,7 @@
 				Remove ((TabPage) value);
 			}
 		}
-		#endregion	// Class TabPage.TabPageCollection
+		#endregion	// Class TabControl.TabPageCollection
 	}
 }
 
Index: class/Managed.Windows.Forms/System.Windows.Forms.Layout/DefaultLayout.cs
===================================================================
--- class/Managed.Windows.Forms/System.Windows.Forms.Layout/DefaultLayout.cs	(Revision 74926)
+++ class/Managed.Windows.Forms/System.Windows.Forms.Layout/DefaultLayout.cs	(Arbeitskopie)
@@ -24,6 +24,7 @@
 //
 // Authors:
 //	Jonathan Pobst ([EMAIL PROTECTED])
+//  Stefan Noack ([EMAIL PROTECTED])
 //
 
 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);
 			}
 		}
+		
+		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  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list

Reply via email to