Lazarus

Programming => General => Topic started by: Jvan on August 18, 2020, 06:08:26 am

Title: StringGrid: How to avoid moving rows over/under some rows?
Post by: Jvan on August 18, 2020, 06:08:26 am
This is the situation:
I have a Grid with 9 rows, with "goRowMoving" property in True. But I need this constraint: rows that are from 1 to 5 can only be  moved among them, and rows that are from 6 to 9 can only be moved among them.

So, I have this code:

Code: Pascal  [Select][+][-]
  1.  
  2. procedure TForm1.StringGrid1ColRowMoved(Sender: TObject; IsColumn: Boolean;
  3.   sIndex, tIndex: Integer);
  4. begin
  5.  
  6.   if not(IsColumn) then begin  //Only rows
  7.     if (sIndex <= 5) and (tIndex > 5) then
  8.       //AVOID MOVING    
  9.     else if (sIndex > 5) and (tIndex <= 5) then
  10.       //AVOID MOVING
  11.   end;
  12.  
  13.  
  14. end;
  15.  
  16.  

But what code must I use to avoid moving the selected row (sIndex) in that cases?
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Handoko on August 18, 2020, 06:42:39 am
Can you tell us what program you are currently building?

You can use a TTimer to move user active cell to wherever you want, which also means to move them back if they try to access non-allowed location.

It's not exactly what you want but with some modification it should work, here is the discussion:
https://forum.lazarus.freepascal.org/index.php/topic,37286.msg250229.html (https://forum.lazarus.freepascal.org/index.php/topic,37286.msg250229.html)
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Jvan on August 18, 2020, 09:27:31 pm
Can you tell us what program you are currently building?

You can use a TTimer to move user active cell to wherever you want, which also means to move them back if they try to access non-allowed location.

It's not exactly what you want but with some modification it should work, here is the discussion:
https://forum.lazarus.freepascal.org/index.php/topic,37286.msg250229.html (https://forum.lazarus.freepascal.org/index.php/topic,37286.msg250229.html)

An accounting software-
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: winni on August 18, 2020, 09:37:01 pm
Hi!

Just filter out the possible combinations.
The illegal combinations are avoided.

Code: Pascal  [Select][+][-]
  1.  
  2. procedure TForm1.StringGrid1ColRowMoved(Sender: TObject; IsColumn: Boolean;
  3.   sIndex, tIndex: Integer);
  4. const set1 = [1..5];
  5.          set2= [6 ..9];
  6. begin
  7.  
  8.   if not(IsColumn) then
  9.      begin  //Only rows
  10.     if ((sIndex in Set1) and (tIndex in Set1) )
  11.       OR
  12.   ((sIndex in Set2) and (tIndex in Set2)) then
  13.     begin
  14.       // MOVE!!!
  15.      end;
  16.   end;
  17.  
  18. end;


Winni
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Blaazen on August 18, 2020, 09:45:55 pm
Winni: This won't help. The row is moved and then is triggered event. You cannot restrict the move from the event.
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Handoko on August 18, 2020, 09:49:25 pm
An accounting software-

That explains why you need a powerful grid. Maybe you can consider this:

http://www.scalabium.com/smdbgrid.htm

Unfortunately it is not for Lazarus.
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: winni on August 18, 2020, 09:56:59 pm
Winni: This won't help. The row is moved and then is triggered event. You cannot restrict the move from the event.

Thanx Blaazen!

Arghhh! I forgot that.

So you have to do it the hard way:
Whenever something changes in the Grid  make an Undo-Copy before the action.
If the row exchange is a unwanted make an Undo.
Sounds like a lot of work.

Winni


Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Scoops on August 18, 2020, 10:03:44 pm
Depending on your data, why not use 2 stringgrids one with 5 rows the other with 4, even place them together to resemble only one grid ? I did this once and it works ok, but like i said it depends on your data.
read you first 5 lines then 4 etc etc. just looping through your data to split between stringgrids.
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Blaazen on August 18, 2020, 10:07:33 pm
If those moves should be done by mouse only, I would use OnMouseDown/Up events and manage it myself and by-pass built in row moving completly.
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Jvan on August 18, 2020, 10:16:19 pm
Well, my explanation is only an example. The grid could contain many groups of rows and that rows must be only exchanged between rows of the same group.


Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: winni on August 18, 2020, 10:17:06 pm
Hi!

I can enhance my source to switch the rows back:


Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1ColRowMoved(Sender: TObject; IsColumn: Boolean;
  2.   sIndex, tIndex: Integer);
  3. const set1 = [1..5];
  4.          set2= [6 ..9];
  5. begin
  6.  
  7.   if not(IsColumn) then
  8.      begin  //Only rows
  9.     if
  10.    NOT (
  11.     ((sIndex in Set1) and (tIndex in Set1) )
  12.       OR
  13.      ((sIndex in Set2) and (tIndex in Set2))
  14.    )
  15.   then
  16.     begin
  17.       StringGrid1.MoveColRow(false, tIndex,sIndex);
  18.      end;
  19.   end;
  20.  
  21. end;
  22.  

Winni
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Jvan on August 18, 2020, 10:19:35 pm
What about the OnColRowExchanged event? How to exchange rows by code? I just thought I can exchange rows after the OnColRowMoved event.
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Blaazen on August 18, 2020, 10:24:34 pm
So managing Row moving by code is quite easy. It needs just two events (OnMouseDown/Up) and one global var.

