| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- /*
- GWEN
- Copyright (c) 2010 Facepunch Studios
- See license in Gwen.h
- */
- #include "Gwen/Gwen.h"
- #include "Gwen/DragAndDrop.h"
- #include "Gwen/Utility.h"
- #include "Gwen/Platform.h"
- using namespace Gwen;
- using namespace Gwen::DragAndDrop;
- DragAndDrop::Package* DragAndDrop::CurrentPackage = NULL;
- Gwen::Controls::Base* DragAndDrop::HoveredControl = NULL;
- Gwen::Controls::Base* DragAndDrop::SourceControl = NULL;
- static Gwen::Controls::Base* LastPressedControl = NULL;
- static Gwen::Controls::Base* NewHoveredControl = NULL;
- static Gwen::Point LastPressedPos;
- void DragAndDrop::ControlDeleted(Gwen::Controls::Base* pControl)
- {
- if (SourceControl == pControl)
- {
- SourceControl = NULL;
- CurrentPackage = NULL;
- HoveredControl = NULL;
- LastPressedControl = NULL;
- }
- if (LastPressedControl == pControl)
- LastPressedControl = NULL;
- if (HoveredControl == pControl)
- HoveredControl = NULL;
- if (NewHoveredControl == pControl)
- NewHoveredControl = NULL;
- }
- static int m_iMouseX = 0;
- static int m_iMouseY = 0;
- bool DragAndDrop::Start(Gwen::Controls::Base* pControl, Package* pPackage)
- {
- if (CurrentPackage)
- {
- return false;
- }
- CurrentPackage = pPackage;
- SourceControl = pControl;
- return true;
- }
- bool OnDrop(int x, int y)
- {
- bool bSuccess = false;
- if (DragAndDrop::HoveredControl)
- {
- DragAndDrop::HoveredControl->DragAndDrop_HoverLeave(DragAndDrop::CurrentPackage);
- bSuccess = DragAndDrop::HoveredControl->DragAndDrop_HandleDrop(DragAndDrop::CurrentPackage, x, y);
- }
- // Report back to the source control, to tell it if we've been successful.
- DragAndDrop::SourceControl->DragAndDrop_EndDragging(bSuccess, x, y);
- DragAndDrop::CurrentPackage = NULL;
- DragAndDrop::SourceControl = NULL;
- return true;
- }
- bool DragAndDrop::OnMouseButton(Gwen::Controls::Base* pHoveredControl, int x, int y, bool bDown)
- {
- if (!bDown)
- {
- LastPressedControl = NULL;
- // Not carrying anything, allow normal actions
- if (!CurrentPackage)
- return false;
- // We were carrying something, drop it.
- OnDrop(x, y);
- return true;
- }
- if (!pHoveredControl) return false;
- if (!pHoveredControl->DragAndDrop_Draggable()) return false;
- // Store the last clicked on control. Don't do anything yet,
- // we'll check it in OnMouseMoved, and if it moves further than
- // x pixels with the mouse down, we'll start to drag.
- LastPressedPos = Gwen::Point(x, y);
- LastPressedControl = pHoveredControl;
- return false;
- }
- bool ShouldStartDraggingControl(int x, int y)
- {
- // We're not holding a control down..
- if (!LastPressedControl) return false;
- // Not been dragged far enough
- int iLength = abs(x - LastPressedPos.x) + abs(y - LastPressedPos.y);
- if (iLength < 5) return false;
- // Create the dragging package
- DragAndDrop::CurrentPackage = LastPressedControl->DragAndDrop_GetPackage(LastPressedPos.x, LastPressedPos.y);
- // We didn't create a package!
- if (!DragAndDrop::CurrentPackage)
- {
- LastPressedControl = NULL;
- DragAndDrop::SourceControl = NULL;
- return false;
- }
- // Now we're dragging something!
- DragAndDrop::SourceControl = LastPressedControl;
- Gwen::MouseFocus = NULL;
- LastPressedControl = NULL;
- DragAndDrop::CurrentPackage->drawcontrol = NULL;
- // Some controls will want to decide whether they should be dragged at that moment.
- // This function is for them (it defaults to true)
- if (!DragAndDrop::SourceControl->DragAndDrop_ShouldStartDrag())
- {
- DragAndDrop::SourceControl = NULL;
- DragAndDrop::CurrentPackage = NULL;
- return false;
- }
- DragAndDrop::SourceControl->DragAndDrop_StartDragging(DragAndDrop::CurrentPackage, LastPressedPos.x, LastPressedPos.y);
- return true;
- }
- void UpdateHoveredControl(Gwen::Controls::Base* pCtrl, int x, int y)
- {
- //
- // We use this global variable to represent our hovered control
- // That way, if the new hovered control gets deleted in one of the
- // Hover callbacks, we won't be left with a hanging pointer.
- // This isn't ideal - but it's minimal.
- //
- NewHoveredControl = pCtrl;
- // Nothing to change..
- if (DragAndDrop::HoveredControl == NewHoveredControl) return;
- // We changed - tell the old hovered control that it's no longer hovered.
- if (DragAndDrop::HoveredControl && DragAndDrop::HoveredControl != NewHoveredControl)
- DragAndDrop::HoveredControl->DragAndDrop_HoverLeave(DragAndDrop::CurrentPackage);
- // If we're hovering where the control came from, just forget it.
- // By changing it to NULL here we're not going to show any error cursors
- // it will just do nothing if you drop it.
- if (NewHoveredControl == DragAndDrop::SourceControl)
- NewHoveredControl = NULL;
- // Check to see if the new potential control can accept this type of package.
- // If not, ignore it and show an error cursor.
- while (NewHoveredControl && !NewHoveredControl->DragAndDrop_CanAcceptPackage(DragAndDrop::CurrentPackage))
- {
- // We can't drop on this control, so lets try to drop
- // onto its parent..
- NewHoveredControl = NewHoveredControl->GetParent();
- // Its parents are dead. We can't drop it here.
- // Show the NO WAY cursor.
- if (!NewHoveredControl)
- {
- Platform::SetCursor(CursorType::No);
- }
- }
- // Become out new hovered control
- DragAndDrop::HoveredControl = NewHoveredControl;
- // If we exist, tell us that we've started hovering.
- if (DragAndDrop::HoveredControl)
- {
- DragAndDrop::HoveredControl->DragAndDrop_HoverEnter(DragAndDrop::CurrentPackage, x, y);
- }
- NewHoveredControl = NULL;
- }
- void DragAndDrop::OnMouseMoved(Gwen::Controls::Base* pHoveredControl, int x, int y)
- {
- // Always keep these up to date, they're used to draw the dragged control.
- m_iMouseX = x;
- m_iMouseY = y;
- // If we're not carrying anything, then check to see if we should
- // pick up from a control that we're holding down. If not, then forget it.
- if (!CurrentPackage && !ShouldStartDraggingControl(x, y))
- return;
- // Swap to this new hovered control and notify them of the change.
- UpdateHoveredControl(pHoveredControl, x, y);
- if (!HoveredControl) return;
- // Update the hovered control every mouse move, so it can show where
- // the dropped control will land etc..
- HoveredControl->DragAndDrop_Hover(CurrentPackage, x, y);
- // Override the cursor - since it might have been set my underlying controls
- // Ideally this would show the 'being dragged' control. TODO
- Platform::SetCursor(CursorType::Normal);
- pHoveredControl->Redraw();
- }
- void DragAndDrop::RenderOverlay(Gwen::Controls::Canvas* /*pCanvas*/, Skin::Base* skin)
- {
- if (!CurrentPackage) return;
- if (!CurrentPackage->drawcontrol) return;
- Gwen::Point pntOld = skin->GetRender()->GetRenderOffset();
- skin->GetRender()->AddRenderOffset(Gwen::Rect(m_iMouseX - SourceControl->X() - CurrentPackage->holdoffset.x, m_iMouseY - SourceControl->Y() - CurrentPackage->holdoffset.y, 0, 0));
- CurrentPackage->drawcontrol->DoRender(skin);
- skin->GetRender()->SetRenderOffset(pntOld);
- }
|