cvs: php-gtk /ext/gtk+ gtk.overrides /main php_gtk_object.c /test gtk.php

From: Date: Sat, 18 Aug 2001 05:49:34 +0000
Subject: cvs: php-gtk /ext/gtk+ gtk.overrides /main php_gtk_object.c /test gtk.php
Groups: php.gtk 
Request: Send a blank email to php-gtk+get-2885@lists.php.net to get a copy of this message
andrei Sat Aug 18 01:49:34 2001 EDT Modified files: /php-gtk/ext/gtk+ gtk.overrides /php-gtk/main php_gtk_object.c /php-gtk/test gtk.php Log: - Fixed callbacks bug that would not invoke a callback if it took a parameter by reference. - Changed "GTK_TYPE_POINTER not supported" from warning to notice and made it return NULL instead of aborting. - Integrated a patch from Markus that implements functions signal_(add|remove)_emission_hook(), signal_lookup(), signal_name() and adds a few more examples to gtk.php.

Index: php-gtk/ext/gtk+/gtk.overrides diff -u php-gtk/ext/gtk+/gtk.overrides:1.12 php-gtk/ext/gtk+/gtk.overrides:1.13 --- php-gtk/ext/gtk+/gtk.overrides:1.12 Wed Aug 15 13:05:15 2001 +++ php-gtk/ext/gtk+/gtk.overrides Sat Aug 18 01:49:33 2001 @@ -9,7 +9,6 @@ gtk_arg_* gtk_args_* gtk_signal_connect* - gtk_signal_add_emission_hook* gtk_signal_new* gtk_init_add_* gtk_quit_add_* @@ -43,8 +42,8 @@ gtk_accel_group_create_remove gtk_accel_groups_from_object gtk_accel_group_entries_from_object + gtk_signal_add_emission_hook_full gtk_signal_set_funcs - gtk_signal_lookup gtk_signal_disconnect_by_func gtk_signal_disconnect_by_data gtk_signal_handler_block_by_func @@ -54,8 +53,6 @@ gtk_signal_handler_pending_by_func gtk_signal_n_emissions gtk_signal_n_emissions_by_name - gtk_signal_name - gtk_signal_remove_emission_hook gtk_signal_query gtk_signal_emit gtk_signal_emit_by_name @@ -297,6 +294,103 @@ data, php_gtk_destroy_notify)); } %% +override gtk_signal_add_emission_hook + +static void php_gtk_emission_hook_marshal(GtkObject *o, guint signal_id, guint nargs, GtkArg *args, gpointer data) +{ + zval *callback_data = (zval *)data; + zval *gtk_args; + zval **callback, **extra = NULL; + zval **callback_filename = NULL, **callback_fileno = NULL; + zval ***hook_args; + zval *wrapper = NULL; + zval *params; + zval *retval = NULL; + char *callback_name; + TSRMLS_FETCH(); + + /* Callback is always passed as the first element. */ + zend_hash_index_find(Z_ARRVAL_P(callback_data), 0, (void**)&callback); + + /* Extra parametrers are always passed as the second element. */ + zend_hash_index_find(Z_ARRVAL_P(callback_data), 1, (void**)&extra); + + /* Third and fourth parameter are always filename and the line number where + * the callback was specified. */ + zend_hash_index_find(Z_ARRVAL_P(callback_data), 2, (void**)&callback_filename); + zend_hash_index_find(Z_ARRVAL_P(callback_data), 3, (void**)&callback_fileno); + + if (!php_gtk_is_callable(*callback, 0, &callback_name)) { + php_error(E_WARNING, "Unable to call emission hook '%s' specified in %s on line %d", callback_name, Z_STRVAL_PP(callback_filename), Z_LVAL_PP(callback_fileno)); + efree(callback_name); + return; + } + + wrapper = php_gtk_new(o); + + /* Prepare the parameters to be passed to the user function. */ + MAKE_STD_ZVAL(params); + array_init(params); + /* Pass the object which emitted the signal as first parameer. */ + add_next_index_zval(params, wrapper); + /* Pass the signal id as second parameter. */ + add_next_index_long(params, signal_id); + + gtk_args = php_gtk_args_as_hash(nargs, args); + php_array_merge(Z_ARRVAL_P(params), Z_ARRVAL_P(gtk_args), 0); + + zval_ptr_dtor(&gtk_args); + + /* + * If there are extra arguments specified by user, add them to the parameter + * array. + */ + if (extra) + php_array_merge(Z_ARRVAL_P(params), Z_ARRVAL_PP(extra), 0); + + hook_args = php_gtk_hash_as_array(params); + + call_user_function_ex(EG(function_table), NULL, *callback, &retval, + zend_hash_num_elements(Z_ARRVAL_P(params)), hook_args, + 0, NULL TSRMLS_CC); + + if (retval) { + if (args) + php_gtk_ret_from_value(&args[nargs], retval); + zval_ptr_dtor(&retval); + } + + efree(hook_args); + zval_ptr_dtor(&params); +} + +PHP_FUNCTION(gtk_signal_add_emission_hook) +{ + guint signal_id; + zval *callback; + char *callback_filename; + uint callback_lineno; + zval *extra; + zval *data; + + if (ZEND_NUM_ARGS() < 2) { + php_error(E_WARNING, "%s() requires at least 2 arguments, %d given", + get_active_function_name(TSRMLS_C), ZEND_NUM_ARGS()); + return; + } + + if (!php_gtk_parse_args(2, "iV", &signal_id, &callback)) + return; + + callback_filename = zend_get_executed_filename(TSRMLS_C); + callback_lineno = zend_get_executed_lineno(TSRMLS_C); + extra = php_gtk_func_args_as_hash(ZEND_NUM_ARGS(), 2, ZEND_NUM_ARGS()); + data = php_gtk_build_value("(VNsi)", callback, extra, callback_filename, callback_lineno); + RETURN_LONG(gtk_signal_add_emission_hook_full(signal_id, + (GtkEmissionHook)php_gtk_emission_hook_marshal, + data, php_gtk_destroy_notify)); +} +%% override gtk_signal_connect static void gtk_signal_connect_impl(INTERNAL_FUNCTION_PARAMETERS, int pass_object, int after) { @@ -1260,7 +1354,7 @@ args = php_gtk_hash_as_array(params); - call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), args, 1, NULL TSRMLS_CC); + call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), args, 0, NULL TSRMLS_CC); if (retval) zval_ptr_dtor(&retval); efree(args); @@ -1426,7 +1520,7 @@ args = php_gtk_hash_as_array(params); - call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), args, 1, NULL TSRMLS_CC); + call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), args, 0, NULL TSRMLS_CC); if (retval) zval_ptr_dtor(&retval); efree(args); @@ -2001,7 +2095,7 @@ params = php_gtk_build_value("(Nii)", php_gtk_new(GTK_OBJECT(menu)), *x, *y); args = php_gtk_hash_as_array(params); - call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), args, 1, NULL TSRMLS_CC); + call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), args, 0, NULL TSRMLS_CC); if (retval) { if (Z_TYPE_P(retval) == IS_ARRAY && Index: php-gtk/main/php_gtk_object.c diff -u php-gtk/main/php_gtk_object.c:1.45 php-gtk/main/php_gtk_object.c:1.46 --- php-gtk/main/php_gtk_object.c:1.45 Mon Aug 6 13:08:11 2001 +++ php-gtk/main/php_gtk_object.c Sat Aug 18 01:49:34 2001 @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: php_gtk_object.c,v 1.45 2001/08/06 17:08:11 fmk Exp $ */ +/* $Id: php_gtk_object.c,v 1.46 2001/08/18 05:49:34 andrei Exp $ */ #include "php_gtk.h" @@ -218,7 +218,7 @@ signal_args = php_gtk_hash_as_array(params); - call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), signal_args, 1, NULL TSRMLS_CC); + call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), signal_args, 0, NULL TSRMLS_CC); if (retval) { if (args) @@ -256,7 +256,7 @@ handler_args = php_gtk_hash_as_array(*extra); num_handler_args = zend_hash_num_elements(Z_ARRVAL_PP(extra)); - call_user_function_ex(EG(function_table), NULL, *callback, &retval, num_handler_args, handler_args, 1, NULL TSRMLS_CC); + call_user_function_ex(EG(function_table), NULL, *callback, &retval, num_handler_args, handler_args, 0, NULL TSRMLS_CC); *GTK_RETLOC_BOOL(args[0]) = FALSE; if (retval) { @@ -297,7 +297,7 @@ php_array_merge(Z_ARRVAL_P(params), Z_ARRVAL_PP(extra), 0); input_args = php_gtk_hash_as_array(params); - call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), input_args, 1, NULL TSRMLS_CC); + call_user_function_ex(EG(function_table), NULL, *callback, &retval, zend_hash_num_elements(Z_ARRVAL_P(params)), input_args, 0, NULL TSRMLS_CC); if (retval) zval_ptr_dtor(&retval); efree(input_args); @@ -510,9 +510,11 @@ break; case GTK_TYPE_POINTER: - php_error(E_WARNING, "%s(): internal error: GTK_TYPE_POINTER unsupported", + php_error(E_NOTICE, "%s(): internal error: GTK_TYPE_POINTER unsupported", get_active_function_name(TSRMLS_C)); - return NULL; + MAKE_STD_ZVAL(value); + ZVAL_NULL(value); + break; case GTK_TYPE_BOXED: if (arg->type == GTK_TYPE_GDK_EVENT) @@ -801,9 +803,11 @@ break; case GTK_TYPE_POINTER: - php_error(E_WARNING, "%s(): internal error: GTK_TYPE_POINTER unsupported", + php_error(E_NOTICE, "%s(): internal error: GTK_TYPE_POINTER unsupported", get_active_function_name(TSRMLS_C)); - return NULL; + MAKE_STD_ZVAL(value); + ZVAL_NULL(value); + break; case GTK_TYPE_BOXED: if (ret->type == GTK_TYPE_GDK_EVENT) Index: php-gtk/test/gtk.php diff -u php-gtk/test/gtk.php:1.32 php-gtk/test/gtk.php:1.33 --- php-gtk/test/gtk.php:1.32 Wed Aug 8 16:49:09 2001 +++ php-gtk/test/gtk.php Sat Aug 18 01:49:34 2001 @@ -1,5 +1,5 @@ <?php -/* $Id: gtk.php,v 1.32 2001/08/08 20:49:09 andrei Exp $ */ +/* $Id: gtk.php,v 1.33 2001/08/18 05:49:34 andrei Exp $ */ if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') dl('php_gtk.dll'); @@ -1938,6 +1938,317 @@ $windows['entry']->show(); } +function toggle_resize($child) +{ + $paned = $child->parent; + + $is_child1 = ($child == $paned->child1); + + $resize = $is_child1 ? $paned->child1_resize : $paned->child2_resize; + $shrink = $is_child1 ? $paned->child1_shrink : $paned->child2_shrink; + + $child->ref(); + + // Zend doesn't yet support overloaded method calls + $parent = $child->parent; + $parent->remove($child); + + if ($is_child1) + $paned->pack1($child, !$resize, $shrink); + else + $paned->pack2($child, !$resize, $shrink); + + $child->unref(); +} + +function toggle_shrink($child) +{ + $paned = $child->parent; + + $is_child1 = ($child == $paned->child1); + + $resize = $is_child1 ? $paned->child1_resize : $paned->child2_resize; + $shrink = $is_child1 ? $paned->child1_shrink : $paned->child2_shrink; + + $child->ref(); + + // Zend doesn't yet support overloaded method calls + $parent = $child->parent; + $parent->remove($child); + + if ($is_child1) + $paned->pack1($child, $resize, !$shrink); + else + $paned->pack2($child, $resize, !$shrink); + + $child->unref(); +} + +function create_pane_options($paned, $frame_label, $label1, $label2) +{ + $frame = &new GtkFrame($frame_label); + $frame->set_border_width(0); + + $table = &new GtkTable(3, 2, true); + $frame->add($table); + + $label = &new GtkLabel($label1); + $table->attach_defaults($label, 0, 1, 0, 1); + + $check_button = &new GtkCheckButton('Resize'); + $table->attach_defaults($check_button, 0, 1, 1, 2); + $check_button->connect_object('toggled', 'toggle_resize', $paned->child1); + + $check_button = &new GtkCheckButton('Shrink'); + $table->attach_defaults($check_button, 0, 1, 2, 3); + $check_button->set_active( true); + $check_button->connect_object('toggled', 'toggle_shrink', $paned->child1); + + $label = &new GtkLabel($label2); + $table->attach_defaults($label,1,2,0,1); + + $check_button = &new GtkCheckButton('Resize'); + $table->attach_defaults($check_button, 1, 2, 1, 2); + $check_button->set_active( true); + $check_button->connect_object('toggled', 'toggle_resize', $paned->child2); + + $check_button = &new GtkCheckButton('Shrink'); + $table->attach_defaults($check_button, 1, 2, 2, 3); + $check_button->set_active( true); + $check_button->connect_object('toggled', 'toggle_shrink', $paned->child2); + + return $frame; +} + +function create_panes() +{ + global $windows; + + if (!isset($windows['panes'])) { + $window = &new GtkWindow; + $windows['panes'] = $window; + $window->connect('delete_event', 'delete_event'); + $window->set_title('GtkPane'); + + $vbox = &new GtkVBox; + $window->add( $vbox); + + $vpaned = &new GtkVPaned; + $vbox->pack_start($vpaned, true, true, 0); + $vpaned->set_border_width( 5); + + $hpaned = &new GtkHPaned; + $vpaned->add1($hpaned); + + $frame = &new GtkFrame; + $frame->set_shadow_type(GTK_SHADOW_IN); + $frame->set_usize(60, 60); + $hpaned->add1($frame); + + $button = &new GtkButton('Hi there'); + $frame->add($button); + + $frame = &new GtkFrame; + $frame->set_shadow_type(GTK_SHADOW_IN); + $frame->set_usize(80, 60); + $hpaned->add2($frame); + + $frame = &new GtkFrame; + $frame->set_shadow_type(GTK_SHADOW_IN); + $frame->set_usize(60, 80); + $vpaned->add2($frame); + + $vbox->pack_start( + create_pane_options( + $hpaned, + 'Horizontal', + 'Left', + 'Right'), + false, false, 0); + + $vbox->pack_start( + create_pane_options( + $vpaned, + 'Vertical', + 'Top', + 'Bottom'), + false, false, 0); + + $separator = &new GtkHSeparator(); + $vbox->pack_start($separator, false); + + $button = &new GtkButton('Close'); + $button->connect('clicked', 'close_window'); + $vbox->pack_start($button); + $button->set_flags(GTK_CAN_DEFAULT); + $button->grab_default(); + $button->show(); + } + $windows['panes']->show_all(); +} + +function create_file_selection() +{ + static $window; + + if (!$window) + { + function file_selection_ok($button, $fs) + { + print "selected '" . $fs->get_filename() . "'\n"; + $fs->destroy(); + } + + $window = new GtkFileSelection('File selection dialog'); + $window->hide_fileop_buttons(); + $window->set_position(GTK_WIN_POS_MOUSE); + $window->connect_object('destroy',create_function('&$w','$w=null;'), $window); + + $button_ok = $window->ok_button; + $button_ok->connect('clicked','file_selection_ok', $window); + + $button_cancel = $window->cancel_button; + $button_cancel->connect_object('clicked', array(&$window, 'destroy')); + + $action_area = $window->action_area; + + $button = &new GtkButton('Hide Fileops'); + $button->connect_object('clicked', create_function('$w', '$w->hide_fileop_buttons();'), $window); + $action_area->pack_start($button, false, false, 0); + $button->show(); + + $button = &new GtkButton('Show Fileops'); + $button->connect_object('clicked', create_function('$w', '$w->show_fileop_buttons();'), $window); + $action_area->pack_start($button, false, false, 0); + $button->show(); + } + + if (!($window->flags() & GTK_VISIBLE)) + $window->show_all(); + else + $window->destroy(); +} + +function label_toggle( $dialog, $label, $dialog) +{ + if (!$label) + { + $label = new GtkLabel('Dialog Test'); + $label->set_padding(10, 10); + $label->connect_object('destroy', create_function('$w', '$w=null;'), &$label); + $vbox = $dialog->vbox; + $vbox->pack_start($label, true, true, 0); + $label->show(); + } else + $label->destroy(); +} + +function create_dialog() +{ + static $dialog = null; + static $label = null; + + if (!$dialog) + { + $dialog = new GtkDialog; + $dialog->set_title('GtkDialog'); + $dialog->set_border_width(0); + $dialog->set_usize(200,110); + $dialog->connect_object('destroy', create_function('$w', '$w = null;'), &$dialog); + + $button = &new GtkButton('Ok'); + $button->set_flags(GTK_CAN_DEFAULT); + $button->connect( 'clicked', 'close_window'); + + $action_area = $dialog->action_area; + $action_area->pack_start($button, true, true, 0); + $button->grab_default(); + $button->show(); + + $button = &new GtkButton('Toggle'); + $button->connect('clicked', 'label_toggle', &$label, $dialog); + $button->set_flags(GTK_CAN_DEFAULT); + $action_area->pack_start($button, true, true, 0); + $button->show(); + } + + if (!($dialog->flags() & GTK_VISIBLE)) + $dialog->show(); + else + $dialog->destroy(); +} + +function event_watcher( $object, $signal_id) +{ + echo 'Event watch: ' . gtk::signal_name( $signal_id) . ' emitted for ' . gtk::type_name( $object->get_type()) . "\n"; + return true; +} + +function event_watcher_toggle(&$event_watcher_enter_id, &$event_watcher_leave_id) +{ + var_dump($event_watcher_enter_id); + if ($event_watcher_enter_id) + event_watcher_down($event_watcher_enter_id, $event_watcher_leave_id); + else + { + $signal_id = Gtk::signal_lookup( 'enter_notify_event', GtkWidget::get_type()); + $event_watcher_enter_id = gtk::signal_add_emission_hook( $signal_id, 'event_watcher'); + $signal_id = Gtk::signal_lookup( 'leave_notify_event', GtkWidget::get_type()); + $event_watcher_leave_id = gtk::signal_add_emission_hook( $signal_id, 'event_watcher'); + } +} + +function event_watcher_down(&$event_watcher_enter_id, &$event_watcher_leave_id) +{ + if ($event_watcher_enter_id) + { + $signal_id = Gtk::signal_lookup( 'enter_notify_event', GtkWidget::get_type()); + gtk::signal_remove_emission_hook($signal_id, $event_watcher_enter_id); + $event_watcher_enter_id = 0; + $signal_id = Gtk::signal_lookup( 'leave_notify_event', GtkWidget::get_type()); + gtk::signal_remove_emission_hook($signal_id, $event_watcher_leave_id); + $event_watcher_leave_id = 0; + } +} + +function create_event_watcher() +{ + static $dialog = null; + static $event_watcher_enter_id = 0; + static $event_watcher_leave_id = 0; + + if (!$dialog) + { + $dialog = new GtkDialog; + $dialog->connect_object('delete_event','event_watcher_down', $event_watcher_enter_id, $event_watcher_leave_id); + $dialog->connect_object('delete_event', 'delete_event'); + $dialog->set_title('Event Watcher'); + $dialog->set_border_width(0); + $dialog->set_usize(200, 110); + + $vbox = $dialog->vbox; + $action_area = $dialog->action_area; + + $button = &new GtkToggleButton('Activate Watch'); + $button->connect_object('clicked', 'event_watcher_toggle', $event_watcher_enter_id, $event_watcher_leave_id); + $button->set_border_width(10); + $vbox->pack_start($button); + $button->show(); + + $button = &new GtkButton('Close'); + $button->connect_object('clicked', 'event_watcher_down', $event_watcher_enter_id, $event_watcher_leave_id); + $button->connect('clicked', 'close_window'); + $button->set_flags(GTK_CAN_DEFAULT); + $action_area->pack_start($button); + $button->grab_default(); + $button->show(); + } + + if (!($dialog->flags() & GTK_VISIBLE)) + $dialog->show(); + else + $dialog->destroy(); +} function create_main_window() { @@ -1954,12 +2265,12 @@ 'color selection' => 'create_color_selection', 'cursors' => 'create_cursor_test', 'ctree' => 'create_ctree', - 'event watcher' => null, + 'event watcher' => 'create_event_watcher', 'notebook' => null, 'drawing area' => null, - 'file selection' => null, - 'dialog' => null, - 'panes' => null, + 'file selection' => 'create_file_selection', + 'dialog' => 'create_dialog', + 'panes' => 'create_panes', 'pixmap' => 'create_pixmap', 'drag\'n\'drop' => 'create_dnd', );
« previous php.gtk (#2885) next »