1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
# You may distribute under the terms of either the GNU General Public License
# or the Artistic License (the same terms as Perl itself)
#
# (C) Paul Evans, 2013-2021 -- leonerd@leonerd.org.uk
use v5.26; # signatures
use Object::Pad 0.73 ':experimental(init_expr)';
package Tickit::Widget::ScrollBox::Extent 0.12;
class Tickit::Widget::ScrollBox::Extent;
=head1 NAME
C<Tickit::Widget::ScrollBox::Extent> - represents the range of scrolling extent
=head1 DESCRIPTION
This small utility object stores the effective scrolling range for a
L<Tickit::Widget::ScrollBox>. They are not constructed directly, but instead
returned by the C<hextent> and C<vextent> methods of the associated ScrollBox.
=cut
field $_start = 0;
field $_total;
field $_scrollbox :param :weak;
field $_id :param;
method $clamp ()
{
my $limit = $self->total - $self->viewport;
$_start = $limit if $_start > $limit;
}
# Internal; used by T:W:ScrollBox
field $_viewport;
method set_viewport ( $viewport )
{
$_viewport = $viewport;
$self->$clamp if defined $_total;
}
=head1 ACCESSORS
=cut
=head2 viewport
$viewport = $extent->viewport
Returns the size of the viewable portion of the scrollable area (the
"viewport").
=cut
method viewport { $_viewport }
=head2 total
$total = $extent->total
Returns the total size of the scrollable area; which is always at least the
size of the viewport.
=head2 set_total
$extent->set_total( $total )
Sets the total size of the scrollable area. This method should only be used by
the child widget, when it is performing smart scrolling.
=cut
method total ()
{
my $viewport = $_viewport;
my $total = $_total;
$total = $viewport if $viewport > $total;
return $total;
}
method real_total () { $_total }
method set_total ( $total )
{
return if defined $_total and $_total == $total;
$_total = $total;
$self->$clamp if defined $_viewport;
$_scrollbox->_extent_scrolled( $_id, 0, undef );
}
=head2 limit
$limit = $extent->limit
Returns the limit of the offset; the largest value the start offset may be.
This is simply C<$total - $viewport>, with a limit applied so that it returns
zero rather than a negative value, in the case that the viewport is larger
than the total.
=cut
method limit ()
{
my $limit = $_total - $_viewport;
$limit = 0 if $limit < 0;
return $limit;
}
=head2 start
$start = $extent->start
Returns the start position offset of the viewport within the total area. This
is always at least zero, and no greater than the limit.
=cut
method start () { $_start }
=head1 METHODS
=cut
=head2 scroll
$extent->scroll( $delta )
Requests to move the start by the amount given. This will be clipped if it
moves outside the allowed range.
=cut
method scroll ( $delta )
{
$self->scroll_to( $self->start + $delta );
}
=head2 scroll_to
$extent->scroll_to( $new_start )
Requests to move the start to that given. This will be clipped if it is
outside the allowed range.
=cut
method scroll_to ( $start )
{
my $limit = $self->limit;
$start = $limit if $start > $limit;
$start = 0 if $start < 0;
return if $_start == $start;
my $delta = $start - $_start;
$_start = $start;
$_scrollbox->_extent_scrolled( $_id, $delta, $start );
}
=head2 scrollbar_geom
( $bar_top, $mark_top, $mark_bottom, $bar_bottom ) = $extent->scrollbar_geom( $top, $length )
Calculates the start and end positions of a scrollbar and the mark within it
to represent the position of the extent. Returns four integer indexes within
C<$length>.
=cut
method scrollbar_geom ( $top, $length )
{
my $total = $self->total;
my $bar_length = int( $self->viewport * $length / $total + 0.5 );
$bar_length = 1 if $bar_length < 1;
my $bar_start = $top + int( $self->start * $length / $total + 0.5 );
return ( $top, $bar_start, $bar_start + $bar_length, $top + $length );
}
=head1 AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
=cut
0x55AA;
|