Make the scrollbar work properly.

Moved the 15 visible items hardcoded in the listbox instead of only
sending 15 languages to the dialog.
This commit is contained in:
Mark de Wever 2008-05-13 16:25:16 +00:00
parent 936b56c650
commit 422cc1b82a
3 changed files with 55 additions and 36 deletions

View file

@ -42,9 +42,7 @@ void tlanguage_selection::show(CVideo& video)
tlistbox* list = dynamic_cast<tlistbox*>(window.get_widget_by_id("language_list"));
VALIDATE(list, "No list defined.");
// Note we only do 15 lines since the listbox can't handle scrolling (yet).
/*const*/ std::vector<language_def>/*&*/ languages = get_languages();
languages.resize(15);
const std::vector<language_def>& languages = get_languages();
const language_def& current_language = get_language();
foreach(const language_def& lang, languages) {

View file

@ -15,9 +15,10 @@
#include "gui/widgets/listbox.hpp"
#include "foreach.hpp"
#include "gui/widgets/toggle_button.hpp"
#include "gui/widgets/helper.hpp"
#include "gui/widgets/scrollbar.hpp"
#include "gui/widgets/spacer.hpp"
#include "gui/widgets/toggle_button.hpp"
#include "log.hpp"
#define DBG_G LOG_STREAM_INDENT(debug, gui)
@ -40,20 +41,28 @@
#define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
#define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
namespace gui2 {
static tlistbox* get_listbox(twidget* widget)
{
do {
widget = widget->parent();
} while (widget && !dynamic_cast<tlistbox*>(widget));
tlistbox* listbox = dynamic_cast<tlistbox*>(widget);
assert(listbox);
return listbox;
}
static void callback_select_list_item(twidget* caller)
{
twidget* parent = caller;
do {
parent = parent->parent();
get_listbox(caller)->list_item_selected(caller);
}
} while (parent && !dynamic_cast<tlistbox*>(parent));
tlistbox* listbox = dynamic_cast<tlistbox*>(parent);
assert(listbox);
listbox->list_item_selected(caller);
static void callback_scrollbar(twidget* caller)
{
get_listbox(caller)->scrollbar_moved(caller);
}
tlistbox::tlistbox() :
@ -75,13 +84,14 @@ tlistbox::tlistbox() :
void tlistbox::list_item_selected(twidget* caller)
{
// FIXME we only need to test the visible rows
for(unsigned i = 0; i < rows_.size(); ++i) {
for(unsigned i = 0; i < scrollbar()->get_visible_items(); ++i) {
assert(rows_[i].grid());
if(rows_[i].grid()->has_widget(caller)) {
const unsigned row = i + scrollbar()->get_item_position();
if(!select_row(i, !rows_[i].get_selected())) {
assert(rows_[row].grid());
if(rows_[row].grid()->has_widget(caller)) {
if(!select_row(row, !rows_[row].get_selected())) {
// if not allowed to deselect reselect.
tselectable_* selectable = dynamic_cast<tselectable_*>(caller);
assert(selectable);
@ -137,6 +147,8 @@ void tlistbox::finalize_setup()
tspacer* spacer = dynamic_cast<tspacer*>(get_widget_by_id("_list"));
assert(spacer);
}
scrollbar()->set_callback_positioner_move(callback_scrollbar);
}
/**
@ -174,6 +186,11 @@ tpoint tlistbox::get_best_size() const
height += best_size.y;
}
// Hack to limit us to 15 items.
if(height) { // if we have a height there are items a height there are items.
height = 15 * height / get_item_count();
}
set_spacer_size(tpoint(width, height), grid());
// Now the container will return the wanted result.
@ -185,23 +202,18 @@ void tlistbox::draw(surface& surface)
// Inherit.
tcontainer_::draw(surface);
// Handle our full redraw for the spacer area.
if(!list_background_) {
//normal_rgb_(0x000000), selected_rgb_(0x000099), heading_rgb_(0x333333
SDL_Rect rect = list_rect_;
list_background_.assign(make_neutral_surface(get_surface_portion(surface, rect)));
// Note since the background is transparent atm it fails so force it black.
SDL_FillRect(list_background_, 0, 0xff000000);
list_background_.assign(gui2::save_background(surface, list_rect_));
} else {
// Full redraw.
// blit_surface(list_background_, 0, surface, &list_rect_);
gui2::restore_background(list_background_, surface, list_rect_);
}
// Hack to force a redraw every run
blit_surface(list_background_, 0, surface, &list_rect_);
// Now paint the list over the spacer.
unsigned offset = list_rect_.y;
foreach(trow& row, rows_) {
for(unsigned i = 0; i < scrollbar()->get_visible_items(); ++i) {
trow& row = rows_[i + scrollbar()->get_item_position()];
assert(row.grid());
if(row.grid()->dirty()) {
row.grid()->draw(row.canvas());
@ -209,9 +221,6 @@ void tlistbox::draw(surface& surface)
// draw background
const SDL_Rect rect = {list_rect_.x, offset, list_rect_.w, row.get_height() };
// const SDL_Rect background_rect = {0, offset - list_rect_.y, 0, 0 };
// blit_surface(list_background_, 0/*&background_rect*/, surface, 0/*&rect*/);
// blit_surface(list_background_, &background_rect, surface, &rect);
// draw widget
blit_surface(row.canvas(), 0, surface, &rect);
@ -252,11 +261,14 @@ twidget* tlistbox::get_widget(const tpoint& coordinate)
int offset = coordinate.y - list_rect_.y;
assert(offset >= 0);
foreach(trow& row, rows_) {
for(unsigned i = 0; i < scrollbar()->get_visible_items(); ++i) {
trow& row = rows_[i + scrollbar()->get_item_position()];
if(offset < row.get_height()) {
assert(row.grid());
return row.grid()->get_widget(tpoint(coordinate.x - list_rect_.x, offset));
return row.grid()->get_widget(
tpoint(coordinate.x - list_rect_.x, offset));
} else {
offset -= row.get_height();
}
@ -264,7 +276,6 @@ twidget* tlistbox::get_widget(const tpoint& coordinate)
}
return result;
}
void tlistbox::add_item(const std::string& label)
@ -283,7 +294,12 @@ void tlistbox::add_item(const std::string& label)
select_row(get_item_count() - 1);
}
scrollbar()->set_visible_items(get_item_count());
scrollbar()->set_item_count(get_item_count());
// Hack to limit the number of visible items.
if(get_item_count() <= 15) {
scrollbar()->set_visible_items(get_item_count());
}
}
tscrollbar_* tlistbox::scrollbar()

View file

@ -46,6 +46,11 @@ public:
*/
void list_item_selected(twidget* caller);
/**
* Callback when the scrollbar moves.
*/
void scrollbar_moved(twidget* /*caller*/) { set_dirty(); }
/** The builder needs to call us so we can write in the proper callbacks. */
void finalize_setup();