FifeGUI 0.2.0
A C++ GUI library designed for games.
dragdrop.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-3-Clause
2// SPDX-FileCopyrightText: 2013 - 2026 Fifengine contributors
3
4// Corresponding header include
5#include <fifechan/dragdrop.hpp>
6
7// Standard library includes
8#include <memory>
9#include <utility>
10
11// Platform config include
12#include "fifechan/platform.hpp"
13
14// Project headers (subdirs before local)
15#include <fifechan/events/dragevent.hpp>
16#include <fifechan/graphics.hpp>
17#include <fifechan/listeners/droptargetlistener.hpp>
18#include <fifechan/widget.hpp>
19
20namespace fcn
21{
22
23 // Merge: provide DragPayload implementation here to avoid a separate translation unit.
24 DragPayload::DragPayload(std::shared_ptr<void> data) : m_data(std::move(data))
25 {
26 }
27
28 DragHandler::DragHandler(Gui* gui) : m_gui(gui)
29 {
30 }
31
33 {
34 return m_state;
35 }
36
38 {
39 return m_hoveredWidget;
40 }
41
43 {
44 return m_activeTarget;
45 }
46
48 {
49 return m_payload.get();
50 }
51
52 bool DragHandler::beginDrag(Widget* source, std::unique_ptr<DragPayload> payload, int mouseX, int mouseY)
53 {
54 if (m_state == DragState::Dragging || !payload) {
55 return false;
56 }
57 m_sourceWidget = source;
58 m_payload = std::move(payload);
59 m_state = DragState::Dragging;
60 m_lastMousePos = DragPoint(mouseX, mouseY);
61 return true;
62 }
63
64 bool DragHandler::beginDragFromWidget(Widget* /*source*/, int /*mouseX*/, int /*mouseY*/)
65 {
66 // Convenience: apps may implement IDragSource; left as TODO for implementation
67 return false;
68 }
69
70 void DragHandler::update(int mouseX, int mouseY)
71 {
72 if (m_state != DragState::Dragging) {
73 return;
74 }
75 m_lastMousePos = DragPoint(mouseX, mouseY);
76
77 if (m_gui == nullptr) {
78 return;
79 }
80
81 Widget* candidate = m_gui->getWidgetAt(mouseX, mouseY);
82
83 if (candidate != m_hoveredWidget) {
84 // Hover changed
85 m_hoveredWidget = candidate;
86 updateActiveTarget();
87 } else {
88 // same hovered widget, forward hover to active target if any
89 if (m_activeTarget != nullptr) {
90 int absX = 0;
91 int absY = 0;
92 m_activeTarget->getAbsolutePosition(absX, absY);
93 int const localX = mouseX - absX;
94 int const localY = mouseY - absY;
95 DragEvent hoverEvt(
96 m_activeTarget, m_payload.get(), DragEvent::Type::Hover, localX, localY, mouseX, mouseY);
97 m_activeTarget->distributeDragHover(hoverEvt);
98 }
99 }
100 }
101
102 DropResult DragHandler::drop(int /*mouseX*/, int /*mouseY*/)
103 {
104 if (m_state != DragState::Dragging) {
106 }
107 if (m_activeTarget != nullptr) {
108 int const mouseX = m_lastMousePos.x;
109 int const mouseY = m_lastMousePos.y;
110 int absX = 0;
111 int absY = 0;
112 m_activeTarget->getAbsolutePosition(absX, absY);
113 int const localX = mouseX - absX;
114 int const localY = mouseY - absY;
115 DragEvent dropEvt(m_activeTarget, m_payload.get(), DragEvent::Type::Drop, localX, localY, mouseX, mouseY);
116 m_activeTarget->distributeDragDrop(dropEvt);
117 m_payload.reset();
118 m_state = DragState::Idle;
119 m_activeTarget = nullptr;
121 }
122
123 m_payload.reset();
124 m_state = DragState::Idle;
126 }
127
129 {
130 if (m_state != DragState::Dragging) {
131 return;
132 }
133 // notify active target about leave if needed
134 if (m_activeTarget != nullptr) {
135 distributeDragLeave();
136 m_activeTarget = nullptr;
137 }
138 m_payload.reset();
139 m_state = DragState::Idle;
140 }
141
142 void DragHandler::render(Graphics& /*graphics*/)
143 {
144 // If a ghost renderer is supplied in m_renderConfig, call it here.
145 }
146
148 {
149 m_renderConfig = std::move(config);
150 }
151
153 {
154 return m_renderConfig;
155 }
156
158 {
159 m_modalWidget = modal;
160 }
162 {
163 return m_modalWidget;
164 }
165
166 Widget* DragHandler::findWidgetAt(Widget* root, int x, int y, bool mustBeVisible, bool mustBeEnabled)
167 {
168 // Defer to Widget's existing hit test - this helper is a convenience placeholder.
169 if (root == nullptr) {
170 return nullptr;
171 }
172 return root->getWidgetAt(x, y);
173 }
174
175 void DragHandler::distributeDragLeave()
176 {
177 if (m_activeTarget == nullptr || m_payload == nullptr) {
178 return;
179 }
180
181 int const mouseX = m_lastMousePos.x;
182 int const mouseY = m_lastMousePos.y;
183 int absX = 0;
184 int absY = 0;
185 m_activeTarget->getAbsolutePosition(absX, absY);
186 int const localX = mouseX - absX;
187 int const localY = mouseY - absY;
188 DragEvent leaveEvt(m_activeTarget, m_payload.get(), DragEvent::Type::Leave, localX, localY, mouseX, mouseY);
189 m_activeTarget->distributeDragLeave(leaveEvt);
190 }
191
192 void DragHandler::distributeDragEnter(Widget* candidate)
193 {
194 if (candidate == nullptr || m_payload == nullptr) {
195 return;
196 }
197
198 int const mouseX = m_lastMousePos.x;
199 int const mouseY = m_lastMousePos.y;
200 int absX = 0;
201 int absY = 0;
202 candidate->getAbsolutePosition(absX, absY);
203 int const localX = mouseX - absX;
204 int const localY = mouseY - absY;
205 DragEvent enterEvt(candidate, m_payload.get(), DragEvent::Type::Enter, localX, localY, mouseX, mouseY);
206 bool const accepted = candidate->distributeDragEnter(enterEvt);
207 if (accepted) {
208 m_activeTarget = candidate;
209 }
210 }
211
212 void DragHandler::updateActiveTarget()
213 {
214 // If we have an active target but no hovered widget, fire leave.
215 if (m_activeTarget != nullptr && m_hoveredWidget != m_activeTarget) {
216 distributeDragLeave();
217 m_activeTarget = nullptr;
218 }
219
220 // If we have a hovered widget and no active target, try to enter it.
221 if (m_hoveredWidget != nullptr && m_activeTarget == nullptr) {
222 distributeDragEnter(m_hoveredWidget);
223 }
224 }
225
226} // namespace fcn
Drag and drop event type container.
Definition dragevent.hpp:23
DragPayload const * getPayload() const
Get the active payload.
Definition dragdrop.cpp:47
DropResult drop(int mouseX, int mouseY)
Drop at the given position.
Definition dragdrop.cpp:102
void render(Graphics &graphics)
Render drag related visuals.
Definition dragdrop.cpp:142
Widget * getHoveredWidget() const
Get the widget currently hovered by the drag.
Definition dragdrop.cpp:37
Widget * getModalWidget() const
Get the modal widget if any.
Definition dragdrop.cpp:161
bool beginDrag(Widget *source, std::unique_ptr< DragPayload > payload, int mouseX, int mouseY)
Start a drag with the given payload.
Definition dragdrop.cpp:52
Widget * getActiveDropTarget() const
Get the active drop target widget.
Definition dragdrop.cpp:42
void update(int mouseX, int mouseY)
Update drag position.
Definition dragdrop.cpp:70
DragRenderConfig const & getRenderConfig() const
Get the current render config.
Definition dragdrop.cpp:152
void setModalWidget(Widget *modal)
Set a modal widget to ignore hits.
Definition dragdrop.cpp:157
DragHandler(Gui *gui)
Create a drag handler for a GUI.
Definition dragdrop.cpp:28
static Widget * findWidgetAt(Widget *root, int x, int y, bool mustBeVisible=true, bool mustBeEnabled=true)
Find a widget at the given coordinates.
Definition dragdrop.cpp:166
void setRenderConfig(DragRenderConfig config)
Set how drag visuals are rendered.
Definition dragdrop.cpp:147
DragState getState() const
Get the current drag state.
Definition dragdrop.cpp:32
void cancel()
Cancel the current drag.
Definition dragdrop.cpp:128
bool beginDragFromWidget(Widget *source, int mouseX, int mouseY)
Start a drag from a widget without explicit payload.
Definition dragdrop.cpp:64
Container for arbitrary data carried during a drag operation.
Definition dragdrop.hpp:83
DragPayload(std::shared_ptr< void > data=nullptr)
Construct a payload.
Definition dragdrop.cpp:24
T * get() const
Get raw pointer to stored data.
Definition dragdrop.hpp:108
Abstract interface providing primitive drawing functions (lines, rectangles, etc.).
Definition graphics.hpp:58
The central GUI manager.
Definition gui.hpp:108
Abstract base class defining the common behavior, properties, and lifecycle of all GUI elements.
Definition widget.hpp:55
Widget * getWidgetAt(int x, int y)
Gets a widget at a certain position in the widget.
Definition widget.hpp:1274
void distributeDragLeave(DragEvent &event)
Distribute a drag leave event to listeners.
Definition widget.cpp:939
virtual void getAbsolutePosition(int &x, int &y) const
Gets the absolute position on the screen for the widget.
Definition widget.cpp:977
Used replacement tokens by configure_file():
DropResult
Result returned after attempting to drop payload onto a target.
Definition dragdrop.hpp:65
@ Accepted
Target accepted the drop.
Definition dragdrop.hpp:67
@ Cancelled
Drop was cancelled before delivery.
Definition dragdrop.hpp:73
DragState
State of the drag controller.
Definition dragdrop.hpp:53
@ Dragging
A drag operation is in progress.
Definition dragdrop.hpp:58
@ Idle
No drag is active.
Definition dragdrop.hpp:55
Simple 2D integer point used for drag offsets and positions.
Definition dragdrop.hpp:30
int y
Y coordinate.
Definition dragdrop.hpp:39
int x
X coordinate.
Definition dragdrop.hpp:34
Configuration for how drag visuals are rendered.
Definition dragdrop.hpp:183