static void find_item(mdc::CanvasItem *item, const std::string &tag, mdc::CanvasItem **found_item) { if (*found_item) return; if (item->get_tag() == tag) { *found_item = item; return; } Layouter *sub = dynamic_cast<Layouter *>(item); if (sub) *found_item = sub->find_item_with_tag(tag); }
void BTwoDimensionalLayout::VerticalCompoundLayouter::DoLayout(float size, LocalLayouter* localLayouter, BLayoutContext* context) { Layouter* layouter; if (_HasHeightForWidth()) { float minHeight, maxHeight, preferredHeight; InternalGetHeightForWidth(localLayouter, context, true, &minHeight, &maxHeight, &preferredHeight); size = max_c(size, minHeight); layouter = fHeightForWidthLayouter; } else layouter = fLayouter; layouter->Layout(fLayoutInfo, size); }
void BSplitLayout::DoLayout() { _ValidateMinMax(); // layout the elements BSize size = _SubtractInsets(LayoutArea().Size()); fHorizontalLayouter->Layout(fHorizontalLayoutInfo, size.width); Layouter* verticalLayouter; if (HasHeightForWidth()) { float minHeight, maxHeight, preferredHeight; _InternalGetHeightForWidth(size.width, true, &minHeight, &maxHeight, &preferredHeight); size.height = max_c(size.height, minHeight); verticalLayouter = fHeightForWidthVerticalLayouter; } else verticalLayouter = fVerticalLayouter; verticalLayouter->Layout(fVerticalLayoutInfo, size.height); float xOffset = fLeftInset; float yOffset = fTopInset; float splitterWidth = 0; // pixel counts, no distances float splitterHeight = 0; // float xSpacing = 0; float ySpacing = 0; if (fOrientation == B_HORIZONTAL) { splitterWidth = fSplitterSize; splitterHeight = size.height + 1; xSpacing = fSpacing; } else { splitterWidth = size.width + 1; splitterHeight = fSplitterSize; ySpacing = fSpacing; } int itemCount = CountItems(); for (int i = 0; i < itemCount; i++) { // layout the splitter if (i > 0) { SplitterItem* splitterItem = _SplitterItemAt(i - 1); _LayoutItem(splitterItem, BRect(xOffset, yOffset, xOffset + splitterWidth - 1, yOffset + splitterHeight - 1), true); if (fOrientation == B_HORIZONTAL) xOffset += splitterWidth + xSpacing; else yOffset += splitterHeight + ySpacing; } // layout the item BLayoutItem* item = ItemAt(i); int32 visibleIndex = fVisibleItems.IndexOf(item); if (visibleIndex < 0) { _LayoutItem(item, BRect(), false); continue; } // get the dimensions of the item float width = fHorizontalLayoutInfo->ElementSize(visibleIndex); float height = fVerticalLayoutInfo->ElementSize(visibleIndex); // place the component _LayoutItem(item, BRect(xOffset, yOffset, xOffset + width, yOffset + height), true); if (fOrientation == B_HORIZONTAL) xOffset += width + xSpacing + 1; else yOffset += height + ySpacing + 1; } fLayoutValid = true; }
void BSplitLayout::_InternalGetHeightForWidth(float width, bool realLayout, float* minHeight, float* maxHeight, float* preferredHeight) { if ((realLayout && fHeightForWidthVerticalLayouterWidth != width) || (!realLayout && fCachedHeightForWidthWidth != width)) { // The general strategy is to clone the vertical layouter, which only // knows the general min/max constraints, do a horizontal layout for the // given width, and add the children's height for width constraints to // the cloned vertical layouter. If this method is invoked internally, // we keep the cloned vertical layouter, for it will be used for doing // the layout. Otherwise we just drop it after we've got the height for // width info. // clone the vertical layouter and get the horizontal layout info to be used LayoutInfo* horizontalLayoutInfo = NULL; Layouter* verticalLayouter = fVerticalLayouter->CloneLayouter(); if (realLayout) { horizontalLayoutInfo = fHorizontalLayoutInfo; delete fHeightForWidthVerticalLayouter; fHeightForWidthVerticalLayouter = verticalLayouter; delete fVerticalLayoutInfo; fVerticalLayoutInfo = verticalLayouter->CreateLayoutInfo(); fHeightForWidthVerticalLayouterWidth = width; } else { if (fHeightForWidthHorizontalLayoutInfo == NULL) { delete fHeightForWidthHorizontalLayoutInfo; fHeightForWidthHorizontalLayoutInfo = fHorizontalLayouter->CreateLayoutInfo(); } horizontalLayoutInfo = fHeightForWidthHorizontalLayoutInfo; } // do the horizontal layout (already done when doing this for the real // layout) if (!realLayout) fHorizontalLayouter->Layout(horizontalLayoutInfo, width); // add the children's height for width constraints int32 count = fHeightForWidthItems.CountItems(); for (int32 i = 0; i < count; i++) { BLayoutItem* item = (BLayoutItem*)fHeightForWidthItems.ItemAt(i); int32 index = fVisibleItems.IndexOf(item); if (index >= 0) { float itemMinHeight, itemMaxHeight, itemPreferredHeight; item->GetHeightForWidth( horizontalLayoutInfo->ElementSize(index), &itemMinHeight, &itemMaxHeight, &itemPreferredHeight); verticalLayouter->AddConstraints(index, 1, itemMinHeight, itemMaxHeight, itemPreferredHeight); } } // get the height for width info fCachedHeightForWidthWidth = width; fCachedMinHeightForWidth = verticalLayouter->MinSize(); fCachedMaxHeightForWidth = verticalLayouter->MaxSize(); fCachedPreferredHeightForWidth = verticalLayouter->PreferredSize(); } if (minHeight) *minHeight = fCachedMinHeightForWidth; if (maxHeight) *maxHeight = fCachedMaxHeightForWidth; if (preferredHeight) *preferredHeight = fCachedPreferredHeightForWidth; }