1 unit AddPkgDependencyDlg;
2
3 {$mode objfpc}{$H+}
4
5 interface
6
7 uses
8 Classes, SysUtils, Types, Laz_AVL_Tree, fgl,
9 // LCL
10 Forms, Controls, Dialogs, StdCtrls, ButtonPanel, LCLProc, LCLType, Graphics,
11 LCLIntf, ExtCtrls,
12 // LazControls
13 ListFilterEdit,
14 // IDEIntf
15 IDEWindowIntf, PackageDependencyIntf, PackageIntf, IDEDialogs, IDEImagesIntf, PackageLinkIntf, MainIntf,
16 // IDE
17 LazarusIDEStrConsts, PackageDefs, PackageSystem, ProjPackCommon, ProjPackChecks;
18
19 type
20
21 TPkgDependencyList = specialize TFPGList<TPkgDependency>;
22
23 { TAddPkgDependencyDialog }
24
25 TAddPkgDependencyDialog = class(TForm)
26 BP: TButtonPanel;
27 cbLocalPkg: TCheckBox;
28 cbOnlinePkg: TCheckBox;
29 DependMaxVersionEdit: TEdit;
30 DependMaxVersionLabel: TLabel;
31 DependMinVersionEdit: TEdit;
32 DependMinVersionLabel: TLabel;
33 DependPkgNameFilter: TListFilterEdit;
34 DependPkgNameLabel: TLabel;
35 DependPkgTypeLabel: TLabel;
36 DependPkgNameListBox: TListBox;
37 pnLocalPkg: TPanel;
38 pnOnlinePkg: TPanel;
39 procedure cbLocalPkgChange(Sender: TObject);
40 procedure CloseButtonClick(Sender: TObject);
41 procedure DependPkgNameListBoxDrawItem(Control: TWinControl;
42 Index: Integer; ARect: TRect; State: TOwnerDrawState);
43 procedure DependPkgNameListBoxSelectionChange(Sender: TObject; {%H-}User: boolean);
44 procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
45 procedure FormCreate(Sender: TObject);
46 procedure OKButtonClick(Sender: TObject);
FindPackageLinknull47 function FindPackageLink(const ALazPackageID: TLazPackageID): TPackageLink;
InstallOnlinePackagesnull48 function InstallOnlinePackages(out ANeedToRebuild: Boolean): TModalResult;
49 private
50 fUpdating: Boolean;
51 fSL: TStringList;
52 fPackages: TAVLTree; // tree of TLazPackage or TPackageLink
53 fProjPack: IProjPack;
54 fResultDependencies: TPkgDependencyList;
55 procedure AddUniquePackagesToList(APackageID: TLazPackageID);
56 procedure UpdateAvailableDependencyNames;
IsInstallButtonVisiblenull57 function IsInstallButtonVisible: Boolean;
58 public
59 constructor Create(TheOwner: TComponent); override;
60 destructor Destroy; override;
61 end;
62
63 var
64 AddPkgDependencyDialog: TAddPkgDependencyDialog;
65
ShowAddPkgDependencyDlgnull66 function ShowAddPkgDependencyDlg(AProjPack: IProjPack;
67 out AResultDependencies: TPkgDependencyList): TModalResult;
68
69 implementation
70
71 {$R *.lfm}
72
ShowAddPkgDependencyDlgnull73 function ShowAddPkgDependencyDlg(AProjPack: IProjPack;
74 out AResultDependencies: TPkgDependencyList): TModalResult;
75 var
76 AddDepDialog: TAddPkgDependencyDialog;
77 begin
78 AddDepDialog:=TAddPkgDependencyDialog.Create(nil);
79 AddDepDialog.fProjPack:=AProjPack;
80 AddDepDialog.UpdateAvailableDependencyNames;
81
82 Result:=AddDepDialog.ShowModal;
83 if Result=mrOk then begin
84 AResultDependencies:=AddDepDialog.fResultDependencies;
85 AddDepDialog.fResultDependencies:=nil;
86 end else begin
87 AResultDependencies:=nil;
88 end;
89 AddDepDialog.Free;
90 end;
91
92 { TAddPkgDependencyDialog }
93
94 constructor TAddPkgDependencyDialog.Create(TheOwner: TComponent);
95 begin
96 inherited Create(TheOwner);
97 Caption:=lisProjAddNewRequirement;
98 fPackages:=TAVLTree.Create(@CompareLazPackageIDNames);
99
100 DependPkgNameLabel.Caption:=lisProjAddPackageName;
101 DependPkgTypeLabel.Caption:=lisProjAddPackageType;
102 cbLocalPkg.Caption:=lisProjAddLocalPkg;
103 cbOnlinePkg.Caption:=lisProjAddOnlinePkg;
104 BP.CloseButton.Caption := lisPckEditInstall;
105 DependMinVersionLabel.Caption:=lisProjAddMinimumVersionOptional;
106 DependMinVersionEdit.Text:='';
107 DependMaxVersionLabel.Caption:=lisProjAddMaximumVersionOptional;
108 DependMaxVersionEdit.Text:='';
109
110 IDEDialogLayoutList.ApplyLayout(Self,400,360);
111 end;
112
113 destructor TAddPkgDependencyDialog.Destroy;
114 begin
115 FreeAndNil(fPackages);
116 inherited Destroy;
117 end;
118
119 procedure TAddPkgDependencyDialog.FormClose(Sender: TObject; var CloseAction: TCloseAction);
120 begin
121 fSL.Free;
122 fSL := nil;
123 IDEDialogLayoutList.SaveLayout(Self);
124 end;
125
126 procedure TAddPkgDependencyDialog.FormCreate(Sender: TObject);
127 begin
128 fSL := TStringList.Create;
129 DependPkgTypeLabel.Visible := OPMInterface <> nil;
130 pnLocalPkg.Visible := OPMInterface <> nil;
131 pnOnlinePkg.Visible := OPMInterface <> nil;
132 BP.CloseButton.Visible := False;
133 DependPkgNameListBox.ItemHeight := MulDiv(20, Screen.PixelsPerInch, 96);
134 end;
135
TAddPkgDependencyDialog.FindPackageLinknull136 function TAddPkgDependencyDialog.FindPackageLink(const ALazPackageID:
137 TLazPackageID): TPackageLink;
138 var
139 I: Integer;
140 begin
141 Result := nil;
142 if (fSL = nil) or (fSL.Count = 0) then
143 Exit;
144 for I := 0 to fSL.Count - 1 do
145 begin
146 if TLazPackageID(fSL.Objects[I]) = ALazPackageID then
147 begin
148 Result := TPackageLink(fSL.Objects[I]);
149 Break;
150 end;
151 end;
152 end;
153
154 procedure TAddPkgDependencyDialog.DependPkgNameListBoxDrawItem(
155 Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState);
156 var
157 ItemText: string;
158 PackageLink: TPackageLink;
159 begin
160 with (Control as TListBox).Canvas do
161 begin
162 if odSelected In State then
163 begin
164 Pen.Color := clHighlightText;
165 Brush.Color := clHighlight;
166 end
167 else
168 begin
169 Pen.Color := (Control as TListBox).Font.Color;
170 Brush.Color := (Control as TListBox).Color;
171 if Assigned(OPMInterface) then
172 begin
173 PackageLink := FindPackageLink(TLazPackageID(DependPkgNameListBox.Items.Objects[Index]));
174 if PackageLink <> nil then
175 begin
176 if PackageLink.Origin = ploOnline then
177 Brush.Color := pnOnlinePkg.Color
178 else
179 Brush.Color := pnLocalPkg.Color
180 end;
181 end
182 end;
183 FillRect(ARect);
184 ItemText := (Control as TListBox).Items[Index];
185 InflateRect(ARect, -1, -1);
186 inc(ARect.Left,3);
187 DrawText(Handle, PChar(ItemText), Length(ItemText), ARect, DT_LEFT or DT_VCENTER or DT_SINGLELINE);
188 end;
189 end;
190
TAddPkgDependencyDialog.IsInstallButtonVisiblenull191 function TAddPkgDependencyDialog.IsInstallButtonVisible: Boolean;
192 var
193 I: Integer;
194 PackageLink: TPackageLink;
195 begin
196 Result := False;
197 if (OPMInterface = nil) or (fSL = nil) or (fSL.Count = 0) then
198 Exit;
199 for I := 0 to DependPkgNameListBox.Count - 1 do
200 begin
201 if DependPkgNameListBox.Selected[I] then
202 begin
203 PackageLink := FindPackageLink(TLazPackageID(DependPkgNameListBox.Items.Objects[I]));
204 if (PackageLink <> nil) and (PackageLink.Origin = ploOnline) then
205 begin
206 Result := True;
207 Break;
208 end;
209 end;
210 end;
211 end;
212
213 procedure TAddPkgDependencyDialog.DependPkgNameListBoxSelectionChange(
214 Sender: TObject; User: boolean);
215 begin
216 BP.CloseButton.Visible := IsInstallButtonVisible;
217 if BP.CloseButton.Visible then
218 BP.OKButton.Enabled := False
219 else
220 BP.OKButton.Enabled := True;
221 end;
222
223 procedure TAddPkgDependencyDialog.cbLocalPkgChange(Sender: TObject);
224 begin
225 UpdateAvailableDependencyNames;
226 end;
227
InstallOnlinePackagesnull228 function TAddPkgDependencyDialog.InstallOnlinePackages(out ANeedToRebuild: Boolean): TModalResult;
229 var
230 I: Integer;
231 PackageLink: TPackageLink;
232 PkgList: TList;
233 begin
234 ANeedToRebuild := False;
235 Result := mrOk;
236 PkgList := TList.Create;
237 try
238 for I := 0 to DependPkgNameListBox.Count - 1 do
239 begin
240 if DependPkgNameListBox.Selected[I] then
241 begin
242 PackageLink := FindPackageLink(TLazPackageID(DependPkgNameListBox.Items.Objects[I]));
243 if (PackageLink <> nil) and (PackageLink.Origin = ploOnline) then
244 PkgList.Add(PackageLink);
245 end;
246 end;
247 if PkgList.Count > 0 then
248 Result := OPMInterface.InstallPackages(PkgList, ANeedToRebuild);
249 finally
250 PkgList.Free;
251 PkgList := nil;
252 end;
253 end;
254
255 procedure TAddPkgDependencyDialog.CloseButtonClick(Sender: TObject);
256 var
257 NeedToRebuild: Boolean;
258 begin
259 ModalResult := mrNone;
260 if InstallOnlinePackages(NeedToRebuild) = mrOK then
261 begin
262 UpdateAvailableDependencyNames;
263 if NeedToRebuild then
264 begin
265 Self.Hide;
266 MainIDEInterface.DoBuildLazarus([]);
267 end;
268 end;
269 end;
270
271 procedure TAddPkgDependencyDialog.AddUniquePackagesToList(APackageID: TLazPackageID);
272 begin
273 if (APackageID.IDAsString<>fProjPack.IDAsString) and (fPackages.Find(APackageID)=Nil) then
274 fPackages.Add(APackageID);
275 end;
276
277 procedure TAddPkgDependencyDialog.UpdateAvailableDependencyNames;
278 var
279 ANode: TAVLTreeNode;
280 CntLocalPkg: Integer;
281 CntOnlinePkg: Integer;
282 begin
283 if fUpdating then
284 Exit;
285
286 fUpdating := True;
287 try
288 CntLocalPkg := 0;
289 CntOnlinePkg := 0;
290 DependPkgNameListBox.Clear;
291 fSL.Clear;
292 fPackages.Clear;
293 PackageGraph.IteratePackages(fpfSearchAllExisting,@AddUniquePackagesToList);
294 ANode:=fPackages.FindLowest;
295 while ANode<>nil do begin
296 if (TPackageLink(ANode.Data).Origin = ploOnline) and (cbOnlinePkg.Checked) and Assigned(OPMInterface) then
297 begin
298 Inc(CntOnlinePkg);
299 fSL.AddObject(TLazPackageID(ANode.Data).Name, TLazPackageID(ANode.Data));
300 end;
301 if (TPackageLink(ANode.Data).Origin <> ploOnline) and (cbLocalPkg.Checked) then
302 begin
303 Inc(CntLocalPkg);
304 fSL.AddObject(TLazPackageID(ANode.Data).Name, TLazPackageID(ANode.Data));
305 end;
306 ANode:=fPackages.FindSuccessor(ANode);
307 end;
308 DependPkgNameFilter.Items.BeginUpdate;
309 try
310 DependPkgNameFilter.Items.Clear;
311 DependPkgNameFilter.Items.Assign(fSL);
312 DependPkgNameFilter.InvalidateFilter;
313 finally
314 DependPkgNameFilter.Items.EndUpdate;
315 end;
316 if Assigned(OPMInterface) then
317 begin
318 cbLocalPkg.Caption := Format(lisProjAddLocalPkg, [IntToStr(CntLocalPkg)]);
319 cbOnlinePkg.Caption := Format(lisProjAddOnlinePkg, [IntToStr(CntOnlinePkg)]);
320 BP.CloseButton.Visible := IsInstallButtonVisible;
321 end;
322 finally
323 fUpdating := False;
324 end;
325 end;
326
327 procedure TAddPkgDependencyDialog.OKButtonClick(Sender: TObject);
328 var
329 NewDependency: TPkgDependency;
330 MinVerTest, MaxVerTest: TPkgVersion;
331 MinMaxVerFlags: TPkgDependencyFlags;
332 i: Integer;
333 begin
334 MinVerTest := Nil;
335 MaxVerTest := Nil;
336 MinMaxVerFlags := [];
337 try
338 // check minimum version
339 if DependMinVersionEdit.Text <> '' then
340 begin
341 MinVerTest := TPkgVersion.Create;
342 if not MinVerTest.ReadString(DependMinVersionEdit.Text) then
343 begin
344 IDEMessageDialog(lisProjAddInvalidVersion,
345 Format(lisProjAddTheMinimumVersionIsInvalid,
346 [DependMinVersionEdit.Text, LineEnding, LineEnding]),
347 mtError,[mbCancel]);
348 exit;
349 end;
350 MinMaxVerFlags := [pdfMinVersion];
351 end;
352 // check maximum version
353 if DependMaxVersionEdit.Text <> '' then
354 begin
355 MaxVerTest := TPkgVersion.Create;
356 if not MaxVerTest.ReadString(DependMaxVersionEdit.Text) then
357 begin
358 IDEMessageDialog(lisProjAddInvalidVersion,
359 Format(lisProjAddTheMaximumVersionIsInvalid,
360 [DependMaxVersionEdit.Text, LineEnding, LineEnding]),
361 mtError,[mbCancel]);
362 exit;
363 end;
364 MinMaxVerFlags := MinMaxVerFlags + [pdfMaxVersion];
365 end;
366
367 // Add all selected packages.
368 fResultDependencies := TPkgDependencyList.Create; // Will be freed by the caller.
369 if DependPkgNameListBox.SelCount > 0 then
370 begin
371 for i := 0 to DependPkgNameListBox.Count-1 do
372 begin
373 if DependPkgNameListBox.Selected[i] then
374 begin
375 NewDependency := TPkgDependency.Create; // Will be added to package graph.
376 NewDependency.PackageName := DependPkgNameListBox.Items[i];
377 if Assigned(MinVerTest) then
378 NewDependency.MinVersion.Assign(MinVerTest);
379 if Assigned(MaxVerTest) then
380 NewDependency.MaxVersion.Assign(MaxVerTest);
381 NewDependency.Flags := NewDependency.Flags + MinMaxVerFlags;
382 if not CheckAddingDependency(fProjPack, NewDependency) then exit;
383 fResultDependencies.Add(NewDependency);
384 NewDependency := nil;
385 end;
386 end;
387 end;
388 ModalResult := mrOk;
389 finally
390 MinVerTest.Free;
391 MaxVerTest.Free;
392 end;
393 end;
394
395 end.
396
397