From 5c1627deff1d20205911bbf3ed38619b9718fcd2 Mon Sep 17 00:00:00 2001 From: maciej-izak Date: Mon, 29 Aug 2016 12:04:59 +0200 Subject: [PATCH 1/3] Fix for AV --- Source/VirtualTrees.pas | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/VirtualTrees.pas b/Source/VirtualTrees.pas index 528f77e49..fd7aa500a 100644 --- a/Source/VirtualTrees.pas +++ b/Source/VirtualTrees.pas @@ -32846,9 +32846,12 @@ procedure TVTEdit.WMKeyDown(var Message: TWMKeyDown); Tree.InvalidateNode(FLink.FNode); NextNode := Tree.GetNextVisible(FLink.FNode, True); Tree.EndEditNode; - Tree.FocusedNode := NextNode; - if Tree.CanEdit(Tree.FocusedNode, Tree.FocusedColumn) then - Tree.DoEdit; + if NextNode <> nil then + begin + Tree.FocusedNode := NextNode; + if Tree.CanEdit(Tree.FocusedNode, Tree.FocusedColumn) then + Tree.DoEdit; + end; end; end; Ord('A'): From 795f982c7db716f4b56c6d4bfb924f3ee63aa3a7 Mon Sep 17 00:00:00 2001 From: maciej-izak Date: Mon, 29 Aug 2016 12:25:08 +0200 Subject: [PATCH 2/3] New feature to set the way of selecting next cells for editing --- Source/VirtualTrees.pas | 74 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/Source/VirtualTrees.pas b/Source/VirtualTrees.pas index fd7aa500a..5b50a8ab2 100644 --- a/Source/VirtualTrees.pas +++ b/Source/VirtualTrees.pas @@ -516,6 +516,12 @@ TCheckStateHelper = record helper for TCheckState ); TVTSelectionOptions = set of TVTSelectionOption; + TVTEditOptions = ( + toDefaultEdit, + toVerticalEdit, + toHorizontalEdit + ); + // Options which do not fit into any of the other groups: TVTMiscOption = ( toAcceptOLEDrop, // Register tree as OLE accepting drop target @@ -599,6 +605,7 @@ TCustomVirtualTreeOptions = class(TPersistent) FSelectionOptions: TVTSelectionOptions; FMiscOptions: TVTMiscOptions; FExportMode: TVTExportMode; + FEditOptions: TVTEditOptions; procedure SetAnimationOptions(const Value: TVTAnimationOptions); procedure SetAutoOptions(const Value: TVTAutoOptions); procedure SetMiscOptions(const Value: TVTMiscOptions); @@ -614,6 +621,7 @@ TCustomVirtualTreeOptions = class(TPersistent) property MiscOptions: TVTMiscOptions read FMiscOptions write SetMiscOptions default DefaultMiscOptions; property PaintOptions: TVTPaintOptions read FPaintOptions write SetPaintOptions default DefaultPaintOptions; property SelectionOptions: TVTSelectionOptions read FSelectionOptions write SetSelectionOptions default DefaultSelectionOptions; + property EditOptions: TVTEditOptions read FEditOptions write FEditOptions; property Owner: TBaseVirtualTree read FOwner; end; @@ -966,6 +974,8 @@ TVirtualTreeColumn = class(TCollectionItem) FMargin, FSpacing: Integer; FOptions: TVTColumnOptions; + FEditOptions: TVTEditOptions; + FEditNextColumn: Integer; FTag: NativeInt; FAlignment: TAlignment; FCaptionAlignment: TAlignment; // Alignment of the caption. @@ -1052,6 +1062,8 @@ TVirtualTreeColumn = class(TCollectionItem) property MaxWidth: Integer read FMaxWidth write SetMaxWidth default 10000; property MinWidth: Integer read FMinWidth write SetMinWidth default 10; property Options: TVTColumnOptions read FOptions write SetOptions default DefaultColumnOptions; + property EditOptions: TVTEditOptions read FEditOptions write FEditOptions default toDefaultEdit; + property EditNextColumn: Integer read FEditNextColumn write FEditNextColumn default -1; property Position: TColumnPosition read FPosition write SetPosition; property Spacing: Integer read FSpacing write SetSpacing default 3; property Style: TVirtualTreeColumnStyle read FStyle write SetStyle default vsText; @@ -3199,6 +3211,7 @@ TStringTreeOptions = class(TCustomStringTreeOptions) property PaintOptions; property SelectionOptions; property StringOptions; + property EditOptions; end; TCustomVirtualStringTree = class; @@ -6710,6 +6723,7 @@ constructor TVirtualTreeColumn.Create(Collection: TCollection); FCheckBox := False; FHasImage := False; FDefaultSortDirection := sdAscending; + fEditNextColumn := -1; inherited Create(Collection); @@ -7651,6 +7665,8 @@ procedure TVirtualTreeColumn.Assign(Source: TPersistent); CaptionAlignment := TVirtualTreeColumn(Source).CaptionAlignment; Color := TVirtualTreeColumn(Source).Color; Tag := TVirtualTreeColumn(Source).Tag; + EditOptions := TVirtualTreeColumn(Source).EditOptions; + EditNextColumn := TVirtualTreeColumn(Source).EditNextColumn; // Order is important. Assign options last. FOptions := OldOptions; @@ -32682,7 +32698,10 @@ procedure TCustomStringTreeOptions.AssignTo(Dest: TPersistent); if Dest is TCustomStringTreeOptions then begin with Dest as TCustomStringTreeOptions do + begin StringOptions := Self.StringOptions; + EditOptions := Self.EditOptions; + end; end; // Let ancestors assign their options to the destination class. @@ -32801,6 +32820,9 @@ procedure TVTEdit.WMKeyDown(var Message: TWMKeyDown); EndEdit: Boolean; Tree: TBaseVirtualTree; NextNode: PVirtualNode; + ColumnCandidate: Integer; + EditOptions: TVTEditOptions; + Column: TVirtualTreeColumn; begin Tree := FLink.FTree; case Message.CharCode of @@ -32823,8 +32845,58 @@ procedure TVTEdit.WMKeyDown(var Message: TWMKeyDown); begin Tree := FLink.FTree; FLink.FTree.InvalidateNode(FLink.FNode); + NextNode := Tree.GetNextVisible(FLink.FNode, True); FLink.FTree.DoEndEdit; - Tree.SetFocus; + + Column := Tree.Header.Columns[Tree.FocusedColumn]; + if Column.EditOptions <> toDefaultEdit then + EditOptions := Column.EditOptions + else + EditOptions := Tree.TreeOptions.EditOptions; + + if Column.EditNextColumn <> -1 then + ColumnCandidate := Column.EditNextColumn + else + ColumnCandidate := -1; + + case EditOptions of + toDefaultEdit: Tree.SetFocus; + toVerticalEdit: + if NextNode <> nil then + begin + Tree.FocusedNode := NextNode; + + if ColumnCandidate <> -1 then + begin + Tree.FocusedColumn := ColumnCandidate; + Tree.EditColumn := ColumnCandidate; + end; + + if Tree.CanEdit(Tree.FocusedNode, Tree.FocusedColumn) then + Tree.DoEdit; + end; + toHorizontalEdit: + begin + if ColumnCandidate = -1 then + begin + ColumnCandidate := Tree.FocusedColumn+1; + while (ColumnCandidate < Tree.Header.Columns.Count) + and not Tree.CanEdit(Tree.FocusedNode, ColumnCandidate) + do + Inc(ColumnCandidate); + end + else + if not Tree.CanEdit(Tree.FocusedNode, ColumnCandidate) then + ColumnCandidate := Tree.Header.Columns.Count; // omit + + if ColumnCandidate < Tree.Header.Columns.Count then + begin + Tree.FocusedColumn := ColumnCandidate; + Tree.EditColumn := ColumnCandidate; + Tree.DoEdit; + end; + end; + end; end; end; VK_UP: From 06b7d58f84eb55e950ce1243bce10e9401405e7a Mon Sep 17 00:00:00 2001 From: maciej-izak Date: Wed, 31 Aug 2016 08:34:57 +0200 Subject: [PATCH 3/3] Add comments for latest changes (new TVTEditOptions and for small fix). --- Source/VirtualTrees.pas | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Source/VirtualTrees.pas b/Source/VirtualTrees.pas index 5b50a8ab2..0dba339ab 100644 --- a/Source/VirtualTrees.pas +++ b/Source/VirtualTrees.pas @@ -517,9 +517,9 @@ TCheckStateHelper = record helper for TCheckState TVTSelectionOptions = set of TVTSelectionOption; TVTEditOptions = ( - toDefaultEdit, - toVerticalEdit, - toHorizontalEdit + toDefaultEdit, // Standard behaviour for end of editing (after VK_RETURN stay on edited cell). + toVerticalEdit, // After VK_RETURN switch to next column. + toHorizontalEdit // After VK_RETURN switch to next row. ); // Options which do not fit into any of the other groups: @@ -32848,12 +32848,15 @@ procedure TVTEdit.WMKeyDown(var Message: TWMKeyDown); NextNode := Tree.GetNextVisible(FLink.FNode, True); FLink.FTree.DoEndEdit; + // get edit options for column as priority. If column has toDefaultEdit + // use global edit options for tree Column := Tree.Header.Columns[Tree.FocusedColumn]; if Column.EditOptions <> toDefaultEdit then EditOptions := Column.EditOptions else EditOptions := Tree.TreeOptions.EditOptions; + // next column candidate for toVerticalEdit and toHorizontalEdit if Column.EditNextColumn <> -1 then ColumnCandidate := Column.EditNextColumn else @@ -32866,6 +32869,8 @@ procedure TVTEdit.WMKeyDown(var Message: TWMKeyDown); begin Tree.FocusedNode := NextNode; + // for toVerticalEdit ColumnCandidate is also proper, + // select ColumnCandidate column in row below if ColumnCandidate <> -1 then begin Tree.FocusedColumn := ColumnCandidate; @@ -32879,6 +32884,8 @@ procedure TVTEdit.WMKeyDown(var Message: TWMKeyDown); begin if ColumnCandidate = -1 then begin + // for toHorizontalEdit if property EditNextColumn is not used + // try to use just next column ColumnCandidate := Tree.FocusedColumn+1; while (ColumnCandidate < Tree.Header.Columns.Count) and not Tree.CanEdit(Tree.FocusedNode, ColumnCandidate) @@ -32887,7 +32894,7 @@ procedure TVTEdit.WMKeyDown(var Message: TWMKeyDown); end else if not Tree.CanEdit(Tree.FocusedNode, ColumnCandidate) then - ColumnCandidate := Tree.Header.Columns.Count; // omit + ColumnCandidate := Tree.Header.Columns.Count; // omit "focus/edit column" (see below) if ColumnCandidate < Tree.Header.Columns.Count then begin @@ -32918,6 +32925,7 @@ procedure TVTEdit.WMKeyDown(var Message: TWMKeyDown); Tree.InvalidateNode(FLink.FNode); NextNode := Tree.GetNextVisible(FLink.FNode, True); Tree.EndEditNode; + // check NextNode, otherwise we got AV if NextNode <> nil then begin Tree.FocusedNode := NextNode;