Logo Search packages:      
Sourcecode: wesnoth-1.9 version File versions  Download package

distributor.cpp

/* $Id: distributor.cpp 46186 2010-09-01 21:12:38Z silene $ */
/*
   Copyright (C) 2009 - 2010 by Mark de Wever <koraq@xs4all.nl>
   Part of the Battle for Wesnoth Project http://www.wesnoth.org/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

#define GETTEXT_DOMAIN "wesnoth-lib"

#include "gui/auxiliary/event/distributor.hpp"

#include "events.hpp"
#include "gui/auxiliary/log.hpp"
#include "gui/auxiliary/timer.hpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/widget.hpp"
#include "gui/widgets/window.hpp"

#include <boost/bind.hpp>

namespace gui2{

namespace event {

/**
 * SDL_AddTimer() callback for the hover event.
 *
 * When this callback is called it pushes a new hover event in the event queue.
 *
 * @param interval                The time parameter of SDL_AddTimer.
 * @param param                   Pointer to a widget that's able to show the
 *                                tooltip (will be used as a dispatcher).
 *
 * @returns                       The new timer interval, 0 to stop.
 */

#if 0
/**
 * SDL_AddTimer() callback for the popup event.
 *
 * This event makes sure the popup is removed again.
 *
 * @param interval                The time parameter of SDL_AddTimer.
 * @param param                   Pointer to parameter structure.
 *
 * @returns                       The new timer interval, 0 to stop.
 */
static Uint32 popup_callback(Uint32 /*interval*/, void* /*param*/)
{
      DBG_GUI_E << "Pushing popup removal event in queue.\n";

      SDL_Event event;
      SDL_UserEvent data;

      data.type = HOVER_REMOVE_POPUP_EVENT;
      data.code = 0;
      data.data1 = 0;
      data.data2 = 0;

      event.type = HOVER_REMOVE_POPUP_EVENT;
      event.user = data;

      SDL_PushEvent(&event);
      return 0;
}
#endif

/**
 * Small helper to keep a resource (boolean) locked.
 *
 * Some of the event handling routines can't be called recursively, this due to
 * the fact that they are attached to the pre queue and when the forward an
 * event the pre queue event gets triggered recursively causing infinite
 * recursion.
 *
 * To prevent that those functions check the lock and exit when the lock is
 * held otherwise grab the lock here.
 */
00087 class tlock
{
public:
      tlock(bool& locked)
            : locked_(locked)
      {
            assert(!locked_);
            locked_ = true;
      }

      ~tlock()
      {
            assert(locked_);
            locked_ = false;
      }
private:
      bool& locked_;
};


/***** ***** ***** ***** tmouse_motion ***** ***** ***** ***** *****/

#define LOG_HEADER "distributor mouse motion [" << owner_.id() << "]: "

tmouse_motion::tmouse_motion(twidget& owner
            , const tdispatcher::tposition queue_position)
      : mouse_focus_(NULL)
      , mouse_captured_(false)
      , owner_(owner)
      , hover_timer_(0)
      , hover_widget_(NULL)
      , hover_position_(0, 0)
      , hover_shown_(true)
      , signal_handler_sdl_mouse_motion_entered_(false)
{
      owner.connect_signal<event::SDL_MOUSE_MOTION>(
              boost::bind(&tmouse_motion::signal_handler_sdl_mouse_motion
                    , this, _2, _3, _5)
            , queue_position);

      owner.connect_signal<event::SHOW_HOVER_TOOLTIP>(
              boost::bind(&tmouse_motion::signal_handler_show_hover_tooltip
                    , this, _2)
            , queue_position);
}

tmouse_motion::~tmouse_motion()
{
      stop_hover_timer();
}

void tmouse_motion::capture_mouse(//twidget* widget)
                  const bool capture)
{
      assert(mouse_focus_);
      mouse_captured_ = capture;
}

void tmouse_motion::signal_handler_sdl_mouse_motion(
              const event::tevent event
            , bool& handled
            , const tpoint& coordinate)
{
      if(signal_handler_sdl_mouse_motion_entered_) {
            return;
      }
      tlock lock(signal_handler_sdl_mouse_motion_entered_);

      DBG_GUI_E << LOG_HEADER << event << ".\n";

      if(mouse_captured_) {
            assert(mouse_focus_);
            if(!owner_.fire(event, *mouse_focus_, coordinate)) {
                  mouse_motion(mouse_focus_, coordinate);
            }
      } else {
            twidget* mouse_over = owner_.find_at(coordinate, true);
            if(mouse_over) {
                  DBG_GUI_E << LOG_HEADER << "Firing: " << event << ".\n";
                  if(owner_.fire(event, *mouse_over, coordinate)) {
                        return;
                  }
            }

            if(!mouse_focus_ && mouse_over) {
                  mouse_enter(mouse_over);
            } else if (mouse_focus_ && !mouse_over) {
                  mouse_leave();
            } else if(mouse_focus_ && mouse_focus_ == mouse_over) {
                  mouse_motion(mouse_over, coordinate);
            } else if(mouse_focus_ && mouse_over) {
                  // moved from one widget to the next
                  mouse_leave();
                  mouse_enter(mouse_over);
            } else {
                  assert(!mouse_focus_ && !mouse_over);
            }
      }
      handled = true;
}

void tmouse_motion::mouse_enter(twidget* mouse_over)
{
      DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_ENTER << ".\n";

      assert(mouse_over);

      mouse_focus_ = mouse_over;
      owner_.fire(event::MOUSE_ENTER, *mouse_over);

      hover_shown_ = false;
      start_hover_timer(mouse_over, get_mouse_position());
}

void tmouse_motion::mouse_motion(twidget* mouse_over, const tpoint& coordinate)
{
      DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_MOTION << ".\n";

      assert(mouse_over);

      owner_.fire(event::MOUSE_MOTION, *mouse_over, coordinate);

      if(hover_timer_) {
            if((abs(hover_position_.x - coordinate.x) > 5)
                        || (abs(hover_position_.y - coordinate.y) > 5)) {

                  stop_hover_timer();
                  start_hover_timer(mouse_over, coordinate);
            }
      }
}

void tmouse_motion::mouse_leave()
{
      DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_LEAVE << ".\n";

      tcontrol* control = dynamic_cast<tcontrol*>(mouse_focus_);
      if(!control || control->get_active()) {
            owner_.fire(event::MOUSE_LEAVE, *mouse_focus_);
      }

      mouse_focus_ = NULL;

      /** @todo also a bit ugly. */
      owner_.get_window()->do_remove_tooltip();
      stop_hover_timer();
}

void tmouse_motion::start_hover_timer(twidget* widget, const tpoint& coordinate)
{
      assert(widget);
      stop_hover_timer();

      if(hover_shown_ || !widget->wants_mouse_hover()) {
            return;
      }

      DBG_GUI_E << LOG_HEADER << "Start hover timer for widget '"
                  << widget->id() << "' at address " << widget << ".\n";

      hover_timer_ = add_timer(50
                  , boost::bind(
                          static_cast<bool (tdispatcher::*) (const tevent
                                , twidget&
                                , void*)>(&tdispatcher::fire)
                        , &owner_
                        , SHOW_HOVER_TOOLTIP
                        , boost::ref(owner_)
                        , static_cast<void*>(NULL)));
      if(hover_timer_) {
            hover_widget_ = widget;
            hover_position_ = coordinate;
      } else {
            ERR_GUI_E << LOG_HEADER << "Failed to add hover timer.\n";
      }
}

void tmouse_motion::stop_hover_timer()
{
      if(hover_timer_) {
            assert(hover_widget_);
            DBG_GUI_E << LOG_HEADER << "Stop hover timer for widget '"
                        << hover_widget_->id() << "' at address "
                        << hover_widget_ << ".\n";

            if(!remove_timer(hover_timer_)) {
                  ERR_GUI_E << LOG_HEADER << "Failed to remove hover timer.\n";
            }

            hover_timer_ = 0;
            hover_widget_ = NULL;
            hover_position_ = tpoint(0, 0);
      }
}

void tmouse_motion::signal_handler_show_hover_tooltip(const event::tevent event)
{
      DBG_GUI_E << LOG_HEADER << event << ".\n";

      if(!hover_widget_) {
            // See tmouse_motion::stop_hover_timer.
            ERR_GUI_E << LOG_HEADER << event << " bailing out, no hover widget.\n";
            return;
      }

      /**
       * @todo See whether this code can be cleanup a bit.
       *
       * It now feels a bit hacky with all the casts. It should work but just is
       * a bit ugly.
       */
      owner_.get_window()->do_show_tooltip(hover_position_
                  , dynamic_cast<tcontrol&>(*hover_widget_).tooltip());
      hover_shown_ = true;

      hover_timer_ = 0;
      hover_widget_ = NULL;
      hover_position_ = tpoint(0, 0);
}

/***** ***** ***** ***** tmouse_button ***** ***** ***** ***** *****/

#undef LOG_HEADER
#define LOG_HEADER "distributor mouse button " \
            << name_ << " [" << owner_.id() << "]: "

template<
              tevent sdl_button_down
            , tevent sdl_button_up
            , tevent button_down
            , tevent button_up
            , tevent button_click
            , tevent button_double_click
> tmouse_button<
              sdl_button_down
            , sdl_button_up
            , button_down
            , button_up
            , button_click
            , button_double_click
>::tmouse_button(
                    const std::string& name_
                  , twidget& owner
                  , const tdispatcher::tposition queue_position)
      : tmouse_motion(owner, queue_position)
      , last_click_stamp_(0)
      , last_clicked_widget_(NULL)
      , focus_(0)
      , name_(name_)
      , is_down_(false)
      , signal_handler_sdl_button_down_entered_(false)
      , signal_handler_sdl_button_up_entered_(false)
{
      owner_.connect_signal<sdl_button_down>(
                    boost::bind(&tmouse_button<
                          sdl_button_down
                        , sdl_button_up
                        , button_down
                        , button_up
                        , button_click
                        , button_double_click
                        >::signal_handler_sdl_button_down, this, _2, _3, _5)
                  , queue_position);
      owner_.connect_signal<sdl_button_up>(
                    boost::bind(&tmouse_button<
                          sdl_button_down
                        , sdl_button_up
                        , button_down
                        , button_up
                        , button_click
                        , button_double_click
                        >::signal_handler_sdl_button_up, this, _2, _3, _5)
                  , queue_position);
}

template<
              tevent sdl_button_down
            , tevent sdl_button_up
            , tevent button_down
            , tevent button_up
            , tevent button_click
            , tevent button_double_click
> void tmouse_button<
              sdl_button_down
            , sdl_button_up
            , button_down
            , button_up
            , button_click
            , button_double_click
>::signal_handler_sdl_button_down(
              const event::tevent event
            , bool& handled
            , const tpoint& coordinate)
{
      if(signal_handler_sdl_button_down_entered_) {
            return;
      }
      tlock lock(signal_handler_sdl_button_down_entered_);

      DBG_GUI_E << LOG_HEADER << event << ".\n";

      if(is_down_) {
            WRN_GUI_E << LOG_HEADER << event
                        << ". The mouse button is already down, "
                        << "we missed an event.\n";
            return;
      }
      is_down_ = true;

      if(mouse_captured_) {
            assert(mouse_focus_);
            focus_ = mouse_focus_;
            DBG_GUI_E << LOG_HEADER << "Firing: " << sdl_button_down << ".\n";
            if(!owner_.fire(sdl_button_down, *focus_, coordinate)) {
                  DBG_GUI_E << LOG_HEADER << "Firing: " << button_down << ".\n";
                  owner_.fire(button_down, *mouse_focus_);
            }
      } else {
            twidget* mouse_over = owner_.find_at(coordinate, true);
            if(!mouse_over) {
                  return;
            }

            if(mouse_over != mouse_focus_) {
                  WRN_GUI_E << LOG_HEADER
                              << ". Mouse down on non focussed widget "
                              << "and mouse not captured, we missed events.\n";
                  mouse_focus_ = mouse_over;
            }

            focus_ = mouse_over;
            DBG_GUI_E << LOG_HEADER << "Firing: " << sdl_button_down << ".\n";
            if(!owner_.fire(sdl_button_down, *focus_, coordinate)) {
                  DBG_GUI_E << LOG_HEADER << "Firing: " << button_down << ".\n";
                  owner_.fire(button_down, *focus_);
            }
      }
      handled = true;
}

template<
              tevent sdl_button_down
            , tevent sdl_button_up
            , tevent button_down
            , tevent button_up
            , tevent button_click
            , tevent button_double_click
> void tmouse_button<
              sdl_button_down
            , sdl_button_up
            , button_down
            , button_up
            , button_click
            , button_double_click
>::signal_handler_sdl_button_up(
              const event::tevent event
            , bool& handled
            , const tpoint& coordinate)
{
      if(signal_handler_sdl_button_up_entered_) {
            return;
      }
      tlock lock(signal_handler_sdl_button_up_entered_);

      DBG_GUI_E << LOG_HEADER << event << ".\n";

      if(!is_down_) {
            WRN_GUI_E << LOG_HEADER << event
                        << ". The mouse button is already up, we missed an event.\n";
            return;
      }
      is_down_ = false;

      if(focus_) {
            DBG_GUI_E << LOG_HEADER << "Firing: " << sdl_button_up << ".\n";
            if(!owner_.fire(sdl_button_up, *focus_, coordinate)) {
                  DBG_GUI_E << LOG_HEADER << "Firing: " << button_up << ".\n";
                  owner_.fire(button_up, *focus_);
            }
      }

      twidget* mouse_over = owner_.find_at(coordinate, true);
      if(mouse_captured_) {
            const unsigned mask =
                        SDL_BUTTON_LMASK | SDL_BUTTON_MMASK | SDL_BUTTON_RMASK;

            if((SDL_GetMouseState(NULL, NULL) & mask ) == 0) {
                  mouse_captured_ = false;
            }

            if(mouse_focus_ == mouse_over) {
                  mouse_button_click(mouse_focus_);
            } else if(!mouse_captured_) {
                  mouse_leave();

                  if(mouse_over) {
                        mouse_enter(mouse_over);
                  }
            }
      } else if(focus_ && focus_ == mouse_over) {
            mouse_button_click(focus_);
      }

      focus_ = NULL;
      handled = true;
}

template<
              tevent sdl_button_down
            , tevent sdl_button_up
            , tevent button_down
            , tevent button_up
            , tevent button_click
            , tevent button_double_click
> void tmouse_button<
              sdl_button_down
            , sdl_button_up
            , button_down
            , button_up
            , button_click
            , button_double_click
>::mouse_button_click(twidget* widget)
{
      Uint32 stamp = SDL_GetTicks();
      if(last_click_stamp_ + settings::double_click_time >= stamp
                  && last_clicked_widget_ == widget) {

            DBG_GUI_E << LOG_HEADER << "Firing: "
                        << button_double_click << ".\n";

            owner_.fire(button_double_click, *widget);
            last_click_stamp_ = 0;
            last_clicked_widget_ = NULL;

      } else {

            DBG_GUI_E << LOG_HEADER << "Firing: " << button_click << ".\n";
            owner_.fire(button_click, *widget);
            last_click_stamp_ = stamp;
            last_clicked_widget_ = widget;
      }
}

/***** ***** ***** ***** tdistributor ***** ***** ***** ***** *****/

#undef LOG_HEADER
#define LOG_HEADER "distributor mouse motion [" << owner_.id() << "]: "

