private Box ChildSetup(Box box, LayoutInfo transform, int maxBoxWidth, int left, int top) { var childTransform = transform.WithMaxWidthOffsetBy(maxBoxWidth, Left, Top); // todo: test box.Layout(childTransform); box.Left = left; box.Top = top; return box; }
// Figure out how much to adjust the top of box, which would be the input value of top // except for overlapping margins, if in fact margin overlaps the previous box. internal int AdjustTopForMargins(int top, LayoutInfo transform, Box prevBox, Box box) { if (prevBox != null) { top -= Math.Min(transform.MpToPixelsY(prevBox.Style.Margins.BottomMp), transform.MpToPixelsY(box.Style.Margins.TopMp)); } return top; }
/// <summary> /// Add another box (to the end of the chain). /// </summary> /// <param name="box"></param> public void AddBox(Box box) { if (box == null) return; if (FirstBox == null) { FirstBox = box; FirstBox.Previous = null; } else { LastBox.Next = box; box.Previous = LastBox; } LastBox = box; box.Next = null; box.Container = this; NumBoxes++; }
/// <summary> /// Return true if this box contains the other one, that is, is one of its containers. /// Only group boxes can contain others. /// </summary> public virtual bool Contains(Box other) { return false; }
/// <summary> /// Answer true if this box is in the sequence of boxes chained after other. /// Optimize JohnT: if we assume they are usually close together but either order is likely, /// it would usually be more efficient to have a double loop that searches both Next chains at once /// until one runs out or we find the other. /// </summary> public bool Follows(Box other) { if (other == null) return false; for (Box box = other.Next; box != null; box = box.Next) { if (box == this) return true; } return false; // this does NOT follow other. }
public Box CommonContainer(Box other) { Box thisChild; Box otherChild; return CommonContainer(other, out thisChild, out otherChild); }
/// <summary> /// Answer true if the box is entirely below the clip rectangle. /// Enhance JohnT: Could refine this to skip a box if only its margin is visible. /// Enhance JohnT: if we do separate page drawing, as in print preview, we may need /// a more precise way to eliminate boxes not on the page. /// Enhance JohnT: may need to include a box that is just out of sight, in case exceptionally /// high stacked diacritics extend above the top of the box? /// </summary> internal override bool IsAfterVisibleBoxes(Box box, IVwGraphics vg, PaintTransform ptrans) { int left, top, right, bottom; vg.GetClipRect(out left, out top, out right, out bottom); return ptrans.ToPaintY(box.Top) > bottom; }
/// <summary> /// This routine and its overrides are used to make sure that the part of the root box between /// yTop and yBottom (measured from the top of the root) can be painted successfully. To facilitate /// the process of replacing a lazy box with real boxes, it is passed the previous box in its /// container (or null if there is none) and returns the next box which the container should /// check is prepared to paint. By default this is simply the next box, but if a lazy box expands /// (part of) itself, it should answer the replacement box. /// Most box classes are always prepared to paint and do nothing. Lazy boxes convert all or part of /// themselves to real boxes if they intersect the specified vertical range (relative to the root as /// a whole). Boxes (currently DivBoxes only) which might contain lazy boxes pass the message on /// to their children, making the appropriate adjustment to the layout transform, just as when /// asking their children to Layout. /// </summary> internal override Box PrepareToPaint(LayoutInfo transform, Box myPrevBox, int dysTop, int dysBottom) { var childMaxWidth = transform.MaxWidth - GapLeading(transform) - GapTrailing(transform); var childTransform = transform.WithMaxWidthOffsetBy(childMaxWidth, Left, Top); Box prevBox = null; for (Box box = FirstBox; box != null; ) { if (transform.YOffset + box.Top > dysBottom) { // nothing further down in this can be visible. Possibly we should return null, // since presumably nothing further down in the container is visible, either. // However, it feels more robust to answer in the usual way and let the container decide // for itself. return Next; } if (transform.YOffset + box.Bottom < dysTop) box = box.Next; // this box is not visible, but a later one might be else box = box.PrepareToPaint(childTransform, prevBox, dysTop, dysBottom); } return Next; }
/// <summary> /// Add a child box after the specified box (one of your children). /// </summary> public void InsertBox(Box newBox, Box insertAfter) { if (newBox == null) return; if (insertAfter == null) { newBox.Next = FirstBox; if(FirstBox != null) FirstBox.Previous = newBox; FirstBox = newBox; FirstBox.Previous = null; } else { if (insertAfter.Container != this) throw new ArgumentException("InsertBox's insertAfter argument must be a child of the box inserted into"); newBox.Next = insertAfter.Next; insertAfter.Next = newBox; newBox.Previous = insertAfter; } if (newBox.Next == null) LastBox = newBox; newBox.Container = this; NumBoxes++; }
/// <summary> /// Return true if this box contains the other one, that is, is one of its containers. /// Only group boxes can contain others. /// </summary> public virtual bool Contains(Box other) { return(false); }
private Box BoxBefore(Box target) { Box result = null; for (Box current = FirstBox; ; current = current.Next) { if (current == target) return result; result = current; } }
internal void RemoveBoxes(Box firstGoner, Box lastGoner) { if (firstGoner.Container != this) throw new ArgumentException("firstGoner must be a child"); if (lastGoner.Container != this) throw new ArgumentException("lastGoner must be a child"); var previous = BoxBefore(firstGoner); // link around them if (previous == null) { FirstBox = lastGoner.Next; if(FirstBox != null) FirstBox.Previous = null; } else { previous.Next = lastGoner.Next; if(lastGoner.Next != null) lastGoner.Next.Previous = previous; } lastGoner.Next = null; // prevents anything accidentally linking back into the real ones. firstGoner.Previous = null; if (lastGoner == LastBox) LastBox = previous; FindNumBoxes(); }
/// <summary> /// Return true if this box contains the other one, that is, is one of its containers. /// Only group boxes can contain others. /// </summary> public override bool Contains(Box other) { for (var container = other.Container; container != null; container = container.Container) { if (container == this) return true; } return false; }
/// <summary> /// Return true if the argument (child) box and all subsequent boxes need not be painted, /// typically because they occur after the end of the clip rectangle specified in the VwGraphics. /// It is acceptable to answer false, if no clipping is wanted, or for the first box for which /// we answer true to be later than the optimal one; this is an optional optimization. /// </summary> internal virtual bool IsAfterVisibleBoxes(Box box, IVwGraphics vg, PaintTransform ptrans) { return false; }
/// <summary> /// Returns the closest container of this and other which is a container of both of them, /// and also the child of that container which is or contains each of them. /// Special cases: /// if they are the same box, all three return values are that box. /// if one of the boxes contains the other, the return value and the corresponding child output /// are both the containing box. /// </summary> /// <param name="other">box to search for</param> /// <param name="thisChild">this or a container of this</param> /// <param name="otherChild">other or a container of other</param> /// <returns></returns> public Box CommonContainer(Box other, out Box thisChild, out Box otherChild) { thisChild = this; otherChild = other; if (other == this) { return this; } var otherContainers = new HashSet<Box>(other.AllContainers.Cast<Box>()); otherContainers.Add(other); if (otherContainers.Contains(this)) { // special case: this contains other. otherChild = (from box in otherContainers where box.Container == this select box).First(); return this; } foreach (var container in AllContainers) { if (container == other) // other IS the common container. return container; // otherChild is already set, and we won't find a box contained by other in the set. if (otherContainers.Contains(container)) { // container is the common container. otherChild = (from box in otherContainers where box.Container == container select box).First(); return container; } thisChild = container; // will be right when we find the true common container. } return Root; // should never happen, but might be the right answer in such a case?? }
/// <summary> /// This routine and its overrides are used to make sure that the part of the root box between /// yTop and yBottom (measured from the top of the root) can be painted successfully. To facilitate /// the process of replacing a lazy box with real boxes, it is passed the previous box in its /// container (or null if there is none) and returns the next box which the container should /// check is prepared to paint. By default this is simply the next box, but if a lazy box expands /// (part of) itself, it should answer the replacement box. /// Most box classes are always prepared to paint and just answer Next. Lazy boxes convert all or part of /// themselves to real boxes if they intersect the specified vertical range (relative to the root as /// a whole). Boxes (currently DivBoxes only) which might contain lazy boxes pass the message on /// to their children, making the appropriate adjustment to the layout transform, just as when /// asking their children to Layout. /// </summary> internal virtual Box PrepareToPaint(LayoutInfo transform, Box prevBox, int yTop, int yBottom) { return Next; }
/// <summary> /// This routine and its overrides are used to make sure that the part of the root box between /// yTop and yBottom (measured from the top of the root) can be painted successfully. To facilitate /// the process of replacing a lazy box with real boxes, it is passed the previous box in its /// container (or null if there is none) and returns the next box which the container should /// check is prepared to paint. By default this is simply the next box, but if a lazy box expands /// (part of) itself, it should answer the replacement box. /// Most box classes are always prepared to paint and just answer Next. Lazy boxes convert all or part of /// themselves to real boxes if they intersect the specified vertical range (relative to the root as /// a whole). Boxes (currently DivBoxes only) which might contain lazy boxes pass the message on /// to their children, making the appropriate adjustment to the layout transform, just as when /// asking their children to Layout. /// </summary> internal virtual Box PrepareToPaint(LayoutInfo transform, Box prevBox, int yTop, int yBottom) { return(Next); }