bool wxScrolledWindow::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { Init(); if (!PreCreation( parent, pos, size ) || !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) { wxFAIL_MSG( wxT("wxWindow creation failed") ); return FALSE; } m_insertCallback = wxInsertChildInScrolledWindow; m_targetWindow = this; m_widget = gtk_scrolled_window_new( (GtkAdjustment *) NULL, (GtkAdjustment *) NULL ); GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(m_widget); GtkScrolledWindowClass *scroll_class = GTK_SCROLLED_WINDOW_CLASS( GTK_OBJECT_GET_CLASS(m_widget) ); scroll_class->scrollbar_spacing = 0; gtk_scrolled_window_set_policy( scrolledWindow, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); m_hAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->hscrollbar) ); m_vAdjust = gtk_range_get_adjustment( GTK_RANGE(scrolledWindow->vscrollbar) ); m_wxwindow = gtk_pizza_new(); gtk_container_add( GTK_CONTAINER(m_widget), m_wxwindow ); GtkPizza *pizza = GTK_PIZZA(m_wxwindow); if (HasFlag(wxRAISED_BORDER)) { gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_OUT ); } else if (HasFlag(wxSUNKEN_BORDER)) { gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_IN ); } else if (HasFlag(wxSIMPLE_BORDER)) { gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_THIN ); } else { gtk_pizza_set_shadow_type( pizza, GTK_MYSHADOW_NONE ); } GTK_WIDGET_SET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); m_acceptsFocus = TRUE; // I _really_ don't want scrollbars in the beginning m_vAdjust->lower = 0.0; m_vAdjust->upper = 1.0; m_vAdjust->value = 0.0; m_vAdjust->step_increment = 1.0; m_vAdjust->page_increment = 2.0; gtk_signal_emit_by_name( GTK_OBJECT(m_vAdjust), "changed" ); m_hAdjust->lower = 0.0; m_hAdjust->upper = 1.0; m_hAdjust->value = 0.0; m_hAdjust->step_increment = 1.0; m_hAdjust->page_increment = 2.0; gtk_signal_emit_by_name( GTK_OBJECT(m_hAdjust), "changed" ); // Handlers for new scrollbar values GtkVConnectEvent(); GtkHConnectEvent(); // these handlers block mouse events to any window during scrolling such as // motion events and prevent GTK and wxWidgets from fighting over where the // slider should be gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_press_event", (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_press_event", (GtkSignalFunc)gtk_scrollbar_button_press_callback, (gpointer) this ); gtk_signal_connect( GTK_OBJECT(scrolledWindow->vscrollbar), "button_release_event", (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); gtk_signal_connect( GTK_OBJECT(scrolledWindow->hscrollbar), "button_release_event", (GtkSignalFunc)gtk_scrollbar_button_release_callback, (gpointer) this ); gtk_widget_show( m_wxwindow ); if (m_parent) m_parent->DoAddChild( this ); m_focusWidget = m_wxwindow; PostCreation(); Show( TRUE ); return 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_gtk_viewport_calc_size (GtkDwViewport *viewport) { GtkWidget *widget; GtkScrolledWindow *scrolled; DwRequisition child_requisition; DwAllocation child_allocation; gint border_width, space; GtkRequisition bar_requisition; gint max_width, max_height, bar_width_diff, bar_height_diff, child_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.) */ widget = GTK_WIDGET (viewport); scrolled = GTK_SCROLLED_WINDOW (widget->parent->parent); space = GTK_SCROLLED_WINDOW_CLASS(GTK_OBJECT(scrolled)->klass) ->scrollbar_spacing; border_width = GTK_CONTAINER(viewport)->border_width; gtk_widget_size_request (scrolled->vscrollbar, &bar_requisition); bar_width_diff = bar_requisition.width + space; max_width = widget->allocation.width - 2 * border_width; if (scrolled->vscrollbar_visible) max_width += bar_width_diff; gtk_widget_size_request (scrolled->hscrollbar, &bar_requisition); bar_height_diff = bar_requisition.height + space; max_height = widget->allocation.height - 2 * border_width; if (scrolled->hscrollbar_visible) max_height += bar_height_diff; DEBUG_MSG (2, "------------------------------------------------->\n"); DEBUG_MSG (2, "Dw_gtk_viewport_calc_size: %d x %d (%c/%c) -> %d x %d\n", widget->allocation.width, widget->allocation.height, scrolled->vscrollbar_visible ? 't' : 'f', scrolled->hscrollbar_visible ? 't' : 'f', max_width, max_height); if (scrolled->vscrollbar_policy == GTK_POLICY_NEVER) child_height = max_height; else child_height = max_height - bar_height_diff; switch (scrolled->vscrollbar_policy) { case GTK_POLICY_ALWAYS: Dw_gtk_viewport_calc_child_size (viewport, max_width - bar_width_diff, child_height, &child_requisition); break; case GTK_POLICY_AUTOMATIC: if (viewport->vscrollbar_used) { DEBUG_MSG (2, "Testing with vertical scrollbar ...\n"); Dw_gtk_viewport_calc_child_size (viewport, max_width - bar_width_diff, child_height, &child_requisition); if (child_requisition.ascent + child_requisition.descent <= child_height) { DEBUG_MSG (2, " failed!\n"); Dw_gtk_viewport_calc_child_size (viewport, max_width, child_height, &child_requisition); viewport->vscrollbar_used = TRUE; } } else { DEBUG_MSG (2, "Testing without vertical scrollbar ...\n"); Dw_gtk_viewport_calc_child_size (viewport, max_width, child_height, &child_requisition); /* todo: see above */ if (child_requisition.ascent + child_requisition.descent > child_height) { DEBUG_MSG (2, " failed!\n"); Dw_gtk_viewport_calc_child_size (viewport, max_width - bar_width_diff, child_height, &child_requisition); viewport->vscrollbar_used = TRUE; } } break; case GTK_POLICY_NEVER: Dw_gtk_viewport_calc_child_size (viewport, max_width, child_height, &child_requisition); } child_allocation.x = border_width; child_allocation.y = border_width; child_allocation.width = child_requisition.width; child_allocation.ascent = child_requisition.ascent; child_allocation.descent = child_requisition.descent; p_Dw_widget_size_allocate (viewport->child, &child_allocation); gtk_layout_set_size (GTK_LAYOUT (viewport), child_requisition.width + 2 * border_width, child_requisition.ascent + child_requisition.descent + 2 * border_width); DEBUG_MSG (1, "Setting size to %d x %d\n", child_requisition.width + 2 * border_width, child_requisition.ascent + child_requisition.descent + 2 * border_width); DEBUG_MSG (2, "<-------------------------------------------------\n"); } else { gtk_layout_set_size (GTK_LAYOUT (viewport), 1, 1); viewport->hscrollbar_used = FALSE; viewport->vscrollbar_used = FALSE; } Dw_gtk_viewport_update_anchor (viewport); gtk_widget_queue_draw (GTK_WIDGET (viewport)); viewport->calc_size_blocked = FALSE; }
static void gtk_combo_get_pos (GtkCombo * combo, gint * x, gint * y, gint * height, gint * width) { GtkBin *popwin; GtkWidget *widget; GtkScrolledWindow *popup; gint real_height; GtkRequisition list_requisition; gboolean show_hscroll = FALSE; gboolean show_vscroll = FALSE; gint avail_height; gint min_height; gint alloc_width; gint work_height; gint old_height; gint old_width; widget = GTK_WIDGET(combo); popup = GTK_SCROLLED_WINDOW (combo->popup); popwin = GTK_BIN (combo->popwin); gdk_window_get_origin (combo->entry->window, x, y); real_height = MIN (combo->entry->requisition.height, combo->entry->allocation.height); *y += real_height; avail_height = gdk_screen_height () - *y; gtk_widget_size_request (combo->list, &list_requisition); min_height = MIN (list_requisition.height, popup->vscrollbar->requisition.height); if (!GTK_LIST (combo->list)->children) list_requisition.height += EMPTY_LIST_HEIGHT; alloc_width = (widget->allocation.width - 2 * popwin->child->style->klass->xthickness - 2 * GTK_CONTAINER (popwin->child)->border_width - 2 * GTK_CONTAINER (combo->popup)->border_width - 2 * GTK_CONTAINER (GTK_BIN (popup)->child)->border_width - 2 * GTK_BIN (popup)->child->style->klass->xthickness); work_height = (2 * popwin->child->style->klass->ythickness + 2 * GTK_CONTAINER (popwin->child)->border_width + 2 * GTK_CONTAINER (combo->popup)->border_width + 2 * GTK_CONTAINER (GTK_BIN (popup)->child)->border_width + 2 * GTK_BIN (popup)->child->style->klass->xthickness); do { old_width = alloc_width; old_height = work_height; if (!show_hscroll && alloc_width < list_requisition.width) { work_height += popup->hscrollbar->requisition.height + GTK_SCROLLED_WINDOW_CLASS (GTK_OBJECT (combo->popup)->klass)->scrollbar_spacing; show_hscroll = TRUE; } if (!show_vscroll && work_height + list_requisition.height > avail_height) { if (work_height + min_height > avail_height && *y - real_height > avail_height) { *y -= (work_height + list_requisition.height + real_height); break; } alloc_width -= popup->vscrollbar->requisition.width + GTK_SCROLLED_WINDOW_CLASS (GTK_OBJECT (combo->popup)->klass)->scrollbar_spacing; show_vscroll = TRUE; } } while (old_width != alloc_width || old_height != work_height); *width = widget->allocation.width; if (show_vscroll) *height = avail_height; else *height = work_height + list_requisition.height; if (*x < 0) *x = 0; }