IDE Window Layout: provide ability to store columns/rows/splitter sizes.

DBG: Watches, store column widths with IDE layout

git-svn-id: trunk@33202 -
This commit is contained in:
martin 2011-11-01 16:31:31 +00:00
parent ed61ffb82a
commit c6a5c6d837
7 changed files with 770 additions and 148 deletions

View File

@ -10,8 +10,6 @@ inherited WatchesDlg: TWatchesDlg
Caption = 'Watch list' Caption = 'Watch list'
ClientHeight = 200 ClientHeight = 200
ClientWidth = 500 ClientWidth = 500
OnClose = FormClose
OnCloseQuery = FormCloseQuery
OnDestroy = FormDestroy OnDestroy = FormDestroy
OnShow = FormShow OnShow = FormShow
object lvWatches: TListView[0] object lvWatches: TListView[0]

View File

@ -39,6 +39,7 @@ interface
uses uses
Classes, SysUtils, LCLProc, Forms, Controls, Graphics, Dialogs, math, Classes, SysUtils, LCLProc, Forms, Controls, Graphics, Dialogs, math,
IDEWindowIntf, IDEOptionDefs,
StdCtrls, Buttons, Menus, ComCtrls, LCLType, ActnList, IDEImagesIntf, StdCtrls, Buttons, Menus, ComCtrls, LCLType, ActnList, IDEImagesIntf,
EnvironmentOpts, LazarusIDEStrConsts, Debugger, DebuggerDlg, BaseDebugManager; EnvironmentOpts, LazarusIDEStrConsts, Debugger, DebuggerDlg, BaseDebugManager;
@ -95,8 +96,6 @@ type
procedure actDisableSelectedExecute(Sender: TObject); procedure actDisableSelectedExecute(Sender: TObject);
procedure actEnableSelectedExecute(Sender: TObject); procedure actEnableSelectedExecute(Sender: TObject);
procedure actPowerExecute(Sender: TObject); procedure actPowerExecute(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
procedure FormDestroy(Sender: TObject); procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject); procedure FormShow(Sender: TObject);
procedure lvWatchesDblClick(Sender: TObject); procedure lvWatchesDblClick(Sender: TObject);
@ -112,7 +111,6 @@ type
function GetWatches: TWatches; function GetWatches: TWatches;
procedure ContextChanged(Sender: TObject); procedure ContextChanged(Sender: TObject);
procedure SnapshotChanged(Sender: TObject); procedure SnapshotChanged(Sender: TObject);
procedure SaveColumnWidths;
private private
FWatchesInView: TWatches; FWatchesInView: TWatches;
FPowerImgIdx, FPowerImgIdxGrey: Integer; FPowerImgIdx, FPowerImgIdxGrey: Integer;
@ -134,6 +132,8 @@ type
protected protected
procedure DoEndUpdate; override; procedure DoEndUpdate; override;
procedure DoWatchesChanged; override; procedure DoWatchesChanged; override;
function ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean;
procedure ColSizeSetter(AColId: Integer; ASize: Integer);
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
property WatchesMonitor; property WatchesMonitor;
@ -148,6 +148,25 @@ implementation
{$R *.lfm} {$R *.lfm}
var
WatchWindowCreator: TIDEWindowCreator;
const
COL_WATCH_EXPR = 1;
COL_WATCH_VALUE = 2;
function WatchesDlgColSizeGetter(AForm: TCustomForm; AColId: Integer; var ASize: Integer): Boolean;
begin
Result := AForm is TWatchesDlg;
if Result then
Result := TWatchesDlg(AForm).ColSizeGetter(AColId, ASize);
end;
procedure WatchesDlgColSizeSetter(AForm: TCustomForm; AColId: Integer; ASize: Integer);
begin
if AForm is TWatchesDlg then
TWatchesDlg(AForm).ColSizeSetter(AColId, ASize);
end;
{ TWatchesDlg } { TWatchesDlg }
constructor TWatchesDlg.Create(AOwner: TComponent); constructor TWatchesDlg.Create(AOwner: TComponent);
@ -351,27 +370,8 @@ begin
end; end;
procedure TWatchesDlg.FormShow(Sender: TObject); procedure TWatchesDlg.FormShow(Sender: TObject);
var
Conf: TDebuggerWatchesDlgConfig;
begin begin
UpdateAll; UpdateAll;
Conf := EnvironmentOptions.DebuggerConfig.DlgWatchesConfig;
if Conf.ColumnNameWidth > 0 then
lvWatches.Column[0].Width := Conf.ColumnNameWidth;
if Conf.ColumnValueWidth > 0 then
lvWatches.Column[1].Width := Conf.ColumnValueWidth;
end;
procedure TWatchesDlg.FormCloseQuery(Sender: TObject; var CanClose: boolean);
begin
//DebugLn('TWatchesDlg.FormCloseQuery ',dbgs(CanClose));
SaveColumnWidths;
end;
procedure TWatchesDlg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
//DebugLn('TWatchesDlg.FormClose ',dbgs(ord(CloseAction)));
SaveColumnWidths;
end; end;
procedure TWatchesDlg.actPowerExecute(Sender: TObject); procedure TWatchesDlg.actPowerExecute(Sender: TObject);
@ -485,15 +485,6 @@ begin
end; end;
end; end;
procedure TWatchesDlg.SaveColumnWidths;
var
Conf: TDebuggerWatchesDlgConfig;
begin
Conf := EnvironmentOptions.DebuggerConfig.DlgWatchesConfig;
Conf.ColumnNameWidth := lvWatches.Column[0].Width;
Conf.ColumnValueWidth := lvWatches.Column[1].Width;
end;
function TWatchesDlg.GetWatches: TWatches; function TWatchesDlg.GetWatches: TWatches;
var var
Snap: TSnapshot; Snap: TSnapshot;
@ -522,6 +513,25 @@ begin
UpdateAll; UpdateAll;
end; end;
function TWatchesDlg.ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean;
begin
Result := True;
case AColId of
COL_WATCH_EXPR: ASize := lvWatches.Column[0].Width;
COL_WATCH_VALUE: ASize := lvWatches.Column[1].Width;
else
Result := False;
end;
end;
procedure TWatchesDlg.ColSizeSetter(AColId: Integer; ASize: Integer);
begin
case AColId of
COL_WATCH_EXPR: lvWatches.Column[0].Width := ASize;
COL_WATCH_VALUE: lvWatches.Column[1].Width := ASize;
end;
end;
procedure TWatchesDlg.popDeleteClick(Sender: TObject); procedure TWatchesDlg.popDeleteClick(Sender: TObject);
var var
Item: TCurrentWatch; Item: TCurrentWatch;
@ -751,5 +761,13 @@ begin
lvWatchesSelectItem(nil, nil, False); lvWatchesSelectItem(nil, nil, False);
end; end;
initialization
WatchWindowCreator := IDEWindowCreators.Add(NonModalIDEWindowNames[nmiwWatches]);
WatchWindowCreator.OnSetDividerSize := @WatchesDlgColSizeSetter;
WatchWindowCreator.OnGetDividerSize := @WatchesDlgColSizeGetter;
WatchWindowCreator.DividerTemplate.Add('ColumnWatchExpr', COL_WATCH_EXPR, dbgLCWatchExpression);
WatchWindowCreator.DividerTemplate.Add('ColumnWatchValue', COL_WATCH_VALUE, dbgLCWatchValue);
end. end.

View File

@ -1682,8 +1682,9 @@ begin
end; end;
for DlgType:=Low(TDebugDialogType) to High(TDebugDialogType) do for DlgType:=Low(TDebugDialogType) to High(TDebugDialogType) do
IDEWindowCreators.Add(NonModalIDEWindowNames[DebugDlgIDEWindow[DlgType]], if not (DlgType in [ddtWatches]) then
nil,@CreateDebugDialog,'','','',''); IDEWindowCreators.Add(NonModalIDEWindowNames[DebugDlgIDEWindow[DlgType]],
nil,@CreateDebugDialog,'','','','');
end; end;
procedure TDebugManager.ConnectSourceNotebookEvents; procedure TDebugManager.ConnectSourceNotebookEvents;

