2008-03-27 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / SplitContainer.cs
1 //
2 // SplitContainer.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 // Copyright (c) 2007 Ivan N. Zlatev
25 //
26 // Authors:
27 //      Jonathan Pobst (monkey@jpobst.com)
28 //      Ivan N. Zlatev (contact@i-nz.net)
29 //
30
31 #if NET_2_0
32 using System;
33 using System.Runtime.InteropServices;
34 using System.ComponentModel;
35 using System.Drawing;
36 using System.Drawing.Drawing2D;
37
38 namespace System.Windows.Forms
39 {
40         [ComVisibleAttribute (true)]
41         [ClassInterfaceAttribute (ClassInterfaceType.AutoDispatch)]
42         [DefaultEvent ("SplitterMoved")]
43         [Docking (DockingBehavior.AutoDock)]
44         [Designer ("System.Windows.Forms.Design.SplitContainerDesigner, " + Consts.AssemblySystem_Design)]
45         public class SplitContainer : ContainerControl
46         {
47                 #region Local Variables
48                 private FixedPanel fixed_panel;
49                 private Orientation orientation;
50
51                 private int splitter_increment;
52                 private Rectangle splitter_rectangle;
53                 private Rectangle splitter_rectangle_moving;
54                 private bool splitter_fixed;
55                 private bool splitter_dragging;
56                 private int splitter_prev_move;
57                 private Cursor restore_cursor;
58                 private double fixed_none_ratio;
59
60                 private SplitterPanel panel1;
61                 private bool panel1_collapsed;
62                 private int panel1_min_size;
63
64                 private SplitterPanel panel2;
65                 private bool panel2_collapsed;
66                 private int panel2_min_size;
67                 #endregion
68
69                 #region Public Events
70                 static object SplitterMovedEvent = new object ();
71                 static object SplitterMovingEvent = new object ();
72
73                 [Browsable (false)]
74                 [EditorBrowsable (EditorBrowsableState.Never)]
75                 public new event EventHandler AutoSizeChanged {
76                         add { base.AutoSizeChanged += value; }
77                         remove { base.AutoSizeChanged -= value; }
78                 }
79
80                 [Browsable (true)]
81                 [EditorBrowsable (EditorBrowsableState.Always)]
82                 public new event EventHandler BackgroundImageChanged {
83                         add { base.BackgroundImageChanged += value; }
84                         remove { base.BackgroundImageChanged -= value; }
85                 }
86
87                 [Browsable (false)]
88                 [EditorBrowsable (EditorBrowsableState.Never)]
89                 public new event EventHandler BackgroundImageLayoutChanged {
90                         add { base.BackgroundImageLayoutChanged += value; }
91                         remove { base.BackgroundImageLayoutChanged -= value; }
92                 }
93
94                 [Browsable (false)]
95                 [EditorBrowsable (EditorBrowsableState.Never)]
96                 public new event ControlEventHandler ControlAdded {
97                         add { base.ControlAdded += value; }
98                         remove { base.ControlAdded -= value; }
99                 }
100
101                 [Browsable (false)]
102                 [EditorBrowsable (EditorBrowsableState.Never)]
103                 public new event ControlEventHandler ControlRemoved {
104                         add { base.ControlRemoved += value; }
105                         remove { base.ControlRemoved -= value; }
106                 }
107
108                 [Browsable (false)]
109                 [EditorBrowsable (EditorBrowsableState.Never)]
110                 public new event EventHandler PaddingChanged {
111                         add { base.PaddingChanged += value; }
112                         remove { base.PaddingChanged -= value; }
113                 }
114                 
115                 public event SplitterEventHandler SplitterMoved {
116                         add { Events.AddHandler (SplitterMovedEvent, value); }
117                         remove { Events.RemoveHandler (SplitterMovedEvent, value); }
118                 }
119
120                 public event SplitterCancelEventHandler SplitterMoving {
121                         add { Events.AddHandler (SplitterMovingEvent, value); }
122                         remove { Events.RemoveHandler (SplitterMovingEvent, value); }
123                 }
124
125                 [Browsable (false)]
126                 [EditorBrowsable (EditorBrowsableState.Never)]
127                 public new event EventHandler TextChanged {
128                         add { base.TextChanged += value; }
129                         remove { base.TextChanged -= value; }
130                 }
131                 #endregion
132
133                 #region Public Constructors
134                 public SplitContainer ()
135                 {
136                         SetStyle (ControlStyles.SupportsTransparentBackColor, true);
137                         SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
138                         
139                         fixed_panel = FixedPanel.None;
140                         orientation = Orientation.Vertical;
141
142                         splitter_rectangle = new Rectangle (50, 0, 4, this.Height);
143                         splitter_increment = 1;
144                         splitter_prev_move = -1;
145                         restore_cursor = null;
146
147                         splitter_fixed = false;
148                         panel1_collapsed = false;
149                         panel2_collapsed = false;
150                         panel1_min_size = 25;
151                         panel2_min_size = 25;
152
153                         panel1 = new SplitterPanel (this);
154                         panel2 = new SplitterPanel (this);
155                         panel1.Size = new Size (50, 50);
156                         UpdateSplitter ();
157
158                         this.Controls.Add (panel2);
159                         this.Controls.Add (panel1);
160                 }
161                 #endregion
162
163                 #region Public Properties
164                 [Browsable (false)]
165                 [EditorBrowsable (EditorBrowsableState.Never)]
166                 [Localizable (true)]
167                 [DefaultValue (false)]
168                 public override bool AutoScroll {
169                         get { return base.AutoScroll; }
170                         set { base.AutoScroll = value; }
171                 }
172
173                 [Browsable (false)]
174                 [EditorBrowsable (EditorBrowsableState.Never)]
175                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
176                 new public Size AutoScrollMargin {
177                         get { return base.AutoScrollMargin; }
178                         set { base.AutoScrollMargin = value; }
179                 }
180
181                 [Browsable (false)]
182                 [EditorBrowsable (EditorBrowsableState.Never)]
183                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
184                 new public Size AutoScrollMinSize {
185                         get { return base.AutoScrollMinSize; }
186                         set { base.AutoScrollMinSize = value; }
187                 }
188
189                 [Browsable (false)]
190                 [DefaultValue ("{X=0,Y=0}")]
191                 [EditorBrowsable (EditorBrowsableState.Never)]
192                 public override Point AutoScrollOffset {
193                         get { return base.AutoScrollOffset; }
194                         set { base.AutoScrollOffset = value; }
195                 }
196
197                 [Browsable (false)]
198                 [EditorBrowsable (EditorBrowsableState.Never)]
199                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
200                 new public Point AutoScrollPosition {
201                         get { return base.AutoScrollPosition; }
202                         set { base.AutoScrollPosition = value; }
203                 }
204
205                 [Browsable (false)]
206                 [EditorBrowsable (EditorBrowsableState.Never)]
207                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
208                 public override bool AutoSize {
209                         get { return base.AutoSize; }
210                         set { base.AutoSize = value; }
211                 }
212
213                 [Browsable (true)]
214                 [EditorBrowsable (EditorBrowsableState.Always)]
215                 public override Image BackgroundImage {
216                         get { return base.BackgroundImage; }
217                         set { base.BackgroundImage = value; }
218                 }
219
220                 [Browsable (false)]
221                 [EditorBrowsable (EditorBrowsableState.Never)]
222                 public override ImageLayout BackgroundImageLayout {
223                         get { return base.BackgroundImageLayout; }
224                         set { base.BackgroundImageLayout = value; }
225                 }
226
227                 [Browsable (false)]
228                 public override BindingContext BindingContext {
229                         get { return base.BindingContext; }
230                         set { base.BindingContext = value; }
231                 }
232
233                 // MSDN says default is Fixed3D, creating a new SplitContainer says otherwise.
234                 [DefaultValue (BorderStyle.None)]
235                 [DispId (-504)]
236                 public BorderStyle BorderStyle {
237                         get { return panel1.BorderStyle; }
238                         set {
239                                 if (!Enum.IsDefined (typeof (BorderStyle), value))
240                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for BorderStyle", value));
241                                         
242                                 panel1.BorderStyle = value;
243                                 panel2.BorderStyle = value;
244                         }
245                 }
246
247                 [EditorBrowsable (EditorBrowsableState.Never)]
248                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
249                 new public ControlCollection Controls { get { return base.Controls; } }
250
251                 new public DockStyle Dock {
252                         get { return base.Dock; }
253                         set { base.Dock = value; }
254                 }
255
256                 [DefaultValue (FixedPanel.None)]
257                 public FixedPanel FixedPanel {
258                         get { return this.fixed_panel; }
259                         set {
260                                 if (!Enum.IsDefined (typeof (FixedPanel), value))
261                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for FixedPanel", value));
262
263                                 this.fixed_panel = value;
264                         }
265                 }
266
267                 [Localizable (true)]
268                 [DefaultValue (false)]
269                 public bool IsSplitterFixed {
270                         get { return splitter_fixed; }
271                         set { splitter_fixed = value; }
272                 }
273
274                 [Localizable (true)]
275                 [DefaultValue (Orientation.Vertical)]
276                 public Orientation Orientation {
277                         get { return this.orientation; }
278                         set {
279                                 if (!Enum.IsDefined (typeof (Orientation), value))
280                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for Orientation", value));
281
282                                 if (this.orientation != value) {
283                                         if (value == Orientation.Vertical) {
284                                                 splitter_rectangle.Width = splitter_rectangle.Height;
285                                                 splitter_rectangle.X = splitter_rectangle.Y;
286                                         } else {
287                                                 splitter_rectangle.Height = splitter_rectangle.Width;
288                                                 splitter_rectangle.Y = splitter_rectangle.X;
289                                         }
290
291                                         this.orientation = value;
292                                         this.UpdateSplitter ();
293                                 }
294                         }
295                 }
296
297                 [Browsable (false)]
298                 [EditorBrowsable (EditorBrowsableState.Never)]
299                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
300                 new public Padding Padding {
301                         get { return base.Padding; }
302                         set { base.Padding = value; }
303                 }
304
305                 [Localizable (false)]
306                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
307                 public SplitterPanel Panel1 { get { return this.panel1; } }
308
309                 [DefaultValue (false)]
310                 public bool Panel1Collapsed {
311                         get { return this.panel1_collapsed; }
312                         set {
313                                 if (panel1_collapsed != value) {
314                                         this.panel1_collapsed = value;
315                                         panel1.Visible = !value;
316                                         PerformLayout ();
317                                 }
318                         }
319                 }
320
321                 [Localizable (true)]
322                 [DefaultValue (25)]
323                 [RefreshProperties (RefreshProperties.All)]
324                 public int Panel1MinSize {
325                         get { return this.panel1_min_size; }
326                         set { 
327                                 this.panel1_min_size = value; 
328                         }
329                 }
330
331                 [Localizable (false)]
332                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
333                 public SplitterPanel Panel2 { get { return this.panel2; } }
334
335                 [DefaultValue (false)]
336                 public bool Panel2Collapsed {
337                         get { return this.panel2_collapsed; }
338                         set {
339                                 if (panel2_collapsed != value) {
340                                         this.panel2_collapsed = value;
341                                         panel2.Visible = !value;
342                                         PerformLayout ();
343                                 }
344                         }
345                 }
346
347                 [Localizable (true)]
348                 [DefaultValue (25)]
349                 [RefreshProperties (RefreshProperties.All)]
350                 public int Panel2MinSize {
351                         get { return this.panel2_min_size; }
352                         set { this.panel2_min_size = value; }
353                 }
354
355                 // MSDN says the default is 40, MS's implementation defaults to 50.
356                 [Localizable (true)]
357                 [DefaultValue (50)]
358                 [SettingsBindable (true)]
359                 public int SplitterDistance {
360                         get { 
361                                 if (orientation == Orientation.Vertical)
362                                         return this.splitter_rectangle.X;
363                                 else
364                                         return this.splitter_rectangle.Y;
365                         }
366                         set {
367                                 if (value < 0)
368                                         throw new ArgumentOutOfRangeException ();
369                                 if (orientation == Orientation.Vertical)
370                                         this.splitter_rectangle.X = value;
371                                 else
372                                         this.splitter_rectangle.Y = value;
373                                 UpdateSplitter ();
374                         }
375                 }
376
377                 [Localizable (true)]
378                 [DefaultValue (1)]
379                 [MonoTODO ("Not implemented.")]
380                 public int SplitterIncrement {
381                         get { return this.splitter_increment; }
382                         set { this.splitter_increment = value; }
383                 }
384
385                 [Browsable (false)]
386                 public Rectangle SplitterRectangle { get { return splitter_rectangle; } }
387
388                 [Localizable (true)]
389                 [DefaultValue (4)]
390                 public int SplitterWidth {
391                         get {
392                                 if (orientation == Orientation.Vertical)
393                                         return this.splitter_rectangle.Width;
394                                 else
395                                         return this.splitter_rectangle.Height;
396                         }
397                         set {
398                                 if (value < 1)
399                                         throw new ArgumentOutOfRangeException ();
400
401                                 if (orientation == Orientation.Vertical)
402                                         this.splitter_rectangle.Width = value;
403                                 else
404                                         this.splitter_rectangle.Height = value;
405                                 UpdateSplitter ();
406                         }
407                 }
408
409                 [DispId (-516)]
410                 [DefaultValue (true)]
411                 [MonoTODO ("Special focus semantics not implemented")]
412                 new public bool TabStop {
413                         get { return false; }
414                         set { }
415                 }
416
417                 [Browsable (false)]
418                 [EditorBrowsable (EditorBrowsableState.Never)]
419                 [Bindable (false)]
420                 public override string Text {
421                         get { return base.Text; }
422                         set { base.Text = value; }
423                 }
424                 #endregion
425
426                 #region Protected Properties
427                 protected override Size DefaultSize { get { return new Size (150, 100); } }
428                 #endregion
429
430                 #region Public Methods
431                 public void OnSplitterMoved (SplitterEventArgs e)
432                 {
433                         SplitterEventHandler eh = (SplitterEventHandler)(Events [SplitterMovedEvent]);
434                         if (eh != null)
435                                 eh (this, e);
436                 }
437
438                 public void OnSplitterMoving (SplitterCancelEventArgs e)
439                 {
440                         SplitterCancelEventHandler eh = (SplitterCancelEventHandler)(Events [SplitterMovingEvent]);
441                         if (eh != null)
442                                 eh (this, e);
443                 }
444                 #endregion
445
446                 #region Protected Methods
447                 [EditorBrowsable (EditorBrowsableState.Advanced)]
448                 protected override ControlCollection CreateControlsInstance ()
449                 {
450                         return new SplitContainerTypedControlCollection (this);
451                 }
452
453                 [MonoTODO ("Special focus semantics not implemented")]
454                 protected override void OnGotFocus (EventArgs e)
455                 {
456                         base.OnGotFocus (e);
457                 }
458
459                 protected override void OnKeyDown (KeyEventArgs e)
460                 {
461                         base.OnKeyDown (e);
462                 }
463
464                 protected override void OnKeyUp (KeyEventArgs e)
465                 {
466                         base.OnKeyUp (e);
467                 }
468
469                 protected override void OnLayout (LayoutEventArgs e)
470                 {
471                         UpdateLayout ();
472                         base.OnLayout (e);
473                 }
474
475                 protected override void OnLostFocus (EventArgs e)
476                 {
477                         base.OnLostFocus (e);
478                 }
479
480                 protected override void OnMouseCaptureChanged (EventArgs e)
481                 {
482                         base.OnMouseCaptureChanged (e);
483                 }
484                 
485                 protected override void OnMouseDown (MouseEventArgs e)
486                 {
487                         base.OnMouseDown (e);
488                         if (!splitter_fixed && SplitterHitTest (e.Location)) {
489                                 splitter_dragging = true;
490                                 SplitterBeginMove (e.Location);
491                         }
492                 }
493
494                 protected override void OnMouseLeave (EventArgs e)
495                 {
496                         base.OnMouseLeave (e);
497                         SplitterRestoreCursor ();
498                 }
499
500                 [EditorBrowsable (EditorBrowsableState.Advanced)]
501                 protected override void OnMouseMove (MouseEventArgs e)
502                 {
503                         base.OnMouseMove (e);
504
505                         if (splitter_dragging)
506                                 SplitterMove (e.Location);
507
508                         if (!splitter_fixed && SplitterHitTest (e.Location))
509                                 SplitterSetCursor (orientation);
510                         
511                 }
512
513                 protected override void OnMouseUp (MouseEventArgs e)
514                 {
515                         base.OnMouseUp (e);
516                         if (splitter_dragging) {
517                                 SplitterEndMove (e.Location, false);
518                                 SplitterRestoreCursor ();
519                                 splitter_dragging = false;
520                         }
521                 }
522                 
523                 protected override void OnPaint (PaintEventArgs e)
524                 {
525                         base.OnPaint (e);
526                 }
527
528                 [EditorBrowsable (EditorBrowsableState.Advanced)]
529                 protected override void OnRightToLeftChanged (EventArgs e)
530                 {
531                         base.OnRightToLeftChanged (e);
532                 }
533
534                 [MonoTODO ("Special focus semantics not implemented")]
535                 protected override bool ProcessDialogKey (Keys keyData)
536                 {
537                         return base.ProcessDialogKey (keyData);
538                 }
539
540                 [MonoTODO ("Special focus semantics not implemented")]
541                 protected override bool ProcessTabKey (bool forward)
542                 {
543                         return base.ProcessTabKey (forward);
544                 }
545
546                 [EditorBrowsable (EditorBrowsableState.Advanced)]
547                 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
548                 {
549                         base.ScaleControl (factor, specified);
550                 }
551                 
552                 [MonoTODO ("Special focus semantics not implemented")]
553                 protected override void Select (bool directed, bool forward)
554                 {
555                         base.Select (directed, forward);
556                 }
557
558                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
559                 {
560                         base.SetBoundsCore (x, y, width, height, specified);
561                 }
562
563                 protected override void WndProc (ref Message msg)
564                 {                       
565                         base.WndProc (ref msg);
566                 }
567                 #endregion
568                 
569                 #region Private Methods
570
571                 private bool SplitterHitTest (Point location)
572                 {
573                         if (location.X >= splitter_rectangle.X &&
574                                 location.X <= splitter_rectangle.X + splitter_rectangle.Width &&
575                                 location.Y >= splitter_rectangle.Y &&
576                                 location.Y <= splitter_rectangle.Y + splitter_rectangle.Height) {
577                                 return true;
578                         }
579                         return false;                              
580                 }
581
582                 private void SplitterBeginMove (Point location)
583                 {
584                         splitter_prev_move = orientation == Orientation.Vertical ? location.X : location.Y;
585                         splitter_rectangle_moving = splitter_rectangle;
586                 }
587
588                 private void SplitterMove (Point location)
589                 {
590
591                         XplatUI.DrawReversibleRectangle (this.Handle, splitter_rectangle_moving, 1);
592
593                         int currentMove = orientation == Orientation.Vertical ? location.X : location.Y;
594                         int delta = currentMove - splitter_prev_move;
595
596                         if (orientation == Orientation.Vertical) {
597                                         if (splitter_rectangle_moving.X + delta > this.panel1_min_size &&
598                                                 splitter_rectangle_moving.X + delta + splitter_rectangle_moving.Width < panel2.Location.X + (panel2.Width - this.panel2_min_size))
599                                                 splitter_rectangle_moving.X += delta;
600                         } else if (orientation == Orientation.Horizontal) {
601                                         if (splitter_rectangle_moving.Y + delta > this.panel1_min_size &&
602                                                 splitter_rectangle_moving.Y + delta + splitter_rectangle_moving.Height < panel2.Location.Y + (panel2.Height - this.panel2_min_size))
603                                                 splitter_rectangle_moving.Y += delta;
604                         }
605
606                         splitter_prev_move = currentMove;
607
608                         OnSplitterMoving (new SplitterCancelEventArgs (location.X, location.Y, 
609                                                                                                          splitter_rectangle.X, splitter_rectangle.Y));
610
611                         XplatUI.DrawReversibleRectangle (this.Handle, splitter_rectangle_moving, 1);
612                 }
613
614                 private void SplitterEndMove (Point location, bool cancel)
615                 {
616                         if (!cancel) {
617                                 splitter_rectangle = splitter_rectangle_moving;
618                                 UpdateSplitter ();
619                         }
620                         SplitterEventArgs args = new SplitterEventArgs (location.X, location.Y, 
621                                                                                                                         splitter_rectangle.X, splitter_rectangle.Y);
622                         OnSplitterMoved (args);
623                 }
624
625                 private void SplitterSetCursor (Orientation orientation)
626                 {
627                         if (restore_cursor == null)
628                                 restore_cursor = this.Cursor;
629                         this.Cursor = orientation == Orientation.Vertical ? Cursors.VSplit : Cursors.HSplit;
630                 }
631
632                 private void SplitterRestoreCursor ()
633                 {
634                         if (restore_cursor != null) {
635                                 this.Cursor = restore_cursor;
636                                 restore_cursor = null;
637                         }
638                 }
639
640                 private void UpdateSplitter ()
641                 {
642                         this.SuspendLayout ();
643                         panel1.SuspendLayout ();
644                         panel2.SuspendLayout ();
645
646                         if (panel1_collapsed) {
647                                 panel2.Size = this.Size;
648                                 panel2.Location = new Point (0, 0);
649                         } else if (panel2_collapsed) {
650                                 panel1.Size = this.Size;
651                                 panel1.Location = new Point (0, 0);
652                         } else {
653                                 panel1.Location = new Point (0, 0);
654                                 if (orientation == Orientation.Vertical) {
655                                         splitter_rectangle.Y = 0;
656                                         panel1.InternalHeight = panel2.InternalHeight = this.Height;
657                                         panel1.InternalWidth = Math.Max (this.SplitterDistance, panel1_min_size);
658                                         panel2.Location = new Point (this.SplitterWidth + this.SplitterDistance, 0);
659                                         panel2.InternalWidth = Math.Max (this.Width - (this.SplitterWidth + this.SplitterDistance), panel2_min_size);
660                                         fixed_none_ratio = (double) this.Width / (double)this.SplitterDistance;
661                                 } else if (orientation == Orientation.Horizontal) {
662                                         splitter_rectangle.X = 0;
663                                         panel1.InternalWidth = panel2.InternalWidth = this.Width;
664                                         panel1.InternalHeight =  Math.Max (this.SplitterDistance, panel1_min_size);
665                                         panel2.Location = new Point (0, this.SplitterWidth + this.SplitterDistance);
666                                         panel2.InternalHeight =  Math.Max (this.Height - (this.SplitterWidth + this.SplitterDistance), panel2_min_size);
667                                         fixed_none_ratio = (double) this.Height / (double)this.SplitterDistance;
668                                 }
669                         }
670                         panel1.ResumeLayout ();
671                         panel2.ResumeLayout ();
672                         this.ResumeLayout ();
673                 }
674
675                 private void UpdateLayout ()
676                 {
677                         panel1.SuspendLayout ();
678                         panel2.SuspendLayout ();
679
680                         if (panel1_collapsed) {
681                                 panel2.Size = this.Size;
682                                 panel2.Location = new Point (0, 0);
683                         } else if (panel2_collapsed) {
684                                 panel1.Size = this.Size;
685                                 panel1.Location = new Point (0, 0);
686                         } else {
687                                 panel1.Location = new Point (0, 0);
688                                 if (orientation == Orientation.Vertical) {
689                                         panel1.Location = new Point (0, 0);
690                                         panel1.InternalHeight = panel2.InternalHeight = this.Height;
691                                         splitter_rectangle.Height = this.Height;
692         
693                                         if (fixed_panel == FixedPanel.None) {
694                                                 splitter_rectangle.X = Math.Max ((int)Math.Floor (((double)this.Width) / fixed_none_ratio), panel1_min_size); //set distance
695                                                 panel1.InternalWidth = this.SplitterDistance;
696                                                 panel2.InternalWidth = this.Width - (this.SplitterWidth + this.SplitterDistance);
697                                                 panel2.Location = new Point (this.SplitterWidth + this.SplitterDistance, 0);
698                                         } else if (fixed_panel == FixedPanel.Panel1) {
699                                                 panel1.InternalWidth = this.SplitterDistance;
700                                                 panel2.InternalWidth = Math.Max (this.Width - (this.SplitterWidth + this.SplitterDistance), panel2_min_size);
701                                                 panel2.Location = new Point (this.SplitterWidth + this.SplitterDistance, 0);
702                                         } else if (fixed_panel == FixedPanel.Panel2) {
703                                                 splitter_rectangle.X = Math.Max (this.Width - (this.SplitterWidth + panel2.Width), panel1_min_size); //set distance
704                                                 panel1.InternalWidth = this.SplitterDistance;
705                                                 panel2.Location = new Point (this.SplitterWidth + this.SplitterDistance, 0);
706                                         }
707                                 } else if (orientation == Orientation.Horizontal) {
708                                         panel1.Location = new Point (0, 0);
709                                         panel1.InternalWidth = panel2.InternalWidth = this.Width;
710                                         splitter_rectangle.Width = this.Width;
711
712                                         if (fixed_panel == FixedPanel.None) {
713                                                 splitter_rectangle.Y = Math.Max ((int) Math.Floor ((double)this.Height / fixed_none_ratio), panel1_min_size); //set distance
714                                                 panel1.InternalHeight = this.SplitterDistance;
715                                                 panel2.InternalHeight = this.Height - (this.SplitterWidth + this.SplitterDistance);
716                                                 panel2.Location = new Point (0, this.SplitterWidth + this.SplitterDistance);
717                                         } else if (fixed_panel == FixedPanel.Panel1) {
718                                                 panel1.InternalHeight = this.SplitterDistance;
719                                                 panel2.InternalHeight = Math.Max (this.Height - (this.SplitterWidth + this.SplitterDistance), panel2_min_size);
720                                                 panel2.Location = new Point (0, this.SplitterWidth + this.SplitterDistance);
721                                         } else if (fixed_panel == FixedPanel.Panel2) {
722                                                 splitter_rectangle.Y =  Math.Max (this.Height - (this.SplitterWidth + panel2.Height), panel1_min_size); //set distance
723                                                 panel1.InternalHeight = this.SplitterDistance;
724                                                 panel2.Location = new Point (0, this.SplitterWidth + this.SplitterDistance);
725                                         }
726                                 }
727                         }
728
729                         panel1.ResumeLayout ();
730                         panel2.ResumeLayout ();
731                 }
732
733                 #endregion
734
735                 #region Internal Classes
736                 internal class SplitContainerTypedControlCollection : ControlCollection
737                 {
738                         public SplitContainerTypedControlCollection (Control owner) : base (owner)
739                         {
740                         }
741                 }
742                 #endregion
743         }
744 }
745 #endif