Subversion Repositories SoapBoxCore

Rev

Rev 7 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 scott 1
//Copyright (c) 2007-2010, Adolfo Marinucci
7 scott 2
//All rights reserved.
3
 
4
//Redistribution and use in source and binary forms, with or without modification, 
5
//are permitted provided that the following conditions are met:
6
//
7
//* Redistributions of source code must retain the above copyright notice, 
8
//  this list of conditions and the following disclaimer.
9
//* Redistributions in binary form must reproduce the above copyright notice, 
10
//  this list of conditions and the following disclaimer in the documentation 
11
//  and/or other materials provided with the distribution.
12
//* Neither the name of Adolfo Marinucci nor the names of its contributors may 
13
//  be used to endorse or promote products derived from this software without 
14
//  specific prior written permission.
15
//
16
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
17
//AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
18
//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
19
//IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
20
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
21
//PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
22
//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
23
//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
24
//EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25
 
26
using System;
27
using System.Collections.Generic;
28
using System.Text;
29
using System.Windows;
30
using System.Windows.Controls;
31
using System.Windows.Controls.Primitives;
32
using System.Windows.Data;
33
using System.Windows.Documents;
34
using System.Windows.Input;
35
using System.Windows.Media;
36
using System.Windows.Media.Imaging;
37
using System.Windows.Shapes;
38
using System.Windows.Markup;
39
using System.Diagnostics;
40
using System.Linq;
41
 
42
 
43
namespace AvalonDock
44
{
45
    public class ResizingPanel : Panel, IDockableControl
46
    {
47
        /// <summary>
48
        /// Gets or sets the orientation of the panel
49
        /// </summary>
50
        /// <remarks>If horizontal oriented children are positioned from left to right and width of each child is computed according to <see cref="ResizingWidth"/> attached property value. When vertical oriented children are arranged from top to bottom, according to <see cref="ResizingHeight"/> of each child.</remarks>
51
        public Orientation Orientation
52
        {
53
            get { return (Orientation)GetValue(OrientationProperty); }
54
            set { SetValue(OrientationProperty, value); }
55
        }
56
 
57
        /// <summary>
58
        /// Give access to Orientation attached property
59
        /// </summary>
60
        /// <remarks>If horizontal oriented children are positioned from left to right and width of each child is computed according to <see cref="ResizingWidth"/> attached property value. When vertical oriented children are arranged from top to bottom, according to <see cref="ResizingHeight"/> of each child.</remarks>
61
        public static readonly DependencyProperty OrientationProperty =
62
            DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ResizingPanel), new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure, OnOrientationChanged));
63
 
64
        static void OnOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
65
        {
66
            ((ResizingPanel)d).splitterListIsDirty = true;
67
        }
68
 
69
        public static GridLength GetResizeWidth(DependencyObject obj)
70
        {
71
            return (GridLength)obj.GetValue(ResizeWidthProperty);
72
        }
73
 
74
        public static void SetResizeWidth(DependencyObject obj, GridLength value)
75
        {
76
            obj.SetValue(ResizeWidthProperty, value);
77
        }
78
 
79
 
80
        public static readonly DependencyProperty ResizeWidthProperty =
81
            DependencyProperty.RegisterAttached("ResizeWidth",
82
            typeof(GridLength),
83
            typeof(ResizingPanel),
84
            new FrameworkPropertyMetadata(new GridLength(1.0, GridUnitType.Star),
85
                OnSplitSizeChanged,
86
                OnCoerceSplitSize),
87
                new ValidateValueCallback(IsSplitSizeValid));
88
 
89
        public static GridLength GetResizeHeight(DependencyObject obj)
90
        {
91
            return (GridLength)obj.GetValue(ResizeHeightProperty);
92
        }
93
 
94
        public static void SetResizeHeight(DependencyObject obj, GridLength value)
95
        {
96
            obj.SetValue(ResizeHeightProperty, value);
97
        }
98
 
99
 
100
        public static readonly DependencyProperty ResizeHeightProperty =
101
            DependencyProperty.RegisterAttached("ResizeHeight",
102
            typeof(GridLength),
103
            typeof(ResizingPanel),
104
            new FrameworkPropertyMetadata(new GridLength(1.0, GridUnitType.Star),
105
                OnSplitSizeChanged,
106
                OnCoerceSplitSize),
107
                new ValidateValueCallback(IsSplitSizeValid));
108
 
109
        static void OnSplitSizeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
110
        {
111
            ResizingPanel parentPanel = LogicalTreeHelper.GetParent(sender) as ResizingPanel;
112
            if (parentPanel != null)
113
                parentPanel.InvalidateMeasure();
114
        }
115
 
116
        static object OnCoerceSplitSize(DependencyObject sender, object value)
117
        {
118
            GridLength gd = (GridLength)value;
119
 
120
            if (gd.Value < 0.0)
121
                gd = new GridLength(0.0, gd.GridUnitType);
122
 
123
            return gd;
124
        }
125
 
126
        static bool IsSplitSizeValid(object value)
127
        {
128
            GridLength v = (GridLength)value;
129
            return v.IsStar || v.IsAbsolute;//at the moment auto is not supported
130
        }
131
 
132
 
133
 
134
        public static Size GetEffectiveSize(DependencyObject obj)
135
        {
136
            return (Size)obj.GetValue(EffectiveSizeProperty);
137
        }
138
 
139
        public static void SetEffectiveSize(DependencyObject obj, Size value)
140
        {
141
            obj.SetValue(EffectiveSizeProperty, value);
142
        }
143
 
144
        public static readonly DependencyProperty EffectiveSizeProperty =
145
            DependencyProperty.RegisterAttached("EffectiveSize", typeof(Size), typeof(ResizingPanel), new FrameworkPropertyMetadata(new Size()));
146
 
147
 
17 scott 148
        List<Resizer> _splitterList = new List<Resizer>();
7 scott 149
 
150
        /// <summary>
151
        /// Correct sizes of children if all of them are set to absolutes
152
        /// </summary>
153
        void CorrectSizes()
154
        {
17 scott 155
            IEnumerable<FrameworkElement> children = Children.OfType<FrameworkElement>().Where<FrameworkElement>(c => !(c is Resizer));
7 scott 156
 
157
            if (children.All<FrameworkElement>(c => c.IsAbsolute()))
158
            {
159
                double totSum = children.Sum<FrameworkElement>(f => f.GetAbsoluteValue());
160
                foreach (var c in children)
161
                {
162
                    if (Orientation == Orientation.Horizontal)
163
                        SetResizeWidth(c, new GridLength(c.GetAbsoluteValue() / totSum, GridUnitType.Star));
164
                    else
165
                        SetResizeHeight(c, new GridLength(c.GetAbsoluteValue() / totSum, GridUnitType.Star));
166
                }
167
            }
168
        }
169
 
170
        /// <summary>
171
        /// Helper funcs which correct elements size of a resizing panel
172
        /// </summary>
173
        internal void AdjustPanelSizes()
174
        {
17 scott 175
            IEnumerable<FrameworkElement> children = Children.OfType<FrameworkElement>().Where<FrameworkElement>(c => !(c is Resizer));
7 scott 176
 
177
            if (!this.IsLogicalChildContained<DocumentPane>())
178
            {
179
                //if no document pane is contained in this panel
180
                //adjust elements so that any child will get a proportional star size
181
                if (Orientation == Orientation.Horizontal)
182
                {
183
                    double totSum = children.Sum<FrameworkElement>(f => f.IsAbsolute() ? f.GetAbsoluteValue() : GetEffectiveSize(f).Width);
184
                    foreach (var c in children)
185
                        SetResizeWidth(c, new GridLength((c.IsAbsolute() ? c.GetAbsoluteValue() : GetEffectiveSize(c).Width) / totSum, GridUnitType.Star));
186
                }
187
                else
188
                {
189
                    double totSum = children.Sum<FrameworkElement>(f => f.IsAbsolute() ? f.GetAbsoluteValue() : GetEffectiveSize(f).Height);
190
                    foreach (var c in children)
191
                        SetResizeHeight(c, new GridLength((c.IsAbsolute() ? c.GetAbsoluteValue() : GetEffectiveSize(c).Height) / totSum, GridUnitType.Star));
192
                }
193
            }
194
 
195
        }
196
 
197
 
198
        /// <summary>
199
        /// Compute the desidered size of the panel
200
        /// </summary>
