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 */