5#include "fifechan/gui.hpp"
16#include "fifechan/deathlistener.hpp"
17#include "fifechan/exception.hpp"
18#include "fifechan/focushandler.hpp"
19#include "fifechan/graphics.hpp"
20#include "fifechan/input.hpp"
21#include "fifechan/keyevent.hpp"
22#include "fifechan/keyinput.hpp"
23#include "fifechan/keylistener.hpp"
24#include "fifechan/mouseevent.hpp"
25#include "fifechan/mouseinput.hpp"
26#include "fifechan/mouselistener.hpp"
27#include "fifechan/rectangle.hpp"
28#include "fifechan/visibilityeventhandler.hpp"
29#include "fifechan/widget.hpp"
66 mFocusHandler(new FocusHandler()),
67 mVisibilityEventHandler(new VisibilityEventHandler(this)),
70 mControlPressed(false),
72 mLastMousePressButton(0),
73 mLastMousePressTimeStamp(0),
77 mLastMouseDragButton(0),
78 mDeathListener(new GuiDeathListener(this))
88 if (
mTop !=
nullptr) {
89 mTop->_setFocusHandler(
nullptr);
107 if (
mTop !=
nullptr) {
108 mTop->_setFocusHandler(
nullptr);
110 if (top !=
nullptr) {
176 void Gui::initialize(std::unique_ptr<Graphics> graphics, std::unique_ptr<Input> input,
int width,
int height)
192 throwException(
"No graphics set");
195 auto createdFont =
mGraphics->createFont(filename, size);
197 throwException(
"Failed to create font using active graphics backend");
206 if (
mTop ==
nullptr) {
207 throwException(
"No top widget set");
228 if (
mTop ==
nullptr) {
229 throwException(
"No top widget set");
233 throwException(
"No graphics set");
236 if (!
mTop->isVisible()) {
282 std::queue<Widget*> tmp;
285 if (shownWidget != widget) {
286 tmp.push(shownWidget);
292 tmp = std::queue<Widget*>();
295 if (hiddenWidget != widget) {
296 tmp.push(hiddenWidget);
305 while (!
mInput->isMouseQueueEmpty()) {
308 switch (mouseInput.
getType()) {
309 case MouseInput::Type::Pressed:
312 case MouseInput::Type::Released:
315 case MouseInput::Type::Moved:
318 case MouseInput::Type::WheelMovedDown:
321 case MouseInput::Type::WheelMovedUp:
324 case MouseInput::Type::WheelMovedRight:
327 case MouseInput::Type::WheelMovedLeft:
331 throwException(
"Unknown mouse input type.");
346 while (!
mInput->isKeyQueueEmpty()) {
355 KeyEvent keyEventToGlobalKeyListeners(
370 if (keyEventToGlobalKeyListeners.
isConsumed()) {
374 bool keyEventConsumed =
false;
403 keyInput.
getType() == KeyInput::Type::Pressed) {
420 if (mouseInput.
getX() < 0 || mouseInput.
getY() < 0 ||
421 !
mTop->getDimension().isContaining(mouseInput.
getX(), mouseInput.
getY())) {
422 std::set<Widget*>::const_iterator iter;
423 for (iter = mLastWidgetsWithMouse.begin(); iter != mLastWidgetsWithMouse.end(); ++iter) {
426 MouseEvent::Type::Exited,
440 std::set<Widget*> mWidgetsWithMouseExited;
441 std::set<Widget*> mWidgetsWithMouseEntered;
442 std::ranges::set_difference(
443 mLastWidgetsWithMouse,
447 std::inserter(mWidgetsWithMouseExited, mWidgetsWithMouseExited.begin()));
448 std::ranges::set_difference(
451 mLastWidgetsWithMouse,
453 std::inserter(mWidgetsWithMouseEntered, mWidgetsWithMouseEntered.begin()));
455 std::set<Widget*>::const_iterator iter;
456 for (iter = mWidgetsWithMouseExited.begin(); iter != mWidgetsWithMouseExited.end(); ++iter) {
459 MouseEvent::Type::Exited,
472 for (iter = mWidgetsWithMouseEntered.begin(); iter != mWidgetsWithMouseEntered.end(); ++iter) {
481 MouseEvent::Type::Entered,
494 MouseEvent::Type::Dragged,
502 MouseEvent::Type::Moved,
517 int sourceWidgetX = 0;
518 int sourceWidgetY = 0;
535 MouseEvent::Type::Pressed,
557 int sourceWidgetX = 0;
558 int sourceWidgetY = 0;
563 MouseEvent::Type::WheelMovedDown,
577 int sourceWidgetX = 0;
578 int sourceWidgetY = 0;
583 MouseEvent::Type::WheelMovedUp,
597 int sourceWidgetX = 0;
598 int sourceWidgetY = 0;
603 MouseEvent::Type::WheelMovedRight,
617 int sourceWidgetX = 0;
618 int sourceWidgetY = 0;
623 MouseEvent::Type::WheelMovedLeft,
641 int sourceWidgetX = 0;
642 int sourceWidgetY = 0;
647 MouseEvent::Type::Released,
656 MouseEvent::Type::Clicked,
678 while (child !=
nullptr) {
683 child = parent->
getWidgetAt(x - parentX, y - parentY, exclude);
692 std::set<Widget*> result;
696 while (widget !=
nullptr) {
697 result.insert(widget);
701 widget = widget->
getWidgetAt(x - absoluteX, y - absoluteY);
745 source, source,
mShiftPressed,
mControlPressed,
mAltPressed,
mMetaPressed, type, button, x, y,
mClickCount);
747 while (parent !=
nullptr) {
761 mouseEvent.
mX = x - widgetX;
762 mouseEvent.
mY = y - widgetY;
767 for (
auto& mouseListener : mouseListeners) {
768 switch (mouseEvent.
getType()) {
769 case MouseEvent::Type::Entered:
770 mouseListener->mouseEntered(mouseEvent);
772 case MouseEvent::Type::Exited:
773 mouseListener->mouseExited(mouseEvent);
775 case MouseEvent::Type::Moved:
776 mouseListener->mouseMoved(mouseEvent);
778 case MouseEvent::Type::Pressed:
779 mouseListener->mousePressed(mouseEvent);
781 case MouseEvent::Type::Released:
782 mouseListener->mouseReleased(mouseEvent);
784 case MouseEvent::Type::WheelMovedUp:
785 mouseListener->mouseWheelMovedUp(mouseEvent);
787 case MouseEvent::Type::WheelMovedDown:
788 mouseListener->mouseWheelMovedDown(mouseEvent);
790 case MouseEvent::Type::WheelMovedRight:
791 mouseListener->mouseWheelMovedRight(mouseEvent);
793 case MouseEvent::Type::WheelMovedLeft:
794 mouseListener->mouseWheelMovedLeft(mouseEvent);
796 case MouseEvent::Type::Dragged:
797 mouseListener->mouseDragged(mouseEvent);
799 case MouseEvent::Type::Clicked:
800 mouseListener->mouseClicked(mouseEvent);
803 throwException(
"Unknown mouse event type.");
812 Widget const * swap = widget;
824 if (
mFocusHandler->getModalMouseInputFocused() !=
nullptr && widget !=
nullptr &&
840 while (parent !=
nullptr) {
854 for (
auto& keyListener : keyListeners) {
856 case KeyEvent::Type::Pressed:
857 keyListener->keyPressed(keyEvent);
859 case KeyEvent::Type::Released:
860 keyListener->keyReleased(keyEvent);
863 throwException(
"Unknown key event type.");
868 Widget const * swap = widget;
886 case KeyEvent::Type::Pressed:
887 (*it)->keyPressed(keyEvent);
889 case KeyEvent::Type::Released:
890 (*it)->keyReleased(keyEvent);
893 throwException(
"Unknown key event type.");
906 (
mFocusHandler->getLastWidgetWithModalMouseInputFocus() ==
nullptr)) {
911 (
mFocusHandler->getLastWidgetWithModalMouseInputFocus() !=
nullptr)) {
936 std::set<Widget*>::const_iterator iter;
937 for (iter = mWidgetsWithMouse.begin(); iter != mWidgetsWithMouse.end(); ++iter) {
938 if ((*iter)->isModalFocused() || (*iter)->isModalMouseInputFocused()) {
943 MouseEvent::Type::Exited,
959 std::set<Widget*>::const_iterator iter;
960 for (iter = mWidgetsWithMouse.begin(); iter != mWidgetsWithMouse.end(); ++iter) {
963 MouseEvent::Type::Entered,
979 std::set<Widget*>::const_iterator iter;
980 for (iter = mWidgetsWithMouse.begin(); iter != mWidgetsWithMouse.end(); ++iter) {
981 if ((*iter)->isModalMouseInputFocused()) {
986 MouseEvent::Type::Exited,
1002 std::set<Widget*>::const_iterator iter;
1003 for (iter = mWidgetsWithMouse.begin(); iter != mWidgetsWithMouse.end(); ++iter) {
1006 MouseEvent::Type::Entered,
1013 mFocusHandler->setLastWidgetWithModalMouseInputFocus(
nullptr);
1025 int hiddenWidgetX = 0;
1026 int hiddenWidgetY = 0;
1037 MouseEvent::Type::Entered,
1038 MouseEvent::Button::Empty,
1057 int shownWidgetX = 0;
1058 int shownWidgetY = 0;
1068 underMouseCursorBefore,
1069 MouseEvent::Type::Exited,
1070 MouseEvent::Button::Empty,
1081 underMouseCursorNow,
1082 MouseEvent::Type::Entered,
1083 MouseEvent::Button::Empty,
Base class for all GUI event objects.
Widget * getSource() const
Gets the source widget of the event.
Manages focus navigation and assignment among widgets within a Gui instance.
virtual Widget * getFocused() const
Gets the widget with focus.
Abstract interface providing primitive drawing functions (lines, rectangles, etc.).
Internal listener that forwards death notifications from widgets to the owning Gui so it can clean up...
GuiDeathListener(Gui *gui)
Construct a GuiDeathListener bound to a Gui instance.
void death(Event const &event) override
Called when a widget dies.
Graphics * mGraphics
Holds the graphics implementation used.
virtual void distributeKeyEvent(KeyEvent &keyEvent)
Distributes a key event.
Widget * mTop
Holds the top widget.
Input * mInput
Holds the input implementation used.
virtual void distributeKeyEventToGlobalKeyListeners(KeyEvent &keyEvent)
Distributes a key event to the global key listeners.
virtual Graphics * getGraphics() const
Gets the graphics object used for drawing.
virtual Input * getInput() const
Gets the input object being used for input handling.
virtual void handleModalMouseInputFocus()
Handles modal mouse input focus.
virtual void focusNone()
Focuses none of the widgets in the Gui.
Widget * getWidgetAt(int x, int y)
Gets the widget at a certain position.
FocusHandler * mFocusHandler
Holds the focus handler for the Gui.
virtual void setRoot(Widget *top)
Alias for setTop.
KeyListenerList mKeyListeners
Holds the global key listeners of the Gui.
bool mTabbing
True if tabbing is enabled, false otherwise.
virtual void draw()
Draws the GUI.
std::queue< Widget * > mShownWidgets
Holds shown widgets.
int mLastMouseDragButton
Holds the last button used when a drag of a widget was initiated.
virtual std::set< Widget * > getWidgetsAt(int x, int y)
Gets all widgets a certain coordinate in the Gui.
virtual void handleModalFocus()
Handles modal focus.
virtual FocusHandler * getFocusHandler() const
Returns the focus handler used by this GUI.
void distributeMouseEvent(Widget *source, MouseEvent::Type type, MouseEvent::Button button, int x, int y)
Convenience overload: distribute a mouse event forwarding to the full overload with force and toSourc...
int mLastMousePressTimeStamp
Holds the last mouse press time stamp.
virtual Widget * getMouseEventSource(int x, int y)
Gets the source of the mouse event.
unsigned int mLastMousePressButton
Holds the last mouse button pressed.
virtual void handleMouseInput()
Handles all mouse input.
virtual void setGraphics(Graphics *graphics)
Sets the graphics object to use for drawing.
virtual void handleModalFocusReleased()
Handles modal focus released.
bool mControlPressed
True if control is pressed, false otherwise.
bool mMetaPressed
True if meta is pressed, false otherwise.
virtual void initialize(std::unique_ptr< Graphics > graphics, std::unique_ptr< Input > input, int width, int height)
Initializes GUI backends in one call.
std::unique_ptr< Widget > mOwnedTop
Optional owned top widget (when Gui takes ownership).
std::unique_ptr< Graphics > mOwnedGraphics
Optional owned graphics backend instance.
virtual Widget * getKeyEventSource()
Gets the source of the key event.
int mLastMouseX
Holds the last mouse x coordinate.
virtual void handleMouseWheelMovedRight(MouseInput const &mouseInput)
Handles mouse wheel moved right input.
virtual void setInput(Input *input)
Sets the input object to use for input handling.
void enqueueShownWidget(Widget *widget)
Inform gui that a widget was shown.
virtual void setTabbingEnabled(bool tabbing)
Sets tabbing enabled, or not.
virtual void handleModalMouseInputFocusReleased()
Handles modal mouse input focus released.
virtual Widget * getTop() const
Gets the top widget.
virtual void handleKeyInput()
Handles key input.
virtual void handleHiddenWidgets()
Handles hidden widgets.
std::queue< Widget * > mHiddenWidgets
Holds hidden widgets.
bool mAltPressed
True if alt is pressed, false otherwise.
int mLastMouseY
Holds the last mouse y coordinate.
KeyListenerList::iterator KeyListenerListIterator
Typedef.
virtual void handleShownWidgets()
Handles shown widgets.
GuiDeathListener * mDeathListener
Listener notified when the GUI or top widget is destroyed.
virtual void handleMouseWheelMovedDown(MouseInput const &mouseInput)
Handles mouse wheel moved down input.
virtual bool isTabbingEnabled()
Checks if tabbing is enabled.
std::unique_ptr< Input > mOwnedInput
Optional owned input backend instance.
virtual void removeGlobalKeyListener(KeyListener *keyListener)
Removes global key listener from the Gui.
std::shared_ptr< Font > mGlobalFont
Shared global font used by widgets when not overridden.
virtual void handleModalMouseInputFocusGained()
Handles modal mouse input focus gained.
virtual void handleMouseMoved(MouseInput const &mouseInput)
Handles mouse moved input.
virtual void handleMouseWheelMovedUp(MouseInput const &mouseInput)
Handles mouse wheel moved up input.
virtual void addGlobalKeyListener(KeyListener *keyListener)
Adds a global key listener to the Gui.
virtual void setTop(Widget *top)
Sets the top widget.
bool mShiftPressed
True if shift is pressed, false otherwise.
void enqueueHiddenWidget(Widget *widget)
Inform gui that a widget was hidden.
virtual void setGlobalFont(std::string const &filename, int size)
Loads a font using the active graphics backend and sets it as global widget font.
virtual void handleModalFocusGained()
Handles modal focus gained.
virtual void handleMouseWheelMovedLeft(MouseInput const &mouseInput)
Handles mouse wheel moved left input.
virtual void handleMousePressed(MouseInput const &mouseInput)
Handles mouse pressed input.
void widgetDied(Widget const *widget)
Inform gui that a widget was deleted.
virtual void logic()
Performs logic of the GUI.
int mClickCount
Holds the current click count.
VisibilityEventHandler * mVisibilityEventHandler
Holds the visibility event handler for the Gui.
virtual void handleMouseReleased(MouseInput const &mouseInput)
Handles mouse released input.
Type getType() const
Gets the type of the event.
Interface for listening to keyboard events.
int getValue() const
Gets the value of the key.
Represents a mouse event.
MouseEvent::Type getType() const
Gets the type of the event.
Button
Mouse button types.
int mY
Holds the y-coordinate of the mouse event.
int mX
Holds the x-coordinate of the mouse event.
Represents a rectangular area (X, Y, Width, Height).
bool isContaining(int x, int y) const
Checks the rectangle contains a point.