⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dw_gtk_viewport.c

📁 浏览器的源代码,可移植到嵌入式设备.
💻 C
📖 第 1 页 / 共 3 页
字号:
   gpointer tmp_anchor;   viewport = GTK_DW_VIEWPORT (widget->viewport);   _MSG("  name(%p)=[%s]\n", name, name);   if (g_hash_table_lookup_extended (viewport->anchors_table, name, NULL,                                     &tmp_anchor)) {      anchor = tmp_anchor;   } else {      anchor = g_new (GtkDwViewportAnchor, 1);      g_hash_table_insert (viewport->anchors_table, name, anchor);   }   anchor->widget = widget;   anchor->y = y;   Dw_gtk_viewport_update_anchor (viewport);}/* * Used by Dw_gtk_viewport_update_anchor_idle. */static gboolean Dw_gtk_viewport_calc_into (gint32 requested_value,                                           gint32 requested_size,                                           gint32 current_value,                                           gint32 size,                                           gint32 *return_value){   if (requested_size > size) {      /* The viewport size is smaller than the size of the region which will       * be shown. If the region is already visible, do not change the       * position. Otherwise, show the left/upper border, this is most likely       * what is needed. */      if (current_value >= requested_value &&          current_value + size < requested_value + requested_size)         return FALSE;      else         requested_size = size;   }   if (requested_value < current_value) {      *return_value = requested_value;      return TRUE;   } else if (requested_value + requested_size > current_value + size) {      *return_value = requested_value - size + requested_size;      return TRUE;   } else      return FALSE;}/* * See Dw_gtk_viewport_scroll_to. */static gint Dw_gtk_viewport_update_anchor_idle (gpointer data){   gint32 vp_width, vp_height, x = 0, y = 0;   GtkScrolledWindow *scrolled;   GtkDwViewport *viewport;   GtkWidget *vwidget;   GtkAdjustment *vadj, *hadj;   gboolean change_x, change_y;   DBG_MSG (data, "scrolling", 0, "Dw_gtk_viewport_update_anchor_idle");   DBG_MSG_START (data);   vwidget = GTK_WIDGET (data);   viewport = GTK_DW_VIEWPORT (vwidget);   scrolled = GTK_SCROLLED_WINDOW (vwidget->parent->parent);   hadj = GTK_LAYOUT(viewport)->hadjustment;   vadj = GTK_LAYOUT(viewport)->vadjustment;   vp_width =      vwidget->allocation.width - GTK_CONTAINER(viewport)->border_width;   vp_height =      vwidget->allocation.height - GTK_CONTAINER(viewport)->border_width;   DBG_MSGF (viewport, "scrolling", 0, "vp_width = %d", vp_width);   DBG_MSGF (viewport, "scrolling", 0, "vp_height = %d", vp_height);   change_x = TRUE;   switch (viewport->anchor_pos.hpos) {   case DW_HPOS_LEFT:      DBG_MSG (viewport, "scrolling", 0, "DW_HPOS_LEFT");      x = viewport->anchor_pos.x;      break;   case DW_HPOS_CENTER:      DBG_MSG (viewport, "scrolling", 0, "DW_HPOS_CENTER");      x = viewport->anchor_pos.x - (vp_width - viewport->anchor_pos.width) / 2;      break;   case DW_HPOS_RIGHT:      DBG_MSG (viewport, "scrolling", 0, "DW_HPOS_RIGHT");      x = viewport->anchor_pos.x - (vp_width - viewport->anchor_pos.width);      break;   case DW_HPOS_INTO_VIEW:      DBG_MSG (viewport, "scrolling", 0, "DW_HPOS_INTO_VIEW");      change_x = Dw_gtk_viewport_calc_into (viewport->anchor_pos.x,                                            viewport->anchor_pos.width,                                            hadj->value, vp_width, &x);      break;   case DW_HPOS_NO_CHANGE:      DBG_MSG (viewport, "scrolling", 0, "DW_HPOS_NO_CHANGE");      change_x = FALSE;      break;   }   change_y = TRUE;   switch (viewport->anchor_pos.vpos) {   case DW_VPOS_TOP:      DBG_MSG (viewport, "scrolling", 0, "DW_VPOS_TOP");      y = viewport->anchor_pos.y;      break;   case DW_VPOS_CENTER:      DBG_MSG (viewport, "scrolling", 0, "DW_VPOS_CENTER");      y = viewport->anchor_pos.y -         (vp_height - viewport->anchor_pos.height) / 2;      break;   case DW_VPOS_BOTTOM:      DBG_MSG (viewport, "scrolling", 0, "DW_VPOS_BOTTOM");      y = viewport->anchor_pos.y - (vp_height - viewport->anchor_pos.height);      break;   case DW_VPOS_INTO_VIEW:      DBG_MSG (viewport, "scrolling", 0, "DW_VPOS_INTO_VIEW");      change_y = Dw_gtk_viewport_calc_into (viewport->anchor_pos.y,                                            viewport->anchor_pos.height,                                            vadj->value, vp_height, &y);   case DW_VPOS_NO_CHANGE:      DBG_MSG (viewport, "scrolling", 0, "DW_VPOS_NO_CHANGE");      change_y = FALSE;      break;   }   DBG_MSGF (viewport, "scrolling", 0, "scrolling to (%d, %d)\n", x, y);   DBG_MSGF (viewport, "scrolling", 0,             "hadj->upper = %g, hadj->page_size = %g",             hadj->upper, hadj->page_size);   DBG_MSGF (viewport, "scrolling", 0,             "vadj->upper = %g, vadj->page_size = %g",             vadj->upper, vadj->page_size);   if (change_x) {      if (x > hadj->upper - hadj->page_size)         gtk_adjustment_set_value (hadj, hadj->upper - hadj->page_size);      else         gtk_adjustment_set_value (hadj, x);   }   if (change_y) {      if (y > vadj->upper - vadj->page_size)         gtk_adjustment_set_value (vadj, vadj->upper - vadj->page_size);      else         gtk_adjustment_set_value (vadj, y);   }   viewport->anchor_idle_id = 0;   DBG_MSG_END (viewport);   return FALSE;}/* * Called when possibly the scroll position has to be changed because * of anchors. */void Dw_gtk_viewport_update_anchor (GtkDwViewport *viewport){   GtkDwViewportAnchor *anchor;   gpointer tmp_anchor;   if (viewport->anchor &&       g_hash_table_lookup_extended (viewport->anchors_table, viewport->anchor,                                     NULL, &tmp_anchor)) {      anchor = tmp_anchor;      Dw_gtk_viewport_scroll_to (viewport, DW_HPOS_NO_CHANGE, DW_VPOS_TOP,                                 0, anchor->y + anchor->widget->allocation.y,                                 0, 0);   }}/* * Sets the anchor to scroll to. */void a_Dw_gtk_viewport_set_anchor (GtkDwViewport *viewport,                                   const gchar *anchor){   Dw_gtk_viewport_remove_anchor (viewport);   if (anchor) {      viewport->anchor = g_strdup (anchor);      Dw_gtk_viewport_update_anchor (viewport);   } else {      viewport->anchor = NULL;      gtk_adjustment_set_value (GTK_LAYOUT(viewport)->vadjustment, 0);   }}/* * Sets the position to scroll to. The current anchor will be removed. */void a_Dw_gtk_viewport_set_scrolling_position (GtkDwViewport *viewport,                                               gint32 x,                                               gint32 y){   Dw_gtk_viewport_remove_anchor (viewport);   Dw_gtk_viewport_scroll_to (viewport, DW_HPOS_LEFT, DW_VPOS_TOP, x, y, 0, 0);}/* * Scrolls the viewport, so that the region [x, y, width, height] (world * coordinates) is seen, according to hpos and vpos. * * The actual scrolling is done in an idle function. */void Dw_gtk_viewport_scroll_to (GtkDwViewport *viewport,                                DwHPosition hpos,                                DwVPosition vpos,                                gint32 x,                                gint32 y,                                gint32 width,                                gint32 height){   viewport->anchor_pos.hpos = hpos;   viewport->anchor_pos.vpos = vpos;   viewport->anchor_pos.x = x;   viewport->anchor_pos.y = y;   viewport->anchor_pos.width = width;   viewport->anchor_pos.height = height;   DBG_OBJ_SET_NUM (viewport, "anchor_pos.hpos", viewport->anchor_pos.hpos);   DBG_OBJ_SET_NUM (viewport, "anchor_pos.vpos", viewport->anchor_pos.vpos);   DBG_OBJ_SET_NUM (viewport, "anchor_pos.x", viewport->anchor_pos.x);   DBG_OBJ_SET_NUM (viewport, "anchor_pos.y", viewport->anchor_pos.y);   DBG_OBJ_SET_NUM (viewport, "anchor_pos.width", viewport->anchor_pos.width);   DBG_OBJ_SET_NUM (viewport, "anchor_pos.height",                    viewport->anchor_pos.height);   if (viewport->anchor_idle_id == 0)      viewport->anchor_idle_id = gtk_idle_add         (Dw_gtk_viewport_update_anchor_idle, (gpointer)viewport);}/* * Remove anchor and idle function. */void Dw_gtk_viewport_remove_anchor (GtkDwViewport *viewport){   if (viewport->anchor) {      g_free (viewport->anchor);      viewport->anchor = NULL;   }   if (viewport->anchor_idle_id != 0) {      gtk_idle_remove (viewport->anchor_idle_id);      viewport->anchor_idle_id = 0;   }}/* * Drawing and resizing is done in this idle function. */static gint Dw_gtk_viewport_draw_resize_idle (gpointer data){   GtkDwViewport *viewport;   GtkLayout *layout;   GtkWidget *widget;   DwRectangle viewport_area, world_area;   GdkRectangle gtk_area;   int i;   viewport = GTK_DW_VIEWPORT (data);   switch (viewport->draw_resize_action) {   case DW_GTK_VIEWPORT_DRAW:      for (i = 0; i < viewport->num_draw_areas; i++) {         widget = GTK_WIDGET (viewport);         layout = GTK_LAYOUT (viewport);         viewport_area.x = gtk_layout_get_hadjustment(layout)->value;         viewport_area.y = gtk_layout_get_vadjustment(layout)->value;;         viewport_area.width = widget->allocation.width;         viewport_area.height = widget->allocation.height;         if (p_Dw_rectangle_intersect (&viewport->draw_areas[i],                                       &viewport_area, &world_area)) {            gtk_area.x = world_area.x - viewport_area.x;            gtk_area.y = world_area.y - viewport_area.y;            gtk_area.width = world_area.width;            gtk_area.height = world_area.height;            gtk_widget_draw (widget, &gtk_area);         }      }      /* No more areas to be drawn. */      viewport->num_draw_areas = 0;      break;   case DW_GTK_VIEWPORT_RESIZE:      Dw_gtk_viewport_calc_size (viewport);      break;   }   viewport->draw_resize_idle_id = 0;   return FALSE;}/* * Queue an area for drawing. This function is called by * p_Dw_widget_queue_draw_area. x and y are passed in world coordinates. */void Dw_gtk_viewport_queue_draw (GtkDwViewport *viewport,                                 gint32 x,                                 gint32 y,                                 gint32 width,                                 gint32 height){   DwRectangle area;   int i;   if (viewport->draw_resize_idle_id == 0) {      viewport->draw_resize_action = DW_GTK_VIEWPORT_DRAW;      viewport->draw_resize_idle_id =         gtk_idle_add (Dw_gtk_viewport_draw_resize_idle, (gpointer)viewport);   } else if (viewport->draw_resize_action == DW_GTK_VIEWPORT_RESIZE)      /* Drawing is always overridden by resizing. */      return;   area.x = x;   area.y = y;   area.width = width;   area.height = height;   /* First, try to keep the list as clean as possible. Check whether other    * rectangles interfer with this one in some way. */   /* An idea for optimization: The list could be sorted, and so the part of    * the list we have to consider here, may be reduced, the start may be    * found via linear search. However, this probably makes balanced binary    * trees necessary, since moving elements within the array may be quite    * time-consuming.    */   _MSG("  num_draw_areas = %d\n", viewport->num_draw_areas);   for (i = 0; i < viewport->num_draw_areas; i++) {      if (p_Dw_rectangle_is_subset (&area, &viewport->draw_areas[i]))         /* First case: area is a subset of an already queued rectangle          * -> nothing to do. */         return;      else if (p_Dw_rectangle_is_subset (&viewport->draw_areas[i], &area)) {         /* Second case: area is a subset of an already queued rectangle          * -> replace the other one with area. */         viewport->draw_areas[i] = area;         return;      }      /* Maybe some more tests: if both areas may exactly be combined to a       * rectangle? Very unlikely case ... */   }   /* No interference: add  the new area to the list. */   viewport->num_draw_areas++;   a_List_add (viewport->draw_areas, viewport->num_draw_areas,               viewport->num_draw_areas_max);   viewport->draw_areas[viewport->num_draw_areas - 1] = area;}/* * Start the resizing idle. This function is called by * p_Dw_widget_queue_resize, after the appropriate attributes have been set in * the widgets, where necessary. */void Dw_gtk_viewport_queue_resize (GtkDwViewport *viewport){   /* Resizing always overrides drawing. */   viewport->draw_resize_action = DW_GTK_VIEWPORT_RESIZE;   viewport->num_draw_areas = 0;   if (viewport->draw_resize_idle_id == 0)      viewport->draw_resize_idle_id =         gtk_idle_add (Dw_gtk_viewport_draw_resize_idle, (gpointer)viewport);}/* * Return the DwWidget which is at position (vx, vy) in viewport coordinates. */DwWidget* a_Dw_gtk_viewport_widget_at_viewport_point (GtkDwViewport *viewport,                                                      gint32 vx,                                                      gint32 vy){   gint32 world_x, world_y;   if (viewport->child) {      world_x = vx + gtk_layout_get_hadjustment(GTK_LAYOUT(viewport))->value;      world_y = vy + gtk_layout_get_vadjustment(GTK_LAYOUT(viewport))->value;      return Dw_gtk_viewport_widget_at_point (viewport, world_x, world_y);   } else      return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -