[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: Can't add new GTK 2.16 methods to GtkStyle



On Wed, Jan 21, 2009 at 9:15 PM, Kevin Ryde <user42 zip com au> wrote:
> Emmanuel Rodriguez <emmanuel rodriguez gmail com> writes:
>>
>> +=for apidoc Gtk2::Style::get
>> +=for signature $style->get (widget_package, ...)
>
> If both gobject get and get_property are hidden perhaps the pod could
> have a crib that GtkStyle doesn't have any GObject properties to get or
> set, though if a subclass did you can always $style->Glib::Object::get
> to access them (assuming that's true).
>
Tested and it's true. I added a comment and unit tests to prove that it works.

>> +=for apidoc Gtk2::Style::get_property
>> +=for arg widget_package (__hide__)
>
> There's some trick to get the two docs together isn't there?
>
Well I just copied from other classes. But if you write Alias for
C<method> you assume that the user will search for the doc of "method"
:)

>> +                warn ("Invalid property `%s' used, returning undef", name);
>
> Should that croak the way g_object_get does on an unknown property?
> When in doubt you could either eval to trap, or ask
> find_style_property() what's available (if that's wrapped).

The code dies and the unit test check for this.

-- 
Emmanuel Rodriguez
Index: xs/GtkStyle.xs
===================================================================
--- xs/GtkStyle.xs	(revision 2116)
+++ xs/GtkStyle.xs	(working copy)
@@ -572,3 +572,87 @@
         RETVAL
 
 #endif
+
+#if GTK_CHECK_VERSION (2, 15, 0) /* FIXME 2.16 */
+
+=for apidoc Gtk2::Style::get
+=for signature $style->get (widget_package, ...)
+=for arg widget_package (string) widget package name (ex: 'Gtk2::TreeView')
+=for arg ... (list) list of property names
+
+Fetch and return the values for the style properties named in I<...> for a
+widget of type I<widget_package>.
+
+B<NOTE>: The methods Gtk2::Style::get() and Gtk2::Style::get_property() override
+respectively Glib::Gobject::get() and Glib::Gobject::get_property(). This
+shouldn't be a problem as Gtk2::Style defines no properties (as of gtk 2.16). 
+Nevertheless in the case where an class will derive Gtk2::Style and adds a
+property or that a new version of gtk adds a property the property can be
+accessed with the following code:
+
+	my $value = $style->Glib::Object::get_property('property');
+
+=cut
+
+=for apidoc Gtk2::Style::get_property
+=for arg widget_package (__hide__)
+=for arg ... (__hide__)
+
+Alias for C<get>.
+
+=cut
+
+void
+gtk_style_get (style, widget_package, ...)
+    GtkStyle    *style
+    const char  *widget_package
+    ALIAS:
+        Gtk2::Style::get = 0
+        Gtk2::Style::get_property = 1
+    PREINIT:
+        int i;
+        GType widget_type;
+        gpointer class_peek;
+        GValue value = {0,};
+
+    CODE:
+        /* Use CODE: instead of PPCODE: so we can handle the stack ourselves in
+         * order to avoid that xsubs called by gtk_style_get_property overwrite
+         * what we put on the stack. */
+        PERL_UNUSED_VAR (ix);
+
+        widget_type = gperl_type_from_package(widget_package);
+        if (widget_type == 0)
+            croak("package %s is not registered with GPerl", widget_package);
+
+        if (! g_type_is_a (widget_type, GTK_TYPE_WIDGET))
+            croak("%s is not a subclass of Gtk2::Widget", widget_package);
+
+        
+        class_peek = g_type_class_ref(widget_type);
+        if (class_peek == NULL)
+            croak("can't find class %s", widget_package);
+
+        
+        
+        for (i = 2 ; i < items ; i++) {
+            GValue value = {0, };
+            gchar *name = SvGChar(ST(i));
+            GParamSpec *pspec = pspec = gtk_widget_class_find_style_property(class_peek, name);
+            if (pspec) {
+                g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+                gtk_style_get_property(style, widget_type, name, &value);
+                ST (i - 2) = sv_2mortal (gperl_sv_from_value(&value));
+                g_value_unset(&value);
+            }
+            else {
+                g_type_class_unref(class_peek);
+                croak("type %s does not support style property '%s'", widget_package, name);
+            }
+        }
+        
+        g_type_class_unref(class_peek);
+        
+        XSRETURN (items - 2);
+
+#endif
Index: t/GtkStyle.t
===================================================================
--- t/GtkStyle.t	(revision 2116)
+++ t/GtkStyle.t	(working copy)
@@ -1,7 +1,8 @@
 #!/usr/bin/perl -w
 # vim: set ft=perl expandtab shiftwidth=2 softtabstop=2 :
 use strict;
