📄 dw_widget.c
字号:
child_area.x = widget->allocation.x; child_area.y = widget->allocation.y; child_area.width = widget->allocation.width; child_area.height = DW_WIDGET_HEIGHT(widget); if (p_Dw_rectangle_intersect (&parent_area, &child_area, intersection)) { intersection->x -= widget->allocation.x; intersection->y -= widget->allocation.y; return TRUE; } else return FALSE;#else intersection->x = 0; intersection->y = 0; intersection->width = widget->allocation.width; intersection->height = DW_WIDGET_HEIGHT(widget); return TRUE;#endif}void p_Dw_widget_set_parent (DwWidget *widget, DwWidget *parent){ gtk_object_ref (GTK_OBJECT (widget)); gtk_object_sink (GTK_OBJECT (widget)); widget->parent = parent; widget->viewport = parent->viewport; /*widget->window = parent->window;*/ if (!widget->button_sensitive_set) widget->button_sensitive = parent->button_sensitive; DBG_OBJ_ASSOC (widget, parent); if (DW_WIDGET_REALIZED (parent)) a_Dw_widget_realize (widget);}/* * Converting between coordinates. */gint32 p_Dw_widget_x_viewport_to_world (DwWidget *widget, gint16 viewport_x){ GtkAdjustment *adjustment; g_return_val_if_fail (widget && widget->viewport, 0); adjustment = gtk_layout_get_hadjustment (GTK_LAYOUT (widget->viewport)); g_return_val_if_fail (adjustment != NULL, 0); return viewport_x + (gint32)adjustment->value;}gint32 p_Dw_widget_y_viewport_to_world (DwWidget *widget, gint16 viewport_y){ GtkAdjustment *adjustment; g_return_val_if_fail (widget && widget->viewport, 0); adjustment = gtk_layout_get_vadjustment (GTK_LAYOUT (widget->viewport)); g_return_val_if_fail (adjustment != NULL, 0); return viewport_y + (gint32)adjustment->value;}gint16 p_Dw_widget_x_world_to_viewport (DwWidget *widget, gint32 world_x){ GtkAdjustment *adjustment; g_return_val_if_fail (widget && widget->viewport, 0); adjustment = gtk_layout_get_hadjustment (GTK_LAYOUT (widget->viewport)); g_return_val_if_fail (adjustment != NULL, 0); return world_x - (gint32)adjustment->value;}gint16 p_Dw_widget_y_world_to_viewport (DwWidget *widget, gint32 world_y){ GtkAdjustment *adjustment; g_return_val_if_fail (widget && widget->viewport, 0); adjustment = gtk_layout_get_vadjustment (GTK_LAYOUT (widget->viewport)); g_return_val_if_fail (adjustment != NULL, 0); return world_y - (gint32)adjustment->value;}/* * Calculate the intersection of (x, y, width, height) (widget * coordinates) and the current viewport area. gdk_intersection has * (of course) viewport coordinates, the return value is TRUE iff the * intersection is not empty. */static gboolean Dw_widget_intersect_viewport (DwWidget *widget, gint32 x, gint32 y, gint32 width, gint32 height, GdkRectangle *gdk_intersection){ GtkLayout *layout; DwRectangle widget_area, viewport_area, intersection; g_return_val_if_fail (widget && widget->viewport, FALSE); layout = GTK_LAYOUT (widget->viewport); widget_area.x = widget->allocation.x + x; widget_area.y = widget->allocation.y + y; widget_area.width = width; widget_area.height = height; viewport_area.x = layout->xoffset; viewport_area.y = layout->yoffset; viewport_area.width = widget->viewport->allocation.width; viewport_area.height = widget->viewport->allocation.height; if (p_Dw_rectangle_intersect (&widget_area, &viewport_area, &intersection)) { gdk_intersection->x = intersection.x - layout->xoffset; gdk_intersection->y = intersection.y - layout->yoffset; gdk_intersection->width = intersection.width; gdk_intersection->height = intersection.height; return TRUE; } else return FALSE;}/* * ... */void p_Dw_widget_queue_draw (DwWidget *widget){ p_Dw_widget_queue_draw_area (widget, 0, 0, widget->allocation.width, DW_WIDGET_HEIGHT(widget));}/* * ... */void p_Dw_widget_queue_draw_area (DwWidget *widget, gint32 x, gint32 y, gint32 width, gint32 height){ /* todo: maybe only the intersection? */ Dw_gtk_viewport_queue_draw (GTK_DW_VIEWPORT (widget->viewport), x + widget->allocation.x, y + widget->allocation.y, width, height);}/* * Resizing of Widgets. * The interface was adopted by Gtk+, but the implementation is far simpler, * since Gtk+ handles a lot of cases which are irrelevant to Dw. *//* * This function should be called, if the widget changed its size. */void p_Dw_widget_queue_resize (DwWidget *widget, gint ref, gboolean extremes_changed){ DwWidget *widget2, *child; DwWidgetClass *klass; DEBUG_MSG (DEBUG_SIZE, "a %stop-level %s with parent_ref = %d has changed its size\n", widget->parent ? "non-" : "", gtk_type_name (GTK_OBJECT_TYPE (widget)), widget->parent_ref); klass = (DwWidgetClass*)(((GtkObject*)widget)->klass); DW_WIDGET_SET_FLAGS (widget, DW_NEEDS_RESIZE); if (klass->mark_size_change) klass->mark_size_change (widget, ref); if (extremes_changed) { DW_WIDGET_SET_FLAGS (widget, DW_EXTREMES_CHANGED); if (klass->mark_extremes_change) klass->mark_extremes_change (widget, ref); } for (widget2 = widget->parent, child = widget; widget2; child = widget2, widget2 = widget2->parent) { klass = (DwWidgetClass*)(((GtkObject*)widget2)->klass); DW_WIDGET_SET_FLAGS (widget2, DW_NEEDS_RESIZE); if (klass->mark_size_change) klass->mark_size_change (widget2, child->parent_ref); DW_WIDGET_SET_FLAGS (widget2, DW_NEEDS_ALLOCATE); DEBUG_MSG (DEBUG_ALLOC, "setting DW_NEEDS_ALLOCATE for a %stop-level %s " "with parent_ref = %d\n", widget2->parent ? "non-" : "", gtk_type_name (GTK_OBJECT_TYPE (widget2)), widget2->parent_ref); if (extremes_changed) { DW_WIDGET_SET_FLAGS (widget2, DW_EXTREMES_CHANGED); if (klass->mark_extremes_change) klass->mark_extremes_change (widget2, child->parent_ref); } } if (widget->viewport) Dw_gtk_viewport_queue_resize (GTK_DW_VIEWPORT (widget->viewport));}/* * If a widget might draw outside of its allocation, this function should be * called at the beginning of the draw method. It will cause drawings be done * in a temporary pixmap, which is later copied into the backing pixmap, so * that drawings outside of the allocation are later discarded. * * Clipping causes a bit overhead due to the second copying, so it should * only used when neccessary. */void p_Dw_widget_will_clip (DwWidget *widget){ DwWidget *widget2; widget->clip_pixmap = gdk_pixmap_new (widget->viewport->window, widget->viewport->allocation.width, widget->viewport->allocation.height, GTK_DW_VIEWPORT(widget->viewport)->depth); /* Determine the effective background color. (There is a defined background * at least for the top-level widget.) */ for (widget2 = widget; widget2 != NULL && widget2->style->background_color == NULL; widget2 = widget2->parent) ; g_return_if_fail (widget2 != NULL); gdk_draw_rectangle (widget->clip_pixmap, widget2->style->background_color->gc, TRUE, 0, 0, widget->viewport->allocation.width, widget->viewport->allocation.height);}/* * Set the background "behind" the widget, if it is not the background of the * parent widget, e.g. the background of a table row. */void p_Dw_widget_set_bg_color (DwWidget *widget, DwStyleColor *color){ widget->bg_color = color;}/* * Get the actual background of a widget. */DwStyleColor* p_Dw_widget_get_bg_color (DwWidget *widget){ while (widget != NULL) { if (widget->style->background_color) return widget->style->background_color; if (widget->bg_color) return widget->bg_color; widget = widget->parent; } g_warning ("No background color found!"); return NULL;}/* * Draw borders and background of a widget part, which allocation is * given by (x, y, width, height) (widget coordinates). */void p_Dw_widget_draw_box (DwWidget *widget, DwStyle *style, DwRectangle *area, gint32 x, gint32 y, gint32 width, gint32 height, gboolean inverse){ GdkRectangle gdk_area; gint32 vx, vy; if (Dw_widget_intersect_viewport (widget, area->x, area->y, area->width, area->height, &gdk_area)) { vx = p_Dw_widget_x_viewport_to_world (widget, 0); vy = p_Dw_widget_y_viewport_to_world (widget, 0); p_Dw_style_draw_border (DW_WIDGET_WINDOW (widget), &gdk_area, vx, vy, widget->allocation.x + x, widget->allocation.y + y, width, height, style, inverse); if (style->background_color) p_Dw_style_draw_background (DW_WIDGET_WINDOW (widget), &gdk_area, vx, vy, widget->allocation.x + x, widget->allocation.y + y, width, height, style, inverse); }}/* * Draw borders and background of a widget. */void p_Dw_widget_draw_widget_box (DwWidget *widget, DwRectangle *area, gboolean inverse){ GdkRectangle gdk_area; gint32 vx, vy; if (Dw_widget_intersect_viewport (widget, area->x, area->y, area->width, area->height, &gdk_area)) { vx = p_Dw_widget_x_viewport_to_world (widget, 0); vy = p_Dw_widget_y_viewport_to_world (widget, 0); p_Dw_style_draw_border (DW_WIDGET_WINDOW (widget), &gdk_area, vx, vy, widget->allocation.x, widget->allocation.y, widget->allocation.width, DW_WIDGET_HEIGHT(widget), widget->style, inverse); /* - Toplevel widget background colors are set as viewport * background color. This is not crucial for the rendering, but * looks a bit nicer when scrolling. Furthermore, the viewport * does anything else in this case. * * - Since widgets are always drawn from top to bottom, it is * *not* necessary to draw the background if * widget->style->background_color is NULL (shining through). */ if (widget->parent && widget->style->background_color) p_Dw_style_draw_background (DW_WIDGET_WINDOW (widget), &gdk_area, vx, vy, widget->allocation.x, widget->allocation.y, widget->allocation.width, DW_WIDGET_HEIGHT(widget), widget->style, inverse); }}/* * This function is used by some widgets, when they are selected (as a whole). * * todo: This could be accelerated by using clipping bitmaps. Two important * issues: * * (i) There should always been a pixel in the upper-left corner of the * *widget*, so probably two different clipping bitmaps have to be * used (10/01 and 01/10). * * (ii) Should a new GC always be created? */void p_Dw_widget_draw_selected (DwWidget *widget, DwRectangle *area){ GdkRectangle gdk_area; /* All coordinates are widget coordinates. */ gint32 x, y, startxa, startya, startxb, startyb, endx, endy, ix, iy; gint32 dx, dy; /* the difference between viewport and widget */ DwStyleColor *bg_color; GdkWindow *window; if (Dw_widget_intersect_viewport (widget, area->x, area->y, area->width, area->height, &gdk_area)) { /* Calculate from where to start the respective drawing loops below. * There should always been a pixel in the upper-left corner of the * *widget*, so the start depends on whether the drawing area (in widget * coordinates) has even or odd offsets. */ /* the intersection in widget coordinates */ ix = p_Dw_widget_x_viewport_to_world (widget, gdk_area.x) - widget->allocation.x; iy = p_Dw_widget_y_viewport_to_world (widget, gdk_area.y) - widget->allocation.y; if (ix % 2 == 0) { startxa = ix; startxb = ix + 1; } else { startxa = ix + 1; startxb = ix; } if (iy % 2 == 0) { startya = iy; startyb = iy + 1; } else { startya = iy + 1; startyb = iy; } dx = p_Dw_widget_x_world_to_viewport (widget, widget->allocation.x); dy = p_Dw_widget_y_world_to_viewport (widget, widget->allocation.y); endx = ix + gdk_area.width; endy = iy + gdk_area.height; bg_color = p_Dw_widget_get_bg_color (widget); window = DW_WIDGET_WINDOW (widget); for (x = startxa; x < endx; x += 2) for (y = startya; y < endy; y += 2) gdk_draw_point (window, bg_color->inverse_gc, x + dx, y + dy); for (x = startxb; x < endx; x += 2) for (y = startyb; y < endy; y += 2) gdk_draw_point (window, bg_color->inverse_gc, x + dx, y + dy); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -