xnode.h
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13  ***************************************************************************/
14 #ifndef xnodeH
15 #define xnodeH
16 
17 #include "transaction.h"
18 #include "xsignal.h"
19 #include "threadlocal.h"
20 
21 class XNode;
22 
25 
26 template <class T>
28 template <class T>
30 
31 #define trans(node) for(Transaction \
32  implicit_tr(node, false); !implicit_tr.isModified() || !implicit_tr.commitOrNext(); ) implicit_tr[node]
33 
34 template <class T>
35 typename std::enable_if<std::is_base_of<XNode, T>::value, const SingleSnapshot<T> >::type
36  operator*(T &node) {
37  return SingleSnapshot<T>(node);
38 }
39 
40 template <typename...Args>
41 using Talker = Transactional::Talker<Snapshot, Args...>;
42 template <typename...Args>
43 using TalkerSingleton = Transactional::TalkerSingleton<Snapshot, Args...>;
44 
45 extern template class Transactional::Node<class XNode>;
46 //! XNode supports accesses from scripts/GUI and shared_from_this(),
47 //! in addition to the features of Transactional::Node.
48 //! \sa Transactional::Node, create(), createOrphan().
49 class DECLSPEC_KAME XNode : public enable_shared_from_this<XNode>, public Transactional::Node<XNode> {
50 public:
51  explicit XNode(const char *name, bool runtime = false);
52  virtual ~XNode();
53 
54  template <class T>
55  shared_ptr<T> create(const char *name) {return create<T>(name, false);}
56  template <class T, typename... Args>
57  shared_ptr<T> create(const char *name, bool runtime, Args&&... args);
58 
59  template <class T>
60  shared_ptr<T> create(Transaction &tr, const char *name) {return create<T>(tr, name, false);}
61  template <class T, typename... Args>
62  shared_ptr<T> create(Transaction &tr, const char *name, bool runtime, Args&&... args);
63 
64  template <class T__>
65  static shared_ptr<T__> createOrphan(const char *name) {return createOrphan<T__>(name, false);}
66  template <class T__, typename... Args_>
67  static shared_ptr<T__> createOrphan(const char *name, bool runtime, Args_&&... args);
68 
69  //! \return internal/scripting name. Use latin1 chars.
70  XString getName() const;
71  //! \return i18n name for UI.
72  virtual XString getLabel() const {return getName();}
73  XString getTypename() const;
74 
75  shared_ptr<XNode> getChild(const XString &var) const;
76  shared_ptr<XNode> getParent() const;
77 
78  //! Enables/disables controls over scripting/GUI.
79  void setUIEnabled(bool v);
80  //! Disables all scripting/GUI operations on this node hereafter.
81  void disable();
82 
83  //! Data holder.
84  //! \sa Transactional::Node::Payload.
85  struct DECLSPEC_KAME Payload : public Transactional::Node<XNode>::Payload {
86  Payload() : Transactional::Node<XNode>::Payload(), m_flags((int)FLAG::NODE_UI_ENABLED) {}
87  //! If true, operations are allowed by UI and scripts.
88  bool isUIEnabled() const {return m_flags & FLAG::NODE_UI_ENABLED;}
89  void setUIEnabled(bool var);
90  bool isDisabled() const {return m_flags & FLAG::NODE_DISABLED;}
91  void disable();
92  bool isRuntime() const {return m_flags & FLAG::NODE_RUNTIME;}
93  void setRuntime(bool var) {m_flags = (m_flags & ~FLAG::NODE_RUNTIME) | (var ? FLAG::NODE_RUNTIME : 0);}
94  //! \sa setUIEnabled
95  Talker<XNode*> &onUIFlagsChanged() {return m_tlkOnUIFlagsChanged;}
96  const Talker<XNode*> &onUIFlagsChanged() const {return m_tlkOnUIFlagsChanged;}
97  private:
98  enum FLAG : int {NODE_UI_ENABLED = 0x1, NODE_DISABLED = 0x2, NODE_RUNTIME = 0x4};
99  int m_flags;
100  TalkerSingleton<XNode*> m_tlkOnUIFlagsChanged;
101  };
102 
103  XNode() = delete;
104 protected:
105 private:
106  const XString m_name;
107 
108  static XThreadLocal<std::deque<shared_ptr<XNode> > > stl_thisCreating;
109 };
110 
111 class DECLSPEC_KAME XTouchableNode : public XNode {
112 public:
113  XTouchableNode(const char *name, bool runtime) : XNode(name, runtime) {}
114 
115  struct DECLSPEC_KAME Payload : public XNode::Payload {
116  void touch();
117  //! \sa touch()
118  Talker<XTouchableNode*> &onTouch() {return m_tlkOnTouch;}
119  const Talker<XTouchableNode*> &onTouch() const {return m_tlkOnTouch;}
120  protected:
121  Talker<XTouchableNode*> m_tlkOnTouch;
122  };
123 protected:
124 };
125 
126 //! Interface class containing values
127 class DECLSPEC_KAME XValueNodeBase : public XNode {
128 protected:
129  XValueNodeBase(const char *name, bool runtime) : XNode(name, runtime), m_validator(0) {}
130 public:
131  using Validator = void (*)(XString &);
132  void setValidator(Validator x) {m_validator = x;}
133 
134  struct DECLSPEC_KAME Payload : public XNode::Payload {
135  Payload() : XNode::Payload() {}
136  //! Gets value as a string, which is used for scripting.
137  virtual XString to_str() const = 0;
138  //! Sets value as a string, which is used for scripting.
139  //! This throws exception when the validator throws.
140  void str(const XString &str) throw (XKameError &) {
141  XString sc(str);
142  if(static_cast<XValueNodeBase&>(node()).m_validator)
143  (*static_cast<XValueNodeBase&>(node()).m_validator)(sc);
144  str_(sc);
145  }
146  Talker<XValueNodeBase*> &onValueChanged() {return m_tlkOnValueChanged;}
147  const Talker<XValueNodeBase*> &onValueChanged() const {return m_tlkOnValueChanged;}
148  protected:
149  //! \a str_() can throw exception due to format issues.
150  //! A marking to \a onValueChanged() is necessary.
151  virtual void str_(const XString &) = 0;
152  TalkerSingleton<XValueNodeBase*> m_tlkOnValueChanged;
153  };
154 protected:
155  Validator m_validator;
156 };
157 
158 //! Base class for integer node.
159 template <typename T, int base = 10>
160 class DECLSPEC_KAME XIntNodeBase : public XValueNodeBase {
161 public:
162  explicit XIntNodeBase(const char *name, bool runtime = false) : XValueNodeBase(name, runtime) {}
163  virtual ~XIntNodeBase() = default;
164 
165  struct DECLSPEC_KAME Payload : public XValueNodeBase::Payload {
166  Payload() : XValueNodeBase::Payload() {this->m_var = 0;}
167  virtual XString to_str() const override;
168  operator T() const {return m_var;}
169  Payload &operator=(T x) {
170  m_var = x;
171  tr().mark(onValueChanged(), static_cast<XValueNodeBase*>(&node()));
172  return *this;
173  }
174  protected:
175  virtual void str_(const XString &) override;
176  T m_var;
177  };
178 };
179 
180 class DECLSPEC_KAME XDoubleNode : public XValueNodeBase {
181 public:
182  explicit XDoubleNode(const char *name, bool runtime = false, const char *format = 0L);
183  virtual ~XDoubleNode() = default;
184 
185  const char *format() const {return local_shared_ptr<XString>(m_format)->c_str();}
186  void setFormat(const char* format);
187 
188  struct DECLSPEC_KAME Payload : public XValueNodeBase::Payload {
189  Payload() : XValueNodeBase::Payload() {this->m_var = 0.0;}
190  virtual XString to_str() const override;
191  operator double() const {return m_var;}
192  Payload &operator=(double x) {
193  m_var = x;
194  tr().mark(onValueChanged(), static_cast<XValueNodeBase*>(&node()));
195  return *this;
196  }
197  protected:
198  virtual void str_(const XString &) override;
199  double m_var;
200  };
202 };
203 
204 class DECLSPEC_KAME XStringNode : public XValueNodeBase {
205 public:
206  explicit XStringNode(const char *name, bool runtime = false);
207  virtual ~XStringNode() = default;
208 
209  struct DECLSPEC_KAME Payload : public XValueNodeBase::Payload {
210  virtual XString to_str() const override {return this->m_var;}
211  operator const XString&() const {return m_var;}
212  Payload &operator=(const XString &x) {
213  m_var = x;
214  tr().mark(onValueChanged(), static_cast<XValueNodeBase*>(&node()));
215  return *this;
216  }
217  protected:
218  virtual void str_(const XString &str) override { *this = str;}
219  XString m_var;
220  };
221 };
222 
229 
230 template <class T, typename... Args>
231 shared_ptr<T>
232 XNode::createOrphan(const char *name, bool runtime, Args&&... args) {
233  Transactional::Node<XNode>::create<T>(name, runtime, std::forward<Args>(args)...);
234  shared_ptr<T> ptr = dynamic_pointer_cast<T>(XNode::stl_thisCreating->back());
235  XNode::stl_thisCreating->pop_back();
236  return ptr;
237 }
238 
239 template <class T, typename... Args>
240 shared_ptr<T>
241 XNode::create(Transaction &tr, const char *name, bool runtime, Args&&... args) {
242  shared_ptr<T> ptr(createOrphan<T>(name, runtime, std::forward<Args>(args)...));
243  if(ptr) insert(tr, ptr, true);
244  return ptr;
245 }
246 
247 template <class T, typename... Args>
248 shared_ptr<T>
249 XNode::create(const char *name, bool runtime, Args&&... args) {
250  shared_ptr<T> ptr(createOrphan<T>(name, runtime, std::forward<Args>(args)...));
251  if(ptr) insert(ptr);
252  return ptr;
253 }
254 
255 //---------------------------------------------------------------------------
256 #endif

Generated for KAME4 by  doxygen 1.8.3