* Synchronize with main VTV repository up to svn rev 622

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3414 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
blikblum
2014-08-03 02:17:08 +00:00
parent e35ca23229
commit 1e3a8bce44

View File

@ -313,7 +313,8 @@ type
coAllowFocus, // Column can be focused. coAllowFocus, // Column can be focused.
coDisableAnimatedResize, // Column resizing is not animated. coDisableAnimatedResize, // Column resizing is not animated.
coWrapCaption, // Caption could be wrapped across several header lines to fit columns width. coWrapCaption, // Caption could be wrapped across several header lines to fit columns width.
coUseCaptionAlignment // Column's caption has its own aligment. coUseCaptionAlignment, // Column's caption has its own aligment.
coEditable // Column can be edited
); );
TVTColumnOptions = set of TVTColumnOption; TVTColumnOptions = set of TVTColumnOption;
@ -510,8 +511,12 @@ type
toRightClickSelect, // Allow selection, dragging etc. with the right mouse button. toRightClickSelect, // Allow selection, dragging etc. with the right mouse button.
toSiblingSelectConstraint, // Constrain selection to nodes with same parent. toSiblingSelectConstraint, // Constrain selection to nodes with same parent.
toCenterScrollIntoView, // Center nodes vertically in the client area when scrolling into view. toCenterScrollIntoView, // Center nodes vertically in the client area when scrolling into view.
toSimpleDrawSelection // Simplifies draw selection, so a node's caption does not need to intersect with the toSimpleDrawSelection, // Simplifies draw selection, so a node's caption does not need to intersect with the
// selection rectangle. // selection rectangle.
toAlwaysSelectNode, // If this flag is set to true, the tree view tries to always have a node selected.
// This behavior is closer to the Windows TreeView and useful in Windows Explorer style applications.
toRestoreSelection // Set to true if upon refill the previously selected nodes should be selected again.
// The nodes will be identified by its caption only.
); );
TVTSelectionOptions = set of TVTSelectionOption; TVTSelectionOptions = set of TVTSelectionOption;
@ -564,7 +569,7 @@ const
DefaultMiscOptions = [toAcceptOLEDrop, toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning, DefaultMiscOptions = [toAcceptOLEDrop, toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning,
toEditOnClick]; toEditOnClick];
DefaultColumnOptions = [coAllowClick, coDraggable, coEnabled, coParentColor, coParentBidiMode, coResizable, DefaultColumnOptions = [coAllowClick, coDraggable, coEnabled, coParentColor, coParentBidiMode, coResizable,
coShowDropmark, coVisible, coAllowFocus]; coShowDropmark, coVisible, coAllowFocus, coEditable];
type type
TBaseVirtualTree = class; TBaseVirtualTree = class;
@ -1932,12 +1937,9 @@ type
FScrollBarVertical: Boolean; FScrollBarVertical: Boolean;
FScrollBarVisible: Boolean; FScrollBarVisible: Boolean;
FScrollBarEnabled: Boolean; FScrollBarEnabled: Boolean;
procedure WMNCHitTest(var Msg: TWMNCHitTest); procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
message WM_NCHITTEST; procedure WMEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND;
procedure WMEraseBkgnd(var Msg: TMessage); procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;
message WM_ERASEBKGND;
procedure WMPaint(var Msg: TWMPaint);
message WM_PAINT;
strict protected strict protected
procedure CreateParams(var Params: TCreateParams); procedure CreateParams(var Params: TCreateParams);
override; override;
@ -1971,36 +1973,23 @@ type
FVertScrollBarUpButtonState: TThemedScrollBar; FVertScrollBarUpButtonState: TThemedScrollBar;
FVertScrollBarWindow: TVclStyleScrollBarWindow; FVertScrollBarWindow: TVclStyleScrollBarWindow;
procedure WMKeyDown(var Msg: TMessage); procedure WMKeyDown(var Msg: TMessage); message WM_KEYDOWN;
message WM_KEYDOWN; procedure WMKeyUp(var Msg: TMessage); message WM_KEYUP;
procedure WMKeyUp(var Msg: TMessage); procedure WMLButtonDown(var Msg: TWMMouse); message WM_LBUTTONDOWN;
message WM_KEYUP; procedure WMLButtonUp(var Msg: TWMMouse); message WM_LBUTTONUP;
procedure WMLButtonDown(var Msg: TWMMouse); procedure WMNCLButtonDown(var Msg: TWMMouse); message WM_NCLBUTTONDOWN;
message WM_LBUTTONDOWN; procedure WMNCMouseMove(var Msg: TWMMouse); message WM_NCMOUSEMOVE;
procedure WMLButtonUp(var Msg: TWMMouse); procedure WMNCLButtonUp(var Msg: TWMMouse); message WM_NCLBUTTONUP;
message WM_LBUTTONUP; procedure WMNCPaint(var Msg: TMessage); message WM_NCPAINT;
procedure WMNCLButtonDown(var Msg: TWMMouse); procedure WMMouseMove(var Msg: TWMMouse); message WM_MOUSEMOVE;
message WM_NCLBUTTONDOWN; procedure WMMouseWheel(var Msg: TMessage); message WM_MOUSEWHEEL;
procedure WMNCMouseMove(var Msg: TWMMouse); procedure WMVScroll(var Msg: TMessage); message WM_VSCROLL;
message WM_NCMOUSEMOVE; procedure WMHScroll(var Msg: TMessage); message WM_HSCROLL;
procedure WMNCLButtonUp(var Msg: TWMMouse); procedure WMCaptureChanged(var Msg: TMessage); message WM_CAPTURECHANGED;
message WM_NCLBUTTONUP; procedure WMNCLButtonDblClk(var Msg: TWMMouse); message WM_NCLBUTTONDBLCLK;
procedure WMNCPaint(var Msg: TMessage); procedure WMSize(var Msg: TMessage); message WM_SIZE;
message WM_NCPAINT; procedure WMMove(var Msg: TMessage); message WM_MOVE;
procedure WMMouseMove(var Msg: TWMMouse); procedure WMPosChanged(var Msg: TMessage); message WM_WINDOWPOSCHANGED;
message WM_MOUSEMOVE;
procedure WMMouseWheel(var Msg: TMessage);
message WM_MOUSEWHEEL;
procedure WMVScroll(var Msg: TMessage);
message WM_VSCROLL;
procedure WMHScroll(var Msg: TMessage);
message WM_HSCROLL;
procedure WMCaptureChanged(var Msg: TMessage);
message WM_CAPTURECHANGED;
procedure WMNCLButtonDblClk(var Msg: TWMMouse);
message WM_NCLBUTTONDBLCLK;
procedure WMSize(var Msg: TMessage);
message WM_SIZE;
protected protected
procedure CalcScrollBarsRect; virtual; procedure CalcScrollBarsRect; virtual;
procedure DrawHorzScrollBar(DC: HDC); virtual; procedure DrawHorzScrollBar(DC: HDC); virtual;
@ -2166,6 +2155,7 @@ type
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 FChangingTheme: Boolean; // Used to indicate that a theme change is goi ng on
fNextNodeToSelect: PVirtualNode; // Next tree node that we would like to select if the current one gets deleted or looses selection for other reasons.
{$ifdef EnableAccessible} {$ifdef EnableAccessible}
// MSAA support // MSAA support
@ -2522,6 +2512,7 @@ type
function GetRangeX: Cardinal; function GetRangeX: Cardinal;
function GetDoubleBuffered: Boolean; function GetDoubleBuffered: Boolean;
procedure SetDoubleBuffered(const Value: Boolean); procedure SetDoubleBuffered(const Value: Boolean);
procedure ChangeTreeStatesAsync(EnterStates, LeaveStates: TChangeStates);
protected protected
procedure AddToSelection(Node: PVirtualNode); overload; virtual; procedure AddToSelection(Node: PVirtualNode); overload; virtual;
procedure AddToSelection(const NewItems: TNodeArray; NewLength: Integer; ForceInsert: Boolean = False); overload; virtual; procedure AddToSelection(const NewItems: TNodeArray; NewLength: Integer; ForceInsert: Boolean = False); overload; virtual;
@ -2644,7 +2635,7 @@ type
procedure DoHeaderMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure DoHeaderMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
procedure DoHotChange(Old, New: PVirtualNode); virtual; procedure DoHotChange(Old, New: PVirtualNode); virtual;
function DoIncrementalSearch(Node: PVirtualNode; const Text: String): Integer; virtual; function DoIncrementalSearch(Node: PVirtualNode; const Text: String): Integer; virtual;
procedure DoInitChildren(Node: PVirtualNode; var ChildCount: Cardinal); virtual; function DoInitChildren(Node: PVirtualNode; var ChildCount: Cardinal): Boolean; virtual;
procedure DoInitNode(Parent, Node: PVirtualNode; var InitStates: TVirtualNodeInitStates); virtual; procedure DoInitNode(Parent, Node: PVirtualNode; var InitStates: TVirtualNodeInitStates); virtual;
function DoKeyAction(var CharCode: Word; var Shift: TShiftState): Boolean; virtual; function DoKeyAction(var CharCode: Word; var Shift: TShiftState): Boolean; virtual;
procedure DoLoadUserData(Node: PVirtualNode; Stream: TStream); virtual; procedure DoLoadUserData(Node: PVirtualNode; Stream: TStream); virtual;
@ -2840,6 +2831,7 @@ type
property LineMode: TVTLineMode read FLineMode write SetLineMode default lmNormal; property LineMode: TVTLineMode read FLineMode write SetLineMode default lmNormal;
property LineStyle: TVTLineStyle read FLineStyle write SetLineStyle default lsDotted; property LineStyle: TVTLineStyle read FLineStyle write SetLineStyle default lsDotted;
property Margin: Integer read FMargin write SetMargin default 4; property Margin: Integer read FMargin write SetMargin default 4;
property NextNodeToSelect: PVirtualNode read fNextNodeToSelect; // Next tree node that we would like to select if the current one gets deleted
property NodeAlignment: TVTNodeAlignment read FNodeAlignment write SetNodeAlignment default naProportional; property NodeAlignment: TVTNodeAlignment read FNodeAlignment write SetNodeAlignment default naProportional;
property NodeDataSize: Integer read FNodeDataSize write SetNodeDataSize default -1; property NodeDataSize: Integer read FNodeDataSize write SetNodeDataSize default -1;
property OperationCanceled: Boolean read GetOperationCanceled; property OperationCanceled: Boolean read GetOperationCanceled;
@ -3020,6 +3012,7 @@ type
function EndEditNode: Boolean; function EndEditNode: Boolean;
procedure EndSynch; procedure EndSynch;
procedure EndUpdate; virtual; procedure EndUpdate; virtual;
procedure EnsureNodeSelected(); virtual;
function ExecuteAction(Action: TBasicAction): Boolean; override; function ExecuteAction(Action: TBasicAction): Boolean; override;
procedure FinishCutOrCopy; procedure FinishCutOrCopy;
procedure FlushClipboard; procedure FlushClipboard;
@ -3035,6 +3028,7 @@ type
function GetFirst(ConsiderChildrenAbove: Boolean = False): PVirtualNode; function GetFirst(ConsiderChildrenAbove: Boolean = False): PVirtualNode;
function GetFirstChecked(State: TCheckState = csCheckedNormal; ConsiderChildrenAbove: Boolean = False): PVirtualNode; function GetFirstChecked(State: TCheckState = csCheckedNormal; ConsiderChildrenAbove: Boolean = False): PVirtualNode;
function GetFirstChild(Node: PVirtualNode): PVirtualNode; function GetFirstChild(Node: PVirtualNode): PVirtualNode;
function GetFirstChildNoInit(Node: PVirtualNode): PVirtualNode;
function GetFirstCutCopy(ConsiderChildrenAbove: Boolean = False): PVirtualNode; function GetFirstCutCopy(ConsiderChildrenAbove: Boolean = False): PVirtualNode;
function GetFirstInitialized(ConsiderChildrenAbove: Boolean = False): PVirtualNode; function GetFirstInitialized(ConsiderChildrenAbove: Boolean = False): PVirtualNode;
function GetFirstLeaf: PVirtualNode; function GetFirstLeaf: PVirtualNode;
@ -3417,6 +3411,7 @@ type
procedure CMFontChanged(var Msg: TLMessage); message CM_FONTCHANGED; procedure CMFontChanged(var Msg: TLMessage); message CM_FONTCHANGED;
procedure GetDataFromGrid(const AStrings : TStringList; const IncludeHeading : Boolean=True); procedure GetDataFromGrid(const AStrings : TStringList; const IncludeHeading : Boolean=True);
protected protected
fPreviouslySelected: TStringList;
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 CalculateStaticTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; virtual;
@ -3460,6 +3455,8 @@ type
property OnDrawText: TVTDrawTextEvent read FOnDrawText write FOnDrawText; property OnDrawText: TVTDrawTextEvent read FOnDrawText write FOnDrawText;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy(); override;
function AddChild(Parent: PVirtualNode; UserData: Pointer = nil): PVirtualNode; override;
function ComputeNodeHeight(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; S: String = ''): Integer; virtual; function ComputeNodeHeight(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; S: String = ''): Integer; virtual;
function ContentToClipboard(Format: Word; Source: TVSTTextSourceType): HGLOBAL; function ContentToClipboard(Format: Word; Source: TVSTTextSourceType): HGLOBAL;
procedure ContentToCustom(Source: TVSTTextSourceType); procedure ContentToCustom(Source: TVSTTextSourceType);
@ -3479,7 +3476,7 @@ type
function InvalidateNode(Node: PVirtualNode): TRect; override; function InvalidateNode(Node: PVirtualNode): TRect; override;
function Path(Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; Delimiter: Char): String; function Path(Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; Delimiter: Char): String;
procedure ReinitNode(Node: PVirtualNode; Recursive: Boolean); override; procedure ReinitNode(Node: PVirtualNode; Recursive: Boolean); override;
procedure Clear(); override;
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 StaticText[Node: PVirtualNode; Column: TColumnIndex]: String read GetStaticText;
@ -4229,7 +4226,6 @@ type
FRefCount: Cardinal; FRefCount: Cardinal;
protected protected
procedure CancelValidation(Tree: TBaseVirtualTree); procedure CancelValidation(Tree: TBaseVirtualTree);
procedure ChangeTreeStates(EnterStates, LeaveStates: TChangeStates);
procedure Execute; override; procedure Execute; override;
public public
constructor Create(CreateSuspended: Boolean); constructor Create(CreateSuspended: Boolean);
@ -5366,24 +5362,17 @@ begin
begin begin
//todo: see if is correct / will work //todo: see if is correct / will work
Application.ProcessMessages; Application.ProcessMessages;
continue;
//TranslateMessage(Msg); //TranslateMessage(Msg);
//DispatchMessage(Msg); //DispatchMessage(Msg);
end; end;
CheckSynchronize();// If this call makes problems consider doing it only when needed by counting Synchronize() calls in a threadsafe counter if (toVariableNodeHeight in Tree.TreeOptions.MiscOptions) then
CheckSynchronize(); // We need to call CheckSynchronize here because we are using TThread.Synchronize in TBaseVirtualTree.MeasureItemHeight()
end; end;
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TWorkerThread.ChangeTreeStates(EnterStates, LeaveStates: TChangeStates);
begin
if Assigned(FCurrentTree) and (FCurrentTree.HandleAllocated) then
SendMessage(FCurrentTree.Handle, WM_CHANGESTATE, Byte(EnterStates), Byte(LeaveStates));
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TWorkerThread.Execute; procedure TWorkerThread.Execute;
// Does some background tasks, like validating tree caches. // Does some background tasks, like validating tree caches.
@ -5420,16 +5409,14 @@ begin
if Assigned(FCurrentTree) then if Assigned(FCurrentTree) then
begin begin
try try
ChangeTreeStates([csValidating], [csUseCache]); FCurrentTree.ChangeTreeStatesAsync([csValidating], [csUseCache, csValidationNeeded]);
EnterStates := []; EnterStates := [];
if not (tsStopValidation in FCurrentTree.FStates) and FCurrentTree.DoValidateCache then if not (tsStopValidation in FCurrentTree.FStates) and FCurrentTree.DoValidateCache then
EnterStates := [csUseCache]; EnterStates := [csUseCache];
finally finally
LeaveStates := [csValidating, csStopValidation]; LeaveStates := [csValidating, csStopValidation];
if csUseCache in EnterStates then FCurrentTree.ChangeTreeStatesAsync(EnterStates, LeaveStates);
Include(LeaveStates, csValidationNeeded);
ChangeTreeStates(EnterStates, LeaveStates);
Synchronize(FCurrentTree.UpdateEditBounds); Synchronize(FCurrentTree.UpdateEditBounds);
FCurrentTree := nil; FCurrentTree := nil;
end; end;
@ -13519,7 +13506,7 @@ begin
WasValidating := (tsValidating in FStates); WasValidating := (tsValidating in FStates);
WorkerThread.RemoveTree(Self); WorkerThread.RemoveTree(Self);
if WasValidating then if WasValidating then
DoStateChange([tsValidationNeeded]); InvalidateCache();
end; end;
{$endif} {$endif}
end; end;
@ -14640,10 +14627,10 @@ begin
// If an edit operation is currently active then update the editors boundaries as well. // If an edit operation is currently active then update the editors boundaries as well.
UpdateEditBounds; UpdateEditBounds;
InvalidateCache;
// Stay away from touching the node cache while it is being validated. // Stay away from touching the node cache while it is being validated.
if not (tsValidating in FStates) and FullyVisible[Node] and not IsEffectivelyFiltered[Node] then if not (tsValidating in FStates) and FullyVisible[Node] and not IsEffectivelyFiltered[Node] then
begin begin
InvalidateCache;
if (FUpdateCount = 0) and ([tsPainting, tsSizing] * FStates = []) then if (FUpdateCount = 0) and ([tsPainting, tsSizing] * FStates = []) then
begin begin
ValidateCache; ValidateCache;
@ -17906,6 +17893,12 @@ begin
end; end;
end; end;
procedure TBaseVirtualTree.ChangeTreeStatesAsync(EnterStates, LeaveStates: TChangeStates);
begin
if (Self.HandleAllocated) then
SendMessage(Self.Handle, WM_CHANGESTATE, Byte(EnterStates), Byte(LeaveStates));
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.CheckParentCheckState(Node: PVirtualNode; NewCheckState: TCheckState): Boolean; function TBaseVirtualTree.CheckParentCheckState(Node: PVirtualNode; NewCheckState: TCheckState): Boolean;
@ -18162,6 +18155,7 @@ begin
{$ifdef Windows} {$ifdef Windows}
// Register tree as OLE drop target. // Register tree as OLE drop target.
if not (csDesigning in ComponentState) and (toAcceptOLEDrop in FOptions.FMiscOptions) then if not (csDesigning in ComponentState) and (toAcceptOLEDrop in FOptions.FMiscOptions) then
if not (csLoading in ComponentState) then // will be done in Loaded after all inherited settings are loaded from the DFMs
RegisterDragDrop(Handle, VTVDragManager as IDropTarget); RegisterDragDrop(Handle, VTVDragManager as IDropTarget);
{$endif} {$endif}
@ -19021,13 +19015,31 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.DoCollapsed(Node: PVirtualNode); procedure TBaseVirtualTree.DoCollapsed(Node: PVirtualNode);
var
lFirstSelected: PVirtualNode;
lParent: PVirtualNode;
begin begin
if Assigned(FOnCollapsed) then if Assigned(FOnCollapsed) then
FOnCollapsed(Self, Node); FOnCollapsed(Self, Node);
{$ifdef EnableAccessible} {$ifdef EnableAccessible}
if Assigned(FAccessibleItem) then
NotifyWinEvent(EVENT_OBJECT_STATECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF); NotifyWinEvent(EVENT_OBJECT_STATECHANGE, Handle, OBJID_CLIENT, CHILDID_SELF);
{$endif} {$endif}
if (toAlwaysSelectNode in TreeOptions.SelectionOptions) then begin
// Select the next visible parent if the currently selected node gets invisible due to a collapse
// This makes the VT behave more like the Win32 custom TreeView control
// This makes only sense no no multi selection is allowed and if there is a selected node at all
lFirstSelected := GetFirstSelected();
if Assigned(lFirstSelected) and not FullyVisible[lFirstSelected] then begin
lParent := GetVisibleParent(lFirstSelected);
Selected[lParent] := True;
Selected[lFirstSelected] := False;
end;//if
//if there is (still) no selected node, then use fNextNodeToSelect to select one
if SelectedCount = 0 then
EnsureNodeSelected();
end;//if
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -19381,6 +19393,7 @@ end;
procedure TBaseVirtualTree.DoEnter(); procedure TBaseVirtualTree.DoEnter();
begin begin
inherited; inherited;
EnsureNodeSelected();
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -19482,6 +19495,7 @@ end;
procedure TBaseVirtualTree.DoFreeNode(Node: PVirtualNode); procedure TBaseVirtualTree.DoFreeNode(Node: PVirtualNode);
begin begin
// Prevent invalid references
if Node = FLastChangedNode then if Node = FLastChangedNode then
FLastChangedNode := nil; FLastChangedNode := nil;
if Node = FCurrentHotNode then if Node = FCurrentHotNode then
@ -19490,9 +19504,31 @@ begin
FDropTargetNode := nil; FDropTargetNode := nil;
if Node = FLastStructureChangeNode then if Node = FLastStructureChangeNode then
FLastStructureChangeNode := nil; FLastStructureChangeNode := nil;
if Node=fNextNodeToSelect then
fNextNodeToSelect := nil;
if Self.UpdateCount = 0 then begin
// Omit this stuff if the control is in a BeginUpdate/EndUpdate bracket to increase performance
// We now try
// Make sure that CurrentNode does not point to an invalid node
if (toAlwaysSelectNode in TreeOptions.SelectionOptions) and (Node = GetFirstSelected()) then begin
if Assigned(fNextNodeToSelect) then
// Select a new node if the currently selected node gets freed
Selected[fNextNodeToSelect] := True
else begin
fNextNodeToSelect := Self.NodeParent[GetFirstSelected()];
if Assigned(fNextNodeToSelect) then
Selected[fNextNodeToSelect] := True
end;//else
end;//if
end;
// fire event
if Assigned(FOnFreeNode) and ([vsInitialized, vsOnFreeNodeCallRequired] * Node.States <> []) then if Assigned(FOnFreeNode) and ([vsInitialized, vsOnFreeNodeCallRequired] * Node.States <> []) then
FOnFreeNode(Self, Node); FOnFreeNode(Self, Node);
FreeMem(Node); FreeMem(Node);
if Self.UpdateCount = 0 then
EnsureNodeSelected();
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -19786,11 +19822,15 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.DoInitChildren(Node: PVirtualNode; var ChildCount: Cardinal); function TBaseVirtualTree.DoInitChildren(Node: PVirtualNode; var ChildCount: Cardinal): Boolean;
/// The function calls the OnInitChildren and returns True if the event was called; it returns False if the caller can expect that no changes have been made to ChildCount
begin begin
if Assigned(FOnInitChildren) then if Assigned(FOnInitChildren) then begin
FOnInitChildren(Self, Node, ChildCount); FOnInitChildren(Self, Node, ChildCount);
Result := True;
end
else
Result := False;
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -21008,6 +21048,18 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.EnsureNodeSelected;
begin
if (toAlwaysSelectNode in TreeOptions.SelectionOptions) and (GetFirstSelected() = nil) and not SelectionLocked then begin
if Assigned(fNextNodeToSelect) then
Selected[fNextNodeToSelect] := True
else if Self.Focused then
Selected[GetFirstVisible] := True;
end;//if
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.FindNodeInSelection(P: PVirtualNode; var Index: Integer; LowBound, function TBaseVirtualTree.FindNodeInSelection(P: PVirtualNode; var Index: Integer; LowBound,
HighBound: Integer): Boolean; HighBound: Integer): Boolean;
@ -22199,7 +22251,8 @@ begin
begin begin
// Is the mouse still over the same node? // Is the mouse still over the same node?
if (HitInfo.HitNode = FFocusedNode) and (hiOnItem in HitInfo.HitPositions) and if (HitInfo.HitNode = FFocusedNode) and (hiOnItem in HitInfo.HitPositions) and
(toEditOnClick in FOptions.FMiscOptions) and CanEdit(FFocusedNode, HitInfo.HitColumn) then (toEditOnClick in FOptions.FMiscOptions) and (FFocusedColumn = HitInfo.HitColumn) and
CanEdit(FFocusedNode, HitInfo.HitColumn) then
begin begin
FEditColumn := FFocusedColumn; FEditColumn := FFocusedColumn;
SetTimer(Handle, EditTimer, FEditDelay, nil); SetTimer(Handle, EditTimer, FEditDelay, nil);
@ -22256,12 +22309,12 @@ begin
if Assigned(Node) and (Node <> FRoot) and (vsHasChildren in Node.States) then if Assigned(Node) and (Node <> FRoot) and (vsHasChildren in Node.States) then
begin begin
Count := Node.ChildCount; Count := Node.ChildCount;
DoInitChildren(Node, Count); if DoInitChildren(Node, Count) then begin
if Count <> Node.ChildCount then
SetChildCount(Node, Count); SetChildCount(Node, Count);
if Count = 0 then if Count = 0 then
Exclude(Node.States, vsHasChildren); Exclude(Node.States, vsHasChildren);
end; end;
end;
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -22919,6 +22972,7 @@ procedure TBaseVirtualTree.InvalidateCache;
begin begin
DoStateChange([tsValidationNeeded], [tsUseCache]); DoStateChange([tsValidationNeeded], [tsUseCache]);
//ChangeTreeStatesAsync([csValidationNeeded], [csUseCache]);
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -22956,7 +23010,12 @@ var
begin begin
inherited; inherited;
// TODO: Hinzugefügt - TBaseVirtualTree.Loaded
// Call RegisterDragDrop after all visual inheritance changes to MiscOptions have been applied.
if not (csDesigning in ComponentState) and (toAcceptOLEDrop in FOptions.FMiscOptions) then
if HandleAllocated then
RegisterDragDrop(Handle, VTVDragManager as IDropTarget);
{$ifdef VCLStyleSupport} {$ifdef VCLStyleSupport}
FSavedBorderWidth := BorderWidth; FSavedBorderWidth := BorderWidth;
FSavedBevelKind := BevelKind; FSavedBevelKind := BevelKind;
@ -23820,7 +23879,7 @@ begin
Theme := OpenThemeData(Application.Handle, 'Explorer::TreeView'); Theme := OpenThemeData(Application.Handle, 'Explorer::TreeView');
RowRect := Rect(0, PaintInfo.CellRect.Top, FRangeX, PaintInfo.CellRect.Bottom); RowRect := Rect(0, PaintInfo.CellRect.Top, FRangeX, PaintInfo.CellRect.Bottom);
if (Header.Columns.Count = 0) and (toFullRowSelect in TreeOptions.SelectionOptions) then if (Header.Columns.Count = 0) and (toFullRowSelect in TreeOptions.SelectionOptions) then
RowRect.Right := ClientWidth; RowRect.Right := Max(ClientWidth, RowRect.Right);
if toShowVertGridLines in FOptions.PaintOptions then if toShowVertGridLines in FOptions.PaintOptions then
Dec(RowRect.Right); Dec(RowRect.Right);
end; end;
@ -24157,6 +24216,20 @@ begin
if FSelectionCount = 0 then if FSelectionCount = 0 then
ResetRangeAnchor; ResetRangeAnchor;
if FSelectionCount <= 1 then begin
// save a potential node to select after the currently selected node will be deleted.
// This will make the VT to behave more like the Win32 TreeView, which always selecta a new node if the currently
// selected one gets deleted.
if GetNextSibling(Node)<>nil then
fNextNodeToSelect := GetNextSibling(Node)
else if GetPreviousSibling(Node)<>nil then
fNextNodeToSelect := GetPreviousSibling(Node)
else if GetNodeLevel(Node)>0 then
fNextNodeToSelect := Node.Parent
else
fNextNodeToSelect := GetFirstChild(Node);
end;//if Assigned(Node);
DoRemoveFromSelection(Node); DoRemoveFromSelection(Node);
Change(Node); Change(Node);
end; end;
@ -24739,7 +24812,8 @@ var
CurrentBidiMode: TBidiMode; CurrentBidiMode: TBidiMode;
begin begin
if (tsEditing in FStates) and Assigned(FFocusedNode) then if (tsEditing in FStates) and Assigned(FFocusedNode) and
(FEditColumn < FHeader.Columns.Count) then // prevent EArgumentOutOfRangeException
begin begin
if (GetCurrentThreadId <> MainThreadID) then begin if (GetCurrentThreadId <> MainThreadID) then begin
// UpdateEditBounds() will be called at the end of the thread // UpdateEditBounds() will be called at the end of the thread
@ -25443,7 +25517,8 @@ function TBaseVirtualTree.CanEdit(Node: PVirtualNode; Column: TColumnIndex): Boo
// Returns True if the given node can be edited. // Returns True if the given node can be edited.
begin begin
Result := (toEditable in FOptions.FMiscOptions) and Enabled and not (toReadOnly in FOptions.FMiscOptions); Result := (toEditable in FOptions.FMiscOptions) and Enabled and not (toReadOnly in FOptions.FMiscOptions)
and ((Column < 0) or (coEditable in FHeader.Columns[Column].Options));
DoCanEdit(Node, Column, Result); DoCanEdit(Node, Column, Result);
end; end;
@ -26532,6 +26607,23 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetFirstChildNoInit(Node: PVirtualNode): PVirtualNode;
// Determines the first child of the given node but does not initialize it.
begin
if (Node = nil) or (Node = FRoot) then
Result := FRoot.FirstChild
else
begin
if vsHasChildren in Node.States then
Result := Node.FirstChild
else
Result := nil;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetFirstCutCopy(ConsiderChildrenAbove: Boolean = False): PVirtualNode; function TBaseVirtualTree.GetFirstCutCopy(ConsiderChildrenAbove: Boolean = False): PVirtualNode;
// Returns the first node in the tree which is currently marked for a clipboard operation. // Returns the first node in the tree which is currently marked for a clipboard operation.
@ -29113,6 +29205,8 @@ begin
Invalidate; Invalidate;
if TriggerChange then if TriggerChange then
Change(nil); Change(nil);
if Self.SelectedCount = 0 then
fNextNodeToSelect := nil;//Ensure that no other node is selected now
end; end;
end; end;
@ -29325,8 +29419,17 @@ begin
Include(Node.States, vsHeightMeasured); Include(Node.States, vsHeightMeasured);
if (toVariableNodeHeight in FOptions.FMiscOptions) then begin if (toVariableNodeHeight in FOptions.FMiscOptions) then begin
NewNodeHeight := Node.NodeHeight; NewNodeHeight := Node.NodeHeight;
{$ifdef HasAnonymousMethods} // Anonymous methods help to make this thread safe easily. In Delphi 2007 and lower developers must take care themselves about thread synchronization when consuming the OnMeasureItemHeight event
if (MainThreadId <> GetCurrentThreadId) then
TThread.Synchronize(nil,
procedure begin
DoMeasureItem(Canvas, Node, NewNodeHeight); DoMeasureItem(Canvas, Node, NewNodeHeight);
if NewNodeHeight <> Node.NodeHeight then SetNodeHeight(Node, NewNodeHeight);
end
)
else
{$ifend}
DoMeasureItem(Canvas, Node, NewNodeHeight); //
SetNodeHeight(Node, NewNodeHeight); SetNodeHeight(Node, NewNodeHeight);
end; end;
end; end;
@ -32388,6 +32491,7 @@ constructor TCustomVirtualStringTree.Create(AOwner: TComponent);
begin begin
inherited; inherited;
fPreviouslySelected := nil;
if (Owner = nil) or (([csReading, csDesigning] * Owner.ComponentState) = [csDesigning]) then if (Owner = nil) or (([csReading, csDesigning] * Owner.ComponentState) = [csDesigning]) then
FDefaultText := 'Node'; FDefaultText := 'Node';
FInternalDataOffset := AllocateInternalDataArea(SizeOf(Cardinal)); FInternalDataOffset := AllocateInternalDataArea(SizeOf(Cardinal));
@ -32825,6 +32929,25 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.AddChild(Parent: PVirtualNode; UserData: Pointer): PVirtualNode;
var
NewNodeText: String;
begin
Result := Inherited AddChild(Parent, UserData);
// Restore the prviously restored node if the caption of this node is knwon and no other node was selected
if (toRestoreSelection in TreeOptions.SelectionOptions) and Assigned(fPreviouslySelected) and (Self.GetFirstSelected=nil) and Assigned(OnGetText) then begin
// See if this was the previously selected node and restore it in this case
Self.OnGetText(Self, Result, 0, ttNormal, NewNodeText);
if fPreviouslySelected.IndexOf(NewNodeText) >= 0 then begin
// Select this node and make sure that the parent node is expanded
Self.Selected[Result] := True;
// if a there is a selected node now, then make sure that it is visible
if Self.GetFirstSelected <> nil then
Self.ScrollIntoView(Self.GetFirstSelected, True);
end;
end
end;
procedure TCustomVirtualStringTree.AdjustPaintCellRect(var PaintInfo: TVTPaintInfo; out NextNonEmpty: TColumnIndex); procedure TCustomVirtualStringTree.AdjustPaintCellRect(var PaintInfo: TVTPaintInfo; out NextNonEmpty: TColumnIndex);
// In the case a node spans several columns (if enabled) we need to determine how many columns. // In the case a node spans several columns (if enabled) we need to determine how many columns.
@ -32924,6 +33047,12 @@ begin
end; end;
{$endif} {$endif}
destructor TCustomVirtualStringTree.Destroy;
begin
FreeAndNil(fPreviouslySelected);
inherited;
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink; function TCustomVirtualStringTree.DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink;
@ -33783,6 +33912,29 @@ begin
end; end;
end; end;
procedure TCustomVirtualStringTree.Clear();
var
lSelectedNode: PVirtualNode;
lSelectedNodeCaption: String;
begin
if (toRestoreSelection in TreeOptions.SelectionOptions) and Assigned(Self.OnGetText) and not (csDestroying in ComponentState) then begin
if not Assigned(fPreviouslySelected) then begin
fPreviouslySelected := TStringList.Create();
fPreviouslySelected.Duplicates := dupIgnore;
fPreviouslySelected.CaseSensitive := False;
end
else
fPreviouslySelected.Clear();
lSelectedNode := Self.GetFirstSelected();
while Assigned(lSelectedNode) do begin
Self.OnGetText(Self, lSelectedNode, 0, ttNormal, lSelectedNodeCaption);
fPreviouslySelected.Add(lSelectedNodeCaption);
lSelectedNode := Self.GetNextSelected(lSelectedNode);
end;//while
end;//if
inherited;
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.ContentToRTF(Source: TVSTTextSourceType): AnsiString; function TCustomVirtualStringTree.ContentToRTF(Source: TVSTTextSourceType): AnsiString;
@ -35070,7 +35222,7 @@ begin
SF.nPos := Round(FScrollPos); SF.nPos := Round(FScrollPos);
SetScrollInfo(Handle, SB_VERT, SF, False); SetScrollInfo(Handle, SB_VERT, SF, False);
PostMessage(Handle, WM_VSCROLL, Integer(SmallPoint(SB_THUMBPOSITION, Round(FScrollPos))), 0); PostMessage(Handle, WM_VSCROLL, Integer(SmallPoint(SB_THUMBPOSITION, Min(Round(FScrollPos), High(SmallInt)))), 0); // Min() prevents range check error
PaintScrollBars; PaintScrollBars;
Handled := True; Handled := True;
@ -35444,6 +35596,22 @@ begin
Handled := True; Handled := True;
end; end;
procedure TVclStyleScrollBarsHook.WMMove(var Msg: TMessage);
begin
CallDefaultProc(TMessage(Msg));
if not (tsWindowCreating in TBaseVirtualTree(Control).FStates) then begin
CalcScrollBarsRect;
UpdateScrollBarWindow;
PaintScrollBars;
end;
Handled := True;
end;
procedure TVclStyleScrollBarsHook.WMPosChanged(var Msg: TMessage);
begin
WMMove(Msg);
end;
procedure TVclStyleScrollBarsHook.WMVScroll(var Msg: TMessage); procedure TVclStyleScrollBarsHook.WMVScroll(var Msg: TMessage);
begin begin
CallDefaultProc(TMessage(Msg)); CallDefaultProc(TMessage(Msg));