Mercurial > ~dholland > hg > ag > index.cgi
diff anagram/guisupport/action.h @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/anagram/guisupport/action.h Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,148 @@ +/* + * AnaGram, A System for Syntax Directed Programming + * Copyright 1997-2002 Parsifal Software. All Rights Reserved. + * See the file COPYING for license and usage terms. + * + * action.h + */ + +#ifndef ACTION_H +#define ACTION_H + +#include "agstack.h" + + +class AgAction { +public: + + class Kernel { + private: + int useCount; + public: + virtual ~Kernel() {} + virtual void perform() const = 0; + + Kernel() : useCount(0) {} + void lock() { useCount++; } + int unlock() { return --useCount <= 0; } + }; + +protected: + Kernel *kernel; + static int running; + + static AgStack<AgAction> startupStack; + +public: + AgAction() : kernel(0) {} + AgAction(AgAction::Kernel *kernel_) : kernel(kernel_) { + if (kernel) { + kernel->lock(); + } + } + AgAction(const AgAction &a) : kernel(a.kernel) { + if (kernel) { + kernel->lock(); + } + } + AgAction &operator = (const AgAction &a) { + if (kernel && kernel->unlock()) { + delete kernel; + } + kernel = a.kernel; + if (kernel) { + kernel->lock(); + } + return *this; + } + ~AgAction() { + if (kernel && kernel->unlock()) { + delete kernel; + kernel = 0; + } + } + int exists() { return kernel != 0; } + void perform() const { if (kernel) kernel->perform(); } + void operator () () const { if (kernel) kernel->perform(); } + //void defer() const; + void performDeferred() const; + static void startup(); + int operator < (const AgAction &a) const { return this < &a; } +}; + + +template<class T> +class AgClassAction : public AgAction { +private: + + class Kernel : public AgAction::Kernel { + private: + T &object; + void (T:: * memberFunction)(); + + public: + Kernel(T &object_, void (T:: * memberFunction_)()) : + object(object_) , + memberFunction(memberFunction_) + {} + void perform() const {(object.*memberFunction)();} + }; + +public: + AgClassAction(T &object_, void (T:: * memberFunction_)()) : + AgAction(new AgClassAction<T>::Kernel(object_,memberFunction_)) + {} + AgClassAction(const AgClassAction<T> &a) : + AgAction(a) + {} +}; + +template <class T> +AgAction actionObject(T *t, void (T:: * memberFunction)()) { + return AgClassAction<T>(*t, memberFunction); +} + +void defer(void (*f)()); + +template <class T> +void defer(T *t, void (T:: * memberFunction)()) { + AgClassAction<T>(*t, memberFunction).performDeferred(); +} + +class AgSimpleAction : public AgAction { +private: + + class Kernel : public AgAction::Kernel { + void (* function)(); + public: + Kernel(void (* function_)()) : + function(function_) + {} + void perform() const {(*function)();} + }; + +public: + AgSimpleAction(void (* function_)()) : + AgAction(new AgSimpleAction::Kernel(function_)) + {} + AgSimpleAction(const AgSimpleAction &a) : + AgAction(a) + {} +}; + +AgAction actionObject(void (* function)()); + + +//////////////////////////////////////////////////////////// +// +// interaction with GUI event loop + +// this must be provided by the GUI - see e.g. vaclgui/actionwin.cpp +// (not defined in action.cpp) +void AgActionEnqueueInGui(AgAction::Kernel *kernel); + +// and the GUI should hand the object back to this function. +void AgActionDispatchFromGui(AgAction::Kernel *kernel); + + +#endif /* ACTION_H */