Unit-Dependencies, PkgGraphExplorer: Add option dialog to modify graph style

git-svn-id: trunk@60892 -
This commit is contained in:
martin 2019-04-07 19:57:35 +00:00
parent ba5ac8f30d
commit 180da00d4a
8 changed files with 1152 additions and 3 deletions

2
.gitattributes vendored
View File

@ -7162,6 +7162,8 @@ ide/customformeditor.pp svneol=native#text/pascal
ide/debugmanager.pas svneol=native#text/pascal
ide/definesgui.lfm svneol=native#text/plain
ide/definesgui.pas svneol=native#text/pascal
ide/dependencygraphoptions.lfm svneol=native#text/plain
ide/dependencygraphoptions.pas -text svneol=native#text/pascal
ide/desktopmanager.lfm svneol=native#text/plain
ide/desktopmanager.pas svneol=native#text/pascal
ide/dialogprocs.pas svneol=native#text/pascal

View File

@ -0,0 +1,508 @@
object DependencyGraphOptDialog: TDependencyGraphOptDialog
Left = 459
Height = 313
Top = 135
Width = 352
AutoSize = True
Caption = 'DependencyGraphOptDialog'
ClientHeight = 313
ClientWidth = 352
Constraints.MinHeight = 100
Constraints.MinWidth = 120
OnCreate = FormCreate
LCLVersion = '2.1.0.0'
object ButtonPanel1: TButtonPanel
Left = 6
Height = 34
Top = 273
Width = 340
OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True
OKButton.OnClick = OKButtonClick
HelpButton.Name = 'HelpButton'
HelpButton.DefaultCaption = True
CloseButton.Name = 'ApplyButton'
CloseButton.Caption = '&Apply'
CloseButton.DefaultCaption = False
CloseButton.OnClick = ApplyButtonClick
CancelButton.Name = 'CancelButton'
CancelButton.DefaultCaption = True
CancelButton.OnClick = CancelButtonClick
ButtonOrder = boCloseOKCancel
TabOrder = 0
ShowButtons = [pbOK, pbCancel]
ShowGlyphs = [pbOK, pbCancel]
end
object ScrollBox1: TScrollBox
Left = 0
Height = 267
Top = 0
Width = 352
HorzScrollBar.Page = 331
VertScrollBar.Page = 246
Align = alClient
ClientHeight = 246
ClientWidth = 331
TabOrder = 1
object OptionsGroup: TGroupBox
Left = 0
Height = 179
Top = 0
Width = 338
Align = alTop
AutoSize = True
BorderSpacing.Bottom = 5
BorderSpacing.InnerBorder = 3
Caption = 'OptionsGroup'
ChildSizing.HorizontalSpacing = 8
ChildSizing.VerticalSpacing = 5
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 2
ClientHeight = 159
ClientWidth = 334
TabOrder = 0
object chkMinimizeEdges: TCheckBox
Left = 0
Height = 19
Top = 0
Width = 160
Caption = 'chkMinimizeEdges'
TabOrder = 0
end
object chkReduceBackEdges: TCheckBox
Left = 168
Height = 19
Top = 0
Width = 160
Caption = 'chkReduceBackEdges'
TabOrder = 8
end
object chkHighEdges: TCheckBox
Left = 0
Height = 19
Top = 24
Width = 160
Caption = 'chkHighEdges'
TabOrder = 1
end
object chkStraigtenGraph: TCheckBox
Left = 168
Height = 19
Top = 24
Width = 160
Caption = 'chkStraigtenGraph'
TabOrder = 5
end
object chkCaptionOnTop: TCheckBox
Left = 0
Height = 19
Top = 48
Width = 160
Caption = 'chkCaptionOnTop'
TabOrder = 6
end
object DummySpaceHolder: TLabel
Left = 168
Height = 19
Top = 48
Width = 160
ParentColor = False
end
object Panel7: TPanel
Left = 0
Height = 38
Top = 72
Width = 160
AutoSize = True
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 38
ClientWidth = 160
TabOrder = 2
object lblEdgeShape: TLabel
Left = 0
Height = 15
Top = 0
Width = 160
Caption = 'lblEdgeShape'
ParentColor = False
end
object dropEdgeShape: TComboBox
Left = 0
Height = 23
Top = 15
Width = 160
Constraints.MinWidth = 160
ItemHeight = 15
Style = csDropDownList
TabOrder = 0
end
end
object Panel8: TPanel
Left = 168
Height = 38
Top = 72
Width = 160
AutoSize = True
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 38
ClientWidth = 160
TabOrder = 3
object lblEdgeSplit: TLabel
Left = 0
Height = 15
Top = 0
Width = 160
Caption = 'lblEdgeSplit'
ParentColor = False
end
object dropEdgeSplit: TComboBox
Left = 0
Height = 23
Top = 15
Width = 160
Constraints.MinWidth = 160
ItemHeight = 15
Style = csDropDownList
TabOrder = 0
end
end
object Panel9: TPanel
Left = 0
Height = 38
Top = 115
Width = 160
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 38
ClientWidth = 160
TabOrder = 4
object lblMaxLevelHeight: TLabel
Left = 0
Height = 15
Top = 0
Width = 160
Caption = 'lblMaxLevelHeight'
ParentColor = False
end
object Panel10: TPanel
Left = 0
Height = 23
Top = 15
Width = 160
BevelOuter = bvNone
ChildSizing.HorizontalSpacing = 6
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 2
ClientHeight = 23
ClientWidth = 160
TabOrder = 0
object spinLvlLimitAbs: TSpinEdit
Left = 0
Height = 23
Top = 0
Width = 77
Constraints.MinWidth = 77
MaxValue = 9999
ParentShowHint = False
ShowHint = True
TabOrder = 0
end
object spinLvlLimitRel: TFloatSpinEdit
Left = 83
Height = 23
Top = 0
Width = 77
Constraints.MinWidth = 77
Increment = 0.1
MaxValue = 999
MinValue = 0
ParentShowHint = False
ShowHint = True
TabOrder = 1
Value = 0
end
end
end
object Panel11: TPanel
Left = 168
Height = 38
Top = 115
Width = 160
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 38
ClientWidth = 160
TabOrder = 7
object lblExtraSpacing: TLabel
Left = 0
Height = 15
Top = 0
Width = 160
Caption = 'lblExtraSpacing'
ParentColor = False
end
object Panel12: TPanel
Left = 0
Height = 23
Top = 15
Width = 160
BevelOuter = bvNone
ChildSizing.HorizontalSpacing = 6
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 2
ClientHeight = 23
ClientWidth = 160
TabOrder = 0
object spinHorizSpacing: TSpinEdit
Left = 0
Height = 23
Top = 0
Width = 77
Constraints.MinWidth = 77
MaxValue = 499
MinValue = -30
ParentShowHint = False
ShowHint = True
TabOrder = 1
end
object spinVertSpacing: TSpinEdit
Left = 83
Height = 23
Top = 0
Width = 77
Constraints.MinWidth = 77
MaxValue = 99
MinValue = -10
ParentShowHint = False
ShowHint = True
TabOrder = 0
end
end
end
end
object InfoGroup: TGroupBox
AnchorSideLeft.Control = ScrollBox1
AnchorSideTop.Control = OptionsGroup
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = ScrollBox1
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = ScrollBox1
Left = 0
Height = 91
Top = 184
Width = 338
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.InnerBorder = 3
Caption = 'InfoGroup'
ChildSizing.HorizontalSpacing = 8
ChildSizing.VerticalSpacing = 5
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 4
ClientHeight = 71
ClientWidth = 334
TabOrder = 1
Visible = False
object Panel1: TPanel
Left = 0
Height = 30
Top = 0
Width = 78
AutoSize = True
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 30
ClientWidth = 78
TabOrder = 0
object lblNodeCnt: TLabel
Left = 0
Height = 15
Top = 0
Width = 63
Caption = 'lblNodeCnt'
ParentColor = False
end
object valNodeCnt: TLabel
Left = 0
Height = 15
Top = 15
Width = 63
Caption = 'valNodeCnt'
Font.Color = clGrayText
ParentColor = False
ParentFont = False
end
end
object Panel2: TPanel
Left = 86
Height = 30
Top = 0
Width = 72
AutoSize = True
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 30
ClientWidth = 72
TabOrder = 1
object lblEdgeCount: TLabel
AnchorSideLeft.Side = asrBottom
Left = 0
Height = 15
Top = 0
Width = 72
Caption = 'lblEdgeCount'
ParentColor = False
end
object valEdgeCnt: TLabel
AnchorSideTop.Side = asrBottom
Left = 0
Height = 15
Top = 15
Width = 72
Caption = 'valEdgeCnt'
Font.Color = clGrayText
ParentColor = False
ParentFont = False
end
end
object Panel3: TPanel
Left = 166
Height = 30
Top = 0
Width = 60
AutoSize = True
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 30
ClientWidth = 60
TabOrder = 2
object lblEdgeLen: TLabel
AnchorSideLeft.Side = asrBottom
Left = 0
Height = 15
Top = 0
Width = 60
Caption = 'lblEdgeLen'
ParentColor = False
end
object valEdgeLen: TLabel
AnchorSideTop.Side = asrBottom
Left = 0
Height = 15
Top = 15
Width = 60
Caption = 'valEdgeLen'
Font.Color = clGrayText
ParentColor = False
ParentFont = False
end
end
object Panel4: TPanel
Left = 234
Height = 30
Top = 0
Width = 76
AutoSize = True
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 30
ClientWidth = 76
TabOrder = 3
object LblLevelCount: TLabel
AnchorSideLeft.Side = asrBottom
Left = 0
Height = 15
Top = 0
Width = 76
Caption = 'LblLevelCount'
ParentColor = False
end
object valLevelCnt: TLabel
AnchorSideTop.Side = asrBottom
Left = 0
Height = 15
Top = 15
Width = 76
Caption = 'valLevelCnt'
Font.Color = clGrayText
ParentColor = False
ParentFont = False
end
end
object Panel5: TPanel
Left = 0
Height = 30
Top = 35
Width = 78
AutoSize = True
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 30
ClientWidth = 78
TabOrder = 4
object LblCrossCount: TLabel
AnchorSideLeft.Side = asrBottom
Left = 0
Height = 15
Top = 0
Width = 78
Caption = 'LblCrossCount'
ParentColor = False
end
object valCrossCnt: TLabel
AnchorSideTop.Side = asrBottom
Left = 0
Height = 15
Top = 15
Width = 78
Caption = 'valCrossCnt'
Font.Color = clGrayText
ParentColor = False
ParentFont = False
end
end
object Panel6: TPanel
Left = 86
Height = 30
Top = 35
Width = 72
AutoSize = True
BevelOuter = bvNone
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 1
ClientHeight = 30
ClientWidth = 72
TabOrder = 5
object lblSplitCount: TLabel
Left = 0
Height = 15
Top = 0
Width = 69
Caption = 'lblSplitCount'
ParentColor = False
end
object valSplitCnt: TLabel
Left = 0
Height = 15
Top = 15
Width = 69
Caption = 'valSplitCnt'
Font.Color = clGrayText
ParentColor = False
ParentFont = False
end
end
end
end
end

