// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System; namespace FlaxEngine.GUI { /// /// The checkbox control states. /// public enum CheckBoxState { /// /// The default state. /// Default, /// /// The checked state. /// Checked, /// /// The intermediate state. /// Intermediate, } /// /// Check box control. /// /// public class CheckBox : Control { /// /// True if checked is being pressed (by mouse or touch). /// protected bool _isPressed; /// /// The current state. /// protected CheckBoxState _state; /// /// The mouse over box state. /// protected bool _mouseOverBox; /// /// The box size. /// protected float _boxSize; /// /// The box rectangle. /// protected Rectangle _box; /// /// Gets or sets the state of the checkbox. /// [EditorOrder(10)] public CheckBoxState State { get => _state; set { if (_state != value) { _state = value; StateChanged?.Invoke(this); } } } /// /// Gets or sets a value indicating whether this is checked. /// [NoSerialize, HideInEditor] public bool Checked { get => _state == CheckBoxState.Checked; set => State = value ? CheckBoxState.Checked : CheckBoxState.Default; } /// /// Gets or sets a value indicating whether this is in the intermediate state. /// [NoSerialize, HideInEditor] public bool Intermediate { get => _state == CheckBoxState.Intermediate; set => State = value ? CheckBoxState.Intermediate : CheckBoxState.Default; } /// /// Gets or sets the size of the box. /// [EditorOrder(20)] public float BoxSize { get => _boxSize; set { _boxSize = value; CacheBox(); } } /// /// Gets or sets the color of the border. /// [EditorDisplay("Border Style"), EditorOrder(2010), ExpandGroups] public Color BorderColor { get; set; } /// /// Gets or sets the border color when checkbox is hovered. /// [EditorDisplay("Border Style"), EditorOrder(2011)] public Color BorderColorHighlighted { get; set; } /// /// Gets or sets the color of the checkbox icon. /// [EditorDisplay("Image Style"), EditorOrder(2020), ExpandGroups] public Color ImageColor { get; set; } /// /// Gets or sets the image used to render checkbox checked state. /// [EditorDisplay("Image Style"), EditorOrder(2021), Tooltip("The image used to render checkbox checked state.")] public IBrush CheckedImage { get; set; } /// /// Gets or sets the image used to render checkbox intermediate state. /// [EditorDisplay("Image Style"), EditorOrder(2022), Tooltip("The image used to render checkbox intermediate state.")] public IBrush IntermediateImage { get; set; } /// /// Event fired when 'checked' state gets changed. /// public event Action StateChanged; /// /// Initializes a new instance of the class. /// public CheckBox() : this(0, 0) { } /// /// Initializes a new instance of the class. /// /// The x. /// The y. /// if set to true set checked on start. /// The checkbox size. public CheckBox(float x, float y, bool isChecked = false, float size = 18) : base(x, y, size, size) { _state = isChecked ? CheckBoxState.Checked : CheckBoxState.Default; _boxSize = Mathf.Min(16.0f, size); var style = Style.Current; ImageColor = style.BorderSelected * 1.2f; BorderColor = style.BorderNormal; BorderColorHighlighted = style.BorderSelected; CheckedImage = new SpriteBrush(style.CheckBoxTick); IntermediateImage = new SpriteBrush(style.CheckBoxIntermediate); CacheBox(); } /// /// Toggles the checked state. /// public void Toggle() { Checked = !Checked; } private void CacheBox() { _box = new Rectangle(0, (Height - _boxSize) * 0.5f, _boxSize, _boxSize); } /// /// Called when mouse or touch clicks the checkbox. /// protected virtual void OnClick() { Toggle(); } /// /// Called when checkbox starts to be pressed by the used (via mouse or touch). /// protected virtual void OnPressBegin() { _isPressed = true; if (AutoFocus) Focus(); } /// /// Called when checkbox ends to be pressed by the used (via mouse or touch). /// protected virtual void OnPressEnd() { _isPressed = false; } /// public override void Draw() { base.Draw(); bool enabled = EnabledInHierarchy; // Border Color borderColor = BorderColor; if (!enabled) borderColor *= 0.5f; else if (_isPressed || _mouseOverBox || IsNavFocused) borderColor = BorderColorHighlighted; Render2D.DrawRectangle(_box.MakeExpanded(-2.0f), borderColor); // Icon if (_state != CheckBoxState.Default) { var color = ImageColor; if (!enabled) color *= 0.6f; if (_state == CheckBoxState.Checked) CheckedImage?.Draw(_box, color); else IntermediateImage?.Draw(_box, color); } } /// public override void OnMouseMove(Float2 location) { base.OnMouseMove(location); _mouseOverBox = _box.Contains(ref location); } /// public override bool OnMouseDown(Float2 location, MouseButton button) { if (button == MouseButton.Left && !_isPressed) { OnPressBegin(); return true; } return base.OnMouseDown(location, button); } /// public override bool OnMouseUp(Float2 location, MouseButton button) { if (button == MouseButton.Left && _isPressed) { OnPressEnd(); if (_box.Contains(ref location)) { OnClick(); return true; } } return base.OnMouseUp(location, button); } /// public override void OnMouseLeave() { if (_isPressed) OnPressEnd(); _mouseOverBox = false; base.OnMouseLeave(); } /// public override bool OnTouchDown(Float2 location, int pointerId) { if (!_isPressed) { OnPressBegin(); return true; } return base.OnTouchDown(location, pointerId); } /// public override bool OnTouchUp(Float2 location, int pointerId) { if (_isPressed) { OnPressEnd(); if (_box.Contains(ref location)) { OnClick(); return true; } } return base.OnTouchUp(location, pointerId); } /// public override void OnTouchLeave() { if (_isPressed) OnPressEnd(); base.OnTouchLeave(); } /// public override void OnLostFocus() { if (_isPressed) OnPressEnd(); base.OnLostFocus(); } /// protected override void OnSizeChanged() { base.OnSizeChanged(); CacheBox(); } /// public override void OnSubmit() { OnClick(); base.OnSubmit(); } } }