Lazarus

Programming => LCL => Topic started by: dbannon on January 31, 2020, 03:09:19 am

Title: TStringGrid sort indicator
Post by: dbannon on January 31, 2020, 03:09:19 am
TStringGrid can have its top row set as a heading and if the user clicks one of its (button like) cells the grid is sorted according to that column. We get nice little green triangles indicating its sorted on that column.

You can also sort programmatically, eg StringGrid1.SortColRow(True, 1);   But that does not set the green triangles or even cancel green triangles that may be there from previous user interaction.

Is there some way we can, programmatically, turn the green triangles off or ideally, move them to the now relevant column ?

David
Title: Re: TStringGrid sort indicator
Post by: GAN on January 31, 2020, 03:50:39 am
Yes, to delete the arrow:

Code: Pascal  [Select][+][-]
  1. StringGrid1.Columns[0].Title.ImageIndex:=-1;

then you can use a TImageList in  the property TitleImageList.
Title: Re: TStringGrid sort indicator
Post by: dbannon on January 31, 2020, 06:02:38 am

Thanks GAN but I don't seem to be able to access the columns property. My (test) grid has two visible columns containing data but there are zero columns and an attempt to call what you suggested gives an error.  My code eg -

Code: Pascal  [Select][+][-]
  1.     Grid.Clear;
  2.     Grid.FixedRows := 0;
  3.     Grid.FixedCols := 0;
  4.     Grid.InsertRowWithValues(0, ['Title', 'Last Change']);
  5.     Grid.FixedRows := 1;
  6.     Grid.InsertRowWithValues(Grid.RowCount, ['A Item', 'Z Item']);
  7.     Grid.InsertRowWithValues(Grid.RowCount, ['B Item', 'X Item']);
  8.     DebugLn('Column count is ' + inttostr(Grid.Columns.Count));
  9.     // Above line prints 'Column count is 0'    
     

I don't understand how Grid.Columns.Count is zero but I can see two columns ....

Davo
             
Title: Re: TStringGrid sort indicator
Post by: HeavyUser on January 31, 2020, 06:16:42 am
there are two different mechanisms that support columns
1) the colCount property and friends for delphi/backward compatibility
2) columns property and friends a newer never cought up construct.

Probably they should be seperated to two controls to avoid confusion or at least sync them in to a single mechanism.
Title: Re: TStringGrid sort indicator
Post by: dbannon on January 31, 2020, 07:44:09 am
Thanks HeavyUser, thats explains a lot for me.  What I was finding was seriously confusing.

I think this is the Lazarus style -
Code: Pascal  [Select][+][-]
  1.     Grid.Clear;
  2.     Grid.FixedCols := 0;
  3.     Grid.Columns.Add;
  4.     Grid.Columns[0].Title.Caption := 'Name';
  5.     Grid.Columns.Add;
  6.     Grid.Columns[1].Title.Caption := 'Last Change';
  7.     Grid.FixedRows:=1;
  8.     Grid.InsertRowWithValues(Grid.RowCount, ['A Item', 'Z Item']);
  9.     Grid.InsertRowWithValues(Grid.RowCount, ['B Item', 'X Item']);
           

And I can get the result on screen that I expect.  And calling StringGrid1.Columns[0].Title.ImageIndex:=-1; as suggested by GAN does not crash it like the way I was doing it did. 

However, GAN's call does not make any difference to the little green triangle, it won't turn it off.  Nor will setting the value to 0 (as suggested by the help files) turn it off.  Setting a positive value such as 1 won't turn it on either.

Hmm....

Davo

 
Title: Re: TStringGrid sort indicator
Post by: GAN on January 31, 2020, 08:48:25 pm
Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1HeaderClick(Sender: TObject; IsColumn: Boolean; Index: Integer);
  2. begin
  3.   StringGrid1.Columns[Index].Title.ImageIndex:=-1;
  4. end;    

