/// <summary>Positions this element and all it's children relative to their parent.</summary> public void PositionLocally() { // This is the first pass of layout requests. // It locates elements locally whilst also finding their width and height. ComputedStyle computed = Style.Computed; if (computed.Display == DisplayType.None) { // Don't draw this element or it's kids. return; } if (!IsRebuildingChildren) { // Update child nodes (thread safety): KidsToRender = ChildNodes; } float depth = Document.Renderer.Depth; float maxDepth = Document.Renderer.MaxDepth; bool elementPositioned = false; if (!computed.FixedDepth) { elementPositioned = (computed.IsOffset() || computed.Position != PositionType.Relative); if (elementPositioned) { // This element has been positioned - make sure it's ontop of the current highest element: Document.Renderer.Depth = Document.Renderer.MaxDepth; if (Document.Renderer.DepthUsed) { Document.Renderer.IncreaseDepth(); } else { Document.Renderer.DepthUsed = true; } computed.ZIndex = Document.Renderer.Depth; } else { computed.ZIndex = depth; } } else { computed.ZIndex = computed.FixedZIndex; } if (KidsToRender != null || HScrollbar || VScrollbar) { if (computed.FixedDepth) { // Set the depth buffer to this element so it's kids are at the right height; restore it after. // Offset by the document's depth if we're in a document in a document (e.g. iframe): Element documentParent = Document.html.parentNode; if (documentParent != null && documentParent != this) { computed.ZIndex += documentParent.Style.Computed.ZIndex; } Document.Renderer.Depth = computed.ZIndex; if (computed.ZIndex > Document.Renderer.MaxDepth) { Document.Renderer.MaxDepth = Document.Renderer.Depth; } } else if (computed.BGImage != null || computed.BGColour != null) { // Only increase the depth if the element has a background image/colour to get it's kids away from. Document.Renderer.IncreaseDepth(); } } if (KidsToRender != null) { for (int i = 0; i < KidsToRender.Count; i++) { KidsToRender[i].PositionLocally(); } } if (HScrollbar) { HorizontalScrollbar.Element.PositionLocally(); } if (VScrollbar) { VerticalScrollbar.Element.PositionLocally(); } // Restore the depth: if (elementPositioned) { // This element has been positioned - everything after it must be ontop of it and all it's kids. Document.Renderer.Depth = Document.Renderer.MaxDepth; Document.Renderer.IncreaseDepth(); } else if (computed.FixedDepth) { Document.Renderer.Depth = depth; Document.Renderer.MaxDepth = maxDepth; } if (computed.Display == Css.DisplayType.Inline && computed.Position == Css.PositionType.Relative) { // Relative Inline - The kids will be packed onto the next element up's lines (this is done internally by the PackOnLine function). // Fixed or absolute pack their own lines. if (computed.BGImage == null && computed.BGColour == null && computed.Border == null) { // Only occurs though if the element has no background or border - if it does, it should act like an inline-block element. return; } } Document.Renderer.BeginLinePack(this); if (KidsToRender != null || HScrollbar || VScrollbar) { if (KidsToRender != null) { for (int i = 0; i < KidsToRender.Count; i++) { Document.Renderer.PackOnLine(KidsToRender[i]); } } if (HScrollbar) { Document.Renderer.PackOnLine(HorizontalScrollbar.Element); } if (VScrollbar) { Document.Renderer.PackOnLine(VerticalScrollbar.Element); } } Document.Renderer.EndLinePack(this); }