201
        /// <param name="availableSize"></param>
202
        /// <returns></returns>
203
        protected override Size MeasureOverride(Size availableSize)
204
        {
17 scott 205
            //Debug.WriteLine("ResizingPanel.MeasureOverride()");
206
 
7 scott 207
            SetupSplitters();
208
 
209
            CorrectSizes();
210
 
211
            //Compute the list of visible children
212
            List<FrameworkElement> visibleChildren = new List<FrameworkElement>();
213
            for (int i = 0; i < VisualChildrenCount; i++)
214
            {
215
                FrameworkElement child = GetVisualChild(i) as FrameworkElement;
216
 
217
                IDockableControl dockableControl = child as IDockableControl;
218
                if (dockableControl  != null &&
219
                    !dockableControl.IsDocked)
220
                {
221
                    child.Measure(Size.Empty);
222
 
223
                    if (i == VisualChildrenCount - 1 &&
224
                        i > 0)
225
                    {
226
                        child = GetVisualChild(i - 1) as FrameworkElement;
17 scott 227
                        Debug.Assert(child is Resizer);
7 scott 228
 
229
                        child.Measure(Size.Empty);
230
 
231
                        if (visibleChildren.Count > 0)
232
                        {
17 scott 233
                            Debug.Assert(visibleChildren[visibleChildren.Count - 1] is Resizer);
7 scott 234
                            visibleChildren[visibleChildren.Count - 1].Measure(Size.Empty);
235
                            visibleChildren.RemoveAt(visibleChildren.Count - 1);
236
                        }
237
                    }
238
                    else if (i < VisualChildrenCount - 1)
239
                    {
240
                        i++;
241
                        child = GetVisualChild(i) as FrameworkElement;
17 scott 242
                        Debug.Assert(child is Resizer);
7 scott 243
                        child.Measure(Size.Empty);
244
                    }
245
 
246
                    continue;
247
                }
248
 
249
                visibleChildren.Add(child);
250
            }
251
 
252
 
253
            //with no children no space needed
254
            if (visibleChildren.Count == 0)
255
                return new Size();
256
 
17 scott 257
            NormalizeStarLength(visibleChildren);
7 scott 258
 
17 scott 259
            Debug.Assert(!(visibleChildren.Last<FrameworkElement>() is Resizer));
260
 
7 scott 261
            if (availableSize.Width == double.PositiveInfinity &&
262
                Orientation == Orientation.Horizontal)
263
            {
264
                Size newAvailSize = new Size();
265
                foreach (FrameworkElement child in visibleChildren)
266
                {
267
                    child.Measure(availableSize);
268
                    newAvailSize.Width += child.DesiredSize.Width;
269
                    newAvailSize.Height = Math.Max(child.DesiredSize.Height, newAvailSize.Height);
270
                }
271
                availableSize = newAvailSize;
272
            }
273
            //Thx to TMx
274
            else if (availableSize.Height == double.PositiveInfinity &&
275
                Orientation == Orientation.Vertical)
276
            {
277
                Size newAvailSize = new Size();
278
                foreach (FrameworkElement child in visibleChildren)
279
                {
280
                    child.Measure(newAvailSize);
281
                    newAvailSize.Width = Math.Max(child.DesiredSize.Width, newAvailSize.Width);
282
                    newAvailSize.Height += child.DesiredSize.Height;
283
                }
284
                availableSize = newAvailSize;
285
            }
286
 
287
            var splitters = from FrameworkElement child in visibleChildren
17 scott 288
                            where child is Resizer
7 scott 289
                            select child;
290
            var childStars = from FrameworkElement child in visibleChildren
17 scott 291
                             where (!(child is Resizer)) && child.IsStar()
7 scott 292
                             select child;
293
 
294
            var childAbsolutes = from FrameworkElement child in visibleChildren
17 scott 295
                                 where (!(child is Resizer)) && child.IsAbsolute()
7 scott 296
                                 select child;
297
 
298
            var childAutoSizes = from FrameworkElement child in visibleChildren
17 scott 299
                                 where (!(child is Resizer)) && child.IsAuto()
7 scott 300
                                 select child;
301
 
302
            //calculate the size of the splitters
303
            Size splitterSize = new Size();
17 scott 304
            foreach (Resizer splitter in splitters)
7 scott 305
            {
306
                splitterSize.Width += splitter.MinWidth;
307
                splitterSize.Height += splitter.MinHeight;
308
            }
309
 
310
            Size minimumSize = new Size(splitterSize.Width, splitterSize.Height);
311
            foreach (FrameworkElement child in childStars)
312
            {
313
                minimumSize.Width += child.MinWidth;
314
                minimumSize.Height += child.MinHeight;
315
            }
316
            foreach (FrameworkElement child in childAbsolutes)
317
            {
318
                minimumSize.Width += child.MinWidth;
319
                minimumSize.Height += child.MinHeight;
320
            }
321
            foreach (FrameworkElement child in childAutoSizes)
322
            {
323
                minimumSize.Width += child.MinWidth;
324
                minimumSize.Height += child.MinHeight;
325
            }
326
 
327
 
328
            Size minimumPrefferedSize = new Size(minimumSize.Width, minimumSize.Height);
329
            foreach (FrameworkElement child in childAbsolutes)
330
            {
331
                minimumPrefferedSize.Width += child.GetAbsoluteValue() - child.MinWidth;
332
                minimumPrefferedSize.Height += child.GetAbsoluteValue() - child.MinHeight;
333
            }
334
            foreach (FrameworkElement child in childAutoSizes)
335
            {
336
                minimumPrefferedSize.Width += child.DesiredSize.Width - child.MinWidth;
337
                minimumPrefferedSize.Height += child.DesiredSize.Height - child.MinHeight;
338
            }
339
 
340
            if (Orientation == Orientation.Horizontal)
341
            {
342
                #region Horizontal Orientation
343
 
344
                //if finalSize is not sufficient...
345
                double offset = 0.0;
346
                double maxHeight = 0.0;
347
                if (minimumSize.Width >= availableSize.Width)
348
                {
349
                    foreach (FrameworkElement child in visibleChildren)
350
                    {
351
                        child.Measure(new Size(child.MinWidth, availableSize.Height));
352
                        maxHeight = Math.Max(child.DesiredSize.Height, maxHeight);
353
                        offset += child.MinWidth;
354
                    }
355
                }
356
                else if (minimumPrefferedSize.Width >= availableSize.Width)
357
                {
358
                    double delta = (minimumPrefferedSize.Width - availableSize.Width) / childAbsolutes.Count<FrameworkElement>();
359
 
360
                    foreach (FrameworkElement child in visibleChildren)
361
                    {
17 scott 362
                        if (child is Resizer)
7 scott 363
                        {
364
                            child.Measure(new Size(child.MinWidth, availableSize.Height));
365
                            maxHeight = Math.Max(child.DesiredSize.Height, maxHeight);
366
                            offset += child.MinWidth;
367
                        }
368
                        else if (child.IsAbsolute())
369
                        {
370
                            child.Measure(new Size(Math.Max(child.GetAbsoluteValue() - delta, child.MinWidth), availableSize.Height));
371
                            maxHeight = Math.Max(child.DesiredSize.Height, maxHeight);
372
                            offset += child.GetAbsoluteValue() - delta;
373
                        }
374
                        else
375
                        {
376
                            child.Measure(new Size(child.MinWidth, availableSize.Height));
377
                            maxHeight = Math.Max(child.DesiredSize.Height, maxHeight);
378
                            offset += child.MinWidth;
379
                        }
380
                    }
381
                }
382
                else
383
                {
384
                    double starsSum = childStars.Sum<FrameworkElement>(v => v.GetStarValue());
385
                    double starsFinalWidth =
386
                        availableSize.Width -
387
                        splitters.Sum<FrameworkElement>(s => s.MinWidth) -
388
                        childAbsolutes.Sum<FrameworkElement>(a => a.GetAbsoluteValue()) -
389
                        childAutoSizes.Sum<FrameworkElement>(a => a.DesiredSize.Width);
390
 
391
                    foreach (FrameworkElement child in visibleChildren)
392
                    {
17 scott 393
                        if (child is Resizer)
7 scott 394
                        {
395
                            child.Measure(new Size(child.MinWidth, availableSize.Height));
396
                            maxHeight = Math.Max(child.DesiredSize.Height, maxHeight);
397
                            offset += child.MinWidth;
398
                        }
399
                        else if (child.IsAbsolute())
400
                        {
401
                            child.Measure(new Size(child.GetAbsoluteValue(), availableSize.Height));
402
                            maxHeight = Math.Max(child.DesiredSize.Height, maxHeight);
403
                            offset += child.GetAbsoluteValue();
404
                        }
405
                        else if (child.IsStar())
406
                        {
407
                            double w = child.GetStarValue() / starsSum * starsFinalWidth;
408
                            child.Measure(new Size(w, availableSize.Height));
409
                            maxHeight = Math.Max(child.DesiredSize.Height, maxHeight);
410
                            offset += w;
411
                        }
412
                        else
413
                        {
414
                            child.Measure(new Size(child.DesiredSize.Width, availableSize.Height));
415
                            maxHeight = Math.Max(child.DesiredSize.Height, maxHeight);
416
                            offset += child.DesiredSize.Width;
417
                        }
418
                    }
419
                }
420
 
421
                return new Size(offset, maxHeight);
422
 
423
                #endregion
424
            }
425
            else
426
            {
427
                #region Vertical Orientation
428
 
429
                //if finalSize is not sufficient...
430
                double offset = 0.0;
431
                double maxWidth = 0.0;
432
                if (minimumSize.Height >= availableSize.Height)
433
                {
434
                    foreach (FrameworkElement child in visibleChildren)
435
                    {
436
                        child.Measure(new Size(availableSize.Width, child.MinHeight));
437
                        maxWidth = Math.Max(child.DesiredSize.Width, maxWidth);
438
                        offset += child.MinHeight;
439
                    }
440
                }
441
                else if (minimumPrefferedSize.Height >= availableSize.Height)
442
                {
443
                    double delta = (minimumPrefferedSize.Height - availableSize.Height) / childAbsolutes.Count<FrameworkElement>();
444
 
445
                    foreach (FrameworkElement child in visibleChildren)
446
                    {
17 scott 447
                        if (child is Resizer)
7 scott 448
                        {
449
                            child.Measure(new Size(availableSize.Width, child.MinHeight));
450
                            maxWidth = Math.Max(child.DesiredSize.Width, maxWidth);
451
                            offset += child.MinHeight;
452
                        }
453
                        else if (child.IsAbsolute())
454
                        {
455
                            child.Measure(new Size(availableSize.Width, Math.Max(child.GetAbsoluteValue() - delta, child.MinHeight)));
456
                            maxWidth = Math.Max(child.DesiredSize.Width, maxWidth);
457
                            offset += child.GetAbsoluteValue() - delta;
458
                        }
459
                        else
460
                        {
461
                            child.Measure(new Size(availableSize.Width, child.MinHeight));
462
                            maxWidth = Math.Max(child.DesiredSize.Width, maxWidth);
463
                            offset += child.MinWidth;
464
                        }
465
                    }
466
                }
467
                else
468
                {
469
                    double starsSum = childStars.Sum<FrameworkElement>(v => v.GetStarValue());
470
                    double starsFinalHeight =
471
                        availableSize.Height -
472
                        splitters.Sum<FrameworkElement>(s => s.MinHeight) -
473
                        childAbsolutes.Sum<FrameworkElement>(a => a.GetAbsoluteValue()) -
474
                        childAutoSizes.Sum<FrameworkElement>(a => a.DesiredSize.Height);
475
 
476
                    foreach (FrameworkElement child in visibleChildren)
477
                    {
17 scott 478
                        if (child is Resizer)
7 scott 479
                        {
480
                            child.Measure(new Size(availableSize.Width, child.MinHeight));
481
                            maxWidth = Math.Max(child.DesiredSize.Width, maxWidth);
482
                            offset += child.MinWidth;
483
                        }
484
                        else if (child.IsAbsolute())
485
                        {
486
                            child.Measure(new Size(availableSize.Width, child.GetAbsoluteValue()));
487
                            maxWidth = Math.Max(child.DesiredSize.Width, maxWidth);
488
                            offset += child.GetAbsoluteValue();
489
                        }
490
                        else if (child.IsStar())
491
                        {
492
                            double w = child.GetStarValue() / starsSum * starsFinalHeight;
493
                            child.Measure(new Size(availableSize.Width, w));
494
                            maxWidth = Math.Max(child.DesiredSize.Width, maxWidth);
495
                            offset += w;
496
                        }
497
                        else
498
                        {
499
                            child.Measure(new Size(availableSize.Width, child.DesiredSize.Height));
500
                            maxWidth = Math.Max(child.DesiredSize.Width, maxWidth);
501
                            offset += child.DesiredSize.Width;
502
                        }
503
                    }
504
                }
505
 
506
                return new Size(maxWidth, offset);
507
 
508
                #endregion
509
 
510
            }
511
        }
