added 'help strings' feature

This commit is contained in:
Dave White 2004-06-08 22:36:39 +00:00
parent 991d42b30f
commit bb90f34fdd
16 changed files with 214 additions and 55 deletions

View file

@ -330,6 +330,40 @@ quit_button="Quit"
quit="Quit Game"
language_button="Language"
help_string_tutorial_button="Start a tutorial to familiarize yourself with the game"
help_string_campaign_button="Start a new single player campaign"
help_string_load_button="Load a single player saved game"
help_string_multiplayer_button="Play multiplayer (hotseat, LAN, or Internet), or a single scenario against the AI"
help_string_quit_button="Quit the game"
help_string_language_button="Change the language"
help_string_about_button="View the credits"
help_string_preferences="Configure the game's settings"
help_string_music_slider="Change the music volume"
help_string_sound_slider="Change the sound effects volume"
help_string_scroll_slider="Change the speed of scrolling around the map"
help_string_gamma_slider="Change the brightness of the display"
help_string_full_screen="Choose whether the game should run full screen or in a window"
help_string_accelerated_speed="Make units move and fight faster"
help_string_skip_ai_moves="Do not animate AI units moving"
help_string_show_grid="Overlay a grid onto the map"
help_string_show_floating_labels="Show text above a unit when it is hit to display damage inflicted"
help_string_turn_dialog="Display a dialog at the beginning of your turn"
help_string_turn_bell="Play a bell sound at the beginning of your turn"
help_string_show_team_colors="Show a colored circle around the base of each unit to show which side it is on"
help_string_show_color_cursors="Use colored mouse cursors (may be slower)"
help_string_show_haloing="Use graphical special effects (may be slower)"
help_string_video_mode="Change the resolution the game runs at"
help_string_hotkeys="View and configure keyboard shortcuts"
help_string_turns_slider="The maximum turns the game will go for"
help_string_village_gold_slider="The amount of income each village yields per turn"
help_string_xp_modifier_slider="The amount of experience a unit needs to advance"
help_string_fog_of_war="Enemy units cannot be seen unless they are in range of your units"
help_string_shroud="The map is unknown until your units explore it"
help_string_observers="Allow users who are not playing to watch the game"
configure_sides="Configure Sides:"
choose_side="Choose Team Settings:"
client_choose_side="Choose your side:"

View file

@ -67,7 +67,8 @@ display::display(unit_map& units, CVideo& video, const gamemap& map,
turbo_(false), grid_(false), sidebarScaling_(1.0),
theme_(theme_cfg,screen_area()), builder_(built_terrains, map),
first_turn_(true), in_game_(false), map_labels_(*this,map),
tod_hex_mask1(NULL), tod_hex_mask2(NULL), diagnostic_label_(0)
tod_hex_mask1(NULL), tod_hex_mask2(NULL), diagnostic_label_(0),
help_string_(0)
{
if(non_interactive())
updatesLocked_++;
@ -259,6 +260,7 @@ void display::scroll(int xmove, int ymove)
//only invalidate if we've actually moved
if(orig_x != xpos_ || orig_y != ypos_) {
map_labels_.scroll(orig_x - xpos_, orig_y - ypos_);
font::scroll_floating_labels(orig_x - xpos_, orig_y - ypos_);
invalidate_all();
}
}
@ -1951,7 +1953,7 @@ void display::float_label(const gamemap::location& loc, const std::string& text,
const SDL_Color colour = {red,green,blue,255};
font::add_floating_label(text,24,colour,get_location_x(loc)+zoom_/2,get_location_y(loc),
0,-2,60,screen_area());
0,-2,60,screen_area(),font::CENTER_ALIGN,NULL,0,font::ANCHOR_LABEL_MAP);
}
void display::draw_unit(int x, int y, SDL_Surface* image,
@ -2228,6 +2230,30 @@ void display::begin_game()
create_buttons();
}
int display::set_help_string(const std::string& str)
{
font::remove_floating_label(help_string_);
const SDL_Color colour = {0x0,0x00,0x00,0x77};
help_string_ = font::add_floating_label(str,18,font::NORMAL_COLOUR,x()/2,y(),0.0,0.0,-1,screen_area(),font::CENTER_ALIGN,&colour,5);
const SDL_Rect& rect = font::get_floating_label_rect(help_string_);
font::move_floating_label(help_string_,0.0,-double(rect.h));
return help_string_;
}
void display::clear_help_string(int handle)
{
if(handle == help_string_) {
font::remove_floating_label(handle);
help_string_ = 0;
}
}
void display::clear_all_help_strings()
{
clear_help_string(help_string_);
}
void display::create_buttons()
{
buttons_.clear();

View file

@ -336,6 +336,13 @@ public:
bool in_game() const { return in_game_; }
//functions to set and clear 'help strings'. A 'help string' is like a tooltip, but it appears
//at the bottom of the screen, so as to not be intrusive. Setting a help string sets what
//is currently displayed there.
int set_help_string(const std::string& str);
void clear_help_string(int handle);
void clear_all_help_strings();
private:
display(const display&);
void operator=(const display&);
@ -477,6 +484,9 @@ private:
std::set<gamemap::location> highlighted_locations_;
int diagnostic_label_;
//variables for help strings
int help_string_;
};
//an object which will lock the display for the duration of its lifetime.

