/*************************************************************************** * gui_callbacks.c - callbacks for gui widgets * * Tue Sep 28 02:14:33 2004 * Copyright 2004 imcintosh * ian_mcintosh@linuxadvocate.org ****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "../include/main.h" #include "../include/draw.h" #include "../include/gui.h" #include "../include/prefs.h" // Create a new backing pixmap of the appropriate size gint on_configure_event(GtkWidget *pDrawingArea, GdkEventConfigure *event) { GdkPixmap* pPixmap = g_object_get_data(G_OBJECT(pDrawingArea), KEY_PIXMAP_POINTER); if(pPixmap != NULL) { gdk_pixmap_unref(pPixmap); } pPixmap = gdk_pixmap_new( pDrawingArea->window, pDrawingArea->allocation.width, pDrawingArea->allocation.height, -1); g_object_set_data(G_OBJECT(pDrawingArea), KEY_PIXMAP_POINTER, pPixmap); // render onto it draw_ruler_window(pDrawingArea); return TRUE; } gboolean on_expose_event(GtkWidget *pDrawingArea, GdkEventExpose *event, gpointer data) { // g_message("on_expose_event(x %d,y %d,a %d,w %d)", event->area.x, event->area.y, event->area.width, event->area.height); GdkPixmap* pPixmap = g_object_get_data(G_OBJECT(pDrawingArea), KEY_PIXMAP_POINTER); // Copy relevant portion of off-screen bitmap to window gdk_draw_pixmap(pDrawingArea->window, pDrawingArea->style->fg_gc[GTK_WIDGET_STATE(pDrawingArea)], pPixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); GtkWidget* pRulerWindow = gtk_widget_get_toplevel(pDrawingArea); g_return_val_if_fail(pRulerWindow != NULL, FALSE); RulerOrientation eRulerOrientation = (RulerOrientation)g_object_get_data(G_OBJECT(pRulerWindow), KEY_RULER_ORIENTATION); g_return_val_if_fail(eRulerOrientation != 0, FALSE); // draw measurement line if turned on if(gui_get_draw_mouse_measurement_lines()) { draw_ruler_window_overlay(pDrawingArea, eRulerOrientation); } return FALSE; } // handler for Preferences menu item void on_preferences_activate(GtkWidget *pWidget, gpointer user_data) { gui_show_preferences_window(); } void on_about_activate(GtkWidget *pWidget, gpointer user_data) { const gchar *ppAuthors[] = { "Ian McIntosh ", "Piotr Smyrak ", NULL }; GtkWidget *pAboutWindow = gnome_about_new( PROGRAM_NAME, VERSION, PROGRAM_COPYRIGHT, PROGRAM_DESCRIPTION, (const gchar **) ppAuthors, NULL, NULL, NULL); gtk_widget_show(pAboutWindow); } // keyboard handler gboolean on_key_press_event(GtkWidget *pWidget, GdkEventKey *event) { // How much do we bump the window? Holding SHIFT speeds it up. int nBump = ((event->state & GDK_SHIFT_MASK) > 0) ? BUMP_LARGE : BUMP_SMALL; // ALT key means resize, otherwise move if(((event->state & GDK_ALT_MASK) > 0)) { // resize GtkWindow *pRulerWindow = GTK_WINDOW(gtk_widget_get_toplevel(pWidget)); g_return_val_if_fail(pRulerWindow != NULL, 1); RulerOrientation eRulerOrientation = (RulerOrientation)g_object_get_data(G_OBJECT(pRulerWindow), KEY_RULER_ORIENTATION); gint nWindowWidth, nWindowHeight; gtk_window_get_size(pRulerWindow, &nWindowWidth, &nWindowHeight); if(eRulerOrientation == RulerOrientationHorizontal) { if(event->keyval == GDK_Left) { nWindowWidth = max(nWindowWidth - nBump, MIN_RULER_LENGTH); gui_set_ruler_length(NULL, nWindowWidth); return TRUE; } else if(event->keyval == GDK_Right) { nWindowWidth = min(nWindowWidth + nBump, MAX_RULER_LENGTH); gui_set_ruler_length(NULL, nWindowWidth); return TRUE; } } else { if(event->keyval == GDK_Up) { nWindowHeight = max(nWindowHeight - nBump, MIN_RULER_LENGTH); gui_set_ruler_length(NULL, nWindowHeight); return TRUE; } else if(event->keyval == GDK_Down) { nWindowHeight = min(nWindowHeight + nBump, MAX_RULER_LENGTH); gui_set_ruler_length(NULL, nWindowHeight); return TRUE; } } } else { // move GtkWindow *pRulerWindow = GTK_WINDOW(gtk_widget_get_toplevel(pWidget)); g_return_val_if_fail(pRulerWindow != NULL, 1); // get position of window in root coords gint nRootX, nRootY; gtk_window_get_position(pRulerWindow, &nRootX, &nRootY); if(event->keyval == GDK_Left) { gtk_window_move(pRulerWindow, nRootX - nBump, nRootY); return TRUE; } else if(event->keyval == GDK_Right) { gtk_window_move(pRulerWindow, nRootX + nBump, nRootY); return TRUE; } else if(event->keyval == GDK_Up) { gtk_window_move(pRulerWindow, nRootX, nRootY - nBump); return TRUE; } else if(event->keyval == GDK_Down) { gtk_window_move(pRulerWindow, nRootX, nRootY + nBump); return TRUE; } } return FALSE; } // callback for mouse button events on a ruler gboolean on_button_press_event(GtkWidget *pWidget, GdkEventButton *event) { // single middle click rotates ruler (double-left-click doesn't work) if(event->button == 2 && event->type == GDK_BUTTON_PRESS) { gui_toggle_rotation(); } // begin drag or resize if left click else if(event->button == 1 && event->type == GDK_BUTTON_PRESS) { // Get the window the widget is in GtkWidget *pTopWindow = GTK_WIDGET(gtk_widget_get_toplevel(pWidget)); g_return_val_if_fail(GTK_WIDGET_TOPLEVEL(pTopWindow), FALSE); // Window dimensions gint nWindowWidth, nWindowHeight; gtk_window_get_size(GTK_WINDOW(pTopWindow), &nWindowWidth, &nWindowHeight); // Get offset into our window gint nWindowClickX, nWindowClickY; gdk_window_get_pointer(pTopWindow->window, &nWindowClickX, &nWindowClickY, NULL); // Get offset on screen gint nRootClickX, nRootClickY; gdk_window_get_pointer(gtk_widget_get_root_window(pWidget), &nRootClickX, &nRootClickY, NULL); RulerOrientation eRulerOrientation = (RulerOrientation)g_object_get_data(G_OBJECT(pWidget), KEY_RULER_ORIENTATION); // click on LEFT or RIGHT edges of a horizontal ruler? if(eRulerOrientation == RulerOrientationHorizontal && (nWindowClickX < EDGE_GRAB_SIZE)) { gtk_window_begin_resize_drag(GTK_WINDOW(pTopWindow), GDK_WINDOW_EDGE_WEST, 0, nRootClickX, nRootClickY, 0); } else if(eRulerOrientation == RulerOrientationHorizontal && (nWindowClickX > (nWindowWidth - EDGE_GRAB_SIZE))) { gtk_window_begin_resize_drag(GTK_WINDOW(pTopWindow), GDK_WINDOW_EDGE_EAST, 0, nRootClickX, nRootClickY, 0); } //~ // BOTTOM or TOP of horizontal //~ else if(eRulerOrientation == RulerOrientationHorizontal && (nWindowClickY > (nWindowHeight - EDGE_GRAB_SIZE))) { //~ gtk_window_begin_resize_drag(GTK_WINDOW(pTopWindow), GDK_WINDOW_EDGE_SOUTH, 0, nRootClickX, nRootClickY, 0); //~ } //~ else if(eRulerOrientation == RulerOrientationHorizontal && (nWindowClickY < (nWindowHeight + EDGE_GRAB_SIZE))) { //~ gtk_window_begin_resize_drag(GTK_WINDOW(pTopWindow), GDK_WINDOW_EDGE_NORTH, 0, nRootClickX, nRootClickY, 0); //~ } // click on TOP or BOTTOM edges of vertical ruler? else if(eRulerOrientation == RulerOrientationVertical && (nWindowClickY < EDGE_GRAB_SIZE)) { gtk_window_begin_resize_drag(GTK_WINDOW(pTopWindow), GDK_WINDOW_EDGE_NORTH, 0, nRootClickX, nRootClickY, 0); } else if(eRulerOrientation == RulerOrientationVertical && (nWindowClickY > (nWindowHeight - EDGE_GRAB_SIZE))) { gtk_window_begin_resize_drag(GTK_WINDOW(pTopWindow), GDK_WINDOW_EDGE_SOUTH, 0, nRootClickX, nRootClickY, 0); } // otherwise begin a window drag else { gtk_window_begin_move_drag(GTK_WINDOW(pTopWindow), 0, nRootClickX, nRootClickY, 0); } } // single-right-click? popup context menu else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { GtkWidget* pPopupMenu = gui_get_popup_widget(); gtk_menu_popup(GTK_MENU(pPopupMenu), NULL, NULL, NULL, NULL, event->button, event->time); return TRUE; } return FALSE; } // generic handler for dialog close buttons (just hides the window) void on_dialog_close(GtkWidget *pWidget, gpointer user_data) { GtkWidget *pTopWindow = gtk_widget_get_toplevel(pWidget); g_return_if_fail(pTopWindow != NULL); gtk_widget_hide(pTopWindow); } // called by colors, font, metric widgets void on_style_changed(GtkColorButton *pWidget, gpointer user_data) { gui_redraw_rulers(); prefs_write_style(); } // called by timer gboolean on_watch_mouse_update(gpointer pData) { if(gui_get_draw_mouse_measurement_lines()) { static gint nSavedMouseX=0, nSavedMouseY=0; gint nMouseX, nMouseY; gdk_window_get_pointer(GTK_WIDGET(pData)->window, &nMouseX, &nMouseY, NULL); if(nSavedMouseX != nMouseX || nSavedMouseY != nMouseY) { nSavedMouseX = nMouseX; nSavedMouseY = nMouseY; gtk_widget_queue_draw(GTK_WIDGET(pData)); } } return TRUE; } // window X button and alt-f4 handler gboolean on_application_delete_event(GtkWidget *pWidget, GdkEvent *event, gpointer user_data) { prefs_write(); gtk_exit(0); return TRUE; // satisfy compiler } // quit menu item handler void on_quit_activate(GtkWidget *pWidget, gpointer user_data) { prefs_write(); gtk_exit(0); } // gboolean on_application_motion_notify_event(GtkWidget* pWidget, GdkEventMotion *event) { // Get the window the widget is in GtkWidget *pTopWindow = GTK_WIDGET(pWidget); gint nWindowWidth, nWindowHeight; gtk_window_get_size(GTK_WINDOW(pTopWindow), &nWindowWidth, &nWindowHeight); gint nWindowClickX, nWindowClickY; gdk_window_get_pointer(pTopWindow->window, &nWindowClickX, &nWindowClickY, NULL); gint nRootClickX, nRootClickY; gdk_window_get_pointer(gtk_widget_get_root_window(pWidget), &nRootClickX, &nRootClickY, NULL); RulerOrientation eRulerOrientation = (RulerOrientation)g_object_get_data(G_OBJECT(pWidget), KEY_RULER_ORIENTATION); GdkCursor* cursor; if(eRulerOrientation == RulerOrientationHorizontal) { if(nWindowClickX < EDGE_GRAB_SIZE) { cursor = gdk_cursor_new(GDK_LEFT_SIDE); } else if((nWindowClickX + EDGE_GRAB_SIZE) > nWindowWidth) { cursor = gdk_cursor_new(GDK_RIGHT_SIDE); } else { cursor = gdk_cursor_new(GDK_LEFT_PTR); } } else { // if(eRulerOrientation == RulerOrientationHorizontal) { if(nWindowClickY < EDGE_GRAB_SIZE) { cursor = gdk_cursor_new(GDK_TOP_SIDE); } else if((nWindowClickY + EDGE_GRAB_SIZE) > nWindowHeight) { cursor = gdk_cursor_new(GDK_BOTTOM_SIDE); } else { cursor = gdk_cursor_new(GDK_LEFT_PTR); } } gdk_window_set_cursor(pTopWindow->window, cursor); gdk_cursor_destroy(cursor); return FALSE; } void on_rotate_activate(GtkWidget *pWidget, gpointer user_data) { gui_toggle_rotation(); } void on_keep_above_activate(GtkWidget *pWidget, gpointer user_data) { gui_toggle_keep_above(); } void on_help_activate(GtkWidget *pWidget, gpointer user_data) { gui_show_help_window(); }