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