Add a new scrollbar mode.

This way the user can select whether or not to show the scrollbar if the
contents fit at the first run. The code will only be used for the new
layout algorithm and does nothing at the moment.
This commit is contained in:
Mark de Wever 2009-04-25 18:57:24 +00:00
parent cf8639b980
commit 4eff96aaa0
6 changed files with 95 additions and 57 deletions

View File

@ -251,15 +251,26 @@ tline::tline(const config& cfg) :
* *
* scrollbar_mode How to show the scrollbar of a widget. * scrollbar_mode How to show the scrollbar of a widget.
* Possible values: * Possible values:
* @* always The scrollbar is always shown, * @* always The scrollbar is always
* regardless whether it's required or not. * shown, regardless whether it's required
* @* never The scrollbar is never shown, * or not.
* even not when needed. (Note when setting * @* never The scrollbar is never
* this mode dialogs might not properly fit * shown, even not when needed. (Note when
* anymore). * setting this mode dialogs might
* not properly fit anymore).
* @* auto Shows the scrollbar when * @* auto Shows the scrollbar when
* needed. The widget will reserve space for * needed. The widget will reserve space for
* the scrollbar, but only show when needed. * the scrollbar, but only show when needed.
* @* initial_auto Like auto, but when the
* scrollbar is not needed the space is not
* reserved.
* @-Use auto when the list can be changed
* dynamically eg the game list in the
* lobby. For optimization you can also
* use auto when you really expect a
* scrollbar, but don't want it to be shown
* when not needed eg the language list
* will need a scrollbar on most screens.
* @end_table * @end_table
* *
* == Section types == * == Section types ==

View File