/**
 * @todo At construction we should get the state and from that moment on we
 * keep track of the changes ourselves, not yet sure what happens when an input
 * blocker is used.
 */
00540 tdistributor::tdistributor(twidget& owner
            , const tdispatcher::tposition queue_position)
      : tmouse_motion(owner, queue_position)
      , tmouse_button_left("left"
                  , owner
                  , queue_position)
      , tmouse_button_middle("middle"
                  , owner
                  , queue_position)
      , tmouse_button_right("right"
                  , owner
                  , queue_position)
      , hover_pending_(false)
      , hover_id_(0)
      , hover_box_()
      , had_hover_(false)
      , tooltip_(0)
      , help_popup_(0)
      , keyboard_focus_(0)
      , keyboard_focus_chain_()
{
      if(SDL_WasInit(SDL_INIT_TIMER) == 0) {
            if(SDL_InitSubSystem(SDL_INIT_TIMER) == -1) {
                  assert(false);
            }
      }

      owner_.connect_signal<event::SDL_KEY_DOWN>(
                  boost::bind(&tdistributor::signal_handler_sdl_key_down
                        , this, _5, _6, _7));


      owner_.connect_signal<event::SDL_WHEEL_UP>(
                  boost::bind(
                          &tdistributor::signal_handler_sdl_wheel<event::SDL_WHEEL_UP>
                        , this));
      owner_.connect_signal<event::SDL_WHEEL_DOWN>(
                  boost::bind(
                          &tdistributor::signal_handler_sdl_wheel<event::SDL_WHEEL_DOWN>
                        , this));
      owner_.connect_signal<event::SDL_WHEEL_LEFT>(
                  boost::bind(
                          &tdistributor::signal_handler_sdl_wheel<event::SDL_WHEEL_LEFT>
                        , this));
      owner_.connect_signal<event::SDL_WHEEL_RIGHT>(
                  boost::bind(
                          &tdistributor::signal_handler_sdl_wheel<
                                event::SDL_WHEEL_RIGHT>
                        , this));


      owner_.connect_signal<event::NOTIFY_REMOVAL>(
                  boost::bind(
                          &tdistributor::signal_handler_notify_removal
                        , this
                        , _1
                        , _2));
}

tdistributor::~tdistributor()
{
      owner_.disconnect_signal<event::SDL_KEY_DOWN>(
                  boost::bind(&tdistributor::signal_handler_sdl_key_down
                        , this, _5, _6, _7));


      owner_.disconnect_signal<event::SDL_WHEEL_UP>(
                  boost::bind(
                          &tdistributor::signal_handler_sdl_wheel<event::SDL_WHEEL_UP>
                        , this));
      owner_.disconnect_signal<event::SDL_WHEEL_DOWN>(
                  boost::bind(
                          &tdistributor::signal_handler_sdl_wheel<event::SDL_WHEEL_DOWN>
                        , this));
      owner_.disconnect_signal<event::SDL_WHEEL_LEFT>(
                  boost::bind(
                          &tdistributor::signal_handler_sdl_wheel<event::SDL_WHEEL_LEFT>
                        , this));
      owner_.disconnect_signal<event::SDL_WHEEL_RIGHT>(
                  boost::bind(
                          &tdistributor::signal_handler_sdl_wheel<
                                event::SDL_WHEEL_RIGHT>
                        , this));


      owner_.disconnect_signal<event::NOTIFY_REMOVAL>(
                  boost::bind(
                          &tdistributor::signal_handler_notify_removal
                        , this
                        , _1
                        , _2));
}

00633 void tdistributor::keyboard_capture(twidget* widget)
{
      if(keyboard_focus_) {
            DBG_GUI_E << LOG_HEADER << "Firing: "
                        << event::LOSE_KEYBOARD_FOCUS << ".\n";

            owner_.fire(event::LOSE_KEYBOARD_FOCUS, *keyboard_focus_, NULL);
      }

      keyboard_focus_ = widget;

      if(keyboard_focus_) {
            DBG_GUI_E << LOG_HEADER << "Firing: "
                        << event::RECEIVE_KEYBOARD_FOCUS << ".\n";

            owner_.fire(event::RECEIVE_KEYBOARD_FOCUS, *keyboard_focus_, NULL);
      }
}

