Slider: made slider positioner snap to values on drag

This isn't perfect, since it's very easy to move the mouse faster than the positioner is updated.
However, this is more a bug in GUI2 than the sliders.
This commit is contained in:
Charles Dang 2016-10-26 18:00:00 +11:00
parent 36ab1f9a5c
commit e2d3d585be
3 changed files with 66 additions and 1 deletions

View file

@ -166,6 +166,11 @@ public:
recalculate();
}
float get_pixels_per_step() const
{
return pixels_per_step_;
}
protected:
unsigned get_positioner_offset() const
{
@ -177,6 +182,11 @@ protected:
return positioner_length_;
}
tpoint get_mouse_position_last_move() const
{
return mouse_;
}
/**
* See @ref tcontrol::update_canvas.
*
@ -346,7 +356,7 @@ private:
* @param distance The distance moved, negative to begin, positive
* to end.
*/
void move_positioner(const int distance);
virtual void move_positioner(const int distance);
/** Inherited from tcontrol. */
void load_config_extra() override;

View file

@ -44,9 +44,12 @@ tslider::tslider()
, minimum_value_label_()
, maximum_value_label_()
, value_labels_()
, current_item_mouse_position_(0,0)
{
connect_signal<event::SDL_KEY_DOWN>(std::bind(
&tslider::signal_handler_sdl_key_down, this, _2, _3, _5));
connect_signal<event::LEFT_BUTTON_DOWN>(
std::bind(&tslider::signal_handler_left_button_down, this, _2, _3));
connect_signal<event::LEFT_BUTTON_UP>(
std::bind(&tslider::signal_handler_left_button_up, this, _2, _3));
}
@ -221,6 +224,35 @@ bool tslider::in_orthogonal_range(const tpoint& coordinate) const
return static_cast<size_t>(coordinate.x) < (get_width() - offset_after());
}
void tslider::update_current_item_mouse_position()
{
tpoint mouse = get_mouse_position();
mouse.x -= get_x();
mouse.y -= get_y();
current_item_mouse_position_ = mouse;
}
void tslider::move_positioner(const int)
{
const int distance_from_last_item = get_length_difference(current_item_mouse_position_, get_mouse_position_last_move());
if(std::abs(distance_from_last_item) >= get_pixels_per_step()) {
const int steps_traveled = distance_from_last_item / get_pixels_per_step();
set_item_position(get_item_position() + steps_traveled);
update_current_item_mouse_position();
child_callback_positioner_moved();
fire(event::NOTIFY_MODIFIED, *this, nullptr);
// positioner_moved_notifier_.notify();
update_canvas();
}
}
void tslider::update_canvas()
{
@ -273,6 +305,15 @@ void tslider::signal_handler_sdl_key_down(const event::tevent event,
}
}
void tslider::signal_handler_left_button_down(const event::tevent event, bool& handled)
{
DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
update_current_item_mouse_position();
handled = true;
}
void tslider::signal_handler_left_button_up(const event::tevent event,
bool& handled)
{

View file

@ -152,6 +152,9 @@ private:
return current.x - original.x;
}
/** Inherited from tscrollbar. */
void move_positioner(const int distance) override;
/** See @ref tcontrol::update_canvas. */
virtual void update_canvas() override;
@ -175,6 +178,15 @@ private:
*/
tlabel_creator value_labels_;
/**
* When initially pessing the positioner and every time a new value is chosen through dragging,
* this value is upda with the mouse position at the time. This allows the widget to track
* how far the mouse has moved since setting the last value.
*/
tpoint current_item_mouse_position_;
void update_current_item_mouse_position();
/** See @ref tcontrol::get_control_type. */
virtual const std::string& get_control_type() const override;
@ -191,6 +203,8 @@ private:
bool& handled,
const SDL_Keycode key);
void signal_handler_left_button_down(const event::tevent event, bool& handled);
// In this subclass, only used to grab keyboard focus -
// see tscrollbar class for more handling of this event.
void signal_handler_left_button_up(const event::tevent event,