/// <summary> /// Measure the tab items for docking at the left or right /// </summary> private Size MeasureVertical(Size availableSize) { int childCount = InternalChildren.Count; double maxChildWidthOrHeight = 0d; EnsureChildRects(); double extentHeight = 0d; double[] heights = new double[childCount]; // we will first measure all the children with unlimited space to get their desired sizes // this will also get us the height required for all TabItems for (int i = 0; i < childCount; i++) { TabItem tabItem = InternalChildren[i] as TabItem; if (tabItem == null) { return(new Size()); } SetDimensions(tabItem); tabItem.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); ClearDimensions(tabItem); // calculate the maximum child width maxChildWidthOrHeight = Math.Max(maxChildWidthOrHeight, Math.Ceiling(tabItem.DesiredSize.Width)); // calculate the child width while respecting the Maximum & Minimum width constraints heights[i] = Math.Min(MaximumChildHeight, Math.Max(MinimumChildHeight, Math.Ceiling(tabItem.DesiredSize.Height))); // determines how much horizontal space we require extentHeight += heights[i]; } maxChildWidthOrHeight = Math.Max(MinimumChildWidth, Math.Min(MaximumChildWidth, maxChildWidthOrHeight)); // observe the constraints _extent = new Size(maxChildWidthOrHeight, extentHeight); bool flag = false; // 1). all the children fit into the available space using there desired widths if (extentHeight <= availableSize.Height) { _maxVisibleItems = childCount; FirstVisibleIndex = 0; double top = 0; for (int i = 0; i < childCount; i++) { _childRects[i] = new Rect(0, top, maxChildWidthOrHeight, heights[i]); top += heights[i]; FrameworkElement child = InternalChildren[i] as FrameworkElement; if (child != null) { child.Measure(new Size(maxChildWidthOrHeight, heights[i])); } } CanScrollLeftOrUp = false; CanScrollRightOrDown = false; flag = true; } // 2). all the children fit in the available space if we reduce their widths to a uniform value // while staying within the MinimumChildWidth and MaximumChildWidth constraints if (!flag) { // make sure the width is not greater than the MaximumChildWidth constraints double targetHeight = Math.Min(MaximumChildHeight, availableSize.Height / childCount); // target width applies now if whether we can fit all items in the available space or whether we are scrolling if (targetHeight >= MinimumChildHeight) { _maxVisibleItems = childCount; FirstVisibleIndex = 0; extentHeight = 0; double top = 0; for (int i = 0; i < childCount; i++) { extentHeight += targetHeight; heights[i] = targetHeight; _childRects[i] = new Rect(0, top, maxChildWidthOrHeight, heights[i]); top += heights[i]; FrameworkElement child = InternalChildren[i] as FrameworkElement; if (child != null) { child.Measure(new Size(maxChildWidthOrHeight, heights[i])); } } _extent = new Size(maxChildWidthOrHeight, extentHeight); flag = true; CanScrollLeftOrUp = false; CanScrollRightOrDown = false; } } // 3) we can not fit all the children in the viewport, so now we will enable scrolling/virtualizing items if (!flag) { _maxVisibleItems = (int)Math.Floor(_viewPort.Height / MinimumChildHeight); // calculate how many visible children we can show at once double targetHeight = availableSize.Height / _maxVisibleItems; // calculate the new target width FirstVisibleIndex = _firstVisibleIndex; extentHeight = 0; double top = 0; for (int i = 0; i < childCount; i++) { extentHeight += targetHeight; heights[i] = targetHeight; _childRects[i] = new Rect(0, top, maxChildWidthOrHeight, heights[i]); top += heights[i]; FrameworkElement child = InternalChildren[i] as FrameworkElement; if (child != null) { child.Measure(new Size(maxChildWidthOrHeight, heights[i])); } } _extent = new Size(maxChildWidthOrHeight, extentHeight); CanScrollLeftOrUp = LastVisibleIndex < childCount - 1; CanScrollRightOrDown = FirstVisibleIndex > 0; } return(new Size(maxChildWidthOrHeight, double.IsInfinity(availableSize.Height) ? _extent.Height : availableSize.Height)); }
/// <summary> /// Measure the tab items for docking at the top or bottom /// </summary> private Size MeasureHorizontal(Size availableSize) { double maxChildWidthOrHeight = 0d; int childCount = InternalChildren.Count; EnsureChildRects(); double extentWidth = 0d; double[] widths = new double[childCount]; // stores the widths of the items for use in the arrange pass for (int i = 0; i < childCount; i++) { TabItem tabItem = InternalChildren[i] as TabItem; if (tabItem == null) { return(new Size()); } SetDimensions(tabItem); tabItem.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); ClearDimensions(tabItem); // calculate the maximum child height maxChildWidthOrHeight = Math.Max(maxChildWidthOrHeight, Math.Ceiling(tabItem.DesiredSize.Height)); // calculate the child width while respecting the Maximum & Minimum width constraints widths[i] = Math.Min(MaximumChildWidth, Math.Max(MinimumChildWidth, Math.Ceiling(tabItem.DesiredSize.Width))); // determines how much horizontal space we require extentWidth += widths[i]; } maxChildWidthOrHeight = Math.Max(MinimumChildHeight, Math.Min(MaximumChildHeight, maxChildWidthOrHeight)); // observe the constraints _extent = new Size(extentWidth, maxChildWidthOrHeight); bool flag = false; // 1). all the children fit into the available space using there desired widths if (extentWidth <= availableSize.Width) { _maxVisibleItems = childCount; FirstVisibleIndex = 0; double left = 0; for (int i = 0; i < childCount; i++) { _childRects[i] = new Rect(left, 0, widths[i], maxChildWidthOrHeight); left += widths[i]; FrameworkElement child = InternalChildren[i] as FrameworkElement; if (child != null) { child.Measure(new Size(widths[i], maxChildWidthOrHeight)); } } CanScrollLeftOrUp = false; CanScrollRightOrDown = false; flag = true; } // 2). all the children fit in the available space if we reduce their widths to a uniform value // while staying within the MinimumChildWidth and MaximumChildWidth constraints if (!flag) { // make sure the width is not greater than the MaximumChildWidth constraints double targetWidth = Math.Min(MaximumChildWidth, availableSize.Width / childCount); // target width applies now if whether we can fit all items in the available space or whether we are scrolling if (targetWidth >= MinimumChildWidth) { _maxVisibleItems = childCount; FirstVisibleIndex = 0; extentWidth = 0; double left = 0; for (int i = 0; i < childCount; i++) { extentWidth += targetWidth; widths[i] = targetWidth; _childRects[i] = new Rect(left, 0, widths[i], maxChildWidthOrHeight); left += widths[i]; FrameworkElement child = InternalChildren[i] as FrameworkElement; if (child != null) { child.Measure(new Size(widths[i], maxChildWidthOrHeight)); } } _extent = new Size(extentWidth, maxChildWidthOrHeight); flag = true; CanScrollLeftOrUp = false; CanScrollRightOrDown = false; } } // 3) we can not fit all the children in the viewport, so now we will enable scrolling/virtualizing items if (!flag) { _maxVisibleItems = (int)Math.Floor(_viewPort.Width / MinimumChildWidth); // calculate how many visible children we can show at once if (_maxVisibleItems == 0) { _maxVisibleItems = 1; } double targetWidth = availableSize.Width / _maxVisibleItems; // calculate the new target width FirstVisibleIndex = _firstVisibleIndex; extentWidth = 0; double left = 0; for (int i = 0; i < childCount; i++) { extentWidth += targetWidth; widths[i] = targetWidth; _childRects[i] = new Rect(left, 0, widths[i], maxChildWidthOrHeight); left += widths[i]; FrameworkElement child = InternalChildren[i] as FrameworkElement; if (child != null) { child.Measure(new Size(widths[i], maxChildWidthOrHeight)); } } _extent = new Size(extentWidth, maxChildWidthOrHeight); CanScrollLeftOrUp = LastVisibleIndex < childCount - 1; CanScrollRightOrDown = FirstVisibleIndex > 0; } return(new Size(double.IsInfinity(availableSize.Width) ? _extent.Width : availableSize.Width, maxChildWidthOrHeight)); }