Works fine for me. Green triangles are never displayed.
Title: Re: TStringGrid sort indicator
Post by: GAN on January 31, 2020, 11:54:25 pm
Hi Dbannon sees the attachment, it can be helpful.
Title: Re: TStringGrid sort indicator
Post by: dbannon on February 01, 2020, 12:46:34 am
Thanks for that Gan, but I see both green and black triangles. your code only controls the black one, the green triangle changes because the click is to the header, not because of the code.

If you move the code out of the StringGrid1HeaderClick() into, say, a Button1Click(), it only controls the black triangle you have added via the image list, it has no effect on the green triangle that is "Built In" to TStringGrid. See -

Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1HeaderClick(Sender: TObject; IsColumn: Boolean; Index: Integer);
  2. begin
  3.  // StringGrid1.Columns[Index].Title.ImageIndex:=-1;
  4. {  if StringGrid1.SortOrder=soAscending then
  5.     StringGrid1.Columns[Index].Title.ImageIndex:=0
  6.   else
  7.     StringGrid1.Columns[Index].Title.ImageIndex:=1; }
  8. end;
  9.  
  10. procedure TForm1.Button1Click(Sender: TObject);
  11. begin
  12.    if (StringGrid1.Columns[0].Title.ImageIndex = 0) then
  13.         StringGrid1.Columns[0].Title.ImageIndex:=1
  14.    else
  15.         StringGrid1.Columns[0].Title.ImageIndex:=0;
  16. end;  
                 

With that code, clicking the button, we can toggle the black triangle up and down but the green one is not affected.  In this image I have clicked the header (to sort the column and display the green triangle) and then clicked the button multiple times. Each click inverts the black triangle but not the green.

I am on Linux (U18.04 Mate) running a GTK2 app. Are you using Qt5 perhaps or Win/Mac ? 

Davo
                             
Title: Re: TStringGrid sort indicator
Post by: GAN on February 01, 2020, 01:00:43 am
I use Linux Mint 17.2 MATE Gtk-2

Please watch the attached video.
Title: Re: TStringGrid sort indicator
Post by: GAN on February 01, 2020, 01:37:00 am
And works fine adding a button too.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids,
  9.   Buttons, StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     ImageList1: TImageList;
  18.     StringGrid1: TStringGrid;
  19.     procedure Button1Click(Sender: TObject);
  20.     procedure StringGrid1HeaderClick(Sender: TObject; IsColumn: Boolean;
  21.       Index: Integer);
  22.   private
  23.     procedure CleanHeaders(selCol:Integer);
  24.   public
  25.  
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.StringGrid1HeaderClick(Sender: TObject; IsColumn: Boolean; Index: Integer);
  38. begin
  39.  // StringGrid1.Columns[Index].Title.ImageIndex:=-1;
  40.   if StringGrid1.SortOrder=soAscending then
  41.     StringGrid1.Columns[Index].Title.ImageIndex:=0
  42.   else
  43.     StringGrid1.Columns[Index].Title.ImageIndex:=1;
  44. end;
  45.  
  46. procedure TForm1.CleanHeaders(selCol: Integer);
  47. var
  48.   i:Integer;
  49. begin
  50.   for i:=0 to StringGrid1.ColCount-1 do
  51.     if i<>selCol then
  52.       StringGrid1.Columns[i].Title.ImageIndex:=-1;
  53. end;
  54.  
  55. procedure TForm1.Button1Click(Sender: TObject);
  56. begin
  57.   if StringGrid1.SortOrder=soAscending then
  58.     begin
  59.       StringGrid1.SortOrder:=soDescending;
  60.       StringGrid1.SortColRow(True,StringGrid1.SelectedColumn.Index);
  61.       StringGrid1.Columns[StringGrid1.SelectedColumn.Index].Title.ImageIndex:=1
  62.     end
  63.   else
  64.     begin
  65.       StringGrid1.SortOrder:=soAscending;
  66.       StringGrid1.SortColRow(True,StringGrid1.SelectedColumn.Index);
  67.       StringGrid1.Columns[StringGrid1.SelectedColumn.Index].Title.ImageIndex:=0;
  68.     end;
  69.     CleanHeaders(StringGrid1.SelectedColumn.Index);
  70. end;
  71.  
  72. end.  
Title: Re: TStringGrid sort indicator
Post by: dbannon on February 02, 2020, 12:41:58 am
Stranger and stranger.
Firstly, I cannot view your Video GAN, can see something in there but nothing I can identify.

I note your tag mentions that you are using Lazarus 1.8.4, I guess thats not accurate but what version of Lazarus are you using ??

I am using fixes_2_0, the oldest one I have installed is 2.0.4 so I might try that. 

Perhaps the issue for me is that the default small green triangle is not being hidden when I  install your black indicators from the imagelist. What do you see if you don't use the imagelist ?  Do you then see the default green triagles show in my attached picture above ? And if you can see the green triangles, can you turn them on and off in the same manner that you can control your own black ones ?

I'll fire up my 2.0.4 and see how that behaves.

Davo
Title: Re: TStringGrid sort indicator
Post by: dbannon on February 02, 2020, 01:27:13 am
OK, I found a copy of Lazarus 2.0.0 and that behaves, for me, just like Lazarus 2.0.7.

GAN, just to be clear, can you please try the attached version of your demo.  In my case, with Lazarus 2.0.0 to 2.0.7 it treats the default green triangle as a completely different thing from the black triangle you add with the image list.

If you click the grid header the green one shows. Click the toggle button and the black one shows and the green one remains visible.  I can see both the green AND the black triangle. Continued clicking of the toggle button makes the black triangle point up or down, it does not do anything to the green triangle.

Click the Black Off button, the black triangle hidss, the green one remains visible. 

The only way to interact with the green triangle is by clicking the grid heading.

GAN, it sounds like your experiences here are different to mine, why ?

Davo

Title: Re: TStringGrid sort indicator
Post by: GAN on February 02, 2020, 05:44:15 am
Stranger and stranger.
Firstly, I cannot view your Video GAN, can see something in there but nothing I can identify.

I note your tag mentions that you are using Lazarus 1.8.4, I guess thats not accurate but what version of Lazarus are you using ??
Lazarus 1.8.4 - Free Pascal 3.0.4
Quote
I am using fixes_2_0, the oldest one I have installed is 2.0.4 so I might try that.
Maybe.

Quote
Perhaps the issue for me is that the default small green triangle is not being hidden when I  install your black indicators from the imagelist. What do you see if you don't use the imagelist ?
I don't see any triangles.

Quote
Perhaps the issue for me is that the default small green triangle is not being hidden when I  install your black indicators from the imagelist. What do you see if you don't use the imagelist ?  Do you then see the default green triagles show in my attached picture above ? And if you can see the green triangles, can you turn them on and off in the same manner that you can control your own black ones ?
Yes, I see your attached image, but in my evidence, I never saw both triangles in the same column. And yes, I can turn them off.

I'll fire up my 2.0.4 and see how that behaves.

Davo
[/quote]
Title: Re: TStringGrid sort indicator
Post by: GAN on February 02, 2020, 06:01:53 am
OK, I found a copy of Lazarus 2.0.0 and that behaves, for me, just like Lazarus 2.0.7.

GAN, just to be clear, can you please try the attached version of your demo.  In my case, with Lazarus 2.0.0 to 2.0.7 it treats the default green triangle as a completely different thing from the black triangle you add with the image list.

If you click the grid header the green one shows. Click the toggle button and the black one shows and the green one remains visible.
Quote
I'm running the project you've attached and.. . no, green is not visible.

Quote
I can see both the green AND the black triangle. Continued clicking of the toggle button makes the black triangle point up or down, it does not do anything to the green triangle.
Clicking Black Off all triangles disapear, in case there are one black on one column and one green in the other, both of them disapear.

Quote
Click the Black Off button, the black triangle hidss, the green one remains visible. 

The only way to interact with the green triangle is by clicking the grid heading.

