Revert a refactoring change (2007-06-30T03:10:14Z!alinkmaze@gmail.com)

...that disappeared the help buttons on the Recruit and Recall menus.
I'll have to redo this right.
This commit is contained in:
Eric S. Raymond 2007-07-06 09:46:21 +00:00
parent 58217e2ea3
commit b59c85149f
19 changed files with 1092 additions and 1196 deletions

View file

@ -54,7 +54,6 @@ wesnoth_SOURCES = \
astarnode.cpp \
astarsearch.cpp \
attack_prediction.cpp \
basic_dialog.cpp \
builder.cpp \
cavegen.cpp \
checksum.cpp \
@ -172,7 +171,6 @@ wesnoth_editor_SOURCES = \
animated_editor.cpp \
astarnode.cpp \
astarsearch.cpp \
basic_dialog.cpp \
builder.cpp \
cavegen.cpp \
checksum.cpp \

View file

@ -1,804 +0,0 @@
/* $Id$ */
/*
Copyright (C) 2006 by Patrick Parker <patrick_x99@hotmail.com>
wesnoth widget Copyright (C) 2003-5 by David White <davidnwhite@verizon.net>
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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "global.hpp"
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "basic_dialog.hpp"
#include "config.hpp"
#include "display.hpp"
#include "events.hpp"
#include "gettext.hpp"
#include "hotkeys.hpp"
#include "image.hpp"
#include "key.hpp"
#include "sound.hpp"
#include "log.hpp"
#include "language.hpp"
#include "marked-up_text.hpp"
#include "widgets/button.hpp"
#include "widgets/menu.hpp"
#include "widgets/textbox.hpp"
#include "sdl_ttf/SDL_ttf.h"
#include <iostream>
#include <numeric>
#define ERR_DP LOG_STREAM(err, display)
#define LOG_DP LOG_STREAM(info, display)
#define ERR_G LOG_STREAM(err, general)
namespace gui {
// This is where the connections between styles and the panel images
// in the data tree gets made.
const struct style basic_dialog::default_style("opaque", 0);
const struct style basic_dialog::message_style("translucent65", 3);
const struct style basic_dialog::titlescreen_style("translucent54", 0);
const struct style basic_dialog::hotkeys_style("menu2", 0);
//static initialization
const int basic_dialog::message_font_size = font::SIZE_PLUS;
const int basic_dialog::caption_font_size = font::SIZE_LARGE;
const size_t basic_dialog::left_padding = font::relative_size(10);
const size_t basic_dialog::right_padding = font::relative_size(10);
const size_t basic_dialog::image_h_pad = font::relative_size(/*image_ == NULL ? 0 :*/ 10);
const size_t basic_dialog::top_padding = font::relative_size(10);
const size_t basic_dialog::bottom_padding = font::relative_size(10);
#ifdef USE_TINY_GUI
const int basic_dialog::max_menu_width = 300;
#else
const int basic_dialog::max_menu_width = -1;
#endif
}
namespace {
std::vector<std::string> empty_string_vector;
} //end anonymous namespace
namespace gui {
basic_dialog::dimension_measurements::dimension_measurements() :x(-1), y(-1), interior(empty_rect),
message(empty_rect), textbox(empty_rect), menu_height(-1)
{
//note: this is not defined in the header file to C++ ODR (one-definition rule)
//since each inclusion of the header file uses a different version of empty_rect
//(unnamed namespace and/or const object defined at declaration time).
}
basic_dialog::basic_dialog(display &disp, const std::string& title, const std::string& message,
const DIALOG_TYPE type, const struct style* dialog_style
) : disp_(disp), image_(NULL),
title_(title), style_(dialog_style), title_widget_(NULL), message_(NULL),
type_(type), menu_(NULL), text_widget_(NULL),
frame_(NULL), bg_restore_(NULL), result_(CONTINUE_DIALOG)
{
CVideo& screen = disp_.video();
switch(type)
{
case MESSAGE:
default:
break;
case OK_ONLY:
add_button(new standard_dialog_button(screen,_("OK"),0,true), BUTTON_STANDARD);
break;
case YES_NO:
add_button(new standard_dialog_button(screen,_("Yes"),0,false), BUTTON_STANDARD);
add_button(new standard_dialog_button(screen,_("No"),1,true), BUTTON_STANDARD);
break;
case OK_CANCEL:
add_button(new standard_dialog_button(screen,_("OK"),0,false), BUTTON_STANDARD);
add_button(new standard_dialog_button(screen,_("Cancel"),1,true), BUTTON_STANDARD);
break;
case CANCEL_ONLY:
add_button(new standard_dialog_button(screen,_("Cancel"),0,true), BUTTON_STANDARD);
break;
case CLOSE_ONLY:
add_button(new standard_dialog_button(screen,_("Close"),0,true), BUTTON_STANDARD);
break;
}
//dialog creator should catch(button::error&) ?
try {
std::string msg = font::word_wrap_text(message, message_font_size, screen.getx() / 2, screen.gety() / 2);
message_ = new label(screen, msg, message_font_size, font::NORMAL_COLOUR, false);
} catch(utils::invalid_utf8_exception&) {
ERR_DP << "Problem handling utf8 in message '" << message << "'\n";
throw;
}
}
basic_dialog::~basic_dialog()
{
if(menu_ != empty_menu)
{
delete menu_;
}
delete title_widget_;
delete message_;
delete text_widget_;
delete image_;
delete frame_;
button_pool_iterator b;
for (b = button_pool_.begin(); b != button_pool_.end(); ++b) {
delete b->first;
}
// pp_iterator p;
// for (p = preview_panes_.begin(); p != preview_panes_.end(); ++p) {
// delete (*p);
// }
delete bg_restore_;
}
const bool basic_dialog::option_checked(unsigned int option_index)
{
unsigned int i = 0;
button_pool_iterator b;
for (b = button_pool_.begin(); b != button_pool_.end(); ++b) {
if(b->first->is_option()) {
if(option_index == i++) {
return b->first->checked();
}
}
}
return false;
}
void basic_dialog::add_button(dialog_button *const btn, BUTTON_LOCATION loc)
{
std::pair<dialog_button *, BUTTON_LOCATION> new_pair(btn,loc);
button_pool_.push_back(new_pair);
switch(loc)
{
case BUTTON_EXTRA:
case BUTTON_EXTRA_LEFT:
case BUTTON_CHECKBOX:
case BUTTON_CHECKBOX_LEFT:
extra_buttons_.push_back(btn);
btn->set_parent(this);
break;
case BUTTON_STANDARD:
standard_buttons_.push_back(btn);
default:
btn->set_parent(this);
break;
}
}
void basic_dialog::add_button(dialog_button_info btn_info, BUTTON_LOCATION loc)
{
dialog_button *btn = new dialog_button(disp_.video(), btn_info.label, button::TYPE_PRESS, CONTINUE_DIALOG, btn_info.handler);
add_button(btn, loc);
}
void basic_dialog::add_option(const std::string& label, bool checked, BUTTON_LOCATION loc)
{
gui::dialog_button *btn = new dialog_button(disp_.video(), label, button::TYPE_CHECK);
btn->set_check(checked);
add_button(btn, loc);
}
void basic_dialog::set_textbox(const std::string& text_widget_label,
const std::string& text_widget_text,
const int text_widget_max_chars, const unsigned int text_box_width)
{
label *label_ptr = new label(disp_.video(), text_widget_label, message_font_size, font::NORMAL_COLOUR, false);
const bool editable_textbox = std::find(text_widget_text.begin(),text_widget_text.end(),'\n') == text_widget_text.end();
text_widget_ = new dialog_textbox(label_ptr, disp_.video(), text_box_width, text_widget_text, editable_textbox, text_widget_max_chars);
text_widget_->set_wrap(!editable_textbox);
}
void basic_dialog::set_menu(const std::vector<std::string> &menu_items)
{
set_menu(new gui::menu(disp_.video(), menu_items, (type_==MESSAGE),
-1, basic_dialog::max_menu_width, NULL, &menu::default_style, false));
}
menu& basic_dialog::get_menu()
{
if(menu_ == NULL)
{
if(empty_menu == NULL) {
empty_menu = new gui::menu(disp_.video(),empty_string_vector,false,-1,-1,NULL,&menu::simple_style);
empty_menu->leave();
}
menu_ = empty_menu; //no menu, so fake it
}
return *menu_;
}
int basic_dialog::show(int xloc, int yloc)
{
layout(xloc, yloc);
return show();
}
int basic_dialog::show()
{
if(disp_.video().update_locked()) {
ERR_DP << "display locked ignoring dialog '" << title_ << "' '" << message_->get_text() << "'\n";
return CLOSE_DIALOG;
}
LOG_DP << "showing dialog '" << title_ << "' '" << message_->get_text() << "'\n";
if(dim_.interior == empty_rect) { layout(); }
//create the event context, remember to instruct any passed-in widgets to join it
const events::event_context dialog_events_context;
const dialog_manager manager;
const events::resize_lock prevent_resizing;
//draw
draw_frame();
update_widget_positions();
draw_contents();
//process
dialog_process_info dp_info;
do
{
events::pump();
set_result(process(dp_info));
if(!done()) {
refresh();
}
action(dp_info);
dp_info.cycle();
} while(!done());
return result();
}
void basic_dialog::draw_contents()
{
if(!preview_panes_.empty()) {
for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
preview_pane *pane = *i;
if(!pane->handler_members().empty())
{
pane->draw();
pane->needs_restore_ = false; //prevent panes from drawing over members
}
}
}
events::raise_draw_event(); //draw widgets
disp_.flip();
disp_.invalidate_all();
}
dialog_frame& basic_dialog::get_frame(button *help_button)
{
if(frame_ == NULL) {
CVideo& screen = disp_.video();
frame_buttons_.clear();
for(button_iterator b = standard_buttons_.begin(); b != standard_buttons_.end(); ++b)
{
frame_buttons_.push_back(*b);
}
delete bg_restore_;
bg_restore_ = new surface_restorer;
frame_ = new dialog_frame(screen, title_, style_, &frame_buttons_, bg_restore_,
help_button);
}
return *frame_;
}
void basic_dialog::draw_frame()
{
get_frame().draw();
}
void basic_dialog::update_widget_positions()
{
if(!preview_panes_.empty()) {
for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
preview_pane *pane = *i;
pane->join();
pane->set_location(dim_.panes.find(pane)->second);
}
}
if(text_widget_) {
text_widget_->join();
text_widget_->set_location(dim_.textbox);
if(text_widget_->get_label()) {
text_widget_->get_label()->set_location(dim_.label_x, dim_.label_y);
}
}
if(get_menu().height() > 0) {
menu_->join();
menu_->set_numeric_keypress_selection(text_widget_ == NULL);
menu_->set_width( dim_.menu_width );
menu_->set_max_width( dim_.menu_width ); //lock the menu width
if(dim_.menu_height >= 0) {
menu_->set_max_height( dim_.menu_height );
}
menu_->set_location( dim_.menu_x, dim_.menu_y );
}
if(image_) {
image_->join();
image_->set_location(dim_.image_x, dim_.image_y);
if(image_->caption()) {
image_->caption()->set_location(dim_.caption_x, dim_.caption_y);
}
}
button_iterator b;
for(b = extra_buttons_.begin(); b != extra_buttons_.end(); ++b) {
dialog_button *btn = *b;
btn->join();
std::pair<int,int> coords = dim_.buttons.find(btn)->second;
btn->set_location(coords.first, coords.second);
}
for(b = standard_buttons_.begin(); b != standard_buttons_.end(); ++b) {
dialog_button *btn = *b;
btn->join();
}
message_->set_location(dim_.message);
message_->join();
}
void basic_dialog::refresh()
{
disp_.flip();
disp_.delay(10);
}
basic_dialog::dimension_measurements basic_dialog::layout(int xloc, int yloc)
{
CVideo& screen = disp_.video();
surface const scr = screen.getSurface();
dimension_measurements dim;
dim.x = xloc;
dim.y = yloc;
const bool use_textbox = (text_widget_ != NULL);
int text_widget_width = 0;
int text_widget_height = 0;
if(use_textbox) {
const SDL_Rect& area = font::text_area(text_widget_->text(),message_font_size);
dim.textbox.w = minimum<size_t>(screen.getx()/2,maximum<size_t>(area.w,text_widget_->width()));
dim.textbox.h = minimum<size_t>(screen.gety()/2,maximum<size_t>(area.h,text_widget_->height()));
text_widget_width = dim.textbox.w;
text_widget_width += (text_widget_->get_label() == NULL) ? 0 : text_widget_->get_label()->width();
text_widget_height = dim.textbox.h + message_font_size;
}
const bool use_menu = (get_menu().height() > 0);
if(!message_->get_text().empty()) {
dim.message.w = message_->width();
dim.message.h = message_->height();
}
unsigned int caption_width = 0;
unsigned int caption_height = 0;
if (image_ != NULL && image_->caption() != NULL) {
caption_width = image_->caption()->width();
caption_height = image_->caption()->height();
}
int check_button_height = 0;
int left_check_button_height = 0;
const int button_height_padding = 5;
for(button_pool_const_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
dialog_button const *const btn = b->first;
switch(b->second)
{
case BUTTON_EXTRA:
case BUTTON_CHECKBOX:
check_button_height += btn->height() + button_height_padding;
break;
case BUTTON_EXTRA_LEFT:
case BUTTON_CHECKBOX_LEFT:
left_check_button_height += btn->height() + button_height_padding;
break;
case BUTTON_STANDARD:
default:
break;
}
}
check_button_height = maximum<int>(check_button_height, left_check_button_height);
size_t above_preview_pane_height = 0, above_left_preview_pane_width = 0, above_right_preview_pane_width = 0;
size_t preview_pane_height = 0, left_preview_pane_width = 0, right_preview_pane_width = 0;
if(!preview_panes_.empty()) {
for(pp_const_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
preview_pane const *const pane = *i;
const SDL_Rect& rect = pane->location();
if(pane->show_above() == false) {
preview_pane_height = maximum<size_t>(rect.h,preview_pane_height);
if(pane->left_side()) {
left_preview_pane_width += rect.w;
} else {
right_preview_pane_width += rect.w;
}
} else {
above_preview_pane_height = maximum<size_t>(rect.h,above_preview_pane_height);
if(pane->left_side()) {
above_left_preview_pane_width += rect.w;
} else {
above_right_preview_pane_width += rect.w;
}
}
}
}
const int menu_hpadding = font::relative_size((dim.message.h > 0 && use_menu) ? 10 : 0);
const size_t image_h_padding = (image_ == NULL)? 0 : image_h_pad;
const size_t padding_width = left_padding + right_padding + image_h_padding;
const size_t padding_height = top_padding + bottom_padding + menu_hpadding;
const size_t image_width = (image_ == NULL) ? 0 : image_->width();
const size_t image_height = (image_ == NULL) ? 0 : image_->height();
const size_t total_text_height = dim.message.h + caption_height;
size_t text_width = dim.message.w;
if(caption_width > text_width)
text_width = caption_width;
// Prevent the menu to be larger than the screen
dim.menu_width = menu_->width();
if(dim.menu_width + image_width + padding_width > size_t(scr->w))
dim.menu_width = scr->w - image_width - padding_width;
if(dim.menu_width > text_width)
text_width = dim.menu_width;
size_t total_width = image_width + text_width + padding_width;
if(text_widget_width+left_padding+right_padding > total_width)
total_width = text_widget_width+left_padding+right_padding;
//Prevent the menu from being too skinny
if(use_menu && preview_panes_.empty() &&
total_width > dim.menu_width + image_width + padding_width) {
dim.menu_width = total_width - image_width - padding_width;
}
const size_t text_and_image_height = image_height > total_text_height ? image_height : total_text_height;
int total_height = text_and_image_height + padding_height + menu_->height() +
text_widget_height + check_button_height;
dim.interior.w = maximum<int>(total_width,above_left_preview_pane_width + above_right_preview_pane_width);
dim.interior.h = maximum<int>(total_height,int(preview_pane_height));
dim.interior.x = maximum<int>(0,dim.x >= 0 ? dim.x : scr->w/2 - (dim.interior.w + left_preview_pane_width + right_preview_pane_width)/2);
dim.interior.y = maximum<int>(0,dim.y >= 0 ? dim.y : scr->h/2 - (dim.interior.h + above_preview_pane_height)/2);
LOG_DP << "above_preview_pane_height: " << above_preview_pane_height << "; "
<< "dim.interior.y: " << scr->h/2 << " - " << (dim.interior.h + above_preview_pane_height)/2 << " = "
<< dim.interior.y << "; " << "dim.interior.h: " << dim.interior.h << "\n";
if(dim.x <= -1 || dim.y <= -1) {
dim.x = dim.interior.x + left_preview_pane_width;
dim.y = dim.interior.y + above_preview_pane_height;
}
if(dim.x + dim.interior.w > scr->w) {
dim.x = scr->w - dim.interior.w;
if(dim.x < dim.interior.x) {
dim.interior.x = dim.x;
}
}
const int frame_top_pad = get_frame().top_padding();
const int frame_bottom_pad = get_frame().bottom_padding();
if(dim.y + dim.interior.h + frame_bottom_pad > scr->h) {
dim.y = maximum<int>(frame_top_pad, scr->h - dim.interior.h - frame_bottom_pad);
if(dim.y < dim.interior.y) {
dim.interior.y = dim.y;
}
}
dim.interior.w += left_preview_pane_width + right_preview_pane_width;
dim.interior.h += above_preview_pane_height;
const int max_height = scr->h - dim.interior.y - frame_bottom_pad;
if(dim.interior.h > max_height) {
//try to rein in the menu height a little bit
const int menu_height = menu_->height();
if(menu_height > 0) {
dim.menu_height = maximum<int>(1, max_height - dim.interior.h + menu_height);
dim.interior.h -= menu_height - dim.menu_height;
}
}
//calculate the positions of the preview panes to the sides of the dialog
if(!preview_panes_.empty()) {
int left_preview_pane = dim.interior.x;
int right_preview_pane = dim.interior.x + total_width + left_preview_pane_width;
int above_left_preview_pane = dim.interior.x + dim.interior.w/2;
int above_right_preview_pane = above_left_preview_pane;
for(pp_const_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
preview_pane const *const pane = *i;
SDL_Rect area = pane->location();
if(pane->show_above() == false) {
area.y = dim.y;
if(pane->left_side()) {
area.x = left_preview_pane;
left_preview_pane += area.w;
} else {
area.x = right_preview_pane;
right_preview_pane += area.w;
}
} else {
area.y = dim.interior.y;
if(pane->left_side()) {
area.x = above_left_preview_pane - area.w;
above_left_preview_pane -= area.w;
} else {
area.x = above_right_preview_pane;
above_right_preview_pane += area.w;
}
}
dim.panes[*i] = area;
}
}
const int text_widget_y = dim.y+top_padding+text_and_image_height-6+menu_hpadding;
if(use_textbox) {
dim.textbox.x = dim.x + left_padding + text_widget_width - dim.textbox.w;
dim.textbox.y = text_widget_y + (text_widget_height - dim.textbox.h)/2;
dim.label_x = dim.x+left_padding;
dim.label_y = dim.textbox.y;
}
dim.menu_x = dim.x+image_width+left_padding+image_h_padding;
dim.menu_y = dim.y+top_padding+text_and_image_height+menu_hpadding+ (use_textbox ? text_widget_->location().h + top_padding : 0);
dim.message.x = dim.x + left_padding;
dim.message.y = dim.y + top_padding + caption_height;
if(image_ != NULL) {
const int x = dim.x + left_padding;
const int y = dim.y + top_padding;
dim.message.x += image_width + image_h_padding;
dim.image_x = x;
dim.image_y = y;
dim.caption_x = dim.x + image_width + left_padding + image_h_padding;
dim.caption_y = dim.y + top_padding;
}
//set the position of any tick boxes. by default, they go right below the menu,
//slammed against the right side of the dialog
if(extra_buttons_.empty() == false) {
int options_y = text_widget_y + text_widget_height + menu_->height() + button_height_padding + menu_hpadding;
int options_left_y = options_y;
for(button_pool_const_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
dialog_button const *const btn = b->first;
std::pair<int,int> coords;
switch(b->second)
{
case BUTTON_EXTRA:
case BUTTON_CHECKBOX:
coords.first = dim.x + total_width - btn->width() - ButtonHPadding;
coords.second = options_y;
dim.buttons[b->first] = coords;
options_y += btn->height() + button_height_padding;
break;
case BUTTON_EXTRA_LEFT:
case BUTTON_CHECKBOX_LEFT:
coords.first = dim.x + ButtonHPadding;
coords.second = options_left_y;
dim.buttons[b->first] = coords;
options_left_y += btn->height() + button_height_padding;
break;
case BUTTON_STANDARD:
default:
break;
}
}
}
set_layout(dim);
return dim;
}
void basic_dialog::set_layout(dimension_measurements &new_dim) {
get_frame().layout(new_dim.interior);
dim_ = new_dim;
}
int basic_dialog::process(dialog_process_info &info)
{
int mousex, mousey;
int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
info.new_right_button = (mouse_flags&SDL_BUTTON_RMASK) != 0;
info.new_left_button = (mouse_flags&SDL_BUTTON_LMASK) != 0;
info.new_key_down = info.key[SDLK_SPACE] || info.key[SDLK_RETURN] ||
info.key[SDLK_ESCAPE] || info.key[SDLK_KP_ENTER];
info.double_clicked = menu_->double_clicked();
get_menu();
const bool use_menu = (menu_ != empty_menu);
if((!info.key_down && info.key[SDLK_RETURN] || info.key[SDLK_KP_ENTER] || info.double_clicked) &&
(type_ == YES_NO || type_ == OK_CANCEL || type_ == OK_ONLY || type_ == CLOSE_ONLY)) {
return (use_menu ? menu_->selection() : 0);
}
//escape quits from the dialog -- unless it's an "ok" dialog with a menu,
//since such dialogs require a selection of some kind.
if(!info.key_down && info.key[SDLK_ESCAPE] && !(type_ == OK_ONLY && use_menu)) {
return (CLOSE_DIALOG);
}
//inform preview panes when there is a new menu selection
if((menu_->selection() != info.selection) || info.first_time) {
info.selection = menu_->selection();
int selection = info.selection;
if(selection < 0) {
selection = 0;
}
if(!preview_panes_.empty()) {
for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
(**i).set_selection(selection);
if(info.first_time) {
(**i).set_dirty();
}
}
}
}
info.first_time = false;
if(use_menu) {
//get any drop-down choice or context-menu click
const int selection = menu_->process();
if(selection != -1)
{
return (selection);
}
}
events::raise_process_event();
events::raise_draw_event();
//left-clicking outside of a drop-down or context-menu should close it
if (info.new_left_button && !info.left_button) {
if (standard_buttons_.empty() && !point_in_rect(mousex,mousey, menu_->location())) {
if (use_menu)
sound::play_UI_sound(game_config::sounds::button_press);
return CLOSE_DIALOG;
}
}
//right-clicking outside of a dialog should close it unless a choice is required
//note: this will also close any context-menu or drop-down when it is right-clicked
// but that may be changed to allow right-click selection instead.
if (info.new_right_button && !info.right_button) {
if( standard_buttons_.empty()
|| (!point_in_rect(mousex,mousey,get_frame().get_layout().exterior)
&& type_ != YES_NO && !(type_ == OK_ONLY && use_menu))) {
sound::play_UI_sound(game_config::sounds::button_press);
return CLOSE_DIALOG;
}
}
//any keypress should close a dialog if it has one standard button (or less)
//and no menu options.
if (info.new_key_down && !info.key_down) {
if (standard_buttons_.size() < 2 && !use_menu)
return CLOSE_DIALOG;
}
//now handle any button presses
for(button_pool_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
if(b->first->pressed()) {
return b->first->action(info);
}
}
return CONTINUE_DIALOG;
}
int dialog_button::action(dialog_process_info &info) {
if(handler_ != NULL) {
menu &menu_ref = parent_->get_menu();
dialog_button_action::RESULT res = handler_->button_pressed(menu_ref.selection());
if(res == DELETE_ITEM || res == CLOSE_DIALOG) {
return res;
}
//reset button-tracking flags so that if the action displays a dialog, a button-press
//at the end of the dialog won't be mistaken for a button-press in this dialog.
//(We should eventually use a proper event-handling system instead of tracking
//flags to avoid problems like this altogether).
info.clear_buttons();
return CONTINUE_DIALOG;
}
return simple_result_;
}
void basic_dialog::action(dialog_process_info& info)
{
//default way of handling a "delete item" request
if(result() == DELETE_ITEM) {
menu &menu_ref = get_menu();
menu_ref.erase_item(menu_ref.selection());
if(menu_ref.nitems() == 0) {
set_result(CLOSE_DIALOG);
} else {
set_result(CONTINUE_DIALOG);
info.first_time = true;
}
}
}
int standard_dialog_button::action(dialog_process_info &/*info*/) {
//if the menu is not used, then return the index of the
//button pressed, otherwise return the index of the menu
//item selected if the last button is not pressed, and
//cancel (-1) otherwise
if(dialog()->get_menu().height() <= 0) {
return simple_result_;
} else if((simple_result_ == 0 && is_last_) || !is_last_) {
return (dialog()->get_menu().selection());
}
return CLOSE_DIALOG;
}
void basic_dialog::set_image(surface surf, const std::string &caption)
{
label *label_ptr = NULL;
if(!caption.empty()) {
label_ptr = new label(disp_.video(), caption, caption_font_size, font::NORMAL_COLOUR, false);
}
set_image( new dialog_image(label_ptr, disp_.video(), surf ));
}
void dialog_image::draw_contents()
{
video().blit_surface(location().x, location().y, surf_);
}
// methods for message_dialog subclass begin here
int message_dialog::show(msecs minimum_lifetime)
{
prevent_misclick_until_ = SDL_GetTicks() + minimum_lifetime;
return basic_dialog::show();
}
void message_dialog::action(gui::dialog_process_info &dp_info)
{
basic_dialog::action(dp_info);
if(done() && SDL_GetTicks() < prevent_misclick_until_ && result() != gui::ESCAPE_DIALOG) {
//discard premature results
set_result(gui::CONTINUE_DIALOG);
}
}
message_dialog::~message_dialog()
{
}
}//end namespace gui

