Add a new debug class for the widgets.

This debug option can output dot files which can be transformed to
images so it's easier to get debug info about the widgets in a
window. This function is enabled by the --enable-debug-window-layout
configure switch. It has not been implemented in the other build
systems yet. (Not sure whether or not it's needed.)
This commit is contained in:
Mark de Wever 2008-11-10 20:01:25 +00:00
parent af0b4a21dd
commit 9c1e36145c
11 changed files with 719 additions and 25 deletions

View File

@ -150,6 +150,16 @@ fi
AM_CONDITIONAL([LOWMEM], [test "x$lowmem" = "xyes"])
AC_ARG_ENABLE([debug-window-layout],
AS_HELP_STRING([--enable-debug-window-layout], [add the debug option to allow the generation of debug layout files in dot format]),
[debug_window_layout=$enableval],
[debug_window_layout=no])
if test "x$debug_window_layout" = "xyes"
then
CPPFLAGS="$CPPFLAGS -DDEBUG_WINDOW_LAYOUT_GRAPHS"
fi
DATADIR=$PACKAGE
AC_ARG_WITH([datadir-name],
AS_HELP_STRING([--with-datadir-name@<:@=DIR@:>@], [change name of data directory @<:@wesnoth@:>@]),

View File

@ -77,6 +77,7 @@ wesnoth_source = \
gui/dialogs/mp_method_selection.cpp \
gui/dialogs/title_screen.cpp \
gui/widgets/button.cpp \
gui/widgets/debug.cpp \
gui/widgets/canvas.cpp \
gui/widgets/control.cpp \
gui/widgets/container.cpp \

View File

@ -37,6 +37,9 @@
#include "gui/dialogs/language_selection.hpp"
#include "gui/dialogs/mp_method_selection.hpp"
#include "gui/dialogs/title_screen.hpp"
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
#include "gui/widgets/debug.hpp"
#endif
#include "gui/widgets/window.hpp"
#include "help.hpp"
#include "hotkeys.hpp"
@ -351,6 +354,12 @@ game_controller::game_controller(int argc, char** argv) :
} else if(val == "--debug" || val == "-d") {
game_config::debug = true;
game_config::mp_debug = true;
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
} else if (val.substr(0, 18) == "--debug-dot-level=") {
gui2::tdebug_layout_graph::set_level(val.substr(18));
} else if (val.substr(0, 19) == "--debug-dot-domain=") {
gui2::tdebug_layout_graph::set_level(val.substr(19));
#endif
} else if(val == "--no-delay") {
game_config::no_delay = true;
} else if (val.substr(0, 6) == "--log-") {
@ -1688,6 +1697,28 @@ static int process_command_args(int argc, char** argv) {
<< " --config-path prints the path of the user config directory and\n"
<< " exits.\n"
<< " -d, --debug enables additional command mode options in-game.\n"
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
<< " --debug-dot-level=<level1>,<level2>,...\n"
<< " sets the level of the debug dot files.\n"
<< " These files are used for debugging the widgets\n"
<< " especially the for the layout engine. When enabled\n"
<< " the engine will produce dot files which can be\n"
<< " converted to images with the dot tool.\n"
<< " Available levels:\n"
<< " - child : generate the data about the grid cells.\n"
<< " - size : generate the size info of the widget.\n"
<< " - state : generate the state info of the widget.\n"
<< " --debug-dot-domain=<domain1>,<domain2>,...\n"
<< " sets the domain of the debug dot files.\n"
<< " see --debug-dot-level for more info.\n"
<< " Available domains:\n"
<< " show : generate the data when the dialog is\n"
<< " about to be shown.\n"
<< " layout : generate the data during the layout\n"
<< " phase (might result in multiple files. \n"
<< " The data can also be generated when the F12 is\n"
<< " pressed in a dialog.\n"
#endif
<< " --dummylocales enables dummy locales for switching to non-system\n"
<< " locales.\n"
#ifndef DISABLE_EDITOR2

View File

@ -29,6 +29,7 @@ namespace gui2 {
*/
class tcontainer_ : public tcontrol
{
friend class tdebug_layout_graph;
public:
tcontainer_(const unsigned canvas_count) :
tcontrol(canvas_count),

View File

@ -28,6 +28,7 @@ namespace gui2 {
/** Base class for all visible items. */
class tcontrol : public virtual twidget
{
friend class tdebug_layout_graph;
public:
tcontrol(const unsigned canvas_count);

437
src/gui/widgets/debug.cpp Normal file
View File

@ -0,0 +1,437 @@
/* $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/debug.hpp"
#include "foreach.hpp"
#include "formatter.hpp"
#include "gui/widgets/window.hpp"
#include "serialization/string_utils.hpp"
#include <fstream>
namespace gui2 {
namespace {
/**
* Gets the id of a grid child cell.
*
* @param parent_id The id of the parent grid.
* @param row Row number in the grid.
* @param col Column number in the grid.
*
* @returns The id of the child cell.
*/
std::string get_child_id(
const std::string& parent_id, const unsigned row, const unsigned col)
{
return (formatter() << parent_id << "_C_" << row << '_' << col).c_str();
}
/**
* Gets the id of a widget in a grid child cell.
*
* @param parent_id The id of the parent grid.
* @param row Row number in the grid.
* @param col Column number in the grid.
*
* @returns The id of the widget.
*/
std::string get_child_widget_id(
const std::string& parent_id, const unsigned row, const unsigned col)
{
return get_child_id(parent_id, row, col) + "_W";
}
/** Gets the prefix of the filename. */
std::string get_base_filename()
{
char buf[17] = {0};
time_t t = time(NULL);
tm* lt = localtime(&t);
if(lt) {
strftime(buf, sizeof(buf), "%Y%m%d_%H%M%S", lt);
}
static unsigned counter = 0;
++counter;
static const std::string
result((formatter() << buf << '_' << counter << '_').c_str());
return result;
}
/***** ***** ***** ***** FLAGS ***** ***** ***** *****/
const unsigned ALL = UINT_MAX; /**< All levels/domains */
// level flags
const unsigned CHILD = 1 << 0; /**<
* Shows the child records of a cell.
*/
const unsigned SIZE_INFO = 1 << 1; /**<
* Shows the size info of
* children/widgets.
*/
const unsigned STATE_INFO = 1 << 2; /**< Shows the state info of widgets. */
// domain flags
const unsigned SHOW = 1 << 0; /**<
* Shows the info when the dialog is
* shown.
*/
const unsigned LAYOUT = 1 << 1; /**<
* Shows the info in all layout
* phases.
*/
unsigned level_ = ALL; /** @todo Should default to 0. */
unsigned domain_ = ALL; /** @todo Should default to 0. */
} //namespace
tdebug_layout_graph::tdebug_layout_graph(const twindow* window)
: window_(window)
, sequence_number_(0)
, filename_base_(get_base_filename())
{
}
void tdebug_layout_graph::set_level(const std::string& level)
{
if(level.empty()) {
level_ = ALL; /** @todo Should default to 0. */
return;
}
std::vector<std::string> params = utils::split(level);
foreach(const std::string& param, params) {
if(param == "all") {
level_ = ALL;
// No need to look further eventhought invalid items are now
// ignored.
return;
} else if(param == "child") {
level_ |= CHILD;
} else if(param == "size") {
level_ |= SIZE_INFO;
} else if(param == "state") {
level_ |= STATE_INFO;
} else {
// loging might not be up yet.
std::cerr << "Unknown level '" << param << "' is ignored.\n";
}
}
}
void tdebug_layout_graph::set_domain(const std::string& domain)
{
if(domain.empty()) {
// return error and die
domain_ = ALL; /** @todo Should default to 0. */
return;
}
std::vector<std::string> params = utils::split(domain);
foreach(const std::string& param, params) {
if(param == "all") {
domain_ = ALL;
// No need to look further eventhought invalid items are now
// ignored.
return;
} else if(param == "show") {
domain_ |= SHOW;
} else if(param == "layout") {
domain_ |= LAYOUT;
} else {
// loging might not be up yet.
std::cerr << "Unknown domain '" << param << "' is ignored.\n";
}
}
}
void tdebug_layout_graph::generate_dot_file(const std::string& generator)
{
const std::string filename = filename_base_ +
lexical_cast<std::string>(++sequence_number_) + "-" + generator + ".dot";
std::ofstream file(filename.c_str());
file << "//Basic layout graph for window id '" << window_->id()
<< "' using definition '" << window_->definition() << "'.\n"
<< "digraph window {\n"
<< "\tnode [shape=record, style=filled, fillcolor=\"bisque\"];\n"
<< "\trankdir=LR;\n"
;
widget_generate_info(file, window_, "root");
file << "}\n";
}
void tdebug_layout_graph::widget_generate_info(
std::ostream& out, const twidget* widget, const std::string& id) const
{
out << "\t" << id
<< " [label=<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\">";
widget_generate_basic_info(out, widget);
if(level_ & STATE_INFO) widget_generate_state_info(out, widget);
if(level_ & SIZE_INFO) widget_generate_size_info(out, widget);
out << "</table>>];\n";
const tgrid* grid = dynamic_cast<const tgrid*>(widget);
if(!grid) {
const tcontainer_* container = dynamic_cast<const tcontainer_*>(widget);
if(container) {
grid = &container->grid();
}
}
if(grid) {
grid_generate_info(out, grid, id);
}
}
void tdebug_layout_graph::widget_generate_basic_info(
std::ostream& out, const twidget* widget) const
{
std::string header_background = level_ & (SIZE_INFO|STATE_INFO)
? " bgcolor=\"gray\"" : "";
const tcontrol* control = dynamic_cast<const tcontrol*>(widget);
out << "<tr><td" << header_background << ">" << '\n'
<< "type=" << get_type(widget) << '\n'
<< "</td></tr>" << '\n'
<< "<tr><td" << header_background << ">" << '\n'
<< "id=" << widget->id() << '\n'
<< "</td></tr>" << '\n'
<< "<tr><td" << header_background << ">" << '\n'
<< "definition=" << widget->definition() << '\n'
<< "</td></tr>" << '\n';
if(control) {
out << "<tr><td" << header_background << ">" << '\n'
<< "label=" << control->label() << '\n'
<< "</td></tr>\n";
}
}
void tdebug_layout_graph::widget_generate_state_info(
std::ostream& out, const twidget* widget) const
{
const tcontrol* control = dynamic_cast<const tcontrol*>(widget);
if(!control) {
return;
}
out << "<tr><td>\n"
<< "tooltip=" << control->tooltip() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "help message" << control->help_message() << '\n'
// FIXME add value and other specific items
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "active=" << control->get_active() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "visible=" << control->get_visible() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "use tooltip on label overflow="
<< control->get_use_tooltip_on_label_overflow() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "does block easy close=" << control->does_block_easy_close() << '\n'
<< "</td></tr>\n";
}
void tdebug_layout_graph::widget_generate_size_info(
std::ostream& out, const twidget* widget) const
{
out << "<tr><td>\n"
<< "minimum size=" << widget->get_minimum_size() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "best size=" << widget->get_best_size() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "maximum size" << widget->get_maximum_size() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "can wrap=" << widget->can_wrap() << '\n'
// FIXME add constrain info
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "has vertical scrollbar="
<< widget->has_vertical_scrollbar() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "has horizontal scrollbar="
<< widget->has_horizontal_scrollbar() << '\n'
<< "</td></tr>\n"
<< "<tr><td>\n"
<< "size=" << widget->get_rect() << '\n'
<< "</td></tr>\n";
}
void tdebug_layout_graph::grid_generate_info(std::ostream& out,
const tgrid* grid, const std::string& parent_id) const
{
const bool show_child = level_ & CHILD;
// maybe change the order to links, child, widgets so the output of the
// dot file might look better.
out << "\n\n\t// The children of " << parent_id << ".\n";
for(unsigned row = 0; row < grid->get_rows(); ++row) {
for(unsigned col = 0; col < grid->get_cols(); ++col) {
const twidget* widget = grid->child(row, col).widget();
assert(widget);
widget_generate_info(
out, widget, get_child_widget_id(parent_id, row, col));
}
}
if(show_child) {
out << "\n\t// The grid child data of " << parent_id << ".\n";
for(unsigned row = 0; row < grid->get_rows(); ++row) {
for(unsigned col = 0; col < grid->get_cols(); ++col) {
child_generate_info(out, grid->child(row, col),
get_child_id(parent_id, row, col));
}
}
}
out << "\n\t// The links of " << parent_id << ".\n";
for(unsigned row = 0; row < grid->get_rows(); ++row) {
for(unsigned col = 0; col < grid->get_cols(); ++col) {
if(show_child) {
// grid -> child
out << "\t" << parent_id << " -> "
<< get_child_id(parent_id, row, col)
<< " [label=\"(" << row << ',' << col
<< ")\"];\n";
// child -> widget
out << "\t" << get_child_id(parent_id, row, col) << " -> "
<< get_child_widget_id(parent_id, row, col) << ";\n";
} else {
// grid -> widget
out << "\t" << parent_id << " -> "
<< get_child_widget_id(parent_id, row, col)
<< " [label=\"(" << row << ',' << col
<< ")\"];\n";
}
}
}
}
void tdebug_layout_graph::child_generate_info(std::ostream& out,
const tgrid::tchild& child, const std::string& id) const
{
unsigned flags = child.get_flags();
out << "\t" << id
<< " [style=\"\", label=<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\">";
out << "<tr><td>"
<< "vertical flag=";
switch(flags & tgrid::VERTICAL_MASK) {
case tgrid::VERTICAL_GROW_SEND_TO_CLIENT : out << "send to client"; break;
case tgrid::VERTICAL_ALIGN_TOP : out << "align to top"; break;
case tgrid::VERTICAL_ALIGN_CENTER : out << "center"; break;
case tgrid::VERTICAL_ALIGN_BOTTOM : out << "align to bottom"; break;
default :
out << "unknown value("
<< ((flags & tgrid::VERTICAL_MASK) >> tgrid::VERTICAL_SHIFT)
<< ")";
}
out << "</td></tr>"
<< "<tr><td>"
<< "horizontal flag=";
switch(flags & tgrid::HORIZONTAL_MASK) {
case tgrid::HORIZONTAL_GROW_SEND_TO_CLIENT : out << "send to client"; break;
case tgrid::HORIZONTAL_ALIGN_LEFT : out << "align to left"; break;
case tgrid::HORIZONTAL_ALIGN_CENTER : out << "center"; break;
case tgrid::HORIZONTAL_ALIGN_RIGHT : out << "align to right"; break;
default :
out << "unknown value("
<< ((flags & tgrid::HORIZONTAL_MASK) >> tgrid::HORIZONTAL_SHIFT)
<< ")";
}
out << "</td></tr>"
<< "<tr><td>"
<< "border location=";
if((flags & tgrid::BORDER_ALL) == 0) {
out << "none";
} else if((flags & tgrid::BORDER_ALL) == tgrid::BORDER_ALL) {
out << "all";
} else {
std::string result;
if(flags & tgrid::BORDER_TOP) result += "top, ";
if(flags & tgrid::BORDER_BOTTOM) result += "bottom, ";
if(flags & tgrid::BORDER_LEFT) result += "left, ";
if(flags & tgrid::BORDER_RIGHT) result += "right, ";
if(!result.empty()) {
result.resize(result.size() - 2);
}
out << result;
}
out << "</td></tr>"
<< "<tr><td>"
<< "border_size="<< child.get_border_size()
<< "</td></tr>";
out << "</table>>];\n";
}
std::string tdebug_layout_graph::get_type(const twidget* widget) const
{
const tcontrol* control = dynamic_cast<const tcontrol*>(widget);
if(control) {
return control->get_control_type();
} else {
const tgrid* grid = dynamic_cast<const tgrid*>(widget);
if(grid) {
return "grid";
} else {
return "unknown";
}
}
}
} // namespace gui2

176
src/gui/widgets/debug.hpp Normal file
View File

@ -0,0 +1,176 @@
/* $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_DEBUG_HPP_INCLUDED
#define GUI_WIDGETS_DEBUG_HPP_INCLUDED
#include "gui/widgets/grid.hpp"
#include <iosfwd>
#include <string>
namespace gui2 {
class twidget;
class twindow;
/**
* Helper class to output the layout to dot files.
*
* The class will generate .dot files in the location where wesnoth is running
* (so needs write access there). These files can be converted to images
* containing the graphs. This is used for debugging the widget libary and its
* sizing algorithm.
*
* This class needs to be friends with a lot of classes so it can view the
* private data in the class. This design is choosen so the debug info can be
* put in a separate class instead of adding the info via virtual functions in
* the classes themselves. Also adding 'friend class foo' doesn't need to
* include the header declaring foo, so it avoids header cluttage.
*
*/
class tdebug_layout_graph
{
public:
/**
* Constructor.
*
* @param window The window, whose information will be
* generated.
*/
tdebug_layout_graph(const twindow* window);
/**
* Sets the level of wanted information.
*
* @param level A comma separated list of levels which are
* wanted. Possible values: child, size, state
* and all.
*/
static void set_level(const std::string& level);
/**
* Sets the domain when to show the information.
*
* @param domain A comma separated list for domains which are
* wanted. Possible values: show, layout and all.
*/
static void set_domain(const std::string& domain);
/**
* Generates a dot file.
*
* The file will have a fixed prefix filename but for every file a part of
* the name will contain where it was generated.
*
* @param generator The location where the name was generated.
*/
void generate_dot_file(const std::string& generator);
private:
/** The window whose info will be shown. */
const twindow* window_;
/** The order in which the files are generated. */
unsigned sequence_number_;
/** Basic part of the filename. */
std::string filename_base_;
/***** ***** Widget ***** *****/
/**
* Generates the info about a widget.
*
* @param out The stream to write the info to.
* @param widget The widget to write the info about.
* @param id The dof-file-id of the widget.
*/
void widget_generate_info(std::ostream& out,
const twidget* widget, const std::string& id) const;
/**
* Generates the basic info about a widget.
*
* @param out The stream to write the info to.
* @param widget The widget to write the info about.
*/
void widget_generate_basic_info(
std::ostream& out, const twidget* widget) const;
/**
* Generates the info about the state of the widget.
*
* @param out The stream to write the info to.
* @param widget The widget to write the info about.
*/
void widget_generate_state_info(
std::ostream& out, const twidget* widget) const;
/**
* Generates the info about the size and layout of the widget.
*
* @param out The stream to write the info to.
* @param widget The widget to write the info about.
*/
void widget_generate_size_info(
std::ostream& out, const twidget* widget) const;
/***** ***** Grid ***** *****/
/**
* Generates the info about a grid.
*
* @param out The stream to write the info to.
* @param grid The grid to write the info about.
* @param parent_id The dot-file-id of the parent of the widget.
*/
void grid_generate_info(std::ostream& out,
const tgrid* grid, const std::string& parent_id) const;
/**
* Generates the info about a grid cell.
*
* @param out The stream to write the info to.
* @param child The grid cell to write the info about.
* @param id The dof-file-id of the child.
*/
void child_generate_info(std::ostream& out,
const tgrid::tchild& child, const std::string& id) const;
/***** ***** Helper ***** *****/
/**
* Returns the control_type of a widget.
*
* This is a small wrapper around tcontrol::get_control_type() since a
* grid is no control and used rather frequently, so we want to give it a
* type.
*
* @param widget The widget to get the type of.
*
* @returns If the widget is a control it returns its
* type. If the widget is a grid it returns
* 'grid', otherwise 'unknown' will be returned.
*/
std::string get_type(const twidget* widget) const;
};
} // namespace gui2
#endif

View File

@ -39,6 +39,7 @@ namespace gui2 {
*/
class tgrid : public virtual twidget
{
friend class tdebug_layout_graph;
public:
tgrid(const unsigned rows = 0, const unsigned cols = 0);

View File

@ -259,6 +259,7 @@ private:
*/
class twidget : public virtual tevent_executor
{
friend class tdebug_layout_graph;
public:
twidget() :
id_(""),

View File

@ -21,6 +21,9 @@
#include "cursor.hpp"
#include "font.hpp"
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
#include "gui/widgets/debug.hpp"
#endif
#include "preferences.hpp"
#include "titlescreen.hpp"
#include "video.hpp"
@ -75,30 +78,33 @@ twindow::twindow(CVideo& video,
const bool automatic_placement,
const unsigned horizontal_placement,
const unsigned vertical_placement,
const std::string& definition) :
tpanel(),
tevent_handler(),
video_(video),
status_(NEW),
retval_(0),
owner_(0),
need_layout_(true),
resized_(true),
suspend_drawing_(true),
top_level_(false),
window_(),
restorer_(),
tooltip_(),
help_popup_(),
automatic_placement_(automatic_placement),
horizontal_placement_(horizontal_placement),
vertical_placement_(vertical_placement),
x_(x),
y_(y),
w_(w),
h_(h),
easy_close_(false),
easy_close_blocker_()
const std::string& definition)
: tpanel()
, tevent_handler()
, video_(video)
, status_(NEW)
, retval_(0)
, owner_(0)
, need_layout_(true)
, resized_(true)
, suspend_drawing_(true)
, top_level_(false)
, window_()
, restorer_()
, tooltip_()
, help_popup_()
, automatic_placement_(automatic_placement)
, horizontal_placement_(horizontal_placement)
, vertical_placement_(vertical_placement)
, x_(x)
, y_(y)
, w_(w)
, h_(h)
, easy_close_(false)
, easy_close_blocker_()
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
, debug_layout_(new tdebug_layout_graph(this))
#endif
{
// We load the config in here as exception.
// Our caller did update the screen size so no need for us to do that again.
@ -185,7 +191,11 @@ twindow::tretval twindow::get_retval_by_id(const std::string& id)
int twindow::show(const bool restore, void* /*flip_function*/)
{
log_scope2(gui_draw, "Window: show.");
log_scope2(gui_draw, "Window: show.");
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
debug_layout_->generate_dot_file("show");
#endif
assert(status_ == NEW);
@ -339,6 +349,12 @@ void twindow::key_press(tevent_handler& /*event_handler*/, bool& handled,
set_retval(CANCEL);
handled = true;
}
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
if(key == SDLK_F12) {
debug_layout_->generate_dot_file("manual");
handled = true;
}
#endif
}
SDL_Rect twindow::get_client_rect() const
@ -457,6 +473,9 @@ void twindow::layout()
x_(variables), y_(variables), w_(variables), h_(variables)));
}
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
debug_layout_->generate_dot_file("layout_finished");
#endif
// Make sure the contrains are cleared, they might be partially set.
clear_width_constrain();
disable_cache = false;
@ -554,5 +573,11 @@ void twindow::draw(surface& /*surf*/, const bool /*force*/,
assert(false);
}
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
twindow::~twindow()
{
delete debug_layout_;
}
#endif
} // namespace gui2

View File

@ -38,6 +38,7 @@ class CVideo;
namespace gui2{
class tdialog;
class tdebug_layout_graph;
/**
* base class of top level items, the only item
@ -45,6 +46,7 @@ class tdialog;
*/
class twindow : public tpanel, public tevent_handler
{
friend class tdebug_layout_graph;
public:
twindow(CVideo& video,
tformula<unsigned>x,
@ -375,6 +377,14 @@ private:
*/
void draw(surface& surface, const bool force = false,
const bool invalidate_background = false);
#ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
tdebug_layout_graph* debug_layout_;
public:
// The destructor only needs to delete the debug_layout_ so declared here.
~twindow();
#endif
};
} // namespace gui2