>From b547542445feddbb0a6e95599d03b6a8251f0a54 Mon Sep 17 00:00:00 2001 From: Quentin Sculo Date: Tue, 13 Apr 2010 19:30:24 +0200 Subject: [PATCH 15/16] wrap GtkInfoBar (new in gtk 2.18) a good part has been copied from GtkDialog which has a similar API --- maps-2.18 | 1 + t/GtkInfoBar.t | 61 +++++++++++ xs/GtkInfoBar.xs | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ xs_files-2.18 | 1 + 4 files changed, 354 insertions(+), 0 deletions(-) create mode 100644 maps-2.18 create mode 100644 t/GtkInfoBar.t create mode 100644 xs/GtkInfoBar.xs create mode 100644 xs_files-2.18 diff --git a/maps-2.18 b/maps-2.18 new file mode 100644 index 0000000..db45a65 --- /dev/null +++ b/maps-2.18 @@ -0,0 +1 @@ +GTK_TYPE_INFO_BAR GtkInfoBar GtkObject Gtk2::InfoBar diff --git a/t/GtkInfoBar.t b/t/GtkInfoBar.t new file mode 100644 index 0000000..f49979e --- /dev/null +++ b/t/GtkInfoBar.t @@ -0,0 +1,61 @@ +#!/usr/bin/perl +# vim: set syntax=perl : +# +# $Id$ +# +# GtkInfoBar Tests + +use Gtk2::TestHelper tests => 15, at_least_version=> [2,18,0]; + +ok( my $win = Gtk2::Window->new('toplevel') ); + +my $infobar=Gtk2::InfoBar->new; +isa_ok ($infobar, 'Gtk2::InfoBar', 'new'); +$win->add($infobar); + +isa_ok ($infobar->get_action_area, 'Gtk2::Widget','get_action_area'); +isa_ok ($infobar->get_content_area, 'Gtk2::Widget','get_content_area'); + +isa_ok( $infobar->add_button(test3=>3), 'Gtk2::Widget', 'add_button'); +is( button_count($infobar), 1, 'add_button count'); +$infobar->add_buttons(test4=>4,test5=>5); +is( button_count($infobar), 3, 'add_buttons'); + +my $button=Gtk2::Button->new("action_widget"); +$infobar->add_action_widget($button, 6); +is( button_count($infobar), 4, 'add_action_widget'); + +my $infobar2=Gtk2::InfoBar->new( + 'gtk-ok' => 'ok', 'test2' => 2, +); +isa_ok ($infobar2, 'Gtk2::InfoBar', 'new_with_buttons'); +is( button_count($infobar2), 2, 'new_with_buttons buttons count'); + +$infobar->set_response_sensitive(6,FALSE); +is( $button->is_sensitive, FALSE, 'set_response_sensitive'); + +$infobar->set_message_type('error'); +is( $infobar->get_message_type, 'error', '[gs]et_message_type'); + +$infobar->set_default_response(4); +ok( 1,'set_default_response'); + +$infobar->signal_connect( response => sub { + my ($infobar,$response)= _; + my $expected=$infobar->{expected_response}; + ok( $response eq $expected, "response '$expected'" ); + 1; + }); +$infobar->response( $infobar->{expected_response}=5 ); +$infobar->response( $infobar->{expected_response}='ok' ); + + +sub button_count +{ my @b=$_[0]->get_action_area->get_children; + return scalar @b; +} + +__END__ + +Copyright (C) 2010 by the gtk2-perl team (see the file AUTHORS for the +full list). See LICENSE for more information. diff --git a/xs/GtkInfoBar.xs b/xs/GtkInfoBar.xs new file mode 100644 index 0000000..43b1939 --- /dev/null +++ b/xs/GtkInfoBar.xs @@ -0,0 +1,291 @@ +/* + * Copyright 2010 by the gtk2-perl team (see the file AUTHORS) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, see . + */ + +#include "gtk2perl.h" +#include + +/* Mostly copied from GtkDialog.xs which has a similar API */ +/* + * GtkInfoBar interprets the response id as completely user-defined for + * positive values, and as special enums for negative values. so, we + * will handle the response_id as a plain SV so we can implement this + * special behavior. + */ + +static gint +sv_to_response_id (SV * sv) +{ + int n; + if (looks_like_number (sv)) + return SvIV (sv); + if (!gperl_try_convert_enum (GTK_TYPE_RESPONSE_TYPE, sv, &n)) + croak ("response_id should be either a GtkResponseType or an integer"); + return n; +} + +static SV * +response_id_to_sv (gint response) +{ + return gperl_convert_back_enum_pass_unknown (GTK_TYPE_RESPONSE_TYPE, + response); +} + +/* +GtkInfoBar's response event is defined in Gtk as having a signal parameter +of type G_TYPE_INT, but GtkResponseType values are passed through it. + +this custom marshaller allows us to catch and convert enum codes like those +returned by $dialog->run , instead of requiring the callback to deal with +the raw negative numeric values for the predefined constants. +*/ +/* FIXME This is the same function as in GtkDialog.xs, don't know if it's possible to share it */ +static void +gtk2perl_dialog_response_marshal (GClosure * closure, + GValue * return_value, + guint n_param_values, + const GValue * param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + dGPERL_CLOSURE_MARSHAL_ARGS; + + GPERL_CLOSURE_MARSHAL_INIT (closure, marshal_data); + + PERL_UNUSED_VAR (return_value); + PERL_UNUSED_VAR (n_param_values); + PERL_UNUSED_VAR (invocation_hint); + + ENTER; + SAVETMPS; + + PUSHMARK (SP); + + GPERL_CLOSURE_MARSHAL_PUSH_INSTANCE (param_values); + + /* the second parameter for this signal is defined as an int + * but is actually a response code, and can have GtkResponseType + * values. */ + XPUSHs (sv_2mortal (response_id_to_sv + (g_value_get_int (param_values + 1)))); + + GPERL_CLOSURE_MARSHAL_PUSH_DATA; + + PUTBACK; + + GPERL_CLOSURE_MARSHAL_CALL (G_DISCARD); + + /* + * clean up + */ + + FREETMPS; + LEAVE; +} + +MODULE = Gtk2::InfoBar PACKAGE = Gtk2::InfoBar PREFIX = gtk_info_bar_ + +BOOT: + gperl_signal_set_marshaller_for (GTK_TYPE_INFO_BAR, "response", + gtk2perl_dialog_response_marshal); + +=for position post_signals + +Note that currently in a Perl subclass of C a class +closure, ie. class default signal handler, for the C signal +will be called with the response ID just as an integer, it's not +turned into an enum string like C<"ok"> the way a handler setup with +C receives. + +Hopefully this will change in the future, so don't count on it. In +the interim the easiest thing to do is install your default handler in +C with a C. (The subtleties of what +order handlers are called in will differ, but often that doesn't +matter.) + +=cut + +=for enum GtkResponseType + +The response type is somewhat abnormal as far as gtk2-perl enums go. In C, +this enum lists named, predefined integer values for a field that is other +composed of whatever integer values you like. In Perl, we allow this to +be either one of the string constants listed here or any positive integer +value. For example, 'ok', 'cancel', 4, and 42 are all valid response ids. +You cannot use arbitrary string values, they must be integers. Be careful, +because unknown string values tend to be mapped to 0. + +=cut + + +=for apidoc Gtk2::InfoBar::new_with_buttons +=for signature $widget = Gtk2::InfoBar->new_with_buttons (...) +=for arg ... of button-text => response-id pairs. + +Alias for the multi-argument version of C<< Gtk2::InfoBar->new >>. + +=cut + +=for apidoc +=for signature $widget = Gtk2::InfoBar->new; +=for signature $widget = Gtk2::InfoBar->new (...) +=for arg ... of button-text => response-id pairs. + +The multi-argument form takes the same list of text => response-id pairs as +C<< $infobar->add_buttons >>. Do not pack widgets directly into the infobar; +add them to C<< $infobar->get_content_area () >>. + +Here's a simple example: + + $infobar = Gtk2::InfoBar->new ( + 'gtk-ok' => 'accept', + 'gtk-cancel' => 'reject'); + +=cut +GtkWidget * +gtk_info_bar_new (class, ...) + ALIAS: + Gtk2::InfoBar::new_with_buttons = 1 + PREINIT: + int i; + GtkWidget * info_bar; + CODE: + PERL_UNUSED_VAR (ix); + if (items == 1) { + /* the easy way out... */ + info_bar = gtk_info_bar_new (); + } else if ( !(items % 2) ) { + croak ("USAGE: Gtk2::InfoBar->new ()\n" + " or Gtk2::InfoBar->new (...)\n" + " where ... is a series of button text and response id pairs"); + } else { + /* we can't really pass on a varargs call (at least, i don't + * know how to convert from perl stack to C va_list), so we + * have to duplicate a bit of the functionality of the C + * version. luckily it's nothing too intense. */ + + info_bar = gtk_info_bar_new (); + + for (i = 1; i < items; i += 2) { + gchar * text = SvGChar (ST (i)); + int response_id = sv_to_response_id (ST (i+1)); + gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), text, + response_id); + } + } + RETVAL = info_bar; + OUTPUT: + RETVAL + + +GtkWidget * +gtk_info_bar_add_button (info_bar, button_text, response_id) + GtkInfoBar * info_bar + const gchar * button_text + SV * response_id + CODE: + RETVAL = gtk_info_bar_add_button (info_bar, button_text, + sv_to_response_id (response_id)); + OUTPUT: + RETVAL + +=for apidoc +=for arg ... of button-text => response-id pairs +Like calling C<< $infobar->add_button >> repeatedly, except you don't get the +created widgets back. The buttons go from left to right, so the first button +added will be the left-most one. +=cut +void +gtk_info_bar_add_buttons (info_bar, ...) + GtkInfoBar * info_bar + PREINIT: + int i; + CODE: + if( !(items % 2) ) + croak("gtk_info_bar_add_buttons: odd number of parameters"); + /* we can't make var args, so we'll call add_button for each */ + for( i = 1; i < items; i += 2 ) + gtk_info_bar_add_button(info_bar, SvGChar(ST(i)), + sv_to_response_id(ST(i+1))); + +=for apidoc +=for arg response_id (GtkResponseType) +=cut +void +gtk_info_bar_add_action_widget (info_bar, child, response_id) + GtkInfoBar * info_bar + GtkWidget * child + SV * response_id + PREINIT: + CODE: + gtk_info_bar_add_action_widget (info_bar, child, + sv_to_response_id (response_id)); + +=for apidoc +=for arg response_id (GtkResponseType) +Enable or disable an action button by its I<$response_id>. +=cut +void +gtk_info_bar_set_response_sensitive (info_bar, response_id, setting) + GtkInfoBar * info_bar + SV * response_id + gboolean setting + CODE: + gtk_info_bar_set_response_sensitive (info_bar, + sv_to_response_id (response_id), + setting); + + +=for apidoc +=for arg response_id (GtkResponseType) +=cut +void +gtk_info_bar_set_default_response (info_bar, response_id) + GtkInfoBar * info_bar + SV * response_id + CODE: + gtk_info_bar_set_default_response (info_bar, + sv_to_response_id (response_id)); + +=for apidoc +=for arg response_id (GtkResponseType) +=cut +void +gtk_info_bar_response (info_bar, response_id) + GtkInfoBar * info_bar + SV * response_id + C_ARGS: + info_bar, sv_to_response_id (response_id) + + +void +gtk_info_bar_set_message_type (info_bar, type); + GtkInfoBar * info_bar + GtkMessageType type + +GtkMessageType +gtk_info_bar_get_message_type (info_bar); + GtkInfoBar * info_bar + +GtkWidget * +gtk_info_bar_get_action_area (info_bar) + GtkInfoBar * info_bar + +GtkWidget * +gtk_info_bar_get_content_area (info_bar) + GtkInfoBar * info_bar + + diff --git a/xs_files-2.18 b/xs_files-2.18 new file mode 100644 index 0000000..a650343 --- /dev/null +++ b/xs_files-2.18 @@ -0,0 +1 @@ +xs/GtkInfoBar.xs -- 1.6.4.4