Events
From Guichan
Guichan comes with a sophisticated event system much like the event system found in Java. Events are very important to understand in order to fully be able to use Guichan.
Contents |
The event hierarchy
All events in Guichan are part of the event hierarchy. The hierarchy is made up of a couple of classes.
Event +-> ActionEvent
|
+-> InputEvent +-> KeyEvent
|
+->MouseEvent
Event is the base class and represents a generic event (such as a death event or a focus event), ActionEvent represents an action event triggered by a widget, InputEvent represents an input event, KeyEvent represents a key input event and MouseEvent represents a mouse input event.
Receiving events
To be able to receive events an implementation of an event listener must be used. In Guichan there exists a listener interface for each type of receivable event. All events come from widgets and all that is required for an implemented listener to receive events is to add the implemented listener to a widget. As soon as an event is fired all listeners of the widget will be notified.
A widget can listen for events from itself. An example of that is the Button widget that implements the MouseListener interface and listens for mouse events from itself in order to get notified it it was clicked or not. How to implement a listener for a certain type of event and how the event is distributed is explained later on.
Basic events
All events derives from the Event base class. How events are distributed and when they are distributed depends on the event type. All events have in common a widget which is the source of the event. The source widget is accessible by calling the Event::getSource function.
void MyCustomWidget::action(const ActionEvent& actionEvent)
{
Widget* sourceWidget = actionEvent.getSource();
}
An example of using Event::getSource with an ActionEvent.
Input events
Input events are events that concerns input. Input can be key input or mouse input. All input events are consumable. The difference between consumed events and non consumed events is that consumed events are simply marked as consumed where as non consumed events are not marked as consumed. It's all up to the listener and receiver of an input event to take a different action depending on if the received event has been consumed or not.
To consume an input event the InputEvent::consume function is used. To check if an input event has been consumed the InputEvent::isConsumed is used.
void MyCustomWidget::mouseWheelMovedDown(MouseEvent& mouseEvent)
{
mouseEvent.consume();
}
An example of using InputEvent::consume with a MouseEvent.
Key events
Key events are events that concerns key input. They fire as soon as key input is received by Guichan. Key events are distributed to the key listeners of the source widget of the event and the source widget's parents. The source widget is always the widget with focus.
Receiving key events
To receive key events an implementation of a key listener must be used.
#include <guichan.hpp>
#include <iostream>
class MyKeyListener : public gcn::KeyListener
{
void keyPressed(gcn::KeyEvent& keyEvent)
{
std::cout << "Key pressed: " << keyEvent.getKey().getValue() << std::endl;
}
void keyReleased(gcn::KeyEvent& keyEvent)
{
std::cout << "Key released: " << keyEvent.getKey().getValue() << std::endl;
}
};
An example of an implemented key listener which prints the key values pressed and released.
To receive key events from a button add the implementation as a key listener of a button.
MyKeyListener myKeyListener;
gcn::Button* button;
void foo()
{
button->addKeyListener(&keyListener);
}
An example of adding a key listener to a button.
To make a widget receive key events the widget should inherit from KeyListener and add itself as a key listener of itself.
#include <guichan.hpp>
#include <iostream>
class MyCustomWidget: public gcn::Widget, public gcn::KeyListener
{
public:
MyCustomWidget()
{
// The widget needs to be focusable in order to receive key events.
setFocusable(true);
addKeyListener(this);
}
void keyPressed(gcn::KeyEvent& keyEvent)
{
std::cout << "Key pressed: " << keyEvent.getKey().getValue() << std::endl;
}
void keyReleased(gcn::KeyEvent& keyEvent)
{
std::cout << "Key released: " << keyEvent.getKey().getValue() << std::endl;
}
};
An example of a widget which is only capable of printing key events.
Mouse events
Mouse events are events which concerns mouse input. They fire as soon as mouse input is received by Guichan. Mouse events are distributed to the mouse listeners of the source widget of the event and the source widget's parents, except when it comes to mouse in and mouse out events which are only distributed to the source widget. The source widget is always the widget directly under the mouse cursor when mouse input is received by Guichan, except when it comes to drag events where the source widget is the widget where the drag event started.
Mouse events are in other words distributed in a bottom up approach. The reason for this is that if a widget, like a button, is pressed using the mouse the widget's container, a window for instance, is also pressed and should therefore also receive the mouse event.
Chain of responsibility
The design of bottom up distribution introduces a chain of responsibility. If a widget needs to consume an event, like a slider wants to consume mouse wheel events, widgets acting on the same event, such as a scroll area, should discard the input if it has been consumed.
Receiving mouse events
To receive mouse events an implementation of a mouse listener must be used.
#include <guichan.hpp>
#include <iostream>
class MyMouseListener : public gcn::MouseListener
{
void mousePressed(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse pressed: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseReleased(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse pressed: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseClicked(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse clicked: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseMoved(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse moved: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseEntered(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse entered: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseExited(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse exited: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseWheelMovedDown(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse wheel down moved: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseWheelMovedUp(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse wheel up moved: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseDragged(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse dragged: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
};
An example of an implemented mouse listener which prints the x and y coordinate of the mouse event. The coordinates are relative to the source widget.
To receive mouse events from a button add the implementation as a mouse listener of a button.
MyMouseListener myMouseListener;
gcn::Button* button;
void foo()
{
button->addMouseListener(&MouseListener);
}
An example of adding a mouse listener to a button.
To make a widget receive mouse events the widget should inherit from MouseListener and add itself as a mouse listener of itself.
#include <guichan.hpp>
#include <iostream>
class MyCustomWidget: public gcn::Widget, public gcn::MouseListener
{
public:
MyCustomWidget()
{
addMouseListener(this);
}
void mousePressed(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse pressed: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
void mouseReleased(gcn::MouseEvent& mouseEvent)
{
std::cout << "Mouse pressed: " << mouseEvent.getX() << " " << mouseEvent.getY() << std::endl;
}
};
An example of a widget that is only capable of printing information about two mouse events.
Action events
Action events are events which concerns widgets. An action event is fired by a widget and distributed to all action listeners of the widget. The source of the event is always the widget that fired the event. What makes the widget fire an action event depends on the widget type. An example of an action event is a button which is pressed or a list box where an item in the list is selected.
Receiving action events
To receive action events an implementation of an action listener must be used. In the example below the action id of the event is printed. The action id is a string which can be set to all widgets by calling Widget::setActionId. A neat thing with the action id is that two widgets can have the same action id and that way two widgets actions can be treated equally with the same action listener.
#include <guichan.hpp>
#include <iostream>
class MyActionListener : public gcn::ActionListener
{
void action(const gcn::ActionEvent& actionEvent)
{
std::cout << "Action : " << actionEvent.getId() << std::endl;
}
};
An example of an implementation of an action listener which prints the id of the action.
To receive action events from a button add the action listener implementation to the action listeners of the button.
MyActionListener myActionListener;
gcn::Button* button;
void foo()
{
button->addActionListener(&myActionListener);
}
An example of adding an action listener to a button.
Death events
Death events are events which concerns the death of a widget. When a widget is deleted it sends a death event to all of it's death listeners. The source widget is always the widget being deleted. Death events doesn't have it's own derived event class, instead the base event class is used.
Receiving death events
To receive death events an implementation of a death listener must be used.
#include <guichan.hpp>
#include <iostream>
class MyDeathListener : public gcn::DeathListener
{
void death(const gcn::Event& event)
{
std::cout << "Death : " << event.getSource() << std::endl;
}
};
An example of an implementation of a death listener which prints the pointer to the widget who died.
To receive death events from a button add the death listener implementation to the death listeners of the button.
MyDeathListener myDeathListener;
gcn::Button* button;
void foo()
{
button->addDeathListener(&myDeathListener);
}
An example of adding a death listener to a button.
Focus events
Focus events are events which concerns focus of a widget. When a widget gains focus or loses focus a focus event is distributed to all focus listeners of the source widget. The source widget is always the widget the focus change concerns. Focus events doesn't have it's own derived event class, instead the base event class is used.
Receiving focus events
To receive focus events an implementation of a focus listener must be used.
#include <guichan.hpp>
#include <iostream>
class MyFocusListener : public gcn::FocusListener
{
void focusGained(const gcn::Event& event)
{
std::cout << "Focus gained: " << event.getSource() << std::endl;
}
void focusLost(const gcn::Event& event)
{
std::cout << "Focus lost : " << event.getSource() << std::endl;
}
};
An example of an implementation of a focus listener which prints the pointer to the widget the focus changes concerns.
To receive focus events from a button add the focus listener implementation to the focus listeners of the button.
MyFocusListener myFocusListener;
gcn::Button* button;
void foo()
{
button->addFocusListener(&myFocusListener);
}
An example of adding a focus listener to a button.
A portable C++ GUI library designed for games using Allegro, HGE, OpenGL, OpenLayer and/or SDL.
