Delphi
--
Questions
--
Followers
Top Experts
I wish to create an array of 10 elements and to add the undo steps.
In this array I wish to store 5 integers and 2 strings values fo each element of the array. How to do that?
On this moment I declare a class derived from TPersistent:
type TgnUndo:...
  FUndo1:integer;
  ........
  FUndo5:string;
........
  property Undo1:integer .....
But maybe exist a better way. This way create a problem when add the 11 step. Then I must delete ( clear ) the first undo, and move all next 9 elements down. The 10 will become clear and to let me to store this step.
I use :
 for i:=1 to 10 do begin
  FgnUndo[i].Undo1:=FgnUndo[
  ....
  end;
Can somebody figure out a better solution ? When I clear the first element to autodecrease the index for first 9 elements and to let me to have 10 element free.
Zero AI Policy
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
1.) Declare your data type:
 type
  PYourData = ^TYourData;
  TYourData = record
   Int1,Int2,Int3,Int4,Int5: integer;
   Str1,Str2: ShortString;
  end;
2.) Create an instance of your list:
  YourUndoList:= TList.Create;
3.) To add to your list do something like:
  procedure AddToList(SomeData: TYourData);
  var d: PYourData;
  begin
   New(d);
   d:= SomeData;
   yl.Add(d);
  end;
4.) You can remove items like this:
   var d : PYourData;
   ...
   d := YourUndoList.Items[0];
   YourUndoList.Delete(0);
   Dispose(d);
5.) remember to free the data before freeing the list when you're done:
   var d : PYourData;
   ...
   for i := 0 to (YourUndoList.Count - 1) do
   begin
    d := YourUndoList.Items[i];
    Dispose(d);
   end;
6.) Free the list when your done
Regards
Pierre
I would say, collections are the Delphi OOP way of doing what you need
The only thing I don't like about collections is that they get quite bulky (lot of code), but I can live with that because of all the benefits
you can read more about collections here:
http://delphi.about.com/library/bluc/text/uc083101d.htm
Oh, btw... You can easily walk through this list by using:
for I := 1 to 10 do FgnUndo[(Index+i) mod 10].DoSomething;
Be aware that normally, arrays are zero-based, though. But in this case, the +1 is useful because Index+1 is the first record in your list, and Index is last...






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
I also considered suggesting using a TStack or TObjectStack but felt that a TList would be better suited for ginsonic's need.
The problem with using an array is that you would have to reassign the array when applying a redo.
i.e. Say you had the following items in your array:
0. Action 1
1. Action 2
...
9.Action 10
Now you want to redo the last done item, so you perform Action 1 and now you need to set the array to the following:
0. Action 2
1. Action 3
...
8. Action 10

Get a FREE t-shirt when you ask your first question.
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
Something I forgot:
To limit the undo records to the last 10 only, you would do the following right after you've added a new undo record to your list:
While YourUndoList.Count >Â 10
 do YourUndoList.Delete(YourUn
program Test1;
{$APPTYPE CONSOLE}
const
 Max = 10;
type
 TDataItem = record
  Number: Integer;
  Name: string;
 end;
 TDataItemList = array[0..Max - 1] of TDataItem;
var
 DataItemList: TDataItemList;
 Index: Integer;
 Len: Integer;
var
 Line: string;
 I: Integer;
begin
 Randomize;
 Index := 0;
 Len := 0;
 repeat
  ReadLn(Line);
  if (Line = '+') then begin
   // Add an item to the list.
   DataItemList[Index].Number
   DataItemList[Index].Name := 'Name ' + Char(Ord('A') + Random(26));
   Index := (Index + 1) mod Max;
   if (Len < Max) then Len := Len + 1;
  end
  else if (Line = '-') then begin
   // Remove the last item in the list.
   Index := (Index + Max - 1) mod Max;
   DataItemList[Index].Number
   DataItemList[Index].Name := ''; // Optional...
   if (Len > 0) then Len := Len - 1; // Simple, isn't it? :)
  end
  else if (Line = '*') then begin
   // Remove the first item from the list.
   DataItemList[(Index + Max - Len) mod Max].Number := 0; // Optional...
   DataItemList[(Index + Max - Len) mod Max].Name := ''; // Optional...
   // Don't adjust the index!
   if (Len > 0) then Len := Len - 1; // Simple, isn't it? :)
  end;
  // Display the list.
  for I := 0 to Pred(Max) do begin
   with DataItemList[(Index + I + Max - Len) mod Max] do
    WriteLn(I: 2, ' - ', (Index + I + Max - Len) mod Max, ':', Number: 2, ': ', Name);
  end;
  WriteLn('Length=', Len, ', index=', Index);
 until (Line = 'x');
end.
Simple console application. I use the +, - and * as commands. The + adds a record, the - a record from the end, and the * a record from the beginning. With a bit more programming, this could be put to use in a simple class.
And Pierre, if you look closely, you'll notice that I'm not moving any records. I'm just doing a bit of math to determine the start and end of the array, which is cycling through the fixed array in Delphi. Delphi uses similar tricks in the way it handles textfiles, for the textbuffer...
True, you could do it too with a list or with a collection but I tend to like just plain vanilla arrays. (Often dynamic arrays too.) The nicest part of my solution is that it doesn't depend on any unit or whatever. It's pure, basic PAscal code. Pretty primitive even.
True, in general you can't get around the Classes unit in most applications anyway, but if you're creating a formless DLL then sometimes you can avoid using the Classes unit. Which is why I try to think of solutions that can avoid the usage of the classes unit. One thing I dislike about the TList is that it's a list of typeless pointers. Thus you need to typecast the pointer to get a pointer to the right type. And of course be aware for unassigned items. Besides, if you look at the source if the TList, you'll notice that it just has an array in the background anyways. Thus, adding and deleting items in a TList just means that pointers are moved around.
But moving pointers is faster than moving records. It's just less data. And the TList uses just the System.Move command to move the pointers up one level. (Or down, when inserting.) But if I used an array of class-types instead of an array of record-types then I could use the same technique for this array. An array of classes is just an array of pointers too. (Just don't forget to free them.)
And true... If you want to delete an item in the middle then my solution isn't optimal. But otherwise it's very powerful.






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
Alex, Thanks for the new trick...
I have a new problem. Can I somehow to insert a new record?
To say tht I have Rec:
0
1
2
3
I get a new record that must become 2 and not 4.
Now  Wished
0 Â Â Â Â Â 0
1 Â Â Â Â Â 1
2 Â Â Â Â Â 2(4)
3 Â Â Â Â Â 3(2)
4 Â Â Â Â Â 4(3)
I will offer 500 point for a fast way. I use in my vcl max 50 steps (REC).

Get a FREE t-shirt when you ask your first question.
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
procedure TUndoList.InsertUndoRec(In
var d: PUndoRec;
begin
 New(d);
 d^:= URec;
 Insert(Index, d);
end;
Remember the list is zero-based, so if you wanted to insert a record at position 2, you would call
  InsertUndoRec(1, SomeUndoRec)
Please visit
https://www.experts-exchange.com/questions/21135872/Points-for-PierreC.html
Delphi
--
Questions
--
Followers
Top Experts
Delphi is the most powerful Object Pascal IDE and component library for cross-platform Native App Development with flexible Cloud services and broad IoT connectivity. It provides powerful VCL controls for Windows 10 and enables FMX development for Windows, Mac and Mobile. Delphi is your choice for ultrafast Enterprise Strong Developmentâ„¢. Look for increased memory for large projects, extended multi-monitor support, improved Object Inspector and much more. Delphi is 5x faster for development and deployment across multiple desktop, mobile, cloud and database platforms including 32-bit and 64-bit Windows 10.