37 #ifndef STAGE_INTERACT_DRAG_RELOCATE_CONTROLLER_H 38 #define STAGE_INTERACT_DRAG_RELOCATE_CONTROLLER_H 65 const gdouble DISTANCE_THRESHOLD = 5.0;
99 bool buttonPressed_ =
false;
101 bool isInFormation_ =
false;
102 gdouble anchorX_ = 0.0;
103 gdouble anchorY_ = 0.0;
112 REQUIRE (not isnil (cmdID));
114 widget.signal_button_press_event().connect(
115 sigc::mem_fun (*
this, &DragRelocateController::watchButton));
116 widget.signal_button_release_event().connect(
117 sigc::mem_fun (*
this, &DragRelocateController::watchButton));
118 widget.signal_motion_notify_event().connect(
119 [&, cmdID](GdkEventMotion* motion) ->
bool 128 watchButton (GdkEventButton* button_event) noexcept
130 REQUIRE (button_event);
131 if (GDK_BUTTON_PRESS == button_event->type)
132 buttonPressed_ =
true;
134 if (GDK_BUTTON_RELEASE == button_event->type)
136 buttonPressed_ =
false;
141 std::cerr <<
_Fmt{
"BUTT %s flag=%d"} % buttonPressed_ % button_event->type << std::endl;
149 if (not buttonPressed_)
151 REQUIRE (motion_event);
152 std::cerr <<
_Fmt{
"MOVE x=%3.1f y=%3.1f subject=%s"}
153 % motion_event->x_root
154 % motion_event->y_root
157 if (not isAnchored())
158 anchor (cmdID, subject, motion_event);
161 probeActivation (motion_event);
163 initGestureTracking(cmdID, subject);
168 doTrackGesture (motion_event);
185 return bool{subject_};
189 anchor (
Symbol cmdID,
Subject& subject, GdkEventMotion* motion_event)
191 REQUIRE (motion_event);
192 this->subject_ = & subject;
193 this->anchorX_ = motion_event->x_root;
194 this->anchorY_ = motion_event->y_root;
195 std::cerr <<
_Fmt{
"ANCHOR at x=%3.1f y=%3.1f ('%s')"}
203 probeActivation (GdkEventMotion* motion_event)
205 isInFormation_ = DISTANCE_THRESHOLD < abs (motion_event->x_root - anchorX_)
206 or DISTANCE_THRESHOLD < abs (motion_event->y_root - anchorY_);
216 doTrackGesture (GdkEventMotion* motion_event)
218 REQUIRE (motion_event);
219 gdouble deltaX = motion_event->x_root - this->anchorX_;
220 gdouble deltaY = motion_event->y_root - this->anchorY_;
222 observer_->updateOffset (deltaX, deltaY);
228 observer_->markGestureCompleted();
234 isInFormation_ =
false;
235 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.