Add the initial slider code,

...the length has an off by one error which will be fixed later.
This commit is contained in:
Mark de Wever 2008-07-17 21:01:38 +00:00
parent 4a9a2b02f4
commit fa431a0582
13 changed files with 562 additions and 12 deletions

View file

@ -0,0 +1,94 @@
###
### Definition of a slider.
###
#define STATE IMAGE_SUFFIX GROOVE_COLOUR TEXT_COLOUR
full_redraw = "true"
[draw]
#
# Groove
#
[line]
x1 = 0
y1 = "(height / 2)"
x2 = "(width - 35)"
y2 = "(height / 2)"
colour = {GROOVE_COLOUR}
thickness = 1
[/line]
#
# Text
#
[text]
x = "(width - 30)"
y = {TEXT_V_CENTRE}
w = 30
h = "(height)"
font_size = 16
colour = {TEXT_COLOUR}
text = "(text)"
[/text]
#
# Slider
#
[image]
x = "(positioner_offset)"
y = "(height - image_height) / 2"
name = "buttons/slider" + {IMAGE_SUFFIX} + ".png"
[/image]
[/draw]
#enddef
[slider_definition]
id = "default"
description = "A slider with it's value on the right hand side."
[resolution]
min_width = 50
min_height = 22
default_width = 150
default_height = 22
max_width = 0
max_height = 22
text_font_size = 16
minimum_positioner_length = 16
maximum_positioner_length = 16
left_offset = 0
right_offset = 35
[state_enabled]
{STATE "" "255, 255, 255, 255" "255, 255, 255, 255"}
[/state_enabled]
[state_disabled]
{STATE "-disabled" "255, 255, 255, 255" "255, 255, 255, 255"}
[/state_disabled]
[state_pressed]
{STATE "-selected" "255, 255, 255, 255" "255, 255, 255, 255"}
[/state_pressed]
[state_focussed]
{STATE "-active" "255, 255, 255, 255" "255, 255, 255, 255"}
[/state_focussed]
[/resolution]
[/slider_definition]
#undef STATE

View file

@ -21,6 +21,7 @@ src/gui/widgets/listbox.cpp
src/gui/widgets/panel.cpp
src/gui/widgets/scrollbar.cpp
src/gui/widgets/settings.cpp
src/gui/widgets/slider.cpp
src/gui/widgets/spacer.cpp
src/gui/widgets/text_box.cpp
src/gui/widgets/text.cpp

View file

