00001
00002
00003
00004
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;
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
00228
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
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
00277 ::ADOBE_REQUIRE_STATUS(::RemoveEventTypesFromHandler(ref_m.get(), n, first));
00278 }
00279
00280
00281
00282 }
00283
00284
00285
00286 #endif
00287
00288