* Synchronize with main VTV repository up to svn rev 419

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3346 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
blikblum
2014-07-20 13:11:13 +00:00
parent e0ef4c244c
commit b7ba0d3727

View File

@ -3,7 +3,7 @@ unit VirtualTrees;
{$mode delphi}{$H+} {$mode delphi}{$H+}
{$packset 1} {$packset 1}
// Version 5.0.0 // Version 5.0.1
// //
// The contents of this file are subject to the Mozilla Public License // The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in compliance // Version 1.1 (the "License"); you may not use this file except in compliance
@ -105,7 +105,7 @@ const
VTMajorVersion = 5; VTMajorVersion = 5;
VTMinorVersion = 0; VTMinorVersion = 0;
VTReleaseVersion = 0; VTReleaseVersion = 1;
VTTreeStreamVersion = 2; VTTreeStreamVersion = 2;
VTHeaderStreamVersion = 6; // The header needs an own stream version to indicate changes only relevant to the header. VTHeaderStreamVersion = 6; // The header needs an own stream version to indicate changes only relevant to the header.
@ -157,6 +157,9 @@ const
ChangeTimer = 5; ChangeTimer = 5;
StructureChangeTimer = 6; StructureChangeTimer = 6;
SearchTimer = 7; SearchTimer = 7;
ThemeChangedTimer = 8;
ThemeChangedTimerDelay = 500;
// Need to use this message to release the edit link interface asynchronously. // Need to use this message to release the edit link interface asynchronously.
WM_CHANGESTATE = WM_APP + 32; WM_CHANGESTATE = WM_APP + 32;
@ -183,9 +186,11 @@ const
IID_IDragSourceHelper: TGUID = (D1: $DE5BF786; D2: $477A; D3: $11D2; D4: ($83, $9D, $00, $C0, $4F, $D9, $18, $D0)); IID_IDragSourceHelper: TGUID = (D1: $DE5BF786; D2: $477A; D3: $11D2; D4: ($83, $9D, $00, $C0, $4F, $D9, $18, $D0));
IID_IDropTarget: TGUID = (D1: $00000122; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00, $46)); IID_IDropTarget: TGUID = (D1: $00000122; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
CLSID_DragDropHelper: TGUID = (D1: $4657278A; D2: $411B; D3: $11D2; D4: ($83, $9A, $00, $C0, $4F, $D9, $18, $D0)); CLSID_DragDropHelper: TGUID = (D1: $4657278A; D2: $411B; D3: $11D2; D4: ($83, $9A, $00, $C0, $4F, $D9, $18, $D0));
DSH_ALLOWDROPDESCRIPTIONTEXT = $1;
SID_IDropTargetHelper = '{4657278B-411B-11D2-839A-00C04FD918D0}'; SID_IDropTargetHelper = '{4657278B-411B-11D2-839A-00C04FD918D0}';
SID_IDragSourceHelper = '{DE5BF786-477A-11D2-839D-00C04FD918D0}'; SID_IDragSourceHelper = '{DE5BF786-477A-11D2-839D-00C04FD918D0}';
SID_IDragSourceHelper2 = '{83E07D0D-0C5F-4163-BF1A-60B274051E40}';
SID_IDropTarget = '{00000122-0000-0000-C000-000000000046}'; SID_IDropTarget = '{00000122-0000-0000-C000-000000000046}';
// Help identifiers for exceptions. Application developers are responsible to link them with actual help topics. // Help identifiers for exceptions. Application developers are responsible to link them with actual help topics.
@ -720,14 +725,21 @@ type
sizeDragImage: TSize; sizeDragImage: TSize;
ptOffset: TPoint; ptOffset: TPoint;
hbmpDragImage: HBITMAP; hbmpDragImage: HBITMAP;
ColorRef: TColorRef; crColorKey: TColorRef;
end; end;
IDragSourceHelper = interface(IUnknown) IDragSourceHelper = interface(IUnknown)
[SID_IDragSourceHelper] [SID_IDragSourceHelper]
function InitializeFromBitmap(var SHDragImage: TSHDragImage; pDataObject: IDataObject): HRESULT; stdcall; function InitializeFromBitmap(SHDragImage: PSHDragImage; pDataObject: IDataObject): HRESULT; stdcall;
function InitializeFromWindow(Window: HWND; var ppt: TPoint; pDataObject: IDataObject): HRESULT; stdcall; function InitializeFromWindow(Window: HWND; var ppt: TPoint; pDataObject: IDataObject): HRESULT; stdcall;
end; end;
{$EXTERNALSYM IDragSourceHelper}
IDragSourceHelper2 = interface(IDragSourceHelper)
[SID_IDragSourceHelper2]
function SetFlags(dwFlags: DWORD): HRESULT; stdcall;
end;
{$EXTERNALSYM IDragSourceHelper2}
IVTDragManager = interface(IUnknown) IVTDragManager = interface(IUnknown)
['{C4B25559-14DA-446B-8901-0C879000EB16}'] ['{C4B25559-14DA-446B-8901-0C879000EB16}']
@ -2042,6 +2054,7 @@ type
FLastClickPos: TPoint; // Used for retained drag start and wheel mouse scrolling. FLastClickPos: TPoint; // Used for retained drag start and wheel mouse scrolling.
FOperationCount: Cardinal; // Counts how many nested long-running operations are in progress. FOperationCount: Cardinal; // Counts how many nested long-running operations are in progress.
FOperationCanceled: Boolean; // Used to indicate that a long-running operation should be canceled. FOperationCanceled: Boolean; // Used to indicate that a long-running operation should be canceled.
FChangingTheme: Boolean; // Used to indicate that a theme change is goi ng on
{$ifdef EnableAccessible} {$ifdef EnableAccessible}
// MSAA support // MSAA support
@ -2315,6 +2328,7 @@ type
procedure SetVisible(Node: PVirtualNode; Value: Boolean); procedure SetVisible(Node: PVirtualNode; Value: Boolean);
procedure SetVisiblePath(Node: PVirtualNode; Value: Boolean); procedure SetVisiblePath(Node: PVirtualNode; Value: Boolean);
procedure StaticBackground(Source: TBitmap; Target: TCanvas; const OffsetPosition: TPoint; const R: TRect); procedure StaticBackground(Source: TBitmap; Target: TCanvas; const OffsetPosition: TPoint; const R: TRect);
procedure SetWindowTheme(const Theme: String);
procedure TileBackground(Source: TBitmap; Target: TCanvas; const Offset: TPoint; R: TRect); procedure TileBackground(Source: TBitmap; Target: TCanvas; const Offset: TPoint; R: TRect);
function ToggleCallback(Step, StepSize: Integer; Data: Pointer): Boolean; function ToggleCallback(Step, StepSize: Integer; Data: Pointer): Boolean;
protected protected
@ -2474,6 +2488,7 @@ type
procedure DoGetLineStyle(var Bits: Pointer); virtual; procedure DoGetLineStyle(var Bits: Pointer); virtual;
function DoGetNodeHint(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; virtual; function DoGetNodeHint(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; virtual;
function DoGetNodeTooltip(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; virtual; function DoGetNodeTooltip(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; virtual;
function DoGetNodeExtraWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; virtual;
function DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; virtual; function DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; virtual;
function DoGetPopupMenu(Node: PVirtualNode; Column: TColumnIndex; const Position: TPoint): TPopupMenu; virtual; function DoGetPopupMenu(Node: PVirtualNode; Column: TColumnIndex; const Position: TPoint): TPopupMenu; virtual;
procedure DoGetUserClipboardFormats(var Formats: TFormatEtcArray); virtual; procedure DoGetUserClipboardFormats(var Formats: TFormatEtcArray); virtual;
@ -3010,7 +3025,7 @@ type
property CutCopyCount: Integer read GetCutCopyCount; property CutCopyCount: Integer read GetCutCopyCount;
property DragImage: TVTDragImage read FDragImage; property DragImage: TVTDragImage read FDragImage;
property VTVDragManager: IVTDragManager read GetDragManager; property VTVDragManager: IVTDragManager read GetDragManager;
property DropTargetNode: PVirtualNode read FDropTargetNode; property DropTargetNode: PVirtualNode read FDropTargetNode write FDropTargetNode;
property EditLink: IVTEditLink read FEditLink; property EditLink: IVTEditLink read FEditLink;
property EmptyListMessage: String read FEmptyListMessage write SetEmptyListMessage; property EmptyListMessage: String read FEmptyListMessage write SetEmptyListMessage;
property Expanded[Node: PVirtualNode]: Boolean read GetExpanded write SetExpanded; property Expanded[Node: PVirtualNode]: Boolean read GetExpanded write SetExpanded;
@ -3230,6 +3245,7 @@ type
procedure GetRenderStartValues(Source: TVSTTextSourceType; out Node: PVirtualNode; procedure GetRenderStartValues(Source: TVSTTextSourceType; out Node: PVirtualNode;
out NextNodeProc: TGetNextNodeProc); out NextNodeProc: TGetNextNodeProc);
function GetOptions: TCustomStringTreeOptions; function GetOptions: TCustomStringTreeOptions;
function GetStaticText(Node: PVirtualNode; Column: TColumnIndex): String;
function GetText(Node: PVirtualNode; Column: TColumnIndex): String; function GetText(Node: PVirtualNode; Column: TColumnIndex): String;
procedure InitializeTextProperties(var PaintInfo: TVTPaintInfo); procedure InitializeTextProperties(var PaintInfo: TVTPaintInfo);
procedure PaintNormalText(var PaintInfo: TVTPaintInfo; TextOutFlags: Integer; Text: String); procedure PaintNormalText(var PaintInfo: TVTPaintInfo; TextOutFlags: Integer; Text: String);
@ -3242,11 +3258,13 @@ type
protected protected
procedure AdjustPaintCellRect(var PaintInfo: TVTPaintInfo; out NextNonEmpty: TColumnIndex); override; procedure AdjustPaintCellRect(var PaintInfo: TVTPaintInfo; out NextNonEmpty: TColumnIndex); override;
function CanExportNode(Node: PVirtualNode): Boolean; function CanExportNode(Node: PVirtualNode): Boolean;
function CalculateStaticTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; virtual;
function CalculateTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; virtual; function CalculateTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; virtual;
function ColumnIsEmpty(Node: PVirtualNode; Column: TColumnIndex): Boolean; override; function ColumnIsEmpty(Node: PVirtualNode; Column: TColumnIndex): Boolean; override;
function DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink; override; function DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink; override;
function DoGetNodeHint(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; override; function DoGetNodeHint(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; override;
function DoGetNodeTooltip(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; override; function DoGetNodeTooltip(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; override;
function DoGetNodeExtraWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; override;
function DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; override; function DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; override;
procedure DoGetText(Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; procedure DoGetText(Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var Text: String); virtual; var Text: String); virtual;
@ -3303,6 +3321,7 @@ type
function SaveToCSVFile(const FileNameWithPath : TFileName; const IncludeHeading : Boolean) : Boolean; function SaveToCSVFile(const FileNameWithPath : TFileName; const IncludeHeading : Boolean) : Boolean;
property ImageText[Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex]: String read GetImageText; property ImageText[Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex]: String read GetImageText;
property StaticText[Node: PVirtualNode; Column: TColumnIndex]: String read GetStaticText;
property Text[Node: PVirtualNode; Column: TColumnIndex]: String read GetText write SetText; property Text[Node: PVirtualNode; Column: TColumnIndex]: String read GetText write SetText;
end; end;
@ -5510,29 +5529,23 @@ begin
if HandleAllocated then if HandleAllocated then
begin begin
{$ifdef ThemeSupport}
//todo
{
if IsWinVistaOrAbove and ((tsUseThemes in FStates) or if IsWinVistaOrAbove and ((tsUseThemes in FStates) or
((toThemeAware in ToBeSet) and StyleServices.Enabled)) and ((toThemeAware in ToBeSet) and StyleServices.Enabled)) and
(toUseExplorerTheme in (ToBeSet + ToBeCleared)) then (toUseExplorerTheme in (ToBeSet + ToBeCleared)) then
if toUseExplorerTheme in ToBeSet then if toUseExplorerTheme in ToBeSet then
begin begin
SetWindowTheme(Handle, 'explorer', nil); SetWindowTheme('explorer');
DoStateChange([tsUseExplorerTheme]); DoStateChange([tsUseExplorerTheme]);
end end
else else
if toUseExplorerTheme in ToBeCleared then if toUseExplorerTheme in ToBeCleared then
begin begin
SetWindowTheme(Handle, '', nil); SetWindowTheme('');
DoStateChange([], [tsUseExplorerTheme]); DoStateChange([], [tsUseExplorerTheme]);
end; end;
}
{$endif ThemeSupport}
if not (csLoading in ComponentState) then if not (csLoading in ComponentState) then
begin begin
{$ifdef ThemeSupport}
if (toThemeAware in ToBeSet + ToBeCleared) or (toUseExplorerTheme in ToBeSet + ToBeCleared) then if (toThemeAware in ToBeSet + ToBeCleared) or (toUseExplorerTheme in ToBeSet + ToBeCleared) then
begin begin
if (toThemeAware in ToBeSet) and StyleServices.Enabled then if (toThemeAware in ToBeSet) and StyleServices.Enabled then
@ -5544,7 +5557,6 @@ begin
PrepareBitmaps(True, False); PrepareBitmaps(True, False);
RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_VALIDATE or RDW_FRAME); RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_VALIDATE or RDW_FRAME);
end; end;
{$endif ThemeSupport}
if toChildrenAbove in ToBeSet + ToBeCleared then if toChildrenAbove in ToBeSet + ToBeCleared then
begin begin
@ -5560,7 +5572,7 @@ begin
end; end;
end; end;
end; end;
end; end;
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -6074,34 +6086,40 @@ var
Height: Integer; Height: Integer;
DragSourceHelper: IDragSourceHelper; DragSourceHelper: IDragSourceHelper;
DragInfo: TSHDragImage; DragInfo: TSHDragImage;
lDragSourceHelper2: IDragSourceHelper2;// Needed to get Windows Vista+ style drag hints.
lNullPoint: TPoint;
begin begin
Width := DragImage.Width; Width := DragImage.Width;
Height := DragImage.Height; Height := DragImage.Height;
// Determine whether the system supports the drag helper interfaces. // Determine whether the system supports the drag helper interfaces.
if Assigned(DataObject) and Succeeded(CoCreateInstance(CLSID_DragDropHelper, nil, CLSCTX_INPROC_SERVER, if Assigned(DataObject) and Succeeded(CoCreateInstance(CLSID_DragDropHelper, nil, CLSCTX_INPROC_SERVER,
IID_IDragSourceHelper, DragSourceHelper)) then IDragSourceHelper, DragSourceHelper)) then
begin begin
Include(FStates, disSystemSupport); Include(FStates, disSystemSupport);
lNullPoint := Point(0,0);
if Supports(DragSourceHelper, IDragSourceHelper2, lDragSourceHelper2) then
lDragSourceHelper2.SetFlags(DSH_ALLOWDROPDESCRIPTIONTEXT);// Show description texts
if not Succeeded(DragSourceHelper.InitializeFromWindow(0, lNullPoint, DataObject)) then begin // First let the system try to initialze the DragSourceHelper, this works fine e.g. for file system objects
// Supply the drag source helper with our drag image. // Supply the drag source helper with our drag image.
DragInfo.sizeDragImage.cx := Width; DragInfo.sizeDragImage.cx := Width;
DragInfo.sizeDragImage.cy := Height; DragInfo.sizeDragImage.cy := Height;
DragInfo.ptOffset.x := Width div 2; DragInfo.ptOffset.x := Width div 2;
DragInfo.ptOffset.y := Height div 2; DragInfo.ptOffset.y := Height div 2;
//lcl
//todo: replace CopyImage. Alternatively reimplement Drag support //todo: replace CopyImage. Alternatively reimplement Drag support
{$ifndef INCOMPLETE_WINAPI} {$ifndef INCOMPLETE_WINAPI}
DragInfo.hbmpDragImage := CopyImage(DragImage.Handle, IMAGE_BITMAP, Width, Height, LR_COPYRETURNORG); DragInfo.hbmpDragImage := CopyImage(DragImage.Handle, IMAGE_BITMAP, Width, Height, LR_COPYRETURNORG);
{$else} {$else}
DragInfo.hbmpDragImage := 0; DragInfo.hbmpDragImage := 0;
{$endif} {$endif}
DragInfo.ColorRef := ColorToRGB(FColorKey); DragInfo.crColorKey := ColorToRGB(FColorKey);
if not Succeeded(DragSourceHelper.InitializeFromBitmap(DragInfo, DataObject)) then if not Succeeded(DragSourceHelper.InitializeFromBitmap(@DragInfo, DataObject)) then
begin begin
DeleteObject(DragInfo.hbmpDragImage); DeleteObject(DragInfo.hbmpDragImage);
Exclude(FStates, disSystemSupport); Exclude(FStates, disSystemSupport);
end; end;
end;
end end
else else
Exclude(FStates, disSystemSupport); Exclude(FStates, disSystemSupport);
@ -7057,7 +7075,7 @@ begin
// If the text is taller than the given height, perform no vertical centration as this // If the text is taller than the given height, perform no vertical centration as this
// would make the text even less readable. // would make the text even less readable.
//Using Max() fixes badly positioned text if Extra Large fonts have been activated in the Windows display options //Using Max() fixes badly positioned text if Extra Large fonts have been activated in the Windows display options
TextPos.Y := Max(-5,(ClientSize.Y - TextSize.cy) div 2); TextPos.Y := Max(-5, (ClientSize.Y - TextSize.cy) div 2);
end end
else else
begin begin
@ -7248,7 +7266,11 @@ begin
if Layout = blGlyphLeft then if Layout = blGlyphLeft then
MinLeft := HeaderGlyphPos.X + HeaderGlyphSize.X + FSpacing; MinLeft := HeaderGlyphPos.X + HeaderGlyphSize.X + FSpacing;
if FCheckBox and (Owner.Header.MainColumn = Self.Index) then if FCheckBox and (Owner.Header.MainColumn = Self.Index) then
Dec(HeaderGlyphPos.X, 2 + 2 * Integer(toShowRoot in Owner.FHeader.Treeview.TreeOptions.FPaintOptions)); Dec(HeaderGlyphPos.X, 2 + 2 * Integer(toShowRoot in Owner.FHeader.Treeview.TreeOptions.FPaintOptions))
else
if Owner.Header.MainColumn <> Self.Index then
Dec(HeaderGlyphPos.X, 2);
// Finally transform header glyph to its actual position. // Finally transform header glyph to its actual position.
Inc(HeaderGlyphPos.X, Client.Left); Inc(HeaderGlyphPos.X, Client.Left);
Inc(HeaderGlyphPos.Y, Client.Top); Inc(HeaderGlyphPos.Y, Client.Top);
@ -11601,6 +11623,12 @@ begin
if HandleAllocated then if HandleAllocated then
DestroyWindowHandle; DestroyWindowHandle;
} }
// Release FDottedBrush in case WM_NCDESTROY hasn't been triggered.
if FDottedBrush <> 0 then
DeleteObject(FDottedBrush);
FDottedBrush := 0;
FOptions.Free; FOptions.Free;
FreeAndNil(FHeader); FreeAndNil(FHeader);
@ -11755,7 +11783,7 @@ begin
VAlign := MulDiv(Integer(Node.NodeHeight), Node.Align, 100); VAlign := MulDiv(Integer(Node.NodeHeight), Node.Align, 100);
end; end;
VButtonAlign := VAlign - FPlusBM.Height div 2; VButtonAlign := VAlign - FPlusBM.Height div 2 - (FPlusBM.Height and 1);
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -14632,6 +14660,17 @@ begin
end; end;
end; end;
//----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.SetWindowTheme(const Theme: String);
begin
FChangingTheme := True;
//lcl: todo
//UxTheme.SetWindowTheme(Handle, PAnsiChar(Theme), nil);
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.TileBackground(Source: TBitmap; Target: TCanvas; const Offset: TPoint; R: TRect); procedure TBaseVirtualTree.TileBackground(Source: TBitmap; Target: TCanvas; const Offset: TPoint; R: TRect);
@ -14644,7 +14683,6 @@ var
SourceX, SourceX,
SourceY, SourceY,
TargetX, TargetX,
DeltaY: Integer; DeltaY: Integer;
begin begin
@ -15463,6 +15501,7 @@ begin
KillTimer(Handle, EditTimer); KillTimer(Handle, EditTimer);
KillTimer(Handle, ScrollTimer); KillTimer(Handle, ScrollTimer);
KillTimer(Handle, SearchTimer); KillTimer(Handle, SearchTimer);
KillTimer(Handle, ThemeChangedTimer);
FSearchBuffer := ''; FSearchBuffer := '';
FLastSearchNode := nil; FLastSearchNode := nil;
@ -16898,8 +16937,13 @@ begin
DoStateChange([tsUseThemes]) DoStateChange([tsUseThemes])
else else
DoStateChange([], [tsUseThemes]); DoStateChange([], [tsUseThemes]);
RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_VALIDATE or RDW_FRAME);
end; // Updating the visuals here will not work correctly. Therefore we postpone
// the update by using a timer.
if not FChangingTheme then
SetTimer(Handle, ThemeChangedTimer, ThemeChangedTimerDelay, nil);
FChangingTheme := False;
end;
{$endif} {$endif}
{$endif ThemeSupport} {$endif ThemeSupport}
@ -16943,6 +16987,11 @@ begin
FSearchBuffer := ''; FSearchBuffer := '';
FLastSearchNode := nil; FLastSearchNode := nil;
end; end;
ThemeChangedTimer:
begin
KillTimer(Handle, ThemeChangedTimer);
RecreateWnd(Self);
end;
end; end;
end; end;
{$ifdef DEBUG_VTV}Logger.ExitMethod([lcMessages,lcTimer],'WMTimer');{$endif} {$ifdef DEBUG_VTV}Logger.ExitMethod([lcMessages,lcTimer],'WMTimer');{$endif}
@ -17703,17 +17752,19 @@ begin
{$ifdef DEBUG_VTV}Logger.Send([lcInfo],'Handle (CreateWnd)',Handle);{$endif} {$ifdef DEBUG_VTV}Logger.Send([lcInfo],'Handle (CreateWnd)',Handle);{$endif}
DoStateChange([], [tsWindowCreating]); DoStateChange([], [tsWindowCreating]);
{$ifdef ThemeSupport}
if StyleServices.Enabled and (toThemeAware in TreeOptions.PaintOptions) then if StyleServices.Enabled and (toThemeAware in TreeOptions.PaintOptions) then
begin begin
DoStateChange([tsUseThemes]); DoStateChange([tsUseThemes]);
//todo if (toUseExplorerTheme in FOptions.FPaintOptions) and IsWinVistaOrAbove then
//if (toUseExplorerTheme in FOptions.FPaintOptions) and IsWinVistaOrAbove then begin
// SetWindowTheme(Handle, 'explorer', nil); DoStateChange([tsUseExplorerTheme]);
SetWindowTheme('explorer');
end end
else else
{$endif ThemeSupport} DoStateChange([], [tsUseExplorerTheme]);
DoStateChange([], [tsUseThemes]); end
else
DoStateChange([], [tsUseThemes, tsUseExplorerTheme]);
// Because of the special recursion and update stopper when creating the window (or resizing it) // Because of the special recursion and update stopper when creating the window (or resizing it)
// we have to manually trigger the auto size calculation here. // we have to manually trigger the auto size calculation here.
@ -17776,8 +17827,9 @@ var
begin begin
ImageHit := HitInfo.HitPositions * [hiOnNormalIcon, hiOnStateIcon] <> []; ImageHit := HitInfo.HitPositions * [hiOnNormalIcon, hiOnStateIcon] <> [];
LabelHit := hiOnItemLabel in HitInfo.HitPositions; LabelHit := hiOnItemLabel in HitInfo.HitPositions;
ItemHit := ((hiOnItem in HitInfo.HitPositions) and ((toFullRowDrag in FOptions.FMiscOptions) or ItemHit := ((hiOnItem in HitInfo.HitPositions) and
(toFullRowSelect in FOptions.FSelectionOptions))); ((toFullRowDrag in FOptions.FMiscOptions) or (toFullRowSelect in FOptions.FSelectionOptions)));
// In report mode only direct hits of the node captions/images in the main column are accepted as hits. // In report mode only direct hits of the node captions/images in the main column are accepted as hits.
if (toReportMode in FOptions.FMiscOptions) and not (ItemHit or ((LabelHit or ImageHit) and if (toReportMode in FOptions.FMiscOptions) and not (ItemHit or ((LabelHit or ImageHit) and
(HitInfo.HitColumn = FHeader.MainColumn))) then (HitInfo.HitColumn = FHeader.MainColumn))) then
@ -17785,7 +17837,7 @@ begin
if Assigned(HitInfo.HitNode) then if Assigned(HitInfo.HitNode) then
begin begin
if ItemHit or LabelHit or ImageHit or not (toShowDropmark in FOptions.FPaintOptions) then if LabelHit or ImageHit or not (toShowDropmark in FOptions.FPaintOptions) then
Result := dmOnNode Result := dmOnNode
else else
if ((NodeRect.Top + NodeRect.Bottom) div 2) > P.Y then if ((NodeRect.Top + NodeRect.Bottom) div 2) > P.Y then
@ -19174,8 +19226,20 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.DoGetNodeExtraWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer;
// Returns the pixel width of extra space occupied by node contents (for example, static text).
begin
Result := 0;
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; function TBaseVirtualTree.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer;
// Returns the pixel width of a node.
begin begin
Result := 0; Result := 0;
end; end;
@ -20065,6 +20129,14 @@ procedure TBaseVirtualTree.DragAndDrop(AllowedEffects: LongWord;
begin begin
{$ifdef Windows} {$ifdef Windows}
//lcl
//todo
{
if IsWinVistaOrAbove then begin
SHDoDragDrop(Self.Handle, DataObject, nil, AllowedEffects, DragEffect); // supports drag hints on Windows Vista and later
end
else
}
ActiveX.DoDragDrop(DataObject, VTVDragManager as IDropSource, AllowedEffects, @DragEffect); ActiveX.DoDragDrop(DataObject, VTVDragManager as IDropSource, AllowedEffects, @DragEffect);
{$endif} {$endif}
end; end;
@ -21359,8 +21431,9 @@ begin
DoStateChange([], [tsEditPending]); DoStateChange([], [tsEditPending]);
end; end;
if not (tsEditing in FStates) or DoEndEdit then if (tsEditing in FStates) then
begin DoEndEdit;
// Focus change. Don't use the SetFocus method as this does not work for MDI windows. // Focus change. Don't use the SetFocus method as this does not work for MDI windows.
if not Focused and CanFocus then if not Focused and CanFocus then
begin begin
@ -21611,7 +21684,6 @@ begin
if AutoDrag and IsAnyHit and (FStates * [tsLeftButtonDown, tsRightButtonDown, tsMiddleButtonDown] <> []) then if AutoDrag and IsAnyHit and (FStates * [tsLeftButtonDown, tsRightButtonDown, tsMiddleButtonDown] <> []) then
BeginDrag(False); BeginDrag(False);
end; end;
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -23157,7 +23229,7 @@ begin
for I := 0 to IndentSize - 1 do for I := 0 to IndentSize - 1 do
begin begin
DoBeforeDrawLineImage(PaintInfo.Node, I + Ord(not (toShowRoot in TreeOptions.PaintOptions)), XPos); DoBeforeDrawLineImage(PaintInfo.Node, I + Ord(not (toShowRoot in TreeOptions.PaintOptions)), XPos);
DrawLineImage(PaintInfo, XPos, CellRect.Top, NodeHeight[Node] - 1, VAlignment, NewStyles[I], DrawLineImage(PaintInfo, XPos, CellRect.Top, NodeHeight[Node] - 1, VAlignment - 1, NewStyles[I],
BidiMode <> bdLeftToRight); BidiMode <> bdLeftToRight);
Inc(XPos, Offset); Inc(XPos, Offset);
end; end;
@ -23170,7 +23242,7 @@ begin
for I := 0 to IndentSize - 1 do for I := 0 to IndentSize - 1 do
begin begin
DoBeforeDrawLineImage(PaintInfo.Node, I + Ord(not (toShowRoot in TreeOptions.PaintOptions)), XPos); DoBeforeDrawLineImage(PaintInfo.Node, I + Ord(not (toShowRoot in TreeOptions.PaintOptions)), XPos);
DrawLineImage(PaintInfo, XPos, CellRect.Top, NodeHeight[Node], VAlignment, LineImage[I], DrawLineImage(PaintInfo, XPos, CellRect.Top, NodeHeight[Node], VAlignment - 1, LineImage[I],
BidiMode <> bdLeftToRight); BidiMode <> bdLeftToRight);
Inc(XPos, Offset); Inc(XPos, Offset);
end; end;
@ -26631,7 +26703,7 @@ begin
else else
StateImageOffset := 0; StateImageOffset := 0;
if Assigned(FCheckImages) then if Assigned(FCheckImages) then
CheckOffset := FCheckImages.Height + 2 CheckOffset := FCheckImages.Width + 2
else else
CheckOffset := 0; CheckOffset := 0;
@ -26680,6 +26752,7 @@ begin
Inc(TextLeft, StateImageOffset); Inc(TextLeft, StateImageOffset);
CurrentWidth := DoGetNodeWidth(Run, Column); CurrentWidth := DoGetNodeWidth(Run, Column);
Inc(CurrentWidth, DoGetNodeExtraWidth(Run, Column));
Inc(CurrentWidth, DoGetCellContentMargin(Run, Column).X); Inc(CurrentWidth, DoGetCellContentMargin(Run, Column).X);
if Result < (TextLeft + CurrentWidth) then if Result < (TextLeft + CurrentWidth) then
@ -28978,6 +29051,10 @@ var
SelectLevel: Integer; // > 0 if current node is selected or child/grandchild etc. of a selected node SelectLevel: Integer; // > 0 if current node is selected or child/grandchild etc. of a selected node
FirstColumn: TColumnIndex; // index of first column which is at least partially visible in the given window FirstColumn: TColumnIndex; // index of first column which is at least partially visible in the given window
MaxRight,
ColLeft,
ColRight: Integer;
SavedTargetDC: Integer; SavedTargetDC: Integer;
PaintWidth: Integer; PaintWidth: Integer;
CurrentNodeHeight: Integer; CurrentNodeHeight: Integer;
@ -29046,7 +29123,7 @@ begin
// Prepare the current selection rectangle once. The corner points are absolute tree coordinates. // Prepare the current selection rectangle once. The corner points are absolute tree coordinates.
SelectionRect := OrderRect(FNewSelRect); SelectionRect := OrderRect(FNewSelRect);
{$ifdef DEBUG_VTV}Logger.Send([lcPaintDetails, lcSelection],'SelectionRect', SelectionRect);{$endif} {$ifdef DEBUG_VTV}Logger.Send([lcPaintDetails, lcSelection],'SelectionRect', SelectionRect);{$endif}
DrawSelectionRect := IsMouseSelecting and not IsRectEmpty(SelectionRect); DrawSelectionRect := IsMouseSelecting and not IsRectEmpty(SelectionRect) and (GetKeyState(VK_LBUTTON) < 0);
{$ifdef DEBUG_VTV}Logger.Watch([lcPaintDetails],'DrawSelectionRect',DrawSelectionRect);{$endif} {$ifdef DEBUG_VTV}Logger.Watch([lcPaintDetails],'DrawSelectionRect',DrawSelectionRect);{$endif}
// R represents an entire node (all columns), but is a bit unprecise when it comes to // R represents an entire node (all columns), but is a bit unprecise when it comes to
// trees without any column defined, because FRangeX only represents the maximum width of all // trees without any column defined, because FRangeX only represents the maximum width of all
@ -29098,7 +29175,7 @@ begin
if Assigned(PaintInfo.Node) then if Assigned(PaintInfo.Node) then
begin begin
ButtonX := Round((Integer(FIndent) - FPlusBM.Width) / 2); ButtonX := Round((Integer(FIndent) - FPlusBM.Width) / 2) + 1;
// ----- main node paint loop // ----- main node paint loop
while Assigned(PaintInfo.Node) do while Assigned(PaintInfo.Node) do
@ -29111,7 +29188,7 @@ begin
SelectLevel := DetermineLineImageAndSelectLevel(PaintInfo.Node, LineImage); SelectLevel := DetermineLineImageAndSelectLevel(PaintInfo.Node, LineImage);
IndentSize := Length(LineImage); IndentSize := Length(LineImage);
if not (toFixedIndent in FOptions.FPaintOptions) then if not (toFixedIndent in FOptions.FPaintOptions) then
ButtonX := (IndentSize - 1) * FIndent + Round((FIndent - FPlusBM.Width) / 2); ButtonX := (IndentSize - 1) * Integer(FIndent) + Round((Integer(FIndent) - FPlusBM.Width) / 2) + 1;
// Initialize node if not already done. // Initialize node if not already done.
if not (vsInitialized in PaintInfo.Node.States) then if not (vsInitialized in PaintInfo.Node.States) then
@ -29540,9 +29617,23 @@ begin
R.Right := R.Left + Items[FirstColumn].FWidth; R.Right := R.Left + Items[FirstColumn].FWidth;
end; end;
// Initialize MaxRight.
MaxRight := Target.X - 1;
PaintInfo.Canvas.Font.Color := FColors.GridLineColor; PaintInfo.Canvas.Font.Color := FColors.GridLineColor;
while (FirstColumn <> InvalidColumn) and (R.Left < TargetRect.Right + Target.X) do while (FirstColumn <> InvalidColumn) and (MaxRight < TargetRect.Right + Target.X) do
begin begin
// Determine left and right coordinate of the current column
ColLeft := Items[FirstColumn].Left;
ColRight := (ColLeft + Items[FirstColumn].FWidth);
// Check wether this column needs to be painted at all.
if (ColRight >= MaxRight) then
begin
R.Left := MaxRight; // Continue where we left off
R.Right := ColRight; // Paint to the right of the column
MaxRight := ColRight; // And record were to start the next column.
if (poGridLines in PaintOptions) and if (poGridLines in PaintOptions) and
(toFullVertGridLines in FOptions.FPaintOptions) and (toFullVertGridLines in FOptions.FPaintOptions) and
(toShowVertGridLines in FOptions.FPaintOptions) and (toShowVertGridLines in FOptions.FPaintOptions) and
@ -29558,12 +29649,8 @@ begin
PaintInfo.Canvas.Brush.Color := Color; PaintInfo.Canvas.Brush.Color := Color;
PaintInfo.Canvas.FillRect(R); PaintInfo.Canvas.FillRect(R);
FirstColumn := GetNextVisibleColumn(FirstColumn);
if FirstColumn <> InvalidColumn then
begin
R.Left := Items[FirstColumn].Left;
R.Right := R.Left + Items[FirstColumn].FWidth;
end; end;
FirstColumn := GetNextVisibleColumn(FirstColumn);
end; end;
// Erase also the part of the tree not covert by a column. // Erase also the part of the tree not covert by a column.
@ -31854,6 +31941,21 @@ begin
Result := FOptions as TCustomStringTreeOptions; Result := FOptions as TCustomStringTreeOptions;
end; end;
//----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.GetStaticText(Node: PVirtualNode; Column: TColumnIndex): String;
begin
Assert(Assigned(Node), 'Node must not be nil.');
if not (vsInitialized in Node.States) then
InitNode(Node);
Result := '';
DoGetText(Node, Column, ttStatic, Result);
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.GetText(Node: PVirtualNode; Column: TColumnIndex): String; function TCustomVirtualStringTree.GetText(Node: PVirtualNode; Column: TColumnIndex): String;
@ -31927,6 +32029,7 @@ var
R: TRect; R: TRect;
DrawFormat: Cardinal; DrawFormat: Cardinal;
Size: TSize; Size: TSize;
Height: Integer;
begin begin
{$ifdef DEBUG_VTV}Logger.EnterMethod([lcPaintDetails],'PaintNormalText') ;{$endif} {$ifdef DEBUG_VTV}Logger.EnterMethod([lcPaintDetails],'PaintNormalText') ;{$endif}
@ -31936,6 +32039,7 @@ begin
R := ContentRect; R := ContentRect;
//todo_lcl See how TextStyle should be set //todo_lcl See how TextStyle should be set
//Canvas.TextFlags := 0; //Canvas.TextFlags := 0;
InflateRect(R, -FTextMargin, 0);
// Multiline nodes don't need special font handling or text manipulation. // Multiline nodes don't need special font handling or text manipulation.
// Note: multiline support requires the Unicode version of DrawText, which is able to do word breaking. // Note: multiline support requires the Unicode version of DrawText, which is able to do word breaking.
@ -31944,7 +32048,7 @@ begin
// for 9x/Me. // for 9x/Me.
if vsMultiline in Node.States then if vsMultiline in Node.States then
begin begin
InflateRect(R, -FTextMargin, 0); Height := ComputeNodeHeight(Canvas, Node, Column);
DoPaintText(Node, Canvas, Column, ttNormal); DoPaintText(Node, Canvas, Column, ttNormal);
// Disabled node color overrides all other variants. // Disabled node color overrides all other variants.
if (vsDisabled in Node.States) or not Enabled then if (vsDisabled in Node.States) or not Enabled then
@ -31955,10 +32059,13 @@ begin
DrawFormat := DT_NOPREFIX or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or AlignmentToDrawFlag[Alignment]; DrawFormat := DT_NOPREFIX or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or AlignmentToDrawFlag[Alignment];
if BidiMode <> bdLeftToRight then if BidiMode <> bdLeftToRight then
DrawFormat := DrawFormat or DT_RTLREADING; DrawFormat := DrawFormat or DT_RTLREADING;
// Center the text vertically if it fits entirely into the content rect.
if R.Bottom - R.Top > Height then
InflateRect(R, 0, (Height - R.Bottom - R.Top) div 2);
end end
else else
begin begin
InflateRect(R, -FTextMargin, 0);
FFontChanged := False; FFontChanged := False;
TripleWidth := FEllipsisWidth; TripleWidth := FEllipsisWidth;
DoPaintText(Node, Canvas, Column, ttNormal); DoPaintText(Node, Canvas, Column, ttNormal);
@ -32184,7 +32291,25 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.CalculateTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; function TCustomVirtualStringTree.CalculateStaticTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
const Text: String): Integer;
begin
Result := 0;
if (Length(Text) > 0) and (Alignment <> taCenter) and not
(vsMultiline in Node.States) and (toShowStaticText in TreeOptions.FStringOptions) then
begin
DoPaintText(Node, Canvas, Column, ttStatic);
Inc(Result, DoTextMeasuring(Canvas, Node, Column, Text).cx);
Inc(Result, FTextMargin);
end;
end;
//----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.CalculateTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
const Text: String): Integer;
// Determines the width of the given text. // Determines the width of the given text.
@ -32273,6 +32398,17 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.DoGetNodeExtraWidth(Node: PVirtualNode; Column: TColumnIndex;
Canvas: TCanvas = nil): Integer;
begin
if Canvas = nil then
Canvas := Self.Canvas;
Result := CalculateStaticTextWidth(Canvas, Node, Column, StaticText[Node, Column]);
end;
//----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; function TCustomVirtualStringTree.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer;
// Returns the text width of the given node in pixels. // Returns the text width of the given node in pixels.