258. How to use GtkSheet - Part 11 - setup combobox in cell?

Problem

You would like to display combobox or pulldown menu in a GtkSheet as shown below:

How to use GtkSheet - Part 11 - setup combobox in cell?


Solution

Important Note: This only works for PHP-GTK2 compliled with the additional library GtkExtra. For linux, you can download the files from http://gtkextra.sourceforge.net/ and do a recompile. For windows, you may use the builds by Elizabeth Smith or the official php-gtk2 beta release available at http://gtk.php.net/download.php. Both contain all the required gtkextra libraries and dll's. In the php.ini, don't forget to add php-gtk.extensions = php_gtk_extra2.dll to turn on GtkExtra.


Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
18   
19   
20   
21   
22   
23   
24   
25   
26   
27   
28   
29   
30   
31   
32   
33   
34   
36   
37   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
49   
50   
51   
52   
53   
54   
55   
57   
60   
61   
62   
64   
65   
66   
67   
68   
69   
71   
72   
73   
74   
75   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
88   
92   
93   
94   
98   
99   
103   
104   
105   
114   
115   
116   
117   
118   
119   
124   
125   
128   
129   
130   
131   
132   
133   
134   
135   
136   
137   
138   
139   
140   
141   
142   
143   
144   
145   
146   
147   
148   
149   
151   
152   
153   
161   
162   
163   
164   
165   
166   
167   
168   
169   
174   
<?php
$window = new GtkWindow();
$window->set_title($argv[0]);
$window->set_size_request(480, 250);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Using GtkSheet\n".
"Part 11 - setup combobox in cell");
$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, 0, 0);
$alignment->add($title);
$vbox->pack_start($alignment, 0, 0);
$vbox->pack_start(new GtkLabel(), 0, 0);

// the 2D table
$data = array(
array('row0', 'item 42', 2, 3.1, ''),
array('row1', 'item 36', 20, 6.21, ''),
array('row2', 'item 21', 8, 9.36, ''),
array('row3', 'item 10', 11, 12.4, ''),
array('row4', 'item 7', 5, 15.5, ''),
array('row5', 'item 4', 17, 18.6, ''),
array('row6', 'item 3', 20, 21.73, ''));

$max_col = count($data[0])-1;
$max_row = count($data)-1;

$field_header = array('Row #', 'Description', 'Qty', 'Price', 'Category');
$justification = array('LEFT', 'LEFT', 'CENTER', 'RIGHT', 'LEFT');
$category_list = array('grp 1', 'grp 2', 'grp 3', 'grp 4'); // note 1

$vbox->pack_start($hbox = new GtkHBox(), 0);
$hbox->pack_start($button = new GtkButton('Read Values'), 0);
$sheet = display_table($vbox, $data, $field_header, $justification);

$button->connect('clicked', 'read_values', $sheet);

$window->show_all();
Gtk::main();

function display_table($vbox, $data, $field_header, $justification) {

    $scrolled_win = new GtkScrolledWindow();
    $scrolled_win->set_policy( Gtk::POLICY_AUTOMATIC,
        Gtk::POLICY_AUTOMATIC);
    $vbox->pack_start($scrolled_win);

    $sheet = new GtkSheet(count($data), count($data[0]), 'Test 123');
    $sheet->set_autoresize(1);
    $scrolled_win->add($sheet);

    $sheet->connect('key-press-event', 'on_keypress');

    // set column header
    for ($col=0; $col<count($field_header); ++$col) {
        $sheet->column_button_add_label($col, $field_header[$col]);
        $justify = constant("Gtk::JUSTIFY_".$justification[$col]);
        $sheet->column_button_justify($col, $justify);
    }

    // set up the liststore for combobox
    global $category_list;
    if (defined("GObject::TYPE_STRING")) {
        $model = new GtkListStore(GObject::TYPE_STRING); // note 2
    } else {
        $model = new GtkListStore(Gtk::TYPE_STRING); // note 2
    }
    foreach($category_list as $choice) {
        $model->append(array($choice)); // note 3
    }

    global $combobox;
    $alignment_val = array('LEFT'=>0.0, 'CENTER'=>0.5, 'RIGHT'=>1.0);
    for ($row=0; $row<count($data); ++$row) {
        $sheet->row_button_add_label($row, $row+1);
        for ($col=0; $col<count($data[$row]); ++$col) {

            if ($col==count($data[$row])-1) {
                $combobox[$row][$col] = setup_combobox($model); // note 4
                $sheet->attach_default($combobox[$row][$col], $row, $col); // note 5
            } else {
                $justify = constant("Gtk::JUSTIFY_".$justification[$col]);
                $sheet->set_cell($row, $col, $justify, $data[$row][$col]); // note 6
            }
        }
    }
    return $sheet;
}

function on_keypress($sheet, $event) {
    global $max_col, $max_row;
    list($row, $col) = $sheet->get_active_cell();
    if ($event->keyval == Gdk::KEY_Tab) {
        if ($col<$max_col || $row==$max_row) return false;
        $sheet->set_active_cell($row+1, 0);
        return true;
    } else {
        return false;
    }
}

function setup_combobox($model) {
    $combobox = new GtkComboBox();
    $combobox->set_model($model);
    $cell_renderer = new GtkCellRendererText();
    $combobox->pack_start($cell_renderer);
    $combobox->set_attributes($cell_renderer, 'text', 0);
    return $combobox;
}

function read_values($button, $sheet) {
    global $combobox;
    $num_rows = $sheet->get_rows_count();
    $num_cols = $sheet->get_columns_count();
    for ($row=0; $row<$num_rows; ++$row) {
        for ($col=0; $col<$num_cols; ++$col) {
            if ($col==$num_cols-1) {
                $value = $combobox[$row][$col]->get_active_text();
            } else {
                $value = $sheet->cell_get_text($row, $col);
            }
            if ($value!='') print "row $row col $col: $value\n";
        }
    }
}

?>

Output

As shown above.
 

Explanation

The example above makes use of the code from How to use GtkSheet - Part 2 - read values? and How to use GtkSheet - Part 8 - alternate row colors?

What's new here:

  1. These are the choices that will appear in the combobox.
  2. Create the list store.
  3. Populate the choices.
  4. Set up the combobox. For detailed explanation, please refer to How to setup and process GtkComboBox?
  5. Attach the combobox to the cell.
  6. For all other columns, we use GtkLabel for standard text.

Note

You might want to compare this with the example How to use GtkCellRendererCombo - Part 3 - process user selection? which uses a GtkTreeView.

Also, as I've mentioned in the blog, there's some problem with this method.

Try pressing the Tab key. Did you see the underlying GtkItemEntry?

I'm not sure if this is a feature or a bug. Although I could find some ways to "gobble" up the Tab or arrow keys so that the GtkItemEntry doesn't appear, I know this should not be the right way of doing things.

Anybody knows how to "deactivate" the underlying GtkItemEntry?

Related Links

Add comment


Security code
Refresh