NAME
Glib::Ex::ConnectProperties -- link properties between objects
SYNOPSIS
use Glib::Ex::ConnectProperties;
my $conn = Glib::Ex::ConnectProperties->new ([$check,'active'],
[$widget,'visible']);
$conn->disconnect; # explicit disconnect
DESCRIPTION
Glib::Ex::ConnectProperties
links together specified properties on two or more Glib::Object
s (including Gtk widgets) so a change made to any one of them is propagated to the others.
This is an easy way to tie a user control widget to a setting elsewhere. For example a CheckButton active
could be linked to the visible
of another widget, letting the user click to hide or show it.
+--------------------+ +-------------+
| CheckButton/active | <-------> | Foo/visible |
+--------------------+ +-------------+
The advantage of ConnectProperties is that it's bi-directional, so if other code changes "Foo/visible" then that change is sent to "CheckButton/active" too, ensuring the button display is up-to-date with what it's controlling, no matter how the target changes.
Property types
String, number, enum, flags, and object properties are supported. Some boxed types like Gtk2::Gdk::Color
work too, but others have potential problems (see "IMPLEMENTATION NOTES" below).
Read-only properties can be used. They're read and propagated, but changes in other linked properties are not stored to read-onlys; though this leaves different values, rather defeating the purpose of the linkage. Linking a read-only probably only makes sense if the read-only one is the only one changing.
Write-only properties can be used. Nothing is read out of them, they're just set from changes in the other linked properties. (Write-only properties are often pseudo "add" methods etc, so it's probably unlikely linking in a write-only will do much good.)
It works to connect two properties on the same object; doing so can ensure they update together. It also works to have two different ConnectProperties with an object/property in common; a change coming from one group propagates through to the other just fine. In fact such a setup arises quite naturally if you've got two controls for the same target; neither of them needs to know the other exists.
Currently there's no transformations applied to values copied between property settings. The intention is to have some "map" options or transformation functions on a per object+property basis.
FUNCTIONS
$conn = Glib::Ex::ConnectProperties->new ([$obj1,$prop1],[$obj,$prop2],...)
-
Connect two or more given object+property combinations. Each argument is an array ref to an object and a property name. For example
$conn = Glib::Ex::ConnectProperties->new ([$first_object, 'first-property-name'], [$second_object, 'second-property-name']);
The return value is a Perl object of type
Glib::Ex::ConnectProperties
. You can keep that to later break the connection explicitly withdisconnect
below, or otherwise you can ignore it.A ConnectProperties linkage lasts as long as the linked objects exist, but it only keeps weak references to those objects, so the linkage doesn't prevent some or all of them being garbage collected.
$conn->disconnect()
-
Disconnect the given ConnectProperties linkage.
IMPLEMENTATION NOTES
ConnectProperties uses a notify
signal handler on each object to update the others. Updating those others makes them in turn emit further notify
signals (even if the value is unchanged), so some care must be taken not to cause an infinite loop. The present strategy for that is twofold
An "in progress" flag in the ConnectProperties object, so during an update any further
notify
emissions are recognised as its own doing and can be ignored.The value from a
get
is compared before doing aset
. If it's already what's wanted then theset
call is not made at all.
The in-progress flag is effective against immediate further notify
s. They could also be avoided by disconnecting or blocking the respective handlers temporarily, but that'd probably take more bookkeeping work than just ignoring.
The compare-before-set is essential to cope with freeze_notify
, because in that case the notify
calls don't come while the "in progress" flag is on, only later, perhaps a long time later.
It might be wondered if something simpler is possible, and the short answer is that for the general case, not really. The specific set_foo
methods on most widgets and objects will skip an unchanged setting, but alas when using the generic set_property
the protection above is needed.
Equality
Glib-Perl doesn't yet wrap values_cmp
to do an "equal" test of arbitrary property values for the compare-before-set. ConnectProperties recognises the types noted above, and can use an object equal
or compare
method at the Perl level like boxed types Gtk2::Gdk::Region
and Gtk2::TreePath
have. (Boxed types get copied so unfortunately you don't see the same pointer twice, let alone the same Perl ref, making a direct ==
no good.)
Notifies
Incidentally, if you're writing a widget don't forget you have to explicitly notify
if changing a property from anywhere outside your SET_PROPERTY
method. (Duplicate notifies from within that method are ok and are collapsed to just one emission at the end.) Of course this is required for any widget, but failing to do will mean in particular that ConnectProperties won't work.
SEE ALSO
HOME PAGE
http://www.geocities.com/user42_kevin/glib-ex-connectproperties/
LICENSE
Copyright 2007, 2008 Kevin Ryde
Glib-Ex-ConnectProperties is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Glib-Ex-ConnectProperties 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 General Public License for more details.
You should have received a copy of the GNU General Public License along with Glib-Ex-ConnectProperties. If not, see http://www.gnu.org/licenses/.