stlab.adobe.com Adobe Systems Incorporated

macintosh_events.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
00005 */
00006 
00007 /**************************************************************************************************/
00008 
00009 #ifndef ADOBE_MACINTOSH_EVENTS_HPP
00010 #define ADOBE_MACINTOSH_EVENTS_HPP
00011 
00012 /**************************************************************************************************/
00013 
00014 #include <adobe/algorithm/lower_bound.hpp>
00015 #include <adobe/algorithm/sort.hpp>
00016 #include <adobe/algorithm/unique.hpp>
00017 #include <adobe/future/macintosh_error.hpp>
00018 #include <adobe/macintosh_carbon_safe.hpp>
00019 #include <adobe/macintosh_memory.hpp>
00020 
00021 #include <boost/noncopyable.hpp>
00022 #include <boost/static_assert.hpp>
00023 #include <boost/type_traits.hpp>
00024 
00025 #include <iterator>
00026 #include <vector>
00027 
00028 /**************************************************************************************************/
00029 
00030 inline bool operator == (const ::EventTypeSpec& x, const ::EventTypeSpec& y)
00031 { return x.eventClass == y.eventClass && x.eventKind == y.eventKind; }
00032 
00033 inline bool operator < (const ::EventTypeSpec& x, const ::EventTypeSpec& y)
00034 { return x.eventClass < y.eventClass || x.eventClass == y.eventClass && x.eventKind < y.eventKind; }
00035 
00036 /**************************************************************************************************/
00037 
00038 namespace adobe {
00039 
00040 /**************************************************************************************************/
00041 
00042 template <typename T> struct event_param_type;
00043 
00044 #define ADOBE_EVENT_PARAM_TYPE_HELPER(type, event_type) \
00045 template <> struct event_param_type< type > { static const ::EventParamType value = event_type; }
00046 
00047 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFArrayRef,             typeCFArrayRef);
00048 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFDictionaryRef,        typeCFDictionaryRef);
00049 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFMutableArrayRef,      typeCFMutableArrayRef);
00050 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFMutableDictionaryRef, typeCFMutableDictionaryRef);
00051 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFMutableStringRef,     typeCFMutableStringRef);
00052 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFStringRef,            typeCFStringRef);
00053 ADOBE_EVENT_PARAM_TYPE_HELPER(::CFTypeRef,              typeCFTypeRef);
00054 ADOBE_EVENT_PARAM_TYPE_HELPER(::ControlPartCode,        typeControlPartCode);
00055 ADOBE_EVENT_PARAM_TYPE_HELPER(::DragRef,                typeDragRef);
00056 ADOBE_EVENT_PARAM_TYPE_HELPER(::EventMouseWheelAxis,    typeMouseWheelAxis);
00057 ADOBE_EVENT_PARAM_TYPE_HELPER(::EventTargetRef,         typeEventTargetRef);
00058 ADOBE_EVENT_PARAM_TYPE_HELPER(::HICommand,              typeHICommand);
00059 ADOBE_EVENT_PARAM_TYPE_HELPER(::HIPoint,                typeHIPoint);
00060 ADOBE_EVENT_PARAM_TYPE_HELPER(::SInt32,                 typeLongInteger);
00061 ADOBE_EVENT_PARAM_TYPE_HELPER(::TabletPointRec,         typeTabletPointRec);
00062 ADOBE_EVENT_PARAM_TYPE_HELPER(::TabletProximityRec,     typeTabletProximityRec);
00063 ADOBE_EVENT_PARAM_TYPE_HELPER(::UInt32,                 typeUInt32);
00064 ADOBE_EVENT_PARAM_TYPE_HELPER(::WindowRef,              typeWindowRef);
00065 ADOBE_EVENT_PARAM_TYPE_HELPER(bool,                     typeBoolean);
00066 
00067 #undef ADOBE_EVENT_PARAM_TYPE_HELPER
00068 
00069 /**************************************************************************************************/
00070 
00071 template < ::EventParamName name, typename T >
00072 bool get_event_parameter(::EventRef       the_event,
00073                          T&               value,
00074                          ::EventParamType type = event_param_type<T>::value)
00075 {
00076     ::EventParamType actual_type;
00077     ::UInt32         actual_size;
00078     ::OSStatus       err(::GetEventParameter(the_event,
00079                                              name,
00080                                              type,
00081                                              &actual_type,
00082                                              sizeof(T),
00083                                              &actual_size,
00084                                              &value));
00085 
00086     return err == noErr && actual_type == type && actual_size == sizeof(T);
00087 }
00088 
00089 /**************************************************************************************************/
00090 
00091 template < ::EventParamName name, typename T >
00092 bool set_event_parameter(::EventRef       the_event,
00093                          const T&         value,
00094                          ::EventParamType type = event_param_type<T>::value)
00095 {
00096     ::OSStatus err(::SetEventParameter(the_event,
00097                                        name,
00098                                        type,
00099                                        sizeof(T),
00100                                        &value));
00101 
00102     return err == noErr;
00103 }
00104 
00105 /**************************************************************************************************/
00106 
00107 template <typename Target>
00108 ::EventTargetRef get_event_target(Target target);
00109 
00110 #define ADOBE_GET_EVENT_TARGET_HELPER(type, proc) \
00111 template <> inline ::EventTargetRef get_event_target<>(type target) { return proc(target); }
00112 
00113 ADOBE_GET_EVENT_TARGET_HELPER(::WindowRef,      ::GetWindowEventTarget)
00114 ADOBE_GET_EVENT_TARGET_HELPER(::ControlRef,     ::GetControlEventTarget)
00115 ADOBE_GET_EVENT_TARGET_HELPER(::MenuRef,        ::GetMenuEventTarget)
00116 ADOBE_GET_EVENT_TARGET_HELPER(::EventTargetRef, ::EventTargetRef)
00117 
00118 #undef ADOBE_GET_EVENT_TARGET_HELPER
00119 
00120 /**************************************************************************************************/
00121 
00122 class event_handler_t : boost::noncopyable
00123 {
00124 public:
00125     typedef boost::function< ::OSStatus (::EventHandlerCallRef, ::EventRef) > monitor_proc_t;
00126 
00127     event_handler_t();
00128 
00129     template <typename Target>
00130     void install(Target target)
00131         { install(get_event_target(target)); }
00132 
00133     void install(::EventTargetRef target);
00134 
00135     void uninstall();
00136 
00137     bool is_installed() const
00138         { return ref_m.get() != 0; }
00139 
00140     void insert(const ::EventTypeSpec& event_spec);
00141 
00142     void insert(::UInt32 event_class, ::UInt32 event_kind)
00143         { ::EventTypeSpec event = { event_class, event_kind }; insert(event); }
00144 
00145     template <typename ForwardIterator>
00146     void insert(const ForwardIterator first, const ForwardIterator last)
00147     {
00148         typedef typename std::iterator_traits<ForwardIterator>::value_type        value_type;
00149         typedef typename std::iterator_traits<ForwardIterator>::iterator_category iterator_category;
00150 
00151         BOOST_STATIC_ASSERT((boost::is_convertible<value_type, ::EventTypeSpec>::value));
00152 
00153         insert(first, last, iterator_category());
00154     }
00155 
00156     void erase(const ::EventTypeSpec& event_spec);
00157 
00158     void erase(::UInt32 event_class, ::UInt32 event_kind)
00159         { ::EventTypeSpec event = { event_class, event_kind }; erase(event); }
00160 
00161     template <typename ForwardIterator>
00162     void erase(const ForwardIterator first, const ForwardIterator last)
00163     {
00164         typedef typename std::iterator_traits<ForwardIterator>::value_type        value_type;
00165         typedef typename std::iterator_traits<ForwardIterator>::iterator_category iterator_category;
00166 
00167         BOOST_STATIC_ASSERT((boost::is_convertible<value_type, ::EventTypeSpec>::value));
00168 
00169         erase(first, last, iterator_category());
00170     }
00171 
00172     monitor_proc_t monitor_proc_m; // no need to be private
00173 
00174 private:
00175     template <typename ForwardIterator>
00176     void insert(const ForwardIterator first,
00177                 const ForwardIterator last,
00178                 std::forward_iterator_tag);
00179 
00180     template <typename ForwardIterator>
00181     void insert(const ForwardIterator first,
00182                 const ForwardIterator last,
00183                 std::random_access_iterator_tag);
00184 
00185     template <typename ForwardIterator>
00186     void erase(const ForwardIterator first,
00187                const ForwardIterator last,
00188                std::forward_iterator_tag);
00189 
00190     template <typename ForwardIterator>
00191     void erase(const ForwardIterator first,
00192                const ForwardIterator last,
00193                std::random_access_iterator_tag);
00194 
00195     typedef adobe::auto_resource< ::EventHandlerRef > auto_ref_t;
00196     typedef adobe::auto_resource< ::EventHandlerUPP > auto_upp_t;
00197     typedef std::vector< ::EventTypeSpec >            event_type_set_t;
00198 
00199     auto_ref_t       ref_m;
00200     auto_upp_t       upp_m;
00201     event_type_set_t event_type_set_m;
00202 };
00203 
00204 /**************************************************************************************************/
00205 
00206 template <typename ForwardIterator>
00207 void event_handler_t::insert(const ForwardIterator first,
00208                              const ForwardIterator last,
00209                              std::forward_iterator_tag)
00210 {
00211     typedef void (event_handler_t::*proc_type)(const ::EventTypeSpec&);
00212 
00213     proc_type proc(&event_handler_t::insert);
00214 
00215     std::for_each(first, last, boost::bind(proc, boost::ref(*this), _1));
00216 }
00217 
00218 /**************************************************************************************************/
00219 
00220 template <typename ForwardIterator>
00221 void event_handler_t::insert(const ForwardIterator first,
00222                              const ForwardIterator last,
00223                              std::random_access_iterator_tag)
00224 {
00225     std::size_t n(std::distance(first, last));
00226 
00227     // this will fill the event_type_set_m vector with new
00228     // events without duplicating ones already present.
00229     event_type_set_m.insert(event_type_set_m.end(), first, last);
00230     adobe::sort(event_type_set_m);
00231     event_type_set_m.erase(adobe::unique(event_type_set_m), event_type_set_m.end());
00232 
00233     if (!is_installed())
00234         return;
00235 
00236     // now add the event set to the handler.
00237     ::ADOBE_REQUIRE_STATUS(::AddEventTypesToHandler(ref_m.get(), n, first));
00238 }
00239 
00240 /**************************************************************************************************/
00241 
00242 template <typename ForwardIterator>
00243 void event_handler_t::erase(const ForwardIterator first,
00244                             const ForwardIterator last,
00245                             std::forward_iterator_tag)
00246 {
00247     typedef void (event_handler_t::*proc_type)(const ::EventTypeSpec&);
00248 
00249     proc_type proc(&event_handler_t::erase);
00250 
00251     std::for_each(first, last, boost::bind(proc, boost::ref(*this), _1));
00252 }
00253 
00254 /**************************************************************************************************/
00255 
00256 template <typename ForwardIterator>
00257 void event_handler_t::erase(const ForwardIterator first,
00258                             const ForwardIterator last,
00259                             std::random_access_iterator_tag)
00260 {
00261     std::size_t n(std::distance(first, last));
00262 
00263     adobe::sort(event_type_set_m);
00264 
00265     for (ForwardIterator iter(first); iter != last; ++iter)
00266     {
00267         ForwardIterator found(adobe::lower_bound(event_type_set_m, *iter));
00268 
00269         if (found != event_type_set_m.end() && *found == *iter)
00270             event_type_set_m.erase(found);
00271     }
00272 
00273     if (!is_installed())
00274         return;
00275 
00276     // now remove the event set from the handler.
00277     ::ADOBE_REQUIRE_STATUS(::RemoveEventTypesFromHandler(ref_m.get(), n, first));
00278 }
00279 
00280 /**************************************************************************************************/
00281 
00282 } // namespace adobe
00283 
00284 /**************************************************************************************************/
00285 
00286 #endif
00287 
00288 /**************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google