Recent

Author Topic: TListView - Canvas.Font not implemented?  (Read 10893 times)

Dick, from the internet

  • Full Member
  • ***
  • Posts: 198
TListView - Canvas.Font not implemented?
« on: July 24, 2011, 09:29:12 pm »
BLUF: I have not been able to change the font style or color for just a single line within a TListView.

I have been working on this for most of two days now and would like another set of eyes on it to ensure I haven't overlooked something entirely obvious.  I have also searched this forum as well as the bug tracker and have not seen any issues addressing this particular problem - I may have missed that even.

The problem:  I have a TListView control that I have populated with a list of names.  While the control is populating, it calls AdvancedCustomDrawItem where I check if a single line meets my criteria (in the case of the example, if the name contains the word 'Van').  If the word is present, the line should be displayed with a bold, red font.

I have done the same thing with a TTreeView control, and it works correctly (to my expectations, at any rate!).

Here is my test project code:
Code: [Select]
unit tviewtest;
(*
  created with Lazarus
  version #: 0.9.30
  Date: 2011-06-26
  FPC Version: 2.4.2
  SVN Revision: unknown
  x86_64-linux-gtk 2

  machine info:
  AMD64
  Linux (Fedora 14) 64bit
*)
{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
  StdCtrls, ButtonPanel, ShellCtrls, ExtCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    ListView1: TListView;
    StatusBar1: TStatusBar;
    TreeView1: TTreeView;
    procedure Button1Click(Sender: TObject);
    procedure ListView1AdvancedCustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
      var DefaultDraw: Boolean);
    procedure ListView1CustomDrawItem(Sender: TCustomListView; Item: TListItem;
      State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
      Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
      var PaintImages, DefaultDraw: Boolean);
    procedure TreeView1CustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
      State: TCustomDrawState; var DefaultDraw: Boolean);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;


implementation

{$R *.lfm}

{ TForm1 }


// LISTVIEW ***************************************


procedure TForm1.ListView1AdvancedCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
  var DefaultDraw: Boolean);
begin
  if (pos('Van', Item.Caption) > 0) then
    begin
      statusbar1.Panels[0].Text := 'this text demonstrates that AdvancedCustomDrawItem event is firing as it should';
      Sender.Canvas.Font.Color := clRed;
      Sender.Canvas.Font.Style := [fsBold];
    end
  else
  begin      //if you think the next two lines are the offenders, comment them out and try again
    Sender.Canvas.Font.Style := [];
    Sender.Canvas.Font.Color := clBlue;
  end;

  (* yes, I have even tried to change the font attributes this way
     un-comment this block and comment out the previous block to check *)
 { if (pos('Van', Item.Caption) > 0) then
    begin
      Sender.Font.Color := clRed;
      Sender.Font.Style := [fsBold];
    end
  else
  begin
    Sender.Font.Style := [];               //this sets the font and color for the
    Sender.Font.Color := clBlack;          //entire ListView
  end;         }

end;


procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  (* this has been commented out to ensure no conflicts with AdvancedCustomDrawItem
      but is here for testing purposes - only one or the other method is used at a
      time in the main program; if you uncomment this section, you should comment out
      the AdvancedCustomDrawItem method *)

{  if (pos('Van', Item.Caption) > 0) then
    begin
      Sender.Canvas.Font.Color := clRed;
      Sender.Canvas.Font.Style := [fsBold];
    end
  else
  begin
    Sender.Canvas.Font.Style := [];
    Sender.Canvas.Font.Color := clBlack;
  end;        }
end;



//BUTTON1 *****************************************

procedure TForm1.Button1Click(Sender: TObject);
  var LI : TListItem;
       f : textfile;
     str : string;
       i : integer;
begin
  (* even reloading the control after the form has finished painting has no effect *)
  i := 0;
  ListView1.Clear;
  statusbar1.Panels[0].Text := 'reloaded from text file';
  AssignFile(f, 'testfile');
  Reset(f);
  while not eof(f) do
    begin
(* when I un-comment this section, I also comment out the AdvancedCustomDrawItem section.
    this shows me that it is not just an issue with the CustomDrawItem methods*)
 {     if i = 0 then
        begin
          ListView1.Canvas.Font.Style := [fsBold];
          ListView1.Canvas.Font.Color := clRed;
        end
      else
        begin
          ListView1.Canvas.Font.Style := [];
          ListView1.Canvas.Font.Color := clBlue;
        end;                           }
      Readln(f, str);
      LI := ListView1.Items.Insert(0);
      LI.Caption := str;
      inc(i);
    end;
  CloseFile(f);
end;



//  TREEVIEW1 ***********************************

