Rather large changeset, the primary change is allowing tooltips...
...and help messageto be shown. Secondary changes are: - moving hovering in tcontrol instead of the widgets. - make the visible flag working for drawing. - small refactoring of the window_builder class.
This commit is contained in:
parent
1348cf80d2
commit
a1cbcd5a49
22 changed files with 566 additions and 42 deletions
52
data/gui/default/widget/tooltip.cfg
Normal file
52
data/gui/default/widget/tooltip.cfg
Normal file
|
@ -0,0 +1,52 @@
|
|||
###
|
||||
### Definition of a tooltip.
|
||||
###
|
||||
|
||||
[tooltip_definition]
|
||||
id = "default"
|
||||
description = "small help tooltip"
|
||||
|
||||
[resolution]
|
||||
min_width = 0
|
||||
min_height = 0
|
||||
|
||||
default_width = 0 #fixme hack
|
||||
default_height = 0
|
||||
|
||||
max_width = 200 # fixme hack
|
||||
max_height = 0
|
||||
|
||||
text_font_size = 16
|
||||
|
||||
[state_enabled]
|
||||
|
||||
full_redraw = "true"
|
||||
|
||||
[draw]
|
||||
|
||||
[rectangle]
|
||||
x = 0
|
||||
y = 0
|
||||
w = "(width)"
|
||||
h = "(height)"
|
||||
border_thickness = 0
|
||||
fill_colour = "64, 64, 64, 128"
|
||||
[/rectangle]
|
||||
|
||||
[text]
|
||||
x = 0
|
||||
y = 0
|
||||
w = "(text_width)"
|
||||
h = "(text_height)"
|
||||
font_size = 16
|
||||
colour = "255, 255, 255, 0"
|
||||
text = "(text)"
|
||||
[/text]
|
||||
|
||||
[/draw]
|
||||
|
||||
[/state_enabled]
|
||||
|
||||
[/resolution]
|
||||
|
||||
[/tooltip_definition]
|
|
@ -142,6 +142,10 @@
|
|||
# just show how the default looks.
|
||||
definition = "default"
|
||||
|
||||
tooltip = "Manage locally installed addons."
|
||||
|
||||
help = "With this feature you can remove locally installed addons, after doing so you need to restart Wesnoth."
|
||||
|
||||
size_text = _ "manage addons"
|
||||
label = _ "manage addons"
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ wesnoth_source = \
|
|||
gui/widgets/label.cpp \
|
||||
gui/widgets/settings.cpp \
|
||||
gui/widgets/text_box.cpp \
|
||||
gui/widgets/tooltip.cpp \
|
||||
gui/widgets/helper.cpp \
|
||||
gui/widgets/widget.cpp \
|
||||
gui/widgets/window.cpp \
|
||||
|
@ -306,6 +307,7 @@ noinst_HEADERS = \
|
|||
gui/widgets/label.hpp \
|
||||
gui/widgets/settings.hpp \
|
||||
gui/widgets/text_box.hpp \
|
||||
gui/widgets/tooltip.hpp \
|
||||
gui/widgets/helper.hpp \
|
||||
gui/widgets/widget.hpp \
|
||||
gui/widgets/window.hpp \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
//our user-defined double-click event type
|
||||
#define DOUBLE_CLICK_EVENT SDL_USEREVENT
|
||||
#define HOVER_EVENT (SDL_USEREVENT + 1)
|
||||
#define HOVER_REMOVE_POPUP_EVENT (SDL_USEREVENT + 2)
|
||||
|
||||
namespace events
|
||||
{
|
||||
|
|
|
@ -47,12 +47,6 @@ void tbutton::mouse_enter(tevent_handler&)
|
|||
set_state(FOCUSSED);
|
||||
}
|
||||
|
||||
void tbutton::mouse_hover(tevent_handler&)
|
||||
{
|
||||
DBG_G_E << "Button: mouse hover.\n";
|
||||
|
||||
}
|
||||
|
||||
void tbutton::mouse_leave(tevent_handler&)
|
||||
{
|
||||
DBG_G_E << "Button: mouse leave.\n";
|
||||
|
|
|
@ -33,7 +33,6 @@ public:
|
|||
}
|
||||
|
||||
void mouse_enter(tevent_handler&);
|
||||
void mouse_hover(tevent_handler&);
|
||||
void mouse_leave(tevent_handler&);
|
||||
|
||||
void mouse_left_button_down(tevent_handler& event);
|
||||
|
|
|
@ -52,6 +52,18 @@ tcontrol::tcontrol(const unsigned canvas_count) :
|
|||
{
|
||||
}
|
||||
|
||||
void tcontrol::mouse_hover(tevent_handler& event)
|
||||
{
|
||||
DBG_G_E << "Control: mouse hover.\n";
|
||||
event.show_tooltip(tooltip_, 5000); //FIXME timout should be a parameter
|
||||
}
|
||||
|
||||
void tcontrol::help_key(tevent_handler& event)
|
||||
{
|
||||
DBG_G_E << "Control: help key.\n";
|
||||
event.show_help_popup(help_message_, 0); //FIXME timout should be a parameter
|
||||
}
|
||||
|
||||
void tcontrol::set_width(const unsigned width)
|
||||
{
|
||||
// resize canvasses
|
||||
|
@ -121,6 +133,8 @@ tpoint tcontrol::get_best_size() const
|
|||
|
||||
SDL_Rect rect = font::line_size(label_, config_->text_font_size, config_->text_font_style);
|
||||
const tpoint text_size(rect.w + config_->text_extra_width, rect.h + config_->text_extra_height);
|
||||
// FIXME test x and y separatly if Y == 0
|
||||
// FIXME also test for max
|
||||
return maximum(default_size, text_size);
|
||||
}
|
||||
|
||||
|
@ -148,8 +162,20 @@ void tcontrol::set_canvas_text()
|
|||
|
||||
void tcontrol::draw(surface& surface)
|
||||
{
|
||||
set_dirty(false);
|
||||
SDL_Rect rect = get_rect();
|
||||
|
||||
if(!visible_) {
|
||||
// When not visible we first restore our original surface.
|
||||
// Next time when visible we grab the background again.
|
||||
if(restorer_) {
|
||||
DBG_G_D << "Control: drawing setting invisible.\n";
|
||||
SDL_BlitSurface(restorer_, 0, surface, &rect);
|
||||
restorer_ = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DBG_G_D << "Control: drawing.\n";
|
||||
if(!restorer_) {
|
||||
restorer_ = get_surface_portion(surface, rect);
|
||||
|
@ -160,8 +186,6 @@ void tcontrol::draw(surface& surface)
|
|||
}
|
||||
canvas(get_state()).draw(true);
|
||||
SDL_BlitSurface(canvas(get_state()).surf(), 0, surface, &rect);
|
||||
|
||||
set_dirty(false);
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -32,6 +32,12 @@ public:
|
|||
tcontrol(const unsigned canvas_count);
|
||||
virtual ~tcontrol() {}
|
||||
|
||||
//! Inherted from twidget.
|
||||
void mouse_hover(tevent_handler& event);
|
||||
|
||||
//! Inherted from twidget.
|
||||
void help_key(tevent_handler& event);
|
||||
|
||||
//! Inherited from twidget.
|
||||
void set_width(const unsigned width);
|
||||
|
||||
|
@ -41,7 +47,7 @@ public:
|
|||
//! Inherited from twidget.
|
||||
void set_size(const SDL_Rect& rect);
|
||||
|
||||
void set_visible(const bool visible)
|
||||
void set_visible(const bool visible = true)
|
||||
{ if(visible_ != visible) { visible_ = visible; set_dirty();} }
|
||||
bool get_visible() const { return visible_; }
|
||||
|
||||
|
@ -50,7 +56,8 @@ public:
|
|||
const t_string& label() const { return label_; }
|
||||
|
||||
// Note setting the tooltip_ doesn't dirty an object.
|
||||
void set_tooltip(const t_string& tooltip) { tooltip_ = tooltip; }
|
||||
void set_tooltip(const t_string& tooltip)
|
||||
{ tooltip_ = tooltip; set_wants_mouse_hover(!tooltip_.empty()); }
|
||||
const t_string& tooltip() const { return tooltip_; }
|
||||
|
||||
// Note setting the help_message_ doesn't dirty an object.
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "gui/widgets/window.hpp"
|
||||
#include "log.hpp"
|
||||
#include "serialization/parser.hpp"
|
||||
#include "tstring.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
#define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
|
||||
|
@ -52,6 +53,25 @@ static Uint32 hover_callback(Uint32 interval, void *param)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static Uint32 popup_callback(Uint32 interval, void*)
|
||||
{
|
||||
DBG_G_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;
|
||||
}
|
||||
|
||||
//! 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.
|
||||
|
@ -71,6 +91,8 @@ tevent_handler::tevent_handler() :
|
|||
hover_id_(0),
|
||||
hover_box_(),
|
||||
had_hover_(false),
|
||||
tooltip_(0),
|
||||
help_popup_(0),
|
||||
mouse_focus_(0),
|
||||
mouse_captured_(false),
|
||||
keyboard_focus_(0)
|
||||
|
@ -144,6 +166,11 @@ void tevent_handler::handle_event(const SDL_Event& event)
|
|||
mouse_hover(event, 0);
|
||||
break;
|
||||
|
||||
case HOVER_REMOVE_POPUP_EVENT:
|
||||
remove_tooltip();
|
||||
remove_help_popup();
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
key_down(event);
|
||||
break;
|
||||
|
@ -166,8 +193,77 @@ void tevent_handler::mouse_capture(const bool capture)
|
|||
mouse_captured_ = capture;
|
||||
}
|
||||
|
||||
void tevent_handler::show_tooltip(const t_string& tooltip, const unsigned timeout)
|
||||
{
|
||||
DBG_G_E << "Event: show tooltip.\n";
|
||||
|
||||
assert(!tooltip_);
|
||||
|
||||
if(help_popup_) {
|
||||
remove_help_popup();
|
||||
}
|
||||
|
||||
tooltip_ = mouse_focus_;
|
||||
|
||||
do_show_tooltip(get_window().client_position(tpoint(mouse_x_, mouse_y_)), tooltip);
|
||||
|
||||
if(timeout) {
|
||||
SDL_AddTimer(timeout, popup_callback, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void tevent_handler::remove_tooltip()
|
||||
{
|
||||
if(!tooltip_) {
|
||||
return;
|
||||
}
|
||||
|
||||
tooltip_ = 0;
|
||||
|
||||
do_remove_tooltip();
|
||||
}
|
||||
|
||||
void tevent_handler::show_help_popup(const t_string& help_popup, const unsigned timeout)
|
||||
{
|
||||
DBG_G_E << "Event: show help popup.\n";
|
||||
|
||||
if(help_popup_) {
|
||||
DBG_G_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(get_window().client_position(tpoint(mouse_x_, mouse_y_)), help_popup);
|
||||
|
||||
if(timeout) {
|
||||
SDL_AddTimer(timeout, popup_callback, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void tevent_handler::remove_help_popup()
|
||||
{
|
||||
if(!help_popup_) {
|
||||
return;
|
||||
}
|
||||
|
||||
help_popup_ = 0;
|
||||
|
||||
do_remove_help_popup();
|
||||
}
|
||||
|
||||
void tevent_handler::mouse_enter(const SDL_Event& event, twidget* mouse_over)
|
||||
{
|
||||
DBG_G_E << "Event: remove tooltip.\n";
|
||||
|
||||
assert(mouse_over);
|
||||
|
||||
mouse_focus_ = mouse_over;
|
||||
|
@ -225,6 +321,9 @@ void tevent_handler::mouse_leave(const SDL_Event& event, twidget* mouse_over)
|
|||
had_hover_ = false;
|
||||
hover_pending_ =false;
|
||||
|
||||
remove_tooltip();
|
||||
remove_help_popup();
|
||||
|
||||
mouse_focus_->mouse_leave(*this);
|
||||
mouse_focus_ = 0;
|
||||
}
|
||||
|
@ -352,6 +451,14 @@ void tevent_handler::set_hover(const bool test_on_widget)
|
|||
|
||||
void tevent_handler::key_down(const SDL_Event& event)
|
||||
{
|
||||
// We capture the F! for the help, but only if the mouse is on an object.
|
||||
if(mouse_focus_/* && !mouse_captured_
|
||||
&& event.key.keysym.mod == 0 */ && event.key.keysym.sym == SDLK_F1) {
|
||||
|
||||
mouse_focus_->help_key(*this);
|
||||
return;
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
if(keyboard_focus_) {
|
||||
keyboard_focus_->key_press(*this, handled, event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode);
|
||||
|
|
|
@ -19,13 +19,14 @@
|
|||
#define __GUI_WIDGETS_EVENT_INFO_HPP_INCLUDED__
|
||||
|
||||
#include "events.hpp"
|
||||
#include "gui/widgets/helper.hpp"
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
class t_string;
|
||||
|
||||
namespace gui2{
|
||||
|
||||
class tpoint;
|
||||
class twidget;
|
||||
class twindow;
|
||||
|
||||
|
@ -48,6 +49,13 @@ public:
|
|||
void mouse_capture(const bool capture = true);
|
||||
void keyboard_capture(twidget* widget) { keyboard_focus_ = widget; }
|
||||
|
||||
//! We impement the handling of the tip, but call the do functions
|
||||
//! which are virtual.
|
||||
void show_tooltip(const t_string& tooltip, const unsigned timeout);
|
||||
void remove_tooltip();
|
||||
void show_help_popup(const t_string& help_popup, const unsigned timeout);
|
||||
void remove_help_popup();
|
||||
|
||||
private:
|
||||
//! we create a new event context so we're always modal.
|
||||
//! Maybe this has to change, but not sure yet.
|
||||
|
@ -70,6 +78,10 @@ private:
|
|||
//! invalidates the pending hover event.
|
||||
bool had_hover_; //! A widget only gets one hover event per enter cycle.
|
||||
|
||||
//! The widget that created the tooltip / tooltip.
|
||||
twidget* tooltip_;
|
||||
twidget* help_popup_;
|
||||
|
||||
|
||||
twidget* mouse_focus_;
|
||||
bool mouse_captured_;
|
||||
|
@ -89,6 +101,10 @@ private:
|
|||
|
||||
void key_down(const SDL_Event& event);
|
||||
|
||||
virtual void do_show_tooltip(const tpoint& location, const t_string& tooltip) = 0;
|
||||
virtual void do_remove_tooltip() = 0;
|
||||
virtual void do_show_help_popup(const tpoint& location, const t_string& help_popup) = 0;
|
||||
virtual void do_remove_help_popup() = 0;
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -39,11 +39,6 @@
|
|||
|
||||
namespace gui2 {
|
||||
|
||||
void tlabel::mouse_hover(tevent_handler&)
|
||||
{
|
||||
DBG_G_E << "Text_box: mouse hover.\n";
|
||||
}
|
||||
|
||||
void tlabel::set_state(tstate state)
|
||||
{
|
||||
if(state != state_) {
|
||||
|
|
|
@ -34,8 +34,6 @@ public:
|
|||
bool get_active() const { return state_ == ENABLED; }
|
||||
unsigned get_state() const { return state_; }
|
||||
|
||||
void mouse_hover(tevent_handler&);
|
||||
|
||||
//! Inherited from twidget.
|
||||
void load_config();
|
||||
|
||||
|
|
|
@ -193,6 +193,18 @@ const std::string& tgui_definition::read(const config& cfg)
|
|||
|
||||
VALIDATE(text_boxs.find("default") != text_boxs.end(), _ ("No default text box defined."));
|
||||
|
||||
/***** Tooltip definitions *****/
|
||||
const config::child_list& tooltip_cfg = cfg.get_children("tooltip_definition");
|
||||
for(std::vector<config*>::const_iterator itor = tooltip_cfg.begin();
|
||||
itor != tooltip_cfg.end(); ++itor) {
|
||||
|
||||
std::pair<std::string, ttooltip_definition> child;
|
||||
child.first = child.second.read(**itor);
|
||||
tooltips.insert(child);
|
||||
}
|
||||
|
||||
VALIDATE(tooltips.find("default") != tooltips.end(), _ ("No default tooltip defined."));
|
||||
|
||||
/***** Window types *****/
|
||||
const config::child_list& window_instance_cfgs = cfg.get_children("window");
|
||||
for(std::vector<config*>::const_iterator itor = window_instance_cfgs.begin();
|
||||
|
@ -449,6 +461,51 @@ void ttext_box_definition::tresolution::read_extra(const config& cfg)
|
|||
state.push_back(tstate_definition(cfg.child("state_focussed")));
|
||||
}
|
||||
|
||||
const std::string& ttooltip_definition::read(const config& cfg)
|
||||
{
|
||||
/*WIKI
|
||||
* [tooltip_definition]
|
||||
* The definition of a tooltip box.
|
||||
*
|
||||
* id = (string = "") Unique id for this gui (theme).
|
||||
* description = (t_string = "") Unique translatable name for this gui.
|
||||
*
|
||||
* [resolution] The definitions of the tooltip in various
|
||||
* resolutions.
|
||||
* [/tooltip_definition]
|
||||
*/
|
||||
id = cfg["id"];
|
||||
description = cfg["description"];
|
||||
|
||||
VALIDATE(!id.empty(), missing_mandatory_wml_key("gui", "id"));
|
||||
VALIDATE(!description.empty(), missing_mandatory_wml_key("gui", "description"));
|
||||
|
||||
DBG_G_P << "Parsing tooltip " << id << '\n';
|
||||
|
||||
const config::child_list& cfgs = cfg.get_children("resolution");
|
||||
VALIDATE(!cfgs.empty(), _("No resolution defined."));
|
||||
for(std::vector<config*>::const_iterator itor = cfgs.begin();
|
||||
itor != cfgs.end(); ++itor) {
|
||||
|
||||
resolutions.push_back(new tresolution(**itor));
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void ttooltip_definition::tresolution::read_extra(const config& cfg)
|
||||
{
|
||||
/*WIKI
|
||||
* [label_definition][resolution]
|
||||
* [state_enabled] Settings for the enabled state.
|
||||
* [/resolution][/label_definition]
|
||||
*/
|
||||
|
||||
// Note only one state for a tooltip.
|
||||
state.push_back(tstate_definition(cfg.child("state_enabled")));
|
||||
}
|
||||
|
||||
|
||||
const std::string& twindow_definition::read(const config& cfg)
|
||||
{
|
||||
/*WIKI
|
||||
|
@ -618,6 +675,36 @@ tresolution_definition_* get_text_box(const std::string& definition)
|
|||
assert(false);
|
||||
}
|
||||
|
||||
tresolution_definition_* get_tooltip(const std::string& definition)
|
||||
{
|
||||
std::map<std::string, ttooltip_definition>::const_iterator
|
||||
tooltip = current_gui->second.tooltips.find(definition);
|
||||
|
||||
if(tooltip == current_gui->second.tooltips.end()) {
|
||||
LOG_G << "Tooltip: definition '"
|
||||
<< definition << "' not found, falling back to 'default'.\n";
|
||||
tooltip = current_gui->second.tooltips.find("default");
|
||||
assert(tooltip != current_gui->second.tooltips.end());
|
||||
}
|
||||
|
||||
for(std::vector<tresolution_definition_*>::const_iterator
|
||||
itor = tooltip->second.resolutions.begin(),
|
||||
end = tooltip->second.resolutions.end();
|
||||
itor != end;
|
||||
++itor) {
|
||||
|
||||
if(screen_width <= (**itor).window_width &&
|
||||
screen_height <= (**itor).window_height) {
|
||||
|
||||
return *itor;
|
||||
} else if (itor == end - 1) {
|
||||
return *itor;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
std::vector<twindow_definition::tresolution>::const_iterator get_window(const std::string& definition)
|
||||
{
|
||||
std::map<std::string, twindow_definition>::const_iterator
|
||||
|
|
|
@ -151,6 +151,26 @@ struct ttext_box_definition
|
|||
std::vector<tresolution_definition_*> resolutions;
|
||||
};
|
||||
|
||||
struct ttooltip_definition
|
||||
{
|
||||
std::string id;
|
||||
t_string description;
|
||||
|
||||
const std::string& read(const config& cfg);
|
||||
|
||||
struct tresolution : public tresolution_definition_
|
||||
{
|
||||
tresolution(const config& cfg) :
|
||||
tresolution_definition_(cfg)
|
||||
{ read_extra(cfg); }
|
||||
|
||||
private:
|
||||
void read_extra(const config& cfg);
|
||||
};
|
||||
|
||||
std::vector<tresolution_definition_*> resolutions;
|
||||
};
|
||||
|
||||
struct twindow_definition
|
||||
{
|
||||
|
||||
|
@ -208,6 +228,7 @@ struct tgui_definition
|
|||
std::map<std::string, tbutton_definition> buttons;
|
||||
std::map<std::string, tlabel_definition> labels;
|
||||
std::map<std::string, ttext_box_definition> text_boxs;
|
||||
std::map<std::string, ttooltip_definition> tooltips;
|
||||
std::map<std::string, twindow_definition> windows;
|
||||
|
||||
std::map<std::string, twindow_builder> window_types;
|
||||
|
@ -216,6 +237,7 @@ struct tgui_definition
|
|||
tresolution_definition_* get_button(const std::string& definition);
|
||||
tresolution_definition_* get_label(const std::string& definition);
|
||||
tresolution_definition_* get_text_box(const std::string& definition);
|
||||
tresolution_definition_* get_tooltip(const std::string& definition);
|
||||
std::vector<twindow_definition::tresolution>::const_iterator get_window(const std::string& definition);
|
||||
|
||||
std::vector<twindow_builder::tresolution>::const_iterator get_window_builder(const std::string& type);
|
||||
|
|
|
@ -75,11 +75,6 @@ void ttext_::mouse_move(tevent_handler&)
|
|||
// if in select mode select text and move cursor
|
||||
}
|
||||
|
||||
void ttext_::mouse_hover(tevent_handler&)
|
||||
{
|
||||
DBG_G_E << "Text_box: mouse hover.\n";
|
||||
}
|
||||
|
||||
void ttext_::mouse_left_button_down(tevent_handler& event)
|
||||
{
|
||||
DBG_G_E << "Text_box: left mouse button down.\n";
|
||||
|
|
|
@ -46,7 +46,6 @@ public:
|
|||
unsigned get_state() const { return state_; }
|
||||
|
||||
void mouse_move(tevent_handler&);
|
||||
void mouse_hover(tevent_handler&);
|
||||
|
||||
void mouse_left_button_down(tevent_handler& event);
|
||||
void mouse_left_button_up(tevent_handler&);
|
||||
|
|
56
src/gui/widgets/tooltip.cpp
Normal file
56
src/gui/widgets/tooltip.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
copyright (c) 2008 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 version 2
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "gui/widgets/tooltip.hpp"
|
||||
|
||||
#include "log.hpp"
|
||||
|
||||
#define DBG_G LOG_STREAM_INDENT(debug, gui)
|
||||
#define LOG_G LOG_STREAM_INDENT(info, gui)
|
||||
#define WRN_G LOG_STREAM_INDENT(warn, gui)
|
||||
#define ERR_G LOG_STREAM_INDENT(err, gui)
|
||||
|
||||
#define DBG_G_D LOG_STREAM_INDENT(debug, gui_draw)
|
||||
#define LOG_G_D LOG_STREAM_INDENT(info, gui_draw)
|
||||
#define WRN_G_D LOG_STREAM_INDENT(warn, gui_draw)
|
||||
#define ERR_G_D LOG_STREAM_INDENT(err, gui_draw)
|
||||
|
||||
#define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
|
||||
#define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
|
||||
#define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
|
||||
#define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
|
||||
|
||||
#define DBG_G_P LOG_STREAM_INDENT(debug, gui_parse)
|
||||
#define LOG_G_P LOG_STREAM_INDENT(info, gui_parse)
|
||||
#define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
|
||||
#define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
void ttooltip::load_config()
|
||||
{
|
||||
if(!config()) {
|
||||
set_config(get_tooltip(definition()));
|
||||
|
||||
assert(canvas().size() == config()->state.size());
|
||||
for(size_t i = 0; i < canvas().size(); ++i) {
|
||||
canvas(i) = config()->state[i].canvas;
|
||||
}
|
||||
|
||||
set_canvas_text();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
42
src/gui/widgets/tooltip.hpp
Normal file
42
src/gui/widgets/tooltip.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
copyright (c) 2008 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 version 2
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __GUI_WIDGETS_TOOLTIP_HPP_INCLUDED__
|
||||
#define __GUI_WIDGETS_TOOLTIP_HPP_INCLUDED__
|
||||
|
||||
#include "gui/widgets/control.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
class ttooltip : public tcontrol
|
||||
{
|
||||
public:
|
||||
|
||||
ttooltip() :
|
||||
tcontrol(1)
|
||||
{}
|
||||
|
||||
//! Inherited from tcontrol.
|
||||
// We are always active, might not be visible but always active.
|
||||
void set_active(const bool) {}
|
||||
bool get_active() const { return true; }
|
||||
unsigned get_state() const { return 0; }
|
||||
|
||||
//! Inherited from twidget.
|
||||
void load_config();
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
|
@ -80,9 +80,8 @@ public:
|
|||
virtual void window_resize(tevent_handler&, const unsigned /* new_width */,
|
||||
const unsigned /* new_height */) {}
|
||||
|
||||
#if 0
|
||||
virtual void help(); // send when F1 is pressed on widget to get more help
|
||||
#endif
|
||||
//! When F1 is pressed this event is triggered.
|
||||
virtual void help_key(tevent_handler&) {}
|
||||
|
||||
bool wants_mouse_hover() const { return wants_mouse_hover_; }
|
||||
|
||||
|
@ -206,6 +205,9 @@ public:
|
|||
//! loads the configuration of the widget, mainly used for controls.
|
||||
virtual void load_config() {}
|
||||
|
||||
SDL_Rect get_rect() const
|
||||
{ return ::create_rect( x_, y_, w_, h_ ); }
|
||||
|
||||
protected:
|
||||
virtual void set_dirty(const bool dirty = true)
|
||||
{
|
||||
|
@ -213,9 +215,6 @@ protected:
|
|||
if(parent_ && dirty) parent_->set_dirty(true);
|
||||
}
|
||||
|
||||
SDL_Rect get_rect() const
|
||||
{ return ::create_rect( x_, y_, w_, h_ ); }
|
||||
|
||||
private:
|
||||
//! The id is the unique name of the widget in a certain context. This is
|
||||
//! needed for certain widgets so the engine knows which widget is which.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "gui/widgets/window.hpp"
|
||||
|
||||
#include "config.hpp"
|
||||
#include "font.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "log.hpp"
|
||||
#include "serialization/parser.hpp"
|
||||
|
@ -58,12 +59,22 @@ twindow::twindow(CVideo& video,
|
|||
need_layout_(true),
|
||||
restorer_(),
|
||||
canvas_background_(),
|
||||
canvas_foreground_()
|
||||
canvas_foreground_(),
|
||||
tooltip_(),
|
||||
help_popup_()
|
||||
{
|
||||
set_x(x);
|
||||
set_y(y);
|
||||
set_width(w);
|
||||
set_height(h);
|
||||
|
||||
tooltip_.set_definition("default");
|
||||
tooltip_.load_config();
|
||||
tooltip_.set_visible(false);
|
||||
|
||||
help_popup_.set_definition("default");
|
||||
help_popup_.load_config();
|
||||
help_popup_.set_visible(false);
|
||||
}
|
||||
|
||||
int twindow::show(const bool restore, void* /*flip_function*/)
|
||||
|
@ -127,6 +138,12 @@ int twindow::show(const bool restore, void* /*flip_function*/)
|
|||
SDL_Rect blit = {0, 0, screen->w, screen->h};
|
||||
SDL_BlitSurface(canvas_foreground_.surf(), 0, screen, &blit);
|
||||
}
|
||||
if(tooltip_.dirty()) {
|
||||
tooltip_.draw(screen);
|
||||
}
|
||||
if(help_popup_.dirty()) {
|
||||
help_popup_.draw(screen);
|
||||
}
|
||||
|
||||
rect = get_rect();
|
||||
SDL_BlitSurface(screen, 0, video_.getSurface(), &rect);
|
||||
|
@ -228,5 +245,83 @@ SDL_Rect twindow::get_client_rect() const
|
|||
|
||||
}
|
||||
|
||||
void twindow::do_show_tooltip(const tpoint& location, const t_string& tooltip)
|
||||
{
|
||||
DBG_G << "Showing tooltip message: '" << tooltip << "'.\n";
|
||||
|
||||
assert(!tooltip.empty());
|
||||
|
||||
twidget* widget = get_widget(location);
|
||||
assert(widget);
|
||||
|
||||
const SDL_Rect widget_rect = widget->get_rect();
|
||||
const SDL_Rect client_rect = get_client_rect();
|
||||
|
||||
tooltip_.set_label(tooltip);
|
||||
const tpoint size = tooltip_.get_best_size();
|
||||
|
||||
SDL_Rect tooltip_rect = {0, 0, size.x, size.y};
|
||||
|
||||
// Find the best position to place the widget
|
||||
if(widget_rect.y - size.y > 0) {
|
||||
// put above
|
||||
tooltip_rect.y = widget_rect.y - size.y;
|
||||
} else {
|
||||
//put below no test
|
||||
tooltip_rect.y = widget_rect.y + widget_rect.h;
|
||||
}
|
||||
|
||||
if(widget_rect.x + size.x < client_rect.w) {
|
||||
// Directly above the mouse
|
||||
tooltip_rect.x = widget_rect.x;
|
||||
} else {
|
||||
// shift left, no test
|
||||
tooltip_rect.x = client_rect.w - size.x;
|
||||
}
|
||||
|
||||
tooltip_.set_size(tooltip_rect);
|
||||
tooltip_.set_visible();
|
||||
}
|
||||
|
||||
void twindow::do_show_help_popup(const tpoint& location, const t_string& help_popup)
|
||||
{
|
||||
// Note copy past of twindow::do_show_tooltip except that the help may be empty.
|
||||
DBG_G << "Showing help message: '" << help_popup << "'.\n";
|
||||
|
||||
if(help_popup.empty()) {
|
||||
return;
|
||||
}
|
||||
twidget* widget = get_widget(location);
|
||||
assert(widget);
|
||||
|
||||
const SDL_Rect widget_rect = widget->get_rect();
|
||||
const SDL_Rect client_rect = get_client_rect();
|
||||
|
||||
help_popup_.set_label(help_popup);
|
||||
const tpoint size = help_popup_.get_best_size();
|
||||
|
||||
SDL_Rect help_popup_rect = {0, 0, size.x, size.y};
|
||||
|
||||
// Find the best position to place the widget
|
||||
if(widget_rect.y - size.y > 0) {
|
||||
// put above
|
||||
help_popup_rect.y = widget_rect.y - size.y;
|
||||
} else {
|
||||
//put below no test
|
||||
help_popup_rect.y = widget_rect.y + widget_rect.h;
|
||||
}
|
||||
|
||||
if(widget_rect.x + size.x < client_rect.w) {
|
||||
// Directly above the mouse
|
||||
help_popup_rect.x = widget_rect.x;
|
||||
} else {
|
||||
// shift left, no test
|
||||
help_popup_rect.x = client_rect.w - size.x;
|
||||
}
|
||||
|
||||
help_popup_.set_size(help_popup_rect);
|
||||
help_popup_.set_visible();
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "gui/widgets/grid.hpp"
|
||||
#include "gui/widgets/helper.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/tooltip.hpp"
|
||||
|
||||
#include "sdl_utils.hpp"
|
||||
#include "video.hpp"
|
||||
|
@ -79,6 +80,10 @@ public:
|
|||
tpoint client_position(const tpoint& screen_position) const
|
||||
{ return tpoint(screen_position.x - get_x(), screen_position.y - get_y()); }
|
||||
|
||||
tpoint screen_position(const tpoint& client_position) const
|
||||
{ return tpoint(client_position.x + get_x(), client_position.y + get_y()); }
|
||||
|
||||
|
||||
void window_resize(tevent_handler&,
|
||||
const unsigned new_width, const unsigned new_height);
|
||||
|
||||
|
@ -88,7 +93,7 @@ public:
|
|||
unsigned get_state() const { return 0; }
|
||||
bool full_redraw() const { return false; /* FIXME IMPLEMENT */ }
|
||||
|
||||
// Inherited from twidget.
|
||||
//! Inherited from twidget.
|
||||
tpoint get_minimum_size() const { /*FIXME IMPLEMENT*/ return tpoint(0,0); }
|
||||
tpoint get_best_size() const { /*FIXME IMPLEMENT*/ return tpoint(0,0); }
|
||||
tpoint get_maximum_size() const { /*FIXME IMPLEMENT*/ return tpoint(0,0); }
|
||||
|
@ -120,6 +125,18 @@ private:
|
|||
void resolve_definition();
|
||||
|
||||
SDL_Rect get_client_rect() const;
|
||||
|
||||
//! Inherited from tevent_handler.
|
||||
void do_show_tooltip(const tpoint& location, const t_string& tooltip);
|
||||
void do_remove_tooltip() { tooltip_.set_visible(false); }
|
||||
void do_show_help_popup(const tpoint& location, const t_string& help_popup);
|
||||
void do_remove_help_popup() { help_popup_.set_visible(false); }
|
||||
|
||||
//! Widget for the tooltip.
|
||||
ttooltip tooltip_;
|
||||
|
||||
//! Widget for the help popup FIXME should be thelp_popup.
|
||||
ttooltip help_popup_;
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -57,10 +57,14 @@ public:
|
|||
|
||||
tbuilder_control(const config& cfg);
|
||||
|
||||
void init_control(tcontrol* control) const;
|
||||
|
||||
//! Parameters for the control.
|
||||
std::string id;
|
||||
std::string definition;
|
||||
t_string label;
|
||||
t_string tooltip;
|
||||
t_string help;
|
||||
};
|
||||
|
||||
struct tbuilder_button : public tbuilder_control
|
||||
|
@ -360,7 +364,9 @@ tbuilder_control::tbuilder_control(const config& cfg) :
|
|||
tbuilder_widget(cfg),
|
||||
id(cfg["id"]),
|
||||
definition(cfg["definition"]),
|
||||
label(cfg["label"])
|
||||
label(cfg["label"]),
|
||||
tooltip(cfg["tooltip"]),
|
||||
help(cfg["help"])
|
||||
{
|
||||
|
||||
if(definition.empty()) {
|
||||
|
@ -372,13 +378,22 @@ tbuilder_control::tbuilder_control(const config& cfg) :
|
|||
<< id << "' and definition '" << definition << "'.\n";
|
||||
}
|
||||
|
||||
void tbuilder_control::init_control(tcontrol* control) const
|
||||
{
|
||||
assert(control);
|
||||
|
||||
control->set_id(id);
|
||||
control->set_definition(definition);
|
||||
control->set_label(label);
|
||||
control->set_tooltip(tooltip);
|
||||
control->set_help_message(help);
|
||||
}
|
||||
|
||||
twidget* tbuilder_button::build() const
|
||||
{
|
||||
tbutton *button = new tbutton();
|
||||
|
||||
button->set_id(id);
|
||||
button->set_definition(definition);
|
||||
button->set_label(label);
|
||||
init_control(button);
|
||||
|
||||
if(retval_) {
|
||||
button->set_retval(retval_);
|
||||
|
@ -402,9 +417,7 @@ twidget* tbuilder_label::build() const
|
|||
{
|
||||
tlabel *tmp_label = new tlabel();
|
||||
|
||||
tmp_label->set_id(id);
|
||||
tmp_label->set_definition(definition);
|
||||
tmp_label->set_label(label);
|
||||
init_control(tmp_label);
|
||||
|
||||
DBG_G << "Window builder: placed label '" << id << "' with defintion '"
|
||||
<< definition << "'.\n";
|
||||
|
@ -416,8 +429,8 @@ twidget* tbuilder_text_box::build() const
|
|||
{
|
||||
ttext_box *text_box = new ttext_box();
|
||||
|
||||
text_box->set_id(id);
|
||||
text_box->set_definition(definition);
|
||||
init_control(text_box);
|
||||
|
||||
// A textbox doesn't have a label but a text
|
||||
text_box->set_text(label);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue