46 #ifndef STAGE_INTERACT_DRAG_RELOCATE_CONTROLLER_H 47 #define STAGE_INTERACT_DRAG_RELOCATE_CONTROLLER_H 74 const gdouble DISTANCE_THRESHOLD = 5.0;
108 bool buttonPressed_ =
false;
110 bool isInFormation_ =
false;
111 gdouble anchorX_ = 0.0;
112 gdouble anchorY_ = 0.0;
121 REQUIRE (not isnil (cmdID));
123 widget.signal_button_press_event().connect(
124 sigc::mem_fun (*
this, &DragRelocateController::watchButton));
125 widget.signal_button_release_event().connect(
126 sigc::mem_fun (*
this, &DragRelocateController::watchButton));
127 widget.signal_motion_notify_event().connect(
128 [&, cmdID](GdkEventMotion* motion) ->
bool 137 watchButton (GdkEventButton* button_event) noexcept
139 REQUIRE (button_event);
140 if (GDK_BUTTON_PRESS == button_event->type)
141 buttonPressed_ =
true;
143 if (GDK_BUTTON_RELEASE == button_event->type)
145 buttonPressed_ =
false;
150 std::cerr <<
_Fmt{
"BUTT %s flag=%d"} % buttonPressed_ % button_event->type << std::endl;
158 if (not buttonPressed_)
160 REQUIRE (motion_event);
161 std::cerr <<
_Fmt{
"MOVE x=%3.1f y=%3.1f subject=%s"}
162 % motion_event->x_root
163 % motion_event->y_root
166 if (not isAnchored())
167 anchor (cmdID, subject, motion_event);
170 probeActivation (motion_event);
172 initGestureTracking(cmdID, subject);
177 doTrackGesture (motion_event);
194 return bool{subject_};
198 anchor (
Symbol cmdID,
Subject& subject, GdkEventMotion* motion_event)
200 REQUIRE (motion_event);
201 this->subject_ = & subject;
202 this->anchorX_ = motion_event->x_root;
203 this->anchorY_ = motion_event->y_root;
204 std::cerr <<
_Fmt{
"ANCHOR at x=%3.1f y=%3.1f ('%s')"}
212 probeActivation (GdkEventMotion* motion_event)
214 isInFormation_ = DISTANCE_THRESHOLD < abs (motion_event->x_root - anchorX_)
215 or DISTANCE_THRESHOLD < abs (motion_event->y_root - anchorY_);
225 doTrackGesture (GdkEventMotion* motion_event)
227 REQUIRE (motion_event);
228 gdouble deltaX = motion_event->x_root - this->anchorX_;
229 gdouble deltaY = motion_event->y_root - this->anchorY_;
231 observer_->updateOffset (deltaX, deltaY);
237 observer_->markGestureCompleted();
243 isInFormation_ =
false;
244 anchorX_ = anchorY_ = 0.0;
Abstraction: a component to watch, maintain and guide UI state.
bool maybeActivate(Symbol cmdID, Subject &subject, GdkEventMotion *motion_event)
Gesture detection state logic.
#define ON_EXCEPTION_RETURN(_VAL_, _OP_DESCR_)
convenience shortcut to catch and absorb any exception, then returning a default value instead...
const size_t OBSERVER_BUFF_SIZ
heuristics for sizing the inline buffer where the Subject will construct its Observer/Adapter ...
A front-end for using printf-style formatting.
Abstract foundation for context dependent UI interactions.
Token or Atom with distinct identity.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
Lumiera GTK UI implementation root.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Helper allowing type erasure while holding the actual object inline.
virtual void buildGestureObserver(Symbol cmdID, Buffer)=0
prompt the Subject to build an Observer for the gesture in formation
virtual Gtk::Widget & exposeWidget()=0
the exposed widget can be used for wiring signal handlers
Gesture controller for dragging objects within the Timeline display.
A set of basic GTK includes for the UI.
Abstraction: support for binding command invocation into an UI context.
Role-Interface: the Subject of Interaction.
void linkTrigger(Subject &subject, Symbol cmdID) override
Hook up a trigger signal to initiate a specific interaction gesture.