Sponsoring The Perl Toolchain Summit 2025: Help make this important event another success Learn more

our $VERSION = '0.15';
use strict;
sub _ID { 'searchbar' }
sub _ref { Kephra::ToolBar::_ref( _ID(), $_[0]) }
sub _config { Kephra::API::settings()->{app}{ _ID() } }
sub _search_config { Kephra::API::settings()->{search} }
my $highlight_search; # set 1 if searchbar turns red
#
sub create {
# load searchbar definition
my $bar_def = Kephra::Config::File::load_from_node_data( _config() );
unless ($bar_def) {
$bar_def = Kephra::Config::Tree::get_subtree
( Kephra::Config::Default::toolbars(), _ID() );
}
# create searchbar with buttons
my $rest_widgets = Kephra::ToolBar::create_new( _ID(), $bar_def);
my $bar = _ref();
# apply special searchbar widgets
for my $item_data (@$rest_widgets){
my $ctrl;
if ($item_data->{type} eq 'combobox' and $item_data->{id} eq 'find'){
my $find_input = $bar->{find_input} = Wx::ComboBox->new (
$bar , -1, '', [-1,-1], [$item_data->{size},-1], [],
&Wx::wxTE_PROCESS_ENTER
);
$find_input->SetDropTarget
( Kephra::Edit::Search::InputTarget->new($find_input, 'find'));
$find_input->SetValue( Kephra::Edit::Search::get_find_item() );
$find_input->SetSize($item_data->{size},-1) if $item_data->{size};
if ( _search_config()->{history}{use} ){
$find_input->Append($_) for @{ Kephra::Edit::Search::get_find_history() }
}
Wx::Event::EVT_TEXT( $bar, $find_input, sub {
my ($bar, $event) = @_;
my $old = Kephra::Edit::Search::get_find_item();
my $new = $find_input->GetValue;
if ($new ne $old){
Kephra::Edit::Search::set_find_item( $new );
Kephra::Edit::Search::first_increment()
if _search_config()->{attribute}{incremental}
and Wx::Window::FindFocus() eq $find_input;
}
} );
Wx::Event::EVT_KEY_DOWN( $find_input, sub {
my ( $fi, $event ) = @_;
my $key = $event->GetKeyCode;
my $found_something;
my $ep = Kephra::App::EditPanel::_ref();
if ( $key == &Wx::WXK_RETURN ) {
if ($event->ControlDown and $event->ShiftDown)
{Kephra::Edit::Search::find_last() }
elsif ($event->ControlDown){Kephra::Edit::Search::find_first()}
elsif ($event->ShiftDown) {Kephra::Edit::Search::find_prev() }
else {Kephra::Edit::Search::find_next() }
} elsif ($key == &Wx::WXK_F3){
$event->ShiftDown
? Kephra::Edit::Search::find_prev()
: Kephra::Edit::Search::find_next();
} elsif ($key == &Wx::WXK_ESCAPE) {
give_editpanel_focus_back()
} elsif ($key == 65 and $event->ControlDown) {# A
$bar->{find_input}->SetSelection
(0, $bar->{find_input}->GetLastPosition);
} elsif ($key == 70 and $event->ControlDown) {# F
give_editpanel_focus_back()
} elsif ( $key == 71 ) { # G
if ($event->ControlDown and $event->ShiftDown){
give_editpanel_focus_back();
Kephra::Edit::Goto::last_edit();
}
} elsif ($key == 81) { # Q
switch_visibility() if $event->ControlDown;
#} elsif ( $key == &Wx::WXK_LEFT ){ &Wx::wxSTC_CMD_CHARLEFT return
#} elsif ($key == &Wx::WXK_RIGHT ){ &Wx::wxSTC_CMD_CHARRIGHT return;
} elsif ($key == &Wx::WXK_UP){
if ($event->ControlDown) {
$ep->CmdKeyExecute( &Wx::wxSTC_CMD_LINESCROLLUP ); return;
}
} elsif ($key == &Wx::WXK_DOWN) {
if ($event->ControlDown) {
$ep->CmdKeyExecute( &Wx::wxSTC_CMD_LINESCROLLDOWN ); return;
}
} elsif ($key == &Wx::WXK_PAGEUP) {
if ($event->ControlDown) {
my $pos = $bar->{find_input}->GetInsertionPoint;
Kephra::Document::Change::tab_left();
Wx::Window::SetFocus($bar->{find_input});
$bar->{find_input}->SetInsertionPoint($pos);
} else {
$ep->CmdKeyExecute( &Wx::wxSTC_CMD_PAGEUP );
}
return;
} elsif ($key == &Wx::WXK_PAGEDOWN){
if ($event->ControlDown) {
my $pos = $bar->{find_input}->GetInsertionPoint;
Kephra::Document::Change::tab_right();
Wx::Window::SetFocus($bar->{find_input});
$bar->{find_input}->SetInsertionPoint($pos);
} else {
$ep->CmdKeyExecute( &Wx::wxSTC_CMD_PAGEDOWN );
}
return;
} elsif ($key == &Wx::WXK_HOME and $event->ControlDown) {
$ep->CmdKeyExecute( &Wx::wxSTC_CMD_DOCUMENTSTART ); return;
} elsif ($key == &Wx::WXK_END and $event->ControlDown) {
$ep->CmdKeyExecute( &Wx::wxSTC_CMD_DOCUMENTEND ); return;
} elsif ($key == &Wx::WXK_BACK and $event->ControlDown and $event->ShiftDown) {
my $pos = $bar->{find_input}->GetInsertionPoint;
Kephra::Document::Change::switch_back();
Wx::Window::SetFocus($bar->{find_input});
$bar->{find_input}->SetInsertionPoint($pos);
} else {
#print "$key\n"
}
$event->Skip;
} );
#Wx::Event::EVT_COMBOBOX( $find_input, -1, sub{ } );
Wx::Event::EVT_ENTER_WINDOW( $find_input, sub {
Wx::Window::SetFocus($find_input) if _config()->{autofocus};
disconnect_find_input();
});
Wx::Event::EVT_LEAVE_WINDOW( $find_input,sub{connect_find_input($find_input) });
connect_find_input($find_input);
$highlight_search = 1;
$ctrl = $find_input;
}
elsif ($item_data->{type} eq 'combobox' and $item_data->{id} eq 'replace'){
my $replace_input = $bar->{replace_input} = Wx::ComboBox->new (
$bar , -1, '', [-1,-1], [$item_data->{size},-1], [],
&Wx::wxTE_PROCESS_ENTER
);
$replace_input->SetDropTarget
( Kephra::Edit::Search::InputTarget->new($replace_input, 'replace'));
$replace_input->SetValue( Kephra::Edit::Search::get_replace_item() );
$replace_input->SetSize($item_data->{size},-1) if $item_data->{size};
if ( _search_config()->{history}{use} ){
$replace_input->Append($_) for @{ Kephra::Edit::Search::get_replace_history() }
}
$ctrl = $replace_input;
}
if (ref $ctrl) {
$bar->InsertControl( $item_data->{pos}, $ctrl );
}
}
Wx::Event::EVT_MIDDLE_DOWN( $bar, sub {
my ($widget, $event) = @_;
my $ep = Kephra::App::EditPanel::_ref();
if ($ep->GetSelectedText){
Kephra::Edit::Search::set_selection_as_find_item();
Kephra::Edit::Search::find_next();
} else {
Kephra::Edit::Goto::last_edit();
}
} );
Wx::Event::EVT_RIGHT_DOWN ( $bar, sub {
return unless get_contextmenu_visibility();
my ($widget, $event) = @_;
my ($x, $y) = ($event->GetX, $event->GetY);
my $menu = Kephra::App::ContextMenu::get(_config()->{contextmenu});
$bar->PopupMenu($menu, $x, $y) if Kephra::Menu::is($menu);
} );
Wx::Event::EVT_LEAVE_WINDOW($bar, \&leave_focus);
$bar->Realize;
$bar;
}
sub destroy{ Kephra::ToolBar::destroy ( _ID() ) }
#
sub connect_find_input {
my $find_input = shift;
my $ID = _ID();
my $add_call = \&Kephra::EventTable::add_call;
&$add_call( 'find.item.changed', $ID.'_input_refresh', sub {
my $value = Kephra::Edit::Search::get_find_item();
return if $value eq $find_input->GetValue;
$find_input->SetValue( $value );
my $pos = $find_input->GetLastPosition;
$find_input->SetSelection($pos,$pos);
}, $ID);
&$add_call( 'find.item.history.changed', $ID.'_popupmenu', sub {
$find_input->Clear();
$find_input->Append($_) for @{ Kephra::Edit::Search::get_find_history() };
$find_input->SetValue( Kephra::Edit::Search::get_find_item() );
$find_input->SetInsertionPointEnd;
}, $ID);
&$add_call( 'find', $ID.'_color_refresh', \&colour_find_input, $ID);
}
sub disconnect_find_input{ Kephra::EventTable::del_own_subscriptions(_ID()) }
#
sub colour_find_input {
my $find_input = _ref()->{find_input};
my $found_something = Kephra::Edit::Search::_find_pos() > -1
? 1 : 0;
return if $highlight_search eq $found_something;
$highlight_search = $found_something;
if ($found_something){
$find_input->SetForegroundColour( Wx::Colour->new( 0x00, 0x00, 0x55 ) );
$find_input->SetBackgroundColour( Wx::Colour->new( 0xff, 0xff, 0xff ) );
} else {
$find_input->SetForegroundColour( Wx::Colour->new( 0xff, 0x33, 0x33 ) );
$find_input->SetBackgroundColour( Wx::Colour->new( 0xff, 0xff, 0xff ) );
}
$find_input->Refresh;
}
sub enter_focus {
my $bar = _ref();
switch_visibility() unless get_visibility();
Wx::Window::SetFocus($bar->{find_input}) if defined $bar->{find_input};
}
sub leave_focus { switch_visibility() if _config()->{autohide} }
#
sub give_editpanel_focus_back{
leave_focus();
Wx::Window::SetFocus( Kephra::App::EditPanel::_ref() );
}
sub position { _config()->{position} }
#
# set visibility
sub show {
my $visible = shift || get_visibility();
my $bar = _ref();
return unless $bar;
my $sizer = $bar->GetParent->GetSizer;
$sizer->Show( $bar, $visible );
$sizer->Layout();
_config()->{visible} = $visible;
}
sub get_visibility { _config()->{visible} }
sub switch_visibility { _config()->{visible} ^= 1; show(); }
sub get_contextmenu_visibility { _config()->{contextmenu_visible} }
sub switch_contextmenu_visibility { _config()->{contextmenu_visible} ^= 1 }
1;
=head1 NAME
Kephra::App::SearchBar - specialized toolbar for naviagtion related things
=head1 DESCRIPTION
=cut