procedure TForm1.TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
  var PaintImages, DefaultDraw: Boolean);
begin
  if (pos('Van', Node.Text) > 0) then
    begin
      Sender.Canvas.Font.Color := clRed;
      Sender.Canvas.Font.Style := [fsBold];
    end
  else
  begin
    Sender.Canvas.Font.Style := [];
    Sender.Canvas.Font.Color := clBlue;
  end;
end;

procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  (* this has been commented out to ensure no conflicts with AdvancedCustomDrawItem
      but is here for testing purposes - only one or the other method is used at a
      time in the main program; if you uncomment this section, you should comment out
      the AdvancedCustomDrawItem method *)

{  if (pos('Van', Node.Text) > 0) then
    begin
      Sender.Canvas.Font.Color := clRed;
      Sender.Canvas.Font.Style := [fsBold];
    end
  else
  begin
    Sender.Canvas.Font.Style := [];
    Sender.Canvas.Font.Color := clBlack;
  end;     }
end;

end.
 

This is not a make or break for anything I am working on, but it sure is irritating; mainly because I just cannot leave it alone and move on to the rest of my application (personal fault)

I would appreciate any comments or a nudge in the right direction.

Thanks,
  geno.

« Last Edit: July 24, 2011, 09:37:10 pm by fleshmang »

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4571
  • I like bugs.
Re: TListView - Canvas.Font not implemented?
« Reply #1 on: July 24, 2011, 10:36:27 pm »
What OS and Lazarus version?
Is AdvancedCustomDrawItem called at all?
There are at least reports for LCL-Carbon:

19394: TListView.OnAdvancedCustomDraw never called in virtual mode
18513: TListView Carbon: onCustomDrawXYZ and OnAdvancedCustomDrawXYZ never fire ...

You can also search bug reports with "TListView". If you don't find one matching your problem, please create a new one.

Juha
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

Dick, from the internet

  • Full Member
  • ***
  • Posts: 198
Re: TListView - Canvas.Font not implemented?
« Reply #2 on: July 24, 2011, 11:02:59 pm »
My apologies; I had this information in the test code I pasted into my  post, but did not include it in the message body itself.
(*
  created with Lazarus
  version #: 0.9.30
  Date: 2011-06-26
  FPC Version: 2.4.2
  SVN Revision: unknown
  x86_64-linux-gtk 2

  machine info:
  AMD64
  Linux (Fedora 14) 64bit
*)

Quote
Is AdvancedCustomDrawItem called at all?
Yes it is, if you take a quick look at the example I posted, you will see that I put a statement to update the text in the statusbar; it works correctly.  I even created a routine that is executed from the buttonclick (after commenting out the routine in the CustomDraw) that should do the same outside of the AdvancedCustomDrawItem method.  It fails as well, though it will post text to the statusbar as it should.
Quote
There are at least reports for LCL-Carbon:

19394: TListView.OnAdvancedCustomDraw never called in virtual mode
18513: TListView Carbon: onCustomDrawXYZ and OnAdvancedCustomDrawXYZ never fire ...

I looked at those reports, and they address the CustomDraw/AdvancedCustomDraw; I do not think this is a problem with the method itself, but rather the .Canvas.Font.Style and .Canvas.Font.Color implementations.

The TListView control correctly updates the font, for the entire control, when using .Font.Style or .Font.Color (as I demonstrate in the code).

I hope I covered everything here.  Let me know if you need anything else.  Right now I am installing Lazarus on my WinXP VM and will see if I have the same issues on that platform.  I'll let you know my results (will probably take my slow-ass several hours! heh-heh)

Thanks,
  geno.


UPDATE:  just did a quick check on windows version:
(*
version #: 0.9.30
Date: 2011-03-08
FPC Version: 2.4.2
SVN Revision: 29749
i386-win32-win32/win64


This is running on a VMWare virtual machine hosted on the aforementioned Linux distro.
*)

This is what I found so far:  ListView implements .Canvas.Font.Color, but not the .Canvas.Font.Style, however, TreeView implements .Canvas.Font.Style but not the .Canvas.Font.Color (of course, everything worked the way it should on Turbo Delphi for Win)

Can someone verify that I haven't  goofed something?

geno.




« Last Edit: July 25, 2011, 12:31:18 am by fleshmang »

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4571
  • I like bugs.
Re: TListView - Canvas.Font not implemented?
« Reply #3 on: July 25, 2011, 05:53:01 pm »
> My apologies; I had this information in the test code I pasted into my  post, but did not include it in the message body itself.

No, my apologies, I should have read more carefully.
I don't know the TListView source well myself. You should either find an existing bug report about the problem or then create a new one. The report should include a (as simple as possible) demo application.

If you are able to fix the problem yourself then attach a patch with the report. :)

Juha
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

Dick, from the internet

  • Full Member
  • ***
  • Posts: 198
Re: TListView - Canvas.Font not implemented? [bug report submitted]
« Reply #4 on: July 26, 2011, 10:31:49 pm »
I have submitted a bug report for this issue, it can be viewed here:

http://mantis.freepascal.org/view.php?id=19816

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1263
Re: TListView - Canvas.Font not implemented?
« Reply #5 on: July 28, 2011, 08:21:29 am »
Fleshmag - Heh, we should be having the discussion about the Canvas drawing in here - feel free to post your reply here, I'll find it :-)
Lazarus Trunk/FPC Trunk on Windows [7, 10]
  Have you tried searching this forum or the wiki?:   http://wiki.lazarus.freepascal.org/Alternative_Main_Page
  BOOKS! (Free and otherwise): http://wiki.lazarus.freepascal.org/Pascal_and_Lazarus_Books_and_Magazines

felipemdc

  • Administrator
  • Hero Member
  • *
  • Posts: 3538
Re: TListView - Canvas.Font not implemented?
« Reply #6 on: July 28, 2011, 08:35:24 am »
TListView is a native control and as such one should expect that it might have issues with mixing custom drawing with it in some widgetsets (the most problematic ones are gtk2 and carbon. qt and win32/ce generally should work fine).

I think that the most reliable solution would be building a custom-drawn listview, just like there is TVirtualTreeView:

http://wiki.lazarus.freepascal.org/Lazarus_Custom_Drawn_Controls
http://wiki.lazarus.freepascal.org/VirtualTreeview

In fact, a custom-drawn TListView is something that I would like to see done for some time now.

Dick, from the internet

  • Full Member
  • ***
  • Posts: 198
Re: TListView - Canvas.Font not implemented?
« Reply #7 on: July 29, 2011, 04:41:25 am »
Quote
Fleshmag - Heh, we should be having the discussion about the Canvas drawing in here - feel free to post your reply here, I'll find it :-)
  For interested passers-by, Mike is referring to this thread  http://www.lazarus.freepascal.org/index.php/topic,13977.0.html

You are right - I have a tendency to just jump on and start typing, forgetting there are others around who might be interested in the back-and-forth here and would get lost on the mixed topics.  And furthermore, I have been pulled back to realize I have been chasing down the rabbit hole again and have strayed from my original assertion:  the TListView control does not implement the .Canvas.Font.Style nor the .Canvas.Font.Color properties in the AdvancedCustomDrawItem event, as does it's cousin, TTreeView control.

@felipemdc
Quote
TListView is a native control and as such one should expect that it might have issues with mixing custom drawing with it in some widgetsets (the most problematic ones are gtk2 and carbon. qt and win32/ce generally should work fine).

And you are right, I am certain there probably isn't any one perfect solution for each control - I suppose I could change over to qt, but I'll probably find that one of the other controls I use flakes out on me!  And here I am again.....<grin>

I spent some time this morning trying to reproduce the steps Mike described rebuilding the LCL, but I don't think I got the results that were expected; it was a clean build right back into the IDE - no command prompts nor make commands.  Guess I must have missed a step.  No big deal though, I did open up GTK2CustomListView.inc and looked through there until my eyes got tired (comes with old age, I guess), gave up and went back to work on a couple of projects -- All good fun! that's all this is to me....

As I have said, it is not a show-stopper for me, just an annoyance, and if I feel that I need to implement some of these 'cool functions' I'll just load up qt4 and have a go at it!!

Anyway, if you make any headway or major breakthroughs, give me a shout here.  Thanks again, guys!!


  geno.

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1263
Re: TListView - Canvas.Font not implemented?
« Reply #8 on: August 06, 2011, 10:40:24 pm »
Minor update - we're still missing some of the calls in GTK, but I have found that those Draw events that do work will correctly change the canvas.font style ONLY if you set DefaultDraw to false.   Unfortunately, this means you are now fully responsible for drawing both caption and icon (and this means you'll need to query GTK (or possibly the ListView - haven't investgated) for the correct caption and icon padding).    This differs from Win32 behaviour whereby if you set DefaultDraw to true (or simply leave it alone), then your canvas changes are kept.   Does give us a way forward for now though...
Lazarus Trunk/FPC Trunk on Windows [7, 10]
  Have you tried searching this forum or the wiki?:   http://wiki.lazarus.freepascal.org/Alternative_Main_Page
  BOOKS! (Free and otherwise): http://wiki.lazarus.freepascal.org/Pascal_and_Lazarus_Books_and_Magazines

 

TinyPortal © 2005-2018