View File

@ -0,0 +1,486 @@
unit DependencyGraphOptions;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ButtonPanel, StdCtrls,
ExtCtrls, Spin, LvlGraphCtrl, Laz_XMLCfg, math, LazarusIDEStrConsts,
EnvironmentOpts;
type
{ TLvlGraphOptions }
TLvlGraphOptions = class(TIDESubOptions)
private
FCaptionPos: TLvlGraphNodeCaptionPosition;
FEdgeShape: TLvlGraphEdgeShape;
FEdgeSplit: TLvlGraphEdgeSplitMode;
FExtraSpacingHoriz: integer;
FExtraSpacingVert: integer;
FHighLevels: Boolean;
FLimitLvlHeighAbs: integer;
FLimitLvlHeighRel: Single;
FMinimizeEdges: Boolean;
FOnLoaded: TNotifyEvent;
FReduceBackEdges: Boolean;
FStraightenGraph: Boolean;
public
constructor Create;
procedure ReadFromXml(AnXmlConf: TRttiXMLConfig; APath: String); override;
procedure WriteToXml(AnXmlConf: TRttiXMLConfig; APath: String); override;
procedure Assign(ASrc: TPersistent); override;
procedure WriteToGraph(AValue: TLvlGraphControl);
procedure ReadFromGraph(AValue: TLvlGraphControl);
published
property MinimizeEdges: Boolean read FMinimizeEdges write FMinimizeEdges;
property HighLevels: Boolean read FHighLevels write FHighLevels;
property ReduceBackEdges: Boolean read FReduceBackEdges write FReduceBackEdges;
property ExtraSpacingHoriz: integer read FExtraSpacingHoriz write FExtraSpacingHoriz;
property ExtraSpacingVert: integer read FExtraSpacingVert write FExtraSpacingVert;
property CaptionPos: TLvlGraphNodeCaptionPosition read FCaptionPos write FCaptionPos;
property EdgeShape: TLvlGraphEdgeShape read FEdgeShape write FEdgeShape;
property EdgeSplit: TLvlGraphEdgeSplitMode read FEdgeSplit write FEdgeSplit;
property StraightenGraph: Boolean read FStraightenGraph write FStraightenGraph;
property LimitLvlHeighAbs: integer read FLimitLvlHeighAbs write FLimitLvlHeighAbs;
property LimitLvlHeighRel: Single read FLimitLvlHeighRel write FLimitLvlHeighRel;
property OnLoaded: TNotifyEvent read FOnLoaded write FOnLoaded;
end;
TApplyOptionsProc = procedure(AnOpts: TLvlGraphOptions; AGraph: TLvlGraph) of object;
TLvlGraphEdgeSplitModes = set of TLvlGraphEdgeSplitMode;
{ TDependencyGraphOptDialog }
TDependencyGraphOptDialog = class(TForm)
ApplyButton: TPanelBitBtn;
ButtonPanel1: TButtonPanel;
chkReduceBackEdges: TCheckBox;
chkStraigtenGraph: TCheckBox;
chkMinimizeEdges: TCheckBox;
chkHighEdges: TCheckBox;
chkCaptionOnTop: TCheckBox;
dropEdgeShape: TComboBox;
dropEdgeSplit: TComboBox;
DummySpaceHolder: TLabel;
lblExtraSpacing: TLabel;
Panel11: TPanel;
Panel12: TPanel;
spinVertSpacing: TSpinEdit;
spinHorizSpacing: TSpinEdit;
spinLvlLimitRel: TFloatSpinEdit;
lblMaxLevelHeight: TLabel;
lblEdgeShape: TLabel;
lblEdgeSplit: TLabel;
lblSplitCount: TLabel;
Panel1: TPanel;
Panel10: TPanel;
Panel2: TPanel;
Panel3: TPanel;
Panel4: TPanel;
Panel5: TPanel;
Panel6: TPanel;
Panel7: TPanel;
Panel8: TPanel;
Panel9: TPanel;
spinLvlLimitAbs: TSpinEdit;
valSplitCnt: TLabel;
valLevelCnt: TLabel;
valCrossCnt: TLabel;
LblCrossCount: TLabel;
lblNodeCnt: TLabel;
valNodeCnt: TLabel;
lblEdgeCount: TLabel;
valEdgeCnt: TLabel;
lblEdgeLen: TLabel;
valEdgeLen: TLabel;
LblLevelCount: TLabel;
OptionsGroup: TGroupBox;
InfoGroup: TGroupBox;
ScrollBox1: TScrollBox;
procedure ApplyButtonClick(Sender: TObject);
procedure CancelButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure OKButtonClick(Sender: TObject);
private
FApplyCallback: TApplyOptionsProc;
FGraph: TLvlGraph;
FOptions: TLvlGraphOptions;
FShowInfo: Boolean;
FShowSplitModes: TLvlGraphEdgeSplitModes;
FEdgeSplitMap: array[0..ord(high(TLvlGraphEdgeSplitMode))] of TLvlGraphEdgeSplitMode;
FEdgeRevSplitMap: array[low(TLvlGraphEdgeSplitMode)..high(TLvlGraphEdgeSplitMode)] of integer;
procedure SetApplyCallback(AValue: TApplyOptionsProc);
procedure SetGraph(AValue: TLvlGraph);
procedure SetOptions(AValue: TLvlGraphOptions);
procedure SetShowInfo(AValue: Boolean);
procedure SetShowSplitModes(AValue: TLvlGraphEdgeSplitModes);
procedure PopulateEdgeSplit;
procedure PopulateEdgeShape;
procedure WriteToOpts;
procedure ReadFromOpts;
procedure UpdateInfo;
public
property Options: TLvlGraphOptions read FOptions write SetOptions;
property Graph: TLvlGraph read FGraph write SetGraph;
property ApplyCallback: TApplyOptionsProc read FApplyCallback write SetApplyCallback;
property ShowInfo: Boolean read FShowInfo write SetShowInfo;
property ShowSplitModes: TLvlGraphEdgeSplitModes read FShowSplitModes write SetShowSplitModes;
end;
function ShowDependencyGraphOptions(AnOpts: TLvlGraphOptions; AGraph: TLvlGraph; ACaption: String;
AnApplyCallback: TApplyOptionsProc = nil): TModalResult;
implementation
function ShowDependencyGraphOptions(AnOpts: TLvlGraphOptions; AGraph: TLvlGraph; ACaption: String;
AnApplyCallback: TApplyOptionsProc = nil): TModalResult;
var
Dlg: TDependencyGraphOptDialog;
begin
Dlg := TDependencyGraphOptDialog.Create(Application);
Dlg.Caption := ACaption;
Dlg.Graph := AGraph;
Dlg.Options := AnOpts;
Dlg.ApplyCallback := AnApplyCallback;
Result := Dlg.ShowModal;
Dlg.Free;
end;
{$R *.lfm}
{ TDependencyGraphOptDialog }
procedure TDependencyGraphOptDialog.CancelButtonClick(Sender: TObject);
begin
ModalResult := mrCancel;
end;
procedure TDependencyGraphOptDialog.FormCreate(Sender: TObject);
begin
FShowInfo := True;
FShowSplitModes := [lgesSeparate, lgesMergeSource, lgesMergeTarget, lgesMergeHighest];
chkMinimizeEdges.Caption := LvlGraphShapeMinimizeEdge;
chkHighEdges.Caption := LvlGraphShapeCalculateLay;
chkReduceBackEdges.Caption := LvlGraphReduceBackedges;
chkStraigtenGraph.Caption := LvlGraphStraightenGraph;
chkCaptionOnTop.Caption := LvlGraphNamesAboveNode;
lblEdgeSplit.Caption := LvlGraphShapeEdgesSplitMo;
lblEdgeShape.Caption := LvlGraphShapeEdgesShape;
dropEdgeSplit.Constraints.MinWidth := Max(dropEdgeSplit.Constraints.MinWidth,
lblEdgeSplit.Width);
dropEdgeShape.Constraints.MinWidth := Max(dropEdgeShape.Constraints.MinWidth,
lblEdgeShape.Width);
OptionsGroup.Caption := lisOptions;
InfoGroup.Caption := LvlGraphOptInfo;
lblNodeCnt.Caption := LvlGraphShapeNodes;
lblEdgeCount.Caption := LvlGraphOptEdges;
lblEdgeLen.Caption := LvlGraphOptEdgeLen;
LblLevelCount.Caption := LvlGraphOptLevels;
LblCrossCount.Caption := LvlGraphOptCrossings;
lblSplitCount.Caption := LvlGraphOptSplitpoints;
lblMaxLevelHeight.Caption := LvlGraphOptLimitHeightOfLvl;
lblExtraSpacing.Caption := LvlGraphExtraSpacing;
spinLvlLimitAbs.Hint := Format(LvlGraphOptAbsoluteLimi, [LineEnding]);
spinLvlLimitRel.Hint := Format(LvlGraphOptLimitRelativ, [LineEnding]);
spinHorizSpacing.Hint := Format(LvlGraphAddHorizontalSpacing, [LineEnding]);
spinVertSpacing.Hint := Format(LvlGraphAddVerticalSpacingAr, [LineEnding]);
PopulateEdgeSplit;
PopulateEdgeShape;
end;
procedure TDependencyGraphOptDialog.OKButtonClick(Sender: TObject);
begin
WriteToOpts;
ModalResult := mrOK;
end;
procedure TDependencyGraphOptDialog.ApplyButtonClick(Sender: TObject);
begin
if ApplyCallback <> nil then begin
WriteToOpts;
ApplyCallback(Options, Graph);
ModalResult := mrNone;
UpdateInfo;
end;
end;
procedure TDependencyGraphOptDialog.SetApplyCallback(AValue: TApplyOptionsProc);
begin
if FApplyCallback = AValue then Exit;
FApplyCallback := AValue;
if FApplyCallback <> nil then
ButtonPanel1.ShowButtons := ButtonPanel1.ShowButtons + [pbClose]
else
ButtonPanel1.ShowButtons := ButtonPanel1.ShowButtons - [pbClose];
end;
procedure TDependencyGraphOptDialog.SetGraph(AValue: TLvlGraph);
begin
if FGraph = AValue then Exit;
FGraph := AValue;
UpdateInfo;
end;
procedure TDependencyGraphOptDialog.SetOptions(AValue: TLvlGraphOptions);
begin
if FOptions = AValue then Exit;
FOptions := AValue;
ReadFromOpts;
end;
procedure TDependencyGraphOptDialog.SetShowInfo(AValue: Boolean);
begin
if FShowInfo = AValue then Exit;
FShowInfo := AValue;
UpdateInfo;
end;
procedure TDependencyGraphOptDialog.SetShowSplitModes(
AValue: TLvlGraphEdgeSplitModes);
begin
if FShowSplitModes = AValue then Exit;
FShowSplitModes := AValue;
PopulateEdgeSplit;
end;
procedure TDependencyGraphOptDialog.PopulateEdgeSplit;
var
i: TLvlGraphEdgeSplitMode;
j: Integer;
begin
dropEdgeSplit.Items.Clear;
j := 0;
for i := low(TLvlGraphEdgeSplitMode) to high(TLvlGraphEdgeSplitMode) do begin
if not (i in FShowSplitModes) then
continue;
FEdgeSplitMap[j] := i;
FEdgeRevSplitMap[i] := j;
case i of
lgesNone: dropEdgeSplit.Items.Add(LvlGraphSplitNone);
lgesSeparate: dropEdgeSplit.Items.Add(LvlGraphSplitSeparate);
lgesMergeSource: dropEdgeSplit.Items.Add(LvlGraphSplitMergeAtSourc);
lgesMergeTarget: dropEdgeSplit.Items.Add(LvlGraphSplitMergeAtTarge);
lgesMergeHighest: dropEdgeSplit.Items.Add(LvlGraphSplitMergeAtHighe);
else dropEdgeSplit.Items.Add('?');
end;
inc(j);
end;
end;
procedure TDependencyGraphOptDialog.PopulateEdgeShape;
var
i: TLvlGraphEdgeShape;
begin
dropEdgeShape.Items.Clear;
for i := low(TLvlGraphEdgeShape) to high(TLvlGraphEdgeShape) do begin
case i of
lgesStraight: dropEdgeShape.Items.Add(LvlGraphShapeStraight);
lgesCurved: dropEdgeShape.Items.Add(LvlGraphShapeCurved);
else dropEdgeShape.Items.Add('?');
end;
end;
end;
procedure TDependencyGraphOptDialog.WriteToOpts;
begin
Options.MinimizeEdges := chkMinimizeEdges.Checked;
Options.HighLevels := chkHighEdges.Checked;
Options.ReduceBackEdges := chkReduceBackEdges.Checked;
Options.StraightenGraph := chkStraigtenGraph.Checked;
Options.EdgeSplit := FEdgeSplitMap[max(0, dropEdgeSplit.ItemIndex)];
Options.EdgeShape := TLvlGraphEdgeShape(max(0, dropEdgeShape.ItemIndex));
if chkCaptionOnTop.Checked then
Options.CaptionPos := lgncTop
else
Options.CaptionPos := lgncBottom;
Options.ExtraSpacingHoriz := spinHorizSpacing.Value;
Options.ExtraSpacingVert := spinVertSpacing.Value;
Options.LimitLvlHeighAbs := spinLvlLimitAbs.Value;
Options.LimitLvlHeighRel := spinLvlLimitRel.Value;
end;
procedure TDependencyGraphOptDialog.ReadFromOpts;
begin
chkMinimizeEdges.Checked := Options.MinimizeEdges;
chkHighEdges.Checked := Options.HighLevels;
chkReduceBackEdges.Checked := Options.ReduceBackEdges;
chkStraigtenGraph.Checked := Options.StraightenGraph;
dropEdgeSplit.ItemIndex := FEdgeRevSplitMap[Options.EdgeSplit];
dropEdgeShape.ItemIndex := ord(Options.EdgeShape);
chkCaptionOnTop.Checked := Options.CaptionPos = lgncTop;
spinHorizSpacing.Value := Options.ExtraSpacingHoriz;
spinVertSpacing.Value := Options.ExtraSpacingVert;
spinLvlLimitAbs.Value := Options.LimitLvlHeighAbs;
spinLvlLimitRel.Value := Options.LimitLvlHeighRel;
end;
procedure TDependencyGraphOptDialog.UpdateInfo;
function ComputeCrossCount: integer;
var
l,i,j,e1,e2: Integer;
Level: TLvlGraphLevel;
Node1, Node2, Target1, Target2: TLvlGraphNode;
begin
Result:=0;
for l:=0 to Graph.LevelCount-2 do begin
Level:=Graph.Levels[l];
for i:=0 to Level.Count-2 do begin
Node1:=Level.Nodes[i];
for j:=i+1 to Level.Count-1 do begin
Node2:=Level.Nodes[j];
for e1:=0 to Node1.OutEdgeCount-1 do begin
Target1:=Node1.OutEdges[e1].Target;
for e2:=0 to Node2.OutEdgeCount-1 do begin
Target2:=Node2.OutEdges[e2].Target;
if Target1.IndexInLevel>Target2.IndexInLevel then
Result+=1;
end;
end;
end;
end;
end;
end;
var
InfoNodeCnt, InfoEdgeCnt, InfoEdgeLen, InfoSplitCnt: Integer;
i, j: Integer;
Node: TLvlGraphNode;
Targets: TLvlGraphNodeArray;
begin
InfoGroup.Visible := FGraph <> nil;
if FGraph = nil then
exit;
InfoNodeCnt := 0;
InfoEdgeCnt := 0;
InfoEdgeLen := 0;
InfoSplitCnt := 0;
for i := 0 to Graph.NodeCount - 1 do begin
Node := Graph.Nodes[i];
if not Node.Visible then begin
if (Node.OutEdgeCount > 1) or (Node.InEdgeCount > 1) then
InfoSplitCnt := InfoSplitCnt + 1;
continue;
end;
InfoNodeCnt := InfoNodeCnt + 1;
Targets := Node.GetVisibleTargetNodes;
InfoEdgeCnt := InfoEdgeCnt + length(Targets);
for j := 0 to high(Targets) do
InfoEdgeLen := InfoEdgeLen + abs(Targets[j].Level.Index - Node.Level.Index);
end;
valNodeCnt.Caption := IntToStr(InfoNodeCnt);
valEdgeCnt.Caption := IntToStr(InfoEdgeCnt);
valEdgeLen.Caption := IntToStr(InfoEdgeLen);
valLevelCnt.Caption := IntToStr(Graph.LevelCount);
valCrossCnt.Caption := IntToStr(ComputeCrossCount);
valSplitCnt.Caption := IntToStr(InfoSplitCnt);
end;
{ TLvlGraphOptions }
constructor TLvlGraphOptions.Create;
begin
inherited;
FMinimizeEdges := True;
FHighLevels := False;
ReduceBackEdges := True;
FExtraSpacingVert := 0;
FExtraSpacingHoriz := 0;
FCaptionPos := lgncTop;
FEdgeShape := lgesCurved;
FEdgeSplit := lgesMergeHighest;
FStraightenGraph := True;
FLimitLvlHeighAbs := 0;
FLimitLvlHeighRel := 1.5;
end;
procedure TLvlGraphOptions.ReadFromXml(AnXmlConf: TRttiXMLConfig; APath: String);
var
Def: TLvlGraphOptions;
begin
Def := TLvlGraphOptions.Create;
AnXmlConf.ReadObject(APath, Self, Def);
Def.Free;
if OnLoaded <> nil then
OnLoaded(Self);
end;
procedure TLvlGraphOptions.WriteToXml(AnXmlConf: TRttiXMLConfig; APath: String);
var
Def: TLvlGraphOptions;
begin
Def := TLvlGraphOptions.Create;
AnXmlConf.WriteObject(APath, Self, Def);
Def.Free;
end;
procedure TLvlGraphOptions.Assign(ASrc: TPersistent);
begin
FMinimizeEdges := TLvlGraphOptions(ASrc).FMinimizeEdges;
FHighLevels := TLvlGraphOptions(ASrc).FHighLevels;
FReduceBackEdges := TLvlGraphOptions(ASrc).FReduceBackEdges;
FExtraSpacingVert := TLvlGraphOptions(ASrc).FExtraSpacingVert;
FExtraSpacingHoriz := TLvlGraphOptions(ASrc).FExtraSpacingHoriz;
FCaptionPos := TLvlGraphOptions(ASrc).FCaptionPos;
FEdgeShape := TLvlGraphOptions(ASrc).FEdgeShape;
FEdgeSplit := TLvlGraphOptions(ASrc).FEdgeSplit;
FStraightenGraph := TLvlGraphOptions(ASrc).FStraightenGraph;
FLimitLvlHeighAbs := TLvlGraphOptions(ASrc).FLimitLvlHeighAbs;
FLimitLvlHeighRel := TLvlGraphOptions(ASrc).FLimitLvlHeighRel;
end;
procedure TLvlGraphOptions.WriteToGraph(AValue: TLvlGraphControl);
var
i: Integer;
begin
if MinimizeEdges then
AValue.Options := AValue.Options + [lgoMinimizeEdgeLens]
else
AValue.Options := AValue.Options - [lgoMinimizeEdgeLens];
if HighLevels then
AValue.Options := AValue.Options + [lgoHighLevels]
else
AValue.Options := AValue.Options - [lgoHighLevels];
if ReduceBackEdges then
AValue.Options := AValue.Options + [lgoReduceBackEdges]
else
AValue.Options := AValue.Options - [lgoReduceBackEdges];
i := ExtraSpacingVert div 2;
AValue.NodeStyle.GapTop := DefaultLvlGraphNodeGapTop + i;
AValue.NodeStyle.GapBottom := DefaultLvlGraphNodeGapBottom + ExtraSpacingVert - i;
AValue.NodeStyle.GapRight := DefaultLvlGraphNodeGapRight + ExtraSpacingHoriz;
AValue.NodeStyle.CaptionPosition := FCaptionPos;
AValue.EdgeStyle.SplitMode := EdgeSplit;
AValue.EdgeStyle.Shape := EdgeShape;
if StraightenGraph then
AValue.Options := AValue.Options + [lgoStraightenGraph]
else
AValue.Options := AValue.Options - [lgoStraightenGraph];
AValue.Limits.MaxLevelHeightAbs := LimitLvlHeighAbs;
AValue.Limits.MaxLevelHeightRel := LimitLvlHeighRel;
end;
procedure TLvlGraphOptions.ReadFromGraph(AValue: TLvlGraphControl);
begin
MinimizeEdges := lgoMinimizeEdgeLens in AValue.Options;
HighLevels := lgoHighLevels in AValue.Options;
ReduceBackEdges := lgoReduceBackEdges in AValue.Options;
ExtraSpacingVert := AValue.NodeStyle.GapTop - DefaultLvlGraphNodeGapTop
+ AValue.NodeStyle.GapBottom - DefaultLvlGraphNodeGapBottom;
ExtraSpacingHoriz := AValue.NodeStyle.GapRight - DefaultLvlGraphNodeGapRight;
FCaptionPos := AValue.NodeStyle.CaptionPosition;
EdgeSplit := AValue.EdgeStyle.SplitMode;
EdgeShape := AValue.EdgeStyle.Shape;
StraightenGraph := lgoStraightenGraph in AValue.Options;
LimitLvlHeighAbs := AValue.Limits.MaxLevelHeightAbs;
LimitLvlHeighRel := AValue.Limits.MaxLevelHeightRel;
end;
end.

