[[drawing code fixes]]
* Rewrote the drawing code to be able to force a redraw and to invalidate the background. This fixes the ttoggle_panel redraw problems. * Removed the no_redraw label hack * Updated the WIKI comment blocks to fix some typos and add some forgotten info.
This commit is contained in:
parent
fd802000dd
commit
e8b1280a7b
20 changed files with 123 additions and 106 deletions
|
@ -72,64 +72,3 @@
|
|||
{LABEL_DEFINITION "title" "label used for titles" {FONT_SIZE_NORMAL__TITLE} {FONT_COLOUR_TITLE} "bold"}
|
||||
|
||||
#undef LABEL_DEFINITION
|
||||
|
||||
###
|
||||
### Temporary class to avoid the redraw problem for labels in a ttoggle_panel
|
||||
### This hack can be removed once the the redraw problem is fixed
|
||||
###
|
||||
[label_definition]
|
||||
id = no_redraw
|
||||
description = "temp hack to avoid redraw problems when used in a toggle panel."
|
||||
|
||||
[resolution]
|
||||
min_width = 0
|
||||
min_height = 0
|
||||
|
||||
default_width = 0
|
||||
default_height = 0
|
||||
|
||||
max_width = 0
|
||||
max_height = 0
|
||||
|
||||
text_font_size = 16
|
||||
|
||||
[state_enabled]
|
||||
|
||||
[draw]
|
||||
|
||||
[text]
|
||||
x = 0
|
||||
y = {TEXT_V_CENTRE}
|
||||
w = "(text_width)"
|
||||
h = "(text_height)"
|
||||
font_size = 16
|
||||
colour = {FONT_COLOUR_ENABLED}
|
||||
text = "(text)"
|
||||
[/text]
|
||||
|
||||
[/draw]
|
||||
|
||||
[/state_enabled]
|
||||
|
||||
[state_disabled]
|
||||
|
||||
[draw]
|
||||
|
||||
[text]
|
||||
x = 0
|
||||
y = {TEXT_V_CENTRE}
|
||||
w = "(text_width)"
|
||||
h = "(text_height)"
|
||||
font_size = 16
|
||||
colour = {FONT_COLOUR_ENABLED}
|
||||
text = "(text)"
|
||||
[/text]
|
||||
|
||||
[/draw]
|
||||
|
||||
[/state_disabled]
|
||||
|
||||
[/resolution]
|
||||
|
||||
[/label_definition]
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
|
||||
[label]
|
||||
id = "name"
|
||||
definition = "no_redraw"
|
||||
definition = "default"
|
||||
|
||||
[/label]
|
||||
|
||||
|
@ -143,7 +143,7 @@
|
|||
|
||||
[label]
|
||||
id = "address"
|
||||
definition = "no_redraw"
|
||||
definition = "default"
|
||||
|
||||
[/label]
|
||||
|
||||
|
|
|
@ -71,12 +71,16 @@ tpoint tcontainer_::get_best_size() const
|
|||
return size;
|
||||
}
|
||||
|
||||
void tcontainer_::draw(surface& surface)
|
||||
void tcontainer_::draw(surface& surface, const bool force,
|
||||
const bool invalidate_background)
|
||||
{
|
||||
// Inherited.
|
||||
tcontrol::draw(surface);
|
||||
tcontrol::draw(surface, force, invalidate_background);
|
||||
|
||||
grid_.draw(surface);
|
||||
const bool redraw_background = invalidate_background || has_background_changed();
|
||||
set_background_changed(false);
|
||||
|
||||
grid_.draw(surface, force, redraw_background);
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -31,7 +31,8 @@ class tcontainer_ : public tcontrol
|
|||
{
|
||||
public:
|
||||
tcontainer_(const unsigned canvas_count) :
|
||||
tcontrol(canvas_count)
|
||||
tcontrol(canvas_count),
|
||||
background_changed_(true)
|
||||
{
|
||||
grid_.set_parent(this);
|
||||
}
|
||||
|
@ -63,7 +64,8 @@ public:
|
|||
tpoint get_best_size() const;
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
void draw(surface& surface);
|
||||
void draw(surface& surface, const bool force = false,
|
||||
const bool invalidate_background = false);
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
twidget* find_widget(const tpoint& coordinate, const bool must_be_active)
|
||||
|
@ -131,6 +133,10 @@ protected:
|
|||
|
||||
const tgrid& grid() const { return grid_; }
|
||||
tgrid& grid() { return grid_; }
|
||||
|
||||
void set_background_changed(const bool changed = true)
|
||||
{ background_changed_ = changed; }
|
||||
bool has_background_changed() const { return background_changed_; }
|
||||
|
||||
private:
|
||||
|
||||
|
@ -139,6 +145,13 @@ private:
|
|||
|
||||
/** Returns the space used by the border. */
|
||||
virtual tpoint border_space() const { return tpoint(0, 0); }
|
||||
|
||||
/**
|
||||
* If the background has been changed the next draw cycle needs to do a full
|
||||
* redraw and also tell the child items to invalidate their background. This
|
||||
* overrides the 'invalidate_background' parameter send to draw().
|
||||
*/
|
||||
bool background_changed_;
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -143,10 +143,18 @@ tpoint tcontrol::get_maximum_size() const
|
|||
return tpoint(config_->max_width, config_->max_height);
|
||||
}
|
||||
|
||||
void tcontrol::draw(surface& surface)
|
||||
void tcontrol::draw(surface& surface, const bool force,
|
||||
const bool invalidate_background)
|
||||
{
|
||||
assert(config_);
|
||||
|
||||
if(!dirty() && !force && !invalidate_background) {
|
||||
return;
|
||||
}
|
||||
if(invalidate_background) {
|
||||
restorer_ = 0;
|
||||
}
|
||||
|
||||
set_dirty(false);
|
||||
SDL_Rect rect = get_rect();
|
||||
|
||||
|
|
|
@ -101,7 +101,8 @@ public:
|
|||
tpoint get_maximum_size() const;
|
||||
|
||||
/** Inherited from twidget. */
|
||||
void draw(surface& surface);
|
||||
void draw(surface& surface, const bool force = false,
|
||||
const bool invalidate_background = false);
|
||||
|
||||
/** Inherited from twidget. */
|
||||
twidget* find_widget(const tpoint& coordinate, const bool must_be_active)
|
||||
|
|
|
@ -201,21 +201,15 @@ bool tgrid::has_vertical_scrollbar() const
|
|||
return twidget::has_vertical_scrollbar();
|
||||
}
|
||||
|
||||
void tgrid::draw(surface& surface)
|
||||
void tgrid::draw(surface& surface, const bool force,
|
||||
const bool invalidate_background)
|
||||
{
|
||||
for(iterator itor = begin(); itor != end(); ++itor) {
|
||||
/**
|
||||
* @todo temporary disabled until the nested drawing for
|
||||
* ttoggle_panel works with this flag set.
|
||||
*/
|
||||
/*
|
||||
if(! *itor || !itor->dirty()) {
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
log_scope2(gui_draw, "Grid: draw child.");
|
||||
|
||||
itor->draw(surface);
|
||||
assert(*itor);
|
||||
itor->draw(surface, force, invalidate_background);
|
||||
}
|
||||
|
||||
set_dirty(false);
|
||||
|
|
|
@ -167,7 +167,8 @@ public:
|
|||
bool has_vertical_scrollbar() const;
|
||||
|
||||
/** Inherited from twidget. */
|
||||
void draw(surface& surface);
|
||||
void draw(surface& surface, const bool force = false,
|
||||
const bool invalidate_background = false);
|
||||
|
||||
/** Inherited from twidget. */
|
||||
twidget* find_widget(const tpoint& coordinate, const bool must_be_active);
|
||||
|
|
|
@ -234,10 +234,15 @@ tpoint tlistbox::get_best_size() const
|
|||
return tcontainer_::get_best_size();
|
||||
}
|
||||
|
||||
void tlistbox::draw(surface& surface)
|
||||
void tlistbox::draw(surface& surface, const bool force,
|
||||
const bool invalidate_background)
|
||||
{
|
||||
// Inherit.
|
||||
tcontainer_::draw(surface);
|
||||
tcontainer_::draw(surface, force, invalidate_background);
|
||||
|
||||
if(invalidate_background) {
|
||||
list_background_.assign(NULL);
|
||||
}
|
||||
|
||||
// Handle our full redraw for the spacer area.
|
||||
if(!list_background_) {
|
||||
|
@ -252,9 +257,7 @@ void tlistbox::draw(surface& surface)
|
|||
trow& row = rows_[i + scrollbar()->get_item_position()];
|
||||
|
||||
assert(row.grid());
|
||||
if(row.grid()->dirty()) {
|
||||
row.grid()->draw(row.canvas());
|
||||
}
|
||||
row.grid()->draw(row.canvas(), force, invalidate_background);
|
||||
|
||||
// draw background
|
||||
const SDL_Rect rect = {list_rect_.x, offset, list_rect_.w, row.get_height() };
|
||||
|
|
|
@ -77,7 +77,8 @@ public:
|
|||
tpoint get_best_size() const;
|
||||
|
||||
/** Inherited from tcontainer. */
|
||||
void draw(surface& surface);
|
||||
void draw(surface& surface, const bool force = false,
|
||||
const bool invalidate_background = false);
|
||||
|
||||
/** Inherited from tcontainer. */
|
||||
void set_size(const SDL_Rect& rect);
|
||||
|
|
|
@ -53,15 +53,16 @@ SDL_Rect tpanel::get_client_rect() const
|
|||
return result;
|
||||
}
|
||||
|
||||
void tpanel::draw(surface& surface)
|
||||
void tpanel::draw(surface& surface, const bool force,
|
||||
const bool invalidate_background)
|
||||
{
|
||||
// Need to preserve the state and inherited draw clear the flag.
|
||||
const bool is_dirty = dirty();
|
||||
|
||||
tcontainer_::draw(surface);
|
||||
tcontainer_::draw(surface, force, invalidate_background);
|
||||
|
||||
// foreground
|
||||
if(is_dirty) {
|
||||
if(is_dirty || force) {
|
||||
SDL_Rect rect = get_rect();
|
||||
canvas(1).draw(true);
|
||||
blit_surface(canvas(1).surf(), 0, surface, &rect);
|
||||
|
|
|
@ -60,7 +60,8 @@ public:
|
|||
unsigned get_state() const { return 0; }
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
void draw(surface& surface);
|
||||
void draw(surface& surface, const bool force = false,
|
||||
const bool invalidate_background = false);
|
||||
|
||||
/** Inherited from tcontainer_. */
|
||||
bool has_vertical_scrollbar() const { return false; }
|
||||
|
@ -73,6 +74,7 @@ private:
|
|||
|
||||
/** Inherited from tcontainer_. */
|
||||
tpoint border_space() const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -622,7 +622,7 @@ tpanel_definition::tresolution::tresolution(const config& cfg) :
|
|||
* grid. A panel is always enabled and can't be disabled. Instead it uses the
|
||||
* states as layers to draw on.
|
||||
*
|
||||
* The resolution for a text box also contains the following keys:
|
||||
* The resolution for a panel also contains the following keys:
|
||||
* @start_table = config
|
||||
* top_border (unsigned = 0) The size which isn't used for the client area.
|
||||
* bottom_border (unsigned = 0) The size which isn't used for the client area.
|
||||
|
@ -763,7 +763,8 @@ ttoggle_panel_definition::tresolution::tresolution(const config& cfg) :
|
|||
top_border(lexical_cast_default<unsigned>(cfg["top_border"])),
|
||||
bottom_border(lexical_cast_default<unsigned>(cfg["bottom_border"])),
|
||||
left_border(lexical_cast_default<unsigned>(cfg["left_border"])),
|
||||
right_border(lexical_cast_default<unsigned>(cfg["right_border"]))
|
||||
right_border(lexical_cast_default<unsigned>(cfg["right_border"])),
|
||||
state_change_full_redraw(utils::string_bool(cfg["state_change_full_redraw"], true))
|
||||
{
|
||||
/*WIKI
|
||||
* @page = GUIToolkitWML
|
||||
|
@ -771,7 +772,28 @@ ttoggle_panel_definition::tresolution::tresolution(const config& cfg) :
|
|||
*
|
||||
* == Toogle panel ==
|
||||
*
|
||||
* The definition of a toggle panel.
|
||||
* The definition of a toggle panel. A toggle panel is like a toggle button, but
|
||||
* instead of being a button it's a panel. This means it can hold multiple child
|
||||
* items.
|
||||
*
|
||||
* The resolution for a toggle panel also contains the following keys:
|
||||
* @start_table = config
|
||||
* top_border (unsigned = 0) The size which isn't used for the client area.
|
||||
* bottom_border (unsigned = 0) The size which isn't used for the client area.
|
||||
* left_border (unsigned = 0) The size which isn't used for the client area.
|
||||
* right_border (unsigned = 0) The size which isn't used for the client area.
|
||||
* state_change_full_redraw (bool = true)
|
||||
* When the state of the toggle panel changes
|
||||
* it can change it's background. If that
|
||||
* happens all child items need to redraw
|
||||
* themselves and need to modify their cached
|
||||
* background. Set this variable to true if
|
||||
* that's the case, in case of doubt set it to
|
||||
* true, it might give a small performance hit
|
||||
* but the drawing will always be correct.
|
||||
* @end_table
|
||||
*
|
||||
* The following layers exist:
|
||||
*
|
||||
* The following states exist:
|
||||
* * state_enabled, the panel is enabled and not selected.
|
||||
|
|
|
@ -214,6 +214,8 @@ struct ttoggle_panel_definition : public tcontrol_definition
|
|||
|
||||
unsigned left_border;
|
||||
unsigned right_border;
|
||||
|
||||
bool state_change_full_redraw;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -55,7 +55,8 @@ public:
|
|||
*
|
||||
* Since we're always empty the draw does nothing.
|
||||
*/
|
||||
void draw(surface&) {}
|
||||
void draw(surface& /*surface*/, const bool /*force*/ = false,
|
||||
const bool /*invalidate_background*/ = false) {}
|
||||
|
||||
|
||||
void set_best_size(const tpoint& best_size) { best_size_ = best_size; }
|
||||
|
|
|
@ -146,9 +146,19 @@ void ttoggle_panel::set_selected(const bool selected)
|
|||
|
||||
void ttoggle_panel::set_state(tstate state)
|
||||
{
|
||||
if(state != state_) {
|
||||
state_ = state;
|
||||
set_dirty(true);
|
||||
if(state == state_) {
|
||||
return;
|
||||
}
|
||||
|
||||
state_ = state;
|
||||
set_dirty(true);
|
||||
|
||||
const ttoggle_panel_definition::tresolution* conf =
|
||||
dynamic_cast<const ttoggle_panel_definition::tresolution*>(config());
|
||||
assert(conf);
|
||||
|
||||
if(conf->state_change_full_redraw) {
|
||||
set_background_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,9 @@ public:
|
|||
unsigned get_state() const { return state_; }
|
||||
|
||||
/** Inherited from tpanel. */
|
||||
void draw(surface& surface) { tcontainer_::draw(surface); }
|
||||
void draw(surface& surface, const bool force = false,
|
||||
const bool invalidate_background = false)
|
||||
{ tcontainer_::draw(surface, force, invalidate_background); }
|
||||
|
||||
/**
|
||||
* Inherited from tpanel.
|
||||
|
|
|
@ -340,8 +340,20 @@ public:
|
|||
*
|
||||
* @param surface The surface to draw the widget upon using the
|
||||
* coordinates and size of the widget.
|
||||
* @param force Does the widget need to be drawn even if not
|
||||
* dirty?
|
||||
* @param invalidate_background
|
||||
* Some widgets can cache the background in order
|
||||
* to undraw and redraw themselves if needed. If
|
||||
* the background changes this 'feature' will
|
||||
* cause glitches. When this parameter is set the
|
||||
* widget need to reload the background and use
|
||||
* that as new undraw cache.
|
||||
* \n Note if this is set the widget should also
|
||||
* be redrawn.
|
||||
*/
|
||||
virtual void draw(surface& /*surface*/) = 0;
|
||||
virtual void draw(surface& /*surface*/, const bool /*force*/ = false,
|
||||
const bool /*invalidate_background*/ = false) = 0;
|
||||
|
||||
/***** ***** ***** ***** query ***** ***** ***** *****/
|
||||
|
||||
|
|
|
@ -135,10 +135,10 @@ void twindow::layout(const SDL_Rect position)
|
|||
need_layout_ = false;
|
||||
}
|
||||
|
||||
//! Inherited from tpanel.
|
||||
void twindow::draw(surface& surface)
|
||||
void twindow::draw(surface& surface, const bool force,
|
||||
const bool invalidate_background)
|
||||
{
|
||||
const bool draw_foreground = need_layout_;
|
||||
const bool draw_foreground = need_layout_ || force;
|
||||
if(need_layout_) {
|
||||
DBG_G << "Window: layout client area.\n";
|
||||
layout(get_client_rect());
|
||||
|
@ -154,7 +154,7 @@ void twindow::draw(surface& surface)
|
|||
|
||||
log_scope2(gui_draw, "Window: draw child.");
|
||||
|
||||
itor->draw(surface);
|
||||
itor->draw(surface, force, invalidate_background);
|
||||
}
|
||||
if(draw_foreground) {
|
||||
canvas(1).draw();
|
||||
|
|
|
@ -119,7 +119,8 @@ public:
|
|||
bool full_redraw() const { return false; /* FIXME IMPLEMENT */ }
|
||||
|
||||
//! Inherited from tpanel.
|
||||
void draw(surface& surface);
|
||||
void draw(surface& surface, const bool force = false,
|
||||
const bool invalidate_background = false);
|
||||
|
||||
//! Gets the coordinates of the client area, for external use the height
|
||||
//! and the width are the most interesting things.
|
||||
|
|
Loading…
Add table
Reference in a new issue