Add the scroll label widget.

This commit is contained in:
Mark de Wever 2008-09-19 16:39:16 +00:00
parent 7d6778fa08
commit 3a47eef6b3
12 changed files with 594 additions and 2 deletions

View file

@ -0,0 +1,150 @@
###
### Definition of a scroll label.
###
#define _GUI_RESOLUTION RESOLUTION FONT_SIZE FONT_STYLE FONT_COLOUR_ENABLED FONT_COLOUR_DISABLED
[resolution]
{RESOLUTION}
min_width = 0
min_height = 0
default_width = 0
default_height = 0
max_width = 0
max_height = 0
text_font_size = {FONT_SIZE}
text_font_style = {FONT_STYLE}
[state_enabled]
full_redraw = "true"
[draw]
[/draw]
[/state_enabled]
[state_disabled]
full_redraw = "true"
[draw]
[/draw]
[/state_disabled]
[grid]
[row]
[column]
[grid]
id = "_content_grid"
[row]
[column]
[label]
id = "_label"
definition = "default"
[/label]
[/column]
[/row]
[/grid]
[/column]
[column]
[grid]
#TODO the definition of this might be one macro...
# evaluate later.
id = "_scrollbar_grid"
[row]
[column]
# note we want a special button definition for this later.
[button]
id = "_half_page_up"
definition = "up_arrow"
[/button]
[/column]
[/row]
[row]
grow_factor = 1
[column]
vertical_grow = "true"
[vertical_scrollbar]
id = "_scrollbar"
definition = "default"
[/vertical_scrollbar]
[/column]
[/row]
[row]
[column]
# note we want a special button definition for this later.
[button]
id = "_half_page_down"
definition = "down_arrow"
[/button]
[/column]
[/row]
[/grid]
[/column]
[/row]
[/grid]
[/resolution]
#enddef
[scroll_label_definition]
id = "default"
description = "The default scroll label."
{_GUI_RESOLUTION
({GUI_TINY__RESOLUTION})
({GUI_TINY__FONT_SIZE__{FONT_SIZE}})
({FONT_STYLE})
({GUI__FONT_COLOUR_ENABLED__{FONT_COLOUR}})
({GUI__FONT_COLOUR_DISABLED__{FONT_COLOUR}})
}
{_GUI_RESOLUTION
({GUI_NORMAL__RESOLUTION})
({GUI_NORMAL__FONT_SIZE__{FONT_SIZE}})
({FONT_STYLE})
({GUI__FONT_COLOUR_ENABLED__{FONT_COLOUR}})
({GUI__FONT_COLOUR_DISABLED__{FONT_COLOUR}})
}
[/scroll_label_definition]
#undef _GUI_RESOLUTION

View file

@ -24,6 +24,7 @@ src/gui/widgets/listbox.cpp
src/gui/widgets/menubar.cpp
src/gui/widgets/minimap.cpp
src/gui/widgets/panel.cpp
src/gui/widgets/scroll_label.cpp
src/gui/widgets/scrollbar.cpp
src/gui/widgets/settings.cpp
src/gui/widgets/slider.cpp

View file

