Allow the WML message dialog to show a portrait on both sides

This commit is contained in:
Celtic Minstrel 2016-08-25 15:57:45 -04:00
parent dae453fe43
commit b1141fe457
4 changed files with 418 additions and 299 deletions

View file

@ -192,6 +192,50 @@ where calculated_width = {__GUI_IMAGE_WIDTH}
[/window_definition]
[window_definition]
id = "wml_message_double"
description = "bar"
[resolution]
[background]
[draw]
[/draw]
[/background]
[foreground]
[draw]
[image]
x = "{__GUI_IMAGE_DISPLAYED_X}"
y = "{__GUI_IMAGE_DISPLAYED_Y}"
w = "{__GUI_IMAGE_DISPLAYED_WIDTH}"
h = "{__GUI_IMAGE_DISPLAYED_HEIGHT}"
name = "(portrait_image)"
vertical_mirror = "(portrait_mirror)"
[/image]
[image]
x = "(width - {__GUI_IMAGE_DISPLAYED_WIDTH})"
y = "(height - image_height)"
w = "{__GUI_IMAGE_DISPLAYED_WIDTH}"
h = "{__GUI_IMAGE_DISPLAYED_HEIGHT}"
name = "(second_portrait_image)"
vertical_mirror = "(second_portrait_mirror)"
[/image]
[/draw]
[/foreground]
[/resolution]
[/window_definition]
#define _GUI_INPUT_LIST
[listbox]
id = "input_list"
@ -272,6 +316,129 @@ where calculated_width = {__GUI_IMAGE_WIDTH}
[/listbox]
#enddef
#define _GUI_WML_MESSAGE_CONTENT
[column]
grow_factor = 1
horizontal_grow = "true"
[grid]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
id = "title"
definition = "title"
[/label]
[/column]
[/row]
[row]
[column]
grow_factor = 1
horizontal_grow = "true"
border = "all"
border_size = 5
[scroll_label]
id = "message"
definition = "wml_message"
[/scroll_label]
[/column]
[/row]
[row]
[column]
grow_factor = 1
horizontal_grow = "true"
[grid]
[row]
[column]
border = "all"
border_size = 5
[label]
id = "input_caption"
definition = "default"
[/label]
[/column]
[column]
grow_factor = 1
horizontal_grow = "true"
border = "all"
border_size = 5
[text_box]
id = "input"
definition = "transparent"
[/text_box]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_grow = "true"
{_GUI_INPUT_LIST}
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "center"
[button]
# This button will be shown or hidden depending on the
# whether or not a scrollbar is needed to show the
# text.
id = "ok"
definition = "transparent"
label = _ "OK"
[/button]
[/column]
[/row]
[/grid]
[/column]
#enddef
[window]
id = "wml_message_left"
description = "Dialog showing a unit portrait on the left side"
@ -347,127 +514,8 @@ where calculated_width = {__GUI_IMAGE_WIDTH}
[/spacer]
[/column]
[column]
grow_factor = 1
horizontal_grow = "true"
[grid]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
id = "title"
definition = "title"
[/label]
[/column]
[/row]
[row]
[column]
grow_factor = 1
horizontal_grow = "true"
border = "all"
border_size = 5
[scroll_label]
id = "message"
definition = "wml_message"
[/scroll_label]
[/column]
[/row]
[row]
[column]
grow_factor = 1
horizontal_grow = "true"
[grid]
[row]
[column]
border = "all"
border_size = 5
[label]
id = "input_caption"
definition = "default"
[/label]
[/column]
[column]
grow_factor = 1
horizontal_grow = "true"
border = "all"
border_size = 5
[text_box]
id = "input"
definition = "transparent"
[/text_box]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_grow = "true"
{_GUI_INPUT_LIST}
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "center"
[button]
# This button will be shown or hidden depending on the
# whether or not a scrollbar is needed to show the
# text.
id = "ok"
definition = "transparent"
label = _ "OK"
[/button]
[/column]
[/row]
[/grid]
[/column]
{_GUI_WML_MESSAGE_CONTENT}
[column]
@ -577,127 +625,134 @@ if(gamemap_width - ({__GUI_IMAGE_WIDTH}) > {MAX_TEXT_WIDTH}
[/column]
{_GUI_WML_MESSAGE_CONTENT}
[column]
grow_factor = 1
horizontal_grow = "true"
[grid]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
id = "title"
definition = "title"
[/label]
[/column]
[/row]
[row]
[column]
grow_factor = 1
horizontal_grow = "true"
border = "all"
border_size = 5
[scroll_label]
id = "message"
definition = "default"
[/scroll_label]
[/column]
[/row]
[row]
[column]
grow_factor = 1
horizontal_grow = "true"
[grid]
[row]
[column]
border = "all"
border_size = 5
[label]
id = "input_caption"
definition = "default"
[/label]
[/column]
[column]
grow_factor = 1
horizontal_grow = "true"
border = "all"
border_size = 5
[text_box]
id = "input"
definition = "transparent"
[/text_box]
[/column]
[/row]
[/grid]
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_grow = "true"
{_GUI_INPUT_LIST}
[/column]
[/row]
[row]
[column]
border = "all"
border_size = 5
horizontal_alignment = "center"
[button]
# This button will be shown or hidden depending on the
# whether or not a scrollbar is needed to show the
# text.
id = "ok"
definition = "transparent"
label = _ "OK"
[/button]
[/column]
[/row]
[/grid]
[spacer]
width = "(
if(gamemap_width - (10 + ({__GUI_IMAGE_WIDTH})) > {MAX_TEXT_WIDTH}
, gamemap_width - (10 + ({__GUI_IMAGE_WIDTH}) + {MAX_TEXT_WIDTH})
, 0
))"
height = 75
[/spacer]
[/column]
[column]
[spacer]
# reserve place for the image and set a minimum height for the text
id = "image_place_holder"
width = {_GUI_IMAGE_WIDTH}
height = 75
[/spacer]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
[/panel]
[/column]
[/row]
[/grid]
[/resolution]
[/window]
[window]
id = "wml_message_double"
description = "Dialog showing a unit portrait on each side"
[resolution]
window_width = 0
window_height = 0
definition = "wml_message_double"
automatic_placement = "false"
x = "(gamemap_x_offset)"
y = 30
width = "(gamemap_width)"
height = "(screen_height - 30)"
click_dismiss = "true"
[linked_group]
id = "icon"
fixed_width = "true"
[/linked_group]
[linked_group]
id = "label"
fixed_width = "true"
[/linked_group]
[linked_group]
id = "description"
fixed_width = "true"
[/linked_group]
[tooltip]
id = "tooltip"
[/tooltip]
[helptip]
id = "tooltip"
[/helptip]
[grid]
[row]
[column]
vertical_alignment = "bottom"
horizontal_grow = "true"
[panel]
definition = "wml_message"
[grid]
[row]
[column]
horizontal_grow = "true"
[grid]
[row]
[column]
[spacer]
# reserve place for the image and set a minimum height for the text
id = "image_place_holder"
width = {_GUI_IMAGE_WIDTH}
height = 75
[/spacer]
[/column]
{_GUI_WML_MESSAGE_CONTENT}
[column]
[spacer]

