mvctypes.pas
来自「本系统前端界面采用WINDOWS 窗口风格」· PAS 代码 · 共 569 行 · 第 1/2 页
PAS
569 行
end;
implementation
{ Let's go }
{ *********************************************************************** }
constructor TMVCNode.Create;
begin
inherited Create;
FChildren:=TList.Create;
end;
destructor TMVCNode.Destroy;
begin
if Assigned(FParent) then
with FParent do
RemoveChild(FChildren.IndexOf(Self));
{ When destroying free all children. }
while ChildCount>0 do DestroyChild(0);
inherited Destroy;
end;
function TMVCNode.GetImageIndex:integer;
begin
{ Take a close look at your data and return the index of whatever image
you want next to it. Here we base the choice on the length of the
caption. No caption, no icon. }
if Caption=''
then Result:=-1 else Result:=(Length(Caption) mod 4);
end;
procedure TMVCNode.InvalidateVirtualNode;
var T:TBaseVirtualTree;
begin
{ If the tree has a node that displays this Node then invalidate it. }
if Assigned(FVirtualNode) then
begin
T := TreeFromNode(FVirtualNode);
T.InvalidateNode(FVirtualNode);
end;
end;
procedure TMVCNode.SetCheckState(aCheckState:TCheckState);
begin
{ Update the checkstate that is stored in our Node. If the tree has a
node for the Node then invalidate it. }
if aCheckState=FCheckstate then exit;
FCheckState:=aCheckState;
if Assigned(FVirtualNode) then FVirtualNode.CheckState:=aCheckState;
InvalidateVirtualNode;
end;
procedure TMVCNode.SetIncidence(aValue:integer);
begin
{ Set the Nodes property Incidence and invalidate the node in the tree
if there is one. We fix the value into its valid range. }
if aValue=FIncidence then exit;
FIncidence:=aValue;
if FIncidence<0
then FIncidence:=0
else
if FIncidence>63
then FIncidence:=63;
InvalidateVirtualNode;
end;
procedure TMVCNode.SetCaption(aCaption:string);
begin
{ Set the Nodes property Caption and invalidate the node in the tree
if there is one. }
if aCaption=FCaption then exit;
FCaption:=aCaption;
InvalidateVirtualNode;
end;
procedure TMVCNode.SetSubCaption(aSubCaption:string);
begin
{ Set the Nodes property Subcaption and invalidate the node in the tree
if there is one. }
if aSubCaption=FSubCaption then exit;
FSubCaption:=aSubCaption;
InvalidateVirtualNode;
end;
function TMVCNode.GetChildCount:integer;
begin
Result:=FChildren.Count;
end;
function TMVCNode.GetChild(n:integer):TMVCNode;
begin
Result:=TMVCNode(FChildren[n]);
end;
function TMVCNode.CreateChild:TMVCNode;
begin
Result:=TMVCNode.Create;
Result.FParent:=Self;
FChildren.Add(Result);
if Assigned(FVirtualNode) then
with TreeFromNode(FVirtualNode) do
begin
ReinitNode(FVirtualNode,False);
InvalidateToBottom(FVirtualNode);
end;
end;
procedure TMVCNode.RemoveChild(n:integer);
var C:TMVCNode;
begin
{ Remove Child number n from our Children-List and the tree }
C:=Child[n];
C.FParent:=NIL;
FChildren.Delete(n);
if Assigned(C.FVirtualNode) then
TreeFromNode(C.FVirtualNode).DeleteNode(C.FVirtualNode);
end;
procedure TMVCNode.DestroyChild(n:integer);
var C:TMVCNode;
begin
C:=Child[n];
RemoveChild(n);
C.Free;
end;
{*************************************************************************}
constructor TMVCTree.Create;
begin
inherited Create;
FRoot:=TMVCNode.Create;
end;
destructor TMVCTree.Destroy;
begin
{ Upon destruction we need to break the link to the Viewer and free
all our Nodes and last the list itself. }
Viewer:=NIL;
FRoot.Free;
FRoot:=NIL;
inherited Destroy;
end;
procedure TMVCTree.SetViewer(aViewer:TObject);
begin
{ Assign a viewer, De-Assign a viewer (by passing NIL) and assigning
a different viewer than the one that is already linked. }
{ Prevent recursion when the viewer itself sets this property. }
if FSettingViewer>0 then exit;
inc(FSettingViewer);
try
{ First de-assign any viewer that is already linked. }
if Assigned(FViewer) then TMVCTreeView(FViewer).Tree:=NIL;
{ Set our field to point to the new viewer. }
FViewer:=aViewer;
{ Now assign this List to the new viewer. }
if Assigned(FViewer) then TMVCTreeView(FViewer).Tree:=Self;
finally
dec(FSettingViewer);
end;
end;
procedure TMVCTree.BeginUpdate;
begin
if Assigned(FViewer) then TMVCTreeView(FViewer).BeginUpdate;
end;
procedure TMVCTree.EndUpdate;
begin
if Assigned(FViewer) then TMVCTreeView(FViewer).EndUpdate;
end;
{ *********************************************************************** }
{ Now the tree. }
{ The internal node-data assigned to every virtual node consist only of
a reference to an instance of TMVCNode. }
type PMyNodeData=^TMyNodeData;
TMyNodeData=packed record Node:TMVCNode end;
destructor TMVCTreeView.Destroy;
begin
{ When destroying the tree, break the link with the list. Note that
we do NOT set FNodes:=NIL. By using the Set-Method it is made sure
that the List gets notified of our demise and sets its own reference
to NIL too. }
Tree:=NIL;
inherited Destroy;
end;
procedure TMVCTreeView.SetTree(aTree:TMVCTree);
begin
if FTree=aTree then exit;
{ If we already have a list, break the link to it. }
if Assigned(FTree) then FTree.Viewer:=NIL;
{ Now make a link to the new structure: }
FTree:=aTree;
if Assigned(FTree)
then
begin
FTree.Viewer:=Self;
RootNodeCount:=FTree.Root.ChildCount;
if FTree.Root.ChildCount>0 then ValidateNode(GetFirst, False);
end
else RootNodeCount:=0;
end;
function TMVCTreeView.GetMVCNode(VirtualNode:PVirtualNode):TMVCNode;
begin
{ Return the reference to the TMVCNode that is represented by
Virtualnode }
if VirtualNode=NIL
then Result:=NIL
else Result:=PMyNodeData(InternalData(VirtualNode)).Node;
end;
procedure TMVCTreeView.SetMVCNode(VirtualNode:PVirtualNode;aNode:TMVCNode);
begin
{ Note the relationship between a VirtualNode and the TMVCNode it
represents in the Nodes data. }
PMyNodeData(InternalData(VirtualNode)).Node:=aNode;
end;
function TMVCTreeView.DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink;
var Link:TMVCEditLink;
begin
Result:=inherited DoCreateEditor(Node,Column);
if Result=nil then
begin
Link:=TMVCEditLink.Create;
Result:=Link;
end;
end;
function TMVCTreeView.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer;
{ How wide is the the node in pixels. This is interesting if the graphic
representation includes elements that are not text and whose width needs
to be calculated. Here we draw a bar whose width corresponds to the
value of the Incidence-property of the MVCNode. }
var N:TMVCNode;
Text: string;
begin
N:=GetMVCNode(Node);
if Canvas = nil then
Canvas := Self.Canvas;
if not Assigned(N)
then Result:=0
else
begin
Text:=GetNodeText(N, Column);
Result:=Canvas.TextWidth(Text);
if Column + 1 in [0, 1] then
Result := Result + 8 + N.Incidence;
end;
end;
function TMVCTreeView.GetNodeText(aNode:TMVCNode;aColumn:integer):string;
{ This method returns the text that is to be displayed in aColumn for
the Node aNode. It is in a separate function so that it can be used
for the calculation of width and for the actual drawing. You could
also process the data from the actual Node as stored in your structure
to give some other text as shown here for the third column. }
begin
case aColumn of
-1,0:Result:=aNode.Caption;
1:Result:=aNode.SubCaption;
2:case aNode.Incidence of
0..5:Result:='under 6';
6..20:Result:='6 to 21';
21..62:Result:='21 or above';
63:Result:='Max.';
else Result:='What?';
end; (* of case Incidence *)
else Result:='What *"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?