415. How to switch signal handlers on the fly - Part 2 - using block unblock?

Problem

This is in response to Manar's post titled "How to disconnect an event?"

He has set up a button-press-event, and he would like to switch the signal handler processing the button-press-event depending on some conditions.

In Part 1 we used the methods connect() and disconnect().

In this Part 2, we'll use the methods block() and unblock() as shown below:

How to switch signal handlers on the fly - Part 2 - using block unblock?


Solution

  • If you need to 'connect', 'disconnect' and 'reconnect' a signal repeatedly such as the case shown in this example, you might want to consider using GObject::block() and GObject::unblock($signal_handler_id) (instead of connect/disconnect) to switch the signal handlers.
  • The effect of the above sample code is exactly the same as that of the previous example using connect/disconnect.

Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
17   
18   
19   
20   
21   
22   
23   
24   
25   
26   
27   
28   
29   
30   
31   
32   
33   
34   
35   
36   
37   
38   
40   
41   
42   
43   
44   
45   
46   
47   
48   
49   
51   
52   
53   
54   
57   
58   
59   
60   
61   
62   
63   
64   
65   
66   
67   
69   
70   
71   
72   
73   
74   
75   
76   
77   
78   
79   
80   
81   
82   
83   
<?php
$window = new GtkWindow();
$window->set_size_request(400, 175);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Switching signal handlers on the fly\n".
"Part 2 - using block / unblock");
$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);
$vbox->pack_start($title, 0);
$vbox->pack_start(new GtkLabel(), 0);

$label = new GtkLabel('Click on the blue sqaure once. '.
    'It will change to green.');
$vbox->pack_start($label, 0);

setup_colorbox('#0000ff', 'blue', $vbox); // note 1

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


function setup_colorbox($color, $label, $vbox) {
    $hbox = new GtkHBox();
    $hbox->set_size_request(30, 30);
    $eventbox = new GtkEventBox();
    $eventbox->add($hbox);
    $eventbox->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse($color));

    global $signal_id1, $signal_id2;
    $signal_id1 = $eventbox->connect('button-press-event', 
        'on_button_press1'); // note 2
    $signal_id2 = $eventbox->connect('button-press-event', 
        'on_button_press2'); // note 2
    $eventbox->block($signal_id2); // note 3

    $hbox = new GtkHBox();
    $vbox->pack_start($hbox, 0);
    $hbox->pack_start(new GtkLabel());
    $hbox->pack_start($eventbox, 0);
    $hbox->pack_start(new GtkLabel());

}

function on_button_press1($eventbox, $event) {
    if ($event->type!=Gdk::BUTTON_PRESS) return false;
    echo "on_button_press1!\n";
    $eventbox->modify_bg(Gtk::STATE_NORMAL,
        GdkColor::parse('#00ff00'));

    global $signal_id1, $signal_id2;
    $eventbox->block($signal_id1); // note 4
    $eventbox->unblock($signal_id2); // note 4

    global $label;
    $label->set_text('Click on this again. It will change to yellow.');
    return true;
}

function on_button_press2($eventbox, $event) {
    if ($event->type!=Gdk::BUTTON_PRESS) return false;
    echo "on_button_press2!\n";
    $eventbox->modify_bg(Gtk::STATE_NORMAL,
        GdkColor::parse('#ffff00'));

    global $signal_id1, $signal_id2;
    $eventbox->block($signal_id2); // note 5
    $eventbox->unblock($signal_id1);  // note 5

    global $label;
    $label->set_text('Click on this again. It will change to green.');
    return true;
}

?>

Output

As shown above.

 

Explanation

We make use of the code from How to switch signal handlers on the fly - Part 1 - using connect disconnect?

What's new here:

  1. Set up the blue color box.
  2. Set up the button-press-event signal. Note that here we register two callback functions on the same button. Don't forget to take note of the signal handler id's.
  3. Block the second callback function so that only the first one is active.
  4. Block the first callback function and unblock the second callback function.
  5. Block the second callback function and unblock the first callback function.

Related Links

Add comment


Security code
Refresh