#if FRAMEWORK20 using System.Collections; using System.Collections.Generic; using System.Drawing; using DevComponents.UI.ContentManager; namespace DevComponents.DotNetBar { public class SuperTabItemLayoutManager : BlockLayoutManager { #region Private variables private int _SelLine; private Size _CloseButtonSize = new Size(16, 16); private Size _FixedTabSize = Size.Empty; private Size _TabLayoutOffset = Size.Empty; private SuperTabStripItem _TabStripItem; private Dictionary _List; #endregion /// /// Constructor /// public SuperTabItemLayoutManager() { } /// /// Constructor /// /// Associated SuperTabStripItem public SuperTabItemLayoutManager(SuperTabStripItem tabStripItem) { _TabStripItem = tabStripItem; _List = new Dictionary(); } #region Public properties /// /// gets or sets the FixedTabSize /// public Size FixedTabSize { get { return _FixedTabSize; } set { _FixedTabSize = value; } } /// /// Gets or sets the TabLayoutOffset /// public Size TabLayoutOffset { get { return _TabLayoutOffset; } set { _TabLayoutOffset = value; } } #endregion #region Internal properties /// /// Gets the TabDisplay /// internal SuperTabStripBaseDisplay TabDisplay { get { return (_TabStripItem.TabDisplay); } } #endregion #region Layout /// /// Resizes the content block and sets it's Bounds property to reflect new size. /// /// Content block to resize. /// public override void Layout(IBlock block, Size availableSize) { if (block.Visible == true) { if (block is SuperTabItem) LayoutTab(block as SuperTabItem); else if (block is BaseItem) LayoutBaseItem(block as BaseItem); } } #region LayoutTab private void LayoutTab(SuperTabItem tab) { Size size = new Size(); Rectangle bounds = Rectangle.Empty; if (_FixedTabSize.Width <= 0 || _FixedTabSize.Height <= 0 || tab.TextMarkupBody != null) { size = MeasureTab(tab); } // If the user has set a FixedTabSize, then apply it if (tab.FixedTabSize.Width > 0) size.Width = tab.FixedTabSize.Width; else if (_FixedTabSize.Width > 0) size.Width = _FixedTabSize.Width; if (tab.FixedTabSize.Height > 0) size.Height = tab.FixedTabSize.Height; else if (_FixedTabSize.Height > 0) size.Height = _FixedTabSize.Height; // Make sure we keep the tab size within the tab style minimum Size minSize = TabDisplay.MinTabSize; if (size.Width < minSize.Width) size.Width = minSize.Width; if (size.Height < minSize.Height) size.Height = minSize.Height; bounds.Size = (tab.IsVertical == true) ? new Size(size.Height, size.Width) : size; // Let the user have one last crack at measuring the tab bounds.Size = _TabStripItem.OnMeasureTabItem(tab, bounds.Size, Graphics); tab.Bounds = bounds; tab.RecalcSize(); } #endregion #region MeasureTab /// /// Measures the given tab /// /// /// private Size MeasureTab(SuperTabItem tab) { Size size = new Size(0, 0); // Measure the tab Text Font font = GetSizingFont(Graphics, tab); Size textSize = (tab.TextMarkupBody != null) ? MeasureMarkup(tab, Graphics, font) : MeasureText(tab, Graphics, font); textSize.Width += _TabLayoutOffset.Width; textSize.Height += _TabLayoutOffset.Height; bool displayText = (tab.IsSelected || _TabStripItem.DisplaySelectedTextOnly == false); // Add in our overlap, spacing, and selection padding if (_TabStripItem.IsVertical == false || _TabStripItem.HorizontalText == false) { if (displayText == true) size.Width += (textSize.Width + _TabStripItem.TabHorizontalSpacing); if (textSize.Height > size.Height) size.Height = textSize.Height; size.Width += (TabDisplay.TabOverlap + TabDisplay.TabSpacing); } else { if (displayText == true) { if (textSize.Height > size.Height) size.Height = textSize.Height; } size.Height += (TabDisplay.TabOverlap + TabDisplay.TabSpacing); size.Width += (textSize.Width + _TabStripItem.TabHorizontalSpacing + TabDisplay.SelectedPaddingWidth); } // Add in any image space needed size = GetSizeWithImage(tab, size); // Add in the Close Button if (TabDisplay.CloseButtonOnTabs && tab.CloseButtonVisible) { size.Width += (_CloseButtonSize.Width + _TabStripItem.TabHorizontalSpacing); if (size.Height < _CloseButtonSize.Height + _TabStripItem.TabVerticalSpacing) size.Height = _CloseButtonSize.Height + _TabStripItem.TabVerticalSpacing; if (size.Height < _CloseButtonSize.Height + 4) size.Height = _CloseButtonSize.Height + 4; } // Add our default spacing _TabStripItem.TabDisplay.AddDefaultPadding(ref size); return (size); } #region GetSizingFont private Font GetSizingFont(Graphics g, SuperTabItem tab) { if (tab.SizingFont == null) { Size selectedSize = Size.Empty; Font sfont = tab.SelectedFont; if (sfont != null) { selectedSize = (tab.TextMarkupBody != null) ? MeasureMarkup(tab, g, sfont) : MeasureText(tab, g, sfont); } Size unselectedSize = Size.Empty; Font unsfont = tab.UnselectedFont; if (unsfont != null) { unselectedSize = (tab.TextMarkupBody != null) ? MeasureMarkup(tab, g, unsfont) : MeasureText(tab, g, unsfont); } tab.SizingFont = (selectedSize.Width > unselectedSize.Width) ? sfont : unsfont; } return (tab.SizingFont); } #endregion #region GetSizeWithImage private Size GetSizeWithImage(SuperTabItem tab, Size size) { Size imageSize = Size.Empty; if (string.IsNullOrEmpty(tab.SymbolRealized) == false) { imageSize = tab.GetSymbolSize(); } else { CompositeImage tabImage = tab.GetTabImage(); if (tabImage != null) imageSize = tabImage.Size; } if (imageSize.IsEmpty == false) { int h = _TabStripItem.TabVerticalSpacing + tab.ImagePadding.Vertical; int w = _TabStripItem.TabHorizontalSpacing + tab.ImagePadding.Horizontal; switch (tab.EffectiveImageAlignment) { case ImageAlignment.TopLeft: case ImageAlignment.TopCenter: case ImageAlignment.TopRight: case ImageAlignment.BottomLeft: case ImageAlignment.BottomCenter: case ImageAlignment.BottomRight: size.Height += (imageSize.Height + h); break; case ImageAlignment.MiddleLeft: case ImageAlignment.MiddleRight: size.Width += (imageSize.Width + w); if (size.Height < imageSize.Height + h) size.Height = imageSize.Height + h; break; case ImageAlignment.MiddleCenter: if (size.Width < imageSize.Width + w) size.Width = imageSize.Width + w; if (size.Height < imageSize.Height + h) size.Height = imageSize.Height + h; break; } if (_TabStripItem.IsVertical == true && _TabStripItem.HorizontalText == true) { int n = imageSize.Height + _TabStripItem.TabDisplay.TabOverlap + _TabStripItem.TabDisplay.TabSpacing + 4; if (size.Height < n) size.Height = n; } } return (size); } #endregion #endregion #region MeasureMarkup /// /// Measures the markup text /// /// /// /// /// private Size MeasureMarkup(SuperTabItem tab, Graphics g, Font font) { TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(g, font, Color.Black, false); Size size = new Size(5000, 5000); tab.TextMarkupBody.InvalidateElementsSize(); tab.TextMarkupBody.Measure(size, d); d.RightToLeft = _TabStripItem.IsRightToLeft; tab.TextMarkupBody.Arrange(new Rectangle(Point.Empty, tab.TextMarkupBody.Bounds.Size), d); size = tab.TextMarkupBody.Bounds.Size; return (size); } #endregion #region MeasureText /// /// Measures the given text /// /// /// /// /// private Size MeasureText(SuperTabItem tab, Graphics g, Font font) { string text = string.IsNullOrEmpty(tab.Text) ? "M" : tab.Text; Size textSize = tab.IsVertical ? TextDrawing.MeasureStringLegacy(g, text, font, Size.Empty, eTextFormat.Default) : TextDrawing.MeasureString(g, text, font, 0, eTextFormat.Default); return (textSize); } #endregion #region LayoutBaseItem private void LayoutBaseItem(BaseItem item) { Size size = new Size(); Rectangle bounds = Rectangle.Empty; if (_FixedTabSize.Width <= 0 || _FixedTabSize.Height <= 0 || (item is ButtonItem && ((ButtonItem)item).FixedSize.IsEmpty)) { item.RecalcSize(); size = item.Bounds.Size; size.Width += _TabLayoutOffset.Width; size.Height += _TabLayoutOffset.Height; size.Width += _TabStripItem.ItemPadding.Horizontal; size.Height += _TabStripItem.ItemPadding.Vertical; } if (_FixedTabSize.Width > 0) size.Width = _FixedTabSize.Width; if (_FixedTabSize.Height > 0) size.Height = _FixedTabSize.Height; if (!(item is ButtonItem && !((ButtonItem)item).FixedSize.IsEmpty)) { bounds.Size = size; item.Bounds = bounds; } if (item.Stretch == false) _List[item] = size; } #endregion #endregion #region FinalizeLayout /// /// Finalizes the layout /// /// /// /// /// public override Rectangle FinalizeLayout( Rectangle containerBounds, Rectangle blocksBounds, ArrayList lines) { if (lines.Count > 1) { int line = FindSelectedLine(lines); ReorderLines(lines, line); SetBlockDisplay(containerBounds, lines); ResizeMultiLine(lines); } else { SetBlockDisplay(containerBounds, lines); PromoteSelectedTab(containerBounds, lines); ResizeSingleLine(lines); } _TabStripItem.TabLines = lines.Count; _List.Clear(); return (blocksBounds); } #endregion #region ReorderLines /// /// Reorders the lines to keep the selected tab as line 0. /// /// /// private void ReorderLines(ArrayList lines, int line) { _SelLine = 0; switch (_TabStripItem.TabAlignment) { case eTabStripAlignment.Top: case eTabStripAlignment.Left: line++; _SelLine = lines.Count - line; break; default: _SelLine = line; break; } if (_SelLine > 0) AdjustLines(lines, line); } #region AdjustLines /// /// Adjusts the line layout /// /// /// private void AdjustLines(ArrayList lines, int n) { Size[] szs = GetLineSizes(lines); Point pt = new Point(); for (int i = 0; i < lines.Count; i++) { int t = (i + n) % lines.Count; SerialContentLayoutManager.BlockLineInfo info = lines[t] as SerialContentLayoutManager.BlockLineInfo; if (info != null) { AdjustBlocks(info, pt); pt.X += szs[t].Width; pt.Y += szs[t].Height; } } } #endregion #region GetLineSizes /// /// Gets the array od line sizes /// /// /// private Size[] GetLineSizes(ArrayList lines) { Size[] szs = new Size[lines.Count]; for (int i = 0; i < lines.Count; i++) { SerialContentLayoutManager.BlockLineInfo info = lines[i] as SerialContentLayoutManager.BlockLineInfo; if (info != null) { IBlock item = info.Blocks[0] as IBlock; if (item != null) szs[i] = item.Bounds.Size; } } return (szs); } #endregion #region AdjustBlocks /// /// Adjusts the individual blocks within a given line /// /// /// private void AdjustBlocks(SerialContentLayoutManager.BlockLineInfo info, Point pt) { for (int i = 0; i < info.Blocks.Count; i++) { BaseItem item = info.Blocks[i] as BaseItem; if (item != null) { switch (_TabStripItem.TabAlignment) { case eTabStripAlignment.Top: case eTabStripAlignment.Bottom: item.TopInternal = pt.Y; break; default: item.LeftInternal = pt.X; break; } } } } #endregion #endregion #region SetBlockDisplay #region SetBlockDisplay /// /// Sets the Displayed status for the line blocks /// /// /// private void SetBlockDisplay( Rectangle containerBounds, ArrayList lines) { for (int i = 0; i < lines.Count; i++) { SerialContentLayoutManager.BlockLineInfo info = lines[i] as SerialContentLayoutManager.BlockLineInfo; if (info != null) { bool checkBreaks = true; // Set each item's display state, and // align each item if they aren't being stretched for (int j = 0; j < info.Blocks.Count; j++) { BaseItem item = info.Blocks[j] as BaseItem; if (item != null) { bool displayed = item.Visible; if (info.Blocks.Count > 1 && containerBounds.Contains(item.Bounds) == false) { checkBreaks = false; displayed = false; } item.Displayed = displayed; if (item.Displayed == true) AlignBaseItem(item); } } // Check item breaks, if we have extra // room to spare if (checkBreaks == true) { Size size; int count = GetBreakCount(info, out size); if (count > 0) { if (_TabStripItem.IsVertical) ProcessBreaks(info, count, containerBounds.Height - size.Height, true); else ProcessBreaks(info, count, containerBounds.Width - size.Width, false); } } } } } #endregion #region AlignBaseItem private void AlignBaseItem(BaseItem item) { Rectangle r = item.Bounds; if (item.Stretch == false) { Size size; if (_List.TryGetValue(item, out size) == true) { r.Size = size; r.Y = item.Bounds.Y + (item.Bounds.Height - r.Height)/2; switch (item.ItemAlignment) { case eItemAlignment.Center: r.X += (item.Bounds.Width - r.Width)/2; break; case eItemAlignment.Far: r.X = item.Bounds.Right - r.Width; break; } } } // Take user specified padding into account // for all non-SuperTabItems only if (item is SuperTabItem == false) { r.X += _TabStripItem.ItemPadding.Left; r.Y += _TabStripItem.ItemPadding.Top; r.Width -= (_TabStripItem.ItemPadding.Horizontal); r.Height -= (_TabStripItem.ItemPadding.Vertical); } item.Bounds = r; } #endregion #region GetBreakCount /// /// Gets the count of BeginBreak groups /// /// /// /// private int GetBreakCount( SerialContentLayoutManager.BlockLineInfo info, out Size size) { int cnt = 0; size = Size.Empty; for (int i = 0; i < info.Blocks.Count; i++) { BaseItem item = info.Blocks[i] as BaseItem; if (item != null) { if (item.Displayed == true) { size.Width = item.Bounds.Right; size.Height = item.Bounds.Bottom; if (item.BeginGroup == true) cnt++; } } } return (cnt); } #endregion #region ProcessBreaks /// /// Process item BeginBreaks /// /// /// /// /// private void ProcessBreaks(SerialContentLayoutManager.BlockLineInfo info, int count, int span, bool vertical) { int dcnt = 0; float delta = 0; float n = (float) span / count; for (int i = 0; i < info.Blocks.Count; i++) { BaseItem item = info.Blocks[i] as BaseItem; if (item != null && item.Displayed == true) { if (item.BeginGroup == true) delta = (++dcnt == count) ? span : delta + n; if (delta > 0) { if (vertical == true) item.TopInternal += (int) delta; else item.LeftInternal += (int) delta; } } } } #endregion #endregion #region PromoteSelectedTab /// /// Makes sure the "VisibleTab" is in fact visible. /// /// /// private void PromoteSelectedTab(Rectangle containerBounds, ArrayList lines) { BaseItem vItem = _TabStripItem.VisibleTab; if (vItem != null && vItem.Displayed == false) { SerialContentLayoutManager.BlockLineInfo info = lines[0] as SerialContentLayoutManager.BlockLineInfo; if (info != null) { for (int i = info.Blocks.Count - 1; i >= 0; i--) { BaseItem item = info.Blocks[i] as BaseItem; if (item != null) { Rectangle r = _TabStripItem.TabDisplay.NextBlockPosition(item, vItem); if (containerBounds.Contains(r) == true) { vItem.Bounds = r; vItem.Displayed = true; break; } item.Displayed = false; if (i == 0) { r = item.Bounds; r.Size = vItem.Size; vItem.Bounds = r; vItem.Displayed = true; } } } } } } #endregion #region FindSelectedLine /// /// Determines what line th selected tab lies within /// /// /// private int FindSelectedLine(ArrayList lines) { for (int i = 0; i < lines.Count; i++) { SerialContentLayoutManager.BlockLineInfo line = lines[i] as SerialContentLayoutManager.BlockLineInfo; if (line != null) { int iBlock = FindSelectedBlock(line.Blocks); if (iBlock >= 0) return (i); } } return (-1); } #endregion #region FindSelectedBlock /// /// Finds the SelectedTab block /// /// /// private int FindSelectedBlock(ArrayList blocks) { for (int i = 0; i < blocks.Count; i++) { SuperTabItem tab = blocks[i] as SuperTabItem; if (tab != null) { if (tab == _TabStripItem.SelectedTab) return (i); } } return (-1); } #endregion #region ResizeSingleLine /// /// Resizes single line layouts /// /// private void ResizeSingleLine(ArrayList lines) { SerialContentLayoutManager.BlockLineInfo info = lines[0] as SerialContentLayoutManager.BlockLineInfo; if (info != null) { switch (_TabStripItem.TabAlignment) { case eTabStripAlignment.Top: ResizeSingleLine1(info, 0, _TabLayoutOffset.Height, 0, -_TabLayoutOffset.Height); break; case eTabStripAlignment.Left: ResizeSingleLine1(info, _TabLayoutOffset.Width, 0, -_TabLayoutOffset.Width, 0); break; case eTabStripAlignment.Bottom: ResizeSingleLine2(info, 0, 2, 0, -_TabLayoutOffset.Height); break; case eTabStripAlignment.Right: ResizeSingleLine2(info, 2, 0, -_TabLayoutOffset.Width, 0); break; } } } #region ResizeSingleLine1 private void ResizeSingleLine1( SerialContentLayoutManager.BlockLineInfo info, int dx, int dy, int dw, int dh) { for (int i = 0; i < info.Blocks.Count; i++) { BaseItem item = info.Blocks[i] as BaseItem; if (item != null) { SuperTabItem tab = info.Blocks[i] as SuperTabItem; if (tab == null || tab.IsSelected == false) { Rectangle r = item.Bounds; r.X += dx; r.Y += dy; r.Width += dw; r.Height += dh; item.Bounds = r; } } } } #endregion #region ResizeSingleLine2 private void ResizeSingleLine2( SerialContentLayoutManager.BlockLineInfo info, int dx, int dy, int dw, int dh) { for (int i = 0; i < info.Blocks.Count; i++) { BaseItem item = info.Blocks[i] as BaseItem; if (item != null) { Rectangle r = item.Bounds; SuperTabItem tab = info.Blocks[i] as SuperTabItem; r.X += dx; r.Y += dy; if (tab == null || tab.IsSelected == false) { r.Width += dw; r.Height += dh; } item.Bounds = r; } } } #endregion #endregion #region ResizeMultiLine /// /// Resizes multiline layouts /// /// private void ResizeMultiLine(ArrayList lines) { switch (_TabStripItem.TabAlignment) { case eTabStripAlignment.Top: ResizeMultiLineTop(); break; case eTabStripAlignment.Left: ResizeMultiLineLeft(); break; case eTabStripAlignment.Bottom: ResizeMultiLineBottom(lines); break; case eTabStripAlignment.Right: ResizeMultiLineRight(lines); break; } } #region ResizeMultiLineTop private void ResizeMultiLineTop() { if (_TabStripItem.SelectedTab != null) { Rectangle r = _TabStripItem.SelectedTab.Bounds; r.Y -= _TabLayoutOffset.Height; r.Height += _TabLayoutOffset.Height; _TabStripItem.SelectedTab.Bounds = r; } } #endregion #region ResizeMultiLineLeft private void ResizeMultiLineLeft() { if (_TabStripItem.SelectedTab != null) { Rectangle r = _TabStripItem.SelectedTab.Bounds; r.X -= _TabLayoutOffset.Width; r.Width += _TabLayoutOffset.Width; _TabStripItem.SelectedTab.Bounds = r; } } #endregion #region ResizeMultiLineBottom private void ResizeMultiLineBottom(ArrayList lines) { for (int i = 0; i < lines.Count; i++) { SerialContentLayoutManager.BlockLineInfo info = lines[i] as SerialContentLayoutManager.BlockLineInfo; if (info != null) { for (int j = 0; j < info.Blocks.Count; j++) { BaseItem item = info.Blocks[j] as BaseItem; if (item != null) { Rectangle r = item.Bounds; r.Y += 2; SuperTabItem tab = info.Blocks[j] as SuperTabItem; if (tab != null && tab.IsSelected == true) r.Height += _TabLayoutOffset.Height; item.Bounds = r; } } } } } #endregion #region ResizeMultiLineRight private void ResizeMultiLineRight(ArrayList lines) { for (int i = 0; i < lines.Count; i++) { SerialContentLayoutManager.BlockLineInfo info = lines[i] as SerialContentLayoutManager.BlockLineInfo; if (info != null) { for (int j = 0; j < info.Blocks.Count; j++) { BaseItem item = info.Blocks[j] as BaseItem; if (item != null) { Rectangle r = item.Bounds; r.X += 2; SuperTabItem tab = info.Blocks[j] as SuperTabItem; if (tab != null && tab.IsSelected == true) r.Width += _TabLayoutOffset.Width; item.Bounds = r; } } } } } #endregion #endregion } } #endif