512
 
17 scott 513
        private void NormalizeStarLength(IEnumerable<FrameworkElement> visibleChildren)
514
        {
515
            var childrenWithStarLength = visibleChildren.Where(c => c is IDockableControl && c.IsStar());
516
            int childrenWithStartLengthCount = childrenWithStarLength.Count();
517
 
518
            if (childrenWithStartLengthCount == 0)
519
                return;
520
 
521
            if (childrenWithStartLengthCount == 1)
522
            {
523
                ResizingPanel.SetResizeWidth(childrenWithStarLength.First(), new GridLength(1.0, GridUnitType.Star));
524
                return;
525
            }
526
 
527
            double sumStars = childrenWithStarLength.Sum(c => c.GetStarValue());
528
 
529
            if (sumStars == 0)
530
            {
531
                //problem!?! try to fix...
532
                childrenWithStarLength.ForEach(c =>
533
                    {
534
                        ResizingPanel.SetResizeWidth(c, new GridLength(1.0 / childrenWithStartLengthCount, GridUnitType.Star));
535
                    });
536
            }
537
            else
538
            {
539
                childrenWithStarLength.ForEach(c =>
540
                {
541
                    ResizingPanel.SetResizeWidth(c, new GridLength(1.0 * c.GetStarValue() / sumStars, GridUnitType.Star));
542
                });                
543
            }
544
 
545
        }
546
 
7 scott 547
        Size[] _childrenFinalSizes = null;
548
 
549
        /// <summary>
550
        /// Arranges children giving them a proportional space according to their <see cref="SplitSize"/> attached property value
551
        /// </summary>
552
        /// <param name="finalSize"></param>
553
        /// <returns></returns>
554
        protected override Size ArrangeOverride(Size finalSize)
