our
$VERSION
=
'0.27'
;
sub
_ID {
'search_dialog'
}
my
$ref
;
sub
_ref {
$ref
=
ref
$_
[0] eq
'Wx::Dialog'
?
$_
[0] :
$ref
}
my
$highlight_search
;
my
$active
;
my
%color
= (
norm_fore
=> Wx::Colour->new( 0x00, 0x00, 0x55 ),
norm_back
=> Wx::Colour->new( 0xff, 0xff, 0xff ),
alert_fore
=> Wx::Colour->new( 0xff, 0x33, 0x33 ),
alert_back
=> Wx::Colour->new( 0xff, 0xff, 0xff ),
);
sub
find {
my
$d
= ready();
my
$selection
= Kephra::App::EditPanel::_ref()->GetSelectedText;
if
(
$selection
and not
$d
->{selection_radio}->GetValue ) {
Kephra::Edit::Search::set_find_item(
$selection
);
$d
->{find_input}->SetValue(
$selection
);
}
else
{
$d
->{find_input}->SetValue( Kephra::Edit::Search::get_find_item())}
$d
->{replace_input}->SetValue( Kephra::Edit::Search::get_replace_item() );
Wx::Window::SetFocus(
$d
->{find_input} );
}
sub
replace {
my
$d
= ready();
my
$selection
= Kephra::App::EditPanel::_ref()->GetSelectedText;
if
(
length
$selection
> 0 and not
$d
->{selection_radio}->GetValue ) {
Kephra::Edit::Search::set_replace_item(
$selection
);
$d
->{replace_input}->SetValue(
$selection
);
}
else
{
$d
->{replace_input}->SetValue(Kephra::Edit::Search::get_replace_item());
}
$d
->{find_input}->SetValue(
$selection
);
Wx::Window::SetFocus(
$d
->{replace_input} );
}
sub
ready {
if
( not
$active
) {
my
$edit_panel
= Kephra::App::EditPanel::_ref();
my
$attr
= Kephra::Edit::Search::_attributes();
my
$dsettings
= Kephra::API::settings()->{dialog}{search};
my
$l18n
= Kephra::API::localisation();
my
$label
=
$l18n
->{dialog}{search}{label};
my
$hint
=
$l18n
->{dialog}{search}{hint};
my
@find_history
= ();
my
@replace_history
= ();
my
$d_style
=
&Wx::wxNO_FULL_REPAINT_ON_RESIZE
|
&Wx::wxSYSTEM_MENU
|
&Wx::wxCAPTION
|
&Wx::wxMINIMIZE_BOX
|
&Wx::wxCLOSE_BOX
;
$d_style
|=
&Wx::wxSTAY_ON_TOP
if
$Kephra::config
{app}{window}{stay_on_top};
$dsettings
->{position_x} = 10
if
$dsettings
->{position_x} < 0;
$dsettings
->{position_y} = 10
if
$dsettings
->{position_y} < 0;
$dsettings
->{width} = Wx::wxMSW() ? 436 : 496;
if
( Kephra::Edit::Search::_history()->{
use
} ) {
@find_history
= @{ Kephra::Edit::Search::get_find_history() };
@replace_history
= @{ Kephra::Edit::Search::get_replace_history() };
}
Kephra::Edit::Search::_refresh_search_flags();
$active
= 1;
$Kephra::temp
{dialog}{active}++;
$highlight_search
= 1;
my
$d
= Wx::Dialog->new(
Kephra::App::Window::_ref(), -1,
$l18n
->{dialog}{search}{title},
[
$dsettings
->{position_x},
$dsettings
->{position_y} ],
[ -1 , 268 ],
$d_style
);
my
$icon
= Wx::Icon->new;
my
$icon_bmp
= Kephra::CommandList::get_cmd_property
(
'view-dialog-find'
,
'icon'
);
$icon
->CopyFromBitmap(
$icon_bmp
)
if
ref
$icon_bmp
eq
'Wx::Bitmap'
;
$d
->SetIcon(
$icon
);
$d
->SetTransparent(1 -
int
(
$dsettings
->{transparency} * 255))
if
defined
$dsettings
->{transparency};
_ref(
$d
);
$d
->{find_label} = Wx::StaticText->new(
$d
, -1,
$label
->{search_for} );
$d
->{replace_label}= Wx::StaticText->new(
$d
, -1,
$label
->{replace_with} );
$d
->{find_input} = Wx::ComboBox->new
(
$d
, -1,
''
, [-1,-1], [324,22], [
@find_history
],
&Wx::wxTE_PROCESS_ENTER
);
$d
->{find_input}->SetDropTarget
( Kephra::Edit::Search::InputTarget->new(
$d
->{find_input},
'find'
));
$d
->{replace_input} = Wx::ComboBox->new
(
$d
, -1,
''
, [-1,-1], [324,22], [
@replace_history
],
&Wx::wxTE_PROCESS_ENTER
);
$d
->{replace_input}->SetDropTarget
( Kephra::Edit::Search::InputTarget->new(
$d
->{replace_input},
'replace'
));
$d
->{sep_line} = Wx::StaticLine->new(
$d
, -1, [0,0], [420,1],
&Wx::wxLI_HORIZONTAL
,);
$d
->{inc_box} = Wx::CheckBox->new(
$d
, -1,
$label
->{incremental});
$d
->{case_box} = Wx::CheckBox->new(
$d
, -1,
$label
->{case});
$d
->{begin_box}= Wx::CheckBox->new(
$d
, -1,
$label
->{word_begin});
$d
->{word_box} = Wx::CheckBox->new(
$d
, -1,
$label
->{whole_word});
$d
->{regex_box}= Wx::CheckBox->new(
$d
, -1,
$label
->{regex});
$d
->{wrap_box} = Wx::CheckBox->new(
$d
, -1,
$label
->{auto_wrap});
$d
->{inc_box} ->SetValue(
$attr
->{incremental} );
$d
->{case_box} ->SetValue(
$attr
->{match_case} );
$d
->{begin_box}->SetValue(
$attr
->{match_word_begin} );
$d
->{word_box} ->SetValue(
$attr
->{match_whole_word} );
$d
->{regex_box}->SetValue(
$attr
->{match_regex} );
$d
->{wrap_box} ->SetValue(
$attr
->{auto_wrap} );
my
$range_box
= Wx::StaticBox->new(
$d
, -1,
$label
->{search_in},
[-1,-1], [-1,-1],
&Wx::wxSIMPLE_BORDER
|
&Wx::wxRAISED_BORDER
,
);
$d
->{selection_radio}= Wx::RadioButton->new(
$d
, -1,
$label
->{selection});
$d
->{document_radio} = Wx::RadioButton->new(
$d
, -1,
$label
->{document} );
$d
->{all_open_radio} = Wx::RadioButton->new(
$d
, -1,
$label
->{open_documents} );
my
$bmp
= \
&Kephra::Config::icon_bitmap
;
$d
->{replace_back}=Wx::BitmapButton->new(
$d
,-1,
&$bmp
(
'replace-previous.xpm'
));
$d
->{replace_fore}=Wx::BitmapButton->new(
$d
,-1,
&$bmp
(
'replace-next.xpm'
));
$d
->{backward_button}=Wx::BitmapButton->new(
$d
,-1,
&$bmp
(
'go-previous.xpm'
));
$d
->{foreward_button}=Wx::BitmapButton->new(
$d
,-1,
&$bmp
(
'go-next.xpm'
));
$d
->{fast_back_button}=Wx::BitmapButton->new(
$d
,-1,
&$bmp
(
'go-fast-backward.xpm'
));
$d
->{fast_fore_button}=Wx::BitmapButton->new(
$d
,-1,
&$bmp
(
'go-fast-forward.xpm'
));
$d
->{first_button}=Wx::BitmapButton->new(
$d
,-1,
&$bmp
(
'go-first.xpm'
));
$d
->{last_button}=Wx::BitmapButton->new(
$d
,-1,
&$bmp
(
'go-last.xpm'
));
$d
->{search_button} = Wx::Button->new(
$d
, -1,
$label
->{search} );
$d
->{replace_button}= Wx::Button->new(
$d
, -1,
$label
->{replace_all} );
$d
->{confirm_button}= Wx::Button->new(
$d
, -1,
$label
->{with_confirmation} );
$d
->{close_button} = Wx::Button->new(
$d
, -1,
$l18n
->{dialog}{general}{
close
} );
if
(
$dsettings
->{tooltips} ) {
$d
->{foreward_button}->SetToolTip(
$hint
->{forward});
$d
->{backward_button}->SetToolTip(
$hint
->{backward});
$d
->{fast_fore_button}->SetToolTip(
$hint
->{fast_forward});
$d
->{fast_back_button}->SetToolTip(
$hint
->{fast_backward});
$d
->{first_button}->SetToolTip(
$hint
->{document_start});
$d
->{last_button}->SetToolTip(
$hint
->{document_end});
$d
->{replace_fore}->SetToolTip(
$hint
->{replace_forward});
$d
->{replace_back}->SetToolTip(
$hint
->{replace_backward});
$d
->{case_box}->SetToolTip(
$hint
->{match_case});
$d
->{begin_box}->SetToolTip(
$hint
->{match_word_begin});
$d
->{word_box}->SetToolTip(
$hint
->{match_whole_word});
$d
->{regex_box}->SetToolTip(
$hint
->{match_regex});
$d
->{wrap_box}->SetToolTip(
$hint
->{auto_wrap});
$d
->{inc_box}->SetToolTip(
$hint
->{incremental});
}
Wx::Event::EVT_KEY_DOWN(
$d
->{find_input}, \
&find_input_keyfilter
);
Wx::Event::EVT_KEY_DOWN(
$d
->{replace_input}, \
&replace_input_keyfilter
);
Wx::Event::EVT_TEXT(
$d
,
$d
->{find_input}, \
&incremental_search
);
Wx::Event::EVT_TEXT(
$d
,
$d
->{replace_input},
sub
{
my
$input
=
$d
->{replace_input};
my
$pos
=
$input
->GetInsertionPoint;
Kephra::Edit::Search::set_replace_item(
$input
->GetValue );
$input
->SetInsertionPoint(
$pos
);
});
Wx::Event::EVT_CHECKBOX(
$d
,
$d
->{case_box},
sub
{
$$attr
{match_case} =
$d
->{case_box}->GetValue;
Kephra::Edit::Search::_refresh_search_flags();
} );
Wx::Event::EVT_CHECKBOX(
$d
,
$d
->{begin_box},
sub
{
$$attr
{match_word_begin} =
$d
->{begin_box}->GetValue;
Kephra::Edit::Search::_refresh_search_flags();
} );
Wx::Event::EVT_CHECKBOX(
$d
,
$d
->{word_box},
sub
{
$$attr
{match_whole_word} =
$d
->{word_box}->GetValue;
Kephra::Edit::Search::_refresh_search_flags();
} );
Wx::Event::EVT_CHECKBOX(
$d
,
$d
->{regex_box},
sub
{
$$attr
{match_regex} =
$d
->{regex_box}->GetValue;
Kephra::Edit::Search::_refresh_search_flags();
} );
Wx::Event::EVT_CHECKBOX(
$d
,
$d
->{wrap_box},
sub
{
$$attr
{auto_wrap} =
$d
->{wrap_box}->GetValue;
} );
Wx::Event::EVT_CHECKBOX(
$d
,
$d
->{inc_box},
sub
{
$$attr
{incremental} =
$d
->{inc_box}->GetValue;
} );
Wx::Event::EVT_RADIOBUTTON(
$d
,
$d
->{selection_radio},
sub
{
$attr
->{in} =
'selection'
});
Wx::Event::EVT_RADIOBUTTON(
$d
,
$d
->{document_radio},
sub
{
$attr
->{in} =
'document'
});
Wx::Event::EVT_RADIOBUTTON(
$d
,
$d
->{all_open_radio},
sub
{
$attr
->{in} =
'open_docs'
});
Wx::Event::EVT_BUTTON(
$d
,
$d
->{foreward_button},
sub
{
&no_sel_range
; Kephra::Edit::Search::find_next();
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{backward_button},
sub
{
&no_sel_range
; Kephra::Edit::Search::find_prev();
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{fast_fore_button},
sub
{
&no_sel_range
; Kephra::Edit::Search::fast_fore();
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{fast_back_button},
sub
{
&no_sel_range
; Kephra::Edit::Search::fast_back();
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{first_button},
sub
{
&no_sel_range
; Kephra::Edit::Search::find_first();
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{last_button},
sub
{
&no_sel_range
; Kephra::Edit::Search::find_last();
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{replace_fore},
sub
{
&no_sel_range
; Kephra::Edit::Search::replace_fore();
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{replace_back},
sub
{
&no_sel_range
; Kephra::Edit::Search::replace_back();
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{search_button},
sub
{
&Kephra::Edit::Search::find_first
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{replace_button},
sub
{
&Kephra::Edit::Search::replace_all
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{confirm_button},
sub
{
&Kephra::Edit::Search::replace_confirm
} );
Wx::Event::EVT_BUTTON(
$d
,
$d
->{close_button},
sub
{
shift
->Close() } );
Wx::Event::EVT_CLOSE(
$d
, \
&quit_search_dialog
);
my
$ID
= _ID();
my
$add_call
= \
&Kephra::EventTable::add_call
;
&$add_call
(
'find'
,
$ID
.
'_color_refresh'
, \
&colour_find_input
,
$ID
);
&$add_call
(
'find.item.changed'
,
$ID
,
sub
{
$d
->{find_input}->SetValue(Kephra::Edit::Search::get_find_item());
$d
->{find_input}->SetInsertionPointEnd;
},
$ID
);
&$add_call
(
'replace.item.changed'
,
$ID
,
sub
{
$d
->{replace_input}->SetValue(Kephra::Edit::Search::get_replace_item());
$d
->{replace_input}->SetInsertionPointEnd;
},
$ID
);
Kephra::EventTable::add_call(
'find.item.history.changed'
,
$ID
,
sub
{
Kephra::App::_ref()->Yield();
my
$cb
=
$d
->{find_input};
$Kephra::temp
{dialog}{search}{control} = 1;
$cb
->Clear();
$cb
->Append(
$_
)
for
@{ Kephra::Edit::Search::get_find_history() };
$cb
->SetValue( Kephra::Edit::Search::get_find_item() );
$cb
->SetInsertionPointEnd;
$Kephra::temp
{dialog}{search}{control} = 0;
},
$ID
);
Kephra::EventTable::add_call(
'replace.item.history.changed'
,
$ID
,
sub
{
my
$cb
=
$d
->{replace_input};
$Kephra::temp
{dialog}{search}{control} = 1;
$cb
->Clear();
$cb
->Append(
$_
)
for
@{ Kephra::Edit::Search::get_replace_history() };
$cb
->SetValue( Kephra::Edit::Search::get_replace_item() );
$cb
->SetInsertionPointEnd;
$Kephra::temp
{dialog}{search}{control} = 0;
},
$ID
);
if
(
$edit_panel
->LineFromPosition(
$edit_panel
->GetSelectionStart )
!=
$edit_panel
->LineFromPosition(
$edit_panel
->GetSelectionEnd ) ) {
$attr
->{in} =
'selection'
;
$d
->{selection_radio}->SetValue(1);
}
elsif
(
$attr
->{in} eq
'open_docs'
) {
$d
->{all_open_radio}->SetValue(1);
}
else
{
$attr
->{in} =
'document'
;
$d
->{document_radio}->SetValue(1);
}
my
$option_sizer
= Wx::BoxSizer->new(
&Wx::wxVERTICAL
);
$option_sizer
->Add(
$d
->{inc_box}, 0,
&Wx::wxTOP
, 0 );
$option_sizer
->Add(
$d
->{case_box}, 0,
&Wx::wxTOP
, 15 );
$option_sizer
->Add(
$d
->{begin_box}, 0,
&Wx::wxTOP
, 5 );
$option_sizer
->Add(
$d
->{word_box}, 0,
&Wx::wxTOP
, 5 );
$option_sizer
->Add(
$d
->{regex_box}, 0,
&Wx::wxTOP
, 5 );
my
$rbz
= Wx::StaticBoxSizer->new(
$range_box
,
&Wx::wxVERTICAL
);
$rbz
->Add(
$d
->{selection_radio}, 1,
&Wx::wxTOP
, 5 );
$rbz
->Add(
$d
->{document_radio}, 1,
&Wx::wxTOP
, 5 );
$rbz
->Add(
$d
->{all_open_radio}, 1,
&Wx::wxTOP
, 5 );
my
$range_sizer
= Wx::BoxSizer->new(
&Wx::wxVERTICAL
);
$range_sizer
->Add(
$d
->{wrap_box}, 0,
&Wx::wxTOP
|
&Wx::wxALIGN_CENTER_HORIZONTAL
, 0 );
$range_sizer
->Add(
$rbz
, 0,
&Wx::wxGROW
|
&Wx::wxTOP
, 10 );
my
$pad_grid
= Wx::FlexGridSizer->new( 4, 2, 0 , 1 );
$pad_grid
->Add(
$d
->{replace_back}, 0,
&Wx::wxBOTTOM
, 5);
$pad_grid
->Add(
$d
->{replace_fore}, 0,
&Wx::wxBOTTOM
, 5);
$pad_grid
->Add(
$d
->{backward_button}, 0, ,0);
$pad_grid
->Add(
$d
->{foreward_button}, 0, ,0);
$pad_grid
->Add(
$d
->{fast_back_button},0, ,0);
$pad_grid
->Add(
$d
->{fast_fore_button},0, ,0);
$pad_grid
->Add(
$d
->{first_button}, 0, ,0);
$pad_grid
->Add(
$d
->{last_button}, 0, ,0);
my
$pads_sizer
= Wx::BoxSizer->new(
&Wx::wxHORIZONTAL
);
$pads_sizer
->Add(
$option_sizer
,0,
&Wx::wxALIGN_LEFT
,0);
$pads_sizer
->Add(
$range_sizer
,1,
&Wx::wxALIGN_CENTER
|
&Wx::wxLEFT
|
&Wx::wxRIGHT
|
&Wx::wxGROW
,20);
$pads_sizer
->Add(
$pad_grid
,0,
&Wx::wxALIGN_RIGHT
,0);
my
$button_sizer
= Wx::BoxSizer->new(
&Wx::wxHORIZONTAL
);
$button_sizer
->Add(
$d
->{search_button}, 0,
&Wx::wxLEFT
, 15 );
$button_sizer
->Add(
$d
->{replace_button}, 0,
&Wx::wxLEFT
, 10 );
$button_sizer
->Add(
$d
->{confirm_button}, 0,
&Wx::wxLEFT
, 10 );
$button_sizer
->AddStretchSpacer;
$button_sizer
->Add(
$d
->{close_button}, 0,
&Wx::wxALIGN_RIGHT
|
&Wx::wxRIGHT
, 15 );
my
$b_grid
= Wx::FlexGridSizer->new( 3, 2, 10, 0 );
$b_grid
->Add(
$d
->{find_label}, 0,
&Wx::wxLEFT
|
&Wx::wxRIGHT
|
&Wx::wxALIGN_CENTER_VERTICAL
|
&Wx::wxALIGN_RIGHT
, 10);
$b_grid
->Add(
$d
->{find_input}, 0,
&Wx::wxTOP
, 0);
$b_grid
->Add(
$d
->{replace_label}, 0,
&Wx::wxLEFT
|
&Wx::wxRIGHT
|
&Wx::wxALIGN_CENTER_VERTICAL
|
&Wx::wxALIGN_RIGHT
, 10);
$b_grid
->Add(
$d
->{replace_input}, 0,
&Wx::wxTOP
, 0);
$b_grid
->AddSpacer(5);
$b_grid
->Add(
$pads_sizer
, 1,
&Wx::wxTOP
|
&Wx::wxGROW
, 5);
my
$d_sizer
= Wx::BoxSizer->new(
&Wx::wxVERTICAL
);
$d_sizer
->Add(
$b_grid
, 1,
&Wx::wxTOP
, 15);
$d_sizer
->Add(
$d
->{sep_line}, 0,
&Wx::wxTOP
|
&Wx::wxALIGN_CENTER_HORIZONTAL
|
&Wx::wxGROW
, 8);
$d_sizer
->Add(
$button_sizer
, 0,
&Wx::wxTOP
|
&Wx::wxBOTTOM
|
&Wx::wxGROW
, 9);
$d
->SetSizer(
$d_sizer
);
$d
->Fit();
$d
->Show(1);
return
$d
;
}
else
{
my
$d
= _ref();
$d
->Iconize(0);
$d
->Raise;
return
$d
;
}
}
sub
no_sel_range {
my
$dialog
= _ref();
if
(
$dialog
->{selection_radio}->GetValue ) {
$dialog
->{document_radio}->SetValue(1);
Kephra::Edit::Search::_attributes()->{in} =
'document'
;
}
}
sub
find_input_keyfilter {
my
(
$input
,
$event
) =
@_
;
my
$dialog
= _ref();
my
$wx_frame
=
$dialog
->GetParent;
my
$key_code
=
$event
->GetKeyCode;
if
(
$key_code
==
&Wx::WXK_RETURN
) {
no_sel_range();
if
(
$event
->ControlDown){Kephra::Edit::Search::find_first();
$dialog
->Close; }
elsif
(
$event
->ShiftDown ){Kephra::Edit::Search::find_prev() }
else
{Kephra::Edit::Search::find_next() }
return
;
}
elsif
(
$key_code
==
&Wx::WXK_ESCAPE
) {
$dialog
->Close }
elsif
(
$key_code
==
&Wx::WXK_TAB
){
if
(
$event
->ShiftDown ) {
$dialog
->{close_button}->SetFocus }
else
{
$dialog
->{replace_input}->SetFocus}
}
$event
->Skip;
}
sub
colour_find_input {
my
$input
= _ref()->{find_input};
my
$pos
=
$input
->GetInsertionPoint;
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
){
$input
->SetForegroundColour(
$color
{norm_fore} );
$input
->SetBackgroundColour(
$color
{norm_back} );
}
else
{
$input
->SetForegroundColour(
$color
{alert_fore} );
$input
->SetBackgroundColour(
$color
{alert_back} );
}
$input
->SetInsertionPoint(
$pos
);
$input
->Refresh;
}
sub
incremental_search {
if
( Kephra::Edit::Search::_attributes()->{incremental}
and not
$Kephra::temp
{dialog}{search}{control} ) {
my
$input
= _ref()->{find_input};
Kephra::Edit::Search::set_find_item(
$input
->GetValue);
Kephra::Edit::Search::first_increment();
}
}
sub
replace_input_keyfilter {
my
(
$input
,
$event
) =
@_
;
my
$dialog
= _ref();
my
$key_code
=
$event
->GetKeyCode;
if
(
$key_code
==
&Wx::WXK_RETURN
) {
if
(
$event
->ControlDown ) {
Kephra::Edit::Search::replace_all();
$dialog
->Close;
}
elsif
(
$event
->AltDown ) { replace_confirm(
$dialog
) }
else
{ Kephra::Edit::Search::replace_all() }
}
if
(
$key_code
==
&Wx::WXK_ESCAPE
) {
$dialog
->Close }
elsif
(
$key_code
==
&Wx::WXK_TAB
){
if
(
$event
->ShiftDown ) {
$dialog
->{find_input}->SetFocus }
else
{
$dialog
->{inc_box}->SetFocus }
}
$event
->Skip;
}
sub
replace_all { Kephra::Edit::Search::replace_all() }
sub
replace_confirm { Kephra::Edit::Search::replace_confirm() }
sub
raise_if_active { _ref()->Raise
if
$active
}
sub
quit_search_dialog {
my
(
$win
,
$event
) =
@_
;
my
$config
= Kephra::API::settings()->{dialog}{search};
(
$config
->{position_x},
$config
->{position_y} ) =
$win
->GetPositionXY
if
$config
->{save_position} == 1;
$active
= 0;
$Kephra::temp
{dialog}{active}--;
Kephra::EventTable::del_own_subscriptions( _ID() );
$win
->Destroy();
}
1;