Crazy Eddie's GUI System  0.8.3
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
PropertyLinkDefinition.h
1 /***********************************************************************
2  filename: CEGUIPropertyLinkDefinition.h
3  created: Sat Oct 8 2005
4  author: Paul D Turner <paul@cegui.org.uk>
5 *************************************************************************/
6 /***************************************************************************
7  * Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26  * OTHER DEALINGS IN THE SOFTWARE.
27  ***************************************************************************/
28 #ifndef _CEGUIFalPropertyLinkDefinition_h_
29 #define _CEGUIFalPropertyLinkDefinition_h_
30 
31 #include "CEGUI/falagard/FalagardPropertyBase.h"
32 #include "CEGUI/IteratorBase.h"
33 #include <vector>
34 
35 #if defined (_MSC_VER)
36 # pragma warning(push)
37 # pragma warning(disable : 4251)
38 #endif
39 
40 namespace CEGUI
41 {
42 extern const String S_parentIdentifier;
43 
49 template <typename T>
51 {
52 public:
53  //------------------------------------------------------------------------//
54  typedef typename TypedProperty<T>::Helper Helper;
55 
56  //------------------------------------------------------------------------//
57  PropertyLinkDefinition(const String& propertyName, const String& widgetName,
58  const String& targetProperty, const String& initialValue,
59  const String& origin,
60  bool redrawOnWrite, bool layoutOnWrite,
61  const String& fireEvent, const String& eventNamespace) :
62  FalagardPropertyBase<T>(propertyName,
63  "Falagard property link definition - links a "
64  "property on this window to properties "
65  "defined on one or more child windows, or "
66  "the parent window.",
67  initialValue, origin,
68  redrawOnWrite, layoutOnWrite,
69  fireEvent, eventNamespace)
70  {
71  // add initial target if it was specified via constructor
72  // (typically meaning it came via XML attributes)
73  if (!widgetName.empty() || !targetProperty.empty())
74  addLinkTarget(widgetName, targetProperty);
75  }
76 
78 
79  //------------------------------------------------------------------------//
81  void addLinkTarget(const String& widget, const String& property)
82  {
83  d_targets.push_back(std::make_pair(widget,property));
84  }
85 
86  //------------------------------------------------------------------------//
89  {
90  d_targets.clear();
91  }
92 
93  //------------------------------------------------------------------------//
94  // return whether a the given widget / property pair is a target of this
95  // property link.
96  bool isTargetProperty(const String& widget, const String& property) const
97  {
98  LinkTargetCollection::const_iterator i = d_targets.begin();
99  for (; i != d_targets.end(); ++i)
100  {
101  if (property == i->second && widget == i->first)
102  return true;
103  }
104 
105  return false;
106  }
107 
108  //------------------------------------------------------------------------//
110  {
111  updateLinkTargets(receiver, Helper::fromString(this->d_default));
112  }
113 
114  //------------------------------------------------------------------------//
115  Property* clone() const
116  {
117  return CEGUI_NEW_AO PropertyLinkDefinition<T>(*this);
118  }
119 
120 protected:
121  // override members from FalagardPropertyBase
122  //------------------------------------------------------------------------//
123  typename Helper::safe_method_return_type
124  getNative_impl(const PropertyReceiver* receiver) const
125  {
126  const LinkTargetCollection::const_iterator i(d_targets.begin());
127 
128  const Window* const target_wnd =
129  getTargetWindow(receiver, i->first);
130 
131  // if no target, or target (currently) invalid, return the default value
132  if (d_targets.empty() || !target_wnd)
133  return Helper::fromString(TypedProperty<T>::d_default);
134 
135  // otherwise return the value of the property for first target, since
136  // this is considered the 'master' target for get operations.
137  return Helper::fromString(target_wnd->getProperty(i->second.empty() ?
138  TypedProperty<T>::d_name : i->second));
139  }
140 
141  //------------------------------------------------------------------------//
142  void setNative_impl(PropertyReceiver* receiver,
143  typename Helper::pass_type value)
144  {
145  updateLinkTargets(receiver, value);
146 
147  // base handles things like ensuring redraws and such happen
148  FalagardPropertyBase<T>::setNative_impl(receiver, value);
149  }
150 
151  //------------------------------------------------------------------------//
152  void updateLinkTargets(PropertyReceiver* receiver,
153  typename Helper::pass_type value) const
154  {
155  LinkTargetCollection::const_iterator i = d_targets.begin();
156  for ( ; i != d_targets.end(); ++i)
157  {
158  Window* target_wnd = getTargetWindow(receiver, i->first);
159 
160  // only try to set property if target is currently valid.
161  if (target_wnd)
162  target_wnd->setProperty(i->second.empty() ?
163  TypedProperty<T>::d_name : i->second, Helper::toString(value));
164  }
165  }
166 
167  //------------------------------------------------------------------------//
169  {
170  xml_stream.openTag("PropertyLinkDefinition");
171  }
172 
173  //------------------------------------------------------------------------//
174  void writeFalagardXMLAttributes(XMLSerializer& xml_stream) const
175  {
177 
178  // HACK: Here we abuse some intimate knowledge in that we know it's
179  // safe to write our sub-elements out although the function is named
180  // for writing attributes. The alternative was to repeat code from the
181  // base class, also demonstrating intimate knowledge ;)
182 
183  LinkTargetCollection::const_iterator i(d_targets.begin());
184 
185  // if there is one target only, write it out as attributes
186  if (d_targets.size() == 1)
187  {
188  if (!i->first.empty())
189  xml_stream.attribute("widget", i->first);
190 
191  if (!i->second.empty())
192  xml_stream.attribute("targetProperty", i->second);
193  }
194  // we have multiple targets, so write them as PropertyLinkTarget tags
195  else
196  {
197  for ( ; i != d_targets.end(); ++i)
198  {
199  xml_stream.openTag("PropertyLinkTarget");
200 
201  if (!i->first.empty())
202  xml_stream.attribute("widget", i->first);
203 
204  if (!i->second.empty())
205  xml_stream.attribute("property", i->second);
206 
207  xml_stream.closeTag();
208  }
209  }
210  }
211 
212  //------------------------------------------------------------------------//
214  const Window* getTargetWindow(const PropertyReceiver* receiver,
215  const String& name) const
216  {
217  if (name.empty())
218  return static_cast<const Window*>(receiver);
219 
220  // handle link back to parent. Return receiver if no parent.
221  if (name== S_parentIdentifier)
222  return static_cast<const Window*>(receiver)->getParent();
223 
224  return static_cast<const Window*>(receiver)->getChild(name);
225  }
226 
227  //------------------------------------------------------------------------//
230  const String& name) const
231  {
232  return const_cast<Window*>(
233  getTargetWindow(static_cast<const PropertyReceiver*>(receiver), name));
234  }
235 
236  //------------------------------------------------------------------------//
237  typedef std::pair<String,String> StringPair;
239  typedef std::vector<StringPair CEGUI_VECTOR_ALLOC(StringPair)> LinkTargetCollection;
240 
243 
244 public:
246 
247  LinkTargetIterator getLinkTargetIterator() const
248  {
249  return LinkTargetIterator(d_targets.begin(),d_targets.end());
250  }
251 };
252 
253 }
254 
255 #if defined (_MSC_VER)
256 # pragma warning(pop)
257 #endif
258 
259 #endif
260