home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1997 May / Pcwk0597.iso / delphi / dnarrays.lzh / ARRTEST1.PAS < prev    next >
Pascal/Delphi Source File  |  1995-07-16  |  41KB  |  1,169 lines

  1. {+------------------------------------------------------------
  2.  | Unit ArrTest1
  3.  |
  4.  | Version: 1.0  Last modified: 06/14/95, 21:47:55
  5.  | Author : P. Below
  6.  | Project: Dynamic Arrays
  7.  | Description:
  8.  |   This Unit contains all the form and menu handling code of
  9.  |   the array test program. The implementation Uses the other
  10.  |   units ( arrtest2-arrtest8 ) that contain the divers & sundry
  11.  |   dialogs that get called from several menu items.
  12.  +------------------------------------------------------------}
  13. unit Arrtest1;
  14.  
  15. interface
  16.  
  17. uses
  18.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  19.   Forms, Dialogs, StdCtrls, Menus, Arrays;
  20.  
  21. type
  22.   TFixedStr = string[ 25 ];   { a custom data object  }
  23.   PFixedStr = ^TFixedStr;     
  24.   TArrType = ( TA_Long, TA_Double, TA_Fixed, TA_String, TA_PChar );
  25.     { this enumerated type is used to keep track of the current 
  26.       array we have in a TMainForm instance }
  27.  
  28.   TMainForm = class(TForm)
  29.     (* all the stuff below is added by Delphi. HANDS OFF! *)
  30.     MainMenu1: TMainMenu;
  31.     Datei1: TMenuItem;
  32.     MnuFileExit: TMenuItem;
  33.     Arrays1: TMenuItem;
  34.     MnuUse: TMenuItem;
  35.     MnuArraysRedim: TMenuItem;
  36.     MnuArraysDestroy: TMenuItem;
  37.     ArrayItems: TListBox;
  38.     ArrayGroupbox: TGroupBox;
  39.     ArrayProperties: TGroupBox;
  40.     Label1: TLabel;
  41.     ArrayType: TLabel;
  42.     ArraySize: TLabel;
  43.     Label2: TLabel;
  44.     EditItems: TGroupBox;
  45.     EdtItem: TEdit;
  46.     BtnSet: TButton;
  47.     BtnGet: TButton;
  48.     BtnClose: TButton;
  49.     BtnFill: TButton;
  50.     Label3: TLabel;
  51.     Label4: TLabel;
  52.     EdtIndex: TEdit;
  53.     BtnInsert: TButton;
  54.     BtnDelete: TButton;
  55.     N1: TMenuItem;
  56.     MnuArraysSum: TMenuItem;
  57.     MnuArraysFind: TMenuItem;
  58.     MnuArraysSort: TMenuItem;
  59.     MnuArraysClone: TMenuItem;
  60.     N2: TMenuItem;
  61.     MnuCopyItems: TMenuItem;
  62.     N3: TMenuItem;
  63.     MnuFileOpen: TMenuItem;
  64.     MnuFileSaveAs: TMenuItem;
  65.     N4: TMenuItem;
  66.     MnuFileReadStream: TMenuItem;
  67.     MnuFileWriteStream: TMenuItem;
  68.     MnuTextfileRead: TMenuItem;
  69.     MnuTextfileWrite: TMenuItem;
  70.     N5: TMenuItem;
  71.     MnuInspect: TMenuItem;
  72.     MnuArrayEnlarge: TMenuItem;
  73.     procedure MnuFileExitClick(Sender: TObject);
  74.     procedure ArrayItemsClick(Sender: TObject);
  75.     procedure FormCreate(Sender: TObject);
  76.     procedure BtnSetClick(Sender: TObject);
  77.     procedure FormDestroy(Sender: TObject);
  78.     procedure BtnGetClick(Sender: TObject);
  79.     procedure BtnInsertClick(Sender: TObject);
  80.     procedure BtnDeleteClick(Sender: TObject);
  81.     procedure BtnFillClick(Sender: TObject);
  82.     procedure MnuArraysRedimClick(Sender: TObject);
  83.     procedure MnuArraysFindClick(Sender: TObject);
  84.     procedure MnuArraysSortClick(Sender: TObject);
  85.     procedure MnuArraysSumClick(Sender: TObject);
  86.     procedure Arrays1Click(Sender: TObject);
  87.     procedure MnuUseClick(Sender: TObject);
  88.     procedure MnuArraysCloneClick(Sender: TObject);
  89.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  90.     procedure MnuCopyItemsClick(Sender: TObject);
  91.     procedure MnuFileOpenClick(Sender: TObject);
  92.     procedure MnuFileSaveAsClick(Sender: TObject);
  93.     procedure MnuFileReadStreamClick(Sender: TObject);
  94.     procedure MnuFileWriteStreamClick(Sender: TObject);
  95.     procedure Datei1Click(Sender: TObject);
  96.     procedure MnuTextfileReadClick(Sender: TObject);
  97.     procedure MnuTextfileWriteClick(Sender: TObject);
  98.     procedure MnuInspectClick(Sender: TObject);
  99.     procedure MnuArrayEnlargeClick(Sender: TObject);
  100.   private
  101.     { the stuff below has been added by hand }
  102.     FArray: T64KArray;       { the array, may be a derived class }
  103.     FArrayType: TArrType;    { the current array type }
  104.   public
  105.     Procedure UpdateDisplay; { show array type and item count }
  106.     Procedure FillListbox;   { fill listbox with array content }
  107.     Function GetIndex( Var n: Cardinal ): Boolean;
  108.                              { get array index from edit & check it } 
  109.   end;
  110.  
  111. var
  112.   MainForm: TMainForm;
  113.  
  114. implementation
  115.  
  116. Uses ArrTest2, ArrTest3, ArrTest4, ArrTest5, ArrTest6, ArrTest7,
  117.      ArrTest8;
  118.  
  119. {$R *.DFM}
  120.  
  121. Type
  122.   TArrayTypenames = Array [ TArrType ] of TFixedStr;
  123. Const
  124.   (* the following constant is used to display the array type *)
  125.   ArrayTypenames: TArrayTypenames = ( 'Long Integers',
  126.                                       'Real Numbers (Double)',
  127.                                       'Fixed-length Strings',
  128.                                       'Any Pascal String',
  129.                                       'Zero-term. Strings' );
  130. {+------------------------------------------------------------------------
  131.  | UpdateDisplay updates two statics on the main form to show the current 
  132.  | arrays type and size and also sets the limit on the edit field for     
  133.  | changing items.                                                        
  134.  +-----------------------------------------------------------------------}
  135. Procedure TMainForm.UpdateDisplay;
  136.   Begin
  137.     ArrayType.Caption := ArrayTypenames[ FArrayType ];
  138.     ArraySize.Caption := IntToStr( FArray.MaxIndex+1 );
  139.     Case FArrayType Of
  140.       TA_Long: EdtItem.MaxLength := 12;
  141.       TA_Double, TA_Fixed: EdtItem.MaxLength := 25;
  142.       TA_String, TA_PChar: EdtItem.MaxLength := 255;
  143.     End;
  144.   End; { UpdateDisplay }
  145.  
  146. {+---------------------------------------------------------------------------
  147.  | FillLIstbox fills the listbox with data from the current array, converted 
  148.  | to strings, if necessary. This may take some time for a large array, so   
  149.  | we put up the hourglass cursor.                                           
  150.  +--------------------------------------------------------------------------}
  151.  Procedure TMainForm.FillListbox;
  152.   Var
  153.     i: Cardinal;
  154.     p: Pointer;
  155.   Begin
  156.     Screen.Cursor := crHourGlass;
  157.     ArrayItems.Perform( WM_SETREDRAW, 0, 0 );
  158.     ArrayItems.Clear;
  159.     Case FArrayType of
  160.       TA_LONG:
  161.         With FArray As TLongIntArray Do
  162.           For i:= 0 To MaxIndex Do
  163.             ArrayItems.Items.Add( IntToStr( Data[i] ));
  164.       TA_DOUBLE:
  165.         With FArray As TDoubleArray Do
  166.           For i:= 0 To MaxIndex Do
  167.             ArrayItems.Items.Add( FormatFloat( '0.00000',Data[i] ));
  168.       TA_FIXED:
  169.         For i:= 0 To FArray.MaxIndex Do
  170.           ArrayItems.Items.Add( PFixedStr( FArray.GetItemPtr(i))^ );
  171.       TA_STRING:
  172.         With FArray As TPStringArray Do
  173.           For i:= 0 To MaxIndex Do
  174.             ArrayItems.Items.Add( Data[i] );
  175.       TA_PChar:
  176.         With FArray As TPCharArray Do
  177.           For i:= 0 To MaxIndex Do
  178.             ArrayItems.Items.Add( AsString[i] );
  179.     End;
  180.     ArrayItems.Perform( WM_SETREDRAW, 1, 0 );
  181.     ArrayItems.Refresh;
  182.     Screen.Cursor := crDefault;
  183.   End; { FillListbox }
  184.  
  185. {+-------------------------------------------------------------------------
  186.  | GetIndex obtains the contents of the index edit control and tries to    
  187.  | convert it into a number. If that fails it will use the current listbox 
  188.  | index or 0, if no item is selected.                                     
  189.  +------------------------------------------------------------------------}
  190.  Function TMainForm.GetIndex( Var n: Cardinal ): Boolean;
  191.   Begin
  192.     Result := True;
  193.     try
  194.       n := StrToInt(EdtIndex.Text);
  195.     except
  196.       n := Cardinal(ArrayItems.ItemIndex);
  197.       If n = Cardinal(-1) Then n:= 0;
  198.     end;
  199.   End;
  200.  
  201. {+=================================
  202.  | Menu handlers for the main menu 
  203.  |   The File Menu
  204.  +================================}
  205.  
  206. {+--------------------------------------------------------------------
  207.  | This handler is called when the File menu is opened. It enables or 
  208.  | disables some items depending on array type.                       
  209.  +-------------------------------------------------------------------}
  210. procedure TMainForm.Datei1Click(Sender: TObject);
  211. begin
  212.   MnuTextfileRead.Enabled := FArrayType In [TA_STRING, TA_PCHAR];
  213.   MnuTextfileWrite.Enabled := FArrayType In [TA_STRING, TA_PCHAR];
  214. end;
  215.  
  216. {+------------------------------------------------------------------------
  217.  | This handler is called from the File|Exit menu and also if Close is    
  218.  | selected from the system menu of a form. If the form is a clone of the 
  219.  | main form only the form will close ( and be released ), otherwise the  
  220.  | application will terminate.                                            
  221.  +-----------------------------------------------------------------------}
  222. procedure TMainForm.MnuFileExitClick(Sender: TObject);
  223. begin
  224.   If Pos('Clone',Caption) = 1 Then
  225.     Close
  226.   Else
  227.     Application.Terminate;
  228. end;
  229.  
  230. {+----------------------------------------------------------------------------
  231.  | This handler is called from the File|Open menu item. It puts up a standard 
  232.  | file open dialog, asking for an filename for a file to load. This has to
  233.  | be a file created with File|Save As from an array of the same type, or
  234.  | garbage will result! The file is loaded into the array, deleting any 
  235.  | previous contents. The display is updated.
  236.  +---------------------------------------------------------------------------}
  237. procedure TMainForm.MnuFileOpenClick(Sender: TObject);
  238. Var
  239.   OpenDlg: TOpenDialog;
  240. begin
  241.   OpenDlg := TOpenDialog.Create( Self );
  242.   try
  243.     With OpenDlg Do Begin
  244.       DefaultExt := 'ARY';
  245.       Filter := 'Array Files|*.ARY';
  246.       Options := [ofFileMustExist, ofReadOnly, ofPathMustExist];
  247.       Title := 'Open an Array File';
  248.       If Execute Then Begin
  249.         Screen.Cursor:= crHourglass;
  250.         try
  251.           Farray.LoadFromFile( Filename );
  252.         finally
  253.           UpdateDisplay;
  254.           FillListbox;
  255.           Screen.Cursor := crDefault;
  256.         end;
  257.       End;
  258.     End;
  259.   finally
  260.     OpenDlg.Free
  261.   end;
  262. end;
  263.  
  264. {+-------------------------------------------------------------------------
  265.  | This handler is called from the File|Save As menu item. It puts up a 
  266.  | standard file save dialog, asking for a filename for a file to write. 
  267.  | The file generated is a File of Componenttype for most of the array
  268.  | types but not for String and PChar arrays. It can be read via the 
  269.  | File|Open menu.
  270.  +------------------------------------------------------------------------}
  271. procedure TMainForm.MnuFileSaveAsClick(Sender: TObject);
  272. Var
  273.   SaveDlg: TSaveDialog;
  274. begin
  275.   SaveDlg := TSaveDialog.Create( Self );
  276.   try
  277.     With SaveDlg Do Begin
  278.       DefaultExt := 'ARY';
  279.       Filter := 'Array Files|*.ARY';
  280.       Options := [ofPathMustExist, ofHideReadOnly, ofOverwritePrompt];
  281.       Title := 'Create an Array File';
  282.       If Execute Then Begin
  283.         Screen.Cursor:= crHourglass;
  284.         try
  285.           Farray.SaveToFile( Filename );
  286.         finally
  287.           Screen.Cursor:= crDefault
  288.         end;
  289.       End;
  290.     End;
  291.   finally
  292.     SaveDlg.Free
  293.   end;
  294. end;
  295.  
  296. {+----------------------------------------------------------------------------
  297.  | This handler is called from the File|Read Stream menu item. It puts up a 
  298.  | file open dialog, asking for an filename for a file to load. This has to
  299.  | be a file created with File|Write Stream from an array of the same type, or
  300.  | garbage will result! The file is loaded into the array, deleting any 
  301.  | previous contents. The display is updated.
  302.  +---------------------------------------------------------------------------}
  303. procedure TMainForm.MnuFileReadStreamClick(Sender: TObject);
  304. Var
  305.   OpenDlg: TOpenDialog;
  306.   Stream : TFileStream;
  307. begin
  308.   OpenDlg := TOpenDialog.Create( Self );
  309.   try
  310.     With OpenDlg Do Begin
  311.       DefaultExt := 'AST';
  312.       Filter := 'Array Streams|*.AST';
  313.       Options := [ofFileMustExist, ofReadOnly, ofPathMustExist];
  314.       Title := 'Read an Array Stream';
  315.       If Execute Then Begin
  316.         Stream:= TFileStream.Create( Filename, fmOpenRead or fmShareDenyWrite );
  317.         Screen.Cursor:= crHourglass;
  318.         try
  319.           Farray.LoadFromStream( Stream );
  320.         finally
  321.           Stream.Free;
  322.           UpdateDisplay;
  323.           FillListbox;
  324.           Screen.Cursor:= crDefault;
  325.         end;
  326.       End;
  327.     End;
  328.   finally
  329.     OpenDlg.Free
  330.   end;
  331. end;
  332.  
  333. {+-------------------------------------------------------------------------
  334.  | This handler is called from the File|Write Stream menu item. It puts up a 
  335.  | standard file save dialog, asking for a filename for a file to write. 
  336.  | The file generated is contains a small header in addition to the array
  337.  | data, so is not compatible with the format produced by File|Save As, 
  338.  | unless the array is an array of strings or pchars. For the latter two
  339.  | the file I/O calls the stream I/O methods to make life simpler for the
  340.  | weary programmer.
  341.  +------------------------------------------------------------------------}
  342. procedure TMainForm.MnuFileWriteStreamClick(Sender: TObject);
  343. Var
  344.   SaveDlg: TSaveDialog;
  345.   Stream : TFileStream;
  346. begin
  347.   SaveDlg := TSaveDialog.Create( Self );
  348.   try
  349.     With SaveDlg Do Begin
  350.       DefaultExt := 'AST';
  351.       Filter := 'Array Streams|*.AST';
  352.       Options := [ofPathMustExist, ofHideReadOnly, ofOverwritePrompt];
  353.       Title := 'Write an Array Stream';
  354.       If Execute Then Begin
  355.         Stream:= TFileStream.Create( Filename, fmCreate );
  356.         try
  357.           Screen.Cursor := crHourGlass;
  358.           Farray.SaveToStream( Stream );
  359.         finally
  360.           Screen.Cursor:= crDefault;
  361.           Stream.Free
  362.         end;
  363.       End;
  364.     End;
  365.   finally
  366.     SaveDlg.Free
  367.   end;
  368. end;
  369.  
  370. {+-------------------------------------------------------------------------
  371.  | This handler is called from the File|Read Textfile menu item, which is 
  372.  | only accessible for String and PChar arrays. The methods puts up a standard
  373.  | file open dialog, asking for an filename for a file to load. This can be
  374.  | any normal text file, with lines terminated by CR/LF combinations. The
  375.  | array has a limit of 16K lines, anything longer will produce an error
  376.  | which is handled gracefully. While the file loads a progress dialog is
  377.  | displayed that allows the process to be aborted. 
  378.  +------------------------------------------------------------------------}
  379. procedure TMainForm.MnuTextfileReadClick(Sender: TObject);
  380. Var
  381.   OpenDlg: TOpenDialog;
  382.   appendData: Boolean;
  383.   ProgressDlg: TProgressDlg;
  384. begin
  385.   OpenDlg := TOpenDialog.Create( Self );
  386.   try
  387.     With OpenDlg Do Begin
  388.       DefaultExt := 'TXT';
  389.       Filter := 'Textfiles|*.TXT';
  390.       Options := [ofFileMustExist, ofReadOnly, ofPathMustExist];
  391.       Title := 'Read a Textfile';
  392.       If Execute Then Begin
  393.         appendData :=
  394.           MessageDlg('Do you want to append the files text to the array?',
  395.                      mtConfirmation, [mbYes, mbNo], 0) = mrYes;
  396.         ProgressDlg:= TProgressDlg.Create(Self);
  397.         try
  398.           ProgressDlg.Gauge.Value := 0;
  399.           ProgressDlg.LblFilename.Caption := Filename;
  400.           ProgressDlg.LblAction.Caption   := 'Reading file';
  401.           ProgressDlg.Show;
  402.           Case FArrayType Of
  403.             TA_STRING:
  404.               TPStringArray( FArray).LoadFromTextfile( Filename, appendData,
  405.                         ProgressDlg.ReportProgressOnLoad );
  406.             TA_PCHAR:
  407.               TPCharArray( FArray).LoadFromTextfile( Filename, appendData,
  408.                         ProgressDlg.ReportProgressOnLoad );
  409.           End;
  410.         finally
  411.           ProgressDlg.Close;
  412.           UpdateDisplay;
  413.           FillListbox;
  414.         end;
  415.       End;
  416.     End;
  417.   finally
  418.     OpenDlg.Free
  419.   end;
  420. end;
  421.  
  422. {+-------------------------------------------------------------------------
  423.  | This handler is called from the File|Write Textfile menu item, which is 
  424.  | only accessible for String and PChar arrays. The methods puts up a standard
  425.  | file save dialog, asking for an filename for a file to load. The file 
  426.  | produced is a normal text file, with lines terminated by CR/LF combinations.
  427.  | While the file is written a progress dialog is displayed that allows the 
  428.  | process to be aborted. 
  429.  +------------------------------------------------------------------------}
  430. procedure TMainForm.MnuTextfileWriteClick(Sender: TObject);
  431. Var
  432.   SaveDlg: TSaveDialog;
  433.   appendData: Boolean;
  434.   ProgressDlg: TProgressDlg;
  435. begin
  436.   SaveDlg := TSaveDialog.Create( Self );
  437.   try
  438.     With SaveDlg Do Begin
  439.       DefaultExt := 'TXT';
  440.       Filter := 'Textfiles|*.TXT';
  441.       Title := 'Read a Textfile';
  442.       Options := [ofPathMustExist, ofHideReadOnly];
  443.       If Execute Then Begin
  444.         If FileExists( Filename ) Then
  445.           appendData :=
  446.             MessageDlg('Do you want to append the array text to the file?',
  447.                        mtConfirmation, [mbYes, mbNo], 0) = mrYes
  448.         Else
  449.           appendData := False;
  450.         ProgressDlg:= TProgressDlg.Create(Self);
  451.         try
  452.           ProgressDlg.Gauge.Value := 0;
  453.           ProgressDlg.LblFilename.Caption := Filename;
  454.           ProgressDlg.LblAction.Caption   := 'Writing file';
  455.           ProgressDlg.Show;
  456.           Case FArrayType Of
  457.             TA_STRING:
  458.               TPStringArray( FArray).SaveToTextfile( Filename, appendData,
  459.                         ProgressDlg.ReportProgressOnStore );
  460.             TA_PCHAR:
  461.               TPCharArray( FArray).SaveToTextfile( Filename, appendData,
  462.                         ProgressDlg.ReportProgressOnStore );
  463.           End;
  464.         finally
  465.           ProgressDlg.Close;
  466.         end;
  467.       End;
  468.     End;
  469.   finally
  470.     SaveDlg.Free
  471.   end;
  472. end;
  473.  
  474. {+=================================
  475.  | Menu handlers for the main menu 
  476.  |   The Arrays Menu
  477.  +================================}
  478.  
  479. {+--------------------------------------------------------------------
  480.  | This handler is called when the Arrays menu is opened. It sets the
  481.  | enabled/disbaled states for a few menu items that are dependent on
  482.  | the arrays type.
  483.  +-------------------------------------------------------------------}
  484. procedure TMainForm.Arrays1Click(Sender: TObject);
  485. begin
  486.   MnuArraysSum.Enabled := FArrayType In [TA_LONG, TA_DOUBLE];
  487.   MnuArraysSort.Enabled := FArray.HasFlag( AF_CanCompare );
  488.   MnuArraysFind.Enabled := FArray.HasFlag( AF_CanCompare );
  489.   MnuArrayEnlarge.Enabled := FArrayType In [TA_String, TA_PChar];
  490. end;
  491.  
  492. {+---------------------------------------------------------------------------
  493.  | This handler is called when the Arrays|Use menu item is clicked. It
  494.  | displays a selection of the available array types and creates an new
  495.  | array of the requested type, deleting the old one. All arrays start
  496.  | with a default size and empty items. 
  497.  +--------------------------------------------------------------------------}
  498. procedure TMainForm.MnuUseClick(Sender: TObject);
  499. Var
  500.   typesDlg: TTypesDlg;
  501. begin
  502.   typesDlg := TTypesDlg.Create( Self );
  503.   typesDlg.GrpArrayStyles.ItemIndex := Ord(FArrayType);
  504.   try
  505.     If typesDlg.ShowModal = mrOK Then
  506.       If typesDlg.GrpArrayStyles.ItemIndex <> Ord(FArrayType) Then Begin
  507.         FArray.Free;
  508.         Case typesDlg.GrpArrayStyles.ItemIndex Of
  509.           0: Begin
  510.                FArray := TLongIntArray.Create(20,0);
  511.                FArrayType := TA_LONG;
  512.              End;
  513.           1: Begin
  514.                FArray := TDoubleArray.Create(20,0);
  515.                FArrayType := TA_DOUBLE;
  516.              End;
  517.           2: Begin
  518.                FArray := T64KArray.Create(20,Sizeof( TFixedStr));
  519.                FArrayType := TA_FIXED;
  520.              End;
  521.           3: Begin
  522.                FArray := TPStringArray.Create(20,0);
  523.                FArrayType := TA_STRING;
  524.              End;
  525.           4: Begin
  526.                FArray := TPCharArray.Create(20,0);
  527.                FArrayType := TA_PCHAR;
  528.              End;
  529.         End;
  530.         UpdateDisplay;
  531.         FillListbox;
  532.         ArrayItems.ItemIndex := 0;
  533.       End;
  534.   finally
  535.     sortDlg.Free
  536.   end;
  537. end;
  538.  
  539. {+---------------------------------------------------------------------------
  540.  | This handler is called when the Arrays|Redim menu item is clicked. It
  541.  | displays an input dialog to ask the user for the new size of the array
  542.  | he wants and, if the dialog was not canceled and the input it a valid
  543.  | number, resize the arrays and refresh the display to reflect the changes.
  544.  +--------------------------------------------------------------------------}
  545. procedure TMainForm.MnuArraysRedimClick(Sender: TObject);
  546. Var
  547.   n: Cardinal;
  548.   inputDialog: TInputDialog;
  549. begin
  550.   inputDialog := TInputDialog.Create( Self );
  551.   try
  552.     With InputDialog Do Begin
  553.       Caption := 'Redim Array';
  554.       Prompt.Caption := 'Enter the number of items you want';
  555.       EdtInput.Text := '';
  556.       EdtInput.MaxLength := 5;
  557.       If ShowModal = mrOk Then Begin
  558.         try
  559.           n := StrToInt( EdtInput.Text );
  560.           FArray.Redim( n );
  561.         except
  562.           on EConvertError Do
  563.             ShowMessage('Your input was not a valid integer number!');
  564.         end;
  565.       End;
  566.     End;
  567.   finally
  568.     inputdialog.Free;
  569.     UpdateDisplay;
  570.     FillListbox;
  571.     ArrayItems.ItemIndex := 0;
  572.   end;
  573. end;
  574.  
  575. {+----------------------------------------------------------------------------
  576.  | This handler is called from the Arrays|Find menu item. It puts up a dialog 
  577.  | asking the user for an item to search for (it has to be of the same type
  578.  | as the arrays), and, if the dialog was not canceled and the data looks
  579.  | ok, tries to search for the item and displays the index of the found entry,
  580.  | or an error message.
  581.  | Note that we do not check whether the current array has the ability to
  582.  | search for items. That is not necessary because the menu item will be
  583.  | disabled if the array cannot compare items!
  584.  +---------------------------------------------------------------------------}
  585.  procedure TMainForm.MnuArraysFindClick(Sender: TObject);
  586. Var
  587.   n: Cardinal;
  588.   l : LongInt;
  589.   f : Double;
  590.   s : TFixedStr;
  591.   pCh: PChar;
  592.   str: PString;
  593.   inputDialog: TInputDialog;
  594. begin
  595.   inputDialog := TInputDialog.Create( Self );
  596.   try
  597.     With InputDialog Do Begin
  598.       Caption := 'Find Item';
  599.       Prompt.Caption := 'Enter the value to search for';
  600.       EdtInput.Text := '';
  601.       EdtInput.MaxLength := 20;
  602.       n := NOT_FOUND;
  603.       If ShowModal = mrOk Then Begin
  604.         try
  605.           Case FArrayType Of
  606.             TA_LONG: Begin
  607.                 l := StrToInt(EdtInput.Text );
  608.                 n := FArray.Find( l );
  609.               End;
  610.             TA_Double: Begin
  611.                 f := StrToFloat(EdtInput.Text );
  612.                 n := FArray.Find( f );
  613.               End;
  614.             TA_FIXED: Begin
  615.                 s := EdtInput.Text;
  616.                 n := FArray.Find( s );
  617.               End;
  618.             TA_STRING: Begin
  619.                 str := NewStr( EdtInput.Text );
  620.                 try
  621.                   n := FArray.Find( str );
  622.                 finally
  623.                   DisposeStr( str );
  624.                 end;
  625.               End;
  626.             TA_PCHAR: Begin
  627.                 pCh := StrAlloc( EdtItem.GetTextLen + 1 );
  628.                 try
  629.                  EdtItem.GetTextBuf( pCh, StrBufSize( pCh ));
  630.                  n := FArray.Find( pCh );
  631.                 finally
  632.                   StrDispose( pCh );
  633.                 end;
  634.               End;
  635.           End;
  636.           If n = NOT_FOUND Then
  637.             ShowMessage('The value was not found!')
  638.           Else Begin
  639.             ShowMessage(Format('The value was found at index %u.',
  640.                         [n]));
  641.             ArrayItems.ItemIndex := n;
  642.           End;
  643.         except
  644.           on EConvertError Do
  645.             ShowMessage('Your input was not a valid value for the array current type!');
  646.         end;
  647.       End;
  648.     End;
  649.   finally
  650.     inputdialog.Free;
  651.   end;
  652. end;
  653.  
  654. {+----------------------------------------------------------------------------
  655.  | This handler is called from the Arrays|Sort menu item. It puts up a dialog 
  656.  | that allows a choice of ascending or descending search and then sorts the
  657.  | array according to the users selection. Finally the display is updated.
  658.  +---------------------------------------------------------------------------}
  659.  procedure TMainForm.MnuArraysSortClick(Sender: TObject);
  660. Var
  661.   sortDlg: TSortDlg;
  662.   ascending: Boolean;
  663. begin
  664.   sortDlg := TSortDlg.Create( Self );
  665.   try
  666.     If sortDlg.ShowModal = mrOK Then Begin
  667.       ascending := sortdlg.GrpSortOrder.ItemIndex = 0;
  668.       FArray.Sort( ascending );
  669.     End;
  670.   finally
  671.     sortDlg.Free;
  672.     FillListbox;
  673.     ArrayItems.ItemIndex := 0;
  674.   end;
  675. end;
  676.  
  677. (* The following tiny object is used by the MnuArraysSumClick method
  678.    to add up the numbers in a numeric array by using the ForEach iterator.
  679.    Using a temporary object makes the use of a local procedure ( like for
  680.    Borland Pascal Collections ) unnecessary. *)
  681. Type
  682.   TSumObj = class
  683.     public
  684.     sumf: Double;
  685.     suml: LongInt;
  686.  
  687.     Procedure AddLongs( VAR Item; index: cardinal );
  688.     Procedure AddFloats(VAR Item; index: cardinal );
  689.   end;
  690. procedure TSumObj.AddLongs;
  691. Var
  692.   Long: LongInt absolute Item;
  693. Begin
  694.   suml := suml + Long;
  695. end;
  696. procedure TSumObj.AddFloats;
  697. Var
  698.   Dbl: Double absolute Item;
  699. Begin
  700.   sumf := sumf + Dbl;
  701. end;
  702.  
  703. {+----------------------------------------------------------------------------
  704.  | This handler is called from the Arrays|Sum menu item. This item will only
  705.  | be enabled if the array is an array of numbers. The handler creates a 
  706.  | local object instance of TSumObj and uses one of the methods of TSumObj 
  707.  | as an iterator in the call to ForEach. The result is displayed in a 
  708.  | message.
  709.  +---------------------------------------------------------------------------}
  710. procedure TMainForm.MnuArraysSumClick(Sender: TObject);
  711. Var
  712.   sumobj: TSumObj;
  713. begin
  714.   If FArrayType In [TA_LONG, TA_DOUBLE] Then Begin
  715.     sumObj := TSumObj.Create;
  716.     try
  717.       If FArrayType = TA_LONG Then
  718.         FArray.ForEach( sumObj.AddLongs, false, 1 )
  719.       Else
  720.         FArray.ForEach( sumObj.AddFloats, false, 1 );
  721.       ShowMessage( Format(
  722.           'Sum over Longs : %d'+#13#10+
  723.           'Sum over Floats: %12.6f', [sumObj.suml, sumObj.sumf]));
  724.     finally
  725.       sumObj.Free;
  726.     end;
  727.   End;
  728. end;
  729.  
  730. {+---------------------------------------------------------------------------
  731.  | This handler is called when the Arrays|Use menu item is selected. It pops
  732.  | up a dialog presenting the available array classes. If the user makes a
  733.  | selection of a different type than the current array type, the current
  734.  | array gets deleted and a new one of the reqested type is created. The 
  735.  | display is finally updated. All arrays start of with 20 empty ( =0 )
  736.  | entries.
  737.  +--------------------------------------------------------------------------}
  738. procedure TMainForm.MnuArraysCloneClick(Sender: TObject);
  739. Const
  740.   newtag: Integer = 0;
  741. Var
  742.   NewForm: TMainForm;
  743.   i: cardinal;
  744.   n: Integer;
  745. begin
  746.   Screen.Cursor := crHourGlass;
  747.   try
  748.     Application.CreateForm( TMainForm, NewForm );
  749.     Inc(newtag);
  750.     With NewForm Do Begin
  751.       try
  752.         FArray.Free;
  753.         FArray := Self.FArray.Clone;
  754.         FArrayType := Self.FArrayType;
  755.         UpdateDisplay;
  756.         FillListbox;
  757.         Caption := 'Clone'+IntToStr(newtag);
  758.         Name := Caption;
  759.         Tag := newtag;
  760.         Position := poDefault;
  761.         Show;
  762.       except
  763.         Close;
  764.         raise
  765.       end;
  766.     End;
  767.   finally
  768.     Screen.Cursor := crDefault;;
  769.   end;
  770. end;
  771.  
  772. {+---------------------------------------------------------------------
  773.  | This handler is called when the Arrays|Copy menu item is selected. 
  774.  | It presents a dialog with two listboxes and a few fields. The listboxes
  775.  | both show all the currently open instances of the main window by title.
  776.  | The user can select a source and a target for a copy operation ( both
  777.  | may be the same ), source and target index and the number of 
  778.  | items to copy. If the dialog is not canceled the items are then copied
  779.  | from source to target and the display is refreshed.
  780.  +--------------------------------------------------------------------}
  781.  procedure TMainForm.MnuCopyItemsClick(Sender: TObject);
  782. Var
  783.   CopyDlg: TCopyDlg;
  784.   i: Cardinal;
  785.   iTo, iFrom, iCount: Integer;
  786.   source, target: TMainForm;
  787. begin
  788.   CopyDlg := TCopyDlg.Create( Self );
  789.   try
  790.     CopyDlg.LstSource.Clear;
  791.     CopyDlg.LstTarget.Clear;
  792.     For i:= 0 To Application.ComponentCount-1 Do
  793.       If Application.Components[i] Is TMainForm Then
  794.       With Application.Components[i] Do Begin
  795.         CopyDlg.LstSource.Items.Add( Name );
  796.         CopyDlg.LstTarget.Items.Add( Name );
  797.       End;
  798.     With CopyDlg Do Begin
  799.       LstSource.ItemIndex:= 0;
  800.       LstTarget.ItemIndex:= 0;
  801.       EdtFromIndex.Text := '0';
  802.       EdtToIndex.Text := '0';
  803.       EdtNumItems.Text := '0';
  804.       If ShowModal = mrOK Then Begin
  805.         try
  806.           iFrom := StrToInt( EdtFromIndex.Text );
  807.           iTo   := StrToInt( EdtToIndex.Text );
  808.           iCount := StrToInt( EdtNumItems.Text );
  809.         except
  810.           on E:EConvertError Do Begin
  811.             iFrom := 0;
  812.             iTo   := 0;
  813.             iCount:= 0;
  814.             ShowException( E, ErrorAddr );
  815.           End
  816.         End;
  817.         If (iCount > 0) and
  818.            (LstSource.ItemIndex >= 0) and
  819.            (LstTarget.ItemIndex >= 0)
  820.         Then Begin
  821.                     Screen.Cursor := crHourGlass;
  822.           Source := Application.FindComponent(
  823.                       LstSource.Items[LstSource.ItemIndex] )
  824.                     As TMainForm;
  825.           Target := Application.FindComponent(
  826.                       LstTarget.Items[LstTarget.ItemIndex] )
  827.                     As TMainForm;
  828.           try
  829.             Target.FArray.BlockCopy( Source.FArray, iFrom, iTo, iCount );
  830.           finally
  831.             Target.FillListbox;
  832.             Screen.Cursor := crDefault;
  833.           end;
  834.         End;
  835.       End;
  836.     End;
  837.   finally
  838.     CopyDlg.Free;
  839.   end;
  840. end;
  841.  
  842. {+---------------------------------------------------------------------------
  843.  | This handler is called from the Arrays|Inspect menu item. It will display 
  844.  | a dialog that shows the state of all the 16 array flags. Only the 
  845.  | AF_AutoSize flag can be changed in this dialog. It determines whether 
  846.  | the array will automatically resize when items are inserted and deleted.
  847.  | Each flag corresponds to a checkbox on this dialog and the checkboxes 
  848.  | have Tag values that correspond to the ordinal value of the flags.
  849.  +--------------------------------------------------------------------------}
  850. procedure TMainForm.MnuInspectClick(Sender: TObject);
  851. Var
  852.   inpDlg: TInspectionDlg;
  853.   f : TArrayFlags;
  854.   n : Cardinal;
  855. begin
  856.   inpDlg := TInspectionDlg.Create(Self);
  857.   try
  858.     For f:= Low(TarrayFlags) To High(TArrayFlags) Do
  859.       If Farray.HasFlag( f ) Then
  860.       With inpDlg.GrpFlags Do Begin
  861.         For n:= 0 To ControlCount Do
  862.           With Controls[n] As TCheckbox Do
  863.             If Tag = Ord(f) Then Begin
  864.               Checked := True;
  865.               Break
  866.             End;
  867.       End;
  868.     inpDlg.ShowModal;
  869.     If inpDlg.ChkAutoSize.Checked Then
  870.       Farray.SetFlag( AF_AutoSize )
  871.     Else
  872.       Farray.ClearFlag( AF_AutoSize );
  873.   finally
  874.     inpDlg.Free;
  875.   end;
  876. end;
  877.  
  878. {+------------------------------------------------------------------------
  879.  | This handler is called from the Arrays|Enlarge menu item. This item is 
  880.  | only selectable for string an pchar arrays. It pops up a resizeable 
  881.  | dialog with a wide listbox and a close button. The listbox shows the 
  882.  | arrays contents like the one on the main form, but it will show longer
  883.  | lines of text in their full glory. The dialog is nonmodal, so you can
  884.  | conceivably open several for one main form. Is hard on the resources,
  885.  | though!
  886.  +-----------------------------------------------------------------------}
  887. procedure TMainForm.MnuArrayEnlargeClick(Sender: TObject);
  888. Var
  889.   n: Cardinal;
  890. begin
  891.   With TEnlargedViewDlg.Create(Self) Do Begin
  892.     Screen.Cursor:= crHourGlass;
  893.     try
  894.       try
  895.         For n:= 0 To ArrayItems.Items.Count-1 Do
  896.           LstView.Items.Add( ArrayItems.Items[n] );
  897.         Show;
  898.       finally
  899.         Screen.Cursor := crDefault;
  900.       end
  901.     except
  902.       Free
  903.     end;
  904.   End;
  905. end;
  906.  
  907. {+=====================
  908.  | Form event handlers 
  909.  +====================}
  910.  
  911. {+---------------------------------------------------------------------------
  912.  | This handler is called when a form is created. It creates a default array 
  913.  | of integers and displays it.                                              
  914.  +--------------------------------------------------------------------------}
  915. procedure TMainForm.FormCreate(Sender: TObject);
  916. begin
  917.   FArray := TLongIntArray.Create(20,0);
  918.   FArrayType := TA_LONG;
  919.   UpdateDisplay;
  920.   FillListbox;
  921. end;
  922.  
  923. {+----------------------------------------------------------------------
  924.  | This handler is called when the form is destroyed. It frees the array. 
  925.  +---------------------------------------------------------------------}
  926. procedure TMainForm.FormDestroy(Sender: TObject);
  927. begin
  928.   FArray.Free;
  929. end;
  930.  
  931. {+---------------------------------------------------------------------------
  932.  | This handler is called when the form is about to close. We tell Delphi to 
  933.  | actually destroy the form, not only hide it.                              
  934.  +--------------------------------------------------------------------------}
  935. procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
  936. begin
  937.   Action := caFree;
  938. end;
  939.  
  940. {+========================
  941.  | Control event handlers 
  942.  |   Listbox events
  943.  +=======================}
  944.  
  945. {+---------------------------------------------------------------------
  946.  | This handler is called when the user clicks on a listbox item or if 
  947.  | the item is selected by program. The method puts the selected items
  948.  | index and content into two edit controls on the form.
  949.  +--------------------------------------------------------------------}
  950. procedure TMainForm.ArrayItemsClick(Sender: TObject);
  951. begin
  952.   If ArrayItems.ItemIndex >= 0 Then Begin
  953.     EdtIndex.Text := IntToStr( ArrayItems.ItemIndex );
  954.     EdtItem.Text := ArrayItems.Items[ ArrayItems.ItemIndex ];
  955.   End
  956.   Else Begin
  957.     EdtIndex.Text := '';
  958.     EdtItem.Text := '';
  959.   End;
  960. end;
  961.  
  962. {+========================
  963.  | Control event handlers 
  964.  |   Button events
  965.  +=======================}
  966.  
  967. {+---------------------------------------------------------------------------
  968.  | This handler is called when the Set button is clicked. It tries to obtain 
  969.  | the contents of the edit controls ( an index and a value for an item ) an
  970.  | overwrites the array item at the selected index with the value from the
  971.  | edit. The changes are reflected in the listbox. 
  972.  +--------------------------------------------------------------------------}
  973. procedure TMainForm.BtnSetClick(Sender: TObject);
  974. Var
  975.   n: Cardinal;
  976.   f: Double;
  977.   s: TFixedStr;
  978. begin
  979.   If not GetIndex(n) Then Exit;
  980.   { we do no check the index on purpose to show how the array
  981.     objects raises exceptions on index range errors }
  982.   Case FarrayType of
  983.     TA_LONG: Begin
  984.         try
  985.           (FArray As TLongIntArray)[n] := StrToInt( EdtItem.Text );
  986.         except
  987.           On EConvertError Do Begin
  988.             ShowMessage( 'The entered string is not a valid integer!');
  989.             Exit;
  990.           End;
  991.         End;
  992.       End;
  993.     TA_DOUBLE: Begin
  994.         try
  995.           (FArray As TDoubleArray)[n] := StrToFloat( EdtItem.Text );
  996.         except
  997.           On EConvertError Do Begin
  998.             ShowMessage( 'The entered string is not a valid real number!');
  999.             Exit;
  1000.           End;
  1001.         End;
  1002.       End;
  1003.     TA_FIXED: Begin
  1004.         s := EdtItem.Text;
  1005.         FArray.PutItem( n, s );
  1006.       End;
  1007.     TA_STRING: (FArray As TPStringArray)[n] := EdtItem.Text;
  1008.     TA_PCHAR : (FArray As TPCharArray).AsString[n] := EdtItem.Text;
  1009.   End;
  1010.   FillListbox;
  1011.   ArrayItems.ItemIndex := n;
  1012. end;
  1013.  
  1014. {+----------------------------------------------------------------------------
  1015.  | This handler is called by a click on the Get button. This button retrieves
  1016.  | an index value from the index edit and copies the requested array item 
  1017.  | to the value edit field. The item is selected in the listbox.
  1018.  +---------------------------------------------------------------------------}
  1019. procedure TMainForm.BtnGetClick(Sender: TObject);
  1020. Var
  1021.   n: Cardinal;
  1022. begin
  1023.   If not GetIndex(n) Then Exit;
  1024.   EdtItem.Text := ArrayItems.Items[n];
  1025.   ArrayItems.ItemIndex := n;
  1026. end;
  1027.  
  1028.  
  1029. {+----------------------------------------------------------------------------
  1030.  | This handler is called by a click on the Insert button. This button 
  1031.  | retrieves an index value from the index edit and a value form the value 
  1032.  | edit field and inserts the value into the array at the requested position.
  1033.  | This will cause the array to grow if its AutoSize flag is set, otherwise
  1034.  | the last entry will fall off into The Great Bit Bucket Beyond.
  1035.  +---------------------------------------------------------------------------}
  1036. procedure TMainForm.BtnInsertClick(Sender: TObject);
  1037. Var
  1038.   n: Cardinal;
  1039.   f: Double;
  1040.   l: LongInt;
  1041.   s: TFixedStr;
  1042.   str: PString;
  1043.   pCh: PChar;
  1044. begin
  1045.   If not GetIndex(n) Then Exit;
  1046.   try
  1047.   Case FarrayType of
  1048.     TA_LONG: Begin
  1049.         try
  1050.           l := StrToInt( EdtItem.Text );
  1051.           FArray.Insert(l, n, 1);
  1052.         except
  1053.           On EConvertError Do Begin
  1054.             ShowMessage( 'The entered string is not a valid integer!');
  1055.             Exit;
  1056.           End;
  1057.         End;
  1058.       End;
  1059.     TA_DOUBLE: Begin
  1060.         try
  1061.           f := StrToFloat( EdtItem.Text );
  1062.           FArray.Insert(f, n, 1);
  1063.         except
  1064.           On EConvertError Do Begin
  1065.             ShowMessage( 'The entered string is not a valid real number!');
  1066.             Exit;
  1067.           End;
  1068.         End;
  1069.       End;
  1070.     TA_FIXED: Begin
  1071.         s := EdtItem.Text;
  1072.         FArray.Insert( s, n, 1 );
  1073.       End;
  1074.     TA_STRING: Begin
  1075.         New( str );
  1076.         try
  1077.          str^ := EdtItem.Text;
  1078.          FArray.Insert( str, n, 1 );
  1079.         finally
  1080.           Dispose( str );
  1081.         end;
  1082.       End;
  1083.     TA_PCHAR: Begin
  1084.         pCh := StrAlloc( EdtItem.GetTextLen + 1 );
  1085.         try
  1086.          EdtItem.GetTextBuf( pCh, StrBufSize( pCh ));
  1087.          FArray.Insert( pCh, n, 1 );
  1088.         finally
  1089.           StrDispose( pCh );
  1090.         end;
  1091.       End;
  1092.   End;
  1093.   finally
  1094.     UpdateDisplay;
  1095.     FillListbox;
  1096.     ArrayItems.ItemIndex := n;
  1097.   end;
  1098. end;
  1099.  
  1100. {+----------------------------------------------------------------------------
  1101.  | This handler is called by a click on the Delete button. This button 
  1102.  | retrieves an index value from the index edit and deletes the item 
  1103.  | at the requested position from the array .
  1104.  | This will cause the array to shrink if its AutoSize flag is set, otherwise
  1105.  | the last entry will be set to 0.
  1106.  +---------------------------------------------------------------------------}
  1107. procedure TMainForm.BtnDeleteClick(Sender: TObject);
  1108. Var
  1109.   n: Cardinal;
  1110. begin
  1111.   If GetIndex(n) Then Begin
  1112.     try
  1113.       FArray.Delete(n, 1);
  1114.     finally
  1115.       FillListbox;
  1116.       UpdateDisplay;
  1117.       ArrayItems.ItemIndex := n;
  1118.     end;
  1119.   End;
  1120. end;
  1121.  
  1122. {+----------------------------------------------------------------------------
  1123.  | This handler is called by a click on the Fill button. This causes the 
  1124.  | array to be filled with default values, depending on the array type.
  1125.  +---------------------------------------------------------------------------}
  1126. procedure TMainForm.BtnFillClick(Sender: TObject);
  1127. Var
  1128.   n: Cardinal;
  1129.   s: TFixedStr;
  1130.   pCh: PChar;
  1131.   l: LongInt;
  1132. begin
  1133.   Case FArrayType Of
  1134.     TA_LONG:
  1135.       For n:= 0 To FArray.MaxIndex Do
  1136.         TLongIntArray(FArray)[n] := Random( 500 );
  1137.     TA_DOUBLE:
  1138.       For n:= 0 To FArray.MaxIndex Do
  1139.         TDoubleArray(FArray)[n] := Sqrt( Round(Random(10000)));
  1140.     TA_FIXED:
  1141.       For n:= 0 To FArray.MaxIndex Do Begin
  1142.         s := Format('<%.8d>',[n]);
  1143.         FArray.PutItem( n, s );
  1144.       End;
  1145.     TA_STRING:
  1146.       For n:= 0 To FArray.MaxIndex Do
  1147.         TPStringArray(FArray)[n] :=
  1148.            Format('This is Line number %d!',[n]);
  1149.     TA_PCHAR: Begin
  1150.         pCh := StrAlloc( 100 );
  1151.         try
  1152.           For n:= 0 To FArray.MaxIndex Do Begin
  1153.             l := n;
  1154.             wvsprintf( pCh, 'This is Line number %#lX!', l );
  1155.             TPCharArray(FArray)[n] := pCh;
  1156.           End;
  1157.         finally
  1158.           StrDispose( pCh );
  1159.         end;
  1160.       End;
  1161.   End; { Case }
  1162.   FillListbox;
  1163.   ArrayItems.ItemIndex:= 0;
  1164. end;
  1165.  
  1166. begin
  1167.   Randomize;
  1168. end.
  1169.