comboboxes for gui2

This adds a new combobox widget to gui2. Like the gui1 combobox widget
this is more or less only a button that prompts a list dialog below the
button when you click on it.
This commit is contained in:
gfgtdf 2016-01-20 17:44:13 +01:00
parent 6cf9790c02
commit 4739413502
15 changed files with 941 additions and 0 deletions

View file

@ -0,0 +1,119 @@
#textdomain wesnoth-lib
###
### Definition of the default button.
###
#define _GUI_RESOLUTION RESOLUTION MIN_WIDTH DEFAULT_WIDTH HEIGHT EXTRA_WIDTH EXTRA_HEIGHT FONT_SIZE BASE_NAME IPF
[resolution]
{RESOLUTION}
min_width = {MIN_WIDTH}
min_height = {HEIGHT}
default_width = {DEFAULT_WIDTH}
default_height = {HEIGHT}
max_width = 0
max_height = {HEIGHT}
text_extra_width = {EXTRA_WIDTH}
text_extra_height = {EXTRA_HEIGHT}
text_font_size = {FONT_SIZE}
[state_enabled]
[draw]
[image]
w = "(width)"
h = "(height)"
name = "buttons/{BASE_NAME}.png{IPF}"
[/image]
{GUI__CENTERED_TEXT ({FONT_SIZE}) () ({GUI__FONT_COLOR_ENABLED__TITLE})}
[image]
x = "(width - 12)"
y = 7
name = "buttons/sliders/slider_arrow_blue.png~ROTATE(180)"
[/image]
[/draw]
[/state_enabled]
[state_disabled]
[draw]
[image]
w = "(width)"
h = "(height)"
name = "buttons/{BASE_NAME}.png~GS(){IPF}"
[/image]
{GUI__CENTERED_TEXT ({FONT_SIZE}) () ({GUI__FONT_COLOR_DISABLED__TITLE})}
[image]
x = "(width - 12)"
y = 7
name = "buttons/sliders/slider_arrow_blue.png~ROTATE(180)"
[/image]
[/draw]
[/state_disabled]
[state_pressed]
[draw]
[image]
w = "(width)"
h = "(height)"
name = "buttons/{BASE_NAME}-pressed.png{IPF}"
[/image]
{GUI__CENTERED_TEXT ({FONT_SIZE}) () ({GUI__FONT_COLOR_ENABLED__TITLE})}
[image]
x = "(width - 12)"
y = 7
name = "buttons/sliders/slider_arrow_blue.png~ROTATE(180)"
[/image]
[/draw]
[/state_pressed]
[state_focused]
[draw]
[image]
w = "(width)"
h = "(height)"
name = "buttons/{BASE_NAME}-active.png{IPF}"
[/image]
{GUI__CENTERED_TEXT ({FONT_SIZE}) () ({GUI__FONT_COLOR_ENABLED__TITLE})}
[image]
x = "(width - 12)"
y = 7
name = "buttons/sliders/slider_arrow_blue.png~ROTATE(180)"
[/image]
[/draw]
[/state_focused]
[/resolution]
#enddef
[combobox_definition]
id = "default"
description = "Default button"
# Tiny gui sizes haven't been tested yet so might need some tuning.
{_GUI_RESOLUTION ({GUI_TINY__RESOLUTION}) 20 54 11 6 2 ({GUI_TINY__FONT_SIZE__SMALL}) "button_normal/button_H22" ()}
{_GUI_RESOLUTION () 40 108 22 13 4 ({GUI_NORMAL__FONT_SIZE__SMALL}) "button_normal/button_H22" ()}
[/combobox_definition]
#undef _GUI_RESOLUTION

View file

