Started to implement the grid flags:

- panel no longer decends from a grid but contains one, give less problems with
  the functions with the same name.

- flags are read from the .cfg file.

Still more testing and some cleaning up is required.
This commit is contained in:
Mark de Wever 2008-04-07 18:16:30 +00:00
parent adaa158611
commit 0f420d967a
16 changed files with 642 additions and 130 deletions

View file

@ -19,8 +19,14 @@
[grid]
[row]
scale = 1
[column]
scale = 0
border = "all"
border_size = 5
horizontal_alignment = "left"
[label]
label_definition = "default"
@ -31,6 +37,11 @@
[/column]
[column]
scale = 1
border = "all"
border_size = 5
horizontal_grow = "true"
[text_box]
id = "host_name"
@ -45,6 +56,7 @@
[/row]
[row]
scale = 0
[column]
@ -58,6 +70,9 @@
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
# just show how the default looks.
@ -77,8 +92,12 @@
[/row]
[row]
scale = 0
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "ok"
@ -91,6 +110,9 @@
[/column]
[column]
border = "all"
border_size = 5
horizontal_alignment = "right"
[button]
id = "cancel"

View file

@ -97,6 +97,15 @@ void tbutton::mouse_left_button_double_click(tevent_handler&)
DBG_G_E << "Button: left mouse button double click.\n";
}
tpoint tbutton::get_minimum_size() const
{
if(definition_ == std::vector<tbutton_definition::tresolution>::const_iterator()) {
return tpoint(get_button(definition())->min_width, get_button(definition())->min_height);
} else {
return tpoint(definition_->min_width, definition_->min_height);
}
}
tpoint tbutton::get_best_size() const
{
if(definition_ == std::vector<tbutton_definition::tresolution>::const_iterator()) {
@ -106,6 +115,15 @@ tpoint tbutton::get_best_size() const
}
}
tpoint tbutton::get_maximum_size() const
{
if(definition_ == std::vector<tbutton_definition::tresolution>::const_iterator()) {
return tpoint(get_button(definition())->max_width, get_button(definition())->max_height);
} else {
return tpoint(definition_->max_width, definition_->max_height);
}
}
void tbutton::set_best_size(const tpoint& origin)
{
resolve_definition();

View file

@ -43,7 +43,10 @@ public:
void mouse_left_button_double_click(tevent_handler&); //FIXME remove
// note we should check whether the label fits in the button
// Inherited from twidget.
tpoint get_minimum_size() const;
tpoint get_best_size() const;
tpoint get_maximum_size() const;
void set_best_size(const tpoint& origin);

View file

@ -70,6 +70,18 @@ void tcontrol::set_height(const unsigned height)
twidget::set_height(height);
}
void tcontrol::set_size(const SDL_Rect& rect)
{
// resize canvasses
foreach(tcanvas& canvas, canvas_) {
canvas.set_width(rect.w);
canvas.set_height(rect.h);
}
// inherited
twidget::set_size(rect);
}
void tcontrol::set_label(const std::string& label)
{
if(label == label_) {

View file

@ -37,6 +37,9 @@ public:
//! Inherited from twidget.
void set_height(const unsigned height);
//! Inherited from twidget.
void set_size(const SDL_Rect& rect);
void set_visible(const bool visible)
{ if(visible_ != visible) { visible_ = visible; set_dirty();} }
bool get_visible() const { return visible_; }

View file

@ -14,6 +14,7 @@
#include "gui/widgets/grid.hpp"
#include "foreach.hpp"
#include "log.hpp"
#include <cassert>
@ -48,6 +49,14 @@ tgrid::tgrid(const unsigned rows, const unsigned cols,
cols_(cols),
default_flags_(default_flags),
default_border_size_(default_border_size),
best_row_height_(),
best_col_width_(),
minimum_row_height_(),
minimum_col_width_(),
row_height_(),
col_width_(),
row_scaling_(),
col_scaling_(),
children_(rows * cols)
{
}
@ -89,6 +98,8 @@ void tgrid::add_child(twidget* widget, const unsigned row,
} else {
cell.set_id("");
}
clear_cache();
}
void tgrid::set_rows(const unsigned rows)
@ -122,7 +133,10 @@ void tgrid::set_rows_cols(const unsigned rows, const unsigned cols)
rows_ = rows;
cols_ = cols;
row_scaling_.resize(rows);
col_scaling_.resize(cols);
children_.resize(rows_ * cols_);
clear_cache();
}
void tgrid::remove_child(const unsigned row, const unsigned col)
@ -133,6 +147,7 @@ void tgrid::remove_child(const unsigned row, const unsigned col)
cell.set_id("");
cell.set_widget(0);
clear_cache();
}
void tgrid::remove_child(const std::string& id, const bool find_all)
@ -143,6 +158,7 @@ void tgrid::remove_child(const std::string& id, const bool find_all)
if(itor->id() == id) {
itor->set_id("");
itor->set_widget(0);
clear_cache();
if(!find_all) {
break;
@ -151,90 +167,155 @@ void tgrid::remove_child(const std::string& id, const bool find_all)
}
}
tpoint tgrid::get_best_size()
tpoint tgrid::get_best_size() const
{
std::vector<unsigned> best_col_width(cols_, 0);
std::vector<unsigned> best_row_height(rows_, 0);
if(best_row_height_.empty() || best_col_width_.empty()) {
DBG_G << "Grid: calculate best size.\n";
best_row_height_.resize(rows_, 0);
best_col_width_.resize(cols_, 0);
// First get the best sizes for all items.
for(unsigned row = 0; row < rows_; ++row) {
for(unsigned col = 0; col < cols_; ++col) {
const tpoint size = child(row, col).get_best_size();
tpoint size = child(row, col).get_best_size();
if(size.x > best_col_width[col]) {
best_col_width[col] = size.x;
if(size.x > best_col_width_[col]) {
best_col_width_[col] = size.x;
}
if(size.y > best_row_height[row]) {
best_row_height[row] = size.y;
if(size.y > best_row_height_[row]) {
best_row_height_[row] = size.y;
}
}
}
} else {
DBG_G << "Grid: used cached best size.\n";
}
for(unsigned row = 0; row < rows_; ++row) {
DBG_G << "Grid: the best height for row " << row
<< " will be " << best_row_height[row] << ".\n";
<< " will be " << best_row_height_[row] << ".\n";
}
for(unsigned col = 0; col < cols_; ++col) {
DBG_G << "Grid: the best width for col " << col
<< " will be " << best_col_width[col] << ".\n";
<< " will be " << best_col_width_[col] << ".\n";
}
return tpoint(
std::accumulate(best_col_width.begin(), best_col_width.end(), 0),
std::accumulate(best_row_height.begin(), best_row_height.end(), 0));
std::accumulate(best_col_width_.begin(), best_col_width_.end(), 0),
std::accumulate(best_row_height_.begin(), best_row_height_.end(), 0));
}
void tgrid::set_best_size(const tpoint& origin)
{
std::vector<unsigned> best_col_width(cols_, 0);
std::vector<unsigned> best_row_height(rows_, 0);
// Update the sizes.
get_best_size();
assert(best_col_width_.size() == cols_);
assert(best_row_height_.size() == rows_);
// First get the best sizes for all items. (FIXME copy and paste of get best size)
for(unsigned row = 0; row < rows_; ++row) {
for(unsigned col = 0; col < cols_; ++col) {
row_height_ = best_row_height_;
col_width_ = best_col_width_;
const tpoint size = child(row, col).get_best_size();
if(size.x > best_col_width[col]) {
best_col_width[col] = size.x;
}
if(size.y > best_row_height[row]) {
best_row_height[row] = size.y;
}
layout(origin);
return;
}
void tgrid::set_size(const SDL_Rect& rect)
{
twidget::set_size(rect);
const tpoint orig(rect.x, rect.y);
const tpoint size(rect.w, rect.h);
const tpoint best_size = get_best_size();
row_height_ = best_row_height_;
col_width_ = best_col_width_;
assert(row_height_.size() == rows_);
assert(col_width_.size() == cols_);
assert(row_scaling_.size() == rows_);
assert(col_scaling_.size() == cols_);
if(best_size == size) {
row_height_ = best_row_height_;
col_width_ = best_col_width_;
layout(orig);
return;
}
// Set the sizes
tpoint orig = origin;
for(unsigned row = 0; row < rows_; ++row) {
for(unsigned col = 0; col < cols_; ++col) {
if(best_size < size) {
row_height_ = best_row_height_;
col_width_ = best_col_width_;
DBG_G << "Grid: set widget at " << row
<< ',' << col << " at origin " << orig << ".\n";
// expand it.
const unsigned w = size.x - best_size.x;
unsigned w_size = std::accumulate(col_scaling_.begin(), col_scaling_.end(), 0);
DBG_G << "Grid: extra width " << w << " will be divided amount " << w_size << " units in " << cols_ << " columns.\n";
if(child(row, col).widget()) {
child(row, col).widget()->set_best_size(orig);
if(w_size == 0) {
// If all sizes are 0 reset them to 1
foreach(unsigned& val, col_scaling_) {
val = 1;
}
w_size = cols_;
}
// We might have a bit 'extra' if the division doesn't fix exactly
// but we ignore that part for now.
const unsigned w_normal = w / w_size;
for(unsigned i = 0; i < cols_; ++i) {
col_width_[i] += w_normal * col_scaling_[i];
DBG_G << "Grid: column " << i << " with scale factor "
<< col_scaling_[i] << " set width to " << col_width_[i] << ".\n";
}
orig.x += best_col_width[col];
const unsigned h = size.y - best_size.y;
unsigned h_size = std::accumulate(row_scaling_.begin(), row_scaling_.end(), 0);
DBG_G << "Grid: extra height " << h << " will be divided amount " << h_size << " units in " << rows_ << " rows.\n";
if(h_size == 0) {
// If all sizes are 0 reset them to 1
foreach(unsigned& val, row_scaling_) {
val = 1;
}
orig.y += best_row_height[row];
orig.x = origin.x;
h_size = rows_;
}
// We might have a bit 'extra' if the division doesn't fix exactly
// but we ignore that part for now.
const unsigned h_normal = h / h_size;
for(unsigned i = 0; i < rows_; ++i) {
row_height_[i] += h_normal * row_scaling_[i];
DBG_G << "Grid: row " << i << " with scale factor "
<< row_scaling_[i] << " set height to " << row_height_[i] << ".\n";
}
layout(orig);
return;
}
// FIXME make other cases work as well
assert(false);
/*
const tpoint minimum_size = get_minimum_size();
if(minimum_size == size) {
*/
}
twidget* tgrid::get_widget(const tpoint& coordinate)
{
//! FIXME we need to store the sizes, since this is quite
//! pathatic.
//! FIXME use iterator.
for(unsigned row = 0; row < rows_; ++row) {
for(unsigned col = 0; col < cols_; ++col) {
@ -245,6 +326,7 @@ twidget* tgrid::get_widget(const tpoint& coordinate)
widget = widget->get_widget(coordinate);
if(widget) {
clear_cache();
return widget;
}
}
@ -257,9 +339,7 @@ twidget* tgrid::get_widget(const tpoint& coordinate)
//! Override base class.
twidget* tgrid::get_widget_by_id(const std::string& id)
{
//! FIXME we need to store the sizes, since this is quite
//! pathatic.
//! FIXME use iterator.
for(unsigned row = 0; row < rows_; ++row) {
for(unsigned col = 0; col < cols_; ++col) {
@ -270,6 +350,7 @@ twidget* tgrid::get_widget_by_id(const std::string& id)
widget = widget->get_widget_by_id(id);
if(widget) {
clear_cache();
return widget;
}
}
@ -278,24 +359,170 @@ twidget* tgrid::get_widget_by_id(const std::string& id)
return twidget::get_widget_by_id(id);
}
tpoint tgrid::tchild::get_best_size()
void tgrid::clear_cache()
{
if(!dirty_ && (!widget_ || !widget_->dirty())) {
best_row_height_.clear();
best_col_width_.clear();
minimum_row_height_.clear();
minimum_col_width_.clear();
}
void tgrid::layout(const tpoint& origin)
{
tpoint orig = origin;
for(unsigned row = 0; row < rows_; ++row) {
for(unsigned col = 0; col < cols_; ++col) {
const tpoint size(col_width_[col], row_height_[row]);
DBG_G << "Grid: set widget at " << row << ',' << col
<< " at origin " << orig << " with size " << size << ".\n";
if(child(row, col).widget()) {
child(row, col).set_size(orig, size);
}
orig.x += col_width_[col];
}
orig.y += row_height_[row];
orig.x = origin.x;
}
}
tpoint tgrid::tchild::get_best_size() const
{
if(!widget_) {
return tpoint(0, 0);
}
if(widget_->dirty() || best_size_ == tpoint(0, 0)) {
best_size_ = widget_->get_best_size();
if(border_size_) {
if(flags_ & BORDER_TOP) best_size_.y += border_size_;
if(flags_ & BORDER_BOTTOM) best_size_.y += border_size_;
if(flags_ & BORDER_LEFT) best_size_.x += border_size_;
if(flags_ & BORDER_RIGHT) best_size_.x += border_size_;
}
}
return best_size_;
}
best_size_ = widget_ ? widget_->get_best_size() : tpoint(0, 0);
//FIXME take care of the border configuration.
best_size_.x += 2 * border_size_;
best_size_.y += 2 * border_size_;
dirty_ = false;
return best_size_;
void tgrid::tchild::set_size(tpoint orig, tpoint size)
{
assert(widget());
widget()->set_best_size(orig); // needed for calling resolve_resolution()
if(border_size_) {
if(flags_ & BORDER_TOP) {
orig.y += border_size_;
size.y -= border_size_;
}
if(flags_ & BORDER_BOTTOM) {
size.y -= border_size_;
}
if(flags_ & BORDER_LEFT) {
orig.x += border_size_;
size.x -= border_size_;
}
if(flags_ & BORDER_RIGHT) {
size.x -= border_size_;
}
}
// If size smaller or equal to best size set that size.
// No need to check > min size since this is what we got.
const tpoint best_size = widget()->get_best_size();
if(size <= best_size) {
DBG_G << "Grid cell: in best size range setting widget to "
<< orig << " x " << size << ".\n";
widget()->set_size(create_rect(orig, size));
return;
}
const tpoint maximum_size = widget()->get_maximum_size();
if(flags_ & (HORIZONTAL_GROW_SEND_TO_CLIENT | HORIZONTAL_GROW_SEND_TO_CLIENT)) {
if(maximum_size == tpoint(0,0) || size <= maximum_size) {
DBG_G << "Grid cell: in maximum size range setting widget to "
<< orig << " x " << size << ".\n";
widget()->set_size(create_rect(orig, size));
return;
}
}
tpoint widget_size = best_size;
tpoint widget_orig = orig;
if(flags_ & HORIZONTAL_GROW_SEND_TO_CLIENT) {
if(maximum_size.x) {
widget_size.x = std::min(size.x, maximum_size.x);
} else {
widget_size.x = size.x;
}
DBG_G << "Grid cell: horizontal growing from " << best_size.x << " to " << widget_size.x << ".\n";
}
if(flags_ & VERTICAL_GROW_SEND_TO_CLIENT) {
if(maximum_size.y) {
widget_size.y = std::min(size.y, maximum_size.y);
} else {
widget_size.y = size.y;
}
DBG_G << "Grid cell: vertical growing from " << best_size.y << " to " << widget_size.y << ".\n";
}
if((flags_ & VERTICAL_ALIGN_TOP) == VERTICAL_ALIGN_TOP) {
// Do nothing.
DBG_G << "Grid cell: vertically aligned at the top.\n";
} else if((flags_ & VERTICAL_ALIGN_CENTER) == VERTICAL_ALIGN_CENTER) {
widget_orig.y += (size.y - widget_size.y) / 2;
DBG_G << "Grid cell: vertically centred.\n";
} else if((flags_ & VERTICAL_ALIGN_BOTTOM) == VERTICAL_ALIGN_BOTTOM) {
widget_orig.y += (size.y - widget_size.y);
DBG_G << "Grid cell: vertically aligned at the bottom.\n";
} else {
assert(false);
}
if((flags_ & HORIZONTAL_ALIGN_LEFT) == HORIZONTAL_ALIGN_LEFT) {
// Do nothing.
DBG_G << "Grid cell: horizontally aligned at the left.\n";
} else if((flags_ & HORIZONTAL_ALIGN_CENTER) == HORIZONTAL_ALIGN_CENTER) {
widget_orig.x += (size.x - widget_size.x) / 2;
DBG_G << "Grid cell: horizontally centred.\n";
} else if((flags_ & HORIZONTAL_ALIGN_RIGHT) == HORIZONTAL_ALIGN_RIGHT) {
widget_orig.x += (size.x - widget_size.x);
DBG_G << "Grid cell: horizontally aligned at the right.\n";
} else {
assert(false);
}
DBG_G << "Grid cell: resize widget to "
<< widget_orig << " x " << widget_size << ".\n";
widget()->set_size(create_rect(widget_orig, widget_size));
}
} // namespace gui2

View file

@ -26,22 +26,22 @@ class tgrid : public virtual twidget
public:
// ***** ***** FLAGS ***** *****
static const unsigned VERTICAL_RESIZE_GROW = 1 << 1;
// static const unsigned VERTICAL_RESIZE_GROW = 1 << 1;
static const unsigned VERTICAL_GROW_SEND_TO_CLIENT = 1 << 2;
static const unsigned VERTICAL_ALIGN_TOP = 1 << 4;
static const unsigned VERTICAL_ALIGN_CENTER = 1 << 5;
static const unsigned VERTICAL_ALIGN_BOTTOM = 1 << 6;
static const unsigned VERTICAL_ALIGN_LANGUAGE = 1 << 7;
static const unsigned VERTICAL_ALIGN_TOP = 3 << 4;
static const unsigned VERTICAL_ALIGN_CENTER = 2 << 4;
static const unsigned VERTICAL_ALIGN_BOTTOM = 1 << 4;
// static const unsigned VERTICAL_ALIGN_LANGUAGE = 0 << 4;
static const unsigned HORIZONTAL_RESIZE_GROW = 1 << 16;
// static const unsigned HORIZONTAL_RESIZE_GROW = 1 << 16;
static const unsigned HORIZONTAL_GROW_SEND_TO_CLIENT = 1 << 17;
static const unsigned HORIZONTAL_ALIGN_TOP = 1 << 18;
static const unsigned HORIZONTAL_ALIGN_CENTER = 1 << 19;
static const unsigned HORIZONTAL_ALIGN_BOTTOM = 1 << 20;
static const unsigned HORIZONTAL_ALIGN_LANGUAGE = 1 << 21;
static const unsigned HORIZONTAL_ALIGN_LEFT = 3 << 18;
static const unsigned HORIZONTAL_ALIGN_CENTER = 2 << 18;
static const unsigned HORIZONTAL_ALIGN_RIGHT = 1 << 18;
// static const unsigned HORIZONTAL_ALIGN_LANGUAGE = 0 << 18;
static const unsigned BORDER_TOP = 1 << 24;
@ -55,15 +55,16 @@ public:
virtual ~tgrid();
void add_child(twidget* widget, const unsigned row,
const unsigned col, const unsigned flags, const unsigned border_size);
void add_child(twidget* widget, const unsigned row, const unsigned col)
{ add_child(widget, row, col, default_flags_, default_border_size_); }
#if 0
// FIXME if these are really not needed remove them.
void add_child(twidget* widget, const unsigned row, const unsigned col, const unsigned flags)
{ add_child(widget, row, col, flags, default_border_size_); }
void add_child(twidget* widget, const unsigned row, const unsigned col)
{ add_child(widget, row, col, default_flags_, default_border_size_); }
#endif
void add_child(twidget* widget, const unsigned row,
const unsigned col, const unsigned flags, const unsigned border_size);
void set_rows(const unsigned rows);
unsigned int get_rows() const { return rows_; }
@ -73,15 +74,28 @@ public:
void set_rows_cols(const unsigned rows, const unsigned cols);
void set_row_scaling(const unsigned row, const unsigned scale)
{ row_scaling_[row] = scale; set_dirty(); } //FIXME add assert.
void set_col_scaling(const unsigned col, const unsigned scale)
{ col_scaling_[col] = scale; set_dirty(); } //FIXME add assert.
void remove_child(const unsigned row, const unsigned col);
void remove_child(const std::string& id, const bool find_all = false);
//! Inherited
tpoint get_best_size();
//FIXME add the option to set the proportional growth for each row and column
//! Inherited
//! Inherited from twidget.
tpoint get_minimum_size() const { /*FIXME IMPLEMENT*/ return tpoint(0,0); }
tpoint get_best_size() const;
tpoint get_maximum_size() const { /*FIXME IMPLEMENT*/ return tpoint(0,0); }
//! Inherited from twidget.
void set_best_size(const tpoint& origin);
//! Inherited from twidget.
void set_size(const SDL_Rect& rect);
//! Gets the widget at the wanted coordinates.
//! Override base class.
twidget* get_widget(const tpoint& coordinate);
@ -90,6 +104,9 @@ public:
//! Override base class.
twidget* get_widget_by_id(const std::string& id);
//! Inherited from twidget.
void draw(surface& surface) { /* FIXME IMPLEMENT */ }
private:
class tchild
{
@ -100,7 +117,7 @@ private:
border_size_(0),
widget_(0),
best_size_(0, 0),
dirty_(true),
minimum_size_(0, 0),
clip_()
// Fixme make a class wo we can store some properties in the cache
@ -111,18 +128,20 @@ private:
void set_id(const std::string& id) { id_ = id; }
unsigned get_flags() const { return flags_; }
void set_flags(const unsigned flags) { flags_ = flags; dirty_ = true; }
void set_flags(const unsigned flags) { flags_ = flags; set_dirty(); }
unsigned get_border_size() const { return border_size_; }
void set_border_size(const unsigned border_size)
{ border_size_ = border_size; dirty_ = true; }
{ border_size_ = border_size; set_dirty(); }
twidget* widget() { return widget_; }
void set_widget(twidget* widget) { widget_ = widget; dirty_ = true; }
void set_widget(twidget* widget) { widget_ = widget; set_dirty(); }
//! Gets the best size for the cell, not const since we modify the internal
//! state, might use mutable later (if really needed).
tpoint get_best_size();
tpoint get_best_size() const;
void set_size(tpoint orig, tpoint size);
private:
//! The id of the widget if it has a widget.
@ -140,15 +159,23 @@ private:
//! The best size for this cell, determined by the best size
//! of the widget and the border_size_ and flags_.
tpoint best_size_;
mutable tpoint best_size_;
//! Tracks the dirty state of the cell regarding best_size_.
bool dirty_;
//! The minimum size for this cell, like best_size_.
mutable tpoint minimum_size_;
//! The clipping area for the widget. This is also the size of
//! the container.
SDL_Rect clip_;
//! Sets the calculations to be dirty, this means all caches
//! are simply cleared.
void set_dirty() // FIXME rename to clear cache??
{
best_size_ = tpoint(0, 0);
minimum_size_ = tpoint(0, 0);
}
}; // class tchild
public:
@ -178,33 +205,101 @@ public:
iterator end() { return iterator(children_.end()); }
private:
//! The number of rows / columns.
unsigned rows_;
unsigned cols_;
//! Default flags for a grid cell.
const unsigned default_flags_;
//! Default border size for a grid cell.
const unsigned default_border_size_;
//! The optimal row heights / col widths.
mutable std::vector<unsigned> best_row_height_; //FIXME implement
mutable std::vector<unsigned> best_col_width_; //FIXME implement
//! The minimal row heights / col widths.
mutable std::vector<unsigned> minimum_row_height_; //FIXME implement
mutable std::vector<unsigned> minimum_col_width_; //FIXME implement
//! The row heights / col widths currently used.
std::vector<unsigned> row_height_;
std::vector<unsigned> col_width_;
//! The resize factors for rows / cols.
std::vector<unsigned> row_scaling_;
std::vector<unsigned> col_scaling_;
//! Contains all cells.
std::vector<tchild> children_;
tchild& child(const unsigned row, const unsigned col)
const tchild& child(const unsigned row, const unsigned col) const
{ return children_[rows_ * col + row]; }
tchild& child(const unsigned row, const unsigned col)
{ clear_cache(); return children_[rows_ * col + row]; }
void clear_cache();
void layout(const tpoint& origin);
};
//! Visible container to hold children.
class tpanel : public tgrid, public tcontrol
class tpanel : public tcontrol
{
public:
tpanel() :
tgrid(0, 0, 0, 0),
tcontrol(0)
{}
tcontrol(0),
grid_(0, 0, 0, 0)
{
grid_.set_parent(this);
}
// Inherited from twidget.
twidget* get_widget(const tpoint& coordinate) { return grid_.get_widget(coordinate); }
// Inherited from twidget.
twidget* get_widget_by_id(const std::string& id) { return grid_.get_widget_by_id(id); }
// Inherited from twidget.
bool dirty() const { return twidget::dirty() || grid_.dirty(); }
//***** **** wrappers to the grid **** ****
tgrid::iterator begin() { return grid_.begin(); }
tgrid::iterator end() { return grid_.end(); }
void set_client_size(const SDL_Rect& rect) { grid_.set_size(rect); }
void set_rows(const unsigned rows) { grid_.set_rows(rows); }
unsigned int get_rows() const { return grid_.get_rows(); }
void set_cols(const unsigned cols) { grid_.set_cols(cols); }
unsigned int get_cols() const { return grid_.get_cols(); }
void set_rows_cols(const unsigned rows, const unsigned cols)
{ grid_.set_rows_cols(rows, cols); }
#if 0
// FIXME if these are really not needed remove them.
void add_child(twidget* widget, const unsigned row, const unsigned col)
{ grid_.add_child(widget, row, col); }
void add_child(twidget* widget, const unsigned row, const unsigned col, const unsigned flags)
{ grid_.add_child(widget, row, col, flags); }
#endif
void add_child(twidget* widget, const unsigned row,
const unsigned col, const unsigned flags, const unsigned border_size)
{ grid_.add_child(widget, row, col, flags, border_size); }
void set_row_scaling(const unsigned row, const unsigned scale)
{ grid_.set_row_scaling(row, scale); }
void set_col_scaling(const unsigned col, const unsigned scale)
{ grid_.set_col_scaling(col, scale); }
private:
tgrid grid_;
};

View file

@ -39,6 +39,15 @@
namespace gui2 {
tpoint tlabel::get_minimum_size() const
{
if(definition_ == std::vector<tlabel_definition::tresolution>::const_iterator()) {
return tpoint(get_label(definition())->min_width, get_label(definition())->min_height);
} else {
return tpoint(definition_->min_width, definition_->min_height);
}
}
tpoint tlabel::get_best_size() const
{
if(definition_ == std::vector<tlabel_definition::tresolution>::const_iterator()) {
@ -48,6 +57,15 @@ tpoint tlabel::get_best_size() const
}
}
tpoint tlabel::get_maximum_size() const
{
if(definition_ == std::vector<tlabel_definition::tresolution>::const_iterator()) {
return tpoint(get_label(definition())->max_width, get_label(definition())->max_height);
} else {
return tpoint(definition_->max_width, definition_->max_height);
}
}
void tlabel::mouse_hover(tevent_handler&)
{
DBG_G_E << "Text_box: mouse hover.\n";

View file

@ -39,7 +39,10 @@ public:
void draw(surface& surface);
// note we should check whether the label fits in the label
// Inherited from twidget.
tpoint get_minimum_size() const;
tpoint get_best_size() const;
tpoint get_maximum_size() const;
void set_best_size(const tpoint& origin);
private:

View file

@ -420,6 +420,15 @@ void ttext_box::set_canvas_text()
}
}
tpoint ttext_box::get_minimum_size() const
{
if(definition_ == std::vector<ttext_box_definition::tresolution>::const_iterator()) {
return tpoint(get_text_box(definition())->min_width, get_text_box(definition())->min_height);
} else {
return tpoint(definition_->min_width, definition_->min_height);
}
}
tpoint ttext_box::get_best_size() const
{
if(definition_ == std::vector<ttext_box_definition::tresolution>::const_iterator()) {
@ -429,6 +438,15 @@ tpoint ttext_box::get_best_size() const
}
}
tpoint ttext_box::get_maximum_size() const
{
if(definition_ == std::vector<ttext_box_definition::tresolution>::const_iterator()) {
return tpoint(get_text_box(definition())->max_width, get_text_box(definition())->max_height);
} else {
return tpoint(definition_->max_width, definition_->max_height);
}
}
void ttext_box::set_best_size(const tpoint& origin)
{
resolve_definition();

View file

@ -198,7 +198,11 @@ protected:
void goto_end_of_line(const bool select = false) { goto_end_of_data(select); }
void goto_start_of_line(const bool select = false) { goto_start_of_data(select); }
// note we should check whether the label fits in the button
// Inherited from twidget.
tpoint get_minimum_size() const;
tpoint get_best_size() const;
tpoint get_maximum_size() const;
void set_best_size(const tpoint& origin);
private:

View file

@ -37,8 +37,17 @@ struct tpoint
int x;
int y;
bool operator==(const tpoint& point) const { return x == point.x && y == point.y; }
bool operator<(const tpoint& point) const
{ return x < point.x || (x == point.x && y < point.y); }
bool operator<=(const tpoint& point) const
{ return x < point.x || (x == point.x && y <= point.y); }
};
std::ostream &operator<<(std::ostream &stream, const tpoint& point);
SDL_Rect create_rect(const tpoint& origin, const tpoint& size);
@ -108,14 +117,6 @@ public:
virtual void help(); // send when F1 is pressed on widget to get more help
#endif
//! determines the best size for a widget.
// x = best width
// y = best height
virtual tpoint get_best_size() const { return tpoint(0, 0); }
//! determines the minimal size for a widget, needed?
// layout sets up the children, this is only used by container
// containers should know their own size and optimize their
// children.
@ -204,7 +205,8 @@ public:
virtual void set_height(const unsigned height) { h_ = height; set_dirty(); }
unsigned get_height() const { return h_; }
bool dirty() const { return dirty_; }
//! Is the widget dirty?
virtual bool dirty() const { return dirty_; }
//! Sets the best size for the object.
virtual void set_best_size(const tpoint& origin)
@ -214,6 +216,15 @@ public:
//! Sets the minumum size for the object.
// virtual void set_minimum_size();
//! Gets the minimum size for the object should != 0,0.
virtual tpoint get_minimum_size() const = 0;
//! Gets the best size for the object should != 0,0.
virtual tpoint get_best_size() const = 0;
//! Gets the best size for an object, 0,0 means no limits.
virtual tpoint get_maximum_size() const = 0;
//! Sets a predefined size for the object.
virtual void set_size(const SDL_Rect& rect)
{
@ -225,14 +236,14 @@ public:
}
//! Gets the widget at the wanted coordinates.
twidget* get_widget(const tpoint& coordinate)
virtual twidget* get_widget(const tpoint& coordinate)
{
return coordinate.x >= x_ && coordinate.x < (x_ + w_) &&
coordinate.y >= y_ && coordinate.y < (y_ + h_) ? this : 0;
}
//! Gets a widget with the wanted id.
twidget* get_widget_by_id(const std::string& id)
virtual twidget* get_widget_by_id(const std::string& id)
{ return id_ == id ? this : 0; }
//! The toplevel item should always be a window if not null is returned

View file

@ -109,9 +109,8 @@ int twindow::show(const bool restore, void* /*flip_function*/)
SDL_Rect temp_rect = {0, 0, screen->w, screen->h};
fill_rect_alpha(temp_rect, 0, 1, screen);
#endif
// FIXME call grid().draw() and it do it's drawing.
for(tgrid::iterator itor = begin(); itor != end(); ++itor) {
if(! *itor || !itor->dirty()) {
continue;
}
@ -152,21 +151,11 @@ void twindow::layout(const SDL_Rect position)
{
need_layout_ = false;
tpoint best_size = get_best_size();
DBG_G << "Window: layout area " << position.x
<< ',' << position.y << " x " << position.w
<< ',' << position.h << ".\n";
if(best_size.x < position.w && best_size.y < position.h) {
set_best_size(tpoint(position.x, position.y));
return;
}
DBG_G << "Window: layout can't be set to best size, try minimum.\n";
// Implement the code.
assert(false);
// Failed at best size try minumum.
// Failed at minimum log error and try to do the best possible thing.
set_client_size(position);
}
void twindow::set_width(const unsigned width)

View file

@ -74,7 +74,8 @@ public:
twindow& get_window() { return *this; }
twidget* get_widget(const tpoint& coordinate) { return tgrid::get_widget(coordinate); }
//! Inherited from tevent_handler
twidget* get_widget(const tpoint& coordinate) { return tpanel::get_widget(coordinate); }
tpoint client_position(const tpoint& screen_position) const
{ return tpoint(screen_position.x - get_x(), screen_position.y - get_y()); }
@ -88,6 +89,11 @@ public:
unsigned get_state() const { return 0; }
bool full_redraw() const { return false; /* FIXME IMPLEMENT */ }
// Inherited from twidget.
tpoint get_minimum_size() const { /*FIXME IMPLEMENT*/ return tpoint(0,0); }
tpoint get_best_size() const { /*FIXME IMPLEMENT*/ return tpoint(0,0); }
tpoint get_maximum_size() const { /*FIXME IMPLEMENT*/ return tpoint(0,0); }
protected:
private:

View file

@ -104,7 +104,8 @@ twindow build(CVideo& video, const std::string& type)
definition = get_window_builder(type);
twindow window(video, 100, 100, definition->width, definition->height);
twindow window(video, 100, 100, definition->width, definition->height); // FIXME use proper origin
// twindow window(video, 0, 0, definition->width, definition->height); // FIXME use proper origin
const unsigned rows = definition->grid.rows;
const unsigned cols = definition->grid.cols;
@ -112,10 +113,15 @@ twindow build(CVideo& video, const std::string& type)
window.set_rows_cols(rows, cols);
for(unsigned x = 0; x < rows; ++x) {
window.set_row_scaling(x, definition->grid.row_scale[x]);
for(unsigned y = 0; y < cols; ++y) {
if(x == 0) {
window.set_col_scaling(y, definition->grid.col_scale[y]);
}
twidget* widget = definition->grid.widgets[x * cols + y]->build();
window.add_child(widget, x, y);
window.add_child(widget, x, y, definition->grid.flags[x * cols + y], definition->grid.border_size[x * cols + y]);
}
}
@ -196,6 +202,59 @@ twindow_builder::tresolution::tresolution(const config& cfg) :
}
static unsigned read_flags(const config& cfg)
{
unsigned flags = 0;
// Read the flags. FIXME document.
std::string v_align = cfg["vertical_alignment"];
if(v_align == "top") {
flags |= tgrid::VERTICAL_ALIGN_TOP;
} else if(v_align == "bottom") {
flags |= tgrid::VERTICAL_ALIGN_BOTTOM;
} else {
flags |= tgrid::VERTICAL_ALIGN_CENTER;
}
std::string h_align = cfg["horizontal_alignment"];
if(h_align == "left") {
flags |= tgrid::HORIZONTAL_ALIGN_LEFT;
} else if(h_align == "right") {
flags |= tgrid::HORIZONTAL_ALIGN_RIGHT;
} else {
flags |= tgrid::HORIZONTAL_ALIGN_CENTER;
}
std::vector<std::string> border = utils::split(cfg["border"]);
if(std::find(border.begin(), border.end(), "all") != border.end()) {
flags |= tgrid::BORDER_TOP
| tgrid::BORDER_BOTTOM | tgrid::BORDER_LEFT | tgrid::BORDER_RIGHT;
} else {
if(std::find(border.begin(), border.end(), "top") != border.end()) {
flags |= tgrid::BORDER_TOP;
}
if(std::find(border.begin(), border.end(), "bottom") != border.end()) {
flags |= tgrid::BORDER_BOTTOM;
}
if(std::find(border.begin(), border.end(), "left") != border.end()) {
flags |= tgrid::BORDER_LEFT;
}
if(std::find(border.begin(), border.end(), "right") != border.end()) {
flags |= tgrid::BORDER_RIGHT;
}
}
if(utils::string_bool(cfg["vertical_grow"])) {
flags |= tgrid::VERTICAL_GROW_SEND_TO_CLIENT;
}
if(utils::string_bool(cfg["horizontal_grow"])) {
flags |= tgrid::HORIZONTAL_GROW_SEND_TO_CLIENT;
}
return flags;
}
twindow_builder::tresolution::tgrid::tgrid(const config* cfg) :
rows(0),
cols(0),
@ -209,10 +268,18 @@ twindow_builder::tresolution::tgrid::tgrid(const config* cfg) :
unsigned col = 0;
row_scale.push_back(lexical_cast_default<unsigned>((**row_itor)["scale"]));
const config::child_list& col_cfgs = (**row_itor).get_children("column");
for(std::vector<config*>::const_iterator col_itor = col_cfgs.begin();
col_itor != col_cfgs.end(); ++col_itor) {
flags.push_back(read_flags(**col_itor));
border_size.push_back(lexical_cast_default<unsigned>((**col_itor)["border_size"]));
if(rows == 0) {
col_scale.push_back(lexical_cast_default<unsigned>((**col_itor)["scale"]));
}
if((**col_itor).child("button")) {
widgets.push_back(new tbuilder_button(*((**col_itor).child("button"))));
} else if((**col_itor).child("label")) {
@ -250,6 +317,7 @@ tbuilder_widget::tbuilder_widget(const config& cfg) :
definition = "default";
}
DBG_G_P << "Window builder: found widget with id '"
<< id << "' and definition '" << definition << "'.\n";
}

View file

@ -41,6 +41,7 @@ private:
public:
tbuilder_widget(const config& cfg);
//! Parameters for the widget.
std::string id;
std::string definition;
t_string label;
@ -73,6 +74,9 @@ public:
// note x, y hardcoded.
// FIXME add min max and default size
// the we can use best size to get the best.
std::string definition;
struct tgrid
@ -86,6 +90,17 @@ public:
unsigned rows;
unsigned cols;
//! The scale factor for the rows / columns.
std::vector<unsigned> row_scale;
std::vector<unsigned> col_scale;
//! The flags per grid cell.
std::vector<unsigned> flags;
//! The border size per grid cell.
std::vector<unsigned> border_size;
//! The widgets per grid cell.
std::vector<tbuilder_widget_ptr> widgets;
};