View file

@ -237,7 +237,12 @@ void pump()
break;
}
case SDL_MOUSEMOTION: {
raise_help_string_event(event.motion.x,event.motion.y);
break;
}
case SDL_MOUSEBUTTONDOWN: {
if(event.button.button == SDL_BUTTON_LEFT) {
@ -351,4 +356,16 @@ void raise_volatile_undraw_event()
}
}
void raise_help_string_event(int mousex, int mousey)
{
if(event_contexts.empty() == false) {
const std::vector<handler*>& event_handlers = event_contexts.back().handlers;
for(size_t i1 = 0, i2 = event_handlers.size(); i1 != i2 && i1 < event_handlers.size(); ++i1) {
event_handlers[i1]->process_help_string(mousex,mousey);
}
}
}
}

View file

@ -35,6 +35,8 @@ public:
virtual bool requires_event_focus() const { return false; }
virtual void process_help_string(int mousex, int mousey) {}
protected:
handler();
virtual ~handler();
@ -70,6 +72,7 @@ void raise_process_event();
void raise_draw_event();
void raise_volatile_draw_event();
void raise_volatile_undraw_event();
void raise_help_string_event(int mousex, int mousey);
}
#endif

View file

@ -26,6 +26,7 @@
#include <iostream>
#include <map>
#include <sstream>
#include <stack>
#include <string>
namespace {
@ -617,10 +618,10 @@ class floating_label
public:
floating_label(const std::string& text, int font_size, const SDL_Color& colour, const SDL_Color& bgcolour,
double xpos, double ypos, double xmove, double ymove, int lifetime, const SDL_Rect& clip_rect, font::ALIGN align,
int border_size)
int border_size, bool scroll_with_map)
: surf_(NULL), buf_(NULL), foreground_(NULL), text_(text), font_size_(font_size), colour_(colour), bgcolour_(bgcolour), bgalpha_(bgcolour.unused), xpos_(xpos), ypos_(ypos),
xmove_(xmove), ymove_(ymove), lifetime_(lifetime), clip_rect_(clip_rect),
alpha_change_(-255/lifetime), visible_(true), align_(align), border_(border_size)
alpha_change_(-255/lifetime), visible_(true), align_(align), border_(border_size), scroll_(scroll_with_map)
{}
void move(double xmove, double ymove);
@ -636,6 +637,8 @@ public:
void show(bool value);
bool scroll() const { return scroll_; }
private:
int xpos(size_t width) const;
@ -652,13 +655,14 @@ private:
bool visible_;
font::ALIGN align_;
int border_;
bool scroll_;
};
typedef std::map<int,floating_label> label_map;
label_map labels;
int label_id = 1;
bool hide_floating_labels = false;
std::stack<std::set<int> > label_contexts;
void floating_label::move(double xmove, double ymove)
{
@ -816,8 +820,12 @@ void floating_label::show(bool value) { visible_ = value; }
namespace font {
int add_floating_label(const std::string& text, int font_size, const SDL_Color& colour,
double xpos, double ypos, double xmove, double ymove, int lifetime, const SDL_Rect& clip_rect, ALIGN align,
const SDL_Color* bg_colour, int border_size)
const SDL_Color* bg_colour, int border_size, LABEL_SCROLL_MODE scroll_mode)
{
if(label_contexts.empty()) {
return 0;
}
if(lifetime <= 0) {
lifetime = -1;
}
@ -827,7 +835,8 @@ int add_floating_label(const std::string& text, int font_size, const SDL_Color&
bg = *bg_colour;
}
labels.insert(std::pair<int,floating_label>(label_id++,floating_label(text,font_size,colour,bg,xpos,ypos,xmove,ymove,lifetime,clip_rect,align,border_size)));
labels.insert(std::pair<int,floating_label>(label_id++,floating_label(text,font_size,colour,bg,xpos,ypos,xmove,ymove,lifetime,clip_rect,align,border_size,scroll_mode == ANCHOR_LABEL_MAP)));
label_contexts.top().insert(label_id-1);
return label_id-1;
}
@ -839,10 +848,23 @@ void move_floating_label(int handle, double xmove, double ymove)
}
}
void scroll_floating_labels(double xmove, double ymove)
{
for(label_map::iterator i = labels.begin(); i != labels.end(); ++i) {
if(i->second.scroll()) {
i->second.move(xmove,ymove);
}
}
}
void remove_floating_label(int handle)
{
const label_map::iterator i = labels.find(handle);
if(i != labels.end()) {
if(label_contexts.empty() == false) {
label_contexts.top().erase(i->first);
}
labels.erase(i);
}
}
@ -881,28 +903,24 @@ SDL_Rect get_floating_label_rect(int handle)
return empty_rect;
}
floating_label_manager::floating_label_manager()
{
}
floating_label_manager::~floating_label_manager()
{
labels.clear();
}
floating_label_hider::floating_label_hider() : old_(hide_floating_labels)
floating_label_context::floating_label_context()
{
SDL_Surface* const screen = SDL_GetVideoSurface();
if(screen != NULL) {
draw_floating_labels(screen);
}
hide_floating_labels = true;
label_contexts.push(std::set<int>());
}
floating_label_hider::~floating_label_hider()
floating_label_context::~floating_label_context()
{
hide_floating_labels = old_;
const std::set<int>& labels = label_contexts.top();
for(std::set<int>::const_iterator i = labels.begin(); i != labels.end(); ++i) {
remove_floating_label(*i);
}
label_contexts.pop();
SDL_Surface* const screen = SDL_GetVideoSurface();
if(screen != NULL) {
@ -912,32 +930,40 @@ floating_label_hider::~floating_label_hider()
void draw_floating_labels(SDL_Surface* screen)
{
if(hide_floating_labels) {
if(label_contexts.empty()) {
return;
}
const std::set<int>& context = label_contexts.top();
//draw the labels in the order they were added, so later added labels (likely to be tooltips)
//are displayed over earlier added labels.
for(label_map::iterator i = labels.begin(); i != labels.end(); ++i) {
i->second.draw(screen);
if(context.count(i->first) > 0) {
i->second.draw(screen);
}
}
}
void undraw_floating_labels(SDL_Surface* screen)
{
if(hide_floating_labels) {
if(label_contexts.empty()) {
return;
}
const std::set<int>& context = label_contexts.top();
//undraw labels in reverse order, so that a LIFO process occurs, and the screen is restored
//into the exact state it started in.
for(label_map::reverse_iterator i = labels.rbegin(); i != labels.rend(); ++i) {
i->second.undraw(screen);
if(context.count(i->first) > 0) {
i->second.undraw(screen);
}
}
//remove expired labels
for(label_map::iterator j = labels.begin(); j != labels.end(); ) {
if(j->second.expired()) {
if(context.count(i->first) > 0 && j->second.expired()) {
labels.erase(j++);
} else {
j++;

View file

@ -112,27 +112,18 @@ SDL_Rect draw_wrapped_text(display* gui, const SDL_Rect& area, int font_size,
int x, int y, int max_width, SDL_Surface* bg = NULL);
/// structure which manages floating labels. All floating labels on the screen
/// will be removed when this object is destroyed
struct floating_label_manager
/// structure which will hide all current floating labels, and cause floating labels
/// instantiated after it is created to be displayed
struct floating_label_context
{
floating_label_manager();
~floating_label_manager();
};
/// structure which will hide floating labels for its lifetime
/// it will draw the floating labels in its constructor, and then
/// undraw them in its destructor
struct floating_label_hider
{
floating_label_hider();
~floating_label_hider();
private:
bool old_;
floating_label_context();
~floating_label_context();
};
enum ALIGN { LEFT_ALIGN, CENTER_ALIGN, RIGHT_ALIGN };
enum LABEL_SCROLL_MODE { ANCHOR_LABEL_SCREEN, ANCHOR_LABEL_MAP };
/// add a label floating on the screen above everything else.
/// 'text': the text to display
/// 'font_size': the size to display the text in
@ -145,11 +136,14 @@ enum ALIGN { LEFT_ALIGN, CENTER_ALIGN, RIGHT_ALIGN };
/// @returns a handle to the label which can be used with other label functions
int add_floating_label(const std::string& text, int font_size, const SDL_Color& colour,
double xpos, double ypos, double xmove, double ymove, int lifetime, const SDL_Rect& clip_rect, ALIGN alignment=CENTER_ALIGN,
const SDL_Color* bg_colour=NULL, int border_size=0);
const SDL_Color* bg_colour=NULL, int border_size=0, LABEL_SCROLL_MODE scroll_mode=ANCHOR_LABEL_SCREEN);
/// moves the floating label given by 'handle' by (xmove,ymove)
void move_floating_label(int handle, double xmove, double ymove);
/// moves all floating labels that have 'scroll_mode' set to ANCHOR_LABEL_MAP
void scroll_floating_labels(double xmove, double ymove);
/// removes the floating label given by 'handle' from the screen
void remove_floating_label(int handle);

View file

@ -97,25 +97,31 @@ multiplayer_game_setup_dialog::multiplayer_game_setup_dialog(
turns_slider_->set_min(20);
turns_slider_->set_max(100);
turns_slider_->set_value(50);
turns_slider_->set_help_string(string_table["help_string_turns_slider"]);
village_gold_slider_.assign(new gui::slider(disp_,rect));
village_gold_slider_->set_min(1);
village_gold_slider_->set_max(5);
village_gold_slider_->set_value(1);
village_gold_slider_->set_help_string(string_table["help_string_village_gold_slider"]);
xp_modifier_slider_.assign(new gui::slider(disp_,rect));
xp_modifier_slider_->set_min(25);
xp_modifier_slider_->set_max(200);
xp_modifier_slider_->set_value(100);
xp_modifier_slider_->set_help_string(string_table["help_string_xp_modifier_slider"]);
fog_game_.assign(new gui::button(disp_,string_table["fog_of_war"],gui::button::TYPE_CHECK));
fog_game_->set_check(false);
fog_game_->set_help_string(string_table["help_string_fog_of_war"]);
shroud_game_.assign(new gui::button(disp_,string_table["shroud"],gui::button::TYPE_CHECK));
shroud_game_->set_check(false);
shroud_game_->set_help_string(string_table["help_string_shroud"]);
observers_game_.assign(new gui::button(disp_,string_table["observers"],gui::button::TYPE_CHECK));
observers_game_->set_check(true);
observers_game_->set_help_string(string_table["help_string_observers"]);
cancel_game_.assign(new gui::button(disp_,string_table["cancel_button"]));
launch_game_.assign(new gui::button(disp_,string_table["ok_button"]));

View file

@ -15,6 +15,7 @@
#include "config.hpp"
#include "display.hpp"
#include "font.hpp"
#include "gamestatus.hpp"
#include "mapgen.hpp"
#include "multiplayer_lobby.hpp"
@ -35,7 +36,7 @@ struct network_game_manager {
~network_game_manager();
};
class multiplayer_game_setup_dialog : public lobby::dialog
class multiplayer_game_setup_dialog : public lobby::dialog, public font::floating_label_context
{
public:
multiplayer_game_setup_dialog(display& disp, game_data& units_data,

View file

@ -295,7 +295,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, const config& game_config,
std::cerr << "done initializing display... " << (SDL_GetTicks() - ticks) << "\n";
//object that will make sure that labels are removed at the end of the scenario
const font::floating_label_manager labels_manager;
const font::floating_label_context labels_manager;
const halo::manager halo_manager(gui);

View file

@ -567,75 +567,87 @@ void show_preferences_dialog(display& disp)
sound_slider.set_min(1);
sound_slider.set_max(100);
sound_slider.set_value(sound_volume());
sound_slider.set_help_string(string_table["help_string_sound_slider"]);
slider_rect.y = music_pos;
gui::slider music_slider(disp,slider_rect);
music_slider.set_min(1);
music_slider.set_max(100);
music_slider.set_value(music_volume());
music_slider.set_help_string(string_table["help_string_music_slider"]);
slider_rect.y = scroll_pos;
gui::slider scroll_slider(disp,slider_rect);
scroll_slider.set_min(1);
scroll_slider.set_max(100);
scroll_slider.set_value(scroll_speed());
scroll_slider.set_help_string(string_table["help_string_scroll_slider"]);
slider_rect.y = gamma_pos;
gui::slider gamma_slider(disp,slider_rect);
gamma_slider.set_min(50);
gamma_slider.set_max(200);
gamma_slider.set_value(gamma());
gamma_slider.set_help_string(string_table["help_string_gamma_slider"]);
gui::button fullscreen_button(disp,string_table["full_screen"],
gui::button::TYPE_CHECK);
fullscreen_button.set_check(fullscreen());
fullscreen_button.set_location(slider_left,buttons_pos );
fullscreen_button.set_help_string(string_table["help_string_full_screen"]);
gui::button turbo_button(disp,string_table["speed_turbo"],gui::button::TYPE_CHECK);
turbo_button.set_check(turbo());
turbo_button.set_location(slider_left,buttons_pos + 50);
turbo_button.set_help_string(string_table["help_string_accelerated_speed"]);
gui::button show_ai_moves_button(disp,string_table["skip_ai_moves"],gui::button::TYPE_CHECK);
show_ai_moves_button.set_check(!show_ai_moves());
show_ai_moves_button.set_location(slider_left,buttons_pos + 100);
show_ai_moves_button.set_help_string(string_table["help_string_skip_ai_moves"]);
gui::button grid_button(disp,string_table["grid_button"],gui::button::TYPE_CHECK);
grid_button.set_check(grid());
grid_button.set_location(slider_left,buttons_pos + 150);
grid_button.set_help_string(string_table["help_string_show_grid"]);
gui::button floating_labels_button(disp,string_table["floating_labels_button"],gui::button::TYPE_CHECK);
floating_labels_button.set_check(show_floating_labels());
floating_labels_button.set_location(slider_left,buttons_pos + 200);
floating_labels_button.set_help_string(string_table["help_string_show_floating_labels"]);
gui::button resolution_button(disp,string_table["video_mode"]);
resolution_button.set_location(slider_left,buttons_pos + 250);
resolution_button.set_help_string(string_table["help_string_video_mode"]);
gui::button turn_dialog_button(disp,string_table["turn_dialog_button"],gui::button::TYPE_CHECK);
turn_dialog_button.set_check(turn_dialog());
turn_dialog_button.set_location(slider_left+fullscreen_button.width()+100,buttons_pos);
turn_dialog_button.set_help_string(string_table["help_string_turn_dialog"]);
gui::button turn_bell_button(disp,string_table["turn_bell_button"],gui::button::TYPE_CHECK);
turn_bell_button.set_check(turn_bell());
turn_bell_button.set_location(slider_left+fullscreen_button.width()+100,buttons_pos + 50);
turn_bell_button.set_help_string(string_table["help_string_turn_bell"]);
gui::button side_colours_button(disp,string_table["show_side_colours"],gui::button::TYPE_CHECK);
side_colours_button.set_check(show_side_colours());
side_colours_button.set_location(slider_left + fullscreen_button.width() + 100,buttons_pos + 100);
side_colours_button.set_help_string(string_table["help_string_show_team_colors"]);
gui::button colour_cursors_button(disp,string_table["show_colour_cursors"],gui::button::TYPE_CHECK);
colour_cursors_button.set_check(use_colour_cursors());
colour_cursors_button.set_location(slider_left + fullscreen_button.width() + 100,buttons_pos + 150);
colour_cursors_button.set_help_string(string_table["help_string_show_color_cursors"]);
gui::button haloes_button(disp,string_table["show_haloes"],gui::button::TYPE_CHECK);
haloes_button.set_check(show_haloes());
haloes_button.set_location(slider_left + fullscreen_button.width() + 100,buttons_pos + 200);
haloes_button.set_help_string(string_table["help_string_show_haloing"]);
gui::button hotkeys_button (disp,string_table["hotkeys_button"]);
hotkeys_button.set_location(slider_left + fullscreen_button.width() + 100,buttons_pos + 250);
hotkeys_button.set_help_string(string_table["help_string_hotkeys"]);
bool redraw_all = true;
@ -717,8 +729,8 @@ void show_preferences_dialog(display& disp)
//the underlying frame buffer is changing, so cancel
//the surface restorer restoring the frame buffer state
restorer.cancel();
break;
}
break;
}
if(turn_bell_button.process(mousex,mousey,left_button)) {

View file

@ -38,7 +38,7 @@ extern const int ButtonVPadding;
bool in_dialog();
struct dialog_manager : private cursor::setter, private font::floating_label_hider, private halo::halo_hider {
struct dialog_manager : private cursor::setter, private font::floating_label_context, private halo::halo_hider {
dialog_manager();
~dialog_manager();

View file

@ -115,6 +115,8 @@ TITLE_RESULT show_title(display& screen, int* ntip)
const hotkey::basic_handler key_handler(&screen);
const video_change_detector disp_change_detector(screen.video());
const font::floating_label_context label_manager;
const scoped_sdl_surface title_surface_unscaled(image::get_image(game_config::game_title,image::UNSCALED));
const scoped_sdl_surface title_surface(scale_surface(title_surface_unscaled,screen.x(),screen.y()));
@ -163,6 +165,8 @@ TITLE_RESULT show_title(display& screen, int* ntip)
for(b = 0; b != nbuttons; ++b) {
buttons.push_back(button(screen,string_table[button_labels[b]]));
buttons.back().set_location(menu_xbase + b*menu_xincr, menu_ybase + b*menu_yincr);
buttons.back().set_help_string(string_table["help_string_" + button_labels[b]]);
std::cerr << "set help string for '" << button_labels[b] << "' -> '" << string_table["help_string_" + button_labels[b]] << "'\n";
max_width = maximum<size_t>(max_width,buttons.back().width());
}

View file

@ -151,7 +151,7 @@ void slider::process()
int new_value = value_;
if(dragging_) {
if(dragging_ || new_click && point_in_rect(mousex,mousey,rect)) {
int tmp = mousex - location().x;
if (tmp < 0)
tmp = 0;

View file

@ -8,18 +8,19 @@ namespace {
namespace gui {
widget::widget(const widget &o) :
disp_(o.disp_), rect_(o.rect_), focus_(o.focus_), dirty_(o.dirty_), hidden_(false), volatile_(o.volatile_)
disp_(o.disp_), rect_(o.rect_), focus_(o.focus_), dirty_(o.dirty_), hidden_(false), volatile_(o.volatile_),
help_string_(o.help_string_), help_text_(o.help_text_)
{
bg_backup();
}
widget::widget(display& disp) :
disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), hidden_(false), volatile_(false)
disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), hidden_(false), volatile_(false), help_string_(0)
{
}
widget::widget(display& disp, SDL_Rect& rect) :
disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), hidden_(false), volatile_(false)
disp_(&disp), rect_(EmptyRect), focus_(true), dirty_(true), hidden_(false), volatile_(false), help_string_(0)
{
set_location(rect);
bg_backup();
@ -182,4 +183,22 @@ void widget::volatile_undraw()
bg_restore();
}
void widget::set_help_string(const std::string& str)
{
help_text_ = str;
}
void widget::process_help_string(int mousex, int mousey)
{
if(point_in_rect(mousex,mousey,location())) {
if(help_string_ == 0 && help_text_ != "") {
std::cerr << "setting help string to '" << help_text_ << "'\n";
help_string_ = disp().set_help_string(help_text_);
}
} else if(help_string_ > 0) {
disp().clear_help_string(help_string_);
help_string_ = 0;
}
}
}

View file

@ -44,6 +44,10 @@ public:
void set_dirty(bool dirty=true);
const bool dirty() const;
void set_help_string(const std::string& str);
virtual void process_help_string(int mousex, int mousey);
protected:
widget(const widget &o);
widget(display& disp);
@ -69,6 +73,9 @@ private:
bool hidden_;
bool volatile_;
std::string help_text_;
int help_string_;
};
}