📄 dw_widget.c
字号:
Dw_gtk_viewport_scroll_to (GTK_DW_VIEWPORT (it1->widget->viewport), hpos, vpos, alloc.x, alloc.y, alloc.width, alloc.ascent + alloc.descent); } else { /* First, determine the rectangle all iterators from it1 and it2 * allocate, i.e. the smallest rectangle containing all allocations of * these iterators. */ eit1 = a_Dw_ext_iterator_new (it1); eit2 = a_Dw_ext_iterator_new (it2); x1 = DW_INFINITY; x2 = - DW_INFINITY; y1 = DW_INFINITY; y2 = - DW_INFINITY; DBG_MSG_START (it1->widget->viewport); for (eit = a_Dw_ext_iterator_clone (eit1), at_start = TRUE; (cmp = a_Dw_ext_iterator_compare (eit, eit2)) <= 0; a_Dw_ext_iterator_next (eit), at_start = FALSE) { if (at_start) cur_start = start; else cur_start = 0; if (cmp == 0) cur_end = end; else cur_end = DW_INFINITY; a_Dw_ext_iterator_get_allocation (eit, cur_start, cur_end, &alloc); DBG_MSGF (it1->widget->viewport, "scrolling", 0, "allocation of %s, from %d to %d: [%d, %d, %d x %d x %d]\n", a_Dw_content_html (&eit->content), cur_start, cur_end, alloc.x, alloc.y, alloc.width, alloc.ascent, alloc.descent); x1 = MIN (x1, alloc.x); x2 = MAX (x2, alloc.x + alloc.width); y1 = MIN (y1, alloc.y); y2 = MAX (y2, alloc.y + alloc.ascent + alloc.descent); DBG_MSGF (it1->widget->viewport, "scrolling", 0, "result is [%d, %d, %d x %d]", x1, y1, x2 - x1, y2 - y1); } DBG_MSG_END (it1->widget->viewport); DBG_MSGF (it1->widget->viewport, "scrolling", 0, "1. region is [%d, %d, %d x %d]", x1, y1, x2 - x1, y2 - y1); a_Dw_iterator_get_allocation (it1, start, DW_INFINITY, &alloc1); a_Dw_iterator_get_allocation (it2, 0, end, &alloc2); DBG_MSGF (it1->widget->viewport, "scrolling", 0, "alloc1 = [%d, %d, %d x %d x %d]", alloc1.x, alloc1.y, alloc1.width, alloc1.ascent, alloc1.descent); DBG_MSGF (it2->widget->viewport, "scrolling", 0, "alloc2 = [%d, %d, %d x %d x %d]", alloc2.x, alloc2.y, alloc2.width, alloc2.ascent, alloc2.descent); if (alloc1.x > alloc2.x) { /* * This is due to a line break within the region. When the line is * longer than the viewport, and the region is actually quite short, * the user would not see anything of the region, as in this figure * (with region marked as "#"): * * +----------+ ,-- alloc1 * | | V * | | ### ### * ### ### | | * ^ | | <-- viewport * | +----------+ * `-- alloc2 * |----------------------------| * width * * Therefor, we the region smaller, so that the region will be * displayed like this: * * ,-- alloc1 * +----|-----+ * | V | * | ### ###| * ### ### | | * ^ | | <-- viewport * `-- alloc2 +----------+ * |----------| * width * * todo: Changes in the viewport size, until the idle function is * called, are not regarded. */ vp_width = it1->widget->viewport->allocation.width - GTK_CONTAINER(it1->widget->viewport)->border_width; DBG_MSGF (it2->widget->viewport, "scrolling", 0, "vp_width = %d", vp_width); if (x2 - x1 > vp_width) { x1 = x2 - vp_width; x2 = x1 + vp_width; } } if (alloc1.y > alloc2.y) { /* This is similar to the case above, e.g. if the region ends in * another table column. */ vp_height = it1->widget->viewport->allocation.height - GTK_CONTAINER(it1->widget->viewport)->border_width; DBG_MSGF (it2->widget->viewport, "scrolling", 0, "vp_height = %d", vp_height); if (y2 - y1 > vp_height) { y1 = y2 - vp_height; y2 = y1 + vp_height; } } DBG_MSGF (it1->widget->viewport, "scrolling", 0, "2. region is [%d, %d, %d x %d]", x1, y1, x2 - x1, y2 - y1); Dw_gtk_viewport_scroll_to (GTK_DW_VIEWPORT (it1->widget->viewport), hpos, vpos, x1, y1, x2 - x1, y2 - y1); } DBG_MSG_END (it1->widget->viewport);}/* * For DwIteratorInt. */DwIterator* p_Dw_iterator_clone_std_int (DwIterator *it){ DwIteratorInt *it2 = g_new (DwIteratorInt, 1); *it2 = *(DwIteratorInt*)it; return (DwIterator*)it2;}/* * For DwIteratorInt. */gint p_Dw_iterator_compare_std_int (DwIterator *it1, DwIterator *it2){ DwIteratorInt *ii1 = (DwIteratorInt*)it1; DwIteratorInt *ii2 = (DwIteratorInt*)it2; g_return_val_if_fail (it1->widget == it2->widget, 0); if (ii1->pos == ii2->pos) return 0; if (ii1->pos < ii2->pos) return -1; else return +1;}/* * This function returns a descriptive text for a piece of content, * useful for debugging. * NOTE: This function is not very reliable, and should really only * used for non-critical tasks like debugging. */gchar *a_Dw_content_text (DwContent *content){ /* We cycle through several buffers, so that printf should have * no problems. */#define BUF_NUM 5#define BUF_SIZE 2048 static gchar buf[BUF_SIZE * BUF_NUM]; static int cur_buf = 0; gchar *ptr; ptr = buf + cur_buf * BUF_SIZE; cur_buf = (cur_buf + 1) % BUF_NUM; switch (content->type) { case DW_CONTENT_START: sprintf (ptr, "<start>"); break; case DW_CONTENT_END: sprintf (ptr, "<end>"); break; case DW_CONTENT_TEXT: sprintf (ptr, "\"%s\"", content->data.text); break; case DW_CONTENT_WIDGET: sprintf (ptr, "the %s %p", gtk_type_name (GTK_OBJECT_TYPE (content->data.widget)), content->data.widget); break; case DW_CONTENT_ANCHOR: sprintf (ptr, "#%s", content->data.anchor); break; case DW_CONTENT_BREAK: sprintf (ptr, "<break(%d)>", content->data.break_space); break; default: sprintf (ptr, "<unknown %d>", content->type); break; } return ptr;}/* * Like a_Dw_content_text, but returns HTML. * NOTE: This function is not very reliable, and should really only * used for non-critical tasks like debugging. */gchar* a_Dw_content_html (DwContent *content){ /* We cycle through several buffers, so that printf should have * no problems. */#define BUF_NUM 5#define BUF_SIZE 2048 static gchar buf[BUF_SIZE * BUF_NUM]; static int cur_buf = 0; gchar *ptr, *ptr1, *ptr2; ptr = buf + cur_buf * BUF_SIZE; cur_buf = (cur_buf + 1) % BUF_NUM; switch (content->type) { case DW_CONTENT_START: sprintf (ptr, "<i><start></i>"); break; case DW_CONTENT_END: sprintf (ptr, "<i><end></i>"); break; case DW_CONTENT_TEXT: *ptr = '"'; ptr2 = ptr + 1; for (ptr1 = content->data.text; *ptr1; ptr1++) { switch (*ptr1) { case '<': strcpy (ptr2, "<"); ptr2 += 4; break; case '>': strcpy (ptr2, ">"); ptr2 += 4; break; case '&': strcpy (ptr2, "&"); ptr2 += 5; break; default: *ptr2 = *ptr1; ptr2++; } } ptr2[0] = '"'; ptr2[1] = 0; break; case DW_CONTENT_WIDGET: sprintf (ptr, "the %s %p", gtk_type_name (GTK_OBJECT_TYPE (content->data.widget)), content->data.widget); break; case DW_CONTENT_ANCHOR: sprintf (ptr, "#%s", content->data.anchor); break; case DW_CONTENT_BREAK: sprintf (ptr, "<i><break(%d)></i>", content->data.break_space); break; default: sprintf (ptr, "<i><unknown %d></i>", content->type); break; } return ptr;}/* * This function returns a descriptive text for an iterator, useful * for debugging. * NOTE: This function is not very reliable, and should really only * used for non-critical tasks like debugging. */gchar *a_Dw_iterator_text (DwIterator *it){ /* We cycle through several buffers, so that printf should have * no problems. */#define BUF_NUM 5#define BUF_SIZE 2048 static gchar buf[BUF_SIZE * BUF_NUM]; static int cur_buf = 0; gchar *ptr; ptr = buf + cur_buf * BUF_SIZE; cur_buf = (cur_buf + 1) % BUF_NUM; if (it) sprintf (ptr, "[%s in the %s %p]", a_Dw_content_text (&it->content), gtk_type_name (GTK_OBJECT_TYPE (it->widget)), it->widget); else strcpy (ptr, "[NULL]"); return ptr;}/* * This function prints the contents of a whole widget tree. * NOTE: This function is not very reliable, and should really only * used for non-critical tasks like debugging. */static void Dw_widget_print_tree0 (DwWidget *widget, int indent){ DwIterator *it; MSG ("%*sthe %s %p, contains:\n", indent, "", gtk_type_name (GTK_OBJECT_TYPE (widget)), widget); it = a_Dw_widget_iterator (widget, 0xff, FALSE); while (a_Dw_iterator_next (it)) { if (it->content.type == DW_CONTENT_WIDGET) Dw_widget_print_tree0 (it->content.data.widget, indent + 3); else MSG ("%*s%s\n", indent + 3, "", a_Dw_content_text (&it->content)); }}void a_Dw_widget_print_tree (DwWidget *widget){ MSG ("--- START OF WIDGET TREE ---\n"); Dw_widget_print_tree0 (widget, 0); MSG ("--- END OF WIDGET TREE ---\n");}/* * The following is a standard implementation for iterators containing * exactly one piece of text. */DwIterator* p_Dw_widget_text_iterator (DwWidget *widget, gint32 mask, gboolean at_end, gchar *text){ DwIteratorText *it; if (mask & DW_CONTENT_TEXT) { it = g_new (DwIteratorText, 1); it->it.widget = widget; it->it.mask = mask; it->it.content.type = (at_end ? DW_CONTENT_END : DW_CONTENT_START); it->it.next = p_Dw_iterator_text_next; it->it.prev = p_Dw_iterator_text_prev; it->it.clone = p_Dw_iterator_text_clone; it->it.compare = p_Dw_iterator_text_compare; it->it.free = p_Dw_iterator_free_std; it->it.highlight = p_Dw_iterator_highlight_std; it->it.get_allocation = p_Dw_iterator_text_get_allocation; it->text = text; } else it = NULL; return (DwIterator*)it;}gboolean p_Dw_iterator_text_next (DwIterator *it){ if (it->content.type == DW_CONTENT_START) { it->content.type = DW_CONTENT_TEXT; it->content.data.text = ((DwIteratorText*)it)->text; return TRUE; } else { it->content.type = DW_CONTENT_END; return FALSE; }}gboolean p_Dw_iterator_text_prev (DwIterator *it){ if (it->content.type == DW_CONTENT_END) { it->content.type = DW_CONTENT_TEXT; it->content.data.text = ((DwIteratorText*)it)->text; return TRUE; } else { it->content.type = DW_CONTENT_START; return FALSE; }}DwIterator* p_Dw_iterator_text_clone (DwIterator *it){ DwIteratorText *it2 = g_new (DwIteratorText, 1); *it2 = *(DwIteratorText*)it; return (DwIterator*)it2;}gint p_Dw_iterator_text_compare (DwIterator *it1, DwIterator *it2){ if (it1->content.type == it2->content.type) return 0; switch (it1->content.type) { case DW_CONTENT_START: return -1; case DW_CONTENT_TEXT: if (it2->content.type == DW_CONTENT_START) return +1; else return -1; case DW_CONTENT_END: return +1; default: return 0; }}void p_Dw_iterator_text_get_allocation (DwIterator *it, gint start, gint end, DwAllocation *allocation){ /* * Return the allocation of the widget. This is a bit incorrect, since * start and end are not regarded, but should be correct enough for most * purposes. */ *allocation = it->widget->allocation;}/* * Calculates the intersection of widget->allocation and area, returned in * intersection (in widget coordinates!). Typically used by containers when * drawing their children. Returns whether intersection is not empty. */gint p_Dw_widget_intersect (DwWidget *widget, DwRectangle *area, DwRectangle *intersection){#if 1 DwRectangle parent_area, child_area; parent_area = *area; parent_area.x += widget->parent->allocation.x; parent_area.y += widget->parent->allocation.y;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -