AdvStringGrid[8.0.1.0] - node exapand/collapse bug

  1. Create a grid.
  2. Fill with random data
  3. Group the lines.
  4. Expand node.
  5. Collapse node.
  6. Profit!
Fill with random data
Expand the last node



Collapse the last node, (first bug: сolumns moved to the left by 1)



Expand last but one


Collapse last but one (second bug: hides the last line)




// test.pas

unit Test;


interface


uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.Grids, AdvObj, BaseGrid, AdvGrid, Vcl.StdCtrls;


type
    TTestColumns = (
        f_node = 0,
        f_col1, f_col2, f_col3,
        f_colcount
    );


  TTestForm = class(TForm)
    grid: TAdvStringGrid;
    Panel1: TPanel;
    bLoadTreeStatic: TButton;
    bLoadTreeDynamic: TButton;
    procedure bLoadTreeStaticClick(Sender: TObject);
    procedure bLoadTreeDynamicClick(Sender: TObject);
  private
    procedure gridExpandNodeDynamic(Sender: TObject; ARow, ARowreal: Integer);
    procedure CreateEmpryGrid;
    { Private declarations }
  public
    { Public declarations }
  end;


var
  TestForm: TTestForm;


implementation


{$R *.dfm}


procedure TTestForm.CreateEmpryGrid();
var
    col:integer;
begin
    grid.UnHideColumnsAll();
    grid.ClearAll();
    grid.ColCount := ord(f_colcount);
    grid.FixedRows := 1;
    grid.GridLineColor := clBlack;
    grid.GridFixedLineColor := clBlack;
    grid.Clear();
    grid.DefaultColWidth := 100;
    grid.AllColWidths[ord(f_node)] := 25;
    grid.DrawingStyle := gdsClassic;
    grid.Options := [goFixedVertLine, goFixedHorzLine,
                     goVertLine, goHorzLine, goRangeSelect,
                     goRowSizing, goColSizing, goFixedColClick,
                     goFixedRowClick, goFixedHotTrack];
    grid.HoverRowCells := [hcNormal, hcSelected];
    grid.CellNode.NodeType := cnLeaf;
end;


procedure TTestForm.bLoadTreeDynamicClick(Sender: TObject);
var
  row:Integer;
begin
    CreateEmpryGrid();
    grid.RowCount := 5;
    grid.OnExpandNode := gridExpandNodeDynamic;


    for row := 1 to grid.RowCount-1 do begin


        grid.Cells[ord(f_col1), row] := format('apple %d',  [row]);
        grid.Cells[ord(f_col2), row] := format('banana %d', [row]);
        grid.Cells[ord(f_col3), row] := format('orange %d', [row]);


        grid.RowColor[row] := rgb(100, 100, 100);
        grid.AddNode(row, 1);
    end;


    grid.ContractAll();
end;


procedure TTestForm.bLoadTreeStaticClick(Sender: TObject);
const
    group_count = 3;
var
    row: Integer;
begin
    CreateEmpryGrid();
    grid.RowCount := 10;


    for row := 1 to grid.RowCount-1 do begin
        grid.Cells[ord(f_col1), row] := format('apple %d',  [row]);
        grid.Cells[ord(f_col2), row] := format('banana %d', [row]);
        grid.Cells[ord(f_col3), row] := format('orange %d', [row]);


        // create node
        if (row mod group_count) = 0 then begin
            grid.AddNode(row - group_count + 1, group_count);
            grid.RowColor[row - group_count + 1] := rgb(100, 100, 100);
        end;
    end;


    grid.ContractAll();
end;


procedure TTestForm.gridExpandNodeDynamic(Sender: TObject; ARow, ARowreal: Integer);
var
    //lv,
   sp, row: integer;
begin
    //lv := grid.GetNodeLevel(ARow);
    sp := grid.GetNodeSpan(ARow);
    if sp > 1 then exit;


    for row := 0 to 3 do begin
        grid.InsertChildRow(ARowreal);
        grid.Cells[ord(f_col1), ARow+1] := format('auto %d',   [row]);
        grid.Cells[ord(f_col2), ARow+1] := format('manual %d', [row]);
        grid.Cells[ord(f_col3), ARow+1] := format('test %d',   [row]);
    end;
end;


end.



// test.dfm

object TestForm: TTestForm
  Left = 0
  Top = 0
  Caption = 'TestForm'
  ClientHeight = 396
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object grid: TAdvStringGrid
    Left = 0
    Top = 41
    Width = 635
    Height = 355
    Cursor = crDefault
    Align = alClient
    DrawingStyle = gdsClassic
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentFont = False
    ScrollBars = ssBoth
    TabOrder = 0
    HoverRowCells = [hcNormal, hcSelected]
    ActiveCellFont.Charset = DEFAULT_CHARSET
    ActiveCellFont.Color = clWindowText
    ActiveCellFont.Height = -11
    ActiveCellFont.Name = 'Tahoma'
    ActiveCellFont.Style = [fsBold]
    ControlLook.FixedGradientHoverFrom = clGray
    ControlLook.FixedGradientHoverTo = clWhite
    ControlLook.FixedGradientDownFrom = clGray
    ControlLook.FixedGradientDownTo = clSilver
    ControlLook.DropDownHeader.Font.Charset = DEFAULT_CHARSET
    ControlLook.DropDownHeader.Font.Color = clWindowText
    ControlLook.DropDownHeader.Font.Height = -11
    ControlLook.DropDownHeader.Font.Name = 'Tahoma'
    ControlLook.DropDownHeader.Font.Style = []
    ControlLook.DropDownHeader.Visible = True
    ControlLook.DropDownHeader.Buttons = <>
    ControlLook.DropDownFooter.Font.Charset = DEFAULT_CHARSET
    ControlLook.DropDownFooter.Font.Color = clWindowText
    ControlLook.DropDownFooter.Font.Height = -11
    ControlLook.DropDownFooter.Font.Name = 'Tahoma'
    ControlLook.DropDownFooter.Font.Style = []
    ControlLook.DropDownFooter.Visible = True
    ControlLook.DropDownFooter.Buttons = <>
    Filter = <>
    FilterDropDown.Font.Charset = DEFAULT_CHARSET
    FilterDropDown.Font.Color = clWindowText
    FilterDropDown.Font.Height = -11
    FilterDropDown.Font.Name = 'Tahoma'
    FilterDropDown.Font.Style = []
    FilterDropDown.TextChecked = 'Checked'
    FilterDropDown.TextUnChecked = 'Unchecked'
    FilterDropDownClear = '(All)'
    FilterEdit.TypeNames.Strings = (
      'Starts with'
      'Ends with'
      'Contains'
      'Not contains'
      'Equal'
      'Not equal'
      'Larger than'
      'Smaller than'
      'Clear')
    FixedRowHeight = 22
    FixedFont.Charset = DEFAULT_CHARSET
    FixedFont.Color = clWindowText
    FixedFont.Height = -11
    FixedFont.Name = 'Tahoma'
    FixedFont.Style = [fsBold]
    FloatFormat = '%.2f'
    HoverButtons.Buttons = <>
    HoverButtons.Position = hbLeftFromColumnLeft
    HTMLSettings.ImageFolder = 'images'
    HTMLSettings.ImageBaseName = 'img'
    PrintSettings.DateFormat = 'dd/mm/yyyy'
    PrintSettings.Font.Charset = DEFAULT_CHARSET
    PrintSettings.Font.Color = clWindowText
    PrintSettings.Font.Height = -11
    PrintSettings.Font.Name = 'Tahoma'
    PrintSettings.Font.Style = []
    PrintSettings.FixedFont.Charset = DEFAULT_CHARSET
    PrintSettings.FixedFont.Color = clWindowText
    PrintSettings.FixedFont.Height = -11
    PrintSettings.FixedFont.Name = 'Tahoma'
    PrintSettings.FixedFont.Style = []
    PrintSettings.HeaderFont.Charset = DEFAULT_CHARSET
    PrintSettings.HeaderFont.Color = clWindowText
    PrintSettings.HeaderFont.Height = -11
    PrintSettings.HeaderFont.Name = 'Tahoma'
    PrintSettings.HeaderFont.Style = []
    PrintSettings.FooterFont.Charset = DEFAULT_CHARSET
    PrintSettings.FooterFont.Color = clWindowText
    PrintSettings.FooterFont.Height = -11
    PrintSettings.FooterFont.Name = 'Tahoma'
    PrintSettings.FooterFont.Style = []
    PrintSettings.PageNumSep = '/'
    SearchFooter.FindNextCaption = 'Find &next'
    SearchFooter.FindPrevCaption = 'Find &previous'
    SearchFooter.Font.Charset = DEFAULT_CHARSET
    SearchFooter.Font.Color = clWindowText
    SearchFooter.Font.Height = -11
    SearchFooter.Font.Name = 'Tahoma'
    SearchFooter.Font.Style = []
    SearchFooter.HighLightCaption = 'Highlight'
    SearchFooter.HintClose = 'Close'
    SearchFooter.HintFindNext = 'Find next occurrence'
    SearchFooter.HintFindPrev = 'Find previous occurrence'
    SearchFooter.HintHighlight = 'Highlight occurrences'
    SearchFooter.MatchCaseCaption = 'Match case'
    SortSettings.DefaultFormat = ssAutomatic
    Version = '7.8.5.0'
    ColWidths = (
      64
      64
      64
      64
      64)
    RowHeights = (
      22
      22
      22
      22
      22
      22
      22
      22
      22
      22)
  end
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 635
    Height = 41
    Align = alTop
    TabOrder = 1
    object bLoadTreeStatic: TButton
      Left = 178
      Top = 8
      Width = 120
      Height = 25
      Caption = 'Load as tree static'
      TabOrder = 0
      OnClick = bLoadTreeStaticClick
    end
    object bLoadTreeDynamic: TButton
      Left = 337
      Top = 8
      Width = 120
      Height = 25
      Caption = 'Load as tree dynamic'
      TabOrder = 1
      OnClick = bLoadTreeDynamicClick
    end
  end
