/Scenes/UserInterfaces/Controls/Button.cs
C# | 507 lines | 262 code | 56 blank | 189 comment | 22 complexity | d73fa62f1883cea99e996262773ca6e0 MD5 | raw file
Possible License(s): Apache-2.0
- using Delta.Engine;
- using Delta.Engine.SettingsNodes;
- using Delta.InputSystem;
- using Delta.Scenes.Enums;
- using Delta.Utilities;
- using Delta.Utilities.Datatypes;
- using NUnit.Framework;
- using Delta.Multimedia;
-
- namespace Delta.Scenes.UserInterfaces.Controls
- {
- /// <summary>
- /// A button control which supports additionally to the normal control states
- /// the 'Pressed' state and also a 'Clicked' event.
- /// </summary>
- public class Button : Label
- {
- #region Constants
- /// <summary>
- /// The name of the control class which is saved in the content data to
- /// describe and "detect" the data in the loading code again.
- /// </summary>
- private const string SavingClassName = "UIButtonControl";
-
- /// <summary>
- /// The current version of the implementation of this control class.
- /// </summary>
- private const int WorkingVersion = 1;
- #endregion
-
- #region Delegates
- /// <summary>
- /// The delegate declaration for any input event that will forwarded to an
- /// UI control.
- /// </summary>
- /// <param name="sender">Sender</param>
- /// <param name="input">The data of that event</param>
- public delegate void ControlInputEvent(BaseControl sender,
- CommandTrigger input);
- #endregion
-
- #region Protected
-
- #region FallbackDesign (Protected)
- /// <summary>
- /// Defines the theme which will be used if no "Theme" was set explicitely.
- /// </summary>
- protected override ControlDesign FallbackDesign
- {
- get
- {
- return Theme.Current.ButtonDesign;
- }
- }
- #endregion
-
- #endregion
-
- #region Clicked (Event)
- /// <summary>
- /// Occurs if the left pointing device button was pressed.
- /// </summary>
- public event ControlInputEvent Clicked;
- #endregion
-
- #region ClickedSound
- /// <summary>
- /// The sound which will be played if this button is clicked (Optional).
- /// </summary>
- public Sound ClickedSound
- {
- get;
- set;
- }
- #endregion
-
- #region Methods (Private)
-
- #region OnInputEvent
- /// <summary>
- /// On input event
- /// </summary>
- /// <param name="input">Input</param>
- protected override void OnInputEvent(CommandTrigger input)
- {
- // If the event was already handled we don't need to do anything
- if (input.IsHandled)
- {
- return;
- }
-
- switch (input.CommandName)
- {
- case Command.UIClickBegin:
- //IsInPressedState = true;
- State = ElementState.Pressed;
- input.IsHandled = true;
- //return base.OnInputEvent(inputEvent);
- return;
-
- case Command.UIClick:
- //Log.Test("UI event '" + command.EventName + "' happened.");
-
- // The button click will only be handled if the click was initiated
- // (even by a drag) on this control
- if (State != ElementState.Pressed)
- {
- return;
- } // if
-
- // At first give the control the chance to react on that event (for
- // internal logic which wasn't thought for any subscribers)
- OnClicked(input, IsInControl(input.Position));
- // if the input event wasn't needed for its own logic
- if (Clicked != null &&
- input.IsHandled == false)
- {
- // then inform all subscribers (if there are ones)
- Clicked(this, input);
- }
-
- // Finally close the current clicked begin state
- //IsInPressedState = false;
-
- // Michael: Added an invisible check so the button
- // will correctly be hidden when the state is changed
- // during "Clicked" events
- if (State != ElementState.Invisible)
- {
- State =
- IsInControl(input.Position)
- ? ElementState.Hovered
- : ElementState.Enabled;
- }
- //return inputEvent.IsHandled;
- if (Clicked == null &&
- input.IsHandled == false)
- {
- Log.Warning(
- "There is no code which handles the '" +input.CommandName +
- "' event for button '"+Name+"', which seems to be strange.");
- }
- return;
-
- default:
- // Unknown input event for the UI control
- base.OnInputEvent(input);
- return;
- } // switch
- }
- #endregion
-
- // OnInputEvent(command)
-
- #region OnClicked
- /// <summary>
- /// On clicked
- /// </summary>
- /// <param name="input">Input data like the click position.</param>
- /// <param name="isInsideControl">
- /// 'True' if the event is occurring inside the control, otherwise 'false'.
- /// </param>
- protected virtual void OnClicked(CommandTrigger input,
- bool isInsideControl)
- {
- // For a button we only "count" a click if it starts AND ends inside of
- // the control, otherwise we just ignore the event
- // Note: All other required management stuff of the control like
- // restoring the correct state will be still done
- if (isInsideControl == false)
- {
- input.IsHandled = true;
- return;
- } // if
-
- if (ClickedSound != null)
- {
- ClickedSound.Play();
- } // if
- }
- #endregion
-
- #endregion
-
- /// <summary>
- /// Tests for Button controls
- /// </summary>
- [Category("Visual")]
- internal class ButtonTests
- {
- #region DisplayButton (Static)
- /// <summary>
- /// Display button
- /// </summary>
- [Test]
- public static void DisplayButton()
- {
- int clickCount = 0;
-
- Button button = new Button
- {
- //LocalArea = new Rectangle(0.25f, 0.25f, 0.5f, 0.15f),
- LocalArea = new Rectangle(0.5f, 0.5f, 0.5f, 0.15f),
- //Rotation = 45,
- //Alignment = AlignmentType.Middle,
- Text = "Click me",
- };
- button.Clicked += delegate(BaseControl sender, CommandTrigger input)
- {
- button.Text = (++clickCount) + "x clicked";
- Log.Test(button.Text);
- input.IsHandled = true;
- };
-
- // Finally we still have to add the button to a scene that should
- // manage the button
- Screen testScene = new Screen();
- testScene.Add(button);
-
- //Base.UI.ShowDebugInfo = true;
- // Open now the scene to "activate" for the test
- testScene.Open();
-
- Settings.Debug.SetDrawDebugInfoMode(ProfilingMode.UI, false); // true);
- Application.Start();
- }
- #endregion
-
- #region DisabledButton (Static)
- /// <summary>
- /// Disabled button
- /// </summary>
- [Test]
- public static void DisabledButton()
- {
- int clickCount = 0;
- Button button = new Button
- {
- LocalArea = new Rectangle(0.25f, 0.25f, 0.5f, 0.15f),
- Text = "Enabled",
- //AllowEventsWhenDisabled = true,
- };
- button.Clicked += delegate(BaseControl control, CommandTrigger input)
- {
- button.Text = (++clickCount) + "x clicked";
- input.IsHandled = true;
- };
-
- // Finally we still have to add the button to a screen that should
- // manage the button
- Screen testScene = new Screen();
- testScene.Add(button);
-
- // Open now the scene to "activate" for the test
- testScene.Open();
- Application.Start(delegate
- {
- // Start the visual test to see the button
-
- // Disable/enable the button by pressing the keyboard "Space" button
- if (Input.Keyboard.SpaceReleased)
- {
- if (button.State >= ElementState.Enabled)
- {
- button.State = ElementState.Disabled;
- }
- else
- {
- button.State = button.IsInControl(Input.Mouse.Position)
- ? ElementState.Hovered
- : ElementState.Enabled;
- } // else
- button.Text = button.State.ToString();
- clickCount = 0;
- }
- });
- }
- #endregion
-
- #region DestroyButton (Static)
- /// <summary>
- /// Destroy button
- /// </summary>
- [Test]
- public static void DestroyButton()
- {
- bool isButtonDestroyed = false;
- Button testButton = new Button
- {
- LocalArea = new Rectangle(0.25f, 0.25f, 0.5f, 0.15f),
- };
- testButton.Clicked += delegate
- {
- if (isButtonDestroyed)
- {
- Log.Test("Hmm...the button should be actually destroyed.");
- }
- else
- {
- testButton.Dispose();
- isButtonDestroyed = true;
- } // else
- };
-
- // Finally we still have to add the button to a scene that should
- // manage the button
- Screen testScene = new Screen();
- testScene.Add(testButton);
-
- // Open now the scene to "activate" for the test
- testScene.Open();
- Application.Start();
- }
- #endregion
-
- #region CursorMoveTest (Static)
- /// <summary>
- /// Cursor move test
- /// </summary>
- [Test]
- public static void CursorMoveTest()
- {
- // Button testButton = new Button
- // {
- // //ControlArea = new Rectangle(0.4f, 0.4f, 0.2f, 0.2f));
- // //ControlArea = new Rectangle(0.4f, 0.4f, 0.4f, 0.4f));
- // //ControlArea = new Rectangle(0.0f, 0.0f, 0.5f, 0.5f));
- // LocalArea = new Rectangle(0.25f, 0.25f, 0.5f, 0.15f),
- // //Rotation = 45,
- // Alignment = AlignmentType.Middle,
- // //PressedDesign = null,
- // };
-
- // testButton.CursorMove += delegate
- // {
- // Log.Test(Time.Milliseconds + ": CursorMoving on button");
- // }; // CursorMoveTest()
-
- // UIScene testScene = new UIScene();
- // testScene.Add(testButton);
-
- // // Open now the scene to "activate" for the test
- // testScene.Open();
- // Application.Start();
- }
- #endregion
-
- #region UsingChilds (Static)
- /// <summary>
- /// Using childs
- /// </summary>
- [Test]
- public static void UsingChilds()
- {
- Settings.Debug.SetDrawDebugInfoMode(ProfilingMode.UI, true);
-
- // The used UI scene for the unit test
- Screen testScene = new Screen();
-
- // The "parent" button which contains the "child1" and "child2" buttons
- Button parent = new Button
- {
- Text = "Parent",
- LocalArea = new Rectangle(0.3f, 0.5f, 0.4f, 0.1f),
- };
- //parent.Rotation = 45;
-
- // Child 1 of the "parent" button
- Button child1 = new Button
- {
- Text = "Child 1",
- LocalArea = new Rectangle(-0.25f, 0.1f, 0.4f, 0.1f),
- };
- parent.Add(child1);
-
- // Child 2 of the "parent" button
- Button child2 = new Button
- {
- Text = "Child 2",
- LocalArea = new Rectangle(0.25f, 0.1f, 0.4f, 0.1f),
- };
- parent.Add(child2);
- // Finally we still have to add the button to a screen that should
- // manage the button
- testScene.Add(parent);
-
- // The label control which shows us the current focued control
- Label focusLabel = new Label
- {
- LocalArea = new Rectangle(0.5f, 0.2f, 0.3f, 0.05f),
- //Alignment = AlignmentType.Top,
- };
- // and the "debug" label
- testScene.Add(focusLabel);
-
- // Finally we "register" the dragging event for all buttons
- //parent.Dragging += DragButton;
- //child1.Dragging += DragButton;
- //child2.Dragging += DragButton;
-
- // Open now the scene to "activate" for the test
- testScene.Open();
- // before we finally start the graphical test...
- Application.Start(delegate
- {
- //// Cycling through all alignment modes of the "parent" button by
- //// pressing the "Space" key
- //if (Input.Keyboard.SpaceReleased)
- //{
- // parent.Alignment = EnumHelper.NextValue(parent.Alignment);
- // parent.Text = "Alignment=" + parent.Alignment;
- //}
-
- // For easier checking we just display the current focused on the
- // label
- Button button = testScene.FocusedControl as Button;
- if (testScene.FocusedControl != null)
- {
- string focusesText = (button != null)
- ? button.Text
- : testScene.FocusedControl.GetType().Name;
- focusLabel.Text = "Focused=" + focusesText;
- } // if
- else
- {
- focusLabel.Text = "Nothing Focused";
- }
- // Start the visual test to see the button
- });
- }
- #endregion
-
- #region Rotation (Static)
- /// <summary>
- /// Rotation
- /// </summary>
- [Test]
- public static void Rotation()
- {
- // Button testButton = new Button
- // {
- // LocalArea = new Rectangle(0.05f, 0.15f, 0.3f, 0.1f),
- // //Alignment = AlignmentType.Middle,
- // };
-
- // UIScene testScene = new UIScene();
- // testScene.Add(testButton);
-
- // // Open now the scene to "activate" for the test
- // testScene.Open();
-
- // Application.Start(delegate
- // {
- // testButton.Rotation += 20.0f * Time.Delta;
- // // Start the visual test to see the button
- // });
- }
- #endregion
-
- #region DepthLayers (Static)
- /// <summary>
- /// Depth layers
- /// </summary>
- [Test]
- public static void DepthLayers()
- {
- // // The used UI scene for the unit test
- // UIScene uiScene = Base.GameScreen.OverlayScreen.UIScene;
-
- // Button buttonDepth6 = new Button
- // {
- // LocalArea = new Rectangle(0.25f, 0.25f, 0.4f, 0.2f),
- // DepthLayer = 6,
- // };
- // buttonDepth6.Text = "DepthLayer=" + buttonDepth6.DepthLayer;
- // buttonDepth6.BlendColor = Color.Green;
- // uiScene.Add(buttonDepth6);
-
- // Button buttonDepth10 = new Button
- // {
- // LocalArea = new Rectangle(0.45f, 0.3f, 0.4f, 0.2f),
- // DepthLayer = 10,
- // };
- // buttonDepth10.Text = "DepthLayer=" + buttonDepth10.DepthLayer;
- // buttonDepth10.BlendColor = Color.Blue;
- // uiScene.Add(buttonDepth10);
-
- // Button buttonDefaultLayer = new Button
- // {
- // LocalArea = new Rectangle(0.35f, 0.4f, 0.4f, 0.2f),
- // };
- // buttonDefaultLayer.Text = "DefaultLayer (DepthLayer=" +
- // buttonDefaultLayer.DepthLayer + ")";
- // buttonDefaultLayer.BlendColor = Color.Grey;
- // uiScene.Add(buttonDefaultLayer);
-
- // Base.UI.ShowDebugInfo = true;
-
- // Base.StartTest("Display Button", delegate
- // {
- // // Start the visuial test to see the button
- // });
- }
- #endregion
- }
- }
- }