View File

@ -6532,6 +6532,37 @@ resourcestring
dbgEventWatchScopeEnded = 'Watchpoint for "%s" out of scope %s';
dbgEventUnknownWatchPointScopeEnded = 'Unknown Watchpoint out of scope %s';
rsAddNewTerm = 'Add new term';
LvlGraphSplitNone = 'None';
LvlGraphSplitSeparate = 'Separate';
LvlGraphSplitMergeAtSourc = 'Merge at source';
LvlGraphSplitMergeAtTarge = 'Merge at target';
LvlGraphSplitMergeAtHighe = 'Merge at highest';
LvlGraphShapeStraight = 'Straight';
LvlGraphShapeCurved = 'Curved';
LvlGraphShapeMinimizeEdge = 'Minimize edges len';
LvlGraphShapeCalculateLay = 'Calculate layout from high-edge';
LvlGraphStraightenGraph = 'Straighten graph';
LvlGraphNamesAboveNode = 'Names above node';
LvlGraphExtraSpacing = 'Extra spacing (x/y)';
LvlGraphAddHorizontalSpacing = 'Add horizontal spacing between columns';
LvlGraphAddVerticalSpacingAr = 'Add vertical spacing around nodes';
LvlGraphShapeEdgesSplitMo = 'Edges split mode';
LvlGraphShapeEdgesShape = 'Edges shape';
LvlGraphShapeNodes = 'Nodes';
LvlGraphOptEdges = 'Edges';
LvlGraphOptEdgeLen = 'Edge len';
LvlGraphOptLevels = 'Levels';
LvlGraphOptCrossings = 'Crossings';
LvlGraphOptSplitpoints = 'Splitpoints';
LvlGraphOptInfo = 'Info';
LvlGraphOptLimitHeightOfLvl = 'Limit height of Levels';
LvlGraphOptAbsoluteLimi = 'Absolute limit for height of levels';
LvlGraphOptLimitRelativ = 'Limit relative to node-count for height of levels.%0s'
+'Limit = min(3, val*sqrt(NodeCount))';
ShowOptions = 'Show options';
UnitDepOptionsForPackage = 'Options for Package graph';
UnitDepOptionsForUnit = 'Options for Unit graph';
LvlGraphReduceBackedges = 'Reduce backedges';
implementation

View File

@ -458,4 +458,12 @@ object UnitDependenciesWindow: TUnitDependenciesWindow
left = 465
top = 175
end
object GraphPopupMenu: TPopupMenu
left = 207
top = 70
object GraphOptsMenuItem: TMenuItem
Caption = 'GraphOptsMenuItem'
OnClick = GraphOptsMenuItemClick
end
end
end

View File

@ -50,7 +50,8 @@ uses
LazIDEIntf, ProjectIntf, IDEWindowIntf, PackageIntf, SrcEditorIntf, IDEImagesIntf,
IDEMsgIntf, IDEExternToolIntf, IDECommands, IDEDialogs,
// IDE
IDEOptionDefs, LazarusIDEStrConsts, UnusedUnitsDlg;
IDEOptionDefs, LazarusIDEStrConsts, UnusedUnitsDlg, DependencyGraphOptions,
MainIntf, EnvironmentOpts;
const
GroupPrefixProject = '-Project-';
@ -156,6 +157,9 @@ type
AllUnitsShowDirsSpeedButton: TSpeedButton;
AllUnitsShowGroupNodesSpeedButton: TSpeedButton;
AllUnitsTreeView: TTreeView; // Node.Data is TUDNode
GraphPopupMenu: TPopupMenu;
GraphOptsMenuItem: TMenuItem;
PopupMenu1: TPopupMenu;
UnitGraphFilter: TCheckListBox;
MainPageControl: TPageControl;
UnitGraphOptionSplitter: TSplitter;
@ -194,6 +198,7 @@ type
procedure AllUnitsShowDirsSpeedButtonClick(Sender: TObject);
procedure AllUnitsShowGroupNodesSpeedButtonClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure GraphOptsMenuItemClick(Sender: TObject);
procedure RefreshButtonClick(Sender: TObject);
procedure SelUnitsTreeViewExpanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
@ -226,6 +231,8 @@ type
procedure UnitsTVPopupMenuPopup(Sender: TObject);
procedure UnitsTVUnusedUnitsMenuItemClick(Sender: TObject);
private
FPackageGraphOpts: TLvlGraphOptions;
FUnitGraphOpts: TLvlGraphOptions;
FCurrentUnit: TUGUnit;
FIdleConnected: boolean;
FPendingUnitDependencyRoute: TStrings;
@ -250,6 +257,7 @@ type
FGroupLvlGraphSelectionsList: TStringList;
function CreateAllUnitsTree: TUDNode;
function CreateSelUnitsTree: TUDNode;
procedure DoLoadedOpts(Sender: TObject);
procedure ExpandPendingUnitDependencyRoute(RootNode: TUDNode);
procedure ConvertUnitNameRouteToPath(Route: TStrings); // inserts missing links
procedure AddUsesSubNodes(UDNode: TUDNode);
@ -257,6 +265,8 @@ type
ParentTVNode: TTreeNode; ParentUDNode: TUDNode; Expand: boolean);
procedure FreeUsesGraph;
function GetPopupTV_UDNode(out UDNode: TUDNode): boolean;
procedure GraphOptsApplyClicked(AnOpts: TLvlGraphOptions; AGraph: TLvlGraph
);
procedure SelectNextSearchTV(TV: TTreeView; StartTVNode: TTreeNode;
SearchNext, SkipStart: boolean);
function FindNextTVNode(StartNode: TTreeNode;
@ -571,12 +581,20 @@ begin
Caption:=lisMenuViewUnitDependencies;
RefreshButton.Caption:=dlgUnitDepRefresh;
GraphOptsMenuItem.Caption := ShowOptions;
MainPageControl.ActivePage:=UnitsTabSheet;
SetupUnitsTabSheet;
SetupGroupsTabSheet;
FPackageGraphOpts := TLvlGraphOptions.Create;
FPackageGraphOpts.OnLoaded := @DoLoadedOpts;
FUnitGraphOpts := TLvlGraphOptions.Create;
FUnitGraphOpts.OnLoaded := @DoLoadedOpts;
EnvironmentOptions.RegisterSubConfig(FPackageGraphOpts, 'UnitDependencies/PackageGraph');
EnvironmentOptions.RegisterSubConfig(FUnitGraphOpts, 'UnitDependencies/UnitGraph');
StartParsing;
end;
@ -617,6 +635,27 @@ begin
SelUnitsSearchEdit.TextHint:=ResStrSearch;
end;
procedure TUnitDependenciesWindow.GraphOptsMenuItemClick(Sender: TObject);
begin
if GraphPopupMenu.PopupComponent = GroupsLvlGraph then begin
if ShowDependencyGraphOptions(FPackageGraphOpts, GroupsLvlGraph.Graph,
UnitDepOptionsForPackage, @GraphOptsApplyClicked) = mrOK then begin
FPackageGraphOpts.WriteToGraph(GroupsLvlGraph);
UpdateGroupsLvlGraph;
MainIDEInterface.SaveEnvironment;
end;
end
else
begin
if ShowDependencyGraphOptions(FUnitGraphOpts, UnitsLvlGraph.Graph,
UnitDepOptionsForUnit, @GraphOptsApplyClicked) = mrOK then begin
FUnitGraphOpts.WriteToGraph(UnitsLvlGraph);
UpdateUnitsLvlGraph;
MainIDEInterface.SaveEnvironment;
end;
end;
end;
procedure TUnitDependenciesWindow.RefreshButtonClick(Sender: TObject);
begin
if udwParsing in FFlags then exit;
@ -815,6 +854,12 @@ begin
FreeAndNil(FNewUsesGraph);
FreeAndNil(FPendingUnitDependencyRoute);
FreeAndNil(FGroupLvlGraphSelectionsList);
if EnvironmentOptions <> nil then begin
EnvironmentOptions.UnRegisterSubConfig(FPackageGraphOpts);
EnvironmentOptions.UnRegisterSubConfig(FUnitGraphOpts);
end;
FreeAndNil(FPackageGraphOpts);
FreeAndNil(FUnitGraphOpts);
end;
procedure TUnitDependenciesWindow.GroupsLvlGraphSelectionChanged(Sender: TObject
@ -1478,6 +1523,14 @@ begin
Result:=RootNode;
end;
procedure TUnitDependenciesWindow.DoLoadedOpts(Sender: TObject);
begin
if Sender = FPackageGraphOpts then
FPackageGraphOpts.WriteToGraph(GroupsLvlGraph)
else
FUnitGraphOpts.WriteToGraph(UnitsLvlGraph);
end;
procedure TUnitDependenciesWindow.ExpandPendingUnitDependencyRoute(RootNode: TUDNode);
var
i: Integer;
@ -1809,6 +1862,7 @@ begin
Options := Options + [lgoMinimizeEdgeLens];
OnSelectionChanged:=@GroupsLvlGraphSelectionChanged;
Images:=IDEImages.Images_16;
PopupMenu := GraphPopupMenu;
end;
GroupsSplitter.Top:=GroupsLvlGraph.Height;
@ -1825,6 +1879,7 @@ begin
OnSelectionChanged:=@UnitsLvlGraphSelectionChanged;
OnMouseDown:=@UnitsLvlGraphMouseDown;
Images:=IDEImages.Images_16;
PopupMenu := GraphPopupMenu;
end;
end;
@ -2183,6 +2238,22 @@ begin
Result:=true;
end;
procedure TUnitDependenciesWindow.GraphOptsApplyClicked(
AnOpts: TLvlGraphOptions; AGraph: TLvlGraph);
begin
if AGraph = GroupsLvlGraph.Graph then begin
AnOpts.WriteToGraph(GroupsLvlGraph);
UpdateGroupsLvlGraph;
GroupsLvlGraph.AutoLayout;
end
else begin
AnOpts.WriteToGraph(UnitsLvlGraph);
UpdateUnitsLvlGraph;
UnitsLvlGraph.AutoLayout;
end;
MainIDEInterface.SaveEnvironment;
end;
procedure TUnitDependenciesWindow.UpdateAllUnitsTreeView;
var
TV: TTreeView;

View File

@ -121,5 +121,9 @@ object PkgGraphExplorerDlg: TPkgGraphExplorerDlg
Caption = 'Unneeded dependencies'
OnClick = CleanPkgDepsMenuItemClick
end
object GraphOptionsMenuItem: TMenuItem
Caption = 'GraphOptionsMenuItem'
OnClick = GraphOptionsMenuItemClick
end
end
end

View File

@ -48,8 +48,9 @@ uses
// IdeIntf
IDECommands, PackageIntf, IDEImagesIntf,
// IDE
LazarusIDEStrConsts, IDEOptionDefs, Project,
PackageDefs, PackageSystem, PackageEditor, CleanPkgDeps;
LazarusIDEStrConsts, IDEOptionDefs, Project, DependencyGraphOptions,
EnvironmentOpts, MainIntf, PackageDefs, PackageSystem, PackageEditor,
CleanPkgDeps;
const
GroupPrefixProject = '-Project-';
@ -63,6 +64,7 @@ type
TPkgGraphExplorerDlg = class(TForm)
ButtonPanel1: TButtonPanel;
CleanPkgDepsMenuItem: TMenuItem;
GraphOptionsMenuItem: TMenuItem;
PkgTreeView: TTreeView;
InfoMemo: TMemo;
LvlGraphControl1: TLvlGraphControl;
@ -73,6 +75,7 @@ type
UninstallMenuItem: TMenuItem;
procedure CleanPkgDepsMenuItemClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure GraphOptionsMenuItemClick(Sender: TObject);
procedure HelpButtonClick(Sender: TObject);
procedure LvlGraphControl1DblClick(Sender: TObject);
procedure LvlGraphControl1SelectionChanged(Sender: TObject);
@ -87,6 +90,7 @@ type
procedure PkgTreeViewSelectionChanged(Sender: TObject);
procedure UninstallMenuItemClick(Sender: TObject);
private
FPackageGraphOpts: TLvlGraphOptions;
FOnOpenProject: TOnOpenProject;
FOnUninstallPackage: TOnPkgEvent;
ImgIndexProject: integer;
@ -100,6 +104,9 @@ type
FChangedDuringLock: boolean;
FUpdateLock: integer;
FUpdatingSelection: boolean;
procedure DoLoadedOpts(Sender: TObject);
procedure GraphOptsApplyClicked(AnOpts: TLvlGraphOptions; AGraph: TLvlGraph
);
procedure OpenDependencyOwner(DependencyOwner: TObject);
procedure SetupComponents;
function GetPackageImageIndex(Pkg: TLazPackage; InstallPkgList: TFPList): integer;
@ -214,6 +221,18 @@ end;
procedure TPkgGraphExplorerDlg.FormCreate(Sender: TObject);
begin
ButtonPanel1.OKButton.Caption:= lisClose;
GraphOptionsMenuItem.Caption := ShowOptions;
end;
procedure TPkgGraphExplorerDlg.GraphOptionsMenuItemClick(Sender: TObject);
begin
if ShowDependencyGraphOptions(FPackageGraphOpts, LvlGraphControl1.Graph,
UnitDepOptionsForPackage, @GraphOptsApplyClicked) = mrOK then begin
FPackageGraphOpts.WriteToGraph(LvlGraphControl1);
UpdateLvlGraph;
LvlGraphControl1.AutoLayout;
MainIDEInterface.SaveEnvironment;
end;
end;
procedure TPkgGraphExplorerDlg.HelpButtonClick(Sender: TObject);
@ -452,10 +471,17 @@ begin
Caption:=lisMenuPackageGraph;
SetupComponents;
FPackageGraphOpts := TLvlGraphOptions.Create;
FPackageGraphOpts.OnLoaded := @DoLoadedOpts;
EnvironmentOptions.RegisterSubConfig(FPackageGraphOpts, 'Packages/PackageGraph');
end;
destructor TPkgGraphExplorerDlg.Destroy;
begin
if EnvironmentOptions <> nil then
EnvironmentOptions.UnRegisterSubConfig(FPackageGraphOpts);
FPackageGraphOpts.Free;
inherited Destroy;
end;
@ -703,6 +729,19 @@ begin
end;
end;
procedure TPkgGraphExplorerDlg.DoLoadedOpts(Sender: TObject);
begin
FPackageGraphOpts.WriteToGraph(LvlGraphControl1);
end;
procedure TPkgGraphExplorerDlg.GraphOptsApplyClicked(AnOpts: TLvlGraphOptions;
AGraph: TLvlGraph);
begin
AnOpts.WriteToGraph(LvlGraphControl1);
UpdateLvlGraph;
MainIDEInterface.SaveEnvironment;
end;
function TPkgGraphExplorerDlg.FindLvlGraphNodeWithText(const s: string): TLvlGraphNode;
begin
Result:=LvlGraphControl1.Graph.GetNode(s,false);