$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: jared_at_[hidden]
Date: 2007-07-22 20:27:38
Author: jared
Date: 2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
New Revision: 7508
URL: http://svn.boost.org/trac/boost/changeset/7508
Log:
Initial checkin of project pinhole
Added:
   sandbox/pinhole/
   sandbox/pinhole/boost/
   sandbox/pinhole/boost/pinhole/
   sandbox/pinhole/boost/pinhole/BoolEditor.h
   sandbox/pinhole/boost/pinhole/DoubleEditor.h
   sandbox/pinhole/boost/pinhole/Editor.h
   sandbox/pinhole/boost/pinhole/EditorTypeFinder.h
   sandbox/pinhole/boost/pinhole/FloatEditor.h
   sandbox/pinhole/boost/pinhole/IntegerEditor.h
   sandbox/pinhole/boost/pinhole/StringEditor.h
   sandbox/pinhole/boost/pinhole/action_info.h
   sandbox/pinhole/boost/pinhole/exceptions.h
   sandbox/pinhole/boost/pinhole/find.h
   sandbox/pinhole/boost/pinhole/main.cpp
   sandbox/pinhole/boost/pinhole/map_key_value_iterators.h
   sandbox/pinhole/boost/pinhole/property_group.h
   sandbox/pinhole/boost/pinhole/property_group_wrapper.h
   sandbox/pinhole/boost/pinhole/property_info.h
   sandbox/pinhole/boost/pinhole/property_manager.h
   sandbox/pinhole/doc/
   sandbox/pinhole/libs/
   sandbox/pinhole/libs/pinhole/
