1 {
2 /***************************************************************************
3 projectinspector.pas
4 --------------------
5
6
7 ***************************************************************************/
8
9 ***************************************************************************
10 * *
11 * This source is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This code is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19 * General Public License for more details. *
20 * *
21 * A copy of the GNU General Public License is available on the World *
22 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
23 * obtain it by writing to the Free Software Foundation, *
24 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
25 * *
26 ***************************************************************************
27
28 Author: Mattias Gaertner
29
30 Abstract:
31 TProjectInspectorForm is the form of the project inspector.
32
33 ToDo:
34 - project groups:
35 - activate
36 popup menu:
37 - copy file name
38 - save
39 - options
40 - activate
41 - compile
42 - build
43 - view source
44 - close
45 - remove project
46 - build sooner Ctrl+Up
47 - build later Ctrl+Down
48 - compile all from here
49 - build all from here
50 }
51 unit ProjectInspector;
52
53 {$mode objfpc}{$H+}
54
55 interface
56
57 uses
58 Classes, SysUtils,
59 // LCL
60 LCLType, LCLIntf, Forms, Controls, Buttons, ComCtrls, Menus, Dialogs,
61 ExtCtrls, StdCtrls, Graphics,
62 // LazControls
63 TreeFilterEdit,
64 // LazUtils
65 FileUtil, LazFileUtils, LazUtilities, LazLoggerBase, LazTracer, LazFileCache,
66 // Codetools
67 CodeToolsStructs, CodeToolManager, FileProcs, CodeCache, CodeTree, FindDeclarationTool,
68 // BuildIntf
69 ProjectIntf, PackageIntf, PackageLinkIntf, PackageDependencyIntf,
70 // IDEIntf
71 IDEHelpIntf, IDECommands, IDEDialogs, IDEImagesIntf, LazIDEIntf, ToolBarIntf,
72 // IDE
73 LazarusIDEStrConsts, MainBase, IDEProcs, DialogProcs, IDEOptionDefs, Project,
74 InputHistory, TransferMacros, EnvironmentOpts, BuildManager, BasePkgManager,
75 ProjPackChecks, ProjPackEditing, ProjPackFilePropGui, PackageDefs,
76 AddToProjectDlg, AddPkgDependencyDlg, AddFPMakeDependencyDlg, LResources;
77
78 type
79 TOnAddUnitToProject =
endernull80 function(Sender: TObject; AnUnitInfo: TUnitInfo): TModalresult of object;
81 TRemoveProjInspFileEvent =
endernull82 function(Sender: TObject; AnUnitInfo: TUnitInfo): TModalResult of object;
endernull83 TRemoveProjInspDepEvent = function(Sender: TObject;
84 ADependency: TPkgDependency): TModalResult of object;
endernull85 TAddProjInspDepEvent = function(Sender: TObject;
86 ADependency: TPkgDependency): TModalResult of object;
87
88 { TProjectInspectorForm }
89
90 TProjectInspectorForm = class(TForm,IFilesEditorInterface)
91 AddPopupMenu: TPopupMenu;
92 FilterPanel: TPanel;
93 DirectoryHierarchyButton: TSpeedButton;
94 FilterEdit: TTreeFilterEdit;
95 PropsGroupBox: TGroupBox;
96 MenuItem1: TMenuItem;
97 MenuItem2: TMenuItem;
98 mnuAddFPMakeReq: TMenuItem;
99 mnuAddEditorFiles: TMenuItem;
100 mnuAddDiskFile: TMenuItem;
101 mnuAddReq: TMenuItem;
102 OpenButton: TSpeedButton;
103 ItemsTreeView: TTreeView;
104 ItemsPopupMenu: TPopupMenu;
105 SortAlphabeticallyButton: TSpeedButton;
106 Splitter1: TSplitter;
107 // toolbar
108 ToolBar: TToolBar;
109 // toolbuttons
110 AddBitBtn: TToolButton;
111 RemoveBitBtn: TToolButton;
112 OptionsBitBtn: TToolButton;
113 HelpBitBtn: TToolButton;
114 procedure CopyMoveToDirMenuItemClick(Sender: TObject);
115 procedure DirectoryHierarchyButtonClick(Sender: TObject);
116 procedure FilterEditKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
117 procedure FormActivate(Sender: TObject);
118 procedure FormCreate(Sender: TObject);
119 procedure FormDeactivate(Sender: TObject);
120 procedure FormDestroy(Sender: TObject);
121 procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
122 procedure ItemsPopupMenuPopup(Sender: TObject);
123 procedure ItemsTreeViewAdvancedCustomDrawItem(Sender: TCustomTreeView;
124 Node: TTreeNode; {%H-}State: TCustomDrawState; Stage: TCustomDrawStage;
125 var {%H-}PaintImages, {%H-}DefaultDraw: Boolean);
126 procedure ItemsTreeViewDblClick(Sender: TObject);
127 procedure ItemsTreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
128 procedure ItemsTreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
129 State: TDragState; var Accept: Boolean);
130 procedure ItemsTreeViewKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
131 procedure ItemsTreeViewSelectionChanged(Sender: TObject);
132 procedure mnuAddDiskFileClick(Sender: TObject);
133 procedure mnuAddEditorFilesClick(Sender: TObject);
134 procedure mnuAddFPMakeReqClick(Sender: TObject);
135 procedure mnuAddReqClick(Sender: TObject);
136 procedure mnuOpenFolderClick(Sender: TObject);
137 procedure MoveDependencyUpClick(Sender: TObject);
138 procedure MoveDependencyDownClick(Sender: TObject);
139 procedure SetDependencyDefaultFilenameMenuItemClick(Sender: TObject);
140 procedure SetDependencyPreferredFilenameMenuItemClick(Sender: TObject);
141 procedure ClearDependencyFilenameMenuItemClick(Sender: TObject);
142 procedure OpenButtonClick(Sender: TObject);
143 procedure OptionsBitBtnClick(Sender: TObject);
144 procedure HelpBitBtnClick(Sender: TObject);
145 procedure ReAddMenuItemClick(Sender: TObject);
146 procedure RemoveBitBtnClick(Sender: TObject);
147 procedure RemoveNonExistingFilesMenuItemClick(Sender: TObject);
148 procedure SortAlphabeticallyButtonClick(Sender: TObject);
149 procedure EnableI18NForLFMMenuItemClick(Sender: TObject);
150 procedure DisableI18NForLFMMenuItemClick(Sender: TObject);
151 private
152 FIdleConnected: boolean;
153 FOnAddDependency: TAddProjInspDepEvent;
154 FOnAddUnitToProject: TOnAddUnitToProject;
155 FOnCopyMoveFiles: TNotifyEvent;
156 FOnDragDropTreeView: TDragDropEvent;
157 FOnDragOverTreeView: TOnDragOverTreeView;
158 FOnReAddDependency: TAddProjInspDepEvent;
159 FOnRemoveDependency: TRemoveProjInspDepEvent;
160 FOnRemoveFile: TRemoveProjInspFileEvent;
161 FOnShowOptions: TNotifyEvent;
162 FShowDirectoryHierarchy: boolean;
163 FSortAlphabetically: boolean;
164 FUpdateLock: integer;
165 FLazProject: TProject;
166 FFilesNode: TTreeNode;
167 FNextSelectedPart: TObject;// select this file/dependency on next update
168 FDependenciesNode: TTreeNode;
169 FRemovedDependenciesNode: TTreeNode;
170 ImageIndexFiles: integer;
171 ImageIndexProject: integer;
172 ImageIndexUnit: integer;
173 ImageIndexRegisterUnit: integer;
174 ImageIndexText: integer;
175 ImageIndexBinary: integer;
176 ImageIndexDirectory: integer;
177 FFlags: TPEFlags;
178 FPropGui: TProjPackFilePropGui;
179 procedure AddMenuItemClick(Sender: TObject);
AddOneFilenull180 function AddOneFile(aFilename: string): TModalResult;
181 procedure DoAddMoreDialog;
182 procedure DoAddDepDialog;
183 procedure DoAddFPMakeDepDialog;
CreateToolButtonnull184 function CreateToolButton(AName, ACaption, AHint, AImageName: String;
185 AOnClick: TNotifyEvent): TToolButton;
CreateDividernull186 function CreateDivider: TToolButton;
187 procedure SetDependencyDefaultFilename(AsPreferred: boolean);
188 procedure SetIdleConnected(AValue: boolean);
189 procedure SetLazProject(const AValue: TProject);
190 procedure SetShowDirectoryHierarchy(const AValue: boolean);
191 procedure SetSortAlphabetically(const AValue: boolean);
192 procedure SetupComponents;
GetDependencyToUpdatenull193 function GetDependencyToUpdate(Immediately: boolean): TPkgDependencyID;
GetSingleSelectedDependencynull194 function GetSingleSelectedDependency: TPkgDependency;
195 procedure ApplyDependencyButtonClick(Sender: TObject);
TreeViewGetImageIndexnull196 function TreeViewGetImageIndex({%H-}Str: String; Data: TObject; var {%H-}AIsEnabled: Boolean): Integer;
197 procedure ProjectBeginUpdate(Sender: TObject);
198 procedure ProjectEndUpdate(Sender: TObject; ProjectChanged: boolean);
199 procedure EnableI18NForSelectedLFM(TheEnable: boolean);
200 procedure PackageListAvailable(Sender: TObject);
CanUpdatenull201 function CanUpdate(Flag: TPEFlag; Immediately: boolean): boolean;
202 procedure UpdateFiles(Immediately: boolean = false);
203 procedure UpdateProperties(Immediately: boolean = false);
204 procedure UpdateButtons(Immediately: boolean = false);
205 procedure UpdatePending;
206 protected
207 procedure KeyDown(var Key: Word; Shift: TShiftState); override;
208 procedure IdleHandler(Sender: TObject; var {%H-}Done: Boolean);
209 public
210 constructor Create(TheOwner: TComponent); override;
211 destructor Destroy; override;
IsUpdateLockednull212 function IsUpdateLocked: boolean; inline;
213 procedure UpdateTitle(Immediately: boolean = false);
214 procedure UpdateRequiredPackages(Immediately: boolean = false);
TreeViewToInspectornull215 function TreeViewToInspector(TV: TTreeView): TProjectInspectorForm;
216 public
217 // IFilesEditorInterface
218 procedure BeginUpdate;
219 procedure EndUpdate;
220 procedure UpdateAll(Immediately: boolean = false);
GetNodeItemnull221 function GetNodeItem(NodeData: TPENodeData): TObject;
GetNodeDataItemnull222 function GetNodeDataItem(TVNode: TTreeNode; out NodeData: TPENodeData;
223 out Item: TObject): boolean;
ExtendIncSearchPathnull224 function ExtendIncSearchPath(NewIncPaths: string): boolean;
ExtendUnitSearchPathnull225 function ExtendUnitSearchPath(NewUnitPaths: string): boolean;
FilesBaseDirectorynull226 function FilesBaseDirectory: string;
FilesEditFormnull227 function FilesEditForm: TCustomForm;
FilesEditTreeViewnull228 function FilesEditTreeView: TTreeView;
FilesOwnernull229 function FilesOwner: TObject;
FilesOwnerNamenull230 function FilesOwnerName: string;
FilesOwnerReadOnlynull231 function FilesOwnerReadOnly: boolean;
FirstRequiredDependencynull232 function FirstRequiredDependency: TPkgDependency;
GetNodeFilenamenull233 function GetNodeFilename(Node: TTreeNode): string;
IsDirectoryNodenull234 function IsDirectoryNode(Node: TTreeNode): boolean;
TVNodeFilesnull235 function TVNodeFiles: TTreeNode;
TVNodeRequiredPackagesnull236 function TVNodeRequiredPackages: TTreeNode;
237 public
238 property LazProject: TProject read FLazProject write SetLazProject;
239 property OnShowOptions: TNotifyEvent read FOnShowOptions write FOnShowOptions;
240 property OnAddUnitToProject: TOnAddUnitToProject read FOnAddUnitToProject
241 write FOnAddUnitToProject;
242 property OnAddDependency: TAddProjInspDepEvent
243 read FOnAddDependency write FOnAddDependency;
244 property OnRemoveFile: TRemoveProjInspFileEvent read FOnRemoveFile
245 write FOnRemoveFile;
246 property OnRemoveDependency: TRemoveProjInspDepEvent
247 read FOnRemoveDependency write FOnRemoveDependency;
248 property OnReAddDependency: TAddProjInspDepEvent
249 read FOnReAddDependency write FOnReAddDependency;
250 property OnDragDropTreeView: TDragDropEvent read FOnDragDropTreeView
251 write FOnDragDropTreeView;
252 property OnDragOverTreeView: TOnDragOverTreeView read FOnDragOverTreeView
253 write FOnDragOverTreeView;
254 property OnCopyMoveFiles: TNotifyEvent read FOnCopyMoveFiles
255 write FOnCopyMoveFiles;
256 property SortAlphabetically: boolean read FSortAlphabetically write SetSortAlphabetically;
257 property ShowDirectoryHierarchy: boolean read FShowDirectoryHierarchy write SetShowDirectoryHierarchy;
258 property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
259 end;
260
261 { TSetBuildModeToolButton }
262
263 TSetBuildModeToolButton = class(TIDEToolButton)
264 public type
265 TBuildModeMenuItem = class(TMenuItem)
266 public
267 BuildModeIndex: Integer;
268 procedure Click; override;
269 end;
270
271 TBuildModeMenu = class(TPopupMenu)
272 protected
273 procedure DoPopup(Sender: TObject); override;
274 end;
275 public
276 procedure DoOnAdded; override;
277 end;
278
279 var
280 ProjInspector: TProjectInspectorForm = nil;
281
282
UpdateUnitInfoResourceBaseClassnull283 function UpdateUnitInfoResourceBaseClass(AnUnitInfo: TUnitInfo; Quiet: boolean): boolean;
284
285
286 implementation
287
288 {$R *.lfm}
289
UpdateUnitInfoResourceBaseClassnull290 function UpdateUnitInfoResourceBaseClass(AnUnitInfo: TUnitInfo; Quiet: boolean): boolean;
291 var
292 LFMFilename, LFMType, Ancestor, LFMClassName, LFMComponentName: String;
293 LFMCode, Code: TCodeBuffer;
294 LoadFileFlags: TLoadBufferFlags;
295 ClearOldInfo: Boolean;
296 Tool: TCodeTool;
297 Node: TCodeTreeNode;
298 ListOfPFindContext: TFPList;
299 i: Integer;
300 Context: PFindContext;
301 begin
302 Result:=false;
303 if AnUnitInfo.Component<>nil then
304 exit(true); // a loaded resource is always uptodate
305 if AnUnitInfo.IsVirtual then
306 exit(true); // a new unit is always uptodate
307 ListOfPFindContext:=nil;
308 ClearOldInfo:=true;
309 try
310 // find lfm file
311 if not FilenameIsPascalUnit(AnUnitInfo.Filename) then
312 exit(true); // not a unit -> clear info
313 LFMFilename:=AnUnitInfo.UnitResourceFileformat.GetUnitResourceFilename(
314 AnUnitInfo.Filename,true);
315 if (LFMFilename='') or not FileExistsCached(LFMFilename) then
316 exit(true); // no lfm -> clear info
317 finally
318 if ClearOldInfo then begin
319 AnUnitInfo.ResourceBaseClass:=pfcbcNone;
320 AnUnitInfo.ComponentName:='';
321 AnUnitInfo.ComponentResourceName:='';
322 end;
323 end;
324 try
325 if not FilenameExtIs(LFMFilename,'lfm',true) then
326 exit(true); // no lfm format -> keep old info
327 // clear old info
328 AnUnitInfo.ResourceBaseClass:=pfcbcNone;
329 AnUnitInfo.ComponentName:='';
330 AnUnitInfo.ComponentResourceName:='';
331 // load lfm
332 LoadFileFlags:=[lbfUpdateFromDisk,lbfCheckIfText];
333 if Quiet then
334 Include(LoadFileFlags,lbfQuiet);
335 if LoadCodeBuffer(LFMCode,LFMFilename,LoadFileFlags,false)<>mrOk then
336 exit; // lfm read error
337 // read lfm header
338 ReadLFMHeader(LFMCode.Source,LFMType,LFMComponentName,LFMClassName);
339 if LFMClassName='' then
340 exit; // lfm syntax error
341
342 // LFM component name
343 AnUnitInfo.ComponentName:=LFMComponentName;
344 AnUnitInfo.ComponentResourceName:=LFMComponentName;
345
346 // check ancestors
347 if LoadCodeBuffer(Code,AnUnitInfo.Filename,LoadFileFlags,false)<>mrOk then
348 exit; // pas read error
349 CodeToolBoss.Explore(Code,Tool,false,true);
350 if Tool=nil then
351 exit; // pas load error
352 try
353 Node:=Tool.FindDeclarationNodeInInterface(LFMClassName,true);
354 if Node=nil then
355 exit(Tool.FindImplementationNode<>nil); // class not found, reliable if whole interface was read
356
357 if (Node.Desc<>ctnTypeDefinition)
358 or (Node.FirstChild=nil) or (Node.FirstChild.Desc<>ctnClass) then
359 exit(true); // this is not a class
360 Tool.FindClassAndAncestors(Node.FirstChild,ListOfPFindContext,false);
361 if ListOfPFindContext=nil then
362 exit; // ancestor not found -> probably syntax error
363
364 for i:=0 to ListOfPFindContext.Count-1 do begin
365 Context:=PFindContext(ListOfPFindContext[i]);
366 Ancestor:=UpperCase(Context^.Tool.ExtractClassName(Context^.Node,false));
367 if (Ancestor='TFORM') then begin
368 AnUnitInfo.ResourceBaseClass:=pfcbcForm;
369 Result:=true;
370 Break;
371 end else if (Ancestor='TCUSTOMFORM') then begin
372 AnUnitInfo.ResourceBaseClass:=pfcbcCustomForm;
373 Result:=true;
374 Break;
375 end else if Ancestor='TDATAMODULE' then begin
376 AnUnitInfo.ResourceBaseClass:=pfcbcDataModule;
377 Result:=true;
378 Break;
379 end else if (Ancestor='TFRAME') or (Ancestor='TCUSTOMFRAME') then begin
380 AnUnitInfo.ResourceBaseClass:=pfcbcFrame;
381 Result:=true;
382 Break;
383 end else if Ancestor='TCOMPONENT' then begin
384 Result:=true;
385 Break;
386 end;
387 end;
388 except
389 exit; // syntax error or unit not found
390 end;
391 if not Result then exit;
392
393 // Maybe auto-create it
394 // (pfMainUnitHasCreateFormStatements in Project1.Flags)
395 // and Project1.AutoCreateForms are checked by caller.
396 if (AnUnitInfo.ResourceBaseClass in [pfcbcForm,pfcbcCustomForm,pfcbcDataModule])
397 and (LFMComponentName<>'')
398 and (IDEMessageDialog(lisAddToStartupComponents,
399 Format(lisShouldTheComponentBeAutoCreatedWhenTheApplicationS,
400 [LFMComponentName]),
401 mtInformation,[mbYes,mbNo])=mrYes)
402 then
403 Project1.AddCreateFormToProjectFile(LFMClassName,LFMComponentName);
404 finally
405 FreeListOfPFindContext(ListOfPFindContext);
406 end;
407 end;
408
409
410 { TProjectInspectorForm }
411
412 // inline
TProjectInspectorForm.IsUpdateLockednull413 function TProjectInspectorForm.IsUpdateLocked: boolean;
414 begin
415 Result:=FUpdateLock>0;
416 end;
417
TVNodeFilesnull418 function TProjectInspectorForm.TVNodeFiles: TTreeNode;
419 begin
420 Result:=FFilesNode;
421 end;
422
TProjectInspectorForm.TVNodeRequiredPackagesnull423 function TProjectInspectorForm.TVNodeRequiredPackages: TTreeNode;
424 begin
425 Result:=FDependenciesNode;
426 end;
427
428 procedure TProjectInspectorForm.ItemsTreeViewDblClick(Sender: TObject);
429 begin
430 OpenButtonClick(Self);
431 end;
432
433 procedure TProjectInspectorForm.ItemsTreeViewDragDrop(Sender, Source: TObject;
434 X, Y: Integer);
435 begin
436 OnDragDropTreeView(Sender,Source,X,Y);
437 end;
438
439 procedure TProjectInspectorForm.ItemsTreeViewDragOver(Sender, Source: TObject;
440 X, Y: Integer; State: TDragState; var Accept: Boolean);
441 var
442 TargetTVNode: TTreeNode;
443 TargetTVType: TTreeViewInsertMarkType;
444 begin
445 if not OnDragOverTreeView(Sender,Source,X,Y, TargetTVNode, TargetTVType) then
446 begin
447 ItemsTreeView.SetInsertMark(nil,tvimNone);
448 Accept:=false;
449 exit;
450 end;
451
452 if State=dsDragLeave then
453 ItemsTreeView.SetInsertMark(nil,tvimNone)
454 else
455 ItemsTreeView.SetInsertMark(TargetTVNode,TargetTVType);
456 Accept:=true;
457 end;
458
459 procedure TProjectInspectorForm.ItemsTreeViewKeyDown(Sender: TObject;
460 var Key: Word; Shift: TShiftState);
461 var
462 Handled: Boolean;
463 begin
464 Handled := True;
465 try
466 if Key = VK_ESCAPE then
467 Close
468 else if Key = VK_RETURN then
469 OpenButtonClick(Nil)
470 else if Key = VK_DELETE then
471 RemoveBitBtnClick(Nil)
472 else if Key = VK_INSERT then
473 AddMenuItemClick(Nil)
474 else
475 Handled := False;
476 finally
477 if Handled then
478 Key := VK_UNKNOWN;
479 end;
480 end;
481
482 procedure TProjectInspectorForm.ItemsTreeViewSelectionChanged(Sender: TObject);
483 begin
484 UpdateProperties;
485 UpdateButtons;
486 end;
487
488 procedure TProjectInspectorForm.mnuAddDiskFileClick(Sender: TObject);
489 var
490 OpenDialog: TOpenDialog;
491 ADirectory, NewFilename: String;
492 i: Integer;
493 begin
494 OpenDialog:=IDEOpenDialogClass.Create(nil);
495 try
496 InputHistories.ApplyFileDialogSettings(OpenDialog);
497 ADirectory:=LazProject.Directory;
498 if not FilenameIsAbsolute(ADirectory) then
499 ADirectory:='';
500 if ADirectory<>'' then
501 OpenDialog.InitialDir:=ADirectory;
502 OpenDialog.Title:=lisOpenFile;
503 OpenDialog.Options:=OpenDialog.Options
504 +[ofFileMustExist,ofPathMustExist,ofAllowMultiSelect];
505 OpenDialog.Filter:=dlgFilterAll+' ('+GetAllFilesMask+')|'+GetAllFilesMask
506 +'|'+dlgFilterLazarusUnit+' (*.pas;*.pp)|*.pas;*.pp'
507 +'|'+dlgFilterLazarusInclude+' (*.inc)|*.inc'
508 +'|'+dlgFilterLazarusForm+' (*.lfm;*.dfm)|*.lfm;*.dfm';
509 if OpenDialog.Execute then
510 begin
511 InputHistories.StoreFileDialogSettings(OpenDialog);
512 for i:=0 to OpenDialog.Files.Count-1 do
513 begin
514 NewFilename := OpenDialog.Files[i];
515 case TPrjFileCheck.AddingFile(LazProject, NewFilename) of
516 mrOk: if not (AddOneFile(NewFilename) in [mrOk, mrIgnore]) then
517 break;
518 mrIgnore: continue;
519 mrCancel: exit;
520 end;
521 end;
522 end;
523 finally
524 OpenDialog.Free;
525 end;
526 end;
527
528 procedure TProjectInspectorForm.mnuAddEditorFilesClick(Sender: TObject);
529 begin
530 DoAddMoreDialog;
531 end;
532
533 procedure TProjectInspectorForm.mnuAddFPMakeReqClick(Sender: TObject);
534 begin
535 DoAddFPMakeDepDialog;
536 end;
537
538 procedure TProjectInspectorForm.mnuAddReqClick(Sender: TObject);
539 begin
540 DoAddDepDialog;
541 end;
542
543 procedure TProjectInspectorForm.mnuOpenFolderClick(Sender: TObject);
544 begin
545 OpenDocument(LazProject.Directory);
546 end;
547
548 procedure TProjectInspectorForm.MoveDependencyUpClick(Sender: TObject);
549 var
550 Dependency: TPkgDependency;
551 begin
552 Dependency:=GetSingleSelectedDependency;
553 if SortAlphabetically or (Dependency=nil) or Dependency.Removed
554 or (Dependency.PrevRequiresDependency=nil) then exit;
555 LazProject.MoveRequiredDependencyUp(Dependency);
556 end;
557
558 procedure TProjectInspectorForm.MoveDependencyDownClick(Sender: TObject);
559 var
560 Dependency: TPkgDependency;
561 begin
562 Dependency:=GetSingleSelectedDependency;
563 if SortAlphabetically or (Dependency=nil) or Dependency.Removed
564 or (Dependency.NextRequiresDependency=nil) then exit;
565 LazProject.MoveRequiredDependencyDown(Dependency);
566 end;
567
568 procedure TProjectInspectorForm.SetDependencyDefaultFilenameMenuItemClick(Sender: TObject);
569 begin
570 SetDependencyDefaultFilename(false);
571 end;
572
573 procedure TProjectInspectorForm.SetDependencyPreferredFilenameMenuItemClick(Sender: TObject);
574 begin
575 SetDependencyDefaultFilename(true);
576 end;
577
578 procedure TProjectInspectorForm.ClearDependencyFilenameMenuItemClick(Sender: TObject);
579 var
580 CurDependency: TPkgDependency;
581 i: Integer;
582 TVNode: TTreeNode;
583 NodeData: TPENodeData;
584 Item: TObject;
585 begin
586 BeginUpdate;
587 try
588 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
589 TVNode:=ItemsTreeView.Selections[i];
590 if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
591 if not (Item is TPkgDependency) then continue;
592 CurDependency:=TPkgDependency(Item);
593 if CurDependency.DefaultFilename='' then exit;
594 CurDependency.DefaultFilename:='';
595 CurDependency.PreferDefaultFilename:=false;
596 LazProject.Modified:=true;
597 UpdateRequiredPackages;
598 end;
599 finally
600 EndUpdate;
601 end;
602 end;
603
TProjectInspectorForm.AddOneFilenull604 function TProjectInspectorForm.AddOneFile(aFilename: string): TModalResult;
605 var
606 NewUnit: TUnitInfo;
607 begin
608 Result := mrOK;
609 NewUnit:=LazProject.UnitInfoWithFilename(aFilename);
610 if NewUnit<>nil then begin
611 if NewUnit.IsPartOfProject then Exit(mrIgnore);
612 end else begin
613 NewUnit:=TUnitInfo.Create(nil);
614 NewUnit.Filename:=aFilename;
615 if LazProject.AutoCreateForms and FilenameIsPascalUnit(NewUnit.Filename)
616 and (pfMainUnitHasCreateFormStatements in LazProject.Flags) then
617 UpdateUnitInfoResourceBaseClass(NewUnit, true);
618 LazProject.AddFile(NewUnit,false);
619 end;
620 if Assigned(OnAddUnitToProject) then begin
621 Result:=OnAddUnitToProject(Self,NewUnit);
622 if Result<>mrOK then Exit;
623 end;
624 FNextSelectedPart:=NewUnit;
625 end;
626
627 procedure TProjectInspectorForm.AddMenuItemClick(Sender: TObject);
628 begin
629 //check the selected item in ItemsTreeView
630 // -> if it's "Required Packages", call "New Requirement" (mnuAddReqClick)
631 // -> otherwise (selected = "Files") call "Add files from file system" (AddBitBtnClick)
632 if NodeTreeIsIn(ItemsTreeView.Selected, FDependenciesNode) then
633 mnuAddReqClick(Sender)
634 else
635 mnuAddDiskFileClick(Sender);
636 end;
637
638 procedure TProjectInspectorForm.DoAddMoreDialog;
639 var
640 Files: TStringList;
641 i: Integer;
642 begin
643 Files:=TStringList.Create;
644 try
645 if ShowAddToProjectDlg(LazProject,Files)<>mrOk then
646 exit;
647 BeginUpdate;
648 for i:=0 to Files.Count-1 do
649 if not (AddOneFile(Files[i]) in [mrOk, mrIgnore]) then break;
650 UpdateAll;
651 EndUpdate;
652 finally
653 Files.Free;
654 end;
655 end;
656
657 procedure TProjectInspectorForm.DoAddDepDialog;
658 var
659 Deps: TPkgDependencyList;
660 i: Integer;
661 Resu: TModalResult;
662 begin
663 Resu:=ShowAddPkgDependencyDlg(LazProject, Deps);
664 try
665 if (Resu<>mrOK) or (Deps.Count=0) or (OnAddDependency=nil) then exit;
666 try
667 BeginUpdate;
668 for i := 0 to Deps.Count-1 do
669 OnAddDependency(Self, Deps[i]);
670 FNextSelectedPart:=Deps[Deps.Count-1];
671 UpdateRequiredPackages;
672 finally
673 EndUpdate;
674 end;
675 finally
676 Deps.Free;
677 end;
678 end;
679
680 procedure TProjectInspectorForm.DoAddFPMakeDepDialog;
681 var
682 Deps: TPkgDependencyList;
683 i: Integer;
684 Resu: TModalResult;
685 begin
686 Resu:=ShowAddFPMakeDependencyDlg(LazProject, Deps);
687 try
688 if (Resu<>mrOK) or (Deps.Count=0) then exit;
689 try
690 BeginUpdate;
691 for i := 0 to Deps.Count-1 do
692 OnAddDependency(Self, Deps[i]);
693 FNextSelectedPart:=Deps[Deps.Count-1];
694 finally
695 EndUpdate;
696 end;
697 finally
698 Deps.Free;
699 end;
700 end;
701
702 procedure TProjectInspectorForm.CopyMoveToDirMenuItemClick(Sender: TObject);
703 begin
704 OnCopyMoveFiles(Self);
705 end;
706
707 procedure TProjectInspectorForm.DirectoryHierarchyButtonClick(Sender: TObject);
708 begin
709 ShowDirectoryHierarchy:=DirectoryHierarchyButton.Down;
710 end;
711
712 procedure TProjectInspectorForm.FilterEditKeyDown(Sender: TObject;
713 var Key: Word; Shift: TShiftState);
714 begin
715 if Key = VK_RETURN then
716 begin
717 OpenButtonClick(Nil);
718 Key := VK_UNKNOWN;
719 end;
720 end;
721
722 procedure TProjectInspectorForm.FormCreate(Sender: TObject);
723 begin
724 if LazarusIDE.IDEStarted and (LazProject=nil) then
725 begin // User opens this window for the very first time. Set active project.
726 LazProject := Project1;
727 UpdateAll;
728 end;
729 if OPMInterface <> nil then
730 OPMInterface.AddPackageListNotification(@PackageListAvailable);
731 end;
732
733 procedure TProjectInspectorForm.FormDestroy(Sender: TObject);
734 begin
735 if OPMInterface <> nil then
736 OPMInterface.RemovePackageListNotification(@PackageListAvailable);
737 end;
738
739 procedure TProjectInspectorForm.FormActivate(Sender: TObject);
740 begin
741 //DebugLn('* TProjectInspectorForm.FormActivate *');
742 ItemsTreeView.OnSelectionChanged := @ItemsTreeViewSelectionChanged;
743 end;
744
745 procedure TProjectInspectorForm.FormDeactivate(Sender: TObject);
746 begin
747 // Prevent calling handler when the tree gets updated with a project.
748 ItemsTreeView.OnSelectionChanged := Nil;
749 end;
750
751 procedure TProjectInspectorForm.FormDropFiles(Sender: TObject;
752 const FileNames: array of String);
753 var
754 i: Integer;
755 begin
756 {$IFDEF VerboseProjInspDrag}
757 debugln(['TProjectInspectorForm.FormDropFiles ',length(FileNames)]);
758 {$ENDIF}
759 if length(FileNames)=0 then exit;
760 BeginUpdate;
761 try
762 for i:=0 to high(Filenames) do
763 if not (AddOneFile(FileNames[i]) in [mrOk, mrIgnore]) then break;
764 UpdateAll;
765 finally
766 EndUpdate;
767 end;
768 end;
769
770 procedure TProjectInspectorForm.ItemsPopupMenuPopup(Sender: TObject);
771 var
772 ItemCnt: integer;
773
774 function AddPopupMenuItem(const ACaption: string; AnEvent: TNotifyEvent;
775 EnabledFlag: boolean = True): TMenuItem;
776 begin
777 if ItemsPopupMenu.Items.Count<=ItemCnt then begin
778 Result:=TMenuItem.Create(Self);
779 ItemsPopupMenu.Items.Add(Result);
780 end else
781 Result:=ItemsPopupMenu.Items[ItemCnt];
782 Result.Caption:=ACaption;
783 Result.OnClick:=AnEvent;
784 Result.Enabled:=EnabledFlag;
785 Result.Checked:=false;
786 Result.ShowAlwaysCheckable:=false;
787 Result.Visible:=true;
788 Result.RadioItem:=false;
789 Result.ImageIndex:=-1;
790 inc(ItemCnt);
791 end;
792
793 var
794 i: Integer;
795 TVNode: TTreeNode;
796 NodeData: TPENodeData;
797 Item: TObject;
798 CanRemoveCount: Integer;
799 CanOpenCount: Integer;
800 HasLFMCount: Integer;
801 CurUnitInfo: TUnitInfo;
802 DisabledI18NForLFMCount: Integer;
803 CanReAddCount: Integer;
804 SingleSelectedDep: TPkgDependency;
805 DepCount: Integer;
806 Dependency: TPkgDependency;
807 HasValidDep: Integer;
808 CanClearDep: Integer;
809 CanMoveFileCount: Integer;
810 OpenItemCapt: String;
811 begin
812 ItemCnt:=0;
813
814 CanRemoveCount:=0;
815 CanOpenCount:=0;
816 CanMoveFileCount:=0;
817 HasLFMCount:=0;
818 DisabledI18NForLFMCount:=0;
819 CanReAddCount:=0;
820 SingleSelectedDep:=nil;
821 DepCount:=0;
822 HasValidDep:=0;
823 CanClearDep:=0;
824 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
825 TVNode:=ItemsTreeView.Selections[i];
826 if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
827 if Item is TUnitInfo then begin
828 CurUnitInfo:=TUnitInfo(Item);
829 inc(CanOpenCount);
830 if (CurUnitInfo<>LazProject.MainUnitInfo) and (not NodeData.Removed) then begin
831 inc(CanRemoveCount);
832 inc(CanMoveFileCount);
833 end;
834 if FilenameIsPascalSource(CurUnitInfo.Filename)
835 and FileExistsCached(ChangeFileExt(CurUnitInfo.Filename,'.lfm')) then begin
836 inc(HasLFMCount);
837 if CurUnitInfo.DisableI18NForLFM then
838 inc(DisabledI18NForLFMCount);
839 end;
840 end else if Item is TPkgDependency then begin
841 Dependency:=TPkgDependency(Item);
842 if NodeData.Removed then begin
843 inc(CanReAddCount);
844 end else begin
845 inc(DepCount);
846 if DepCount=1 then
847 SingleSelectedDep:=Dependency
848 else
849 SingleSelectedDep:=nil;
850 inc(CanRemoveCount);
851 if Dependency.DependencyType=pdtLazarus then
852 inc(CanOpenCount);
853 if Dependency.RequiredPackage<>nil then
854 inc(HasValidDep);
855 if (Dependency.DefaultFilename<>'') then
856 inc(CanClearDep);
857 end;
858 end;
859 end;
860
861 if ItemsTreeView.Selected = FFilesNode then
862 begin
863 // Only the Files node is selected.
864 Assert(AddBitBtn.Enabled, 'AddBitBtn not Enabled');
865 AddPopupMenuItem(lisBtnDlgAdd, @mnuAddDiskFileClick);
866 if not LazProject.IsVirtual then
867 AddPopupMenuItem(lisRemoveNonExistingFiles,@RemoveNonExistingFilesMenuItemClick);
868 AddPopupMenuItem(cLineCaption, Nil, False); // Separator
869 AddPopupMenuItem(lisMenuOpenFolder, @mnuOpenFolderClick);
870 end
871 else if ItemsTreeView.Selected = FDependenciesNode then
872 begin
873 // Only the Required Packages node is selected.
874 AddPopupMenuItem(lisBtnDlgAdd, @mnuAddReqClick);
875 end
876 else begin
877 // Files, dependencies or everything mixed is selected.
878 if CanOpenCount>0 then begin
879 OpenItemCapt := lisOpen;
880 if Assigned(SingleSelectedDep) then
881 case SingleSelectedDep.LoadPackageResult of
882 lprAvailableOnline:
883 OpenItemCapt:=lisPckEditInstall;
884 lprNotFound:
885 if Assigned(OPMInterface) and not OPMInterface.IsPackageListLoaded then
886 OpenItemCapt:=lisPckEditCheckAvailabilityOnline;
887 end;
888 AddPopupMenuItem(OpenItemCapt, @OpenButtonClick);
889 end;
890 if CanRemoveCount>0 then
891 AddPopupMenuItem(lisRemove, @RemoveBitBtnClick);
892 // files section
893 if CanMoveFileCount>0 then
894 AddPopupMenuItem(lisCopyMoveFileToDirectory,@CopyMoveToDirMenuItemClick);
895 end;
896
897 if LazProject.EnableI18N and LazProject.EnableI18NForLFM
898 and (HasLFMCount>0) then begin
899 AddPopupMenuItem(lisEnableI18NForLFM,
900 @EnableI18NForLFMMenuItemClick, DisabledI18NForLFMCount>0);
901 AddPopupMenuItem(lisDisableI18NForLFM,
902 @DisableI18NForLFMMenuItemClick, DisabledI18NForLFMCount<HasLFMCount);
903 end;
904
905 // Required packages section
906 if CanReAddCount>0 then
907 AddPopupMenuItem(lisPckEditReAddDependency, @ReAddMenuItemClick, true);
908 if SingleSelectedDep<>nil then begin
909 AddPopupMenuItem(lisPckEditMoveDependencyUp, @MoveDependencyUpClick,
910 (SingleSelectedDep.PrevRequiresDependency<>nil));
911 AddPopupMenuItem(lisPckEditMoveDependencyDown, @MoveDependencyDownClick,
912 (SingleSelectedDep.NextRequiresDependency<>nil));
913 end;
914 if HasValidDep>0 then begin
915 AddPopupMenuItem(lisPckEditStoreFileNameAsDefaultForThisDependency,
916 @SetDependencyDefaultFilenameMenuItemClick, true);
917 AddPopupMenuItem(lisPckEditStoreFileNameAsPreferredForThisDependency,
918 @SetDependencyPreferredFilenameMenuItemClick, true);
919 end;
920 if CanClearDep>0 then begin
921 AddPopupMenuItem(lisPckEditClearDefaultPreferredFilenameOfDependency,
922 @ClearDependencyFilenameMenuItemClick, true);
923 end;
924
925 while ItemsPopupMenu.Items.Count>ItemCnt do
926 ItemsPopupMenu.Items.Delete(ItemsPopupMenu.Items.Count-1);
927 end;
928
929 procedure TProjectInspectorForm.ItemsTreeViewAdvancedCustomDrawItem(
930 Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
931 Stage: TCustomDrawStage; var PaintImages, DefaultDraw: Boolean);
932 var
933 NodeData: TPENodeData;
934 r: TRect;
935 y: Integer;
936 begin
937 if Stage=cdPostPaint then begin
938 NodeData:=GetNodeData(Node);
939 if (NodeData<>nil) then begin
940 if (NodeData.Typ=penFile) and (not NodeData.Removed)
941 and FilenameIsAbsolute(NodeData.Name)
942 and (not FileExistsCached(NodeData.Name))
943 then begin
944 r:=Node.DisplayRect(true);
945 ItemsTreeView.Canvas.Pen.Color:=clRed;
946 y:=(r.Top+r.Bottom) div 2;
947 ItemsTreeView.Canvas.Line(r.Left,y,r.Right,y);
948 end;
949 end;
950 end;
951 end;
952
953 procedure TProjectInspectorForm.OpenButtonClick(Sender: TObject);
954 var
955 i: Integer;
956 NodeData: TPENodeData;
957 Item: TObject;
958 begin
959 for i:=0 to ItemsTreeView.SelectionCount-1 do
960 begin
961 if GetNodeDataItem(ItemsTreeView.Selections[i], NodeData, Item) then
962 begin
963 if Item is TUnitInfo then
964 begin
965 if LazarusIDE.DoOpenEditorFile(TUnitInfo(Item).Filename,
966 -1,-1,[ofAddToRecent]) <> mrOk then
967 Exit;
968 end
969 else if Item is TPkgDependency then
970 if not OpmAddOrOpenDependency(TPkgDependency(Item)) then
971 Exit;
972 end;
973 end;
974 OpmInstallPendingDependencies;
975 end;
976
977 procedure TProjectInspectorForm.OptionsBitBtnClick(Sender: TObject);
978 begin
979 if Assigned(OnShowOptions) then OnShowOptions(Self);
980 end;
981
982 procedure TProjectInspectorForm.HelpBitBtnClick(Sender: TObject);
983 begin
984 LazarusHelp.ShowHelpForIDEControl(Self);
985 end;
986
987 procedure TProjectInspectorForm.ReAddMenuItemClick(Sender: TObject);
988 var
989 Dependency: TPkgDependency;
990 i: Integer;
991 TVNode: TTreeNode;
992 NodeData: TPENodeData;
993 Item: TObject;
994 begin
995 BeginUpdate;
996 try
997 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
998 TVNode:=ItemsTreeView.Selections[i];
999 if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
1000 if not NodeData.Removed then continue;
1001 if not (Item is TPkgDependency) then continue;
1002 Dependency:=TPkgDependency(Item);
1003 if TPrjFileCheck.AddingDependency(LazProject,Dependency)<>mrOK then exit;
1004 if Assigned(OnReAddDependency) then
1005 OnReAddDependency(Self,Dependency);
1006 end;
1007 finally
1008 EndUpdate;
1009 end;
1010 end;
1011
1012 procedure TProjectInspectorForm.RemoveBitBtnClick(Sender: TObject);
1013 var
1014 CurDependency: TPkgDependency;
1015 i: Integer;
1016 TVNode: TTreeNode;
1017 NodeData: TPENodeData;
1018 Item: TObject;
1019 Msg, Cap: String;
1020 DeleteCount: Integer;
1021 CurFile: TUnitInfo;
1022 begin
1023 BeginUpdate;
1024 try
1025 // check selection
1026 Msg:='';
1027 DeleteCount:=0;
1028 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
1029 TVNode:=ItemsTreeView.Selections[i];
1030 if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
1031 if Item is TUnitInfo then begin
1032 CurFile:=TUnitInfo(Item);
1033 if CurFile=LazProject.MainUnitInfo then continue;
1034 // remove file
1035 inc(DeleteCount);
1036 Msg:=Format(lisProjInspRemoveFileFromProject, [CurFile.Filename]);
1037 end else if Item is TPkgDependency then begin
1038 CurDependency:=TPkgDependency(item);
1039 if NodeData.Removed then continue;
1040 // remove dependency
1041 inc(DeleteCount);
1042 Msg:=Format(lisProjInspDeleteDependencyFor, [CurDependency.AsString]);
1043 end;
1044 end;
1045
1046 // ask for confirmation
1047 if DeleteCount=0 then exit;
1048 if DeleteCount>1 then
1049 Msg:=Format(lisProjInspRemoveItemsF, [IntToStr(DeleteCount)]);
1050 if CurFile<>nil then
1051 Cap:=lisProjInspConfirmRemovingFile
1052 else
1053 Cap:=lisProjInspConfirmDeletingDependency;
1054 if IDEMessageDialog(Cap,
1055 Msg, mtConfirmation,[mbYes,mbNo])<>mrYes then exit;
1056
1057 // delete
1058 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
1059 TVNode:=ItemsTreeView.Selections[i];
1060 if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
1061 if Item is TUnitInfo then begin
1062 CurFile:=TUnitInfo(Item);
1063 if CurFile=LazProject.MainUnitInfo then continue;
1064 // remove file
1065 if Assigned(OnRemoveFile) then OnRemoveFile(Self,CurFile);
1066 end else if Item is TPkgDependency then begin
1067 CurDependency:=TPkgDependency(item);
1068 if NodeData.Removed then continue;
1069 // remove dependency
1070 if Assigned(OnRemoveDependency) then
1071 OnRemoveDependency(Self,CurDependency);
1072 end;
1073 end;
1074 finally
1075 EndUpdate;
1076 end;
1077 end;
1078
1079 procedure TProjectInspectorForm.RemoveNonExistingFilesMenuItemClick(Sender: TObject);
1080 var
1081 AnUnitInfo: TUnitInfo;
1082 NextUnitInfo: TUnitInfo;
1083 HasChanged: Boolean;
1084 begin
1085 if LazProject.IsVirtual then exit;
1086 BeginUpdate;
1087 try
1088 HasChanged:=false;
1089 AnUnitInfo:=LazProject.FirstPartOfProject;
1090 while AnUnitInfo<>nil do begin
1091 NextUnitInfo:=AnUnitInfo.NextPartOfProject;
1092 if not (AnUnitInfo.IsVirtual or FileExistsUTF8(AnUnitInfo.Filename)) then begin
1093 AnUnitInfo.IsPartOfProject:=false;
1094 HasChanged:=true;
1095 end;
1096 AnUnitInfo:=NextUnitInfo;
1097 end;
1098 if HasChanged then begin
1099 LazProject.Modified:=true;
1100 UpdateFiles;
1101 end;
1102 finally
1103 EndUpdate;
1104 end;
1105 end;
1106
1107 procedure TProjectInspectorForm.SortAlphabeticallyButtonClick(Sender: TObject);
1108 begin
1109 SortAlphabetically:=SortAlphabeticallyButton.Down;
1110 end;
1111
1112 procedure TProjectInspectorForm.EnableI18NForLFMMenuItemClick(Sender: TObject);
1113 begin
1114 EnableI18NForSelectedLFM(true);
1115 end;
1116
1117 procedure TProjectInspectorForm.DisableI18NForLFMMenuItemClick(Sender: TObject);
1118 begin
1119 EnableI18NForSelectedLFM(false);
1120 end;
1121
1122 procedure TProjectInspectorForm.SetLazProject(const AValue: TProject);
1123 begin
1124 if FLazProject=AValue then exit;
1125 if FLazProject<>nil then begin // Old Project
1126 dec(FUpdateLock,LazProject.UpdateLock);
1127 FLazProject.OnBeginUpdate:=nil;
1128 FLazProject.OnEndUpdate:=nil;
1129 end;
1130 FLazProject:=AValue;
1131 if FLazProject<>nil then begin // New Project
1132 inc(FUpdateLock,LazProject.UpdateLock);
1133 FLazProject.OnBeginUpdate:=@ProjectBeginUpdate;
1134 FLazProject.OnEndUpdate:=@ProjectEndUpdate;
1135 end
1136 else // Only update when no project. ProjectEndUpdate will update a project.
1137 UpdateAll;
1138 end;
1139
1140 procedure TProjectInspectorForm.SetShowDirectoryHierarchy(const AValue: boolean);
1141 begin
1142 if FShowDirectoryHierarchy=AValue then exit;
1143 FShowDirectoryHierarchy:=AValue;
1144 DirectoryHierarchyButton.Down:=FShowDirectoryHierarchy;
1145 FilterEdit.ShowDirHierarchy:=FShowDirectoryHierarchy;
1146 FilterEdit.InvalidateFilter;
1147 EnvironmentOptions.ProjInspShowDirHierarchy := ShowDirectoryHierarchy;
1148 end;
1149
1150 procedure TProjectInspectorForm.SetSortAlphabetically(const AValue: boolean);
1151 begin
1152 if FSortAlphabetically=AValue then exit;
1153 FSortAlphabetically:=AValue;
1154 SortAlphabeticallyButton.Down:=FSortAlphabetically;
1155 FilterEdit.SortData:=FSortAlphabetically;
1156 FilterEdit.InvalidateFilter;
1157 EnvironmentOptions.ProjInspSortAlphabetically := SortAlphabetically;
1158 end;
1159
1160 procedure TProjectInspectorForm.SetDependencyDefaultFilename(AsPreferred: boolean);
1161 var
1162 NewFilename: String;
1163 CurDependency: TPkgDependency;
1164 i: Integer;
1165 TVNode: TTreeNode;
1166 NodeData: TPENodeData;
1167 Item: TObject;
1168 begin
1169 BeginUpdate;
1170 try
1171 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
1172 TVNode:=ItemsTreeView.Selections[i];
1173 if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
1174 if NodeData.Removed then continue;
1175 if not (Item is TPkgDependency) then continue;
1176 CurDependency:=TPkgDependency(Item);
1177 if CurDependency.RequiredPackage=nil then continue;
1178 NewFilename:=CurDependency.RequiredPackage.Filename;
1179 if (NewFilename=CurDependency.DefaultFilename) // do not use CompareFilenames
1180 and (CurDependency.PreferDefaultFilename=AsPreferred) then continue;
1181 CurDependency.DefaultFilename:=NewFilename;
1182 CurDependency.PreferDefaultFilename:=AsPreferred;
1183 LazProject.Modified:=true;
1184 UpdateRequiredPackages;
1185 end;
1186 finally
1187 EndUpdate;
1188 end;
1189 end;
1190
1191 procedure TProjectInspectorForm.SetIdleConnected(AValue: boolean);
1192 begin
1193 if csDestroying in ComponentState then
1194 AValue:=false;
1195 if FIdleConnected=AValue then exit;
1196 FIdleConnected:=AValue;
1197 if FIdleConnected then
1198 Application.AddOnIdleHandler(@IdleHandler)
1199 else
1200 Application.RemoveOnIdleHandler(@IdleHandler);
1201 end;
1202
GetDependencyToUpdatenull1203 function TProjectInspectorForm.GetDependencyToUpdate(Immediately: boolean): TPkgDependencyID;
1204 begin
1205 if CanUpdate(pefNeedUpdateApplyDependencyButton,Immediately) then
1206 Result:=GetSingleSelectedDependency
1207 else
1208 Result:=nil;
1209 end;
1210
1211 procedure TProjectInspectorForm.ApplyDependencyButtonClick(Sender: TObject);
1212 var
1213 CurDependency: TPkgDependency;
1214 begin
1215 CurDependency:=GetSingleSelectedDependency;
1216 if (LazProject=nil) or (CurDependency=nil)
1217 or not FPropGui.CheckApplyDependency(CurDependency) then exit;
1218 LazProject.Modified:=True;
1219 PkgBoss.ApplyDependency(CurDependency);
1220 end;
1221
CreateToolButtonnull1222 function TProjectInspectorForm.CreateToolButton(AName, ACaption, AHint, AImageName: String;
1223 AOnClick: TNotifyEvent): TToolButton;
1224 begin
1225 Result := TToolButton.Create(Self);
1226 Result.Name := AName;
1227 Result.Caption := ACaption;
1228 Result.Hint := AHint;
1229 if AImageName <> '' then
1230 Result.ImageIndex := IDEImages.LoadImage(AImageName);
1231 Result.ShowHint := True;
1232 Result.OnClick := AOnClick;
1233 Result.AutoSize := True;
1234 Result.Parent := ToolBar;
1235 end;
1236
CreateDividernull1237 function TProjectInspectorForm.CreateDivider: TToolButton;
1238 begin
1239 Result := TToolButton.Create(Self);
1240 Result.Style := tbsDivider;
1241 Result.AutoSize := True;
1242 Result.Parent := ToolBar;
1243 end;
1244
1245 procedure TProjectInspectorForm.SetupComponents;
1246 begin
1247 ImageIndexFiles := IDEImages.LoadImage('pkg_files');
1248 ImageIndexProject := IDEImages.LoadImage('item_project_source');
1249 ImageIndexUnit := IDEImages.LoadImage('item_unit');
1250 ImageIndexRegisterUnit := IDEImages.LoadImage('pkg_registerunit');
1251 ImageIndexText := IDEImages.LoadImage('pkg_text');
1252 ImageIndexBinary := IDEImages.LoadImage('pkg_binary');
1253 ImageIndexDirectory := IDEImages.LoadImage('pkg_files');
1254
1255 ItemsTreeView.Images := IDEImages.Images_16;
1256 ToolBar.Images := IDEImages.Images_16;
1257 FilterEdit.OnGetImageIndex:=@TreeViewGetImageIndex;
1258
1259 AddBitBtn := CreateToolButton('AddBitBtn', lisAdd, lisClickToSeeTheChoices, 'laz_add', nil);
1260 AddBitBtn.Style:=tbsButtonDrop;
1261 RemoveBitBtn := CreateToolButton('RemoveBitBtn', lisRemove, lisPckEditRemoveSelectedItem, 'laz_delete', @RemoveBitBtnClick);
1262 CreateDivider;
1263 OptionsBitBtn := CreateToolButton('OptionsBitBtn', lisOptions, lisPckEditEditGeneralOptions, 'menu_environment_options', @OptionsBitBtnClick);
1264 OptionsBitBtn.DropdownMenu := TSetBuildModeToolButton.TBuildModeMenu.Create(Self);
1265 OptionsBitBtn.Style := tbsDropDown;
1266 HelpBitBtn := CreateToolButton('HelpBitBtn', GetButtonCaption(idButtonHelp), lisMenuOnlineHelp, 'btn_help', @HelpBitBtnClick);
1267
1268 AddBitBtn.DropdownMenu:=AddPopupMenu;
1269 mnuAddDiskFile.Caption:=lisPckEditAddFilesFromFileSystem;
1270 mnuAddEditorFiles.Caption:=lisProjAddEditorFile;
1271 mnuAddReq.Caption:=lisProjAddNewRequirement;
1272 mnuAddFPMakeReq.Caption:=lisProjAddNewFPMakeRequirement;
1273
1274 IDEImages.AssignImage(OpenButton, 'laz_open');
1275 OpenButton.Caption:='';
1276 OpenButton.Hint:=lisOpenFile2;
1277 SortAlphabeticallyButton.Hint:=lisPESortFilesAlphabetically;
1278 IDEImages.AssignImage(SortAlphabeticallyButton, 'pkg_sortalphabetically');
1279 DirectoryHierarchyButton.Hint:=lisPEShowDirectoryHierarchy;
1280 IDEImages.AssignImage(DirectoryHierarchyButton, 'pkg_hierarchical');
1281
1282 FPropGui.OnGetPkgDep := @GetDependencyToUpdate;
1283 FPropGui.ApplyDependencyButton.OnClick := @ApplyDependencyButtonClick;
1284
1285 with ItemsTreeView do begin
1286 FFilesNode:=Items.Add(nil, dlgEnvFiles);
1287 FFilesNode.ImageIndex:=ImageIndexFiles;
1288 FFilesNode.SelectedIndex:=FFilesNode.ImageIndex;
1289 FDependenciesNode:=Items.Add(nil, lisPckEditRequiredPackages);
1290 FDependenciesNode.ImageIndex:=FPropGui.ImageIndexRequired;
1291 FDependenciesNode.SelectedIndex:=FDependenciesNode.ImageIndex;
1292 end;
1293 end;
1294
TreeViewGetImageIndexnull1295 function TProjectInspectorForm.TreeViewGetImageIndex(Str: String; Data: TObject;
1296 var AIsEnabled: Boolean): Integer;
1297 var
1298 NodeData: TPENodeData;
1299 Item: TObject;
1300 begin
1301 Result := -1;
1302 if not (Data is TPENodeData) then exit;
1303 NodeData:=TPENodeData(Data);
1304 Item:=GetNodeItem(NodeData);
1305 if Item=nil then exit;
1306 if Item is TUnitInfo then begin
1307 if FilenameHasPascalExt(TUnitInfo(Item).Filename) then
1308 Result:=ImageIndexUnit
1309 else if (LazProject<>nil) and (LazProject.MainUnitinfo=Item) then
1310 Result:=ImageIndexProject
1311 else
1312 Result:=ImageIndexText;
1313 end
1314 else if Item is TPkgDependency then
1315 Result:=FPropGui.GetDependencyImageIndex(TPkgDependency(Item));
1316 end;
1317
1318 procedure TProjectInspectorForm.UpdateFiles(Immediately: boolean);
1319 var
1320 CurFile: TUnitInfo;
1321 FilesBranch: TTreeFilterBranch;
1322 Filename: String;
1323 ANodeData : TPENodeData;
1324 begin
1325 if not CanUpdate(pefNeedUpdateFiles,Immediately) then exit;
1326 FilesBranch:=FilterEdit.GetCleanBranch(FFilesNode);
1327 FilesBranch.ClearNodeData;
1328 FPropGui.FreeNodeData(penFile);
1329 if LazProject<>nil then begin
1330 FilterEdit.SelectedPart:=FNextSelectedPart;
1331 FilterEdit.ShowDirHierarchy:=ShowDirectoryHierarchy;
1332 FilterEdit.SortData:=SortAlphabetically;
1333 FilterEdit.ImageIndexDirectory:=ImageIndexDirectory;
1334 // collect and sort files
1335 CurFile:=LazProject.FirstPartOfProject;
1336 while CurFile<>nil do begin
1337 Filename:=CurFile.GetShortFilename(true);
1338 if Filename<>'' then Begin
1339 ANodeData:=FPropGui.CreateNodeData(penFile, CurFile.Filename, False);
1340 FilesBranch.AddNodeData(Filename, ANodeData, CurFile.Filename);
1341 end;
1342 CurFile:=CurFile.NextPartOfProject;
1343 end;
1344 end;
1345 FilterEdit.InvalidateFilter; // Data is shown by FilterEdit.
1346 UpdateProperties;
1347 UpdateButtons;
1348 end;
1349
1350 procedure TProjectInspectorForm.UpdateRequiredPackages(Immediately: boolean);
1351 var
1352 Dependency: TPkgDependency;
1353 RequiredBranch, RemovedBranch: TTreeFilterBranch;
1354 ANodeData : TPENodeData;
1355 begin
1356 if not CanUpdate(pefNeedUpdateRequiredPkgs,Immediately) then exit;
1357 RequiredBranch:=FilterEdit.GetCleanBranch(FDependenciesNode);
1358 RequiredBranch.ClearNodeData;
1359 FPropGui.FreeNodeData(penDependency);
1360 Dependency:=Nil;
1361 if LazProject<>nil then begin
1362 // required packages
1363 Dependency:=LazProject.FirstRequiredDependency;
1364 while Dependency<>nil do begin
1365 // Add the required package under the branch
1366 ANodeData:=FPropGui.CreateNodeData(penDependency, Dependency.PackageName, False);
1367 RequiredBranch.AddNodeData(Dependency.AsString(False,True)+OPNote(Dependency), ANodeData);
1368 Dependency:=Dependency.NextRequiresDependency;
1369 end;
1370
1371 // removed required packages
1372 Dependency:=LazProject.FirstRemovedDependency;
1373 if Dependency<>nil then begin
1374 // Create root node for removed dependencies if not done yet.
1375 if FRemovedDependenciesNode=nil then begin
1376 FRemovedDependenciesNode:=ItemsTreeView.Items.Add(FDependenciesNode,
1377 lisProjInspRemovedRequiredPackages);
1378 FRemovedDependenciesNode.ImageIndex:=FPropGui.ImageIndexRemovedRequired;
1379 FRemovedDependenciesNode.SelectedIndex:=FRemovedDependenciesNode.ImageIndex;
1380 end;
1381 RemovedBranch:=FilterEdit.GetCleanBranch(FRemovedDependenciesNode);
1382 // Add all removed dependencies under the branch
1383 while Dependency<>nil do begin
1384 ANodeData := FPropGui.CreateNodeData(penDependency, Dependency.PackageName, True);
1385 RemovedBranch.AddNodeData(Dependency.AsString, ANodeData);
1386 Dependency:=Dependency.NextRequiresDependency;
1387 end;
1388 end;
1389 end;
1390
1391 // Dependency is set to removed required packages if there is active project
1392 if (Dependency=nil) and (FRemovedDependenciesNode<>nil) then begin
1393 // No removed dependencies -> delete the root node
1394 FilterEdit.DeleteBranch(FRemovedDependenciesNode);
1395 FreeThenNil(FRemovedDependenciesNode);
1396 end;
1397 FilterEdit.InvalidateFilter;
1398 UpdateProperties;
1399 UpdateButtons;
1400 end;
1401
1402 procedure TProjectInspectorForm.ProjectBeginUpdate(Sender: TObject);
1403 begin
1404 BeginUpdate;
1405 end;
1406
1407 procedure TProjectInspectorForm.ProjectEndUpdate(Sender: TObject; ProjectChanged: boolean);
1408 begin
1409 if ProjectChanged then
1410 UpdateAll;
1411 EndUpdate;
1412 end;
1413
1414 procedure TProjectInspectorForm.EnableI18NForSelectedLFM(TheEnable: boolean);
1415 var
1416 i: Integer;
1417 TVNode: TTreeNode;
1418 NodeData: TPENodeData;
1419 Item: TObject;
1420 CurUnitInfo: TUnitInfo;
1421 begin
1422 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
1423 TVNode:=ItemsTreeView.Selections[i];
1424 if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
1425 if not (Item is TUnitInfo) then continue;
1426 CurUnitInfo:=TUnitInfo(Item);
1427 if not FilenameIsPascalSource(CurUnitInfo.Filename) then continue;
1428 CurUnitInfo.DisableI18NForLFM:=not TheEnable;
1429 end;
1430 end;
1431
1432 procedure TProjectInspectorForm.PackageListAvailable(Sender: TObject);
1433 begin
1434 //DebugLn(['TProjectInspectorForm.PackageListAvailable: ', LazProject.Title]);
1435 UpdateRequiredPackages;
1436 end;
1437
1438 procedure TProjectInspectorForm.KeyDown(var Key: Word; Shift: TShiftState);
1439 begin
1440 inherited KeyDown(Key, Shift);
1441 ExecuteIDEShortCut(Self,Key,Shift,nil);
1442 end;
1443
1444 procedure TProjectInspectorForm.IdleHandler(Sender: TObject; var Done: Boolean);
1445 begin
1446 if fUpdateLock>0 then exit;
1447 IdleConnected:=false;
1448 UpdatePending;
1449 end;
1450
GetSingleSelectedDependencynull1451 function TProjectInspectorForm.GetSingleSelectedDependency: TPkgDependency;
1452 var
1453 Item: TObject;
1454 NodeData: TPENodeData;
1455 begin
1456 Result:=nil;
1457 if not GetNodeDataItem(ItemsTreeView.Selected,NodeData,Item) then exit;
1458 if Item is TPkgDependency then
1459 Result:=TPkgDependency(Item);
1460 end;
1461
TreeViewToInspectornull1462 function TProjectInspectorForm.TreeViewToInspector(TV: TTreeView): TProjectInspectorForm;
1463 begin
1464 if TV=ItemsTreeView then
1465 Result:=Self
1466 else
1467 Result:=nil;
1468 end;
1469
1470 constructor TProjectInspectorForm.Create(TheOwner: TComponent);
1471 begin
1472 inherited Create(TheOwner);
1473 Name:=NonModalIDEWindowNames[nmiwProjectInspector];
1474 Caption:=lisMenuProjectInspector;
1475 KeyPreview:=true;
1476 FPropGui:=TProjPackFilePropGui.Create(PropsGroupBox, False);
1477 SetupComponents;
1478 KeyPreview:=true;
1479 SortAlphabetically := EnvironmentOptions.ProjInspSortAlphabetically;
1480 ShowDirectoryHierarchy := EnvironmentOptions.ProjInspShowDirHierarchy;
1481 end;
1482
1483 destructor TProjectInspectorForm.Destroy;
1484 begin
1485 IdleConnected:=false;
1486 LazProject:=nil;
1487 inherited Destroy;
1488 FreeAndNil(FPropGui);
1489 if ProjInspector=Self then
1490 ProjInspector:=nil;
1491 end;
1492
ExtendIncSearchPathnull1493 function TProjectInspectorForm.ExtendIncSearchPath(NewIncPaths: string): boolean;
1494 begin
1495 Result:=LazProject.ExtendIncSearchPath(NewIncPaths);
1496 end;
1497
ExtendUnitSearchPathnull1498 function TProjectInspectorForm.ExtendUnitSearchPath(NewUnitPaths: string): boolean;
1499 begin
1500 Result:=LazProject.ExtendUnitSearchPath(NewUnitPaths);
1501 end;
1502
FilesBaseDirectorynull1503 function TProjectInspectorForm.FilesBaseDirectory: string;
1504 begin
1505 if LazProject<>nil then
1506 Result:=LazProject.Directory
1507 else
1508 Result:='';
1509 end;
1510
FilesEditFormnull1511 function TProjectInspectorForm.FilesEditForm: TCustomForm;
1512 begin
1513 Result:=Self;
1514 end;
1515
FilesEditTreeViewnull1516 function TProjectInspectorForm.FilesEditTreeView: TTreeView;
1517 begin
1518 Result:=ItemsTreeView;
1519 end;
1520
FilesOwnernull1521 function TProjectInspectorForm.FilesOwner: TObject;
1522 begin
1523 Result:=LazProject;
1524 end;
1525
FilesOwnerNamenull1526 function TProjectInspectorForm.FilesOwnerName: string;
1527 begin
1528 Result:=lisProject3;
1529 end;
1530
FilesOwnerReadOnlynull1531 function TProjectInspectorForm.FilesOwnerReadOnly: boolean;
1532 begin
1533 Result:=false;
1534 end;
1535
FirstRequiredDependencynull1536 function TProjectInspectorForm.FirstRequiredDependency: TPkgDependency;
1537 begin
1538 if LazProject<>nil then
1539 Result:=LazProject.FirstRequiredDependency
1540 else
1541 Result:=nil;
1542 end;
1543
GetNodeFilenamenull1544 function TProjectInspectorForm.GetNodeFilename(Node: TTreeNode): string;
1545 var
1546 Item: TFileNameItem;
1547 begin
1548 Result:='';
1549 if Node=nil then exit;
1550 if Node=FFilesNode then
1551 exit(FilesBaseDirectory);
1552 Item:=TFileNameItem(Node.Data);
1553 if (Item is TFileNameItem) then begin
1554 Result:=Item.Filename;
1555 end else if Node.HasAsParent(FFilesNode) then begin
1556 // directory node
1557 Result:=Node.Text;
1558 end else
1559 exit;
1560 if not FilenameIsAbsolute(Result) then
1561 Result:=AppendPathDelim(FilesBaseDirectory)+Result;
1562 end;
1563
IsDirectoryNodenull1564 function TProjectInspectorForm.IsDirectoryNode(Node: TTreeNode): boolean;
1565 begin
1566 Result:=(Node<>nil) and (Node.Data=nil) and Node.HasAsParent(FFilesNode);
1567 end;
1568
1569 procedure TProjectInspectorForm.BeginUpdate;
1570 begin
1571 inc(FUpdateLock);
1572 end;
1573
1574 procedure TProjectInspectorForm.EndUpdate;
1575 begin
1576 if FUpdateLock=0 then RaiseGDBException('TProjectInspectorForm.EndUpdate');
1577 dec(FUpdateLock);
1578 if FUpdateLock=0 then
1579 IdleConnected:=true;
1580 end;
1581
1582 procedure TProjectInspectorForm.UpdateAll(Immediately: boolean);
1583 begin
1584 if csDestroying in ComponentState then exit;
1585 fFlags:=fFlags+[
1586 pefNeedUpdateTitle,
1587 pefNeedUpdateFiles,
1588 pefNeedUpdateRequiredPkgs,
1589 pefNeedUpdateProperties,
1590 pefNeedUpdateButtons,
1591 pefNeedUpdateApplyDependencyButton,
1592 pefNeedUpdateStatusBar];
1593 //UpdateTitle;
1594 //UpdateFiles;
1595 //UpdateRequiredPackages;
1596 //UpdateButtons;
1597 if Immediately then
1598 UpdatePending
1599 else
1600 IdleConnected:=true;
1601 end;
1602
1603 procedure TProjectInspectorForm.UpdateTitle(Immediately: boolean);
1604 var
1605 NewCaption: String;
1606 IconStream: TStream;
1607 begin
1608 if not CanUpdate(pefNeedUpdateTitle,Immediately) then exit;
1609 Icon.Clear;
1610 if LazProject=nil then
1611 Caption:=lisMenuProjectInspector
1612 else begin
1613 NewCaption:=LazProject.GetTitle;
1614 if NewCaption='' then
1615 NewCaption:=ExtractFilenameOnly(LazProject.ProjectInfoFile);
1616 NewCaption:=Format(lisProjInspProjectInspector, [NewCaption]);
1617 if (LazProject.ActiveBuildMode.GetCaption<>'') then
1618 NewCaption := NewCaption + ' ['+LazProject.ActiveBuildMode.GetCaption+']';
1619 Caption := NewCaption;
1620
1621 if not LazProject.ProjResources.ProjectIcon.IsEmpty then
1622 begin
1623 IconStream := LazProject.ProjResources.ProjectIcon.GetStream;
1624 if IconStream<>nil then
1625 try
1626 Icon.LoadFromStream(IconStream);
1627 finally
1628 IconStream.Free;
1629 end;
1630 end;
1631 end;
1632 end;
1633
1634 procedure TProjectInspectorForm.UpdateProperties(Immediately: boolean);
1635 var
1636 CurDependency, SingleSelectedDep: TPkgDependency;
1637 TVNode, SingleSelectedDirectory: TTreeNode;
1638 NodeData: TPENodeData;
1639 Item: TObject;
1640 i, SelFileCount, SelDepCount, SelUnitCount, SelDirCount: Integer;
1641 SingleSelectedRemoved: Boolean;
1642 begin
1643 if not CanUpdate(pefNeedUpdateProperties,Immediately) then exit;
1644 //GuiToFileOptions(False);
1645
1646 // check selection
1647 SingleSelectedDep:=nil;
1648 SingleSelectedDirectory:=nil;
1649 SingleSelectedRemoved:=false;
1650 SelFileCount:=0;
1651 SelDepCount:=0;
1652 SelUnitCount:=0;
1653 SelDirCount:=0;
1654 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
1655 TVNode:=ItemsTreeView.Selections[i];
1656 if GetNodeDataItem(TVNode,NodeData,Item) then begin
1657 if Item is TUnitInfo then begin
1658 inc(SelFileCount);
1659 SingleSelectedRemoved:=NodeData.Removed;
1660 inc(SelUnitCount);
1661 end
1662 else if Item is TPkgDependency then begin
1663 inc(SelDepCount);
1664 CurDependency:=TPkgDependency(Item);
1665 SingleSelectedDep:=CurDependency;
1666 SingleSelectedRemoved:=NodeData.Removed;
1667 end;
1668 end else if IsDirectoryNode(TVNode) or (TVNode=FFilesNode) then begin
1669 inc(SelDirCount);
1670 SingleSelectedDirectory:=TVNode;
1671 end //else if TVNode=FRequiredPackagesNode then
1672 // DebugLn('UpdatePEProperties: Required packages selected');
1673 end;
1674
1675 if (SelFileCount+SelDepCount+SelDirCount>1) then begin
1676 // it is a multi selection
1677 SingleSelectedDep:=nil;
1678 SingleSelectedDirectory:=nil;
1679 end;
1680
1681 //OnlyFilesWithUnitsSelected:=
1682 // (SelFileCount>0) and (SelDepCount=0) and (SelDirCount=0) and (SelUnitCount>0);
1683 //FPropGui.ControlVisible := OnlyFilesWithUnitsSelected;
1684 FPropGui.ControlEnabled := True; //not LazProject.ReadOnly;
1685 DisableAlign;
1686 try
1687 // Min/Max version of dependency (only single selection)
1688 FPropGui.ControlVisible := SingleSelectedDep<>nil;
1689 FPropGui.SetMinMaxVisibility;
1690 if SelFileCount>0 then begin
1691 PropsGroupBox.Enabled:=true;
1692 PropsGroupBox.Caption:=lisPckEditFileProperties;
1693 end
1694 else if SingleSelectedDep<>nil then begin
1695 PropsGroupBox.Enabled:=not SingleSelectedRemoved;
1696 PropsGroupBox.Caption:=lisPckEditDependencyProperties;
1697 FPropGui.SetMinMaxValues(SingleSelectedDep);
1698 FPropGui.UpdateApplyDependencyButton;
1699 end
1700 else if SingleSelectedDirectory<>nil then begin
1701 //PropsGroupBox.Enabled:=true;
1702 //PropsGroupBox.Caption:=lisPckEditFileProperties;
1703 end
1704 else begin
1705 PropsGroupBox.Enabled:=false;
1706 PropsGroupBox.Caption:=lisPckEditDependencyProperties;
1707 end;
1708 finally
1709 EnableAlign;
1710 end;
1711 end;
1712
1713 procedure TProjectInspectorForm.UpdateButtons(Immediately: boolean);
1714 var
1715 i: Integer;
1716 TVNode: TTreeNode;
1717 NodeData: TPENodeData;
1718 Item: TObject;
1719 CanRemoveCount: Integer;
1720 CurUnitInfo: TUnitInfo;
1721 CanOpenCount: Integer;
1722 begin
1723 if not CanUpdate(pefNeedUpdateButtons,Immediately) then exit;
1724 CanRemoveCount:=0;
1725 CanOpenCount:=0;
1726 if Assigned(LazProject) then
1727 begin
1728 for i:=0 to ItemsTreeView.SelectionCount-1 do begin
1729 TVNode:=ItemsTreeView.Selections[i];
1730 if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
1731 if Item is TUnitInfo then begin
1732 CurUnitInfo:=TUnitInfo(Item);
1733 inc(CanOpenCount);
1734 if CurUnitInfo<>LazProject.MainUnitInfo then
1735 inc(CanRemoveCount);
1736 end else if Item is TPkgDependency then begin
1737 if not NodeData.Removed and (TPkgDependency(Item).DependencyType=pdtLazarus) then begin
1738 inc(CanRemoveCount);
1739 inc(CanOpenCount);
1740 end;
1741 end;
1742 end;
1743 end;
1744 AddBitBtn.Enabled:=Assigned(LazProject);
1745 RemoveBitBtn.Enabled:=(CanRemoveCount>0);
1746 OpenButton.Enabled:=(CanOpenCount>0);
1747 OptionsBitBtn.Enabled:=Assigned(LazProject);
1748 end;
1749
1750 procedure TProjectInspectorForm.UpdatePending;
1751 begin
1752 ItemsTreeView.BeginUpdate;
1753 try
1754 if pefNeedUpdateTitle in FFlags then
1755 UpdateTitle(True);
1756 if pefNeedUpdateFiles in FFlags then
1757 UpdateFiles(True);
1758 if pefNeedUpdateRequiredPkgs in FFlags then
1759 UpdateRequiredPackages(True);
1760 if pefNeedUpdateProperties in FFlags then
1761 UpdateProperties(True);
1762 if pefNeedUpdateButtons in FFlags then
1763 UpdateButtons(True);
1764 //if pefNeedUpdateApplyDependencyButton in fFlags then
1765 // FPropGui.UpdateApplyDependencyButton(true);
1766 IdleConnected:=false;
1767 finally
1768 ItemsTreeView.EndUpdate;
1769 end;
1770 end;
1771
CanUpdatenull1772 function TProjectInspectorForm.CanUpdate(Flag: TPEFlag; Immediately: boolean): boolean;
1773 begin
1774 Result:=false;
1775 if csDestroying in ComponentState then exit;
1776 if (FUpdateLock>0) and not Immediately then begin
1777 Include(fFlags,Flag);
1778 IdleConnected:=true;
1779 end else begin
1780 Exclude(fFlags,Flag);
1781 Result:=true;
1782 end;
1783 end;
1784
GetNodeItemnull1785 function TProjectInspectorForm.GetNodeItem(NodeData: TPENodeData): TObject;
1786 begin
1787 Result:=nil;
1788 if (LazProject=nil) or (NodeData=nil) then exit;
1789 case NodeData.Typ of
1790 penFile:
1791 if NodeData.Removed then
1792 Result:=nil
1793 else
1794 Result:=LazProject.UnitInfoWithFilename(NodeData.Name,[pfsfOnlyProjectFiles]);
1795 penDependency:
1796 if NodeData.Removed then
1797 Result:=LazProject.FindRemovedDependencyByName(NodeData.Name)
1798 else
1799 Result:=LazProject.FindDependencyByName(NodeData.Name);
1800 end;
1801 end;
1802
GetNodeDataItemnull1803 function TProjectInspectorForm.GetNodeDataItem(TVNode: TTreeNode; out
1804 NodeData: TPENodeData; out Item: TObject): boolean;
1805 begin
1806 Result:=false;
1807 Item:=nil;
1808 NodeData:=GetNodeData(TVNode);
1809 Item:=GetNodeItem(NodeData);
1810 Result:=Item<>nil;
1811 end;
1812
1813 { TSetBuildModeToolButton.TBuildModeMenu }
1814
1815 procedure TSetBuildModeToolButton.TBuildModeMenu.DoPopup(Sender: TObject);
1816 var
1817 CurIndex: Integer;
1818 i: Integer;
1819
1820 procedure AddMode(BuildModeIndex: Integer; CurMode: TProjectBuildMode);
1821 var
1822 AMenuItem: TBuildModeMenuItem;
1823 begin
1824 if Items.Count > CurIndex then
1825 AMenuItem := Items[CurIndex] as TBuildModeMenuItem
1826 else
1827 begin
1828 AMenuItem := TBuildModeMenuItem.Create(Self);
1829 AMenuItem.Name := Name + 'Mode' + IntToStr(CurIndex);
1830 Items.Add(AMenuItem);
1831 end;
1832 AMenuItem.BuildModeIndex := BuildModeIndex;
1833 AMenuItem.Caption := CurMode.GetCaption;
1834 AMenuItem.Checked := (Project1<>nil) and (Project1.ActiveBuildMode=CurMode);
1835 AMenuItem.ShowAlwaysCheckable:=true;
1836 inc(CurIndex);
1837 end;
1838
1839 begin
1840 // fill the PopupMenu
1841 CurIndex := 0;
1842 if Project1<>nil then
1843 for i:=0 to Project1.BuildModes.Count-1 do
1844 AddMode(i, Project1.BuildModes[i]);
1845 // remove unused menuitems
1846 while Items.Count > CurIndex do
1847 Items[Items.Count - 1].Free;
1848
1849 inherited DoPopup(Sender);
1850 end;
1851
1852 { TSetBuildModeToolButton.TBuildModeMenuItem }
1853
1854 procedure TSetBuildModeToolButton.TBuildModeMenuItem.Click;
1855 var
1856 NewMode: TProjectBuildMode;
1857 begin
1858 inherited Click;
1859
1860 NewMode := Project1.BuildModes[BuildModeIndex];
1861 if NewMode = Project1.ActiveBuildMode then exit;
1862 if not (MainIDE.ToolStatus in [itNone,itDebugger]) then begin
1863 IDEMessageDialog(dlgMsgWinColorUrgentError,
1864 lisYouCanNotChangeTheBuildModeWhileCompiling,
1865 mtError,[mbOk]);
1866 exit;
1867 end;
1868
1869 Project1.ActiveBuildMode := NewMode;
1870 Project1.DefineTemplates.AllChanged(false);
1871 IncreaseCompilerParseStamp;
1872 MainBuildBoss.SetBuildTargetProject1(false);
1873 MainIDE.UpdateCaption;
1874 if Assigned(ProjInspector) then
1875 ProjInspector.UpdateTitle;
1876 end;
1877
1878 { TSetBuildModeToolButton }
1879
1880 procedure TSetBuildModeToolButton.DoOnAdded;
1881 begin
1882 inherited DoOnAdded;
1883
1884 DropdownMenu := TBuildModeMenu.Create(Self);
1885 Style := tbsDropDown;
1886 end;
1887
1888 end.
1889
1890