package Kephra::App::EditPanel::Fold; our $VERSION = '0.05'; use strict; use warnings; # sub _ep_ref { Kephra::App::EditPanel::is($_[0]) ? $_[0] : Kephra::App::EditPanel::_ref() } sub _config { Kephra::App::EditPanel::Margin::_config()->{fold} } sub _attribute { 'folded_lines' } # sub _is_head_level { # is this the fold level of a head node ? my $level = shift; return 1 if ($level % 1024) < (($level >> 16) % 1024); } sub _is_node { my $line = shift; return 1 if _ep_ref()->GetFoldParent($line+1) == $line; } sub _get_line { # my ($ep, $event) = @_; $ep = _ep_ref(); my $line = Kephra::App::EditPanel::Margin::clicked_on_line($event); # save position where context menu poped so we can fold there if ($line == -1){ if (defined $event and ref $event eq 'Wx::StyledTextEvent'){ $line = $ep->LineFromPosition( $event->GetPosition() ); } else { $line = $ep->GetCurrentLine() } } return $line; } # sub store { for my $doc_nr (@{Kephra::Document::Data::all_nr()}) { my $ep = Kephra::Document::Data::_ep($doc_nr); my @lines; for (0 .. $ep->GetLineCount()-1) { push @lines, $_ unless $ep->GetFoldExpanded( $_ ); } Kephra::Document::Data::set_attribute( _attribute(), \@lines, $doc_nr); } } sub restore { my $doc_nr = Kephra::Document::Data::valid_or_current_doc_nr(shift); my $ep = Kephra::Document::Data::_ep($doc_nr); return if $doc_nr < 0 or not ref $ep; my $lines = Kephra::Document::Data::get_attribute( _attribute(), $doc_nr); return unless ref $lines eq 'ARRAY'; for (reverse @$lines){ $ep->ToggleFold($_) if $ep->GetFoldExpanded($_); } } # # folding functions # sub toggle_here { my $ep = _ep_ref(); my $line = _get_line(@_); $ep->ToggleFold($line); Kephra::Edit::Goto::next_visible_pos() if _config()->{keep_caret_visible} and not $ep->GetFoldExpanded($line); } sub toggle_recursively { my $ep = _ep_ref(); my $line = _get_line(@_); unless ( _is_node( $line ) ) { $line = $ep->GetFoldParent($line); return if $line == -1; } my $node_xpanded = not $ep->GetFoldExpanded($line); my $cursor = $ep->GetLastChild($line, -1); while ($cursor >= $line) { $ep->ToggleFold($cursor) if $ep->GetFoldExpanded($cursor) xor $node_xpanded; $cursor--; } Kephra::Edit::Goto::next_visible_pos() if _config()->{keep_caret_visible} and not $node_xpanded; } sub toggle_siblings { toggle_siblings_of_line( _get_line(@_) ) } sub toggle_siblings_of_line { my $ep = _ep_ref(); my $line = shift; return if $line < 0 or $line > ($ep->GetLineCount()-1); my $level = $ep->GetFoldLevel($line); my $parent = $ep->GetFoldParent($line); my $xp = not $ep->GetFoldExpanded($line); my $first_line = $parent; my $cursor = $ep->GetLastChild($parent, -1 ); ($first_line, $cursor) = (-1, $ep->GetLineCount()-2) if $parent == -1; while ($cursor > $first_line){ $ep->ToggleFold($cursor) if $ep->GetFoldLevel($cursor) == $level and ($ep->GetFoldExpanded($cursor) xor $xp); $cursor--; } Kephra::Edit::Goto::next_visible_pos() if _config()->{keep_caret_visible} and not $xp; $ep->EnsureCaretVisible; } sub toggle_level { my $ep = _ep_ref(); my $line = _get_line(@_); return if $line < 0 or $line > ($ep->GetLineCount()-1); my $level = $ep->GetFoldLevel($line); my $xp = not $ep->GetFoldExpanded($line); for (0 .. $ep->GetLineCount()-1) { $ep->ToggleFold($_) if $ep->GetFoldLevel($_) == $level and ($ep->GetFoldExpanded($_) xor $xp); } Kephra::Edit::Goto::next_visible_pos() if _config()->{keep_caret_visible} and not $xp; $ep->EnsureCaretVisible; } sub toggle_all { my $ep = _ep_ref(); my $newline = my $oldline = $ep->GetLineCount(); # looking for the head of heads // capi di capi while ($oldline == $newline and $oldline > 0){ $newline = --$oldline; $newline = $ep->GetFoldParent($newline) while $ep->GetFoldParent($newline) > -1; } my $root_unfolded = $ep->GetFoldExpanded($newline); $root_unfolded ? fold_all() : unfold_all(); Kephra::Edit::Goto::next_visible_pos() if _config()->{keep_caret_visible} and $root_unfolded; } sub fold_all { my $ep = _ep_ref(); my $cursor = $ep->GetLineCount()-1; while ($cursor > -1) { $ep->ToggleFold($cursor) if $ep->GetFoldExpanded($cursor); $cursor--; } } sub unfold_all { my $ep = _ep_ref(); my $cursor = $ep->GetLineCount()-1; while ($cursor > -1) { $ep->ToggleFold($cursor) unless $ep->GetFoldExpanded($cursor); $cursor--; } } sub show_folded_children { #my $ep = _ep_ref(); #my $parent = _get_line(@_); #unless ( _is_head_level( $ep->GetFoldLevel($parent) ) ) { #$parent = $ep->GetFoldParent($parent); #return if $parent == -1; #} #$ep->ToggleFold($parent) unless $ep->GetFoldExpanded($parent); #my $cursöor = $ep->GetLastChild( $parent, -1 ); #my $level = $ep->GetFoldLevel($parent) >> 16; #while (@cursor > $parent) { #$ep->ToggleFold($cursor) if $ep->GetFoldLevel($cursor) % 2048 == $level #and $ep->GetFoldExpanded($cursor); #$cursor--; #} } 1; =head1 NAME Kephra::App::EditPanel::Fold - code folding functions =head1 DESCRIPTION =cut