@ -240,6 +240,7 @@ SET(wesnoth-main_SRC
gui/widgets/listbox.cpp
gui/widgets/panel.cpp
gui/widgets/settings.cpp
gui/widgets/slider.cpp
gui/widgets/spacer.cpp
gui/widgets/scrollbar.cpp
gui/widgets/text.cpp

View file

@ -88,6 +88,7 @@ wesnoth_source = \
gui/widgets/panel.cpp \
gui/widgets/settings.cpp \
gui/widgets/scrollbar.cpp \
gui/widgets/slider.cpp \
gui/widgets/spacer.cpp \
gui/widgets/text.cpp \
gui/widgets/text_box.cpp \

View file

@ -215,6 +215,7 @@ wesnoth_sources = Split("""
gui/widgets/panel.cpp
gui/widgets/settings.cpp
gui/widgets/scrollbar.cpp
gui/widgets/slider.cpp
gui/widgets/spacer.cpp
gui/widgets/text.cpp
gui/widgets/text_box.cpp

View file

@ -207,6 +207,15 @@ void tscrollbar_::set_item_position(const unsigned item_position)
update_canvas();
}
void tscrollbar_::update_canvas() {
foreach(tcanvas& tmp, canvas()) {
tmp.set_variable("positioner_offset", variant(positioner_offset_));
tmp.set_variable("positioner_length", variant(positioner_length_));
}
set_dirty();
}
void tscrollbar_::set_state(const tstate state)
{
if(state != state_) {
@ -286,15 +295,6 @@ void tscrollbar_::recalculate_positioner()
}
}
void tscrollbar_::update_canvas() {
foreach(tcanvas& tmp, canvas()) {
tmp.set_variable("positioner_offset", variant(positioner_offset_));
tmp.set_variable("positioner_length", variant(positioner_length_));
}
set_dirty();
}
void tscrollbar_::move_positioner(const int distance)
{
if(distance < 0 && -distance > static_cast<int>(positioner_offset_)) {

View file

@ -153,6 +153,9 @@ protected:
unsigned get_positioner_length() const { return positioner_length_; }
/** After a recalculation the canvasses also need to be updated. */
virtual void update_canvas();
private:
/**
* Possible states of the widget.
@ -298,9 +301,6 @@ private:
*/
void recalculate_positioner();
/** After a recalculation the canvasses also need to be updated. */
void update_canvas();
/**
* Moves the positioner.
*

View file

@ -177,6 +177,7 @@ const std::string& tgui_definition::read(const config& cfg)
* label_definition A label.
* listbox_definition A listbox.
* panel_definition A panel.
* slider_definition A slider.
* spacer_definition A spacer.
* text_box_definition A single line text box.
* toggle_button_definition A kind of button with two 'states' normal
@ -211,6 +212,7 @@ const std::string& tgui_definition::read(const config& cfg)
load_definitions<tlabel_definition>("label", cfg.get_children("label_definition"));
load_definitions<tlistbox_definition>("listbox", cfg.get_children("listbox_definition"));
load_definitions<tpanel_definition>("panel", cfg.get_children("panel_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"));
load_definitions<ttoggle_button_definition>("toggle_button", cfg.get_children("toggle_button_definition"));
@ -640,6 +642,68 @@ tpanel_definition::tresolution::tresolution(const config& cfg) :
state.push_back(tstate_definition(cfg.child("foreground")));
}
tslider_definition::tslider_definition(const config& cfg) :
tcontrol_definition(cfg)
{
DBG_G_P << "Parsing slider " << id << '\n';
load_resolutions<tresolution>(cfg.get_children("resolution"));
}
tslider_definition::tresolution::tresolution(const config& cfg) :
tresolution_definition_(cfg),
minimum_positioner_length(
lexical_cast_default<unsigned>(cfg["minimum_positioner_length"])),
maximum_positioner_length(
lexical_cast_default<unsigned>(cfg["maximum_positioner_length"])),
left_offset(lexical_cast_default<unsigned>(cfg["left_offset"])),
right_offset(lexical_cast_default<unsigned>(cfg["right_offset"]))
{
/*WIKI
* @page = GUIToolkitWML
* @order = 1_widget_slider
*
* == Slider ==
*
* The definition of a normal slider. A slider is a widget that can be moved by
* the user to indicate the wanted value.
*
* @start_table = config
* minimum_positioner_length (unsigned)
* The minumum size the positioner is
* allowed to be. The engine needs to know
* this in order to calculate the best size
* for the positioner.
* maximum_positioner_length (unsigned = 0)
* The maximum size the positioner is
* allowed to be. If minimum and maximum are
* the same value the positioner is fixed
* size. If the maximum is 0 (and the
* minimum not) there's no maximum.
* left_offset (unsigned = 0) The number of pixels at the left side
* which can't be used by the positioner.
* right_offset (unsigned = 0) The number of pixels at the right side
* which can't be used by the positioner.
* @end_table
*
*
* The following states exist:
* * state_enabled, the slider is enabled.
* * state_disabled, the slider is disabled.
* * state_pressed, the left mouse button is down on the positioner of the slider.
* * state_focussed, the mouse is over the positioner of the slider.
*
*/
VALIDATE(minimum_positioner_length,
missing_mandatory_wml_key("resolution", "minimum_positioner_length"));
// Note the order should be the same as the enum tstate is slider.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_focussed")));
}
tspacer_definition::tspacer_definition(const config& cfg) :
tcontrol_definition(cfg)
{

View file

@ -165,6 +165,22 @@ struct tpanel_definition : public tcontrol_definition
};
};
struct tslider_definition : public tcontrol_definition
{
tslider_definition(const config& cfg);
struct tresolution : public tresolution_definition_
{
tresolution(const config& cfg);
unsigned minimum_positioner_length;
unsigned maximum_positioner_length;
unsigned left_offset;
unsigned right_offset;
};
};
struct tspacer_definition : public tcontrol_definition
{

186
src/gui/widgets/slider.cpp Normal file
View file

@ -0,0 +1,186 @@
/* $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/slider.hpp"
#include "foreach.hpp"
#include "formatter.hpp"
#include "log.hpp"
#include <cassert>
#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 {
static int distance(const int a, const int b)
{
/**
* @todo once this works properly the assert can be removed and the code
* inlined.
*/
int result = b - a;
assert(result >= 0);
return result;
}
void tslider::set_value(const int value)
{
if(value == get_value()) {
return;
}
if(value < minimum_value_) {
set_value(minimum_value_);
} else if(value > get_maximum_value()) {
set_value(get_maximum_value());
} else {
set_item_position(distance(minimum_value_, value));
}
}
void tslider::set_minimum_value(const int minimum_value)
{
if(minimum_value == minimum_value_) {
return;
}
/** @todo maybe make it a VALIDATE. */
assert(minimum_value < get_maximum_value());
const int value = get_value();
const int maximum_value = get_maximum_value();
minimum_value_ = minimum_value;
set_item_count(distance(minimum_value_, maximum_value));
if(value < minimum_value_) {
set_item_position(0);
} else {
set_item_position(minimum_value_ + value);
}
}
void tslider::set_maximum_value(const int maximum_value)
{
if(maximum_value == get_maximum_value()) {
return;
}
/** @todo maybe make it a VALIDATE. */
assert(minimum_value_ < maximum_value);
const int value = get_value();
set_item_count(distance(minimum_value_, maximum_value));
if(value > maximum_value) {
set_item_position(get_maximum_value());
} else {
set_item_position(minimum_value_ + value);
}
}
unsigned tslider::minimum_positioner_length() const
{
const tslider_definition::tresolution* conf =
dynamic_cast<const tslider_definition::tresolution*>(config());
assert(conf);
return conf->minimum_positioner_length;
}
unsigned tslider::maximum_positioner_length() const
{
const tslider_definition::tresolution* conf =
dynamic_cast<const tslider_definition::tresolution*>(config());
assert(conf);
return conf->maximum_positioner_length;
}
unsigned tslider::offset_before() const
{
const tslider_definition::tresolution* conf =
dynamic_cast<const tslider_definition::tresolution*>(config());
assert(conf);
return conf->left_offset;
}
unsigned tslider::offset_after() const
{
const tslider_definition::tresolution* conf =
dynamic_cast<const tslider_definition::tresolution*>(config());
assert(conf);
return conf->right_offset;
}
bool tslider::on_positioner(const tpoint& coordinate) const
{
// Note we assume the positioner is over the entire height of the widget.
return coordinate.x >= static_cast<int>(get_positioner_offset())
&& coordinate.x < static_cast<int>(get_positioner_offset() + get_positioner_length())
&& coordinate.y > 0
&& coordinate.y < static_cast<int>(get_height());
}
int tslider::on_bar(const tpoint& coordinate) const
{
// Not on the widget, leave.
if(coordinate.x < 0 || coordinate.x > get_width()
|| coordinate.y < 0 || coordinate.y > get_height()) {
return 0;
}
// we also assume the bar is over the entire height of the widget.
if(coordinate.x < get_positioner_offset()) {
return -1;
} else if(coordinate.x >get_positioner_offset() + get_positioner_length()) {
return 1;
} else {
return 0;
}
}
void tslider::update_canvas()
{
// Inherited.
tscrollbar_::update_canvas();
foreach(tcanvas& tmp, canvas()) {
tmp.set_variable("text", variant((formatter() << get_value()).str()));
}
}
} // namespace gui2

View file

@ -0,0 +1,99 @@
/* $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_SLIDER_HPP_INCLUDED
#define GUI_WIDGETS_SLIDER_HPP_INCLUDED
#include "gui/widgets/scrollbar.hpp"
namespace gui2 {
/** A slider. */
class tslider : public tscrollbar_, public tinteger_selector_
{
public:
tslider() :
tscrollbar_(),
minimum_value_(0)
{
}
/***** ***** ***** ***** Inherited ***** ***** ***** *****/
/** Inherited from tinteger_selector_. */
void set_value(const int value);
/** Inherited from tinteger_selector_. */
int get_value() const { return minimum_value_ + get_item_position(); }
/** Inherited from tinteger_selector_. */
void set_minimum_value(const int minimum_value);
/** Inherited from tinteger_selector_. */
int get_minimum_value() const { return minimum_value_; }
/** Inherited from tinteger_selector_. */
void set_maximum_value(const int maximum_value);
/** Inherited from tinteger_selector_. */
int get_maximum_value() const { return minimum_value_ + get_item_count(); }
private:
/**
* The minimum value the slider holds.
*
* The maximum value is minimum + item_count_.
* The current value is minimum + item_position_.
*/
int minimum_value_;
/** Inherited from tscrollbar. */
unsigned get_length() const { return get_width(); }
/** Inherited from tscrollbar. */
unsigned minimum_positioner_length() const;
/** Inherited from tscrollbar. */
unsigned maximum_positioner_length() const;
/** Inherited from tscrollbar. */
unsigned offset_before() const;
/** Inherited from tscrollbar. */
unsigned offset_after() const;
/** Inherited from tscrollbar. */
bool on_positioner(const tpoint& coordinate) const;
/** Inherited from tscrollbar. */
int on_bar(const tpoint& coordinate) const;
/** Inherited from tscrollbar. */
int get_length_difference(const tpoint& original, const tpoint& current) const
{ return current.x - original.x; }
/** Inherited from tscrollbar. */
void update_canvas();
/** Inherited from tcontrol. */
const std::string& get_control_type() const
{ static const std::string type = "slider"; return type; }
};
} // namespace gui2
#endif

View file

@ -551,6 +551,36 @@ public:
virtual void set_selected(const bool = true) = 0;
};
/**
* Small abstract helper class.
*
* Parts of the engine inherit this class so we can have generic
* widgets to select an integer value.
*/
class tinteger_selector_
{
public:
virtual ~tinteger_selector_() {}
/** Sets the selected value. */
virtual void set_value(const int value) = 0;
/** Gets the selected value. */
virtual int get_value() const = 0;
/** Sets the minimum value. */
virtual void set_minimum_value(const int value) = 0;
/** Gets the minimum value. */
virtual int get_minimum_value() const = 0;
/** Sets the maximum value. */
virtual void set_maximum_value(const int value) = 0;
/** Gets the maximum value. */
virtual int get_maximum_value() const = 0;
};
} // namespace gui2
#endif

View file

@ -20,6 +20,7 @@
#include "gui/widgets/button.hpp"
#include "gui/widgets/label.hpp"
#include "gui/widgets/listbox.hpp"
#include "gui/widgets/slider.hpp"
#include "gui/widgets/spacer.hpp"
#include "gui/widgets/text_box.hpp"
#include "gui/widgets/toggle_button.hpp"
@ -154,6 +155,42 @@ public:
tbuilder_grid* grid;
};
struct tbuilder_slider : public tbuilder_control
{
private:
tbuilder_slider();
public:
/*WIKI
* @page = GUIToolkitWML
* @order = 3_widget_slider
*
* == Slider ==
*
* @start_table = config
* minimum_value (unsigned = 0) The width of the slider.
* maximum_value (unsigned = 0) The height of the slider.
* step_size (unsigned = 0) The height of the slider.
* value (unsigned = 0) The height of the slider.
* @end_table
*/
tbuilder_slider(const config& cfg) :
tbuilder_control(cfg),
minimum_value_(lexical_cast_default<unsigned>(cfg["minimum_value"])),
maximum_value_(lexical_cast_default<unsigned>(cfg["maximum_value"])),
step_size_(lexical_cast_default<unsigned>(cfg["step_size"])),
value_(lexical_cast_default<unsigned>(cfg["value"]))
{}
twidget* build () const;
private:
int minimum_value_;
int maximum_value_;
int step_size_;
int value_;
};
struct tbuilder_spacer : public tbuilder_control
{
@ -578,6 +615,7 @@ tbuilder_grid::tbuilder_grid(const config& cfg) :
* * label a label.
* * listbox a listbox.
* * panel a panel (a grid which can be drawn on).
* * slider a slider.
* * spacer a filler item.
* * text_box a text box.
* * vertical_scrollbar a vertical scrollbar.
@ -613,6 +651,8 @@ tbuilder_grid::tbuilder_grid(const config& cfg) :
widgets.push_back(new tbuilder_listbox(*((**col_itor).child("listbox"))));
} else if((**col_itor).child("panel")) {
widgets.push_back(new tbuilder_panel(*((**col_itor).child("panel"))));
} else if((**col_itor).child("slider")) {
widgets.push_back(new tbuilder_slider(*((**col_itor).child("slider"))));
} else if((**col_itor).child("spacer")) {
widgets.push_back(new tbuilder_spacer(*((**col_itor).child("spacer"))));
} else if((**col_itor).child("text_box")) {
@ -1010,6 +1050,23 @@ twidget* tbuilder_panel::build() const
return panel;
}
twidget* tbuilder_slider::build() const
{
tslider* slider = new tslider();
init_control(slider);
slider->set_maximum_value(maximum_value_);
slider->set_minimum_value(minimum_value_);
slider->set_step_size(step_size_);
slider->set_value(value_);
DBG_G << "Window builder: placed slider '" << id << "' with defintion '"
<< definition << "'.\n";
return slider;
}
twidget* tbuilder_spacer::build() const
{
tspacer* spacer = new tspacer();