View File

@ -54,7 +54,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideTop.Side = asrCenter AnchorSideTop.Side = asrCenter
Left = 6 Left = 6
Height = 3 Height = 3
Top = 168 Top = 139
Width = 50 Width = 50
BorderSpacing.Left = 6 BorderSpacing.Left = 6
end end
@ -67,7 +67,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 178 Left = 178
Height = 3 Height = 3
Top = 168 Top = 139
Width = 378 Width = 378
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6 BorderSpacing.Left = 6
@ -79,7 +79,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 70 Left = 70
Height = 16 Height = 16
Top = 161 Top = 132
Width = 102 Width = 102
BorderSpacing.Left = 70 BorderSpacing.Left = 70
BorderSpacing.Top = 6 BorderSpacing.Top = 6
@ -94,7 +94,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Control = LeftEdit AnchorSideRight.Control = LeftEdit
Left = 294 Left = 294
Height = 16 Height = 16
Top = 186 Top = 218
Width = 49 Width = 49
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Right = 3 BorderSpacing.Right = 3
@ -107,7 +107,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Control = TopEdit AnchorSideRight.Control = TopEdit
Left = 293 Left = 293
Height = 16 Height = 16
Top = 215 Top = 247
Width = 50 Width = 50
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Right = 3 BorderSpacing.Right = 3
@ -120,7 +120,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Control = WidthEdit AnchorSideRight.Control = WidthEdit
Left = 417 Left = 417
Height = 16 Height = 16
Top = 186 Top = 218
Width = 61 Width = 61
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Right = 3 BorderSpacing.Right = 3
@ -133,7 +133,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Control = HeightEdit AnchorSideRight.Control = HeightEdit
Left = 413 Left = 413
Height = 16 Height = 16
Top = 215 Top = 247
Width = 65 Width = 65
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Right = 3 BorderSpacing.Right = 3
@ -146,7 +146,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Control = WindowPositionsGroupBox AnchorSideRight.Control = WindowPositionsGroupBox
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 6 Left = 6
Height = 149 Height = 120
Top = 6 Top = 6
Width = 550 Width = 550
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
@ -157,11 +157,11 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
end end
object UseWindowManagerSettingRadioButton: TRadioButton object UseWindowManagerSettingRadioButton: TRadioButton
AnchorSideLeft.Control = WindowPositionsGroupBox AnchorSideLeft.Control = WindowPositionsGroupBox
AnchorSideTop.Control = lblWindowCaption AnchorSideTop.Control = SplitterPanel
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 6 Left = 6
Height = 19 Height = 19
Top = 183 Top = 215
Width = 233 Width = 233
BorderSpacing.Around = 6 BorderSpacing.Around = 6
Caption = 'UseWindowManagerSettingRadioButton' Caption = 'UseWindowManagerSettingRadioButton'
@ -175,7 +175,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 6 Left = 6
Height = 19 Height = 19
Top = 208 Top = 240
Width = 124 Width = 124
BorderSpacing.Around = 6 BorderSpacing.Around = 6
Caption = 'DefaultRadioButton' Caption = 'DefaultRadioButton'
@ -187,7 +187,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 6 Left = 6
Height = 19 Height = 19
Top = 233 Top = 265
Width = 221 Width = 221
BorderSpacing.Around = 6 BorderSpacing.Around = 6
Caption = 'RestoreWindowGeometryRadioButton' Caption = 'RestoreWindowGeometryRadioButton'
@ -199,19 +199,19 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
Left = 6 Left = 6
Height = 19 Height = 19
Top = 258 Top = 290
Width = 171 Width = 171
BorderSpacing.Around = 6 BorderSpacing.Around = 6
Caption = 'CustomPositionRadioButton' Caption = 'CustomPositionRadioButton'
TabOrder = 4 TabOrder = 4
end end
object LeftEdit: TSpinEdit object LeftEdit: TSpinEdit
AnchorSideTop.Control = lblWindowCaption AnchorSideTop.Control = SplitterPanel
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = WidthEdit AnchorSideRight.Control = WidthEdit
Left = 346 Left = 346
Height = 23 Height = 23
Top = 183 Top = 215
Width = 75 Width = 75
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Top = 6 BorderSpacing.Top = 6
@ -226,7 +226,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Control = HeightEdit AnchorSideRight.Control = HeightEdit
Left = 346 Left = 346
Height = 23 Height = 23
Top = 212 Top = 244
Width = 75 Width = 75
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Top = 6 BorderSpacing.Top = 6
@ -236,13 +236,13 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
TabOrder = 6 TabOrder = 6
end end
object WidthEdit: TSpinEdit object WidthEdit: TSpinEdit
AnchorSideTop.Control = lblWindowCaption AnchorSideTop.Control = SplitterPanel
AnchorSideTop.Side = asrBottom AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = WindowPositionsGroupBox AnchorSideRight.Control = WindowPositionsGroupBox
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 481 Left = 481
Height = 23 Height = 23
Top = 183 Top = 215
Width = 75 Width = 75
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Top = 6 BorderSpacing.Top = 6
@ -257,7 +257,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 481 Left = 481
Height = 23 Height = 23
Top = 212 Top = 244
Width = 75 Width = 75
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
BorderSpacing.Top = 6 BorderSpacing.Top = 6
@ -271,7 +271,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Control = ApplyButton AnchorSideRight.Control = ApplyButton
Left = 290 Left = 290
Height = 25 Height = 25
Top = 241 Top = 273
Width = 167 Width = 167
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
AutoSize = True AutoSize = True
@ -288,7 +288,7 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 463 Left = 463
Height = 25 Height = 25
Top = 241 Top = 273
Width = 93 Width = 93
Anchors = [akTop, akRight] Anchors = [akTop, akRight]
AutoSize = True AutoSize = True
@ -298,6 +298,84 @@ inherited WindowOptionsFrame: TWindowOptionsFrame
OnClick = ApplyButtonClick OnClick = ApplyButtonClick
TabOrder = 10 TabOrder = 10
end end
object SplitterPanel: TPanel
AnchorSideLeft.Control = WindowPositionsGroupBox
AnchorSideTop.Control = lblWindowCaption
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = WindowPositionsGroupBox
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = WindowPositionsGroupBox
AnchorSideBottom.Side = asrBottom
Left = 4
Height = 57
Top = 152
Width = 554
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Around = 4
BevelOuter = bvNone
BorderWidth = 1
BorderStyle = bsSingle
Caption = ' '
ClientHeight = 53
ClientWidth = 550
TabOrder = 11
Visible = False
object SplitterList: TListBox
AnchorSideLeft.Control = SplitterPanel
AnchorSideTop.Control = SplitterPanel
AnchorSideBottom.Control = SplitterPanel
AnchorSideBottom.Side = asrBottom
Left = 1
Height = 51
Top = 1
Width = 275
Anchors = [akTop, akLeft, akBottom]
ItemHeight = 0
OnSelectionChange = SplitterListSelectionChange
TabOrder = 0
end
object SplitLabel: TLabel
AnchorSideTop.Control = SplitEdit
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = SplitEdit
Left = 422
Height = 16
Top = 32
Width = 52
Anchors = [akTop, akRight]
Caption = 'SplitLabel'
ParentColor = False
end
object SplitEdit: TSpinEdit
AnchorSideRight.Control = SplitterPanel
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = SplitterPanel
AnchorSideBottom.Side = asrBottom
Left = 474
Height = 23
Top = 29
Width = 75
Anchors = [akRight, akBottom]
MaxValue = 5000
TabOrder = 1
end
object dropSplitterPlacement: TComboBox
AnchorSideLeft.Control = SplitterList
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = SplitterPanel
AnchorSideRight.Control = SplitterPanel
AnchorSideRight.Side = asrBottom
Left = 282
Height = 23
Top = 1
Width = 267
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
ItemHeight = 15
Style = csDropDownList
TabOrder = 2
end
end
end end
object HideMessagesIconsCheckBox: TCheckBox[3] object HideMessagesIconsCheckBox: TCheckBox[3]
AnchorSideLeft.Control = Owner AnchorSideLeft.Control = Owner

View File

@ -38,6 +38,7 @@ type
ApplyButton: TButton; ApplyButton: TButton;
Bevel1: TBevel; Bevel1: TBevel;
Bevel2: TBevel; Bevel2: TBevel;
dropSplitterPlacement: TComboBox;
CustomPositionRadioButton: TRadioButton; CustomPositionRadioButton: TRadioButton;
DefaultRadioButton: TRadioButton; DefaultRadioButton: TRadioButton;
GetWindowPositionButton: TButton; GetWindowPositionButton: TButton;
@ -45,11 +46,15 @@ type
HeightLabel: TLabel; HeightLabel: TLabel;
HideIDEOnRunCheckBox: TCheckBox; HideIDEOnRunCheckBox: TCheckBox;
HideMessagesIconsCheckBox: TCheckBox; HideMessagesIconsCheckBox: TCheckBox;
SplitLabel: TLabel;
lblWindowCaption: TLabel; lblWindowCaption: TLabel;
LeftEdit: TSpinEdit; LeftEdit: TSpinEdit;
LeftLabel: TLabel; LeftLabel: TLabel;
SplitterList: TListBox;
SplitterPanel: TPanel;
SingleTaskBarButtonCheckBox: TCheckBox; SingleTaskBarButtonCheckBox: TCheckBox;
RestoreWindowGeometryRadioButton: TRadioButton; RestoreWindowGeometryRadioButton: TRadioButton;
SplitEdit: TSpinEdit;
TitleStartsWithProjectCheckBox: TCheckBox; TitleStartsWithProjectCheckBox: TCheckBox;
ProjectDirInIdeTitleCheckBox: TCheckBox; ProjectDirInIdeTitleCheckBox: TCheckBox;
TopEdit: TSpinEdit; TopEdit: TSpinEdit;
@ -61,17 +66,22 @@ type
WindowPositionsListBox: TListBox; WindowPositionsListBox: TListBox;
procedure ApplyButtonClick(Sender: TObject); procedure ApplyButtonClick(Sender: TObject);
procedure GetWindowPositionButtonClick(Sender: TObject); procedure GetWindowPositionButtonClick(Sender: TObject);
procedure SplitterListSelectionChange(Sender: TObject; User: boolean);
procedure WindowPositionsListBoxSelectionChange(Sender: TObject; User: boolean); procedure WindowPositionsListBoxSelectionChange(Sender: TObject; User: boolean);
private private
FLayouts: TSimpleWindowLayoutList; FLayouts: TSimpleWindowLayoutList;
FLayout: TSimpleWindowLayout; FLayout: TSimpleWindowLayout;
FDivider: TSimpleWindowLayoutDividerPos;
FShowSimpleLayout: boolean; FShowSimpleLayout: boolean;
function GetPlacementRadioButtons(APlacement: TIDEWindowPlacement): TRadioButton; function GetPlacementRadioButtons(APlacement: TIDEWindowPlacement): TRadioButton;
procedure SetLayout(const AValue: TSimpleWindowLayout); procedure SetLayout(const AValue: TSimpleWindowLayout);
procedure SetDivider(const AValue: TSimpleWindowLayoutDividerPos);
procedure SetWindowPositionsItem(Index: integer); procedure SetWindowPositionsItem(Index: integer);
procedure SaveCurrentSplitterLayout;
procedure SaveLayout; procedure SaveLayout;
function GetLayoutCaption(ALayout: TSimpleWindowLayout): String; function GetLayoutCaption(ALayout: TSimpleWindowLayout): String;
property Layout: TSimpleWindowLayout read FLayout write SetLayout; property Layout: TSimpleWindowLayout read FLayout write SetLayout;
property Divider: TSimpleWindowLayoutDividerPos read FDivider write SetDivider;
public public
constructor Create(TheOwner: TComponent); override; constructor Create(TheOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
@ -144,6 +154,7 @@ begin
WindowPositionsListBox.Items.AddObject(GetLayoutCaption(FLayouts[j]),FLayouts[j]); WindowPositionsListBox.Items.AddObject(GetLayoutCaption(FLayouts[j]),FLayouts[j]);
end; end;
end; end;
//WindowPositionsListBox.Sorted := True;
WindowPositionsListBox.Items.EndUpdate; WindowPositionsListBox.Items.EndUpdate;
LeftLabel.Caption := dlgLeftPos; LeftLabel.Caption := dlgLeftPos;
@ -152,12 +163,19 @@ begin
HeightLabel.Caption := DlgHeightPos; HeightLabel.Caption := DlgHeightPos;
ApplyButton.Caption := dlgButApply; ApplyButton.Caption := dlgButApply;
GetWindowPositionButton.Caption := dlgGetPosition; GetWindowPositionButton.Caption := dlgGetPosition;
SplitLabel.Caption := dlgWidthPos;
UseWindowManagerSettingRadioButton.Caption := rsiwpUseWindowManagerSetting; UseWindowManagerSettingRadioButton.Caption := rsiwpUseWindowManagerSetting;
DefaultRadioButton.Caption := rsiwpDefault; DefaultRadioButton.Caption := rsiwpDefault;
RestoreWindowGeometryRadioButton.Caption := rsiwpRestoreWindowGeometry; RestoreWindowGeometryRadioButton.Caption := rsiwpRestoreWindowGeometry;
CustomPositionRadioButton.Caption := rsiwpCustomPosition; CustomPositionRadioButton.Caption := rsiwpCustomPosition;
dropSplitterPlacement.Clear;
dropSplitterPlacement.Items.Add(rsiwpSplitterFollowWindow);
dropSplitterPlacement.Items.Add(rsiwpSplitterDefault);
dropSplitterPlacement.Items.Add(rsiwpSplitterRestoreWindowGeometry);
dropSplitterPlacement.Items.Add(rsiwpSplitterCustomPosition);
SetWindowPositionsItem(0); SetWindowPositionsItem(0);
end else begin end else begin
WindowPositionsGroupBox.Parent:=nil; WindowPositionsGroupBox.Parent:=nil;
@ -198,9 +216,14 @@ var
APlacement: TIDEWindowPlacement; APlacement: TIDEWindowPlacement;
RadioButton: TRadioButton; RadioButton: TRadioButton;
p: TPoint; p: TPoint;
i: Integer;
begin begin
FLayout := AValue; FLayout := AValue;
if Layout=nil then Exit; Divider := nil;
if Layout=nil then begin
SplitterPanel.Visible := False;
Exit;
end;
//debugln(['TWindowOptionsFrame.SetLayout ',Layout.FormID,' ',IDEWindowPlacementNames[Layout.WindowPlacement]]); //debugln(['TWindowOptionsFrame.SetLayout ',Layout.FormID,' ',IDEWindowPlacementNames[Layout.WindowPlacement]]);
for APlacement := Low(TIDEWindowPlacement) to High(TIDEWindowPlacement) do for APlacement := Low(TIDEWindowPlacement) to High(TIDEWindowPlacement) do
@ -242,6 +265,27 @@ begin
end; end;
GetWindowPositionButton.Enabled := (Layout.Form <> nil); GetWindowPositionButton.Enabled := (Layout.Form <> nil);
SplitterPanel.Visible := Layout.Dividers.NamedCount > 0;
SplitterList.Clear;
for i := 0 to Layout.Dividers.NamedCount - 1 do
SplitterList.AddItem(Layout.Dividers.NamedItems[i].DisplayName, Layout.Dividers.NamedItems[i]);
if Layout.Dividers.NamedCount > 0 then
SplitterList.ItemIndex := 0;
end;
procedure TWindowOptionsFrame.SetDivider(const AValue: TSimpleWindowLayoutDividerPos);
begin
FDivider := AValue;
if FDivider=nil then exit;
SplitEdit.Value := FDivider.Size;
case FDivider.Placement of
iwpdUseWindowSetting: dropSplitterPlacement.ItemIndex := 0;
iwpdDefault: dropSplitterPlacement.ItemIndex := 1;
iwpdRestore: dropSplitterPlacement.ItemIndex := 2;
iwpdCustomSize: dropSplitterPlacement.ItemIndex := 3;
end;
end; end;
procedure TWindowOptionsFrame.WindowPositionsListBoxSelectionChange( procedure TWindowOptionsFrame.WindowPositionsListBoxSelectionChange(
@ -257,29 +301,32 @@ var
begin begin
SaveLayout; SaveLayout;
if (Layout<>nil) and (Layout.Form<>nil) and (Layout.Form.Parent=nil) if (Layout<>nil) and (Layout.Form<>nil) and (Layout.Form.Parent=nil)
and (Layout.WindowPlacement in [iwpCustomPosition,iwpRestoreWindowGeometry])
then begin then begin
if (Layout.CustomCoordinatesAreValid) then begin if (Layout.WindowPlacement in [iwpCustomPosition,iwpRestoreWindowGeometry])
// explicit position then begin
NewBounds:=Bounds(Layout.Left,Layout.Top,Layout.Width,Layout.Height); if (Layout.CustomCoordinatesAreValid) then begin
// set minimum size // explicit position
if NewBounds.Right-NewBounds.Left<20 then NewBounds:=Bounds(Layout.Left,Layout.Top,Layout.Width,Layout.Height);
NewBounds.Right:=NewBounds.Left+20; // set minimum size
if NewBounds.Bottom-NewBounds.Top<20 then if NewBounds.Right-NewBounds.Left<20 then
NewBounds.Bottom:=NewBounds.Top+20; NewBounds.Right:=NewBounds.Left+20;
// move to visible area if NewBounds.Bottom-NewBounds.Top<20 then
if NewBounds.Right<20 then NewBounds.Bottom:=NewBounds.Top+20;
OffsetRect(NewBounds,20-NewBounds.Right,0); // move to visible area
if NewBounds.Bottom<20 then if NewBounds.Right<20 then
OffsetRect(NewBounds,0,20-NewBounds.Bottom); OffsetRect(NewBounds,20-NewBounds.Right,0);
if NewBounds.Left>Screen.DesktopWidth-20 then if NewBounds.Bottom<20 then
OffsetRect(NewBounds,NewBounds.Left-(Screen.DesktopWidth-20),0); OffsetRect(NewBounds,0,20-NewBounds.Bottom);
if NewBounds.Top>Screen.DesktopHeight-20 then if NewBounds.Left>Screen.DesktopWidth-20 then
OffsetRect(NewBounds,NewBounds.Top-(Screen.DesktopHeight-20),0); OffsetRect(NewBounds,NewBounds.Left-(Screen.DesktopWidth-20),0);
Layout.Form.SetBounds( if NewBounds.Top>Screen.DesktopHeight-20 then
NewBounds.Left,NewBounds.Top, OffsetRect(NewBounds,NewBounds.Top-(Screen.DesktopHeight-20),0);
NewBounds.Right-NewBounds.Left,NewBounds.Bottom-NewBounds.Top); Layout.Form.SetBounds(
NewBounds.Left,NewBounds.Top,
NewBounds.Right-NewBounds.Left,NewBounds.Bottom-NewBounds.Top);
end;
end; end;
Layout.ApplyDivider(True);
end; end;
end; end;
@ -292,6 +339,16 @@ begin
WidthEdit.Value := Layout.Form.Width; WidthEdit.Value := Layout.Form.Width;
HeightEdit.Value := Layout.Form.Height; HeightEdit.Value := Layout.Form.Height;
end; end;
Layout.ReadCurrentDividers(True);
SplitterListSelectionChange(nil, False);
end;
procedure TWindowOptionsFrame.SplitterListSelectionChange(Sender: TObject; User: boolean);
begin
if User then SaveCurrentSplitterLayout;
if (SplitterList.Count = 0) or (SplitterList.ItemIndex < 0) then exit;
SetDivider(TSimpleWindowLayoutDividerPos(SplitterList.Items.Objects[SplitterList.ItemIndex]));
end; end;
procedure TWindowOptionsFrame.SetWindowPositionsItem(Index: integer); procedure TWindowOptionsFrame.SetWindowPositionsItem(Index: integer);
@ -308,6 +365,18 @@ begin
lblWindowCaption.Caption := WindowPositionsListBox.Items[Index]; lblWindowCaption.Caption := WindowPositionsListBox.Items[Index];
end; end;
procedure TWindowOptionsFrame.SaveCurrentSplitterLayout;
begin
if FDivider = nil then exit;
case dropSplitterPlacement.ItemIndex of
0: FDivider.Placement := iwpdUseWindowSetting;
1: FDivider.Placement := iwpdDefault;
2: FDivider.Placement := iwpdRestore;
3: FDivider.Placement := iwpdCustomSize;
end;
FDivider.Size := SplitEdit.Value;
end;
procedure TWindowOptionsFrame.SaveLayout; procedure TWindowOptionsFrame.SaveLayout;
var var
APlacement: TIDEWindowPlacement; APlacement: TIDEWindowPlacement;
@ -329,6 +398,7 @@ begin
Layout.Height := HeightEdit.Value; Layout.Height := HeightEdit.Value;
end; end;
end; end;
SaveCurrentSplitterLayout;
end; end;
function TWindowOptionsFrame.GetLayoutCaption(ALayout: TSimpleWindowLayout function TWindowOptionsFrame.GetLayoutCaption(ALayout: TSimpleWindowLayout

View File

@ -2230,6 +2230,11 @@ resourcestring
rsiwpCustomPosition = 'Custom position'; rsiwpCustomPosition = 'Custom position';
rsiwpRestoreWindowSize = 'Restore window size'; rsiwpRestoreWindowSize = 'Restore window size';
rsiwpSplitterFollowWindow = 'Restore with window';
rsiwpSplitterDefault = 'Default Size';
rsiwpSplitterRestoreWindowGeometry = 'Restore Size';
rsiwpSplitterCustomPosition = 'Custom Size';
// Code Explorer // Code Explorer
lisCodeExplorer = 'Code Explorer'; lisCodeExplorer = 'Code Explorer';
lisCode = 'Code'; lisCode = 'Code';
@ -5366,6 +5371,8 @@ resourcestring
lisDiscardChangesAndQuit = 'Discard changes and quit'; lisDiscardChangesAndQuit = 'Discard changes and quit';
dbgBreakPropertyGroupNotFound = 'Some groups in the Enable/Disable list do not exist.%0:s' dbgBreakPropertyGroupNotFound = 'Some groups in the Enable/Disable list do not exist.%0:s'
+'Create them?%0:s%0:s%1:s'; +'Create them?%0:s%0:s%1:s';
dbgLCWatchExpression = 'Watch Expression';
dbgLCWatchValue = 'Watch Value';
implementation implementation

View File

@ -123,6 +123,77 @@ type
TIDEWindowState = (iwsNormal, iwsMaximized, iwsMinimized, iwsHidden); TIDEWindowState = (iwsNormal, iwsMaximized, iwsMinimized, iwsHidden);
TIDEWindowStates = set of TIDEWindowState; TIDEWindowStates = set of TIDEWindowState;
TSimpleWindowLayoutDividerPosPlacement = (
iwpdDefault, // set column/row/splitter to the default size
iwpdCustomSize, // set column/row/splitter to the custom size
iwpdRestore, // save column/row/splitter size on exit, and restore
iwpdUseWindowSetting
);
TSimpleWindowLayoutDividerPosSizeGetter =
function(AForm: TCustomForm; AColId: Integer; var ASize: Integer): Boolean;
TSimpleWindowLayoutDividerPosSizeSetter =
procedure(AForm: TCustomForm; AColId: Integer; ASize: Integer);
{ TSimpleWindowLayoutDividerPos }
TSimpleWindowLayoutDividerPos = class
private
FDefaultSize: integer;
FDisplayName: String;
FId: Integer;
FIdString: String;
FPlacement: TSimpleWindowLayoutDividerPosPlacement;
FSize: integer;
protected
procedure SetDisplayName(ADisplayName: String);
procedure SetId(AnId: Integer);
public
constructor Create(AnIdString: String);
constructor Create(AnIdString: String; AnId: Integer; ADisplayName: String);
procedure Assign(ADividerPos: TSimpleWindowLayoutDividerPos); reintroduce;
procedure LoadFromConfig(Config: TConfigStorage; const Path: string);
procedure SaveToConfig(Config: TConfigStorage; const Path: string);
procedure Clear;
property IdString: String read FIdString;
property Id: Integer read FId;
property DisplayName: String read FDisplayName;
property Placement: TSimpleWindowLayoutDividerPosPlacement read FPlacement write FPlacement;
property Size: integer read FSize write FSize;
property DefaultSize: integer read FDefaultSize write FDefaultSize;
end;
{ TSimpleWindowLayoutDividerPosList }
TSimpleWindowLayoutDividerPosList = class
private
FList: TList;
function GetItems(Index: Integer): TSimpleWindowLayoutDividerPos;
function GetNamedItems(Index: Integer): TSimpleWindowLayoutDividerPos;
protected
procedure Merge(AnItem: TSimpleWindowLayoutDividerPos);
public
constructor Create;
destructor Destroy; override;
procedure Assign(ADividerPosList: TSimpleWindowLayoutDividerPosList); reintroduce;
procedure LoadFromConfig(Config: TConfigStorage; const Path: string);
procedure SaveToConfig(Config: TConfigStorage; const Path: string);
procedure Clear;
procedure ClearItems;
function Add(AnIdString: String; AnId: Integer; ADisplayName: String): TSimpleWindowLayoutDividerPos;
function Add(AnIdString: String): TSimpleWindowLayoutDividerPos;
function Count: Integer;
function NamedCount: Integer;
function Find(AnId: Integer): TSimpleWindowLayoutDividerPos;
function Find(AnIdString: String): TSimpleWindowLayoutDividerPos;
function IndexOf(AnId: Integer): Integer;
function IndexOf(AnIdString: String): Integer;
function IndexOf(AnItem: TSimpleWindowLayoutDividerPos): Integer;
property Items[Index: Integer]: TSimpleWindowLayoutDividerPos read GetItems; default;
property NamedItems[Index: Integer]: TSimpleWindowLayoutDividerPos read GetNamedItems;
end;
{ TSimpleWindowLayout } { TSimpleWindowLayout }
TSimpleWindowLayout = class(TComponent) TSimpleWindowLayout = class(TComponent)
@ -139,6 +210,7 @@ type
fForm: TCustomForm; fForm: TCustomForm;
fFormID: string; fFormID: string;
fDefaultWindowPlacement: TIDEWindowPlacement; fDefaultWindowPlacement: TIDEWindowPlacement;
FDividers: TSimpleWindowLayoutDividerPosList;
function GetFormCaption: string; function GetFormCaption: string;
function GetFormID: string; function GetFormID: string;
procedure SetForm(const AValue: TCustomForm); procedure SetForm(const AValue: TCustomForm);
@ -148,9 +220,13 @@ type
public public
constructor Create(AFormID: string); reintroduce; constructor Create(AFormID: string); reintroduce;
destructor Destroy; override; destructor Destroy; override;
function CreateCopy: TSimpleWindowLayout;
procedure Clear; procedure Clear;
procedure GetCurrentPosition; procedure GetCurrentPosition;
function Apply: Boolean;
procedure ApplyDivider(AForce: Boolean = False);
procedure Assign(Layout: TSimpleWindowLayout); reintroduce; procedure Assign(Layout: TSimpleWindowLayout); reintroduce;
procedure ReadCurrentDividers(AForce: Boolean = False);
procedure ReadCurrentCoordinates; procedure ReadCurrentCoordinates;
procedure ReadCurrentState; procedure ReadCurrentState;
procedure LoadFromConfig(Config: TConfigStorage; const Path: string); procedure LoadFromConfig(Config: TConfigStorage; const Path: string);
@ -172,6 +248,7 @@ type
property Form: TCustomForm read fForm write SetForm; property Form: TCustomForm read fForm write SetForm;
property Visible: boolean read FVisible write FVisible; property Visible: boolean read FVisible write FVisible;
property Applied: boolean read FApplied write FApplied; property Applied: boolean read FApplied write FApplied;
property Dividers: TSimpleWindowLayoutDividerPosList read FDividers;
end; end;
{ TSimpleWindowLayoutList } { TSimpleWindowLayoutList }
@ -250,10 +327,14 @@ type
FBottom: string; FBottom: string;
FLeft: string; FLeft: string;
FMulti: boolean; FMulti: boolean;
FOnGetDividerSize: TSimpleWindowLayoutDividerPosSizeGetter;
FOnGetLayout: TGetDefaultIDEWindowLayoutEvent; FOnGetLayout: TGetDefaultIDEWindowLayoutEvent;
FOnSetDividerSize: TSimpleWindowLayoutDividerPosSizeSetter;
FState: TIWCState; FState: TIWCState;
FTop: string; FTop: string;
FRight: string; FRight: string;
FDividerTemplate: TSimpleWindowLayoutDividerPosList;
function GetDividerTemplate: TSimpleWindowLayoutDividerPosList;
procedure SetBottom(const AValue: string); procedure SetBottom(const AValue: string);
procedure SetLeft(const AValue: string); procedure SetLeft(const AValue: string);
procedure SetTop(const AValue: string); procedure SetTop(const AValue: string);
@ -268,6 +349,7 @@ type
aDockAlign: TAlign = alNone; aDockAlign: TAlign = alNone;
aMulti: boolean = false; aMulti: boolean = false;
GetLayoutEvent: TGetDefaultIDEWindowLayoutEvent = nil); overload; GetLayoutEvent: TGetDefaultIDEWindowLayoutEvent = nil); overload;
destructor Destroy; override;
property FormName: string read FFormName; // prefix for all forms property FormName: string read FFormName; // prefix for all forms
property Multi: boolean read FMulti; // there can be more than one of this form, e.g. the source editors and the package editors property Multi: boolean read FMulti; // there can be more than one of this form, e.g. the source editors and the package editors
property OnCreateFormMethod: TCreateIDEWindowMethod read FCreateFormMethod write FCreateFormMethod; property OnCreateFormMethod: TCreateIDEWindowMethod read FCreateFormMethod write FCreateFormMethod;
@ -286,6 +368,13 @@ type
write FOnGetLayout; write FOnGetLayout;
procedure CheckBoundValue(s: string); procedure CheckBoundValue(s: string);
procedure GetDefaultBounds(AForm: TCustomForm; out DefBounds: TRect); procedure GetDefaultBounds(AForm: TCustomForm; out DefBounds: TRect);
procedure InitSimpleLayout(ALayout: TSimpleWindowLayout);
// TODO: Need a WindowCreator factory, by class of TForm
// then this data can be stored per window class
property DividerTemplate: TSimpleWindowLayoutDividerPosList read GetDividerTemplate;
property OnGetDividerSize: TSimpleWindowLayoutDividerPosSizeGetter read FOnGetDividerSize write FOnGetDividerSize;
property OnSetDividerSize: TSimpleWindowLayoutDividerPosSizeSetter read FOnSetDividerSize write FOnSetDividerSize;
end; end;
{ TIDEWindowCreatorList } { TIDEWindowCreatorList }
@ -431,6 +520,273 @@ begin
RegisterComponents('Misc',[TIDEDialogLayoutStorage]); RegisterComponents('Misc',[TIDEDialogLayoutStorage]);
end; end;
{ TSimpleWindowLayoutDividerPosList }
function TSimpleWindowLayoutDividerPosList.GetItems(Index: Integer): TSimpleWindowLayoutDividerPos;
begin
Result := TSimpleWindowLayoutDividerPos(FList[Index]);
end;
function TSimpleWindowLayoutDividerPosList.GetNamedItems(Index: Integer): TSimpleWindowLayoutDividerPos;
var
i: Integer;
begin
Result := nil;
i := 0;
while i < Count do begin
if Items[i].DisplayName <> '' then begin
if Index = 0 then begin
Result := Items[i];
exit;
end;
dec(Index);
end;
inc(i);
end;
end;
procedure TSimpleWindowLayoutDividerPosList.Merge(AnItem: TSimpleWindowLayoutDividerPos);
var
i: Integer;
old: TSimpleWindowLayoutDividerPos;
begin
i := IndexOf(AnItem.IdString);
FList.Add(AnItem);
if i < 0 then
exit;
old := Items[i];
if AnItem.Id < 0 then
AnItem.SetId(old.Id);
if AnItem.DisplayName = '' then
AnItem.SetDisplayName(old.DisplayName);
if AnItem.DefaultSize < 0 then
AnItem.DefaultSize := old.DefaultSize;
FList.Remove(old);
old.Free;
end;
constructor TSimpleWindowLayoutDividerPosList.Create;
begin
FList := TList.Create;
end;
destructor TSimpleWindowLayoutDividerPosList.Destroy;
begin
Clear;
inherited Destroy;
FreeAndNil(FList);
end;
procedure TSimpleWindowLayoutDividerPosList.Assign(ADividerPosList: TSimpleWindowLayoutDividerPosList);
var
i: Integer;
tmp: TSimpleWindowLayoutDividerPos;
begin
Clear;
for i := 0 to ADividerPosList.Count - 1 do begin
tmp := Add('');
tmp.Assign(ADividerPosList[i]);
end;
end;
procedure TSimpleWindowLayoutDividerPosList.LoadFromConfig(Config: TConfigStorage;
const Path: string);
var
tmp: TSimpleWindowLayoutDividerPos;
c, i: Integer;
begin
ClearItems;
c := Config.GetValue(Path+'Count', 0);
for i := 0 to c - 1 do begin
tmp := TSimpleWindowLayoutDividerPos.Create('');
tmp.LoadFromConfig(Config, Path + 'Item' + IntToStr(i) + '/');
Merge(tmp);
end;
end;
procedure TSimpleWindowLayoutDividerPosList.SaveToConfig(Config: TConfigStorage;
const Path: string);
var
i: Integer;
begin
Config.SetDeleteValue(Path+'Count', Count, 0);
for i := 0 to Count - 1 do
Items[i].SaveToConfig(Config, Path + 'Item' + IntToStr(i) + '/');
end;
procedure TSimpleWindowLayoutDividerPosList.Clear;
begin
while FList.Count > 0 do begin
TObject(FList[0]).Free;
FList.Delete(0);
end;
end;
procedure TSimpleWindowLayoutDividerPosList.ClearItems;
var
i: Integer;
begin
for i := 0 to Count - 1 do
Items[i].Clear;
end;
function TSimpleWindowLayoutDividerPosList.Add(AnIdString: String;
AnId: Integer; ADisplayName: String): TSimpleWindowLayoutDividerPos;
var
i: Integer;
begin
i := IndexOf(AnId);
if i < 0
then begin
Result := TSimpleWindowLayoutDividerPos.Create(AnIdString, AnId, ADisplayName);
FList.Add(Result);
end
else begin
Result := Items[i];
if ADisplayName = '' then
Result.SetDisplayName(ADisplayName);
end
end;
function TSimpleWindowLayoutDividerPosList.Add(AnIdString: String): TSimpleWindowLayoutDividerPos;
begin
Result := Add(AnIdString, -1, '');
end;
function TSimpleWindowLayoutDividerPosList.Count: Integer;
begin
Result := FList.Count;
end;
function TSimpleWindowLayoutDividerPosList.NamedCount: Integer;
var
i: Integer;
begin
Result := 0;
i := Count - 1;
while i >= 0 do begin
if Items[i].DisplayName <> '' then inc(Result);
dec(i);
end;
end;
function TSimpleWindowLayoutDividerPosList.Find(AnId: Integer): TSimpleWindowLayoutDividerPos;
var
i: Integer;
begin
Result := nil;
i := IndexOf(AnId);
if i >= 0 then
Result := Items[i];
end;
function TSimpleWindowLayoutDividerPosList.Find(AnIdString: String): TSimpleWindowLayoutDividerPos;
var
i: Integer;
begin
Result := nil;
i := IndexOf(AnIdString);
if i >= 0 then
Result := Items[i];
end;
function TSimpleWindowLayoutDividerPosList.IndexOf(AnId: Integer): Integer;
begin
Result := Flist.Count-1;
while Result >= 0 do begin
if Items[Result].Id = AnId then
exit;
dec(Result);
end;
end;
function TSimpleWindowLayoutDividerPosList.IndexOf(AnIdString: String): Integer;
begin
Result := Flist.Count-1;
while Result >= 0 do begin
if Items[Result].IdString = AnIdString then
exit;
dec(Result);
end;
end;
function TSimpleWindowLayoutDividerPosList.IndexOf(AnItem: TSimpleWindowLayoutDividerPos): Integer;
begin
Result := FList.IndexOf(AnItem);
end;
{ TSimpleWindowLayoutDividerPos }
procedure TSimpleWindowLayoutDividerPos.SetDisplayName(ADisplayName: String);
begin
FDisplayName := ADisplayName;
end;
procedure TSimpleWindowLayoutDividerPos.SetId(AnId: Integer);
begin
FId := AnId;
end;
constructor TSimpleWindowLayoutDividerPos.Create(AnIdString: String);
begin
Create(AnIdString, -1, '');
end;
constructor TSimpleWindowLayoutDividerPos.Create(AnIdString: String;
AnId: Integer; ADisplayName: String);
begin
FDefaultSize := -1;
Clear;
FId := AnId;
FIdString := AnIdString;
FDisplayName := ADisplayName;
end;
procedure TSimpleWindowLayoutDividerPos.Assign(ADividerPos: TSimpleWindowLayoutDividerPos);
begin
FDefaultSize := ADividerPos.FDefaultSize;
FDisplayName := ADividerPos.FDisplayName;
FId := ADividerPos.FId;
FIdString := ADividerPos.FIdString;
FPlacement := ADividerPos.FPlacement;
FSize := ADividerPos.FSize;
end;
procedure TSimpleWindowLayoutDividerPos.LoadFromConfig(Config: TConfigStorage;
const Path: string);
var
s: String;
begin
Clear;
FIdString := Config.GetValue(Path+'ID', '');
FSize := Config.GetValue(Path+'Size', -1);
s := Config.GetValue(Path+'Placement', 'iwpdUseWindowSetting');
try
ReadStr(s, FPlacement);
except
FPlacement := iwpdUseWindowSetting;
end;
end;
procedure TSimpleWindowLayoutDividerPos.SaveToConfig(Config: TConfigStorage;
const Path: string);
var
s: String;
begin
WriteStr(s, FPlacement);
Config.SetDeleteValue(Path+'ID', FIdString, '');
Config.SetDeleteValue(Path+'Size', FSize, -1);
Config.SetDeleteValue(Path+'Placement', s, 'iwpdUseWindowSetting');
end;
procedure TSimpleWindowLayoutDividerPos.Clear;
begin
FSize := FDefaultSize;
FPlacement := iwpdUseWindowSetting;
end;
{ TIDEDialogLayout } { TIDEDialogLayout }
procedure TIDEDialogLayout.SetList(const AValue: TIDEDialogLayoutList); procedure TIDEDialogLayout.SetList(const AValue: TIDEDialogLayoutList);
@ -667,17 +1023,30 @@ end;
{ TSimpleWindowLayout } { TSimpleWindowLayout }
constructor TSimpleWindowLayout.Create(AFormID: string); constructor TSimpleWindowLayout.Create(AFormID: string);
var
Creator: TIDEWindowCreator;
begin begin
inherited Create(nil); inherited Create(nil);
FDividers := TSimpleWindowLayoutDividerPosList.Create;
FormID:=AFormID; FormID:=AFormID;
fDefaultWindowPlacement:=iwpRestoreWindowGeometry; fDefaultWindowPlacement:=iwpRestoreWindowGeometry;
Clear; Clear;
Creator := IDEWindowCreators.FindWithName(AFormID);
if Creator <> nil then
Creator.InitSimpleLayout(Self);
end; end;
destructor TSimpleWindowLayout.Destroy; destructor TSimpleWindowLayout.Destroy;
begin begin
Form:=nil; Form:=nil;
inherited Destroy; inherited Destroy;
FDividers.Free;
end;
function TSimpleWindowLayout.CreateCopy: TSimpleWindowLayout;
begin
Result := TSimpleWindowLayout.Create(FFormID);
Result.Assign(Self);
end; end;
procedure TSimpleWindowLayout.LoadFromConfig(Config: TConfigStorage; const Path: string); procedure TSimpleWindowLayout.LoadFromConfig(Config: TConfigStorage; const Path: string);
@ -705,6 +1074,7 @@ begin
P+'WindowState/Value',IDEWindowStateNames[fWindowState])); P+'WindowState/Value',IDEWindowStateNames[fWindowState]));
FVisible:=Config.GetValue(P+'Visible/Value',false); FVisible:=Config.GetValue(P+'Visible/Value',false);
//debugln(['TSimpleWindowLayout.LoadFromConfig ',FormID,' ',Left,',',Top,',',Width,',',Height]); //debugln(['TSimpleWindowLayout.LoadFromConfig ',FormID,' ',Left,',',Top,',',Width,',',Height]);
FDividers.LoadFromConfig(Config, P + 'Divider/');
end; end;
procedure TSimpleWindowLayout.SaveToConfig(Config: TConfigStorage; procedure TSimpleWindowLayout.SaveToConfig(Config: TConfigStorage;
@ -729,6 +1099,7 @@ begin
// state // state
Config.SetValue(P+'WindowState/Value',IDEWindowStateNames[fWindowState]); Config.SetValue(P+'WindowState/Value',IDEWindowStateNames[fWindowState]);
Config.SetDeleteValue(P+'Visible/Value',FVisible,false); Config.SetDeleteValue(P+'Visible/Value',FVisible,false);
FDividers.SaveToConfig(Config, P + 'Divider/');
end; end;
procedure TSimpleWindowLayout.OnFormClose(Sender: TObject; procedure TSimpleWindowLayout.OnFormClose(Sender: TObject;
@ -817,6 +1188,7 @@ begin
fWidth:=0; fWidth:=0;
fHeight:=0; fHeight:=0;
fWindowState:=iwsNormal; fWindowState:=iwsNormal;
FDividers.ClearItems;
end; end;
procedure TSimpleWindowLayout.ReadCurrentCoordinates; procedure TSimpleWindowLayout.ReadCurrentCoordinates;
@ -861,6 +1233,31 @@ begin
fWindowState:=Layout.fWindowState; fWindowState:=Layout.fWindowState;
fFormID:=Layout.fFormID; fFormID:=Layout.fFormID;
fDefaultWindowPlacement:=Layout.fDefaultWindowPlacement; fDefaultWindowPlacement:=Layout.fDefaultWindowPlacement;
FDividers.Assign(Layout.FDividers);
end;
procedure TSimpleWindowLayout.ReadCurrentDividers(AForce: Boolean = False);
var
i, j: Integer;
f: Boolean;
Creator: TIDEWindowCreator;
begin
Creator:=IDEWindowCreators.FindWithName(FormID);
if (Creator = nil) or (Creator.OnGetDividerSize = nil) then exit;
if fForm = nil then exit;;
for i := 0 to FDividers.Count - 1 do begin
if FDividers[i].FId < 0 then continue;
f := AForce;
case FDividers[i].Placement of
iwpdRestore:
f := true;
iwpdUseWindowSetting:
f := WindowPlacement in [iwpRestoreWindowGeometry, iwpRestoreWindowSize];
end;
if f then
if Creator.OnGetDividerSize(fForm, FDividers[i].Id, j) then
FDividers[i].Size := j;
end;
end; end;
procedure TSimpleWindowLayout.GetCurrentPosition; procedure TSimpleWindowLayout.GetCurrentPosition;
@ -870,10 +1267,107 @@ begin
iwpRestoreWindowGeometry, iwpRestoreWindowSize: iwpRestoreWindowGeometry, iwpRestoreWindowSize:
ReadCurrentCoordinates; ReadCurrentCoordinates;
end; end;
ReadCurrentDividers;
ReadCurrentState; ReadCurrentState;
//debugln('TSimpleWindowLayout.GetCurrentPosition ',DbgSName(Self),' ',FormID,' Width=',dbgs(Width)); //debugln('TSimpleWindowLayout.GetCurrentPosition ',DbgSName(Self),' ',FormID,' Width=',dbgs(Width));
end; end;
function TSimpleWindowLayout.Apply: Boolean;
var
NewBounds: TRect;
i: Integer;
begin
Result := False;
if fForm = nil then exit;
Applied:=true;
{$IFDEF VerboseIDEDocking}
debugln(['TSimpleWindowLayoutList.ApplyAndShow restore ',
FormID,' ',IDEWindowPlacementNames[WindowPlacement],
' Valid=',CustomCoordinatesAreValid,' ',Left,',',
Top,',',Width,',',Height]);
{$ENDIF}
case WindowPlacement of
iwpCustomPosition,iwpRestoreWindowGeometry:
begin
//DebugLn(['TMainIDE.OnApplyWindowLayout ',IDEWindowStateNames[WindowState]]);
case WindowState of
iwsMinimized: FForm.WindowState:=wsMinimized;
iwsMaximized: FForm.WindowState:=wsMaximized;
end;
if (CustomCoordinatesAreValid) then begin
// explicit position
NewBounds:=Bounds(Left,Top,Width,Height);
// set minimum size
if NewBounds.Right-NewBounds.Left<60 then
NewBounds.Right:=NewBounds.Left+60;
if NewBounds.Bottom-NewBounds.Top<60 then
NewBounds.Bottom:=NewBounds.Top+60;
// Move to visible area :
// window is out at left side of screen
if NewBounds.Right<Screen.DesktopLeft+60 then
OffsetRect(NewBounds,Screen.DesktopLeft+60-NewBounds.Right,0);
// window is out above the screen
if NewBounds.Bottom<Screen.DesktopTop+60 then
OffsetRect(NewBounds,0,Screen.DesktopTop+60-NewBounds.Bottom);
// window is out at right side of screen, i = right edge of screen - 60
i:=Screen.DesktopWidth+Screen.DesktopLeft-60;
if NewBounds.Left > i then begin
NewBounds.Left := i;
NewBounds.Right := NewBounds.Right + i - NewBounds.Left;
end;
// window is out below the screen, i = bottom edge of screen - 60
i:=Screen.DesktopHeight+Screen.DesktopTop-60;
if NewBounds.Top > i then begin
NewBounds.Top := i;
NewBounds.Bottom := NewBounds.Bottom + i - NewBounds.Top;
end;
// set bounds (do not use SetRestoredBounds - that flickers with the current LCL implementation)
FForm.SetBounds(NewBounds.Left,NewBounds.Top,
NewBounds.Right-NewBounds.Left,
NewBounds.Bottom-NewBounds.Top);
Result := True;
end;
if WindowState in [iwsMinimized, iwsMaximized] then
Result := True;
end;
iwpUseWindowManagerSetting:
Result := True;
end;
ApplyDivider;
end;
procedure TSimpleWindowLayout.ApplyDivider(AForce: Boolean = False);
var
i: Integer;
f: Boolean;
Creator: TIDEWindowCreator;
begin
Creator:=IDEWindowCreators.FindWithName(FormID);
if (Creator <> nil) and (Creator.OnSetDividerSize <> nil) then begin
for i := 0 to FDividers.Count - 1 do begin
if (FDividers[i].FId < 0) or (FDividers[i].Size < 0) then continue;
f := AForce;
case FDividers[i].Placement of
iwpdRestore, iwpdCustomSize:
f := true;
iwpdUseWindowSetting:
f := WindowPlacement in [iwpRestoreWindowGeometry, iwpRestoreWindowSize];
end;
if f then
Creator.OnSetDividerSize(fForm, FDividers[i].Id, FDividers[i].Size);
end;
end;
end;
{ TSimpleWindowLayoutList } { TSimpleWindowLayoutList }
procedure TSimpleWindowLayoutList.Clear; procedure TSimpleWindowLayoutList.Clear;
@ -1027,71 +1521,7 @@ begin
begin begin
ALayout.Form:=AForm; ALayout.Form:=AForm;
if ALayout.Applied then exit; if ALayout.Applied then exit;
ALayout.Applied:=true; if ALayout.Apply then exit;
{$IFDEF VerboseIDEDocking}
debugln(['TSimpleWindowLayoutList.ApplyAndShow restore ',
ALayout.FormID,' ',IDEWindowPlacementNames[ALayout.WindowPlacement],
' Valid=',ALayout.CustomCoordinatesAreValid,' ',ALayout.Left,',',
ALayout.Top,',',ALayout.Width,',',ALayout.Height]);
{$ENDIF}
case ALayout.WindowPlacement of
iwpCustomPosition,iwpRestoreWindowGeometry:
begin
//DebugLn(['TMainIDE.OnApplyWindowLayout ',IDEWindowStateNames[ALayout.WindowState]]);
case ALayout.WindowState of
iwsMinimized: AForm.WindowState:=wsMinimized;
iwsMaximized: AForm.WindowState:=wsMaximized;
end;
if (ALayout.CustomCoordinatesAreValid) then begin
// explicit position
NewBounds:=Bounds(ALayout.Left,ALayout.Top,ALayout.Width,ALayout.Height);
// set minimum size
if NewBounds.Right-NewBounds.Left<60 then
NewBounds.Right:=NewBounds.Left+60;
if NewBounds.Bottom-NewBounds.Top<60 then
NewBounds.Bottom:=NewBounds.Top+60;
// Move to visible area :
// window is out at left side of screen
if NewBounds.Right<Screen.DesktopLeft+60 then
OffsetRect(NewBounds,Screen.DesktopLeft+60-NewBounds.Right,0);
// window is out above the screen
if NewBounds.Bottom<Screen.DesktopTop+60 then
OffsetRect(NewBounds,0,Screen.DesktopTop+60-NewBounds.Bottom);
// window is out at right side of screen, i = right edge of screen - 60
i:=Screen.DesktopWidth+Screen.DesktopLeft-60;
if NewBounds.Left > i then begin
NewBounds.Left := i;
NewBounds.Right := NewBounds.Right + i - NewBounds.Left;
end;
// window is out below the screen, i = bottom edge of screen - 60
i:=Screen.DesktopHeight+Screen.DesktopTop-60;
if NewBounds.Top > i then begin
NewBounds.Top := i;
NewBounds.Bottom := NewBounds.Bottom + i - NewBounds.Top;
end;
// set bounds (do not use SetRestoredBounds - that flickers with the current LCL implementation)
AForm.SetBounds(NewBounds.Left,NewBounds.Top,
NewBounds.Right-NewBounds.Left,
NewBounds.Bottom-NewBounds.Top);
exit;
end;
if ALayout.WindowState in [iwsMinimized, iwsMaximized] then
exit;
end;
iwpUseWindowManagerSetting:
begin
exit;
end;
end;
end; end;
{$IFDEF VerboseIDEDocking} {$IFDEF VerboseIDEDocking}
@ -1183,15 +1613,13 @@ begin
end; end;
procedure TSimpleWindowLayoutList.Assign(SrcList: TSimpleWindowLayoutList); procedure TSimpleWindowLayoutList.Assign(SrcList: TSimpleWindowLayoutList);
var i: integer; var
NewLayout: TSimpleWindowLayout; i: integer;
begin begin
Clear; Clear;
if SrcList=nil then exit; if SrcList=nil then exit;
for i:=0 to SrcList.Count-1 do begin for i:=0 to SrcList.Count-1 do begin
NewLayout:=TSimpleWindowLayout.Create(SrcList[i].FormID); Add(SrcList[i].CreateCopy);
NewLayout.Assign(SrcList[i]);
Add(NewLayout);
end; end;
end; end;
@ -1227,6 +1655,13 @@ begin
FBottom:=AValue; FBottom:=AValue;
end; end;
function TIDEWindowCreator.GetDividerTemplate: TSimpleWindowLayoutDividerPosList;
begin
If FDividerTemplate = nil then
FDividerTemplate := TSimpleWindowLayoutDividerPosList.Create;
Result := FDividerTemplate;
end;
procedure TIDEWindowCreator.SetLeft(const AValue: string); procedure TIDEWindowCreator.SetLeft(const AValue: string);
begin begin
CheckBoundValue(AValue); CheckBoundValue(AValue);
@ -1337,9 +1772,18 @@ begin
DefBounds.Bottom:=aBottom; DefBounds.Bottom:=aBottom;
end; end;
procedure TIDEWindowCreator.InitSimpleLayout(ALayout: TSimpleWindowLayout);
begin
if FDividerTemplate <> nil then
ALayout.Dividers.Assign(FDividerTemplate);
end;
constructor TIDEWindowCreator.Create(aFormName: string); constructor TIDEWindowCreator.Create(aFormName: string);
var
sl: TSimpleWindowLayout;
begin begin
FFormName:=aFormName; FFormName:=aFormName;
FDividerTemplate := nil;
end; end;
constructor TIDEWindowCreator.Create(aFormName: string; constructor TIDEWindowCreator.Create(aFormName: string;
@ -1361,6 +1805,12 @@ begin
OnGetLayout:=GetLayoutEvent; OnGetLayout:=GetLayoutEvent;
end; end;
destructor TIDEWindowCreator.Destroy;
begin
inherited Destroy;
FreeAndNil(FDividerTemplate);
end;
function TIDEWindowCreator.NameFits(const AName: string): boolean; function TIDEWindowCreator.NameFits(const AName: string): boolean;
begin begin
Result:=CompareText(copy(AName,1,Length(FormName)),FormName)=0; Result:=CompareText(copy(AName,1,Length(FormName)),FormName)=0;