View file

@ -1,293 +0,0 @@
/* $Id$ */
/*
Copyright (C) 2006 by Patrick Parker <patrick_x99@hotmail.com>
wesnoth widget Copyright (C) 2003-5 by David White <davidnwhite@verizon.net>
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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef BASIC_DIALOG_H_INCLUDED
#define BASIC_DIALOG_H_INCLUDED
#include "show_dialog.hpp"
#include "widgets/label.hpp"
#include "widgets/textbox.hpp"
#include "widgets/button.hpp"
#include "widgets/menu.hpp"
#include "key.hpp"
#include "sdl_utils.hpp"
namespace gui {
struct style {
style(std::string const& p, int br) : panel(p), blur_radius(br) {}
std::string panel;
int blur_radius;
};
struct dialog_process_info
{
public:
dialog_process_info() : left_button(true), right_button(true), key_down(true),
first_time(true), double_clicked(false), selection(-1), clear_buttons_(false)
{}
void clear_buttons() {
clear_buttons_ = true;
}
void cycle() {
if(clear_buttons_) {
left_button = true;
right_button = true;
key_down = true;
clear_buttons_ = false;
} else {
left_button = new_left_button;
right_button = new_right_button;
key_down = new_key_down;
}
}
CKey key;
bool left_button, right_button, key_down, first_time, double_clicked;
bool new_left_button, new_right_button, new_key_down;
int selection;
private:
bool clear_buttons_;
};
class dialog_image : public widget {
public:
dialog_image(label *const caption, CVideo &video, surface img) : widget(video, false),
surf_(img), caption_(caption)
{
if(!img.null()) {
set_measurements(img->w, img->h);
}
}
~dialog_image() { delete caption_; }
//surface surface() const { return surf_; }
label *caption() const { return caption_; }
void draw_contents();
handler_vector handler_members() {
handler_vector h;
if(caption_) h.push_back(caption_);
return h;
}
private:
surface surf_;
label *caption_;
};
class dialog_textbox : public textbox {
public:
dialog_textbox(label *const label_widget, CVideo &video, int width, const std::string& text="", bool editable=true, size_t max_size = 256, double alpha = 0.4, double alpha_focus = 0.2)
: textbox(video, width, text, editable, max_size, alpha, alpha_focus, false),
label_(label_widget)
{}
~dialog_textbox() { delete label_; }
label *get_label() const { return label_; }
handler_vector handler_members() {
handler_vector h = textbox::handler_members();
if(label_) h.push_back(label_);
return h;
}
private:
label *label_;
};
class dialog_button : public button {
public:
dialog_button(CVideo& video, const std::string& label, TYPE type=TYPE_PRESS,
int simple_result=CONTINUE_DIALOG, dialog_button_action *handler=NULL)
: button(video,label,type,"",DEFAULT_SPACE,false), simple_result_(simple_result),
parent_(NULL), handler_(handler)
{}
void set_parent(class basic_dialog *parent) {
parent_ = parent;
}
bool is_option() const {
return (type_ == TYPE_CHECK);
}
virtual int action(dialog_process_info &info);
protected:
class basic_dialog *dialog() const { return parent_; }
const int simple_result_;
private:
class basic_dialog *parent_;
dialog_button_action *handler_;
};
class standard_dialog_button : public dialog_button {
public:
standard_dialog_button(CVideo& video, const std::string& label, const int index, const bool is_last)
: dialog_button(video,label,TYPE_PRESS,index), is_last_(is_last)
{}
int action(dialog_process_info &info);
private:
const bool is_last_;
};
class basic_dialog {
public:
enum BUTTON_LOCATION { BUTTON_STANDARD, BUTTON_EXTRA, BUTTON_EXTRA_LEFT, BUTTON_CHECKBOX, BUTTON_CHECKBOX_LEFT };
struct dimension_measurements {
dimension_measurements();
int x, y;
SDL_Rect interior, message, textbox;
unsigned int menu_width;
std::map<preview_pane *const, SDL_Rect > panes;
int label_x, label_y;
int menu_x, menu_y, menu_height;
int image_x, image_y, caption_x, caption_y;
std::map<dialog_button *const, std::pair<int,int> > buttons;
//use get_frame().get_layout() to check frame dimensions
};
private:
typedef std::vector<preview_pane *>::iterator pp_iterator;
typedef std::vector<preview_pane *>::const_iterator pp_const_iterator;
typedef std::vector<dialog_button *>::iterator button_iterator;
typedef std::vector<dialog_button *>::const_iterator button_const_iterator;
typedef std::vector< std::pair<dialog_button *, BUTTON_LOCATION> >::iterator button_pool_iterator;
typedef std::vector< std::pair<dialog_button *, BUTTON_LOCATION> >::const_iterator button_pool_const_iterator;
public:
//Static members
static const struct style default_style;
static const struct style message_style;
static const struct style titlescreen_style;
static const struct style hotkeys_style;
static const int message_font_size;
static const int caption_font_size;
static const int max_menu_width;
static const size_t left_padding;
static const size_t right_padding;
static const size_t image_h_pad;
static const size_t top_padding;
static const size_t bottom_padding;
//Constructor & destructor
//dialog - throws button::error() if standard buttons fail to initialize
// throws utils::invalid_utf8_exception() if message is invalid
basic_dialog(display &disp, const std::string& title="", const std::string& message="",
const DIALOG_TYPE type=MESSAGE,
const struct style *dialog_style=&default_style);
virtual ~basic_dialog();
//Adding components - the dialog will manage the memory of these widgets,
//therefore do not attempt to reference its widgets after destroying it
void set_image(dialog_image *const img) { delete image_; image_ = img; }
void set_image(surface surf, const std::string &caption="");
void set_menu(menu *const m) { if(menu_ != empty_menu) delete menu_; menu_ = m; }
void set_menu(const std::vector<std::string> & menu_items);
//add_pane - preview panes are not currently memory managed (for backwards compat)
void add_pane(preview_pane *const pp) { preview_panes_.push_back(pp); }
void set_panes(std::vector<preview_pane*> panes) { preview_panes_ = panes; }
void set_textbox(dialog_textbox *const box) {
delete text_widget_;
text_widget_ = box;
}
void set_textbox(const std::string& text_widget_label="",
const std::string &text_widget_text="",
const int text_widget_max_chars = 256,
const unsigned int text_box_width = font::relative_size(350));
void add_button(dialog_button *const btn, BUTTON_LOCATION loc);
void add_button(dialog_button_info btn_info, BUTTON_LOCATION loc=BUTTON_EXTRA);
void add_option(const std::string& label, bool checked=false, BUTTON_LOCATION loc=BUTTON_CHECKBOX);
//Specific preparations
//layout - determines dialog measurements based on all components
virtual dimension_measurements layout(int xloc=-1, int yloc=-1);
void set_layout(dimension_measurements &new_dim);
dimension_measurements get_layout() const { return dim_; }
//Launching the dialog
//show - the return value of this method should be the same as result()
virtual int show(int xloc, int yloc);
virtual int show();
//Results
int result() const { return result_; }
menu &get_menu();
bool done() const { return (result_ != CONTINUE_DIALOG); }
const std::string textbox_text() const { return text_widget_->text();}
dialog_textbox& get_textbox() const { return *text_widget_; }
const bool option_checked(unsigned int option_index=0);
display& get_display() { return disp_; }
protected:
void set_result(const int result) { result_ = result; }
//action - invoked at the end of the dialog-processing loop
virtual void action(dialog_process_info &dp_info);
//refresh - forces the display to refresh
void refresh();
label& get_message() const { return *message_; }
virtual dialog_frame& get_frame(button *help_button=NULL);
display &disp_;
//process - execute a single dialog processing loop
//and return the result
virtual int process(dialog_process_info &info);
virtual void update_widget_positions();
private:
void draw_frame();
void draw_contents();
//Members
dialog_image *image_;
const std::string title_;
const struct style *style_;
label *title_widget_, *message_;
const DIALOG_TYPE type_;
gui::menu *menu_;
std::vector<preview_pane*> preview_panes_;
std::vector< std::pair<dialog_button*,BUTTON_LOCATION> > button_pool_;
std::vector<dialog_button*> standard_buttons_;
std::vector<dialog_button*> extra_buttons_;
std::vector<button*> frame_buttons_;
dialog_textbox *text_widget_;
dialog_frame *frame_;
surface_restorer *bg_restore_;
dimension_measurements dim_;
int result_;
};
typedef Uint32 msecs;
const msecs three_blinks = 300; // 3 times the 0.1sec human reflex-arc time
class message_dialog : public gui::basic_dialog
{
public:
message_dialog(display &disp, const std::string& title="", const std::string& message="", const gui::DIALOG_TYPE type=gui::MESSAGE)
: basic_dialog(disp, title, message, type, &message_style), prevent_misclick_until_(0)
{}
~message_dialog();
int show(msecs minimum_lifetime = three_blinks);
protected:
void action(gui::dialog_process_info &dp_info);
private:
msecs prevent_misclick_until_;
};
} //end namespace gui
#endif

View file

@ -14,14 +14,73 @@
#include "global.hpp"
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "construct_dialog.hpp"
#include "config.hpp"
#include "cursor.hpp"
#include "display.hpp"
#include "events.hpp"
#include "gettext.hpp"
#include "help.hpp"
#include "hotkeys.hpp"
#include "image.hpp"
#include "key.hpp"
#include "sound.hpp"
#include "log.hpp"
#include "marked-up_text.hpp"
#include "thread.hpp"
#include "language.hpp"
#include "sdl_utils.hpp"
#include "tooltips.hpp"
#include "util.hpp"
#include "video.hpp"
#include "widgets/button.hpp"
#include "widgets/menu.hpp"
#include "widgets/progressbar.hpp"
#include "widgets/textbox.hpp"
#include "wassert.hpp"
#include "sdl_ttf/SDL_ttf.h"
#include <iostream>
#include <numeric>
#define ERR_DP LOG_STREAM(err, display)
#define LOG_DP LOG_STREAM(info, display)
#define ERR_G LOG_STREAM(err, general)
namespace gui {
// This is where the connections between styles and the panel images
// in the data tree gets made.
const struct style dialog::default_style("opaque", 0);
const struct style dialog::message_style("translucent65", 3);
const struct style dialog::titlescreen_style("translucent54", 0);
const struct style dialog::hotkeys_style("menu2", 0);
//static initialization
const std::string dialog::no_help("");
const int dialog::message_font_size = font::SIZE_PLUS;
const int dialog::caption_font_size = font::SIZE_LARGE;
const size_t dialog::left_padding = font::relative_size(10);
const size_t dialog::right_padding = font::relative_size(10);
const size_t dialog::image_h_pad = font::relative_size(/*image_ == NULL ? 0 :*/ 10);
const size_t dialog::top_padding = font::relative_size(10);
const size_t dialog::bottom_padding = font::relative_size(10);
#ifdef USE_TINY_GUI
const int dialog::max_menu_width = 300;
#else
const int dialog::max_menu_width = -1;
#endif
}
namespace {
std::vector<std::string> empty_string_vector;
struct help_handler : public hotkey::command_executor
{
help_handler(display& disp, const std::string& topic) : disp_(disp), topic_(topic)
@ -48,38 +107,158 @@ private:
namespace gui {
dialog::dimension_measurements::dimension_measurements() :x(-1), y(-1), interior(empty_rect),
message(empty_rect), textbox(empty_rect), menu_height(-1)
{
//note: this is not defined in the header file to C++ ODR (one-definition rule)
//since each inclusion of the header file uses a different version of empty_rect
//(unnamed namespace and/or const object defined at declaration time).
}
dialog::dialog(display &disp, const std::string& title, const std::string& message,
const DIALOG_TYPE type, const struct style* dialog_style,
const std::string& help_topic) :
basic_dialog(disp, title, message, type, dialog_style),
help_button_(disp, help_topic)
const std::string& help_topic) : disp_(disp), image_(NULL),
title_(title), style_(dialog_style), title_widget_(NULL), message_(NULL),
type_(type), menu_(NULL),
help_button_(disp, help_topic), text_widget_(NULL),
frame_(NULL), bg_restore_(NULL), result_(CONTINUE_DIALOG)
{
CVideo& screen = disp_.video();
help_button_.set_parent(this);
}
switch(type)
{
case MESSAGE:
default:
break;
case OK_ONLY:
add_button(new standard_dialog_button(screen,_("OK"),0,true), BUTTON_STANDARD);
break;
case YES_NO:
add_button(new standard_dialog_button(screen,_("Yes"),0,false), BUTTON_STANDARD);
add_button(new standard_dialog_button(screen,_("No"),1,true), BUTTON_STANDARD);
break;
case OK_CANCEL:
add_button(new standard_dialog_button(screen,_("OK"),0,false), BUTTON_STANDARD);
add_button(new standard_dialog_button(screen,_("Cancel"),1,true), BUTTON_STANDARD);
break;
case CANCEL_ONLY:
add_button(new standard_dialog_button(screen,_("Cancel"),0,true), BUTTON_STANDARD);
break;
case CLOSE_ONLY:
add_button(new standard_dialog_button(screen,_("Close"),0,true), BUTTON_STANDARD);
break;
}
//dialog creator should catch(button::error&) ?
void dialog::update_widget_positions()
{
basic_dialog::update_widget_positions();
help_button_.join();
}
int dialog::process(dialog_process_info &info)
{
int res = basic_dialog::process(info);
if(res == CONTINUE_DIALOG && help_button_.pressed()) {
return help_button_.action(info);
try {
std::string msg = font::word_wrap_text(message, message_font_size, screen.getx() / 2, screen.gety() / 2);
message_ = new label(screen, msg, message_font_size, font::NORMAL_COLOUR, false);
} catch(utils::invalid_utf8_exception&) {
ERR_DP << "Problem handling utf8 in message '" << message << "'\n";
throw;
}
return res;
}
int dialog::show()
dialog::~dialog()
{
help_handler helper(disp_,help_button_.topic());
hotkey::basic_handler help_dispatcher(&disp_,&helper);
if(menu_ != empty_menu)
{
delete menu_;
}
delete title_widget_;
delete message_;
delete text_widget_;
delete image_;
delete frame_;
return basic_dialog::show();
button_pool_iterator b;
for (b = button_pool_.begin(); b != button_pool_.end(); ++b) {
delete b->first;
}
// pp_iterator p;
// for (p = preview_panes_.begin(); p != preview_panes_.end(); ++p) {
// delete (*p);
// }
delete bg_restore_;
}
const bool dialog::option_checked(unsigned int option_index)
{
unsigned int i = 0;
button_pool_iterator b;
for (b = button_pool_.begin(); b != button_pool_.end(); ++b) {
if(b->first->is_option()) {
if(option_index == i++) {
return b->first->checked();
}
}
}
return false;
}
void dialog::add_button(dialog_button *const btn, BUTTON_LOCATION loc)
{
std::pair<dialog_button *, BUTTON_LOCATION> new_pair(btn,loc);
button_pool_.push_back(new_pair);
switch(loc)
{
case BUTTON_EXTRA:
case BUTTON_EXTRA_LEFT:
case BUTTON_CHECKBOX:
case BUTTON_CHECKBOX_LEFT:
extra_buttons_.push_back(btn);
btn->set_parent(this);
break;
case BUTTON_STANDARD:
standard_buttons_.push_back(btn);
default:
btn->set_parent(this);
break;
}
}
void dialog::add_button(dialog_button_info btn_info, BUTTON_LOCATION loc)
{
dialog_button *btn = new dialog_button(disp_.video(), btn_info.label, button::TYPE_PRESS, CONTINUE_DIALOG, btn_info.handler);
add_button(btn, loc);
}
void dialog::add_option(const std::string& label, bool checked, BUTTON_LOCATION loc)
{
gui::dialog_button *btn = new dialog_button(disp_.video(), label, button::TYPE_CHECK);
btn->set_check(checked);
add_button(btn, loc);
}
void dialog::set_textbox(const std::string& text_widget_label,
const std::string& text_widget_text,
const int text_widget_max_chars, const unsigned int text_box_width)
{
label *label_ptr = new label(disp_.video(), text_widget_label, message_font_size, font::NORMAL_COLOUR, false);
const bool editable_textbox = std::find(text_widget_text.begin(),text_widget_text.end(),'\n') == text_widget_text.end();
text_widget_ = new dialog_textbox(label_ptr, disp_.video(), text_box_width, text_widget_text, editable_textbox, text_widget_max_chars);
text_widget_->set_wrap(!editable_textbox);
}
void dialog::set_menu(const std::vector<std::string> &menu_items)
{
set_menu(new gui::menu(disp_.video(), menu_items, (type_==MESSAGE),
-1, dialog::max_menu_width, NULL, &menu::default_style, false));
}
menu& dialog::get_menu()
{
if(menu_ == NULL)
{
if(empty_menu == NULL) {
empty_menu = new gui::menu(disp_.video(),empty_string_vector,false,-1,-1,NULL,&menu::simple_style);
empty_menu->leave();
}
menu_ = empty_menu; //no menu, so fake it
}
return *menu_;
}
int dialog::show(int xloc, int yloc)
@ -88,11 +267,546 @@ int dialog::show(int xloc, int yloc)
return show();
}
int dialog::show()
{
if(disp_.video().update_locked()) {
ERR_DP << "display locked ignoring dialog '" << title_ << "' '" << message_->get_text() << "'\n";
return CLOSE_DIALOG;
}
LOG_DP << "showing dialog '" << title_ << "' '" << message_->get_text() << "'\n";
if(dim_.interior == empty_rect) { layout(); }
//create the event context, remember to instruct any passed-in widgets to join it
const events::event_context dialog_events_context;
const dialog_manager manager;
const events::resize_lock prevent_resizing;
help_handler helper(disp_,help_button_.topic());
hotkey::basic_handler help_dispatcher(&disp_,&helper);
//draw
draw_frame();
update_widget_positions();
draw_contents();
//process
dialog_process_info dp_info;
do
{
events::pump();
set_result(process(dp_info));
if(!done()) {
refresh();
}
action(dp_info);
dp_info.cycle();
} while(!done());
return result();
}
void dialog::draw_contents()
{
if(!preview_panes_.empty()) {
for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
preview_pane *pane = *i;
if(!pane->handler_members().empty())
{
pane->draw();
pane->needs_restore_ = false; //prevent panes from drawing over members
}
}
}
events::raise_draw_event(); //draw widgets
disp_.flip();
disp_.invalidate_all();
}
dialog_frame& dialog::get_frame()
{
return basic_dialog::get_frame(help_button_.topic().empty() ? NULL : &help_button_);
if(frame_ == NULL) {
CVideo& screen = disp_.video();
frame_buttons_.clear();
for(button_iterator b = standard_buttons_.begin(); b != standard_buttons_.end(); ++b)
{
frame_buttons_.push_back(*b);
}
delete bg_restore_;
bg_restore_ = new surface_restorer;
frame_ = new dialog_frame(screen, title_, style_, &frame_buttons_, bg_restore_,
help_button_.topic().empty() ? NULL : &help_button_);
}
return *frame_;
}
void dialog::draw_frame()
{
get_frame().draw();
}
void dialog::update_widget_positions()
{
if(!preview_panes_.empty()) {
for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
preview_pane *pane = *i;
pane->join();
pane->set_location(dim_.panes.find(pane)->second);
}
}
if(text_widget_) {
text_widget_->join();
text_widget_->set_location(dim_.textbox);
if(text_widget_->get_label()) {
text_widget_->get_label()->set_location(dim_.label_x, dim_.label_y);
}
}
if(get_menu().height() > 0) {
menu_->join();
menu_->set_numeric_keypress_selection(text_widget_ == NULL);
menu_->set_width( dim_.menu_width );
menu_->set_max_width( dim_.menu_width ); //lock the menu width
if(dim_.menu_height >= 0) {
menu_->set_max_height( dim_.menu_height );
}
menu_->set_location( dim_.menu_x, dim_.menu_y );
}
if(image_) {
image_->join();
image_->set_location(dim_.image_x, dim_.image_y);
if(image_->caption()) {
image_->caption()->set_location(dim_.caption_x, dim_.caption_y);
}
}
button_iterator b;
for(b = extra_buttons_.begin(); b != extra_buttons_.end(); ++b) {
dialog_button *btn = *b;
btn->join();
std::pair<int,int> coords = dim_.buttons.find(btn)->second;
btn->set_location(coords.first, coords.second);
}
for(b = standard_buttons_.begin(); b != standard_buttons_.end(); ++b) {
dialog_button *btn = *b;
btn->join();
}
help_button_.join();
message_->set_location(dim_.message);
message_->join();
}
void dialog::refresh()
{
disp_.flip();
disp_.delay(10);
}
dialog::dimension_measurements dialog::layout(int xloc, int yloc)
{
CVideo& screen = disp_.video();
surface const scr = screen.getSurface();
dimension_measurements dim;
dim.x = xloc;
dim.y = yloc;
const bool use_textbox = (text_widget_ != NULL);
int text_widget_width = 0;
int text_widget_height = 0;
if(use_textbox) {
const SDL_Rect& area = font::text_area(text_widget_->text(),message_font_size);
dim.textbox.w = minimum<size_t>(screen.getx()/2,maximum<size_t>(area.w,text_widget_->width()));
dim.textbox.h = minimum<size_t>(screen.gety()/2,maximum<size_t>(area.h,text_widget_->height()));
text_widget_width = dim.textbox.w;
text_widget_width += (text_widget_->get_label() == NULL) ? 0 : text_widget_->get_label()->width();
text_widget_height = dim.textbox.h + message_font_size;
}
const bool use_menu = (get_menu().height() > 0);
if(!message_->get_text().empty()) {
dim.message.w = message_->width();
dim.message.h = message_->height();
}
unsigned int caption_width = 0;
unsigned int caption_height = 0;
if (image_ != NULL && image_->caption() != NULL) {
caption_width = image_->caption()->width();
caption_height = image_->caption()->height();
}
int check_button_height = 0;
int left_check_button_height = 0;
const int button_height_padding = 5;
for(button_pool_const_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
dialog_button const *const btn = b->first;
switch(b->second)
{
case BUTTON_EXTRA:
case BUTTON_CHECKBOX:
check_button_height += btn->height() + button_height_padding;
break;
case BUTTON_EXTRA_LEFT:
case BUTTON_CHECKBOX_LEFT:
left_check_button_height += btn->height() + button_height_padding;
break;
case BUTTON_STANDARD:
default:
break;
}
}
check_button_height = maximum<int>(check_button_height, left_check_button_height);
size_t above_preview_pane_height = 0, above_left_preview_pane_width = 0, above_right_preview_pane_width = 0;
size_t preview_pane_height = 0, left_preview_pane_width = 0, right_preview_pane_width = 0;
if(!preview_panes_.empty()) {
for(pp_const_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
preview_pane const *const pane = *i;
const SDL_Rect& rect = pane->location();
if(pane->show_above() == false) {
preview_pane_height = maximum<size_t>(rect.h,preview_pane_height);
if(pane->left_side()) {
left_preview_pane_width += rect.w;
} else {
right_preview_pane_width += rect.w;
}
} else {
above_preview_pane_height = maximum<size_t>(rect.h,above_preview_pane_height);
if(pane->left_side()) {
above_left_preview_pane_width += rect.w;
} else {
above_right_preview_pane_width += rect.w;
}
}
}
}
const int menu_hpadding = font::relative_size((dim.message.h > 0 && use_menu) ? 10 : 0);
const size_t image_h_padding = (image_ == NULL)? 0 : image_h_pad;
const size_t padding_width = left_padding + right_padding + image_h_padding;
const size_t padding_height = top_padding + bottom_padding + menu_hpadding;
const size_t image_width = (image_ == NULL) ? 0 : image_->width();
const size_t image_height = (image_ == NULL) ? 0 : image_->height();
const size_t total_text_height = dim.message.h + caption_height;
size_t text_width = dim.message.w;
if(caption_width > text_width)
text_width = caption_width;
// Prevent the menu to be larger than the screen
dim.menu_width = menu_->width();
if(dim.menu_width + image_width + padding_width > size_t(scr->w))
dim.menu_width = scr->w - image_width - padding_width;
if(dim.menu_width > text_width)
text_width = dim.menu_width;
size_t total_width = image_width + text_width + padding_width;
if(text_widget_width+left_padding+right_padding > total_width)
total_width = text_widget_width+left_padding+right_padding;
//Prevent the menu from being too skinny
if(use_menu && preview_panes_.empty() &&
total_width > dim.menu_width + image_width + padding_width) {
dim.menu_width = total_width - image_width - padding_width;
}
const size_t text_and_image_height = image_height > total_text_height ? image_height : total_text_height;
int total_height = text_and_image_height + padding_height + menu_->height() +
text_widget_height + check_button_height;
dim.interior.w = maximum<int>(total_width,above_left_preview_pane_width + above_right_preview_pane_width);
dim.interior.h = maximum<int>(total_height,int(preview_pane_height));
dim.interior.x = maximum<int>(0,dim.x >= 0 ? dim.x : scr->w/2 - (dim.interior.w + left_preview_pane_width + right_preview_pane_width)/2);
dim.interior.y = maximum<int>(0,dim.y >= 0 ? dim.y : scr->h/2 - (dim.interior.h + above_preview_pane_height)/2);
LOG_DP << "above_preview_pane_height: " << above_preview_pane_height << "; "
<< "dim.interior.y: " << scr->h/2 << " - " << (dim.interior.h + above_preview_pane_height)/2 << " = "
<< dim.interior.y << "; " << "dim.interior.h: " << dim.interior.h << "\n";
if(dim.x <= -1 || dim.y <= -1) {
dim.x = dim.interior.x + left_preview_pane_width;
dim.y = dim.interior.y + above_preview_pane_height;
}
if(dim.x + dim.interior.w > scr->w) {
dim.x = scr->w - dim.interior.w;
if(dim.x < dim.interior.x) {
dim.interior.x = dim.x;
}
}
const int frame_top_pad = get_frame().top_padding();
const int frame_bottom_pad = get_frame().bottom_padding();
if(dim.y + dim.interior.h + frame_bottom_pad > scr->h) {
dim.y = maximum<int>(frame_top_pad, scr->h - dim.interior.h - frame_bottom_pad);
if(dim.y < dim.interior.y) {
dim.interior.y = dim.y;
}
}
dim.interior.w += left_preview_pane_width + right_preview_pane_width;
dim.interior.h += above_preview_pane_height;
const int max_height = scr->h - dim.interior.y - frame_bottom_pad;
if(dim.interior.h > max_height) {
//try to rein in the menu height a little bit
const int menu_height = menu_->height();
if(menu_height > 0) {
dim.menu_height = maximum<int>(1, max_height - dim.interior.h + menu_height);
dim.interior.h -= menu_height - dim.menu_height;
}
}
//calculate the positions of the preview panes to the sides of the dialog
if(!preview_panes_.empty()) {
int left_preview_pane = dim.interior.x;
int right_preview_pane = dim.interior.x + total_width + left_preview_pane_width;
int above_left_preview_pane = dim.interior.x + dim.interior.w/2;
int above_right_preview_pane = above_left_preview_pane;
for(pp_const_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
preview_pane const *const pane = *i;
SDL_Rect area = pane->location();
if(pane->show_above() == false) {
area.y = dim.y;
if(pane->left_side()) {
area.x = left_preview_pane;
left_preview_pane += area.w;
} else {
area.x = right_preview_pane;
right_preview_pane += area.w;
}
} else {
area.y = dim.interior.y;
if(pane->left_side()) {
area.x = above_left_preview_pane - area.w;
above_left_preview_pane -= area.w;
} else {
area.x = above_right_preview_pane;
above_right_preview_pane += area.w;
}
}
dim.panes[*i] = area;
}
}
const int text_widget_y = dim.y+top_padding+text_and_image_height-6+menu_hpadding;
if(use_textbox) {
dim.textbox.x = dim.x + left_padding + text_widget_width - dim.textbox.w;
dim.textbox.y = text_widget_y + (text_widget_height - dim.textbox.h)/2;
dim.label_x = dim.x+left_padding;
dim.label_y = dim.textbox.y;
}
dim.menu_x = dim.x+image_width+left_padding+image_h_padding;
dim.menu_y = dim.y+top_padding+text_and_image_height+menu_hpadding+ (use_textbox ? text_widget_->location().h + top_padding : 0);
dim.message.x = dim.x + left_padding;
dim.message.y = dim.y + top_padding + caption_height;
if(image_ != NULL) {
const int x = dim.x + left_padding;
const int y = dim.y + top_padding;
dim.message.x += image_width + image_h_padding;
dim.image_x = x;
dim.image_y = y;
dim.caption_x = dim.x + image_width + left_padding + image_h_padding;
dim.caption_y = dim.y + top_padding;
}
//set the position of any tick boxes. by default, they go right below the menu,
//slammed against the right side of the dialog
if(extra_buttons_.empty() == false) {
int options_y = text_widget_y + text_widget_height + menu_->height() + button_height_padding + menu_hpadding;
int options_left_y = options_y;
for(button_pool_const_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
dialog_button const *const btn = b->first;
std::pair<int,int> coords;
switch(b->second)
{
case BUTTON_EXTRA:
case BUTTON_CHECKBOX:
coords.first = dim.x + total_width - btn->width() - ButtonHPadding;
coords.second = options_y;
dim.buttons[b->first] = coords;
options_y += btn->height() + button_height_padding;
break;
case BUTTON_EXTRA_LEFT:
case BUTTON_CHECKBOX_LEFT:
coords.first = dim.x + ButtonHPadding;
coords.second = options_left_y;
dim.buttons[b->first] = coords;
options_left_y += btn->height() + button_height_padding;
break;
case BUTTON_STANDARD:
default:
break;
}
}
}
set_layout(dim);
return dim;
}
void dialog::set_layout(dimension_measurements &new_dim) {
get_frame().layout(new_dim.interior);
dim_ = new_dim;
}
int dialog::process(dialog_process_info &info)
{
int mousex, mousey;
int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
info.new_right_button = (mouse_flags&SDL_BUTTON_RMASK) != 0;
info.new_left_button = (mouse_flags&SDL_BUTTON_LMASK) != 0;
info.new_key_down = info.key[SDLK_SPACE] || info.key[SDLK_RETURN] ||
info.key[SDLK_ESCAPE] || info.key[SDLK_KP_ENTER];
info.double_clicked = menu_->double_clicked();
get_menu();
const bool use_menu = (menu_ != empty_menu);
if((!info.key_down && info.key[SDLK_RETURN] || info.key[SDLK_KP_ENTER] || info.double_clicked) &&
(type_ == YES_NO || type_ == OK_CANCEL || type_ == OK_ONLY || type_ == CLOSE_ONLY)) {
return (use_menu ? menu_->selection() : 0);
}
//escape quits from the dialog -- unless it's an "ok" dialog with a menu,
//since such dialogs require a selection of some kind.
if(!info.key_down && info.key[SDLK_ESCAPE] && !(type_ == OK_ONLY && use_menu)) {
return (CLOSE_DIALOG);
}
//inform preview panes when there is a new menu selection
if((menu_->selection() != info.selection) || info.first_time) {
info.selection = menu_->selection();
int selection = info.selection;
if(selection < 0) {
selection = 0;
}
if(!preview_panes_.empty()) {
for(pp_iterator i = preview_panes_.begin(); i != preview_panes_.end(); ++i) {
(**i).set_selection(selection);
if(info.first_time) {
(**i).set_dirty();
}
}
}
}
info.first_time = false;
if(use_menu) {
//get any drop-down choice or context-menu click
const int selection = menu_->process();
if(selection != -1)
{
return (selection);
}
}
events::raise_process_event();
events::raise_draw_event();
//left-clicking outside of a drop-down or context-menu should close it
if (info.new_left_button && !info.left_button) {
if (standard_buttons_.empty() && !point_in_rect(mousex,mousey, menu_->location())) {
if (use_menu)
sound::play_UI_sound(game_config::sounds::button_press);
return CLOSE_DIALOG;
}
}
//right-clicking outside of a dialog should close it unless a choice is required
//note: this will also close any context-menu or drop-down when it is right-clicked
// but that may be changed to allow right-click selection instead.
if (info.new_right_button && !info.right_button) {
if( standard_buttons_.empty()
|| (!point_in_rect(mousex,mousey,get_frame().get_layout().exterior)
&& type_ != YES_NO && !(type_ == OK_ONLY && use_menu))) {
sound::play_UI_sound(game_config::sounds::button_press);
return CLOSE_DIALOG;
}
}
//any keypress should close a dialog if it has one standard button (or less)
//and no menu options.
if (info.new_key_down && !info.key_down) {
if (standard_buttons_.size() < 2 && !use_menu)
return CLOSE_DIALOG;
}
//now handle any button presses
for(button_pool_iterator b = button_pool_.begin(); b != button_pool_.end(); ++b) {
if(b->first->pressed()) {
return b->first->action(info);
}
}
if(help_button_.pressed()) {
return help_button_.action(info);
}
return CONTINUE_DIALOG;
}
int dialog_button::action(dialog_process_info &info) {
if(handler_ != NULL) {
menu &menu_ref = parent_->get_menu();
dialog_button_action::RESULT res = handler_->button_pressed(menu_ref.selection());
if(res == DELETE_ITEM || res == CLOSE_DIALOG) {
return res;
}
//reset button-tracking flags so that if the action displays a dialog, a button-press
//at the end of the dialog won't be mistaken for a button-press in this dialog.
//(We should eventually use a proper event-handling system instead of tracking
//flags to avoid problems like this altogether).
info.clear_buttons();
return CONTINUE_DIALOG;
}
return simple_result_;
}
void dialog::action(dialog_process_info& info)
{
//default way of handling a "delete item" request
if(result() == DELETE_ITEM) {
menu &menu_ref = get_menu();
menu_ref.erase_item(menu_ref.selection());
if(menu_ref.nitems() == 0) {
set_result(CLOSE_DIALOG);
} else {
set_result(CONTINUE_DIALOG);
info.first_time = true;
}
}
}
int standard_dialog_button::action(dialog_process_info &/*info*/) {
//if the menu is not used, then return the index of the
//button pressed, otherwise return the index of the menu
//item selected if the last button is not pressed, and
//cancel (-1) otherwise
if(dialog()->get_menu().height() <= 0) {
return simple_result_;
} else if((simple_result_ == 0 && is_last_) || !is_last_) {
return (dialog()->get_menu().selection());
}
return CLOSE_DIALOG;
}
dialog::help_button::help_button(display& disp, const std::string &help_topic)
: dialog_button(disp.video(), _("Help")), disp_(disp), topic_(help_topic)
{}
@ -104,5 +818,37 @@ int dialog::help_button::action(dialog_process_info &info) {
}
return CONTINUE_DIALOG;
}
void dialog::set_image(surface surf, const std::string &caption)
{
label *label_ptr = NULL;
if(!caption.empty()) {
label_ptr = new label(disp_.video(), caption, caption_font_size, font::NORMAL_COLOUR, false);
}
set_image( new dialog_image(label_ptr, disp_.video(), surf ));
}
void dialog_image::draw_contents()
{
video().blit_surface(location().x, location().y, surf_);
}
int message_dialog::show(msecs minimum_lifetime)
{
prevent_misclick_until_ = SDL_GetTicks() + minimum_lifetime;
return dialog::show();
}
void message_dialog::action(gui::dialog_process_info &dp_info)
{
dialog::action(dp_info);
if(done() && SDL_GetTicks() < prevent_misclick_until_ && result() != gui::ESCAPE_DIALOG) {
//discard premature results
set_result(gui::CONTINUE_DIALOG);
}
}
message_dialog::~message_dialog()
{
}
}//end namespace gui

