--- gtk+-2.6.4/gtk/gtkhbbox.c 2004-08-09 19:59:52.000000000 +0300 +++ gtk+-2.6.4/gtk/gtkhbbox.c 2005-04-06 16:19:36.644967480 +0300 @@ -24,10 +24,20 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +/* Modified for Nokia Oyj during 2002-2005. See CHANGES file for list + * of changes. + */ + +/* Hildon : Button spacing according to the spec. */ +#define HILDON_BUTTON_SPACING 5 +/* Selecting hetefogenous mode for a childlayout */ +#define GTK_BUTTONBOX_HETEROGENOUS 6 + #include #include "gtkalias.h" #include "gtkhbbox.h" - +/* Hildon : We need this to mess with buttons graphics. */ +#include "gtkbutton.h" static void gtk_hbutton_box_class_init (GtkHButtonBoxClass *klass); static void gtk_hbutton_box_init (GtkHButtonBox *box); @@ -36,6 +46,15 @@ static void gtk_hbutton_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation); +static void osso_gtk_hbutton_child_showhide_handler (GtkWidget *widget, + gpointer user_data); +static void osso_gtk_hbutton_box_remove_child_signal_handlers (GtkHButtonBox *hbbox, + GtkWidget *removed_widget, + gpointer data); +static void osso_gtk_hbutton_box_find_button_detail (GtkHButtonBox *hbbox, + GtkWidget *addremovewidget, + gpointer data); + static gint default_spacing = 30; static gint default_layout_style = GTK_BUTTONBOX_EDGE; @@ -76,12 +95,23 @@ widget_class->size_request = gtk_hbutton_box_size_request; widget_class->size_allocate = gtk_hbutton_box_size_allocate; + + /* HILDON: + * Name buttons only if hildon like style property is set + */ + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boolean + ( "hildonlike", + "hildonlike looks", + "Name buttons, 1/0", + FALSE, + G_PARAM_READABLE) ); } static void gtk_hbutton_box_init (GtkHButtonBox *hbutton_box) { - /* button_box_init has done everything allready */ + /* button_box_init has done everything allready */ } GtkWidget* @@ -91,6 +121,24 @@ hbutton_box = g_object_new (GTK_TYPE_HBUTTON_BOX, NULL); + /* Attach signal handler for 'hildonizing' buttons. + * gtk_hbutton_box_hildonize_buttons will check the name + * and if it is something we're interested in i.e. + * + * hildon_dialogbuttons + * hildon_viewbuttons + * + * it will do the hildonizing + */ + g_signal_connect_after (G_OBJECT (hbutton_box), "remove", + G_CALLBACK (osso_gtk_hbutton_box_remove_child_signal_handlers), + NULL); + g_signal_connect_after( G_OBJECT( hbutton_box ), "add", + G_CALLBACK( osso_gtk_hbutton_box_find_button_detail ), + NULL ); + g_signal_connect_after( G_OBJECT( hbutton_box ), "remove", + G_CALLBACK( osso_gtk_hbutton_box_find_button_detail ), + NULL ); return GTK_WIDGET (hbutton_box); } @@ -145,6 +193,11 @@ gint child_height; gint spacing; GtkButtonBoxStyle layout; + gint child_xpad=0; + GtkBoxChild *child_req; + GList *children_req; + GtkRequisition treq; + box = GTK_BOX (widget); bbox = GTK_BUTTON_BOX (widget); @@ -159,6 +212,12 @@ &child_width, &child_height); + /* should GTK_BUTTONBOX_HETEROGENOUS add into the GtkButtonBoxStyle + enum struct + */ + if( !box->homogeneous ) + layout = GTK_BUTTONBOX_HETEROGENOUS; + if (nvis_children == 0) { requisition->width = 0; @@ -177,11 +236,36 @@ case GTK_BUTTONBOX_END: requisition->width = nvis_children*child_width + ((nvis_children-1)*spacing); break; + case GTK_BUTTONBOX_HETEROGENOUS: + children_req = GTK_BOX (box)->children; + child_req = children_req->data; + requisition->width = 0; + + while (children_req) + { + child_req = children_req->data; + children_req = children_req->next; + + if (GTK_WIDGET_VISIBLE (child_req->widget)) + { + gtk_widget_get_child_requisition( child_req->widget, + &(treq) ); + requisition->width += treq.width; + + gtk_widget_style_get(widget, + "child-internal-pad-x", + &(child_xpad), NULL); + requisition->width += (child_xpad*2); + } + } + requisition->width += ((nvis_children-1)*spacing); + + break; default: g_assert_not_reached(); break; } - + requisition->height = child_height; } @@ -227,6 +311,10 @@ &child_height); widget->allocation = *allocation; width = allocation->width - GTK_CONTAINER (box)->border_width*2; + + if( !base_box->homogeneous ) + layout = GTK_BUTTONBOX_HETEROGENOUS; + switch (layout) { case GTK_BUTTONBOX_SPREAD: @@ -264,6 +352,39 @@ - GTK_CONTAINER (box)->border_width; secondary_x = allocation->x + GTK_CONTAINER (box)->border_width; break; + case GTK_BUTTONBOX_HETEROGENOUS: + { + gint sumwidth = 0; + GtkBoxChild *child_h; + GList *children_h = GTK_BOX (box)->children; + /* heterogenous sized childs onto center */ + childspacing = spacing; + child_h = children_h->data; + + while (children_h ) + { + if ( g_list_length (children_h) == 0 ) break; + + child_h = children_h->data; + children_h = children_h->next; + + if (GTK_WIDGET_VISIBLE (child_h->widget)) + { + gint child_xpad = 0; + GtkRequisition treq; + gtk_widget_get_child_requisition( child_h->widget, &(treq) ); + sumwidth += treq.width; + + gtk_widget_style_get(widget, + "child-internal-pad-x", + &(child_xpad), NULL); + sumwidth += (child_xpad*2); + } + } + x = secondary_x = allocation->x + + ( (allocation->width - sumwidth - (spacing * (nvis_children - 1)))/2 ); + break; + } default: g_assert_not_reached(); break; @@ -282,10 +403,33 @@ if (GTK_WIDGET_VISIBLE (child->widget)) { - child_allocation.width = child_width; child_allocation.height = child_height; child_allocation.y = y; + if(layout != GTK_BUTTONBOX_HETEROGENOUS) + { + child_allocation.width = child_width; + } + else /* if layout will be hetergenous */ + { + gint child_hwidth = 0; + GtkRequisition treq; + gint child_xpad = 0; + + gtk_widget_get_child_requisition( child->widget, &(treq) ); + child_hwidth += treq.width; + + gtk_widget_style_get(widget, + "child-internal-pad-x", + &child_xpad, NULL); + child_hwidth += (child_xpad*2); + + child_allocation.width = child_hwidth; + childspace = child_hwidth + childspacing; + + } + + /* calculate the horizontal location */ if (child->is_secondary) { child_allocation.x = secondary_x; @@ -304,4 +448,104 @@ } } } + +/* Function to wrap "hide" and "show" signals to call + * osso_gtk_hbutton_box_find_button_detail -function.*/ +static void osso_gtk_hbutton_child_showhide_handler (GtkWidget *widget, + gpointer user_data) +{ + osso_gtk_hbutton_box_find_button_detail (widget, GTK_WIDGET (user_data), NULL); +} +/* Function to remove "show"&"hide" signal handlers + * from a child when it's removed. */ +static void osso_gtk_hbutton_box_remove_child_signal_handlers (GtkHButtonBox *hbbox, + GtkWidget *removed_widget, + gpointer data) +{ + g_signal_handlers_disconnect_by_func (G_OBJECT (removed_widget), osso_gtk_hbutton_box_find_button_detail, hbbox); +} + +/* Signal handler called when we have to set + * painting detail values for buttons in this + * gtk_horizontal_button_box. + */ +static void osso_gtk_hbutton_box_find_button_detail (GtkHButtonBox *hbbox, + GtkWidget *addremovewidget, + gpointer data) +{ + GList *child; + gint visible_buttons = 0; + gint secondary_buttons = 0; + GtkWidget *leftmost_button = NULL; + GtkWidget *rightmost_button = NULL; + + for( child = GTK_BOX (hbbox)->children ; child ; child = child->next ) + { + GtkBoxChild *box_child = child->data; + GtkWidget *child_widget = box_child->widget; + gulong signal_handler = g_signal_handler_find ( G_OBJECT( child_widget ), + G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, + G_CALLBACK (osso_gtk_hbutton_child_showhide_handler), + NULL); + + if (signal_handler == 0) + { + g_signal_connect_object ( G_OBJECT( child_widget ), + "hide", + G_CALLBACK ( osso_gtk_hbutton_child_showhide_handler ), + hbbox, G_CONNECT_SWAPPED); + g_signal_connect_object ( G_OBJECT( child_widget ), + "show", + G_CALLBACK ( osso_gtk_hbutton_child_showhide_handler ), + hbbox, G_CONNECT_SWAPPED); + } + + if ((GTK_WIDGET_VISIBLE (child_widget)) && + (GTK_IS_BUTTON (child_widget))) + visible_buttons++; + else + continue; + + if (leftmost_button == NULL) + leftmost_button = child_widget; + + if (secondary_buttons == 0) + rightmost_button = child_widget; + else + if (box_child->is_secondary) + { + rightmost_button = child_widget; + secondary_buttons++; + } + + if (box_child->is_secondary) + rightmost_button = child_widget; + } + + if (visible_buttons == 0) + return; + + for( child = GTK_BOX (hbbox)->children ; child ; child = child->next ) + { + GtkBoxChild *box_child = child->data; + GtkWidget *child_widget = box_child->widget; + OssoGtkButtonAttachFlags attachflags = OSSO_GTK_BUTTON_ATTACH_NORTH | OSSO_GTK_BUTTON_ATTACH_SOUTH; + gboolean automatic_detail; + + if (!((GTK_WIDGET_VISIBLE (child_widget)) && + (GTK_IS_BUTTON (child_widget)))) + continue; + + if (child_widget == leftmost_button) + attachflags |= OSSO_GTK_BUTTON_ATTACH_WEST; + + if (child_widget == rightmost_button) + attachflags |= OSSO_GTK_BUTTON_ATTACH_EAST; + + g_object_get (G_OBJECT (child_widget), "automatic_detail", &automatic_detail, NULL); + if (automatic_detail == TRUE) + g_object_set (G_OBJECT (child_widget), "detail", osso_gtk_button_attach_details[attachflags], NULL); + } +}