S.F.Tracker(289)

公開:2007-10-30 20:48
更新:2020-02-15 04:36
カテゴリ:sftracker,c++,windows,audio,tracker

component_iterator実装の続き。
BOOST_FOREACHに回せるように少しコードを追加。
だがまだ不完全である。

ソースコード

#pragma once
/*
==============================================================================
This file is part of the S.F.Tracker
Copyright 2005-7 by Satoshi Fujiwara.
S.F.Tracker can be redistributed and/or modified 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.
S.F.Tracker is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with S.F.Tracker; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
==============================================================================
*/
/** @file
*  @author S.F. (Satoshi Fujiwara)
*  @brief Component を iterateしたり、rangeしたりするhelper class library.
*/
#include <boost/iterator_adaptors.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/utility/enable_if.hpp>
#include "src\juce_WithoutMacros.h"
#include <boost/foreach.hpp>
namespace sf {
/** child component iteration */
template <typename ComponentType>
struct component_iterator_base :
public boost::iterator_facade<component_iterator_base<ComponentType>,ComponentType*,boost::random_access_traversal_tag>
{
private:
struct enabler {};
public:
template <class OtherValue>
component_iterator_base(
component_iterator_base<OtherValue> const& other
, typename boost::enable_if<
boost::is_convertible<OtherValue*,ComponentType*>
, enabler
>::type = enabler()
) : comp_(other.comp_),index_(other.index_){}
explicit component_iterator_base<ComponentType>(ComponentType& comp,int index = 0) :
comp_(&comp),index_(index)
{
};
private:
component_iterator_base<ComponentType>() :comp_(0),index_(0){};
friend struct component_iterator_base;
friend class boost::iterator_core_access;
void increment()
{
if(index_  < (comp_->getNumChildComponents()))
{
++index_;
}
};
void decrement()
{
if(index_ >= 0)
{
--index_;
}
}
template <typename OtherType>
bool equal( component_iterator_base<OtherType> const & other) const
{
if((index_ >= 0 && index_ < comp_->getNumChildComponents())
&& (other.index_ >= 0 && other.index_ < other.comp_->getNumChildComponents())){
return comp_->getChildComponent(index_) == other.comp_->getChildComponent(other.index_);
} else {
return index_ == other.index_;
}
}
reference dereference() const
{    Component* t = comp_->getChildComponent(index_);
return t;
};
void advance(difference_type n)
{
index_ += n;
//            valid_ = (index_ < comp_->getNumChildComponents() - 1) && (index_ > 0);
};
difference_type distance_to (component_iterator_base const& other) const
{
return other.index_ - index_;
}
mutable int index_;
mutable ComponentType* comp_;
};
typedef component_iterator_base<Component> component_iterator;
typedef component_iterator_base<Component const> const_component_iterator;
//template <typename ComponentType >
//    inline component_iterator_base<ComponentType> begin(ComponentType& parent_comp)
//    { return component_iterator_base<ComponentType>(parent_comp);};
//template <typename ComponentType >
//    inline component_iterator_base<ComponentType> end(ComponentType& parent_comp)
//    { return component_iterator_base<ComponentType>(parent_comp,parent_comp.getNumChildComponents());};
inline sf::component_iterator begin(Component  & parent_comp)
{ return sf::component_iterator(parent_comp);};
inline sf::component_iterator end(Component  & parent_comp)
{ return sf::component_iterator(parent_comp,parent_comp.getNumChildComponents());};
inline sf::const_component_iterator begin(Component const & parent_comp)
{ return sf::const_component_iterator(parent_comp);};
inline sf::const_component_iterator end(Component const & parent_comp)
{ return sf::const_component_iterator(parent_comp,parent_comp.getNumChildComponents());};
}
namespace juce
{
inline sf::component_iterator boost_range_begin(Component& parent_comp) { return sf::begin(parent_comp);};
inline sf::component_iterator boost_range_end(Component& parent_comp) { return sf::end(parent_comp);};
inline sf::const_component_iterator boost_range_begin(Component const & parent_comp) { return sf::begin(parent_comp);};
inline sf::const_component_iterator boost_range_end(Component const & parent_comp) { return sf::end(parent_comp);};
}
namespace boost
{
// specialize rannge_iterator and range_const_iterator in namespace boost
template<class ComponentType>
struct range_iterator< typename boost::lazy_enable_if<
boost::is_base_and_derived<
juce::Component,ComponentType
> , ComponentType
>
>
{
typedef sf::component_iterator_base<ComponentType> type;
};
//specialize rannge_iterator and range_const_iterator in namespace boost
template<>
struct range_iterator<juce::Component>
{
typedef sf::component_iterator type;
};
template<>
struct range_const_iterator< juce::Component>
{
typedef  sf::const_component_iterator type;
};
namespace foreach
{
template<>
struct is_noncopyable< juce::Component >
: mpl::true_
{
};
}
}
テストコード
#include "StdAfxtest.h"
#include <boost/test/unit_test.hpp>
#include "component_iterator_test.h"
#include "../sftrackermain/component_iterator.h"
using namespace boost::unit_test;
using namespace sf;
void component_iterator_test1()
{
TextButton btn(_T("button1"));
for(int i = 0;i < 10;++i){
btn.addChildComponent(new TextButton((format(_T("button %d")) % i).str().c_str()));
}
{
int i = 0;
// forward++ Test
for(component_iterator it = begin(btn),it_e = end(btn);it != it_e;++it)
{
//            std::cout << (const TCHAR*)((*it)->getName()) << std::endl;
BOOST_CHECK((*it)->getName() == btn.getChildComponent(i)->getName());
++i;
}
// [] Operator Test
component_iterator it = begin(btn);
for(i  = btn.getNumChildComponents() - 1 ;i >= 0; --i)
{
BOOST_CHECK((*it[i]).getName() == btn.getChildComponent(i)->getName());
}
i = 0;
Component* pc = &btn;
BOOST_FOREACH(Component *p , static_cast<Component&>(btn))
{
BOOST_CHECK(p->getName() == btn.getChildComponent(i++)->getName());
}
}
}
test_suite* component_iterator_test()
{
test_suite* test_ BOOST_TEST_SUITE("coomponent_iterator_test");
test_->add(BOOST_TEST_CASE(&component_iterator_test1));
return test_;
}