555
        {
17 scott 556
            //Debug.WriteLine("ResizingPanel.ArrangeOverride()");
557
 
7 scott 558
            //Compute the list of visible children
559
            List<FrameworkElement> visibleChildren = new List<FrameworkElement>();
560
            for (int i = 0; i < VisualChildrenCount; i++)
561
            {
562
                FrameworkElement child = GetVisualChild(i) as FrameworkElement;
563
 
564
                IDockableControl dockableControl = child as IDockableControl;
565
                if (dockableControl != null &&
566
                    !dockableControl.IsDocked)
567
                {
568
                    child.Arrange(new Rect());
569
 
570
                    if (i == VisualChildrenCount - 1 &&
571
                        i > 0)
572
                    {
573
                        child = GetVisualChild(i - 1) as FrameworkElement;
17 scott 574
                        Debug.Assert(child is Resizer);
7 scott 575
 
576
                        child.Arrange(new Rect());
577
 
578
                        if (visibleChildren.Count > 0)
579
                        {
17 scott 580
                            Debug.Assert(visibleChildren[visibleChildren.Count - 1] is Resizer);
7 scott 581
                            visibleChildren[visibleChildren.Count - 1].Arrange(new Rect());
582
                            visibleChildren.RemoveAt(visibleChildren.Count - 1);
583
                        }
584
 
585
                    }
586
                    else if (i < VisualChildrenCount - 1)
587
                    {
588
                        i++;
589
                        child = GetVisualChild(i) as FrameworkElement;
590
                        child.Arrange(new Rect());
17 scott 591
                        Debug.Assert(child is Resizer);
7 scott 592
                    }
593
 
594
                    continue;
595
                }
596
 
597
                visibleChildren.Add(child);
598
            }
599
 
600
            //with no children fill the space
601
            if (visibleChildren.Count == 0)
602
            {
603
                _childrenFinalSizes = new Size[] { };
604
                return new Size();
605
            }
606
 
17 scott 607
            Debug.Assert(!(visibleChildren.Last<FrameworkElement>() is Resizer));
7 scott 608
 
609
 
610
            _childrenFinalSizes = new Size[visibleChildren.Count];
611
 
612
            var splitters = from FrameworkElement child in visibleChildren
17 scott 613
                            where child is Resizer
7 scott 614
                            select child;
615
            var childStars = from FrameworkElement child in visibleChildren
17 scott 616
                             where (!(child is Resizer)) && child.IsStar()
7 scott 617
                             select child;
618
 
619
            var childAbsolutes = from FrameworkElement child in visibleChildren
17 scott 620
                                 where (!(child is Resizer)) && child.IsAbsolute()
7 scott 621
                                 select child;
622
 
623
            var childAutoSizes = from FrameworkElement child in visibleChildren
17 scott 624
                                 where (!(child is Resizer)) && child.IsAuto()
7 scott 625
                                 select child;
626
 
627
            //calculate the size of the splitters
628
            Size splitterSize = new Size();
17 scott 629
            foreach (Resizer splitter in splitters)
7 scott 630
            {
631
                splitterSize.Width += splitter.MinWidth;
632
                splitterSize.Height += splitter.MinHeight;
633
            }
634
 
635
            Size minimumSize = new Size(splitterSize.Width, splitterSize.Height);
636
            foreach (FrameworkElement child in childStars)
637
            {
638
                minimumSize.Width += child.MinWidth;
639
                minimumSize.Height += child.MinHeight;
640
            }
641
            foreach (FrameworkElement child in childAbsolutes)
642
            {
643
                minimumSize.Width += child.MinWidth;
644
                minimumSize.Height += child.MinHeight;
645
            }
646
            foreach (FrameworkElement child in childAutoSizes)
647
            {
648
                minimumSize.Width += child.MinWidth;
649
                minimumSize.Height += child.MinHeight;
650
            }
651
 
652
 
653
            Size minimumPrefferedSize = new Size(minimumSize.Width, minimumSize.Height);
654
            foreach (FrameworkElement child in childAbsolutes)
655
            {
656
                minimumPrefferedSize.Width += child.GetAbsoluteValue() - child.MinWidth;
657
                minimumPrefferedSize.Height += child.GetAbsoluteValue() - child.MinHeight;
658
            }
659
            foreach (FrameworkElement child in childAutoSizes)
660
            {
661
                minimumPrefferedSize.Width += child.DesiredSize.Width - child.MinWidth;
662
                minimumPrefferedSize.Height += child.DesiredSize.Height - child.MinHeight;
663
            }
664
 
665
            int iChild = 0;
666
 
667
            if (Orientation == Orientation.Horizontal)
668
            {
669
                #region Horizontal Orientation
670
 
671
                //if finalSize is not sufficient...
672
                if (minimumSize.Width >= finalSize.Width)
673
                {
674
                    foreach (FrameworkElement child in visibleChildren)
675
                    {
676
                        _childrenFinalSizes[iChild++] = new Size(child.MinWidth, finalSize.Height);
677
                    }
678
                }
679
                else if (minimumPrefferedSize.Width >= finalSize.Width)
680
                {
681
                    double delta = (minimumPrefferedSize.Width - finalSize.Width) / childAbsolutes.Count<FrameworkElement>();
682
 
683
                    foreach (FrameworkElement child in visibleChildren)
684
                    {
17 scott 685
                        if (child is Resizer)
7 scott 686
                            _childrenFinalSizes[iChild++] = new Size(child.MinWidth, finalSize.Height);
687
                        else if (child.IsAbsolute())
688
                            _childrenFinalSizes[iChild++] = new Size(Math.Max(child.GetAbsoluteValue() - delta, 0.0), finalSize.Height);
689
                        else
690
                            _childrenFinalSizes[iChild++] = new Size(child.MinWidth, finalSize.Height);
691
                    }
692
                }
693
                else
694
                {
695
                    double starsSum = childStars.Sum<FrameworkElement>(v => v.GetStarValue());
696
                    double starsFinalWidth =
697
                        finalSize.Width -
698
                        splitters.Sum<FrameworkElement>(s => s.MinWidth) -
699
                        childAbsolutes.Sum<FrameworkElement>(a => a.GetAbsoluteValue()) -
700
                        childAutoSizes.Sum<FrameworkElement>(a => a.DesiredSize.Width);
701
 
702
                    foreach (FrameworkElement child in visibleChildren)
703
                    {
17 scott 704
                        if (child is Resizer)
7 scott 705
                            _childrenFinalSizes[iChild++] = new Size(child.MinWidth, finalSize.Height);
706
                        else if (child.IsAbsolute())
707
                            _childrenFinalSizes[iChild++] = new Size(child.GetAbsoluteValue(), finalSize.Height);
708
                        else if (child.IsStar())
709
                            _childrenFinalSizes[iChild++] = new Size(child.GetStarValue() / starsSum * starsFinalWidth, finalSize.Height);
710
                        else
711
                            _childrenFinalSizes[iChild++] = new Size(child.DesiredSize.Width, finalSize.Height);
712
                    }
713
 
714
                }
715
 
716
                double offset = 0.0;
717
 
718
                for (int i = 0; i < visibleChildren.Count; i++)
719
                {
720
                    FrameworkElement child = visibleChildren[i] as FrameworkElement;
721
                    child.Arrange(new Rect(offset, 0.0, _childrenFinalSizes[i].Width, finalSize.Height));
722
                    offset += _childrenFinalSizes[i].Width;
723
 
724
                    SetEffectiveSize(child, new Size(_childrenFinalSizes[i].Width, finalSize.Height));
725
                }
726
 
727
                return new Size(offset, finalSize.Height);
728
                #endregion
729
            }
730
            else
731
            {
732
                #region Vertical Orientation
733
 
734
                //if finalSize is not sufficient...
735
                if (minimumSize.Height >= finalSize.Height)
736
                {
737
                    foreach (FrameworkElement child in visibleChildren)
738
                    {
739
                        _childrenFinalSizes[iChild++] = new Size(finalSize.Width, child.MinHeight);
740
                    }
741
                }
742
                else if (minimumPrefferedSize.Height >= finalSize.Height)
743
                {
744
                    double delta = (minimumPrefferedSize.Height - finalSize.Height) / childAbsolutes.Count<FrameworkElement>();
745
 
746
                    foreach (FrameworkElement child in visibleChildren)
747
                    {
17 scott 748
                        if (child is Resizer)
7 scott 749
                            _childrenFinalSizes[iChild++] = new Size(finalSize.Width, child.MinHeight);
750
                        else if (child.IsAbsolute())
751
                            _childrenFinalSizes[iChild++] = new Size(finalSize.Width, Math.Max(child.GetAbsoluteValue() - delta, 0.0));
752
                        else
753
                            _childrenFinalSizes[iChild++] = new Size(finalSize.Width, child.MinHeight);
754
                    }
755
                }
756
                else
757
                {
758
                    double starsSum = childStars.Sum<FrameworkElement>(v => v.GetStarValue());
759
                    double starsFinalHeight =
760
                        finalSize.Height -
761
                        splitters.Sum<FrameworkElement>(s => s.MinHeight) -
762
                        childAbsolutes.Sum<FrameworkElement>(a => a.GetAbsoluteValue()) -
763
                        childAutoSizes.Sum<FrameworkElement>(a => a.DesiredSize.Height);
764
 
765
                    foreach (FrameworkElement child in visibleChildren)
766
                    {
17 scott 767
                        if (child is Resizer)
7 scott 768
                            _childrenFinalSizes[iChild++] = new Size(finalSize.Width, child.MinHeight);
769
                        else if (child.IsAbsolute())
770
                            _childrenFinalSizes[iChild++] = new Size(finalSize.Width, child.GetAbsoluteValue());
771
                        else if (child.IsStar())
772
                            _childrenFinalSizes[iChild++] = new Size(finalSize.Width, child.GetStarValue() / starsSum * starsFinalHeight);
773
                        else
774
                            _childrenFinalSizes[iChild++] = new Size(finalSize.Width, child.DesiredSize.Height);
775
                    }
776
 
777
                }
778
 
779
                double offset = 0.0;
780
 
781
                for (int i = 0; i < visibleChildren.Count; i++)
782
                {
783
                    FrameworkElement child = visibleChildren[i] as FrameworkElement;
784
                    child.Arrange(new Rect(0.0, offset, finalSize.Width, _childrenFinalSizes[i].Height));
785
                    offset += _childrenFinalSizes[i].Height;
786
                    SetEffectiveSize(child, new Size(finalSize.Width, _childrenFinalSizes[i].Height));
787
                }
788
 
789
                return new Size(finalSize.Width, offset);
790
                #endregion
791
            }
792
 
793
 
794
        }
795
 
796
        bool setupSplitters = false;
797
        bool splitterListIsDirty = false;
17 scott 798
 
7 scott 799
        void SetupSplitters()
800
        {
801
            if (!splitterListIsDirty)
802
                return;
803
 
804
            if (setupSplitters)
805
                return;
806
 
807
            setupSplitters = true;
808
 
809
            while (_splitterList.Count > 0)
810
            {
17 scott 811
                Resizer splitter = _splitterList[0];
7 scott 812
                splitter.DragStarted -= new DragStartedEventHandler(splitter_DragStarted);
813
                splitter.DragDelta -= new DragDeltaEventHandler(splitter_DragDelta);
814
                splitter.DragCompleted -= new DragCompletedEventHandler(splitter_DragCompleted);
815
                _splitterList.Remove(splitter);
816
                Children.Remove(splitter);
817
            }
818
 
819
            int i = 0;//child index
820
            int j = 0;//splitter index
821
 
822
            while (i < Children.Count - 1)
823
            {
824
                if (j == _splitterList.Count)
825
                {
17 scott 826
                    Resizer splitter = new Resizer();
827
                    splitter.Cursor =  this.Orientation == Orientation.Horizontal ? Cursors.SizeWE : Cursors.SizeNS;
7 scott 828
                    _splitterList.Add(splitter);
829
                    splitter.DragStarted += new DragStartedEventHandler(splitter_DragStarted);
830
                    splitter.DragDelta += new DragDeltaEventHandler(splitter_DragDelta);
831
                    splitter.DragCompleted += new DragCompletedEventHandler(splitter_DragCompleted);
832
                    Children.Insert(i + 1, splitter);
833
                }
834
 
835
                i += 2;
836
                j++;
837
            }
838
 
839
            for (j = 0; j < _splitterList.Count; j++)
840
            {
17 scott 841
                _splitterList[j].Width = (Orientation == Orientation.Horizontal) ? 6 : double.NaN;
842
                _splitterList[j].Height = (Orientation == Orientation.Vertical) ? 6 : double.NaN;
7 scott 843
            }
844
 
845
#if DEBUG
846
            Debug.Assert(_splitterList.Count == Children.Count / 2);
847
            i = 0;
848
            while (Children.Count > 0)
849
            {
850
                Debug.Assert(Children[i] != null);
17 scott 851
                Debug.Assert(!(Children[i] is Resizer));
7 scott 852
                i++;
853
                if (i >= Children.Count)
854
                    break;
855
 
17 scott 856
                Debug.Assert((Children[i] is Resizer));
7 scott 857
                i++;
858
 
859
            }
860
#endif
861
            splitterListIsDirty = false;
862
            setupSplitters = false;
863
        }
864
 
865
        protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
866
        {
867
            base.OnVisualChildrenChanged(visualAdded, visualRemoved);
868
 
869
            splitterListIsDirty = true;
870
        }
871
 
872
 
873
        /// <summary>
874
        /// This method is called by a splitter when it is dragged
875
        /// </summary>
876
        /// <param name="splitter">Dragged splitter</param>
877
        /// <param name="delta"></param>
878
        void splitter_DragDelta(object sender, DragDeltaEventArgs e)
