App-Chart

 view release on metacpan or  search on metacpan

lib/App/Chart/Gtk2/Ex/LineClipper.pm  view on Meta::CPAN


C<$points> is a reference to an array of X,Y values, one after the other.
C<$drawable> is a C<Gtk2::Gdk::Drawable> (window, pixmap, etc) and C<$gc> is
a C<Gtk2::Gdk::GC>.  Eg.

    App::Chart::Gtk2::Ex::LineClipper::clipped_draw_lines
        ($drawable, $gc, 1, [ 100,100, 200,200, 300,100 ]);

C<$line_width> should be the width in pixels of the lines C<$gc> will draw.
This is used to know how far off the drawable the clipping must extend so
the C<cap_style> doesn't show.  C<clipped_draw_lines> doesn't simply read
C<$line_width> from C<< $gc->get_values >> because that call does a
round-trip to the X server.  A width bigger than actually in use is fine;
for instance you might just pass 20 pixels if you know you never draw lines
wider than that.  A width 0 is interpreted as a 1 pixel "thin line", the
same as happens in the GC.

If C<$points> is an empty array, or an array of just one X,Y point, then
nothing at all is drawn.  This handling of one point adds certainty to what
plain C<< $win->draw_lines >> does; for it a single X,Y of a 0-width "thin
line" might or might not be drawn, depending on the server.

=back

=head1 ACCUMULATOR OBJECT

=over 4

=item C<< App::Chart::Gtk2::Ex::LineClipper->new (drawable => $drawable, ...) >>

Create and return a new LineClipper object to accumulate and draw connected
line segments on C<$drawable> using C<clipped_draw_lines> above.
C<$drawable> is a C<Gtk2::Gdk::Drawable> object as above, and a
C<line_width> parameter can be passed to set that for the clipping (again as
above).

    my $linedrawer = App::Chart::Gtk2::Ex::LineClipper->new
                         (drawable => $drawable,
                          line_width => 5); # pixels

By default a single solitary X,Y point is not drawn, on the principle that
it's not a line segment, but the C<draw_point> option can be set true to
have it shown as a circle of the given C<line_width>.  Eg.

    my $linedrawer = App::Chart::Gtk2::Ex::LineClipper->new
                         (drawable => $drawable,
                          line_width => 5,  # pixels
                          draw_point => 1); # true

If you're wondering that C<line_width> used as a diameter won't come out
circular if the pixels aren't square, well, yes, but the same is true of the
line drawing.  The single width used vertically and horizontally for the
line segments makes them appear wider or narrower according to their angle.

=item C<< $linedrawer->add ($gc, $x, $y) >>

Add a point to C<$linedrawer>.  The points accumulated will have connected line
segments drawn from each to the next, in the order they're added.

C<$gc> is a C<Gtk2::Gdk::GC> for the new segment, ie. from the current
endpoint to the new C<$x>,C<$y>.  Different GCs can be used for different
segments and the LineClipper takes care of passing runs of the same GC to
C<clipped_draw_lines>.

=item C<< $linedrawer->end() >>

Draw the line segments accumulated, if any, and set C<$linedrawer> back to
empty, ready to start a new completely separate sequence of points.

You can use this to force a gap between points, ie. draw everything
accumulated so far and make subsequent points a new run.

C<end> is called automatically when C<$linedrawer> is destroyed, which means
that if you've got a complicated loop generating the points then you can
just C<return> or jump out from multiple places, confident that letting the
LineClipper go out of scope will flush what you've accumulated.

=back

=head1 OTHER NOTES

The choice between the direct C<clipped_draw_lines> and the accumulator
object is purely a matter of convenience.  If you've got all your values in
an array and want to draw just one colour (one GC) then the best idea is to
C<map> or whatever to scale and build an X,Y array, then call
C<clipped_draw_lines>.  But if you're going to make decisions about skipping
some points or changing colours or leaving gaps while passing over the data
then you may find the accumulator easier.

When switching to a different GC with C<add>, the join between the lines in
the old and new GCs doesn't use the join style (C<Gtk2::Gdk::JoinStyle>) of
either GC, but rather merely gets the cap style (C<Gtk2::Gdk::CapStyle>) of
each where the C<draw_lines> from one ends and the other begins.  This means
you can't get a nice mitre or bevel when changing colours etc.  For now it
seems far too much trouble to try to do anything about that.  The suggestion
would be to use a cap style of C<round> which comes out looking nice at any
angle.  Or if you only do GC switching with lines a few pixels wide then one
or two slightly off where they meet will be hardly noticeable.

=head1 SEE ALSO

L<Gtk2::Gdk::Drawable>, L<Gtk2::Gdk::GC>, L<Gtk2::Ex::WidgetBits>

=cut



( run in 1.196 second using v1.01-cache-2.11-cpan-39bf76dae61 )