@ -251,6 +251,7 @@ SET(wesnoth-main_SRC
gui/widgets/settings.cpp
gui/widgets/slider.cpp
gui/widgets/spacer.cpp
gui/widgets/scroll_label.cpp
gui/widgets/scrollbar.cpp
gui/widgets/text.cpp
gui/widgets/text_box.cpp

View file

@ -92,6 +92,7 @@ wesnoth_source = \
gui/widgets/minimap.cpp \
gui/widgets/panel.cpp \
gui/widgets/settings.cpp \
gui/widgets/scroll_label.cpp \
gui/widgets/scrollbar.cpp \
gui/widgets/slider.cpp \
gui/widgets/spacer.cpp \

View file

@ -224,6 +224,7 @@ wesnoth_sources = Split("""
gui/widgets/minimap.cpp
gui/widgets/panel.cpp
gui/widgets/settings.cpp
gui/widgets/scroll_label.cpp
gui/widgets/scrollbar.cpp
gui/widgets/slider.cpp
gui/widgets/spacer.cpp

View file

@ -0,0 +1,174 @@
/* $Id$ */
/*
copyright (C) 2008 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 version 2
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.
*/
#include "gui/widgets/scroll_label.hpp"
#include "foreach.hpp"
#include "gui/widgets/label.hpp"
#include "gui/widgets/scrollbar.hpp"
#include "gui/widgets/spacer.hpp"
#include "log.hpp"
#define DBG_G LOG_STREAM_INDENT(debug, gui)
#define LOG_G LOG_STREAM_INDENT(info, gui)
#define WRN_G LOG_STREAM_INDENT(warn, gui)
#define ERR_G LOG_STREAM_INDENT(err, gui)
#define DBG_G_D LOG_STREAM_INDENT(debug, gui_draw)
#define LOG_G_D LOG_STREAM_INDENT(info, gui_draw)
#define WRN_G_D LOG_STREAM_INDENT(warn, gui_draw)
#define ERR_G_D LOG_STREAM_INDENT(err, gui_draw)
#define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
#define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
#define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
#define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
#define DBG_G_P LOG_STREAM_INDENT(debug, gui_parse)
#define LOG_G_P LOG_STREAM_INDENT(info, gui_parse)
#define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
#define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
namespace gui2 {
tscroll_label::tscroll_label()
: tvertical_scrollbar_container_(COUNT)
, state_(ENABLED)
, label_(NULL)
{
}
tscroll_label::~tscroll_label()
{
delete label_;
}
void tscroll_label::set_label(const t_string& label)
{
// Inherit.
tcontrol::set_label(label);
tlabel* widget = find_label(false);
if(widget) {
widget->set_label(label);
}
}
tlabel* tscroll_label::find_label(const bool must_exist)
{
if(label_) {
return label_;
} else {
return find_widget<tlabel>("_label", false, must_exist);
}
}
const tlabel* tscroll_label::find_label(const bool must_exist) const
{
if(label_) {
return label_;
} else {
return find_widget<const tlabel>("_label", false, must_exist);
}
}
tspacer* tscroll_label::find_spacer(const bool must_exist)
{
assert(label_ || !must_exist);
return find_widget<tspacer>("_label", false, must_exist);
}
const tspacer* tscroll_label::find_spacer(const bool must_exist) const
{
assert(label_ || !must_exist);
return find_widget<const tspacer>("_label", false, must_exist);
}
void tscroll_label::finalize()
{
find_label(true)->set_label(label());
tspacer* spacer = new tspacer();
spacer->set_id("_label");
spacer->set_definition("default");
label_ = dynamic_cast<tlabel*>(grid().swap_child("_label", spacer, true));
assert(label_);
}
tpoint tscroll_label::get_content_best_size(const tpoint& maximum_size) const
{
return tpoint(get_content_best_size().x, maximum_size.y);
}
tpoint tscroll_label::get_content_best_size() const
{
assert(label_);
return label_->get_best_size();
}
void tscroll_label::set_content_size(const SDL_Rect& rect)
{
//maybe add a get best height for a label with a given width...
assert(label_);
SDL_Rect size = { 0, 0, get_best_size().x, get_best_size().y };
label_->set_size(size);
tscrollbar_* scrollbar = find_scrollbar(false);
if(scrollbar) {
scrollbar->set_item_count(size.h);
scrollbar->set_visible_items(rect.h);
}
}
void tscroll_label::draw_content(surface& surf, const bool force,
const bool invalidate_background)
{
assert(label_);
if(label_ == NULL) {
find_content_grid()->draw(surf, force, invalidate_background);
return;
}
// For now redraw the label every cycle
surface label_surf(
create_neutral_surface(label_->get_width(), label_->get_height()));
label_->draw(label_surf, true, true);
SDL_Rect src_rect = find_spacer()->get_rect();
src_rect.x = 0;
tscrollbar_* scrollbar = find_scrollbar(false);
src_rect.y = scrollbar ? scrollbar->get_item_position() : 0;
const SDL_Rect dst_rect = find_spacer()->get_rect();
blit_surface(label_surf, &src_rect , surf, &dst_rect);
}
twidget* tscroll_label::find_content_widget(
const tpoint& /*coordinate*/, const bool /*must_be_active*/)
{
return label_;
}
const twidget* tscroll_label::find_content_widget(const tpoint& /*coordinate*/,
const bool /*must_be_active*/) const
{
return label_;
}
} // namespace gui2

View file

@ -0,0 +1,132 @@
/* $Id$ */
/*
copyright (C) 2008 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 version 2
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.
*/
#ifndef GUI_WIDGETS_SCROLL_LABEL_HPP_INCLUDED
#define GUI_WIDGETS_SCROLL_LABEL_HPP_INCLUDED
#include "gui/widgets/vertical_scrollbar_container.hpp"
namespace gui2 {
class tlabel;
class tspacer;
/**
* Label showing a text.
*
* This version shows a scrollbar if the text gets too long and has some
* scrolling features. In general this widget is slower as the normal label so
* the normal label should be preferred.
*/
class tscroll_label : public tvertical_scrollbar_container_
{
friend class tbuilder_scroll_label;
public:
tscroll_label();
~tscroll_label();
/** Inherited from twidget. */
bool has_vertical_scrollbar() const { return true; }
/** *OVERRIDDEN* from tcontrol */
void set_label(const t_string& label);
/** Inherited from tcontainer_. */
void set_self_active(const bool active)
{ state_ = active ? ENABLED : DISABLED; }
/***** ***** ***** setters / getters for members ***** ****** *****/
bool get_active() const { return state_ != DISABLED; }
unsigned get_state() const { return state_; }
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, COUNT };
// It's not needed for now so keep it disabled, no definition exists yet.
// 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_;
/**
* Helper label.
*
* The text is rendered on a separate label widget. After rendering this
* widget the part which can be shown is shown on the dummy spacer. This
* dummy spacer is put in the container so it widget has a size.
*/
tlabel* label_;
/**
* Returns the label widget.
*
* This always returns the label, regardless of the mode.
*/
tlabel* find_label(const bool must_exist = true);
const tlabel* find_label(const bool must_exist = true) const;
/**
* Returns the spacer which is the replacement for the label
*/
tspacer* find_spacer(const bool must_exist = true);
const tspacer* find_spacer(const bool must_exist = true) const;
void finalize();
/***** ***** ***** inherited ****** *****/
/** Inherited from tcontrol. */
const std::string& get_control_type() const
{ static const std::string type = "scroll_label"; return type; }
/** Inherited from tvertical_scrollbar_container_. */
tpoint get_content_best_size(const tpoint& maximum_size) const;
/** Inherited from tvertical_scrollbar_container_. */
tpoint get_content_best_size() const;
/** Inherited from tvertical_scrollbar_container_. */
void set_content_size(const SDL_Rect& rect);
/** Inherited from tvertical_scrollbar_container_. */
void draw_content(surface& surface, const bool force = false,
const bool invalidate_background = false);
/** Inherited from tvertical_scrollbar_container_. */
twidget* find_content_widget(
const tpoint& coordinate, const bool must_be_active);
/** Inherited from tvertical_scrollbar_container_. */
const twidget* find_content_widget(const tpoint& coordinate,
const bool must_be_active) const;
};
} // namespace gui2
#endif

View file

@ -193,6 +193,7 @@ const std::string& tgui_definition::read(const config& cfg)
* label_definition A label.
* listbox_definition A listbox.
* panel_definition A panel.
* scroll_label_definition A scroll_label.
* slider_definition A slider.
* spacer_definition A spacer.
* text_box_definition A single line text box.
@ -230,6 +231,7 @@ const std::string& tgui_definition::read(const config& cfg)
load_definitions<tmenubar_definition>("menubar", cfg.get_children("menubar_definition"));
load_definitions<tminimap_definition>("minimap", cfg.get_children("minimap_definition"));
load_definitions<tpanel_definition>("panel", cfg.get_children("panel_definition"));
load_definitions<tscroll_label_definition>("scroll_label", cfg.get_children("scroll_label_definition"));
load_definitions<tslider_definition>("slider", cfg.get_children("slider_definition"));
load_definitions<tspacer_definition>("spacer", cfg.get_children("spacer_definition"));
load_definitions<ttext_box_definition>("text_box", cfg.get_children("text_box_definition"));
@ -714,7 +716,7 @@ tpanel_definition::tresolution::tresolution(const config& cfg) :
*
* The following layers exist:
* * background, the background of the panel.
* * foreground, the foreground of the panel/
* * foreground, the foreground of the panel.
*/
// The panel needs to know the order.
@ -722,6 +724,60 @@ tpanel_definition::tresolution::tresolution(const config& cfg) :
state.push_back(tstate_definition(cfg.child("foreground")));
}
tscroll_label_definition::tscroll_label_definition(const config& cfg) :
tcontrol_definition(cfg)
{
DBG_G_P << "Parsing scroll label " << id << '\n';
load_resolutions<tresolution>(cfg.get_children("resolution"));
}
tscroll_label_definition::tresolution::tresolution(const config& cfg) :
tresolution_definition_(cfg),
grid(NULL)
{
/*WIKI
* @page = GUIToolkitWML
* @order = 1_widget_scroll_label
*
* == Scroll label ==
*
* The definition of a normal scroll label. A scroll label is a label that
* wraps its text and also has a vertical scrollbar. This way a text can't be
* too long to be shown for this widget. This widget is slower as a normal
* label widget so only use this widget when the scrollbar is required (or
* expected to become required).
*
* @start_table = config
* grid (section) A grid containing the widgets for main
* widget.
* @end_table
*
* TODO we need one definition for a vertical scrollbar since this is the second
* time we use it.
*
* @start_table = container
* _content_grid (grid) A grid which should only contain one
* label widget.
* _scrollbar_grid (grid) A grid for the scrollbar
* (Merge with listbox info.)
* @end_table
*
* The following states exist:
* * state_enabled, the scroll label is enabled.
* * state_disabled, the scroll label is disabled.
*
*/
// Note the order should be the same as the enum tstate is scroll_label.hpp.
state.push_back(tstate_definition(cfg.child("state_enabled")));
state.push_back(tstate_definition(cfg.child("state_disabled")));
const config* child = cfg.child("grid");
VALIDATE(child, _("No grid defined."));
grid = new tbuilder_grid(*child);
}
tslider_definition::tslider_definition(const config& cfg) :
tcontrol_definition(cfg)
{

View file

@ -204,6 +204,19 @@ struct tpanel_definition : public tcontrol_definition
};
};
struct tscroll_label_definition : public tcontrol_definition
{
tscroll_label_definition(const config& cfg);
struct tresolution : public tresolution_definition_
{
tresolution(const config& cfg);
tbuilder_grid_ptr grid;
};
};
struct tslider_definition : public tcontrol_definition
{
tslider_definition(const config& cfg);

View file

@ -26,7 +26,7 @@ class tvertical_scrollbar_container_ : public tcontainer_
{
// Builders need to be able to finalize the object.
friend class tbuilder_listbox;
friend class tbuilder_scroll_label;
// Callbacks can call update routines. Note these are not further declared
// here only need external linkage to be friends.

View file

@ -20,6 +20,7 @@
#include "gui/widgets/label.hpp"
#include "gui/widgets/listbox.hpp"
#include "gui/widgets/minimap.hpp"
#include "gui/widgets/scroll_label.hpp"
#include "gui/widgets/slider.hpp"
#include "gui/widgets/spacer.hpp"
#include "gui/widgets/text_box.hpp"
@ -401,6 +402,8 @@ tbuilder_grid::tbuilder_grid(const config& cfg) :
widgets.push_back(new tbuilder_minimap(*((**col_itor).child("minimap"))));
} else if((**col_itor).child("panel")) {
widgets.push_back(new tbuilder_panel(*((**col_itor).child("panel"))));
} else if((**col_itor).child("scroll_label")) {
widgets.push_back(new tbuilder_scroll_label(*((**col_itor).child("scroll_label"))));
} else if((**col_itor).child("slider")) {
widgets.push_back(new tbuilder_slider(*((**col_itor).child("slider"))));
} else if((**col_itor).child("spacer")) {
@ -584,6 +587,8 @@ tbuilder_gridcell::tbuilder_gridcell(const config& cfg) :
widget=new tbuilder_minimap(*((cfg).child("minimap")));
} else if((cfg).child("panel")) {
widget=new tbuilder_panel(*((cfg).child("panel")));
} else if((cfg).child("scroll_label")) {
widget=new tbuilder_scroll_label(*((cfg).child("scroll_label")));
} else if((cfg).child("slider")) {
widget=new tbuilder_slider(*((cfg).child("slider")));
} else if((cfg).child("spacer")) {
@ -971,6 +976,33 @@ twidget* tbuilder_panel::build() const
return panel;
}
twidget* tbuilder_scroll_label::build() const
{
tscroll_label* widget = new tscroll_label();
init_control(widget);
boost::intrusive_ptr<const tscroll_label_definition::tresolution> conf =
boost::dynamic_pointer_cast<const tscroll_label_definition::tresolution>(widget->config());
assert(conf);
tgrid* grid = dynamic_cast<tgrid*>(conf->grid->build());
assert(grid);
widget->grid().set_rows_cols(1, 1);
widget->grid().set_child(grid, 0, 0,
tgrid::VERTICAL_GROW_SEND_TO_CLIENT
| tgrid::HORIZONTAL_GROW_SEND_TO_CLIENT
, 0);
widget->finalize_setup();
DBG_G << "Window builder: placed scroll label '" << id << "' with defintion '"
<< definition << "'.\n";
return widget;
}
tbuilder_slider::tbuilder_slider(const config& cfg) :
tbuilder_control(cfg),
best_slider_length_(lexical_cast_default<unsigned>(cfg["best_slider_length"])),

View file

@ -206,6 +206,37 @@ private:
std::vector<t_string> value_labels_;
};
struct tbuilder_scroll_label : public tbuilder_control
{
public:
/*WIKI
* @page = GUIToolkitWML
* @order = 3_widget_scroll_label
*
* == Scroll label ==
*
* A scroll label has no special fields.
*
* @start_table = config
* auto_hide_scrollbar (bool = true)
* Automatically hide the scrollbar when the
* text can be shown without the scrollbar.
* @end_table
*/
tbuilder_scroll_label(const config& cfg)
: tbuilder_control(cfg)
, auto_hide_scrollbar_(
utils::string_bool(cfg["auto_hide_scrollbar"], true))
{
}
twidget* build () const;
private:
bool auto_hide_scrollbar_;
};
struct tbuilder_spacer : public tbuilder_control
{