Crazy Eddie's GUI System  0.8.4
PropertyLinkDefinition.h
00001 /***********************************************************************
00002     created:    Sat Oct 8 2005
00003     author:     Paul D Turner <paul@cegui.org.uk>
00004 *************************************************************************/
00005 /***************************************************************************
00006  *   Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
00007  *
00008  *   Permission is hereby granted, free of charge, to any person obtaining
00009  *   a copy of this software and associated documentation files (the
00010  *   "Software"), to deal in the Software without restriction, including
00011  *   without limitation the rights to use, copy, modify, merge, publish,
00012  *   distribute, sublicense, and/or sell copies of the Software, and to
00013  *   permit persons to whom the Software is furnished to do so, subject to
00014  *   the following conditions:
00015  *
00016  *   The above copyright notice and this permission notice shall be
00017  *   included in all copies or substantial portions of the Software.
00018  *
00019  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00020  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00021  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00022  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
00023  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00024  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00025  *   OTHER DEALINGS IN THE SOFTWARE.
00026  ***************************************************************************/
00027 #ifndef _CEGUIFalPropertyLinkDefinition_h_
00028 #define _CEGUIFalPropertyLinkDefinition_h_
00029 
00030 #include "CEGUI/falagard/FalagardPropertyBase.h"
00031 #include "CEGUI/falagard/XMLHandler.h"
00032 #include "CEGUI/IteratorBase.h"
00033 #include <vector>
00034 
00035 #if defined (_MSC_VER)
00036 #       pragma warning(push)
00037 #       pragma warning(disable : 4251)
00038 #endif
00039 
00040 namespace CEGUI
00041 {
00042 
00048 template <typename T>
00049 class PropertyLinkDefinition : public FalagardPropertyBase<T>
00050 {
00051 public:
00052     //------------------------------------------------------------------------//
00053     typedef typename TypedProperty<T>::Helper Helper;
00054 
00055     //------------------------------------------------------------------------//
00056     PropertyLinkDefinition(const String& propertyName, const String& widgetName,
00057                            const String& targetProperty, const String& initialValue,
00058                            const String& origin,
00059                            bool redrawOnWrite, bool layoutOnWrite,
00060                            const String& fireEvent, const String& eventNamespace) :
00061         FalagardPropertyBase<T>(propertyName,
00062                                 Falagard_xmlHandler::PropertyLinkDefinitionHelpDefaultValue,
00063                                 initialValue, origin,
00064                                 redrawOnWrite, layoutOnWrite,
00065                                 fireEvent, eventNamespace)
00066     {
00067         // add initial target if it was specified via constructor
00068         // (typically meaning it came via XML attributes)
00069         if (!widgetName.empty() || !targetProperty.empty())
00070             addLinkTarget(widgetName, targetProperty);
00071     }
00072 
00073     ~PropertyLinkDefinition() {}
00074 
00075     //------------------------------------------------------------------------//
00077     void addLinkTarget(const String& widget, const String& property)
00078     {
00079         d_targets.push_back(std::make_pair(widget,property));
00080     }
00081 
00082     //------------------------------------------------------------------------//
00084     void clearLinkTargets()
00085     {
00086         d_targets.clear();
00087     }
00088 
00089     //------------------------------------------------------------------------//
00090     // return whether a the given widget / property pair is a target of this
00091     // property link.
00092     bool isTargetProperty(const String& widget, const String& property) const
00093     {
00094         LinkTargetCollection::const_iterator i = d_targets.begin();
00095         for (; i != d_targets.end(); ++i)
00096         {
00097             if (property == i->second && widget == i->first)
00098                 return true;
00099         }
00100 
00101         return false;
00102     }
00103 
00104     //------------------------------------------------------------------------//
00105     void initialisePropertyReceiver(PropertyReceiver* receiver) const
00106     {
00107         updateLinkTargets(receiver, Helper::fromString(this->d_default));
00108     }
00109 
00110     //------------------------------------------------------------------------//
00111     Property* clone() const
00112     {
00113         return CEGUI_NEW_AO PropertyLinkDefinition<T>(*this);
00114     }
00115 
00116 protected:
00117     // override members from FalagardPropertyBase
00118     //------------------------------------------------------------------------//
00119     typename Helper::safe_method_return_type
00120     getNative_impl(const PropertyReceiver* receiver) const
00121     {
00122         const LinkTargetCollection::const_iterator i(d_targets.begin());
00123 
00124         const Window* const target_wnd =
00125             getTargetWindow(receiver, i->first);
00126 
00127         // if no target, or target (currently) invalid, return the default value
00128         if (d_targets.empty() || !target_wnd)
00129             return Helper::fromString(TypedProperty<T>::d_default);
00130 
00131         // otherwise return the value of the property for first target, since
00132         // this is considered the 'master' target for get operations.
00133         return Helper::fromString(target_wnd->getProperty(i->second.empty() ?
00134                 TypedProperty<T>::d_name : i->second));
00135     }
00136 
00137     //------------------------------------------------------------------------//
00138     void setNative_impl(PropertyReceiver* receiver,
00139                         typename Helper::pass_type value)
00140     {
00141         updateLinkTargets(receiver, value);
00142 
00143         // base handles things like ensuring redraws and such happen
00144         FalagardPropertyBase<T>::setNative_impl(receiver, value);
00145     }
00146 
00147     //------------------------------------------------------------------------//
00148     void updateLinkTargets(PropertyReceiver* receiver,
00149                            typename Helper::pass_type value) const
00150     {
00151         LinkTargetCollection::const_iterator i = d_targets.begin();
00152         for ( ; i != d_targets.end(); ++i)
00153         {
00154             Window* target_wnd = getTargetWindow(receiver, i->first);
00155 
00156             // only try to set property if target is currently valid.
00157             if (target_wnd)
00158                 target_wnd->setProperty(i->second.empty() ?
00159                     TypedProperty<T>::d_name : i->second, Helper::toString(value));
00160         }
00161     }
00162 
00163     //------------------------------------------------------------------------//
00164     void writeDefinitionXMLElementType(XMLSerializer& xml_stream) const
00165     {
00166         xml_stream.openTag(Falagard_xmlHandler::PropertyLinkDefinitionElement);
00167         writeFalagardXMLAttributes(xml_stream);
00168         writeDefinitionXMLAdditionalAttributes(xml_stream);
00169     }
00170 
00171     //------------------------------------------------------------------------//
00172     void writeDefinitionXMLAdditionalAttributes(XMLSerializer& xml_stream) const
00173     {
00174         if(FalagardPropertyBase<T>::d_dataType.compare(Falagard_xmlHandler::GenericDataType) != 0)
00175             xml_stream.attribute(Falagard_xmlHandler::TypeAttribute, FalagardPropertyBase<T>::d_dataType);
00176 
00177         if (!PropertyDefinitionBase::d_helpString.empty() && PropertyDefinitionBase::d_helpString.compare(CEGUI::Falagard_xmlHandler::PropertyLinkDefinitionHelpDefaultValue) != 0)
00178             xml_stream.attribute(Falagard_xmlHandler::HelpStringAttribute, PropertyDefinitionBase::d_helpString);
00179     }
00180 
00181     //------------------------------------------------------------------------//
00182     void writeFalagardXMLAttributes(XMLSerializer& xml_stream) const
00183     {
00184         // HACK: Here we abuse some intimate knowledge in that we know it's
00185         // safe to write our sub-elements out although the function is named
00186         // for writing attributes.  The alternative was to repeat code from the
00187         // base class, also demonstrating intimate knowledge ;)
00188 
00189         LinkTargetCollection::const_iterator i(d_targets.begin());
00190 
00191         // if there is one target only, write it out as attributes
00192         if (d_targets.size() == 1)
00193         {
00194             if (!i->first.empty())
00195                 xml_stream.attribute(Falagard_xmlHandler::WidgetAttribute, i->first);
00196 
00197             if (!i->second.empty())
00198                 xml_stream.attribute(Falagard_xmlHandler::TargetPropertyAttribute, i->second);
00199         }
00200         // we have multiple targets, so write them as PropertyLinkTarget tags
00201         else
00202         {
00203             for ( ; i != d_targets.end(); ++i)
00204             {
00205                 xml_stream.openTag(Falagard_xmlHandler::PropertyLinkTargetElement);
00206 
00207                 if (!i->first.empty())
00208                     xml_stream.attribute(Falagard_xmlHandler::WidgetAttribute, i->first);
00209 
00210                 if (!i->second.empty())
00211                     xml_stream.attribute(Falagard_xmlHandler::PropertyAttribute, i->second);
00212 
00213                 xml_stream.closeTag();
00214             }
00215         }
00216     }
00217 
00218     //------------------------------------------------------------------------//
00220     const Window* getTargetWindow(const PropertyReceiver* receiver,
00221                                   const String& name) const
00222     {
00223         if (name.empty())
00224             return static_cast<const Window*>(receiver);
00225 
00226         // handle link back to parent.  Return receiver if no parent.
00227         if (name == Falagard_xmlHandler::ParentIdentifier)
00228             return static_cast<const Window*>(receiver)->getParent();
00229 
00230         return static_cast<const Window*>(receiver)->getChild(name);
00231     }
00232 
00233     //------------------------------------------------------------------------//
00235     Window* getTargetWindow(PropertyReceiver* receiver,
00236                             const String& name) const
00237     {
00238         return const_cast<Window*>(
00239             getTargetWindow(static_cast<const PropertyReceiver*>(receiver), name));
00240     }
00241 
00242     //------------------------------------------------------------------------//
00243     typedef std::pair<String,String> StringPair;
00245     typedef std::vector<StringPair CEGUI_VECTOR_ALLOC(StringPair)> LinkTargetCollection;
00246 
00248     LinkTargetCollection d_targets;
00249 
00250 public:
00251     typedef ConstVectorIterator<LinkTargetCollection> LinkTargetIterator;
00252 
00253     LinkTargetIterator getLinkTargetIterator() const
00254     {
00255         return LinkTargetIterator(d_targets.begin(),d_targets.end());
00256     }
00257 };
00258 
00259 }
00260 
00261 #if defined (_MSC_VER)
00262 #       pragma warning(pop)
00263 #endif
00264 
00265 #endif
00266 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends