📄 dw_widget.c
字号:
* all other draw calls are done for children. */ GtkDwViewport *viewport; GdkDrawable *orig_pixmap, *dest; gint x, y; orig_pixmap = widget->parent ? widget->parent->clip_pixmap : NULL; widget->clip_pixmap = orig_pixmap; gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW], area, event); if (widget->clip_pixmap && (widget->parent == NULL || widget->clip_pixmap != widget->parent->clip_pixmap)) { /* Copy clipping pixmap into backing pixmap, when this widget has called * p_Dw_widget_will_clip(). */ viewport = GTK_DW_VIEWPORT (widget->viewport); dest = orig_pixmap ? orig_pixmap : viewport->back_pixmap; x = area->x + widget->allocation.x - gtk_layout_get_hadjustment(GTK_LAYOUT(viewport))->value; y = area->y + widget->allocation.y - gtk_layout_get_vadjustment(GTK_LAYOUT(viewport))->value; gdk_draw_pixmap (dest, widget->viewport->style->black_gc, widget->clip_pixmap, x, y, x, y, area->width, area->height); gdk_pixmap_unref (widget->clip_pixmap); }}void a_Dw_widget_realize (DwWidget *widget){ if (!DW_WIDGET_REALIZED (widget)) { gtk_signal_emit (GTK_OBJECT (widget), widget_signals[REALIZE]); DW_WIDGET_SET_FLAGS (widget, DW_REALIZED); if (DW_IS_CONTAINER (widget)) a_Dw_container_forall (DW_CONTAINER (widget), (DwCallback) a_Dw_widget_realize, NULL); Dw_widget_update_cursor (widget); if (widget->parent == NULL && widget->style->background_color != NULL) gdk_window_set_background (GTK_LAYOUT(widget->viewport)->bin_window, &widget->style->background_color->color); }}void a_Dw_widget_unrealize (DwWidget *widget){ if (DW_WIDGET_REALIZED (widget)) { a_Dw_widget_set_cursor (widget, NULL); gtk_signal_emit (GTK_OBJECT (widget), widget_signals[UNREALIZE]); DW_WIDGET_UNSET_FLAGS (widget, DW_REALIZED); if (DW_IS_CONTAINER (widget)) a_Dw_container_forall (DW_CONTAINER (widget), (DwCallback) a_Dw_widget_unrealize, NULL); }}/* * Handles a mouse event. * * This function is called by Dw_gtk_viewport_mouse_event, the type of * the event is determined by event->type. x and y are world coordinates. * widget may be NULL (if the pointer is outside the top-level widget). * * When event is NULL, GDK_MOTION_NOTIFY is used as the type. This will * soon be the case when GDK_MOTION_NOTIFY events are simulated as a * result of viewport changes (bug #94) */gint Dw_widget_mouse_event (DwWidget *widget, GtkWidget *viewwidget, gint32 x, gint32 y, GdkEvent *event){ gint signal_no; gboolean return_val; DwWidgetClass *klass; GtkDwViewport *viewport = GTK_DW_VIEWPORT (viewwidget); GdkEventType event_type; DwWidget *ancestor, *w1, *w2, **track; gint track_len, i; DEBUG_MSG(DEBUG_EVENT, "------------------------- EVENT -------------------------\n"); /* simulate crossing events */ /* todo: resizing/moving widgets */ if (widget != viewport->last_entered) { DEBUG_MSG (DEBUG_EVENT, "----------> crossing event\n"); DEBUG_MSG (DEBUG_EVENT, " last = %p, now = %p\n", viewport->last_entered, widget); /* Determine the next common ancestor of the widgets. */ if (viewport->last_entered == NULL || widget == NULL) ancestor = NULL; else { /* There is probably a faster algorithm. ;-) */ ancestor = NULL; for (w1 = viewport->last_entered; ancestor == NULL && w1 != NULL; w1 = w1->parent) for (w2 = widget; ancestor == NULL && w2 != NULL; w2 = w2->parent) if (w1 == w2) ancestor = w1; } /* Construct the track: * viewport->last_entered => anchestor => (current) widget */ DEBUG_MSG (DEBUG_EVENT, "common ancestor: %s %p\n", (ancestor ? gtk_type_name (GTK_OBJECT_TYPE (ancestor)) : "(none)"), ancestor); track_len = 0; if (viewport->last_entered) for (w1 = viewport->last_entered; w1 != ancestor; w1 = w1->parent) track_len++; if (ancestor) track_len++; /* for the ancestor */ if (widget) for (w1 = widget; w1 != ancestor; w1 = w1->parent) track_len++; track = g_new (DwWidget*, track_len); i = 0; if (viewport->last_entered) for (w1 = viewport->last_entered; w1 != ancestor; w1 = w1->parent) track[i++] = w1; if (ancestor) track[i++] = ancestor; if (widget) { i = track_len - 1; for (w1 = widget; w1 != ancestor; w1 = w1->parent) track[i--] = w1; } /* Send events to all events on the track */ /* todo: emit signals */ for (i = 0; i < track_len; i++) { klass = DW_WIDGET_CLASS (GTK_OBJECT(track[i])->klass); if (i != 0) { if (klass->enter_notify_event) klass->enter_notify_event (track[i], track[i - 1], (GdkEventMotion*) event); DEBUG_MSG (DEBUG_EVENT, "entering %s %p\n", gtk_type_name (GTK_OBJECT_TYPE (track[i])), track[i]); } if (i != track_len - 1) { if (klass->leave_notify_event) klass->leave_notify_event (track[i], track[i + 1], (GdkEventMotion*) event); DEBUG_MSG (DEBUG_EVENT, "leaving %s %p\n", gtk_type_name (GTK_OBJECT_TYPE (track[i])), track[i]); } } DEBUG_MSG (DEBUG_EVENT, "<----------\n"); g_free (track); viewport->last_entered = widget; if (widget) Dw_widget_update_cursor(widget); else gdk_window_set_cursor (GTK_LAYOUT(viewport)->bin_window, NULL); } /* other events */ event_type = event ? event->type : GDK_MOTION_NOTIFY; while (widget) { switch (event_type) { case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: if (widget->button_sensitive) signal_no = widget_signals[BUTTON_PRESS_EVENT]; else signal_no = -1; break; case GDK_BUTTON_RELEASE: if (widget->button_sensitive) signal_no = widget_signals[BUTTON_RELEASE_EVENT]; else signal_no = -1; break; case GDK_MOTION_NOTIFY: signal_no = widget_signals[MOTION_NOTIFY_EVENT]; break; default: signal_no = -1; break; } DEBUG_MSG (DEBUG_EVENT, "Sending %s event to %p, a %s.\n", (event_type == GDK_MOTION_NOTIFY ? "motion notify" : event_type == GDK_BUTTON_RELEASE ? "button release" : "button press"), widget, gtk_type_name (GTK_OBJECT_TYPE (widget))); if (signal_no != -1) { return_val = FALSE; gtk_signal_emit (GTK_OBJECT (widget), signal_no, x - widget->allocation.x, y - widget->allocation.y, event, &return_val); if (return_val) { DEBUG_MSG (DEBUG_EVENT, "-> Processed.\n"); return TRUE; } } widget = widget->parent; } DEBUG_MSG (DEBUG_EVENT, "-> Not processed at all.\n"); return FALSE;}/* * Change the style of a widget. The old style is automatically * unreferred, the new is referred. If this call causes the widget to * change its size, Dw_widget_queue_resize is called. */void a_Dw_widget_set_style (DwWidget *widget, DwStyle *style){ gboolean size_changed; if (widget->style) { a_Dw_style_unref (widget->style); size_changed = a_Dw_style_size_diffs (widget->style, style); } else size_changed = TRUE; a_Dw_style_ref (style); widget->style = style; if (widget->parent == NULL && DW_WIDGET_REALIZED (widget) && widget->style->background_color != NULL) gdk_window_set_background (GTK_LAYOUT(widget->viewport)->bin_window, &widget->style->background_color->color); if (DW_WIDGET_REALIZED (widget)) { if (size_changed) p_Dw_widget_queue_resize (widget, 0, TRUE); else p_Dw_widget_queue_draw (widget); }}/* * Set the cursor of the viewport. * Called from several other functions. */static void Dw_widget_update_cursor (DwWidget *widget){ GtkDwViewport *viewport = GTK_DW_VIEWPORT (widget->viewport); DwWidget *cursor_widget; if (GTK_WIDGET_REALIZED (viewport)) { /* Search cursor to use, going up from last_entered (not from widget!). */ cursor_widget = viewport->last_entered; while (cursor_widget && cursor_widget->cursor == NULL) cursor_widget = cursor_widget->parent; if (cursor_widget) gdk_window_set_cursor (GTK_LAYOUT(viewport)->bin_window, cursor_widget->cursor); else gdk_window_set_cursor (GTK_LAYOUT(viewport)->bin_window, NULL); }}/* * Set the cursor for a DwWidget. cursor has to be stored elsewhere, it * is not copied (and not destroyed). If cursor is NULL, the cursor of * the parent widget is used. */void a_Dw_widget_set_cursor (DwWidget *widget, GdkCursor *cursor){ widget->cursor = cursor; if (DW_WIDGET_REALIZED (widget)) Dw_widget_update_cursor (widget);}/* * If this function is called with button_sensitive == FALSE, the widget will * never receive button press/release events, instead they are sent to the * parent widgets. This attribute is inherited from the parent, if this * function is never called. * * TODO: A bit hackish, this is only needed for disabling selection * within <BUTTON>'s, and so make the button accessible at all. * It would be better to handle this problem in a way links are handled, * but this case is much more complicated, since a button is more complex * than a link. * * NOTE: This may be replaced by somehow using signals for events. */void a_Dw_widget_set_button_sensitive (DwWidget *widget, gboolean button_sensitive){ widget->button_sensitive = button_sensitive; widget->button_sensitive_set = TRUE;}/* * ... */DwWidget *a_Dw_widget_get_toplevel (DwWidget *widget){ while (widget->parent) widget = widget->parent; return widget;}/* * Scrolls the viewport, so that the region [x, y, width, height] (widget * coordinates) is seen, according to hpos and vpos. */void a_Dw_widget_scroll_to (DwWidget *widget, DwHPosition hpos, DwVPosition vpos, gint32 x, gint32 y, gint32 width, gint32 height){ Dw_gtk_viewport_scroll_to (GTK_DW_VIEWPORT (widget->viewport), hpos, vpos, x + widget->allocation.x, y + widget->allocation.y, width, height);}/* * Retreive an iterator pointing before the first content element * of the widget. */DwIterator* a_Dw_widget_iterator (DwWidget *widget, gint mask, gboolean at_end){ DwWidgetClass *klass = DW_WIDGET_CLASS (GTK_OBJECT(widget)->klass); if (klass->iterator) return klass->iterator(widget, mask, at_end); else return NULL;}/* * This implementation of DwIterator::clone() can be used, when the * structure DwIterator is used. */DwIterator* p_Dw_iterator_clone_std (DwIterator *it){ DwIterator *it2 = g_new (DwIterator, 1); *it2 = *it; return it2;}/* * An implementation of DwIterator::free(), which should be sufficient for most * iterator implementations. */void p_Dw_iterator_free_std (DwIterator *it){ g_free (it);}/* * No-op implementation of DwIterator::highlight(). */void p_Dw_iterator_highlight_std (DwIterator *it, gint start, gint end, DwHighlightLayer layer){ /* do nothing */}/* * This implementation of DwIterator::get_allocation can be used by all * widgets, whose iterators only return widgets themselves. */void p_Dw_iterator_get_allocation_std_only_widgets (DwIterator *it, gint start, gint end, DwAllocation *allocation){ g_return_if_fail (it->content.type == DW_CONTENT_WIDGET); *allocation = it->content.data.widget->allocation;}/* * Scrolls the viewport, so that the region between it1 and it2 is * seen, according to hpos and vpos. The parameters start and end have * the same meaning as in DwIterator::get_allocation(); start refers * to it1, while end ferers to it2. * * If it1 and it2 point to the same location (see code below), only * it1 is regarded, and both start and end refer to it. */void a_Dw_iterator_scroll_to (DwIterator *it1, DwIterator *it2, gint start, gint end, DwHPosition hpos, DwVPosition vpos){ DwAllocation alloc1, alloc2, alloc; gint32 x1, x2, y1, y2, vp_width, vp_height; DwExtIterator *eit1, *eit2, *eit; gint cur_start, cur_end, cmp; gboolean at_start; DBG_MSG (it1->widget->viewport, "scrolling", 0, "a_Dw_iterator_scroll_to"); DBG_MSG_START (it1->widget->viewport); if (it1 == it2 || (it1->widget == it2->widget && a_Dw_iterator_compare (it1, it2) == 0)) { a_Dw_iterator_get_allocation (it1, start, end, &alloc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -