gtk/tests/testheightforwidth.c
Tristan Van Berkom e83a8826e6 Implemented GtkSizeRequest on GtkExpander and added test
Now the expander requests and distributes space naturally,
the expander widget prioritizes the child widget vertically
and only allocates the minimum height for width to the label
widget.
2010-08-05 12:50:25 -04:00

690 lines
30 KiB
C

/* extendedlayoutexample.c
* Copyright (C) 2010 Openismus GmbH
*
* Author:
* Tristan Van Berkom <tristan.van.berkom@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gtk/gtk.h>
typedef struct {
const gchar *name;
const gchar *tooltip;
const gchar *interface;
GtkWidget *window;
} TestInterface;
/* These strings were generated with:
*
* IFS=""; while read line; do echo -n \"; echo -n $line | sed -e 's|\"|\\"|g'; echo \"; done < file.glade
*/
TestInterface interfaces[] = {
{
"Ellipsizing Labels",
"Demonstrates how labels will request a natural size in a horizontal space",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_width\">450</property>"
" <property name=\"default_height\">50</property>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox5\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label9\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Some labels do ellipsize</property>"
" <property name=\"ellipsize\">end</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#09610feefe03\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label10\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">but some</property>"
" <property name=\"ellipsize\">end</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#0000af6b0993\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label11\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">do not at all</property>"
" <attributes>"
" <attribute name=\"style\" value=\"normal\"/>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">2</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Wrapping Label",
"Demonstrates how a wrapping label can require a height contextual to its allocated width",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.18\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"border_width\">12</property>"
" <property name=\"default_width\">300</property>"
" <child>"
" <object class=\"GtkHPaned\" id=\"hpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkVBox\" id=\"vbox2\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label3\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">A short static label.</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkFrame\" id=\"frame1\">"
" <property name=\"label\">Long label</property>"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This is a really long label for the purpose of testing line wrapping is working correctly in conjunction with height-for-width support in GTK+</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"max_width_chars\">30</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#18c52119f796\"/>"
" </attributes>"
" </object>"
" </child>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkButton\" id=\"button2\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <property name=\"receives_default\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">A really really long label inside a button to demonstrate height for width working inside buttons</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"max_width_chars\">25</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#1e3687ab0a52\"/>"
" </attributes>"
" </object>"
" </child>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">2</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label4\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This static label\n"
"can shrink.</property>"
" <property name=\"justify\">center</property>"
" <attributes>"
" <attribute name=\"style\" value=\"normal\"/>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"resize\">True</property>"
" <property name=\"shrink\">True</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Horizontal Box",
"Demonstrates how a horizontal box can calculate the collective height for an allocated width",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_height\">200</property>"
" <property name=\"default_width\">600</property>"
" <child>"
" <object class=\"GtkHPaned\" id=\"hpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkVBox\" id=\"vbox1\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox1\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkButton\" id=\"button1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <property name=\"receives_default\">True</property>"
" <property name=\"use_action_appearance\">False</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">A button that wraps.</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#0000041dffff\"/>"
" </attributes>"
" </object>"
" </child>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Lets try setting up some long text to wrap up in this hbox and see if the height-for-width is gonna work !</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">30</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#07d0a9b20972\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkButton\" id=\"button2\">"
" <property name=\"label\" translatable=\"yes\">A button that expands in the vbox</property>"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <property name=\"receives_default\">True</property>"
" <property name=\"use_action_appearance\">False</property>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label4\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This label is\n"
"set to shrink inside\n"
"the paned window.</property>"
" <property name=\"justify\">center</property>"
" <attributes>"
" <attribute name=\"style\" value=\"normal\"/>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"resize\">True</property>"
" <property name=\"shrink\">True</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Vertical Labels",
"Demonstrates how a horizontal box will consider width-for-height when allocating children "
"even if the toplevel window is requested as height-for-width.",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_width\">400</property>"
" <property name=\"default_height\">300</property>"
" <child>"
" <object class=\"GtkVPaned\" id=\"vpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox1\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Some long width-for-height text that wraps</property>"
" <property name=\"justify\">center</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <property name=\"angle\">90</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#03e307ddfb5f\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkFrame\" id=\"frame1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label_xalign\">0</property>"
" <property name=\"shadow_type\">out</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label5\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Neither of the panes are\n"
"set to shrink.</property>"
" <property name=\"justify\">center</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" </child>"
" <child type=\"label_item\">"
" <placeholder/>"
" </child>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox2\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkFrame\" id=\"frame2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label_xalign\">0</property>"
" <property name=\"shadow_type\">out</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label4\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">The interface is allocated as height\n"
"for width, but the horizontal boxes\n"
"allocate in width for height mode.</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#000097970808\"/>"
" </attributes>"
" </object>"
" </child>"
" <child type=\"label_item\">"
" <placeholder/>"
" </child>"
" </object>"
" <packing>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label3\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Some long width-for-height text that wraps</property>"
" <property name=\"justify\">center</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <property name=\"angle\">270</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#03e307ddfb5f\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Label Parameters",
"This test demonstrates how \"width-chars\" and \"max-width-chars\" can be used "
"to effect minimum and natural widths in wrapping labels.",
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_width\">900</property>"
" <child>"
" <object class=\"GtkHPaned\" id=\"hpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkVBox\" id=\"vbox1\">"
" <property name=\"visible\">True</property>"
" <child>"
" <object class=\"GtkHBox\" id=\"hbox1\">"
" <property name=\"visible\">True</property>"
" <property name=\"spacing\">6</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">The first 2 labels require 10 characters.</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">False</property>"
" <property name=\"fill\">False</property>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This label has a maximum natural width of 20 characters. The second two labels expand.</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <property name=\"max_width_chars\">20</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#05c2a161134b\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"expand\">True</property>"
" <property name=\"fill\">True</property>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label3\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This label requires a default minimum size.</property>"
" <property name=\"wrap\">True</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#03e30758fb5f\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">2</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"position\">0</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label4\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">This test demonstrates how the \"width-chars\" and \"max-width-chars\"\n"
"properties can be used to specify the minimum requested wrap width\n"
"and the maximum natural wrap width respectively.</property>"
" <property name=\"ellipsize\">end</property>"
" <property name=\"width_chars\">30</property>"
" <attributes>"
" <attribute name=\"style\" value=\"normal\"/>"
" <attribute name=\"foreground\" value=\"#05470000abaf\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"position\">1</property>"
" </packing>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label5\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Some static\n"
"text that shrinks.\n"
"\n"
"You will need to stretch\n"
"this window quite wide\n"
"to see the effects.</property>"
" <property name=\"justify\">center</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"#ffff00000000\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"resize\">True</property>"
" <property name=\"shrink\">True</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
{
"Wrapping Expander",
"This test demonstrates how the expander label can fill to its natural width "
"and also trade height for width.",
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<interface>"
" <requires lib=\"gtk+\" version=\"2.20\"/>"
" <!-- interface-naming-policy project-wide -->"
" <object class=\"GtkWindow\" id=\"window\">"
" <property name=\"default_width\">500</property>"
" <child>"
" <object class=\"GtkHPaned\" id=\"hpaned1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkExpander\" id=\"expander1\">"
" <property name=\"visible\">True</property>"
" <property name=\"can_focus\">True</property>"
" <child>"
" <object class=\"GtkLabel\" id=\"label2\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">More wrapping text to fill the largish content area in the expander </property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"#0000D0F00000\"/>"
" </attributes>"
" </object>"
" </child>"
" <child type=\"label\">"
" <object class=\"GtkLabel\" id=\"label1\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">Here is some expander text that wraps</property>"
" <property name=\"wrap\">True</property>"
" <property name=\"width_chars\">10</property>"
" <attributes>"
" <attribute name=\"weight\" value=\"bold\"/>"
" <attribute name=\"foreground\" value=\"blue\"/>"
" </attributes>"
" </object>"
" </child>"
" </object>"
" <packing>"
" <property name=\"resize\">False</property>"
" <property name=\"shrink\">False</property>"
" </packing>"
" </child>"
" <child>"
" <object class=\"GtkLabel\" id=\"label3\">"
" <property name=\"visible\">True</property>"
" <property name=\"label\" translatable=\"yes\">static\n"
"text\n"
"here</property>"
" <attributes>"
" <attribute name=\"foreground\" value=\"red\"/>"
" </attributes>"
" </object>"
" <packing>"
" <property name=\"resize\">True</property>"
" <property name=\"shrink\">True</property>"
" </packing>"
" </child>"
" </object>"
" </child>"
" </object>"
"</interface>",
NULL
},
};
static void
test_clicked (GtkWidget *button,
TestInterface *interface)
{
if (!interface->window)
{
GtkBuilder *builder = gtk_builder_new ();
gtk_builder_add_from_string (builder, interface->interface, -1, NULL);
interface->window = (GtkWidget *)gtk_builder_get_object (builder, "window");
g_signal_connect (interface->window, "delete_event",
G_CALLBACK (gtk_widget_hide_on_delete), NULL);
}
gtk_widget_show (interface->window);
}
static GtkWidget *
create_window (void)
{
GtkWidget *window, *vbox, *button;
gint i;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
vbox = gtk_vbox_new (FALSE, 6);
gtk_container_set_border_width (GTK_CONTAINER (window), 8);
gtk_widget_show (vbox);
gtk_container_add (GTK_CONTAINER (window), vbox);
for (i = 0; i < G_N_ELEMENTS (interfaces); i++)
{
button = gtk_button_new_with_label (interfaces[i].name);
gtk_widget_set_tooltip_text (button, interfaces[i].tooltip);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (test_clicked), &interfaces[i]);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
}
return window;
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
gtk_init (&argc, &argv);
window = create_window ();
g_signal_connect (window, "delete-event",
G_CALLBACK (gtk_main_quit), window);
gtk_widget_show (window);
gtk_main ();
return 0;
}