00652 void tdistributor::keyboard_add_to_chain(twidget* widget)
{
      assert(widget);
      assert(std::find(keyboard_focus_chain_.begin()
                        , keyboard_focus_chain_.end()
                        , widget)
                  == keyboard_focus_chain_.end());

      keyboard_focus_chain_.push_back(widget);
}

00663 void tdistributor::keyboard_remove_from_chain(twidget* widget)
{
      assert(widget);
      std::vector<twidget*>::iterator itor = std::find(
            keyboard_focus_chain_.begin(), keyboard_focus_chain_.end(), widget);

      if(itor != keyboard_focus_chain_.end()) {
            keyboard_focus_chain_.erase(itor);
      }
}
#if 0
void tdistributor::show_tooltip(const t_string& message, const unsigned timeout)
{
      DBG_GUI_E << "Event: show tooltip.\n";

      assert(!tooltip_);

      if(help_popup_) {
            remove_help_popup();
      }

      tooltip_ = mouse_focus_;

      do_show_tooltip(tpoint(mouse_x_, mouse_y_), message);

      if(timeout) {
            SDL_AddTimer(timeout, popup_callback, 0);
      }
}

void tdistributor::remove_tooltip()
{
      if(!tooltip_) {
            return;
      }

      tooltip_ = 0;

      do_remove_tooltip();
}

void tdistributor::show_help_popup(const t_string& message, const unsigned timeout)
{
      DBG_GUI_E << "Event: show help popup.\n";

      if(help_popup_) {
            DBG_GUI_E << "Help is already there, bailing out.\n";
            return;
      }

      if(tooltip_) {
            remove_tooltip();
      }

      // Kill hover events FIXME not documented.
      had_hover_ = true;
      hover_pending_ = false;

      help_popup_ = mouse_focus_;

      do_show_help_popup(tpoint(mouse_x_, mouse_y_), message);

      if(timeout) {
            SDL_AddTimer(timeout, popup_callback, 0);
      }
}

void tdistributor::remove_help_popup()
{
      if(!help_popup_) {
            return;
      }

      help_popup_ = 0;

      do_remove_help_popup();
}

void tdistributor::set_hover(const bool test_on_widget)
{
      // Only one hover event.
      if(had_hover_) {
            return;
      }

      // Don't want a hover.
      if(!mouse_focus_ || !mouse_focus_->wants_mouse_hover()) {
            return;
      }

      // Have an hover and still in the bounding rect.
      if(hover_pending_ && point_in_rect(mouse_x_, mouse_y_, hover_box_)) {
            return;
      }

      // Mouse down, no hovering
      if(left_.is_down_ || middle_.is_down_ || right_.is_down_) {
            return;
      }

      if(test_on_widget) {
            // FIXME implement
      }

      static unsigned hover_id = 0;

      hover_pending_ = true;
      // FIXME hover dimentions should be from the settings
      // also should check the entire box is on the widget???
      hover_box_ = ::create_rect(mouse_x_ - 5, mouse_y_ - 5, 10, 10);

      unsigned *hover = new unsigned;
      *hover = hover_id;
      hover_id_ = hover_id++;

      SDL_AddTimer(settings::popup_show_delay, hover_callback, hover);
}
#endif