end


Delphi XE10 Seattle

What to do?

The way you are trying to use the grid's nodes is not the way it was designed for. You create nodes with one child that do not really have one (or more childs) and then dynamically add the childs when the node is expanded. The node expand / collaps events were not designed with this type of use in mind. We'd need to investigate if somehow it can be adapted so it can be used this way, but this is a non-trivial change.

Well, how then to be with сolumns moved to the left by 1 (image 3)?

When filling the grid with data & nodes in one time, i.e. not dynamically as you do, I cannot reproduce such issue.

I have the same bug with the colomns moved to the left by one.

(but not the one that hides rows)



All nodes were declared by the AddNode command, after the grid data was supplied.



It worked fine.



Last week I installed the full component pack and recompiled my soft.



And then the bug appear on all my grid that use node.



Remark : if I use the expandall and contractall command in my program, there is no problem,



The bug is only present when expending/contracting a node manually !!



Can you please  contact us by email and send a sample source project where this issue is isolated so we can reproduce this here as I cannot see or reproduce this.

Hello,
That began to deal with this problem and found the following.
The procedures ExpandNodeInt \ ContractNodeInt blocks of code have been added:

if IsNode(ARow) then
begin
	for c := 0 to ColCount - 1 do
	begin
		obj := GridObjects[c,Arow];
		if Assigned(obj) then
		begin
			cp := TCellProperties(obj);
			cp.MergeCollaps := true;// or false in ExpandNodeInt
		end;
	end;
end;


This innovation is killing all the old functionality
Everything works fine up to version 7.8.3.1 or later,
until the input of these changes.

If you comment out the blocks, then everything works as before.

We have traced & solved this issue meanwhile. The next update will address this.

There is another problem, which has appeared in recent versions
When dynamically load nodes and then Expand/Contract of the last line is a loss.

The solution to this problem:

// function TAdvStringGrid.RemapRowInv(ARow: Integer): Integer;
............................
+// == begin 2014.05.11 (fixed hide last row)
+      FHiddenRowLookup.Free;
+      FHiddenRowLookup:=nil;
+// == end 2014.05.11
       InitHiddenRowLookup;


full diff:



diff --git a/TmsComponents/advgrid.pas b/TmsComponents/advgrid.pas
index 610a2ef..eca3cb7 100644
--- a/TmsComponents/advgrid.pas
+++ b/TmsComponents/advgrid.pas
@@ -15336,18 +15336,20 @@ begin
   else
     Exit;
 
-  if IsNode(ARow) then
-  begin
-    for c := 0 to ColCount - 1 do
-    begin
-      obj := GridObjects[c,ARow];
-      if Assigned(obj) then
-      begin
-        cp := TCellProperties(obj);
-        cp.MergeCollaps := false;
-      end;
-    end;
-  end;
+// == begin 2015.10.13 (fixed column moving)
+//  if IsNode(ARow) then
+//  begin
+//    for c := 0 to ColCount - 1 do
+//    begin
+//      obj := GridObjects[c,ARow];
+//      if Assigned(obj) then
+//      begin
+//        cp := TCellProperties(obj);
+//        cp.MergeCollaps := false;
+//      end;
+//    end;
+//  end;
+// == end 2015.10.13
 
   i := ARow + 1;
   if (cg.CellIndex = 0) then
@@ -15419,19 +15421,20 @@ begin
     Exit;
   end;
 
-  if IsNode(ARow) then
-  begin
-    for c := 0 to ColCount - 1 do
-    begin
-      obj := GridObjects[c,Arow];
-      if Assigned(obj) then
-      begin
-        cp := TCellProperties(obj);
-        cp.MergeCollaps := true;
-      end;
-    end;
-  end;
-
+// == begin 2015.10.13 (fixed column moving)
+//  if IsNode(ARow) then
+//  begin
+//    for c := 0 to ColCount - 1 do
+//    begin
+//      obj := GridObjects[c,Arow];
+//      if Assigned(obj) then
+//      begin
+//        cp := TCellProperties(obj);
+//        cp.MergeCollaps := true;
+//      end;
+//    end;
+//  end;
+// == end 2015.10.13
 
   i := ARow + 1;
 
@@ -18287,6 +18290,10 @@ begin
   begin
     //lh := nil;
     //try
+// == begin 2014.05.11 (fixed hide last row)
+      FHiddenRowLookup.Free;
+      FHiddenRowLookup:=nil;
+// == end 2014.05.11
       InitHiddenRowLookup;
 
       while (k <= ARow) do




Sorry for my bad english

What exactly do you mean with

"When dynamically load nodes and then Expand/Contract of the last line is a loss."

I tested this here with programmatically adding a node that should collaps the last grid row and I cannot see a problem.