1 {
2  ***************************************************************************
3  *                                                                         *
4  *   This source is free software; you can redistribute it and/or modify   *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This code is distributed in the hope that it will be useful, but      *
10  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
12  *   General Public License for more details.                              *
13  *                                                                         *
14  *   A copy of the GNU General Public License is available on the World    *
15  *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
16  *   obtain it by writing to the Free Software Foundation,                 *
17  *   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.   *
18  *                                                                         *
19  ***************************************************************************
20 
21   Author: Mattias Gaertner
22 
23   Abstract:
24     TAddToPackageDlg is the form for adding files to an open package.
25 }
26 unit AddToPackageDlg;
27 
28 {$mode objfpc}{$H+}
29 
30 interface
31 
32 uses
33   Classes, SysUtils, Laz_AVL_Tree,
34   // LCL
35   LCLProc, LCLType, Forms, Controls, Buttons, ExtDlgs, StdCtrls, ExtCtrls,
36   Dialogs, ComCtrls, ButtonPanel,
37   // LazUtils
38   FileUtil, LazFileUtils,
39   // IDEIntf
40   NewItemIntf, PackageIntf, FormEditingIntf, IDEWindowIntf, ComponentReg,
41   IDEDialogs,
42   // IDE
43   LazarusIDEStrConsts, InputHistory, EnvironmentOpts,
44   PackageSystem, PackageDefs, ProjPackChecks;
45 
46 type
47 
48   { TAddToPkgResult }
49 
50   TAddToPkgResult = class
51   public
52     Pkg: TLazPackage;
53     UnitFilename: string;
54     Unit_Name: string;
55     AncestorType: string;
56     NewClassName: string;
57     PageName: string;
58     FileType: TPkgFileType;
59     PkgFileFlags: TPkgFileFlags;
60     UsedUnitname: string;
61     IconNormFile: string;
62     Icon150File: string;
63     Icon200File: string;
64     AutoAddLFMFile: boolean;
65     AutoAddLRSFile: boolean;
66     NewItem: TNewIDEItemTemplate;
67     Next: TAddToPkgResult;
68     procedure Clear;
69     destructor Destroy; override;
70   end;
71 
72   TOnGetUnitRegisterInfo = procedure(Sender: TObject; const AFilename: string;
73     out TheUnitName: string; out HasRegisterProc: boolean) of object;
74 
75   { TIconGuiStuff }
76 
77   TIconGuiStuff = class
78   // Join icon related GUI controls together. Streamlines the code.
79   private
80     Btn: TBitBtn;
81     InfoLabel: TLabel;
82     Title: string;
83     FileName: string;
84   public
85     constructor Create(aBtn: TBitBtn; aInfoLabel: TLabel; aTitle: string);
86     procedure LoadIcon(aLazPackage: TLazPackage; aFileName: string);
87   end;
88 
89   { TAddToPackageDlg }
90 
91   TAddToPackageDlg = class(TForm)
92     AncestorComboBox: TComboBox;
93     AncestorShowAllCheckBox: TCheckBox;
94     AncestorTypeLabel: TLabel;
95     ButtonPanel1: TButtonPanel;
96     ClassNameEdit: TEdit;
97     ClassNameLabel: TLabel;
98     Icon200Label: TLabel;
99     IconNormBitBtn: TBitBtn;
100     Icon150BitBtn: TBitBtn;
101     Icon150InfoLabel: TLabel;
102     Icon200InfoLabel: TLabel;
103     IconNormLabel: TLabel;
104     UnitFilenameExistsLabel: TLabel;
105     UnitDirectoryBrowseButton: TButton;
106     UnitDirectoryEdit: TEdit;
107     UnitDirectoryLabel: TLabel;
108     UnitDirectoryShortenButton: TButton;
109     UnitNameEdit: TEdit;
110     UnitNameLabel: TLabel;
111     Icon200BitBtn: TBitBtn;
112     Icon150Label: TLabel;
113     IconNormInfoLabel: TLabel;
114     UnitFilenameLabel: TLabel;
115     PalettePageCombobox: TComboBox;
116     PalettePageLabel: TLabel;
117     procedure AddToPackageDlgClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
118     procedure AncestorComboBoxChange(Sender: TObject);
119     procedure AncestorComboBoxCloseUp(Sender: TObject);
120     procedure AncestorShowAllCheckBoxClick(Sender: TObject);
121     procedure ClassNameEditChange(Sender: TObject);
122     procedure IconBitBtnClick(Sender: TObject);
123     procedure UnitDirectoryBrowseButtonClick(Sender: TObject);
124     procedure UnitDirectoryShortenButtonClick(Sender: TObject);
125     procedure UnitDirectoryEditChange(Sender: TObject);
126     procedure UnitNameEditChange(Sender: TObject);
127     procedure FormCreate(Sender: TObject);
128     procedure FormDestroy(Sender: TObject);
129     procedure NewComponentButtonClick(Sender: TObject);
130   private
131     fLastNewAncestorType: string;
132     fLastNewClassName: string;
133     FLazPackage: TLazPackage;
134     fPkgComponents: TAVLTree;// tree of TPkgComponent
135     fPackages: TAVLTree;// tree of  TLazPackage or TPackageLink
136     fParams: TAddToPkgResult;
137     fIconDlg: TOpenPictureDialog;
138     fIconNormGUI: TIconGuiStuff;
139     fIcon150GUI: TIconGuiStuff;
140     fIcon200GUI: TIconGuiStuff;
GenerateUnitFileNamenull141     function GenerateUnitFileName: string;
RelatedIconFilenull142     function RelatedIconFile(aSuffix: string): string;
143     procedure SetLazPackage(const AValue: TLazPackage);
144     procedure OnIterateComponentClasses(PkgComponent: TPkgComponent);
CheckNewCompOknull145     function CheckNewCompOk: Boolean;
146     procedure AutoCompleteNewComponent;
147     procedure AutoCompleteUnitName;
148     procedure UpdateUnitFilename;
149   public
150     procedure UpdateAvailableAncestorTypes;
151     procedure UpdateAvailablePageNames;
152   public
153     property LazPackage: TLazPackage read FLazPackage write SetLazPackage;
154   end;
155 
ShowAddToPackageDlgnull156 function ShowAddToPackageDlg(Pkg: TLazPackage; out Params: TAddToPkgResult): TModalResult;
157 
158 
159 implementation
160 
161 {$R *.lfm}
162 
ShowAddToPackageDlgnull163 function ShowAddToPackageDlg(Pkg: TLazPackage; out Params: TAddToPkgResult): TModalResult;
164 var
165   AddDlg: TAddToPackageDlg;
166 begin
167   Params:=nil;
168   AddDlg:=TAddToPackageDlg.Create(nil);
169   try
170     AddDlg.LazPackage:=Pkg;
171     Result:=AddDlg.ShowModal;
172     if Result=mrOk then begin
173       Params:=AddDlg.fParams;
174       AddDlg.fParams:=nil;
175     end;
176   finally
177     AddDlg.Free;
178   end;
179 end;
180 
181 { TIconGuiStuff }
182 
183 constructor TIconGuiStuff.Create(aBtn: TBitBtn; aInfoLabel: TLabel; aTitle: string);
184 begin
185   Btn:=aBtn;
186   InfoLabel:=aInfoLabel;
187   Title:=aTitle;
188   InfoLabel.Caption:='';
189 end;
190 
191 procedure TIconGuiStuff.LoadIcon(aLazPackage: TLazPackage; aFileName: string);
192 var
193   ShortFN: String;
194   Image: TImage;
195   W, H: Integer;
196 begin
197   Filename:=aFileName;
198   try
199     Image:=TImage.Create(nil);
200     try
201       Image.Picture.LoadFromFile(Filename);
202       W:=Image.Picture.Graphic.Width+6;
203       H:=Image.Picture.Graphic.Height+6;
204       if W > 32 then
205         Btn.Width:=W;
206       if H > 32 then
207         Btn.Height:=H;
208       Btn.Glyph.Assign(Image.Picture.Graphic);
209       ShortFN:=Filename;
210       aLazPackage.ShortenFilename(ShortFN,true);
211       InfoLabel.Caption:=Format('%s (%dx%d)',[ShortFN, Btn.Glyph.Width, Btn.Glyph.Height]);
212     finally
213       Image.Free;
214     end;
215   except
216     on E: Exception do begin
217       IDEMessageDialog(lisCCOErrorCaption,
218         Format(lisErrorLoadingFile2,[FileName]) + LineEnding + E.Message,
219         mtError, [mbCancel]);
220       Btn.Glyph.Clear;
221       InfoLabel.Caption:=lisNoneClickToChooseOne;
222       FileName:='';
223     end;
224   end;
225 end;
226 
227 { TAddToPackageDlg }
228 
229 procedure TAddToPackageDlg.FormCreate(Sender: TObject);
230 begin
231   Caption:=lisMenuNewComponent;
232   fPkgComponents:=TAVLTree.Create(@CompareIDEComponentByClassName);
233   fPackages:=TAVLTree.Create(@CompareLazPackageID);
234   fParams:=TAddToPkgResult.Create;
235   IDEDialogLayoutList.ApplyLayout(Self,700,400);
236   // Setup Components
237   ButtonPanel1.OkButton.Caption:=lisA2PCreateNewComp;
238   ButtonPanel1.OkButton.OnClick:=@NewComponentButtonClick;
239   CheckNewCompOk;
240   AncestorTypeLabel.Caption:=lisA2PAncestorType;
241   AncestorComboBox.Text:='';
242   AncestorShowAllCheckBox.Caption:=lisA2PShowAll;
243   ClassNameLabel.Caption:=lisA2PNewClassName;
244   ClassNameEdit.Text:='';
245   PalettePageLabel.Caption:=lisA2PPalettePage;
246   PalettePageCombobox.Text:='';
247   UnitDirectoryLabel.Caption:=lisA2PDirectoryForUnitFile;
248   UnitDirectoryEdit.Text:='';
249   UnitFilenameLabel.Caption:='';
250   UnitFilenameExistsLabel.Caption:='';
251   with UnitDirectoryBrowseButton do begin
252     Caption:='...';
253     ShowHint:=true;
254     Hint:=lisChooseDirectory;
255   end;
256   with UnitDirectoryShortenButton do begin
257     Caption:='<>';
258     ShowHint:=true;
259     Hint:=lisA2PShortenOrExpandFilename;
260   end;
261   UnitNameLabel.Caption:=lisA2PUnitName;
262   UnitNameEdit.Text:='';
263   IconNormLabel.Caption:=lisA2PIcon24x24;
264   Icon150Label.Caption:=lisA2PIcon36x36;
265   Icon200Label.Caption:=lisA2PIcon48x48;
266   fIconDlg:=TOpenPictureDialog.Create(nil);
267   // Helper objects to join icon related GUI controls together
268   fIconNormGUI:=TIconGuiStuff.Create(IconNormBitBtn, IconNormInfoLabel, lisA2PIcon24x24);
269   fIcon150GUI:=TIconGuiStuff.Create(Icon150BitBtn, Icon150InfoLabel, lisA2PIcon36x36);
270   fIcon200GUI:=TIconGuiStuff.Create(Icon200BitBtn, Icon200InfoLabel, lisA2PIcon48x48);
271 end;
272 
273 procedure TAddToPackageDlg.FormDestroy(Sender: TObject);
274 begin
275   FreeAndNil(fIcon200GUI);
276   FreeAndNil(fIcon150GUI);
277   FreeAndNil(fIconNormGUI);
278   FreeAndNil(fIconDlg);
279   FreeAndNil(fParams);
280   FreeAndNil(fPackages);
281   FreeAndNil(fPkgComponents);
282 end;
283 
284 procedure TAddToPackageDlg.AddToPackageDlgClose(Sender: TObject;
285   var CloseAction: TCloseAction);
286 begin
287   IDEDialogLayoutList.SaveLayout(Self);
288 end;
289 
290 procedure TAddToPackageDlg.AncestorComboBoxChange(Sender: TObject);
291 begin
292   CheckNewCompOk;
293 end;
294 
295 procedure TAddToPackageDlg.AncestorComboBoxCloseUp(Sender: TObject);
296 begin
297   if fLastNewAncestorType<>AncestorComboBox.Text then
298     AutoCompleteNewComponent;
299 end;
300 
301 procedure TAddToPackageDlg.AncestorShowAllCheckBoxClick(Sender: TObject);
302 begin
303   UpdateAvailableAncestorTypes;
304 end;
305 
306 procedure TAddToPackageDlg.ClassNameEditChange(Sender: TObject);
307 begin
308   AutoCompleteUnitName;
309   CheckNewCompOk;
310 end;
311 
TAddToPackageDlg.RelatedIconFilenull312 function TAddToPackageDlg.RelatedIconFile(aSuffix: string): string;
313 var
314   Ext: String;
315 begin
316   Ext := ExtractFileExt(fIconDlg.FileName);
317   Result := ExtractFileNameWithoutExt(fIconDlg.FileName)+ASuffix+Ext;
318 end;
319 
320 procedure TAddToPackageDlg.IconBitBtnClick(Sender: TObject);
321 var
322   Btn: TBitBtn;
323   IconGUI: TIconGuiStuff;
324   OtherIconFile: string;
325 begin
326   Btn:=Sender as TBitBtn;
327   if Btn = IconNormBitBtn then
328     IconGUI:=fIconNormGUI
329   else if Btn = Icon150BitBtn then
330     IconGUI:=fIcon150GUI
331   else if Btn = Icon200BitBtn then
332     IconGUI:=fIcon200GUI;
333   if fIconDlg.InitialDir='' then
334     fIconDlg.InitialDir:=LazPackage.Directory;
335   fIconDlg.Title:=IconGUI.Title;
336   fIconDlg.Options:=fIconDlg.Options+[ofPathMustExist];
337   fIconDlg.Filter:=Format('%s|*.png|%s|*.bmp|%s|*.xpm|%s|%s',
338     [dlgFilterImagesPng,
339      dlgFilterImagesBitmap,
340      dlgFilterImagesPixmap,
341      dlgFilterAll, GetAllFilesMask]);
342 
343   if fIconDlg.Execute then begin
344     IconGUI.LoadIcon(LazPackage, fIconDlg.FileName);
345     // Load high resolution icons automatically if found.
346     if Btn = IconNormBitBtn then begin
347       // 150%
348       OtherIconFile:=RelatedIconFile('_150');
349       if FileExists(OtherIconFile) then
350         fIcon150GUI.LoadIcon(LazPackage, OtherIconFile);
351       // 200%
352       OtherIconFile:=RelatedIconFile('_200');
353       if FileExists(OtherIconFile) then
354         fIcon200GUI.LoadIcon(LazPackage, OtherIconFile);
355     end;
356   end;
357 end;
358 
359 procedure TAddToPackageDlg.UnitDirectoryBrowseButtonClick(Sender: TObject);
360 var
361   DirDialog: TSelectDirectoryDialog;
362 begin
363   DirDialog:=TSelectDirectoryDialog.Create(nil);
364   try
365     InputHistories.ApplyFileDialogSettings(DirDialog);
366     DirDialog.InitialDir:=LazPackage.Directory;
367     DirDialog.Title:=lisA2PDirectoryForUnitFile;
368     //DirDialog.Options:=DirDialog.Options+[ofPathMustExist];
369     //DirDialog.Filter:=Format('%s|*.pas;*.pp', [dlgFilterPascalFile]);
370     if DirDialog.Execute then begin
371       UnitDirectoryEdit.Text:=DirDialog.Filename;
372       UpdateUnitFilename;
373     end;
374     InputHistories.StoreFileDialogSettings(DirDialog);
375   finally
376     DirDialog.Free;
377   end;
378 end;
379 
380 procedure TAddToPackageDlg.UnitDirectoryShortenButtonClick(Sender: TObject);
381 var
382   S: string;
383 begin
384   Assert(LazPackage.HasDirectory and FilenameIsAbsolute(LazPackage.Directory),
385          'Unexpected package directory');
386   S:=UnitDirectoryEdit.Text;
387   if (S='') then
388     S:='.';
389   // Toggle between absolute and relative paths.
390   if FilenameIsAbsolute(S) then
391     UnitDirectoryEdit.Text:=CreateRelativePath(S,LazPackage.Directory,True)
392   else
393     UnitDirectoryEdit.Text:=CreateAbsolutePath(S,LazPackage.Directory);
394   UpdateUnitFilename;
395 end;
396 
397 procedure TAddToPackageDlg.UnitDirectoryEditChange(Sender: TObject);
398 begin
399   UpdateUnitFilename;
400   if UnitDirectoryEdit.Text<>'' then
401     fIconDlg.InitialDir:=UnitDirectoryEdit.Text;
402 end;
403 
404 procedure TAddToPackageDlg.UnitNameEditChange(Sender: TObject);
405 begin
406   CheckNewCompOk;
407   UpdateUnitFilename;
408 end;
409 
410 procedure TAddToPackageDlg.NewComponentButtonClick(Sender: TObject);
411 var
412   PkgFile: TPkgFile;
413   PkgComponent: TPkgComponent;
414   ARequiredPackage: TLazPackage;
415   NewDependency: TPkgDependency;
416   ThePath: String;
417 begin
418   fParams.Clear;
419   fParams.FileType:=pftUnit;
420   fParams.PkgFileFlags:=[pffHasRegisterProc,pffAddToPkgUsesSection];
421   fParams.AncestorType:=AncestorComboBox.Text;
422   fParams.NewClassName:=ClassNameEdit.Text;
423   fParams.PageName:=PalettePageCombobox.Text;
424   fParams.Unit_Name:=UnitNameEdit.Text;
425   fParams.UsedUnitname:='';
426   fParams.IconNormFile:=fIconNormGUI.Filename;
427   fParams.Icon150File:=fIcon150GUI.Filename;
428   fParams.Icon200File:=fIcon200GUI.Filename;
429 
430   // prepend path to unit filename
431   ThePath:=UnitDirectoryEdit.Text;
432   if ThePath='' then
433     ThePath:='.';
434   ThePath:=CreateAbsolutePath(ThePath,LazPackage.Directory);
435   if not DirectoryExists(ThePath) then
436     if not ForceDirectories(ThePath) then
437       raise Exception.Create('NewComponentButtonClick: Cannot create directory '+ThePath);
438   fParams.UnitFilename:=AppendPathDelim(ThePath)+GenerateUnitFileName;
439 
440   // check if package is readonly
441   if LazPackage.ReadOnly then begin
442     IDEMessageDialog(lisAF2PPackageIsReadOnly,
443       Format(lisAF2PThePackageIsReadOnly, [LazPackage.IDAsString]),
444       mtError,[mbCancel]);
445     exit;
446   end;
447   // check Ancestor Type
448   if not IsValidIdent(fParams.AncestorType) then begin
449     IDEMessageDialog(lisA2PInvalidAncestorType,
450       Format(lisA2PTheAncestorTypeIsNotAValidPascalIdentifier, [fParams.AncestorType]),
451       mtError,[mbCancel]);
452     exit;
453   end;
454   // check pagename
455   if length(fParams.PageName)>100 then begin
456     IDEMessageDialog(lisA2PPageNameTooLong,
457       Format(lisA2PThePageNameIsTooLongMax100Chars, [fParams.PageName]),
458       mtError,[mbCancel]);
459     exit;
460   end;
461   // check classname
462   if not IsValidIdent(fParams.NewClassName) then begin
463     IDEMessageDialog(lisA2PInvalidClassName,
464       Format(lisA2PTheClassNameIsNotAValidPascalIdentifier, [fParams.NewClassName]),
465       mtError,[mbCancel]);
466     exit;
467   end;
468   // check classname<>ancestortype
469   if CompareText(fParams.NewClassName,fParams.AncestorType)=0 then begin
470     IDEMessageDialog(lisA2PInvalidCircularDependency,
471       Format(lisA2PTheClassNameAndAncestorTypeAreTheSame,[fParams.NewClassName,fParams.AncestorType]),
472       mtError,[mbCancel]);
473     exit;
474   end;
475   // check ancestor type is not unitname
476   PkgFile:=PackageGraph.FindUnit(LazPackage,fParams.AncestorType,true,true);
477   if PkgFile<>nil then begin
478     if IDEMessageDialog(lisA2PAmbiguousAncestorType,
479       Format(lisA2PTheAncestorTypeHasTheSameNameAsTheUnit,
480              [fParams.AncestorType, LineEnding, PkgFile.Filename]),
481       mtError,[mbCancel,mbIgnore])<>mrIgnore
482     then
483       exit;
484   end;
485   // check classname does not interfere with an existing unitname
486   PkgFile:=PackageGraph.FindUnit(LazPackage,fParams.NewClassName,true,true);
487   if PkgFile<>nil then begin
488     if IDEMessageDialog(lisA2PAmbiguousClassName,
489       Format(lisA2PTheClassNameHasTheSameNameAsTheUnit,
490              [fParams.AncestorType, LineEnding, PkgFile.Filename]),
491       mtError,[mbCancel,mbIgnore])<>mrIgnore
492     then
493       exit;
494   end;
495   // check if classname already exists
496   PkgComponent:=TPkgComponent(IDEComponentPalette.FindComponent(fParams.NewClassname));
497   if PkgComponent<>nil then begin
498     if IDEMessageDialog(lisA2PClassNameAlreadyExists,
499       Format(lisA2PTheClassNameExistsAlreadyInPackageFile, [fParams.NewClassName, LineEnding,
500         PkgComponent.PkgFile.LazPackage.IDAsString, LineEnding, PkgComponent.PkgFile.Filename]),
501       mtError,[mbCancel,mbIgnore])<>mrIgnore
502     then
503       exit;
504   end;
505   // check if unitname is a componentclass
506   if IDEComponentPalette.FindComponent(fParams.Unit_Name)<>nil then begin
507     if IDEMessageDialog(lisA2PAmbiguousUnitName,
508       Format(lisA2PTheUnitNameIsTheSameAsAnRegisteredComponent,[fParams.Unit_Name,LineEnding]),
509       mtWarning,[mbCancel,mbIgnore])<>mrIgnore
510     then
511       exit;
512   end;
513 
514   // create dependency if needed
515   PkgComponent:=TPkgComponent(IDEComponentPalette.FindComponent(fParams.AncestorType));
516   if PkgComponent<>nil then begin
517     fParams.UsedUnitname:=PkgComponent.GetUnitName;
518     ARequiredPackage:=PkgComponent.PkgFile.LazPackage;
519     ARequiredPackage:=TLazPackage(PackageEditingInterface.RedirectPackageDependency(ARequiredPackage));
520     NewDependency:=TPkgDependency.Create;
521     NewDependency.DependencyType:=pdtLazarus;
522     NewDependency.PackageName:=ARequiredPackage.Name;
523     if CheckAddingPackageDependency(LazPackage,NewDependency,false,false)=mrOK then
524       PackageGraph.AddDependencyToPackage(LazPackage, NewDependency)
525     else
526       NewDependency.Free;
527   end;
528   ModalResult:=mrOk;
529 end;
530 
531 procedure TAddToPackageDlg.SetLazPackage(const AValue: TLazPackage);
532 begin
533   if FLazPackage=AValue then exit;
534   FLazPackage:=AValue;
535   fParams.Pkg:=FLazPackage;
536   UpdateAvailableAncestorTypes;
537   UpdateAvailablePageNames;
538 end;
539 
TAddToPackageDlg.CheckNewCompOknull540 function TAddToPackageDlg.CheckNewCompOk: Boolean;
541 begin
542   Result:=(AncestorComboBox.Text<>'') and (ClassNameEdit.Text<>'') and (UnitNameEdit.Text<>'');
543   ButtonPanel1.OKButton.Enabled:=Result;
544 end;
545 
546 procedure TAddToPackageDlg.OnIterateComponentClasses(PkgComponent: TPkgComponent);
547 begin
548   if fPkgComponents.Find(PkgComponent)=nil then
549     fPkgComponents.Add(PkgComponent);
550 end;
551 
GenerateUnitFileNamenull552 function TAddToPackageDlg.GenerateUnitFileName: string;
553 begin
554   Result:=UnitNameEdit.Text;
555   if Result='' then Exit;
556   if EnvironmentOptions.CharcaseFileAction in [ccfaAsk, ccfaAutoRename] then
557     Result:=LowerCase(Result);
558   // append pascal file extension
559   Result:=Result+PascalExtension[EnvironmentOptions.PascalFileExtension];
560 end;
561 
562 procedure TAddToPackageDlg.AutoCompleteNewComponent;
563 var
564   PkgComponent: TPkgComponent;
565 begin
566   fLastNewAncestorType:=AncestorComboBox.Text;
567   if not IsValidIdent(fLastNewAncestorType) then exit;
568   PkgComponent:=TPkgComponent(IDEComponentPalette.FindComponent(fLastNewAncestorType));
569   // create unique classname
570   ClassNameEdit.Text:=IDEComponentPalette.CreateNewClassName(fLastNewAncestorType);
571   // choose the same page name
572   if (PkgComponent<>nil) and (PkgComponent.RealPage<>nil) then
573     PalettePageCombobox.Text:=PkgComponent.RealPage.PageName;
574   // filename
575   AutoCompleteUnitName;
576   ButtonPanel1.OkButton.Enabled:=True;
577 end;
578 
579 procedure TAddToPackageDlg.AutoCompleteUnitName;
580 var
581   CurClassName: String;
582   NewUnitName: String;
583 begin
584   // check if update needed
585   CurClassName:=ClassNameEdit.Text;
586   if fLastNewClassName=CurClassName then exit;
587   fLastNewClassName:=CurClassName;
588   // check classname
589   if not IsValidIdent(CurClassName) then exit;
590   // create unitname
591   NewUnitName:=CurClassName;
592   if NewUnitName[1]='T' then
593     NewUnitName:=copy(NewUnitName,2,length(NewUnitName)-1);
594   NewUnitName:=PackageGraph.CreateUniqueUnitName(NewUnitName);
595   UnitNameEdit.Text:=NewUnitName;
596   // default directory
597   UnitDirectoryEdit.Text:=LazPackage.Directory;
598 end;
599 
600 procedure TAddToPackageDlg.UpdateUnitFilename;
601 begin
602   UnitFilenameLabel.Caption:=AppendPathDelim(UnitDirectoryEdit.Text)+GenerateUnitFileName;
603   if FileExists(UnitFilenameLabel.Caption) then
604     UnitFilenameExistsLabel.Caption:=lisA2PFileAlreadyExists
605   else
606     UnitFilenameExistsLabel.Caption:='';
607 end;
608 
609 procedure TAddToPackageDlg.UpdateAvailableAncestorTypes;
610 var
611   ANode: TAVLTreeNode;
612   sl: TStringList;
613   OldAncestorType: String;
614 begin
615   // get all available registered components
616   fPkgComponents.Clear;
617   if AncestorShowAllCheckBox.Checked then begin
618     PackageGraph.IterateAllComponentClasses(@OnIterateComponentClasses);
619   end else begin
620     PackageGraph.IterateComponentClasses(LazPackage,@OnIterateComponentClasses,
621                                          true,true);
622   end;
623   // put them into a list
624   sl:=TStringList.Create;
625   ANode:=fPkgComponents.FindLowest;
626   while ANode<>nil do begin
627     sl.Add(TPkgComponent(ANode.Data).ComponentClass.ClassName);
628     ANode:=fPkgComponents.FindSuccessor(ANode);
629   end;
630   // add at least TComponent
631   sl.Add('TComponent');
632   sl.Sort;
633 
634   // put them into the combobox
635   OldAncestorType:=AncestorComboBox.Text;
636   AncestorComboBox.Items.Assign(sl);
637   AncestorComboBox.Text:=OldAncestorType;
638   sl.Free;
639 end;
640 
641 procedure TAddToPackageDlg.UpdateAvailablePageNames;
642 var
643   i: Integer;
644   APageName: String;
645   sl: TStringList;
646 begin
647   // get all current pagenames (excluding the hidden page)
648   sl:=TStringList.Create;
649   for i:=0 to IDEComponentPalette.Pages.Count-1 do begin
650     APageName:=IDEComponentPalette.Pages[i].PageName;
651     if APageName<>'' then
652       sl.Add(APageName);
653   end;
654   sl.Sort;
655   PalettePageCombobox.Items.Assign(sl);
656   sl.Free;
657 end;
658 
659 { TAddToPkgResult }
660 
661 procedure TAddToPkgResult.Clear;
662 begin
663   UnitFilename:='';
664   Unit_Name:='';
665   AncestorType:='';
666   NewClassName:='';
667   PageName:='';
668   FileType:=pftUnit;
669   PkgFileFlags:=[];
670   UsedUnitname:='';
671   AutoAddLFMFile:=false;
672   AutoAddLRSFile:=false;
673   FreeThenNil(Next);
674 end;
675 
676 destructor TAddToPkgResult.Destroy;
677 begin
678   FreeThenNil(Next);
679   inherited Destroy;
680 end;
681 
682 end.
683 
684