mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
Refactor code in SQL help dialog, replace the TTreeView with a VirtualTree.
This commit is contained in:
@ -5,7 +5,7 @@ interface
|
||||
uses
|
||||
Windows, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls,
|
||||
Buttons, SynMemo, SynEditHighlighter, SynHighlighterURI,
|
||||
SynURIOpener, SynEdit,
|
||||
SynURIOpener, SynEdit, VirtualTrees, Graphics,
|
||||
mysql_connection;
|
||||
|
||||
type
|
||||
@ -17,7 +17,7 @@ type
|
||||
ButtonClose: TButton;
|
||||
pnlMain: TPanel;
|
||||
pnlLeft: TPanel;
|
||||
treeTopics: TTreeView;
|
||||
treeTopics: TVirtualStringTree;
|
||||
editFilter: TButtonedEdit;
|
||||
pnlRight: TPanel;
|
||||
Splitter2: TSplitter;
|
||||
@ -27,23 +27,34 @@ type
|
||||
memoDescription: TSynMemo;
|
||||
lblExample: TLabel;
|
||||
MemoExample: TSynMemo;
|
||||
timerSearch: TTimer;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure treeTopicsExpanding(Sender: TObject; Node: TTreeNode;
|
||||
var AllowExpansion: Boolean);
|
||||
procedure treeTopicsChange(Sender: TObject; Node: TTreeNode);
|
||||
procedure FormShow(Sender: TObject);
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure memosKeyDown(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
procedure ButtonOnlinehelpClick(Sender: TObject);
|
||||
procedure ButtonCloseClick(Sender: TObject);
|
||||
function ShowHelpItem: Boolean;
|
||||
procedure fillTreeLevel( ParentNode: TTreeNode );
|
||||
procedure findKeywordInTree;
|
||||
procedure DoSearch(Sender: TObject);
|
||||
procedure treeTopicsGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
|
||||
procedure treeTopicsInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
|
||||
var InitialStates: TVirtualNodeInitStates);
|
||||
procedure treeTopicsInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
var ChildCount: Cardinal);
|
||||
procedure treeTopicsGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
|
||||
procedure treeTopicsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
|
||||
procedure treeTopicsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
procedure treeTopicsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Column: TColumnIndex);
|
||||
procedure editFilterChange(Sender: TObject);
|
||||
procedure editFilterRightButtonClick(Sender: TObject);
|
||||
|
||||
private
|
||||
{ Private declarations }
|
||||
FKeyword: String;
|
||||
FRootTopics: TMySQLQuery;
|
||||
function GetHelpResult(Node: PVirtualNode): TMySQLQuery;
|
||||
procedure SetKeyword(Value: String);
|
||||
public
|
||||
{ Public declarations }
|
||||
@ -65,22 +76,11 @@ uses helpers, main;
|
||||
{$R *.dfm}
|
||||
|
||||
|
||||
{**
|
||||
FormCreate
|
||||
}
|
||||
procedure TfrmSQLhelp.FormCreate(Sender: TObject);
|
||||
begin
|
||||
// Set window-layout
|
||||
InheritFont(Font);
|
||||
SetWindowSizeGrip(Handle, True);
|
||||
end;
|
||||
|
||||
|
||||
{***
|
||||
Startup
|
||||
}
|
||||
procedure TfrmSQLhelp.FormShow(Sender: TObject);
|
||||
begin
|
||||
// Set window-layout
|
||||
Top := GetRegValue( REGNAME_SQLHELPWINTOP, Top );
|
||||
Left := GetRegValue( REGNAME_SQLHELPWINLEFT, Left );
|
||||
Width := GetRegValue( REGNAME_SQLHELPWINWIDTH, Width );
|
||||
@ -89,191 +89,154 @@ begin
|
||||
memoDescription.Height := GetRegValue( REGNAME_SQLHELPPRHEIGHT, memoDescription.Height );
|
||||
Caption := DEFAULT_WINDOW_CAPTION;
|
||||
MainForm.SetupSynEditors;
|
||||
FixVT(treeTopics);
|
||||
|
||||
// Gather help contents for treeview with SQL: HELP "CONTENTS"
|
||||
fillTreeLevel( nil );
|
||||
treeTopics.Clear;
|
||||
FreeAndNil(FRootTopics);
|
||||
FRootTopics := Mainform.Connection.GetResults('HELP '+esc('CONTENTS'));
|
||||
treeTopics.RootNodeCount := FRootTopics.RecordCount;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{***
|
||||
Fills exactly one level of the folder-tree
|
||||
Call with NIL to generate the root folders,
|
||||
then call recursively to iterate through all folders and fill them
|
||||
@param TTreeNode Parent node to fill (or NIL)
|
||||
}
|
||||
procedure TfrmSQLhelp.fillTreeLevel( ParentNode: TTreeNode );
|
||||
procedure TfrmSQLhelp.treeTopicsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Column: TColumnIndex);
|
||||
var
|
||||
tnode: TTreeNode;
|
||||
Results: TMySQLQuery;
|
||||
topic: String;
|
||||
VT: TVirtualStringTree;
|
||||
begin
|
||||
if ParentNode = nil then begin
|
||||
treeTopics.Items.Clear;
|
||||
topic := 'CONTENTS';
|
||||
end else begin
|
||||
ParentNode.DeleteChildren;
|
||||
topic := ParentNode.Text;
|
||||
end;
|
||||
try
|
||||
Screen.Cursor := crHourglass;
|
||||
Results := Mainform.Connection.GetResults( 'HELP "'+topic+'"' );
|
||||
while not Results.Eof do begin
|
||||
tnode := treeTopics.Items.AddChild( ParentNode, Results.Col('name'));
|
||||
if (Results.Col('is_it_category', True) = 'Y') and ((ParentNode = nil) or (ParentNode.Text <> tnode.Text)) then begin
|
||||
tnode.ImageIndex := ICONINDEX_CATEGORY_CLOSED;
|
||||
tnode.SelectedIndex := ICONINDEX_CATEGORY_OPENED;
|
||||
// Add a dummy item to show the plus-button so the user sees that there this
|
||||
// is a category. When the plus-button is clicked, fetch the content of the category
|
||||
treeTopics.Items.AddChild( tnode, DUMMY_NODE_TEXT );
|
||||
end else begin
|
||||
tnode.ImageIndex := ICONINDEX_HELPITEM;
|
||||
tnode.SelectedIndex := tnode.ImageIndex;
|
||||
end;
|
||||
Results.Next;
|
||||
end;
|
||||
finally
|
||||
FreeAndNil(Results);
|
||||
Screen.Cursor := crDefault;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{***
|
||||
Show selected keyword in Tree
|
||||
}
|
||||
procedure TfrmSQLhelp.findKeywordInTree;
|
||||
var
|
||||
tnode : TTreeNode;
|
||||
i : Integer;
|
||||
tmp : Boolean;
|
||||
begin
|
||||
if Assigned(treeTopics.Selected) and (treeTopics.Selected.Text = FKeyword) then begin
|
||||
// We've come here after user selected a tree node via mouse. No need to search for it.
|
||||
// Topic selected
|
||||
VT := Sender as TVirtualStringTree;
|
||||
if not Assigned(VT.FocusedNode) then
|
||||
Exit;
|
||||
end;
|
||||
i := 0;
|
||||
while i < treeTopics.Items.Count do
|
||||
begin
|
||||
tnode := treeTopics.Items[i];
|
||||
inc(i);
|
||||
if tnode.Text = FKeyword then
|
||||
begin
|
||||
tnode.MakeVisible;
|
||||
treeTopics.Selected := tnode;
|
||||
break;
|
||||
end;
|
||||
treeTopicsExpanding( self, tnode, tmp );
|
||||
end;
|
||||
treeTopics.SetFocus;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{***
|
||||
Selected item in treeTopics has changed
|
||||
}
|
||||
procedure TfrmSQLhelp.treeTopicsChange(Sender: TObject; Node: TTreeNode);
|
||||
procedure OpenFolderIcons( ANode: TTreeNode );
|
||||
begin
|
||||
if ANode = nil then
|
||||
exit;
|
||||
if ANode.ImageIndex = ICONINDEX_CATEGORY_CLOSED then
|
||||
begin
|
||||
ANode.ImageIndex := ICONINDEX_CATEGORY_OPENED;
|
||||
end;
|
||||
// Recursively update ANode's parent node
|
||||
OpenFolderIcons( ANode.Parent );
|
||||
end;
|
||||
|
||||
var
|
||||
i : Integer;
|
||||
tNode : TTreeNode;
|
||||
begin
|
||||
// 1. Show corresponding help-text
|
||||
if Node.ImageIndex = ICONINDEX_HELPITEM then
|
||||
Keyword := Node.Text;
|
||||
|
||||
// 2. Ensure the icons in the preceding tree-path of the selected item
|
||||
// show opened folders on each level
|
||||
i := 0;
|
||||
while i < treeTopics.Items.Count do
|
||||
begin
|
||||
tNode := treeTopics.Items[i];
|
||||
if tNode.ImageIndex = ICONINDEX_CATEGORY_OPENED then
|
||||
begin
|
||||
tNode.ImageIndex := ICONINDEX_CATEGORY_CLOSED;
|
||||
end;
|
||||
inc(i);
|
||||
end;
|
||||
OpenFolderIcons( Node );
|
||||
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{***
|
||||
Get topics from category
|
||||
}
|
||||
procedure TfrmSQLhelp.treeTopicsExpanding(Sender: TObject; Node: TTreeNode;
|
||||
var AllowExpansion: Boolean);
|
||||
begin
|
||||
if (Node.getFirstChild <> nil) and (Node.getFirstChild.Text = DUMMY_NODE_TEXT) then
|
||||
begin
|
||||
fillTreeLevel( Node );
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{***
|
||||
Fetch and show text of help-item in synmemo's
|
||||
@return boolean Was the keyword found?
|
||||
}
|
||||
function TfrmSQLhelp.ShowHelpItem: Boolean;
|
||||
var
|
||||
Results: TMySQLQuery;
|
||||
begin
|
||||
lblKeyword.Caption := Copy(Keyword, 0, 100);
|
||||
if VT.HasChildren[VT.FocusedNode] then
|
||||
Exit;
|
||||
FKeyword := VT.Text[VT.FocusedNode, VT.FocusedColumn];
|
||||
lblKeyword.Caption := Copy(FKeyword, 0, 100);
|
||||
MemoDescription.Lines.Clear;
|
||||
MemoExample.Lines.Clear;
|
||||
Caption := DEFAULT_WINDOW_CAPTION;
|
||||
result := false; // Keyword not found yet
|
||||
|
||||
if Keyword <> '' then
|
||||
try
|
||||
if FKeyword <> '' then try
|
||||
Screen.Cursor := crHourglass;
|
||||
Results := Mainform.Connection.GetResults('HELP "'+lblKeyword.Caption+'"');
|
||||
if Results.RecordCount = 1 then begin
|
||||
// We found exactly one matching help item
|
||||
lblKeyword.Caption := Results.Col('name');
|
||||
FKeyword := lblKeyword.Caption;
|
||||
if lblKeyword.Caption = '&' then
|
||||
lblKeyword.Caption := '&&'; // Avoid displaying "_" as alt-hotkey
|
||||
Caption := Caption + ' - ' + Keyword;
|
||||
MemoDescription.Text := fixNewlines(Results.Col('description'));
|
||||
MemoExample.Text := fixNewlines(Results.Col('example'));
|
||||
result := true;
|
||||
end;
|
||||
Results := Mainform.Connection.GetResults('HELP '+esc(FKeyword));
|
||||
Caption := Caption + ' - ' + FKeyword;
|
||||
MemoDescription.Text := fixNewlines(Results.Col('description', True));
|
||||
MemoExample.Text := fixNewlines(Results.Col('example', True));
|
||||
finally
|
||||
FreeAndNil(Results);
|
||||
Screen.Cursor := crDefault;
|
||||
end;
|
||||
|
||||
// Show the user if topic is (not) available
|
||||
if memoDescription.Text = '' then
|
||||
if memoDescription.GetTextLen = 0 then
|
||||
memoDescription.Text := 'No help available for this keyword or no keyword was selected.';
|
||||
if memoExample.Text = '' then
|
||||
if memoExample.GetTextLen = 0 then
|
||||
memoExample.Text := 'No example available or no keyword was selected.';
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
var
|
||||
Results: PMySQLQuery;
|
||||
begin
|
||||
// Node gets destroyed - free memory used for bound SQL result
|
||||
Results := Sender.GetNodeData(Node);
|
||||
if Assigned(Results^) then
|
||||
Results^.Free;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
|
||||
begin
|
||||
// Return open or closed book icon for folders, or document icon for topics
|
||||
if not (Kind in [ikNormal, ikSelected]) then
|
||||
Exit;
|
||||
if Sender.HasChildren[Node] then begin
|
||||
if Sender.Expanded[Node] then
|
||||
ImageIndex := ICONINDEX_CATEGORY_OPENED
|
||||
else
|
||||
ImageIndex := ICONINDEX_CATEGORY_CLOSED;
|
||||
end else
|
||||
ImageIndex := ICONINDEX_HELPITEM;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsGetNodeDataSize(Sender: TBaseVirtualTree;
|
||||
var NodeDataSize: Integer);
|
||||
begin
|
||||
// We bind one TMySQLQuery to a node
|
||||
NodeDataSize := SizeOf(TMySQLQuery);
|
||||
end;
|
||||
|
||||
|
||||
function TfrmSQLhelp.GetHelpResult(Node: PVirtualNode): TMySQLQuery;
|
||||
var
|
||||
P: PMySQLQuery;
|
||||
begin
|
||||
// Find right result set for given node
|
||||
if treeTopics.GetNodeLevel(Node) = 0 then
|
||||
Result := FRootTopics
|
||||
else begin
|
||||
P := treeTopics.GetNodeData(Node.Parent);
|
||||
Result := P^;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
|
||||
var
|
||||
Results: TMySQLQuery;
|
||||
begin
|
||||
// Ask result set for node text
|
||||
Results := GetHelpResult(Node);
|
||||
Results.RecNo := Node.Index;
|
||||
CellText := Results.Col('name');
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;
|
||||
var ChildCount: Cardinal);
|
||||
var
|
||||
Results: PMySQLQuery;
|
||||
VT: TVirtualStringTree;
|
||||
begin
|
||||
// Return number of children for folder
|
||||
VT := Sender as TVirtualStringTree;
|
||||
Results := VT.GetNodeData(Node);
|
||||
Results^ := MainForm.Connection.GetResults('HELP '+esc(VT.Text[Node, VT.Header.MainColumn]));
|
||||
ChildCount := Results.RecordCount;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.treeTopicsInitNode(Sender: TBaseVirtualTree; ParentNode,
|
||||
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
|
||||
var
|
||||
Results: TMySQLQuery;
|
||||
Folder: String;
|
||||
begin
|
||||
// Display plus button for nodes which are folders
|
||||
Results := GetHelpResult(Node);
|
||||
Results.RecNo := Node.Index;
|
||||
Folder := '';
|
||||
if Assigned(ParentNode) then
|
||||
Folder := treeTopics.Text[ParentNode, treeTopics.Header.MainColumn];
|
||||
if Results.ColExists('is_it_category')
|
||||
and (Results.Col('is_it_category') = 'Y')
|
||||
and (Results.Col('name') <> Folder)
|
||||
then
|
||||
Include(InitialStates, ivsHasChildren);
|
||||
end;
|
||||
|
||||
|
||||
{***
|
||||
Save layout and close window
|
||||
}
|
||||
procedure TfrmSQLhelp.ButtonCloseClick(Sender: TObject);
|
||||
begin
|
||||
Close;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
OpenRegistry;
|
||||
MainReg.WriteInteger( REGNAME_SQLHELPWINLEFT, Left );
|
||||
@ -282,81 +245,144 @@ begin
|
||||
MainReg.WriteInteger( REGNAME_SQLHELPWINHEIGHT, Height );
|
||||
MainReg.WriteInteger( REGNAME_SQLHELPPLWIDTH, pnlLeft.Width );
|
||||
MainReg.WriteInteger( REGNAME_SQLHELPPRHEIGHT, memoDescription.Height );
|
||||
Close;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{***
|
||||
Link/redirect to mysql.com for further help
|
||||
@see http://www.heidisql.com/sqlhelp.php
|
||||
}
|
||||
procedure TfrmSQLhelp.ButtonOnlinehelpClick(Sender: TObject);
|
||||
begin
|
||||
// Link/redirect to mysql.com for further help
|
||||
ShellExec( APPDOMAIN + 'sqlhelp.php?mysqlversion='+inttostr(Mainform.Connection.ServerVersionInt)+
|
||||
'&keyword='+urlencode(keyword) );
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{***
|
||||
Esc pressed - close form.
|
||||
Seems that if we're in a memo, the ButtonClose.Cancel=True doesn't have an effect
|
||||
}
|
||||
procedure TfrmSQLhelp.memosKeyDown(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
procedure TfrmSQLhelp.memosKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
||||
begin
|
||||
// Esc pressed - close form.
|
||||
// Seems that if we're in a memo, the ButtonClose.Cancel=True doesn't have an effect
|
||||
if Key = VK_ESCAPE then
|
||||
ButtonCloseClick(self);
|
||||
Close;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.SetKeyword(Value: string);
|
||||
var
|
||||
VT: TVirtualStringTree;
|
||||
Node: PVirtualNode;
|
||||
Results: TMySQLQuery;
|
||||
SearchNoInit: Boolean;
|
||||
begin
|
||||
// Find keyword in tree
|
||||
FKeyword := Value;
|
||||
if ShowHelpItem then
|
||||
findKeywordInTree;
|
||||
if FKeyword = '' then
|
||||
Exit;
|
||||
Results := Mainform.Connection.GetResults('HELP '+esc(FKeyword));
|
||||
while not Results.Eof do begin
|
||||
if Results.Col('is_it_category', true) = 'N' then begin
|
||||
FKeyword := Results.Col('name');
|
||||
break;
|
||||
end;
|
||||
Results.Next;
|
||||
end;
|
||||
FreeAndNil(Results);
|
||||
|
||||
VT := treeTopics;
|
||||
if (not Assigned(VT.FocusedNode)) // No node selected
|
||||
or VT.HasChildren[VT.FocusedNode] // Selected node is a folder, not a document
|
||||
or (VT.Text[VT.FocusedNode, VT.Header.MainColumn] <> FKeyword) // Node is not the right one
|
||||
then begin
|
||||
// Start searching in initialized nodes, to minimize number of "HELP xyz" queries in certain cases
|
||||
Node := VT.GetFirst;
|
||||
SearchNoInit := False;
|
||||
while Assigned(Node) do begin
|
||||
if (not VT.HasChildren[Node]) and (UpperCase(VT.Text[Node, VT.Header.MainColumn]) = UpperCase(FKeyword)) then begin
|
||||
SelectNode(VT, Node);
|
||||
break;
|
||||
end;
|
||||
if not SearchNoInit then begin
|
||||
Node := VT.GetNextInitialized(Node);
|
||||
if not Assigned(Node) then begin
|
||||
SearchNoInit := True;
|
||||
Node := VT.GetFirst;
|
||||
end;
|
||||
end;
|
||||
if SearchNoInit then
|
||||
Node := VT.GetNext(Node);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.editFilterChange(Sender: TObject);
|
||||
var
|
||||
tnode: TTreeNode;
|
||||
Results: TMySQLQuery;
|
||||
topic: String;
|
||||
begin
|
||||
// Apply filter text
|
||||
if Trim(editFilter.Text) = '' then begin
|
||||
fillTreeLevel(nil);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Keyword := editFilter.Text;
|
||||
treeTopics.Items.Clear;
|
||||
topic := Keyword;
|
||||
try
|
||||
Screen.Cursor := crHourglass;
|
||||
Results := Mainform.Connection.GetResults('HELP "%'+topic+'%"');
|
||||
while not Results.Eof do begin
|
||||
tnode := treeTopics.Items.AddChild(nil, Results.Col('name'));
|
||||
if Results.ColExists('is_it_category') and (Results.Col('is_it_category') = 'Y') then begin
|
||||
tnode.ImageIndex := ICONINDEX_CATEGORY_CLOSED;
|
||||
tnode.SelectedIndex := ICONINDEX_CATEGORY_OPENED;
|
||||
// Add a dummy item to show the plus-button so the user sees that there this
|
||||
// is a category. When the plus-button is clicked, fetch the content of the category
|
||||
treeTopics.Items.AddChild(tnode, DUMMY_NODE_TEXT);
|
||||
end else begin
|
||||
tnode.ImageIndex := ICONINDEX_HELPITEM;
|
||||
tnode.SelectedIndex := tnode.ImageIndex;
|
||||
end;
|
||||
Results.Next;
|
||||
end;
|
||||
finally
|
||||
FreeAndNil(Results);
|
||||
Screen.Cursor := crDefault;
|
||||
end;
|
||||
editFilter.SetFocus;
|
||||
timerSearch.Enabled := False;
|
||||
timerSearch.Enabled := True;
|
||||
editFilter.RightButton.Visible := Trim(editFilter.Text) <> '';
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.editFilterRightButtonClick(Sender: TObject);
|
||||
begin
|
||||
editFilter.Clear;
|
||||
end;
|
||||
|
||||
|
||||
procedure TfrmSQLhelp.DoSearch(Sender: TObject);
|
||||
var
|
||||
Node: PVirtualNode;
|
||||
Search: String;
|
||||
Vis: Boolean;
|
||||
|
||||
function HasVisibleChildItems(Node: PVirtualNode): Boolean;
|
||||
var
|
||||
N: PVirtualNode;
|
||||
begin
|
||||
N := treeTopics.GetFirstChild(Node);
|
||||
Result := False;
|
||||
while Assigned(N) do begin
|
||||
if treeTopics.HasChildren[N] then
|
||||
Result := HasVisibleChildItems(N)
|
||||
else
|
||||
Result := treeTopics.IsVisible[N];
|
||||
if Result then
|
||||
Exit;
|
||||
N := treeTopics.GetNextSibling(N);
|
||||
end;
|
||||
end;
|
||||
begin
|
||||
// Apply filter text
|
||||
Screen.Cursor := crHourglass;
|
||||
treeTopics.BeginUpdate;
|
||||
timerSearch.Enabled := False;
|
||||
Search := Trim(editFilter.Text);
|
||||
if Search = '' then begin
|
||||
// Show all items
|
||||
Node := treeTopics.GetFirstInitialized;
|
||||
while Assigned(Node) do begin
|
||||
treeTopics.IsVisible[Node] := True;
|
||||
Node := treeTopics.GetNextInitialized(Node);
|
||||
end;
|
||||
end else begin
|
||||
// Hide non matching child items
|
||||
Node := treeTopics.GetFirst;
|
||||
while Assigned(Node) do begin
|
||||
if not treeTopics.HasChildren[Node] then
|
||||
treeTopics.IsVisible[Node] := Pos(UpperCase(Search), UpperCase(treeTopics.Text[Node, treeTopics.Header.MainColumn])) > 0;
|
||||
Node := treeTopics.GetNext(Node);
|
||||
end;
|
||||
// Hide empty folders
|
||||
Node := treeTopics.GetFirst;
|
||||
while Assigned(Node) do begin
|
||||
if treeTopics.HasChildren[Node] then begin
|
||||
Vis := HasVisibleChildItems(Node);
|
||||
treeTopics.Expanded[Node] := Vis;
|
||||
treeTopics.IsVisible[Node] := Vis;
|
||||
end;
|
||||
Node := treeTopics.GetNext(Node);
|
||||
end;
|
||||
end;
|
||||
treeTopics.EndUpdate;
|
||||
Screen.Cursor := crDefault;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Reference in New Issue
Block a user