internal static void UpdateDrawLocation(this UIControl control) { if (control.SuspendLayout) { return; } _UpdateDrawLocation(control); if (control is UIContainer) { UIContainer container = control as UIContainer; foreach (UIControl child in container.Controls) { UpdateDrawLocation(child); } } if (control.HasDecorations) { control.Decorations.ForEach(c => UpdateDrawLocation(c)); } }
/// <summary> /// Adds a UI constraint to this control. /// </summary> /// <param name="control">Control instance.</param> /// <param name="controlEdge">Control edge to constraint.</param> /// <param name="anchor">Anchoring control on which the control edge is constrained. If 'null', the control is anchored relative to the viewport.</param> /// <param name="anchorEdge">Anchor edge on which the control edge is constrained relative to.</param> /// <param name="edgeDistance">Distance between control and anchor constraint edges.</param> /// <param name="category">The category this constraint belongs to.</param> public static void AddConstraint(this UIControl control, Edge controlEdge, UIControl anchor, Edge anchorEdge, float edgeDistance = 0, ConstraintCategory category = ConstraintCategory.All) { if (control == anchor) { throw new ArgumentException("Cannot anchor control to itself."); } //// Separate edges into their basic flags. //// E.g. 'Edge.BottomRight' is separated into 'Edge.Bottom' and 'Edge.Right', and added as individual edges. //List<Edge> controlEdges = new List<Edge>(4); //List<Edge> anchorEdges = new List<Edge>(4); //foreach (Edge edgeType in UIConstrainer.EdgeTypes) //{ // if (controlEdge.ContainsFlag(edgeType)) // { // controlEdges.Add(edgeType); // } // if (anchorEdge.ContainsFlag(edgeType)) // { // anchorEdges.Add(edgeType); // } //} //if (controlEdges.Count != anchorEdges.Count) //{ // throw new ArgumentException("There must be an equal amount of control and anchor edges."); //} if (control.Constrainer == null) { control.Constrainer = new UIConstrainer(); } control.Constrainer.AddConstraint(controlEdge, anchor, anchorEdge, edgeDistance, category); //for (int i = 0; i < controlEdges.Count; i++) //{ // control.Constrainer.AddConstraint(controlEdges[i], anchor, anchorEdges[i], edgeDistance, category); //} }
/// <summary> /// Adds a UI constraint to this control. /// </summary> /// <param name="control">Control instance.</param> /// <param name="controlEdge">Control edge to constraint.</param> /// <param name="anchor">Anchoring control on which the control edge is constrained. If 'null', the control is anchored relative to the viewport.</param> /// <param name="anchorEdge">Anchor edge on which the control edge is constrained relative to.</param> /// <param name="edgeDistance">Distance between control and anchor constraint edges.</param> /// <param name="category">The category this constaint belongs to.</param> public static void AddConstraint(this UIControl control, Edge controlEdge, UIControl anchor, Edge anchorEdge, float edgeDistance = 0, ConstraintCategory category = ConstraintCategory.All) { if (control == anchor) { throw new ArgumentException("Cannot anchor control to itself."); } List <Edge> controlEdges = new List <Edge>(4); List <Edge> anchorEdges = new List <Edge>(4); foreach (Edge edgeType in UIConstrainer.EdgeTypes) { if (controlEdge.ContainsFlag(edgeType)) { controlEdges.Add(edgeType); } if (anchorEdge.ContainsFlag(edgeType)) { anchorEdges.Add(edgeType); } } if (controlEdges.Count != anchorEdges.Count) { throw new ArgumentException("There must be an equal amount of control and anchor edges."); } if (control.Constrainer == null) { control.Constrainer = new UIConstrainer(); } for (int i = 0; i < controlEdges.Count; i++) { control.Constrainer.AddConstraint(controlEdges[i], anchor, anchorEdges[i], edgeDistance, category); } }
internal void AssignParent(UIControl control) { CheckInitialize(); parent = control; HasParent = control != null; }
protected virtual bool HandlePointerEvents() { if (heldControl != null && heldControl != this) { return(false); } bool pointerHandled = false; if (pointedControl == this) { pointerHandled = true; if (IntersectsPointer()) { if (CheckEvent(onInputHover, MouseButton.None)) { } } else { //Console.WriteLine("Left 1: " + ToString()); CheckEvent(onInputLeave, MouseButton.None); pointedControl = null; } } else { if (IntersectsPointer()) { if (pointedControl != null && pointedControl != this) { //Console.WriteLine("Left 2: " + pointedControl.ToString()); pointedControl.CheckEvent(pointedControl.onInputLeave, MouseButton.None); pointedControl = null; } //Console.WriteLine("Entered: " + ToString()); CheckEvent(onInputEnter, MouseButton.None); UIControl.pointedControl = this; pointerHandled = true; } } if (PointerDown) { if (InputManager.AnyMousePressed && CheckEvent(onInputPressed, InputManager.MousePressed)) { //Console.WriteLine("Pressed: " + ToString()); pointerHandled = true; heldControl = this; } if (InputManager.AnyMouseDown) { bool inputMoveInitiated = false; if (InputManager.MouseMoved) { inputMoveInitiated = CheckEvent(onInputMoved, InputManager.MouseDown); //Console.WriteLine( ToString() + ": Moved " + mouseMoveInitiated ); } if (CheckEvent(onInputHeld, InputManager.MouseDown)) { //Console.WriteLine("Pointer held: " + ToString()); pointerHandled = true; heldControl = this; } pointerHandled = AbsorbPointer || inputMoveInitiated; } if (InputManager.AnyMouseReleased && IntersectsPointer() && CheckEvent(onInputReleased, InputManager.MouseReleased)) { //Console.WriteLine("Release: " + ToString()); pointerHandled = true; heldControl = null; } if (!InputManager.AnyMouseDown) { //Console.WriteLine("Pointer Up: " + ToString()); PointerDown = false; if (CheckEvent(onInputReleasedAnywhere, InputManager.MouseReleased)) { pointerHandled = true; } if (heldControl != null) { heldControl = null; pointerHandled = true; } } } return(pointerHandled); }
internal static void EnforceConstraints(this UIControl control, ConstraintCategory category = ConstraintCategory.All) { if (control.SuspendLayout) { return; } UIManager.layoutProfiler.Start(); UIConstrainer constrainer = control.Constrainer; if (constrainer != null) { foreach (UIConstraint constraint in constrainer.Constraints) { // Check whether the constaint should be enforced. if (category != ConstraintCategory.All && !category.ContainsFlag(constraint.Category)) { continue; } Edge controlEdge = constraint.ControlEdge; UIControl anchor = constraint.Anchor; float distance = constraint.Distance; Vector2 pos = Vector2.Zero; Vector2 anchorSize = Engine.ScreenSize; if (anchor != null) { anchorSize = anchor.Size * anchor.scale; if (anchor.Parent == control.Parent) // Is anchor and control children of the same parent? { pos = anchor.location; // ..then set control position relative to the anchor. } Vector2 scaleDelta = anchor.ScaledSize - anchor.Size; pos -= anchor.NormalizedOrigin * scaleDelta; } Vector2 halfAnchorSize = anchorSize * 0.5f; switch (constraint.AnchorEdge) { case Edge.Left: pos.X += distance; break; case Edge.Top: pos.Y += distance; break; case Edge.Right: pos.X += anchorSize.X - distance; break; case Edge.Bottom: pos.Y += anchorSize.Y - distance; break; case Edge.CenterX: pos.X += halfAnchorSize.X + distance; break; case Edge.CenterY: pos.Y += halfAnchorSize.Y + distance; break; } if (!constrainer.ControlAnchoredOpposite(controlEdge)) { switch (controlEdge) { case Edge.Left: control.location.X = pos.X; break; case Edge.Top: control.location.Y = pos.Y; break; case Edge.Right: control.location.X = pos.X - control.Width; break; case Edge.Bottom: control.location.Y = pos.Y - control.Height; break; case Edge.CenterX: control.location.X = pos.X - control.HalfWidth; break; case Edge.CenterY: control.location.Y = pos.Y - control.HalfHeight; break; } } else { switch (controlEdge) { case Edge.Left: case Edge.CenterX: control.size.X += control.location.X - pos.X; control.location.X = pos.X; break; case Edge.Top: case Edge.CenterY: control.size.Y += control.location.Y - pos.Y; control.location.Y = pos.Y; break; case Edge.Right: control.size.X += (pos.X - control.Width) - control.location.X; //control.location.X += pos.X - control.size.X; break; case Edge.Bottom: control.size.Y += (pos.Y - control.Height) - control.location.Y; //control.location.Y += pos.Y - control.size.Y; break; } } } } _UpdateDrawLocation(control); UIManager.layoutProfiler.Stop(); }
/// <summary> /// Adds a UI constraint to this control. /// </summary> /// <param name="control">Control instance.</param> /// <param name="controlEdge">Control edge to constraint.</param> /// <param name="anchor">Anchoring control on which the control edge is constrained. If 'null', the control is anchored relative to the viewport.</param> /// <param name="anchorEdge">Anchor edge on which the control edge is constrained relative to.</param> /// <param name="category">The category this constaint belongs to.</param> public static void AddConstraint(this UIControl control, Edge controlEdge, UIControl anchor, Edge anchorEdge, ConstraintCategory category) { control.AddConstraint(controlEdge, anchor, anchorEdge, 0f, category); }
protected virtual bool HandlePointerEvents() { if (heldControl != null && heldControl != this) { return(false); } bool pointerHandled = false; if (pointedControl == this) { pointerHandled = true; if (IntersectsPointer()) { CheckEvent(onInputHover); } else { //Console.WriteLine("Leave 1: " + ToString()); CheckEvent(onInputLeave); pointedControl = null; } } else { if (AbsorbPointer && IntersectsPointer()) { if (pointedControl != null && pointedControl != this) { //Console.WriteLine("Leave 2: " + pointedControl.ToString()); pointedControl.CheckEvent(pointedControl.onInputLeave); pointedControl = null; } // TODO: Enable fall-through logic for onInputEnter //Console.WriteLine("Entered: " + ToString()); CheckEvent(onInputEnter); pointedControl = this; pointerHandled = true; } } //Console.WriteLine("Pointer AbsorbPointer: " + ToString() + " " + AbsorbPointer); if (PointerDown) { if (InputManager.AnyMousePressed && CheckEvent(onInputPressed, InputManager.MousePressed)) { //Console.WriteLine("Pressed: " + ToString()); pointerHandled = true; heldControl = this; } if (InputManager.AnyMouseHeld) { //Console.WriteLine(ToString() + ": AnyMouseHeld"); bool inputMoveInitiated = false; if (InputManager.MouseMoved) { inputMoveInitiated = CheckEvent(onInputMoved, InputManager.MouseHeld); //Console.WriteLine( ToString() + ": Moved " + mouseMoveInitiated ); if (inputMoveInitiated) { heldControl = this; // TODO: This has not been tested properly } } if (CheckEvent(onInputHeld, InputManager.MouseHeld)) { //Console.WriteLine("Pointer held: " + ToString()); pointerHandled = true; heldControl = this; } pointerHandled = AbsorbPointer || inputMoveInitiated; } if (InputManager.AnyMouseReleased && IntersectsPointer() && CheckEvent(onInputReleased, InputManager.MouseReleased)) { //Console.WriteLine("Release: " + ToString()); pointerHandled = true; heldControl = null; } if (!InputManager.AnyMouseHeld) { //Console.WriteLine("Pointer Up: " + ToString()); PointerDown = false; pointerHandled = true; if (CheckEvent(onInputReleasedAnywhere, InputManager.MouseReleased)) { pointerHandled = true; } if (heldControl != null) { heldControl = null; pointerHandled = true; } } } return(pointerHandled); }
/// <summary> /// Overload added to prevent implicit casting to ConstraintCategory when edgeDistance is set to 0. /// http://geekswithblogs.net/BlackRabbitCoder/archive/2012/01/26/c.net-little-pitfalls-implicit-zero-to-enum-conversion.aspx /// </summary> public static void AddConstraint(this UIControl control, Edge controlEdge, UIControl anchor, Edge anchorEdge, int edgeDistance) { control.AddConstraint(controlEdge, anchor, anchorEdge, edgeDistance, ConstraintCategory.All); }
private static void EnforceConstraints(this UIControl control, UIConstrainer constrainer, ConstraintCategory category = ConstraintCategory.All) { if (constrainer != null) { foreach (UIConstraint constraint in constrainer.Constraints) { // Check whether the constraint should be enforced. if (category != ConstraintCategory.All && !category.ContainsFlag(constraint.Category)) { continue; } Edge controlEdge = constraint.ControlEdge; UIControl anchor = constraint.Anchor; float distance = constraint.Distance; bool anchorVisible = true; Vector2 pos = Vector2.Zero; Vector2 anchorSize = Engine.ScreenSize; if (anchor != null) { anchorVisible = anchor.Visible; anchorSize = anchorVisible ? (anchor.Size * anchor.scale).Max(anchor.MinimumSize * anchor.scale) : Vector2.Zero; if (anchor.Parent == control.Parent) // Is anchor and control children of the same parent? { pos = anchor.position; // ..then set control position relative to the anchor. } Vector2 scaleDelta = anchor.ScaledSize - anchor.Size; pos -= anchor.NormalizedOrigin * scaleDelta; } Vector2 halfAnchorSize = anchorSize * 0.5f; switch (constraint.AnchorEdge) { case Edge.Left: pos.X += distance; break; case Edge.Top: pos.Y += distance; break; case Edge.Right: pos.X += anchorSize.X - distance; break; case Edge.Bottom: pos.Y += anchorSize.Y - distance; break; case Edge.CenterX: pos.X += halfAnchorSize.X + distance; break; case Edge.CenterY: pos.Y += halfAnchorSize.Y + distance; break; } if (!constrainer.AnchoredOpposite(controlEdge)) { switch (controlEdge) { case Edge.Left: control.position.X = pos.X; break; case Edge.Top: control.position.Y = pos.Y; break; case Edge.Right: control.position.X = pos.X - Math.Max(control.Width, control.MinimumSize.X); break; case Edge.Bottom: control.position.Y = pos.Y - Math.Max(control.Height, control.MinimumSize.Y); break; case Edge.CenterX: control.position.X = pos.X - Math.Max(control.HalfWidth, control.MinimumSize.X * 0.5f); break; case Edge.CenterY: control.position.Y = pos.Y - Math.Max(control.HalfHeight, control.MinimumSize.Y * 0.5f); break; } } else { switch (controlEdge) { case Edge.Left: case Edge.CenterX: control.size.X += control.position.X - pos.X; control.position.X = pos.X; break; case Edge.Top: case Edge.CenterY: control.size.Y += control.position.Y - pos.Y; control.position.Y = pos.Y; break; case Edge.Right: control.size.X += (pos.X - control.Width) - control.position.X; if (!anchorVisible) { control.size.X += anchor.size.X; // TODO: Needs proper testing } //control.location.X += pos.X - control.size.X; break; case Edge.Bottom: control.size.Y += (pos.Y - control.Height) - control.position.Y; if (!anchorVisible) { control.size.Y += anchor.size.Y; // TODO: Needs proper testing } //control.location.Y += pos.Y - control.size.Y; break; } control.UpdateTransformation = true; // Control transformation needs a recalculation when its size is updated. } } } if (control.MinimumSize != Vector2.Zero) { control.size = control.size.Max(control.MinimumSize); control.UpdateTransformation = true; } _UpdateDrawPosition(control); }
public UIScrollBar(ScrollBarOrientation orientation = ScrollBarOrientation.Vertical) { Orientation = orientation; string arrowResource = string.Empty; Vector2 sliderSize = Vector2.Zero; switch (orientation) { case ScrollBarOrientation.Vertical: sliderSize = new Vector2(0, 20); arrowResource = "graphics/arrow_down"; break; case ScrollBarOrientation.Horizontal: sliderSize = new Vector2(20, 0); arrowResource = "graphics/arrow_left"; break; } AutoSize = false; scrollStep = 0.02f; Color = new Color(240, 240, 240); Alpha = 1f; DrawBounds = true; sliderBackground = new UIPanel(); sliderBackground.Color = new Color(240, 240, 240); sliderBackground.Alpha = 1f; sliderBackground.InputMoved += sliderBackground_MouseMoved; sliderBackground.InputPressed += sliderBackground_MousePressed; slider = new UIPanel(); slider.Color = new Color(205, 205, 205); slider.Alpha = 1f; slider.AutoSize = false; slider.AbsorbPointer = false; slider.Size = sliderSize; //slider.InputDown += sliderBackground_MousePressed; arrowA = new UIButton(); var arrowAImg = new UIImage(arrowResource); arrowAImg.Color = new Color(96, 96, 96); arrowAImg.AddConstraint(Edge.Dock, arrowA, Edge.Dock); arrowA.Tag = "bla"; arrowA.AddDecoration(arrowAImg); arrowA.PointedColor = new Color(190, 190, 190); arrowA.PressedColor = new Color(120, 120, 120); arrowA.HighlightZoom = false; arrowA.InputDown += arrowA_MouseHeld; arrowB = new UIButton(); var arrowBImg = new UIImage(arrowResource); arrowBImg.Color = new Color(96, 96, 96); arrowBImg.AddConstraint(Edge.Dock, arrowB, Edge.Dock); arrowB.AddDecoration(arrowBImg); arrowB.PointedColor = new Color(190, 190, 190); arrowB.PressedColor = new Color(120, 120, 120); arrowB.HighlightZoom = false; arrowB.InputDown += arrowB_MouseHeld; switch (orientation) { case ScrollBarOrientation.Vertical: arrowAImg.SpriteEffect = SpriteEffects.FlipVertically; arrowA.AddConstraint(Edge.Horizontal | Edge.Top, this, Edge.Horizontal | Edge.Top); arrowB.AddConstraint(Edge.Horizontal, this, Edge.Horizontal); arrowB.AddConstraint(Edge.Bottom, this, Edge.Bottom); sliderBackground.AddConstraint(Edge.Horizontal, this, Edge.Horizontal); sliderBackground.AddConstraint(Edge.Top, arrowA, Edge.Bottom); sliderBackground.AddConstraint(Edge.Bottom, arrowB, Edge.Top); slider.AddConstraint(Edge.Top, sliderBackground, Edge.Top, ConstraintCategory.Initialization); slider.AddConstraint(Edge.Horizontal, sliderBackground, Edge.Horizontal); break; case ScrollBarOrientation.Horizontal: arrowBImg.SpriteEffect = SpriteEffects.FlipHorizontally; arrowA.AddConstraint(Edge.Vertical | Edge.Left, this, Edge.Vertical | Edge.Left); arrowB.AddConstraint(Edge.Vertical, this, Edge.Vertical); arrowB.AddConstraint(Edge.Right, this, Edge.Right); sliderBackground.AddConstraint(Edge.Vertical, this, Edge.Vertical); sliderBackground.AddConstraint(Edge.Left, arrowA, Edge.Right); sliderBackground.AddConstraint(Edge.Right, arrowB, Edge.Left); slider.AddConstraint(Edge.Left, sliderBackground, Edge.Left, ConstraintCategory.Initialization); slider.AddConstraint(Edge.Vertical, sliderBackground, Edge.Vertical); break; } AbsorbPointer = false; //base.AbsorbPointer = true; //slider.AbsorbPointer = true; //arrowDown.AbsorbPointer = true; //arrowUp.AbsorbPointer = true; sliderBackground.AbsorbPointer = true; AddChild(arrowA); AddChild(arrowB); AddChild(sliderBackground); AddChild(slider); }