lazarus-ccr/components/fpspreadsheet/examples/visual/shared/ssearchform.pas
2015-09-08 21:43:02 +00:00

333 lines
9.5 KiB
ObjectPascal

unit sSearchForm;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
StdCtrls, ExtCtrls, Buttons, ComCtrls, fpsTypes, fpspreadsheet, fpsSearch;
type
TsSearchEvent = procedure (Sender: TObject; AFound: Boolean;
AWorksheet: TsWorksheet; ARow, ACol: Cardinal) of object;
{ TSearchForm }
TSearchForm = class(TForm)
Bevel1: TBevel;
BtnSearchBack: TBitBtn;
BtnClose: TBitBtn;
BtnSearch: TBitBtn;
CbSearchText: TComboBox;
CbReplaceText: TComboBox;
CgOptions: TCheckGroup;
LblSearchText: TLabel;
ButtonPanel: TPanel;
LblSearchText1: TLabel;
SearchParamsPanel: TPanel;
SearchTextPanel: TPanel;
RgSearchStart: TRadioGroup;
RgSearchWithin: TRadioGroup;
ReplaceTextPanel: TPanel;
TabControl: TTabControl;
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure ExecuteClick(Sender: TObject);
procedure TabControlChange(Sender: TObject);
procedure TabControlChanging(Sender: TObject; var AllowChange: Boolean);
private
{ private declarations }
FSearchEngine: TsSearchEngine;
FWorkbook: TsWorkbook;
FFoundWorksheet: TsWorksheet;
FFoundRow, FFoundCol: Cardinal;
FSearchParams: TsSearchParams;
FReplaceParams: TsReplaceParams;
FOnFound: TsSearchEvent;
function GetReplaceParams: TsReplaceParams;
function GetSearchParams: TsSearchParams;
procedure SetReplaceParams(const AValue: TsReplaceParams);
procedure SetSearchParams(const AValue: TsSearchParams);
protected
procedure ConfirmReplacementHandler(Sender: TObject; AWorksheet: TsWorksheet;
ARow, ACol: Cardinal; const ASearchText, AReplaceText: String; var Allow: Boolean);
procedure PopulateOptions;
public
{ public declarations }
procedure Execute(AWorkbook: TsWorkbook);
property Workbook: TsWorkbook read FWorkbook;
property SearchParams: TsSearchParams read GetSearchParams write SetSearchParams;
property ReplaceParams: TsReplaceParams read GetReplaceParams write SetReplaceParams;
property OnFound: TsSearchEvent read FOnFound write FOnFound;
end;
var
SearchForm: TSearchForm;
DefaultSearchParams: TsSearchParams = (
SearchText: '';
Options: [];
Within: swWorksheet
);
DefaultReplaceParams: TsReplaceParams = (
ReplaceText: '';
Options: [roConfirm]
);
implementation
{$R *.lfm}
uses
fpsUtils;
const
MAX_SEARCH_ITEMS = 10;
// Search & replace
COMPARE_ENTIRE_CELL = 0;
MATCH_CASE = 1;
REGULAR_EXPRESSION = 2;
SEARCH_ALONG_ROWS = 3;
CONTINUE_AT_START_END = 4;
// Replace only
REPLACE_ENTIRE_CELL = 5;
REPLACE_ALL = 6;
CONFIRM_REPLACEMENT = 7;
BASE_HEIGHT = 340; // Design height of SearchForm
SEARCH_TAB = 0;
REPLACE_TAB = 1;
{ TSearchForms }
procedure TSearchForm.ConfirmReplacementHandler(Sender: TObject;
AWorksheet: TsWorksheet; ARow, ACol: Cardinal;
const ASearchText, AReplaceText: String; var Allow: Boolean);
begin
Unused(AWorksheet, ARow, ACol);
Unused(ASearchText, AReplaceText);
Allow := MessageDlg('Replace?', mtConfirmation, [mbYes, mbNo], 0) = mrYes;
end;
procedure TSearchForm.Execute(AWorkbook: TsWorkbook);
begin
FWorkbook := AWorkbook;
Show;
end;
procedure TSearchForm.ExecuteClick(Sender: TObject);
var
sp: TsSearchParams;
rp: TsReplaceParams;
found: Boolean;
crs: TCursor;
begin
sp := GetSearchParams;
if sp.SearchText = '' then
exit;
if TabControl.TabIndex = REPLACE_TAB then
rp := GetReplaceParams;
if CbSearchText.Items.IndexOf(sp.SearchText) = -1 then
begin
CbSearchText.Items.Insert(0, sp.SearchText);
while CbSearchText.Items.Count > MAX_SEARCH_ITEMS do
CbSearchText.Items.Delete(CbSearchText.Items.Count-1);
end;
if (TabControl.TabIndex = REPLACE_TAB) and
(CbReplaceText.Items.IndexOf(rp.ReplaceText) = -1) then
begin
CbReplaceText.items.Insert(0, rp.ReplaceText);
while CbReplaceText.Items.Count > MAX_SEARCH_ITEMS do
CbReplaceText.Items.Delete(CbReplaceText.Items.Count-1);
end;
crs := Screen.Cursor;
try
Screen.Cursor := crHourglass;
if FSearchEngine = nil then
begin
FSearchEngine := TsSearchEngine.Create(FWorkbook);
FSearchEngine.OnConfirmReplacement := @ConfirmReplacementHandler;
if (soBackward in sp.Options) then
Include(sp.Options, soBackward) else
Exclude(sp.Options, soBackward);
case Tabcontrol.TabIndex of
0: found := FSearchEngine.FindFirst(sp, FFoundWorksheet, FFoundRow, FFoundCol);
1: found := FSearchEngine.ReplaceFirst(sp, rp, FFoundWorksheet, FFoundRow, FFoundCol);
end;
end else
begin
if (Sender = BtnSearchBack) then
Include(sp.Options, soBackward) else
Exclude(sp.Options, soBackward);
// User may select a different worksheet/different cell to continue search!
FFoundWorksheet := FWorkbook.ActiveWorksheet;
FFoundRow := FFoundWorksheet.ActiveCellRow;
FFoundCol := FFoundWorksheet.ActiveCellCol;
case TabControl.TabIndex of
0: found := FSearchEngine.FindNext(sp, FFoundWorksheet, FFoundRow, FFoundCol);
1: found := FSearchEngine.ReplaceNext(sp, rp, FFoundWorksheet, FFoundRow, FFoundCol);
end;
end;
finally
Screen.Cursor := crs;
end;
if Assigned(FOnFound) then
FOnFound(self, found, FFoundWorksheet, FFoundRow, FFoundCol);
BtnSearchBack.Visible := true;
BtnSearch.Caption := 'Next';
end;
procedure TSearchForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var
P: TPoint;
begin
Unused(CloseAction);
FreeAndNil(FSearchEngine);
P.X := Left;
P.Y := Top;
Position := poDesigned;
Left := P.X;
Top := P.Y;
end;
procedure TSearchForm.FormCreate(Sender: TObject);
begin
Position := poMainFormCenter;
PopulateOptions;
end;
procedure TSearchForm.FormShow(Sender: TObject);
begin
BtnSearch.Caption := 'Search';
BtnSearchBack.Visible := false;
FFoundCol := UNASSIGNED_ROW_COL_INDEX;
FFoundRow := UNASSIGNED_ROW_COL_INDEX;
FFoundWorksheet := nil;
end;
function TSearchForm.GetReplaceParams: TsReplaceParams;
begin
if TabControl.TabIndex = 0 then
Result := FReplaceParams
else
begin
Result.ReplaceText := CbReplaceText.Text;
Result.Options := [];
if CgOptions.Checked[REPLACE_ENTIRE_CELL] then
Include(Result.Options, roReplaceEntireCell);
if CgOptions.Checked[REPLACE_ALL] then
Include(Result.Options, roReplaceAll);
if CgOptions.Checked[CONFIRM_REPLACEMENT] then
Include(Result.Options, roConfirm);
FReplaceParams := Result;
end;
end;
function TSearchForm.GetSearchParams: TsSearchParams;
begin
Result.SearchText := CbSearchText.Text;
Result.Options := [];
if CgOptions.Checked[COMPARE_ENTIRE_CELL] then
Include(Result.Options, soCompareEntireCell);
if CgOptions.Checked[MATCH_CASE] then
Include(Result.Options, soMatchCase);
if CgOptions.Checked[REGULAR_EXPRESSION] then
Include(Result.Options, soRegularExpr);
if CgOptions.Checked[SEARCH_ALONG_ROWS] then
Include(Result.Options, soAlongRows);
if CgOptions.Checked[CONTINUE_AT_START_END] then
Include(Result.Options, soWrapDocument);
if RgSearchStart.ItemIndex = 1 then
Include(Result.Options, soEntireDocument);
Result.Within := TsSearchWithin(RgSearchWithin.ItemIndex);
end;
procedure TSearchForm.PopulateOptions;
begin
with CgOptions.Items do
begin
Clear;
Add('Compare entire cell');
Add('Match case');
Add('Regular expression');
Add('Search along rows');
Add('Continue at start/end');
if TabControl.TabIndex = REPLACE_TAB then
begin
Add('Replace entire cell');
Add('Replace all');
Add('Confirm replacement');
end;
end;
end;
procedure TSearchForm.SetSearchParams(const AValue: TsSearchParams);
begin
CbSearchText.Text := Avalue.SearchText;
CgOptions.Checked[COMPARE_ENTIRE_CELL] := (soCompareEntireCell in AValue.Options);
CgOptions.Checked[MATCH_CASE] := (soMatchCase in AValue.Options);
CgOptions.Checked[REGULAR_EXPRESSION] := (soRegularExpr in Avalue.Options);
CgOptions.Checked[SEARCH_ALONG_ROWS] := (soAlongRows in AValue.Options);
CgOptions.Checked[CONTINUE_AT_START_END] := (soWrapDocument in Avalue.Options);
RgSearchWithin.ItemIndex := ord(AValue.Within);
RgSearchStart.ItemIndex := ord(soEntireDocument in AValue.Options);
end;
procedure TSearchForm.SetReplaceParams(const AValue: TsReplaceParams);
begin
FReplaceParams := AValue;
if TabControl.TabIndex = REPLACE_TAB then
begin
CbReplaceText.Text := AValue.ReplaceText;
CgOptions.Checked[REPLACE_ENTIRE_CELL] := (roReplaceEntireCell in AValue.Options);
CgOptions.Checked[REPLACE_ALL] := (roReplaceAll in AValue.Options);
CgOptions.Checked[CONFIRM_REPLACEMENT] := (roConfirm in AValue.Options);
end;
end;
procedure TSearchForm.TabControlChange(Sender: TObject);
var
h, d: Integer;
begin
ReplaceTextPanel.Visible := (TabControl.TabIndex = REPLACE_TAB);
PopulateOptions;
SetSearchParams(FSearchParams);
SetReplaceParams(FReplaceParams);
h := RgSearchStart.Top + RgSearchStart.Height - CgOptions.Top;
if TabControl.TabIndex = 0 then
begin
CgOptions.Height := h;
Height := BASE_HEIGHT - ReplaceTextPanel.Height;
end else
begin
d := 3 * 16;
CgOptions.Height := h + d;
Height := BASE_HEIGHT + d;
end;
end;
procedure TSearchForm.TabControlChanging(Sender: TObject;
var AllowChange: Boolean);
begin
AllowChange := true;
FSearchParams := GetSearchParams;
FReplaceParams := GetReplaceParams;
end;
end.