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