Add new gui2 iterator framework.
This commit is contained in:
parent
4ac8cababc
commit
797142008b
26 changed files with 1845 additions and 0 deletions
|
@ -20,6 +20,7 @@ Version 1.9.5+svn:
|
|||
(fixes bug #17743).
|
||||
* Applied patch #2611: removed redundant own_side attribute
|
||||
* Applied patch #2600: improved MP creation screen logging
|
||||
* Added: New gui2 iterator framework.
|
||||
|
||||
Version 1.9.5:
|
||||
* Graphics:
|
||||
|
|
|
@ -8,6 +8,9 @@ src/gui/auxiliary/canvas.cpp
|
|||
src/gui/auxiliary/event/dispatcher.cpp
|
||||
src/gui/auxiliary/event/distributor.cpp
|
||||
src/gui/auxiliary/event/handler.cpp
|
||||
src/gui/auxiliary/iterator/iterator.cpp
|
||||
src/gui/auxiliary/iterator/walker_grid.cpp
|
||||
src/gui/auxiliary/iterator/walker_widget.cpp
|
||||
src/gui/auxiliary/log.cpp
|
||||
src/gui/auxiliary/tips.cpp
|
||||
src/gui/auxiliary/widget_definition/button.cpp
|
||||
|
@ -138,7 +141,9 @@ src/side_filter.cpp
|
|||
src/terrain_filter.cpp
|
||||
src/terrain_translation.cpp
|
||||
src/tests/gui/fire_event.cpp
|
||||
src/tests/gui/iterator.cpp
|
||||
src/tests/gui/test_gui2.cpp
|
||||
src/tests/gui/visitor.cpp
|
||||
src/text.cpp
|
||||
src/widgets/button.cpp
|
||||
src/widgets/combo.cpp
|
||||
|
|
|
@ -363,6 +363,9 @@ set(wesnoth-main_SRC
|
|||
gui/auxiliary/event/dispatcher.cpp
|
||||
gui/auxiliary/event/distributor.cpp
|
||||
gui/auxiliary/event/handler.cpp
|
||||
gui/auxiliary/iterator/iterator.cpp
|
||||
gui/auxiliary/iterator/walker_grid.cpp
|
||||
gui/auxiliary/iterator/walker_widget.cpp
|
||||
gui/auxiliary/log.cpp
|
||||
gui/auxiliary/old_markup.cpp
|
||||
gui/auxiliary/timer.cpp
|
||||
|
@ -798,9 +801,11 @@ if(ENABLE_TESTS)
|
|||
tests/test_util.cpp
|
||||
tests/test_serialization.cpp
|
||||
tests/test_version.cpp
|
||||
tests/gui/iterator.cpp
|
||||
tests/gui/fire_event.cpp
|
||||
tests/gui/test_drop_target.cpp
|
||||
tests/gui/test_gui2.cpp
|
||||
tests/gui/visitor.cpp
|
||||
tests/gui/test_save_dialog.cpp
|
||||
)
|
||||
if(NOT ENABLE_GAME)
|
||||
|
|
|
@ -229,6 +229,9 @@ wesnoth_sources = Split("""
|
|||
gui/auxiliary/event/dispatcher.cpp
|
||||
gui/auxiliary/event/distributor.cpp
|
||||
gui/auxiliary/event/handler.cpp
|
||||
gui/auxiliary/iterator/iterator.cpp
|
||||
gui/auxiliary/iterator/walker_grid.cpp
|
||||
gui/auxiliary/iterator/walker_widget.cpp
|
||||
gui/auxiliary/log.cpp
|
||||
gui/auxiliary/old_markup.cpp
|
||||
gui/auxiliary/timer.cpp
|
||||
|
@ -522,9 +525,11 @@ test_sources = Split("""
|
|||
tests/test_serialization.cpp
|
||||
tests/test_version.cpp
|
||||
tests/gui/fire_event.cpp
|
||||
tests/gui/iterator.cpp
|
||||
tests/gui/test_drop_target.cpp
|
||||
tests/gui/test_gui2.cpp
|
||||
tests/gui/test_save_dialog.cpp
|
||||
tests/gui/visitor.cpp
|
||||
tests/utils/play_scenario.cpp
|
||||
""")
|
||||
test_sources.extend(test_env.Object("tests/test_config_cache.cpp"))
|
||||
|
|
79
src/gui/auxiliary/iterator/exception.hpp
Normal file
79
src/gui/auxiliary/iterator/exception.hpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains the exceptions throw by the @ref gui2::iterator::titerator classes.
|
||||
*/
|
||||
|
||||
#ifndef GUI_WIDGETS_AUXILIARY_ITERATOR_EXCEPTION_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_ITERATOR_EXCEPTION_HPP_INCLUDED
|
||||
|
||||
#include "lua_jailbreak_exception.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
/**
|
||||
* Thrown when deferring an invalid iterator.
|
||||
*
|
||||
* Invalid means the initial state at_end() == true.
|
||||
*/
|
||||
class tlogic_error
|
||||
: public std::logic_error
|
||||
, public tlua_jailbreak_exception
|
||||
{
|
||||
public:
|
||||
explicit tlogic_error(const std::string message)
|
||||
: std::logic_error("GUI2 ITERATOR: " + message)
|
||||
, tlua_jailbreak_exception()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(tlogic_error)
|
||||
};
|
||||
|
||||
/**
|
||||
* Thrown when moving an invalid iterator.
|
||||
*
|
||||
* Invalid means the initial state at_end() == true.
|
||||
*/
|
||||
class trange_error
|
||||
: public std::range_error
|
||||
, public tlua_jailbreak_exception
|
||||
{
|
||||
public:
|
||||
explicit trange_error(const std::string message)
|
||||
: std::range_error("GUI2 ITERATOR: " + message)
|
||||
, tlua_jailbreak_exception()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
IMPLEMENT_LUA_JAILBREAK_EXCEPTION(trange_error)
|
||||
};
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
188
src/gui/auxiliary/iterator/iterator.cpp
Normal file
188
src/gui/auxiliary/iterator/iterator.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include "gui/auxiliary/iterator/iterator.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
|
||||
/**
|
||||
* @page gui2_iterator GUI2 Iterator.
|
||||
*
|
||||
* The iterator class allows the user to iterate over a group of widgets.
|
||||
* The idea is to add a visitor class later as well, where the two classes
|
||||
* can be combined.
|
||||
*
|
||||
* This page describes how the iterator class works. The iterator is build
|
||||
* from several parts:
|
||||
* - level, the part and subparts of the widget to visit.
|
||||
* - walker, iterates over a single widget at several levels.
|
||||
* - visit policy, whether a level should be visited or not.
|
||||
* - order policy, the order in which the several levels are traversed.
|
||||
* - iterator, the user interface for iteration.
|
||||
*
|
||||
*
|
||||
* @section gui2_iterator_level Level
|
||||
*
|
||||
* The levels are defined in @ref gui2::iterator::twalker_::tlevel. The
|
||||
* level allows the user to only visit a part of the widget tree.
|
||||
*
|
||||
* @note At the moment when gui2::iterator::twalker_::widget is skipped the
|
||||
* child class also skips its children. This behaviour might change.
|
||||
*
|
||||
*
|
||||
* @section gui2_iterator_walker Walker
|
||||
*
|
||||
* The is a group of classes inheriting from @ref gui2::iterator::twalker_
|
||||
* the objects are created from @ref gui2::twidget::create_walker. The
|
||||
* walker allows to visit the several levels of the widget. This means
|
||||
* several widgets need to override the function in a subclass. For example
|
||||
* most @em simple widgets don't have a grid or children so they can use the
|
||||
* walker created from @ref gui2::tcontrol. But containers need to create a
|
||||
* different walker.
|
||||
*
|
||||
*
|
||||
* @section gui2_iterator_visit_policy Visit policy
|
||||
*
|
||||
* This policy simply defines whether or not to visit the widgets at a
|
||||
* certain level. There are two visit policies:
|
||||
* - @ref gui2::iterator::policy::visit::tvisit visits the widget at the level.
|
||||
* - @ref gui2::iterator::policy::visit::tskip skips the widget at the level.
|
||||
*
|
||||
* There are no more visit policies expected for the future. These policies
|
||||
* are normally not used directly, but set from the @ref
|
||||
* gui2_iterator_order_policy.
|
||||
*
|
||||
*
|
||||
* @section gui2_iterator_order_policy Order policy
|
||||
*
|
||||
* This policy determines in which order the widgets are traversed, children
|
||||
* first, this level before diving down etc. @ref tests/gui/iterator.cpp
|
||||
* shows more information.
|
||||
* The following policies have been defined:
|
||||
* - @ref gui2::iterator::policy::order::ttop_down
|
||||
* - @ref gui2::iterator::policy::order::tbottom_up
|
||||
*
|
||||
* The next sections describe in which order the widgets are visited. In the
|
||||
* description we use the following widget tree.
|
||||
*
|
||||
* [0] @n
|
||||
* \ @n
|
||||
* [1|2|3|4] @n
|
||||
* \ @n
|
||||
* [5|6|7|8] @n
|
||||
*
|
||||
* The types are:
|
||||
* - grid 0, 1
|
||||
* - control 2, 3, 4, 6, 7, 8
|
||||
*
|
||||
* The examples assume all levels will be visited.
|
||||
*
|
||||
*
|
||||
* @subsection gui2_iterator_visit_policy_top_down Top down
|
||||
*
|
||||
* The widgets visited first is the initial widget. After that it tries to go
|
||||
* down to a child widget and will continue down. Once that fails it will visit
|
||||
* the siblings at that level before going up again.
|
||||
*
|
||||
* @todo Write the entire visiting algorithm.
|
||||
*
|
||||
* The visiting order in our example is:
|
||||
* 0, 1, 5, 6, 7, 8, 2, 3, 4
|
||||
*
|
||||
*
|
||||
* @subsection gui2_iterator_visit_policy_bottom_up Bottom up
|
||||
*
|
||||
* When the iterator is created the iterator tries to go down all the child
|
||||
* widgets to get at the bottom level. That widget will be visited first. Then
|
||||
* it will first visit all sibblings before going up the the next layer.
|
||||
*
|
||||
* @todo Write the entire visiting algorithm.
|
||||
*
|
||||
* The visiting order in our example is:
|
||||
* 5, 6, 7, 8, 1, 2, 3, 4, 0
|
||||
*
|
||||
*
|
||||
* @section gui2_iterator_iterator Iterator
|
||||
*
|
||||
* The iterator is the class the users should care about. The user creates the
|
||||
* iterator with the selected policy and the root widget. Then the user can
|
||||
* visit the widgets.
|
||||
*
|
||||
* When during the iteration a widget is added to or removed from the
|
||||
* widget-tree being walked the iterator becomes invalid. Using the iterator
|
||||
* when it is invalid results in Undefined Behaviour.
|
||||
*
|
||||
* When it's certain there's at least one widget to visit a simple do while loop
|
||||
* can be used. It the policy visits the widget, it's certain there is at least
|
||||
* one widget to visit. Below some sample code:
|
||||
@code
|
||||
titerator<policy> itor(root);
|
||||
assert(!itor.at_end());
|
||||
do {
|
||||
...
|
||||
...
|
||||
} while(itor.next());
|
||||
@endcode
|
||||
*
|
||||
* When there might be no widget to visit a simple for loop can be used:
|
||||
@code
|
||||
for(titerator<policy> itor(root); !itor.at_end(); ++itor) {
|
||||
...
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
*
|
||||
*
|
||||
* @subsection gui2_iterator_iterator_design Design
|
||||
*
|
||||
* As seen in the examples above the iterator doesn't look like a iterator in
|
||||
* the C++ standard library. The iterator is more designed after the iterator
|
||||
* design of the Gang of Four [GoF]. The reason for the different design is that
|
||||
* GoF design fits better to the classes as a normal C++ iterator. The rest of
|
||||
* this section explains some of the reasons why this design is chosen. The main
|
||||
* reason is simple; the iteration of the widgets feels better suited for the
|
||||
* GoF-style iteration as the C++-style iteration.
|
||||
*
|
||||
* The iterator is not lightweight like most C++ iterators, therefore the class
|
||||
* in non-copyable. (This is for example also the reason why a std::list has no
|
||||
* operator[].) Since operator++(int) should return a copy of the original
|
||||
* object it's also omitted.
|
||||
*
|
||||
* The design makes it hard to back-track the iteration (or costs more memory),
|
||||
* so the iterator is forward only. The order policy is added to allow the
|
||||
* wanted walking direction, but one-way only.
|
||||
*
|
||||
* The iterator has a begin, but it's not easy to go back to it and the
|
||||
* operation involves rewinding the state, which might be costly. Therefore no
|
||||
* begin() function.
|
||||
*
|
||||
* The end is known at the moment it's reached, but not upfront. That combined
|
||||
* with the forward only, makes implementing an end() hard and therefore it is
|
||||
* omitted.
|
||||
*
|
||||
*
|
||||
* [GoF] http://en.wikipedia.org/wiki/Design_Patterns_%28book%29
|
||||
*/
|
||||
|
101
src/gui/auxiliary/iterator/iterator.hpp
Normal file
101
src/gui/auxiliary/iterator/iterator.hpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains the base iterator class for the gui2 widgets.
|
||||
*
|
||||
* For more information @see @ref gui2_iterator for more information.
|
||||
*/
|
||||
|
||||
#ifndef GUI_WIDGETS_AUXILIARY_ITERATOR_ITERATOR_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_ITERATOR_ITERATOR_HPP_INCLUDED
|
||||
|
||||
#include "gui/auxiliary/iterator/policy_order.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
/**
|
||||
* The iterator class.
|
||||
*
|
||||
* @see @ref gui2_iterator_iterator for more information.
|
||||
*/
|
||||
template<class order>
|
||||
class titerator
|
||||
: private order
|
||||
, private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Contstructor.
|
||||
*
|
||||
* @param root The widget where to start the iteration.
|
||||
*/
|
||||
titerator(twidget& root)
|
||||
: order(root)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the iterator reached the end?
|
||||
*
|
||||
* @returns The status.
|
||||
* @retval [true] At the end.
|
||||
* @retval [false] Not at the end.
|
||||
*/
|
||||
bool at_end() const { return order::at_end(); }
|
||||
|
||||
/**
|
||||
* Visit the next widget.
|
||||
*
|
||||
* @pre @ref at_end() == false
|
||||
*
|
||||
* @throws @ref trange_error upon pre condition violation.
|
||||
*
|
||||
* @returns Whether the next widget can be safely
|
||||
* deferred.
|
||||
*/
|
||||
bool next() { return order::next(); }
|
||||
|
||||
/** See @ref next. */
|
||||
titerator<order>& operator++()
|
||||
{
|
||||
order::next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current widget.
|
||||
*
|
||||
* @returns The current widget.
|
||||
*/
|
||||
twidget& operator*() { return order::operator*(); }
|
||||
|
||||
/** See @ref operator*. */
|
||||
twidget* operator->()
|
||||
{
|
||||
return &(operator*());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
376
src/gui/auxiliary/iterator/policy_order.hpp
Normal file
376
src/gui/auxiliary/iterator/policy_order.hpp
Normal file
|
@ -0,0 +1,376 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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_AUXILIARY_ITERATOR_POLICY_ORDER_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_ITERATOR_POLICY_ORDER_HPP_INCLUDED
|
||||
|
||||
#include "gui/auxiliary/iterator/exception.hpp"
|
||||
#include "gui/auxiliary/iterator/policy_visit.hpp"
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
#include "gui/widgets/widget.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
namespace policy {
|
||||
|
||||
namespace order {
|
||||
|
||||
template<
|
||||
bool visit_widget
|
||||
, bool visit_grid
|
||||
, bool visit_child
|
||||
>
|
||||
class tbottom_up
|
||||
: public tvisit<visit_widget, twalker_::widget>
|
||||
, public tvisit<visit_grid, twalker_::grid>
|
||||
, public tvisit<visit_child, twalker_::child>
|
||||
{
|
||||
typedef tvisit<visit_widget, twalker_::widget> tvisit_widget;
|
||||
typedef tvisit<visit_grid, twalker_::grid> tvisit_grid;
|
||||
typedef tvisit<visit_child, twalker_::child> tvisit_child;
|
||||
public:
|
||||
explicit tbottom_up(twidget& root)
|
||||
: root_(root.create_walker())
|
||||
, stack_()
|
||||
{
|
||||
TST_GUI_I << "Constructor: ";
|
||||
while(!tvisit_child::at_end(*root_)) {
|
||||
stack_.push_back(root_);
|
||||
root_ = tvisit_child::get(*root_)->create_walker();
|
||||
TST_GUI_I << " Down widget '" << operator*().id() << "'.";
|
||||
}
|
||||
|
||||
if(!at_end()) {
|
||||
TST_GUI_I << " Finished at '" << operator*().id() << "'.\n";
|
||||
} else {
|
||||
TST_GUI_I << " Finished at the end.\n";
|
||||
}
|
||||
}
|
||||
|
||||
~tbottom_up()
|
||||
{
|
||||
delete root_;
|
||||
for(std::vector<iterator::twalker_*>::iterator itor = stack_.begin()
|
||||
; itor != stack_.end()
|
||||
; ++itor) {
|
||||
|
||||
delete *itor;
|
||||
}
|
||||
}
|
||||
|
||||
bool at_end() const
|
||||
{
|
||||
return tvisit_widget::at_end(*root_)
|
||||
&& tvisit_grid::at_end(*root_)
|
||||
&& tvisit_child::at_end(*root_);
|
||||
}
|
||||
|
||||
bool next()
|
||||
{
|
||||
if(at_end()) {
|
||||
ERR_GUI_I << "Tried to move beyond end of the iteration range.\n";
|
||||
throw trange_error("Tried to move beyond end of range.");
|
||||
}
|
||||
|
||||
TST_GUI_I << "At '" << operator*().id() << "'.";
|
||||
|
||||
/***** WIDGET *****/
|
||||
TST_GUI_I << " Iterate widget:";
|
||||
if(!tvisit_widget::at_end(*root_)) {
|
||||
switch(tvisit_widget::next(*root_)) {
|
||||
case twalker_::valid :
|
||||
TST_GUI_I << " visit '" << operator*().id() << "'.\n";
|
||||
return true;
|
||||
case twalker_::invalid :
|
||||
TST_GUI_I << " reached the end.";
|
||||
break;
|
||||
case twalker_::fail:
|
||||
TST_GUI_I << "\n";
|
||||
ERR_GUI_E << "Tried to move beyond end of "
|
||||
"the widget iteration range.\n";
|
||||
throw trange_error("Tried to move beyond end of range.");
|
||||
}
|
||||
} else {
|
||||
TST_GUI_I << " failed.";
|
||||
}
|
||||
|
||||
/***** GRID *****/
|
||||
TST_GUI_I << " Iterate grid:";
|
||||
if(!tvisit_grid::at_end(*root_)) {
|
||||
switch(tvisit_grid::next(*root_)) {
|
||||
case twalker_::valid :
|
||||
TST_GUI_I << " visit '" << operator*().id() << "'.\n";
|
||||
return true;
|
||||
case twalker_::invalid :
|
||||
TST_GUI_I << " reached the end.";
|
||||
break;
|
||||
case twalker_::fail:
|
||||
TST_GUI_I << "\n";
|
||||
ERR_GUI_E << "Tried to move beyond end of "
|
||||
"the grid iteration range.\n";
|
||||
throw trange_error("Tried to move beyond end of range.");
|
||||
}
|
||||
} else {
|
||||
TST_GUI_I << " failed.";
|
||||
}
|
||||
|
||||
/***** TRAVERSE CHILDREN *****/
|
||||
|
||||
TST_GUI_I << " Iterate child:";
|
||||
if(tvisit_child::at_end(*root_)) {
|
||||
if(stack_.empty()) {
|
||||
TST_GUI_I << " Finished iteration.\n";
|
||||
return false;
|
||||
} else {
|
||||
delete root_;
|
||||
|
||||
root_ = stack_.back();
|
||||
stack_.pop_back();
|
||||
TST_GUI_I << " Up '" << operator*().id() << "'.";
|
||||
}
|
||||
}
|
||||
TST_GUI_I << " Iterate child:";
|
||||
if(!tvisit_child::at_end(*root_)) {
|
||||
switch(tvisit_child::next(*root_)) {
|
||||
case twalker_::valid :
|
||||
TST_GUI_I << " visit '" << operator*().id() << "'.";
|
||||
break;
|
||||
case twalker_::invalid :
|
||||
TST_GUI_I << " reached the end.";
|
||||
break;
|
||||
case twalker_::fail:
|
||||
TST_GUI_I << "\n";
|
||||
ERR_GUI_E << "Tried to move beyond end of "
|
||||
"the child iteration range.\n";
|
||||
throw trange_error("Tried to move beyond end of range.");
|
||||
}
|
||||
} else {
|
||||
TST_GUI_I << " already at the end.";
|
||||
}
|
||||
|
||||
while(!tvisit_child::at_end(*root_)) {
|
||||
stack_.push_back(root_);
|
||||
root_ = tvisit_child::get(*root_)->create_walker();
|
||||
TST_GUI_I << " Down widget '"
|
||||
<< operator*().id() << "'.";
|
||||
}
|
||||
TST_GUI_I << " Visit '" << operator*().id() << "'.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
twidget& operator*()
|
||||
{
|
||||
if(at_end()) {
|
||||
ERR_GUI_I << "Tried to defer beyond end its "
|
||||
"iteration range iterator.\n";
|
||||
throw tlogic_error("Tried to defer an invalid iterator.");
|
||||
}
|
||||
if(!tvisit_widget::at_end(*root_)) {
|
||||
return *tvisit_widget::get(*root_);
|
||||
}
|
||||
if(!tvisit_grid::at_end(*root_)) {
|
||||
return *tvisit_grid::get(*root_);
|
||||
}
|
||||
if(!tvisit_child::at_end(*root_)) {
|
||||
return *tvisit_child::get(*root_);
|
||||
}
|
||||
ERR_GUI_I << "The iterator ended in an unknown "
|
||||
"state while deferring iteself.\n";
|
||||
throw tlogic_error("Tried to defer an invalid iterator.");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
iterator::twalker_* root_;
|
||||
|
||||
std::vector<iterator::twalker_*> stack_;
|
||||
};
|
||||
|
||||
template<
|
||||
bool visit_widget
|
||||
, bool visit_grid
|
||||
, bool visit_child
|
||||
>
|
||||
class ttop_down
|
||||
: public tvisit<visit_widget, twalker_::widget>
|
||||
, public tvisit<visit_grid, twalker_::grid>
|
||||
, public tvisit<visit_child, twalker_::child>
|
||||
{
|
||||
typedef tvisit<visit_widget, twalker_::widget> tvisit_widget;
|
||||
typedef tvisit<visit_grid, twalker_::grid> tvisit_grid;
|
||||
typedef tvisit<visit_child, twalker_::child> tvisit_child;
|
||||
public:
|
||||
explicit ttop_down (twidget& root)
|
||||
: root_(root.create_walker())
|
||||
, stack_()
|
||||
{
|
||||
}
|
||||
|
||||
~ttop_down()
|
||||
{
|
||||
delete root_;
|
||||
for(std::vector<iterator::twalker_*>::iterator itor = stack_.begin()
|
||||
; itor != stack_.end()
|
||||
; ++itor) {
|
||||
|
||||
delete *itor;
|
||||
}
|
||||
}
|
||||
|
||||
bool at_end() const
|
||||
{
|
||||
return tvisit_widget::at_end(*root_)
|
||||
&& tvisit_grid::at_end(*root_)
|
||||
&& tvisit_child::at_end(*root_);
|
||||
}
|
||||
|
||||
bool next()
|
||||
{
|
||||
if(at_end()) {
|
||||
ERR_GUI_I << "Tried to move beyond end of the iteration range.\n";
|
||||
throw trange_error("Tried to move beyond end of range.");
|
||||
}
|
||||
|
||||
TST_GUI_I << "At '" << operator*().id() << "'.";
|
||||
|
||||
/***** WIDGET *****/
|
||||
TST_GUI_I << " Iterate widget:";
|
||||
if(!tvisit_widget::at_end(*root_)) {
|
||||
switch(tvisit_widget::next(*root_)) {
|
||||
case twalker_::valid :
|
||||
TST_GUI_I << " visit '" << operator*().id() << "'.\n";
|
||||
return true;
|
||||
case twalker_::invalid :
|
||||
TST_GUI_I << " reached the end.";
|
||||
break;
|
||||
case twalker_::fail:
|
||||
TST_GUI_I << "\n";
|
||||
ERR_GUI_E << "Tried to move beyond end of the "
|
||||
"widget iteration range.\n";
|
||||
throw trange_error("Tried to move beyond end of range.");
|
||||
}
|
||||
} else {
|
||||
TST_GUI_I << " failed.";
|
||||
}
|
||||
|
||||
/***** GRID *****/
|
||||
TST_GUI_I << " Iterate grid:";
|
||||
if(!tvisit_grid::at_end(*root_)) {
|
||||
switch(tvisit_grid::next(*root_)) {
|
||||
case twalker_::valid :
|
||||
TST_GUI_I << " visit '" << operator*().id() << "'.\n";
|
||||
return true;
|
||||
case twalker_::invalid :
|
||||
TST_GUI_I << " reached the end.";
|
||||
break;
|
||||
case twalker_::fail:
|
||||
TST_GUI_I << "\n";
|
||||
ERR_GUI_E << "Tried to move beyond end of the grid "
|
||||
"iteration range.\n";
|
||||
throw trange_error("Tried to move beyond end of range.");
|
||||
}
|
||||
} else {
|
||||
TST_GUI_I << " failed.";
|
||||
}
|
||||
|
||||
/***** TRAVERSE CHILDREN *****/
|
||||
|
||||
TST_GUI_I << " Iterate child:";
|
||||
if(tvisit_child::at_end(*root_)) {
|
||||
TST_GUI_I << " reached the end.";
|
||||
up();
|
||||
} else {
|
||||
TST_GUI_I << " proceed.";
|
||||
}
|
||||
|
||||
if(!tvisit_child::at_end(*root_)) {
|
||||
stack_.push_back(root_);
|
||||
root_ = tvisit_child::get(*root_)->create_walker();
|
||||
|
||||
assert(root_);
|
||||
assert(!at_end());
|
||||
TST_GUI_I << " Down and visit '" << operator*().id() << "'.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
TST_GUI_I << " Finished iteration.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
twidget& operator*()
|
||||
{
|
||||
if(at_end()) {
|
||||
ERR_GUI_I << "Tried to defer beyond end of the iteration "
|
||||
"range iterator.\n";
|
||||
throw tlogic_error("Tried to defer an invalid iterator.");
|
||||
}
|
||||
if(!tvisit_widget::at_end(*root_)) {
|
||||
return *tvisit_widget::get(*root_);
|
||||
}
|
||||
if(!tvisit_grid::at_end(*root_)) {
|
||||
return *tvisit_grid::get(*root_);
|
||||
}
|
||||
if(!tvisit_child::at_end(*root_)) {
|
||||
return *tvisit_child::get(*root_);
|
||||
}
|
||||
ERR_GUI_I << "The iterator ended in an unknown "
|
||||
"state while deferring iteself.\n";
|
||||
throw tlogic_error("Tried to defer an invalid iterator.");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool up()
|
||||
{
|
||||
while(!stack_.empty()) {
|
||||
delete root_;
|
||||
|
||||
root_ = stack_.back();
|
||||
stack_.pop_back();
|
||||
TST_GUI_I << " Up widget '" << operator*().id() << "'. Iterate:";
|
||||
switch(tvisit_child::next(*root_)) {
|
||||
case twalker_::valid:
|
||||
TST_GUI_I << " reached '" << operator*().id() << "'.";
|
||||
return true;
|
||||
case twalker_::invalid:
|
||||
TST_GUI_I << " failed.";
|
||||
break;
|
||||
case twalker_::fail:
|
||||
throw trange_error("Tried to move beyond end of range.");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
iterator::twalker_* root_;
|
||||
|
||||
std::vector<iterator::twalker_*> stack_;
|
||||
};
|
||||
|
||||
} // namespace order
|
||||
|
||||
} // namespace policy
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
||||
|
123
src/gui/auxiliary/iterator/policy_visit.hpp
Normal file
123
src/gui/auxiliary/iterator/policy_visit.hpp
Normal file
|
@ -0,0 +1,123 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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_AUXILIARY_ITERATOR_POLICY_VISIT_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_ITERATOR_POLICY_VISIT_HPP_INCLUDED
|
||||
|
||||
#include "gui/auxiliary/iterator/walker.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
namespace policy {
|
||||
|
||||
namespace visit {
|
||||
|
||||
/**
|
||||
* This policy skips the current level.
|
||||
*/
|
||||
class tskip
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Acts like @ref twalker_::next for the level where the policy is used.
|
||||
*/
|
||||
twalker_::tstate next(twalker_&) { return twalker_::fail; }
|
||||
|
||||
/**
|
||||
* Acts like @ref twalker_::at_end for the level where the policy is used.
|
||||
*/
|
||||
bool at_end(const twalker_&) const { return true; }
|
||||
|
||||
/**
|
||||
* Acts like @ref twalker_::get for the level where the policy is used.
|
||||
*/
|
||||
gui2::twidget* get(twalker_&) { return NULL; }
|
||||
};
|
||||
|
||||
/**
|
||||
* This policy tries to visit the current level.
|
||||
*
|
||||
* @tparam level The level to visit.
|
||||
*/
|
||||
template<twalker_::tlevel level>
|
||||
class tvisit
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Acts like @ref twalker_::next for the level where the policy is used.
|
||||
*/
|
||||
twalker_::tstate next(twalker_& visitor)
|
||||
{
|
||||
return visitor.next(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts like @ref twalker_::at_end for the level where the policy is used.
|
||||
*/
|
||||
bool at_end(const twalker_& visitor) const
|
||||
{
|
||||
return visitor.at_end(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts like @ref twalker_::get for the level where the policy is used.
|
||||
*/
|
||||
gui2::twidget* get(twalker_& visitor)
|
||||
{
|
||||
return visitor.get(level);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace visit
|
||||
|
||||
/**
|
||||
* Helper class to select to visit or skip a level.
|
||||
*
|
||||
* @tparam level The level to determine the policy for.
|
||||
*/
|
||||
template<bool, twalker_::tlevel level>
|
||||
class tvisit
|
||||
{
|
||||
};
|
||||
|
||||
/** Specialized to select the @ref visit::tskip policy. */
|
||||
template<twalker_::tlevel level>
|
||||
class tvisit<false, level>
|
||||
: public visit::tskip
|
||||
{
|
||||
};
|
||||
|
||||
/** Specialized to select the @ref visit::tvisit policy. */
|
||||
template<twalker_::tlevel level>
|
||||
class tvisit<true, level>
|
||||
: public visit::tvisit<level>
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace policy
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
||||
|
121
src/gui/auxiliary/iterator/walker.hpp
Normal file
121
src/gui/auxiliary/iterator/walker.hpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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_AUXILIARY_ITERATOR_WALKER_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_ITERATOR_WALKER_HPP_INCLUDED
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
class twidget;
|
||||
|
||||
namespace iterator {
|
||||
|
||||
/** The walker abstract base class. */
|
||||
class twalker_
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~twalker_() {}
|
||||
|
||||
/** The level to walk at. */
|
||||
enum tlevel
|
||||
{
|
||||
/** Visit the widget itself. */
|
||||
widget
|
||||
/** Visit its nested grid. */
|
||||
, grid
|
||||
/** Visit the children of its nested grid. */
|
||||
, child
|
||||
};
|
||||
|
||||
/**
|
||||
* The state of the walker.
|
||||
*
|
||||
* The enum is used to return the state of @ref next.
|
||||
*/
|
||||
enum tstate
|
||||
{
|
||||
/**
|
||||
* When calling next the following it has the following results.
|
||||
*
|
||||
* @pre at_end == false
|
||||
*
|
||||
* @post the next widget became the current one.
|
||||
* @post at_end == false
|
||||
*/
|
||||
valid
|
||||
|
||||
/**
|
||||
* When calling next the following it has the following results.
|
||||
*
|
||||
* @pre at_end == false
|
||||
*
|
||||
* @post there is no longer a current widget.
|
||||
* @post at_end == true
|
||||
*/
|
||||
, invalid
|
||||
|
||||
/**
|
||||
* When calling next the following it has the following results.
|
||||
*
|
||||
* @pre at_end == true
|
||||
*
|
||||
* @post at_end == true
|
||||
*/
|
||||
, fail
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the next widget the current one.
|
||||
*
|
||||
* @param level Determines on which level the next one should
|
||||
* be selected.
|
||||
*
|
||||
* @returns The status of the operation.
|
||||
*/
|
||||
virtual tstate next(const tlevel level) = 0;
|
||||
|
||||
/**
|
||||
* Returns whether the current widget is valid.
|
||||
*
|
||||
* @param level Determines on which level the test should be
|
||||
* executed.
|
||||
*
|
||||
*
|
||||
* @returns Whether the current widget is valid.
|
||||
*/
|
||||
virtual bool at_end(const tlevel level) const = 0;
|
||||
|
||||
/**
|
||||
* Returns a pointer to the current widget.
|
||||
*
|
||||
* @pre @ref at_end(level) == false
|
||||
*
|
||||
* @param level Determines from which level should the
|
||||
* current widget be returned.
|
||||
*
|
||||
* @returns Pointer to the current widget.
|
||||
*/
|
||||
virtual gui2::twidget* get(const tlevel level) = 0;
|
||||
};
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
||||
|
101
src/gui/auxiliary/iterator/walker_grid.cpp
Normal file
101
src/gui/auxiliary/iterator/walker_grid.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include "gui/auxiliary/iterator/walker_grid.hpp"
|
||||
|
||||
#include "asserts.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
tgrid::tgrid(gui2::tgrid& grid)
|
||||
: grid_(grid)
|
||||
, widget_(&grid)
|
||||
, itor_(grid.begin())
|
||||
{
|
||||
}
|
||||
|
||||
twalker_::tstate tgrid::next(const tlevel level)
|
||||
{
|
||||
if(at_end(level)) {
|
||||
return fail;
|
||||
}
|
||||
|
||||
switch(level) {
|
||||
case widget:
|
||||
if(widget_) {
|
||||
widget_ = NULL;
|
||||
return invalid;
|
||||
} else {
|
||||
/* FALL DOWN */
|
||||
}
|
||||
case grid:
|
||||
assert(false);
|
||||
return fail;
|
||||
case child:
|
||||
if(itor_ == grid_.end()) {
|
||||
/* FALL DOWN */
|
||||
} else {
|
||||
++itor_;
|
||||
return itor_ == grid_.end() ? invalid : valid;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return fail;
|
||||
}
|
||||
|
||||
bool tgrid::at_end(const tlevel level) const
|
||||
{
|
||||
switch(level) {
|
||||
case widget:
|
||||
return widget_ == NULL;
|
||||
case grid:
|
||||
return true;
|
||||
case child:
|
||||
return (itor_ == grid_.end());
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
gui2::twidget* tgrid::get(const tlevel level)
|
||||
{
|
||||
switch(level) {
|
||||
case widget:
|
||||
return widget_;
|
||||
case grid:
|
||||
return NULL;
|
||||
case child:
|
||||
if(itor_ == grid_.end()) {
|
||||
return NULL;
|
||||
} else {
|
||||
return *itor_;
|
||||
}
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
|
78
src/gui/auxiliary/iterator/walker_grid.hpp
Normal file
78
src/gui/auxiliary/iterator/walker_grid.hpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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_AUXILIARY_WALKER_VISITOR_GRID_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_WALKER_VISITOR_GRID_HPP_INCLUDED
|
||||
|
||||
#include "gui/auxiliary/iterator/walker.hpp"
|
||||
|
||||
#include "gui/widgets/grid.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
/** A walker for a @ref gui2::tgrid. */
|
||||
class tgrid
|
||||
: public twalker_
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param grid The grid which the walker is attached to.
|
||||
*/
|
||||
explicit tgrid(gui2::tgrid& grid);
|
||||
|
||||
/** Inherited from @ref gui2::iterator::twalker_. */
|
||||
virtual tstate next(const tlevel level);
|
||||
|
||||
/** Inherited from @ref gui2::iterator::twalker_. */
|
||||
virtual bool at_end(const tlevel level) const;
|
||||
|
||||
/** Inherited from @ref gui2::iterator::twalker_. */
|
||||
virtual gui2::twidget* get(const tlevel level);
|
||||
|
||||
private:
|
||||
|
||||
/** The grid which the walker is attached to. */
|
||||
gui2::tgrid& grid_;
|
||||
|
||||
/**
|
||||
* The grid which the walker is attached to.
|
||||
*
|
||||
* This variable is used to track whether the @ref
|
||||
* gui2::iterator::twalker_::widget level has been visited.
|
||||
*/
|
||||
gui2::twidget* widget_;
|
||||
|
||||
/**
|
||||
* The iterator to the children of @ref grid_.
|
||||
*
|
||||
* This variable is used to track where the @ref
|
||||
* gui2::iterator::twalker_::child level visiting is.
|
||||
*/
|
||||
gui2::tgrid::iterator itor_;
|
||||
};
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
91
src/gui/auxiliary/iterator/walker_widget.cpp
Normal file
91
src/gui/auxiliary/iterator/walker_widget.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include "gui/auxiliary/iterator/walker_widget.hpp"
|
||||
|
||||
#include "asserts.hpp"
|
||||
#include "gui/widgets/widget.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
namespace walker {
|
||||
|
||||
twidget::twidget(gui2::twidget& widget)
|
||||
: widget_(&widget)
|
||||
{
|
||||
}
|
||||
|
||||
twalker_::tstate twidget::next(const tlevel level)
|
||||
{
|
||||
if(at_end(level)) {
|
||||
return fail;
|
||||
}
|
||||
|
||||
switch(level) {
|
||||
case widget:
|
||||
if(widget_) {
|
||||
widget_ = NULL;
|
||||
return invalid;
|
||||
} else {
|
||||
/* FALL DOWN */
|
||||
}
|
||||
case grid: /* FALL DOWN */
|
||||
case child: /* FALL DOWN */
|
||||
;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return fail;
|
||||
}
|
||||
|
||||
bool twidget::at_end(const tlevel level) const
|
||||
{
|
||||
switch(level) {
|
||||
case widget:
|
||||
return widget_ == NULL;
|
||||
case grid: /* FALL DOWN */
|
||||
case child:
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
gui2::twidget* twidget::get(const tlevel level)
|
||||
{
|
||||
switch(level) {
|
||||
case widget:
|
||||
return widget_;
|
||||
case grid: /* FALL DOWN */
|
||||
case child:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace walker
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
|
62
src/gui/auxiliary/iterator/walker_widget.hpp
Normal file
62
src/gui/auxiliary/iterator/walker_widget.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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_AUXILIARY_ITERATOR_WALKER_WIDGET_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_AUXILIARY_ITERATOR_WALKER_WIDGET_HPP_INCLUDED
|
||||
|
||||
#include "gui/auxiliary/iterator/walker.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace iterator {
|
||||
|
||||
namespace walker {
|
||||
|
||||
/** A walker for a @ref gui2::tcontrol. */
|
||||
class twidget
|
||||
: public twalker_
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param widget The control which the walker is attached to.
|
||||
*/
|
||||
explicit twidget(gui2::twidget& widget);
|
||||
|
||||
/** Inherited from @ref gui2::iterator::twalker_. */
|
||||
virtual tstate next(const tlevel level);
|
||||
|
||||
/** Inherited from @ref gui2::iterator::twalker_. */
|
||||
virtual bool at_end(const tlevel level) const;
|
||||
|
||||
/** Inherited from @ref gui2::iterator::twalker_. */
|
||||
virtual gui2::twidget* get(const tlevel level);
|
||||
|
||||
private:
|
||||
|
||||
/** The control which the walker is attached to. */
|
||||
gui2::twidget* widget_;
|
||||
};
|
||||
|
||||
} // namespace walker
|
||||
|
||||
} // namespace iterator
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@ namespace gui2 {
|
|||
lg::log_domain log_gui_draw ("gui/draw");
|
||||
lg::log_domain log_gui_event ("gui/event");
|
||||
lg::log_domain log_gui_general ("gui/general");
|
||||
lg::log_domain log_gui_iterator("gui/iterator");
|
||||
lg::log_domain log_gui_lifetime("gui/lifetime");
|
||||
lg::log_domain log_gui_layout ("gui/layout");
|
||||
lg::log_domain log_gui_parse ("gui/parse");
|
||||
|
|
|
@ -43,6 +43,15 @@ extern lg::log_domain log_gui_general;
|
|||
#define WRN_GUI_G LOG_STREAM_INDENT(warn, gui2::log_gui_general)
|
||||
#define ERR_GUI_G LOG_STREAM_INDENT(err, gui2::log_gui_general)
|
||||
|
||||
extern lg::log_domain log_gui_iterator;
|
||||
#define TST_GUI_I \
|
||||
if(lg::debug.dont_log(gui2::log_gui_iterator)); \
|
||||
else lg::debug(gui2::log_gui_iterator, false, false)
|
||||
#define DBG_GUI_I LOG_STREAM_INDENT(debug, gui2::log_gui_iterator)
|
||||
#define LOG_GUI_I LOG_STREAM_INDENT(info, gui2::log_gui_iterator)
|
||||
#define WRN_GUI_I LOG_STREAM_INDENT(warn, gui2::log_gui_iterator)
|
||||
#define ERR_GUI_I LOG_STREAM_INDENT(err, gui2::log_gui_iterator)
|
||||
|
||||
extern lg::log_domain log_gui_layout;
|
||||
#define DBG_GUI_L LOG_STREAM_INDENT(debug, gui2::log_gui_layout)
|
||||
#define LOG_GUI_L LOG_STREAM_INDENT(info, gui2::log_gui_layout)
|
||||
|
|
|
@ -148,6 +148,13 @@ public:
|
|||
/** Inherited from tcontrol. */
|
||||
bool disable_click_dismiss() const;
|
||||
|
||||
/**
|
||||
* Inherited from twidget.
|
||||
*
|
||||
* @todo Implement properly.
|
||||
*/
|
||||
virtual iterator::twalker_* create_walker() { return NULL; }
|
||||
|
||||
/**
|
||||
* Initializes and builds the grid.
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "font.hpp"
|
||||
#include "foreach.hpp"
|
||||
#include "formula_string_utils.hpp"
|
||||
#include "gui/auxiliary/iterator/walker_widget.hpp"
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
#include "gui/auxiliary/event/message.hpp"
|
||||
#include "gui/dialogs/tip.hpp"
|
||||
|
@ -111,6 +112,11 @@ bool tcontrol::disable_click_dismiss() const
|
|||
return get_visible() == twidget::VISIBLE && get_active();
|
||||
}
|
||||
|
||||
iterator::twalker_* tcontrol::create_walker()
|
||||
{
|
||||
return new iterator::walker::twidget(*this);
|
||||
}
|
||||
|
||||
tpoint tcontrol::get_config_minimum_size() const
|
||||
{
|
||||
assert(config_);
|
||||
|
|
|
@ -80,6 +80,9 @@ public:
|
|||
*/
|
||||
bool disable_click_dismiss() const;
|
||||
|
||||
/** Inherited from twidget. */
|
||||
virtual iterator::twalker_* create_walker();
|
||||
|
||||
/***** ***** ***** ***** layout functions ***** ***** ***** *****/
|
||||
|
||||
/**
|
||||
|
|
|
@ -846,6 +846,13 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherited from twidget.
|
||||
*
|
||||
* @todo Implement properly.
|
||||
*/
|
||||
virtual iterator::twalker_* create_walker() { return NULL; }
|
||||
|
||||
/***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
|
||||
|
||||
/** Inherited from tgenerator_. */
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "gui/widgets/grid_private.hpp"
|
||||
|
||||
#include "gui/auxiliary/iterator/walker_grid.hpp"
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
#include "gui/auxiliary/layout_exception.hpp"
|
||||
|
||||
|
@ -651,6 +652,11 @@ bool tgrid::disable_click_dismiss() const
|
|||
return false;
|
||||
}
|
||||
|
||||
iterator::twalker_* tgrid::create_walker()
|
||||
{
|
||||
return new gui2::iterator::tgrid(*this);
|
||||
}
|
||||
|
||||
void tgrid::set_rows(const unsigned rows)
|
||||
{
|
||||
if(rows == rows_) {
|
||||
|
|
|
@ -272,6 +272,9 @@ public:
|
|||
/** Inherited from tcontrol. */
|
||||
bool disable_click_dismiss() const;
|
||||
|
||||
/** Inherited from twidget. */
|
||||
virtual iterator::twalker_* create_walker();
|
||||
|
||||
/***** ***** ***** setters / getters for members ***** ****** *****/
|
||||
|
||||
void set_rows(const unsigned rows);
|
||||
|
@ -375,6 +378,9 @@ public:
|
|||
twidget* operator->() { return itor_->widget(); }
|
||||
twidget* operator*() { return itor_->widget(); }
|
||||
|
||||
bool operator==(const iterator& i) const
|
||||
{ return i.itor_ == this->itor_; }
|
||||
|
||||
bool operator!=(const iterator& i) const
|
||||
{ return i.itor_ != this->itor_; }
|
||||
|
||||
|
|
|
@ -121,6 +121,13 @@ public:
|
|||
// void unfold(const texpand_mode mode); // FIXME implement
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Inherited from twidget.
|
||||
*
|
||||
* @todo Implement properly.
|
||||
*/
|
||||
virtual iterator::twalker_* create_walker() { return NULL; }
|
||||
|
||||
/** Inherited from twidget.*/
|
||||
twidget* find_at(const tpoint& coordinate, const bool must_be_active);
|
||||
|
||||
|
|
|
@ -32,6 +32,10 @@ namespace gui2 {
|
|||
class tdialog;
|
||||
class twindow;
|
||||
|
||||
namespace iterator {
|
||||
class twalker_;
|
||||
} // namespace iterator
|
||||
|
||||
typedef std::map< std::string, t_string > string_map;
|
||||
|
||||
/**
|
||||
|
@ -347,6 +351,9 @@ public:
|
|||
/** Does the widget disable easy close? */
|
||||
virtual bool disable_click_dismiss() const = 0;
|
||||
|
||||
/** Creates a new walker object on the heap. */
|
||||
virtual iterator::twalker_* create_walker() = 0;
|
||||
|
||||
/***** ***** ***** setters / getters for members ***** ****** *****/
|
||||
|
||||
twidget* parent() { return parent_; }
|
||||
|
|
282
src/tests/gui/iterator.cpp
Normal file
282
src/tests/gui/iterator.cpp
Normal file
|
@ -0,0 +1,282 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "config_cache.hpp"
|
||||
#include "gui/auxiliary/iterator/iterator.hpp"
|
||||
#include "gui/widgets/label.hpp"
|
||||
#include "gui/widgets/grid.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <typeinfo>
|
||||
|
||||
/*
|
||||
* In the unit tests we use a widget tree that looks like:
|
||||
*
|
||||
* [0]
|
||||
* \
|
||||
* [1|2|3|4]
|
||||
* \
|
||||
* [5|6|7|8]
|
||||
*
|
||||
* Where widgets 0 and 1 are a grid and the rest of the widgets a label.
|
||||
* The unit tests traverse the tree.
|
||||
*/
|
||||
|
||||
static std::string top_down_t_t_t_result()
|
||||
{
|
||||
static const std::string result =
|
||||
"At '0'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: proceed. Down and visit '1'.\n"
|
||||
"At '1'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: proceed. Down and visit '5'.\n"
|
||||
"At '5'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: reached the end. Up widget '5'. "
|
||||
"Iterate: reached '6'. Down and visit '6'.\n"
|
||||
"At '6'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: reached the end. Up widget '6'. "
|
||||
"Iterate: reached '7'. Down and visit '7'.\n"
|
||||
"At '7'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: reached the end. Up widget '7'. "
|
||||
"Iterate: reached '8'. Down and visit '8'.\n"
|
||||
"At '8'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: reached the end. Up widget '8'. "
|
||||
"Iterate: failed. Up widget '1'. "
|
||||
"Iterate: reached '2'. Down and visit '2'.\n"
|
||||
"At '2'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: reached the end. Up widget '2'. "
|
||||
"Iterate: reached '3'. Down and visit '3'.\n"
|
||||
"At '3'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: reached the end. Up widget '3'. "
|
||||
"Iterate: reached '4'. Down and visit '4'.\n"
|
||||
"At '4'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: reached the end. Up widget '4'. "
|
||||
"Iterate: failed. Finished iteration.\n";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string bottom_up_t_t_t_result()
|
||||
{
|
||||
static const std::string result =
|
||||
"Constructor: Down widget '1'. Down widget '5'. Finished at '5'.\n"
|
||||
"At '5'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Up '1'. Iterate child: visit '1'. "
|
||||
"Down widget '6'. Visit '6'.\n"
|
||||
"At '6'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Up '1'. Iterate child: visit '1'. "
|
||||
"Down widget '7'. Visit '7'.\n"
|
||||
"At '7'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Up '1'. Iterate child: visit '1'. "
|
||||
"Down widget '8'. Visit '8'.\n"
|
||||
"At '8'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Up '1'. Iterate child: reached the end. Visit '1'.\n"
|
||||
"At '1'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Up '0'. Iterate child: visit '0'. "
|
||||
"Down widget '2'. Visit '2'.\n"
|
||||
"At '2'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Up '0'. Iterate child: visit '0'. "
|
||||
"Down widget '3'. Visit '3'.\n"
|
||||
"At '3'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Up '0'. Iterate child: visit '0'. "
|
||||
"Down widget '4'. Visit '4'.\n"
|
||||
"At '4'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Up '0'. Iterate child: reached the end. Visit '0'.\n"
|
||||
"At '0'. Iterate widget: reached the end. Iterate grid: failed. "
|
||||
"Iterate child: Finished iteration.\n";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void add_widget(gui2::tgrid& grid
|
||||
, gui2::twidget* widget
|
||||
, const std::string& id
|
||||
, const unsigned row
|
||||
, const unsigned column)
|
||||
{
|
||||
BOOST_REQUIRE_NE(widget, (gui2::twidget*)NULL);
|
||||
|
||||
widget->set_id(id);
|
||||
grid.set_child(widget
|
||||
, row
|
||||
, column
|
||||
, gui2::tgrid::VERTICAL_GROW_SEND_TO_CLIENT
|
||||
| gui2::tgrid::HORIZONTAL_GROW_SEND_TO_CLIENT
|
||||
, 0);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void test_control()
|
||||
{
|
||||
T control;
|
||||
|
||||
{
|
||||
gui2::iterator::titerator< gui2::iterator::policy::order::ttop_down<
|
||||
true
|
||||
, true
|
||||
, true> >
|
||||
iterator(control);
|
||||
|
||||
/***** INITIAL STATE *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(iterator.at_end(), false);
|
||||
|
||||
BOOST_CHECK_EQUAL(&*iterator, &control);
|
||||
|
||||
/***** POST END *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(iterator.next(), false);
|
||||
|
||||
BOOST_CHECK_EQUAL(iterator.at_end(), true);
|
||||
|
||||
}
|
||||
{
|
||||
gui2::iterator::titerator< gui2::iterator::policy::order::ttop_down<
|
||||
false
|
||||
, true
|
||||
, true> >
|
||||
iterator(control);
|
||||
|
||||
/***** INITIAL STATE *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(iterator.at_end(), true);
|
||||
}
|
||||
|
||||
{
|
||||
gui2::iterator::titerator<gui2::iterator::policy::order::tbottom_up<true, true, true> > iterator(control);
|
||||
BOOST_CHECK_EQUAL(iterator.at_end(), false);
|
||||
}
|
||||
{
|
||||
gui2::iterator::titerator<gui2::iterator::policy::order::tbottom_up<false, false, false> > iterator(control);
|
||||
BOOST_CHECK_EQUAL(iterator.at_end(), true);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_control()
|
||||
{
|
||||
/* Could add more widgets to the list. */
|
||||
test_control<gui2::tlabel>();
|
||||
|
||||
}
|
||||
|
||||
static void test_grid()
|
||||
{
|
||||
/* An empty grid behaves the same as a control so test here. */
|
||||
test_control<gui2::tgrid>();
|
||||
|
||||
/* Test the child part here. */
|
||||
gui2::tgrid grid(2 ,2);
|
||||
grid.set_id("0");
|
||||
|
||||
gui2::tgrid* g = new gui2::tgrid(2, 2);
|
||||
add_widget(grid, g, "1", 0, 0);
|
||||
add_widget(grid, new gui2::tlabel(), "2", 1, 0);
|
||||
add_widget(grid, new gui2::tlabel(), "3", 0, 1);
|
||||
add_widget(grid, new gui2::tlabel(), "4", 1, 1);
|
||||
|
||||
add_widget(*g, new gui2::tlabel(), "5", 0, 0);
|
||||
add_widget(*g, new gui2::tlabel(), "6", 1, 0);
|
||||
add_widget(*g, new gui2::tlabel(), "7", 0, 1);
|
||||
add_widget(*g, new gui2::tlabel(), "8", 1, 1);
|
||||
|
||||
{
|
||||
std::stringstream sstr;
|
||||
lg::tredirect_output_setter redirect_output(sstr);
|
||||
|
||||
gui2::iterator::titerator<gui2::iterator::policy::order::ttop_down<
|
||||
true
|
||||
, true
|
||||
, true> >
|
||||
iterator(grid);
|
||||
|
||||
while(iterator.next()) {
|
||||
/* DO NOTHING */
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(top_down_t_t_t_result(), sstr.str());
|
||||
}
|
||||
{
|
||||
std::stringstream sstr;
|
||||
lg::tredirect_output_setter redirect_output(sstr);
|
||||
|
||||
gui2::iterator::titerator<gui2::iterator::policy::order::ttop_down<
|
||||
true
|
||||
, true
|
||||
, true> >
|
||||
iterator(grid);
|
||||
|
||||
for( ; !iterator.at_end(); ++iterator) {
|
||||
/* DO NOTHING */
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(top_down_t_t_t_result(), sstr.str());
|
||||
}
|
||||
{
|
||||
std::stringstream sstr;
|
||||
lg::tredirect_output_setter redirect_output(sstr);
|
||||
|
||||
gui2::iterator::titerator<gui2::iterator::policy::order::tbottom_up<
|
||||
true
|
||||
, true
|
||||
, true> >
|
||||
iterator(grid);
|
||||
|
||||
while(iterator.next()) {
|
||||
/* DO NOTHING */
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(bottom_up_t_t_t_result(), sstr.str());
|
||||
}
|
||||
{
|
||||
std::stringstream sstr;
|
||||
lg::tredirect_output_setter redirect_output(sstr);
|
||||
|
||||
gui2::iterator::titerator<gui2::iterator::policy::order::tbottom_up<
|
||||
true
|
||||
, true
|
||||
, true> >
|
||||
iterator(grid);
|
||||
|
||||
for( ; !iterator.at_end(); ++iterator) {
|
||||
/* DO NOTHING */
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(bottom_up_t_t_t_result(), sstr.str());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_gui2_iterator)
|
||||
{
|
||||
/**** Initialize the environment. *****/
|
||||
game_config::config_cache& cache = game_config::config_cache::instance();
|
||||
|
||||
cache.clear_defines();
|
||||
cache.add_define("EDITOR");
|
||||
cache.add_define("MULTIPLAYER");
|
||||
|
||||
lg::set_log_domain_severity("gui/iterator", 3); // FIXME get_severity or something like it
|
||||
lg::timestamps(false);
|
||||
|
||||
std::stringstream sstr;
|
||||
lg::tredirect_output_setter redirect_output(sstr);
|
||||
|
||||
test_control();
|
||||
test_grid();
|
||||
}
|
||||
|
168
src/tests/gui/visitor.cpp
Normal file
168
src/tests/gui/visitor.cpp
Normal file
|
@ -0,0 +1,168 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2011 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 as published by
|
||||
the Free Software Foundation; either version 2 of the License, 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.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "config_cache.hpp"
|
||||
#include "gui/auxiliary/iterator/walker.hpp"
|
||||
#include "gui/widgets/label.hpp"
|
||||
#include "gui/widgets/grid.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
|
||||
static void add_widget(gui2::tgrid& grid
|
||||
, gui2::twidget* widget
|
||||
, const std::string& id
|
||||
, const unsigned row
|
||||
, const unsigned column)
|
||||
{
|
||||
BOOST_REQUIRE_NE(widget, (gui2::twidget*)NULL);
|
||||
|
||||
widget->set_id(id);
|
||||
grid.set_child(widget
|
||||
, row
|
||||
, column
|
||||
, gui2::tgrid::VERTICAL_GROW_SEND_TO_CLIENT
|
||||
| gui2::tgrid::HORIZONTAL_GROW_SEND_TO_CLIENT
|
||||
, 0);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void test_control()
|
||||
{
|
||||
std::cerr << __func__ << ": " << typeid(T).name() << ".\n";
|
||||
|
||||
T control;
|
||||
std::auto_ptr<gui2::iterator::twalker_> visitor(control.create_walker());
|
||||
|
||||
BOOST_REQUIRE_NE(visitor.get(), (void*)NULL);
|
||||
|
||||
/***** INITIAL STATE *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::widget), false);
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::grid), true);
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::child), true);
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::widget), &control);
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::grid), (void*)NULL);
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::child), (void*)NULL);
|
||||
|
||||
/***** VISITING WIDGET *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::widget), gui2::iterator::twalker_::invalid);
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::grid), gui2::iterator::twalker_::fail);
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::child), gui2::iterator::twalker_::fail);
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::widget), true);
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::grid), true);
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::child), true);
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::widget), (void*)NULL);
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::grid), (void*)NULL);
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::child), (void*)NULL);
|
||||
|
||||
/***** POST END *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::widget), gui2::iterator::twalker_::fail);
|
||||
}
|
||||
|
||||
static void test_control()
|
||||
{
|
||||
/* Could add more widgets to the list. */
|
||||
test_control<gui2::tlabel>();
|
||||
|
||||
}
|
||||
|
||||
static void test_grid()
|
||||
{
|
||||
/* An empty grid behaves the same as a control so test here. */
|
||||
test_control<gui2::tgrid>();
|
||||
|
||||
std::cerr << __func__ << ": Detailed test.\n";
|
||||
|
||||
/* Test the child part here. */
|
||||
gui2::tgrid grid(2 ,2);
|
||||
add_widget(grid, new gui2::tlabel(), "(1,1)", 0, 0);
|
||||
add_widget(grid, new gui2::tlabel(), "(1,2)", 0, 1);
|
||||
add_widget(grid, new gui2::tlabel(), "(2,1)", 1, 0);
|
||||
add_widget(grid, new gui2::tlabel(), "(2,2)", 1, 1);
|
||||
|
||||
std::auto_ptr<gui2::iterator::twalker_> visitor(grid.create_walker());
|
||||
|
||||
/***** LABEL 1,1 *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::child), false);
|
||||
|
||||
BOOST_REQUIRE_NE(visitor->get(gui2::iterator::twalker_::child), (void*)NULL);
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::child)->id(), "(1,1)");
|
||||
|
||||
/***** LABEL 2,1 *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::child), gui2::iterator::twalker_::valid);
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::child), false);
|
||||
|
||||
BOOST_REQUIRE_NE(visitor->get(gui2::iterator::twalker_::child), (void*)NULL);
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::child)->id(), "(2,1)");
|
||||
|
||||
/***** LABEL 1,2 *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::child), gui2::iterator::twalker_::valid);
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::child), false);
|
||||
|
||||
BOOST_REQUIRE_NE(visitor->get(gui2::iterator::twalker_::child), (void*)NULL);
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::child)->id(), "(1,2)");
|
||||
|
||||
/***** LABEL 2,2 *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::child), gui2::iterator::twalker_::valid);
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::child), false);
|
||||
|
||||
BOOST_REQUIRE_NE(visitor->get(gui2::iterator::twalker_::child), (void*)NULL);
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::child)->id(), "(2,2)");
|
||||
|
||||
/***** END *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::child), gui2::iterator::twalker_::invalid);
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->at_end(gui2::iterator::twalker_::child), true);
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->get(gui2::iterator::twalker_::child), (void*)NULL);
|
||||
|
||||
/***** POST END *****/
|
||||
|
||||
BOOST_CHECK_EQUAL(visitor->next(gui2::iterator::twalker_::child), gui2::iterator::twalker_::fail);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_gui2_visitor)
|
||||
{
|
||||
|
||||
/**** Initialize the environment. *****/
|
||||
game_config::config_cache& cache = game_config::config_cache::instance();
|
||||
|
||||
cache.clear_defines();
|
||||
cache.add_define("EDITOR");
|
||||
cache.add_define("MULTIPLAYER");
|
||||
|
||||
test_control();
|
||||
test_grid();
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue