How to auto size spanned column in TVirtualStringTree?

Viewed 1006

I have simple example of VirtualStringTree (VST) with 4 columns and in 2nd or 3rd column I could have more text that fit the default column width. I have hoAutoSpanColumns enabled so the large text will overlap other columns, if they are empty. This works good. The problem is when text in 2nd or 3rd column should span over the full length of VST. In this case the large columns only extend to the end of last (4th) column.

Here is how 2nd column in line 3 only spans over 3rd and 4th columns and then it stops at the width of 4th column:

enter image description here

If I use AutoFitColumns to auto size 2nd column:

VST1.Header.AutoFitColumns(false, smaUseColumnOption,1,1);

then it pushes 3rd and 4th columns so they start at the end of 2nd column:

enter image description here

But I need 3rd and 4th column to stay at the same positions, like this:

enter image description here

Is there a way to auto fit 2nd column to text, but keep 3rd and 4th columns at the same positions as they were originally?

1 Answers

There is no built-in way to autofit header to a spanned column text at this time. To autosize a given column to see the whole spanned text you can write a code like this (for single node). Do note that autospan feature in VT doesn't support RTL reading at this time (so this code doesn't as well):

type
  TVirtualStringTree = class(VirtualTrees.TVirtualStringTree)
  protected
    function GetSpanColumn(Node: PVirtualNode): TColumnIndex; virtual;
  public
    procedure AutoFitSpanColumn(DestColumn: TColumnIndex; Node: PVirtualNode);
  end;

implementation

{ TVirtualStringTree }

function TVirtualStringTree.GetSpanColumn(Node: PVirtualNode): TColumnIndex;
begin
  { this returns visible span column for the given node, InvalidColumn otherwise }
  Result := Header.Columns.GetLastVisibleColumn;
  while ColumnIsEmpty(Node, Result) and (Result <> InvalidColumn) do
    Result := Header.Columns.GetPreviousVisibleColumn(Result);
end;

procedure TVirtualStringTree.AutoFitSpanColumn(DestColumn: TColumnIndex; Node: PVirtualNode);
var
  ColsWidth: Integer;
  SpanWidth: Integer;
  SpanOffset: Integer;
  SpanColumn: TColumnIndex;
begin
  SpanColumn := GetSpanColumn(Node);

  if SpanColumn <> InvalidColumn then
  begin
    { get the total width of the header }
    ColsWidth := Header.Columns.TotalWidth;
    { get the width of the span text cell as it would be autosized }
    SpanWidth := DoGetNodeWidth(Node, SpanColumn) + DoGetNodeExtraWidth(Node, SpanColumn) +
      DoGetCellContentMargin(Node, SpanColumn).X + Margin;
    { and get the left position of the span cell column in header }
    SpanOffset := Header.Columns[SpanColumn].GetRect.Left;
    { now, the width of the autosized column we increase by the subtraction of the fully
      visible span cell width and all columns width increased by offset of the span cell
      column; in other words, we'll just increase or decrease width of the DestColumn to
      the difference of width needed for the span column to be fully visible, or "fit" }
    Header.Columns[DestColumn].Width := Header.Columns[DestColumn].Width +
      SpanWidth - ColsWidth + SpanOffset;
  end;
end;
Related