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