1# You may distribute under the terms of either the GNU General Public License 2# or the Artistic License (the same terms as Perl itself) 3# 4# (C) Paul Evans, 2013-2021 -- leonerd@leonerd.org.uk 5 6use Object::Pad 0.57; 7 8package Tickit::Widget::VSplit 0.34; 9class Tickit::Widget::VSplit 10 :isa(Tickit::Widget::LinearSplit); 11 12use Tickit::Style; 13use Tickit::RenderBuffer qw( LINE_SINGLE CAP_BOTH ); 14 15use Carp; 16 17use List::Util qw( sum max ); 18 19=head1 NAME 20 21C<Tickit::Widget::VSplit> - an adjustable vertical split between two widgets 22 23=head1 SYNOPSIS 24 25 use Tickit; 26 use Tickit::Widget::VSplit; 27 use Tickit::Widget::Static; 28 29 my $vsplit = Tickit::Widget::VSplit->new 30 ->set_left_child ( Tickit::Widget::Static->new( text => "Text above" ) ), 31 ->set_right_child( Tickit::Widget::Static->new( text => "Text below" ) ); 32 33 Tickit->new( root => $vsplit )->run; 34 35=head1 DESCRIPTION 36 37This container widget holds two child widgets, displayed side by side. The two 38widgets are displayed with a vertical split bar between them, which reacts to 39mouse click-drag events, allowing the user to adjust the proportion of space 40given to the two widgets. 41 42=head1 STYLE 43 44The default style pen is used as the widget pen. The following style pen 45prefixes are also used: 46 47=over 4 48 49=item split => PEN 50 51The pen used to render the vertical split area 52 53=back 54 55The following style keys are used: 56 57=over 4 58 59=item spacing => INT 60 61The number of columns of spacing between the left and right child widgets 62 63=back 64 65The following style tags are used: 66 67=over 4 68 69=item :active 70 71Set when a mouse drag resize operation is occurring 72 73=back 74 75=cut 76 77style_definition base => 78 split_fg => "white", 79 split_bg => "blue", 80 spacing => 1; 81 82style_definition ':active' => 83 split_fg => "hi-white", 84 split_b => 1; 85 86style_reshape_keys qw( spacing ); 87 88use constant WIDGET_PEN_FROM_STYLE => 1; 89 90use constant VALUE_METHOD => "cols"; 91 92=head1 CONSTRUCTOR 93 94=head2 new 95 96 $vsplit = Tickit::Widget::VSplit->new( %args ) 97 98Constructs a new C<Tickit::Widget::VSplit> object. 99 100=cut 101 102ADJUSTPARAMS 103{ 104 my ( $params ) = @_; 105 106 croak "The 'left_child' constructor argument to ${\ref $self} is no longer recognised; use ->set_left_child instead" 107 if delete $params->{left_child}; 108 109 croak "The 'right_child' constructor argument to ${\ref $self} is no longer recognised; use ->set_right_child instead" 110 if delete $params->{right_child}; 111} 112 113method lines 114{ 115 return max( 116 $self->left_child ? $self->left_child->requested_lines : 1, 117 $self->right_child ? $self->right_child->requested_lines : 1, 118 ); 119} 120 121method cols 122{ 123 my $spacing = $self->get_style_values( "spacing" ); 124 return sum( 125 $self->left_child ? $self->left_child->requested_cols : 1, 126 $spacing, 127 $self->right_child ? $self->right_child->requested_cols : 1, 128 ); 129} 130 131=head1 ACCESSORS 132 133=cut 134 135=head2 left_child 136 137=head2 set_left_child 138 139 $child = $hsplit->left_child 140 141 $vsplit->set_left_child( $child ) 142 143Accessor for the child widget used in the left half of the display. 144 145=cut 146 147*left_child = __PACKAGE__->can( "A_child" ); 148*set_left_child = __PACKAGE__->can( "set_A_child" ); 149 150=head2 right_child 151 152=head2 set_right_child 153 154 $child = $hsplit->right_child 155 156 $vsplit->set_right_child( $child ) 157 158Accessor for the child widget used in the right half of the display. 159 160These mutators returning the container widget itself making them suitable to 161use as chaining mutators; e.g. 162 163 my $container = Tickit::Widget::VSplit->new( ... ) 164 ->set_left_child ( Tickit::Widget::Box->new ... ) 165 ->set_right_child( Tickit::Widget::Box->new ... ); 166 167=cut 168 169*right_child = __PACKAGE__->can( "B_child" ); 170*set_right_child = __PACKAGE__->can( "set_B_child" ); 171 172method _make_child_geom 173{ 174 my ( $start, $len ) = @_; 175 return ( 0, $start, $self->window->lines, $len ); 176} 177 178method render_to_rb 179{ 180 my ( $rb, $rect ) = @_; 181 182 my $split_len = $self->_split_len; 183 my $split_at = $self->_split_at; 184 185 my $lines = $self->window->lines; 186 187 $rb->setpen( $self->get_style_pen( "split" ) ); 188 189 $rb->vline_at( 0, $lines-1, $split_at, LINE_SINGLE, undef, CAP_BOTH ); 190 191 if( $split_len > 2 ) { 192 foreach my $line ( $rect->linerange ) { 193 $rb->erase_at( $line, $split_at + 1, $split_len - 2 ); 194 } 195 } 196 if( $split_len > 1 ) { 197 $rb->vline_at( 0, $lines-1, $split_at + $split_len - 1, LINE_SINGLE, undef, CAP_BOTH ); 198 } 199} 200 201method on_mouse 202{ 203 my ( $args ) = @_; 204 205 if( $args->type ne "wheel" and $args->button == 1 ) { 206 return $self->_on_mouse( $args->type, $args->col ); 207 } 208 return; 209} 210 211=head1 AUTHOR 212 213Paul Evans <leonerd@leonerd.org.uk> 214 215=cut 216 2170x55AA; 218