Added: sandbox/pinhole/boost/pinhole/BoolEditor.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/BoolEditor.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,35 @@
+// MscProperty system BoolEditor.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_BOOLEDITOR
+#define BOOST_BOOLEDITOR
+
+#include "Editor.h"
+
+namespace boost { namespace pinhole
+{
+    class BoolEditor : public Editor
+    {
+    public:
+        BoolEditor(EditorControlType controlType=Radio)
+        {
+            m_UItype = controlType;
+        }
+        
+        ~BoolEditor() {;}
+
+        /**
+        * Retrieves the type of the property for the editor.
+        */
+        EditorPropertyType getEditorPropertyType() const
+        {
+            return( BooleanType );
+        }
+    };
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/DoubleEditor.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/DoubleEditor.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,84 @@
+// MscProperty system DoubleEditor.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_DOUBLEEDITOR
+#define BOOST_DOUBLEEDITOR
+
+#include "Editor.h"
+
+namespace boost { namespace pinhole
+{
+    class DoubleEditor : public Editor
+    {
+    public:
+        DoubleEditor()
+        {
+            m_UItype = EditBox;
+        }
+
+        DoubleEditor( double dLowRange, 
+                      double dHighRange, 
+                      double dIncrement=0.5,
+                      EditorControlType controlType=EditBox ) :
+        m_dLowRange( dLowRange ), 
+        m_dHighRange( dHighRange ),
+        m_dIncrement( dIncrement ),
+        m_bHasRange( true )
+        {
+            m_UItype = controlType;
+        }
+        
+
+        ~DoubleEditor() {;}
+
+        /**
+        * Retrieves the low range of the property for the editor.
+        */
+        double getLowRange() const
+        {
+            return( m_dLowRange );
+        }
+
+        /**
+        * Retrieves the high range of the property for the editor.
+        */
+        double getHighRange() const
+        {
+            return( m_dHighRange );
+        }
+
+        /**
+        * Retrieves the increment of the property for the editor.
+        */
+        double getIncrement() const
+        {
+            return( m_dIncrement );
+        }
+
+        /**
+        * Retrieves the flag to use range of the property for the editor.
+        */
+        bool UseRange() const
+        {
+            return( m_bHasRange );
+        }
+
+        /**
+        * Retrieves the type of the property for the editor.
+        */
+        EditorPropertyType getEditorPropertyType() const
+        {
+            return( DoubleType );
+        }
+
+    private:
+        double m_dLowRange, m_dHighRange, m_dIncrement;
+        bool m_bHasRange;
+    };
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/Editor.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/Editor.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,117 @@
+// MscProperty system Editor.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_EDITOR
+#define BOOST_EDITOR
+
+#include <map>
+#include <string>
+
+using namespace std;
+//using namespace boost;
+
+namespace boost { namespace pinhole
+{
+    enum EditorPropertyType
+    {
+        StringType,
+        IntegerType,
+        BooleanType,
+        FloatType,
+        DoubleType
+    };
+
+    enum EditorControlType
+    {
+        None=0,
+        EditBox=1,
+        Tracker=2,
+        DropDown=3,
+        Radio=4,
+        UpDown=5
+    };
+
+    class Editor
+    {
+    public:
+        typedef std::map<std::string, std::string> property_collection;
+        typedef property_collection::size_type size_type;
+        typedef property_collection::iterator iterator;
+        typedef property_collection::const_iterator const_iterator;
+
+        /**
+         * Constructor which creates a default editor that is defined as
+         * no editor.
+         */
+        Editor() : m_UItype(EditBox) {;}
+
+        /**
+         * Constructor that created an editor of the specified type.
+         * @param type The editor to use.
+         */
+        Editor(EditorControlType type)
+        {
+            m_UItype = type;
+        }
+
+        /**
+        * Destructor
+        */
+        virtual ~Editor() {;}
+
+        /**
+         * Retrieves the type of the editor to use.
+         */
+        EditorControlType GetControlType() const
+        {
+            return m_UItype;
+        }
+
+        /**
+         * Sets a property for the editor. Properties are simple key/value
+         * string pairs that are used by the editor to make decision. Each
+         * editor has a different set of properties that it will read.
+         * @param key The property key.
+         * @param value The property value.
+         */
+        Editor& operator()( std::string key, std::string value )
+        {
+            m_properties.insert( make_pair(key,value) );
+            
+            return *this;
+        }
+
+        /**
+         * Overloaded operator equal.
+         * @param editor The Editor class to copy.
+         */
+        virtual Editor& operator=( const Editor& editor )
+        {
+            m_UItype = editor.m_UItype;
+            
+            m_properties.clear();
+            m_properties.insert( editor.m_properties.begin(), editor.m_properties.end() );
+            
+            return *this;
+        }
+        
+
+        /**
+        * Retrieves the type of the property for the editor.
+        */
+        virtual EditorPropertyType getEditorPropertyType() const = 0;
+
+        protected:
+            EditorControlType m_UItype;
+#pragma warning(push)
+#pragma warning( disable: 4251 )
+            property_collection m_properties;
+#pragma warning(pop)
+    };
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/EditorTypeFinder.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/EditorTypeFinder.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,64 @@
+// MscProperty system EditorTypeFinder.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_DETAIL_EDITORTYPEFINDER
+#define BOOST_DETAIL_EDITORTYPEFINDER
+
+#include <boost/mpl/void.hpp>
+#include "BoolEditor.h"
+#include "DoubleEditor.h"
+#include "FloatEditor.h"
+#include "IntegerEditor.h"
+#include "StringEditor.h"
+
+namespace boost { namespace pinhole { namespace detail
+{
+
+    template<typename Value_Type>
+    struct EditorTypeFinder
+    {
+        typedef boost::mpl::void_ type;
+    };
+
+    template<>
+    struct EditorTypeFinder<bool>
+    {
+        typedef BoolEditor type;
+    };
+
+    template<>
+    struct EditorTypeFinder<double>
+    {
+        typedef DoubleEditor type;
+    };
+
+    template<>
+    struct EditorTypeFinder<float>
+    {
+        typedef FloatEditor type;
+    };
+
+    template<>
+    struct EditorTypeFinder<int>
+    {
+        typedef IntegerEditor type;
+    };
+
+    template<>
+    struct EditorTypeFinder<time_t>
+    {
+        typedef IntegerEditor type;
+    };
+
+    template<>
+    struct EditorTypeFinder<std::string>
+    {
+        typedef StringEditor type;
+    };
+}}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/FloatEditor.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/FloatEditor.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,83 @@
+// MscProperty system FloatEditor.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FLOATEDITOR
+#define BOOST_FLOATEDITOR
+
+#include "Editor.h"
+
+namespace boost { namespace pinhole
+{
+    class FloatEditor : public Editor
+    {
+    public:
+        FloatEditor()
+        {
+            m_UItype = EditBox;
+        };
+
+        FloatEditor( float fLowRange, 
+                     float fHighRange, 
+                     float fIncrement=0.5,
+                     EditorControlType controlType=EditBox ) :
+            m_fLowRange( fLowRange ), 
+            m_fHighRange( fHighRange ),
+            m_fIncrement( fIncrement )
+        {
+                m_UItype = controlType;
+                m_bHasRange = true;
+        }
+
+        ~FloatEditor() {;}
+
+        /**
+        * Retrieves the low range of the property for the editor.
+        */
+        float getLowRange() const
+        {
+            return( m_fLowRange );
+        }
+
+        /**
+        * Retrieves the high range of the property for the editor.
+        */
+        float getHighRange() const
+        {
+            return( m_fHighRange );
+        }
+
+        /**
+        * Retrieves the increment of the property for the editor.
+        */
+        float getIncrement() const
+        {
+            return( m_fIncrement );
+        }
+
+        /**
+        * Retrieves the flag to use range of the property for the editor.
+        */
+        bool UseRange() const
+        {
+            return( m_bHasRange );
+        }
+
+        /**
+        * Retrieves the type of the property for the editor.
+        */
+        EditorPropertyType getEditorPropertyType() const
+        {
+            return( FloatType );
+        }
+
+    private:
+        float m_fLowRange, m_fHighRange, m_fIncrement;
+        bool m_bHasRange;
+    };
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/IntegerEditor.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/IntegerEditor.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,85 @@
+// MscProperty system IntegerEditor.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_INTEGEREDITOR
+#define BOOST_INTEGEREDITOR
+
+#include "Editor.h"
+
+namespace boost { namespace pinhole
+{
+    class IntegerEditor : public Editor
+    {
+    public:
+        IntegerEditor()
+        {
+            m_UItype = EditBox;
+            m_bHasRange = false;
+        }
+        
+        IntegerEditor( int iLowRange, 
+                       int iHighRange, 
+                       int iIncrement=0,
+                       EditorControlType controlType=EditBox ) :
+            m_iLowRange( iLowRange ), 
+            m_iHighRange( iHighRange ),
+            m_iIncrement( iIncrement )
+        {
+                m_UItype = controlType;
+                m_bHasRange = true;
+        }
+        
+        virtual ~IntegerEditor() {;}
+        
+
+        /**
+        * Retrieves the low range of the property for the editor.
+        */
+        int getLowRange() const
+        {
+            return( m_iLowRange );
+        }
+
+        /**
+        * Retrieves the high range of the property for the editor.
+        */
+        int getHighRange() const
+        {
+            return( m_iHighRange );
+        }
+
+        /**
+        * Retrieves the increment of the property for the editor.
+        */
+        int getIncrement() const
+        {
+            return( m_iIncrement );
+        }
+
+        /**
+        * Retrieves the flag to use range of the property for the editor.
+        */
+        bool UseRange() const
+        {
+            return( m_bHasRange );
+        }
+
+        /**
+        * Retrieves the type of the property for the editor.
+        */
+        EditorPropertyType getEditorPropertyType() const
+        {
+            return( IntegerType );
+        }
+
+    private:
+        int m_iLowRange, m_iHighRange, m_iIncrement;
+        bool m_bHasRange;
+    };
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/StringEditor.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/StringEditor.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,35 @@
+// MscProperty system StringEditor.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_STRINGEDITOR
+#define BOOST_STRINGEDITOR
+
+#include "Editor.h"
+
+namespace boost { namespace pinhole
+{
+    class StringEditor : public Editor
+    {
+    public:
+        StringEditor()
+        {
+            m_UItype = EditBox;
+        }
+
+        ~StringEditor() {;}
+
+        /**
+        * Retrieves the type of the property for the editor.
+        */
+        EditorPropertyType getEditorPropertyType() const
+        {
+            return( StringType );
+        }
+    };
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/action_info.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/action_info.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,49 @@
+// MscProperty system action_info.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_DETAILS_ACTION_INFO
+#define BOOST_DETAILS_ACTION_INFO
+
+#pragma warning(push)
+#pragma warning( disable: 4272 4394 )
+#include "Editor.h"
+#pragma warning(pop)
+
+#pragma warning(push)
+#pragma warning( disable: 4561 4793 )
+#include <boost/type_traits.hpp>
+#include <boost/function.hpp>
+#include <boost/lexical_cast.hpp>
+#pragma warning(pop)
+
+namespace boost { namespace pinhole { namespace detail
+{
+    struct action_info
+    {
+    private:
+        template<typename type> struct Internal;
+
+    public:
+        typedef boost::function<void ()> action_type;
+
+        action_type m_action;
+        std::string m_name;
+        std::string m_description;
+
+        /**
+         * Calls the appropriate action function for this parameter.
+         *
+         * @throw boost::bad_function_call There isn't a set function associated with this property.
+         */
+        virtual void trigger()
+        {
+            m_action();
+        }
+    };
+}}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/exceptions.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/exceptions.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,36 @@
+// MscProperty system Exceptions.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_DETAIL_EXCEPTIONS
+#define BOOST_DETAIL_EXCEPTIONS
+
+#include <exception>
+#include <stdexcept>
+#include <string>
+
+namespace boost { namespace pinhole
+{
+    class multiple_property_groups : public std::runtime_error
+    {
+        public: multiple_property_groups(const std::string& strErrMsg) : std::runtime_error(strErrMsg) {;}
+    };
+
+    class invalid_path : public std::runtime_error
+    {
+        public: invalid_path(const std::string& strErrMsg) : std::runtime_error(strErrMsg) {;}
+    };
+
+    class failed_to_find_group : public std::exception{};
+    
+    class no_metadata_defined_error : public std::runtime_error
+    {
+        public:
+        no_metadata_defined_error() : runtime_error( "No Property Editor Defined" ) {;}
+    };
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/find.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/find.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,207 @@
+// MscProperty system Find.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_FIND
+#define BOOST_FIND
+
+#include "property_manager.h"
+
+namespace boost { namespace pinhole
+{
+    namespace detail
+    {
+        property_group* search_single_property_group_based_on_name( children_collection* current_property_group_collection,
+                                                                    const string& property_group_name)
+        {
+            property_group* property_group_found = 0;
+            for( children_collection::iterator iter = current_property_group_collection->begin(); iter != current_property_group_collection->end(); iter++)
+            {
+                property_group* current_property_group = *iter;
+                if(current_property_group->get_name() == property_group_name)
+                {
+                    if(property_group_found != 0)
+                    {
+                        string strError = "Multiple " + property_group_name + " are found in property_manager::selectSingleNode";
+                        throw multiple_property_groups(strError.c_str());
+                    }
+                    property_group_found = current_property_group;
+                }
+            }
+            if(property_group_found == 0)
+            {
+                throw no_metadata_defined_error();
+            }
+            return property_group_found;
+        }
+
+        property_group* search_single_property_group_based_on_property_value( children_collection* current_property_group_collection, 
+                                                                              const string& property_group_name, 
+                                                                              const string& property_name,
+                                                                              const string& property_value )
+        {
+            property_group* property_group_found = 0;
+            for(children_collection::iterator iter = current_property_group_collection->begin(); iter != current_property_group_collection->end(); iter++)
+            {
+                property_group* current_property_group = *iter;
+                if((current_property_group->get_name() == property_group_name) && (current_property_group->get_as_string(property_name) == property_value))
+                {
+                    if(property_group_found != 0)
+                    {
+                        string strError = "Multiple " + property_group_name + "." + property_name + "=" + property_value + " are found in property_manager::selectSingleNode";
+                        throw multiple_property_groups(strError.c_str());
+                    }
+                    property_group_found = current_property_group;
+                }
+            }
+            if(property_group_found == 0)
+            {
+                throw no_metadata_defined_error();
+            }
+            return property_group_found;
+        }
+    }
+
+    /** 
+     * Returns a property_group based on a path that describes where that property_group
+     * exists within the property group hierarchy. This path can either be from the
+     * root of the hierarchy, or relative to the property_group passed in to the function 
+     * @n
+     * Path format one: /A/X.Y=Z @n
+     * A represents a property group name. The assumption is that A is the only property
+     * group in the current level. The path search will start from root
+     * @n
+     * Path format two: A/X.Y=Z @n
+     * A represents a property group name. The assumption is that A is the only property
+     * group in the current level. The path search will start from current_property_group
+     * @n
+     * Path format three: /A.B=C/X.Y=Z @n
+     * A and X represent property group names. B and Y represent property names. C and Z
+     * represent property values. The path search will start from root.
+     * @n
+     * Path format four: A.B=C/X.Y=Z @n
+     * A and X represent property group names. B and Y represent property names. C and Z
+     * represent property values. The path search will start from current_property_group.
+     *
+     * @param current_property_group The property_group to perform relative searches under.
+     * @param path The path to search with.
+     * @return The property_group that was found to match the path.
+     * @retval NULL No property_group was found to match the path.
+     * @throw invalid_path The path does not meet the requirements for a valid path.
+     * @throw multiple_property_groups There were multiple property groups matching this path.
+     */
+    property_group* select_single_node(property_group* current_property_group, const string& path)
+    {
+        children_collection* current_property_group_collection = NULL;
+        if( NULL != current_property_group )
+        {
+            current_property_group_collection = ¤t_property_group->get_children_collection();
+        }
+        children_collection* root_property_group_collection = 0; //The root collection might not be needed if it is not referred.
+        
+        typedef vector< string > split_vector_type;
+        split_vector_type vecproperty_groups; 
+        boost::split( vecproperty_groups, path, boost::is_any_of("/") ); //Note: "/" is the separator for a property group
+        try
+        {
+            for(split_vector_type::const_iterator iter_property_group = vecproperty_groups.begin(); iter_property_group != vecproperty_groups.end(); iter_property_group++)
+            {
+                string strproperty_group = *iter_property_group;
+                split_vector_type properties;
+                boost::split( properties, strproperty_group, boost::is_any_of(".=") ); 
+                //Note: "." is the separator between Property group name and Property name.
+                //"=" is the separator between property name and property value. If there's no "." or "=",
+                //we will just use this property group.
+                size_t nNumOfItems = properties.size();
+                switch(nNumOfItems)
+                {
+                    case 1:
+                    {
+                        string strItem = properties[0]; //It either is "/" or the property group name.
+                        boost::trim(strItem);
+                        if(strItem.empty()) //It is "/"
+                        {
+                            property_manager *manager = property_manager::instance();
+                            root_property_group_collection = new children_collection();
+                            property_manager::iterator iter    = manager->begin();
+                            property_manager::iterator iterEnd = manager->end();
+                            for( ; iter != iterEnd; iter++)
+                            {
+                                root_property_group_collection->push_back(*iter);
+                            }
+                            current_property_group_collection = root_property_group_collection; //From now on, we only care about current_property_group_collection.
+                        }
+                        else
+                        {
+                            //strItem here must be a property group name.
+                            //If multiple or none is found ,exception will be thrown.
+                            current_property_group = detail::search_single_property_group_based_on_name(current_property_group_collection, strItem);
+                            current_property_group_collection = ¤t_property_group->get_children_collection();
+                        }
+                    }
+                        break;
+                    case 3:
+                    {
+                        string property_group_name = properties[0];
+                        boost::trim(property_group_name);
+                        
+                        string property_name = properties[1];
+                        boost::trim(property_name);
+                        
+                        string property_value = properties[2];
+                        boost::trim(property_value);
+                        current_property_group = detail::search_single_property_group_based_on_property_value(current_property_group_collection, property_group_name, property_name, property_value);
+                        current_property_group_collection = ¤t_property_group->get_children_collection();
+                    }
+                        break;
+                    default:
+                    {
+                        string strError = path + " is not a valid path. Details: " + strproperty_group + " should be either A.B=C or A format";
+                        throw invalid_path(strError.c_str());
+                    }
+                }
+            }
+        }
+        catch(no_metadata_defined_error&)
+        {
+            current_property_group = NULL;
+        }
+        
+        delete root_property_group_collection;
+        return current_property_group;
+    }
+
+    property_group* select_single_node(property_group& current_property_group, const string& path)
+    {
+        return select_single_node(¤t_property_group, path);
+    }
+
+    /** 
+    * Returns a property_group based on a path that describes where that property_group
+    * exists within the property group hierarchy. This version does not allow for relative
+    * path accessing.
+    * @n
+    * Path format one: /A/X.Y=Z @n
+    * A represents a property group name. The assumption is that A is the only property
+    * group in the current level. The path search will start from root\
+    * @n
+    * Path format two: /A.B=C/X.Y=Z @n
+    * A and X represent property group names. B and Y represent property names. C and Z
+    * represent property values. The path search will start from root.
+    *
+    * @param path The path to search with.
+    * @return The property_group that was found to match the path.
+    * @retval NULL No property_group was found to match the path.
+    * @throw invalid_path The path does not meet the requirements for a valid path.
+    * @throw multiple_property_groups There were multiple property groups matching this path.
+    */
+    property_group* select_single_node(const string& path)
+    {
+        return select_single_node(NULL, path);
+    }
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/main.cpp
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/main.cpp	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,258 @@
+// MscProperty system property_manager.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include "property_group.h"
+#include "property_manager.h"
+#include "find.h"
+
+using namespace std;
+using namespace boost;
+using namespace boost::pinhole;
+        
+// I can hide these two line if I don't do everything in headers
+shared_ptr<property_manager> property_manager::m_instance(new property_manager);
+event_source* event_source::m_instance = 0;
+
+class SubGroup : public property_group
+{
+public:
+    SubGroup(property_group* pParentproperty_group) : property_group("SubGroup", pParentproperty_group)
+    {
+            add_property<string>("Name", "name", BOOST_SETTER_NONE, BOOST_GETTER(&SubGroup::GetName));
+    }
+
+    string GetName()
+    {
+        return "SubGroup";
+    }
+};
+
+// For an object to be a property group, it must inherit from property_group. You could also
+// use the PropertGroupWrapper to create properties without inheriting, but it isn't as nice to work with,
+// and I don't have any examples here. We currently only use it to create logical property groups under an
+// existing property group that don't have an object to match up with them. I probably need to make an
+// example to have that make any sense.
+class test_group : public property_group
+{
+public:
+    enum eExample
+    {
+        Example1,
+        Example2
+    };
+    
+    // The property_group constructor requires you to give the class a name and it's parent property_group if
+    // it has one. The name is used by the property system for path based lookups, but our code uses it,
+    // especially in the property debugging user interface. If your object never has a parent property group,
+    // as is the case here, default it to NULL and it will become a root property group. To see an example
+    // of parenting, see the definition of SubGroup above, and the use below. If you wanted to make SubGroup
+    // a root property group, you would just pass it NULL as parent.
+    //
+    // A root property group is one that shows up in the root list in property_manager. This has important
+    // implications in tree iteration and path lookup.
+    test_group() : property_group("test_group", NULL),
+        a_sub_group(this)
+    {
+        // Setup default values for our variables.
+        name = "Hello World!";
+        iVal = 123;
+        fFloat = 0.0f;
+        
+        // Simple hooking up of getter/setters as properties
+        add_property<string>("Name", "name", BOOST_SETTER(&test_group::SetName), BOOST_GETTER(&test_group::GetName));
+        add_property<int>("iVal", "name", BOOST_SETTER(&test_group::SetIVal), BOOST_GETTER(&test_group::GetIVal));
+        
+        // Slightly more advanced. Converts a function that takes two parameters into multiple valid getters
+        // for the property system by hard-coding one of the values passed in.
+        add_property<int>("example1", "name", BOOST_SETTER_NONE, boost::bind(&test_group::GetExample, this, Example1));
+        add_property<int>("example2", "name", BOOST_SETTER_NONE, boost::bind(&test_group::GetExample, this, Example2));
+        
+        // Here is an example of how to expose a variable without associated getter/setter functions
+        add_property<float>("variable", "name", BOOST_SETTER_VAR(fFloat), BOOST_GETTER_VAR(fFloat));
+    }
+    
+    string GetName()
+    {
+        return name;
+    }
+    
+    void SetName(string newName)
+    {
+        name = newName;
+    }
+    
+    int GetExample(eExample eVal)
+    {
+        switch(eVal)
+        {
+            case Example1:
+                return 1;
+            case Example2:
+                return 2;
+        }
+        
+        return 0;
+    }
+    
+    int GetIVal()
+    {
+        return iVal;
+    }
+    
+    void SetIVal(int value)
+    {
+        iVal = value;
+    }
+    
+    float fFloat;
+    string name;
+    int iVal;
+    SubGroup a_sub_group;
+};
+
+int main (int argc, char * const argv[])
+{
+    test_group test;
+
+    // This is an example of basic runtime type-safe property accessors (get/set)
+    cout << test.get<string>("Name") << endl;
+    test.set("Name", string("newName"));
+    cout << test.get<string>("Name") << endl;
+
+    // This is an example of accessors that return strings for all types. This is very
+    // useful when you need to write code that doesn't know anything about the types
+    // it is processing over. Examples of this are generic user interfaces that show
+    // all the property groups and their properties in the system so that they can be
+    // manipulated when the system is running. The UI can't know what the types are, but
+    // using this method it can still display them, and allow them to be changed.
+    string i = test.get_as_string("iVal");
+    cout << "Fetched by string: " << i << endl;
+    test.set_as_string("iVal", "20");
+    i = test.get_as_string("iVal");
+    cout << "Fetched by string: " << i << endl;
+
+    // This is an example of an accessor that is getting data from a function that isn't
+    // a simple getter function. Each one of these properties is actually calling the same
+    // function, but with different default parameters passed in. See the definition of
+    // test_group for more details.
+    cout << "Example1: " << test.get<int>("example1") << endl;
+    cout << "Example2: " << test.get<int>("example2") << endl;
+
+    // This is fetching from a property that is exposing a variable directly. There aren't any
+    // getter/setter methods for it, though you could add them later if you needed to change
+    // the default behavior and the users wouldn't have to change.
+    test.set("variable", 1.234567f);
+    cout << "Fetched wrapped variable: " << test.get<float>("variable") << endl;
+
+    // Here is an example of fetching a child property group based on a search path. The
+    // You can also iterate through all the children, and thus walk the entire property
+    // tree if you would like, or if you're code doesn't know what the hierarchy looks like
+    // when it is compiled.
+    property_group* found_property_group = select_single_node(test, "SubGroup.Name=SubGroup");
+    cout << "Subproperty_group Name: " << found_property_group->get<string>("Name") << endl;
+
+    // Here is an example of the above, but using a full path from the root of the property
+    // group tree. Note that we use the value "newName" for Name since we changed the name
+    // in an earlier example.
+    found_property_group = select_single_node("/test_group.Name=newName/SubGroup.Name=SubGroup");
+    cout << "Subproperty_group Name: " << found_property_group->get<string>("Name") << endl;
+
+    // Here is an example of iterating through all the child propety groups.
+    // ** I don't like the way this works today, so I'm leaving the example out for now.
+
+    // Here we see that we can get to the test_group instance from the property_manager.
+    property_manager* manager = property_manager::instance();
+
+    // Here is an example of iterating through all the root propety groups.
+    property_manager::iterator itrRoot    = manager->begin();
+    property_manager::iterator itrRootEnd = manager->end();
+    for( ; itrRoot != itrRootEnd; ++itrRoot )
+    {
+        cout << "Found Root Item: " << (*itrRoot)->get_name() << endl;;
+    }
+
+    // All properties can have metadata associated to them. In the current form we store
+    // instances of the Editor class with each property (see "Areas that need work" below
+    // for where I admit this is too specific of a design). If you don't specify the Editor
+    // object in your call to add_property, the property system tries to find a default Editor
+    // based on the property type. None of the above examples specify an Editor, so they are
+    // all defaulted.
+    //
+    // Here is an example of accessing metadata for a specified property.
+    // ** I don't like the way this works today, so I'm leaving the example out for now.
+
+    /*
+    Areas that need work:
+
+    1) Generic Metadata: Properties need to have metadata associated with them so that the system can learn more about
+    them. However, this metadata is system specific. I don't want to force everyone to use my metadata, when they will
+    likely need something completely different. Currently the property system is built for our simulation's needs, so
+    this metadata is hardcoded to the types it wants. This needs to be made generic. Perhaps use boost::any or maybe
+    an additional key/value pair component would work. Either way, it would be nice to try to keep the auto-selection of
+    metadata that already exists in the system.
+     
+    2) Extra Type Specification: There has to be a way to derive the type from the functions when you call add_property.
+    It is really ugly to have to specify it every time.
+
+    2) Algorithms: We currently only have one path based search algorithm. This expects a single matching value and
+    throws otherwise. This is a useful search algorithm as is, but we need more. We need one that returns iterators
+    over all the items found. We need a version of that that returns them as they exist in the system, and one that
+    returns them sorted based on a given criteria. I also imagine there may be other algorithms for processing entire
+    property trees, or sub-trees. For example, we have a serialization algorithm that walks the entire tree and stores
+    the values of all properties. Given the same tree structure, it can re-walk the tree and set the values to their
+    stored values.
+
+    3) More compile time optimizations: There are a lot of powerful things you can do by creating properties at runtime.
+    However, our experience shows that most properties are simple, and everything about them is known at compile time.
+    There should be some template mechanism we could use for creating this type of property that would reduce the amount
+    of time that is used at runtime to setup the property without reducing the utility of the system to create properties
+    purely at runtime.
+
+    4) Property Manager Singleton: Currently the property manager is a singleton. This has been extremely helpful in
+    allowing us to build out the full property group tree and access it from anywhere. However, some people have
+    an aversion to this pattern, and there are cases where you may want multiple managers (if you have multiple copies
+    of your data layer, you probably don't want all those copies combined into the same property group tree). We haven't
+    really thought much further on how to do this better and are looking for insights.
+     
+    5) Safe Property Group: This is something I've been toying around with for a while. Currently it is advantagious to
+    get a property group and hold on to it. However, since property groups are retrieved largely as pointers, this can
+    be dangerious. I can't use shared_ptr since the object that it is pointing to may have been created on the stack,
+    and it won't have control over deletion (among other issues). I have a prototype class that wraps the property group
+    and listens to the property manager to see when it is destroyed, but I'm not sure I like that idea (and it is part of
+    our C++/CLI wrapper, so it isn't something I can share).
+
+    6) Documentation: We currently have doxygen documented objects for this code. If we are going to submit to boost, we
+    would need quickbook docs on top of that that show how to use everything.
+
+    7) Unit Tests: We currently have an entire set of unit tests for this code, but it uses UnitTest++. We'd need to
+    convert this to Boost::Test to submit it. This shouldn't be too hard.
+    
+    Discussion Points:
+     
+    1) Header Files: I'm distributing this as header only. I did this since it simplified initial distribution (I didn't have
+    to get bjam working right away). In house, we build a library. There a lot of things that can be hidden from the user,
+    including defineing the static instances of the singeltons, if we use a library.
+     
+    2) Right now we have several different begin/end function pairs in property_group for accessing the different data in
+    the system. Is that really the best way to do it? Whould we be passing back const references to the collections instead?
+    If we did that, then what dop we do about retrieving a list of all the property names. That is really just keys to a map,
+    but we can hide that complexity from the user using the technique we use now.
+     
+    Dreams:
+     
+    1) Events: Wouldn't it be cool if you could hook to an event that was fired whenever a specified property value
+    changed. Since the system is really just wrapping existing function calls, I haven't come up with a way to do this
+    that doesn't add a lot of work to property implementers, and would have high risk of being buggy. Any ideas?
+     
+    2) Thread Safety: Since the system is really just wrapping existing function calls, any thread safety is tied to
+    those function calls. I currently have no way of exposing complex techniques. Any ideas?
+    */
+    
+    return 0;
+}
Added: sandbox/pinhole/boost/pinhole/map_key_value_iterators.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/map_key_value_iterators.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,126 @@
+// MscProperty system map_key_value_iterators.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MAP_KEY_VALUE_ITERATORS
+#define BOOST_MAP_KEY_VALUE_ITERATORS
+
+#pragma warning(push)
+#pragma warning(disable: 4561 4996)
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/static_assert.hpp>
+#pragma warning(pop)
+
+namespace boost { namespace pinhole
+{
+    template <class Reference, class Iterator>
+    class map_key_iterator;
+
+    namespace map_key_iterator_detail
+    {
+        template <class Reference, class Iterator>
+        struct iterator_base
+        {
+            typedef boost::iterator_adaptor<
+                map_key_iterator<Reference, Iterator>
+              , Iterator                        // Base
+              , boost::use_default              // Value
+              , boost::use_default//boost::forward_traversal_tag    // CategoryOrTraversal
+              , Reference
+            > type;
+        };
+    }
+
+    /** Iterates over all the keys in a map. */
+    template <class Reference, class Iterator>
+    class map_key_iterator
+        : public map_key_iterator_detail::iterator_base<Reference, Iterator>::type
+    {
+     private:
+        struct enabler {};  // a private type avoids misuse
+        
+        typedef typename map_key_iterator_detail::iterator_base<
+              Reference, Iterator
+          >::type super_t;
+
+        friend class iterator_core_access;
+
+     public:
+        map_key_iterator() { }
+
+        map_key_iterator( Iterator x, Iterator end = Iterator()) : super_t(x) { }
+
+        Reference dereference() const
+        {
+            return (*this->base()).first;
+        }
+    };
+
+    /** Factory for creating map_key_iterator iterators. */
+    template <class Reference, class Iterator>
+    map_key_iterator<Reference, Iterator>
+        make_map_key_iterator(Iterator x, Iterator end = Iterator())
+    {
+        return map_key_iterator<Reference,Iterator>(x,end);
+    }
+
+    template <class Reference, class Iterator>
+    class map_value_iterator;
+
+    namespace map_value_iterator_detail
+    {
+        template <class Reference, class Iterator>
+        struct iterator_base
+        {
+            typedef boost::iterator_adaptor<
+                map_value_iterator<Reference, Iterator>
+              , Iterator                        // Base
+              , boost::use_default              // Value
+              , boost::use_default//boost::forward_traversal_tag    // CategoryOrTraversal
+              , Reference
+            > type;
+        };
+    }
+
+    /** Iterates over all the keys in a map. */
+    template <class Reference, class Iterator>
+    class map_value_iterator
+        : public map_value_iterator_detail::iterator_base<Reference, Iterator>::type
+    {
+     private:
+        struct enabler {};  // a private type avoids misuse
+        
+        typedef typename map_value_iterator_detail::iterator_base<
+              Reference, Iterator
+          >::type super_t;
+
+        friend class iterator_core_access;
+
+     public:
+        map_value_iterator() { }
+
+        map_value_iterator( Iterator x, Iterator end = Iterator()) : super_t(x) { }
+
+        Reference dereference() const
+        {
+            return (*this->base()).second;
+        }
+    };
+
+    /** Factory for creating map_value_iterator iterators. */
+    template <class Reference, class Iterator>
+    map_value_iterator<Reference, Iterator>
+        make_map_value_iterator(Iterator x, Iterator end = Iterator())
+    {
+        return map_value_iterator<Reference,Iterator>(x,end);
+    }
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/property_group.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/property_group.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,680 @@
+// MscProperty system property_group.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROPERTY_GROUP
+#define BOOST_PROPERTY_GROUP
+
+#include "map_key_value_iterators.h"
+#include "EditorTypeFinder.h"
+#include "property_info.h"
+#include "action_info.h"
+#include "property_manager.h"
+#include <set>
+#include <list>
+#include <sstream>
+
+#pragma warning(push)
+#pragma warning( disable: 4561)
+#include <boost/bind.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/function.hpp>
+#include <boost/any.hpp>
+#pragma warning(pop)
+
+#define BOOST_SETTER(c) boost::bind(c, this, _1)
+#define BOOST_GETTER(c) boost::bind(c, this)
+#define BOOST_ACTION(c) boost::bind(c, this)
+
+namespace boost { namespace pinhole
+{
+    template<typename T>
+    struct property_system_var_setter
+    {
+        typedef T result_type;
+        
+        property_system_var_setter(T &t) : var(t){}
+            
+        void operator()(const T &value)
+        {
+            var = value;
+        }
+        
+        T &var;
+    };
+
+    template<typename T>
+    inline boost::function<void (const T&)> property_system_var_setter_builder(T &t)
+    {
+        return boost::bind<void>(property_system_var_setter<T>(t), _1);
+    }
+
+    #define BOOST_SETTER_VAR(c) property_system_var_setter_builder(c)
+
+    template<typename T>
+    struct property_system_var_getter
+    {
+        typedef T result_type;
+        
+        property_system_var_getter(T &t) : var(t){}
+            
+            T operator()()
+        {
+                return var;
+        }
+        
+        T &var;
+    };
+
+    template<typename T>
+    inline boost::function<T ()> property_system_var_getter_builder(T &t)
+    {
+        return boost::bind<T>(property_system_var_getter<T>(t));
+    }
+
+    #define BOOST_GETTER_VAR(c) property_system_var_getter_builder(c)
+
+    #define BOOST_SETTER_NONE NULL
+    #define BOOST_GETTER_NONE NULL
+
+    class property_group;
+
+    typedef std::set<std::string> category_collection; 
+    typedef std::list<property_group*> children_collection;
+    typedef std::map<std::string, detail::property_info_base*> property_collection;
+    typedef std::map<std::string, detail::action_info*> action_collection;
+
+    /**
+     * Manages a list of properties for an object. A property is defined by a
+     * string that is unique to the object and a set of getter and setter
+     * functions that set and retrieve values.
+     */
+    class property_group
+    {
+    public:
+        /**
+         * Constructor.
+         * @param name The name of this property group
+         * @param parent The parent of the this object or NULL if it is a root group.
+         */
+        property_group( std::string name, property_group *parent=NULL ) :
+            m_name( name ), 
+            m_parent( parent )
+        {
+                setup_parent_and_category_and_manager();
+        }
+        
+        explicit property_group( const property_group& old_property_group )
+        {
+            m_name    = old_property_group.m_name;
+            m_parent = old_property_group.m_parent;
+            
+            setup_parent_and_category_and_manager();
+        }
+
+        /** Destructor. */
+        virtual ~property_group()
+        {
+            // Calling OnParentDeleting will likely modify m_children_collection,
+            // so we can't use it directly.
+            children_collection temp_child(m_children_collection);
+            children_collection::iterator childIter    = temp_child.begin();
+            children_collection::iterator childIterEnd = temp_child.end();
+            for( ; childIter != childIterEnd; ++childIter )
+            {
+                (*childIter)->set_parent(NULL);
+            }
+            temp_child.clear();
+            
+            if ( NULL != m_parent )
+            {
+                m_parent->remove_child(this);
+            }
+            
+            if ( property_manager::instance() != NULL )
+            {
+                // Unregister this group with this property manager...
+                property_manager::instance()->unregister_property_group( this, m_category_collection );
+            }
+            
+            // cleanup all the property_manager classes
+            property_collection::iterator propItr    = m_properties.begin();
+            property_collection::iterator propItrEnd = m_properties.end();
+            for( ; propItr != propItrEnd; ++propItr )
+            {
+                delete (*propItr).second;
+                (*propItr).second = NULL;
+            }
+            m_properties.clear();
+            
+            // cleanup all the action classes
+            action_collection::iterator actionItr    = m_actions.begin();
+            action_collection::iterator actionItrEnd = m_actions.end();
+            for( ; actionItr != actionItrEnd; ++actionItr )
+            {
+                delete (*actionItr).second;
+                (*actionItr).second = NULL;
+            }
+            m_actions.clear();
+        }
+        
+
+        /**
+        * Gets the parent of this property group.
+        * @return The parent of this property group.
+        */
+        property_group* get_parent() const
+        {
+            return( m_parent );
+        }
+
+        /**
+        * Sets the parent of this property group.
+        * @param new_parent The new parent of this property group.
+        */
+        void set_parent(property_group* new_parent)
+        {
+            if( NULL != property_manager::instance() )
+            {
+                // Register this group with this property manager...
+                property_manager::instance()->unregister_property_group(this, m_category_collection);
+            }
+            
+            if ( NULL != m_parent )
+            {
+                m_parent->remove_child(this);
+            }
+            
+            m_parent = new_parent;
+            
+            
+            if ( NULL != m_parent )
+            {
+                m_parent->add_child(this);
+            }
+            
+            if( NULL != property_manager::instance() )
+            {
+                // Register this group with this property manager...
+                property_manager::instance()->register_property_group(this);
+            }
+        }
+
+        /**
+        * Gets the name of this property group.
+        * @return The name of this property group.
+        */
+        const std::string get_name() const
+        {
+            return( m_name );
+        }
+
+        /**
+        * Gets the category collection of this property group.
+        * @return The category collection of this property group.
+        * @todo Remove this accessor
+        */
+        const category_collection& get_category_collection()
+        {
+            return( m_category_collection );
+        }
+
+        /**
+        * Gets the property group children collection of this property group.
+        * @return The property group children collection of this property group.
+        * @todo Remove this accessor
+        */
+        children_collection& get_children_collection()
+        {
+            return( m_children_collection );
+        }
+
+        /** @name Properties */
+        //@{
+            typedef property_collection::size_type prop_size_type;
+            typedef map_key_iterator<std::string, property_collection::iterator> prop_iterator;
+            typedef map_key_iterator<std::string, property_collection::const_iterator> const_prop_iterator;
+
+            /**
+             * Retrieves an iterator pointing to the name of the first property.
+             */
+            prop_iterator prop_begin()
+            {
+                return make_map_key_iterator<string>( m_properties.begin() );
+            }
+
+            /**
+             * Retrieves an iterator pointing to the name of the first property.
+             */
+            const_prop_iterator prop_begin() const
+            {
+                return make_map_key_iterator<string>( m_properties.begin() );
+            }
+
+            /**
+             * Retrieves an iterator pointing to the end of the property list.
+             */
+            prop_iterator prop_end()
+            {
+                return make_map_key_iterator<string>( m_properties.end() );
+            }
+
+            /**
+             * Retrieves an iterator pointing to the end of the property list.
+             */
+            const_prop_iterator prop_end() const
+            {
+                return make_map_key_iterator<string>( m_properties.end() );
+            }
+
+            /**
+             * Retrieves the number of properties.
+             */
+            prop_size_type prop_count() const
+            {
+                return m_properties.size();
+            }
+
+            /**
+             * Gets a property's value by it's type.
+             * @param property The name of the property.
+             * @return The value of the property.
+             * @throw boost::bad_function_call There isn't a get_as_string function associated with this property.
+             * @throw std::out_of_range The property requested does not exist.
+             * @throw std::bad_cast The requested return_type was not the same as the property's type.
+             */
+            template<typename Return_Type>
+            Return_Type get(const std::string &property) const
+            {
+                // The system does not allow you to use pointers as property
+                // types due to the ambiguity of their use.
+                BOOST_STATIC_ASSERT(false == boost::is_pointer<Return_Type>::value);
+                
+                property_collection::const_iterator itemItr = m_properties.find(property);
+                
+                if( m_properties.end() != itemItr )
+                {
+                    detail::property_info_base* propInfo = (*itemItr).second;
+                    
+                    // throws boost::bad_function_call if there isn't a get_as_string
+                    // function associated with this property.
+                    if( NULL != propInfo && typeid(Return_Type) == propInfo->m_type )
+                    {
+                        return static_cast<detail::property_info<Return_Type>*>(propInfo)->getter();
+                    }
+                    
+                    throw std::bad_cast();
+                }
+                
+                stringstream err;
+                err << "The requested property \"" << property << "\" does not exist.";
+                throw std::out_of_range(err.str().c_str());                
+            }
+            
+            /**
+             * Sets a property's value.
+             * @param property The name of the property.
+             * @param value The value to set on the property.
+             * @throw boost::bad_function_call There isn't a set_as_string function associated with this property.
+             * @throw std::out_of_range The property requested does not exist.
+             * @throw std::bad_cast The Set_Type was not the same as the property's type.
+             */
+            template<typename Set_Type>
+                void set(const std::string &property, Set_Type value) const
+            {
+                // The system does not allow you to use pointers as property
+                // types due to the ambiguity of their use.
+                BOOST_STATIC_ASSERT(false == boost::is_pointer<Set_Type>::value);
+                
+                property_collection::const_iterator itemItr = m_properties.find(property);
+                
+                if( m_properties.end() != itemItr )
+                {
+                    detail::property_info_base* propInfo = (*itemItr).second;
+
+                    // throws  boost::bad_function_call if there isn't a get_as_string
+                    // function associated with this property.
+                    if( NULL != propInfo && typeid(Set_Type) == propInfo->m_type )
+                    {
+                        return static_cast<detail::property_info<Set_Type>*>(propInfo)->setter(value);
+                    }
+                    
+                    throw std::bad_cast();
+                }
+                
+                stringstream err;
+                err << "The requested property \"" << property << "\" does not exist.";
+                throw std::out_of_range(err.str().c_str());                
+            }
+
+            /**
+             * Sets a property's value.
+             * @param property The name of the property.
+             * @param value A String representation of the value to set on the property.
+             * @throw boost::bad_function_call There isn't a set_as_string function associated with this property.
+             * @throw std::out_of_range The property requested does not exist.
+             * @throw std::invalid_argument The value string could not be converted to the
+             * type expected by the internal setter function.
+             */
+            void set_as_string(const std::string &property, const std::string &value)
+            {
+                property_collection::iterator itemItr = m_properties.find(property);
+                
+                if( m_properties.end() != itemItr )
+                {
+                    // throws  boost::bad_function_call if there isn't a set_as_string
+                    // function associated with this property.
+                    (*itemItr).second->set_as_string(value);
+                }
+                else
+                {
+                    stringstream err;
+                    err << "The requested property \"" << property << "\" does not exist.";
+                    throw std::out_of_range(err.str().c_str());
+                }
+            }
+
+            /**
+             * Gets a property's value.
+             * @param property The name of the property.
+             * @return A String representation of the value of the property.
+             * @throw boost::bad_function_call There isn't a get_as_string function associated with this property.
+             * @throw std::out_of_range The property requested does not exist.
+             */
+            std::string get_as_string(const std::string &property) const
+            {
+                property_collection::const_iterator itemItr = m_properties.find(property);
+                
+                if( m_properties.end() != itemItr )
+                {
+                    // throws  boost::bad_function_call if there isn't a get_as_string
+                    // function associated with this property.
+                    return (*itemItr).second->get_as_string();
+                }
+                
+                stringstream err;
+                err << "The requested property \"" << property << "\" does not exist.";
+                throw std::out_of_range(err.str().c_str());    
+            }
+
+            /**
+            * Gets a property's Editor object.
+            * @param property The name of the property.
+            * @return The Editor of the property.
+            * @throw no_metadata_defined_error There isn't a property editor associated with this property.
+            * @throw std::out_of_range The property requested does not exist.
+            */
+            const Editor* get_metadata(const std::string &property) const
+            {
+                property_collection::const_iterator itemItr = m_properties.find(property);
+                
+                if( itemItr != m_properties.end() )
+                {
+                    // throws  boost::bad_function_call if there isn't a get
+                    // function associated with this property.
+                    if ( (*itemItr).second->m_editor == NULL )
+                    {
+                        throw( no_metadata_defined_error() );
+                    }
+                    else
+                    {
+                        return( (*itemItr).second->m_editor );
+                    }
+                }
+                else
+                {
+                    stringstream err;
+                    err << "The requested property \"" << property << "\" does not exist.";
+                    throw std::out_of_range(err.str().c_str());
+                }
+            }
+
+            /**
+            * Gets a property's type_info structure.
+            * @param property The name of the property.
+            * @return The type_info structure of the property.
+            * @throw std::out_of_range The property requested does not exist.
+            */
+            const type_info& get_type_info(const std::string &property) const
+            {
+                property_collection::const_iterator itemItr = m_properties.find(property);
+                
+                if( itemItr != m_properties.end() )
+                {
+                    return (*itemItr).second->m_type;
+                }
+                else
+                {
+                    stringstream err;
+                    err << "The requested property \"" << property << "\" does not exist.";
+                    throw std::out_of_range(err.str().c_str());
+                }
+            }
+
+            /**
+            * Retrieves whether the property is read only or not.
+            * @param property The name of the property.
+            * @retval true The property is read only.
+            * @retval false The property is writeable.
+            * @throw std::out_of_range The property requested does not exist.
+            */
+            bool is_read_only(const std::string &property) const;
+        //@}
+
+        /** @name Actions */
+        //@{
+            typedef action_collection::size_type action_size_type;
+            typedef map_key_iterator<std::string, action_collection::iterator> action_iterator;
+            typedef map_key_iterator<std::string, action_collection::const_iterator> const_action_iterator;
+
+            /**
+             * Retrieves an iterator pointing to the name of the first property.
+             */
+            action_iterator action_begin()
+            {
+                return make_map_key_iterator<string>( m_actions.begin() );
+            }
+
+            /**
+             * Retrieves an iterator pointing to the name of the first property.
+             */
+            const_action_iterator action_begin() const
+            {
+                return make_map_key_iterator<string>( m_actions.begin() );
+            }
+
+            /**
+             * Retrieves an iterator pointing to the end of the property list.
+             */
+            action_iterator action_end()
+            {
+                return make_map_key_iterator<string>( m_actions.end() );
+            }
+
+            /**
+             * Retrieves an iterator pointing to the end of the property list.
+             */
+            const_action_iterator action_end() const
+            {
+                return make_map_key_iterator<string>( m_actions.end() );
+            }
+
+            /**
+             * Retrieves the number of properties.
+             */
+            action_size_type action_count() const
+            {
+                return m_actions.size();
+            }
+
+            /**
+             * Triggers an action.
+             * @param action The name of the action.
+             * @throw std::out_of_range The property requested does not exist.
+             */
+            void trigger(const std::string &action) const
+            {
+                action_collection::const_iterator itemItr = m_actions.find(action);
+                
+                if( m_actions.end() != itemItr )
+                {
+                    // throws  boost::bad_function_call if there isn't a set
+                    // function associated with this property.
+                    (*itemItr).second->trigger();
+                }
+                else
+                {
+                    stringstream err;
+                    err << "The requested action \"" << action << "\" does not exist.";
+                    throw std::out_of_range(err.str().c_str());
+                }
+            }
+
+        //@}
+
+    protected:
+
+        /**
+         * Adds a property to the property list.
+         * @param The name of the property.
+         * @param description A brief description of the property for the user interface.
+         * @param setter The function used to set the property.
+         * @param getter The function used to get the property.
+         */
+        template<typename Value_Type>
+        void add_property( std::string name, 
+                           std::string description,
+                           boost::function<void (const Value_Type&)> setter, 
+                           boost::function<Value_Type ()> getter )
+        {
+            typedef typename detail::EditorTypeFinder<Value_Type>::type editor_type;
+
+            // You are using a Value_Type that does not have a default editor defined. Use once
+            // of the add_property functions where you explicitly define the editor or editor type.
+            BOOST_STATIC_ASSERT((false == boost::is_same<editor_type, boost::mpl::void_>::value));
+
+            add_property<Value_Type>( name, description, setter, getter, new editor_type() );
+        }
+
+        /**
+         * Adds a property to the property list.
+         * @param The name of the property.
+         * @param description A brief description of the property for the user interface.
+         * @param setter The function used to set the property.
+         * @param getter The function used to get the property.
+         * @param pEditor A pointer to the editor to be used with this property, or null
+         *                if there isn't one.
+         */
+        template<typename Value_Type>
+        void add_property( std::string name, 
+                           std::string description,
+                           boost::function<void (const Value_Type&)> setter, 
+                           boost::function<Value_Type ()> getter,
+                           Editor *pEditor )
+        {
+            // If you get an error here, then the type you are using for the property likely doesn't have a proper operator<< for it
+            detail::property_info<Value_Type> *prop = new detail::property_info<Value_Type>();
+
+            prop->m_name        = name;
+            prop->m_description = description;
+            if( BOOST_SETTER_NONE != setter )
+            {
+                prop->setter  = setter;
+            }
+            if( BOOST_GETTER_NONE != getter )
+            {
+                prop->getter  = getter;
+            }
+            prop->m_editor  = pEditor;
+
+            m_properties.insert( std::make_pair(name, prop) );
+        }
+
+        /**
+         * Adds an action to the action list.
+         * @param The name of the action.
+         * @param description A brief description of the action for the user interface.
+         * @param action The function used to trigger the action.
+         */
+        void add_action( std::string name, 
+                         std::string description,
+                         boost::function<void ()> action )
+        {
+            detail::action_info *action_info = new detail::action_info();
+            
+            action_info->m_name        = name;
+            action_info->m_description = description;
+            action_info->m_action      = action;
+            
+            m_actions.insert( std::make_pair(name, action_info) );
+        }
+
+        /**
+        * Adds this property to the specified category.
+        * @param category_name The name of the category to add.
+        */
+        void add_category( const std::string &category_name )
+        {
+            m_category_collection.insert( category_name );
+            
+            // notify the Property Manager of this new category
+            if ( property_manager::instance() != NULL )
+            {
+                property_manager::instance()->add_category( category_name, this );
+            }
+        }
+
+        #pragma warning(push)
+        #pragma warning( disable: 4251 )
+            category_collection m_category_collection;
+            children_collection m_children_collection;
+            property_collection m_properties;
+            action_collection m_actions;
+        #pragma warning(pop)
+
+    private:
+        property_group();
+
+        void add_child(property_group* pChild)
+        {
+            if( NULL != pChild )
+            {
+                m_children_collection.push_back( pChild );
+            }
+        }
+        
+        void remove_child(property_group* pChild)
+        {
+            if( NULL != pChild )
+            {
+                m_children_collection.remove(pChild);
+            }
+        }
+            
+        void setup_parent_and_category_and_manager()
+        {
+            if ( NULL != m_parent )
+            {
+                m_parent->add_child(this);
+            }
+            
+            add_category( "All" );
+            
+            if ( property_manager::instance() != NULL )
+            {
+                // Register this group with this property manager...
+                property_manager::instance()->register_property_group( this );
+            }
+        }        
+
+        std::string m_name;
+        property_group *m_parent;
+    };
+
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/property_group_wrapper.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/property_group_wrapper.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,100 @@
+// MscProperty system property_group_wrapper.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROPERTY_GROUP_WRAPPER
+#define BOOST_PROPERTY_GROUP_WRAPPER
+
+#include "property_group.h"
+
+namespace boost { namespace pinhole
+{
+    /**
+     * The property_group_wrapper allows you to create property groups without inheriting directly
+     * from property_group. This allows you to do things like create groups of properties for
+     * display in the UI that don't have a matching logical object in the system.
+     */
+    class property_group_wrapper : public property_group
+    {
+    public:
+        /**
+         * Constructor.
+         * @param name The name of this property group (like an xml node name)
+         * @param parent The parent of the this object.
+         */
+        property_group_wrapper(std::string name, property_group *parent) :
+            : property_group(name, parent){;}
+        
+        ~property_group_wrapper(void){;}
+
+        /**
+         * Adds a property to the property list.
+         * @param The name of the property.
+         * @param description A brief description of the property for the user interface.
+         * @param setter The function used to set the property.
+         * @param getter The function used to get the property.
+         */
+        template<typename Value_Type>
+        void add_property( std::string name, 
+                           std::string description,
+                           boost::function<void (const Value_Type&)> setter, 
+                           boost::function<Value_Type ()> getter )
+        {
+            property_group::add_property<Value_Type>( name, description,setter, getter );
+        }
+
+        /**
+         * Adds a property to the property list.
+         * @param The name of the property.
+         * @param description A brief description of the property for the user interface.
+         * @param setter The function used to set the property.
+         * @param getter The function used to get the property.
+         * @param pEditor A pointer to the editor to be used with this property, or null
+         *                if there isn't one.
+         */
+        template<typename Value_Type>
+        void add_property( std::string name, 
+                           std::string description,
+                           boost::function<void (const Value_Type&)> setter, 
+                           boost::function<Value_Type ()> getter,
+                           Editor *pEditor )
+        {
+            
+            property_group::add_property<Value_Type>( name, description,setter, getter, pEditor );
+        }
+
+        /**
+         * Adds an action to the action list.
+         * @param The name of the action.
+         * @param description A brief description of the action for the user interface.
+         * @param action The function used to trigger the action.
+         */
+        inline void add_action( std::string name, 
+                                std::string description,
+                                boost::function<void ()> action )
+        {
+            
+            property_group::add_action( name, description, action );
+        }
+
+        /**
+        * Gets an xml string representation of this property group
+        * @param string The name of the new category.
+        * @return The xml string representation of this property group.
+        */
+        inline void add_category( const std::string &category_name )
+        {
+            property_group::add_category( category_name );
+        }
+
+    private:
+        property_group_wrapper() : property_group("", NULL) {;}
+        property_group_wrapper(const property_group& object) : property_group(object) {;}
+        property_group_wrapper(const property_group_wrapper& object) : property_group(object) {;}
+    };
+}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/property_info.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/property_info.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,236 @@
+// MscProperty system property_manager.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROPERTY_INFO
+#define BOOST_PROPERTY_INFO
+
+#pragma warning(push)
+#pragma warning( disable: 4272 4394 )
+#include "Editor.h"
+#pragma warning(pop)
+
+#pragma warning(push)
+#pragma warning( disable: 4561 4793 )
+#include <boost/type_traits.hpp>
+#include <boost/function.hpp>
+#include <boost/lexical_cast.hpp>
+#pragma warning(pop)
+
+namespace boost { namespace pinhole { namespace detail
+{
+    #define BOOL_TRUE ("True")
+    #define BOOL_FALSE ("False")
+
+    ///////////////////////////////////////////////////
+    //               set_as_string Override Functors
+    ///////////////////////////////////////////////////
+
+    /**
+     * The default setter processor. This uses lexical cast
+     * to convert the passed in set string to any type that
+     * has proper stream operators.
+     */
+    template<typename Value_Type>
+    struct internal_string_set
+    {
+        template<typename Set_Type>
+        inline void operator()( Set_Type setter, std::string value )
+        {
+            try
+            {
+                setter( boost::lexical_cast<Value_Type>(value) );
+            }
+            catch(boost::bad_lexical_cast &)
+            {
+                std::stringstream err;
+                err << "The value '" << value << "' is not valid for this property.";
+                throw std::invalid_argument(err.str().c_str());
+            }
+        }
+    };
+
+    /**
+     * Setter for handling string types. Since a string was passed in, and
+     * the type in the setter function is a string, we don't need to do any
+     * conversion.
+     */
+    template<>
+    struct internal_string_set<std::string>
+    {
+        template<typename Set_Type>
+        inline void operator()( Set_Type setter, std::string value )
+        {
+            setter( value );
+        }
+    };
+
+
+    /**
+    * Setter for handling bool types. Since a bool was passed in, 
+    * we need to convert 
+    */
+    template<>
+    struct internal_string_set<bool>
+    {
+        template<typename Set_Type>
+        inline void operator()( Set_Type setter, std::string value )
+        {
+            setter( value == BOOL_TRUE );
+        }
+    };
+
+    ///////////////////////////////////////////////////
+    //               get_as_string Override Functors
+    ///////////////////////////////////////////////////
+
+    /**
+     * The default getter processor. This uses lexical cast
+     * to convert the returned value from the propertied
+     * getter function and convert to a string using
+     * lexical_cast. Any type that has proper stream operators
+     * should work.
+     */
+
+    template<typename Value_Type>
+    struct internal_string_get
+    {
+        template<typename Get_Type>
+        inline std::string operator()( Get_Type getter ) const
+        {
+            return boost::lexical_cast<string>( getter() );
+        }
+    };
+
+    /**
+     * Getter for handling string types. Since a string returned,
+     * and getter returns a string type, we don't need to do any
+     * conversion.
+     */
+    template<>
+    struct internal_string_get<std::string>
+    {
+        template<typename Get_Type>
+        inline std::string operator()( Get_Type getter ) const
+        {
+            return getter();
+        }
+    };
+
+    /**
+    * Getter for handling bool types. Since a string is returned,
+    * we need to convert the bool to a string.
+    */
+    template<>
+    struct internal_string_get<bool>
+    {
+        template<typename Get_Type>
+        inline std::string operator()( Get_Type getter ) const
+        {
+            return( getter() ? "True" : "False" );
+        }
+    };
+
+    struct property_info_base
+    {
+    public:
+        property_info_base(const type_info &type) : 
+          m_editor( NULL ),
+          m_type(type)
+        {;}
+
+        virtual ~property_info_base() 
+        {
+            if ( m_editor != NULL )
+                delete( m_editor );
+        }
+
+        std::string      m_name;
+        std::string      m_description;
+        Editor          *m_editor;
+        const type_info &m_type;
+
+        virtual void set_as_string(std::string value) = 0;
+        virtual std::string get_as_string() const = 0;
+        virtual bool is_read_only() const = 0;
+    };
+
+    template<typename T>
+    struct property_info : property_info_base
+    {
+    private:
+
+    public:
+        typedef typename boost::remove_reference<T>::type Value_Type;
+        typedef boost::function<void (const Value_Type&)> setter_type;
+        typedef boost::function<Value_Type ()> getter_type;
+
+        // The system does not allow you to use pointers as property
+        // types due to the ambiguity of their use.
+        BOOST_STATIC_ASSERT(false == boost::is_pointer<Value_Type>::value);
+
+        setter_type       setter;
+        getter_type       getter;
+
+        property_info() : property_info_base(typeid(T)) {;}
+
+        /**
+         * Calls the appropriate getter function for this parameter and converts
+         * the value to a string for return.
+         *
+         * @return A String representation of the value of the property.
+         * @throw boost::bad_function_call There isn't a get_as_string function associated with this property.
+         */
+        virtual std::string get_as_string() const
+        {
+            // If you get an error here, and it complains about:
+            // error C2679: binary '<<' : no operator found which takes a right-hand operand of type
+            // then the type you are using for the property doesn't have a proper operator<< for it
+            //
+            // throws  boost::bad_function_call if there isn't a get_as_string function associated with this property.
+            return internal_string_get<Value_Type>()(getter);
+        }
+
+        /**
+         * Calls the appropriate setter function for this parameter and converts
+         * the passed in string to whatever type the setter is expect. For example,
+         * if the properties setter is expecting an int, the string will be
+         * converted to an int before being passed to the function.
+         * <br><br>
+         * We call an internal setter in a struct so that we can  override
+         * what the set does based on the type of Value_Type. For example,
+         * we wanted to write a special handler for the string type for
+         * performance, so we overrode the string handler in "struct Internal<string>"
+         * to just pass the string along instead of convert it. The beauty of doing it
+         * this way is that there is no runtime cost. All functions are inlined,
+         * and the additional function calls and type processing are optimized out
+         * at compile time.
+         *
+         * @param value A String representation of the value to set on the property.
+         * @throw boost::bad_function_call There isn't a set_as_string function associated with this property.
+         * @throw std::invalid_argument The value string could not be converted to the
+         * type expected by the internal setter function.
+         */
+        virtual void set_as_string(std::string value)
+        {
+            // see the function documentation for more information about this.
+            //
+            // throws  boost::bad_function_call if there isn't a set_as_string function associated with this property.
+            internal_string_set<Value_Type>()(setter, value);
+        }
+
+        /**
+        * Checks if this is a read-only property (ie, cant set)
+        * @return true if the property is read-only.
+        */
+        virtual bool is_read_only() const
+        {
+            return( !setter );
+        }
+    };
+}}}
+
+#endif // include guard
\ No newline at end of file
Added: sandbox/pinhole/boost/pinhole/property_manager.h
==============================================================================
--- (empty file)
+++ sandbox/pinhole/boost/pinhole/property_manager.h	2007-07-22 20:27:37 EDT (Sun, 22 Jul 2007)
@@ -0,0 +1,270 @@
+// MscProperty system property_manager.h file
+//
+// Copyright Jared McIntyre 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_PROPERTY_MANAGER
+#define BOOST_PROPERTY_MANAGER
+
+#include "exceptions.h"
+#include <set>
+#include <string>
+
+#pragma warning(push)
+#pragma warning( disable: 4561 4793 )
+#include <boost/shared_ptr.hpp>
+#include <boost/signals.hpp>
+#include <boost/algorithm/string.hpp>
+#pragma warning(pop)
+
+namespace boost { namespace pinhole
+{
+    class property_group;
+    
+    typedef std::set<std::string> category_collection;
+    typedef std::list<property_group*> children_collection;
+    
+    class event_source
+    {
+    public :
+        static event_source* instance()
+        {
+            if ( m_instance == 0 )  // is it the first call?
+            {  
+                m_instance = new event_source; // create sole instance
+            }
+            
+            return m_instance; // address of sole instance
+        }
+        
+        #pragma warning(push)
+        #pragma warning( disable: 4251 )
+            boost::signal<void(property_group*)> add_event;
+            boost::signal<void(property_group*)> remove_event;
+        #pragma warning(pop)
+        void raise_on_add_event( property_group *group )
+        {
+            add_event( group );
+        }
+        
+        void raise_on_remove_event( property_group *group )
+        {
+            remove_event( group );
+        }
+        
+    private :
+        static event_source *m_instance;
+        event_source(){};
+        
+    };
+
+    class property_manager
+    {
+    private:
+        static void deleter(property_manager* manager)
+        {
+            delete manager;
+        }
+        
+    public:
+        typedef multimap<string, property_group*> category_to_property_group_map;
+        typedef map_value_iterator<property_group*, category_to_property_group_map::iterator> iterator;
+        typedef map_value_iterator<property_group*, category_to_property_group_map::const_iterator> const_iterator;
+        
+        static property_manager* instance()
+        {
+            if ( m_instance.get() == NULL )  // is it the first call?
+            {  
+                m_instance.reset( new property_manager, property_manager::deleter ); // create sole instance
+            }
+            
+            return m_instance.get(); // address of sole instance
+        }
+        
+        static bool exists()
+        {
+            return m_instance.get() != NULL;
+        }
+        
+        static void delete_instance()
+        {
+            if( m_instance.get() != NULL )
+            {
+                m_instance.reset();
+            }
+        }
+        
+    protected:
+        property_manager(){;}
+    
+    // TODO: This needs to be protected so no-one will deal with it, but
+    // checked_delete can't be made a friend in gcc, so I can't shared_ptr
+    // to work.
+    public:
+        ~property_manager()
+        {
+            category_to_property_group_map::iterator itr    = m_property_group_collection.begin();
+            category_to_property_group_map::iterator itr_end = m_property_group_collection.end();
+            for( ; itr != itr_end; ++itr )
+            {
+                event_source::instance()->raise_on_remove_event((*itr).second);
+            }
+        }
+        
+    public:        
+        /**
+         * Retrieves an iterator pointing to the first property group.
+         */
+        iterator begin()
+        {
+            return make_map_value_iterator<property_group*>( m_property_group_collection.lower_bound("All"),
+                                                             m_property_group_collection.upper_bound("All") );
+        }
+        
+        /**
+         * Retrieves an iterator pointing to the first property group.
+         */
+        const_iterator begin() const
+        {
+            return make_map_value_iterator<property_group*>( m_property_group_collection.lower_bound("All"),
+                                                             m_property_group_collection.upper_bound("All") );
+        }
+        
+        /**
+         * Retrieves an iterator pointing to the end of the root property list.
+         */
+        iterator end()
+        {
+            return make_map_value_iterator<property_group*>( m_property_group_collection.upper_bound("All") );
+        }
+        
+        /**
+         * Retrieves an iterator pointing to the end of the root property list.
+         */
+        const_iterator end() const
+        {
+            return make_map_value_iterator<property_group*>( m_property_group_collection.upper_bound("All") );
+        }
+        
+        /**
+         * Retrieves the number of property groups.
+         */
+        size_t count() const
+        {
+            return m_property_group_collection.count("All");
+        }
+        
+        /**
+         * Retrieves an iterator pointing to the first property group for a specified category.
+         */
+        iterator begin(const string& strCategory)
+        {
+            return make_map_value_iterator<property_group*>( m_property_group_collection.lower_bound(strCategory) );
+        }
+        
+        /**
+         * Retrieves an iterator pointing to the first property group for a specified category.
+         */
+        const_iterator begin(const string& strCategory) const
+        {
+            return make_map_value_iterator<property_group*>( m_property_group_collection.lower_bound(strCategory) );
+        }
+        
+        /**
+         * Retrieves an iterator pointing to the end of the root property list for a specified category.
+         */
+        iterator end(const string& strCategory)
+        {
+            return make_map_value_iterator<property_group*>( m_property_group_collection.upper_bound(strCategory) );
+        }
+        
+        /**
+         * Retrieves an iterator pointing to the end of the root property list for a specified category.
+         */
+        const_iterator end(const string& strCategory) const
+        {
+            return make_map_value_iterator<property_group*>( m_property_group_collection.upper_bound(strCategory) );
+        }
+        
+        /**
+         * Retrieves the number of property groups for a specified category.
+         */
+        size_t count(const string& strCategory) const
+        {
+            return m_property_group_collection.count(strCategory);
+        }
+        
+        /**
+         * Gets the master category list.
+         * @return master category list.
+         */
+        const category_collection* get_category_collection()
+        {
+            return( &m_category_collection );
+        }
+
+    protected:
+        /**
+         * Register's group with the property_manager.
+         */
+        virtual void register_property_group( property_group *group )
+        {
+            event_source::instance()->raise_on_add_event( group );
+        }
+        
+        /**
+         * Unregister's group from the property_manager.
+         */
+        virtual void unregister_property_group( property_group *group, category_collection &categories )
+        {
+                category_collection::const_iterator categoryItr = categories.begin();
+                category_collection::const_iterator categoryEnd = categories.end();
+                for ( ; categoryItr != categoryEnd; ++categoryItr )
+                {
+                    remove_category( *categoryItr, group );
+                }
+                
+                event_source::instance()->raise_on_remove_event( group );
+        }
+        
+        /**
+         * Adds a new category for the property group.
+         */
+        virtual void add_category( const string &category_name, property_group *group )
+        {
+            m_category_collection.insert( category_name );
+            m_property_group_collection.insert( make_pair( category_name, group ) );
+        }
+        
+        virtual void remove_category( const string &category_name, property_group *group )
+        {
+            category_to_property_group_map::iterator pgItr;
+            for ( pgItr = m_property_group_collection.find( category_name ); 
+                  pgItr != m_property_group_collection.end(); )
+            {
+                if ( pgItr->second == group )
+                {
+                    m_property_group_collection.erase( pgItr++ );
+                }
+                else
+                {
+                    pgItr++;
+                }
+            }
+        }
+        
+    protected:
+        #pragma warning(push)
+        #pragma warning( disable: 4251 )
+            static boost::shared_ptr<property_manager> m_instance;
+            category_to_property_group_map m_property_group_collection;
+            category_collection m_category_collection;
+        #pragma warning(pop)
+            
+        friend class property_group;
+    };
+}}
+
+#endif // include guard
\ No newline at end of file