mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-21 11:02:40 +02:00
745 lines
20 KiB
ObjectPascal
745 lines
20 KiB
ObjectPascal
unit CodyUnitDepWnd;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, types, AVL_Tree, contnrs, FileUtil, lazutf8classes,
|
|
LazLogger, TreeFilterEdit, CTUnitGraph, CodeToolManager, DefineTemplates,
|
|
Forms, Controls, Graphics, Dialogs, ExtCtrls, Buttons, ComCtrls,
|
|
LCLType, LazIDEIntf, ProjectIntf, IDEWindowIntf;
|
|
|
|
resourcestring
|
|
a='';
|
|
rsSelectAUnit = 'Select a unit';
|
|
rsClose = 'Close';
|
|
|
|
const
|
|
DefaultCategoryGap = 0.04;
|
|
DefaultFirstCategory = 0;
|
|
DefaultCategoryMinSize = 0.05;
|
|
type
|
|
TCustomCircleDiagramControl = class;
|
|
TCircleDiagramCategory = class;
|
|
|
|
{ TCircleDiagramItem }
|
|
|
|
TCircleDiagramItem = class(TPersistent)
|
|
private
|
|
FCaption: TCaption;
|
|
FCategory: TCircleDiagramCategory;
|
|
FSize: single;
|
|
procedure SetCaption(AValue: TCaption);
|
|
procedure SetSize(AValue: single);
|
|
procedure UpdateLayout;
|
|
public
|
|
constructor Create(TheCategory: TCircleDiagramCategory);
|
|
destructor Destroy; override;
|
|
property Category: TCircleDiagramCategory read FCategory;
|
|
property Caption: TCaption read FCaption write SetCaption;
|
|
property Size: single read FSize write SetSize;
|
|
end;
|
|
|
|
{ TCircleDiagramCategory }
|
|
|
|
TCircleDiagramCategory = class(TPersistent)
|
|
private
|
|
FCaption: TCaption;
|
|
FColor: TColor;
|
|
FDiagram: TCustomCircleDiagramControl;
|
|
FMinSize: single;
|
|
fItems: TObjectList; // list of TCircleDiagramItem
|
|
function GetItems(Index: integer): TCircleDiagramItem;
|
|
procedure SetCaption(AValue: TCaption);
|
|
procedure SetColor(AValue: TColor);
|
|
procedure SetMinSize(AValue: single);
|
|
procedure UpdateLayout;
|
|
procedure Invalidate;
|
|
procedure InternalRemoveItem(Item: TCircleDiagramItem);
|
|
public
|
|
constructor Create(TheDiagram: TCustomCircleDiagramControl);
|
|
destructor Destroy; override;
|
|
function InsertItem(Index: integer; aCaption: string): TCircleDiagramItem;
|
|
function AddItem(aCaption: string): TCircleDiagramItem;
|
|
property Diagram: TCustomCircleDiagramControl read FDiagram;
|
|
property Caption: TCaption read FCaption write SetCaption;
|
|
property MinSize: single read FMinSize write SetMinSize default DefaultCategoryMinSize;
|
|
function Count: integer;
|
|
property Items[Index: integer]: TCircleDiagramItem read GetItems;
|
|
property Color: TColor read FColor write SetColor;
|
|
end;
|
|
|
|
TCircleDiagramCtrlFlag = (
|
|
cdcNeedUpdateLayout
|
|
);
|
|
TCircleDiagramCtrlFlags = set of TCircleDiagramCtrlFlag;
|
|
|
|
{ TCustomCircleDiagramControl }
|
|
|
|
TCustomCircleDiagramControl = class(TCustomControl)
|
|
private
|
|
FCategoryGap: single;
|
|
FCenterCaption: TCaption;
|
|
FCenterCaptionRect: TRect;
|
|
FFirstCategory: single;
|
|
fCategories: TObjectList; // list of TCircleDiagramCategory
|
|
fUpdateLock: integer;
|
|
fFlags: TCircleDiagramCtrlFlags;
|
|
function GetCategories(Index: integer): TCircleDiagramCategory;
|
|
procedure SetCategoryGap(AValue: single);
|
|
procedure SetCenterCaption(AValue: TCaption);
|
|
procedure SetFirstCategory(AValue: single);
|
|
procedure InternalRemoveCategory(Category: TCircleDiagramCategory);
|
|
protected
|
|
//procedure WMVScroll(var Msg: TLMScroll); message LM_VSCROLL;
|
|
//procedure WMMouseWheel(var Message: TLMMouseEvent); message LM_MOUSEWHEEL;
|
|
procedure CreateWnd; override;
|
|
procedure UpdateScrollBar;
|
|
procedure DoSetBounds(ALeft, ATop, AWidth, AHeight: integer); override;
|
|
|
|
//procedure MouseDown(Button:TMouseButton; Shift:TShiftState; X,Y:integer); override;
|
|
//procedure MouseMove(Shift:TShiftState; X,Y:integer); override;
|
|
//procedure MouseUp(Button:TMouseButton; Shift:TShiftState; X,Y:integer); override;
|
|
|
|
//procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
//procedure HandleStandardKeys(var Key: Word; Shift: TShiftState); virtual;
|
|
//procedure HandleKeyUp(var Key: Word; Shift: TShiftState); virtual;
|
|
|
|
procedure Paint; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
property CenterCaption: TCaption read FCenterCaption write SetCenterCaption;
|
|
procedure Clear;
|
|
procedure BeginUpdate; virtual;
|
|
procedure EndUpdate; virtual;
|
|
procedure UpdateLayout;
|
|
procedure EraseBackground({%H-}DC: HDC); override;
|
|
function InsertCategory(Index: integer; aCaption: TCaption): TCircleDiagramCategory;
|
|
function AddCategory(aCaption: TCaption): TCircleDiagramCategory;
|
|
function IndexOfCategory(aCaption: TCaption): integer;
|
|
function FindCategory(aCaption: TCaption): TCircleDiagramCategory;
|
|
property CategoryGap: single read FCategoryGap write SetCategoryGap default DefaultCategoryGap; // in part of a full circle
|
|
property FirstCategory: single read FFirstCategory write SetFirstCategory default DefaultFirstCategory; // in part of a full circle starting at top
|
|
function CategoryCount: integer;
|
|
property Categories[Index: integer]: TCircleDiagramCategory read GetCategories;
|
|
property Color default clWhite;
|
|
property CenterCaptionRect: TRect read FCenterCaptionRect;
|
|
end;
|
|
|
|
{ TCircleDiagramControl }
|
|
|
|
TCircleDiagramControl = class(TCustomCircleDiagramControl)
|
|
published
|
|
property Align;
|
|
property Anchors;
|
|
property BorderSpacing;
|
|
property BorderStyle;
|
|
property BorderWidth;
|
|
property Color;
|
|
property Constraints;
|
|
property DragKind;
|
|
property DragCursor;
|
|
property DragMode;
|
|
property Enabled;
|
|
property Font;
|
|
property ParentColor default False;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property ShowHint;
|
|
property TabOrder;
|
|
property TabStop default True;
|
|
property Tag;
|
|
property Visible;
|
|
property OnClick;
|
|
property OnContextPopup;
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnShowHint;
|
|
property OnStartDrag;
|
|
property OnUTF8KeyPress;
|
|
end;
|
|
|
|
TUDDUsesType = (
|
|
uddutInterfaceUses,
|
|
uddutImplementationUses,
|
|
uddutUsedByInterface,
|
|
uddutUsedByImplementation
|
|
);
|
|
TUDDUsesTypes = set of TUDDUsesType;
|
|
|
|
{ TUnitDependenciesDialog }
|
|
|
|
TUnitDependenciesDialog = class(TForm)
|
|
BtnPanel: TPanel;
|
|
CloseBitBtn: TBitBtn;
|
|
CurUnitPanel: TPanel;
|
|
CurUnitSplitter: TSplitter;
|
|
CurUnitTreeView: TTreeView;
|
|
ProgressBar1: TProgressBar;
|
|
Timer1: TTimer;
|
|
CurUnitTreeFilterEdit: TTreeFilterEdit;
|
|
procedure CloseBitBtnClick(Sender: TObject);
|
|
procedure CurUnitTreeViewSelectionChanged(Sender: TObject);
|
|
procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean);
|
|
procedure Timer1Timer(Sender: TObject);
|
|
private
|
|
FCurrentUnit: TUGUnit;
|
|
FIdleConnected: boolean;
|
|
FUsesGraph: TUsesGraph;
|
|
fCircleCategories: array[TUDDUsesType] of TCircleDiagramCategory;
|
|
procedure SetCurrentUnit(AValue: TUGUnit);
|
|
procedure SetIdleConnected(AValue: boolean);
|
|
procedure AddStartAndTargetUnits;
|
|
procedure UpdateAll;
|
|
procedure UpdateCurUnitDiagram;
|
|
procedure UpdateCurUnitTreeView;
|
|
function NodeTextToUnit(NodeText: string): TUGUnit;
|
|
function UGUnitToNodeText(UGUnit: TUGUnit): string;
|
|
public
|
|
CurUnitDiagram: TCircleDiagramControl;
|
|
property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
|
|
property UsesGraph: TUsesGraph read FUsesGraph;
|
|
property CurrentUnit: TUGUnit read FCurrentUnit write SetCurrentUnit;
|
|
end;
|
|
|
|
var
|
|
UnitDependenciesDialog: TUnitDependenciesDialog;
|
|
|
|
procedure ShowUnitDependenciesDialog(Sender: TObject);
|
|
|
|
implementation
|
|
|
|
procedure ShowUnitDependenciesDialog(Sender: TObject);
|
|
var
|
|
Dlg: TUnitDependenciesDialog;
|
|
begin
|
|
Dlg:=TUnitDependenciesDialog.Create(nil);
|
|
try
|
|
Dlg.ShowModal;
|
|
finally
|
|
Dlg.Free;
|
|
end;
|
|
end;
|
|
|
|
{ TCustomCircleDiagramControl }
|
|
|
|
procedure TCustomCircleDiagramControl.SetCategoryGap(AValue: single);
|
|
begin
|
|
if AValue<0 then AValue:=0;
|
|
if AValue>0.3 then AValue:=0.3;
|
|
if FCategoryGap=AValue then Exit;
|
|
FCategoryGap:=AValue;
|
|
UpdateLayout;
|
|
end;
|
|
|
|
function TCustomCircleDiagramControl.GetCategories(Index: integer
|
|
): TCircleDiagramCategory;
|
|
begin
|
|
Result:=TCircleDiagramCategory(fCategories[Index]);
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.SetCenterCaption(AValue: TCaption);
|
|
begin
|
|
if FCenterCaption=AValue then Exit;
|
|
FCenterCaption:=AValue;
|
|
UpdateLayout;
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.SetFirstCategory(AValue: single);
|
|
begin
|
|
if FFirstCategory=AValue then Exit;
|
|
FFirstCategory:=AValue;
|
|
UpdateLayout;
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.InternalRemoveCategory(
|
|
Category: TCircleDiagramCategory);
|
|
begin
|
|
fCategories.Remove(Category);
|
|
UpdateLayout;
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.CreateWnd;
|
|
begin
|
|
inherited CreateWnd;
|
|
UpdateScrollBar;
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.UpdateScrollBar;
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.DoSetBounds(ALeft, ATop, AWidth,
|
|
AHeight: integer);
|
|
begin
|
|
inherited DoSetBounds(ALeft, ATop, AWidth, AHeight);
|
|
UpdateScrollBar;
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.Paint;
|
|
begin
|
|
inherited Paint;
|
|
if cdcNeedUpdateLayout in fFlags then
|
|
UpdateLayout;
|
|
|
|
// background
|
|
Canvas.Brush.Style:=bsSolid;
|
|
Canvas.Brush.Color:=Color;
|
|
Canvas.FillRect(ClientRect);
|
|
|
|
// center caption
|
|
Canvas.TextOut(FCenterCaptionRect.Left,FCenterCaptionRect.Top,CenterCaption);
|
|
end;
|
|
|
|
constructor TCustomCircleDiagramControl.Create(AOwner: TComponent);
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
inherited Create(AOwner);
|
|
fCategories:=TObjectList.create(true);
|
|
Color:=clWhite;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
destructor TCustomCircleDiagramControl.Destroy;
|
|
begin
|
|
BeginUpdate; // disable updates
|
|
FreeAndNil(fCategories);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.Clear;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
while CategoryCount>0 do
|
|
Categories[0].Free;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.BeginUpdate;
|
|
begin
|
|
inc(fUpdateLock);
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.EndUpdate;
|
|
begin
|
|
if fUpdateLock=0 then
|
|
raise Exception.Create('TCustomCircleDiagramControl.EndUpdate');
|
|
dec(fUpdateLock);
|
|
if fUpdateLock=0 then begin
|
|
if cdcNeedUpdateLayout in fFlags then
|
|
UpdateLayout;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.UpdateLayout;
|
|
var
|
|
aSize: TSize;
|
|
begin
|
|
if (fUpdateLock>0) or (not IsVisible) or (not HandleAllocated) then begin
|
|
Include(fFlags,cdcNeedUpdateLayout);
|
|
exit;
|
|
end;
|
|
Exclude(fFlags,cdcNeedUpdateLayout);
|
|
|
|
// center caption
|
|
aSize:=Canvas.TextExtent(CenterCaption);
|
|
FCenterCaptionRect:=Bounds((ClientWidth-aSize.cx) div 2,
|
|
(ClientHeight-aSize.cy) div 2,aSize.cx,aSize.cy);
|
|
end;
|
|
|
|
procedure TCustomCircleDiagramControl.EraseBackground(DC: HDC);
|
|
begin
|
|
// do not erase background, Paint will paint the whole area
|
|
end;
|
|
|
|
function TCustomCircleDiagramControl.InsertCategory(Index: integer;
|
|
aCaption: TCaption): TCircleDiagramCategory;
|
|
begin
|
|
Result:=TCircleDiagramCategory.Create(Self);
|
|
Result.Caption:=aCaption;
|
|
fCategories.Insert(Index,Result);
|
|
end;
|
|
|
|
function TCustomCircleDiagramControl.AddCategory(aCaption: TCaption
|
|
): TCircleDiagramCategory;
|
|
begin
|
|
Result:=InsertCategory(CategoryCount,aCaption);
|
|
end;
|
|
|
|
function TCustomCircleDiagramControl.IndexOfCategory(aCaption: TCaption
|
|
): integer;
|
|
begin
|
|
Result:=CategoryCount-1;
|
|
while Result>=0 do begin
|
|
if Categories[Result].Caption=aCaption then exit;
|
|
dec(Result);
|
|
end;
|
|
end;
|
|
|
|
function TCustomCircleDiagramControl.FindCategory(aCaption: TCaption
|
|
): TCircleDiagramCategory;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i:=IndexOfCategory(aCaption);
|
|
if i>=0 then
|
|
Result:=Categories[i]
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
function TCustomCircleDiagramControl.CategoryCount: integer;
|
|
begin
|
|
Result:=fCategories.Count;
|
|
end;
|
|
|
|
{ TCircleDiagramCategory }
|
|
|
|
procedure TCircleDiagramCategory.SetCaption(AValue: TCaption);
|
|
begin
|
|
if FCaption=AValue then Exit;
|
|
FCaption:=AValue;
|
|
end;
|
|
|
|
procedure TCircleDiagramCategory.SetColor(AValue: TColor);
|
|
begin
|
|
if FColor=AValue then Exit;
|
|
FColor:=AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
function TCircleDiagramCategory.GetItems(Index: integer): TCircleDiagramItem;
|
|
begin
|
|
Result:=TCircleDiagramItem(fItems[Index]);
|
|
end;
|
|
|
|
procedure TCircleDiagramCategory.SetMinSize(AValue: single);
|
|
begin
|
|
if FMinSize=AValue then Exit;
|
|
FMinSize:=AValue;
|
|
end;
|
|
|
|
procedure TCircleDiagramCategory.UpdateLayout;
|
|
begin
|
|
if Diagram<>nil then
|
|
Diagram.UpdateLayout;
|
|
end;
|
|
|
|
procedure TCircleDiagramCategory.Invalidate;
|
|
begin
|
|
if Diagram<>nil then
|
|
Diagram.Invalidate;
|
|
end;
|
|
|
|
procedure TCircleDiagramCategory.InternalRemoveItem(Item: TCircleDiagramItem);
|
|
begin
|
|
fItems.Remove(Item);
|
|
UpdateLayout;
|
|
end;
|
|
|
|
constructor TCircleDiagramCategory.Create(
|
|
TheDiagram: TCustomCircleDiagramControl);
|
|
begin
|
|
FDiagram:=TheDiagram;
|
|
fItems:=TObjectList.Create(true);
|
|
end;
|
|
|
|
destructor TCircleDiagramCategory.Destroy;
|
|
begin
|
|
if Diagram<>nil then
|
|
Diagram.InternalRemoveCategory(Self);
|
|
FreeAndNil(fItems);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TCircleDiagramCategory.InsertItem(Index: integer; aCaption: string
|
|
): TCircleDiagramItem;
|
|
begin
|
|
Result:=TCircleDiagramItem.Create(Self);
|
|
Result.Caption:=aCaption;
|
|
fItems.Insert(Index,Result);
|
|
end;
|
|
|
|
function TCircleDiagramCategory.AddItem(aCaption: string): TCircleDiagramItem;
|
|
begin
|
|
Result:=InsertItem(Count,aCaption);
|
|
end;
|
|
|
|
function TCircleDiagramCategory.Count: integer;
|
|
begin
|
|
Result:=fItems.Count;
|
|
end;
|
|
|
|
{ TCircleDiagramItem }
|
|
|
|
procedure TCircleDiagramItem.SetCaption(AValue: TCaption);
|
|
begin
|
|
if FCaption=AValue then Exit;
|
|
FCaption:=AValue;
|
|
UpdateLayout;
|
|
end;
|
|
|
|
procedure TCircleDiagramItem.SetSize(AValue: single);
|
|
begin
|
|
if FSize=AValue then Exit;
|
|
FSize:=AValue;
|
|
UpdateLayout;
|
|
end;
|
|
|
|
procedure TCircleDiagramItem.UpdateLayout;
|
|
begin
|
|
if Category<>nil then
|
|
Category.UpdateLayout;
|
|
end;
|
|
|
|
constructor TCircleDiagramItem.Create(TheCategory: TCircleDiagramCategory);
|
|
begin
|
|
FCategory:=TheCategory;
|
|
end;
|
|
|
|
destructor TCircleDiagramItem.Destroy;
|
|
begin
|
|
if Category<>nil then
|
|
Category.InternalRemoveItem(Self);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ TUnitDependenciesDialog }
|
|
|
|
procedure TUnitDependenciesDialog.CloseBitBtnClick(Sender: TObject);
|
|
begin
|
|
ModalResult:=mrCancel;
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.CurUnitTreeViewSelectionChanged(
|
|
Sender: TObject);
|
|
var
|
|
CurUnit: TUGUnit;
|
|
begin
|
|
if CurUnitTreeView.Selected=nil then exit;
|
|
CurUnit:=NodeTextToUnit(CurUnitTreeView.Selected.Text);
|
|
if CurUnit=nil then exit;
|
|
CurrentUnit:=CurUnit;
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.FormClose(Sender: TObject;
|
|
var CloseAction: TCloseAction);
|
|
begin
|
|
IDEDialogLayoutList.SaveLayout(Self);
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.FormCreate(Sender: TObject);
|
|
begin
|
|
FUsesGraph:=CodeToolBoss.CreateUsesGraph;
|
|
ProgressBar1.Style:=pbstMarquee;
|
|
AddStartAndTargetUnits;
|
|
|
|
Caption:='Unit Dependencies';
|
|
CloseBitBtn.Caption:=rsClose;
|
|
|
|
IDEDialogLayoutList.ApplyLayout(Self,600,400);
|
|
|
|
CurUnitDiagram:=TCircleDiagramControl.Create(Self);
|
|
with CurUnitDiagram do begin
|
|
Name:='CurUnitDiagram';
|
|
Align:=alClient;
|
|
fCircleCategories[uddutInterfaceUses]:=AddCategory('Interface uses');
|
|
fCircleCategories[uddutImplementationUses]:=AddCategory('Implementation uses');
|
|
fCircleCategories[uddutUsedByInterface]:=AddCategory('Used by interfaces');
|
|
fCircleCategories[uddutUsedByImplementation]:=AddCategory('Used by implementations');
|
|
CenterCaption:=rsSelectAUnit;
|
|
Parent:=Self;
|
|
end;
|
|
|
|
IdleConnected:=true;
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.FormDestroy(Sender: TObject);
|
|
begin
|
|
IdleConnected:=false;
|
|
FreeAndNil(FUsesGraph);
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.OnIdle(Sender: TObject; var Done: Boolean);
|
|
var
|
|
Completed: boolean;
|
|
begin
|
|
UsesGraph.Parse(true,Completed,200);
|
|
if Completed then begin
|
|
IdleConnected:=false;
|
|
ProgressBar1.Visible:=false;
|
|
ProgressBar1.Style:=pbstNormal;
|
|
Timer1.Enabled:=false;
|
|
UpdateAll;
|
|
end;
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.Timer1Timer(Sender: TObject);
|
|
begin
|
|
UpdateAll;
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.SetIdleConnected(AValue: boolean);
|
|
begin
|
|
if FIdleConnected=AValue then Exit;
|
|
FIdleConnected:=AValue;
|
|
if IdleConnected then
|
|
Application.AddOnIdleHandler(@OnIdle)
|
|
else
|
|
Application.RemoveOnIdleHandler(@OnIdle);
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.SetCurrentUnit(AValue: TUGUnit);
|
|
begin
|
|
if FCurrentUnit=AValue then Exit;
|
|
FCurrentUnit:=AValue;
|
|
UpdateCurUnitDiagram;
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.AddStartAndTargetUnits;
|
|
var
|
|
aProject: TLazProject;
|
|
begin
|
|
UsesGraph.TargetAll:=true;
|
|
|
|
// project lpr
|
|
aProject:=LazarusIDE.ActiveProject;
|
|
if (aProject<>nil) and (aProject.MainFile<>nil) then
|
|
UsesGraph.AddStartUnit(aProject.MainFile.Filename);
|
|
|
|
// ToDo: add all open packages
|
|
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.UpdateAll;
|
|
begin
|
|
UpdateCurUnitTreeView;
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.UpdateCurUnitDiagram;
|
|
|
|
procedure UpdateCircleCategory(List: TFPList; t: TUDDUsesType);
|
|
// List is CurrentUnit.UsesUnits or CurrentUnit.UsedByUnits
|
|
var
|
|
i: Integer;
|
|
CurUses: TUGUses;
|
|
Item: TCircleDiagramItem;
|
|
CurUnit: TUGUnit;
|
|
Cnt: Integer;
|
|
s: String;
|
|
begin
|
|
Cnt:=0;
|
|
for i:=0 to List.Count-1 do begin
|
|
CurUses:=TUGUses(List[i]);
|
|
if CurUses.InImplementation<>(t in [uddutImplementationUses,uddutUsedByImplementation])
|
|
then continue;
|
|
if t in [uddutInterfaceUses,uddutImplementationUses] then
|
|
CurUnit:=CurUses.Owner
|
|
else
|
|
CurUnit:=CurUses.UsesUnit;
|
|
s:=ExtractFileName(CurUnit.Filename);
|
|
if fCircleCategories[t].Count>Cnt then begin
|
|
Item:=fCircleCategories[t].Items[Cnt];
|
|
Item.Caption:=s
|
|
end else
|
|
Item:=fCircleCategories[t].AddItem(s);
|
|
inc(Cnt);
|
|
end;
|
|
while fCircleCategories[t].Count>Cnt do
|
|
fCircleCategories[t].Items[Cnt].Free;
|
|
end;
|
|
|
|
begin
|
|
CurUnitDiagram.BeginUpdate;
|
|
try
|
|
if CurrentUnit<>nil then begin
|
|
CurUnitDiagram.CenterCaption:=ExtractFilename(CurrentUnit.Filename);
|
|
UpdateCircleCategory(CurrentUnit.UsesUnits,uddutInterfaceUses);
|
|
UpdateCircleCategory(CurrentUnit.UsesUnits,uddutImplementationUses);
|
|
UpdateCircleCategory(CurrentUnit.UsedByUnits,uddutUsedByInterface);
|
|
UpdateCircleCategory(CurrentUnit.UsedByUnits,uddutUsedByImplementation);
|
|
end else begin
|
|
CurUnitDiagram.CenterCaption:=rsSelectAUnit;
|
|
end;
|
|
finally
|
|
CurUnitDiagram.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TUnitDependenciesDialog.UpdateCurUnitTreeView;
|
|
var
|
|
AVLNode: TAVLTreeNode;
|
|
CurUnit: TUGUnit;
|
|
sl: TStringListUTF8;
|
|
i: Integer;
|
|
begin
|
|
CurUnitTreeView.BeginUpdate;
|
|
sl:=TStringListUTF8.Create;
|
|
try
|
|
CurUnitTreeView.Items.Clear;
|
|
|
|
AVLNode:=UsesGraph.FilesTree.FindLowest;
|
|
while AVLNode<>nil do begin
|
|
CurUnit:=TUGUnit(AVLNode.Data);
|
|
sl.Add(UGUnitToNodeText(CurUnit));
|
|
AVLNode:=UsesGraph.FilesTree.FindSuccessor(AVLNode);
|
|
end;
|
|
|
|
sl.CustomSort(@CompareStringListItemsUTF8LowerCase);
|
|
for i:=0 to sl.Count-1 do begin
|
|
CurUnitTreeView.Items.Add(nil,sl[i]);
|
|
end;
|
|
finally
|
|
sl.Free;
|
|
CurUnitTreeView.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TUnitDependenciesDialog.NodeTextToUnit(NodeText: string): TUGUnit;
|
|
var
|
|
AVLNode: TAVLTreeNode;
|
|
begin
|
|
AVLNode:=UsesGraph.FilesTree.FindLowest;
|
|
while AVLNode<>nil do begin
|
|
Result:=TUGUnit(AVLNode.Data);
|
|
if NodeText=UGUnitToNodeText(Result) then exit;
|
|
AVLNode:=UsesGraph.FilesTree.FindSuccessor(AVLNode);
|
|
end;
|
|
Result:=nil;
|
|
end;
|
|
|
|
function TUnitDependenciesDialog.UGUnitToNodeText(UGUnit: TUGUnit): string;
|
|
begin
|
|
Result:=ExtractFileName(UGUnit.Filename);
|
|
end;
|
|
|
|
{$R *.lfm}
|
|
|
|
end.
|
|
|