VirtualTreeView - different color of text in the same node
Asked Answered
K

1

8

I am attempting to create a view in TVirtualStringTree which will be similar to something like this:

Folder view with different font colors

In the above example I have shown some of the possible scenarios I want to reach. FolderA has bold text and after that red-colored unbolded text just behind it in the same node. I am looking for way to make this sort of output.

However, if this is too hard or too problematic to create, I would be happy with FolderB or FolderC type of output - which could probably be made with 2 columns, one containing the folder name and another containing the count of files inside.

FolderD is here just as example of a folder with no files and the output for that folder (text is unbolded and there is no number).

I am looking for any directions how to make this effect as it seems that VirtualTreeView can only have single color or bold setting per one node. Any tips or suggestions how to move in the direction of FolderA or FolderB or FolderC highly appreciated so I have a starting point. Delphi or C++ Builder examples are both welcome (the final code will be in C++ Builder though).

Kentiga answered 3/12, 2014 at 15:19 Comment(4)
You can handle the OnMeasureTextWidth event to provide the overall text width and render both texts in the OnDrawText event handler. But I would personally use 2 columns, which would allow the users to always see the count.Exemplification
@Exemplification I agree that 2 column does have its advantages and it is likely I will switch to that at later time. But at this moment I need a quick solution and toShowStaticText does exactly that. It is unfortunate I can only accept only one answer as both of your answers are good solutions.Kentiga
I don't see anyhow more complicated handling the OnPaintText and switching on Column in case of two columns.Exemplification
@Exemplification OK, maybe I wasn't clear enough - "FolderA" was first choice, the B and C variants were just plans B or C if A doesn't work out. The "quick" part was that I don't need to introduce some additional code to handle columns (not the VirtualTree code that one is indeed rather simple but some other extras). I really do appreciate the answer you offered I will surely upvote it if you add it as additional answer (I am sure someone else will prefer it over my preference too, so it will get more upvotes that's for sure!).Kentiga
S
13

You could simply use the toShowStaticText (StringOptions) option:

implementation

type
  PNodeRec = ^TNodeRec;
  TNodeRec = record
    Name: WideString;
    Count: Integer;
    IsBold: Boolean;
  end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Node: PVirtualNode;
  NodeRec: PNodeRec;
  I: Integer;
begin
  VirtualStringTree1.TreeOptions.StringOptions := 
    VirtualStringTree1.TreeOptions.StringOptions + [toShowStaticText];
  VirtualStringTree1.NodeDataSize := Sizeof(TNodeRec);
  // Populate some data
  for I := 1 to 10 do
  begin
    Node := VirtualStringTree1.AddChild(nil);
    NodeRec := VirtualStringTree1.GetNodeData(Node);
    Initialize(NodeRec^);
    NodeRec.Name := 'Node' + IntToStr(I);
    NodeRec.Count := I;
    NodeRec.IsBold := I mod 2 = 0;
  end;
end;

procedure TForm1.VirtualStringTree1GetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
var
  NodeRec: PNodeRec;
begin
  NodeRec := PNodeRec(TVirtualStringTree(Sender).GetNodeData(Node));
  if TextType = ttNormal then
    CellText := NodeRec^.Name
  else // ttStatic
    CellText := Format('(%d)', [NodeRec^.Count]);
end;

procedure TForm1.VirtualStringTree1PaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  NodeRec: PNodeRec;
begin
  NodeRec := PNodeRec(TVirtualStringTree(Sender).GetNodeData(Node));
  if TextType = ttNormal then
  begin
    if NodeRec^.IsBold then
      TargetCanvas.Font.Style := TargetCanvas.Font.Style + [fsBold];
  end
  else // ttStatic
    TargetCanvas.Font.Color := clRed;
end;

Output:

enter image description here

Sturm answered 3/12, 2014 at 16:25 Comment(4)
That was way too easy! I just tried it out and works great, thanks a million! The only minor problem I have now is that the static part is a bit too much on the right side (like one extra space or so). Can this left-margin of the ttStatic (or right-margin of ttNormal) be adjusted too?Kentiga
I'm not aware of a build-in feature like this (but I'm also using a rather old version of VT). You could handle the drawing on PaintText event (and not handle the GetText for ttStatic). you have the Canvas + TargetCanvas. position the text as you wish.Sturm
+ you have the TextMargin property. which will affect both normal and static text.Sturm
Ad custom text drawing in current version; do not draw in the OnPaintText event (at most prepare the font for the canvas there). Draw in the OnDrawText event (don't forget to set DefaultDraw to False). Except that you may need to re-measure the node text rectangle (e.g. width in the OnMeasureTextWidth event) to match your variable font settings and texts to be rendered (that's what my answer was about).Exemplification

© 2022 - 2024 — McMap. All rights reserved.