253 lines
7.3 KiB
C++
253 lines
7.3 KiB
C++
|
/*
|
||
|
* Copyright 2019 University of Toronto
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
* Authors: Mario Badr, Sameh Attia and Tanner Young-Schultz
|
||
|
*/
|
||
|
|
||
|
#include "ezgl/callback.hpp"
|
||
|
|
||
|
namespace ezgl {
|
||
|
|
||
|
// File wide static variables to track whether the middle mouse
|
||
|
// button is currently pressed AND the old x and y positions of the mouse pointer
|
||
|
bool middle_mouse_button_pressed = false;
|
||
|
int last_panning_event_time = 0;
|
||
|
double prev_x = 0, prev_y = 0;
|
||
|
|
||
|
gboolean press_key(GtkWidget *, GdkEventKey *event, gpointer data)
|
||
|
{
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
// Call the user-defined key press callback if defined
|
||
|
if(application->key_press_callback != nullptr) {
|
||
|
// see: https://developer.gnome.org/gdk3/stable/gdk3-Keyboard-Handling.html
|
||
|
application->key_press_callback(application, event, gdk_keyval_name(event->keyval));
|
||
|
}
|
||
|
|
||
|
return FALSE; // propagate the event
|
||
|
}
|
||
|
|
||
|
gboolean press_mouse(GtkWidget *, GdkEventButton *event, gpointer data)
|
||
|
{
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
if(event->type == GDK_BUTTON_PRESS) {
|
||
|
|
||
|
// Check for Middle mouse press to support dragging
|
||
|
if(event->button == 2) {
|
||
|
middle_mouse_button_pressed = true;
|
||
|
prev_x = event->x;
|
||
|
prev_y = event->y;
|
||
|
}
|
||
|
|
||
|
// Call the user-defined mouse press callback if defined
|
||
|
if(application->mouse_press_callback != nullptr) {
|
||
|
ezgl::point2d const widget_coordinates(event->x, event->y);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
ezgl::canvas *canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::point2d const world = canvas->get_camera().widget_to_world(widget_coordinates);
|
||
|
application->mouse_press_callback(application, event, world.x, world.y);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE; // consume the event
|
||
|
}
|
||
|
|
||
|
gboolean release_mouse(GtkWidget *, GdkEventButton *event, gpointer )
|
||
|
{
|
||
|
if(event->type == GDK_BUTTON_RELEASE) {
|
||
|
// Check for Middle mouse release to support dragging
|
||
|
if(event->button == 2) {
|
||
|
middle_mouse_button_pressed = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE; // consume the event
|
||
|
}
|
||
|
|
||
|
gboolean move_mouse(GtkWidget *, GdkEventButton *event, gpointer data)
|
||
|
{
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
if(event->type == GDK_MOTION_NOTIFY) {
|
||
|
|
||
|
// Check if the middle mouse is pressed to support dragging
|
||
|
if(middle_mouse_button_pressed) {
|
||
|
// drop this panning event if we have just served another one
|
||
|
if(gtk_get_current_event_time() - last_panning_event_time < 100)
|
||
|
return true;
|
||
|
|
||
|
last_panning_event_time = gtk_get_current_event_time();
|
||
|
|
||
|
GdkEventMotion *motion_event = (GdkEventMotion *)event;
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
point2d curr_trans = canvas->get_camera().widget_to_world({motion_event->x, motion_event->y});
|
||
|
point2d prev_trans = canvas->get_camera().widget_to_world({prev_x, prev_y});
|
||
|
|
||
|
double dx = curr_trans.x - prev_trans.x;
|
||
|
double dy = curr_trans.y - prev_trans.y;
|
||
|
|
||
|
prev_x = motion_event->x;
|
||
|
prev_y = motion_event->y;
|
||
|
|
||
|
// Flip the delta x to avoid inverted dragging
|
||
|
translate(canvas, -dx, -dy);
|
||
|
}
|
||
|
// Else call the user-defined mouse move callback if defined
|
||
|
else if(application->mouse_move_callback != nullptr) {
|
||
|
ezgl::point2d const widget_coordinates(event->x, event->y);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
ezgl::canvas *canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::point2d const world = canvas->get_camera().widget_to_world(widget_coordinates);
|
||
|
application->mouse_move_callback(application, event, world.x, world.y);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE; // consume the event
|
||
|
}
|
||
|
|
||
|
gboolean scroll_mouse(GtkWidget *, GdkEvent *event, gpointer data)
|
||
|
{
|
||
|
|
||
|
if(event->type == GDK_SCROLL) {
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
GdkEventScroll *scroll_event = (GdkEventScroll *)event;
|
||
|
|
||
|
ezgl::point2d scroll_point(scroll_event->x, scroll_event->y);
|
||
|
|
||
|
if(scroll_event->direction == GDK_SCROLL_UP) {
|
||
|
// Zoom in at the scroll point
|
||
|
ezgl::zoom_in(canvas, scroll_point, 5.0 / 3.0);
|
||
|
} else if(scroll_event->direction == GDK_SCROLL_DOWN) {
|
||
|
// Zoom out at the scroll point
|
||
|
ezgl::zoom_out(canvas, scroll_point, 5.0 / 3.0);
|
||
|
} else if(scroll_event->direction == GDK_SCROLL_SMOOTH) {
|
||
|
// Doesn't seem to be happening
|
||
|
} // NOTE: We ignore scroll GDK_SCROLL_LEFT and GDK_SCROLL_RIGHT
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean press_zoom_fit(GtkWidget *, gpointer data)
|
||
|
{
|
||
|
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::zoom_fit(canvas, canvas->get_camera().get_initial_world());
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean press_zoom_in(GtkWidget *, gpointer data)
|
||
|
{
|
||
|
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::zoom_in(canvas, 5.0 / 3.0);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean press_zoom_out(GtkWidget *, gpointer data)
|
||
|
{
|
||
|
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::zoom_out(canvas, 5.0 / 3.0);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean press_up(GtkWidget *, gpointer data)
|
||
|
{
|
||
|
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::translate_up(canvas, 5.0);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean press_down(GtkWidget *, gpointer data)
|
||
|
{
|
||
|
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::translate_down(canvas, 5.0);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean press_left(GtkWidget *, gpointer data)
|
||
|
{
|
||
|
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::translate_left(canvas, 5.0);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean press_right(GtkWidget *, gpointer data)
|
||
|
{
|
||
|
|
||
|
auto application = static_cast<ezgl::application *>(data);
|
||
|
|
||
|
std::string main_canvas_id = application->get_main_canvas_id();
|
||
|
auto canvas = application->get_canvas(main_canvas_id);
|
||
|
|
||
|
ezgl::translate_right(canvas, 5.0);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean press_proceed(GtkWidget *, gpointer data)
|
||
|
{
|
||
|
auto ezgl_app = static_cast<ezgl::application *>(data);
|
||
|
ezgl_app->quit();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|