00782 void tdistributor::signal_handler_sdl_key_down(const SDLKey key
            , const SDLMod modifier
            , const Uint16 unicode)
{
      /** @todo Test whether recursion protection is needed. */

      DBG_GUI_E << LOG_HEADER << event::SDL_KEY_DOWN << ".\n";

      if(keyboard_focus_) {
            // Attempt to cast to control, to avoid sending events if the
            // widget is disabled. If the cast fails, we assume the widget
            // is enabled and ready to receive events.
            tcontrol* control = dynamic_cast<tcontrol*>(keyboard_focus_);
            if(!control || control->get_active()) {
                  DBG_GUI_E << LOG_HEADER << "Firing: " << event::SDL_KEY_DOWN << ".\n";
                  if(owner_.fire(event::SDL_KEY_DOWN
                              , *keyboard_focus_, key, modifier, unicode)) {
                        return;
                  }
            }
      }

      for(std::vector<twidget*>::reverse_iterator
                        ritor = keyboard_focus_chain_.rbegin()
                  ; ritor != keyboard_focus_chain_.rend()
                  ; ++ritor) {

            if(*ritor == keyboard_focus_) {
                  continue;
            }

            if(*ritor == &owner_) {
                  /**
                   * @todo Make sure we're not in the event chain.
                   *
                   * No idea why we're here, but needs to be fixed, otherwise we keep
                   * calling this function recursively upon unhandled events...
                   *
                   * Probably added to make sure the window can grab the events and
                   * handle + block them when needed, this is no longer needed with
                   * the chain.
                   */
                  continue;
            }

            // Attempt to cast to control, to avoid sending events if the
            // widget is disabled. If the cast fails, we assume the widget
            // is enabled and ready to receive events.
            tcontrol* control = dynamic_cast<tcontrol*>(keyboard_focus_);
            if(control != NULL && !control->get_active()) {
                  continue;
            }

            DBG_GUI_E << LOG_HEADER << "Firing: " << event::SDL_KEY_DOWN << ".\n";
            if(owner_.fire(event::SDL_KEY_DOWN
                        , **ritor, key, modifier, unicode)) {

                  return;
            }
      }
}

template<tevent event>
00845 void tdistributor::signal_handler_sdl_wheel()
{
      /** @todo Test whether recursion protection is needed. */

      DBG_GUI_E << LOG_HEADER << event << ".\n";

      if(keyboard_focus_) {
            DBG_GUI_E << LOG_HEADER << "Firing: " << event  << ".\n";
            owner_.fire(event, *keyboard_focus_);
      }
}

00857 void tdistributor::signal_handler_notify_removal(
                  tdispatcher& widget, const tevent event)
{
      DBG_GUI_E << LOG_HEADER << event << ".\n";

      /**
       * @todo Evaluate whether moving the cleanup parts in the subclasses.
       *
       * It might be cleaner to do it that way, but creates extra small
       * functions...
       */

      if(hover_widget_ == &widget) {
            stop_hover_timer();
      }

      if(tmouse_button_left::last_clicked_widget_ == &widget) {
            tmouse_button_left::last_clicked_widget_ = NULL;
      }
      if(tmouse_button_left::focus_ == &widget) {
            tmouse_button_left::focus_ = NULL;
      }

      if(tmouse_button_middle::last_clicked_widget_ == &widget) {
            tmouse_button_middle::last_clicked_widget_ = NULL;
      }
      if(tmouse_button_middle::focus_ == &widget) {
            tmouse_button_middle::focus_ = NULL;
      }

      if(tmouse_button_right::last_clicked_widget_ == &widget) {
            tmouse_button_right::last_clicked_widget_ = NULL;
      }
      if(tmouse_button_right::focus_ == &widget) {
            tmouse_button_right::focus_ = NULL;
      }

      if(mouse_focus_ == &widget) {
            mouse_focus_ = NULL;
      }

      if(keyboard_focus_ == &widget) {
            keyboard_focus_ = NULL;
      }
      const std::vector<twidget*>::iterator itor = std::find(
                    keyboard_focus_chain_.begin()
                  , keyboard_focus_chain_.end()
                  , &widget);
      if(itor != keyboard_focus_chain_.end()) {
            keyboard_focus_chain_.erase(itor);
      }
}

} // namespace event

} // namespace gui2


Generated by  Doxygen 1.6.0   Back to index