Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Maintaining a list of TIWFrames and descendants of TIWFrame
#5
I have created two general use frames; one for a grid and one for a single record CRUD.

The two frames work hand in hand where I assign values to the grid frame properties and it's smart enough to get the data for the grid, create the desired columns with headings and provide navigation and single record CRUD when one of the CRUD events is fired.  The grid frame includes a property for setting the CRUD frame (TframeBaseEdit).  

Basically, by assigning the appropriate CRUD frame to the Grid frame, we have a reusable method of grid display + CRUD.

Currently I am using a separate strongly typed array to maintain the list of "live" frames, separated by type:


 TframeBase = class(TIWFrame)
 TframeEditBase = class(TframeBase)
 TframeGridBase = class(TframeBase)

 FframeArray: Array of TIWFrame;  
 FframeBaseArray: Array of TframeBase;  
 FframeEditBaseArray: Array of TframeEditBase;
 FframeGridBaseArray: Array of TframeGridBase;

Currently...when I create the various frames, I insert them into the appropriate array, based on the frame type.  

I make sure that all of the frames are invisible and have no daddy. This is one example where I have 4 separate arrays, each of a type that is descended from the previous.  A single array of type ??? would help.  Or, should I create an array of pointers and assign the frames to the array by reference?
Code:
 for i := 0 to iFrameCount - 1 do
   begin
     if Assigned(Self.FframeArray[i]) then
       begin
         (Self.FframeArray[i] as TIWFrame).Visible := False;
         (Self.FframeArray[i] as TIWFrame).Parent := nil;
       end;
     if Assigned(Self.FframeBaseArray[i]) then
       begin
         Self.FframeBaseArray[i].Visible := False;
         Self.FframeBaseArray[i].Parent := nil;
       end;
     if Assigned(Self.FframeGridBaseArray[i]) then
       begin
         Self.FframeGridBaseArray[i].Visible := False;
         Self.FframeGridBaseArray[i].Parent := nil;
       end;
     if Assigned(Self.FframeEditBaseArray[i]) then
       begin
         Self.FframeEditBaseArray[i].Visible := False;
         Self.FframeEditBaseArray[i].Parent := nil;
       end;
   end;

This code is showing where I initialize the frame (the end result of .Initialize is that the frame is rendered).  Clearly this would be better with a single array rather than an array for each type of frame.

Code:
     if Assigned(Self.FframeArray[iFrame]) then
       begin
         SetFrameParent(Self.FframeArray[iFrame], Self.regionMain);
       end;
     if Assigned(Self.FframeBaseArray[iFrame]) then
       begin
         SetFrameParent(Self.FframeBaseArray[iFrame], Self.regionMain);
         Self.FframeBaseArray[iFrame].Initialize;
       end;
     if Assigned(Self.FframeGridBaseArray[iFrame]) then
       begin
         SetFrameParent(Self.FframeGridBaseArray[iFrame], Self.regionMain);
         Self.FframeGridBaseArray[iFrame].Initialize;
       end;
     if Assigned(Self.FframeEditBaseArray[iFrame]) then
       begin
         SetFrameParent(Self.FframeEditBaseArray[iFrame], Self.regionMain);
         Self.FframeEditBaseArray[iFrame].Initialize;
       end;
Here is some of the code where I'm creating the various regular frames, grid frames  and their CRUD frames:

