Limit for the number of FObject child objects

This commit is contained in:
Markus Gans 2020-09-26 19:06:49 +02:00
parent c1a2ef59e4
commit 72bcce87b7
6 changed files with 65 additions and 22 deletions

View File

@ -1,5 +1,8 @@
2020-09-26 Markus Gans <guru.mail@muenster.de> 2020-09-26 Markus Gans <guru.mail@muenster.de>
* FData improvements * FData improvements
* The number of FObject children can now be limited with
setMaxChildren()
* FApplication can now have no more than one child widget
2020-09-25 Markus Gans <guru.mail@muenster.de> 2020-09-25 Markus Gans <guru.mail@muenster.de>
* std::clog now streams everything to the FLogger object * std::clog now streams everything to the FLogger object

View File

@ -388,6 +388,9 @@ void FApplication::processExternalUserEvent()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FApplication::init() void FApplication::init()
{ {
// FApplication cannot have a second child widget
setMaxChildren(1);
// Initialize the last event time // Initialize the last event time
time_last_event.tv_sec = 0; time_last_event.tv_sec = 0;
time_last_event.tv_usec = 0; time_last_event.tv_usec = 0;

View File

@ -48,7 +48,6 @@ FObject::FObject (FObject* parent)
if ( parent ) // add object to parent if ( parent ) // add object to parent
{ {
parent->addChild(this); parent->addChild(this);
has_parent = true;
} }
else else
{ {
@ -107,7 +106,7 @@ FObject* FObject::getChild (int index) const
if ( ! hasChildren() ) if ( ! hasChildren() )
return nullptr; return nullptr;
if ( index <= 0 || index > numOfChildren() ) if ( index <= 0 || index > int(numOfChildren()) )
return nullptr; return nullptr;
auto iter = begin(); auto iter = begin();
@ -148,6 +147,9 @@ void FObject::addChild (FObject* obj)
if ( ! obj ) if ( ! obj )
return; return;
if ( max_children != UNLIMITED && max_children <= numOfChildren() )
throw std::length_error ("max. child objects reached");
if ( obj->parent_obj ) if ( obj->parent_obj )
obj->parent_obj->delChild(obj); obj->parent_obj->delChild(obj);

View File

@ -698,7 +698,7 @@ int FTermLinux::setScreenFont ( const uChar fontdata[], uInt count
} }
for (std::size_t i{0}; i < count; i++) for (std::size_t i{0}; i < count; i++)
std::memcpy ( const_cast<uChar*>(font.data + bytes_per_line * 32 * i) std::memcpy ( font.data + bytes_per_line * 32 * i
, &fontdata[i * font.height] , &fontdata[i * font.height]
, font.height); , font.height);
} }

View File

@ -78,6 +78,9 @@ class FObject
typedef FObjectList::iterator iterator; typedef FObjectList::iterator iterator;
typedef FObjectList::const_iterator const_iterator; typedef FObjectList::const_iterator const_iterator;
// Constants
static constexpr std::size_t UNLIMITED = static_cast<std::size_t>(-1);
// Constructor // Constructor
explicit FObject (FObject* = nullptr); explicit FObject (FObject* = nullptr);
@ -96,12 +99,16 @@ class FObject
FObject* getChild (int) const; FObject* getChild (int) const;
FObjectList& getChildren(); FObjectList& getChildren();
const FObjectList& getChildren() const; const FObjectList& getChildren() const;
int numOfChildren() const; std::size_t getMaxChildren() const;
std::size_t numOfChildren() const;
iterator begin(); iterator begin();
iterator end(); iterator end();
const_iterator begin() const; const_iterator begin() const;
const_iterator end() const; const_iterator end() const;
// Mutator
void setMaxChildren (std::size_t);
// Inquiries // Inquiries
bool hasParent() const; bool hasParent() const;
bool hasChildren() const; bool hasChildren() const;
@ -160,6 +167,7 @@ class FObject
// Data members // Data members
FObject* parent_obj{nullptr}; FObject* parent_obj{nullptr};
FObjectList children_list{}; // no children yet FObjectList children_list{}; // no children yet
std::size_t max_children{UNLIMITED};
bool has_parent{false}; bool has_parent{false};
bool widget_object{false}; bool widget_object{false};
static bool timer_modify_lock; static bool timer_modify_lock;
@ -184,8 +192,12 @@ inline const FObject::FObjectList& FObject::getChildren() const
{ return children_list; } { return children_list; }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline int FObject::numOfChildren() const inline std::size_t FObject::getMaxChildren() const
{ return int(children_list.size()); } { return max_children; }
//----------------------------------------------------------------------
inline std::size_t FObject::numOfChildren() const
{ return children_list.size(); }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline FObject::iterator FObject::begin() inline FObject::iterator FObject::begin()
@ -203,6 +215,10 @@ inline FObject::const_iterator FObject::begin() const
inline FObject::const_iterator FObject::end() const inline FObject::const_iterator FObject::end() const
{ return children_list.end(); } { return children_list.end(); }
//----------------------------------------------------------------------
inline void FObject::setMaxChildren (std::size_t max)
{ max_children = max; }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FObject::hasParent() const inline bool FObject::hasParent() const
{ return has_parent; } { return has_parent; }

View File

@ -376,38 +376,57 @@ void FObjectTest::addTest()
{ {
// obj -> child // obj -> child
auto obj = new finalcut::FObject(); auto obj1 = new finalcut::FObject();
auto child = new finalcut::FObject(); auto child = new finalcut::FObject();
CPPUNIT_ASSERT ( ! obj->hasChildren() ); CPPUNIT_ASSERT ( ! obj1->hasChildren() );
CPPUNIT_ASSERT ( obj->numOfChildren() == 0 ); CPPUNIT_ASSERT ( obj1->numOfChildren() == 0 );
CPPUNIT_ASSERT ( ! obj->isChild(child) ); CPPUNIT_ASSERT ( ! obj1->isChild(child) );
CPPUNIT_ASSERT ( ! child->hasParent() ); CPPUNIT_ASSERT ( ! child->hasParent() );
CPPUNIT_ASSERT ( child->getParent() != obj ); CPPUNIT_ASSERT ( child->getParent() != obj1 );
obj->addChild(child); obj1->addChild(child);
CPPUNIT_ASSERT ( obj->hasChildren() ); CPPUNIT_ASSERT ( obj1->hasChildren() );
CPPUNIT_ASSERT ( obj->numOfChildren() == 1 ); CPPUNIT_ASSERT ( obj1->numOfChildren() == 1 );
CPPUNIT_ASSERT ( obj->isChild(child) ); CPPUNIT_ASSERT ( obj1->isChild(child) );
CPPUNIT_ASSERT ( child->hasParent() ); CPPUNIT_ASSERT ( child->hasParent() );
CPPUNIT_ASSERT ( child->getParent() == obj ); CPPUNIT_ASSERT ( child->getParent() == obj1 );
// Switch of the parent by a second addChild // Switch of the parent by a second addChild
auto obj2 = new finalcut::FObject(); auto obj2 = new finalcut::FObject();
obj2->addChild(child); obj2->addChild(child);
CPPUNIT_ASSERT ( child->hasParent() ); CPPUNIT_ASSERT ( child->hasParent() );
CPPUNIT_ASSERT ( ! obj->hasChildren() ); CPPUNIT_ASSERT ( ! obj1->hasChildren() );
CPPUNIT_ASSERT ( obj->numOfChildren() == 0 ); CPPUNIT_ASSERT ( obj1->numOfChildren() == 0 );
CPPUNIT_ASSERT ( ! obj->isChild(child) ); CPPUNIT_ASSERT ( ! obj1->isChild(child) );
CPPUNIT_ASSERT ( child->getParent() != obj ); CPPUNIT_ASSERT ( child->getParent() != obj1 );
CPPUNIT_ASSERT ( obj2->hasChildren() ); CPPUNIT_ASSERT ( obj2->hasChildren() );
CPPUNIT_ASSERT ( obj2->numOfChildren() == 1 ); CPPUNIT_ASSERT ( obj2->numOfChildren() == 1 );
CPPUNIT_ASSERT ( obj2->isChild(child) ); CPPUNIT_ASSERT ( obj2->isChild(child) );
CPPUNIT_ASSERT ( child->getParent() == obj2 ); CPPUNIT_ASSERT ( child->getParent() == obj2 );
delete obj; // also deletes the child object // Are the maximum number of child objects reached?
CPPUNIT_ASSERT ( obj2->getMaxChildren() == finalcut::FObject::UNLIMITED );
obj2->setMaxChildren(1);
CPPUNIT_ASSERT ( obj2->hasChildren() );
CPPUNIT_ASSERT ( obj2->getMaxChildren() == 1 );
CPPUNIT_ASSERT ( obj2->numOfChildren() == 1 );
auto child2 = new finalcut::FObject();
CPPUNIT_ASSERT ( ! child2->hasParent() );
CPPUNIT_ASSERT_THROW ( obj2->addChild(child2), std::length_error );
CPPUNIT_ASSERT ( obj2->numOfChildren() == 1 );
obj2->setMaxChildren(2);
CPPUNIT_ASSERT ( ! child2->hasParent() );
CPPUNIT_ASSERT ( obj2->getMaxChildren() == 2 );
obj2->addChild(child2);
CPPUNIT_ASSERT ( child2->hasParent() );
CPPUNIT_ASSERT ( obj2->hasChildren() );
CPPUNIT_ASSERT ( obj2->numOfChildren() == 2 );
delete obj1;
delete obj2; // also deletes the child object
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -456,7 +475,7 @@ void FObjectTest::iteratorTest()
finalcut::FObject::const_iterator c_iter, c_last; finalcut::FObject::const_iterator c_iter, c_last;
c_iter = obj->begin(); c_iter = obj->begin();
c_last = obj->end(); c_last = obj->end();
int i = 0; std::size_t i = 0;
while ( c_iter != c_last ) while ( c_iter != c_last )
{ {