package Kephra::App::EditPanel::Margin; our $VERSION = '0.13'; use strict; use warnings; my $mouse_y_pos; sub _ep_ref { Kephra::App::EditPanel::is($_[0]) ? $_[0] : Kephra::App::EditPanel::_ref() } sub _all_ref { Kephra::Document::Data::get_all_ep() } sub _edit_config { Kephra::App::EditPanel::_config() } sub _config { _edit_config()->{margin}} sub _line_config { _config()->{linenumber}} sub _fold_config { _config()->{fold} } sub _marker_config { _config()->{marker} } sub width { my $ep = _ep_ref(shift); my $width; $width += $ep->GetMarginWidth($_) for 0..2; $width } sub in_nr { my $x = shift; my $ep = _ep_ref(shift); my $border; for my $margin (0..2){ $border += $ep->GetMarginWidth($margin); return $margin if $x <= $border; } return -1; } sub apply_settings_here {# eval view settings for the margin of this edit panel obj my $ep = _ep_ref(shift); # defining the 3 margins $ep->SetMarginType( 0, &Wx::wxSTC_MARGIN_SYMBOL ); $ep->SetMarginType( 1, &Wx::wxSTC_MARGIN_NUMBER ); $ep->SetMarginType( 2, &Wx::wxSTC_MARGIN_SYMBOL ); $ep->SetMarginMask( 0, 0x01FFFFFF ); $ep->SetMarginMask( 1, 0 ); $ep->SetMarginMask( 2, &Wx::wxSTC_MASK_FOLDERS ); $ep->SetMarginSensitive( 0, 1 ); $ep->SetMarginSensitive( 1, 1 ); $ep->SetMarginSensitive( 2, 1 ); # setting folding markers my $color = \&Kephra::Config::color; my $f = &$color( _fold_config()->{fore_color} ); my $b = &$color( _fold_config()->{back_color} ); if (_fold_config()->{style} eq 'arrows') { $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDER, &Wx::wxSTC_MARK_ARROW, $b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDEREND, &Wx::wxSTC_MARK_ARROW, $b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDEROPEN, &Wx::wxSTC_MARK_ARROWDOWN,$b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDEROPENMID,&Wx::wxSTC_MARK_ARROWDOWN,$b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDERMIDTAIL,&Wx::wxSTC_MARK_EMPTY, $b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDERTAIL, &Wx::wxSTC_MARK_EMPTY, $b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDERSUB, &Wx::wxSTC_MARK_EMPTY, $b,$f); } else { $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDER, &Wx::wxSTC_MARK_BOXPLUS, $b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDEREND, &Wx::wxSTC_MARK_BOXPLUSCONNECTED,$b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDEROPEN, &Wx::wxSTC_MARK_BOXMINUS, $b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDEROPENMID,&Wx::wxSTC_MARK_BOXMINUSCONNECTED,$b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDERMIDTAIL,&Wx::wxSTC_MARK_TCORNER, $b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDERTAIL, &Wx::wxSTC_MARK_LCORNER, $b,$f); $ep->MarkerDefine(&Wx::wxSTC_MARKNUM_FOLDERSUB, &Wx::wxSTC_MARK_VLINE, $b,$f); } $ep->SetFoldFlags(16) if _fold_config()->{flag_line}; show_marker_here($ep); Kephra::Document::Data::set_attribute('margin_linemax', 0); #apply_line_number_width_here($ep); apply_line_number_color_here($ep); show_fold_here($ep); apply_text_width_here($ep); } sub refresh_changeable_settings { my $ep = _ep_ref(shift); apply_line_number_color_here($ep); apply_fold_flag_color_here($ep); } sub get_contextmenu_visibility { _edit_config()->{contextmenu}{margin} } sub switch_contextmenu_visibility { _edit_config()->{contextmenu}{margin} ^= 1 } # # deciding what to do when clicked on edit panel margin # sub on_left_click { my ($ep, $event, $nr) = @_; if ($nr < 2) {Kephra::Edit::Marker::toggle_marker_here(@_) } elsif ($nr == 2) {Kephra::App::EditPanel::Fold::toggle_here(@_) } } sub on_middle_click { my ($ep, $event, $nr) = @_; Kephra::Edit::Marker::toggle_bookmark_here(@_) if $nr < 2; Kephra::App::EditPanel::Fold::toggle_recursively($ep, $event) if $nr == 2; } sub on_right_click { my ($ep, $event, $nr) = @_; my ($x, $y) = ($event->GetX, $event->GetY); if ($nr > -1 and $nr < 2 and get_contextmenu_visibility() ){ $mouse_y_pos = $event->GetY; $ep->PopupMenu( Kephra::App::ContextMenu::get (_edit_config()->{contextmenu}{ID_margin} ), $x, $y); undef $mouse_y_pos; } elsif ($nr == 2) { $event->LeftIsDown ? Kephra::App::EditPanel::Fold::toggle_all() : Kephra::App::EditPanel::Fold::toggle_level($ep, $event); } } sub clicked_on_line { my $event = shift; return -1 unless defined $mouse_y_pos or ref $event eq 'Wx::MouseEvent'; my $ep = _ep_ref(); my $x = width($ep) + 5; # $mouse_y_pos is saved position where context menu poped so we can fold there my $y = defined $mouse_y_pos ? $mouse_y_pos : $event->GetY; my $max_y = $ep->GetSize->GetHeight; my $pos = $ep->PositionFromPointClose($x, $y); while ($pos < 0 and $y+10 < $max_y) { $pos = $ep->PositionFromPointClose($x, $y += 10); } return $ep->LineFromPosition($pos); } # # line number margin # sub line_number_visible{ _line_config->{visible} } sub switch_line_number { _line_config->{visible} ^= 1; apply_line_number_width() } sub apply_line_number_width { apply_line_number_width_here($_) for @{_all_ref()} } sub apply_line_number_width_here { my $ep = _ep_ref(shift); my $doc_nr = shift; $doc_nr = Kephra::Document::Data::nr_from_ep($ep) unless defined $doc_nr; my $config = _line_config(); my $char_width = Kephra::Document::Data::get_attribute('line_nr_margin_width', $doc_nr); if (not defined $char_width or not $char_width) { $char_width = needed_line_number_width($ep); Kephra::Document::Data::set_attribute ('line_nr_margin_width', $char_width, $doc_nr); } my $px_width = $config->{visible} ? $char_width * _edit_config()->{font}{size} : 0; $ep->SetMarginWidth( 1, $px_width ); if ($config->{autosize} and $config->{visible}) { Kephra::EventTable::add_call ('document.text.change', 'autosize_line_number', \&line_number_autosize_update); } else { Kephra::EventTable::del_call ('document.text.change', 'autosize_line_number'); } } sub set_line_number_width_here { my $width = shift; my $doc_nr = shift or Kephra::Document::Data::current_nr(); my $config = _line_config(); Kephra::Document::Data::set_attribute('line_nr_margin_width', $width, $doc_nr); Kephra::Document::Data::set_attribute('margin_linemax', 10 ** $width - 1, $doc_nr); apply_line_number_width_here( Kephra::Document::Data::_ep($doc_nr) ); } sub needed_line_number_width { my $width = length _ep_ref(shift)->GetLineCount; my $min = _line_config()->{min_width}; $width = $min if defined $min and $min and $min > $width; return $width; } sub autosize_line_number { my $ep = _ep_ref(shift); my $doc_nr = shift; $doc_nr = Kephra::Document::Data::nr_from_ep($ep) unless defined $doc_nr; my $config = _line_config(); return unless _line_config()->{autosize}; my $need = needed_line_number_width($ep); my $is = Kephra::Document::Data::get_attribute('line_nr_margin_width', $doc_nr); set_line_number_width_here($need, $doc_nr) if not defined $is or $need > $is; } sub line_number_autosize_update { my $line_max = Kephra::Document::Data::get_attribute('margin_linemax'); my $ep = _ep_ref(); autosize_line_number($ep) if $ep->GetLineCount > $line_max; } sub apply_line_number_color { apply_line_number_color_here($_) for @{_all_ref()} } sub apply_line_number_color_here { my $ep = _ep_ref(shift); my $config = _line_config(); my $color = \&Kephra::Config::color; $ep->StyleSetForeground(&Wx::wxSTC_STYLE_LINENUMBER,&$color($config->{fore_color})); $ep->StyleSetBackground(&Wx::wxSTC_STYLE_LINENUMBER,&$color($config->{back_color})); } # # marker margin # sub marker_visible { _marker_config->{visible} } sub show_marker { show_marker_here($_) for @{_all_ref()} } sub show_marker_here { my $ep = _ep_ref(shift); marker_visible() ? $ep->SetMarginWidth(0, 16) : $ep->SetMarginWidth(0, 0); } sub switch_marker { _marker_config->{visible} ^= 1; show_marker(); } # # fold margin # sub fold_visible { _fold_config()->{visible} } sub show_fold { show_fold_here($_) for @{_all_ref()} } sub show_fold_here { my $ep = _ep_ref(shift); my $visible = fold_visible(); my $width = $visible ? 16 : 0; $ep->SetProperty('fold' => $visible); $ep->SetMarginWidth( 2, $width ); Kephra::App::EditPanel::Fold::unfold_all() unless $visible; } sub switch_fold { _fold_config()->{visible} ^= 1; show_fold(); } sub apply_fold_flag_color { apply_text_width_here($_) for @{_all_ref()}; } sub apply_fold_flag_color_here { my $ep = _ep_ref(shift); my $color = Kephra::Config::color( _fold_config()->{fore_color} ); $ep->StyleSetForeground(&Wx::wxSTC_STYLE_DEFAULT, $color); } # # extra text margin # sub get_text_width { _config->{text} } sub set_text_width { _config->{text} = shift; apply_text_width(); } sub apply_text_width { apply_text_width_here($_) for @{_all_ref()} } sub apply_text_width_here { my $ep = _ep_ref(shift); my $width = get_text_width(); $ep->SetMargins( $width, $width ); } 1; #wxSTC_MARK_MINUS wxSTC_MARK_PLUS wxSTC_MARK_CIRCLE wxSTC_MARK_SHORTARROW #wxSTC_FOLDFLAG_LINEBEFORE_CONTRACTED =head1 NAME Kephra::App::EditPanel::Margin - managing margin visuals for marker, linenumber, folding & extra space =head1 DESCRIPTION =cut