/***********************************************************************
* fobject.h - Object container base class of all widget objects *
* *
* This file is part of the FINAL CUT widget toolkit *
* *
* Copyright 2015-2021 Markus Gans *
* *
* FINAL CUT is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* FINAL CUT 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* . *
***********************************************************************/
/* Base class
* ══════════
*
* ▕▔▔▔▔▔▔▔▔▔▏
* ▕ FObject ▏
* ▕▁▁▁▁▁▁▁▁▁▏
*/
#ifndef FOBJECT_H
#define FOBJECT_H
#if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
#error "Only can be included directly."
#endif
#if !defined (__cplusplus)
#error "You need a C++ compiler like g++ or clang++"
#elif __cplusplus > 1 && __cplusplus < 201103
#error "Your C++ compiler does not support the C++11 standard!"
#endif
#include // need for gettimeofday
#include
#include
#include
#include
#include
#include "final/fstring.h"
namespace finalcut
{
// class forward declaration
class FEvent;
class FKeyEvent;
class FMouseEvent;
class FWheelEvent;
class FFocusEvent;
class FAccelEvent;
class FShowEvent;
class FHideEvent;
class FCloseEvent;
class FTimerEvent;
class FUserEvent;
//----------------------------------------------------------------------
// class FObject
//----------------------------------------------------------------------
class FObject
{
public:
// Using-declarations
using FObjectList = std::list;
using iterator = FObjectList::iterator;
using const_iterator = FObjectList::const_iterator;
using reference = FObjectList::reference;
using const_reference = FObjectList::const_reference;
// Constants
static constexpr auto UNLIMITED = static_cast(-1);
// Constructor
explicit FObject (FObject* = nullptr);
// Disable copy constructor
FObject (const FObject&) = delete;
// Destructor
virtual ~FObject();
// Disable copy assignment operator (=)
FObject& operator = (const FObject&) = delete;
// Accessors
virtual FString getClassName() const;
FObject* getParent() const;
FObject* getChild (int) const;
FObjectList& getChildren();
const FObjectList& getChildren() const;
std::size_t getMaxChildren() const;
std::size_t numOfChildren() const;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
reference front();
reference back();
const_reference front() const;
const_reference back() const;
// Mutator
void setMaxChildren (std::size_t);
// Inquiries
bool hasParent() const;
bool hasChildren() const;
bool isChild (const FObject*) const;
bool isDirectChild (const FObject*) const;
bool isWidget() const;
bool isInstanceOf (const FString&) const;
bool isTimerInUpdating() const;
// Methods
void removeParent();
void addChild (FObject*);
void delChild (FObject*);
void setParent (FObject*);
// Event handler
virtual bool event (FEvent*);
// Timer methods
static void getCurrentTime (timeval*);
static bool isTimeout (const timeval*, uInt64);
int addTimer (int);
bool delTimer (int) const;
bool delOwnTimers() const;
bool delAllTimers() const;
protected:
struct FTimerData
{
int id;
timeval interval;
timeval timeout;
FObject* object;
};
// Using-declaration
using FTimerList = std::vector;
using FTimerListUniquePtr = std::unique_ptr;
// Accessor
FTimerList* getTimerList() const;
// Mutator
void setWidgetProperty (bool = true);
// Method
uInt processTimerEvent();
// Event handler
virtual void onTimer (FTimerEvent*);
virtual void onUserEvent (FUserEvent*);
private:
// Method
virtual void performTimerAction (FObject*, FEvent*);
static auto globalTimerList() -> const FTimerListUniquePtr&;
// Data members
FObject* parent_obj{nullptr};
FObjectList children_list{}; // no children yet
std::size_t max_children{UNLIMITED};
bool has_parent{false};
bool widget_object{false};
static bool timer_modify_lock;
};
//----------------------------------------------------------------------
inline FString FObject::getClassName() const
{ return "FObject"; }
//----------------------------------------------------------------------
inline FObject* FObject::getParent() const
{ return parent_obj; }
//----------------------------------------------------------------------
inline FObject::FObjectList& FObject::getChildren()
{ return children_list; }
//----------------------------------------------------------------------
inline const FObject::FObjectList& FObject::getChildren() const
{ return children_list; }
//----------------------------------------------------------------------
inline std::size_t FObject::getMaxChildren() const
{ return max_children; }
//----------------------------------------------------------------------
inline std::size_t FObject::numOfChildren() const
{ return children_list.size(); }
//----------------------------------------------------------------------
inline FObject::iterator FObject::begin()
{ return children_list.begin(); }
//----------------------------------------------------------------------
inline FObject::iterator FObject::end()
{ return children_list.end(); }
//----------------------------------------------------------------------
inline FObject::const_iterator FObject::begin() const
{ return children_list.begin(); }
//----------------------------------------------------------------------
inline FObject::const_iterator FObject::end() const
{ return children_list.end(); }
//----------------------------------------------------------------------
inline FObject::reference FObject::front()
{ return children_list.front(); }
//----------------------------------------------------------------------
inline FObject::reference FObject::back()
{ return children_list.back(); }
//----------------------------------------------------------------------
inline FObject::const_reference FObject::front() const
{ return children_list.front(); }
//----------------------------------------------------------------------
inline FObject::const_reference FObject::back() const
{ return children_list.back(); }
//----------------------------------------------------------------------
inline void FObject::setMaxChildren (std::size_t max)
{ max_children = max; }
//----------------------------------------------------------------------
inline bool FObject::hasParent() const
{ return has_parent; }
//----------------------------------------------------------------------
inline bool FObject::hasChildren() const
{ return ! children_list.empty(); }
//----------------------------------------------------------------------
inline bool FObject::isDirectChild (const FObject* obj) const
{ return obj->getParent() == this; }
//----------------------------------------------------------------------
inline bool FObject::isWidget() const
{ return widget_object; }
//----------------------------------------------------------------------
inline bool FObject::isInstanceOf (const FString& classname) const
{ return classname == getClassName(); }
//----------------------------------------------------------------------
inline bool FObject::isTimerInUpdating() const
{ return timer_modify_lock; }
//----------------------------------------------------------------------
inline FObject::FTimerList* FObject::getTimerList() const
{ return globalTimerList().get(); }
//----------------------------------------------------------------------
inline void FObject::setWidgetProperty (bool property)
{ widget_object = property; }
//----------------------------------------------------------------------
// Operator functions for timeval
//----------------------------------------------------------------------
static inline timeval operator + (const timeval& t1, const timeval& t2)
{
timeval tmp{};
tmp.tv_sec = t1.tv_sec + t2.tv_sec;
if ( (tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000 )
{
tmp.tv_sec++;
tmp.tv_usec -= 1000000;
}
return tmp;
}
//----------------------------------------------------------------------
static inline timeval operator - (const timeval& t1, const timeval& t2)
{
timeval tmp{};
tmp.tv_sec = t1.tv_sec - t2.tv_sec;
if ( (tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0 )
{
tmp.tv_sec--;
tmp.tv_usec += 1000000;
}
return tmp;
}
//----------------------------------------------------------------------
static inline timeval& operator += (timeval& t1, const timeval& t2)
{
t1.tv_sec += t2.tv_sec;
if ( (t1.tv_usec += t2.tv_usec) >= 1000000 )
{
t1.tv_sec++;
t1.tv_usec -= 1000000;
}
return t1;
}
//----------------------------------------------------------------------
static inline bool operator < (const timeval& t1, const timeval& t2)
{
return (t1.tv_sec < t2.tv_sec)
|| (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec);
}
} // namespace finalcut
#endif // FOBJECT_H