View file

@ -145,37 +145,43 @@ void twml_message_::post_show(twindow& window)
}
}
void twml_message_double::pre_show(twindow& window)
{
twml_message_left::pre_show(window);
window.canvas(1).set_variable("second_portrait_image", variant(second_portrait_));
window.canvas(1).set_variable("second_portrait_mirror", variant(second_mirror_));
}
REGISTER_DIALOG(wml_message_left)
REGISTER_DIALOG(wml_message_right)
int show_wml_message(const bool left_side,
CVideo& video,
REGISTER_DIALOG(wml_message_double)
int show_wml_message(CVideo& video,
const std::string& title,
const std::string& message,
const std::string& portrait,
const bool mirror,
const bool has_input,
const std::string& input_caption,
std::string* input_text,
const unsigned maximum_length,
const std::vector<twml_message_option>& option_list,
int* chosen_option)
const twml_message_portrait* left,
const twml_message_portrait* right,
const twml_message_options& options,
const twml_message_input& input)
{
std::shared_ptr<twml_message_> dlg;
if(left_side) {
dlg.reset(new twml_message_left(title, message, portrait, mirror));
if(left && !right) {
dlg.reset(new twml_message_left(title, message, left->portrait, left->mirror));
} else if(!left && right) {
dlg.reset(new twml_message_right(title, message, right->portrait, right->mirror));
} else {
dlg.reset(new twml_message_right(title, message, portrait, mirror));
dlg.reset(new twml_message_double(title, message, left->portrait, left->mirror, right->portrait, right->mirror));
}
assert(dlg.get());
if(has_input) {
dlg->set_input(input_caption, input_text, maximum_length);
if(!input.caption.empty()) {
dlg->set_input(input.caption, &input.text, input.maximum_length);
}
if(!option_list.empty()) {
dlg->set_option_list(option_list, chosen_option);
if(!options.option_list.empty()) {
dlg->set_option_list(options.option_list, &options.chosen_option);
}
dlg->show(video);

View file

@ -122,9 +122,11 @@ private:
/** The chosen option. */
int* chosen_option_;
protected:
/** Inherited from tdialog. */
void pre_show(twindow& window);
private:
/** Inherited from tdialog. */
void post_show(twindow& window);
};
@ -163,43 +165,90 @@ private:
virtual const std::string& window_id() const;
};
/** Shows a dialog with two portraits, one on each side. */
class twml_message_double : public twml_message_left
{
public:
twml_message_double(const std::string& title,
const std::string& message,
const std::string& portrait,
const bool mirror,
const std::string& second_portrait,
const bool second_mirror)
: twml_message_left(title, message, portrait, mirror)
, second_portrait_(second_portrait)
, second_mirror_(second_mirror)
{
}
private:
/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
virtual const std::string& window_id() const;
/** Inherited from tdialog. */
void pre_show(twindow& window);
std::string second_portrait_;
bool second_mirror_;
};
/**
* Parameter pack for message list input options
*/
struct twml_message_options
{
/// A list of options to select in the dialog.
std::vector<twml_message_option> option_list;
/// The initially chosen option.
/// Will be set to the chosen option when the dialog closes.
mutable int chosen_option;
};
/**
* Parameter pack for message text input options
*/
struct twml_message_input
{
/// The caption for the optional input text box.
/// If empty, there is no input box.
std::string caption;
/// The initial text value.
/// Will be set to the result.
mutable std::string text;
/// The maximum length of the text.
unsigned maximum_length;
};
/**
* Parameter pack for message portrait
*/
struct twml_message_portrait
{
/// FIlename of the portrait.
std::string portrait;
/// Does the portrait need to be mirrored?
bool mirror;
};
/**
* Helper function to show a portrait.
*
* @param left_side If true the portrait is shown on the left,
* on the right side otherwise.
* @param video The display variable.
* @param title The title of the dialog.
* @param message The message to show.
* @param portrait Filename of the portrait.
* @param mirror Does the portrait need to be mirrored?
*
* @param has_input Do we need to show the input box.
* @param input_caption The caption for the optional input text
* box. If this value != "" there is an input
* and the input text parameter is mandatory.
* @param input_text Pointer to the initial text value will be
* set to the result.
* @param maximum_length The maximum length of the text.
*
* @param option_list A list of options to select in the dialog.
* @param chosen_option Pointer to the initially chosen option.
* Will be set to the chosen option when the
* dialog closes.
* @param left Portrait to show on the left.
* @param right Portrait to show on the right.
* @param options Options to offer.
* @param input Info on text input.
*/
int show_wml_message(const bool left_side,
CVideo& video,
int show_wml_message(CVideo& video,
const std::string& title,
const std::string& message,
const std::string& portrait,
const bool mirror,
const bool has_input,
const std::string& input_caption,
std::string* input_text,
const unsigned maximum_length,
const std::vector<twml_message_option>& option_list,
int* chosen_option);
const twml_message_portrait* left,
const twml_message_portrait* right,
const twml_message_options& options,
const twml_message_input& input);
} // namespace gui2

View file

@ -255,12 +255,13 @@ int show_message_dialog(lua_State *L, CVideo & video)
{
config txt_cfg;
const bool has_input = !lua_isnoneornil(L, 3) && luaW_toconfig(L, 3, txt_cfg) && !txt_cfg.empty();
const std::string& input_caption = txt_cfg["label"];
std::string input_text = txt_cfg["text"].str();
unsigned int input_max_len = txt_cfg["max_length"].to_int(256);
std::vector<gui2::twml_message_option> options;
int chosen_option = -1;
gui2::twml_message_input input;
input.caption = txt_cfg["label"].str();
input.text = txt_cfg["text"].str();
input.maximum_length = txt_cfg["max_length"].to_int(256);
gui2::twml_message_options options;
if (!lua_isnoneornil(L, 2)) {
luaL_checktype(L, 2, LUA_TTABLE);
size_t n = lua_rawlen(L, 2);
@ -296,9 +297,9 @@ int show_message_dialog(lua_State *L, CVideo & video)
}
gui2::twml_message_option option(opt["label"], opt["description"], opt["image"]);
if(opt["default"].to_bool(false)) {
chosen_option = i - 1;
options.chosen_option = i - 1;
}
options.push_back(option);
options.option_list.push_back(option);
lua_pop(L, 1);
}
lua_getfield(L, 2, "default");
@ -309,7 +310,7 @@ int show_message_dialog(lua_State *L, CVideo & video)
error << "default= key in options list is not a valid option index (1-" << n << ")";
return luaL_argerror(L, 2, error.str().c_str());
}
chosen_option = i - 1;
options.chosen_option = i - 1;
}
lua_pop(L, 1);
}
@ -317,24 +318,32 @@ int show_message_dialog(lua_State *L, CVideo & video)
const config& def_cfg = luaW_checkconfig(L, 1);
const std::string& title = def_cfg["title"];
const std::string& message = def_cfg["message"];
const std::string& portrait = def_cfg["portrait"];
using portrait = gui2::twml_message_portrait;
std::unique_ptr<portrait> left;
std::unique_ptr<portrait> right;
const bool is_double = def_cfg.has_attribute("second_portrait");
const bool left_side = def_cfg["left_side"].to_bool(true);
const bool mirror = def_cfg["mirror"].to_bool(false);
if(is_double || left_side) {
left.reset(new portrait {def_cfg["portrait"], def_cfg["mirror"].to_bool(false)});
} else {
// This means right side only.
right.reset(new portrait {def_cfg["portrait"], def_cfg["mirror"].to_bool(false)});
}
if(is_double) {
right.reset(new portrait {def_cfg["second_portrait"], def_cfg["second_mirror"].to_bool(false)});
}
int dlg_result = gui2::show_wml_message(
left_side, video, title, message, portrait, mirror,
has_input, input_caption, &input_text, input_max_len,
options, &chosen_option
);
int dlg_result = gui2::show_wml_message(video, title, message, left.get(), right.get(), options, input);
if (!has_input && options.empty()) {
if (!has_input && options.option_list.empty()) {
lua_pushinteger(L, dlg_result);
} else {
lua_pushinteger(L, chosen_option + 1);
lua_pushinteger(L, options.chosen_option + 1);
}
if (has_input) {
lua_pushlstring(L, input_text.c_str(), input_text.length());
lua_pushlstring(L, input.text.c_str(), input.text.length());
} else {
lua_pushnil(L);
}