Code: Pascal  [Select][+][-]
  1. procedure TForm18.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2. var aPt: TPoint;
  3. begin
  4.   aPt:=StringGrid1.MouseToCell(Point(X, Y));
  5.   if aPt.X=0 then
  6.     begin
  7.       writeln('From', aPt.Y);
  8.       ReadyRow:=aPt.Y;
  9.     end else
  10.     ReadyRow:=-1;
  11. end;
  12.  
  13. procedure TForm18.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  14. var aPt: TPoint;
  15. begin
  16.   aPt:=StringGrid1.MouseToCell(Point(X, Y));
  17.   if (aPt.X=0) and (ReadyRow>0) then
  18.     begin
  19.       writeln('To', aPt.Y);
  20.       StringGrid1.MoveColRow(False, ReadyRow, aPt.Y);
  21.     end;
  22.   ReadyRow:=-1;
  23. end;

With this, you can move rows by dragging on the leftmost column.
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Jvan on August 18, 2020, 10:29:46 pm
Hi!

I can enhance my source to switch the rows back:


Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1ColRowMoved(Sender: TObject; IsColumn: Boolean;
  2.   sIndex, tIndex: Integer);
  3. const set1 = [1..5];
  4.          set2= [6 ..9];
  5. begin
  6.  
  7.   if not(IsColumn) then
  8.      begin  //Only rows
  9.     if
  10.    NOT (
  11.     ((sIndex in Set1) and (tIndex in Set1) )
  12.       OR
  13.      ((sIndex in Set2) and (tIndex in Set2))
  14.    )
  15.   then
  16.     begin
  17.       StringGrid1.MoveColRow(false, tIndex,sIndex);
  18.      end;
  19.   end;
  20.  
  21. end;
  22.  

Winni

I had the error of the image.
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Jvan on August 18, 2020, 10:59:33 pm
So managing Row moving by code is quite easy. It needs just two events (OnMouseDown/Up) and one global var.

Code: Pascal  [Select][+][-]
  1. procedure TForm18.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2. var aPt: TPoint;
  3. begin
  4.   aPt:=StringGrid1.MouseToCell(Point(X, Y));
  5.   if aPt.X=0 then
  6.     begin
  7.       writeln('From', aPt.Y);
  8.       ReadyRow:=aPt.Y;
  9.     end else
  10.     ReadyRow:=-1;
  11. end;
  12.  
  13. procedure TForm18.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  14. var aPt: TPoint;
  15. begin
  16.   aPt:=StringGrid1.MouseToCell(Point(X, Y));
  17.   if (aPt.X=0) and (ReadyRow>0) then
  18.     begin
  19.       writeln('To', aPt.Y);
  20.       StringGrid1.MoveColRow(False, ReadyRow, aPt.Y);
  21.     end;
  22.   ReadyRow:=-1;
  23. end;

With this, you can move rows by dragging on the leftmost column.

The rows don't move with up/down keys and I have an error when clicking the row header.


Code: Pascal  [Select][+][-]
  1.  
  2. unit Unit1;
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Grids;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     StringGrid1: TStringGrid;
  17.     procedure StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
  18.       Shift: TShiftState; X, Y: Integer);
  19.     procedure StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  20.       Shift: TShiftState; X, Y: Integer);
  21.   private
  22.  
  23.   public
  24.  
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.   ReadyRow: Integer;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37.  
  38.  
  39. procedure TForm1.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
  40.   Shift: TShiftState; X, Y: Integer);
  41. var aPt: TPoint;
  42. begin
  43.   aPt:=StringGrid1.MouseToCell(Point(X, Y));
  44.   if aPt.X=0 then
  45.     begin
  46.       writeln('From', aPt.Y);
  47.       ReadyRow:=aPt.Y;
  48.     end else
  49.     ReadyRow:=-1;
  50. end;
  51.  
  52. procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  53.   Shift: TShiftState; X, Y: Integer);
  54. var aPt: TPoint;
  55. begin
  56.   aPt:=StringGrid1.MouseToCell(Point(X, Y));
  57.   if (aPt.X=0) and (ReadyRow>0) then
  58.     begin
  59.       writeln('To', aPt.Y);
  60.       StringGrid1.MoveColRow(False, ReadyRow, aPt.Y);
  61.     end;
  62.   ReadyRow:=-1;
  63. end;
  64.  
  65. end.    
  66.  
Title: Re: StringGrid: How to avoid moving rows over/under some rows?
Post by: Jvan on August 18, 2020, 11:21:23 pm
Finally, I did it.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1ColRowMoved(Sender: TObject; IsColumn: Boolean;
  2.   sIndex, tIndex: Integer);
  3. begin
  4.   if not(IsColumn) and (StringGrid1.Tag = 0) then begin  //Only rows
  5.     if (sIndex <= 5) and (tIndex > 5) then begin
  6.       //AVOID MOVING
  7.       StringGrid1.Tag := 1;
  8.       ShowMessage('Error: La fila que desea mover no corresponde al grupo de su nuevo lugar.');
  9.       StringGrid1.MoveColRow(false, tIndex, sIndex);
  10.       StringGrid1.Tag := 0;
  11.     end else if (sIndex > 5) and (tIndex <= 5) then begin
  12.       //AVOID MOVING
  13.       StringGrid1.Tag := 1;
  14.       ShowMessage('Error: La fila que desea mover no corresponde al grupo de su nuevo lugar.');
  15.       StringGrid1.MoveColRow(false, tIndex, sIndex);
  16.       StringGrid1.Tag := 0;
  17.     end;
  18.   end;
  19. end;
  20.  
  21.  
TinyPortal © 2005-2018