View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0037145 | Lazarus | LCL | public | 2020-05-26 08:34 | 2020-08-28 07:13 |
Reporter | Joeny Ang | Assigned To | Juha Manninen | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | closed | Resolution | reopened | ||
Product Version | 2.1 (SVN) | ||||
Summary | 0037145: [Patch] TTreeView mouse selection | ||||
Description | The following are addressed by this patch: 1. Multiselect with Shift, no msSiblingOnly; select a first child then select the parent (eg. on the attached example: select Item4, then Item0), this will select everything from Item4 to the last item 2. Setting MultiSelect to False does not clear selection 3. GetNodeAt(X,Y) should honor RowSelect state. When RowSelect=False, it will only return a node if X/Y falls inside the rect of the node and its icon. 4. Added tvoEmptySpaceUnselect option; clicking on white space will clear selection; when RowSelect=True, selection will only be cleared when the space after the last item is clicked. | ||||
Tags | No tags attached. | ||||
Fixed in Revision | r63232, r63235 | ||||
LazTarget | - | ||||
Widgetset | |||||
Attached Files |
|
|
ttreeview-mouse-selection-fix.patch (5,333 bytes)
--- lcl/comctrls.pp +++ lcl/comctrls.pp @@ -3287,7 +3287,8 @@ tvoShowSeparators, tvoToolTips, tvoNoDoubleClickExpand, - tvoThemedDraw + tvoThemedDraw, + tvoEmptySpaceUnselect ); TTreeViewOptions = set of TTreeViewOption; @@ -3425,7 +3426,8 @@ function IsStoredBackgroundColor: Boolean; procedure HintMouseLeave(Sender: TObject); procedure ImageListChange(Sender: TObject); - function MouseDownNode(X, Y: Integer): TTreeNode; + function MouseDownNode(X, Y: Integer; const fIncludeExpandSign: Boolean = + False): TTreeNode; procedure OnChangeTimer(Sender: TObject); procedure SetAutoExpand(Value: Boolean); procedure SetBackgroundColor(Value: TColor); --- lcl/include/treeview.inc +++ lcl/include/treeview.inc @@ -2797,7 +2797,7 @@ end; //select again - bGoNext := (FirstNode.Index <= Node.Index); + bGoNext := (FirstNode.AbsoluteIndex <= Node.AbsoluteIndex); I := FirstNode; I.MultiSelected:=True; while (I<>Node) do @@ -3861,6 +3861,7 @@ begin if MultiSelect <> AValue then begin + ClearSelection; if AValue then Include(FOptions,tvoAllowMultiselect) else @@ -3974,9 +3975,13 @@ function TCustomTreeView.GetNodeAt(X, Y: Integer): TTreeNode; begin - if (X >= BorderWidth) and (X < ClientWidth - BorderWidth) then - Result := GetNodeAtY(Y) - else + Result := GetNodeAtY(Y); + if not Assigned(Result) then + Exit; + if (not (tvoRowSelect in Options) and + ((X < Result.DisplayStateIconLeft) or (X >= Result.DisplayTextRight))) or + ((tvoRowSelect in Options) and // row select + ((X < BorderWidth) or (X >= ClientWidth - BorderWidth))) then Result := nil; end; @@ -5574,9 +5579,22 @@ Result := FIndent >= 0; end; -function TCustomTreeView.MouseDownNode(X, Y: Integer): TTreeNode; -begin - Result := GetNodeAt(X, Y); +function TCustomTreeView.MouseDownNode(X, Y: Integer; const fIncludeExpandSign: + Boolean): TTreeNode; +begin + if fIncludeExpandSign then + begin + Result := GetNodeAtY(Y); + if Assigned(Result) then + if (not (tvoRowSelect in Options) and // need to include DisplayExpandSignLeft + ((X < Result.DisplayExpandSignLeft) or (X >= Result.DisplayTextRight))) or + ((tvoRowSelect in Options) and // row select + ((X < BorderWidth) or (X >= ClientWidth - BorderWidth))) then + Result := nil; + end + else + Result := GetNodeAt(X, Y); + // Update the NodeSelected flag. FMouseDownNodeSelected := Assigned(Result) and (Result.Selected or ((tvoAllowMultiselect in Options) and Result.MultiSelected)); @@ -5601,16 +5619,25 @@ if (Button = mbRight) and RightClickSelect and//right click (([ssDouble, ssTriple, ssQuad] * Shift) = []) and//single or first of a multi click not AllowMultiSelectWithCtrl(Shift) and//only when CTRL is not pressed - (CursorNode <> nil) and - (LogicalX >= CursorNode.DisplayStateIconLeft)//only after expand sign + (CursorNode <> nil) then begin + if not (tvoRowSelect in Options) and + (tvoEmptySpaceUnselect in Options) and + (LogicalX >= CursorNode.DisplayStateIconLeft) and + (LogicalX > CursorNode.DisplayTextRight) then + ClearSelection + else if not (tvoAllowMultiselect in Options) then Selected := CursorNode else if not FMouseDownNodeSelected then Items.SelectOnlyThis(CursorNode); - end; + end + else // empty space below last node + if (Button = mbRight) and RightClickSelect and (CursorNode = nil) and + (tvoEmptySpaceUnselect in Options) then + ClearSelection; if not Focused and CanFocus then SetFocus; @@ -5618,7 +5645,7 @@ inherited MouseDown(Button, Shift, X, Y); //CursorNode must be reassigned again - e.g. in OnMouseDown the node can be deleted or moved. - CursorNode := MouseDownNode(X, Y); + CursorNode := MouseDownNode(LogicalX, Y, True); //Flag is used for DblClick/TripleClick/QuadClick, so set it before testing ShiftState FMouseDownOnFoldingSign := @@ -5634,7 +5661,8 @@ if FMouseDownOnFoldingSign then // mousedown occured on expand sign -> expand/collapse CursorNode.Expanded := not CursorNode.Expanded - else if LogicalX >= CursorNode.DisplayStateIconLeft then + else if (LogicalX >= CursorNode.DisplayStateIconLeft) or + (tvoRowSelect in Options) then begin // mousedown occured in text or icon -> select node and begin drag operation {$IFDEF VerboseDrag} @@ -5671,12 +5699,18 @@ Include(FStates, tvsSingleSelectOnMouseUp); end; end; - end; + end + else if tvoEmptySpaceUnselect in Options then + ClearSelection; end else// multi click if not (tvoNoDoubleClickExpand in Options) and (ssDouble in Shift) and (Button = mbLeft) and (CursorNode<>nil) then - CursorNode.Expanded := not CursorNode.Expanded; + CursorNode.Expanded := not CursorNode.Expanded + else // empty space below last node + if (Button = mbLeft) and (CursorNode = nil) and (tvoEmptySpaceUnselect in Options) and + not AllowMultiSelectWithShift(Shift) and not AllowMultiSelectWithCtrl(Shift) then + ClearSelection; end; procedure TCustomTreeView.MouseMove(Shift: TShiftState; X, Y: Integer); |
|
Looks good. I applied the patch after some refactoring and simplification. You had duplicated the GetNodeAt() code in MouseDownNode(). I removed the latter completely. Please test everybody. |
|
Hi, thanks for applying the patch. Need to re-open this. When RowSelect=False, clicking on the expand icon does not work. The duplicated code was supposed to fix this hehe :) |
|
Hmmm... I thought I did pure refactoring but apparently not. I must study the code some more. |
|
Yes, there was DisplayStateIconLeft versus DisplayExpandSignLeft. Somehow I missed that. Sorry. :) I fixed it and refactored a little. I hope it is OK. Please test. |
|
Nice. Everything's good. Thanks :) |
Date Modified | Username | Field | Change |
---|---|---|---|
2020-05-26 08:34 | Joeny Ang | New Issue | |
2020-05-26 08:34 | Joeny Ang | File Added: ttreeview-mouse-selection-fix.patch | |
2020-05-26 08:34 | Joeny Ang | File Added: ttreeview-test-01.zip | |
2020-05-27 01:23 | Juha Manninen | Assigned To | => Juha Manninen |
2020-05-27 01:23 | Juha Manninen | Status | new => assigned |
2020-05-27 01:27 | Juha Manninen | Status | assigned => resolved |
2020-05-27 01:27 | Juha Manninen | Resolution | open => fixed |
2020-05-27 01:27 | Juha Manninen | Fixed in Revision | => r63232 |
2020-05-27 01:27 | Juha Manninen | LazTarget | => - |
2020-05-27 01:27 | Juha Manninen | Note Added: 0123088 | |
2020-05-27 04:19 | Joeny Ang | Status | resolved => assigned |
2020-05-27 04:19 | Joeny Ang | Resolution | fixed => reopened |
2020-05-27 04:19 | Joeny Ang | Note Added: 0123092 | |
2020-05-27 09:38 | Juha Manninen | Note Added: 0123095 | |
2020-05-27 09:39 | Juha Manninen | Note Edited: 0123095 | View Revisions |
2020-05-27 14:12 | Juha Manninen | Status | assigned => resolved |
2020-05-27 14:12 | Juha Manninen | Fixed in Revision | r63232 => r63232, r63235 |
2020-05-27 14:12 | Juha Manninen | Note Added: 0123100 | |
2020-05-28 07:39 | Joeny Ang | Note Added: 0123105 | |
2020-08-28 07:13 | Joeny Ang | Status | resolved => closed |