]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcombobox.c
buffer_backspace should delete \r\n in one go
[~andy/gtk] / gtk / gtkcombobox.c
index 1255e7c0e113d09a456517a8099defbb7e33dc53..bda2a92f224fa340e1365b44725afbf7551656bb 100644 (file)
@@ -81,6 +81,7 @@ struct _GtkComboBoxPrivate
   gint wrap_width;
   GtkShadowType shadow_type;
 
+  gint active; /* Only temporary */
   GtkTreeRowReference *active_row;
 
   GtkWidget *tree_view;
@@ -928,6 +929,7 @@ gtk_combo_box_init (GtkComboBox *combo_box)
   priv->height = 0;
   priv->wrap_width = 0;
 
+  priv->active = -1;
   priv->active_row = NULL;
   priv->col_column = -1;
   priv->row_column = -1;
@@ -1468,15 +1470,17 @@ gtk_combo_box_menu_position_below (GtkMenu  *menu,
   
   /* FIXME: is using the size request here broken? */
   child = GTK_BIN (combo_box)->child;
-   
-  gdk_window_get_origin (child->window, &sx, &sy);
-   
+
+  sx = sy = 0;
+
   if (GTK_WIDGET_NO_WINDOW (child))
     {
       sx += child->allocation.x;
       sy += child->allocation.y;
     }
 
+  gdk_window_get_root_coords (child->window, sx, sy, &sx, &sy);
+
   if (GTK_SHADOW_NONE != combo_box->priv->shadow_type)
     sx -= GTK_WIDGET (combo_box)->style->xthickness;
 
@@ -1535,10 +1539,9 @@ gtk_combo_box_menu_position_over (GtkMenu  *menu,
   menu_width = requisition.width;
 
   active = gtk_menu_get_active (GTK_MENU (combo_box->priv->popup_widget));
-  gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
 
-  menu_xpos += widget->allocation.x;
-  menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
+  menu_xpos = widget->allocation.x;
+  menu_ypos = widget->allocation.y + widget->allocation.height / 2 - 2;
 
   if (active != NULL)
     {
@@ -1566,6 +1569,9 @@ gtk_combo_box_menu_position_over (GtkMenu  *menu,
   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
     menu_xpos = menu_xpos + widget->allocation.width - menu_width;
 
+  gdk_window_get_root_coords (widget->window, menu_xpos, menu_ypos,
+                             &menu_xpos, &menu_ypos);
+
   /* Clamp the position on screen */
   screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
   
@@ -1605,8 +1611,9 @@ gtk_combo_box_menu_position (GtkMenu  *menu,
       gtk_combo_box_menu_position_over (menu, x, y, push_in, user_data);
     }
 
-  gtk_window_set_type_hint (GTK_WINDOW (GTK_MENU (priv->popup_widget)->toplevel),
-                            GDK_WINDOW_TYPE_HINT_COMBO);
+  if (!GTK_WIDGET_VISIBLE (GTK_MENU (priv->popup_widget)->toplevel))
+    gtk_window_set_type_hint (GTK_WINDOW (GTK_MENU (priv->popup_widget)->toplevel),
+                              GDK_WINDOW_TYPE_HINT_COMBO);
 }
 
 static void
@@ -1627,7 +1634,7 @@ gtk_combo_box_list_position (GtkComboBox *combo_box,
      see bug #340204 */
   GtkWidget *sample = GTK_WIDGET (combo_box);
 
-  gdk_window_get_origin (sample->window, x, y);
+  *x = *y = 0;
 
   if (GTK_WIDGET_NO_WINDOW (sample))
     {
@@ -1635,6 +1642,8 @@ gtk_combo_box_list_position (GtkComboBox *combo_box,
       *y += sample->allocation.y;
     }
   
+  gdk_window_get_root_coords (sample->window, *x, *y, x, y);
+
   *width = sample->allocation.width;
 
   hpolicy = vpolicy = GTK_POLICY_NEVER;
@@ -1692,7 +1701,7 @@ cell_view_is_sensitive (GtkCellView *cell_view)
   GList *cells, *list;
   gboolean sensitive;
   
-  cells = gtk_cell_view_get_cell_renderers (cell_view);
+  cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_view));
 
   sensitive = FALSE;
   for (list = cells; list; list = list->next)
@@ -1729,7 +1738,7 @@ tree_column_row_is_sensitive (GtkComboBox *combo_box,
                                           priv->model,
                                           iter, FALSE, FALSE);
 
-  cells = gtk_tree_view_column_get_cell_renderers (priv->column);
+  cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->column));
 
   sensitive = FALSE;
   for (list = cells; list; list = list->next)
@@ -2293,6 +2302,23 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
               child.width -= child.x;
             }
 
