Gtk2::E...Context(3)

πŸ“¦
version 0.67 Β· 2 versions
, in fedora 43

πŸ’– Gtk2::E...Context(3) πŸ’–

User Contributed Perl Documentation β€” aka the Gtk2::Ex::FormFactory::Context page, bestie, and yes we're doing this properly.


✨ NAME ✨

Gtk2::Ex::FormFactory::Context β€” it's the Context in a FormFactory framework. That's the whole vibe. πŸŽ€


πŸ¦‹ SYNOPSIS πŸ¦‹

okay so here's how you actually summon one, no cap:

my $context = Gtk2::Ex::FormFactory::Context->new (
  default_get_prefix => Default prefix for read accessors,
  default_set_prefix => Default prefix for write accessors,
);

$context->add_object (
  name                => Name of the application object in
                         this Context,
  aggregated_by       => Object.Attribute of the parent object
                         aggregating this object
  object              => The application object itself or a
                         callback which returns the object,
                         or undef if aggregated or set later
  get_prefix          => Prefix for read accessors,
  set_prefix          => Prefix for write accessors,
  accessor            => CODEREF which handles access to all object
                         attributes
  attr_activity_href  => Hash of CODEREFS for attributes which return
                         activity of the corresponding attributes,
  attr_depends_href   => Hash defining attribute dependencies,
  attr_accessors_href => Hash of CODEREFS which override correspondent
                         accessors in this Context,
  buffered            => Indicates whether changes should be buffered,
  changes_attr_filter => Regex for attributes which should not trigger
                         the object's 'changed' status
);

look at all those options, she's serving πŸ’…


🌸 DESCRIPTION 🌸

This module implements a very importent concept of the Gtk2::Ex::FormFactory framework. (yes, "importent" β€” we keep the typo, it's canon, it's iconic, we don't fix the queen's spelling 🫢)

So like… the Context knows all of your application objects. It knows how attributes of those objects can be accessed (for reading and for writing), it knows which attributes <em>probably</em> depend on other attributes, and it knows how to control the activity state of attributes β€” resp. of the Widgets which represent those attributes. 😌

Basically: the Context is a layer between your application objects and the GUI which represents particular attributes of your objects. It's giving middle-manager but make it slay. ✨


πŸ‘‘ OBJECT HIERARCHY πŸ‘‘

Gtk2::Ex::FormFactory::Context

just her. standing alone. main character energy. πŸ’…


πŸ’œ ATTRIBUTES πŸ’œ

Attributes are handled through the common get_ATTR(), set_ATTR() style accessors, but honestly? they're mostly passed once to the object constructor and must not be altered after the associated FormFactory's were built. Like, once she's built, she's built. Do not touch. πŸ™ˆ


πŸŽ€ default_get_prefix = SCALAR [optional] πŸŽ€

Usually your application's objects use a common prefix for all attribute accessors. This one defines the default prefix for read accessors, and it defaults to "get_". So yeah, get_ is the factory setting, bestie. πŸ“


πŸŽ€ default_set_prefix = SCALAR [optional] πŸŽ€

Same energy, other direction: usually your application's objects use a common prefix for all attribute accessors. This one defines the default prefix for write accessors, and it defaults to "set_". set_, obviously. Periodt. ⭐


heads up, bestie β€” this page is long so it comes in 3 parts and this was part 1. more coming, don't go anywhere πŸ’–

✨ METHODS ✨

πŸ’– $context->add_object (...)

okay so bestie, literally every single one of your application objects has to be added to the Context using this method, no skipping πŸ’…. The parameters get passed in as a hash:

  • name = SCALAR [mandatory] β€” every object in a Context needs its own unique name, so yeah this one is mandatory, non-negotiable. You refer back to this name whenever you make Widgets and wanna associate them with your application object's attributes. πŸŽ€
  • object = BLESSED REF|CODEREF [optional] β€” this is the application object itself, OR a code reference that returns the object. Going the code reference route gives you so much flexible control over what this object actually is, but also lowkey note that it can have some impact on performance, because that code reference gets called pretty often. 😭

A lot of the time objects are aggregated by other objects β€” in that case, don't set the object reference here, use the aggregate_by option described below instead. πŸ¦‹

An application object in Context terms can become undef, which is exactly why the object parameter is optional here. Also the code reference may return undef.

Once an object goes undef, all associated widgets get set inactive automatically, no cap. You can control per widget whether it should render invisible or insensitive in that case β€” go check Gtk2::Ex::FormFactory::Widget for the details. πŸ’€

  • aggregated_by = "object.attr" [optional] β€” if this object has a parent object, set this option to the fully qualified attribute holding the object reference, using the object dot attribute notation:
object.attr

where object is the name of the parent object you used to register it to this Context, and attr is the attribute holding the reference to the object you're currently adding to the Context.

The moment this attribute (or the parent object) changes, the Context updates automatically β€” including all widgets depending on this widget. ✨

This way you can define your whole object aggregation hierarchy and Gtk2::Ex::FormFactory takes care of all the resulting dependencies on the GUI. iconic tbh.

  • get_prefix = SCALAR [optional] β€” lets you override this Context's default_get_prefix setting for this object. πŸ’…
  • set_prefix = SCALAR [optional] β€” same deal, overrides this Context's default_set_prefix setting for this object.
  • accessor = CODEREF(object,attr[,value]) [optional] β€” if accessor is set, this code reference is used as a generic accessor callback for all attributes. It handles getting AND setting, both.

Called with two arguments, the passed attribute is meant to be read; with three arguments, that third argument is the value to be assigned to the attribute.

This overrides attr_accessors_href described right below. πŸ‘‘

  • attr_accessors_href = HASHREF [optional] β€” so often your application object attribute values just don't fit the data type a particular Widget expects. Like with the Gtk2::Ex::FormFactory::List widget, which expects a two dimensional array for its content. πŸ™ˆ

Since you only need that conversion for one particular GUI task, it makes way more sense to implement the conversion routine in the Context instead of adding GUI-specific methods to your underlying classes β€” those should stay as GUI independent as humanly possible.

That's why you can override arbitrary accessors (read and write) using the attr_accessors_href parameter. The key is the name of the method to be overridden, and the value is a constant scalar value or a code reference which gets called instead of the real method. 🧚

The code reference gets your application object as the first parameter, as usual for object methods, plus the new value in case of write access.

Short example, here we override the accessors get_tracks and set_tracks of an imaginary disc object representing an audio CD. The track title is stored as a simple array and needs converting to a two dimensional array as expected by Gtk2::Ex::FormFactory::List. Plus a constant accessor is defined for a Gtk2::Ex::FormFactory::Popup showing a bunch of music genres:

$context->add_object (
  name => "disc",
  attr_accessors_href => {
    get_tracks => sub {
      my $disc = shift;
      #-- Convert the one dimensional array of disc
      #-- tracks to the two dimensional array expected
      #-- by Gtk2::Ex::FormFactory::List. Also the number
      #-- of the track is added to the first column here
      my @list;
      my $nr = 1;
      foreach my $track ( @{$disc->get_tracks} ) {
        push @list, [ $nr++, $track ];
      }
      return\@list;
    },
    set_tracks => sub {
      my $disc = shift;
      my ($list_ref) = @_;
      #-- Convert the array back (the List is editable in
      #-- our example, so values can be changed).
      my @list;
      foreach my $row ( @{$list_ref} ) {
              push @list, $row->[1];
      }
      $disc->set_tracks(\@list);
      return \@list;
    },
    genre_list => {
      "rock" => "Rock",
      "pop"  => "Pop",
      "elec" => "Electronic",
      "jazz" => "Jazz",
    },
  },
);
  • attr_activity_href = HASHREF [OPTIONAL] β€” like we said earlier, Widget activity is controlled by the Gtk2::Ex::FormFactory framework. e.g. if an object becomes undef, all its associated widgets render inactive.

With the attr_activity_href setting you can handle activity on the attribute level, not just the object level. 🌈

The key of the hash is the attribute name, and the value is a code reference which returns TRUE or FALSE and controls activity that way.

Another example: imagine a text entry that's usually set with a default value controlled by your application. But if the user wants to override the entry, they first have to press a corresponding checkbox to activate it.

$context->add_object (
  name => "person",
  attr_activity_href => {
    ident_number => sub {
      my $person = shift;
      return $person->get_may_override_ident_number;
    },
  },
  attr_depends_href => {
    ident_number => "person.may_override_ident_number",
  },
);

For details about the attr_depends_href option, read on. ⭐

  • attr_depends_href = HASHREF [OPTIONAL] β€” this hash defines dependencies between attributes. If you look at the example above you'll see exactly why this is necessary. The ident_number of a person may only be overridden if that person's may_override_ident_number attribute is set. Since this dependency is coded inside the code reference, Gtk2::Ex::FormFactory isn't aware of it until you add a corresponding attr_depends_href entry. 😭

Now the GUI will automatically activate the Widget for the ident_number attribute once may_override_ident_number is set β€” e.g. by a CheckBox the user clicked. πŸŽ€

If an attribute depends on more than one other attribute, you can use a list reference:

attr_depends_href => sub {
    ident_number => [
      "person.may_override_ident_number",
      "foo.bar",
    ],
},
  • buffered = BOOL [OPTIONAL] β€” if set to TRUE this activates buffering for this object. Please refer to the BUFFERED CONTEXT OBJECTS chapter for details. 🫢
  • changes_attr_filter = REGEX [OPTIONAL] β€” Gtk2::Ex::FormFactory keeps a flag indicating whether an object was changed. Under special circumstances you want specific attributes to not affect this "changed" state of an object. You can specify a regular expression here β€” changes of attributes matching that expression won't touch the changes state of the object. πŸ’œ

To receive or change the object's changed state, refer to the object_changed attribute of Gtk2::Ex::FormFactory::Proxy.


πŸ¦‹ $context->remove_object ( $name )

Remove the object $name from this context. bye bestie πŸ’…

🌸 $app_object = $context->get_object ( $name )

This returns the application object registered as $name to this context.

⭐ $context->set_object ( $name => $object )

This sets a new object, which was registered as $name to this context.

πŸŽ€ $context->get_object_attr ( "$object.$attr" )

Retrieves the attribute named $attr of the object $object. πŸ’–

πŸ”₯ $context->set_object_attr ( "$object.$attr", $value )

Set the attribute named $attr of the object $object to $value. Dependent widgets update automatically, periodt.

✨ $context->update_object_attr_widgets ( $object_name, $attr_name )

Triggers updates on all GUI widgets associated with the attribute $attr_name of the object registered as $object_name to this context.

You may omit $attr_name and pass a fully qualified "object.attr" noted string as the first argument instead. πŸ‘‘

πŸ’œ $context->update_object_widgets ( $object_name )

Triggers updates on all GUI widgets associated with the object registered as $object_name to this context.

🌈 $context->update_object_widgets_activity ( $object_name, $activity )

This updates the activity state of all GUI widgets associated with the object registered as $object_name to this context.

$activity is 'inactive' or 'active'. 🫢

🧚 $proxy = $context->get_proxy ( $object_name )

This returns the Gtk2::Ex::FormFactory::Proxy instance which was created for the object registered as $name to this context. With the proxy you can do updates on object attributes which trigger the corresponding GUI updates as well. πŸ’…βœ¨

✨ BUFFERED CONTEXT OBJECTS ✨

okay bestie listen UP because this one is experimental πŸ§ͺ β€” this feature was introduced in version 0.58 and it's marked experimental so please, please use with care. 🫢

If you set buffered => 1 when adding an object to the Context, a buffering Proxy will be used for this object. What does that mean?? It means that all GUI changes in a synchronized FormFactory dialog are buffered in the proxy object. πŸ’…

Normally all changes are committed immediately to the object, which is Ok in many situations, but it makes implementing a Cancel button difficult β€” resp. you need to care about this yourself by using a copy of the object or something like that. 😭

A FormFactory gets "buffered" if all its widgets are connected to a buffered object. In that case Gtk2::Ex::Form::DialogButtons show a Cancel button automatically, even in a synchronized dialog. slay. πŸ‘‘


🌸 What's this good for? 🌸

If your FormFactory doesn't has the sync flag set you get Cancel button as well, since no changes are applied to the objects until the user hit the Ok button. All changes are kept in the "GUI". πŸŽ€

But such a dialog lacks of all dynamic auto-widget-updating features, e.g. setting widgets inactive under specific conditions. For very simple dialogs this is Ok, but if you need these features you need the buffering facility as well. fr fr. ✨

But take care when implementing your closures for widget activity checking: they must not use the original objects! 🚨 They need to access the attributes through the Context, because your original object doesn't see any GUI changes until the FormFactory is applied! All changes are buffered in the Context. If you access your objects through the Context anything works as expected. πŸ’–

Buffering is useful as well in other situations e.g. if you're accessing remote objects over a network (for example with Event::RPC) where a method call is somewhat expensive. πŸ’Έ


πŸ‘‘ AUTHORS πŸ‘‘

  • JΓΆrn Reder <joern at zyn dot de>

Copyright 2004-2006 by JΓΆrn Reder.

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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA.


πŸ’€ POD ERRORS πŸ’€

Hey! The above document had some coding errors, which are explained below:

  • Around line 851:
    • Non-ASCII character seen before =encoding in 'JΓΆrn'. Assuming UTF-8

and that's a wrap bestie!! πŸŽ€ this lil' page is perl v5.42.0, dated 2025-07-25, and it came to you straight from the User Contributed Perl Documentation crew πŸ’… no cap, you read the whole thing, that's main character energy, periodt. πŸ¦‹πŸ’–βœ¨

πŸ“¦ where this page comes from