879
        {
17 scott 880
            Resizer splitter = sender as Resizer;
881
 
882
            if (Orientation == System.Windows.Controls.Orientation.Horizontal)
883
            {
884
                Canvas.SetLeft(_resizerGhost, _initialStartPoint.X + e.HorizontalChange);
885
            }
886
            else
887
            {
888
                Canvas.SetTop(_resizerGhost, _initialStartPoint.Y + e.VerticalChange);
889
            }
890
 
891
 
892
            //ResizingPanelSplitter splitter = e.Source as ResizingPanelSplitter;
893
            //int i = 0;
894
 
895
            ////Compute the list of visible children
896
            //List<FrameworkElement> visibleChildren = new List<FrameworkElement>();
897
            //for (i = 0; i < VisualChildrenCount; i++)
898
            //{
899
            //    FrameworkElement child = GetVisualChild(i) as FrameworkElement;
900
 
901
            //    IDockableControl dockableControl = child as IDockableControl;
902
            //    if (dockableControl != null &&
903
            //        !dockableControl.IsDocked)
904
            //    {
905
            //        if (i == VisualChildrenCount - 1 &&
906
            //            i > 0)
907
            //        {
908
            //            //remove the last splitter added
909
            //            if (visibleChildren.Count > 0 &&
910
            //                visibleChildren.Last<FrameworkElement>() is ResizingPanelSplitter)
911
            //                visibleChildren.RemoveAt(visibleChildren.Count - 1);
912
            //        }
913
            //        else if (i < VisualChildrenCount - 1)
914
            //        {
915
            //            //discard the next splitter
916
            //            i++;
917
            //        }
918
 
919
            //        continue;
920
            //    }
921
 
922
            //    visibleChildren.Add(child);
923
            //}
924
 
925
            //if (visibleChildren.Count == 0)
926
            //    return;
927
 
928
            //if (visibleChildren.Last<FrameworkElement>() is ResizingPanelSplitter)
929
            //    visibleChildren.RemoveAt(visibleChildren.Count - 1);
930
 
931
            //Size[] currentSizes = new Size[visibleChildren.Count];
932
            //double delta = Orientation == Orientation.Horizontal ? e.HorizontalChange : e.VerticalChange;
933
 
934
            //if (_childrenFinalSizes == null)
935
            //    return;
936
 
937
            //_childrenFinalSizes.CopyTo(currentSizes, 0);
938
 
939
            //int iSplitter = visibleChildren.IndexOf(splitter);
940
 
941
            //Debug.Assert(iSplitter > -1);
942
 
943
            //List<FrameworkElement> prevChildren = new List<FrameworkElement>();
944
            //for (i = iSplitter - 1; i >= 0; i--)
945
            //{
946
            //    FrameworkElement child = visibleChildren[i] as FrameworkElement;
947
            //    if (child is ResizingPanelSplitter)
948
            //        continue;
949
            //    if (child.IsAbsolute() || child.IsAuto())
950
            //    {
951
            //        if (prevChildren.Count == 0)
952
            //        {
953
            //            prevChildren.Add(child);
954
            //        }
955
            //        break;
956
            //    }
957
            //    if (child.IsStar())
958
            //    {
959
            //        prevChildren.Add(child);
960
            //    }
961
            //}
962
 
963
            //List<FrameworkElement> nextChildren = new List<FrameworkElement>();
964
 
965
            //for (i = iSplitter + 1; i < visibleChildren.Count; i++)
966
            //{
967
            //    FrameworkElement child = visibleChildren[i] as FrameworkElement;
968
            //    if (child is ResizingPanelSplitter)
969
            //        continue;
970
            //    if (child.IsAbsolute() || child.IsAuto())
971
            //    {
972
            //        if (nextChildren.Count == 0)
973
            //            nextChildren.Add(child);
974
            //        break;
975
            //    }
976
            //    if (child.IsStar())
977
            //    {
978
            //        nextChildren.Add(child);
979
            //    }
980
            //}
981
 
982
 
983
            //double prevMinSize = prevChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? c.MinWidth : c.MinHeight);
984
            //double nextMinSize = nextChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? c.MinWidth : c.MinHeight);
985
            //double prevMaxSize = prevChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? c.MaxWidth : c.MaxHeight);
986
            //double nextMaxSize = nextChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? c.MaxWidth : c.MaxHeight);
987
 
988
            //double prevSize = prevChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? currentSizes[visibleChildren.IndexOf(c)].Width : currentSizes[visibleChildren.IndexOf(c)].Height);
989
            //double nextSize = nextChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? currentSizes[visibleChildren.IndexOf(c)].Width : currentSizes[visibleChildren.IndexOf(c)].Height);
990
 
991
            //if (prevSize + delta < prevMinSize)
992
            //    delta = prevMinSize - prevSize;
993
            //if (nextSize - delta < nextMinSize)
994
            //    delta = -(nextMinSize - nextSize);
995
 
996
            //double remDelta = delta * 2;
997
 
998
            //while (!HelperFunc.AreClose(delta, 0.0))
999
            //{
1000
            //    int prevChildrenCountWithNoMinLen =
1001
            //        prevChildren.Count<FrameworkElement>(c => delta > 0 ? true : (Orientation == Orientation.Horizontal ? currentSizes[visibleChildren.IndexOf(c)].Width > c.MinWidth : currentSizes[visibleChildren.IndexOf(c)].Height > c.MinHeight));
1002
            //    int nextChildrenCountWithNoMinLen =
1003
            //        nextChildren.Count<FrameworkElement>(c => delta < 0 ? true : (Orientation == Orientation.Horizontal ? currentSizes[visibleChildren.IndexOf(c)].Width > c.MinWidth : currentSizes[visibleChildren.IndexOf(c)].Height > c.MinHeight));
1004
 
1005
            //    delta = remDelta / 2.0;
1006
 
1007
            //    for (i = 0; i < currentSizes.Length; i++)
1008
            //    {
1009
            //        FrameworkElement child = visibleChildren[i] as FrameworkElement;
1010
            //        if (child is ResizingPanelSplitter)
1011
            //            continue;
1012
 
1013
            //        if (Orientation == Orientation.Horizontal)
1014
            //        {
1015
            //            if (prevChildren.Contains(child) && prevChildrenCountWithNoMinLen > 0)
1016
            //            {
1017
            //                double s = delta / prevChildrenCountWithNoMinLen;
1018
            //                if (currentSizes[i].Width + s < child.MinWidth)
1019
            //                    s = child.MinWidth - currentSizes[i].Width;
1020
 
1021
            //                currentSizes[i].Width += s;
1022
            //                remDelta -= s;
1023
            //            }
1024
            //            if (nextChildren.Contains(child) && nextChildrenCountWithNoMinLen > 0)
1025
            //            {
1026
            //                double s = delta / nextChildrenCountWithNoMinLen;
1027
            //                if (currentSizes[i].Width - s < child.MinWidth)
1028
            //                    s = currentSizes[i].Width - child.MinWidth;
1029
 
1030
            //                currentSizes[i].Width -= s;
1031
            //                remDelta -= s;
1032
            //            }
1033
            //        }
1034
            //        else
1035
            //        {
1036
            //            if (prevChildren.Contains(child) && prevChildrenCountWithNoMinLen > 0)
1037
            //            {
1038
            //                double s = delta / prevChildrenCountWithNoMinLen;
1039
            //                if (currentSizes[i].Height + s < child.MinHeight)
1040
            //                    s = child.MinHeight - currentSizes[i].Height;
1041
 
1042
            //                currentSizes[i].Height += s;
1043
            //                remDelta -= s;
1044
            //            }
1045
            //            if (nextChildren.Contains(child) && nextChildrenCountWithNoMinLen > 0)
1046
            //            {
1047
            //                double s = delta / nextChildrenCountWithNoMinLen;
1048
            //                if (currentSizes[i].Height - s < child.MinHeight)
1049
            //                    s = currentSizes[i].Height - child.MinHeight;
1050
 
1051
            //                currentSizes[i].Height -= s;
1052
            //                remDelta -= s;
1053
            //            }
1054
            //        }
1055
            //    }
1056
            //}
1057
 
1058
            //Debug.Assert(HelperFunc.AreClose(delta, 0.0));
1059
 
1060
            //double totalStartsSum = 0.0;
1061
            //double totalSizeForStarts = 0.0;
1062
 
1063
            //for (i = 0; i < visibleChildren.Count; i++)
1064
            //{ 
1065
            //    FrameworkElement child = visibleChildren[i] as FrameworkElement;
1066
            //    if (child is ResizingPanelSplitter)
1067
            //        continue;
1068
            //    if (child.IsStar())
1069
            //    {
1070
            //        totalStartsSum += child.GetStarValue();
1071
            //        totalSizeForStarts += Orientation == Orientation.Horizontal ? currentSizes[i].Width : currentSizes[i].Height;
1072
            //    }
1073
            //}
1074
 
1075
 
1076
            //double starsScaleFactor = totalStartsSum / totalSizeForStarts;
1077
 
1078
            //for (i = 0; i < currentSizes.Length; i++)
1079
            //{
1080
            //    FrameworkElement child = visibleChildren[i] as FrameworkElement;
1081
 
1082
            //    if (child is ResizingPanelSplitter)
1083
            //        continue;
1084
 
1085
            //    if (child.IsStar())
1086
            //    {
1087
            //        if (Orientation == Orientation.Horizontal)
1088
            //        {
1089
            //            SetResizeWidth(child,
1090
            //                new GridLength(HelperFunc.MultiplyCheckNaN(currentSizes[i].Width, starsScaleFactor), GridUnitType.Star));
1091
            //        }
1092
            //        else
1093
            //        {
1094
            //            SetResizeHeight(child,
1095
            //                new GridLength(HelperFunc.MultiplyCheckNaN(currentSizes[i].Height, starsScaleFactor), GridUnitType.Star));
1096
            //        }
1097
            //    }
1098
            //    else if (child.IsAbsolute())
1099
            //    {
1100
            //        if (Orientation == Orientation.Horizontal)
1101
            //        {
1102
            //            SetResizeWidth(child,
1103
            //                new GridLength(currentSizes[i].Width, GridUnitType.Pixel));
1104
            //        }
1105
            //        else
1106
            //        {
1107
            //            SetResizeHeight(child,
1108
            //                new GridLength(currentSizes[i].Height, GridUnitType.Pixel)); 
1109
            //        }
1110
            //    }
1111
            //}
1112
 
1113
            //InvalidateMeasure();
1114
        }
1115
 
1116
        void splitter_DragStarted(object sender, DragStartedEventArgs e)
1117
        {
1118
            var resizer = sender as Resizer;
1119
            ShowResizerOverlayWindow(resizer);
1120
        }
1121
 
1122
        void splitter_DragCompleted(object sender, DragCompletedEventArgs e)
1123
        {
1124
            HideResizerOverlayWindow();
1125
 
1126
            Resizer splitter = e.Source as Resizer;
7 scott 1127
            int i = 0;
1128
 
1129
            //Compute the list of visible children
1130
            List<FrameworkElement> visibleChildren = new List<FrameworkElement>();
1131
            for (i = 0; i < VisualChildrenCount; i++)
1132
            {
1133
                FrameworkElement child = GetVisualChild(i) as FrameworkElement;
1134
 
1135
                IDockableControl dockableControl = child as IDockableControl;
1136
                if (dockableControl != null &&
1137
                    !dockableControl.IsDocked)
1138
                {
1139
                    if (i == VisualChildrenCount - 1 &&
1140
                        i > 0)
1141
                    {
1142
                        //remove the last splitter added
1143
                        if (visibleChildren.Count > 0 &&
17 scott 1144
                            visibleChildren.Last<FrameworkElement>() is Resizer)
7 scott 1145
                            visibleChildren.RemoveAt(visibleChildren.Count - 1);
1146
                    }
1147
                    else if (i < VisualChildrenCount - 1)
1148
                    {
1149
                        //discard the next splitter
1150
                        i++;
1151
                    }
1152
 
1153
                    continue;
1154
                }
1155
 
1156
                visibleChildren.Add(child);
1157
            }
1158
 
1159
            if (visibleChildren.Count == 0)
1160
                return;
1161
 
17 scott 1162
            if (visibleChildren.Last<FrameworkElement>() is Resizer)
7 scott 1163
                visibleChildren.RemoveAt(visibleChildren.Count - 1);
1164
 
1165
            Size[] currentSizes = new Size[visibleChildren.Count];
1166
            double delta = Orientation == Orientation.Horizontal ? e.HorizontalChange : e.VerticalChange;
1167
 
1168
            if (_childrenFinalSizes == null)
1169
                return;
1170
 
1171
            _childrenFinalSizes.CopyTo(currentSizes, 0);
1172
 
1173
            int iSplitter = visibleChildren.IndexOf(splitter);
1174
 
1175
            Debug.Assert(iSplitter > -1);
1176
 
1177
            List<FrameworkElement> prevChildren = new List<FrameworkElement>();
1178
            for (i = iSplitter - 1; i >= 0; i--)
1179
            {
1180
                FrameworkElement child = visibleChildren[i] as FrameworkElement;
17 scott 1181
                if (child is Resizer)
7 scott 1182
                    continue;
1183
                if (child.IsAbsolute() || child.IsAuto())
1184
                {
1185
                    if (prevChildren.Count == 0)
1186
                    {
1187
                        prevChildren.Add(child);
1188
                    }
1189
                    break;
1190
                }
1191
                if (child.IsStar())
1192
                {
1193
                    prevChildren.Add(child);
1194
                }
1195
            }
1196
 
1197
            List<FrameworkElement> nextChildren = new List<FrameworkElement>();
1198
 
1199
            for (i = iSplitter + 1; i < visibleChildren.Count; i++)
1200
            {
1201
                FrameworkElement child = visibleChildren[i] as FrameworkElement;
17 scott 1202
                if (child is Resizer)
7 scott 1203
                    continue;
1204
                if (child.IsAbsolute() || child.IsAuto())
1205
                {
1206
                    if (nextChildren.Count == 0)
1207
                        nextChildren.Add(child);
1208
                    break;
1209
                }
1210
                if (child.IsStar())
1211
                {
1212
                    nextChildren.Add(child);
1213
                }
1214
            }
1215
 
1216
 
1217
            double prevMinSize = prevChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? c.MinWidth : c.MinHeight);
