Skip to content

Commit

Permalink
* Further work on issue #507: Added IsAssigned(), GetData() and GetDa…
Browse files Browse the repository at this point in the history
…ta<T>() 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.
  • Loading branch information
Joachim Marder committed Mar 11, 2015
1 parent bc0f208 commit 774daed
Showing 1 changed file with 60 additions and 15 deletions.
75 changes: 60 additions & 15 deletions Source/VirtualTrees.pas
Expand Up @@ -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:class>(): T; overload; inline;
end;


// Structure used when info about a certain position in the header is needed.
TVTHeaderHitInfo = record
X,
Expand Down Expand Up @@ -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 = (
Expand Down Expand Up @@ -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<T>(pNode: PVirtualNode): T; overload; inline;
function GetNodeData<T:class>(pNode: PVirtualNode): T; overload; inline;
function GetNodeDataAt<T:class>(pXCoord: Integer; pYCoord: Integer): T;
function GetFirstSelectedNodeData<T>(): T;
function GetFirstSelectedNodeData<T:class>(): T;
function GetNodeLevel(Node: PVirtualNode): Cardinal;
function GetPrevious(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode;
function GetPreviousChecked(Node: PVirtualNode; State: TCheckState = csCheckedNormal;
Expand Down Expand Up @@ -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.


//----------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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.
Expand All @@ -28162,7 +28175,7 @@ function TBaseVirtualTree.GetNodeData(Node: PVirtualNode): Pointer;

function TBaseVirtualTree.GetNodeData<T>(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
Expand All @@ -28175,19 +28188,17 @@ function TBaseVirtualTree.GetNodeData<T>(pNode: PVirtualNode): T;

function TBaseVirtualTree.GetNodeDataAt<T>(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;
begin
lNode := GetNodeAt(pXCoord, pYCoord);

if not Assigned(lNode) then
begin
Exit(nil);
end;

Result := T(Self.GetNodeData(lNode)^);
Result := Self.GetNodeData<T>(lNode);
end;

//----------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -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>: 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;

Expand Down

0 comments on commit 774daed

Please sign in to comment.