📄 dw_gtk_viewport.c
字号:
/* * File: dw_gtk_viewport.c * * Copyright (C) 2001-2003 Sebastian Geerken <S.Geerken@ping.de> * * 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. */#include <gtk/gtk.h>#include "msg.h"#include "dw_gtk_viewport.h"#include "dw_container.h"#include "list.h"/*#define DEBUG_LEVEL 1*/#include "debug.h"#include "msg.h"typedef struct{ DwWidget *widget; gint32 y;} GtkDwViewportAnchor;static GtkLayoutClass *parent_class = NULL;/* object/class initialisation */static void Dw_gtk_viewport_init (GtkDwViewport *viewport);static void Dw_gtk_viewport_class_init (GtkDwViewportClass *klass);/* GtkObject methods */static void Dw_gtk_viewport_destroy (GtkObject *object);/* GtkWidget methods */static void Dw_gtk_viewport_size_allocate (GtkWidget *widget, GtkAllocation *allocation);static void Dw_gtk_viewport_realize (GtkWidget *widget);static void Dw_gtk_viewport_unrealize (GtkWidget *widget);static void Dw_gtk_viewport_draw (GtkWidget *widget, GdkRectangle *area);static gint Dw_gtk_viewport_expose (GtkWidget *widget, GdkEventExpose *event);static gint Dw_gtk_viewport_button_press (GtkWidget *widget, GdkEventButton *event);static gint Dw_gtk_viewport_button_release(GtkWidget *widget, GdkEventButton *event);static gint Dw_gtk_viewport_motion_notify (GtkWidget *widget, GdkEventMotion *event);static gint Dw_gtk_viewport_enter_notify (GtkWidget *widget, GdkEventCrossing *event);static gint Dw_gtk_viewport_leave_notify (GtkWidget *widget, GdkEventCrossing *event);static void Dw_gtk_viewport_adj_changed (GtkAdjustment *adj, GtkDwViewport *viewport);/* * Standard Gtk+ function */GtkType a_Dw_gtk_viewport_get_type (void){ static GtkType type = 0; if (!type) { GtkTypeInfo info = { "GtkDwViewport", sizeof (GtkDwViewport), sizeof (GtkDwViewportClass), (GtkClassInitFunc) Dw_gtk_viewport_class_init, (GtkObjectInitFunc) Dw_gtk_viewport_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL, (GtkClassInitFunc) NULL }; type = gtk_type_unique (GTK_TYPE_LAYOUT, &info); } return type;}/* * Standard Gtk+ function */GtkWidget* a_Dw_gtk_viewport_new (GtkAdjustment *hadjustment, GtkAdjustment *vadjustment){ GtkWidget *widget; widget = gtk_widget_new (GTK_TYPE_DW_VIEWPORT, NULL); gtk_layout_set_hadjustment (GTK_LAYOUT (widget), hadjustment); gtk_layout_set_vadjustment (GTK_LAYOUT (widget), vadjustment); /* Following two statements expect that the adjustments are passed as * arguments (!= NULL), and don't change. This is the case in dillo, * however, for more general perposes, the signal function * "set_scroll_adjustments" had to be redefined. */ gtk_signal_connect (GTK_OBJECT (hadjustment), "value_changed", GTK_SIGNAL_FUNC (Dw_gtk_viewport_adj_changed), (gpointer) widget); gtk_signal_connect (GTK_OBJECT (vadjustment), "value_changed", GTK_SIGNAL_FUNC (Dw_gtk_viewport_adj_changed), (gpointer) widget); return widget;}/********************************* * * * object/class initialisation * * * *********************************//* * Standard Gtk+ function */static void Dw_gtk_viewport_init (GtkDwViewport *viewport){ DBG_OBJ_CREATE (viewport, "GtkDwViewport"); GTK_WIDGET_UNSET_FLAGS (viewport, GTK_NO_WINDOW); GTK_WIDGET_UNSET_FLAGS (viewport, GTK_CAN_FOCUS); /* Without this, gtk_layout_{draw|expose} will clear the window. Look at gtklayout.c */ GTK_WIDGET_SET_FLAGS (viewport, GTK_APP_PAINTABLE); viewport->back_pixmap = NULL; viewport->child = NULL; viewport->last_entered = NULL; viewport->draw_resize_idle_id = 0; viewport->anchor = NULL; viewport->anchor_idle_id = 0; viewport->findtext_state = a_Findtext_state_new (); viewport->selection = a_Selection_new (); viewport->anchors_table = g_hash_table_new (g_str_hash, g_str_equal); viewport->draw_areas = NULL; viewport->num_draw_areas = 0; viewport->num_draw_areas_max = 4; DBG_OBJ_ASSOC (viewport->findtext_state, viewport); DBG_OBJ_ASSOC (viewport->selection, viewport);}/* * Standard Gtk+ function */static void Dw_gtk_viewport_class_init (GtkDwViewportClass *klass){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; parent_class = gtk_type_class (gtk_layout_get_type ()); object_class = (GtkObjectClass*) klass; widget_class = (GtkWidgetClass*) klass; object_class->destroy = Dw_gtk_viewport_destroy; widget_class->size_allocate = Dw_gtk_viewport_size_allocate; widget_class->realize = Dw_gtk_viewport_realize; widget_class->unrealize = Dw_gtk_viewport_unrealize; widget_class->draw = Dw_gtk_viewport_draw; widget_class->expose_event = Dw_gtk_viewport_expose; widget_class->button_press_event = Dw_gtk_viewport_button_press; widget_class->button_release_event = Dw_gtk_viewport_button_release; widget_class->motion_notify_event = Dw_gtk_viewport_motion_notify; widget_class->enter_notify_event = Dw_gtk_viewport_enter_notify; widget_class->leave_notify_event = Dw_gtk_viewport_leave_notify;}/*********************** * * * GtkObject methods * * * ***********************/static gboolean Dw_gtk_viewport_destroy_anchor (gpointer key, gpointer value, gpointer user_data){ g_free (value); return TRUE;}/* * Standard Gtk+ function */static void Dw_gtk_viewport_destroy (GtkObject *object){ GtkDwViewport *viewport; viewport = GTK_DW_VIEWPORT (object); if (viewport->back_pixmap) gdk_pixmap_unref (viewport->back_pixmap); if (viewport->child) gtk_object_destroy (GTK_OBJECT (viewport->child)); if (viewport->draw_resize_idle_id != 0) gtk_idle_remove (viewport->draw_resize_idle_id); if (viewport->anchor_idle_id != 0) gtk_idle_remove (viewport->anchor_idle_id); g_free (viewport->anchor); g_hash_table_foreach_remove (viewport->anchors_table, Dw_gtk_viewport_destroy_anchor, NULL); g_hash_table_destroy (viewport->anchors_table); g_free (viewport->draw_areas); a_Findtext_state_destroy (viewport->findtext_state); a_Selection_free (viewport->selection); GTK_OBJECT_CLASS(parent_class)->destroy (object);}/*********************** * * * GtkWidget methods * * * ***********************//* * Standard Gtk+ function */static void Dw_gtk_viewport_size_allocate (GtkWidget *widget, GtkAllocation *allocation){ GTK_WIDGET_CLASS(parent_class)->size_allocate (widget, allocation); /* gtk_layout_size_allocate() sets them to different values. */ GTK_LAYOUT(widget)->hadjustment->page_increment = allocation->width; GTK_LAYOUT(widget)->vadjustment->page_increment = 0.96 * allocation->height;}/* * Standard Gtk+ function */static void Dw_gtk_viewport_realize (GtkWidget *widget){ GtkDwViewport *viewport; GTK_WIDGET_CLASS(parent_class)->realize (widget); gdk_window_set_events (widget->window, gdk_window_get_events (widget->window) | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); viewport = GTK_DW_VIEWPORT (widget); if (viewport->child) a_Dw_widget_realize (viewport->child); gdk_window_get_geometry (widget->window, NULL, NULL, NULL, NULL, &viewport->depth);}/* * Standard Gtk+ function */static void Dw_gtk_viewport_unrealize (GtkWidget *widget){ GtkDwViewport *viewport; GTK_WIDGET_CLASS(parent_class)->unrealize (widget); viewport = GTK_DW_VIEWPORT (widget); if (viewport->child) a_Dw_widget_unrealize (viewport->child);}/* * (Nearly) standard Gtk+ function */static void Dw_gtk_viewport_paint (GtkWidget *widget, GdkRectangle *area, GdkEventExpose *event){ GtkLayout *layout; DwRectangle parent_area, child_area, intersection; GtkDwViewport *viewport; gboolean new_back_pixmap; if (GTK_WIDGET_DRAWABLE (widget)) { layout = GTK_LAYOUT (widget); viewport = GTK_DW_VIEWPORT (widget); DEBUG_MSG (2, "Drawing (%d, %d), %d x %d\n", area->x, area->y, area->width, area->height); /* Make sure the backing pixmap is large enough. */ if (viewport->child) { if (viewport->back_pixmap) new_back_pixmap = (widget->allocation.width > viewport->back_width || widget->allocation.height > viewport->back_height); else new_back_pixmap = TRUE; if (new_back_pixmap) { if (viewport->back_pixmap) gdk_pixmap_unref (viewport->back_pixmap); viewport->back_pixmap = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, viewport->depth); viewport->back_width = widget->allocation.width; viewport->back_height = widget->allocation.height; DEBUG_MSG (1, " Creating new pixmap, size = %d x %d\n", widget->allocation.width, widget->allocation.height); } /* Draw top-level Dw widget. */ parent_area.x = p_Dw_widget_x_viewport_to_world (viewport->child, area->x); parent_area.y = p_Dw_widget_y_viewport_to_world (viewport->child, area->y); parent_area.width = area->width; parent_area.height = area->height; child_area.x = viewport->child->allocation.x; child_area.y = viewport->child->allocation.y; child_area.width = viewport->child->allocation.width; child_area.height = DW_WIDGET_HEIGHT(viewport->child); if (p_Dw_rectangle_intersect (&parent_area, &child_area, &intersection)) { intersection.x -= viewport->child->allocation.x; intersection.y -= viewport->child->allocation.y; /* "Clear" backing pixmap. */ gdk_draw_rectangle (viewport->back_pixmap, viewport->child->style->background_color->gc, TRUE, area->x, area->y, area->width, area->height); /* Widgets draw in backing pixmap. */ a_Dw_widget_draw (viewport->child, &intersection, event); /* Copy backing pixmap into window. */ gdk_draw_pixmap (layout->bin_window, widget->style->black_gc, viewport->back_pixmap, area->x, area->y, area->x, area->y, area->width, area->height); } } else gdk_window_clear_area (layout->bin_window, area->x, area->y, area->width, area->height); }}/* * Standard Gtk+ function */static void Dw_gtk_viewport_draw (GtkWidget *widget, GdkRectangle *area){ Dw_gtk_viewport_paint (widget, area, NULL); GTK_WIDGET_CLASS(parent_class)->draw (widget, area);}/* * Standard Gtk+ function */static gint Dw_gtk_viewport_expose (GtkWidget *widget, GdkEventExpose *event){ Dw_gtk_viewport_paint (widget, &(event->area), event); return GTK_WIDGET_CLASS(parent_class)->expose_event (widget, event);}/* * Handle the mouse event and deliver it to the Dw widget. * Most is done in a_Dw_widget_mouse_event. */static gint Dw_gtk_viewport_mouse_event (GtkWidget *widget, gint32 x, gint32 y, GdkEvent *event){ GtkDwViewport *viewport; DwWidget *dw_widget; gint32 world_x, world_y; if (event == NULL || event->any.window == widget->window) { viewport = GTK_DW_VIEWPORT (widget); if (viewport->child) { world_x = x + gtk_layout_get_hadjustment(GTK_LAYOUT(viewport))->value;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -