2007-08-28 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / FlowLayoutPanel.cs
index 3a1929885bc682119fc8b37ce8a4f8a36185c1ae..4008d98d6633703934e851e88a3c7a723124e333 100644 (file)
 using System.Windows.Forms.Layout;
 using System.ComponentModel;
 using System.Runtime.InteropServices;
+using System.Drawing;
 
 namespace System.Windows.Forms
 {
        [ComVisibleAttribute (true)]
        [ClassInterfaceAttribute (ClassInterfaceType.AutoDispatch)]
        [ProvideProperty ("FlowBreak", typeof (Control))]
-       [DefaultEvent ("Paint")]
+       [DefaultProperty ("FlowDirection")]
+       [Docking (DockingBehavior.Ask)]
+       [Designer ("System.Windows.Forms.Design.FlowLayoutPanelDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
        public class FlowLayoutPanel : Panel, IExtenderProvider
        {
                private FlowLayoutSettings settings;
 
                public FlowLayoutPanel () : base ()
                {
-                       settings = new FlowLayoutSettings (this);
-                       layout_engine = settings.LayoutEngine;
                }
 
                #region Properties
                [Localizable (true)]
                [DefaultValue (FlowDirection.LeftToRight)]
                public FlowDirection FlowDirection {
-                       get { return settings.FlowDirection; }
-                       set { settings.FlowDirection = value; }
+                       get { return LayoutSettings.FlowDirection; }
+                       set { LayoutSettings.FlowDirection = value; }
                }
 
                [LocalizableAttribute (true)]
                [DefaultValue (true)]
                public bool WrapContents {
-                       get { return settings.WrapContents; }
-                       set { settings.WrapContents = value; }
+                       get { return LayoutSettings.WrapContents; }
+                       set { LayoutSettings.WrapContents = value; }
                }
 
                public override LayoutEngine LayoutEngine {
-                       get { return layout_engine; }
+                       get { return this.LayoutSettings.LayoutEngine; }
                }
 
                internal FlowLayoutSettings LayoutSettings {
-                       get { return this.settings; }
+                       get { 
+                               if (this.settings == null)
+                                       this.settings = new FlowLayoutSettings ();
+                                       
+                               return this.settings;
+                       }
                }
                #endregion
 
                #region Public Methods
                [DefaultValue (false)]
-               //[DisplayName ("FlowBreak")]
+               [DisplayName ("FlowBreak")]
                public bool GetFlowBreak (Control control)
                {
-                       return settings.GetFlowBreak (control);
+                       return LayoutSettings.GetFlowBreak (control);
                }
 
+               [DisplayName ("FlowBreak")]
                public void SetFlowBreak (Control control, bool value)
                {
-                       settings.SetFlowBreak (control, value);
+                       LayoutSettings.SetFlowBreak (control, value);
                        this.PerformLayout (control, "FlowBreak");
                }               
                #endregion
                
                #region IExtenderProvider Members
-               public bool CanExtend (object extendee)
+               bool IExtenderProvider.CanExtend (object extendee)
                {
                        if (extendee is Control)
                                if ((extendee as Control).Parent == this)
@@ -96,6 +103,65 @@ namespace System.Windows.Forms
                        return false;
                }
                #endregion
+
+               #region Internal Methods
+               internal override Size GetPreferredSizeCore (Size proposedSize)
+               {
+                       int width = 0;
+                       int height = 0;
+                       bool horizontal = FlowDirection == FlowDirection.LeftToRight || FlowDirection == FlowDirection.RightToLeft;
+                       if (!WrapContents || (horizontal && proposedSize.Width == 0) || (!horizontal && proposedSize.Height == 0)) {
+                               foreach (Control control in Controls) {
+                                       Size control_preferred_size = control.PreferredSize;
+                                       Padding control_margin = control.Margin;
+                                       if (horizontal) {
+                                               width += control_preferred_size.Width + control_margin.Horizontal;
+                                               height = Math.Max (height, control_preferred_size.Height + control_margin.Vertical);
+                                       } else {
+                                               height += control_preferred_size.Height + control_margin.Vertical;
+                                               width = Math.Max (width, control_preferred_size.Width + control_margin.Horizontal);
+                                       }
+                               }
+                       } else {
+                               int size_in_flow_direction = 0;
+                               int size_in_other_direction = 0;
+                               int increase;
+                               foreach (Control control in Controls) {
+                                       Size control_preferred_size = control.PreferredSize;
+                                       Padding control_margin = control.Margin;
+                                       if (horizontal) {
+                                               increase = control_preferred_size.Width + control_margin.Horizontal;
+                                               if (size_in_flow_direction != 0 && size_in_flow_direction + increase >= proposedSize.Width) {
+                                                       width = Math.Max (width, size_in_flow_direction);
+                                                       size_in_flow_direction = 0;
+                                                       height += size_in_other_direction;
+                                                       size_in_other_direction = 0;
+                                               }
+                                               size_in_flow_direction += increase;
+                                               size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Height + control_margin.Vertical);
+                                       } else {
+                                               increase = control_preferred_size.Height + control_margin.Vertical;
+                                               if (size_in_flow_direction != 0 && size_in_flow_direction + increase >= proposedSize.Height) {
+                                                       height = Math.Max (height, size_in_flow_direction);
+                                                       size_in_flow_direction = 0;
+                                                       width += size_in_other_direction;
+                                                       size_in_other_direction = 0;
+                                               }
+                                               size_in_flow_direction += increase;
+                                               size_in_other_direction = Math.Max (size_in_other_direction, control_preferred_size.Width + control_margin.Horizontal);
+                                       }
+                               }
+                               if (horizontal) {
+                                       width = Math.Max (width, size_in_flow_direction);
+                                       height += size_in_other_direction;
+                               } else {
+                                       height = Math.Max (height, size_in_flow_direction);
+                                       width += size_in_other_direction;
+                               }
+                       }
+                       return new Size (width, height);
+               }
+               #endregion
        }
 }
 #endif