diff --git a/.gitattributes b/.gitattributes index 654d2a2fb2..cc13abb058 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/ide/dependencygraphoptions.lfm b/ide/dependencygraphoptions.lfm new file mode 100644 index 0000000000..d0f312ccf4 --- /dev/null +++ b/ide/dependencygraphoptions.lfm @@ -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 diff --git a/ide/dependencygraphoptions.pas b/ide/dependencygraphoptions.pas new file mode 100644 index 0000000000..79a32dbac1 --- /dev/null +++ b/ide/dependencygraphoptions.pas @@ -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. + diff --git a/ide/lazarusidestrconsts.pas b/ide/lazarusidestrconsts.pas index 6b75cc7eb7..c2f3cb2fe8 100644 --- a/ide/lazarusidestrconsts.pas +++ b/ide/lazarusidestrconsts.pas @@ -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 diff --git a/ide/unitdependencies.lfm b/ide/unitdependencies.lfm index 0f903a6b15..74bbe59827 100644 --- a/ide/unitdependencies.lfm +++ b/ide/unitdependencies.lfm @@ -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 diff --git a/ide/unitdependencies.pas b/ide/unitdependencies.pas index 69761d9126..1f61500a75 100644 --- a/ide/unitdependencies.pas +++ b/ide/unitdependencies.pas @@ -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; diff --git a/packager/pkggraphexplorer.lfm b/packager/pkggraphexplorer.lfm index d4ed3c84cd..b31b52ddf1 100644 --- a/packager/pkggraphexplorer.lfm +++ b/packager/pkggraphexplorer.lfm @@ -121,5 +121,9 @@ object PkgGraphExplorerDlg: TPkgGraphExplorerDlg Caption = 'Unneeded dependencies' OnClick = CleanPkgDepsMenuItemClick end + object GraphOptionsMenuItem: TMenuItem + Caption = 'GraphOptionsMenuItem' + OnClick = GraphOptionsMenuItemClick + end end end diff --git a/packager/pkggraphexplorer.pas b/packager/pkggraphexplorer.pas index 0b6d017fd6..520236d7ed 100644 --- a/packager/pkggraphexplorer.pas +++ b/packager/pkggraphexplorer.pas @@ -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);