So I am building custom UI for my MonoGame project. I've gotten pretty far already, having created Controls such as:
- Button
- Panel
- TextBox
- Form
- ComboBox
- CheckBox
- etc.
All of these controls obviously inherit from my abstract class Control
.
This is how I check for Click on a Control
:
if (Destination.Intersects(inputManager.MouseRect) && inputManager.IsMouseClicked(MouseButton.Left)) {
Click?.Invoke(this, EventArgs.Empty);
_focused = true;
}
else if (!Destination.Intersects(inputManager.MouseRect) && inputManager.IsMouseClicked(MouseButton.Left)) {
_focused = false;
}
This method has gotten me pretty far already, but unfortunately it doesn't work when there are multiple TextBox
es: each TextBox
I click on will become focused, and any key I press will be typed in every focused TextBox
.
Here is how I hacked around this:
- Since all Controls (including
TextBox
es) the user sees are placed in a certainPanel
, they are in that panel's array of Controls. - I added a
Panel _parent
to theControl
class, thus every control would have a reference to the panel that owns it - Then in the
Panel
class I added aControl FocusedControl
, so that everyPanel
will have one field for its focused control
So now I'm checking like this:
if (_parent.FocusedControl == this)
// This specific control is focused
Or like this:
if (_parent.FocusedControl != null)
// There is a focused Control
if (_parent.FocusedControl == null)
// No control is focused in this panel
This works.
But the problem is that I am doing these checks in the controls themselves, and not, for example, in the Panel
class.
This means each control has a reference to the panel that owns it, and that panel has a list of all the controls. Also the panel's public methods and properties are available to the owned control.
This eliminates encapsulation and is effectively terrible design.
I consider this to be a huge mess and a dirty hack. Is there any other way to make sure that a Panel
has only one focused Control
at a time?