From 774daed2a8c58d4be759f979a5c4f91c0a096aeb Mon Sep 17 00:00:00 2001 From: Joachim Marder Date: Wed, 11 Mar 2015 22:10:22 +0100 Subject: [PATCH] * Further work on issue #507: Added IsAssigned(), GetData() and GetData() to TVirtualNode. Added generic constraints for classes. * If the overlay image is the same as the normal image, we don't paint it. Users often forgot to respect the Kind parameter and ended up opening bugs. --- Source/VirtualTrees.pas | 75 ++++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/Source/VirtualTrees.pas b/Source/VirtualTrees.pas index af5b806f7..d33c05fb2 100644 --- a/Source/VirtualTrees.pas +++ b/Source/VirtualTrees.pas @@ -611,9 +611,15 @@ TVTReference = record NextSibling, // link to the node's next sibling or nil if it is the last node FirstChild, // link to the node's first child... LastChild: PVirtualNode; // link to the node's last child... + private Data: record end; // this is a placeholder, each node gets extra data determined by NodeDataSize + public + function IsAssigned(): Boolean; inline; + function GetData(): Pointer; overload; inline; + function GetData(): T; overload; inline; end; + // Structure used when info about a certain position in the header is needed. TVTHeaderHitInfo = record X, @@ -1582,6 +1588,7 @@ TVTImageInfo = record YPos: Integer; // Vertical position in the current target canvas. Ghosted: Boolean; // Flag to indicate that the image must be drawn slightly lighter. Images: TCustomImageList; // The image list to be used for painting. + function Equals(const pImageInfo2: TVTImageInfo): Boolean; end; TVTImageInfoIndex = ( @@ -2944,9 +2951,9 @@ TBaseVirtualTree = class(TCustomControl) function GetNodeAt(X, Y: Integer): PVirtualNode; overload; function GetNodeAt(X, Y: Integer; Relative: Boolean; var NodeTop: Integer): PVirtualNode; overload; function GetNodeData(Node: PVirtualNode): Pointer; overload; - function GetNodeData(pNode: PVirtualNode): T; overload; inline; + function GetNodeData(pNode: PVirtualNode): T; overload; inline; function GetNodeDataAt(pXCoord: Integer; pYCoord: Integer): T; - function GetFirstSelectedNodeData(): T; + function GetFirstSelectedNodeData(): T; function GetNodeLevel(Node: PVirtualNode): Cardinal; function GetPrevious(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode; function GetPreviousChecked(Node: PVirtualNode; State: TCheckState = csCheckedNormal; @@ -3981,8 +3988,8 @@ TCanvasEx = class(TCanvas); UtilityImages, // some small additional images (e.g for header dragging) SystemCheckImages, // global system check images SystemFlatCheckImages: TImageList; // global flat system check images - Initialized: Boolean; // True if global structures have been initialized. - NeedToUnitialize: Boolean; // True if the OLE subsystem could be initialized successfully. + Initialized: Boolean = False; // True if global structures have been initialized. + NeedToUnitialize: Boolean = False; // True if the OLE subsystem could be initialized successfully. //---------------------------------------------------------------------------------------------------------------------- @@ -23533,8 +23540,13 @@ procedure TBaseVirtualTree.PaintImage(var PaintInfo: TVTPaintInfo; ImageInfoInde // Since the overlay image must be specified together with the image to draw // it is meaningfull to retrieve it in advance. - if DoOverlay then - GetImageIndex(PaintInfo, ikOverlay, iiOverlay, Images) + if DoOverlay then begin + GetImageIndex(PaintInfo, ikOverlay, iiOverlay, Images); + // If the overlay image is the same as the normal image, don't paint it. + // Users often forgot to respect the Kind parameter and ended up opening bugs. + if PaintInfo.ImageInfo[iiOverlay].Equals(PaintInfo.ImageInfo[iiNormal]) then + PaintInfo.ImageInfo[iiOverlay].Index := -1; + end else PaintInfo.ImageInfo[iiOverlay].Index := -1; @@ -28143,6 +28155,7 @@ function TBaseVirtualTree.GetNodeAt(X, Y: Integer; Relative: Boolean; var NodeTo //---------------------------------------------------------------------------------------------------------------------- + function TBaseVirtualTree.GetNodeData(Node: PVirtualNode): Pointer; // Returns the address of the user defined data area in the node. @@ -28162,7 +28175,7 @@ function TBaseVirtualTree.GetNodeData(Node: PVirtualNode): Pointer; function TBaseVirtualTree.GetNodeData(pNode: PVirtualNode): T; -// Returns associated data converted to the type given in the generic part of the function. +// Returns the associated data converted to the class given in the generic part of the function. begin if Assigned(pNode) then @@ -28175,7 +28188,7 @@ function TBaseVirtualTree.GetNodeData(pNode: PVirtualNode): T; function TBaseVirtualTree.GetNodeDataAt(pXCoord, pYCoord: Integer): T; -// Returns associated data at the specified coordinates converted to the type given in the generic part of the function. +// Returns the associated data at the specified coordinates converted to the type given in the generic part of the function. var lNode: PVirtualNode; @@ -28183,11 +28196,9 @@ function TBaseVirtualTree.GetNodeDataAt(pXCoord, pYCoord: Integer): T; lNode := GetNodeAt(pXCoord, pYCoord); if not Assigned(lNode) then - begin Exit(nil); - end; - Result := T(Self.GetNodeData(lNode)^); + Result := Self.GetNodeData(lNode); end; //---------------------------------------------------------------------------------------------------------------------- @@ -35445,11 +35456,45 @@ function TVirtualDrawTree.GetOptionsClass: TTreeOptionsClass; //---------------------------------------------------------------------------------------------------------------------- +{ PVirtualNodeHelper } + +function TVirtualNode.GetData(): Pointer; + +// Returns the associated data converted to the class given in the generic part of the function. + +begin + Result := PByte(@Self.Data) + TBaseVirtualTree.FTotalInternalDataSize; + Include(States, vsOnFreeNodeCallRequired); +end; + +function TVirtualNode.GetData: T; + +// Returns the associated data converted to the class given in the generic part of the function. + +begin + Result := T(Pointer((PByte(@(Self.Data)) + TBaseVirtualTree.FTotalInternalDataSize))^); + Include(States, vsOnFreeNodeCallRequired); +end; + +function TVirtualNode.IsAssigned: Boolean; + +// Returns False if this node is nil, True otherwise + +begin + Exit(@Self <> nil); +end; + +{ TVTImageInfo } + +function TVTImageInfo.Equals(const pImageInfo2: TVTImageInfo): Boolean; + + // Returns true if both images are the same, does not regard Ghosted and position. + +begin + Result := (Self.Index = pImageInfo2.Index) and (Self.Images = pImageInfo2.Images); +end; + initialization - // Necessary for dynamic package loading. - Initialized := False; - NeedToUnitialize := False; - // This watcher is used whenever a global structure could be modified by more than one thread. Watcher := TCriticalSection.Create;