GAN, it sounds like your experiences here are different to mine, why ?

Davo

Here: https://drive.google.com/open?id=1QD9ncbeQsk0RJeTJRMN0_vnH4kz1ziUp (https://drive.google.com/open?id=1QD9ncbeQsk0RJeTJRMN0_vnH4kz1ziUp) you have the video and the project working OK.
Please compile this project and tells me what happend?

GAN.
Title: Re: TStringGrid sort indicator
Post by: dbannon on February 02, 2020, 12:41:42 pm
Lazarus 1.8.4 - Free Pascal 3.0.4
......
Clicking Black Off all triangles disapear, in case there are one black on one column and one green in the other, both of them disapear.
OK, that seems to be the key difference then.  In my case, that Black Off button turns only the Black one off. So, wonder if its the version of Lazarus ?  I have tested both 2.0.0 and 2.0.7 and in both of them the "Black Off" button only turns off the black triangle (the triangle from the imagelist).

Just to be clear, what I want to do is move the triangle (either green or black but not both!) from one column to the other. And turn it on for a grid that the user has not yet clicked the heading in.

Its seems those green triangles have been there for some time, Juha and WP mention them here https://forum.lazarus.freepascal.org/index.php/topic,36664.msg244630.html#msg244630
WP mentions "icons cannot be changed" but Juha says they can but he cannot remember. I assume he is refering to your trick.

I followed your link to google drive but the video there has same problem, I assume I don't have the right codec installed, It downloads and plays but is unintelligible.  I downloaded and compiled (2.0.7) the project there. It shows me the green triangles when I click the grid headers and the black ones if I click button1.    Button1 reverses the sort direction but does not alter the column being sorted (and its not intended to).

With another couple of buttons and a bit of code I can turn off the black triangles easily, but I cannot turn off the green ones, I cannot for example, turn off the green one in column 0 and turn it on in column 1. Once the user has clicked a column header, the green triangle appears (even if the black one is already there) and it cannot be removed.

Maybe I need to go back to 1.8.4 and see if that works for me as expected ?  "Something" has gone wrong since then !

GAN, I really appreciate the effort you are putting in here, thanks !

Davo





Davo
Title: Re: TStringGrid sort indicator
Post by: dbannon on February 03, 2020, 01:54:39 am
OK, my conclusions are that the TStringGrid sort indicators are broken but I am not willing to log a bug unless someone else (using a current Lazarus) can confirm my results. GAN does not see this problem using 1.8.4. Here is what I have found, possibly due to using Lazarus 2.0.0 thru to 2.0.7  -


   
In my case I refresh the grid's data from time to time. The data is presorted on what becomes column 1 and while I would prefer to indicate that column 1 is now the sorted against column, I cannot change those green triangles !

So, instead of making the grid display what I want it to, I can may the data I insert agree with what the grid is claiming to be displaying. Yek !

Code: Pascal  [Select][+][-]
  1.  procedure TForm1.PopulateStringGrid(Grid : TStringGrid);
  2. begin
  3.     while Grid.RowCount > 1 do Grid.DeleteRow(Grid.RowCount-1);
  4.     Grid.InsertRowWithValues(Grid.RowCount, ['A Item', 'Z Item']);
  5.     Grid.InsertRowWithValues(Grid.RowCount, ['B Item', 'Y Item']);
  6.     Grid.InsertRowWithValues(Grid.RowCount, ['C Item', 'X Item']);
  7.     // My data is sorted on column 1, if user has not changed that, we do nothing.
  8.     if Grid.SortColumn > -1 then
  9.         Grid.SortColRow(True, Grid.SortColumn);            // Force data to be same as StringGrid claims its displaying
  10. end;
                           

If someone else can confirm this situation, I will log a bug report.

Thanks GAN and HeavyUser for your help here.

