257. How to use GtkSheet - Part 10 - display image in cell?

Problem

You would like to display images in a GtkSheet as shown below:

How to use GtkSheet - Part 10 - display image 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

The following image files are required by the sample code below. Please save a copy of the image files and put them in the same directory where you store the sample code.

 ball_red.png
 ball_green.png

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   
35   
36   
37   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
49   
50   
51   
53   
54   
57   
58   
59   
61   
62   
63   
64   
65   
66   
67   
68   
69   
70   
71   
72   
73   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
91   
92   
93   
94   
95   
99   
100   
101   
102   
103   
108   
109   
112   
113   
114   
115   
116   
117   
118   
119   
120   
125   
<?php
$window = new GtkWindow();
$window->set_title($argv[0]);
$window->set_size_request(430, 250);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Using GtkSheet\n".
"Part 10 - display image 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);
$vbox->pack_start(new GtkLabel('red: Qty<10'), 0, 0);
$vbox->pack_start(new GtkLabel('green: Qty>=10'), 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', 'Status'); // note 1
$justification = array('LEFT', 'LEFT', 'CENTER', 'CENTER');

display_table($vbox, $data, $field_header, $justification);

$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 = GtkSheet::new_browser(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);
    }

    global $eventbox;
    $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) {
            $eventbox[$row][$col] = new GtkEventBox();
            $alignment = new GtkAlignment(
                $alignment_val[$justification[$col]], 0.5, 0, 0);
            $alignment->set_padding(0, 0, 2, 2);

            if ($col==count($data[$row])-1) { // note 2
                if ($data[$row][2]<10) {
                    $img = GtkImage::new_from_file('ball_red.png'); // note 3
                } else {
                    $img = GtkImage::new_from_file('ball_green.png'); // note 4
                }
                $alignment->add($img); // note 5
            } else {
                $alignment->add(new GtkLabel($data[$row][$col])); // note 6
            }
            $eventbox[$row][$col]->add($alignment);
            $row_color = ($row%2==1) ? '#dddddd' : '#ffffff';
            $eventbox[$row][$col]->modify_bg(Gtk::STATE_NORMAL,
                GdkColor::parse($row_color));
            $sheet->attach_default($eventbox[$row][$col], $row, $col);
        }
    }
}

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;
    }
}

?>

Output

As shown above.
 

Explanation

The example above makes use of the code from How to use GtkSheet - Part 9 - using attach with justification?

What's new here:

  1. Note that the last column is now status.
  2. Check if this is the last column.
  3. If quantity is less than 10, we display a red ball.
  4. If quantity is more than 10, we display a green ball.
  5. Stuff the GtkImage in the GtkAlignment.
  6. For all other columns, we use GtkLabel for standard text.

Note

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