stlab.adobe.com Adobe Systems Incorporated

platform_drag_and_drop_data.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 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_CARBON_DRAG_AND_DROP_PLATFORM_DATA_HPP
00010 #define ADOBE_CARBON_DRAG_AND_DROP_PLATFORM_DATA_HPP
00011 
00012 /**************************************************************************************************/
00013 
00014 #include <adobe/config.hpp>
00015 
00016 #include <adobe/algorithm/find.hpp>
00017 #include <adobe/future/drag_and_drop_fwd.hpp>
00018 #include <adobe/future/macintosh_events.hpp>
00019 
00020 #include <boost/cstdint.hpp>
00021 #include <boost/function.hpp>
00022 #include <boost/next_prior.hpp>
00023 
00024 #include <cassert>
00025 #include <functional>
00026 
00027 /**************************************************************************************************/
00028 
00029 namespace adobe {
00030 
00031 /**************************************************************************************************/
00032 
00033 namespace implementation {
00034 
00035 /**************************************************************************************************/
00036 
00037 typedef std::pair< ::DragItemRef, ::UInt16 >                 drag_flavor_descriptor_t;
00038 typedef std::pair<drag_flavor_descriptor_t, boost::uint32_t> drag_flavor_uber_descriptor_t;
00039 
00040 template <typename InputIterator>
00041 drag_flavor_uber_descriptor_t find_drag_flavor(::DragRef     the_drag,
00042                                                InputIterator first,
00043                                                InputIterator last)
00044 {
00045     ::UInt16                 count(0);
00046     drag_flavor_descriptor_t result(0, 0);
00047 
00048     ::CountDragItems(the_drag, &count);
00049 
00050     for (::UInt16 cur_item_index(1); cur_item_index <= count; ++cur_item_index)
00051     {
00052         ::DragItemRef drag_item(0);
00053 
00054         if (::GetDragItemReferenceNumber(the_drag, cur_item_index, &drag_item) != noErr)
00055             continue;
00056 
00057         ::UInt16 flavor_count(0);
00058 
00059         if (::CountDragItemFlavors(the_drag, drag_item, &flavor_count) != noErr)
00060             continue;
00061 
00062         for (::UInt16 cur_flavor(1); cur_flavor <= flavor_count; ++cur_flavor)
00063         {
00064             ::FlavorType flavor_type(0);
00065 
00066             if (::GetFlavorType(the_drag, drag_item, cur_flavor, &flavor_type) == noErr)
00067             {
00068                 InputIterator found(std::find(first, last, flavor_type));
00069 
00070                 if (found != last)
00071                 {
00072                     result.first = drag_item;
00073                     result.second = cur_flavor;
00074 
00075                     return drag_flavor_uber_descriptor_t(result, *found);
00076                 }
00077             }
00078         }
00079     }
00080 
00081     return drag_flavor_uber_descriptor_t(result, flavor_invalid);
00082 }
00083 
00084 /**************************************************************************************************/
00085 
00086 template <typename InputIterator>
00087 drag_flavor_uber_descriptor_t find_drag_flavor(::EventRef    event,
00088                                                InputIterator first,
00089                                                InputIterator last)
00090 {
00091     ::DragRef the_drag(0);
00092 
00093     adobe::get_event_parameter<kEventParamDragRef>(event, the_drag);
00094 
00095     return find_drag_flavor(the_drag, first, last);
00096 }
00097 
00098 /**************************************************************************************************/
00099 
00100 inline drag_flavor_uber_descriptor_t find_drag_flavor(::DragRef the_drag, boost::uint32_t flavor)
00101 {
00102     boost::uint32_t* first(&flavor);
00103 
00104     return find_drag_flavor(the_drag, first, boost::next(first));
00105 }
00106 
00107 /**************************************************************************************************/
00108 
00109 inline drag_flavor_uber_descriptor_t find_drag_flavor(::EventRef event, boost::uint32_t flavor)
00110 {
00111     boost::uint32_t* first(&flavor);
00112 
00113     return find_drag_flavor(event, first, boost::next(first));
00114 }
00115 
00116 /**************************************************************************************************/
00117 
00118 any_regular_t flavor_extract_character_sequence(const dictionary_t& drag_parameters);
00119 
00120 /**************************************************************************************************/
00121 
00125 std::string file_url_to_path(const std::string& src);
00126 
00127 /**************************************************************************************************/
00128 
00129 template <typename T>
00130 struct converter_echo
00131 {
00132     typedef T source_type;
00133     typedef T dest_type;
00134 
00135     inline T convert(const T& x) const
00136     { return x; }
00137 };
00138 
00139 /**************************************************************************************************/
00140 
00141 } // namespace implementation
00142 
00143 /**************************************************************************************************/
00144 
00145 extern aggregate_name_t key_drag_ref;
00146 extern aggregate_name_t key_drag_item;
00147 extern aggregate_name_t key_flavor;
00148 
00149 /**************************************************************************************************/
00150 
00151 template <typename SourceType, typename TargetType>
00152 class drag_and_drop_handler_platform_data
00153 {
00154 public:
00155     typedef SourceType                                 source_type;
00156     typedef TargetType                                 target_type;
00157     typedef boost::function<void (const target_type&)> client_callback_proc_t;
00158 
00159     drag_and_drop_handler_platform_data() :
00160         chosen_flavor_m(flavor_invalid)
00161     {
00162         event_handler_m.monitor_proc_m =
00163             boost::bind(&drag_and_drop_handler_platform_data<source_type, target_type>::handle_event,
00164                         boost::ref(*this), _1, _2);
00165     }
00166 
00167     template <typename InputIterator>
00168     drag_and_drop_handler_platform_data(InputIterator first, InputIterator last) :
00169         flavor_set_m(first, last),
00170         chosen_flavor_m(flavor_invalid)
00171     {
00172         event_handler_m.monitor_proc_m =
00173             boost::bind(&drag_and_drop_handler_platform_data<source_type, target_type>::handle_event,
00174                         boost::ref(*this), _1, _2);
00175     }
00176 
00177     void init()
00178     {
00179         event_handler_m.insert(kEventClassControl, kEventControlDragEnter);
00180         event_handler_m.insert(kEventClassControl, kEventControlDragWithin);
00181         event_handler_m.insert(kEventClassControl, kEventControlDragLeave);
00182         event_handler_m.insert(kEventClassControl, kEventControlDragReceive);
00183 
00184         // REVISIT (fbrereto) : adobe::once this!
00185         // set up platform-specific flavor converters
00186         if (is_dnd_converter_registered<std::string>(flavor_file_url) == false)
00187         {
00188             register_dnd_extractor<std::string>(flavor_file_url,
00189                                                 &implementation::flavor_extract_character_sequence);
00190             register_dnd_extractor<std::string>(flavor_text,
00191                                                 &implementation::flavor_extract_character_sequence);
00192 
00193             register_dnd_converter<std::string>(flavor_file_url,
00194                                                 make_function_as_poly_drag_and_drop_converter
00195                                                     (&implementation::file_url_to_path));
00196             register_dnd_converter<std::string>(flavor_text,
00197                                                 poly_drag_and_drop_converter_t
00198                                                     (implementation::converter_echo<std::string>()));
00199         }
00200     }
00201 
00202     template <typename Client>
00203     void attach(const Client& control, const client_callback_proc_t& proc)
00204     {
00205         set_callback(proc);
00206 
00207         install(control);
00208     }
00209 
00210     void detach()
00211     {
00212         event_handler_m.uninstall();
00213     }
00214 
00215     void insert_flavor(boost::uint32_t flavor)
00216     {
00217         if (adobe::find(flavor_set_m, flavor) == flavor_set_m.end())
00218             flavor_set_m.push_back(flavor);
00219     }
00220 
00221     void erase_flavor(boost::uint32_t flavor)
00222     {
00223         flavor_set_m.erase(adobe::find(flavor_set_m, flavor));
00224     }
00225 
00226     void set_callback(const client_callback_proc_t& proc)
00227     {
00228         callback_m = proc;
00229     }
00230 
00231     void install(::HIViewRef control)
00232     {
00233         event_handler_m.install(control);
00234 
00235         ::SetControlDragTrackingEnabled(control, true);
00236     }
00237 
00238 private:
00239     ::OSStatus handle_event(::EventHandlerCallRef next, ::EventRef event);
00240 
00241     client_callback_proc_t       callback_m;
00242     std::vector<boost::uint32_t> flavor_set_m;
00243     boost::uint32_t              chosen_flavor_m;
00244     event_handler_t              event_handler_m;
00245 };
00246 
00247 /**************************************************************************************************/
00248 
00249 template <typename SourceType, typename TargetType>
00250 ::OSStatus
00251 drag_and_drop_handler_platform_data<SourceType, TargetType>::handle_event(::EventHandlerCallRef /*next*/,
00252                                                                           ::EventRef            event)
00253 {
00254    ::UInt32 event_class(::GetEventClass(event));
00255    ::UInt32 event_kind(::GetEventKind(event));
00256 
00257     assert(event_class == kEventClassControl);
00258 
00259     std::vector<boost::uint32_t> flavor_set(flavor_set_m.empty() ? registered_flavor_set() :
00260                                                                    flavor_set_m);
00261 
00262     if (flavor_set.empty())
00263         return eventNotHandledErr; // drag and drop is totally out of comission
00264 
00265     if (event_kind == kEventControlDragEnter)
00266     {
00267         if (callback_m.empty())
00268             return eventNotHandledErr;
00269     
00270         implementation::drag_flavor_uber_descriptor_t flavor =
00271             implementation::find_drag_flavor(event, flavor_set.begin(), flavor_set.end());
00272 
00273         if (flavor.second != flavor_invalid && callback_m.empty() == false)
00274         {
00275             adobe::set_event_parameter<kEventParamControlWouldAcceptDrop>(event, true);
00276 
00277             chosen_flavor_m = flavor.second;
00278         }
00279     }
00280     else if (event_kind == kEventControlDragWithin)
00281     {
00282         // REVISIT (fbrereto) : Fix me up
00283         ::SetThemeCursor(kThemeCopyArrowCursor);
00284     }
00285     else if (event_kind == kEventControlDragLeave)
00286     {
00287         // REVISIT (fbrereto) : Fix me up
00288         ::SetThemeCursor(kThemeArrowCursor);
00289     }
00290     else if (event_kind == kEventControlDragReceive)
00291     {
00292         ::DragRef the_drag(0);
00293 
00294         adobe::get_event_parameter<kEventParamDragRef>(event, the_drag);
00295 
00296         implementation::drag_flavor_uber_descriptor_t flavor =
00297             implementation::find_drag_flavor(the_drag, chosen_flavor_m);
00298 
00299         assert(flavor.second == chosen_flavor_m);
00300         assert(callback_m.empty() == false);
00301 
00302         dictionary_t drag_parameters;
00303 
00304         drag_parameters.insert(std::make_pair(key_drag_ref, the_drag));
00305         drag_parameters.insert(std::make_pair(key_drag_item, flavor.first.first));
00306         drag_parameters.insert(std::make_pair(key_flavor, chosen_flavor_m));
00307 
00308         source_type flavor_data(invoke_dnd_extractor<source_type>(chosen_flavor_m,
00309                                                                   drag_parameters));
00310 
00311         target_type converted_result =
00312             invoke_dnd_converter<target_type>(chosen_flavor_m, flavor_data);
00313 
00314         callback_m(converted_result);
00315 
00316         chosen_flavor_m = flavor_invalid;
00317     }
00318     else
00319     {
00320         throw std::runtime_error("Bad drag and drop event.");
00321     }
00322 
00323     return noErr;
00324 }
00325 
00326 /**************************************************************************************************/
00327 
00328 } // namespace adobe
00329 
00330 /**************************************************************************************************/
00331 
00332 // ADOBE_CARBON_DRAG_AND_DROP_HPP
00333 #endif
00334 
00335 /**************************************************************************************************/

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