Added some rudimentary mouse handling support.

This commit is contained in:
Mark de Wever 2008-03-11 19:35:49 +00:00
parent f091fbc440
commit 85661240b1
5 changed files with 122 additions and 24 deletions

View file

@ -48,7 +48,9 @@ tevent_info::tevent_info() :
mouse_last_middle_button_down(false),
mouse_last_right_button_down(false),
event_mouse_button(-1)
event_mouse_button(-1),
mouse_focus(0)
{
}

View file

@ -20,6 +20,8 @@
namespace gui2{
class twidget;
struct tevent_info
{
tevent_info();
@ -42,6 +44,9 @@ struct tevent_info
bool mouse_last_right_button_down; //! Was the right mouse button down in the last event?
int event_mouse_button; //! If a mouse event it shows which button changed.
twidget* mouse_focus;
};
} // namespace gui2

View file

@ -65,12 +65,25 @@ struct terror
class tevent_executor
{
public:
tevent_executor(const bool send_double_click = true) :
send_double_click_(send_double_click)
tevent_executor(const bool want_double_click = false/* true */) :
want_double_click_(want_double_click)
{}
virtual ~tevent_executor() {}
//! Happens when a mouse goes down on the widget.
// Description of various event generating scenarios
//
// mouse moves on a widget and the focus isn't stolen:
// - mouse enter
//
// mouse on widget clicked without moving
// - mouse down
// - mouse up
// wait for possible double click if widget wants double click
// - mouse click
//! Happens when a mouse goes down on the widget. When the mouse goes
//! down this widget steals the mouse focus until the button is released.
virtual void mouse_down(const tevent_info&, bool&) {}
//! Happens when a mouse down focussed this widget and is released
@ -79,10 +92,19 @@ public:
//! Happens when a mouse down and up happen on the same widget.
virtual void mouse_click(const tevent_info&, bool&) {}
//! Happens when a mouse down and up happen twice on the same widget.
virtual void mouse_double_click(const tevent_info& event, bool& handled)
{ if(!send_double_click_) mouse_click(event, handled); }
virtual void mouse_double_click(const tevent_info&, bool&) {}
//! Happens when the mouse moves over the widget and the focus
//! isn't stolen by another widget.
virtual void mouse_enter(const tevent_info&, bool&) {}
//! Happens when the mouse leaves a widget, execpt when the focus
//! is captured. If this widget captures the focus the event is
//! send after the mouse button is released.
virtual void mouse_leave(const tevent_info&, bool&) {}
#if 0
virtual void mouse_enter();
@ -107,12 +129,12 @@ public:
// children.
virtual void layout() {}
bool want_double_click() const { return want_double_click_; }
private:
//! If a widget doesn't want a double click we need to send a second
//! click instead of double click.
bool send_double_click_;
bool want_double_click_;
};
//! Base class for all widgets.
@ -120,7 +142,7 @@ private:
class twidget : public virtual tevent_executor
{
public:
twidget(const std::string& id = "") :
twidget(const std::string& id = "") :
id_(id),
parent_(0),
x_(-1),
@ -517,7 +539,12 @@ public:
virtual void set_height(const int height);
void mouse_down(const tevent_info& /*event*/, bool& /*handled*/) { std::cerr << "Hit me again\n"; }
void mouse_down(const tevent_info& /*event*/, bool& /*handled*/) { std::cerr << "mouse down\n"; }
void mouse_up(const tevent_info& /*event*/, bool& /*handled*/) { std::cerr << "mouse up\n"; }
void mouse_click(const tevent_info& /*event*/, bool& /*handled*/) { std::cerr << "mouse click\n"; }
void mouse_double_click(const tevent_info& /*event*/, bool& /*handled*/) { std::cerr << "mouse double click\n"; }
void mouse_enter(const tevent_info& /*event*/, bool& /*handled*/) { std::cerr << "mouse enter\n"; }
void mouse_leave(const tevent_info& /*event*/, bool& /*handled*/) { std::cerr << "mouse leave\n"; }
void draw(surface& canvas);

View file

@ -165,10 +165,10 @@ void twindow::handle_event(const SDL_Event& event)
handle_event_mouse_down(event);
break;
case SDL_MOUSEBUTTONUP:
// std::cerr << "Mouse up on control " << typeid(this).name() << '\n';
handle_event_mouse_up(event);
break;
case SDL_MOUSEMOTION:
// std::cerr << "Mouse move on control " << typeid(this).name() << '\n';
handle_event_mouse_move(event);
break;
}
@ -180,10 +180,15 @@ void twindow::handle_event_mouse_down(const SDL_Event& event)
event_info_.event_mouse_button = event.button.button;
event_info_.mouse_x = event.button.x;
event_info_.mouse_y = event.button.y;
event_info_.mouse_focus = get_widget(tpoint(event_info_.mouse_x - get_x(), event_info_.mouse_y - get_y()));
bool handled = false;
switch(event_info_.event_mouse_button) {
case SDL_BUTTON_LEFT :
event_info_.mouse_left_button_down = true;
if(event_info_.mouse_focus) {
event_info_.mouse_focus->mouse_down(event_info_, handled);
}
break;
case SDL_BUTTON_MIDDLE :
event_info_.mouse_middle_button_down = true;
@ -195,21 +200,74 @@ void twindow::handle_event_mouse_down(const SDL_Event& event)
// Note: other mouse buttons are ignored, the event
// is send but the status won't be remembered.
}
}
//! Handler for a mouse down.
void twindow::handle_event_mouse_up(const SDL_Event& event)
{
event_info_.event_mouse_button = event.button.button;
event_info_.mouse_x = event.button.x;
event_info_.mouse_y = event.button.y;
twidget* mouse_focus = get_widget(tpoint(event_info_.mouse_x - get_x(), event_info_.mouse_y - get_y()));
// Send the event to the widget at this location.
// Note containers first send the event to their child
// and when not handled it's handled by the container.
bool handled = false;
for(tsizer::iterator itor = begin(); itor != end(); ++itor) {
// for(std::multimap<std::string, twidget *>::iterator itor =
// children().begin(); itor != children().end(); ++itor) {
twidget* widget = *itor;
if(widget) {
widget->mouse_down(event_info_, handled);
switch(event_info_.event_mouse_button) {
case SDL_BUTTON_LEFT :
if(event_info_.mouse_focus) {
event_info_.mouse_focus->mouse_up(event_info_, handled);
if(event_info_.mouse_focus == mouse_focus) {
if(event_info_.mouse_focus->want_double_click()) {
// double click not implemented atm.
assert(false);
} else {
event_info_.mouse_focus->mouse_click(event_info_, handled);
}
}
}
event_info_.mouse_left_button_down = false;
break;
case SDL_BUTTON_MIDDLE :
event_info_.mouse_middle_button_down = false;
break;
case SDL_BUTTON_RIGHT :
event_info_.mouse_right_button_down = false;
break;
// Note: other mouse buttons are ignored, the event
// is send but the status won't be remembered.
}
event_info_.mouse_focus = 0; // Note to see what to do after moving
}
//! Handler for a mouse movement.
void twindow::handle_event_mouse_move(const SDL_Event& event)
{
event_info_.mouse_x = event.button.x;
event_info_.mouse_y = event.button.y;
twidget* mouse_focus = get_widget(tpoint(event_info_.mouse_x - get_x(), event_info_.mouse_y - get_y()));
if(mouse_focus != event_info_.mouse_focus) {
if(event_info_.mouse_focus) {
bool handled = false;
event_info_.mouse_focus->mouse_leave(event_info_, handled);
}
if(mouse_focus) {
bool handled = false;
mouse_focus->mouse_enter(event_info_, handled);
}
}
event_info_.mouse_focus = mouse_focus;
}
} // namespace gui2

View file

@ -91,6 +91,12 @@ private:
//! Handler for a mouse down.
void handle_event_mouse_down(const SDL_Event& event);
//! Handler for a mouse up.
void handle_event_mouse_up(const SDL_Event& event);
//! Handler for a mouse movement.
void handle_event_mouse_move(const SDL_Event& event);
};
} // namespace gui2