Blame synfig-studio/src/gui/selectdraghelper.h

Rodolfo Ribeiro Gomes b6afe5
/* === S Y N F I G ========================================================= */
Rodolfo Ribeiro Gomes b6afe5
/*!	\file selectdraghelper.h
Rodolfo Ribeiro Gomes b6afe5
**	\brief Helper to allow to select and drag items in a widget, eg. DrawingArea
Rodolfo Ribeiro Gomes b6afe5
**
Rodolfo Ribeiro Gomes b6afe5
**	$Id$
Rodolfo Ribeiro Gomes b6afe5
**
Rodolfo Ribeiro Gomes b6afe5
**	\legal
Rodolfo Ribeiro Gomes b6afe5
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
Rodolfo Ribeiro Gomes b6afe5
**	Copyright (c) 2019 Rodolfo R Gomes
Rodolfo Ribeiro Gomes b6afe5
**
Rodolfo Ribeiro Gomes b6afe5
**	This package is free software; you can redistribute it and/or
Rodolfo Ribeiro Gomes b6afe5
**	modify it under the terms of the GNU General Public License as
Rodolfo Ribeiro Gomes b6afe5
**	published by the Free Software Foundation; either version 2 of
Rodolfo Ribeiro Gomes b6afe5
**	the License, or (at your option) any later version.
Rodolfo Ribeiro Gomes b6afe5
**
Rodolfo Ribeiro Gomes b6afe5
**	This package is distributed in the hope that it will be useful,
Rodolfo Ribeiro Gomes b6afe5
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Rodolfo Ribeiro Gomes b6afe5
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Rodolfo Ribeiro Gomes b6afe5
**	General Public License for more details.
Rodolfo Ribeiro Gomes b6afe5
**	\endlegal
Rodolfo Ribeiro Gomes b6afe5
*/
Rodolfo Ribeiro Gomes b6afe5
/* ========================================================================= */
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
#ifndef SYNFIG_STUDIO_SELECTDRAGHELPER_H
Rodolfo Ribeiro Gomes b6afe5
#define SYNFIG_STUDIO_SELECTDRAGHELPER_H
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
#include <vector></vector>
Rodolfo Ribeiro Gomes b6afe5
#include <cairomm context.h=""></cairomm>
Rodolfo Ribeiro Gomes b6afe5
#include <gdkmm rectangle.h=""></gdkmm>
Rodolfo Ribeiro Gomes b6afe5
#include <gdkmm event.h=""></gdkmm>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
#include <etl handle=""></etl>
Rodolfo Ribeiro Gomes b6afe5
#include <synfigapp canvasinterface.h=""></synfigapp>
Rodolfo Ribeiro Gomes b6afe5
#include "app.h"
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
namespace synfigapp {
Rodolfo Ribeiro Gomes b6afe5
namespace Action {
Rodolfo Ribeiro Gomes b6afe5
class PassiveGrouper;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
namespace studio {
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
class SelectDragHelper
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
public:
Rodolfo Ribeiro Gomes e409b5
	enum State {POINTER_NONE, POINTER_DRAGGING, POINTER_SELECTING, POINTER_PANNING};
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
private:
Rodolfo Ribeiro Gomes b6afe5
	etl::handle<synfigapp::canvasinterface> canvas_interface;</synfigapp::canvasinterface>
Rodolfo Ribeiro Gomes b6afe5
	const std::string drag_action_name;
Rodolfo Ribeiro Gomes b6afe5
	synfigapp::Action::PassiveGrouper *action_group_drag;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	bool made_dragging_move;
Rodolfo Ribeiro Gomes b6afe5
	bool dragging_started_by_key;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	T hovered_item;
Rodolfo Ribeiro Gomes b6afe5
	std::vector<t> selected_items;</t>
Rodolfo Ribeiro Gomes b6afe5
	const T* active_item;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	State pointer_state;
Rodolfo Ribeiro Gomes b6afe5
	int pointer_tracking_start_x, pointer_tracking_start_y;
Rodolfo Ribeiro Gomes e409b5
	int last_pointer_x, last_pointer_y;
Rodolfo Ribeiro Gomes cb03b1
	Gdk::Point active_item_start_position;
Rodolfo Ribeiro Gomes e409b5
Rodolfo Ribeiro Gomes e409b5
	void start_tracking_pointer(int x, int y);
Rodolfo Ribeiro Gomes e409b5
	void start_tracking_pointer(double x, double y);
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	void start_dragging(const T *pointed_item);
Rodolfo Ribeiro Gomes b6afe5
	void finish_dragging();
Rodolfo Ribeiro Gomes b6afe5
	void cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	bool process_key_press_event(GdkEventKey *event);
Rodolfo Ribeiro Gomes b6afe5
	bool process_key_release_event(GdkEventKey *event);
Rodolfo Ribeiro Gomes 2bfcd3
	bool process_button_double_press_event(GdkEventButton *event);
Rodolfo Ribeiro Gomes b6afe5
	bool process_button_press_event(GdkEventButton *event);
Rodolfo Ribeiro Gomes b6afe5
	bool process_button_release_event(GdkEventButton *event);
Rodolfo Ribeiro Gomes b6afe5
	bool process_motion_event(GdkEventMotion *event);
Rodolfo Ribeiro Gomes b6afe5
	bool process_scroll_event(GdkEventScroll *event);
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_selection_changed_;</void>
Rodolfo Ribeiro Gomes 170e0b
	sigc::signal<void> signal_hovered_item_changed_;</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_zoom_in_requested_;</void>
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_zoom_out_requested_;</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_scroll_up_requested_;</void>
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_scroll_down_requested_;</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes e409b5
	sigc::signal<void, int="" int,=""> signal_panning_requested_;</void,>
Rodolfo Ribeiro Gomes e409b5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_redraw_needed_;</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_focus_requested_;</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_drag_started_;</void>
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_drag_canceled_;</void>
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void> signal_drag_finished_;</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes 8ab677
	sigc::signal<void, const="" gdk::point="" int,="" t&,="" unsigned=""> signal_item_clicked_;</void,>
Rodolfo Ribeiro Gomes 2bfcd3
	sigc::signal<void, const="" gdk::point="" int,="" t&,="" unsigned=""> signal_item_double_clicked_;</void,>
Rodolfo Ribeiro Gomes 8ab677
Rodolfo Ribeiro Gomes 6d55aa
	bool box_selection_enabled = true;
Rodolfo Ribeiro Gomes 6d55aa
	bool multiple_selection_enabled = true;
Rodolfo Ribeiro Gomes 6d55aa
	bool scroll_enabled = false;
Rodolfo Ribeiro Gomes 6d55aa
	bool zoom_enabled = false;
Rodolfo Ribeiro Gomes 6d55aa
	bool pan_enabled = false;
Rodolfo Ribeiro Gomes 6d55aa
	bool drag_enabled = true;
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes b6afe5
public:
Rodolfo Ribeiro Gomes b6afe5
	SelectDragHelper(const char *drag_action_name);
Rodolfo Ribeiro Gomes b6afe5
	virtual ~SelectDragHelper() {delete action_group_drag;}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	void set_canvas_interface(etl::handle<synfigapp::canvasinterface> canvas_interface);</synfigapp::canvasinterface>
Rodolfo Ribeiro Gomes b6afe5
	etl::handle<synfigapp::canvasinterface>& get_canvas_interface();</synfigapp::canvasinterface>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes 233b37
	/// The item whose pointer/mouse is hovering over
Rodolfo Ribeiro Gomes b6afe5
	const T& get_hovered_item() const;
Rodolfo Ribeiro Gomes 233b37
	/// Provides a list of selected items
Rodolfo Ribeiro Gomes b6afe5
	std::vector<t*> get_selected_items();</t*>
Rodolfo Ribeiro Gomes 233b37
	/// Check if an item is selected
Rodolfo Ribeiro Gomes b6afe5
	bool is_selected(const T& item) const;
Rodolfo Ribeiro Gomes 233b37
	/// The selected item user started to drag
Rodolfo Ribeiro Gomes 8e579f
	const T* get_active_item() const;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	State get_state() const;
Rodolfo Ribeiro Gomes 233b37
	/// The point where user clicked
Rodolfo Ribeiro Gomes b6afe5
	void get_initial_tracking_point(int &px, int &py) const;
Rodolfo Ribeiro Gomes cb03b1
	/// The point where active item was initially placed
Rodolfo Ribeiro Gomes cb03b1
	void get_active_item_initial_point(int &px, int &py) const;
Rodolfo Ribeiro Gomes cb03b1
Rodolfo Ribeiro Gomes cb03b1
	//! Retrieve the position of a given item
Rodolfo Ribeiro Gomes cb03b1
	//! @param[out] position the location the provided item
Rodolfo Ribeiro Gomes cb03b1
	virtual void get_item_position(const T &item, Gdk::Point &position) = 0;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes 233b37
	//! Retrieve the item placed at a point
Rodolfo Ribeiro Gomes 233b37
	//! @param[out] item the item in the given position
Rodolfo Ribeiro Gomes 233b37
	//! @return true if an item was found, false otherwise
Rodolfo Ribeiro Gomes 233b37
	virtual bool find_item_at_position(int pos_x, int pos_y, T & item) = 0;
Rodolfo Ribeiro Gomes 233b37
Rodolfo Ribeiro Gomes 233b37
	//! Retrieve all items inside a rectangular area
Rodolfo Ribeiro Gomes 233b37
	//! @param rect the rectangle area
Rodolfo Ribeiro Gomes 233b37
	//! @param[out] the list of items contained inside rect
Rodolfo Ribeiro Gomes 233b37
	//! @return true if any item was found, false otherwise
Rodolfo Ribeiro Gomes b6afe5
	virtual bool find_items_in_rect(Gdk::Rectangle rect, std::vector<t> & list) = 0;</t>
Rodolfo Ribeiro Gomes 233b37
Rodolfo Ribeiro Gomes 233b37
	//! Retrieve all items in collection
Rodolfo Ribeiro Gomes 233b37
	//! @param[out] items the complete item list
Rodolfo Ribeiro Gomes b6afe5
	virtual void get_all_items(std::vector<t> & items) = 0;</t>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	void drag_to(int pointer_x, int pointer_y);
Rodolfo Ribeiro Gomes 233b37
	//! Do drag selected items
Rodolfo Ribeiro Gomes 233b37
	/*!
Rodolfo Ribeiro Gomes 233b37
	 * @param total_dx total pointer/mouse displacement along x-axis since drag start
Rodolfo Ribeiro Gomes 233b37
	 * @param total_dy total pointer/mouse displacement along y-axis since drag start
Rodolfo Ribeiro Gomes 233b37
	 * @param by_keys if the dragging action is being done by key pressing
Rodolfo Ribeiro Gomes 233b37
	*/
Rodolfo Ribeiro Gomes 233b37
	virtual void delta_drag(int total_dx, int total_dy, bool by_keys) = 0;
Rodolfo Ribeiro Gomes 233b37
Rodolfo Ribeiro Gomes 233b37
	//! Call this method to process mouse/pointer/keyboard events to map them
Rodolfo Ribeiro Gomes 233b37
	//! to select/drag/panning/zoom/scrolling behaviours
Rodolfo Ribeiro Gomes b6afe5
	bool process_event(GdkEvent *event);
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	void refresh();
Rodolfo Ribeiro Gomes b6afe5
	void clear();
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	void select_all_items();
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes 6d55aa
	bool get_box_selection_enabled() const;
Rodolfo Ribeiro Gomes 6d55aa
	void set_box_selection_enabled(bool value);
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
	bool get_multiple_selection_enabled() const;
Rodolfo Ribeiro Gomes 6d55aa
	void set_multiple_selection_enabled(bool value);
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
	bool get_scroll_enabled() const;
Rodolfo Ribeiro Gomes 6d55aa
	void set_scroll_enabled(bool value);
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
	bool get_zoom_enabled() const;
Rodolfo Ribeiro Gomes 6d55aa
	void set_zoom_enabled(bool value);
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
	bool get_pan_enabled() const;
Rodolfo Ribeiro Gomes 6d55aa
	void set_pan_enabled(bool value);
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
	bool get_drag_enabled() const;
Rodolfo Ribeiro Gomes 6d55aa
	void set_drag_enabled(bool value);
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_selection_changed() { return signal_selection_changed_; }</void>
Rodolfo Ribeiro Gomes 170e0b
	sigc::signal<void>& signal_hovered_item_changed() { return signal_hovered_item_changed_; }</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_zoom_in_requested() { return signal_zoom_in_requested_; }</void>
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_zoom_out_requested() { return signal_zoom_out_requested_; }</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_scroll_up_requested() { return signal_scroll_up_requested_; }</void>
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_scroll_down_requested() { return signal_scroll_down_requested_; }</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes e409b5
	sigc::signal<void, int="" int,="">& signal_panning_requested() { return signal_panning_requested_; }</void,>
Rodolfo Ribeiro Gomes e409b5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_redraw_needed() { return signal_redraw_needed_; }</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_focus_requested() { return signal_focus_requested_; }</void>
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_drag_started() { return signal_drag_started_; }</void>
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_drag_canceled() { return signal_drag_canceled_; }</void>
Rodolfo Ribeiro Gomes b6afe5
	sigc::signal<void>& signal_drag_finished() { return signal_drag_finished_; }</void>
Rodolfo Ribeiro Gomes 8ab677
Rodolfo Ribeiro Gomes 8ab677
	sigc::signal<void, const="" gdk::point="" int,="" t&,="" unsigned="">& signal_item_clicked() { return signal_item_clicked_; }</void,>
Rodolfo Ribeiro Gomes 2bfcd3
	sigc::signal<void, const="" gdk::point="" int,="" t&,="" unsigned="">& signal_item_double_clicked() { return signal_item_double_clicked_; }</void,>
Rodolfo Ribeiro Gomes b6afe5
};
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
SelectDragHelper<t>::SelectDragHelper(const char* drag_action_name)</t>
Rodolfo Ribeiro Gomes b6afe5
	: drag_action_name(drag_action_name), action_group_drag(nullptr), active_item(nullptr), pointer_state(POINTER_NONE)
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::set_canvas_interface(etl::handle<synfigapp::canvasinterface> canvas_interface)</synfigapp::canvasinterface></t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	if (pointer_state == POINTER_DRAGGING) {
Rodolfo Ribeiro Gomes b6afe5
		cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	this->canvas_interface = canvas_interface;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
etl::handle<synfigapp::canvasinterface>& SelectDragHelper<t>::get_canvas_interface()</t></synfigapp::canvasinterface>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	return canvas_interface;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
const T& SelectDragHelper<t>::get_hovered_item() const</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	return hovered_item;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
std::vector<t*> SelectDragHelper<t>::get_selected_items()</t></t*>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	const size_t nselection = selected_items.size();
Rodolfo Ribeiro Gomes b6afe5
	std::vector<t*> r;</t*>
Rodolfo Ribeiro Gomes b6afe5
	r.reserve(nselection);
Rodolfo Ribeiro Gomes b6afe5
	for (size_t n = 0; n < nselection; n++)
Rodolfo Ribeiro Gomes b6afe5
		r.push_back(&selected_items[n]);
Rodolfo Ribeiro Gomes b6afe5
	return r;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
bool SelectDragHelper<t>::is_selected(const T& item) const {</t>
Rodolfo Ribeiro Gomes b6afe5
	return std::find(selected_items.begin(), selected_items.end(), item) != selected_items.end();
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes 8e579f
const T* SelectDragHelper<t>::get_active_item() const {</t>
Rodolfo Ribeiro Gomes 8e579f
	return active_item;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
typename SelectDragHelper<t>::State SelectDragHelper<t>::get_state() const</t></t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	return pointer_state;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::get_initial_tracking_point(int& px, int& py) const</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	px = pointer_tracking_start_x;
Rodolfo Ribeiro Gomes b6afe5
	py = pointer_tracking_start_y;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes cb03b1
template<class t=""></class>
Rodolfo Ribeiro Gomes cb03b1
void SelectDragHelper<t>::get_active_item_initial_point(int& px, int& py) const</t>
Rodolfo Ribeiro Gomes cb03b1
{
Rodolfo Ribeiro Gomes cb03b1
	px = active_item_start_position.get_x();
Rodolfo Ribeiro Gomes cb03b1
	py = active_item_start_position.get_y();
Rodolfo Ribeiro Gomes cb03b1
}
Rodolfo Ribeiro Gomes cb03b1
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
bool
Rodolfo Ribeiro Gomes b6afe5
SelectDragHelper<t>::process_event(GdkEvent *event)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	switch(event->type) {
Rodolfo Ribeiro Gomes b91e47
	case GDK_SCROLL:
Rodolfo Ribeiro Gomes b91e47
		return process_scroll_event(&event->scroll);
Rodolfo Ribeiro Gomes b6afe5
	case GDK_MOTION_NOTIFY:
Rodolfo Ribeiro Gomes b6afe5
		return process_motion_event(&event->motion);
Rodolfo Ribeiro Gomes 2bfcd3
	case GDK_2BUTTON_PRESS:
Rodolfo Ribeiro Gomes 2bfcd3
		return process_button_double_press_event(&event->button);
Rodolfo Ribeiro Gomes b6afe5
	case GDK_BUTTON_PRESS:
Rodolfo Ribeiro Gomes b6afe5
		return process_button_press_event(&event->button);
Rodolfo Ribeiro Gomes b6afe5
	case GDK_BUTTON_RELEASE:
Rodolfo Ribeiro Gomes b6afe5
		return process_button_release_event(&event->button);
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_RELEASE:
Rodolfo Ribeiro Gomes b6afe5
		return process_key_release_event(&event->key);
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_PRESS:
Rodolfo Ribeiro Gomes b6afe5
		return process_key_press_event(&event->key);
Rodolfo Ribeiro Gomes b6afe5
	default:
Rodolfo Ribeiro Gomes b6afe5
		break;
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	return false;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
bool SelectDragHelper<t>::process_key_press_event(GdkEventKey* event)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	switch (event->keyval) {
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Up:
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Down: {
Rodolfo Ribeiro Gomes 6d55aa
		if (!drag_enabled)
Rodolfo Ribeiro Gomes 6d55aa
			return false;
Rodolfo Ribeiro Gomes b6afe5
		if (selected_items.size() == 0)
Rodolfo Ribeiro Gomes b6afe5
			break;
Rodolfo Ribeiro Gomes b6afe5
		if (pointer_state != POINTER_DRAGGING) {
Rodolfo Ribeiro Gomes b6afe5
			start_dragging(&selected_items.front());
Rodolfo Ribeiro Gomes b6afe5
			dragging_started_by_key = true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
		int delta = 1;
Rodolfo Ribeiro Gomes b6afe5
		if (event->state & GDK_SHIFT_MASK)
Rodolfo Ribeiro Gomes b6afe5
			delta = 10;
Rodolfo Ribeiro Gomes b6afe5
		if (event->keyval == GDK_KEY_Up)
Rodolfo Ribeiro Gomes b6afe5
			delta = -delta;
Rodolfo Ribeiro Gomes b6afe5
		delta_drag(0, delta, true);
Rodolfo Ribeiro Gomes b6afe5
		return true;
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Left:
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Right: {
Rodolfo Ribeiro Gomes 6d55aa
		if (!drag_enabled)
Rodolfo Ribeiro Gomes 6d55aa
			return false;
Rodolfo Ribeiro Gomes b6afe5
		if (selected_items.size() == 0)
Rodolfo Ribeiro Gomes b6afe5
			break;
Rodolfo Ribeiro Gomes b6afe5
		if (pointer_state != POINTER_DRAGGING) {
Rodolfo Ribeiro Gomes b6afe5
			start_dragging(&selected_items.front());
Rodolfo Ribeiro Gomes b6afe5
			dragging_started_by_key = true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
		int delta = 1;
Rodolfo Ribeiro Gomes b6afe5
		if (event->state & GDK_SHIFT_MASK)
Rodolfo Ribeiro Gomes b6afe5
			delta *= 10;
Rodolfo Ribeiro Gomes b6afe5
		if (event->keyval == GDK_KEY_Left)
Rodolfo Ribeiro Gomes b6afe5
			delta = -delta;
Rodolfo Ribeiro Gomes b6afe5
		delta_drag(delta, 0, true);
Rodolfo Ribeiro Gomes b6afe5
		return true;
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_a: {
Rodolfo Ribeiro Gomes b6afe5
		if ((event->state & Gdk::CONTROL_MASK) == Gdk::CONTROL_MASK) {
Rodolfo Ribeiro Gomes b6afe5
			// ctrl a
Rodolfo Ribeiro Gomes b6afe5
			cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
			select_all_items();
Rodolfo Ribeiro Gomes b6afe5
			return true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
		break;
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_d: {
Rodolfo Ribeiro Gomes b6afe5
		if ((event->state & Gdk::CONTROL_MASK) == Gdk::CONTROL_MASK) {
Rodolfo Ribeiro Gomes b6afe5
			// ctrl d
Rodolfo Ribeiro Gomes b6afe5
			cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
			selected_items.clear();
Rodolfo Ribeiro Gomes b6afe5
			signal_redraw_needed().emit();
Rodolfo Ribeiro Gomes b6afe5
			signal_selection_changed().emit();
Rodolfo Ribeiro Gomes b6afe5
			return true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
		break;
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	return false;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
bool SelectDragHelper<t>::process_key_release_event(GdkEventKey* event)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	switch (event->keyval) {
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Escape: {
Rodolfo Ribeiro Gomes b6afe5
		// cancel/undo current action
Rodolfo Ribeiro Gomes b6afe5
		if (pointer_state != POINTER_NONE) {
Rodolfo Ribeiro Gomes b6afe5
			cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
			pointer_state = POINTER_NONE;
Rodolfo Ribeiro Gomes b6afe5
			signal_redraw_needed().emit();
Rodolfo Ribeiro Gomes b6afe5
			return true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Up:
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Down:
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Left:
Rodolfo Ribeiro Gomes b6afe5
	case GDK_KEY_Right: {
Rodolfo Ribeiro Gomes b6afe5
		if (pointer_state == POINTER_DRAGGING) {
Rodolfo Ribeiro Gomes b6afe5
			if (dragging_started_by_key)
Rodolfo Ribeiro Gomes b6afe5
				finish_dragging();
Rodolfo Ribeiro Gomes b6afe5
			dragging_started_by_key = false;
Rodolfo Ribeiro Gomes b6afe5
			return true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	return false;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes 2bfcd3
bool SelectDragHelper<t>::process_button_double_press_event(GdkEventButton* event)</t>
Rodolfo Ribeiro Gomes 2bfcd3
{
Rodolfo Ribeiro Gomes 2bfcd3
	T pointed_item;
Rodolfo Ribeiro Gomes 2bfcd3
	find_item_at_position(event->x, event->y, pointed_item);
Rodolfo Ribeiro Gomes 2bfcd3
	if (pointed_item.is_valid()) {
Rodolfo Ribeiro Gomes 2bfcd3
		int pointer_x = std::trunc(event->x);
Rodolfo Ribeiro Gomes 2bfcd3
		int pointer_y = std::trunc(event->y);
Rodolfo Ribeiro Gomes 2bfcd3
		signal_item_double_clicked().emit(pointed_item, event->button, Gdk::Point(pointer_x, pointer_y));
Rodolfo Ribeiro Gomes 2bfcd3
		return true;
Rodolfo Ribeiro Gomes 2bfcd3
	}
Rodolfo Ribeiro Gomes 2bfcd3
	return false;
Rodolfo Ribeiro Gomes 2bfcd3
}
Rodolfo Ribeiro Gomes 2bfcd3
Rodolfo Ribeiro Gomes 2bfcd3
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
bool SelectDragHelper<t>::process_button_press_event(GdkEventButton* event)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes 8ab677
	bool some_action_done = false;
Rodolfo Ribeiro Gomes 8ab677
Rodolfo Ribeiro Gomes b6afe5
	signal_focus_requested().emit();
Rodolfo Ribeiro Gomes b6afe5
	if (event->button == 3) {
Rodolfo Ribeiro Gomes b6afe5
		// cancel/undo current action
Rodolfo Ribeiro Gomes b6afe5
		if (pointer_state != POINTER_NONE) {
Rodolfo Ribeiro Gomes b6afe5
			cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
			pointer_state = POINTER_NONE;
Rodolfo Ribeiro Gomes b6afe5
			signal_redraw_needed().emit();
Rodolfo Ribeiro Gomes 8ab677
			some_action_done = true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
	} else if (event->button == 1) {
Rodolfo Ribeiro Gomes b6afe5
		if (pointer_state == POINTER_NONE) {
Rodolfo Ribeiro Gomes e409b5
			start_tracking_pointer(event->x, event->y);
Rodolfo Ribeiro Gomes b6afe5
			T pointed_item;
Rodolfo Ribeiro Gomes b6afe5
			find_item_at_position(pointer_tracking_start_x, pointer_tracking_start_y, pointed_item);
Rodolfo Ribeiro Gomes b6afe5
			if (pointed_item.is_valid()) {
Rodolfo Ribeiro Gomes b6afe5
				auto already_selection_it = std::find(selected_items.begin(), selected_items.end(), pointed_item);
Rodolfo Ribeiro Gomes b6afe5
				bool is_already_selected = already_selection_it != selected_items.end();
Rodolfo Ribeiro Gomes b6afe5
				bool using_key_modifiers = (event->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) != 0;
Rodolfo Ribeiro Gomes 6d55aa
				if (using_key_modifiers && box_selection_enabled && multiple_selection_enabled) {
Rodolfo Ribeiro Gomes b6afe5
					pointer_state = POINTER_SELECTING;
Rodolfo Ribeiro Gomes b6afe5
				} else {
Rodolfo Ribeiro Gomes b6afe5
					T* pointed_item_ptr = nullptr;
Rodolfo Ribeiro Gomes b6afe5
					if (is_already_selected) {
Rodolfo Ribeiro Gomes b6afe5
						pointed_item_ptr = &*already_selection_it;
Rodolfo Ribeiro Gomes b6afe5
					} else {
Rodolfo Ribeiro Gomes b6afe5
						selected_items.clear();
Rodolfo Ribeiro Gomes b6afe5
						selected_items.push_back(pointed_item);
Rodolfo Ribeiro Gomes b6afe5
						pointed_item_ptr = &selected_items.front();
Rodolfo Ribeiro Gomes b6afe5
						signal_selection_changed().emit();
Rodolfo Ribeiro Gomes b6afe5
					}
Rodolfo Ribeiro Gomes 6d55aa
					if (drag_enabled) {
Rodolfo Ribeiro Gomes 6d55aa
						start_dragging(pointed_item_ptr);
Rodolfo Ribeiro Gomes 6d55aa
						dragging_started_by_key = false;
Rodolfo Ribeiro Gomes 6d55aa
						pointer_state = POINTER_DRAGGING;
Rodolfo Ribeiro Gomes 6d55aa
					}
Rodolfo Ribeiro Gomes b6afe5
				}
Rodolfo Ribeiro Gomes 6d55aa
				some_action_done = true;
Rodolfo Ribeiro Gomes b6afe5
			} else {
Rodolfo Ribeiro Gomes 6d55aa
				if (box_selection_enabled && multiple_selection_enabled) {
Rodolfo Ribeiro Gomes 6d55aa
					pointer_state = POINTER_SELECTING;
Rodolfo Ribeiro Gomes 6d55aa
					some_action_done = true;
Rodolfo Ribeiro Gomes 6d55aa
				}
Rodolfo Ribeiro Gomes b6afe5
			}
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes e409b5
	} else if (event->button == 2) {
Rodolfo Ribeiro Gomes e409b5
		if (pointer_state == POINTER_DRAGGING)
Rodolfo Ribeiro Gomes e409b5
			finish_dragging();
Rodolfo Ribeiro Gomes e409b5
		start_tracking_pointer(event->x, event->y);
Rodolfo Ribeiro Gomes e409b5
		pointer_state = POINTER_PANNING;
Rodolfo Ribeiro Gomes 6d55aa
		some_action_done = true;
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes 8ab677
	{
Rodolfo Ribeiro Gomes 8ab677
		T pointed_item;
Rodolfo Ribeiro Gomes 8ab677
		find_item_at_position(event->x, event->y, pointed_item);
Rodolfo Ribeiro Gomes 8ab677
		if (pointed_item.is_valid()) {
Rodolfo Ribeiro Gomes 8ab677
			int pointer_x = std::trunc(event->x);
Rodolfo Ribeiro Gomes 8ab677
			int pointer_y = std::trunc(event->y);
Rodolfo Ribeiro Gomes 8ab677
			signal_item_clicked().emit(pointed_item, event->button, Gdk::Point(pointer_x, pointer_y));
Rodolfo Ribeiro Gomes 8ab677
		}
Rodolfo Ribeiro Gomes 8ab677
	}
Rodolfo Ribeiro Gomes 8ab677
	return some_action_done;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
bool SelectDragHelper<t>::process_button_release_event(GdkEventButton* event)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	int pointer_x = std::trunc(event->x);
Rodolfo Ribeiro Gomes b6afe5
	int pointer_y = std::trunc(event->y);
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	if (event->button == 1) {
Rodolfo Ribeiro Gomes b6afe5
		bool selection_changed = false;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
		if (pointer_state == POINTER_SELECTING) {
Rodolfo Ribeiro Gomes b6afe5
			std::vector<t> circled_items;</t>
Rodolfo Ribeiro Gomes b6afe5
			int x0 = std::min(pointer_tracking_start_x, pointer_x);
Rodolfo Ribeiro Gomes b6afe5
			int width = std::abs(pointer_tracking_start_x - pointer_x);
Rodolfo Ribeiro Gomes b6afe5
			int y0 = std::min(pointer_tracking_start_y, pointer_y);
Rodolfo Ribeiro Gomes b6afe5
			int height = std::abs(pointer_tracking_start_y - pointer_y);
Rodolfo Ribeiro Gomes b6afe5
			if (width < 1 && height < 1) {
Rodolfo Ribeiro Gomes b6afe5
				width = 1;
Rodolfo Ribeiro Gomes b6afe5
				height = 1;
Rodolfo Ribeiro Gomes b6afe5
			}
Rodolfo Ribeiro Gomes b6afe5
			Gdk::Rectangle rect(x0, y0, width, height);
Rodolfo Ribeiro Gomes b6afe5
			bool found = find_items_in_rect(rect, circled_items);
Rodolfo Ribeiro Gomes b6afe5
			if (!found) {
Rodolfo Ribeiro Gomes b6afe5
				if (selected_items.size() > 0 && (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) == 0) {
Rodolfo Ribeiro Gomes b6afe5
					selection_changed = true;
Rodolfo Ribeiro Gomes b6afe5
					selected_items.clear();
Rodolfo Ribeiro Gomes b6afe5
				}
Rodolfo Ribeiro Gomes b6afe5
			} else {
Rodolfo Ribeiro Gomes b6afe5
				if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) {
Rodolfo Ribeiro Gomes b6afe5
					// toggle selection status of each point in rectangle
Rodolfo Ribeiro Gomes b6afe5
					for (const T& cp : circled_items) {
Rodolfo Ribeiro Gomes b6afe5
						auto already_selection_it = std::find(selected_items.begin(), selected_items.end(), cp);
Rodolfo Ribeiro Gomes b6afe5
						bool already_selected = already_selection_it != selected_items.end();
Rodolfo Ribeiro Gomes b6afe5
						if (already_selected) {
Rodolfo Ribeiro Gomes b6afe5
							selected_items.erase(already_selection_it);
Rodolfo Ribeiro Gomes b6afe5
							selection_changed = true;
Rodolfo Ribeiro Gomes b6afe5
						} else {
Rodolfo Ribeiro Gomes b6afe5
							selected_items.push_back(cp);
Rodolfo Ribeiro Gomes b6afe5
							selection_changed = true;
Rodolfo Ribeiro Gomes b6afe5
						}
Rodolfo Ribeiro Gomes b6afe5
					}
Rodolfo Ribeiro Gomes b6afe5
				} else if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) {
Rodolfo Ribeiro Gomes b6afe5
					// add to selection, if it aren't yet
Rodolfo Ribeiro Gomes b6afe5
					for (const T& cp : circled_items) {
Rodolfo Ribeiro Gomes b6afe5
						auto already_selection_it = std::find(selected_items.begin(), selected_items.end(), cp);
Rodolfo Ribeiro Gomes b6afe5
						bool already_selected = already_selection_it != selected_items.end();
Rodolfo Ribeiro Gomes b6afe5
						if (!already_selected) {
Rodolfo Ribeiro Gomes b6afe5
							selected_items.push_back(cp);
Rodolfo Ribeiro Gomes b6afe5
							selection_changed = true;
Rodolfo Ribeiro Gomes b6afe5
						}
Rodolfo Ribeiro Gomes b6afe5
					}
Rodolfo Ribeiro Gomes b6afe5
				} else {
Rodolfo Ribeiro Gomes b6afe5
					selected_items.clear();
Rodolfo Ribeiro Gomes b6afe5
					selected_items = circled_items;
Rodolfo Ribeiro Gomes b6afe5
					selection_changed = true;
Rodolfo Ribeiro Gomes b6afe5
				}
Rodolfo Ribeiro Gomes b6afe5
			}
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
		else if (pointer_state == POINTER_DRAGGING) {
Rodolfo Ribeiro Gomes b6afe5
			if (event->button == 1) {
Rodolfo Ribeiro Gomes b6afe5
				if (made_dragging_move)
Rodolfo Ribeiro Gomes b6afe5
					finish_dragging();
Rodolfo Ribeiro Gomes b6afe5
				else {
Rodolfo Ribeiro Gomes b6afe5
					T saved_active_point = *active_item;
Rodolfo Ribeiro Gomes b6afe5
					selected_items.clear();
Rodolfo Ribeiro Gomes b6afe5
					selected_items.push_back(saved_active_point);
Rodolfo Ribeiro Gomes b6afe5
					selection_changed = true;
Rodolfo Ribeiro Gomes b6afe5
					cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
				}
Rodolfo Ribeiro Gomes b6afe5
			}
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
		if (selection_changed) {
Rodolfo Ribeiro Gomes b6afe5
			signal_selection_changed().emit();
Rodolfo Ribeiro Gomes b6afe5
			signal_redraw_needed().emit();
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes e409b5
	else if (event->button == 2) {
Rodolfo Ribeiro Gomes e409b5
		if (pointer_state == POINTER_PANNING)
Rodolfo Ribeiro Gomes e409b5
			pointer_state = POINTER_NONE;
Rodolfo Ribeiro Gomes e409b5
	}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	if (event->button == 1 || event->button == 3) {
Rodolfo Ribeiro Gomes b6afe5
		if (pointer_state != POINTER_NONE) {
Rodolfo Ribeiro Gomes b6afe5
			pointer_state = POINTER_NONE;
Rodolfo Ribeiro Gomes b6afe5
			signal_redraw_needed().emit();
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	return false;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
bool SelectDragHelper<t>::process_motion_event(GdkEventMotion* event)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes 6d55aa
	bool processed = false;
Rodolfo Ribeiro Gomes b6afe5
	auto previous_hovered_point = hovered_item;
Rodolfo Ribeiro Gomes b6afe5
	hovered_item.invalidate();
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	int pointer_x = std::trunc(event->x);
Rodolfo Ribeiro Gomes b6afe5
	int pointer_y = std::trunc(event->y);
Rodolfo Ribeiro Gomes b6afe5
	if (pointer_state != POINTER_DRAGGING)
Rodolfo Ribeiro Gomes b6afe5
		find_item_at_position(pointer_x, pointer_y, hovered_item);
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes 170e0b
	if (previous_hovered_point != hovered_item) {
Rodolfo Ribeiro Gomes 170e0b
		signal_hovered_item_changed().emit();
Rodolfo Ribeiro Gomes b6afe5
		signal_redraw_needed().emit();
Rodolfo Ribeiro Gomes 170e0b
	}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	if (pointer_state == POINTER_DRAGGING && !dragging_started_by_key) {
Rodolfo Ribeiro Gomes b6afe5
		guint any_pointer_button = Gdk::BUTTON1_MASK |Gdk::BUTTON2_MASK | Gdk::BUTTON3_MASK;
Rodolfo Ribeiro Gomes b6afe5
		if ((event->state & any_pointer_button) == 0) {
Rodolfo Ribeiro Gomes b6afe5
			// If some modal window is called, we lose the button-release event...
Rodolfo Ribeiro Gomes b6afe5
			cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
		} else {
Rodolfo Ribeiro Gomes b6afe5
			bool axis_lock = event->state & Gdk::SHIFT_MASK;
Rodolfo Ribeiro Gomes b6afe5
			if (axis_lock) {
Rodolfo Ribeiro Gomes b6afe5
				int dx = pointer_x - pointer_tracking_start_x;
Rodolfo Ribeiro Gomes b6afe5
				int dy = pointer_y - pointer_tracking_start_y;
Rodolfo Ribeiro Gomes b6afe5
				if (std::abs(dy) > std::abs(dx))
Rodolfo Ribeiro Gomes b6afe5
					pointer_x = pointer_tracking_start_x;
Rodolfo Ribeiro Gomes b6afe5
				else
Rodolfo Ribeiro Gomes b6afe5
					pointer_y = pointer_tracking_start_y;
Rodolfo Ribeiro Gomes b6afe5
			}
Rodolfo Ribeiro Gomes b6afe5
			drag_to(pointer_x, pointer_y);
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes 6d55aa
		processed = true;
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes e409b5
	else if (pointer_state == POINTER_PANNING) {
Rodolfo Ribeiro Gomes e409b5
		const int dx = pointer_x - last_pointer_x;
Rodolfo Ribeiro Gomes e409b5
		const int dy = pointer_y - last_pointer_y;
Rodolfo Ribeiro Gomes e409b5
		const int total_dx = pointer_x - pointer_tracking_start_x;
Rodolfo Ribeiro Gomes e409b5
		const int total_dy = pointer_y - pointer_tracking_start_y;
Rodolfo Ribeiro Gomes e409b5
Rodolfo Ribeiro Gomes e409b5
		signal_panning_requested().emit(dx, dy, total_dx, total_dy);
Rodolfo Ribeiro Gomes 6d55aa
		processed = true;
Rodolfo Ribeiro Gomes e409b5
	}
Rodolfo Ribeiro Gomes e409b5
Rodolfo Ribeiro Gomes b6afe5
	if (pointer_state != POINTER_NONE) {
Rodolfo Ribeiro Gomes b6afe5
		signal_redraw_needed().emit();
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes e409b5
Rodolfo Ribeiro Gomes e409b5
	last_pointer_x = pointer_x;
Rodolfo Ribeiro Gomes e409b5
	last_pointer_y = pointer_y;
Rodolfo Ribeiro Gomes 6d55aa
	return processed;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template<class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
bool SelectDragHelper<t>::process_scroll_event(GdkEventScroll* event)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	switch(event->direction) {
Rodolfo Ribeiro Gomes b6afe5
		case GDK_SCROLL_UP:
Rodolfo Ribeiro Gomes b6afe5
		case GDK_SCROLL_RIGHT: {
Rodolfo Ribeiro Gomes 6d55aa
			if ((event->state & GDK_CONTROL_MASK) && zoom_enabled) {
Rodolfo Ribeiro Gomes b6afe5
				// Ctrl+scroll , perform zoom in
Rodolfo Ribeiro Gomes b6afe5
				signal_zoom_in_requested().emit();
Rodolfo Ribeiro Gomes b6afe5
			} else {
Rodolfo Ribeiro Gomes 6d55aa
				if (!scroll_enabled)
Rodolfo Ribeiro Gomes 6d55aa
					return false;
Rodolfo Ribeiro Gomes b6afe5
				// Scroll up
Rodolfo Ribeiro Gomes b6afe5
				signal_scroll_up_requested().emit();
Rodolfo Ribeiro Gomes b6afe5
			}
Rodolfo Ribeiro Gomes b6afe5
			return true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
		case GDK_SCROLL_DOWN:
Rodolfo Ribeiro Gomes b6afe5
		case GDK_SCROLL_LEFT: {
Rodolfo Ribeiro Gomes 6d55aa
			if ((event->state & GDK_CONTROL_MASK) && zoom_enabled) {
Rodolfo Ribeiro Gomes b6afe5
				// Ctrl+scroll , perform zoom out
Rodolfo Ribeiro Gomes b6afe5
				signal_zoom_out_requested().emit();
Rodolfo Ribeiro Gomes b6afe5
			} else {
Rodolfo Ribeiro Gomes 6d55aa
				if (!scroll_enabled)
Rodolfo Ribeiro Gomes 6d55aa
					return false;
Rodolfo Ribeiro Gomes b6afe5
				// Scroll down
Rodolfo Ribeiro Gomes b6afe5
				signal_scroll_down_requested().emit();
Rodolfo Ribeiro Gomes b6afe5
			}
Rodolfo Ribeiro Gomes b6afe5
			return true;
Rodolfo Ribeiro Gomes b6afe5
		}
Rodolfo Ribeiro Gomes b6afe5
		default:
Rodolfo Ribeiro Gomes b6afe5
			break;
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	return false;
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::refresh() {</t>
Rodolfo Ribeiro Gomes b6afe5
	hovered_item.invalidate();
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::clear() {</t>
Rodolfo Ribeiro Gomes b6afe5
	if (pointer_state == POINTER_DRAGGING) {
Rodolfo Ribeiro Gomes b6afe5
		cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
	hovered_item.invalidate();
Rodolfo Ribeiro Gomes b6afe5
	if (!selected_items.empty()) {
Rodolfo Ribeiro Gomes b6afe5
		selected_items.clear();
Rodolfo Ribeiro Gomes b6afe5
		signal_selection_changed().emit();
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes e409b5
void SelectDragHelper<t>::start_tracking_pointer(double x, double y)</t>
Rodolfo Ribeiro Gomes e409b5
{
Rodolfo Ribeiro Gomes e409b5
	pointer_tracking_start_x = std::trunc(x);
Rodolfo Ribeiro Gomes e409b5
	pointer_tracking_start_y = std::trunc(y);
Rodolfo Ribeiro Gomes e409b5
	last_pointer_x = pointer_tracking_start_x;
Rodolfo Ribeiro Gomes e409b5
	last_pointer_y = pointer_tracking_start_y;
Rodolfo Ribeiro Gomes e409b5
}
Rodolfo Ribeiro Gomes e409b5
Rodolfo Ribeiro Gomes e409b5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::start_dragging(const T* pointed_item)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	made_dragging_move = false;
Rodolfo Ribeiro Gomes b6afe5
	active_item = pointed_item;
Rodolfo Ribeiro Gomes cb03b1
	get_item_position(*active_item, active_item_start_position);
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	if (canvas_interface) {
Rodolfo Ribeiro Gomes b6afe5
		action_group_drag = new synfigapp::Action::PassiveGrouper(canvas_interface->get_instance().get(), drag_action_name);
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	pointer_state = POINTER_DRAGGING;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	signal_drag_started().emit();
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::drag_to(int pointer_x, int pointer_y)</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	made_dragging_move = true;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	int pointer_dx = pointer_x - pointer_tracking_start_x;
Rodolfo Ribeiro Gomes b6afe5
	int pointer_dy = pointer_y - pointer_tracking_start_y;
Rodolfo Ribeiro Gomes b6afe5
	delta_drag(pointer_dx, pointer_dy, false);
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::finish_dragging()</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	delete action_group_drag;
Rodolfo Ribeiro Gomes b6afe5
	action_group_drag = nullptr;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	pointer_state = POINTER_NONE;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	signal_drag_finished().emit();
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::cancel_dragging()</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	if (pointer_state != POINTER_DRAGGING)
Rodolfo Ribeiro Gomes b6afe5
		return;
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	// Sadly group->cancel() just remove PassiverGroup indicator, not its actions, from stack
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes 6d55aa
	if (action_group_drag) {
Rodolfo Ribeiro Gomes 6d55aa
		bool has_any_content =  0 < action_group_drag->get_depth();
Rodolfo Ribeiro Gomes 6d55aa
		delete action_group_drag;
Rodolfo Ribeiro Gomes 6d55aa
		action_group_drag = nullptr;
Rodolfo Ribeiro Gomes 6d55aa
		if (has_any_content && canvas_interface) {
Rodolfo Ribeiro Gomes 6d55aa
			canvas_interface->get_instance()->undo();
Rodolfo Ribeiro Gomes 6d55aa
			canvas_interface->get_instance()->clear_redo_stack();
Rodolfo Ribeiro Gomes 6d55aa
		}
Rodolfo Ribeiro Gomes b6afe5
	}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
	pointer_state = POINTER_NONE;
Rodolfo Ribeiro Gomes b6afe5
	signal_drag_canceled().emit();
Rodolfo Ribeiro Gomes b6afe5
	signal_redraw_needed().emit();
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
template <class t=""></class>
Rodolfo Ribeiro Gomes b6afe5
void SelectDragHelper<t>::select_all_items()</t>
Rodolfo Ribeiro Gomes b6afe5
{
Rodolfo Ribeiro Gomes b6afe5
	cancel_dragging();
Rodolfo Ribeiro Gomes b6afe5
	selected_items.clear();
Rodolfo Ribeiro Gomes b6afe5
	std::vector<t> all_items;</t>
Rodolfo Ribeiro Gomes b6afe5
	get_all_items(all_items);
Rodolfo Ribeiro Gomes b6afe5
	selected_items = std::move(all_items);
Rodolfo Ribeiro Gomes b6afe5
	signal_selection_changed().emit();
Rodolfo Ribeiro Gomes b6afe5
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
bool SelectDragHelper<t>::get_box_selection_enabled() const</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	return box_selection_enabled;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
void SelectDragHelper<t>::set_box_selection_enabled(bool value)</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	box_selection_enabled = value;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
bool SelectDragHelper<t>::get_multiple_selection_enabled() const</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	return multiple_selection_enabled;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
void SelectDragHelper<t>::set_multiple_selection_enabled(bool value)</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	multiple_selection_enabled = value;
Rodolfo Ribeiro Gomes 6d55aa
	if (!multiple_selection_enabled && selected_items.size() > 1) {
Rodolfo Ribeiro Gomes 6d55aa
		selected_items.resize(1);
Rodolfo Ribeiro Gomes 6d55aa
		if (active_item && active_item != &selected_items.front()) {
Rodolfo Ribeiro Gomes 6d55aa
			cancel_dragging();
Rodolfo Ribeiro Gomes 6d55aa
		}
Rodolfo Ribeiro Gomes 6d55aa
	}
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
bool SelectDragHelper<t>::get_scroll_enabled() const</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	return scroll_enabled;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
void SelectDragHelper<t>::set_scroll_enabled(bool value)</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	scroll_enabled = value;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
bool SelectDragHelper<t>::get_zoom_enabled() const</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	return zoom_enabled;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
void SelectDragHelper<t>::set_zoom_enabled(bool value)</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	zoom_enabled = value;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
bool SelectDragHelper<t>::get_pan_enabled() const</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	return pan_enabled;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
void SelectDragHelper<t>::set_pan_enabled(bool value)</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	pan_enabled = value;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
bool SelectDragHelper<t>::get_drag_enabled() const</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	return drag_enabled;
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes 6d55aa
Rodolfo Ribeiro Gomes 6d55aa
template <class t=""></class>
Rodolfo Ribeiro Gomes 6d55aa
void SelectDragHelper<t>::set_drag_enabled(bool value)</t>
Rodolfo Ribeiro Gomes 6d55aa
{
Rodolfo Ribeiro Gomes 6d55aa
	drag_enabled = value;
Rodolfo Ribeiro Gomes 6d55aa
	if (!drag_enabled) {
Rodolfo Ribeiro Gomes 6d55aa
		cancel_dragging();
Rodolfo Ribeiro Gomes 6d55aa
	}
Rodolfo Ribeiro Gomes 6d55aa
}
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
};
Rodolfo Ribeiro Gomes b6afe5
Rodolfo Ribeiro Gomes b6afe5
#endif // SYNFIG_STUDIO_SELECTDRAGHELPER_H