David
Title: Re: TStringGrid sort indicator
Post by: GAN on February 04, 2020, 03:10:29 am
Quote
If someone else can confirm this situation, I will log a bug report.
Hi dbannon, do it, because nobody else is writting in this thread. Or it's a bug or a new feature of Lazarus 2.0.x  ;)
Seriously, the green arrows are horrible (sorry), so must be a bug.
Title: Re: TStringGrid sort indicator
Post by: apeoperaio on February 04, 2020, 08:35:07 am
I got a similar issue only using cocoa, see thread https://forum.lazarus.freepascal.org/index.php/topic,48333.0.html
I can disable the green lazarus arrows using:
TStringGrid.ColumnClickSort := False;

Hope it helps.
Title: Re: TStringGrid sort indicator
Post by: dbannon on February 04, 2020, 09:36:52 am
Hey GAN, I just used her Ladyship's laptop, it shows your video perfectly. And leave no doubt what you are getting is very, very different to wha I see on Lazarus 2something

And, interesting, your green arrows are, as you say, very ugly. On 2 series they are much more modest small green triangles. Thats an improvement at least ! But that change may be where our problem started.

Thanks for chiming in apeoperaio, from what you say, you get what you expect from Windows and Linux but experience problems only on Cocoa ?  But I see this on Linux. Are you using the same version of Lazarus on each platform ?

I feel this (what ever 'this' is) needs to be logged but I so don't understand it right now so will do some more testing. I can go to Windows and MacOS as well as my prefered Linux so, I'll add in a  apeoperaio trick and install a 1.8.4, watch this space !

Davo
Title: Re: TStringGrid sort indicator
Post by: apeoperaio on February 04, 2020, 09:52:05 am
Under cocoa I am using Lazarus 2.0.7 r62571M FPC 3.0.4 x86_64-darwin-cocoa (alpha)
While on Windows and Linux lazarus 1.8.4
Title: Re: TStringGrid sort indicator
Post by: dbannon on February 05, 2020, 12:31:07 am
Under cocoa I am using Lazarus 2.0.7 r62571M FPC 3.0.4 x86_64-darwin-cocoa (alpha)
While on Windows and Linux lazarus 1.8.4

Ah, good (sort of). That confirms its the transition from 1.8.4 to 2.0 that is the problem.

Attached is the demo that I will put in with the bug report.  It makes the point that in the 2.0 series -

* you cannot, programmatically, control the built in, green indicators.
* the built in images look heaps better than in 1.8.4
* if you add your own image list, and use them, when the end user clicks a heading, they may get both indicators displayed.

While its nice not to have to provide your own imagelist, too many applications involve refreshing the data and it may not be sorted in the manner the user has set it to.

(for the record, I have set my app to re-sort new data to whatever the Grid currently thinks it is sorted to : 
Code: Pascal  [Select][+][-]
  1. if Grid.SortColumn > -1 then
  2.         Grid.SortColRow(True, Grid.SortColumn);

)
Davo
Title: Re: TStringGrid sort indicator
Post by: wittbo on May 12, 2021, 08:30:19 pm
Perhaps I should start a new topic, but this context is quite precise.

I'm sure, I found the solution. When analyzing the unit grids, one can see, that the behavior of the small green triangle depends on the internal variable FSortColumn. FSortColumn is the number of the column actually sorted, it is -1 if not sorted. Unfortunately the property SortColumn is not writable. I made a check with a copy of the grids unit and modified the property SortColumn as readable AND writable. That's it.

If you set SortColumn to a value of greater or equal 0, the triangle appears, if set to -1, the triangle disappears; changing SortOrder changes the triangle up or down.

The header click routine sets the value of FSortColumn to the column number the user clicked; unfortunately the procedure SortColRow doesn't do so. Therefore the triangle does not appear, when you call SortColRow without clicking into the column header.

I think, it could be a good idea to make few modifications to TCustomGrid:
- property SortOrder: add a setting routine SetSortOrder, which invalidates the grid after setting the value
- property SortColumn: add a setting routine SetSortColumn, which checks the column number and invalidates the grid after setting the value
- Modify SortColRow: add a line    FSortColumn := index;
TinyPortal © 2005-2018