DragAndDrop.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. GWEN
  3. Copyright (c) 2010 Facepunch Studios
  4. See license in Gwen.h
  5. */
  6. #include "Gwen/Gwen.h"
  7. #include "Gwen/DragAndDrop.h"
  8. #include "Gwen/Utility.h"
  9. #include "Gwen/Platform.h"
  10. using namespace Gwen;
  11. using namespace Gwen::DragAndDrop;
  12. DragAndDrop::Package* DragAndDrop::CurrentPackage = NULL;
  13. Gwen::Controls::Base* DragAndDrop::HoveredControl = NULL;
  14. Gwen::Controls::Base* DragAndDrop::SourceControl = NULL;
  15. static Gwen::Controls::Base* LastPressedControl = NULL;
  16. static Gwen::Controls::Base* NewHoveredControl = NULL;
  17. static Gwen::Point LastPressedPos;
  18. void DragAndDrop::ControlDeleted( Gwen::Controls::Base* pControl )
  19. {
  20. if ( SourceControl == pControl )
  21. {
  22. SourceControl = NULL;
  23. CurrentPackage = NULL;
  24. HoveredControl = NULL;
  25. LastPressedControl = NULL;
  26. }
  27. if ( LastPressedControl == pControl )
  28. LastPressedControl = NULL;
  29. if ( HoveredControl == pControl )
  30. HoveredControl = NULL;
  31. if ( NewHoveredControl == pControl )
  32. NewHoveredControl = NULL;
  33. }
  34. static int m_iMouseX = 0;
  35. static int m_iMouseY = 0;
  36. bool DragAndDrop::Start( Gwen::Controls::Base* pControl, Package* pPackage )
  37. {
  38. if ( CurrentPackage )
  39. {
  40. return false;
  41. }
  42. CurrentPackage = pPackage;
  43. SourceControl = pControl;
  44. return true;
  45. }
  46. bool OnDrop( int x, int y )
  47. {
  48. bool bSuccess = false;
  49. if ( DragAndDrop::HoveredControl )
  50. {
  51. DragAndDrop::HoveredControl->DragAndDrop_HoverLeave( DragAndDrop::CurrentPackage );
  52. bSuccess = DragAndDrop::HoveredControl->DragAndDrop_HandleDrop( DragAndDrop::CurrentPackage, x, y );
  53. }
  54. // Report back to the source control, to tell it if we've been successful.
  55. DragAndDrop::SourceControl->DragAndDrop_EndDragging( bSuccess, x, y );
  56. DragAndDrop::CurrentPackage = NULL;
  57. DragAndDrop::SourceControl = NULL;
  58. return true;
  59. }
  60. bool DragAndDrop::OnMouseButton( Gwen::Controls::Base* pHoveredControl, int x, int y, bool bDown )
  61. {
  62. if ( !bDown )
  63. {
  64. LastPressedControl = NULL;
  65. // Not carrying anything, allow normal actions
  66. if ( !CurrentPackage )
  67. return false;
  68. // We were carrying something, drop it.
  69. OnDrop( x, y );
  70. return true;
  71. }
  72. if ( !pHoveredControl ) return false;
  73. if ( !pHoveredControl->DragAndDrop_Draggable() ) return false;
  74. // Store the last clicked on control. Don't do anything yet,
  75. // we'll check it in OnMouseMoved, and if it moves further than
  76. // x pixels with the mouse down, we'll start to drag.
  77. LastPressedPos = Gwen::Point( x, y );
  78. LastPressedControl = pHoveredControl;
  79. return false;
  80. }
  81. bool ShouldStartDraggingControl( int x, int y )
  82. {
  83. // We're not holding a control down..
  84. if ( !LastPressedControl ) return false;
  85. // Not been dragged far enough
  86. int iLength = abs( x - LastPressedPos.x ) + abs( y - LastPressedPos.y );
  87. if ( iLength < 5 ) return false;
  88. // Create the dragging package
  89. DragAndDrop::CurrentPackage = LastPressedControl->DragAndDrop_GetPackage( LastPressedPos.x, LastPressedPos.y );
  90. // We didn't create a package!
  91. if ( !DragAndDrop::CurrentPackage )
  92. {
  93. LastPressedControl = NULL;
  94. DragAndDrop::SourceControl = NULL;
  95. return false;
  96. }
  97. // Now we're dragging something!
  98. DragAndDrop::SourceControl = LastPressedControl;
  99. Gwen::MouseFocus = NULL;
  100. LastPressedControl = NULL;
  101. DragAndDrop::CurrentPackage->drawcontrol = NULL;
  102. // Some controls will want to decide whether they should be dragged at that moment.
  103. // This function is for them (it defaults to true)
  104. if ( !DragAndDrop::SourceControl->DragAndDrop_ShouldStartDrag() )
  105. {
  106. DragAndDrop::SourceControl = NULL;
  107. DragAndDrop::CurrentPackage = NULL;
  108. return false;
  109. }
  110. DragAndDrop::SourceControl->DragAndDrop_StartDragging( DragAndDrop::CurrentPackage, LastPressedPos.x, LastPressedPos.y );
  111. return true;
  112. }
  113. void UpdateHoveredControl( Gwen::Controls::Base* pCtrl, int x, int y )
  114. {
  115. //
  116. // We use this global variable to represent our hovered control
  117. // That way, if the new hovered control gets deleted in one of the
  118. // Hover callbacks, we won't be left with a hanging pointer.
  119. // This isn't ideal - but it's minimal.
  120. //
  121. NewHoveredControl = pCtrl;
  122. // Nothing to change..
  123. if ( DragAndDrop::HoveredControl == NewHoveredControl ) return;
  124. // We changed - tell the old hovered control that it's no longer hovered.
  125. if ( DragAndDrop::HoveredControl && DragAndDrop::HoveredControl != NewHoveredControl )
  126. DragAndDrop::HoveredControl->DragAndDrop_HoverLeave( DragAndDrop::CurrentPackage );
  127. // If we're hovering where the control came from, just forget it.
  128. // By changing it to NULL here we're not going to show any error cursors
  129. // it will just do nothing if you drop it.
  130. if ( NewHoveredControl == DragAndDrop::SourceControl )
  131. NewHoveredControl = NULL;
  132. // Check to see if the new potential control can accept this type of package.
  133. // If not, ignore it and show an error cursor.
  134. while ( NewHoveredControl && !NewHoveredControl->DragAndDrop_CanAcceptPackage( DragAndDrop::CurrentPackage ) )
  135. {
  136. // We can't drop on this control, so lets try to drop
  137. // onto its parent..
  138. NewHoveredControl = NewHoveredControl->GetParent();
  139. // Its parents are dead. We can't drop it here.
  140. // Show the NO WAY cursor.
  141. if ( !NewHoveredControl )
  142. {
  143. Platform::SetCursor( CursorType::No );
  144. }
  145. }
  146. // Become out new hovered control
  147. DragAndDrop::HoveredControl = NewHoveredControl;
  148. // If we exist, tell us that we've started hovering.
  149. if ( DragAndDrop::HoveredControl )
  150. {
  151. DragAndDrop::HoveredControl->DragAndDrop_HoverEnter( DragAndDrop::CurrentPackage, x, y );
  152. }
  153. NewHoveredControl = NULL;
  154. }
  155. void DragAndDrop::OnMouseMoved( Gwen::Controls::Base* pHoveredControl, int x, int y )
  156. {
  157. // Always keep these up to date, they're used to draw the dragged control.
  158. m_iMouseX = x;
  159. m_iMouseY = y;
  160. // If we're not carrying anything, then check to see if we should
  161. // pick up from a control that we're holding down. If not, then forget it.
  162. if ( !CurrentPackage && !ShouldStartDraggingControl( x, y ) )
  163. return;
  164. // Swap to this new hovered control and notify them of the change.
  165. UpdateHoveredControl( pHoveredControl, x, y );
  166. if ( !HoveredControl ) return;
  167. // Update the hovered control every mouse move, so it can show where
  168. // the dropped control will land etc..
  169. HoveredControl->DragAndDrop_Hover( CurrentPackage, x, y );
  170. // Override the cursor - since it might have been set my underlying controls
  171. // Ideally this would show the 'being dragged' control. TODO
  172. Platform::SetCursor( CursorType::Normal );
  173. pHoveredControl->Redraw();
  174. }
  175. void DragAndDrop::RenderOverlay( Gwen::Controls::Canvas* /*pCanvas*/, Skin::Base* skin )
  176. {
  177. if ( !CurrentPackage ) return;
  178. if ( !CurrentPackage->drawcontrol ) return;
  179. Gwen::Point pntOld = skin->GetRender()->GetRenderOffset();
  180. skin->GetRender()->AddRenderOffset( Gwen::Rect( m_iMouseX - SourceControl->X() - CurrentPackage->holdoffset.x, m_iMouseY - SourceControl->Y() - CurrentPackage->holdoffset.y, 0, 0 ) );
  181. CurrentPackage->drawcontrol->DoRender( skin );
  182. skin->GetRender()->SetRenderOffset( pntOld );
  183. }