View file

@ -15,18 +15,240 @@
#ifndef CONSTRUCT_DIALOG_H_INCLUDED
#define CONSTRUCT_DIALOG_H_INCLUDED
#include "basic_dialog.hpp"
#include "show_dialog.hpp"
#include "widgets/label.hpp"
#include "widgets/textbox.hpp"
#include "widgets/button.hpp"
#include "widgets/menu.hpp"
#include "key.hpp"
#include "sdl_utils.hpp"
namespace gui {
class dialog : public gui::basic_dialog
struct style {
style(std::string const& p, int br) : panel(p), blur_radius(br) {}
std::string panel;
int blur_radius;
};
struct dialog_process_info
{
public:
dialog(display &disp, const std::string& title="",
const std::string& message="",
const DIALOG_TYPE type=MESSAGE,
const struct style *dialog_style=&default_style,
const std::string& help_topic="");
dialog_process_info() : left_button(true), right_button(true), key_down(true),
first_time(true), double_clicked(false), selection(-1), clear_buttons_(false)
{}
void clear_buttons() {
clear_buttons_ = true;
}
void cycle() {
if(clear_buttons_) {
left_button = true;
right_button = true;
key_down = true;
clear_buttons_ = false;
} else {
left_button = new_left_button;
right_button = new_right_button;
key_down = new_key_down;
}
}
CKey key;
bool left_button, right_button, key_down, first_time, double_clicked;
bool new_left_button, new_right_button, new_key_down;
int selection;
private:
bool clear_buttons_;
};
class dialog_image : public widget {
public:
dialog_image(label *const caption, CVideo &video, surface img) : widget(video, false),
surf_(img), caption_(caption)
{
if(!img.null()) {
set_measurements(img->w, img->h);
}
}
~dialog_image() { delete caption_; }
//surface surface() const { return surf_; }
label *caption() const { return caption_; }
void draw_contents();
handler_vector handler_members() {
handler_vector h;
if(caption_) h.push_back(caption_);
return h;
}
private:
surface surf_;
label *caption_;
};
class dialog_textbox : public textbox {
public:
dialog_textbox(label *const label_widget, CVideo &video, int width, const std::string& text="", bool editable=true, size_t max_size = 256, double alpha = 0.4, double alpha_focus = 0.2)
: textbox(video, width, text, editable, max_size, alpha, alpha_focus, false),
label_(label_widget)
{}
~dialog_textbox() { delete label_; }
label *get_label() const { return label_; }
handler_vector handler_members() {
handler_vector h = textbox::handler_members();
if(label_) h.push_back(label_);
return h;
}
private:
label *label_;
};
class dialog_button : public button {
public:
dialog_button(CVideo& video, const std::string& label, TYPE type=TYPE_PRESS,
int simple_result=CONTINUE_DIALOG, dialog_button_action *handler=NULL)
: button(video,label,type,"",DEFAULT_SPACE,false), simple_result_(simple_result),
parent_(NULL), handler_(handler)
{}
void set_parent(class dialog *parent) {
parent_ = parent;
}
bool is_option() const {
return (type_ == TYPE_CHECK);
}
virtual int action(dialog_process_info &info);
protected:
class dialog *dialog() const { return parent_; }
const int simple_result_;
private:
class dialog *parent_;
dialog_button_action *handler_;
};
class standard_dialog_button : public dialog_button {
public:
standard_dialog_button(CVideo& video, const std::string& label, const int index, const bool is_last)
: dialog_button(video,label,TYPE_PRESS,index), is_last_(is_last)
{}
int action(dialog_process_info &info);
private:
const bool is_last_;
};
class dialog {
public:
enum BUTTON_LOCATION { BUTTON_STANDARD, BUTTON_EXTRA, BUTTON_EXTRA_LEFT, BUTTON_CHECKBOX, BUTTON_CHECKBOX_LEFT };
struct dimension_measurements {
dimension_measurements();
int x, y;
SDL_Rect interior, message, textbox;
unsigned int menu_width;
std::map<preview_pane *const, SDL_Rect > panes;
int label_x, label_y;
int menu_x, menu_y, menu_height;
int image_x, image_y, caption_x, caption_y;
std::map<dialog_button *const, std::pair<int,int> > buttons;
//use get_frame().get_layout() to check frame dimensions
};
private:
typedef std::vector<preview_pane *>::iterator pp_iterator;
typedef std::vector<preview_pane *>::const_iterator pp_const_iterator;
typedef std::vector<dialog_button *>::iterator button_iterator;
typedef std::vector<dialog_button *>::const_iterator button_const_iterator;
typedef std::vector< std::pair<dialog_button *, BUTTON_LOCATION> >::iterator button_pool_iterator;
typedef std::vector< std::pair<dialog_button *, BUTTON_LOCATION> >::const_iterator button_pool_const_iterator;
public:
//Static members
static const struct style default_style;
static const struct style message_style;
static const struct style titlescreen_style;
static const struct style hotkeys_style;
static const std::string no_help;
static const int message_font_size;
static const int caption_font_size;
static const int max_menu_width;
static const size_t left_padding;
static const size_t right_padding;
static const size_t image_h_pad;
static const size_t top_padding;
static const size_t bottom_padding;
//Constructor & destructor
//dialog - throws button::error() if standard buttons fail to initialize
// throws utils::invalid_utf8_exception() if message is invalid
dialog(display &disp, const std::string& title="", const std::string& message="",
const DIALOG_TYPE type=MESSAGE,
const struct style *dialog_style=&default_style,
const std::string& help_topic=no_help);
virtual ~dialog();
//Adding components - the dialog will manage the memory of these widgets,
//therefore do not attempt to reference its widgets after destroying it
void set_image(dialog_image *const img) { delete image_; image_ = img; }
void set_image(surface surf, const std::string &caption="");
void set_menu(menu *const m) { if(menu_ != empty_menu) delete menu_; menu_ = m; }
void set_menu(const std::vector<std::string> & menu_items);
//add_pane - preview panes are not currently memory managed (for backwards compat)
void add_pane(preview_pane *const pp) { preview_panes_.push_back(pp); }
void set_panes(std::vector<preview_pane*> panes) { preview_panes_ = panes; }
void set_textbox(dialog_textbox *const box) {
delete text_widget_;
text_widget_ = box;
}
void set_textbox(const std::string& text_widget_label="",
const std::string &text_widget_text="",
const int text_widget_max_chars = 256,
const unsigned int text_box_width = font::relative_size(350));
void add_button(dialog_button *const btn, BUTTON_LOCATION loc);
void add_button(dialog_button_info btn_info, BUTTON_LOCATION loc=BUTTON_EXTRA);
void add_option(const std::string& label, bool checked=false, BUTTON_LOCATION loc=BUTTON_CHECKBOX);
//Specific preparations
//layout - determines dialog measurements based on all components
virtual dimension_measurements layout(int xloc=-1, int yloc=-1);
void set_layout(dimension_measurements &new_dim);
dimension_measurements get_layout() const { return dim_; }
//Launching the dialog
//show - the return value of this method should be the same as result()
int show(int xloc, int yloc);
int show();
//Results
int result() const { return result_; }
menu &get_menu();
bool done() const { return (result_ != CONTINUE_DIALOG); }
const std::string textbox_text() const { return text_widget_->text();}
dialog_textbox& get_textbox() const { return *text_widget_; }
const bool option_checked(unsigned int option_index=0);
display& get_display() { return disp_; }
protected:
void set_result(const int result) { result_ = result; }
//action - invoked at the end of the dialog-processing loop
virtual void action(dialog_process_info &dp_info);
//refresh - forces the display to refresh
void refresh();
label& get_message() const { return *message_; }
dialog_frame& get_frame();
private:
void draw_frame();
void update_widget_positions();
void draw_contents();
//process - execute a single dialog processing loop and return the result
int process(dialog_process_info &info);
class help_button : public dialog_button {
public:
@ -38,15 +260,43 @@ public:
const std::string topic_;
};
int process(dialog_process_info &info);
void update_widget_positions();
dialog_frame& get_frame();
int show();
int show(int xloc, int yloc);
//Members
display &disp_;
dialog_image *image_;
const std::string title_;
const struct style *style_;
label *title_widget_, *message_;
const DIALOG_TYPE type_;
gui::menu *menu_;
std::vector<preview_pane*> preview_panes_;
std::vector< std::pair<dialog_button*,BUTTON_LOCATION> > button_pool_;
std::vector<dialog_button*> standard_buttons_;
std::vector<dialog_button*> extra_buttons_;
std::vector<button*> frame_buttons_;
help_button help_button_;
dialog_textbox *text_widget_;
dialog_frame *frame_;
surface_restorer *bg_restore_;
dimension_measurements dim_;
int result_;
};
typedef Uint32 msecs;
const msecs three_blinks = 300; // 3 times the 0.1sec human reflex-arc time
class message_dialog : public gui::dialog
{
public:
message_dialog(display &disp, const std::string& title="", const std::string& message="", const gui::DIALOG_TYPE type=gui::MESSAGE)
: dialog(disp, title, message, type, &message_style), prevent_misclick_until_(0)
{}
~message_dialog();
int show(msecs minimum_lifetime = three_blinks);
protected:
void action(gui::dialog_process_info &dp_info);
private:
msecs prevent_misclick_until_;
};
} //end namespace gui
#endif