Code:
 SetLength(Self.FframeGridBaseArray, iFrameCount);
 SetLength(Self.FframeEditBaseArray, iFrameCount);
 SetLength(Self.FframeBaseArray, iFrameCount);
 SetLength(Self.FframeArray, iFrameCount);
 for i := 0 to iFrameCount - 1 do
   begin
       begin
         if (i = Ord(TApplicationFrames.afInvalidClientIPAddress)) then
           begin
             Self.FframeInvalidClientIPAddress := TframeInvalidClientIPAddress.Create(Self);
             Self.FframeInvalidClientIPAddress.Name := Include.C_FRAME_INVALIDCLIENTIPADDRESS;
             Self.FframeInvalidClientIPAddress.Request := Webapplication.Request;
           end
         else if (i = Ord(TApplicationFrames.afLogin)) then
           begin
             Self.FframeLogin := TframeLogin.Create(Self);
             Self.FframeLogin.Name := Include.C_FRAME_LOGIN;
             Self.FframeLogin.DefaultFrameName := Include.C_FRAME_MAIN;
           end
         else if (i = Ord(TApplicationFrames.afMain)) then
           begin
             Self.FframeArray[i] := TframeMain.Create(Self);
             Self.FframeArray[i].Name := Include.C_FRAME_MAIN;
             (Self.FframeArray[i] as TframeMain).LockIndicator := Self.IWCGJQLockIndicator1;
           end
         else if (i = Ord(TApplicationFrames.afPreferencesCompany)) then
           begin
             Self.FframeEditBaseArray[i] := TframeEditPreferencesCompany.Create(Self);
             Self.FframeEditBaseArray[i].Name := Include.C_FRAME_EDIT_PREFERENCES_COMPANY;
           end
         else if (i = Ord(TApplicationFrames.afUsersList)) then
           begin
             Self.FframeGridBaseArray[i] := TframeGridBase.Create(Self);
             Self.FframeGridBaseArray[i].Name := Include.C_FRAME_GRID_USERS;
             Self.FframeGridBaseArray[i].ViewData := Include.C_VIEW_DATA_LIST_USERS;
             Self.FframeGridBaseArray[i].EditFrame := TframeEditUser.Create(Self);
             Self.FframeGridBaseArray[i].EditFrame.Name := Include.C_FRAME_EDIT_USER;
             // Frame.UnInitialize will call EditFrame.RefreshGridProc if we assign it
             Self.FframeGridBaseArray[i].EditFrame.RefreshGridProc := Self.FframeGridBaseArray[i].RefreshGridData;
             // Assign EditFrame.EditData procedure to GridFrame.EditProc so that when you select a row it will display the EditFrame
             Self.FframeGridBaseArray[i].EditProc := (Self.FframeGridBaseArray[i].EditFrame as TframeEditUser).EditData;
           end
         else if (i = Ord(TApplicationFrames.afSecurityProfileList)) then
           begin
             Self.FframeGridBaseArray[i] := TframeGridBase.Create(Self);
             Self.FframeGridBaseArray[i].Name := Include.C_FRAME_GRID_SECURITY_PROFILES;
             Self.FframeGridBaseArray[i].ViewData := Include.C_VIEW_DATA_LIST_SECURITY_PROFILES;
             Self.FframeGridBaseArray[i].EditFrame := TframeEditSecurityProfile.Create(Self);
             Self.FframeGridBaseArray[i].EditFrame.Name := Include.C_FRAME_EDIT_SECURITY_PROFILE;
             // Frame.UnInitialize will call EditFrame.RefreshGridProc if we assign it
             Self.FframeGridBaseArray[i].EditFrame.RefreshGridProc := Self.FframeGridBaseArray[i].RefreshGridData;
             // Assign EditFrame.EditData procedure to GridFrame.EditProc so that when you select a row it will display the EditFrame
             Self.FframeGridBaseArray[i].EditProc := (Self.FframeGridBaseArray[i].EditFrame as TframeEditSecurityProfile).EditData;
           end
         else if (i = Ord(TApplicationFrames.afEditPassword)) then
           begin
           end
         else if (i = Ord(TApplicationFrames.afExportData)) then
           begin
             Self.FframeArray[i] := TframeExportData.Create(Self);
             Self.FframeArray[i].Name := Include.C_FRAME_EXPORT_DATA;
             (Self.FframeArray[i] as TframeExportData).LockIndicator := Self.IWCGJQLockIndicator1;
           end;

       end;
     if Assigned(Self.FframeArray[i]) then
       begin
         Self.FframeArray[i].Parent  := nil;
         Self.FframeArray[i].Visible := False;
         Self.FframeArray[i].Height  := Self.regionMain.Height;
         Self.FframeArray[i].Width   := Self.regionMain.Width;
         Self.FframeArray[i].Align   := TAlign.alClient;
       end;
     if Assigned(Self.FframeBaseArray[i]) then
       begin
         Self.FframeBaseArray[i].Parent  := nil;
         Self.FframeBaseArray[i].Visible := False;
         Self.FframeBaseArray[i].Height  := Self.regionMain.Height;
         Self.FframeBaseArray[i].Width   := Self.regionMain.Width;
         Self.FframeBaseArray[i].Align   := TAlign.alClient;
         Self.FframeBaseArray[i].LockIndicator := Self.IWCGJQLockIndicator1;
       end;
     if Assigned(Self.FframeGridBaseArray[i]) then
       begin
         Self.FframeGridBaseArray[i].Parent  := nil;
         Self.FframeGridBaseArray[i].Visible := False;
         Self.FframeGridBaseArray[i].Height  := Self.regionMain.Height;
         Self.FframeGridBaseArray[i].Width   := Self.regionMain.Width;
         Self.FframeGridBaseArray[i].Align   := TAlign.alClient;
         Self.FframeGridBaseArray[i].LockIndicator := Self.IWCGJQLockIndicator1;
       end;

The short of it is this:  How do I maintain a single list of these various frame types?

Array of objects?
Array of pointers?
Crayola and Big Chief Pad? Big Grin

I appreciate y'all letting me have a few spin cycles from your personal beanie propeller to help me figure this out.

Thanks,
Scott

(05-04-2018, 04:51 PM)DanBarclay Wrote: What was the complaint, and when (runtime/designtime)?  
Did it sound like a name collision or something?

Dan

myFrames: Array of TframeBase;
...
   myFrames[i] := TframeGridBase.Create(Self);   // << This assignment does not throw an exception, but the parent type (TframeBase) causes me to lose the added functionality in TframeGridBase
Reply


Messages In This Thread
RE: Maintaining a list of TIWFrames and descendants of TIWFrame - by ScottWGast - 05-07-2018, 02:13 PM

Forum Jump:


Users browsing this thread: 1 Guest(s)