Gtk2-Ex-Dragger

 view release on metacpan or  search on metacpan

lib/Gtk2/Ex/Dragger.pm  view on Meta::CPAN


C<value-changed> is emitted on every motion event.

=item C<"delayed">

C<value-changed> is emitted 250 milliseconds after a change.

=item C<"discontinuous">

C<value-changed> is not emitted at all during the drag, only at the end
(button release or C<stop> function).

=item secret default policy

C<value-changed> is emitted after a sync with the server (implemented
without blocking, see L<Gtk2::Ex::SyncCall>) followed by reaching idle in
the main loop, or at a 250 ms timeout if idle is not reached.

This is designed to be a compromise between smoothness and excessive
drawing.  The sync avoids hammering the server, then the idle waits to avoid
excessive work on the client side, but with the timeout cutting it short to
guarantee updates are not deferred indefinitely.

=back

Choosing a policy is a matter of how good the drawing in your target widget
is.  You can see the difference in the example programs included in the
sources which draw a big block of text in a C<Gtk2::TextView> versus a
Viewport plus C<Gtk2::Label>.  The TextView goes very close to coping with
C<continuous> update policy, but the same on the Label's simple-minded
drawing floods the server to the point of being unusable.

Dragger recognises C<pointer-motion-hint-mask> on the target widget (or
rather the motion event C<is_hint>) and knows to do a
C<< $widget->get_pointer >> for current position and further events.  That's
a deliberate server round-trip on each move, with the effect that each
motion waits until the drawing etc from the previous one has finished.
Generally you can set C<update_policy> to C<continuous> in this case.  Give
it a try if you're having trouble with excessive drawing or excessive
network traffic with full motion events.  For the drawing, the Dragger
default C<update_policy> is meant to achieve the same effect asynchronously.

It's a bit unfortunate that an update policy is part of a controller like a
scrollbar or dragger.  It'd be better if redraw frequency were left to the
widgets which are actually redrawing; or at least to an adaptor like a
Viewport for those without their own understanding.

=head1 OTHER NOTES

Some good choices for the C<cursor> while dragging are

    fleur                4-way arrow
    double-arrow         horizontal 2-way
    sb-h-double-arrow    horizontal 2-way
    sb-v-double-arrow    vertical 2-way

There's not much in the standard cursors for a grasping hand so you probably
have to make something like that from a pixmap.

Currently only a weak reference is kept to the target widget, so the fact
there's a dragger feature doesn't keep it alive forever.  This means in
particular it's safe to hold the dragger object in the widget instance data
without creating a circular reference.  But strong references are kept to
the adjustment objects since they probably should stay alive as long as the
widget and dragger do.  But perhaps this will change.

Having the C<button-motion-mask> and C<button-release-mask> set before the
drag won't normally cost very many extra events.

A missed release event can't be properly handled after the fact.
A C<get_pointer> can say whether the button is now down, but it may be the
user pressing elsewhere, and the x,y position of the drag release has been
completely lost.  That final release position is quite important.  If the
application is lagged you still want press/drag/release to move the widget
contents by the corresponding distance.  It's wrong and quite annoying if
the contents jump to where the mouse has gone after release.  The scrollbars
in some versions of mozilla for instance do that wrongly.

It'd be possible for the dragger to turn on C<button-motion-mask> when
starting the drag, if not already on, using an active grab and a
C<< $display->get_pointer >> to check for any missed movement.  But for now
that doesn't seem worthwhile, not while the release mask can't be similarly
adapted.

=head1 BUILDABLE

C<Gtk2::Ex::Dragger> can be built in a C<Gtk2::Builder> spec the same as any
other C<Glib::Object>.  The class name is "Gtk2__Ex__Dragger" as usual for
Perl-Gtk package name to class name conversion.  The target C<widget>,
C<hadjustment> and C<vadjustment> properties can be set to objects created
in the spec, for example

  <object class="Gtk2__Ex__Dragger" id="dragger">
    <property name="widget">viewport</property>
    <property name="hadjustment">hadjustment</property>
    <property name="vadjustment">vadjustment</property>
  </object>

See F<examples/builder.pl> in the Gtk2-Ex-Dragger sources for a complete
program.  Or F<examples/builder-internal.pl> shows how to connect up to
adjustment objects offered as "internal children" of a widget (which is a
handy way to expose what a widget creates, though no Gtk core widgets do
it).

=head1 SEE ALSO

L<Gtk2::Adjustment>, L<Gtk2::Ex::WidgetCursor>, L<Gtk2::Viewport>,
L<Gtk2::ScrolledWindow>

=head1 HOME PAGE

L<http://user42.tuxfamily.org/gtk2-ex-dragger/index.html>

=head1 LICENSE

Copyright 2007, 2008, 2009, 2010, 2011 Kevin Ryde

Gtk2-Ex-Dragger 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.

Gtk2-Ex-Dragger is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY



( run in 2.465 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )