📄 ucatexpert.pas
字号:
if not Assigned(Child) then //no nodes on this level so far?
if Assigned(Parent) then //add as first child
Child := TreeView.Items.AddChildObject(Parent, Value, Pointer(Index))
else
Child := TreeView.Items.AddObject(nil, Value, Pointer(Index))
else
begin
//skip all sub categories
while Assigned(Child) and (TImageIndex(Child.ImageIndex) <> iiOption) do
Child := Child.GetNextSibling;
//search position to insert the option (alphabetically)
while Assigned(Child) and CompareSkip(Child.Text) do
Child := Child.GetNextSibling;
if Assigned(Child) then //not the last?
begin
//add before the node
Child := TreeView.Items.Insert(Child, Value);
//WARNING!
//InsertObject is faulty in Kylix, it will prepend to the parent!
//so, here we do it in two statements
Child.Data := Pointer(Index);
end
else
if Assigned(Parent) then //add as last child
Child := TreeView.Items.AddChildObject(Parent, Value, Pointer(Index))
else
Child := TreeView.Items.AddObject(nil, Value, Pointer(Index))
end;
Child.ImageIndex := ord(iiOption); //node is an option
Child.SelectedIndex := ord(iiOption);
end;
var ChangeEvent :TTVChangedEvent; //event when changing the node
i :Cardinal; //counter through the options
Descr :TOptionDescription; //description of the options
begin
FLastNode := nil; //don't save anything
ChangeEvent := TreeView.OnChange;
try
TreeView.OnChange := nil; //disable events
TreeView.Items.Clear; //clear the tree
finally
TreeView.OnChange := ChangeEvent;
end;
TreeView.Enabled := First < Last; //dis-/enable tree view
if First < Last then
begin
for i := First to Last - 1 do //for each option
begin
FOptions.Description(i, Descr); //get the option
//create the category nodes and create node, also with the value of the
AddOption(GetCreateCategoryNode(Descr.Category), //option
Descr.Name, ValueToString(FOptions.Option[i], Descr), i);
end;
TreeView.FullExpand; //show all options/nodes
TreeView.Selected := TreeView.Items.GetFirstNode; //select something
end;
end;
{Refreshes the text of all nodes. }
procedure TFormCatExpert.RefreshAllNodes;
var i :Integer; //counter through all nodes
Node :TTreeNode; //each node
Option :Cardinal; //index of option of the node
Descr :TOptionDescription; //type of the option
begin
for i := 0 to TreeView.Items.Count - 1 do //for each node
begin
Node := TreeView.Items[i]; //get it
if Node.ImageIndex = ord(iiOption) then //is an option?
begin
Option := Cardinal(Node.Data); //get index of option
FOptions.Description(Option, Descr); //get its description
Node.Text := Descr.Name + ': ' + //refresh its text
ValueToString(FOptions.Option[Option], Descr);
end;
end;
end;
{Saves the value in the component of the currently chosen options.
~param RefreshTreeView if the (new) value of the option should be refreshed in
the outline }
procedure TFormCatExpert.SaveOption(RefreshTreeView: Boolean);
var Descr :TOptionDescription; //type of the option
Value :TOptionValue; //value of the option
begin
if Assigned(FLastNode) then //options to save?
begin
//get type of the option
FOptions.Description(Cardinal(FLastNode.Data), Descr);
case Descr.DataType of //set value of option depending on type
otString: Value.StrData := TEdit(FEditControl).Text;
otBoolean: Value.BoolData := TCheckBox(FEditControl).Checked;
{$IFNDEF USENORMALSPINEDIT}
otInteger: Value.IntData := TGVSpinEdit(FEditControl).Value;
{$ELSE}
otInteger: Value.IntData := TSpinEdit(FEditControl).Value;
{$ENDIF}
{$IFNDEF USENORMALSPINEDIT}
otReal: Value.RealData := TExtSpinEdit(FEditControl).Value;
{$ELSE}
otReal: Value.RealData := TSpinEdit(FEditControl).Value / 1000;
{$ENDIF}
otEnumeration: Value.EnumData := TComboBox(FEditControl).ItemIndex;
otSet: Value.SetData := TSetButton(FEditControl).Value;
end;
//set the value of the option
FOptions.Option[Cardinal(FLastNode.Data)] := Value;
if RefreshTreeView then //new value should be shown?
if ooChangesOtherOptions in Descr.Options then //others changed, too?
RefreshAllNodes //refresh all nodes
else
//refresh value of the node
FLastNode.Text := Descr.Name + ': ' +
ValueToString(FOptions.Option[Cardinal(FLastNode.Data)],
Descr);
end; //if assigned(FLastNode)
end;
{Loads the options from the file.
~param FileName the name of the file to load the options from }
procedure TFormCatExpert.LoadOptions(FileName: String);
var Ini :TIniFile; //the ini file containing the options
Node :TTreeNode; //each node
begin
//ini files need to be marked to be local (in current directory)
if (Pos(PathDelimiter, FileName) = 0) and (Pos(':', FileName) = 0) then
FileName := ExtractFilePath(ParamStr(0)) + FileName;
Ini := TIniFile.Create(FileName); //open the ini file
try
FOptions.LoadAllIniOptions(Ini); //read the options
finally
Ini.Free; //close the file
end;
RefreshAllNodes; //show the loaded options
Node := FLastNode;
FLastNode := nil;
TreeView.OnChange(TreeView, Node); //re-edit current value
end;
{Writes the options to the file.
~param FileName the name of the file to load the options from
~param Hierarchy if the options should be saved common by their individual
topic }
procedure TFormCatExpert.SaveOptions(FileName: String; Hierarchy: Boolean);
var Ini :TIniFile; //ini file to write the options to
{Saves the option to the ini file.
~param Index the index of the option to save
~param Section the section to save it in }
procedure SaveOneOption(Index: Cardinal; Section: String);
var Descr :TOptionDescription; //description of the option
begin
FOptions.Description(Index, Descr); //get type of the option
//option can be readand set again?
if [ooNoRead, ooNoWrite] * Descr.Options = [] then
Ini.WriteString(Section, Descr.Name, //write value in the ini file
QuotedStr(ValueToString(FOptions.Option[Index], Descr)));
end;
var i :Cardinal; //counter through the options
Topic :String; //topic to save all options in
begin
SaveOption(False); //save current option
//ini files need to be marked to be local (in current directory)
if (Pos(PathDelimiter, FileName) = 0) and (Pos(':', FileName) = 0) then
FileName := ExtractFilePath(ParamStr(0)) + FileName;
Ini := TIniFile.Create(FileName); //open the ini file
try
if Hierarchy then //should be written by hierarchy?
for i := 0 to FOptions.Count - 1 do //for each option
SaveOneOption(i, FOptions.Topic(i)) //save it in its topic
else
begin
Topic := FOptions.DefaultTopic; //get topic to save them to
for i := 0 to FOptions.Count - 1 do //for each option
SaveOneOption(i, Topic); //save it
end;
finally
Ini.Free; //close the ini file
end;
end;
{Searches an option, this either means a dialog to enter the search text and
options is shown or a previously entered search is repeated.
~param TrySearchAgain whether a search should be repeated (if one has already
been started) }
procedure TFormCatExpert.DoSearch(TrySearchAgain: Boolean);
begin
//search should and can be repeated?
if TrySearchAgain and (FOptionSearchText <> '') then
SearchOption(FOptionSearchText, FOptionSearchAttributes) //repeat it
else
begin
if not Assigned(FSearchDialog) then //if dialog has not yet been created?
//create it
FSearchDialog := TFormOptionSearchDialog.Create(Self, SearchOption);
//show the dialog (or bring it again to the front)
FSearchDialog.ShowUnModal;
end;
end;
{Does the actual search for an option.
~param Text the text to search options by
~param Attributes the attributes of options to check for the text }
procedure TFormCatExpert.SearchOption(const Text: String;
Attributes: TOptionSearchAttributes);
var SearchText :String; //the search text in lower case
{Checks whether a node meets the requirements of the search criteria.
~param Node the to be checked agains the search criteria
~result whether the option represented by the node satisfies the search
criteria }
function CheckNode(Node: TTreeNode): Boolean;
var Index :Cardinal; //the index of the option
Descr :TOptionDescription; //description of the option
begin
Assert(Assigned(Node));
Result := Node.ImageIndex = Ord(iiOption); //represents an option?
if Result then
begin
Index := Cardinal(Node.Data); //get index of the option
if [osaName, osaDescription, osaCategory] * Attributes <> [] then
begin
FOptions.Description(Index, Descr); //get its description
//check attributes from the description for the text
Result := ((osaName in Attributes) and
(Pos(SearchText, LowerCase(Descr.Name)) <> 0)) or
((osaDescription in Attributes) and
(Pos(SearchText, LowerCase(Descr.Description)) <> 0)) or
((osaCategory in Attributes) and
(Pos(SearchText, LowerCase(Descr.Category)) <> 0));
end
else
Result := False; //not found so far
//not found so far and topic should be checked?
if not Result and (osaTopic in Attributes) then //then check it
Result := Pos(SearchText, LowerCase(FOptions.Topic(Index))) <> 0;
end;
end;
//the message to shown if no option has been found, depending on
//whether the current option matches the criteria
const NotFoundMessages: array[Boolean] of String =
('No matching option found.',
'No further matching options found.');
var Count :Integer; //number of nodes in tree view
StartNode :TTreeNode; //the node where to start search
Node :TTreeNode; //runner through the nodes
begin
FOptionSearchText := Text; //save search parameters
FOptionSearchAttributes := Attributes;
if TreeView.Enabled then //not empty
begin
Count := TreeView.Items.Count; //get number of nodes
if Count > 0 then //check again that it is not empty
begin
if Assigned(TreeView.Selected) then //get starting node
StartNode := TreeView.Selected
else
StartNode := nil; //if none selected start "at end"
SearchText := LowerCase(Text); //get text in lower case
Node := StartNode; //get the following node
if Assigned(Node) then
Node := Node.GetNext;
//and search below current node
while Assigned(Node) and not CheckNode(Node) do
Node := Node.GetNext;
if not Assigned(Node) then //if no option found
begin
Node := TreeView.Items.GetFirstNode; //search from beginning up to the
while (Node <> StartNode) and not CheckNode(Node) do //starting node
Node := Node.GetNext;
end;
//a (different) matching option found?
if Node <> StartNode then
TreeView.Selected := Node //just select it
else
//inform the user that none has been found
MessageDlg(NotFoundMessages[CheckNode(Node)], mtInformation, [mbOK],
ButtonSearchDlg.HelpContext);
end;
end;
end;
{Called when the form is resized.
~param Sender the sender of the event, the form itself }
procedure TFormCatExpert.FormResize(Sender: TObject);
begin
{$IFNDEF LINUX}
//resizing anchored components while resizing is not a good idea
TimerResize.Enabled := True; //so we do it afterwards
{$ENDIF}
end;
{Called when another node in the treeview is selected.
~param Sender the sender of the event, ~[link TreeView]
~param Node the selected Node }
procedure TFormCatExpert.TreeViewChange(Sender: TObject; Node: TTreeNode);
//control class for each type of the options
const EditType: array[TOptionType] of TEditComponentClass =
(TEdit, TCheckBox,
{$IFNDEF USENORMALSPINEDIT}
TGVSpinEdit, TExtSpinEdit,
{$ELSE}
TSpinEdit, TSpinEdit,
{$ENDIF}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -