Reimplemented the tooltip event code.
The code now lets the widget show its own tooltip instead of letting the distributor figure it all out. The commit also adds a new event type class; the message. A message goes from a widget to the window (instead of the other way around). The message class is used to let the widget ask the window to really show the tooltip. The reason for doing so is to both decouple who needs to show the tooltip (no reason why the window is responsible) and to add the new message class. (I've some usage ideas for the class, but nothing to commit yet.)
This commit is contained in:
parent
45dd183c36
commit
c754f1642d
12 changed files with 437 additions and 65 deletions
|
@ -32,6 +32,7 @@ tdispatcher::tdispatcher()
|
|||
, signal_mouse_queue_()
|
||||
, signal_keyboard_queue_()
|
||||
, signal_notification_queue_()
|
||||
, signal_message_queue_()
|
||||
, connected_(false)
|
||||
, hotkeys_()
|
||||
{
|
||||
|
@ -70,6 +71,9 @@ bool tdispatcher::has_event(const tevent event
|
|||
<< " notification "
|
||||
<< find<tset_event_notification>(event, tdispatcher_implementation
|
||||
::thas_handler(event_type, *this))
|
||||
<< " message "
|
||||
<< find<tset_event_message>(event, tdispatcher_implementation
|
||||
::thas_handler(event_type, *this))
|
||||
<< ".\n";
|
||||
#endif
|
||||
|
||||
|
@ -80,7 +84,10 @@ bool tdispatcher::has_event(const tevent event
|
|||
|| find<tset_event_keyboard>(event, tdispatcher_implementation
|
||||
::thas_handler(event_type, *this))
|
||||
|| find<tset_event_notification>(event, tdispatcher_implementation
|
||||
::thas_handler(event_type, *this));
|
||||
::thas_handler(event_type, *this))
|
||||
|| find<tset_event_message>(event, tdispatcher_implementation
|
||||
::thas_handler(event_type, *this))
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,6 +283,37 @@ bool tdispatcher::fire(const tevent event
|
|||
, ttrigger_notification());
|
||||
}
|
||||
|
||||
/** Helper struct to wrap the functor call. */
|
||||
class ttrigger_message
|
||||
{
|
||||
public:
|
||||
ttrigger_message(tmessage& message)
|
||||
: message_(message)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(tsignal_message_function functor
|
||||
, tdispatcher& dispatcher
|
||||
, const tevent event
|
||||
, bool& handled
|
||||
, bool& halt)
|
||||
{
|
||||
functor(dispatcher, event, handled, halt, message_);
|
||||
}
|
||||
|
||||
private:
|
||||
tmessage& message_;
|
||||
};
|
||||
|
||||
bool tdispatcher::fire(const tevent event, twidget& target, tmessage& message)
|
||||
{
|
||||
assert(find<tset_event_message>(event, tevent_in_set()));
|
||||
return fire_event<tsignal_message_function>(event
|
||||
, dynamic_cast<twidget*>(this)
|
||||
, &target
|
||||
, ttrigger_message(message));
|
||||
}
|
||||
|
||||
void tdispatcher::register_hotkey(const hotkey::HOTKEY_COMMAND id
|
||||
, const thotkey_function& function)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,8 @@ class twidget;
|
|||
|
||||
namespace event {
|
||||
|
||||
struct tmessage;
|
||||
|
||||
/**
|
||||
* Callback function signature.
|
||||
*
|
||||
|
@ -97,6 +99,19 @@ typedef
|
|||
, void*)>
|
||||
tsignal_notification_function;
|
||||
|
||||
/**
|
||||
* Callback function signature.
|
||||
*
|
||||
* This function is used for the callbacks in tset_message_notification.
|
||||
*/
|
||||
typedef
|
||||
boost::function<void(
|
||||
tdispatcher& dispatcher
|
||||
, const tevent event
|
||||
, bool& handled
|
||||
, bool& halt
|
||||
, tmessage& message)>
|
||||
tsignal_message_function;
|
||||
|
||||
/** Hotkey function handler signature. */
|
||||
typedef
|
||||
|
@ -198,6 +213,19 @@ public:
|
|||
*/
|
||||
bool fire(const tevent event, twidget& target, void*);
|
||||
|
||||
/**
|
||||
* Fires an event which takes message parameters.
|
||||
*
|
||||
* @param event The event to fire.
|
||||
* @param target The widget that should receive the event.
|
||||
* Normally this is the window holding the
|
||||
* widget.
|
||||
* @param message The extra information needed for a window
|
||||
* (or another widget in the chain) to handle
|
||||
* the message.
|
||||
*/
|
||||
bool fire(const tevent event, twidget& target, tmessage& message);
|
||||
|
||||
/**
|
||||
* The position where to add a new callback in the signal handler.
|
||||
*
|
||||
|
@ -402,6 +430,49 @@ public:
|
|||
signal_notification_queue_.disconnect_signal(E, position, signal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect a signal for callback in tset_event_message.
|
||||
*
|
||||
* @tparam E The event the callback needs to react to.
|
||||
* @param signal The callback function.
|
||||
* @param position The position to place the callback. Since
|
||||
* the message is send to a widget directly
|
||||
* the pre and post positions make no sense
|
||||
* and shouldn't be used.
|
||||
*/
|
||||
template<tevent E>
|
||||
typename boost::enable_if<boost::mpl::has_key<
|
||||
tset_event_message, boost::mpl::int_<E> > >::type
|
||||
connect_signal(const tsignal_message_function& signal
|
||||
, const tposition position = back_child)
|
||||
{
|
||||
signal_message_queue_.connect_signal(E, position, signal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect a signal for callback in tset_event_message.
|
||||
*
|
||||
* @tparam E The event the callback was used for.
|
||||
* @param signal The callback function.
|
||||
* @param position The place where the function was added.
|
||||
* Needed remove the event from the right
|
||||
* place. (The function doesn't care whether
|
||||
* was added in front or back, but it needs
|
||||
* to know the proper queue so it's save to
|
||||
* add with front_child and remove with
|
||||
* back_child. But it's not save to add with
|
||||
* front_child and remove with
|
||||
* front_pre_child)
|
||||
*/
|
||||
template<tevent E>
|
||||
typename boost::enable_if<boost::mpl::has_key<
|
||||
tset_event_message, boost::mpl::int_<E> > >::type
|
||||
disconnect_signal(const tsignal_message_function& signal
|
||||
, const tposition position = back_child)
|
||||
{
|
||||
signal_message_queue_.disconnect_signal(E, position, signal);
|
||||
}
|
||||
|
||||
/**
|
||||
* The behaviour of the mouse events.
|
||||
*
|
||||
|
@ -602,6 +673,9 @@ private:
|
|||
/** Signal queue for callbacks in tset_event_notification. */
|
||||
tsignal_queue<tsignal_notification_function> signal_notification_queue_;
|
||||
|
||||
/** Signal queue for callbacks in tset_event_message. */
|
||||
tsignal_queue<tsignal_message_function> signal_message_queue_;
|
||||
|
||||
/** Are we connected to the event handler. */
|
||||
bool connected_;
|
||||
|
||||
|
|
|
@ -213,6 +213,52 @@ struct tdispatcher_implementation
|
|||
return dispatcher.signal_notification_queue_.queue[event];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signal structure for a tsignal_message_function.
|
||||
*
|
||||
* There are several functions that only overload the return value, in
|
||||
* order to do so they use SFINAE.
|
||||
*
|
||||
* @tparam F tsignal_message_function.
|
||||
* @param dispatcher The dispatcher whose signal queue is used.
|
||||
* @param event The event to get the signal for.
|
||||
*
|
||||
* @returns The signal of the type tdispatcher
|
||||
* ::tsignal<tsignal_message_function>
|
||||
*/
|
||||
template<class F>
|
||||
static typename boost::enable_if<
|
||||
boost::is_same<F, tsignal_message_function>
|
||||
, tdispatcher::tsignal<tsignal_message_function>
|
||||
>::type&
|
||||
event_signal(tdispatcher& dispatcher, const tevent event)
|
||||
{
|
||||
return dispatcher.signal_message_queue_.queue[event];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signal structure for a key in tset_event_message.
|
||||
*
|
||||
* There are several functions that only overload the return value, in
|
||||
* order to do so they use SFINAE.
|
||||
*
|
||||
* @tparam K A key in tset_event_message.
|
||||
* @param dispatcher The dispatcher whose signal queue is used.
|
||||
* @param event The event to get the signal for.
|
||||
*
|
||||
* @returns The signal of the type tdispatcher
|
||||
* ::tsignal<tsignal_message_function>
|
||||
*/
|
||||
template<class K>
|
||||
static typename boost::enable_if<
|
||||
boost::mpl::has_key<tset_event_message, K>
|
||||
, tdispatcher::tsignal<tsignal_message_function>
|
||||
>::type&
|
||||
event_signal(tdispatcher& dispatcher, const tevent event)
|
||||
{
|
||||
return dispatcher.signal_message_queue_.queue[event];
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper class to find out whether dispatcher has an handler for a
|
||||
* certain event.
|
||||
|
@ -365,6 +411,29 @@ inline bool find(E event, F functor)
|
|||
|
||||
namespace implementation {
|
||||
|
||||
/*
|
||||
* Small sample to illustrate the effects of the various build_event_chain
|
||||
* functions. Assume the widgets are in an window with the following widgets:
|
||||
*
|
||||
* -----------------------
|
||||
* | dispatcher |
|
||||
* | ------------------- |
|
||||
* | | container 1 | |
|
||||
* | | --------------- | |
|
||||
* | | | container 2 | | |
|
||||
* | | | ----------- | | |
|
||||
* | | | | widget | | | |
|
||||
* | | | ----------- | | |
|
||||
* | | --------------- | |
|
||||
* | ------------------- |
|
||||
* -----------------------
|
||||
*
|
||||
* Note that the firing routine fires the events from:
|
||||
* - pre child for chain.end() - > chain.begin()
|
||||
* - child for widget
|
||||
* - post child for chain.begin() -> chain.end()
|
||||
*/
|
||||
|
||||
/**
|
||||
* Build the event chain.
|
||||
*
|
||||
|
@ -384,6 +453,11 @@ namespace implementation {
|
|||
* @param widget The widget should parent(s) to check.
|
||||
*
|
||||
* @returns The list of widgets with a handler.
|
||||
* The order will be (assuming all have a
|
||||
* handler):
|
||||
* * container 2
|
||||
* * container 1
|
||||
* * dispatcher
|
||||
*/
|
||||
template<class T>
|
||||
inline std::vector<std::pair<twidget*, tevent> > build_event_chain(
|
||||
|
@ -416,6 +490,8 @@ inline std::vector<std::pair<twidget*, tevent> > build_event_chain(
|
|||
* The notification is only send to the receiver it returns an empty chain.
|
||||
* Since the pre and post queues are unused, it validates whether they are
|
||||
* empty (using asserts).
|
||||
*
|
||||
* @returns An empty vector.
|
||||
*/
|
||||
template<>
|
||||
inline std::vector<std::pair<twidget*, tevent> >
|
||||
|
@ -436,6 +512,50 @@ build_event_chain<tsignal_notification_function>(
|
|||
return std::vector<std::pair<twidget*, tevent> >();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the event chain for tsignal_message_function.
|
||||
*
|
||||
* This function expects that the widget sending it is also the receiver. This
|
||||
* assumption might change, but is valid for now. The function doesn't build an
|
||||
* event chain from @p dispatcher to @p widget but from @p widget to its
|
||||
* toplevel item (the first one without a parent) which we call @p window.
|
||||
*
|
||||
* @pre dispatcher == widget
|
||||
*
|
||||
* @returns The list of widgets with a handler.
|
||||
* The order will be (assuming all have a
|
||||
* handler):
|
||||
* * window
|
||||
* * container 1
|
||||
* * container 2
|
||||
*/
|
||||
template<>
|
||||
inline std::vector<std::pair<twidget*, tevent> >
|
||||
build_event_chain<tsignal_message_function>(
|
||||
const tevent event
|
||||
, twidget* dispatcher
|
||||
, twidget* widget)
|
||||
{
|
||||
assert(dispatcher);
|
||||
assert(widget);
|
||||
assert(widget == dispatcher);
|
||||
|
||||
std::vector<std::pair<twidget*, tevent> > result;
|
||||
|
||||
/* We only should add the parents of the widget to the chain. */
|
||||
while((widget = widget->parent())) {
|
||||
assert(widget);
|
||||
|
||||
if(widget->has_event(event, tdispatcher::tevent_type(
|
||||
tdispatcher::pre | tdispatcher::post))) {
|
||||
|
||||
result.insert(result.begin(), std::make_pair(widget, event));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for fire_event.
|
||||
*
|
||||
|
|
|
@ -123,11 +123,6 @@ tmouse_motion::tmouse_motion(twidget& owner
|
|||
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()
|
||||
|
@ -216,6 +211,31 @@ void tmouse_motion::mouse_motion(twidget* mouse_over, const tpoint& coordinate)
|
|||
}
|
||||
}
|
||||
|
||||
void tmouse_motion::show_tooltip()
|
||||
{
|
||||
DBG_GUI_E << LOG_HEADER << "Firing: " << event::SHOW_TOOLTIP << ".\n";
|
||||
|
||||
if(!hover_widget_) {
|
||||
// See tmouse_motion::stop_hover_timer.
|
||||
ERR_GUI_E << LOG_HEADER
|
||||
<< event::SHOW_TOOLTIP << " bailing out, no hover widget.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore the result of the event, always mark the tooltip as shown. If
|
||||
* there was no handler, there is no reason to assume there will be one
|
||||
* next time.
|
||||
*/
|
||||
owner_.fire(SHOW_TOOLTIP, *hover_widget_, hover_position_);
|
||||
|
||||
hover_shown_ = true;
|
||||
|
||||
hover_timer_ = 0;
|
||||
hover_widget_ = NULL;
|
||||
hover_position_ = tpoint(0, 0);
|
||||
}
|
||||
|
||||
void tmouse_motion::mouse_leave()
|
||||
{
|
||||
DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_LEAVE << ".\n";
|
||||
|
@ -244,15 +264,10 @@ void tmouse_motion::start_hover_timer(twidget* widget, const tpoint& coordinate)
|
|||
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)));
|
||||
hover_timer_ = add_timer(
|
||||
50
|
||||
, boost::bind(&tmouse_motion::show_tooltip, this));
|
||||
|
||||
if(hover_timer_) {
|
||||
hover_widget_ = widget;
|
||||
hover_position_ = coordinate;
|
||||
|
@ -279,31 +294,6 @@ void tmouse_motion::stop_hover_timer()
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -135,14 +135,14 @@ private:
|
|||
*/
|
||||
void mouse_motion(twidget* mouse_over, const tpoint& coordinate);
|
||||
|
||||
/** Called when the mouse wants the widget to show its tooltip. */
|
||||
void show_tooltip();
|
||||
|
||||
bool signal_handler_sdl_mouse_motion_entered_;
|
||||
void signal_handler_sdl_mouse_motion(
|
||||
const event::tevent event
|
||||
, bool& handled
|
||||
, const tpoint& coordinate);
|
||||
|
||||
void signal_handler_show_hover_tooltip(const event::tevent event);
|
||||
|
||||
};
|
||||
|
||||
/***** ***** ***** ***** tmouse_button ***** ***** ***** ***** *****/
|
||||
|
|
|
@ -737,9 +737,10 @@ std::ostream& operator<<(std::ostream& stream, const tevent event)
|
|||
case NOTIFY_MODIFIED : stream << "notify modified"; break;
|
||||
case RECEIVE_KEYBOARD_FOCUS : stream << "receive keyboard focus"; break;
|
||||
case LOSE_KEYBOARD_FOCUS : stream << "lose keyboard focus"; break;
|
||||
case SHOW_HOVER_TOOLTIP : stream << "show hover tooltip"; break;
|
||||
case REMOVE_TOOLTIP : stream << "remove tooltip"; break;
|
||||
case SHOW_TOOLTIP : stream << "show tooltip"; break;
|
||||
case NOTIFY_REMOVE_TOOLTIP : stream << "notify remove tooltip"; break;
|
||||
case SDL_ACTIVATE : stream << "SDL activate"; break;
|
||||
case MESSAGE_SHOW_TOOLTIP : stream << "message show tooltip"; break;
|
||||
}
|
||||
|
||||
return stream;
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
#ifndef GUI_WIDGETS_AUXILIARY_EVENT_HANDLER_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_EVENT_HANDLER_HPP_INCLUDED
|
||||
|
||||
#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
|
||||
#define BOOST_MPL_LIMIT_SET_SIZE 30
|
||||
|
||||
#include <boost/mpl/set.hpp>
|
||||
|
||||
#include <iosfwd>
|
||||
|
@ -106,13 +109,25 @@ enum tevent {
|
|||
* widget. If not documented the modified
|
||||
* means nothing.
|
||||
*/
|
||||
, RECEIVE_KEYBOARD_FOCUS /**< Widget gets keyboard focus. */
|
||||
, LOSE_KEYBOARD_FOCUS /**< Widget loses keyboard focus. */
|
||||
, SHOW_HOVER_TOOLTIP /**< Request to show the hover tooltip. */
|
||||
, REMOVE_TOOLTIP /**< Request to remove a tooltip. */
|
||||
, SDL_ACTIVATE /**<
|
||||
* The main application window is activated.
|
||||
*/
|
||||
|
||||
, RECEIVE_KEYBOARD_FOCUS /**< Widget gets keyboard focus. */
|
||||
, LOSE_KEYBOARD_FOCUS /**< Widget loses keyboard focus. */
|
||||
, SHOW_TOOLTIP /**<
|
||||
* Request the widget to show its hover
|
||||
* tooltip.
|
||||
*/
|
||||
, NOTIFY_REMOVE_TOOLTIP /**<
|
||||
* Request the widget to show its hover
|
||||
* tooltip.
|
||||
*/
|
||||
, SDL_ACTIVATE /**<
|
||||
* The main application window is activated.
|
||||
*/
|
||||
|
||||
, MESSAGE_SHOW_TOOLTIP /**<
|
||||
* Request for somebody to show the tooltip
|
||||
* based on the data send.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -167,6 +182,7 @@ typedef
|
|||
, boost::mpl::int_<SDL_MIDDLE_BUTTON_UP>
|
||||
, boost::mpl::int_<SDL_RIGHT_BUTTON_DOWN>
|
||||
, boost::mpl::int_<SDL_RIGHT_BUTTON_UP>
|
||||
, boost::mpl::int_<SHOW_TOOLTIP>
|
||||
>
|
||||
tset_event_mouse;
|
||||
|
||||
|
@ -195,12 +211,25 @@ typedef
|
|||
, boost::mpl::int_<NOTIFY_MODIFIED>
|
||||
, boost::mpl::int_<RECEIVE_KEYBOARD_FOCUS>
|
||||
, boost::mpl::int_<LOSE_KEYBOARD_FOCUS>
|
||||
, boost::mpl::int_<SHOW_HOVER_TOOLTIP>
|
||||
, boost::mpl::int_<REMOVE_TOOLTIP>
|
||||
, boost::mpl::int_<NOTIFY_REMOVE_TOOLTIP>
|
||||
, boost::mpl::int_<SDL_ACTIVATE>
|
||||
>
|
||||
tset_event_notification;
|
||||
|
||||
/**
|
||||
* Helper for catching use error of tdispatcher::connect_signal.
|
||||
*
|
||||
* This version is for callbacks with a sender aka notification messages.
|
||||
* Unlike the notifications this message is send through the chain. The event
|
||||
* is send from a widget all the way up to the window, who always is the
|
||||
* receiver of the message (unless somebody grabbed it before).
|
||||
*/
|
||||
typedef
|
||||
boost::mpl::set<
|
||||
boost::mpl::int_<MESSAGE_SHOW_TOOLTIP>
|
||||
>
|
||||
tset_event_message;
|
||||
|
||||
/**
|
||||
* Connects a dispatcher to the event handler.
|
||||
*
|
||||
|
|
71
src/gui/auxiliary/event/message.hpp
Normal file
71
src/gui/auxiliary/event/message.hpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains the defintions for the @ref tmessage class.
|
||||
*
|
||||
* The class is used in the @ref tsignal_message_function
|
||||
*/
|
||||
|
||||
#ifndef GUI_WIDGETS_AUXILIARY_EVENT_MESSAGE_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_EVENT_MESSAGE_HPP_INCLUDED
|
||||
|
||||
#include "gui/widgets/helper.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace event {
|
||||
|
||||
/**
|
||||
* The message callbacks hold a reference to a message.
|
||||
*
|
||||
* The contents of the message differ per type. This class is a base with a
|
||||
* virtual destructor, which makes it possible to use a dynamic_cast on the
|
||||
* class received to make sure the proper message type is send.
|
||||
*
|
||||
* This means all messages used in the events need to be derived from this
|
||||
* class.
|
||||
*/
|
||||
struct tmessage
|
||||
{
|
||||
virtual ~tmessage() {}
|
||||
};
|
||||
|
||||
/** The message for MESSAGE_SHOW_TOOLTIP. */
|
||||
struct tmessage_show_tooltip
|
||||
: public tmessage
|
||||
{
|
||||
tmessage_show_tooltip(
|
||||
const std::string& message_
|
||||
, const tpoint& location_)
|
||||
: message(message_)
|
||||
, location(location_)
|
||||
{
|
||||
}
|
||||
|
||||
/** The message to show on the tooltip. */
|
||||
const std::string message;
|
||||
|
||||
/** The location where to show the tooltip. */
|
||||
const tpoint location;
|
||||
};
|
||||
|
||||
} // namespace event
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
|
@ -20,10 +20,13 @@
|
|||
#include "font.hpp"
|
||||
#include "foreach.hpp"
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
#include "gui/auxiliary/event/message.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
#include "marked-up_text.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#define LOG_SCOPE_HEADER "tcontrol(" + get_control_type() + ") [" \
|
||||
|
@ -45,6 +48,12 @@ tcontrol::tcontrol(const unsigned canvas_count)
|
|||
, text_alignment_(PANGO_ALIGN_LEFT)
|
||||
, shrunken_(false)
|
||||
{
|
||||
connect_signal<event::SHOW_TOOLTIP>(boost::bind(
|
||||
&tcontrol::signal_handler_show_tooltip
|
||||
, this
|
||||
, _2
|
||||
, _3
|
||||
, _5));
|
||||
}
|
||||
|
||||
void tcontrol::set_members(const string_map& data)
|
||||
|
@ -371,5 +380,18 @@ tpoint tcontrol::get_best_text_size(
|
|||
return size;
|
||||
}
|
||||
|
||||
void tcontrol::signal_handler_show_tooltip(
|
||||
const event::tevent event
|
||||
, bool& handled
|
||||
, const tpoint& location)
|
||||
{
|
||||
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
|
||||
|
||||
if(!tooltip_.empty()) {
|
||||
event::tmessage_show_tooltip message(tooltip_, location);
|
||||
handled = fire(event::MESSAGE_SHOW_TOOLTIP, *this, message);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
|
|
|
@ -363,6 +363,13 @@ private:
|
|||
|
||||
/** Is the widget smaller as it's best size? */
|
||||
bool shrunken_;
|
||||
|
||||
/***** ***** ***** signal handlers ***** ****** *****/
|
||||
|
||||
void signal_handler_show_tooltip(
|
||||
const event::tevent event
|
||||
, bool& handled
|
||||
, const tpoint& location);
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "gettext.hpp"
|
||||
#include "log.hpp"
|
||||
#include "gui/auxiliary/event/distributor.hpp"
|
||||
#include "gui/auxiliary/event/message.hpp"
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
#include "gui/auxiliary/layout_exception.hpp"
|
||||
#include "gui/auxiliary/window_builder/control.hpp"
|
||||
|
@ -326,6 +327,15 @@ twindow::twindow(CVideo& video,
|
|||
connect_signal<event::SDL_KEY_DOWN>(
|
||||
boost::bind(&twindow::signal_handler_sdl_key_down
|
||||
, this, _2, _3, _5));
|
||||
|
||||
connect_signal<event::MESSAGE_SHOW_TOOLTIP>(
|
||||
boost::bind(
|
||||
&twindow::signal_handler_message_show_tooltip
|
||||
, this
|
||||
, _2
|
||||
, _3
|
||||
, _5)
|
||||
, event::tdispatcher::back_pre_child);
|
||||
}
|
||||
|
||||
twindow::~twindow()
|
||||
|
@ -1026,14 +1036,6 @@ void twindow::layout_linked_widgets()
|
|||
}
|
||||
}
|
||||
|
||||
void twindow::do_show_tooltip(const tpoint& location, const t_string& tooltip)
|
||||
{
|
||||
DBG_GUI_G << LOG_HEADER << " message: '" << tooltip << "'.\n";
|
||||
|
||||
/** @todo Make not hard coded. */
|
||||
tip::show(video_, "tooltip_large", tooltip, location);
|
||||
}
|
||||
|
||||
void twindow::do_remove_tooltip()
|
||||
{
|
||||
tip::remove();
|
||||
|
@ -1321,6 +1323,22 @@ void twindow::signal_handler_sdl_key_down(
|
|||
#endif
|
||||
}
|
||||
|
||||
void twindow::signal_handler_message_show_tooltip(
|
||||
const event::tevent event
|
||||
, bool& handled
|
||||
, event::tmessage& message)
|
||||
{
|
||||
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
|
||||
|
||||
event::tmessage_show_tooltip& tooltip =
|
||||
dynamic_cast<event::tmessage_show_tooltip&>(message);
|
||||
|
||||
/** @todo Make not hard coded. */
|
||||
tip::show(video_, "tooltip_large", tooltip.message, tooltip.location);
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
|
||||
|
|
|
@ -568,9 +568,6 @@ private:
|
|||
void layout_linked_widgets();
|
||||
|
||||
public:
|
||||
/** Inherited from tevent_handler. */
|
||||
void do_show_tooltip(const tpoint& location, const t_string& tooltip);
|
||||
|
||||
/** Inherited from tevent_handler. */
|
||||
void do_remove_tooltip();
|
||||
private:
|
||||
|
@ -665,6 +662,11 @@ private:
|
|||
|
||||
void signal_handler_sdl_key_down(
|
||||
const event::tevent event, bool& handled, const SDLKey key);
|
||||
|
||||
void signal_handler_message_show_tooltip(
|
||||
const event::tevent event
|
||||
, bool& handled
|
||||
, event::tmessage& message);
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
|
Loading…
Add table
Reference in a new issue