View file

@ -98,7 +98,7 @@ void advance_unit(const game_data& info,
std::vector<gui::preview_pane*> preview_panes;
preview_panes.push_back(&unit_preview);
gui::basic_dialog advances = gui::basic_dialog(gui,
gui::dialog advances = gui::dialog(gui,
_("Advance Unit"),
_("What should our victorious unit become?"),
gui::OK_ONLY);
@ -217,7 +217,7 @@ int get_save_name(display & disp,const std::string& message, const std::string&
int overwrite=0;
int res=0;
do {
gui::basic_dialog d(disp, tmp_title, message, dialog_type);
gui::dialog d(disp, tmp_title, message, dialog_type);
d.set_textbox(txt_label, *fname);
if(has_exit_button) {
d.add_button( new gui::dialog_button(disp.video(), _("Quit Game"),
@ -242,7 +242,7 @@ int get_save_name(display & disp,const std::string& message, const std::string&
}
*fname = d.textbox_text();
if (res == 0 && save_game_exists(*fname)) {
overwrite = gui::basic_dialog(disp,_("Overwrite?"),
overwrite = gui::dialog(disp,_("Overwrite?"),
_("Save already exists. Do you want to overwrite it ?"),gui::YES_NO).show();
} else {
overwrite = 0;
@ -276,7 +276,7 @@ gui::dialog_button_action::RESULT delete_save::button_pressed(int menu_selection
//see if we should ask the user for deletion confirmation
if(preferences::ask_delete_saves()) {
gui::basic_dialog dmenu(disp_,"",
gui::dialog dmenu(disp_,"",
_("Do you really want to delete this game?"),
gui::YES_NO);
dmenu.add_option(_("Don't ask me again!"), true);
@ -531,7 +531,7 @@ std::string load_game_dialog(display& disp, const config& game_config, const gam
std::vector<save_info> games = get_saves_list();
if(games.empty()) {
gui::basic_dialog(disp,
gui::dialog(disp,
_("No Saved Games"),
_("There are no saved games to load.\n\n(Games are saved automatically when you complete a scenario)"),
gui::OK_ONLY).show();

View file

@ -15,7 +15,7 @@
#include "SDL_keysym.h"
#include "../config.hpp"
#include "../basic_dialog.hpp"
#include "../construct_dialog.hpp"
#include "../cursor.hpp"
#include "../file_chooser.hpp"
#include "../filesystem.hpp"
@ -460,7 +460,7 @@ void map_editor::change_language() {
const std::string language = _("Language");
const std::string preferred = _("Choose your preferred language:");
gui::basic_dialog lmenu = gui::basic_dialog(gui_, language, preferred,
gui::dialog lmenu = gui::dialog(gui_, language, preferred,
gui::OK_CANCEL);
lmenu.set_menu(langs);
int res = lmenu.show();
@ -510,7 +510,7 @@ void map_editor::edit_save_as() {
continue;
}
else if (file_exists(input_name)) {
overwrite = gui::basic_dialog(gui_, "",
overwrite = gui::dialog(gui_, "",
_("The map already exists. Do you want to overwrite it?"),
gui::YES_NO).show();
}
@ -542,7 +542,7 @@ void map_editor::perform_set_starting_pos() {
str << _("Player") << " " << i + 1;
players.push_back(str.str());
}
gui::basic_dialog pmenu = gui::basic_dialog(gui_,
gui::dialog pmenu = gui::dialog(gui_,
_("Which Player?"),
_("Which player should start here?"),
gui::OK_CANCEL);
@ -1255,11 +1255,11 @@ void map_editor::middle_button_down(const int mousex, const int mousey) {
bool map_editor::confirm_exit_and_save() {
if (!changed_since_save())
return true;
if (gui::basic_dialog(gui_, "",
if (gui::dialog(gui_, "",
_("Quit Editor"), gui::YES_NO).show() != 0) {
return false;
}
if (gui::basic_dialog(gui_, "",
if (gui::dialog(gui_, "",
_("Do you want to save the map before quitting?"), gui::YES_NO).show() == 0) {
if (!save_map("", false)) {
return false;
@ -1346,8 +1346,8 @@ void map_editor::show_menu(const std::vector<std::string>& items, const int xloc
return;
}
static const std::string style = "menu2";
gui::basic_dialog kmenu = gui::basic_dialog(gui_, "", "", gui::MESSAGE,
&gui::basic_dialog::hotkeys_style);
gui::dialog kmenu = gui::dialog(gui_, "", "", gui::MESSAGE,
&gui::dialog::hotkeys_style);
kmenu.set_menu(get_menu_images(items));
const int res = kmenu.show(xloc, yloc);
if(res < 0 || (unsigned)res >= items.size())

View file

@ -27,7 +27,6 @@
#include "../map_create.hpp"
#include "../marked-up_text.hpp"
#include "../construct_dialog.hpp"
#include "../basic_dialog.hpp"
#include "../util.hpp"
#include "../preferences_display.hpp"
#include "../video.hpp"
@ -46,7 +45,7 @@ namespace {
namespace map_editor {
bool confirm_modification_disposal(display& disp) {
const int res = gui::basic_dialog(disp, "",
const int res = gui::dialog(disp, "",
_("Your modifications to the map will be lost. Continue?"),
gui::OK_CANCEL).show();
return res == 0;
@ -497,7 +496,7 @@ FLIP_AXIS flip_dialog(display &disp) {
items.push_back(_("X-Axis"));
items.push_back(_("Y-Axis"));
const std::string msg = _("Flip around (this may change the dimensions of the map):");
gui::basic_dialog flipmenu = gui::basic_dialog(disp, "",
gui::dialog flipmenu = gui::dialog(disp, "",
font::word_wrap_text(msg, 12, 180),
gui::OK_CANCEL);
flipmenu.set_menu(items);

View file

@ -16,7 +16,7 @@
class config;
class display;
#include "basic_dialog.hpp"
#include "construct_dialog.hpp"
namespace gui
{
@ -26,11 +26,11 @@ namespace gui
namespace dialogs
{
class file_dialog : public gui::basic_dialog {
class file_dialog : public gui::dialog {
public:
file_dialog(display &disp, const std::string& file_path, const std::string& title);
virtual gui::basic_dialog::dimension_measurements layout(int xloc=-1, int yloc=-1);
virtual gui::dialog::dimension_measurements layout(int xloc=-1, int yloc=-1);
/// Return the chosen file.
std::string get_choice() const { return chosen_file_; }

View file

@ -39,7 +39,7 @@ int show_file_chooser_dialog(display &disp, std::string &filename,
}
file_dialog::file_dialog(display &disp, const std::string& file_path, const std::string& title)
: gui::basic_dialog(disp, title, file_path, gui::OK_CANCEL), files_list_(NULL), last_selection_(0)
: gui::dialog(disp, title, file_path, gui::OK_CANCEL), files_list_(NULL), last_selection_(0)
{
files_list_ = new gui::file_menu(disp.video(), file_path);
const unsigned file_list_height = (disp.h() / 2);
@ -50,14 +50,14 @@ file_dialog::file_dialog(display &disp, const std::string& file_path, const std:
get_message().set_text(format_dirname(files_list_->get_directory()));
set_textbox(_("File: "), format_filename(file_path), 100);
add_button( new gui::dialog_button(disp.video(), _("Delete File"),
gui::button::TYPE_PRESS, gui::DELETE_ITEM), basic_dialog::BUTTON_EXTRA);
gui::button::TYPE_PRESS, gui::DELETE_ITEM), dialog::BUTTON_EXTRA);
add_button( new gui::dialog_button(disp.video(), _("New Folder"),
gui::button::TYPE_PRESS, gui::CREATE_ITEM), basic_dialog::BUTTON_EXTRA_LEFT);
gui::button::TYPE_PRESS, gui::CREATE_ITEM), dialog::BUTTON_EXTRA_LEFT);
}
gui::dialog::dimension_measurements file_dialog::layout(int xloc, int yloc)
{
gui::dialog::dimension_measurements dim = basic_dialog::layout(xloc, yloc);
gui::dialog::dimension_measurements dim = dialog::layout(xloc, yloc);
//shift the menu up
unsigned y_shift = dim.menu_y - minimum<int>(dim.label_y, dim.textbox.y);
@ -165,7 +165,7 @@ void file_dialog::action(gui::dialog_process_info &dp_info) {
//handle "create item" requests
else if(result() == gui::CREATE_ITEM)
{
gui::basic_dialog d(get_display(), _("New Folder"), "", gui::OK_CANCEL);
gui::dialog d(get_display(), _("New Folder"), "", gui::OK_CANCEL);
d.set_textbox(_("Name: "));
d.show();
if(d.result() != gui::CLOSE_DIALOG && !d.textbox_text().empty())

View file

@ -698,7 +698,7 @@ bool game_controller::load_game()
return false;
}
const int res = gui::basic_dialog(disp(),"",
const int res = gui::dialog(disp(),"",
_("This save is from a different version of the game. Do you want to try to load it?"),
gui::YES_NO).show();
if(res == 1) {
@ -804,7 +804,7 @@ bool game_controller::new_campaign()
return false;
}
gui::basic_dialog cmenu(disp(),_("Campaign"),
gui::dialog cmenu(disp(),_("Campaign"),
_("Choose the campaign you want to play:"),
gui::OK_CANCEL);
cmenu.set_menu(campaign_names);
@ -830,7 +830,7 @@ bool game_controller::new_campaign()
std::copy(difficulties.begin(),difficulties.end(),difficulty_options.begin());
}
gui::basic_dialog dlg(disp(), _("Difficulty"),
gui::dialog dlg(disp(), _("Difficulty"),
_("Select difficulty level:"), gui::OK_CANCEL);
dlg.set_menu(difficulty_options);
if(dlg.show() == -1) {
@ -893,7 +893,7 @@ namespace
{
int res;
gui::basic_dialog d(disp(),
gui::dialog d(disp(),
_("Connect to Server"),
_("You will now connect to a server to download add-ons."),
gui::OK_CANCEL);
@ -945,7 +945,7 @@ namespace
do
{
gui::basic_dialog addon_dialog(disp(),
gui::dialog addon_dialog(disp(),
_("Remove Add-ons"), _("Choose the add-on to remove."),
gui::OK_CANCEL);
gui::menu::imgsel_style &addon_style = gui::menu::bluebg_style;
@ -961,7 +961,7 @@ namespace
"Are you sure you want to remove the add-on \'"
+ addons.at(index)
+ "?\'";
res = gui::basic_dialog(
res = gui::dialog(
disp(),
_("Confirm"),
confirm_message,
@ -995,14 +995,14 @@ namespace
std::string success_message = "Add-on \'" + addons.at(index) + "\' deleted.";
/* GCC-3.3 needs a temp var otherwise compilation fails */
gui::basic_dialog dlg(disp(), _("Add-on deleted"), success_message,
gui::dialog dlg(disp(), _("Add-on deleted"), success_message,
gui::OK_ONLY);
dlg.show();
}
else
{
/* GCC-3.3 needs a temp var otherwise compilation fails */
gui::basic_dialog dlg2(disp(), _("Error"), _("Add-on could not be deleted -- a file was not found."),
gui::dialog dlg2(disp(), _("Error"), _("Add-on could not be deleted -- a file was not found."),
gui::OK_ONLY);
dlg2.show();
}
@ -1133,7 +1133,7 @@ void game_controller::download_campaigns(std::string host)
gui::menu::basic_sorter sorter;
sorter.set_alpha_sort(1).set_alpha_sort(2).set_alpha_sort(3).set_numeric_sort(4).set_position_sort(5,sizes);
gui::basic_dialog addon_dialog(disp(), _("Get Add-ons"),
gui::dialog addon_dialog(disp(), _("Get Add-ons"),
_("Choose the add-on to download."),
gui::OK_CANCEL);
gui::menu::imgsel_style addon_style(gui::menu::bluebg_style);
@ -1176,7 +1176,7 @@ void game_controller::download_campaigns(std::string host)
// TODO: Somehow offer to automatically download
// the missing dependencies.
if (!missing.empty()) {
if (gui::basic_dialog(disp(),
if (gui::dialog(disp(),
_("Dependencies"),
std::string(_("This add-on requires the following additional dependencies:")) +
"\n" + missing +
@ -1273,7 +1273,7 @@ void game_controller::upload_campaign(const std::string& campaign, network::conn
(*data.child("error"))["message"].str() + '"');
return;
} else if(data.child("message")) {
const int res = gui::basic_dialog(disp(),_("Terms"),(*data.child("message"))["message"],gui::OK_CANCEL).show();
const int res = gui::dialog(disp(),_("Terms"),(*data.child("message"))["message"],gui::OK_CANCEL).show();
if(res != 0) {
return;
}
@ -1377,7 +1377,7 @@ bool game_controller::play_multiplayer()
int res;
{
gui::basic_dialog d(disp(), _("Multiplayer"), "", gui::OK_CANCEL);
gui::dialog d(disp(), _("Multiplayer"), "", gui::OK_CANCEL);
d.set_menu(host_or_join);
d.set_textbox(_("Login: "), login, 18, font::relative_size(250));
res = d.show();
@ -1423,14 +1423,14 @@ bool game_controller::play_multiplayer()
std::cerr << "caught network error...\n";
if(e.message != "") {
/* GCC-3.3 needs a temp var otherwise compilation fails */
gui::basic_dialog dlg(disp(),"",e.message,gui::OK_ONLY);
gui::dialog dlg(disp(),"",e.message,gui::OK_ONLY);
dlg.show();
}
} catch(config::error& e) {
std::cerr << "caught config::error...\n";
if(e.message != "") {
/* GCC-3.3 needs a temp var otherwise compilation fails */
gui::basic_dialog dlg2(disp(),"",e.message,gui::OK_ONLY);
gui::dialog dlg2(disp(),"",e.message,gui::OK_ONLY);
dlg2.show();
}
} catch(gamemap::incorrect_format_exception& e) {
@ -1458,7 +1458,7 @@ bool game_controller::change_language()
}
}
gui::basic_dialog lmenu(disp(),_("Language"),
gui::dialog lmenu(disp(),_("Language"),
_("Choose your preferred language:"),
gui::OK_CANCEL);
lmenu.set_menu(langs);

View file

@ -16,7 +16,7 @@
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "config.hpp"
#include "basic_dialog.hpp"
#include "construct_dialog.hpp"
#include "display.hpp"
#include "events.hpp"
#include "hotkeys.hpp"
@ -482,7 +482,7 @@ void key_event(display& disp, const SDL_KeyboardEvent& event, command_executor*
{
if(event.keysym.sym == SDLK_ESCAPE && disp.in_game()) {
std::cerr << "escape pressed..showing quit\n";
const int res = gui::basic_dialog(disp,_("Quit"),_("Do you really want to quit?"),gui::YES_NO).show();
const int res = gui::dialog(disp,_("Quit"),_("Do you really want to quit?"),gui::YES_NO).show();
if(res == 0) {
throw end_level_exception(QUIT);
} else {
@ -786,7 +786,7 @@ void execute_command(display& disp, HOTKEY_COMMAND command, command_executor* ex
case HOTKEY_QUIT_GAME: {
if(disp.in_game()) {
std::cerr << "is in game -- showing quit message\n";
const int res = gui::basic_dialog(disp,_("Quit"),_("Do you really want to quit?"),gui::YES_NO).show();
const int res = gui::dialog(disp,_("Quit"),_("Do you really want to quit?"),gui::YES_NO).show();
if(res == 0) {
throw end_level_exception(QUIT);
}
@ -812,8 +812,8 @@ void command_executor::show_menu(const std::vector<std::string>& items_arg, int
std::vector<std::string> menu = get_menu_images(items);
gui::basic_dialog mmenu = gui::basic_dialog(gui,"","",
gui::MESSAGE, &gui::basic_dialog::hotkeys_style);
gui::dialog mmenu = gui::dialog(gui,"","",
gui::MESSAGE, &gui::dialog::hotkeys_style);
mmenu.set_menu(menu);
const int res = mmenu.show(xloc, yloc);
if (size_t(res) >= items.size())

View file

@ -249,7 +249,7 @@ namespace events{
symbols["noun"] = (u.gender() == unit_race::MALE ? _("him") : _("her"));
message = utils::interpolate_variables_into_string(message, &symbols);
const int res = gui::basic_dialog(disp_,"",message,gui::YES_NO).show();
const int res = gui::dialog(disp_,"",message,gui::YES_NO).show();
if(res != 0) {
return gui::CONTINUE_DIALOG;
}
@ -516,7 +516,7 @@ namespace events{
if (res == 0) {
if (file_exists(input_name)) {
overwrite = gui::basic_dialog(*gui_, "",
overwrite = gui::dialog(*gui_, "",
_("The map already exists. Do you want to overwrite it?"),
gui::YES_NO).show();
}
@ -915,7 +915,7 @@ namespace events{
"You must have at least $cost gold pieces to recall a unit",
game_config::recall_cost,
i18n_symbols);
gui::basic_dialog(*gui_,"",msg.str()).show();
gui::dialog(*gui_,"",msg.str()).show();
} else {
std::cerr << "recall index: " << res << "\n";
unit& un = recall_list[res];
@ -925,7 +925,7 @@ namespace events{
const std::string err = recruit_unit(map_,team_num,units_,un,loc,(gui_!=NULL));
if(!err.empty()) {
recorder.undo();
gui::basic_dialog(*gui_,"",err,gui::OK_ONLY).show();
gui::dialog(*gui_,"",err,gui::OK_ONLY).show();
} else {
statistics::recall_unit(un);
current_team.spend_gold(game_config::recall_cost);
@ -1088,7 +1088,7 @@ namespace events{
recorder.add_checksum_check(action.recall_loc);
} else {
recorder.undo();
gui::basic_dialog(*gui_,"",msg,gui::OK_ONLY).show();
gui::dialog(*gui_,"",msg,gui::OK_ONLY).show();
}
}
} else if(action.is_recruit()) {
@ -1130,7 +1130,7 @@ namespace events{
recorder.add_checksum_check(loc);
} else {
recorder.undo();
gui::basic_dialog(*gui_,"",msg,gui::OK_ONLY).show();
gui::dialog(*gui_,"",msg,gui::OK_ONLY).show();
}
} else {
// Redo movement action
@ -1240,7 +1240,7 @@ namespace events{
//Ask for confirmation if the player hasn't made any moves (other than gotos).
if(preferences::confirm_no_moves() && ! some_units_have_moved) {
const int res = gui::basic_dialog(*gui_,"",_("You have not started your turn yet. Do you really want to end your turn?"), gui::YES_NO).show();
const int res = gui::dialog(*gui_,"",_("You have not started your turn yet. Do you really want to end your turn?"), gui::YES_NO).show();
if(res != 0) {
return false;
}
@ -1248,12 +1248,12 @@ namespace events{
// Ask for confirmation if units still have movement left
if(preferences::yellow_confirm() && partmoved_units) {
const int res = gui::basic_dialog(*gui_,"",_("Some units have movement left. Do you really want to end your turn?"),gui::YES_NO).show();
const int res = gui::dialog(*gui_,"",_("Some units have movement left. Do you really want to end your turn?"),gui::YES_NO).show();
if (res != 0) {
return false;
}
} else if (preferences::green_confirm() && unmoved_units) {
const int res = gui::basic_dialog(*gui_,"",_("Some units have movement left. Do you really want to end your turn?"),gui::YES_NO).show();
const int res = gui::dialog(*gui_,"",_("Some units have movement left. Do you really want to end your turn?"),gui::YES_NO).show();
if (res != 0) {
return false;
}
@ -1785,7 +1785,7 @@ namespace events{
symbols["search"] = last_search_;
const std::string msg = utils::interpolate_variables_into_string(
_("Couldn't find label or unit containing the string '$search'."),&symbols);
gui::basic_dialog(*gui_,"",msg).show();
gui::dialog(*gui_,"",msg).show();
}
}

View file

@ -220,7 +220,7 @@ static server_type open_connection(game_display& disp, const std::string& origin
do {
if(error != NULL) {
gui::basic_dialog(disp,"",(*error)["message"],gui::OK_ONLY).show();
gui::dialog(disp,"",(*error)["message"],gui::OK_ONLY).show();
}
std::string login = preferences::login();

View file

@ -1261,7 +1261,7 @@ void connect::load_game()
return;
}
const int res = gui::basic_dialog(disp(), "",
const int res = gui::dialog(disp(), "",
_("This save is from a different version of the game. Do you want to try to load it?"),
gui::YES_NO).show();
if(res == 1) {

View file

@ -13,7 +13,7 @@
#include "global.hpp"
#include "basic_dialog.hpp"
#include "construct_dialog.hpp"
#include "dialogs.hpp"
#include "game_display.hpp"
#include "game_events.hpp"
@ -340,7 +340,7 @@ void wait::process_network_data(const config& data, const network::connection so
if(data["message"] != "") {
/* GCC-3.3 needs a temp var otherwise compilation fails */
gui::basic_dialog dlg(disp(),_("Response"),data["message"],gui::OK_ONLY);
gui::dialog dlg(disp(),_("Response"),data["message"],gui::OK_ONLY);
dlg.show();
}
if(data["failed"] == "yes") {

View file

@ -390,7 +390,7 @@ bool play_controller::do_replay(const bool replaying){
player_number_,status_,gamestate_);
} catch(replay::error&) {
//in next version after string freeze add to text ". continue playing?"
if(gui::basic_dialog(*gui_,"",_("The file you have tried to load is corrupt"),gui::OK_CANCEL).show())
if(gui::dialog(*gui_,"",_("The file you have tried to load is corrupt"),gui::OK_CANCEL).show())
throw;
result = false;

View file

@ -355,7 +355,7 @@ namespace gui
void show_error_message(display &disp, std::string const &message)
{
ERR_G << message << std::endl;
basic_dialog(disp, _("Error"), message, OK_ONLY).show();
dialog(disp, _("Error"), message, OK_ONLY).show();
}
int show_dialog(display& screen, surface image,

View file

@ -118,7 +118,7 @@ private:
std::string id_;
friend class scrollpane;
friend class basic_dialog;
friend class dialog;
};
}