Flu_DND.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // $Id: Flu_DND.cpp,v 1.21 2004/08/18 11:06:38 jbryan Exp $
  2. /***************************************************************
  3. * FLU - FLTK Utility Widgets
  4. * Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University
  5. *
  6. * This file and its content is protected by a software license.
  7. * You should have received a copy of this license with this file.
  8. * If not, please contact the Ohio Supercomputer Center immediately:
  9. * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212
  10. *
  11. ***************************************************************/
  12. #include <stdio.h>
  13. #include "FLU/Flu_DND.H"
  14. Flu_DND_Event :: Flu_DND_Event()
  15. {
  16. _text = _dataType = 0;
  17. clear();
  18. }
  19. Flu_DND_Event :: ~Flu_DND_Event()
  20. {
  21. clear();
  22. }
  23. void Flu_DND_Event :: clear()
  24. {
  25. // reset everything
  26. objUnderMouse = false;
  27. dragging = false;
  28. exit = false;
  29. if(_text) free(_text); _text = 0;
  30. if(_dataType) free(_dataType); _dataType = 0;
  31. _data = 0;
  32. _grab_x = _grab_y = _drop_x = _drop_y = 0;
  33. }
  34. Flu_DND_Event Flu_DND::dndEvent;
  35. Flu_DND :: Flu_DND( const char *thisType )
  36. {
  37. // initialize everything
  38. nTypes = 0;
  39. _thisType = strdup( thisType );
  40. dnd_allow_text( false );
  41. dnd_callback( 0 );
  42. allowDragging = allowDropping = true;
  43. }
  44. Flu_DND :: ~Flu_DND()
  45. {
  46. // free all the stored types
  47. if( _thisType )
  48. free( _thisType );
  49. for( int i = 0; i < nTypes; i++ )
  50. free( allowedTypes[i] );
  51. }
  52. void Flu_DND :: dnd_allow_type( const char *t )
  53. {
  54. if( nTypes >= FLU_DND_MAX_TYPES )
  55. return;
  56. allowedTypes[nTypes++] = strdup( t );
  57. }
  58. bool Flu_DND :: dnd_type_allowed( const char *t ) const
  59. {
  60. for( int i = 0; i < nTypes; i++ )
  61. if( strcmp( allowedTypes[i], t ) == 0 )
  62. return true;
  63. return false;
  64. }
  65. void Flu_DND :: dnd_grab( void *data, const char *type )
  66. {
  67. dndEvent.clear();
  68. if( !allowDragging || !data )
  69. return;
  70. // remember the event
  71. //printf( "dnd_grab %s %X\n", _thisType, this );
  72. dndEvent.dragging = true;
  73. dndEvent.exit = false;
  74. dndEvent.objUnderMouse = this;
  75. dndEvent._data = data;
  76. dndEvent._dataType = strdup( type );
  77. dndEvent._grab_x = Fl::event_x();
  78. dndEvent._grab_y = Fl::event_y();
  79. // start the fltk system-wide DND
  80. Fl::copy( " ", 1, 0 );
  81. Fl::dnd();
  82. }
  83. void Flu_DND :: on_dnd_enter()
  84. {
  85. }
  86. void Flu_DND :: on_dnd_leave()
  87. {
  88. }
  89. void Flu_DND :: on_dnd_drop( const Flu_DND_Event *e )
  90. {
  91. }
  92. void Flu_DND :: on_dnd_release()
  93. {
  94. }
  95. bool Flu_DND :: on_dnd_drag( int X, int Y )
  96. {
  97. return true;
  98. }
  99. int Flu_DND :: dnd_handle( int event )
  100. {
  101. // if dnd is on, then only DND events are generated
  102. // but, there appears to be a bug in fltk where an FL_NO_EVENT is generated if the mouse
  103. // is released when outside of any fltk widget. so, if we detect the NO_EVENT, and we are still
  104. // dragging, then we need to process it as a release
  105. if( dndEvent.dragging && event == FL_NO_EVENT )
  106. {
  107. if( dndEvent.exit ) // not in any widget
  108. {
  109. // trash the event and return
  110. //printf( "exit %s %X\n", _thisType, this );
  111. dndEvent.clear();
  112. return 1;
  113. }
  114. // otherwise the NO_EVENT is inside a widget. i don't know why a NO_EVENT is generated
  115. // since the event is inside a widget. but, whatever. at any rate, this object should process
  116. // it as a paste, only if it is the object the mouse is over (as tracked by dndEvent.objUnderMouse)
  117. if( dndEvent.objUnderMouse == this )
  118. {
  119. //printf( "FL_NO_EVENT %s %X\n", _thisType, this );
  120. event = FL_PASTE;
  121. }
  122. }
  123. //printf( "event %d %s %X\n", event, _thisType, this );
  124. switch( event )
  125. {
  126. case FL_DND_DRAG:
  127. {
  128. //printf( "FL_DND_DRAG %s %X\n", _thisType, this );
  129. // if we receive a drag event and we are not holding data, then it must be
  130. // from an fltk text widget
  131. // remember where the dragging occurs and check if it's ok for us
  132. // to drop the item here
  133. dndEvent.dragging = true;
  134. dndEvent.objUnderMouse = this;
  135. dndEvent._drop_x = Fl::event_x();
  136. dndEvent._drop_y = Fl::event_y();
  137. return ok2drop();
  138. }
  139. case FL_DND_RELEASE:
  140. //printf( "FL_DND_RELEASE %s %X\n", _thisType, this );
  141. on_dnd_release();
  142. return ok2drop();
  143. //case FL_UNFOCUS:
  144. //printf( "FL_UNFOCUS %s %X\n", _thisType, this );
  145. //return 1;
  146. //case FL_FOCUS:
  147. //printf( "FL_FOCUS %s %X\n", _thisType, this );
  148. //return 1;
  149. case FL_DND_ENTER:
  150. //printf( "FL_DND_ENTER %s %X\n", _thisType, this );
  151. dndEvent.exit = false;
  152. dndEvent.objUnderMouse = this;
  153. dndEvent._drop_x = Fl::event_x();
  154. dndEvent._drop_y = Fl::event_y();
  155. if( ok2drop() ) // if it's ok to drop, then it's ok to enter
  156. {
  157. on_dnd_enter();
  158. return 1;
  159. }
  160. else
  161. return 0;
  162. case FL_DND_LEAVE:
  163. //printf( "FL_DND_LEAVE %s %X\n", _thisType, this );
  164. dndEvent.exit = true;
  165. dndEvent.objUnderMouse = NULL;
  166. on_dnd_leave();
  167. return 1;
  168. case FL_PASTE:
  169. //printf( "FL_PASTE %s %X\n", _thisType, this );
  170. on_dnd_release();
  171. // if the mouse is not inside a DND widget, then there's nothing to do
  172. if( dndEvent.exit )
  173. {
  174. dndEvent.clear();
  175. return 0;
  176. }
  177. //if( dndEvent.objUnderMouse != this )
  178. //return 0;
  179. // if there's no data, then this paste is generated from an FLTK text DND event
  180. if( !dndEvent.data() )
  181. {
  182. dndEvent.clear();
  183. dndEvent._text = strdup( Fl::event_text() );
  184. }
  185. dndEvent._drop_x = Fl::event_x();
  186. dndEvent._drop_y = Fl::event_y();
  187. // if it's ok to drop, then call the drop processing members
  188. if( true )
  189. {
  190. if( dndCallback )
  191. dndCallback( &dndEvent, dndCallbackData );
  192. on_dnd_drop(&dndEvent);
  193. dndEvent.clear();
  194. return 1;
  195. }
  196. else
  197. {
  198. dndEvent.clear();
  199. return 0;
  200. }
  201. default:
  202. // just in case
  203. //printf( "event: %d\n", event );
  204. if( dndEvent.exit )
  205. {
  206. on_dnd_release();
  207. dndEvent.clear();
  208. }
  209. break;
  210. }
  211. return 0;
  212. }
  213. bool Flu_DND :: ok2drop()
  214. {
  215. if( !allowDropping )
  216. return false;
  217. if( dndEvent.data() ) // see if the dnd event is valid
  218. {
  219. // check if the source type is allowed by this class
  220. if( !dnd_type_allowed( dndEvent.data_type() ) )
  221. return false;
  222. }
  223. else if( !allowTextEvents ) // event is a normal FLTK text dnd event
  224. return false;
  225. return on_dnd_drag( Fl::event_x(), Fl::event_y() );
  226. }