@ -84,10 +84,10 @@ void callback_horizontal_scrollbar(twidget* caller)
tscrollbar_container::tscrollbar_container(const unsigned canvas_count) tscrollbar_container::tscrollbar_container(const unsigned canvas_count)
: tcontainer_(canvas_count) : tcontainer_(canvas_count)
, state_(ENABLED) , state_(ENABLED)
, vertical_scrollbar_mode_(SHOW_WHEN_NEEDED) , vertical_scrollbar_mode_(auto_visible)
, horizontal_scrollbar_mode_(SHOW_WHEN_NEEDED) , horizontal_scrollbar_mode_(auto_visible)
, initial_vertical_scrollbar_mode_(SHOW_WHEN_NEEDED) , initial_vertical_scrollbar_mode_(auto_visible)
, initial_horizontal_scrollbar_mode_(SHOW_WHEN_NEEDED) , initial_horizontal_scrollbar_mode_(auto_visible)
, vertical_scrollbar_grid_(NULL) , vertical_scrollbar_grid_(NULL)
, horizontal_scrollbar_grid_(NULL) , horizontal_scrollbar_grid_(NULL)
, vertical_scrollbar_(NULL) , vertical_scrollbar_(NULL)
@ -123,15 +123,15 @@ void tscrollbar_container::layout_init2(const bool full_initialization)
* When the scrollbars should be shown when needed, assume they're not * When the scrollbars should be shown when needed, assume they're not
* needed and unhide them when needed. * needed and unhide them when needed.
*/ */
if(initial_vertical_scrollbar_mode_ == SHOW_WHEN_NEEDED) { if(initial_vertical_scrollbar_mode_ == auto_visible) {
vertical_scrollbar_mode_ = HIDE; vertical_scrollbar_mode_ = always_invisible;
} else { } else {
vertical_scrollbar_mode_ = initial_vertical_scrollbar_mode_; vertical_scrollbar_mode_ = initial_vertical_scrollbar_mode_;
} }
show_vertical_scrollbar(); show_vertical_scrollbar();
if(initial_vertical_scrollbar_mode_ == SHOW_WHEN_NEEDED) { if(initial_vertical_scrollbar_mode_ == auto_visible) {
horizontal_scrollbar_mode_ = HIDE; horizontal_scrollbar_mode_ = always_invisible;
} else { } else {
horizontal_scrollbar_mode_ = initial_horizontal_scrollbar_mode_; horizontal_scrollbar_mode_ = initial_horizontal_scrollbar_mode_;
} }
@ -150,17 +150,21 @@ void tscrollbar_container::NEW_layout_init(const bool full_initialization)
if(full_initialization) { if(full_initialization) {
if(initial_vertical_scrollbar_mode_ == HIDE) {
vertical_scrollbar_mode_ = HIDE; if(initial_vertical_scrollbar_mode_ == always_visible
|| initial_vertical_scrollbar_mode_ == auto_visible) {
vertical_scrollbar_mode_ = always_visible;
} else { } else {
vertical_scrollbar_mode_ = SHOW; vertical_scrollbar_mode_ = always_invisible;
} }
show_vertical_scrollbar(); show_vertical_scrollbar();
if(initial_vertical_scrollbar_mode_ == HIDE) { if(initial_vertical_scrollbar_mode_ == always_visible
horizontal_scrollbar_mode_ = HIDE; || initial_vertical_scrollbar_mode_ == auto_visible) {
horizontal_scrollbar_mode_ = always_visible;
} else { } else {
horizontal_scrollbar_mode_ = SHOW; horizontal_scrollbar_mode_ = always_invisible;
} }
show_horizontal_scrollbar(); show_horizontal_scrollbar();
} }
@ -172,7 +176,7 @@ void tscrollbar_container::NEW_layout_init(const bool full_initialization)
void tscrollbar_container::NEW_request_reduce_height( void tscrollbar_container::NEW_request_reduce_height(
const unsigned maximum_height) const unsigned maximum_height)
{ {
if(initial_horizontal_scrollbar_mode_ == HIDE) { if(initial_horizontal_scrollbar_mode_ == always_invisible) {
return; return;
} }
@ -183,6 +187,15 @@ void tscrollbar_container::NEW_request_reduce_height(
return; return;
} }
const bool unhide =
initial_horizontal_scrollbar_mode_ == auto_visible_first_run
&& vertical_scrollbar_mode_ == always_invisible;
if(unhide) {
horizontal_scrollbar_mode_ = always_visible;
show_horizontal_scrollbar();
}
const tpoint scrollbar_size = vertical_scrollbar_grid_->get_best_size(); const tpoint scrollbar_size = vertical_scrollbar_grid_->get_best_size();
if(maximum_height > static_cast<unsigned>(scrollbar_size.y)) { if(maximum_height > static_cast<unsigned>(scrollbar_size.y)) {
size.y = maximum_height; size.y = maximum_height;
@ -193,6 +206,10 @@ void tscrollbar_container::NEW_request_reduce_height(
// FIXME adjust for the step size of the scrollbar // FIXME adjust for the step size of the scrollbar
set_layout_size(size); set_layout_size(size);
if(unhide) {
/** @todo Throw a width change exception. */
}
} }
void tscrollbar_container::layout_wrap(const unsigned maximum_width) void tscrollbar_container::layout_wrap(const unsigned maximum_width)
@ -201,7 +218,7 @@ void tscrollbar_container::layout_wrap(const unsigned maximum_width)
twidget::layout_wrap(maximum_width); twidget::layout_wrap(maximum_width);
assert(content_grid_ && vertical_scrollbar_grid_); assert(content_grid_ && vertical_scrollbar_grid_);
const unsigned offset = vertical_scrollbar_mode_ == HIDE const unsigned offset = vertical_scrollbar_mode_ == always_invisible
? 0 ? 0
: vertical_scrollbar_grid_->get_best_size().x; : vertical_scrollbar_grid_->get_best_size().x;
@ -214,12 +231,12 @@ bool tscrollbar_container::has_vertical_scrollbar() const
* @todo look at cleaning the has_X_scrollbar and can_wrap to do the * @todo look at cleaning the has_X_scrollbar and can_wrap to do the
* visibility test in a more generic way, preferably in the grid. * visibility test in a more generic way, preferably in the grid.
*/ */
return is_visible() && vertical_scrollbar_mode_ != HIDE; return is_visible() && vertical_scrollbar_mode_ != always_invisible;
} }
bool tscrollbar_container::has_horizontal_scrollbar() const bool tscrollbar_container::has_horizontal_scrollbar() const
{ {
return is_visible() && horizontal_scrollbar_mode_ != HIDE; return is_visible() && horizontal_scrollbar_mode_ != always_invisible;
} }
void tscrollbar_container:: void tscrollbar_container::
@ -313,13 +330,13 @@ tpoint tscrollbar_container::calculate_best_size() const
/***** get vertical scrollbar size *****/ /***** get vertical scrollbar size *****/
const tpoint vertical_scrollbar = const tpoint vertical_scrollbar =
vertical_scrollbar_mode_ == HIDE vertical_scrollbar_mode_ == always_invisible
? tpoint(0, 0) ? tpoint(0, 0)
: vertical_scrollbar_grid_->get_best_size(); : vertical_scrollbar_grid_->get_best_size();
/***** get horizontal scrollbar size *****/ /***** get horizontal scrollbar size *****/
const tpoint horizontal_scrollbar = const tpoint horizontal_scrollbar =
horizontal_scrollbar_mode_ == HIDE horizontal_scrollbar_mode_ == always_invisible
? tpoint(0, 0) ? tpoint(0, 0)
: horizontal_scrollbar_grid_->get_best_size(); : horizontal_scrollbar_grid_->get_best_size();
@ -349,7 +366,7 @@ static void set_scrollbar_mode(tgrid* scrollbar_grid, tscrollbar_* scrollbar,
{ {
assert(scrollbar_grid && scrollbar); assert(scrollbar_grid && scrollbar);
if(scrollbar_mode != tscrollbar_container::HIDE) { if(scrollbar_mode != tscrollbar_container::always_invisible) {
scrollbar->set_item_count(items); scrollbar->set_item_count(items);
scrollbar->set_visible_items(visible_items); scrollbar->set_visible_items(visible_items);
@ -360,9 +377,9 @@ static void set_scrollbar_mode(tgrid* scrollbar_grid, tscrollbar_* scrollbar,
if(!scrollbar_needed) { if(!scrollbar_needed) {
// Hide the scrollbar // Hide the scrollbar
if(scrollbar_mode == tscrollbar_container::SHOW_WHEN_NEEDED) { if(scrollbar_mode == tscrollbar_container::auto_visible) {
if(true) { // extra setting if(true) { // extra setting
scrollbar_mode = tscrollbar_container::HIDE; scrollbar_mode = tscrollbar_container::always_invisible;
} else { } else {
scrollbar_grid->set_visible(twidget::HIDDEN); scrollbar_grid->set_visible(twidget::HIDDEN);
} }
@ -370,7 +387,7 @@ static void set_scrollbar_mode(tgrid* scrollbar_grid, tscrollbar_* scrollbar,
} }
} }
if(scrollbar_mode == tscrollbar_container::HIDE) { if(scrollbar_mode == tscrollbar_container::always_invisible) {
scrollbar_grid->set_visible(twidget::INVISIBLE); scrollbar_grid->set_visible(twidget::INVISIBLE);
} }
} }
@ -683,7 +700,7 @@ void tscrollbar_container::show_vertical_scrollbar()
return; return;
} }
if(vertical_scrollbar_mode_ == HIDE) { if(vertical_scrollbar_mode_ == always_invisible) {
vertical_scrollbar_grid_->set_visible(twidget::INVISIBLE); vertical_scrollbar_grid_->set_visible(twidget::INVISIBLE);
} else { } else {
vertical_scrollbar_grid_->set_visible(twidget::VISIBLE); vertical_scrollbar_grid_->set_visible(twidget::VISIBLE);
@ -696,7 +713,7 @@ void tscrollbar_container::show_horizontal_scrollbar()
return; return;
} }
if(horizontal_scrollbar_mode_ == HIDE) { if(horizontal_scrollbar_mode_ == always_invisible) {
horizontal_scrollbar_grid_->set_visible(twidget::INVISIBLE); horizontal_scrollbar_grid_->set_visible(twidget::INVISIBLE);
} else { } else {
horizontal_scrollbar_grid_->set_visible(twidget::VISIBLE); horizontal_scrollbar_grid_->set_visible(twidget::VISIBLE);
@ -951,12 +968,12 @@ void tscrollbar_container::scrollbar_moved()
assert(vertical_scrollbar_ && horizontal_scrollbar_); assert(vertical_scrollbar_ && horizontal_scrollbar_);
/*** Update the content location. ***/ /*** Update the content location. ***/
const int x_offset = horizontal_scrollbar_mode_ == HIDE const int x_offset = horizontal_scrollbar_mode_ == always_invisible
? 0 ? 0
: horizontal_scrollbar_->get_item_position() * : horizontal_scrollbar_->get_item_position() *
horizontal_scrollbar_->get_step_size(); horizontal_scrollbar_->get_step_size();
const int y_offset = vertical_scrollbar_mode_ == HIDE const int y_offset = vertical_scrollbar_mode_ == always_invisible
? 0 ? 0
: vertical_scrollbar_->get_item_position() * : vertical_scrollbar_->get_item_position() *
vertical_scrollbar_->get_step_size(); vertical_scrollbar_->get_step_size();

View File

@ -46,22 +46,29 @@ public:
/** The way to handle the showing or hiding of the scrollbar. */ /** The way to handle the showing or hiding of the scrollbar. */
enum tscrollbar_mode { enum tscrollbar_mode {
SHOW, /**< always_visible, /**<
* The scrollbar is always shown, whether * The scrollbar is always shown, whether
* needed or not. * needed or not.
*/ */
HIDE, /**< always_invisible, /**<
* The scrollbar is never shown even not when * The scrollbar is never shown even not
* needed. There's also no space reserved for * when needed. There's also no space
* the scrollbar. * reserved for the scrollbar.
*/ */
SHOW_WHEN_NEEDED /**< auto_visible, /**<
* The scrollbar is shown when the number of * The scrollbar is shown when the number of
* items is larger as the visible items. The * items is larger as the visible items. The
* space for the scrollbar is always * space for the scrollbar is always
* reserved, just in case it's needed after * reserved, just in case it's needed after
* the initial sizing (due to adding items). * the initial sizing (due to adding items).
*/ */
auto_visible_first_run /**<
* Like auto_visible, but when not needed
* upon the initial layout phase, the bars
* are not shown and no space is reserved
* for them. (The algorithm hides them by
* default.
*/
}; };
/***** ***** ***** ***** layout functions ***** ***** ***** *****/ /***** ***** ***** ***** layout functions ***** ***** ***** *****/

View File

@ -173,8 +173,9 @@ public:
* @see @ref layout_algorihm for more information. * @see @ref layout_algorihm for more information.
* *
* @param full_initialization For widgets with scrollbars it hides them * @param full_initialization For widgets with scrollbars it hides them
* unless the mode is tscrollbar_mode::SHOW. * unless the mode is
* For other widgets this flag is a NOP. * tscrollbar_mode::always_visible. For other
* widgets this flag is a NOP.
*/ */
virtual void NEW_layout_init(const bool full_initialization); virtual void NEW_layout_init(const bool full_initialization);

View File

@ -1060,7 +1060,7 @@ void twindow::generate_dot_file(const std::string& generator,
* - Clear the internal best size cache for all widgets. * - Clear the internal best size cache for all widgets.
* - For widgets with scrollbars hide them unless the * - For widgets with scrollbars hide them unless the
* @ref gui2::tscrollbar_container::tscrollbar_mode "scrollbar_mode" is * @ref gui2::tscrollbar_container::tscrollbar_mode "scrollbar_mode" is
* SHOW. * always_visible or auto_visible.
* - Handle shared sizes: * - Handle shared sizes:
* - Height and width: * - Height and width:
* - Get the best size for all widgets that share height and width. * - Get the best size for all widgets that share height and width.

View File

@ -144,15 +144,17 @@ tscrollbar_container::tscrollbar_mode
get_scrollbar_mode(const std::string& scrollbar_mode) get_scrollbar_mode(const std::string& scrollbar_mode)
{ {
if(scrollbar_mode == "always") { if(scrollbar_mode == "always") {
return tscrollbar_container::SHOW; return tscrollbar_container::always_visible;
} else if(scrollbar_mode == "never") { } else if(scrollbar_mode == "never") {
return tscrollbar_container::HIDE; return tscrollbar_container::always_invisible;
} else if(scrollbar_mode == "initial_auto") {
return tscrollbar_container::auto_visible_first_run;
} else { } else {
if(!scrollbar_mode.empty() && scrollbar_mode != "auto") { if(!scrollbar_mode.empty() && scrollbar_mode != "auto") {
ERR_GUI_E << "Invalid scrollbar mode '" ERR_GUI_E << "Invalid scrollbar mode '"
<< scrollbar_mode << "' falling back to 'auto'.\n"; << scrollbar_mode << "' falling back to 'auto'.\n";
} }
return tscrollbar_container::SHOW_WHEN_NEEDED; return tscrollbar_container::auto_visible;
} }
} }