@ -0,0 +1,82 @@
#textdomain wesnoth-lib
###
### Definition of the window select the way to access the addon server.
###
[window]
id = "drop_down_list"
description="Not Empty"
[resolution]
maximum_width = 9999
maximum_height = 9999
## click_dismiss = "false"
#define FORMULA_WINDOW_HEIGHT
min(if(window_height > 0, window_height, screen_width), max(button_y, screen_height - button_h - button_y)) #enddef
definition = "default"
width="(if(window_width > 0, window_width, screen_width))"
height="({FORMULA_WINDOW_HEIGHT})"
## Show the droplist below or above the button, whereever we have enough space. Below is preffered.
x="(min(button_x, screen_width - window_width))"
y="(if(screen_height - button_h - button_y > {FORMULA_WINDOW_HEIGHT}, button_h + button_y, button_y - {FORMULA_WINDOW_HEIGHT}))"
automatic_placement = false
#undef FORMULA_WINDOW_HEIGHT
[tooltip]
id = "tooltip_large"
[/tooltip]
[helptip]
id = "tooltip_large"
[/helptip]
[grid]
[row]
[column]
horizontal_grow = "true"
vertical_grow = "true"
border = "all"
border_size = 0
[listbox]
id = "list"
definition = "default"
[list_definition]
[row]
[column]
grow_factor = 1
horizontal_grow = "true"
[toggle_panel]
definition="default"
[grid]
[row]
[column]
[label]
id="label"
[/label]
[/column]
[/row]
[/grid]
[/toggle_panel]
[/column]
[/row]
[/list_definition]
[/listbox]
[/column]
[/row]
[/grid]
[/resolution]
[/window]

View file

@ -584,6 +584,12 @@
[/tag]
[/tag]
[/tag]
[tag]
name="combobox_definition"
min="0"
max="-1"
super="gui/button_definition"
[/tag]
[tag]
name="drawing_definition"
min="0"
@ -1365,6 +1371,22 @@
default=""
[/key]
[/tag]
[tag]
name="combobox"
min="0"
max="-1"
super="gui/window/resolution/grid/row/column/button"
[tag]
name = "option"
min="0"
max="-1"
[key]
name="label"
type="string"
default=""
[/key]
[/tag]
[/tag]
[tag]
name="drawing"
min="0"

View file