1218
            double nextMinSize = nextChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? c.MinWidth : c.MinHeight);
1219
            double prevMaxSize = prevChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? c.MaxWidth : c.MaxHeight);
1220
            double nextMaxSize = nextChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? c.MaxWidth : c.MaxHeight);
1221
 
1222
            double prevSize = prevChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? currentSizes[visibleChildren.IndexOf(c)].Width : currentSizes[visibleChildren.IndexOf(c)].Height);
1223
            double nextSize = nextChildren.Sum<FrameworkElement>(c => Orientation == Orientation.Horizontal ? currentSizes[visibleChildren.IndexOf(c)].Width : currentSizes[visibleChildren.IndexOf(c)].Height);
1224
 
1225
            if (prevSize + delta < prevMinSize)
1226
                delta = prevMinSize - prevSize;
1227
            if (nextSize - delta < nextMinSize)
1228
                delta = -(nextMinSize - nextSize);
1229
 
1230
            double remDelta = delta * 2;
1231
 
1232
            while (!HelperFunc.AreClose(delta, 0.0))
1233
            {
1234
                int prevChildrenCountWithNoMinLen =
1235
                    prevChildren.Count<FrameworkElement>(c => delta > 0 ? true : (Orientation == Orientation.Horizontal ? currentSizes[visibleChildren.IndexOf(c)].Width > c.MinWidth : currentSizes[visibleChildren.IndexOf(c)].Height > c.MinHeight));
1236
                int nextChildrenCountWithNoMinLen =
1237
                    nextChildren.Count<FrameworkElement>(c => delta < 0 ? true : (Orientation == Orientation.Horizontal ? currentSizes[visibleChildren.IndexOf(c)].Width > c.MinWidth : currentSizes[visibleChildren.IndexOf(c)].Height > c.MinHeight));
17 scott 1238
 
7 scott 1239
                delta = remDelta / 2.0;
1240
 
1241
                for (i = 0; i < currentSizes.Length; i++)
1242
                {
1243
                    FrameworkElement child = visibleChildren[i] as FrameworkElement;
17 scott 1244
                    if (child is Resizer)
7 scott 1245
                        continue;
1246
 
1247
                    if (Orientation == Orientation.Horizontal)
1248
                    {
1249
                        if (prevChildren.Contains(child) && prevChildrenCountWithNoMinLen > 0)
1250
                        {
1251
                            double s = delta / prevChildrenCountWithNoMinLen;
1252
                            if (currentSizes[i].Width + s < child.MinWidth)
1253
                                s = child.MinWidth - currentSizes[i].Width;
17 scott 1254
 
7 scott 1255
                            currentSizes[i].Width += s;
1256
                            remDelta -= s;
1257
                        }
1258
                        if (nextChildren.Contains(child) && nextChildrenCountWithNoMinLen > 0)
1259
                        {
1260
                            double s = delta / nextChildrenCountWithNoMinLen;
1261
                            if (currentSizes[i].Width - s < child.MinWidth)
1262
                                s = currentSizes[i].Width - child.MinWidth;
1263
 
1264
                            currentSizes[i].Width -= s;
1265
                            remDelta -= s;
1266
                        }
1267
                    }
1268
                    else
1269
                    {
1270
                        if (prevChildren.Contains(child) && prevChildrenCountWithNoMinLen > 0)
1271
                        {
1272
                            double s = delta / prevChildrenCountWithNoMinLen;
1273
                            if (currentSizes[i].Height + s < child.MinHeight)
1274
                                s = child.MinHeight - currentSizes[i].Height;
1275
 
1276
                            currentSizes[i].Height += s;
1277
                            remDelta -= s;
1278
                        }
1279
                        if (nextChildren.Contains(child) && nextChildrenCountWithNoMinLen > 0)
1280
                        {
1281
                            double s = delta / nextChildrenCountWithNoMinLen;
1282
                            if (currentSizes[i].Height - s < child.MinHeight)
1283
                                s = currentSizes[i].Height - child.MinHeight;
1284
 
1285
                            currentSizes[i].Height -= s;
1286
                            remDelta -= s;
1287
                        }
1288
                    }
1289
                }
1290
            }
1291
 
1292
            Debug.Assert(HelperFunc.AreClose(delta, 0.0));
1293
 
1294
            double totalStartsSum = 0.0;
1295
            double totalSizeForStarts = 0.0;
1296
 
1297
            for (i = 0; i < visibleChildren.Count; i++)
17 scott 1298
            {
7 scott 1299
                FrameworkElement child = visibleChildren[i] as FrameworkElement;
17 scott 1300
                if (child is Resizer)
7 scott 1301
                    continue;
1302
                if (child.IsStar())
1303
                {
1304
                    totalStartsSum += child.GetStarValue();
1305
                    totalSizeForStarts += Orientation == Orientation.Horizontal ? currentSizes[i].Width : currentSizes[i].Height;
1306
                }
1307
            }
1308
 
1309
            double starsScaleFactor = totalStartsSum / totalSizeForStarts;
1310
 
1311
            for (i = 0; i < currentSizes.Length; i++)
1312
            {
1313
                FrameworkElement child = visibleChildren[i] as FrameworkElement;
1314
 
17 scott 1315
                if (child is Resizer)
7 scott 1316
                    continue;
1317
 
1318
                if (child.IsStar())
1319
                {
1320
                    if (Orientation == Orientation.Horizontal)
1321
                    {
1322
                        SetResizeWidth(child,
1323
                            new GridLength(HelperFunc.MultiplyCheckNaN(currentSizes[i].Width, starsScaleFactor), GridUnitType.Star));
1324
                    }
1325
                    else
1326
                    {
1327
                        SetResizeHeight(child,
1328
                            new GridLength(HelperFunc.MultiplyCheckNaN(currentSizes[i].Height, starsScaleFactor), GridUnitType.Star));
1329
                    }
1330
                }
1331
                else if (child.IsAbsolute())
1332
                {
1333
                    if (Orientation == Orientation.Horizontal)
1334
                    {
1335
                        SetResizeWidth(child,
1336
                            new GridLength(currentSizes[i].Width, GridUnitType.Pixel));
1337
                    }
1338
                    else
1339
                    {
1340
                        SetResizeHeight(child,
17 scott 1341
                            new GridLength(currentSizes[i].Height, GridUnitType.Pixel));
7 scott 1342
                    }
1343
                }
1344
            }
1345
 
1346
            InvalidateMeasure();
17 scott 1347
        }
7 scott 1348
 
17 scott 1349
        Border _resizerGhost = null;
1350
        Window _resizerWindowHost = null;
1351
        Vector _initialStartPoint;
7 scott 1352
 
17 scott 1353
        void ShowResizerOverlayWindow(Resizer splitter)
