Implement new grid_listbox widget
This commit is contained in:
parent
943c1bdd57
commit
82153b1da8
7 changed files with 562 additions and 51 deletions
|
@ -614,6 +614,12 @@
|
|||
max="-1"
|
||||
super="gui/listbox_definition"
|
||||
[/tag]
|
||||
[tag]
|
||||
name="grid_listbox_definition"
|
||||
min="0"
|
||||
max="-1"
|
||||
super="gui/listbox_definition"
|
||||
[/tag]
|
||||
[tag]
|
||||
name="horizontal_scrollbar_definition"
|
||||
min="0"
|
||||
|
@ -1525,6 +1531,61 @@
|
|||
default=false
|
||||
[/key]
|
||||
[/tag]
|
||||
[tag]
|
||||
name="grid_listbox"
|
||||
min="0"
|
||||
max="-1"
|
||||
super="generic/widget_instance"
|
||||
[tag]
|
||||
name="footer"
|
||||
min="0"
|
||||
max="1"
|
||||
super="gui/window/resolution/grid"
|
||||
[/tag]
|
||||
[tag]
|
||||
name="header"
|
||||
min="0"
|
||||
max="1"
|
||||
super="gui/window/resolution/grid"
|
||||
[/tag]
|
||||
[tag]
|
||||
name="list_data"
|
||||
min="0"
|
||||
max="1"
|
||||
super="generic/listbox_grid"
|
||||
[/tag]
|
||||
[tag]
|
||||
name="list_definition"
|
||||
min="0"
|
||||
max="1"
|
||||
[tag]
|
||||
name="row"
|
||||
min="1"
|
||||
max="1"
|
||||
super="generic/listbox_grid/row"
|
||||
[/tag]
|
||||
[/tag]
|
||||
[key]
|
||||
name="horizontal_scrollbar_mode"
|
||||
type="scrollbar_mode"
|
||||
default=initial_auto
|
||||
[/key]
|
||||
[key]
|
||||
name="vertical_scrollbar_mode"
|
||||
type="scrollbar_mode"
|
||||
default=initial_auto
|
||||
[/key]
|
||||
[key]
|
||||
name="has_minimum"
|
||||
type="bool"
|
||||
default=true
|
||||
[/key]
|
||||
[key]
|
||||
name="has_maximum"
|
||||
type="bool"
|
||||
default=true
|
||||
[/key]
|
||||
[/tag]
|
||||
[tag]
|
||||
name="listbox"
|
||||
min="0"
|
||||
|
|
|
@ -176,5 +176,19 @@
|
|||
|
||||
[/horizontal_listbox_definition]
|
||||
|
||||
[grid_listbox_definition]
|
||||
id = "default"
|
||||
description = "Default grid listbox."
|
||||
|
||||
{_GUI_RESOLUTION
|
||||
({GUI_NORMAL__RESOLUTION})
|
||||
({GUI_NORMAL__FONT_SIZE__DEFAULT})
|
||||
()
|
||||
({GUI__FONT_COLOR_ENABLED__DEFAULT})
|
||||
({GUI__FONT_COLOR_DISABLED__DEFAULT})
|
||||
}
|
||||
|
||||
[/grid_listbox_definition]
|
||||
|
||||
#undef _GUI_RESOLUTION
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
namespace \
|
||||
{ \
|
||||
\
|
||||
namespace ns_##type \
|
||||
namespace ns_##type##id \
|
||||
{ \
|
||||
\
|
||||
struct tregister_helper \
|
||||
|
|
|
@ -513,6 +513,298 @@ void tvertical_list::handle_key_down_arrow(SDLMod /*modifier*/, bool& handled)
|
|||
}
|
||||
}
|
||||
|
||||
tmatrix::tmatrix() : placed_(false)//, n_cols_(2)
|
||||
{
|
||||
}
|
||||
|
||||
void tmatrix::create_item(const unsigned /*index*/)
|
||||
{
|
||||
if(!placed_) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @todo implement. */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
tpoint tmatrix::calculate_best_size() const
|
||||
{
|
||||
// The best size is the one that minimizes overall width and height
|
||||
// We try a number of columns from 2 up to sqrt(rows) + 1
|
||||
size_t n_items = get_item_count();
|
||||
if(n_items == 0) {
|
||||
return tpoint();
|
||||
} else if(n_items == 1) {
|
||||
return item(0).get_best_size();
|
||||
}
|
||||
size_t max_cols = sqrt(n_items) + 1;
|
||||
std::map<size_t,tpoint> best_sizes;
|
||||
for(size_t cols = 2, n = 0; cols <= max_cols && n < n_items; cols++) {
|
||||
tpoint result;
|
||||
for(size_t i = 0; i < n_items / cols + 1; ++i) {
|
||||
tpoint row_size;
|
||||
for(size_t j = 0; j < cols && n < n_items; j++, n++) {
|
||||
const tgrid& grid = item(n);
|
||||
if(grid.get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(n)) {
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
|
||||
const tpoint best_size = grid.get_best_size();
|
||||
|
||||
row_size.x += best_size.x;
|
||||
|
||||
if(best_size.y > row_size.y) {
|
||||
row_size.y = best_size.y;
|
||||
}
|
||||
}
|
||||
|
||||
if(row_size.x > result.x) {
|
||||
result.x = row_size.x;
|
||||
}
|
||||
|
||||
result.y += row_size.y;
|
||||
}
|
||||
best_sizes[cols] = result;
|
||||
}
|
||||
|
||||
return std::min_element(best_sizes.begin(), best_sizes.end(), [](const std::pair<size_t,tpoint>& p1, const std::pair<size_t,tpoint>& p2) {
|
||||
return p1.second.x + p1.second.y < p2.second.x + p2.second.y;
|
||||
})->second;
|
||||
//n_cols_ = iter->first; // TODO: This needs to be recalculated from the best size somehow?
|
||||
}
|
||||
|
||||
void tmatrix::place(const tpoint& origin, const tpoint& size)
|
||||
{
|
||||
/*
|
||||
* - Set every item to its best size.
|
||||
* - The origin gets increased with the height of the last item.
|
||||
* - No item should be wider as the size.
|
||||
* - In the end the origin should be the sum of the origin and the wanted
|
||||
* height.
|
||||
*/
|
||||
|
||||
tpoint current_origin = origin;
|
||||
for(size_t i = 0; i < get_item_count(); ++i) {
|
||||
|
||||
tgrid& grid = item_ordered(i);
|
||||
if(grid.get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(get_item_at_ordered(i))) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
tpoint best_size = grid.get_best_size();
|
||||
// FIXME should we look at grow factors???
|
||||
// best_size.x = size.x;
|
||||
|
||||
grid.place(current_origin, best_size);
|
||||
|
||||
if(current_origin.x + best_size.x > size.x) {
|
||||
current_origin.x = origin.x;
|
||||
current_origin.y += best_size.y;
|
||||
} else {
|
||||
current_origin.x += best_size.x;
|
||||
}
|
||||
}
|
||||
|
||||
// assert(current_origin.y == origin.y + size.y);
|
||||
}
|
||||
|
||||
void tmatrix::set_origin(const tpoint& origin)
|
||||
{
|
||||
tpoint current_origin = origin;
|
||||
for(size_t i = 0; i < get_item_count(); ++i) {
|
||||
|
||||
tgrid& grid = item_ordered(i);
|
||||
if(grid.get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(get_item_at_ordered(i))) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
grid.set_origin(current_origin);
|
||||
|
||||
if(current_origin.x + grid.get_width() > get_width()) {
|
||||
current_origin.x = origin.x;
|
||||
current_origin.y += grid.get_height();
|
||||
} else {
|
||||
current_origin.x += grid.get_width();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tmatrix::set_visible_rectangle(const SDL_Rect& rectangle)
|
||||
{
|
||||
/*
|
||||
* Note for most implementations this function could work only for the
|
||||
* tindependent class it probably fails. Evaluate to make a generic
|
||||
* function in the tgenerator template class and call it from the wanted
|
||||
* placement functions.
|
||||
*/
|
||||
for(size_t i = 0; i < get_item_count(); ++i) {
|
||||
|
||||
tgrid& grid = item(i);
|
||||
grid.set_visible_rectangle(rectangle);
|
||||
}
|
||||
}
|
||||
|
||||
twidget* tmatrix::find_at(const tpoint& coordinate,
|
||||
const bool must_be_active)
|
||||
{
|
||||
assert(get_window());
|
||||
|
||||
for(size_t i = 0; i < get_item_count(); ++i) {
|
||||
|
||||
tgrid& grid = item(i);
|
||||
if(grid.get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(i)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
twidget* widget = grid.find_at(coordinate, must_be_active);
|
||||
|
||||
if(widget) {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const twidget* tmatrix::find_at(const tpoint& coordinate,
|
||||
const bool must_be_active) const
|
||||
{
|
||||
assert(get_window());
|
||||
|
||||
for(size_t i = 0; i < get_item_count(); ++i) {
|
||||
|
||||
const tgrid& grid = item(i);
|
||||
if(grid.get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(i)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const twidget* widget = grid.find_at(coordinate, must_be_active);
|
||||
|
||||
if(widget) {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void tmatrix::handle_key_up_arrow(SDLMod /*modifier*/, bool& handled)
|
||||
{
|
||||
if(get_selected_item_count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE maybe this should only work if we can select only one item...
|
||||
handled = true;
|
||||
|
||||
for(int i = get_ordered_index(get_selected_item()) - 1; i >= 0; --i) {
|
||||
|
||||
if(item_ordered(i).get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(get_item_at_ordered(i))) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE we check the first widget to be active since grids have no
|
||||
// active flag. This method might not be entirely reliable.
|
||||
tcontrol* control = dynamic_cast<tcontrol*>(item_ordered(i).widget(0, 0));
|
||||
if(control && control->get_active()) {
|
||||
select_item(get_item_at_ordered(i), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tmatrix::handle_key_down_arrow(SDLMod /*modifier*/, bool& handled)
|
||||
{
|
||||
if(get_selected_item_count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE maybe this should only work if we can select only one item...
|
||||
handled = true;
|
||||
|
||||
for(size_t i = get_ordered_index(get_selected_item()) + 1; i < get_item_count(); ++i) {
|
||||
|
||||
if(item_ordered(i).get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(get_item_at_ordered(i))) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE we check the first widget to be active since grids have no
|
||||
// active flag. This method might not be entirely reliable.
|
||||
tcontrol* control = dynamic_cast<tcontrol*>(item_ordered(i).widget(0, 0));
|
||||
if(control && control->get_active()) {
|
||||
select_item(get_item_at_ordered(i), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tmatrix::handle_key_left_arrow(SDLMod /*modifier*/, bool& handled)
|
||||
{
|
||||
if(get_selected_item_count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE maybe this should only work if we can select only one item...
|
||||
handled = true;
|
||||
|
||||
for(int i = get_ordered_index(get_selected_item()) - 1; i >= 0; --i) {
|
||||
|
||||
if(item(get_item_at_ordered(i)).get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(get_item_at_ordered(i))) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE we check the first widget to be active since grids have no
|
||||
// active flag. This method might not be entirely reliable.
|
||||
tcontrol* control = dynamic_cast<tcontrol*>(item(get_item_at_ordered(i)).widget(0, 0));
|
||||
if(control && control->get_active()) {
|
||||
select_item(get_item_at_ordered(i), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tmatrix::handle_key_right_arrow(SDLMod /*modifier*/,
|
||||
bool& handled)
|
||||
{
|
||||
if(get_selected_item_count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE maybe this should only work if we can select only one item...
|
||||
handled = true;
|
||||
|
||||
for(size_t i = get_ordered_index(get_selected_item()) + 1; i < get_item_count(); ++i) {
|
||||
|
||||
if(item(get_item_at_ordered(i)).get_visible() == twidget::tvisible::invisible
|
||||
|| !get_item_shown(get_item_at_ordered(i))) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE we check the first widget to be active since grids have no
|
||||
// active flag. This method might not be entirely reliable.
|
||||
tcontrol* control = dynamic_cast<tcontrol*>(item(get_item_at_ordered(i)).widget(0, 0));
|
||||
if(control && control->get_active()) {
|
||||
select_item(get_item_at_ordered(i), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tindependent::request_reduce_width(const unsigned maximum_width)
|
||||
{
|
||||
for(size_t i = 0; i < get_item_count(); ++i) {
|
||||
|
|
|
@ -349,11 +349,10 @@ private:
|
|||
*/
|
||||
struct tmatrix : public virtual tgenerator_
|
||||
{
|
||||
tmatrix();
|
||||
|
||||
/** See thorizontal_list::create_item(). */
|
||||
void create_item(const unsigned /*index*/)
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
void create_item(const unsigned /*index*/);
|
||||
|
||||
/* Also make the overload from the generator_ visible. */
|
||||
using tgenerator_::create_item;
|
||||
|
@ -372,72 +371,48 @@ struct tmatrix : public virtual tgenerator_
|
|||
}
|
||||
|
||||
/** See @ref twidget::calculate_best_size. */
|
||||
virtual tpoint calculate_best_size() const override
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
virtual tpoint calculate_best_size() const override;
|
||||
|
||||
/** See @ref twidget::place. */
|
||||
virtual void place(const tpoint& /*origin*/
|
||||
,
|
||||
const tpoint& /*size*/) override
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
, const tpoint& /*size*/) override;
|
||||
|
||||
/** See @ref twidget::set_origin. */
|
||||
virtual void set_origin(const tpoint& /*origin*/) override
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
virtual void set_origin(const tpoint& /*origin*/) override;
|
||||
|
||||
/** See @ref thorizontal_list::set_visible_rectangle(). */
|
||||
void set_visible_rectangle(const SDL_Rect& /*rectangle*/)
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
void set_visible_rectangle(const SDL_Rect& /*rectangle*/);
|
||||
|
||||
/** See @ref twidget::find_at. */
|
||||
virtual twidget* find_at(const tpoint& /*coordinate*/
|
||||
,
|
||||
const bool /*must_be_active*/) override
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
, const bool /*must_be_active*/) override;
|
||||
|
||||
/** See @ref twidget::find_at. */
|
||||
virtual const twidget* find_at(const tpoint& /*coordinate*/
|
||||
,
|
||||
const bool /*must_be_active*/) const override
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
, const bool /*must_be_active*/) const override;
|
||||
|
||||
/***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
|
||||
|
||||
/** Inherited from tgenerator_. */
|
||||
void handle_key_up_arrow(SDLMod, bool&)
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
void handle_key_up_arrow(SDLMod, bool&);
|
||||
|
||||
/** Inherited from tgenerator_. */
|
||||
void handle_key_down_arrow(SDLMod, bool&)
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
void handle_key_down_arrow(SDLMod, bool&);
|
||||
|
||||
/** Inherited from tgenerator_. */
|
||||
void handle_key_left_arrow(SDLMod, bool&)
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
void handle_key_left_arrow(SDLMod, bool&);
|
||||
|
||||
/** Inherited from tgenerator_. */
|
||||
void handle_key_right_arrow(SDLMod, bool&)
|
||||
{
|
||||
ERROR_LOG(false);
|
||||
}
|
||||
void handle_key_right_arrow(SDLMod, bool&);
|
||||
private:
|
||||
/**
|
||||
* Has the grid already been placed?
|
||||
*
|
||||
* If the grid is placed it's no problem set the location of the new
|
||||
* item,it hasn't been placed, there's no information about its location
|
||||
* so do nothing.
|
||||
*/
|
||||
bool placed_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,12 +44,11 @@ namespace gui2
|
|||
// ------------ WIDGET -----------{
|
||||
|
||||
REGISTER_WIDGET(listbox)
|
||||
REGISTER_WIDGET3(tlistbox_definition, horizontal_listbox, _4)
|
||||
REGISTER_WIDGET3(tlistbox_definition, grid_listbox, _4)
|
||||
|
||||
namespace
|
||||
{
|
||||
// in separate namespace to avoid name classes
|
||||
REGISTER_WIDGET3(tlistbox_definition, horizontal_listbox, _4)
|
||||
|
||||
void callback_list_item_clicked(twidget& caller)
|
||||
{
|
||||
get_parent<tlistbox>(caller).list_item_clicked(caller);
|
||||
|
@ -1100,6 +1099,150 @@ twidget* tbuilder_horizontal_listbox::build() const
|
|||
#endif
|
||||
}
|
||||
|
||||
/*WIKI_MACRO
|
||||
* @begin{macro}{grid_listbox_description}
|
||||
*
|
||||
* A grid listbox is a control that holds several items of the
|
||||
* same type. Normally the items in a listbox are ordered in rows,
|
||||
* this version orders them in a grid instead.
|
||||
* @end{macro}
|
||||
*/
|
||||
|
||||
/*WIKI
|
||||
* @page = GUIWidgetInstanceWML
|
||||
* @order = 2_grid_listbox
|
||||
* @begin{parent}{name="gui/window/resolution/grid/row/column/"}
|
||||
* @begin{tag}{name="grid_listbox"}{min="0"}{max="-1"}{super="generic/widget_instance"}
|
||||
* == Horizontal listbox ==
|
||||
*
|
||||
* @macro = grid_listbox_description
|
||||
*
|
||||
* List with the grid listbox specific variables:
|
||||
* @begin{table}{config}
|
||||
* vertical_scrollbar_mode & scrollbar_mode & initial_auto &
|
||||
* Determines whether or not to show the
|
||||
* scrollbar. $
|
||||
* horizontal_scrollbar_mode & scrollbar_mode & initial_auto &
|
||||
* Determines whether or not to show the
|
||||
* scrollbar. $
|
||||
*
|
||||
* list_definition & section & & This defines how a listbox item
|
||||
* looks. It must contain the grid
|
||||
* definition for 1 column of the list. $
|
||||
*
|
||||
* list_data & section & [] & A grid alike section which stores the
|
||||
* initial data for the listbox. Every row
|
||||
* must have the same number of columns as
|
||||
* the 'list_definition'. $
|
||||
*
|
||||
* has_minimum & bool & true & If false, less than one cell can be selected. $
|
||||
*
|
||||
* has_maximum & bool & true & If false, more than one cell can be selected. $
|
||||
*
|
||||
* @end{table}
|
||||
* @begin{tag}{name="header"}{min=0}{max=1}{super="gui/window/resolution/grid"}
|
||||
* @end{tag}{name="header"}
|
||||
* @begin{tag}{name="footer"}{min=0}{max=1}{super="gui/window/resolution/grid"}
|
||||
* @end{tag}{name="footer"}
|
||||
* @begin{tag}{name="list_definition"}{min=0}{max=1}
|
||||
* @begin{tag}{name="row"}{min=1}{max=1}{super="generic/listbox_grid/row"}
|
||||
* @end{tag}{name="row"}
|
||||
* @end{tag}{name="list_definition"}
|
||||
* @begin{tag}{name="list_data"}{min=0}{max=1}{super="generic/listbox_grid"}
|
||||
* @end{tag}{name="list_data"}
|
||||
* In order to force widgets to be the same size inside a grid listbox,
|
||||
* the widgets need to be inside a linked_group.
|
||||
*
|
||||
* Inside the list section there are only the following widgets allowed
|
||||
* * grid (to nest)
|
||||
* * selectable widgets which are
|
||||
* ** toggle_button
|
||||
* ** toggle_panel
|
||||
* @end{tag}{name="grid_listbox"}
|
||||
* @end{parent}{name="gui/window/resolution/grid/row/column/"}
|
||||
*/
|
||||
|
||||
tbuilder_grid_listbox::tbuilder_grid_listbox(const config& cfg)
|
||||
: tbuilder_control(cfg)
|
||||
, vertical_scrollbar_mode(
|
||||
get_scrollbar_mode(cfg["vertical_scrollbar_mode"]))
|
||||
, horizontal_scrollbar_mode(
|
||||
get_scrollbar_mode(cfg["horizontal_scrollbar_mode"]))
|
||||
, list_builder(nullptr)
|
||||
, list_data()
|
||||
, has_minimum_(cfg["has_minimum"].to_bool(true))
|
||||
, has_maximum_(cfg["has_maximum"].to_bool(true))
|
||||
{
|
||||
const config& l = cfg.child("list_definition");
|
||||
|
||||
VALIDATE(l, _("No list defined."));
|
||||
list_builder = std::make_shared<tbuilder_grid>(l);
|
||||
assert(list_builder);
|
||||
VALIDATE(list_builder->rows == 1,
|
||||
_("A 'list_definition' should contain one row."));
|
||||
|
||||
const config& data = cfg.child("list_data");
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
for(const auto & row : data.child_range("row"))
|
||||
{
|
||||
unsigned col = 0;
|
||||
|
||||
for(const auto & c : row.child_range("column"))
|
||||
{
|
||||
list_data.push_back(string_map());
|
||||
for(const auto & i : c.attribute_range())
|
||||
{
|
||||
list_data.back()[i.first] = i.second;
|
||||
}
|
||||
++col;
|
||||
}
|
||||
|
||||
VALIDATE(col == list_builder->cols,
|
||||
_("'list_data' must have "
|
||||
"the same number of columns as the 'list_definition'."));
|
||||
}
|
||||
}
|
||||
|
||||
twidget* tbuilder_grid_listbox::build() const
|
||||
{
|
||||
#ifdef GUI2_EXPERIMENTAL_LISTBOX
|
||||
tlist* widget = new tlist(
|
||||
true, true, tgenerator_::grid, true, list_builder);
|
||||
|
||||
init_control(widget);
|
||||
if(!list_data.empty()) {
|
||||
widget->append_rows(list_data);
|
||||
}
|
||||
return widget;
|
||||
#else
|
||||
tlistbox* widget
|
||||
= new tlistbox(has_minimum_, has_maximum_, tgenerator_::grid, true);
|
||||
|
||||
init_control(widget);
|
||||
|
||||
widget->set_list_builder(list_builder); // FIXME in finalize???
|
||||
|
||||
widget->set_vertical_scrollbar_mode(vertical_scrollbar_mode);
|
||||
widget->set_horizontal_scrollbar_mode(horizontal_scrollbar_mode);
|
||||
|
||||
DBG_GUI_G << "Window builder: placed listbox '" << id
|
||||
<< "' with definition '" << definition << "'.\n";
|
||||
|
||||
std::shared_ptr<const tlistbox_definition::tresolution>
|
||||
conf = std::static_pointer_cast<const tlistbox_definition::tresolution>(
|
||||
widget->config());
|
||||
assert(conf);
|
||||
|
||||
widget->init_grid(conf->grid);
|
||||
|
||||
widget->finalize(nullptr, nullptr, list_data);
|
||||
|
||||
return widget;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
// }------------ END --------------
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace implementation
|
|||
{
|
||||
struct tbuilder_listbox;
|
||||
struct tbuilder_horizontal_listbox;
|
||||
struct tbuilder_grid_listbox;
|
||||
}
|
||||
|
||||
/** The listbox class. */
|
||||
|
@ -40,6 +41,7 @@ class tlistbox : public tscrollbar_container
|
|||
{
|
||||
friend struct implementation::tbuilder_listbox;
|
||||
friend struct implementation::tbuilder_horizontal_listbox;
|
||||
friend struct implementation::tbuilder_grid_listbox;
|
||||
friend class tdebug_layout_graph;
|
||||
|
||||
public:
|
||||
|
@ -432,6 +434,30 @@ struct tbuilder_horizontal_listbox : public tbuilder_control
|
|||
bool has_minimum_, has_maximum_;
|
||||
};
|
||||
|
||||
struct tbuilder_grid_listbox : public tbuilder_control
|
||||
{
|
||||
explicit tbuilder_grid_listbox(const config& cfg);
|
||||
|
||||
using tbuilder_control::build;
|
||||
|
||||
twidget* build() const;
|
||||
|
||||
tscrollbar_container::tscrollbar_mode vertical_scrollbar_mode;
|
||||
tscrollbar_container::tscrollbar_mode horizontal_scrollbar_mode;
|
||||
|
||||
tbuilder_grid_ptr list_builder;
|
||||
|
||||
/**
|
||||
* Listbox data.
|
||||
*
|
||||
* Contains a vector with the data to set in every cell, it's used to
|
||||
* serialize the data in the config, so the config is no longer required.
|
||||
*/
|
||||
std::vector<string_map> list_data;
|
||||
|
||||
bool has_minimum_, has_maximum_;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
// }------------ END --------------
|
||||
|
|
Loading…
Add table
Reference in a new issue