@ -569,6 +569,7 @@ add_library(wesnoth-gui_tooltip
# for the widgets since the code has inter dependencies.
set(wesnoth-gui_widget_SRC
gui/widgets/button.cpp
gui/widgets/combobox.cpp
gui/widgets/container.cpp
gui/widgets/control.cpp
gui/widgets/debug.cpp
@ -609,6 +610,7 @@ set(wesnoth-gui_widget_SRC
gui/widgets/window.cpp
gui/auxiliary/window_builder.cpp
gui/auxiliary/window_builder/button.cpp
gui/auxiliary/window_builder/combobox.cpp
gui/auxiliary/window_builder/control.cpp
gui/auxiliary/window_builder/drawing.cpp
gui/auxiliary/window_builder/helper.cpp
@ -662,6 +664,7 @@ target_link_libraries(wesnoth-gui_widget
set(wesnoth-gui_widget_definition_SRC
gui/auxiliary/widget_definition.cpp
gui/auxiliary/widget_definition/button.cpp
gui/auxiliary/widget_definition/combobox.cpp
gui/auxiliary/widget_definition/drawing.cpp
gui/auxiliary/widget_definition/horizontal_scrollbar.cpp
gui/auxiliary/widget_definition/image.cpp
@ -896,6 +899,7 @@ set(wesnoth-main_SRC
gui/dialogs/depcheck_confirm_change.cpp
gui/dialogs/depcheck_select_new.cpp
gui/dialogs/dialog.cpp
gui/dialogs/drop_down_list.cpp
gui/dialogs/edit_label.cpp
gui/dialogs/editor/custom_tod.cpp
gui/dialogs/editor/editor_edit_label.cpp

View file

@ -347,6 +347,7 @@ wesnoth_sources = Split("""
gui/auxiliary/tips.cpp
gui/auxiliary/widget_definition.cpp
gui/auxiliary/widget_definition/button.cpp
gui/auxiliary/widget_definition/combobox.cpp
gui/auxiliary/widget_definition/drawing.cpp
gui/auxiliary/widget_definition/horizontal_scrollbar.cpp
gui/auxiliary/widget_definition/image.cpp
@ -371,6 +372,7 @@ wesnoth_sources = Split("""
gui/auxiliary/widget_definition/window.cpp
gui/auxiliary/window_builder.cpp
gui/auxiliary/window_builder/button.cpp
gui/auxiliary/window_builder/combobox.cpp
gui/auxiliary/window_builder/control.cpp
gui/auxiliary/window_builder/drawing.cpp
gui/auxiliary/window_builder/helper.cpp
@ -415,6 +417,7 @@ wesnoth_sources = Split("""
gui/dialogs/depcheck_confirm_change.cpp
gui/dialogs/depcheck_select_new.cpp
gui/dialogs/dialog.cpp
gui/dialogs/drop_down_list.cpp
gui/dialogs/edit_label.cpp
gui/dialogs/editor/editor_edit_label.cpp
gui/dialogs/editor/editor_edit_scenario.cpp
@ -466,6 +469,7 @@ wesnoth_sources = Split("""
gui/dialogs/wml_message.cpp
gui/lib/types/point.cpp
gui/widgets/button.cpp
gui/widgets/combobox.cpp
gui/widgets/container.cpp
gui/widgets/control.cpp
gui/widgets/drawing.cpp

View file

@ -0,0 +1,70 @@
/*
Copyright (C) 2007 - 2016 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "gui/auxiliary/widget_definition/combobox.hpp"
#include "gui/auxiliary/log.hpp"
namespace gui2
{
tcombobox_definition::tcombobox_definition(const config& cfg)
: tcontrol_definition(cfg)
{
DBG_GUI_P << "Parsing combobox " << id << '\n';
load_resolutions<tresolution>(cfg);
}
/*WIKI
* @page = GUIWidgetDefinitionWML
* @order = 1_combobox
*
* == combobox ==
*
* @macro = combobox_description
*
* The following states exist:
* * state_enabled, the combobox is enabled.
* * state_disabled, the combobox is disabled.
* * state_pressed, the left mouse combobox is down.
* * state_focused, the mouse is over the combobox.
* @begin{parent}{name="gui/"}
* @begin{tag}{name="combobox_definition"}{min=0}{max=-1}{super="generic/widget_definition"}
* @begin{tag}{name="resolution"}{min=0}{max=-1}{super="generic/widget_definition/resolution"}
* @begin{tag}{name="state_enabled"}{min=0}{max=1}{super="generic/state"}
* @end{tag}{name="state_enabled"}
* @begin{tag}{name="state_disabled"}{min=0}{max=1}{super="generic/state"}
* @end{tag}{name="state_disabled"}
* @begin{tag}{name="state_pressed"}{min=0}{max=1}{super="generic/state"}
* @end{tag}{name="state_pressed"}
* @begin{tag}{name="state_focused"}{min=0}{max=1}{super="generic/state"}
* @end{tag}{name="state_focused"}
* @end{tag}{name="resolution"}
* @end{tag}{name="combobox_definition"}
* @end{parent}{name="gui/"}
*/
tcombobox_definition::tresolution::tresolution(const config& cfg)
: tresolution_definition_(cfg)
{
// Note the order should be the same as the enum tstate in combobox.hpp.
state.push_back(tstate_definition(cfg.child("state_enabled")));
state.push_back(tstate_definition(cfg.child("state_disabled")));
state.push_back(tstate_definition(cfg.child("state_pressed")));
state.push_back(tstate_definition(cfg.child("state_focused")));
}
} // namespace gui2

View file

@ -0,0 +1,32 @@
/*
Copyright (C) 2007 - 2016 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
#include "gui/auxiliary/widget_definition.hpp"
namespace gui2
{
struct tcombobox_definition : public tcontrol_definition
{
explicit tcombobox_definition(const config& cfg);
struct tresolution : public tresolution_definition_
{
explicit tresolution(const config& cfg);
};
};
} // namespace gui2

View file

@ -34,6 +34,7 @@
#include "gui/auxiliary/window_builder/scroll_label.hpp"
#include "gui/auxiliary/window_builder/minimap.hpp"
#include "gui/auxiliary/window_builder/button.hpp"
#include "gui/auxiliary/window_builder/combobox.hpp"
#include "gui/auxiliary/window_builder/drawing.hpp"
#include "gui/auxiliary/window_builder/pane.hpp"
#include "gui/auxiliary/window_builder/password_box.hpp"
@ -194,6 +195,12 @@ tbuilder_widget_ptr create_builder_widget(const config& cfg)
* in the final binary only if the #if is enabled.
*
* If this code is executed, which it will cause an assertion failure.
*
* Its likeley that this happens becasue some build this as a library file
* which is then used by the wesnoth executable. For msvc a good try to fix
* this issue is to add __pragma(comment(linker, "/include:" #TYPE)) or
* similar in the REGISTER_WIDGET3 macro. For gcc and similar this can only
* be fixed by using --whole-archive flag when linking this library.
*/
#if 1
#define TRY(name) \
@ -217,6 +224,7 @@ tbuilder_widget_ptr create_builder_widget(const config& cfg)
TRY(matrix);
TRY(minimap);
TRY(button);
TRY(combobox);
TRY(drawing);
TRY(password_box);
#undef TRY

View file

@ -0,0 +1,96 @@
/*
Copyright (C) 2008 - 2016 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "gui/auxiliary/window_builder/combobox.hpp"
#include "config.hpp"
#include "gui/auxiliary/log.hpp"
#include "gui/auxiliary/window_builder/helper.hpp"
#include "gui/widgets/combobox.hpp"
#include "utils/foreach.tpp"
namespace gui2
{
namespace implementation
{
tbuilder_combobox::tbuilder_combobox(const config& cfg)
: tbuilder_control(cfg)
, retval_id_(cfg["return_value_id"])
, retval_(cfg["return_value"])
, options_()
{
FOREACH(const AUTO& option, cfg.child_range("option")) {
options_.push_back(option["label"]);
}
}
twidget* tbuilder_combobox::build() const
{
tcombobox* widget = new tcombobox();
init_control(widget);
widget->set_retval(get_retval(retval_id_, retval_, id));
widget->set_values(options_);
DBG_GUI_G << "Window builder: placed combobox '" << id
<< "' with definition '" << definition << "'.\n";
return widget;
}
} // namespace implementation
} // namespace gui2
/*WIKI_MACRO
* @begin{macro}{combobox_description}
*
* A combobox is a control to choose an element from a list of elements.
* @end{macro}
*/
/*WIKI
* @page = GUIWidgetInstanceWML
* @order = 2_combobox
* @begin{parent}{name="gui/window/resolution/grid/row/column/"}
* @begin{tag}{name="combobox"}{min=0}{max=-1}{super="generic/widget_instance"}
* == combobox ==
*
* @macro = combobox_description
*
* Instance of a combobox. When a combobox has a return value it sets the
* return value for the window. Normally this closes the window and returns
* this value to the caller. The return value can either be defined by the
* user or determined from the id of the combobox. The return value has a
* higher precedence as the one defined by the id. (Of course it's weird to
* give a combobox an id and then override its return value.)
*
* When the combobox doesn't have a standard id, but you still want to use the
* return value of that id, use return_value_id instead. This has a higher
* precedence as return_value.
*
* List with the combobox specific variables:
* @begin{table}{config}
* return_value_id & string & "" & The return value id. $
* return_value & int & 0 & The return value. $
*
* @end{table}
* @end{tag}{name="combobox"}
* @end{parent}{name="gui/window/resolution/grid/row/column/"}
*/

View file

@ -0,0 +1,44 @@
/*
Copyright (C) 2008 - 2016 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
#include "gui/auxiliary/window_builder/control.hpp"
namespace gui2
{
class tcontrol;
namespace implementation
{
struct tbuilder_combobox : public tbuilder_control
{
public:
explicit tbuilder_combobox(const config& cfg);
using tbuilder_control::build;
twidget* build() const;
private:
std::string retval_id_;
int retval_;
std::vector<std::string> options_;
};
} // namespace implementation
} // namespace gui2

View file

@ -0,0 +1,82 @@
/*
Copyright (C) 2008 - 2016 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "gui/dialogs/drop_down_list.hpp"
#include "gui/widgets/listbox.hpp"
#include "gui/auxiliary/find_widget.tpp"
#include "gui/dialogs/dialog.hpp"
#include "gui/widgets/integer_selector.hpp"
#include "gui/widgets/window.hpp"
#include "gui/widgets/settings.hpp"
#include "utils/foreach.tpp"
#include <boost/function.hpp>
#include <boost/bind.hpp>
namespace gui2
{
REGISTER_DIALOG(drop_down_list)
namespace {
void click_callback(twindow& window, bool& handled, bool& halt, tpoint coordinate)
{
SDL_Rect rect = window.get_rectangle();
if(coordinate.x < rect.x || coordinate.x > rect.x + rect.w || coordinate.y < rect.y || coordinate.y > rect.y + rect.h ) {
halt = handled = true;
window.set_retval(twindow::CANCEL);
window.close();
}
}
void resize_callback(twindow& window)
{
window.set_retval(twindow::CANCEL);
window.close();
}
}
void tdrop_down_list::pre_show(CVideo& /*video*/, twindow& window)
{
window.set_variable("button_x", variant(button_pos_.x));
window.set_variable("button_y", variant(button_pos_.y));
window.set_variable("button_w", variant(button_pos_.w));
window.set_variable("button_h", variant(button_pos_.h));
tlistbox& list = find_widget<tlistbox>(&window, "list", true);
std::map<std::string, string_map> data;
t_string& label = data["label"]["label"];
FOREACH(const AUTO& str, items_) {
label = str;
list.add_row(data);
}
list.select_row(selected_item_);
list.set_callback_item_change(boost::bind(&tdrop_down_list::item_change_callback, this, boost::ref(window), _1));
//Dismiss on click outside the window
window.connect_signal<event::SDL_LEFT_BUTTON_UP>(boost::bind(&click_callback, boost::ref(window), _3, _4, _5), event::tdispatcher::front_child);
//Dismiss on resize
window.connect_signal<event::SDL_VIDEO_RESIZE>(boost::bind(&resize_callback, boost::ref(window)), event::tdispatcher::front_child);
}
void tdrop_down_list::item_change_callback(twindow& window, size_t item)
{
selected_item_ = item;
window.set_retval(twindow::OK);
window.close();
}
void tdrop_down_list::post_show(twindow&)
{
}
} // namespace gui2

View file

@ -0,0 +1,52 @@
/*
Copyright (C) 2008 - 2016 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
#include "gui/dialogs/dialog.hpp"
#include "sdl/rect.hpp"
namespace gui2
{
///Used by the combobox widget.
class tdrop_down_list : public tdialog
{
public:
tdrop_down_list(SDL_Rect button_pos, const std::vector<std::string>& items, int selected_item)
: button_pos_(button_pos)
, items_(items)
, selected_item_(selected_item)
{
}
int selected_item() const { return selected_item_; }
private:
/// The screen location of the combobox button that triggred this droplist.
/// Note: we don't adjust the location of this dialog to when resizing the window.
/// Instead this dialog automatically closes itself on resizing.
SDL_Rect button_pos_;
std::vector<std::string> items_;
int selected_item_;
/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
virtual const std::string& window_id() const;
/** Inherited from tdialog. */
void pre_show(CVideo& video, twindow& window);
/** Inherited from tdialog. */
void post_show(twindow& window);
void item_change_callback(twindow& window, size_t item);
};
} // namespace gui2

View file

@ -0,0 +1,184 @@
/*
Copyright (C) 2008 - 2016 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#define GETTEXT_DOMAIN "wesnoth-lib"
#include "gui/widgets/combobox.hpp"
#include "gui/auxiliary/log.hpp"
#include "gui/auxiliary/widget_definition/combobox.hpp"
#include "gui/auxiliary/window_builder/combobox.hpp"
#include "gui/widgets/detail/register.tpp"
#include "gui/widgets/settings.hpp"
#include "gui/widgets/window.hpp"
#include "gui/dialogs/drop_down_list.hpp"
#include "sound.hpp"
#include <boost/bind.hpp>
#define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
#define LOG_HEADER LOG_SCOPE_HEADER + ':'
namespace gui2
{
REGISTER_WIDGET(combobox)
tcombobox::tcombobox()
: tcontrol(COUNT)
, tclickable_()
, state_(ENABLED)
, retval_(0)
, values_()
, selected_()
{
values_.push_back(this->label());
connect_signal<event::MOUSE_ENTER>(
boost::bind(&tcombobox::signal_handler_mouse_enter, this, _2, _3));
connect_signal<event::MOUSE_LEAVE>(
boost::bind(&tcombobox::signal_handler_mouse_leave, this, _2, _3));
connect_signal<event::LEFT_BUTTON_DOWN>(boost::bind(
&tcombobox::signal_handler_left_button_down, this, _2, _3));
connect_signal<event::LEFT_BUTTON_UP>(
boost::bind(&tcombobox::signal_handler_left_button_up, this, _2, _3));
connect_signal<event::LEFT_BUTTON_CLICK>(boost::bind(
&tcombobox::signal_handler_left_button_click, this, _2, _3));
}
void tcombobox::set_active(const bool active)
{
if(get_active() != active) {
set_state(active ? ENABLED : DISABLED);
}
}
bool tcombobox::get_active() const
{
return state_ != DISABLED;
}
unsigned tcombobox::get_state() const
{
return state_;
}
void tcombobox::set_state(const tstate state)
{
if(state != state_) {
state_ = state;
set_is_dirty(true);
}
}
const std::string& tcombobox::get_control_type() const
{
static const std::string type = "button";
return type;
}
void tcombobox::signal_handler_mouse_enter(const event::tevent event,
bool& handled)
{
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
set_state(FOCUSED);
handled = true;
}
void tcombobox::signal_handler_mouse_leave(const event::tevent event,
bool& handled)
{
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
set_state(ENABLED);
handled = true;
}
void tcombobox::signal_handler_left_button_down(const event::tevent event,
bool& handled)
{
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
twindow* window = get_window();
if(window) {
window->mouse_capture();
}
set_state(PRESSED);
handled = true;
}
void tcombobox::signal_handler_left_button_up(const event::tevent event,
bool& handled)
{
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
set_state(FOCUSED);
handled = true;
}
void tcombobox::signal_handler_left_button_click(const event::tevent event,
bool& handled)
{
assert(get_window());
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
sound::play_UI_sound(settings::sound_button_click);
// If a button has a retval do the default handling.
tdrop_down_list droplist(this->get_rectangle(), this->values_, this->selected_);
if(droplist.show(get_window()->video())) {
selected_ = droplist.selected_item();
this->set_label(values_[selected_]);
if(selected_callback_) {
selected_callback_(*this);
}
if(retval_ != 0) {
twindow* window = get_window();
if(window) {
window->set_retval(retval_);
return;
}
}
}
handled = true;
}
void tcombobox::set_values(const std::vector<std::string>& values, int selected)
{
assert(static_cast<size_t>(selected) < values.size());
assert(static_cast<size_t>(selected_) < values_.size());
if(values[selected] != values_[selected_]) {
set_is_dirty(true);
}
values_ = values;
selected_ = selected;
set_label(values_[selected_]);
}
void tcombobox::set_selected(int selected)
{
assert(static_cast<size_t>(selected) < values_.size());
assert(static_cast<size_t>(selected_) < values_.size());
if(selected != selected_) {
set_is_dirty(true);
}
selected_ = selected;
set_label(values_[selected_]);
}
} // namespace gui2

View file

@ -0,0 +1,141 @@
/*
Copyright (C) 2008 - 2016 by Mark de Wever <koraq@xs4all.nl>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
#include "gui/widgets/control.hpp"
#include "gui/widgets/clickable.hpp"
#include "gui/widgets/selectable.hpp"
namespace gui2
{
/**
* Simple push button.
*/
class tcombobox : public tcontrol, public tclickable_, public tselectable_
{
public:
tcombobox();
/***** ***** ***** ***** Inherited ***** ***** ***** *****/
/** See @ref tcontrol::set_active. */
virtual void set_active(const bool active) OVERRIDE;
/** See @ref tcontrol::get_active. */
virtual bool get_active() const OVERRIDE;
/** See @ref tcontrol::get_state. */
virtual unsigned get_state() const OVERRIDE;
/** Inherited from tclickable. */
void connect_click_handler(const event::tsignal_function& signal)
{
connect_signal_mouse_left_click(*this, signal);
}
/** Inherited from tclickable. */
void disconnect_click_handler(const event::tsignal_function& signal)
{
disconnect_signal_mouse_left_click(*this, signal);
}
/***** ***** ***** setters / getters for members ***** ****** *****/
void set_retval(const int retval)
{
retval_ = retval;
}
void set_values(const std::vector<std::string>& values, int selected = 0);
void set_selected(int selected);
/** See tselectable_::set_callback_state_change. */
boost::function<void(twidget&)> callback_state_change_;
/** Inherited from tselectable_ */
virtual unsigned get_value() const OVERRIDE { return selected_; }
/** Inherited from tselectable_ */
virtual void set_value(const unsigned value ) OVERRIDE { set_selected(value); }
/** Inherited from tselectable_ */
virtual unsigned num_states() const OVERRIDE { return values_.size(); }
/** Inherited from tselectable_ */
virtual void set_callback_state_change(boost::function<void(twidget&)> callback)
{
selected_callback_ = callback;
}
private:
/**
* Possible states of the widget.
*
* Note the order of the states must be the same as defined in settings.hpp.
*/
enum tstate {
ENABLED,
DISABLED,
PRESSED,
FOCUSED,
COUNT
};
void set_state(const tstate state);
/**
* Current state of the widget.
*
* The state of the widget determines what to render and how the widget
* reacts to certain 'events'.
*/
tstate state_;
/**
* The return value of the button.
*
* If this value is not 0 and the button is clicked it sets the retval of
* the window and the window closes itself.
*/
int retval_;
/**
*/
std::vector<std::string> values_;
/**
*/
int selected_;
boost::function<void(twidget&)> selected_callback_;
/** See @ref tcontrol::get_control_type. */
virtual const std::string& get_control_type() const OVERRIDE;
/***** ***** ***** signal handlers ***** ****** *****/
void signal_handler_mouse_enter(const event::tevent event, bool& handled);
void signal_handler_mouse_leave(const event::tevent event, bool& handled);
void signal_handler_left_button_down(const event::tevent event,
bool& handled);
void signal_handler_left_button_up(const event::tevent event,
bool& handled);
void signal_handler_left_button_click(const event::tevent event,
bool& handled);
};
} // namespace gui2

View file

@ -472,6 +472,7 @@ BOOST_AUTO_TEST_CASE(test_gui2)
list.erase(std::remove(list.begin(), list.end(), "addon_uninstall_list"), list.end());
list.erase(std::remove(list.begin(), list.end(), "network_transmission"), list.end());
list.erase(std::remove(list.begin(), list.end(), "synced_choice_wait"), list.end());
list.erase(std::remove(list.begin(), list.end(), "drop_down_list"), list.end());
// Test size() instead of empty() to get the number of offenders
BOOST_CHECK_EQUAL(list.size(), 0);