+          if (GTK_WIDGET_VISIBLE (priv->popup_widget))
+            {
+              gint width;
+              GtkRequisition requisition;
+
+              /* Warning here, without the check in the position func */
+              gtk_menu_reposition (GTK_MENU (priv->popup_widget));
+              if (priv->wrap_width == 0)
+                {
+                  width = GTK_WIDGET (combo_box)->allocation.width;
+                  gtk_widget_set_size_request (priv->popup_widget, -1, -1);
+                  gtk_widget_size_request (priv->popup_widget, &requisition);
+                  gtk_widget_set_size_request (priv->popup_widget,
+                    MAX (width, requisition.width), -1);
+               }
+            }
+
          child.width = MAX (1, child.width);
          child.height = MAX (1, child.height);
           gtk_widget_size_allocate (GTK_BIN (widget)->child, &child);
@@ -2362,6 +2388,15 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
           child.width -= delta_x * 2;
           child.height -= delta_y * 2;
         }
+
+      if (GTK_WIDGET_VISIBLE (priv->popup_window))
+        {
+          gint x, y, width, height;
+          gtk_combo_box_list_position (combo_box, &x, &y, &width, &height);
+          gtk_window_move (GTK_WINDOW (priv->popup_window), x, y);
+          gtk_widget_set_size_request (priv->popup_window, width, height);
+        }
+
       
       child.width = MAX (1, child.width);
       child.height = MAX (1, child.height);
@@ -2811,6 +2846,7 @@ gtk_combo_box_menu_setup (GtkComboBox *combo_box,
   /* create our funky menu */
   menu = gtk_menu_new ();
   gtk_widget_set_name (menu, "gtk-combobox-popup-menu");
+  gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
   
   g_signal_connect (menu, "key-press-event",
                    G_CALLBACK (gtk_combo_box_menu_key_press), combo_box);
@@ -2923,6 +2959,7 @@ gtk_combo_box_menu_fill_level (GtkComboBox *combo_box,
          if (gtk_tree_model_iter_has_child (model, &iter))
            {
              submenu = gtk_menu_new ();
+              gtk_menu_set_reserve_toggle_size (GTK_MENU (submenu), FALSE);
              gtk_widget_show (submenu);
              gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
              
@@ -3433,6 +3470,7 @@ gtk_combo_box_menu_row_inserted (GtkTreeModel *model,
       if (!menu)
        {
          menu = gtk_menu_new ();
+          gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
          gtk_widget_show (menu);
          gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), menu);
          
@@ -3989,13 +4027,13 @@ gtk_combo_box_list_auto_scroll (GtkComboBox *combo_box,
          adj->lower < adj->value)
        {
          value = adj->value - (tree_view->allocation.x - x + 1);
-         gtk_adjustment_set_value (adj, value);
+         gtk_adjustment_set_value (adj, CLAMP (value, adj->lower, adj->upper - adj->page_size));
        }
       else if (x >= tree_view->allocation.x + tree_view->allocation.width &&
               adj->upper - adj->page_size > adj->value)
        {
          value = adj->value + (x - tree_view->allocation.x - tree_view->allocation.width + 1);
-         gtk_adjustment_set_value (adj, MAX (value, 0.0));
+         gtk_adjustment_set_value (adj, CLAMP (value, 0.0, adj->upper - adj->page_size));
        }
     }
 
@@ -4006,13 +4044,13 @@ gtk_combo_box_list_auto_scroll (GtkComboBox *combo_box,
          adj->lower < adj->value)
        {
          value = adj->value - (tree_view->allocation.y - y + 1);
-         gtk_adjustment_set_value (adj, value);
+         gtk_adjustment_set_value (adj, CLAMP (value, adj->lower, adj->upper - adj->page_size));
        }
       else if (y >= tree_view->allocation.height &&
               adj->upper - adj->page_size > adj->value)
        {
          value = adj->value + (y - tree_view->allocation.height + 1);
-         gtk_adjustment_set_value (adj, MAX (value, 0.0));
+         gtk_adjustment_set_value (adj, CLAMP (value, 0.0, adj->upper - adj->page_size));
        }
     }
 }
@@ -4068,7 +4106,7 @@ gtk_combo_box_list_select_func (GtkTreeSelection *selection,
       gtk_tree_view_column_cell_set_cell_data (column, model, &iter,
                                               FALSE, FALSE);
 
-      cell = cells = gtk_tree_view_column_get_cell_renderers (column);
+      cell = cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
       while (cell)
         {
          g_object_get (cell->data,
@@ -4812,6 +4850,14 @@ gtk_combo_box_set_active (GtkComboBox *combo_box,
   g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
   g_return_if_fail (index_ >= -1);
 
+  if (combo_box->priv->model == NULL)
+    {
+      /* Save index, in case the model is set after the index */
+      combo_box->priv->active = index_;
+      if (index_ != -1)
+        return;
+    }
+
   if (index_ != -1)
     path = gtk_tree_path_new_from_indices (index_, -1);
    
@@ -4829,7 +4875,10 @@ gtk_combo_box_set_active_internal (GtkComboBox *combo_box,
   GtkTreePath *active_path;
   gint path_cmp;
 
-  if (path && gtk_tree_row_reference_valid (priv->active_row))
+  /* Remember whether the initially active row is valid. */
+  gboolean is_valid_row_reference = gtk_tree_row_reference_valid (priv->active_row);
+
+  if (path && is_valid_row_reference)
     {
       active_path = gtk_tree_row_reference_get_path (priv->active_row);
       path_cmp = gtk_tree_path_compare (path, active_path);
@@ -4858,6 +4907,13 @@ gtk_combo_box_set_active_internal (GtkComboBox *combo_box,
 
       if (priv->cell_view)
         gtk_cell_view_set_displayed_row (GTK_CELL_VIEW (priv->cell_view), NULL);
+
+      /*
+       *  Do not emit a "changed" signal when an already invalid selection was
+       *  now set to invalid.
+       */
+      if (!is_valid_row_reference)
+        return;
     }
   else
     {
@@ -5007,6 +5063,13 @@ gtk_combo_box_set_model (GtkComboBox  *combo_box,
     gtk_cell_view_set_model (GTK_CELL_VIEW (combo_box->priv->cell_view),
                              combo_box->priv->model);
 
+  if (combo_box->priv->active != -1)
+    {
+      /* If an index was set in advance, apply it now */
+      gtk_combo_box_set_active (combo_box, combo_box->priv->active);
+      combo_box->priv->active = -1;
+    }
+
 out:
   gtk_combo_box_update_sensitivity (combo_box);
 
@@ -5197,10 +5260,11 @@ gtk_combo_box_remove_text (GtkComboBox *combo_box,
  *
  * Returns the currently active string in @combo_box or %NULL if none
  * is selected.  Note that you can only use this function with combo
- * boxes constructed with gtk_combo_box_new_text() and with 
+ * boxes constructed with gtk_combo_box_new_text() and with
  * #GtkComboBoxEntry<!-- -->s.
  *
  * Returns: a newly allocated string containing the currently active text.
+ *     Must be freed with g_free().
  *
  * Since: 2.6
  */