Problem
Note: This is a series of examples to show you how to change tab orders in PHP-GTK2.
Ready for something more challenging? Suppose now you have 12 buttons arranged in a circle. You would like to change the tab order to start from the top right button and traverse round the circle, just like that in a monopoly, as shown below:
Solution
Here are the rules to use GtkContainer::set_focus_chain() again:.
- The method takes only one argument - an array of GtkWidgets.
- All the widgets in the array must be direct descedents of the container.
- It's not necessary to define the tab orders of all levels.
Because of Rule #2 above, there are much rework to be done. Based on the way we want the tab order to be, we have repacked the 12 buttons into the following hboxes and vboxes:
hbox_top_row
to hold buttons 1 to 4.hbox_bottom_row
to hold three vboxes.vbox_column1
holds buttons 5, 6 and 7.vbox_column2
holds only one button: buttons 8.vbox_column3
holds only one button: buttons 9.vbox_column4
holds buttons 10, 11 and 12.
Once you have the hboxes and vboxes in place, you then apply GtkContainer::set_focus_chain():
- To change the tab order to
hbox_top_row
so that it goes from left to right. - To change the tab order to
vbox_column4
so that it goes from bottom to top.
That's it! The rest of the tab order are defaults. So using Rule #3, we do not need to define any of them!
Sample Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 19 20 21 22 23 24 25 26 27 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 54 55 56 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | <?php $window = new GtkWindow(); $window->set_title($argv[0]); $window->set_size_request(480, 240); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); // display title $title = new GtkLabel("Set tab order - Example 4"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 40); $title->set_justify(Gtk::JUSTIFY_CENTER); $alignment = new GtkAlignment(0.5, 0.5, 0, 0); $alignment->add($title); $vbox->pack_start($alignment, 0); $alignment = new GtkAlignment(0.5, 0.5, 0, 0); $alignment->add($label = new GtkLabel( "The tab orders are as indicated on the button.\n". "It starts from the top right button and traverse ". "round the circle like the monopoly")); $label->set_justify(Gtk::JUSTIFY_CENTER); $vbox->pack_start($alignment); $vbox->pack_start(new GtkLabel(), 0); $button_hbox = array(); $vbox->pack_start($hbox_top_row = new GtkHBox(), 0); setup_buttons($hbox_top_row, array(4,3,2,1)); $vbox->pack_start($hbox_bottom_row = new GtkHBox(), 0); $hbox_bottom_row->pack_start($vbox_column1 = new GtkVBox(), 0); setup_buttons($vbox_column1, array(5,6,7)); $hbox_bottom_row->pack_start($vbox_column2 = new GtkVBox(), 0); setup_buttons($vbox_column2, array('', '', 8)); $hbox_bottom_row->pack_start($vbox_column3 = new GtkVBox(), 0); setup_buttons($vbox_column3, array('', '', 9)); $hbox_bottom_row->pack_start($vbox_column4 = new GtkVBox(), 0); setup_buttons($vbox_column4, array(12, 11, 10)); // set the tab order $hbox_top_row->set_focus_chain(array($button_hbox[1], // note 1 $button_hbox[2], $button_hbox[3], $button_hbox[4])); $vbox_column4->set_focus_chain(array($button_hbox[10], // note 2 $button_hbox[11], $button_hbox[12])); $window->show_all(); Gtk::main(); function setup_buttons($container, $button_indexes) { global $button_hbox; foreach($button_indexes as $index) { $hbox = new GtkHBox(); // note 3 $hbox->set_size_request(110, 33); if ($index!='') { $button = new GtkButton("tab order $index"); $button->set_size_request(110, 33); $hbox->pack_start($button, 0); $button->connect('clicked', 'on_click', $index); } $container->pack_start($hbox, 0); $button_hbox[$index] = $hbox; // note 4 } } function on_click($button, $index) { echo "You clicked me: button[$index]!\n"; } ?> |
Output
As shown above.
Explanation
- Set the tab order of
hbox_top_row
to go from right to left. Note the use of $button_box instead of $button, because the direct descendent is $button_box and not $button. Try changing it to $button. You will find that it won't work. - Set the tab order of
vbox_column4
to go from bottom to top. Note the use of $button_box instead of $button, because the direct descendent is $button_box and not $button. - In case you're wondering, I pack the button inside another layer of hbox to make it easy to create the "four holes" at the centre of the monopoly.
- Pay particular attention to this. We need the pointer to the hbox when setting the tab order.
Read more...