-use Gtk2::TestHelper tests => 113;
+use Gtk2::TestHelper tests => 125;
+use Carp;
 
 # $Id$
 
@@ -133,6 +134,129 @@
   ok (1);
 }
 
+SKIP: {
+  skip("get_property is new in 2.16", 12)
+    unless (Gtk2->CHECK_VERSION(2, 15, 0)); # FIXME 2.16
+
+  # Test different properties (gint, gboolean, gchar* and GObject)
+  my $treeview = Gtk2::TreeView -> new();
+  
+  # get gboolean
+  is (
+    $style -> get_property('Gtk2::TreeView', 'allow-rules'),
+    $treeview -> style_get_property('allow-rules'),
+    "get_property gboolean"
+  );
+  
+  # get gint
+  is (
+    $style -> get_property('Gtk2::TreeView', 'expander-size'),
+    $treeview -> style_get_property('expander-size'),
+    "get_property gint"
+  );
+  
+  # get gchar*
+  is (
+    $style -> get_property('Gtk2::TreeView', 'grid_line-pattern'),
+    $treeview -> style_get_property('grid_line-pattern'),
+    "get_property gchar*"
+  );
+  
+  # get GObject (a color)
+  is (
+    $style -> get_property('Gtk2::TreeView', 'even-row-color'),
+    $treeview -> style_get_property('even-row-color'),
+    "get_property GObject*"
+  );
+  
+  
+  # Get multiple properties simultaneously
+  my @properties = $style -> get('Gtk2::TreeView', 'expander-size', 'even-row-color', 'grid_line-pattern');
+  is_deeply (
+    \ properties,
+    [
+      $treeview -> style_get_property('expander-size'),
+      $treeview -> style_get_property('even-row-color'),
+      $treeview -> style_get_property('grid_line-pattern'),
+    ],
+    'get multiple properties',
+  );
+
+
+
+  # Make sure that Glib::GObject::get() and Gtk2::Style::get() can coexist.
+  my $custom_style = Custom::Style -> new();
+  is ($custom_style -> Glib::Object::get('perl-string'), 'empty');
+  is ($custom_style -> Glib::Object::get_property('perl-string'), 'empty');
+  is ($style -> get('Gtk2::Button', 'image-spacing'), 2);
+  is ($style -> get_property('Gtk2::Button', 'image-spacing'), 2);
+  
+  
+  
+  # Test for bad usage
+  # Bad class
+  test_die(
+    sub { $style -> get('wrong::class', 'border'); },
+    qr/^package wrong::class is not registered with GPerl/
+  );
+  
+  # Non existing property
+  test_die(
+    sub { $style -> get('Gtk2::Button', 'image-spacing', 'perl-var', 'default-border'); },
+    qr/^type Gtk2::Button does not support style property 'perl-var'/
+  );
+  
+  # Not a Gtk2::Widget
+  test_die(
+    sub { $style -> get('Glib::Object', 'prop'); },
+    qr/^Glib::Object is not a subclass of Gtk2::Widget/
+  );
+}
+
+
+# Test that an error is thrown
+sub test_die {
+  my ($code, $regexp) = @_;
+  croak "usage(code, regexp)" unless ref $code eq 'CODE';
+	
+  my $passed = FALSE;
+  eval {
+    $code->();
+  };
+  if (my $error = $@) {
+    if ($error =~ /$regexp/) {
+      $passed = TRUE;
+    }
+    else {
+      diag("Expected $regexp but got $error");
+    }
+  }
+
+  return Test::More->builder->ok($passed);
+}
+
+
+#
+# Used to get if Gtk2::Style::get() conflicts with Glib::GObject::get(). A new
+# package is needed because up to this moment (2.16) Gtk2::Style defines no
+# properties.
+#
+package Custom::Style;
+
+use Glib::Object::Subclass 'Gtk2::Style' =>
+
+	properties => [
+		Glib::ParamSpec->string(
+			'perl-string',
+			'Test string',
+			'A test string.',
+			'empty',
+			['readable', 'writable'],
+		),
+	],
+;
+
+
 __END__
 
 Copyright (C) 2003-2006 by the gtk2-perl team (see the file AUTHORS for the


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]