📄 dw_viewport.c
字号:
/* * File: dw_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 "dillo.h"#include "msg.h"#include "dw_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;} DwViewportAnchor;/********************** * * * public functions * * * **********************/DwViewport* a_Dw_viewport_new (HWND hwnd){ RECT rc; DwViewport* viewport = g_new0 (DwViewport, 1); viewport->hwnd = hwnd; GetClientRect (hwnd, &rc); viewport->allocation.x = rc.left; viewport->allocation.y = rc.top; viewport->allocation.width = rc.right; viewport->allocation.height = rc.bottom; //printf ("viewport size: %dx%d\n", rc.right, rc.bottom); viewport->anchors_table = g_hash_table_new (g_str_hash, g_str_equal); return viewport;}static gboolean Dw_viewport_destroy_anchor (gpointer key, gpointer value, gpointer user_data){ g_free (value); return TRUE;}void a_Dw_viewport_destroy (DwViewport* viewport){ if (viewport->anchor) g_free (viewport->anchor); g_hash_table_foreach_remove (viewport->anchors_table, Dw_viewport_destroy_anchor, NULL); g_hash_table_destroy (viewport->anchors_table); g_free (viewport->draw_areas); g_free (viewport);}/* * Used by Dw_viewport_calc_size. */static void Dw_viewport_calc_child_size (DwViewport *viewport, gint32 child_width, gint32 child_height, DwRequisition *child_requisition){ if (child_width < 0) child_width = 0; if (child_height < 0) child_height = 0; DEBUG_MSG (2, " width = %d, height = %d ...\n", child_width, child_height); a_Dw_widget_set_width (viewport->child, child_width); a_Dw_widget_set_ascent (viewport->child, child_height); a_Dw_widget_set_descent (viewport->child, 0); a_Dw_widget_size_request (viewport->child, child_requisition);}static void Dw_viewport_set_scrollbars (DwViewport* viewport, gint32 width, gint32 height){ SCROLLINFO si; if (width <= viewport->allocation.width) { SetScrollPos (viewport->hwnd, SB_HORZ, 0); EnableScrollBar (viewport->hwnd, SB_HORZ, FALSE); } else { si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMax = width; si.nMin = 0; si.nPage = viewport->allocation.width; si.nPos = 0; EnableScrollBar (viewport->hwnd, SB_HORZ, TRUE); SetScrollInfo (viewport->hwnd, SB_HORZ, &si, TRUE); } if (height <= viewport->allocation.height) { SetScrollPos (viewport->hwnd, SB_VERT, 0); EnableScrollBar (viewport->hwnd, SB_VERT, FALSE); } else { si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMax = height; si.nMin = 0; si.nPage = viewport->allocation.height; si.nPos = 0; EnableScrollBar (viewport->hwnd, SB_VERT, TRUE); SetScrollInfo (viewport->hwnd, SB_VERT, &si, TRUE); }}/* * Calculate the size of the scrolled area and allocate the top-level * widget. This function is called when the top-level Dw widget has * changed its size etc. */void Dw_viewport_calc_size (DwViewport *viewport){ DwRequisition child_requisition; DwAllocation child_allocation; gint max_width, max_height; if (viewport->calc_size_blocked) return; viewport->calc_size_blocked = TRUE; if (viewport->child) { /* * Determine the size hints for the Dw widget. This is a bit * tricky, because you must know if scrollbars are visible or * not, which depends on the size of the Dw widget, which then * depends on the hints. The idea is to test several * configurations, there are four of them, from combining the * cases horizontal/vertical scrollbar visible/invisible. * * For optimization, the horizontal scrollbar is currently not * regarded, the height hint is always the same, as if the * scrollbar was allways visible. In future, this may be * implemented correctly, by using the minimal width to optimize * most cases. (Minimal widths will also be used by tables.) * * Furthermore, the last result (vertical scrollbar visible or * not) is stored in the viewport, and tested first. This will * make a second test only necessary when the visibility * switches, which normally happens only once when filling the * page with text. (Actually, this assumes that the page size is * always *growing*, but this is nevertheless true in dillo.) */ max_width = viewport->allocation.width; max_height = viewport->allocation.height; DEBUG_MSG (2, "------------------------------------------------->\n"); DEBUG_MSG (2, "Dw_viewport_calc_size: %d x %d -> %d x %d\n", viewport->allocation.width, viewport->allocation.height, max_width, max_height); Dw_viewport_calc_child_size (viewport, max_width, max_height, &child_requisition); child_allocation.x = 0; child_allocation.y = 0; child_allocation.width = child_requisition.width; child_allocation.ascent = child_requisition.ascent; child_allocation.descent = child_requisition.descent; a_Dw_widget_size_allocate (viewport->child, &child_allocation);#if 0 gtk_layout_set_size (GTK_LAYOUT (viewport), child_requisition.width + 2 * border_width, child_requisition.ascent + child_requisition.descent + 2 * border_width);#endif DEBUG_MSG (1, "Setting size to %d x %d\n", child_requisition.width, child_requisition.ascent + child_requisition.descent); DEBUG_MSG (2, "<-------------------------------------------------\n"); Dw_viewport_set_scrollbars (viewport, child_allocation.width, child_requisition.ascent + child_requisition.descent); } else {#if 0 gtk_layout_set_size (GTK_LAYOUT (viewport), 1, 1);#endif viewport->hscrollbar_used = FALSE; viewport->vscrollbar_used = FALSE; } Dw_viewport_update_anchor (viewport); InvalidateRect (viewport->hwnd, NULL, TRUE); viewport->calc_size_blocked = FALSE;}/* * Set the top-level Dw widget. * If there is already one, you must destroy it before, otherwise the * function will fail. */void a_Dw_viewport_add_dw (DwViewport *viewport, DwWidget *widget){ g_return_if_fail (viewport->child == NULL); viewport->child = widget; DBG_OBJ_ASSOC(widget, viewport); widget->parent = NULL; widget->viewport = viewport; /*widget->window = viewport->back_pixmap;*/#if 0 if (GTK_WIDGET_REALIZED (viewport)) a_Dw_widget_realize (widget);#endif a_Dw_widget_realize (widget); Dw_viewport_calc_size (viewport); Dw_viewport_remove_anchor (viewport);#if 0 a_Findtext_state_set_widget (viewport->findtext_state, widget); a_Selection_reset (viewport->selection);#endif}/************************************************** * * * Functions used by DwViewport and DwWidget * * * **************************************************//* * This function only *recognizes* that the top-level Dw widget is to * be removed. It is called by Dw_widget_shutdown. * Don't use this function directly! */void Dw_viewport_remove_dw (DwViewport *viewport){#if 0 a_Findtext_state_set_widget (viewport->findtext_state, NULL);#endif viewport->child = NULL; Dw_viewport_calc_size (viewport); Dw_viewport_remove_anchor (viewport);}/* used by Dw_viewport_widget_at_point */typedef struct{ gint32 x; gint32 y; DwWidget *widget;} WidgetAtPointData;/* used by Dw_viewport_widget_at_point */static void Dw_viewport_widget_at_point_callback (DwWidget *widget, gpointer data){ WidgetAtPointData *callback_data; callback_data = (WidgetAtPointData*) data; DEBUG_MSG (1, " Checking %p ...\n", widget); if (/* As a special exception, for the top-level widget, not the * allocation is regarded, but the whole viewport. This makes * selections more useful, since so the user can start the * selection outside of the allocation. */ widget->parent == NULL || /* Otherwise, check whether pointer is in the allocation. */ (callback_data->x >= widget->allocation.x && callback_data->y >= widget->allocation.y && callback_data->x < widget->allocation.x + widget->allocation.width && callback_data->y < widget->allocation.y + DW_WIDGET_HEIGHT(widget))) { DEBUG_MSG (1, " yes\n"); if (DW_IS_CONTAINER (widget)) a_Dw_container_forall (DW_CONTAINER (widget), Dw_viewport_widget_at_point_callback, data); if (callback_data->widget == NULL) callback_data->widget = widget; }}/* * Return the widget at point (x, y) (world coordinates). */DwWidget* Dw_viewport_widget_at_point (DwViewport *viewport, gint32 x, gint32 y){ WidgetAtPointData callback_data; callback_data.x = x; callback_data.y = y; callback_data.widget = NULL; if (viewport->child) Dw_viewport_widget_at_point_callback (viewport->child, &callback_data);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -