// // PosDim.cs: Pos and Dim objects for view dimensions. // // Authors: // Miguel de Icaza (miguel@gnome.org) // using System; namespace Terminal.Gui { /// /// Describes a position which can be an absolute value, a percentage, centered, or /// relative to the ending dimension. Integer values are implicitly convertible to /// an absolute Pos. These objects are created using the static methods Percent, /// AnchorEnd and Center. The Pos objects can be combined with the addition and /// subtraction operators. /// /// /// /// Use the Pos objects on the X or Y properties of a view to control the position. /// /// /// These can be used to set the absolute position, when merely assigning an /// integer value (via the implicit integer to Pos conversion), and they can be combined /// to produce more useful layouts, like: Pos.Center - 3, which would shift the postion /// of the view 3 characters to the left after centering for example. /// /// public class Pos { internal virtual int Anchor (int width) { return 0; } class PosFactor : Pos { float factor; public PosFactor (float n) { this.factor = n; } internal override int Anchor (int width) { return (int)(width * factor); } public override string ToString () { return $"Pos.Factor({factor})"; } } /// /// Creates a percentage Pos object /// /// The percent Pos object. /// A value between 0 and 100 representing the percentage. public static Pos Percent (float n) { if (n < 0 || n > 100) throw new ArgumentException ("Percent value must be between 0 and 100"); return new PosFactor (n / 100); } static PosAnchorEnd endNoMargin; class PosAnchorEnd : Pos { int n; public PosAnchorEnd (int n) { this.n = n; } internal override int Anchor (int width) { return width - n; } public override string ToString () { return $"Pos.AnchorEnd(margin={n})"; } } /// /// Creates a Pos object that is anchored to the end of the dimension, useful to flush /// the layout from the end. /// /// The Pos object anchored to the end (the bottom or the right side). /// Optional margin to set aside. public static Pos AnchorEnd (int margin = 0) { if (margin < 0) throw new ArgumentException ("Margin must be positive"); if (margin == 0) { if (endNoMargin == null) endNoMargin = new PosAnchorEnd (0); return endNoMargin; } return new PosAnchorEnd (margin); } internal class PosCenter : Pos { internal override int Anchor (int width) { return width / 2; } public override string ToString () { return "Pos.Center"; } } static PosCenter pCenter; /// /// Returns a Pos object that can be used to center the views. /// /// The center Pos. public static Pos Center () { if (pCenter == null) pCenter = new PosCenter (); return pCenter; } class PosAbsolute : Pos { int n; public PosAbsolute (int n) { this.n = n; } public override string ToString () { return $"Pos.Absolute({n})"; } internal override int Anchor (int width) { return n; } } /// /// Creates an Absolute Pos from the specified integer value. /// /// The Absolute Pos. /// The value to convert to the pos. public static implicit operator Pos (int n) { return new PosAbsolute (n); } class PosCombine : Pos { Pos left, right; bool add; public PosCombine (bool add, Pos left, Pos right) { this.left = left; this.right = right; this.add = add; } internal override int Anchor (int width) { var la = left.Anchor (width); var ra = right.Anchor (width); if (add) return la + ra; else return la - ra; } } /// /// Adds a to a , yielding a new . /// /// The first to add. /// The second to add. /// The that is the sum of the values of left and right. public static Pos operator + (Pos left, Pos right) { return new PosCombine (true, left, right); } /// /// Subtracts a from a , yielding a new . /// /// The to subtract from (the minuend). /// The to subtract (the subtrahend). /// The that is the left minus right. public static Pos operator - (Pos left, Pos right) { return new PosCombine (false, left, right); } } /// /// /// /// /// Use the Dim objects on the Width or Height properties of a view to control the position. /// /// /// These can be used to set the absolute position, when merely assigning an /// integer value (via the implicit integer to Pos conversion), and they can be combined /// to produce more useful layouts, like: Pos.Center - 3, which would shift the postion /// of the view 3 characters to the left after centering for example. /// /// public class Dim { internal virtual int Anchor (int width) { return 0; } class DimFactor : Dim { float factor; public DimFactor (float n) { this.factor = n; } internal override int Anchor (int width) { return (int)(width * factor); } public override string ToString () { return $"Dim.Factor({factor})"; } } /// /// Creates a percentage Dim object /// /// The percent Dim object. /// A value between 0 and 100 representing the percentage. public static Dim Percent (float n) { if (n < 0 || n > 100) throw new ArgumentException ("Percent value must be between 0 and 100"); return new DimFactor (n / 100); } class DimAbsolute : Dim { int n; public DimAbsolute (int n) { this.n = n; } public override string ToString () { return $"Dim.Absolute({n})"; } internal override int Anchor (int width) { return n; } } class DimFill : Dim { int margin; public DimFill (int margin) { this.margin = margin; } public override string ToString () { return $"Dim.Fill(margin={margin})"; } internal override int Anchor (int width) { return width-margin; } } static DimFill zeroMargin; /// /// Creates a Dim object that fills the dimension, but leaves the specified number of colums for a margin. /// /// The Fill dimension. /// Margin to use. public static Dim Fill (int margin = 0) { if (margin == 0) { if (zeroMargin == null) zeroMargin = new DimFill (0); return zeroMargin; } return new DimFill (margin); } /// /// Creates an Absolute Pos from the specified integer value. /// /// The Absolute Pos. /// The value to convert to the pos. public static implicit operator Dim (int n) { return new DimAbsolute (n); } class DimCombine : Dim { Dim left, right; bool add; public DimCombine (bool add, Dim left, Dim right) { this.left = left; this.right = right; this.add = add; } internal override int Anchor (int width) { var la = left.Anchor (width); var ra = right.Anchor (width); if (add) return la + ra; else return la - ra; } } /// /// Adds a to a , yielding a new . /// /// The first to add. /// The second to add. /// The that is the sum of the values of left and right. public static Dim operator + (Dim left, Dim right) { return new DimCombine (true, left, right); } /// /// Subtracts a from a , yielding a new . /// /// The to subtract from (the minuend). /// The to subtract (the subtrahend). /// The that is the left minus right. public static Dim operator - (Dim left, Dim right) { return new DimCombine (false, left, right); } } }