PageRenderTime 125ms CodeModel.GetById 24ms app.highlight 86ms RepoModel.GetById 1ms app.codeStats 1ms

/packager/addtopackagedlg.pas

http://github.com/graemeg/lazarus
Pascal | 1335 lines | 1125 code | 120 blank | 90 comment | 117 complexity | 470cf238b6155242726d60b28f023de7 MD5 | raw file
   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.        *
  18 *                                                                         *
  19 ***************************************************************************
  20
  21  Author: Mattias Gaertner
  22
  23  Abstract:
  24    TAddToPackageDlg is the form for adding files to an open package.
  25}
  26unit AddToPackageDlg;
  27
  28{$mode objfpc}{$H+}
  29
  30interface
  31
  32uses
  33  Math, Classes, SysUtils, AVL_Tree,
  34  // LCL
  35  LCLProc, LCLType, Forms, Controls, Buttons, ExtDlgs, StdCtrls, ExtCtrls,
  36  Dialogs, ComCtrls, ButtonPanel,
  37  ListFilterEdit,
  38  // LazUtils
  39  FileUtil, LazFileUtils,
  40  // IDEIntf
  41  NewItemIntf, PackageIntf, FormEditingIntf, IDEWindowIntf, ComponentReg, IDEDialogs,
  42  // IDE
  43  LazarusIDEStrConsts, InputHistory, IDEDefs, EnvironmentOpts,
  44  PackageSystem, PackageDefs, AddDirToPkgDlg;
  45  
  46type
  47  TAddToPkgType = (
  48    d2ptUnit,
  49    d2ptVirtualUnit,
  50    d2ptNewComponent,
  51    d2ptRequiredPkg,
  52    d2ptFile,
  53    d2ptFiles
  54    );
  55    
  56  { TAddToPkgResult }
  57
  58  TAddToPkgResult = class
  59  public
  60    Pkg: TLazPackage;
  61    AddType: TAddToPkgType;
  62    Dependency: TPkgDependency;
  63    UnitFilename: string;
  64    Unit_Name: string;
  65    AncestorType: string;
  66    NewClassName: string;
  67    PageName: string;
  68    FileType: TPkgFileType;
  69    PkgFileFlags: TPkgFileFlags;
  70    UsedUnitname: string;
  71    IconFile: string;
  72    AutoAddLFMFile: boolean;
  73    AutoAddLRSFile: boolean;
  74    NewItem: TNewIDEItemTemplate;
  75    Next: TAddToPkgResult;
  76    procedure Clear;
  77    destructor Destroy; override;
  78  end;
  79  
  80  TOnGetUnitRegisterInfo = procedure(Sender: TObject; const AFilename: string;
  81    out TheUnitName: string; out HasRegisterProc: boolean) of object;
  82
  83  { TAddToPackageDlg }
  84
  85  TAddToPackageDlg = class(TForm)
  86    AddFilesBtnPanel: TPanel;
  87    AddFilesPage: TTabSheet;
  88    AncestorComboBox: TComboBox;
  89    AncestorShowAllCheckBox: TCheckBox;
  90    AncestorTypeLabel: TLabel;
  91    ButtonPanel1: TButtonPanel;
  92    ClassNameEdit: TEdit;
  93    ClassNameLabel: TLabel;
  94    ComponentIconLabel: TLabel;
  95    ComponentIconBitBtn: TBitBtn;
  96    ComponentUnitFileBrowseButton: TButton;
  97    ComponentUnitFileEdit: TEdit;
  98    ComponentUnitFileLabel: TLabel;
  99    ComponentUnitFileShortenButton: TButton;
 100    ComponentUnitNameEdit: TEdit;
 101    ComponentUnitNameLabel: TLabel;
 102    DependMaxVersionEdit: TEdit;
 103    DependMaxVersionLabel: TLabel;
 104    DependMinVersionEdit: TEdit;
 105    DependMinVersionLabel: TLabel;
 106    DependPkgNameLabel: TLabel;
 107    FilesDeleteButton: TBitBtn;
 108    FilesDirButton: TBitBtn;
 109    FilesListView: TListView;
 110    FilesShortenButton: TBitBtn;
 111    LabelIconInfo: TLabel;
 112    DependPkgNameListBox: TListBox;
 113    DependPkgNameFilter: TListFilterEdit;
 114    NewComponentPage: TTabSheet;
 115    NewDepPanel: TPanel;
 116    NewRequirementPage: TTabSheet;
 117    PageControl1: TPageControl;
 118    PalettePageCombobox: TComboBox;
 119    PalettePageLabel: TLabel;
 120    procedure AddToPackageDlgClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
 121    procedure AddToPackageDlgKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
 122    procedure AncestorComboBoxChange(Sender: TObject);
 123    procedure AncestorComboBoxCloseUp(Sender: TObject);
 124    procedure AncestorShowAllCheckBoxClick(Sender: TObject);
 125    procedure CancelAddFileButtonClick(Sender: TObject);
 126    procedure CancelAddUnitButtonClick(Sender: TObject);
 127    procedure ClassNameEditChange(Sender: TObject);
 128    procedure ComponentIconBitBtnClick(Sender: TObject);
 129    procedure ComponentUnitFileBrowseButtonClick(Sender: TObject);
 130    procedure ComponentUnitFileShortenButtonClick(Sender: TObject);
 131    procedure ComponentUnitNameEditChange(Sender: TObject);
 132    procedure DependPkgNameListBoxSelectionChange(Sender: TObject; {%H-}User: boolean);
 133    procedure FilesAddButtonClick(Sender: TObject);
 134    procedure FilesDeleteButtonClick(Sender: TObject);
 135    procedure FilesDirButtonClick(Sender: TObject);
 136    procedure FilesListViewSelectItem(Sender: TObject; {%H-}Item: TListItem; {%H-}Selected: Boolean);
 137    procedure FilesShortenButtonClick(Sender: TObject);
 138    procedure FormCreate(Sender: TObject);
 139    procedure FormDestroy(Sender: TObject);
 140    procedure FormShow(Sender: TObject);
 141    procedure NewComponentButtonClick(Sender: TObject);
 142    procedure NewComponentPageResize(Sender: TObject);
 143    procedure NewDependButtonClick(Sender: TObject);
 144    procedure PageControl1Change(Sender: TObject);
 145  private
 146    fLastNewComponentAncestorType: string;
 147    fLastNewComponentClassName: string;
 148    FLazPackage: TLazPackage;
 149    FOnGetIDEFileInfo: TGetIDEFileStateEvent;
 150    FOnGetUnitRegisterInfo: TOnGetUnitRegisterInfo;
 151    fPkgComponents: TAVLTree;// tree of TPkgComponent
 152    fPackages: TAVLTree;// tree of  TLazPackage or TPackageLink
 153    FComponentIconFilename: string;
 154    function GetActivatePage: TAddToPkgType;
 155    procedure SetActivatePage(AValue: TAddToPkgType);
 156    procedure SetLazPackage(const AValue: TLazPackage);
 157    procedure SetupComponents;
 158    procedure SetupNewComponentPage;
 159    procedure SetupAddDependencyPage;
 160    procedure SetupAddFilesPage;
 161    procedure OnIterateComponentClasses(PkgComponent: TPkgComponent);
 162    procedure OnIteratePackages(APackageID: TLazPackageID);
 163    function CheckNewCompOk: Boolean;
 164    function CheckNewReqOk: Boolean;
 165    function CheckFilesButtonsOk: Boolean;
 166    procedure AutoCompleteNewComponent;
 167    procedure AutoCompleteNewComponentUnitName;
 168    function SwitchRelativeAbsoluteFilename(const Filename: string): string;
 169    function FindFileInFilesList(AFilename: string): Integer;
 170    procedure LoadComponentIcon(AFilename: string);
 171  public
 172    Params: TAddToPkgResult;
 173    procedure UpdateAvailableAncestorTypes;
 174    procedure UpdateAvailablePageNames;
 175    procedure UpdateAvailableDependencyNames;
 176  public
 177    property LazPackage: TLazPackage read FLazPackage write SetLazPackage;
 178    property OnGetIDEFileInfo: TGetIDEFileStateEvent read FOnGetIDEFileInfo
 179                                                     write FOnGetIDEFileInfo;
 180    property OnGetUnitRegisterInfo: TOnGetUnitRegisterInfo
 181                       read FOnGetUnitRegisterInfo write FOnGetUnitRegisterInfo;
 182    property ActivatePage: TAddToPkgType read GetActivatePage write SetActivatePage;
 183  end;
 184  
 185function ShowAddToPackageDlg(Pkg: TLazPackage; out Params: TAddToPkgResult;
 186  OnGetIDEFileInfo: TGetIDEFileStateEvent;
 187  OnGetUnitRegisterInfo: TOnGetUnitRegisterInfo;
 188  var Page: TAddToPkgType): TModalResult;
 189function CheckAddingUnitFilename(LazPackage: TLazPackage;
 190  AddFileType: TAddToPkgType; OnGetIDEFileInfo: TGetIDEFileStateEvent;
 191  var AFilename: string): boolean;
 192function CheckAddingDependency(LazPackage: TLazPackage;
 193  NewDependency: TPkgDependency; Quiet, WarnIfAlreadyThere: boolean
 194  ): TModalResult;// mrOk=can be added, mrCancel=do not add, mrIgnore=already there
 195function CheckAddingPkgDependency(LazPackage: TLazPackage;
 196  RequiredPkg: TLazPackage; Quiet, WarnIfAlreadyThere: boolean): TModalResult;
 197
 198
 199implementation
 200
 201{$R *.lfm}
 202
 203function ShowAddToPackageDlg(Pkg: TLazPackage; out Params: TAddToPkgResult;
 204  OnGetIDEFileInfo: TGetIDEFileStateEvent;
 205  OnGetUnitRegisterInfo: TOnGetUnitRegisterInfo; var Page: TAddToPkgType
 206  ): TModalResult;
 207var
 208  AddDlg: TAddToPackageDlg;
 209begin
 210  Params:=nil;
 211  AddDlg:=TAddToPackageDlg.Create(nil);
 212  AddDlg.OnGetIDEFileInfo:=OnGetIDEFileInfo;
 213  AddDlg.OnGetUnitRegisterInfo:=OnGetUnitRegisterInfo;
 214  AddDlg.LazPackage:=Pkg;
 215  AddDlg.ActivatePage:=Page;
 216
 217  //auto press AddFiles if called with "Add files" page
 218  if Page=d2ptFiles then
 219    AddDlg.FilesDirButton.Click;
 220  //hide tabs for simpler use
 221  AddDlg.PageControl1.ShowTabs:=false;
 222  AddDlg.PageControl1.TabStop:=false;
 223
 224  Result:=AddDlg.ShowModal;
 225  Page:=AddDlg.ActivatePage;
 226  if Result=mrOk then begin
 227    Params:=AddDlg.Params;
 228    AddDlg.Params:=nil;
 229  end;
 230  AddDlg.Free;
 231end;
 232
 233function CheckAddingUnitFilename(LazPackage: TLazPackage;
 234  AddFileType: TAddToPkgType; OnGetIDEFileInfo: TGetIDEFileStateEvent;
 235  var AFilename: string): boolean;
 236var
 237  AnUnitName: String;
 238  PkgFile: TPkgFile;
 239  Msg: String;
 240  IDEFileFlags: TIDEFileStateFlags;
 241begin
 242  Result:=false;
 243  PkgFile:=Nil;
 244
 245  // check if package is readonly
 246  if LazPackage.ReadOnly then begin
 247    IDEMessageDialog(lisAF2PPackageIsReadOnly,
 248      Format(lisAF2PThePackageIsReadOnly, [LazPackage.IDAsString]),
 249      mtError,[mbCancel]);
 250    exit;
 251  end;
 252
 253  // normalize filename
 254  AFilename:=TrimFilename(AFilename);
 255  if (AddFileType<>d2ptVirtualUnit) and (not FilenameIsAbsolute(AFilename)) then
 256  begin
 257    if LazPackage.HasDirectory then
 258      AFilename:=LazPackage.Directory+AFilename
 259    else begin
 260      IDEMessageDialog(lisA2PInvalidFilename,
 261        Format(lisA2PTheFilenameIsAmbiguousPleaseSpecifiyAFilename,[AFilename,LineEnding]),
 262        mtError,[mbCancel]);
 263      exit;
 264    end;
 265  end;
 266
 267  // check if file exists
 268  if (FilenameIsAbsolute(AFilename)) then begin
 269    if (not FileExistsUTF8(AFilename)) then begin
 270      if AddFileType=d2ptUnit then begin
 271        IDEMessageDialog(lisFileNotFound,
 272          Format(lisPkgMangFileNotFound, [AFilename]),
 273          mtError, [mbCancel]);
 274        exit;
 275      end;
 276    end;
 277  end;
 278
 279  // check if file already exists in package
 280  if FilenameIsAbsolute(AFilename) then begin
 281    PkgFile:=LazPackage.FindPkgFile(AFilename,true,false);
 282    if PkgFile<>nil then begin
 283      Msg:=Format(lisA2PFileAlreadyExistsInThePackage, [AFilename]);
 284      if PkgFile.Filename<>AFilename then
 285        Msg:=Msg+LineEnding+Format(lisA2PExistingFile2, [PkgFile.Filename]);
 286      IDEMessageDialog(lisA2PFileAlreadyExists, Msg, mtError, [mbCancel]);
 287      exit;
 288    end;
 289  end;
 290
 291  // check if file is part of project
 292  if FilenameIsAbsolute(AFilename) then begin
 293    if Assigned(OnGetIDEFileInfo) then begin
 294      IDEFileFlags:=[];
 295      OnGetIDEFileInfo(nil,AFilename,[ifsPartOfProject],IDEFileFlags);
 296      if (ifsPartOfProject in IDEFileFlags) then begin
 297        IDEMessageDialog(lisA2PFileIsUsed,
 298          Format(lisA2PTheFileIsPartOfTheCurrentProjectItIsABadIdea,[AFilename,LineEnding]),
 299          mtError,[mbCancel]);
 300        exit;
 301      end;
 302    end;
 303  end;
 304
 305  // check file extension
 306  if AddFileType in [d2ptUnit,d2ptNewComponent,d2ptVirtualUnit] then begin
 307    if not FilenameIsPascalUnit(AFilename) then begin
 308      IDEMessageDialog(lisA2PFileNotUnit,
 309        lisA2PPascalUnitsMustHaveTheExtensionPPOrPas,
 310        mtWarning,[mbCancel]);
 311      exit;
 312    end;
 313  end;
 314
 315  // check unitname
 316  if AddFileType in [d2ptUnit,d2ptNewComponent,d2ptVirtualUnit] then begin
 317    AnUnitName:=ExtractFileNameOnly(AFilename);
 318    if not IsValidUnitName(AnUnitName) then begin
 319      IDEMessageDialog(lisA2PFileNotUnit,
 320        Format(lisA2PisNotAValidUnitName, [AnUnitName]),
 321        mtWarning,[mbCancel]);
 322      exit;
 323    end;
 324
 325    // check if unitname already exists in package
 326    PkgFile:=LazPackage.FindUnit(AnUnitName,true,PkgFile);
 327    if PkgFile<>nil then begin
 328      // a unit with this name already exists in this package => warn
 329      if IDEMessageDialog(lisA2PUnitnameAlreadyExists,
 330        Format(lisA2PTheUnitnameAlreadyExistsInThisPackage, [AnUnitName]),
 331        mtError,[mbCancel,mbIgnore])<>mrIgnore then exit;
 332    end else begin
 333      PkgFile:=PackageGraph.FindUnit(LazPackage,AnUnitName,true,true);
 334      if (PkgFile<>nil) and (PkgFile.LazPackage<>LazPackage) then begin
 335        // there is already a unit with this name in another package => warn
 336        if IDEMessageDialog(lisA2PUnitnameAlreadyExists,
 337          Format(lisA2PTheUnitnameAlreadyExistsInThePackage,
 338                 [AnUnitName, LineEnding, PkgFile.LazPackage.IDAsString]),
 339          mtWarning,[mbCancel,mbIgnore])<>mrIgnore then exit;
 340      end;
 341    end;
 342
 343    // check if unitname is a componentclass
 344    if IDEComponentPalette.FindComponent(AnUnitName)<>nil then begin
 345      if IDEMessageDialog(lisA2PAmbiguousUnitName,
 346        Format(lisA2PTheUnitNameIsTheSameAsAnRegisteredComponent,
 347               [AnUnitName, LineEnding]),
 348        mtWarning,[mbCancel,mbIgnore])<>mrIgnore
 349      then
 350        exit;
 351    end;
 352  end;
 353
 354  // ok
 355  Result:=true;
 356end;
 357
 358function CheckAddingDependency(LazPackage: TLazPackage;
 359  NewDependency: TPkgDependency; Quiet, WarnIfAlreadyThere: boolean): TModalResult;
 360var
 361  NewPkgName: String;
 362  RequiredPackage: TLazPackage;
 363  ProvidingAPackage: TLazPackage;
 364  ConflictDependency: TPkgDependency;
 365  PathList: TFPList;
 366  s: String;
 367begin
 368  Result:=mrCancel;
 369
 370  NewPkgName:=NewDependency.PackageName;
 371
 372  // check Max-Min version
 373  if (pdfMinVersion in NewDependency.Flags)
 374  and (pdfMaxVersion in NewDependency.Flags)
 375  and (NewDependency.MaxVersion.Compare(NewDependency.MinVersion)<0) then
 376  begin
 377    if not Quiet then
 378      IDEMessageDialog(lisProjAddInvalidMinMaxVersion,
 379        lisA2PTheMaximumVersionIsLowerThanTheMinimimVersion,
 380        mtError,[mbCancel]);
 381    exit(mrCancel);
 382  end;
 383
 384  // check packagename
 385  if not IsValidPkgName(NewPkgName) then begin
 386    if not Quiet then
 387      IDEMessageDialog(lisProjAddInvalidPackagename,
 388        Format(lisA2PThePackageNameIsInvalidPleaseChooseAnExisting,[NewPkgName,LineEnding]),
 389        mtError,[mbCancel]);
 390    exit(mrCancel);
 391  end;
 392
 393  // check if package is already required
 394  if (CompareText(NewPkgName,LazPackage.Name)=0)
 395  or (PackageGraph.FindDependencyRecursively(
 396        LazPackage.FirstRequiredDependency,NewPkgName)<>nil)
 397  then begin
 398    if WarnIfAlreadyThere then
 399      IDEMessageDialog(lisProjAddDependencyAlreadyExists,
 400        Format(lisA2PThePackageHasAlreadyADependencyForThe, [NewPkgName]),
 401        mtError,[mbCancel]);
 402    exit(mrIgnore);
 403  end;
 404
 405  // check if required lpk exists
 406  if not PackageGraph.DependencyExists(NewDependency,fpfSearchAllExisting)
 407  then begin
 408    if not Quiet then
 409      IDEMessageDialog(lisProjAddPackageNotFound,
 410        Format(lisA2PNoPackageFoundForDependencyPleaseChooseAnExisting,
 411               [NewDependency.AsString, LineEnding]),
 412        mtError,[mbCancel]);
 413    exit(mrCancel);
 414  end;
 415
 416  RequiredPackage:=PackageGraph.FindPackageWithName(NewPkgName,nil);
 417  if RequiredPackage<>nil then begin
 418    // check if there is a dependency, that requires another version
 419    ConflictDependency:=PackageGraph.FindConflictRecursively(
 420      LazPackage.FirstRequiredDependency,RequiredPackage);
 421    if ConflictDependency<>nil then begin
 422      DebugLn(['CheckAddingDependency ',LazPackage.Name,' requiring ',RequiredPackage.IDAsString,' conflicts with ',ConflictDependency.AsString]);
 423      if not Quiet then
 424        IDEMessageDialog(lisVersionMismatch,
 425          Format(lisUnableToAddTheDependencyBecauseThePackageHasAlread, [
 426            RequiredPackage.IDAsString, LazPackage.Name, ConflictDependency.
 427            AsString]),
 428          mtError,[mbCancel]);
 429      exit(mrCancel);
 430    end;
 431
 432    // check if there is a cycle
 433    PathList:=PackageGraph.FindPath(RequiredPackage,nil,LazPackage.Name);
 434    if PathList<>nil then begin
 435      try
 436        s:=PackagePathToStr(PathList);
 437        DebugLn(['CheckAddingDependency ',LazPackage.Name,' requiring ',RequiredPackage.IDAsString,' creates cycles with ',s]);
 438        if not Quiet then
 439          IDEMessageDialog(lisCircularDependencyDetected,
 440            Format(lisUnableToAddTheDependencyBecauseThisWouldCreateA, [
 441              RequiredPackage.IDAsString, s]),
 442            mtError,[mbCancel]);
 443        exit(mrCancel);
 444      finally
 445        PathList.Free;
 446      end;
 447    end;
 448  end;
 449
 450  ProvidingAPackage:=PackageGraph.FindPackageProvidingName(
 451    LazPackage.FirstRequiredDependency,NewPkgName);
 452  if ProvidingAPackage<>nil then
 453  begin
 454    // package is already provided by another package
 455    DebugLn(['CheckAddingDependency ',LazPackage.Name,' requiring ',NewPkgName,', but is already provided by ',ProvidingAPackage.IDAsString]);
 456    if WarnIfAlreadyThere then
 457      IDEMessageDialog(lisProjAddDependencyAlreadyExists,
 458        Format(lisUnableToAddTheDependencyBecauseThePackageHasAlread, [
 459          RequiredPackage.IDAsString, LazPackage.Name, ProvidingAPackage.Name]),
 460        mtError,[mbCancel]);
 461    exit(mrIgnore);
 462  end;
 463
 464  Result:=mrOk;
 465end;
 466
 467function CheckAddingPkgDependency(LazPackage: TLazPackage;
 468  RequiredPkg: TLazPackage; Quiet, WarnIfAlreadyThere: boolean): TModalResult;
 469var
 470  NewDependency: TPkgDependency;
 471begin
 472  NewDependency:=TPkgDependency.Create;
 473  try
 474    NewDependency.PackageName:=RequiredPkg.Name;
 475    Result:=CheckAddingDependency(LazPackage,NewDependency,Quiet,WarnIfAlreadyThere);
 476  finally
 477    NewDependency.Free;
 478  end;
 479end;
 480
 481{ TAddToPackageDlg }
 482
 483procedure TAddToPackageDlg.AddToPackageDlgClose(Sender: TObject;
 484  var CloseAction: TCloseAction);
 485begin
 486  IDEDialogLayoutList.SaveLayout(Self);
 487end;
 488
 489procedure TAddToPackageDlg.AddToPackageDlgKeyDown(Sender: TObject;
 490  var Key: Word; Shift: TShiftState);
 491begin
 492  if (Key=VK_ESCAPE) and (Shift=[]) then
 493    ModalResult:=mrCancel;
 494end;
 495
 496procedure TAddToPackageDlg.AncestorComboBoxChange(Sender: TObject);
 497begin
 498  CheckNewCompOk;
 499end;
 500
 501procedure TAddToPackageDlg.AncestorComboBoxCloseUp(Sender: TObject);
 502begin
 503  if fLastNewComponentAncestorType<>AncestorComboBox.Text then
 504    AutoCompleteNewComponent;
 505end;
 506
 507procedure TAddToPackageDlg.AncestorShowAllCheckBoxClick(Sender: TObject);
 508begin
 509  UpdateAvailableAncestorTypes;
 510end;
 511
 512procedure TAddToPackageDlg.CancelAddFileButtonClick(Sender: TObject);
 513begin
 514  ModalResult:=mrCancel;
 515end;
 516
 517procedure TAddToPackageDlg.CancelAddUnitButtonClick(Sender: TObject);
 518begin
 519  ModalResult:=mrCancel;
 520end;
 521
 522procedure TAddToPackageDlg.ClassNameEditChange(Sender: TObject);
 523begin
 524  AutoCompleteNewComponentUnitName;
 525  CheckNewCompOk;
 526end;
 527
 528procedure TAddToPackageDlg.ComponentIconBitBtnClick(Sender: TObject);
 529var
 530  Dlg: TOpenPictureDialog;
 531begin
 532  Dlg:=TOpenPictureDialog.Create(nil);
 533  try
 534    InputHistories.ApplyFileDialogSettings(Dlg);
 535    Dlg.InitialDir:=LazPackage.GetFileDialogInitialDir(ExtractFilePath(ComponentUnitFileEdit.Text));
 536    Dlg.Title:=lisTitleOpenComponentIcon24x24;
 537    Dlg.Options:=Dlg.Options+[ofPathMustExist];
 538    Dlg.Filter:=Format('%s|*.png|%s|*.bmp|%s|*.xpm|%s|%s',
 539      [dlgFilterImagesPng,
 540       dlgFilterImagesBitmap,
 541       dlgFilterImagesPixmap,
 542       dlgFilterAll, GetAllFilesMask]);
 543
 544    if Dlg.Execute then begin
 545      LoadComponentIcon(Dlg.FileName);
 546    end;
 547    InputHistories.StoreFileDialogSettings(Dlg);
 548  finally
 549    Dlg.Free;
 550  end;
 551end;
 552
 553procedure TAddToPackageDlg.ComponentUnitFileBrowseButtonClick(Sender: TObject);
 554var
 555  SaveDialog: TSaveDialog;
 556  AFilename: string;
 557begin
 558  SaveDialog:=TSaveDialog.Create(nil);
 559  try
 560    InputHistories.ApplyFileDialogSettings(SaveDialog);
 561    SaveDialog.InitialDir := LazPackage.GetFileDialogInitialDir(SaveDialog.InitialDir);
 562    SaveDialog.Title := lisSaveAs;
 563    SaveDialog.Options := SaveDialog.Options+[ofPathMustExist];
 564    SaveDialog.Filter := Format('%s|*.pas;*.pp', [dlgFilterPascalFile]);
 565    if SaveDialog.Execute then begin
 566      AFilename := CleanAndExpandFilename(SaveDialog.Filename);
 567      if FilenameIsPascalUnit(AFilename) then begin
 568        LazPackage.ShortenFilename(AFilename,true);
 569        ComponentUnitFileEdit.Text := AFilename;
 570      end else begin
 571        IDEMessageDialog(lisA2PInvalidFile,
 572         lisA2PAPascalUnitMustHaveTheExtensionPPOrPas,
 573         mtError,[mbCancel]);
 574      end;
 575    end;
 576    InputHistories.StoreFileDialogSettings(SaveDialog);
 577  finally
 578    SaveDialog.Free;
 579  end;
 580end;
 581
 582procedure TAddToPackageDlg.ComponentUnitFileShortenButtonClick(Sender: TObject);
 583begin
 584  if ''=ComponentUnitFileEdit.Text then exit;
 585  ComponentUnitFileEdit.Text:=SwitchRelativeAbsoluteFilename(ComponentUnitFileEdit.Text);
 586end;
 587
 588procedure TAddToPackageDlg.ComponentUnitNameEditChange(Sender: TObject);
 589begin
 590  CheckNewCompOk;
 591end;
 592
 593procedure TAddToPackageDlg.DependPkgNameListBoxSelectionChange(Sender: TObject; User: boolean);
 594begin
 595  CheckNewReqOk;
 596end;
 597
 598procedure TAddToPackageDlg.FilesAddButtonClick(Sender: TObject);
 599var
 600  i: Integer;
 601  Filename: String;
 602  NewFileType: TPkgFileType;
 603  HasRegisterProc: boolean;
 604  CurParams, LastParams: TAddToPkgResult;
 605  ok: Boolean;
 606begin
 607  ok:=false;
 608  try
 609    LastParams:=nil;
 610    i:=0;
 611    while i<FilesListView.Items.Count do begin
 612      if not FilesListView.Items[i].Selected then begin
 613        Inc(i);
 614        Continue;
 615      end;
 616      Filename:=FilesListView.Items[i].Caption;
 617      LazPackage.LongenFilename(Filename);
 618      Assert(not DirPathExists(Filename));
 619      if LazPackage.FindPkgFile(Filename,true,false)<>nil then begin
 620        FilesListView.Items.Delete(i);     // file already in package
 621        continue;
 622      end;
 623
 624      if LastParams<>nil then begin
 625        LastParams.Next:=TAddToPkgResult.Create;
 626        CurParams:=LastParams.Next;
 627      end else
 628        CurParams:=Params;
 629      CurParams.Clear;
 630      CurParams.AddType:=d2ptFile;
 631      CurParams.UnitFilename:=Filename;
 632      NewFileType:=FileNameToPkgFileType(Filename);
 633      CurParams.FileType:=NewFileType;
 634      if NewFileType=pftUnit then begin
 635        CurParams.AddType:=d2ptUnit;
 636        Include(CurParams.PkgFileFlags,pffAddToPkgUsesSection);
 637
 638        // check filename
 639        if not CheckAddingUnitFilename(LazPackage,CurParams.AddType,
 640          OnGetIDEFileInfo,CurParams.UnitFilename)
 641        then begin
 642          FilesListView.Items.Delete(i);
 643          exit;
 644        end;
 645
 646        CurParams.AutoAddLFMFile:=true;
 647        CurParams.AutoAddLRSFile:=true;
 648        if Assigned(OnGetUnitRegisterInfo) then begin
 649          OnGetUnitRegisterInfo(Self,Filename,CurParams.Unit_Name,HasRegisterProc);
 650          if HasRegisterProc then
 651            Include(CurParams.PkgFileFlags,pffHasRegisterProc);
 652        end;
 653
 654        // check unitname
 655        if CompareText(CurParams.Unit_Name,
 656          ExtractFileNameOnly(CurParams.UnitFilename))<>0
 657        then begin
 658          if IDEMessageDialog(lisA2PInvalidUnitName,
 659              Format(lisA2PTheUnitNameAndFilenameDiffer,
 660                     [CurParams.Unit_Name, LineEnding, CurParams.UnitFilename]),
 661            mtError,[mbIgnore,mbCancel])<>mrIgnore
 662          then begin
 663            FilesListView.Items.Delete(i);
 664            exit;
 665          end;
 666        end;
 667      end;
 668      LastParams:=CurParams;
 669      inc(i);
 670    end;
 671    ButtonPanel1.OKButton.Enabled:=FilesListView.SelCount>0;
 672    ok:=LastParams<>nil;
 673  finally
 674    if not ok then Params.Clear;
 675  end;
 676  if LastParams=nil then begin
 677    exit;
 678  end;
 679  ModalResult:=mrOk;
 680end;
 681
 682procedure TAddToPackageDlg.FilesDeleteButtonClick(Sender: TObject);
 683var
 684  i: Integer;
 685begin
 686  for i:=FilesListView.Items.Count-1 downto 0 do
 687    if FilesListView.Items[i].Selected then
 688      FilesListView.Items.Delete(i);
 689  CheckFilesButtonsOk;
 690end;
 691
 692procedure TAddToPackageDlg.FilesDirButtonClick(Sender: TObject);
 693var
 694  i: Integer;
 695  Files: TStrings;
 696  AFilename: string;
 697  NewListItem: TListItem;
 698  NewPgkFileType: TPkgFileType;
 699begin
 700  Files:=nil;
 701  try
 702    if ShowAddDirToPkgDialog(LazPackage,Files)<>mrOk then exit;
 703    for i:=0 to Files.Count-1 do begin
 704      AFilename:=Files[i];
 705      if FindFileInFilesList(AFilename)<0 then begin
 706        LazPackage.ShortenFilename(AFilename,true);
 707        NewListItem:=FilesListView.Items.Add;
 708        NewListItem.Caption:=AFilename;
 709        NewPgkFileType:=FileNameToPkgFileType(AFilename);
 710        NewListItem.SubItems.Add(GetPkgFileTypeLocalizedName(NewPgkFileType));
 711        NewListItem.Selected:=True;
 712      end;
 713    end;
 714    CheckFilesButtonsOk;
 715  finally
 716    Files.Free;
 717  end;
 718end;
 719
 720procedure TAddToPackageDlg.FilesListViewSelectItem(Sender: TObject;
 721  Item: TListItem; Selected: Boolean);
 722begin
 723  CheckFilesButtonsOk;
 724end;
 725
 726procedure TAddToPackageDlg.FilesShortenButtonClick(Sender: TObject);
 727var
 728  SwitchToAbsolute: Boolean;
 729  i: Integer;
 730  Filename: String;
 731begin
 732  if FilesListView.Items.Count=0 then exit;
 733  if (not LazPackage.HasDirectory)
 734  or (not FilenameIsAbsolute(LazPackage.Directory)) then exit;
 735  SwitchToAbsolute:=not FilenameIsAbsolute(FilesListView.Items[0].Caption);
 736  for i:=0 to FilesListView.Items.Count-1 do begin
 737    Filename:=FilesListView.Items[i].Caption;
 738    if SwitchToAbsolute then
 739      Filename:=CreateAbsolutePath(Filename,LazPackage.Directory)
 740    else
 741      Filename:=CreateRelativePath(Filename,LazPackage.Directory);
 742    FilesListView.Items[i].Caption:=Filename;
 743  end;
 744end;
 745
 746function TAddToPackageDlg.CheckFilesButtonsOk: Boolean;
 747begin
 748  FilesDeleteButton.Enabled:=FilesListView.SelCount>0;
 749  Result:=FilesListView.Items.Count>0;
 750  FilesShortenButton.Enabled:=Result;
 751  ButtonPanel1.OKButton.Enabled:=FilesListView.SelCount>0;
 752end;
 753
 754procedure TAddToPackageDlg.FormCreate(Sender: TObject);
 755begin
 756  Caption:=lisA2PAddToPackage;
 757  fPkgComponents:=TAVLTree.Create(@CompareIDEComponentByClassName);
 758  fPackages:=TAVLTree.Create(@CompareLazPackageID);
 759  Params:=TAddToPkgResult.Create;
 760
 761  IDEDialogLayoutList.ApplyLayout(Self,500,300);
 762  SetupComponents;
 763end;
 764
 765procedure TAddToPackageDlg.FormDestroy(Sender: TObject);
 766begin
 767  FreeAndNil(fPkgComponents);
 768  FreeAndNil(fPackages);
 769  FreeAndNil(Params);
 770end;
 771
 772procedure TAddToPackageDlg.FormShow(Sender: TObject);
 773begin
 774  SelectNext(PageControl1.ActivePage, True, True);
 775end;
 776
 777procedure TAddToPackageDlg.NewComponentButtonClick(Sender: TObject);
 778var
 779  PkgFile: TPkgFile;
 780  PkgComponent: TPkgComponent;
 781  ARequiredPackage: TLazPackage;
 782begin
 783  Params.Clear;
 784  Params.AddType:=d2ptNewComponent;
 785  Params.FileType:=pftUnit;
 786  Params.PkgFileFlags:=[pffHasRegisterProc,pffAddToPkgUsesSection];
 787  Params.AncestorType:=AncestorComboBox.Text;
 788  Params.NewClassName:=ClassNameEdit.Text;
 789  Params.PageName:=PalettePageCombobox.Text;
 790  Params.Unit_Name:=ComponentUnitNameEdit.Text;
 791  Params.UnitFilename:=ComponentUnitFileEdit.Text;
 792  Params.UsedUnitname:='';
 793  Params.IconFile:=FComponentIconFilename;
 794
 795  // check Ancestor Type
 796  if not IsValidIdent(Params.AncestorType) then begin
 797    IDEMessageDialog(lisA2PInvalidAncestorType,
 798      Format(lisA2PTheAncestorTypeIsNotAValidPascalIdentifier, [Params.AncestorType]),
 799      mtError,[mbCancel]);
 800    exit;
 801  end;
 802
 803  // check pagename
 804  if length(Params.PageName)>100 then begin
 805    IDEMessageDialog(lisA2PPageNameTooLong,
 806      Format(lisA2PThePageNameIsTooLongMax100Chars, [Params.PageName]),
 807      mtError,[mbCancel]);
 808    exit;
 809  end;
 810
 811  // check unitname - filename redundancy
 812  if CompareText(Params.Unit_name,ExtractFileNameOnly(Params.UnitFilename))<>0
 813  then begin
 814    IDEMessageDialog(lisA2PUnitNameInvalid,
 815      Format(lisA2PTheUnitNameDoesNotCorrespondToTheFilename, [Params.Unit_Name]),
 816      mtError,[mbCancel]);
 817    exit;
 818  end;
 819
 820  // check classname
 821  if not IsValidIdent(Params.NewClassName) then begin
 822    IDEMessageDialog(lisA2PInvalidClassName,
 823      Format(lisA2PTheClassNameIsNotAValidPascalIdentifier, [Params.NewClassName]),
 824      mtError,[mbCancel]);
 825    exit;
 826  end;
 827
 828  // check classname<>ancestortype
 829  if CompareText(Params.NewClassName,Params.AncestorType)=0 then begin
 830    IDEMessageDialog(lisA2PInvalidCircularDependency,
 831      Format(lisA2PTheClassNameAndAncestorTypeAreTheSame,[Params.NewClassName,Params.AncestorType]),
 832      mtError,[mbCancel]);
 833    exit;
 834  end;
 835
 836  // check ancestor type is not unitname
 837  PkgFile:=PackageGraph.FindUnit(LazPackage,Params.AncestorType,true,true);
 838  if PkgFile<>nil then begin
 839    if IDEMessageDialog(lisA2PAmbiguousAncestorType,
 840      Format(lisA2PTheAncestorTypeHasTheSameNameAsTheUnit,
 841             [Params.AncestorType, LineEnding, PkgFile.Filename]),
 842      mtError,[mbCancel,mbIgnore])<>mrIgnore
 843    then
 844      exit;
 845  end;
 846
 847  // check classname does not interfere with an existing unitname
 848  PkgFile:=PackageGraph.FindUnit(LazPackage,Params.NewClassName,true,true);
 849  if PkgFile<>nil then begin
 850    if IDEMessageDialog(lisA2PAmbiguousClassName,
 851      Format(lisA2PTheClassNameHasTheSameNameAsTheUnit,
 852             [Params.AncestorType, LineEnding, PkgFile.Filename]),
 853      mtError,[mbCancel,mbIgnore])<>mrIgnore
 854    then
 855      exit;
 856  end;
 857
 858  // check if classname already exists
 859  PkgComponent:=TPkgComponent(IDEComponentPalette.FindComponent(Params.NewClassname));
 860  if PkgComponent<>nil then begin
 861    if IDEMessageDialog(lisA2PClassNameAlreadyExists,
 862      Format(lisA2PTheClassNameExistsAlreadyInPackageFile, [Params.NewClassName, LineEnding,
 863        PkgComponent.PkgFile.LazPackage.IDAsString, LineEnding, PkgComponent.PkgFile.Filename]),
 864      mtError,[mbCancel,mbIgnore])<>mrIgnore
 865    then
 866      exit;
 867  end;
 868
 869  // check filename
 870  if not CheckAddingUnitFilename(LazPackage,Params.AddType,
 871    OnGetIDEFileInfo,Params.UnitFilename) then exit;
 872
 873  // create dependency if needed
 874  PkgComponent:=TPkgComponent(IDEComponentPalette.FindComponent(Params.AncestorType));
 875  if PkgComponent<>nil then begin
 876    Params.UsedUnitname:=PkgComponent.GetUnitName;
 877    ARequiredPackage:=PkgComponent.PkgFile.LazPackage;
 878    ARequiredPackage:=TLazPackage(PackageEditingInterface.RedirectPackageDependency(ARequiredPackage));
 879    if (LazPackage<>ARequiredPackage)
 880    and (not LazPackage.Requires(PkgComponent.PkgFile.LazPackage))
 881    then
 882      Params.Dependency:=ARequiredPackage.CreateDependencyWithOwner(nil);
 883  end;
 884  ModalResult:=mrOk;
 885end;
 886
 887procedure TAddToPackageDlg.NewComponentPageResize(Sender: TObject);
 888var
 889  x: Integer;
 890begin
 891  x:=0;
 892  x:=Max(x,AncestorTypeLabel.Left+AncestorTypeLabel.Width);
 893  x:=Max(x,ClassNameLabel.Left+ClassNameLabel.Width);
 894  x:=Max(x,PalettePageLabel.Left+PalettePageLabel.Width);
 895  x:=Max(x,ComponentUnitFileLabel.Left+ComponentUnitFileLabel.Width);
 896  x:=Max(x,ComponentUnitNameLabel.Left+ComponentUnitNameLabel.Width);
 897  x:=Max(x,ComponentIconLabel.Left+ComponentIconLabel.Width);
 898  AncestorComboBox.Left:=x+6;
 899end;
 900
 901procedure TAddToPackageDlg.NewDependButtonClick(Sender: TObject);
 902var
 903  NewDependency: TPkgDependency;
 904begin
 905  Params.Clear;
 906  Params.AddType:=d2ptRequiredPkg;
 907  
 908  NewDependency:=TPkgDependency.Create;
 909  try
 910    // check minimum version
 911    if DependMinVersionEdit.Text<>'' then begin
 912      if not NewDependency.MinVersion.ReadString(DependMinVersionEdit.Text) then
 913      begin
 914        IDEMessageDialog(lisProjAddInvalidVersion,
 915          Format(lisA2PTheMinimumVersionIsInvalidPleaseUseTheFormatMajor,
 916                 [DependMinVersionEdit.Text, LineEnding, LineEnding]),
 917          mtError,[mbCancel]);
 918        exit;
 919      end;
 920      NewDependency.Flags:=NewDependency.Flags+[pdfMinVersion];
 921    end;
 922    // check maximum version
 923    if DependMaxVersionEdit.Text<>'' then begin
 924      if not NewDependency.MaxVersion.ReadString(DependMaxVersionEdit.Text) then
 925      begin
 926        IDEMessageDialog(lisProjAddInvalidVersion,
 927          Format(lisA2PTheMaximumVersionIsInvalidPleaseUseTheFormatMajor,
 928                 [DependMaxVersionEdit.Text, LineEnding, LineEnding]),
 929          mtError,[mbCancel]);
 930        exit;
 931      end;
 932      NewDependency.Flags:=NewDependency.Flags+[pdfMaxVersion];
 933    end;
 934    
 935    NewDependency.PackageName:=DependPkgNameListBox.Items[DependPkgNameListBox.ItemIndex];
 936    ModalResult:=CheckAddingDependency(LazPackage,NewDependency,false,true);
 937    if ModalResult<>mrOk then exit;
 938
 939    // ok
 940    Params.Dependency:=NewDependency;
 941    NewDependency:=nil;
 942  finally
 943    NewDependency.Free;
 944  end;
 945end;
 946
 947procedure TAddToPackageDlg.SetLazPackage(const AValue: TLazPackage);
 948begin
 949  if FLazPackage=AValue then exit;
 950  FLazPackage:=AValue;
 951  Params.Pkg:=FLazPackage;
 952  UpdateAvailableAncestorTypes;
 953  UpdateAvailablePageNames;
 954  UpdateAvailableDependencyNames;
 955end;
 956
 957function TAddToPackageDlg.GetActivatePage: TAddToPkgType;
 958begin
 959  if PageControl1.ActivePage=NewComponentPage then
 960    Result:=d2ptNewComponent
 961  else if PageControl1.ActivePage=NewRequirementPage then
 962    Result:=d2ptRequiredPkg
 963  else {if PageControl1.ActivePage=AddFilesPage then } begin
 964    Assert(PageControl1.ActivePage=AddFilesPage,
 965      'TAddToPackageDlg.GetActivatePage: PageControl1.ActivePage <> AddFilesPage');
 966    Result:=d2ptFiles;
 967  end;
 968  //else
 969  //  Result:=d2ptNewFile;
 970end;
 971
 972procedure TAddToPackageDlg.SetActivatePage(AValue: TAddToPkgType);
 973begin
 974  case AValue of
 975  d2ptNewComponent: PageControl1.ActivePage:=NewComponentPage;
 976  d2ptRequiredPkg: PageControl1.ActivePage:=NewRequirementPage;
 977  d2ptFiles: PageControl1.ActivePage:=AddFilesPage;
 978  else raise Exception.Create('TAddToPackageDlg.SetActivatePage: invalid value.');
 979  end;
 980end;
 981
 982function TAddToPackageDlg.CheckNewCompOk: Boolean;
 983begin
 984  Result:=(AncestorComboBox.Text<>'') and (ClassNameEdit.Text<>'') and (ComponentUnitNameEdit.Text<>'');
 985  ButtonPanel1.OKButton.Enabled:=Result;
 986end;
 987
 988function TAddToPackageDlg.CheckNewReqOk: Boolean;
 989begin
 990  Result:=DependPkgNameListBox.ItemIndex>-1;
 991  ButtonPanel1.OKButton.Enabled:=Result;
 992end;
 993
 994procedure TAddToPackageDlg.PageControl1Change(Sender: TObject);
 995begin
 996  case PageControl1.PageIndex of
 997    0: begin              // New Component
 998      ButtonPanel1.OkButton.Caption:=lisA2PCreateNewComp;
 999      ButtonPanel1.OkButton.OnClick:=@NewComponentButtonClick;
1000      CheckNewCompOk;
1001    end;
1002    1: begin              // New Requirement
1003      ButtonPanel1.OkButton.Caption:=lisA2PCreateNewReq;
1004      ButtonPanel1.OkButton.OnClick:=@NewDependButtonClick;
1005      CheckNewReqOk;
1006    end;
1007    2: begin              // Add Files
1008      ButtonPanel1.OkButton.Caption:=lisA2PAddFilesToPackage;
1009      ButtonPanel1.OkButton.OnClick:=@FilesAddButtonClick;
1010      CheckFilesButtonsOk;
1011    end;
1012  end;
1013end;
1014
1015procedure TAddToPackageDlg.SetupComponents;
1016begin
1017  //NewFilePage.Caption:=lisA2PNewFile;
1018  NewComponentPage.Caption:=lisA2PNewComponent;
1019  NewRequirementPage.Caption:=lisProjAddNewRequirement;
1020  AddFilesPage.Caption:=lisA2PAddFiles;
1021  ButtonPanel1.CancelButton.Caption:=lisCancel;
1022  PageControl1.PageIndex:=0;
1023  PageControl1Change(PageControl1);
1024
1025  //SetupNewFilePage;
1026  SetupNewComponentPage;
1027  SetupAddDependencyPage;
1028  SetupAddFilesPage;
1029end;
1030
1031procedure TAddToPackageDlg.SetupNewComponentPage;
1032begin
1033  AncestorTypeLabel.Caption:=lisA2PAncestorType;
1034  AncestorComboBox.Text:='';
1035  AncestorShowAllCheckBox.Caption:=lisA2PShowAll;
1036  ClassNameLabel.Caption:=lisA2PNewClassName;
1037  ClassNameEdit.Text:='';
1038  PalettePageLabel.Caption:=lisA2PPalettePage;
1039  PalettePageCombobox.Text:='';
1040  ComponentUnitFileLabel.Caption:=lisA2PUnitFileName2;
1041  ComponentUnitFileEdit.Text:='';
1042  with ComponentUnitFileBrowseButton do begin
1043    Caption:='...';
1044    ShowHint:=true;
1045    Hint:=lisA2PSaveFileDialog;
1046  end;
1047  with ComponentUnitFileShortenButton do begin
1048    Caption:='<>';
1049    ShowHint:=true;
1050    Hint:=lisA2PShortenOrExpandFilename;
1051  end;
1052  ComponentUnitNameLabel.Caption:=lisA2PUnitName;
1053  ComponentUnitNameEdit.Text:='';
1054  ComponentIconLabel.Caption:=lisA2PIconAndSize;
1055  ComponentIconBitBtn.Width:=ComponentPaletteBtnWidth;
1056  ComponentIconBitBtn.Height:=ComponentPaletteBtnHeight;
1057end;
1058
1059procedure TAddToPackageDlg.SetupAddDependencyPage;
1060begin
1061  DependPkgNameLabel.Caption:=lisProjAddPackageName;
1062  DependMinVersionLabel.Caption:=lisProjAddMinimumVersionOptional;
1063  DependMinVersionEdit.Text:='';
1064  DependMaxVersionLabel.Caption:=lisProjAddMaximumVersionOptional;
1065  DependMaxVersionEdit.Text:='';
1066end;
1067
1068procedure TAddToPackageDlg.SetupAddFilesPage;
1069var
1070  CurColumn: TListColumn;
1071begin
1072  with FilesListView do begin
1073    CurColumn:=Columns[0];
1074    CurColumn.Width:=200;
1075    CurColumn.Caption:=lisA2PFilename2;
1076    CurColumn:=Columns[1];
1077    CurColumn.Caption:=dlgEnvType;
1078  end;
1079  
1080  with FilesDirButton do begin
1081    Caption:=lisAddFilesInDirectory;
1082    LoadGlyphFromResourceName(HInstance, 'pkg_files');
1083  end;
1084
1085  with FilesShortenButton do begin
1086    Caption:=lisA2PSwitchPaths;
1087    ShowHint:=true;
1088    Hint:=lisToggleShowingFilenamesWithFullPathOrWithRelativePa;
1089  end;
1090
1091  with FilesDeleteButton do begin
1092    Caption:=lisDelete;
1093    ShowHint:=true;
1094    Hint:=lisDeleteSelectedFiles;
1095    LoadGlyphFromResourceName(HInstance, 'laz_delete');
1096  end;
1097
1098  LabelIconInfo.Caption:=lisNoneClickToChooseOne;
1099end;
1100
1101procedure TAddToPackageDlg.OnIterateComponentClasses(PkgComponent: TPkgComponent);
1102begin
1103  if fPkgComponents.Find(PkgComponent)=nil then
1104    fPkgComponents.Add(PkgComponent);
1105end;
1106
1107procedure TAddToPackageDlg.OnIteratePackages(APackageID: TLazPackageID);
1108begin
1109  if (APackageID<>LazPackage) and (fPackages.Find(APackageID)=nil) then begin
1110    //DebugLn(['TAddToPackageDlg.OnIteratePackages ',APackageID.IDAsString,' ',DbgSName(APackageID)]);
1111    fPackages.Add(APackageID);
1112  end;
1113end;
1114
1115procedure TAddToPackageDlg.AutoCompleteNewComponent;
1116var
1117  PkgComponent: TPkgComponent;
1118begin
1119  fLastNewComponentAncestorType:=AncestorComboBox.Text;
1120  if not IsValidIdent(fLastNewComponentAncestorType) then exit;
1121  PkgComponent:=TPkgComponent(
1122    IDEComponentPalette.FindComponent(fLastNewComponentAncestorType));
1123
1124  // create unique classname
1125  if (not IsValidIdent(ClassNameEdit.Text)) or (ClassNameEdit.Text='') then
1126    ClassNameEdit.Text:=IDEComponentPalette.CreateNewClassName(
1127                                                 fLastNewComponentAncestorType);
1128  // choose the same page name
1129  if (PalettePageCombobox.Text='')
1130  and (PkgComponent<>nil) and (PkgComponent.RealPage<>nil) then
1131    PalettePageCombobox.Text:=PkgComponent.RealPage.PageName;
1132  // filename
1133  AutoCompleteNewComponentUnitName;
1134  ButtonPanel1.OkButton.Enabled:=True;
1135end;
1136
1137procedure TAddToPackageDlg.AutoCompleteNewComponentUnitName;
1138var
1139  CurClassName: String;
1140  NewUnitName: String;
1141  NewFileName: String;
1142begin
1143  // check if update needed
1144  CurClassName:=ClassNameEdit.Text;
1145  if fLastNewComponentClassName=CurClassName then exit;
1146  fLastNewComponentClassName:=CurClassName;
1147
1148  // check classname
1149  if not IsValidIdent(CurClassName) then exit;
1150
1151  // create unitname
1152  NewUnitName:=CurClassName;
1153  if NewUnitName[1]='T' then
1154    NewUnitName:=copy(NewUnitName,2,length(NewUnitName)-1);
1155  NewUnitName:=PackageGraph.CreateUniqueUnitName(NewUnitName);
1156  ComponentUnitNameEdit.Text:=NewUnitName;
1157
1158  // create filename
1159  NewFileName:=NewUnitName;
1160
1161  if EnvironmentOptions.CharcaseFileAction in [ccfaAsk, ccfaAutoRename] then
1162    NewFileName:=lowercase(NewFileName);
1163
1164  // append pascal file extension
1165  NewFileName:=NewFileName
1166       +EnvironmentOpts.PascalExtension[EnvironmentOptions.PascalFileExtension];
1167  // prepend path
1168  if LazPackage.HasDirectory then
1169    NewFileName:=LazPackage.Directory+NewFileName;
1170  ComponentUnitFileEdit.Text:=NewFileName;
1171end;
1172
1173function TAddToPackageDlg.SwitchRelativeAbsoluteFilename(const Filename: string
1174  ): string;
1175begin
1176  Result:=Filename;
1177  if (not LazPackage.HasDirectory)
1178  or (not FilenameIsAbsolute(LazPackage.Directory)) then exit;
1179  if FilenameIsAbsolute(Filename) then
1180    Result:=TrimFilename(CreateRelativePath(Filename,LazPackage.Directory))
1181  else
1182    Result:=TrimFilename(CreateAbsoluteSearchPath(Filename,LazPackage.Directory));
1183end;
1184
1185function TAddToPackageDlg.FindFileInFilesList(AFilename: string): Integer;
1186var
1187  i: Integer;
1188  Item: TListItem;
1189  OtherFilename: String;
1190begin
1191  if not FilenameIsAbsolute(AFilename) then
1192    LazPackage.LongenFilename(AFilename);
1193  for i:=0 to FilesListView.Items.Count-1 do begin
1194    Item:=FilesListView.Items[i];
1195    OtherFilename:=Item.Caption;
1196    if not FilenameIsAbsolute(OtherFilename) then
1197      LazPackage.LongenFilename(OtherFilename);
1198    if CompareFilenames(AFilename,OtherFilename)=0 then begin
1199      Result:=i;
1200      exit;
1201    end;
1202  end;
1203  Result:=-1;
1204end;
1205
1206procedure TAddToPackageDlg.LoadComponentIcon(AFilename: string);
1207var
1208  ShortFilename: String;
1209  Image: TImage;
1210begin
1211  try
1212    Image:=TImage.Create(nil);
1213    try
1214      Image.Picture.LoadFromFile(AFilename);
1215      ComponentIconBitBtn.Glyph.Assign(Image.Picture.Graphic);
1216      ShortFilename:=AFilename;
1217      LazPackage.ShortenFilename(ShortFilename,true);
1218      LabelIconInfo.Caption:= Format('%s (%dx%d)',
1219        [ShortFilename, ComponentIconBitBtn.Glyph.Width, ComponentIconBitBtn.Glyph.Height]);
1220      FComponentIconFilename:=AFilename;
1221    finally
1222      Image.Free;
1223    end;
1224  except
1225    on E: Exception do begin
1226      IDEMessageDialog(lisCCOErrorCaption,
1227        Format(lisErrorLoadingFile2,[AFilename]) + LineEnding + E.Message,
1228        mtError, [mbCancel]);
1229      ComponentIconBitBtn.Glyph.Clear;
1230      FComponentIconFilename:='';
1231      LabelIconInfo.Caption:=lisNoneClickToChooseOne;
1232    end;
1233  end;
1234end;
1235
1236procedure TAddToPackageDlg.UpdateAvailableAncestorTypes;
1237var
1238  ANode: TAVLTreeNode;
1239  sl: TStringList;
1240  OldAncestorType: String;
1241begin
1242  // get all available registered components
1243  fPkgComponents.Clear;
1244  if AncestorShowAllCheckBox.Checked then begin
1245    PackageGraph.IterateAllComponentClasses(@OnIterateComponentClasses);
1246  end else begin
1247    PackageGraph.IterateComponentClasses(LazPackage,@OnIterateComponentClasses,
1248                                         true,true);
1249  end;
1250  // put them into a list
1251  sl:=TStringList.Create;
1252  ANode:=fPkgComponents.FindLowest;
1253  while ANode<>nil do begin
1254    sl.Add(TPkgComponent(ANode.Data).ComponentClass.ClassName);
1255    ANode:=fPkgComponents.FindSuccessor(ANode);
1256  end;
1257  // add at least TComponent
1258  sl.Add('TComponent');
1259  sl.Sort;
1260  
1261  // put them into the combobox
1262  OldAncestorType:=AncestorComboBox.Text;
1263  AncestorComboBox.Items.Assign(sl);
1264  AncestorComboBox.Text:=OldAncestorType;
1265  sl.Free;
1266end;
1267
1268procedure TAddToPackageDlg.UpdateAvailablePageNames;
1269var
1270  i: Integer;
1271  APageName: String;
1272  sl: TStringList;
1273begin
1274  // get all current pagenames (excluding the hidden page)
1275  sl:=TStringList.Create;
1276  for i:=0 to IDEComponentPalette.Pages.Count-1 do begin
1277    APageName:=IDEComponentPalette.Pages[i].PageName;
1278    if APageName<>'' then
1279      sl.Add(APageName);
1280  end;
1281  sl.Sort;
1282  PalettePageCombobox.Items.Assign(sl);
1283  sl.Free;
1284end;
1285
1286procedure TAddToPackageDlg.UpdateAvailableDependencyNames;
1287var
1288  ANode: TAVLTreeNode;
1289  sl: TStringList;
1290  PkgName: String;
1291  Pkg: TLazPackage;
1292begin
1293  fPackages.Clear;
1294  PackageGraph.IteratePackages(fpfSearchAllExisting,@OnIteratePackages);
1295  sl:=TStringList.Create;
1296  ANode:=fPackages.FindLowest;
1297  while ANode<>nil do begin
1298    Pkg:=TLazPackage(ANode.Data);
1299    PkgName:=Pkg.Name;
1300    if (sl.IndexOf(PkgName)<0) then
1301      sl.Add(PkgName);
1302    ANode:=fPackages.FindSuccessor(ANode);
1303  end;
1304  DependPkgNameFilter.Items.Assign(sl);
1305  DependPkgNameFilter.InvalidateFilter;
1306  sl.Free;
1307end;
1308
1309{ TAddToPkgResult }
1310
1311procedure TAddToPkgResult.Clear;
1312begin
1313  AddType:=d2ptUnit;
1314  Dependency:=nil;
1315  UnitFilename:='';
1316  Unit_Name:='';
1317  AncestorType:='';
1318  NewClassName:='';
1319  PageName:='';
1320  FileType:=pftUnit;
1321  PkgFileFlags:=[];
1322  UsedUnitname:='';
1323  AutoAddLFMFile:=false;
1324  AutoAddLRSFile:=false;
1325  FreeThenNil(Next);
1326end;
1327
1328destructor TAddToPkgResult.Destroy;
1329begin
1330  FreeThenNil(Next);
1331  inherited Destroy;
1332end;
1333
1334end.
1335