1354
        {
1355
            Point ptTopLeftScreen = this.PointToScreen(new Point());
7 scott 1356
 
17 scott 1357
            _resizerGhost = new Border()
1358
            {
1359
                Background = Brushes.Black,
1360
                Opacity = 0.7
1361
            };
7 scott 1362
 
17 scott 1363
            if (Orientation == System.Windows.Controls.Orientation.Horizontal)
1364
            {
1365
                _resizerGhost.Width = 5.0;
1366
                _resizerGhost.Height = ActualHeight;
1367
            }
1368
            else
1369
            {
1370
                _resizerGhost.Height = 5.0;
1371
                _resizerGhost.Width = ActualWidth;
1372
            }
7 scott 1373
 
17 scott 1374
            _initialStartPoint = splitter.PointToScreen(new Point()) - this.PointToScreen(new Point());
7 scott 1375
 
17 scott 1376
            if (Orientation == System.Windows.Controls.Orientation.Horizontal)
1377
            {
1378
                Canvas.SetLeft(_resizerGhost, _initialStartPoint.X);
1379
            }
1380
            else
1381
            {
1382
                Canvas.SetTop(_resizerGhost, _initialStartPoint.Y);
1383
            }
7 scott 1384
 
17 scott 1385
            Canvas panelHostResizer = new Canvas()
1386
            {
1387
                HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
1388
                VerticalAlignment = System.Windows.VerticalAlignment.Stretch
1389
            };
7 scott 1390
 
17 scott 1391
            panelHostResizer.Children.Add(_resizerGhost);
7 scott 1392
 
17 scott 1393
            _resizerWindowHost = new Window()
1394
            {
1395
                ResizeMode = ResizeMode.NoResize,
1396
                WindowStyle = System.Windows.WindowStyle.None,
1397
                ShowInTaskbar = false,
1398
                AllowsTransparency = true,
1399
                Background = null,
1400
                Width = ActualWidth,
1401
                Height = ActualHeight,
1402
                Left = ptTopLeftScreen.X,
1403
                Top = ptTopLeftScreen.Y,
1404
                ShowActivated = false,
1405
                Owner = Window.GetWindow(this),
1406
                Content = panelHostResizer
1407
            };
7 scott 1408
 
17 scott 1409
            _resizerWindowHost.Show();
7 scott 1410
        }
1411
 
17 scott 1412
        void HideResizerOverlayWindow()
7 scott 1413
        {
17 scott 1414
            if (_resizerWindowHost != null)
1415
            {
1416
                _resizerWindowHost.Close();
1417
                _resizerWindowHost = null;
1418
            }
7 scott 1419
        }
1420
 
1421
        #region IDockableControl Membri di
1422
 
1423
        public bool IsDocked
1424
        {
1425
            get
1426
            {
1427
                foreach (UIElement child in this.Children)
1428
                {
1429
                    if (child is IDockableControl)
1430
                        if (((IDockableControl)child).IsDocked)
1431
                            return true;
1432
                }
1433
 
1434
                return false;
1435
            }
1436
        }
1437
 
1438
        #endregion
1439
 
1440
 
1441
        /// <summary>
1442
        /// Remove a child from children collection
1443
        /// </summary>
1444
        /// <param name="childToRemove"></param>
1445
        internal void RemoveChild(FrameworkElement childToRemove)
1446
        {
1447
            int indexOfChildToRemove = Children.IndexOf(childToRemove);
1448
 
1449
            Debug.Assert(indexOfChildToRemove != -1);
1450
 
1451
            Children.RemoveAt(indexOfChildToRemove);
1452
 
1453
            if (Children.Count > 0)
1454
            {
1455
                SetupSplitters();
1456
 
1457
                if (Children.Count == 1)
1458
                {
1459
                    UIElement singleChild = this.Children[0];
1460
 
1461
                    if (Parent is ResizingPanel)
1462
                    {
1463
                        ResizingPanel parentPanel = Parent as ResizingPanel;
1464
                        if (parentPanel != null)
1465
                        {
1466
                            int indexOfThisPanel = parentPanel.Children.IndexOf(this);
1467
                            parentPanel.Children.RemoveAt(indexOfThisPanel);
1468
                            this.Children.Remove(singleChild);
1469
                            parentPanel.Children.Insert(indexOfThisPanel, singleChild);
1470
 
1471
                            if (parentPanel.Orientation == Orientation.Horizontal)
1472
                            {
1473
                                SetResizeWidth(singleChild, GetResizeWidth(this));
1474
                            }
1475
                            else
1476
                            {
1477
                                SetResizeHeight(singleChild, GetResizeHeight(this));
1478
                            }
1479
                        }
1480
                    }
1481
                    else if (Parent is DockingManager)
1482
                    {
1483
                        DockingManager manager = Parent as DockingManager;
1484
                        if (manager != null)
1485
                        {
1486
                            this.Children.Remove(singleChild);
1487
                            manager.Content = singleChild;
1488
                        }
1489
                    }
1490
 
1491
                }
1492
            }
1493
            else
1494
            {
1495
                ResizingPanel parentPanel = Parent as ResizingPanel;
1496
                if (parentPanel != null)
1497
                {
1498
                    parentPanel.RemoveChild(this);
1499
                }
1500
            }
1501
        }
1502
 
1503
        /// <summary>
1504
        /// Insert a new child element into the children collection.
1505
        /// </summary>
1506
        /// <param name="childToInsert">New child element to insert.</param>
1507
        /// <param name="relativeChild">Child after or before which <see cref="childToInsert"/> element must be insert.</param>
1508
        /// <param name="next">True if new child must be insert after the <see cref="relativeChild"/> element. False otherwise.</param>
1509
        internal void InsertChildRelativeTo(FrameworkElement childToInsert, FrameworkElement relativeChild, bool next)
1510
        {
1511
            int childRelativeIndex = Children.IndexOf(relativeChild);
1512
 
1513
            Debug.Assert(childRelativeIndex != -1);
1514
 
1515
            Children.Insert(
1516
                next ? childRelativeIndex + 1 : childRelativeIndex, childToInsert);
1517
 
1518
            SetupSplitters();
17 scott 1519
 
1520
            InvalidateMeasure();
7 scott 1521
        }
1522
 
17 scott 1523
 
7 scott 1524
 
17 scott 1525
 
7 scott 1526
    }
1527
 
1528
 
1529
    internal static class ResizingPanelExFuncs
1530
    {
1531
        public static double GetAbsoluteValue(this FrameworkElement child)
1532
        {
1533
            ResizingPanel parentPanel = LogicalTreeHelper.GetParent(child) as ResizingPanel;
1534
            GridLength len = parentPanel.Orientation == Orientation.Horizontal ? ResizingPanel.GetResizeWidth(child) : ResizingPanel.GetResizeHeight(child);
1535
            if (!len.IsAbsolute)
1536
                throw new InvalidOperationException();
1537
            return len.Value;
1538
        }
1539
 
1540
        public static double GetStarValue(this FrameworkElement child)
1541
        {
1542
            ResizingPanel parentPanel = LogicalTreeHelper.GetParent(child) as ResizingPanel;
1543
            GridLength len = parentPanel.Orientation == Orientation.Horizontal ? ResizingPanel.GetResizeWidth(child) : ResizingPanel.GetResizeHeight(child);
1544
            if (!len.IsStar)
1545
                throw new InvalidOperationException();
1546
            return len.Value;
1547
        }
1548
 
1549
        public static bool IsStar(this FrameworkElement child)
1550
        {
1551
            ResizingPanel parentPanel = LogicalTreeHelper.GetParent(child) as ResizingPanel;
1552
            return parentPanel.Orientation == Orientation.Horizontal ?
1553
                ResizingPanel.GetResizeWidth(child).IsStar :
1554
                ResizingPanel.GetResizeHeight(child).IsStar;
1555
        }
1556
        public static bool IsAbsolute(this FrameworkElement child)
1557
        {
1558
            ResizingPanel parentPanel = LogicalTreeHelper.GetParent(child) as ResizingPanel;
1559
            return parentPanel.Orientation == Orientation.Horizontal ?
1560
                ResizingPanel.GetResizeWidth(child).IsAbsolute :
1561
                ResizingPanel.GetResizeHeight(child).IsAbsolute;
1562
        }
1563
 
1564
        public static bool IsAuto(this FrameworkElement child)
1565
        {
1566
            ResizingPanel parentPanel = LogicalTreeHelper.GetParent(child) as ResizingPanel;
1567
            return parentPanel.Orientation == Orientation.Horizontal ?
1568
                ResizingPanel.GetResizeWidth(child).IsAuto :
1569
                ResizingPanel.GetResizeHeight(child).IsAuto;
1570
        }
1571
 
1572
    }
1573
 
1574
}