IDE: Resize the main IDE window correctly. Issue #27940, patch from Ondrej Pokorny.

git-svn-id: trunk@48959 -
This commit is contained in:
juha 2015-05-07 05:21:25 +00:00
parent 052987e5bb
commit b920d6079e
9 changed files with 176 additions and 73 deletions

View File

@ -94,6 +94,8 @@ type
procedure MakeIDEWindowDockable(AControl: TWinControl); override;
function AddableInWindowMenu(AForm: TCustomForm): boolean; override;
procedure ShowForm(AForm: TCustomForm; BringToFront: boolean); override;
procedure AdjustMainIDEWindowHeight(const AIDEWindow: TCustomForm;
const AAdjustHeight: Boolean; const ANewHeight: Integer); override;
procedure CloseAll; override;
procedure OnIDERestoreWindows(Sender: TObject);
function OnProjectClose(Sender: TObject; AProject: TLazProject): TModalResult;
@ -287,6 +289,33 @@ begin
Result:=true;
end;
procedure TIDEAnchorDockMaster.AdjustMainIDEWindowHeight(
const AIDEWindow: TCustomForm; const AAdjustHeight: Boolean;
const ANewHeight: Integer);
var
Site: TAnchorDockHostSite;
I: Integer;
SiteNewHeight: Integer;
begin
inherited AdjustMainIDEWindowHeight(AIDEWindow, AAdjustHeight, ANewHeight);
Site := nil;
for I := 0 to AIDEWindow.ControlCount-1 do
if AIDEWindow.Controls[I] is TAnchorDockHostSite then
begin
Site := TAnchorDockHostSite(AIDEWindow.Controls[I]);
Break;
end;
if not Assigned(Site) then
Exit;
Site.BoundSplitter.Enabled := not AAdjustHeight;
SiteNewHeight := Site.Parent.ClientHeight - ANewHeight - Site.BoundSplitter.Height;
if AAdjustHeight and (Site.Height <> SiteNewHeight) then
Site.Height := SiteNewHeight;
end;
function TIDEAnchorDockMaster.GetUserLayoutFilename(Full: boolean): string;
begin
if CmdLineLayoutFile<>'' then begin

View File

@ -452,6 +452,8 @@ type
procedure MakeIDEWindowDockSite(AForm: TCustomForm; ASides: TDockSides = [alBottom]); virtual; abstract; // make AForm a dock site, AForm can not be docked, its Parent must be kept nil, this does not make it visible
procedure ShowForm(AForm: TCustomForm; BringToFront: boolean); virtual; abstract; // make a form visible, set BringToFront=true if form should be shown on active screen and on front of other windows, normally this focus the form
function AddableInWindowMenu({%H-}AForm: TCustomForm): boolean; virtual;
procedure AdjustMainIDEWindowHeight(const {%H-}AIDEWindow: TCustomForm;
const {%H-}AAdjustHeight: Boolean; const {%H-}ANewHeight: Integer); virtual;
procedure CloseAll; virtual; // close all forms, called after IDE has saved all and shuts down
property HideSimpleLayoutOptions: boolean read FHideSimpleLayoutOptions;
end;
@ -2120,6 +2122,13 @@ begin
Result:=true;
end;
procedure TIDEDockMaster.AdjustMainIDEWindowHeight(
const AIDEWindow: TCustomForm; const AAdjustHeight: Boolean;
const ANewHeight: Integer);
begin
end;
procedure TIDEDockMaster.CloseAll;
begin
CloseAllForms;

View File

@ -97,6 +97,7 @@ type
FPageControl: TPageControl;
FOnOpenPackage: TNotifyEvent;
FOnOpenUnit: TNotifyEvent;
FOnChangeActivePage: TNotifyEvent;
fUnregisteredIcon: TCustomBitmap;
fSelectButtonIcon: TCustomBitmap;
fUpdatingPageControl: boolean;
@ -137,6 +138,7 @@ type
property PageControl: TPageControl read FPageControl write SetPageControl;
property OnOpenPackage: TNotifyEvent read FOnOpenPackage write FOnOpenPackage;
property OnOpenUnit: TNotifyEvent read FOnOpenUnit write FOnOpenUnit;
property OnChangeActivePage: TNotifyEvent read FOnChangeActivePage write FOnChangeActivePage;
end;
function CompareControlsWithTag(Control1, Control2: Pointer): integer;
@ -241,12 +243,9 @@ begin
' IsScrollBarVisible=',ScrollBox.HorzScrollBar.IsScrollBarVisible
]);
{$ENDIF}
MaxBtnPerRow:=ButtonTree.Count;
{$IFnDEF LCLCarbon}
// This condition prevents a mysterious repagination on Windows during startup.
if MainIDE.IDEStarted then
MaxBtnPerRow:=((ScrollBox.VertScrollBar.ClientSizeWithoutBar - ButtonX) div ComponentPaletteBtnWidth);
{$ENDIF}
MaxBtnPerRow:=((ScrollBox.VertScrollBar.ClientSizeWithoutBar - ButtonX) div ComponentPaletteBtnWidth);
// If we need to wrap, make sure we have space for the scrollbar
if MaxBtnPerRow < ButtonTree.Count then
MaxBtnPerRow:=((ScrollBox.VertScrollBar.ClientSizeWithBar - ButtonX) div ComponentPaletteBtnWidth);
@ -515,6 +514,9 @@ begin
{$ENDIF}
ReAlignButtons(FPageControl.ActivePage);
Selected:=nil;
if Assigned(FOnChangeActivePage) then
FOnChangeActivePage(Sender);
end;
procedure TComponentPalette.OnScrollBoxResize(Sender: TObject);

View File

@ -288,6 +288,7 @@ type
FHideIDEOnRun: boolean;
FComponentPaletteVisible: boolean;
FAutoAdjustIDEHeight: boolean;
FAutoAdjustIDEHeightFullComponentPalette: boolean;
// CompletionWindow
FCompletionWindowWidth: Integer;
@ -520,6 +521,7 @@ type
property ComponentPaletteVisible: boolean read FComponentPaletteVisible
write FComponentPaletteVisible;
property AutoAdjustIDEHeight: Boolean read FAutoAdjustIDEHeight write FAutoAdjustIDEHeight;
property AutoAdjustIDEHeightFullComponentPalette: Boolean read FAutoAdjustIDEHeightFullComponentPalette write FAutoAdjustIDEHeightFullComponentPalette;
property CompletionWindowWidth: Integer read FCompletionWindowWidth
write FCompletionWindowWidth;
property CompletionWindowHeight: Integer read FCompletionWindowHeight
@ -882,6 +884,7 @@ begin
FIDEProjectDirectoryInIdeTitle:=false;
FComponentPaletteVisible:=true;
FAutoAdjustIDEHeight:=true;
FAutoAdjustIDEHeightFullComponentPalette := true;
// window menu
FIDENameForDesignedFormList:=false;
@ -1210,6 +1213,8 @@ begin
Path+'Desktop/ComponentPaletteVisible/Value',true);
FAutoAdjustIDEHeight:=XMLConfig.GetValue(
Path+'Desktop/AutoAdjustIDEHeight/Value',true);
FAutoAdjustIDEHeightFullComponentPalette:=XMLConfig.GetValue(
Path+'Desktop/AutoAdjustIDEHeightFullComponentPalette/Value',true);
FCompletionWindowWidth:=XMLConfig.GetValue(
Path+'Desktop/CompletionWindowWidth/Value', 320);
FCompletionWindowHeight:=XMLConfig.GetValue(
@ -1601,6 +1606,8 @@ begin
FComponentPaletteVisible,true);
XMLConfig.SetDeleteValue(Path+'Desktop/AutoAdjustIDEHeight/Value',
FAutoAdjustIDEHeight,true);
XMLConfig.SetDeleteValue(Path+'Desktop/AutoAdjustIDEHeightFullComponentPalette/Value',
FAutoAdjustIDEHeightFullComponentPalette,true);
XMLConfig.SetDeleteValue(Path+'Desktop/CompletionWindowWidth/Value',
FCompletionWindowWidth, 320);
XMLConfig.SetDeleteValue(Path+'Desktop/CompletionWindowHeight/Value',

View File

@ -1,9 +1,9 @@
object WindowOptionsFrame: TWindowOptionsFrame
Left = 0
Height = 582
Height = 585
Top = 0
Width = 573
ClientHeight = 582
ClientHeight = 585
ClientWidth = 573
TabOrder = 0
DesignLeft = 349
@ -41,15 +41,15 @@ object WindowOptionsFrame: TWindowOptionsFrame
AnchorSideTop.Side = asrBottom
AnchorSideBottom.Side = asrBottom
Left = 0
Height = 423
Height = 426
Top = 154
Width = 570
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Top = 3
Caption = 'WindowPositionsPanel'
ClientHeight = 423
ClientHeight = 426
ClientWidth = 570
TabOrder = 7
TabOrder = 8
object LeftLabel: TLabel
AnchorSideTop.Control = LeftEdit
AnchorSideTop.Side = asrCenter
@ -459,7 +459,7 @@ object WindowOptionsFrame: TWindowOptionsFrame
end
object lblWindowPosition: TDividerBevel
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = AutoAdjustIDEHeightCheckBox
AnchorSideTop.Control = AutoAdjustIDEHeightFullComponentPaletteCheckBox
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
@ -486,4 +486,18 @@ object WindowOptionsFrame: TWindowOptionsFrame
ShowHint = True
TabOrder = 6
end
object AutoAdjustIDEHeightFullComponentPaletteCheckBox: TCheckBox
AnchorSideLeft.Control = AutoAdjustIDEHeightCheckBox
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = AutoAdjustIDEHeightCheckBox
Left = 189
Height = 17
Top = 115
Width = 274
BorderSpacing.Left = 20
Caption = 'AutoAdjustIDEHeightFullComponentPaletteCheckBox'
ParentShowHint = False
ShowHint = True
TabOrder = 7
end
end

View File

@ -35,6 +35,7 @@ type
TWindowOptionsFrame = class(TAbstractIDEOptionsEditor)
ApplyButton: TButton;
AutoAdjustIDEHeightFullComponentPaletteCheckBox: TCheckBox;
lblWindowPosition: TDividerBevel;
lblShowingWindows: TDividerBevel;
lblWindowCaption: TDividerBevel;
@ -125,6 +126,8 @@ begin
NameForDesignedFormList.Hint:=lisWindowMenuWithNameForDesignedFormHint;
AutoAdjustIDEHeightCheckBox.Caption:=lisAutoAdjustIDEHeight;
AutoAdjustIDEHeightCheckBox.Hint:=lisAutoAdjustIDEHeightHint;
AutoAdjustIDEHeightFullComponentPaletteCheckBox.Caption:=lisAutoAdjustIDEHeightFullComponentPalette;
AutoAdjustIDEHeightFullComponentPaletteCheckBox.Hint:=lisAutoAdjustIDEHeightFullComponentPaletteHint;
ProjectDirInIdeTitleCheckBox.Caption:=lisIDETitleShowsProjectDir;
ProjectDirInIdeTitleCheckBox.Hint:=lisProjectDirectoryIsShowedInIdeTitleBar;
end;
@ -143,6 +146,7 @@ begin
TitleIncludesBuildMode.Checked:=IDETitleIncludesBuildMode;
NameForDesignedFormList.Checked:=IDENameForDesignedFormList;
AutoAdjustIDEHeightCheckBox.Checked:=AutoAdjustIDEHeight;
AutoAdjustIDEHeightFullComponentPaletteCheckBox.Checked:=AutoAdjustIDEHeightFullComponentPalette;
ProjectDirInIdeTitleCheckBox.Checked:=IDEProjectDirectoryInIdeTitle;
end;
@ -224,6 +228,7 @@ begin
IDETitleIncludesBuildMode := TitleIncludesBuildMode.Checked;
IDENameForDesignedFormList := NameForDesignedFormList.Checked;
AutoAdjustIDEHeight := AutoAdjustIDEHeightCheckBox.Checked;
AutoAdjustIDEHeightFullComponentPalette := AutoAdjustIDEHeightFullComponentPaletteCheckBox.Checked;
IDEProjectDirectoryInIdeTitle:=ProjectDirInIdeTitleCheckBox.Checked;
end;
end;

View File

@ -1260,7 +1260,9 @@ resourcestring
lisIDETitleShowsProjectDir = 'IDE title shows project directory';
lisIDETitleShowsBuildMode = 'IDE title shows selected build mode';
lisAutoAdjustIDEHeight = 'Automatically adjust IDE main window height';
lisAutoAdjustIDEHeightHint = 'Applicable only when not maximized and for undocked IDE.';
lisAutoAdjustIDEHeightHint = '';
lisAutoAdjustIDEHeightFullComponentPalette = 'Show complete component palette';
lisAutoAdjustIDEHeightFullComponentPaletteHint = 'If component palette spans over more lines, show them all and not only one.';
lisWindowMenuWithNameForDesignedForm = 'Window menu shows designed form''s name instead of caption';
lisWindowMenuWithNameForDesignedFormHint = 'Useful especially if the caption is left empty.';
dlgWinPos = 'Window positions';

View File

@ -1517,6 +1517,7 @@ begin
CompPalette.OnOpenPackage:=@PkgMngr.IDEComponentPaletteOpenPackage;
CompPalette.OnOpenUnit:=@PkgMngr.IDEComponentPaletteOpenUnit;
CompPalette.PageControl:=MainIDEBar.ComponentPageControl;
CompPalette.OnChangeActivePage:=@MainIDEBar.SetMainIDEHeightEvent;
// load installed packages
PkgBoss.LoadInstalledPackages;
@ -2002,13 +2003,11 @@ begin
MainIDEBar.MainSplitter.Parent := MainIDEBar;
MainIDEBar.MainSplitter.Align := alLeft;
MainIDEBar.MainSplitter.MinSize := 50;
MainIDEBar.MainSplitter.Tag := 112;
MainIDEBar.MainSplitter.OnMoved := @MainIDEBar.MainSplitterMoved;
MainIDEBar.CoolBar := TCoolBar.Create(OwningComponent);
MainIDEBar.CoolBar.Parent := MainIDEBar;
MainIDEBar.CoolBar.Tag := 112;
if EnvironmentOptions.ComponentPaletteVisible then
begin
MainIDEBar.CoolBar.Align := alLeft;
@ -2017,7 +2016,6 @@ begin
else
MainIDEBar.CoolBar.Align := alClient;
MainIDEBar.mnuMainMenu.Tag := 112;
// IDE Coolbar object wraps MainIDEBar.CoolBar.
IDECoolBar := TIDECoolBar.Create(MainIDEBar.CoolBar);
IDECoolBar.IsVisible := EnvironmentOptions.IDECoolBarOptions.IDECoolBarVisible;;
@ -2050,7 +2048,6 @@ begin
Align := alClient;
Visible:=EnvironmentOptions.ComponentPaletteVisible;
Parent := MainIDEBar;
Tag := 112;
end;
end;
@ -3709,6 +3706,9 @@ begin
MainIDEBar.CoolBar.Align := alClient;
MainIDEBar.MainSplitter.Visible := MainIDEBar.Coolbar.Visible and
MainIDEBar.ComponentPageControl.Visible;
if ComponentPaletteVisible then//when showing component palette, it must be visible to calculate it correctly
MainIDEBar.DoSetMainIDEHeight(MainIDEBar.WindowState = wsMaximized, 100);//it will cause the IDE to flicker, but it's better than to have wrongly calculated IDE height
MainIDEBar.SetMainIDEHeight;
end;

View File

@ -362,12 +362,12 @@ type
const FileNames: array of String);
procedure CoolBarOnChange(Sender: TObject);
procedure MainSplitterMoved(Sender: TObject);
procedure SetMainIDEHeightEvent(Sender: TObject);
private
FOldWindowState: TWindowState;
FOnActive: TNotifyEvent;
procedure NewUnitFormDefaultClick(Sender: TObject);
procedure NewUnitFormPopupMenuPopup(Sender: TObject);
function IsDefaultIDE: Boolean;
function CalcMainIDEHeight: Integer;
function CalcNonClientHeight: Integer;
protected
@ -375,7 +375,6 @@ type
procedure DoShow; override;
procedure WndProc(var Message: TLMessage); override;
procedure DoSetMainIDEHeight(const AIDEIsMaximized: Boolean);
procedure Resizing(State: TWindowState); override;
public
constructor Create(TheOwner: TComponent); override;
@ -386,6 +385,7 @@ type
procedure UpdateDockCaption({%H-}Exclude: TControl); override;
procedure RefreshCoolbar;
procedure SetMainIDEHeight;
procedure DoSetMainIDEHeight(const AIDEIsMaximized: Boolean; ANewHeight: Integer = 0);
end;
var
@ -394,7 +394,7 @@ var
implementation
uses
LCLIntf, LCLType, InterfaceBase, Math;
LCLIntf, LCLType, Math, IDEWindowIntf;
{ TMainIDEBar }
@ -479,27 +479,38 @@ begin
FOnActive(Self);
end;
procedure TMainIDEBar.DoSetMainIDEHeight(const AIDEIsMaximized: Boolean);
var
NewHeight: Integer;
procedure TMainIDEBar.DoSetMainIDEHeight(const AIDEIsMaximized: Boolean;
ANewHeight: Integer);
begin
if not (Showing and IsDefaultIDE) then
if not Showing then
Exit;
if (AIDEIsMaximized or EnvironmentOptions.AutoAdjustIDEHeight) then
if ANewHeight <= 0 then
ANewHeight := CalcMainIDEHeight;
if Assigned(IDEDockMaster) then
begin
NewHeight := CalcMainIDEHeight + CalcNonClientHeight;
if NewHeight <> Constraints.MaxHeight then
begin
Constraints.MaxHeight := NewHeight;
Constraints.MinHeight := Constraints.MaxHeight;
ClientHeight := Constraints.MaxHeight;
end;
if EnvironmentOptions.AutoAdjustIDEHeight then
IDEDockMaster.AdjustMainIDEWindowHeight(Self, True, ANewHeight)
else
IDEDockMaster.AdjustMainIDEWindowHeight(Self, False, 0);
end else
if Constraints.MaxHeight <> 0 then
begin
Constraints.MaxHeight := 0;
Constraints.MinHeight := 0;
if (AIDEIsMaximized or EnvironmentOptions.AutoAdjustIDEHeight) then
begin
ANewHeight := ANewHeight + CalcNonClientHeight;
if ANewHeight <> Constraints.MaxHeight then
begin
Constraints.MaxHeight := ANewHeight;
Constraints.MinHeight := Constraints.MaxHeight;
ClientHeight := Constraints.MaxHeight;
end;
end else
if Constraints.MaxHeight <> 0 then
begin
Constraints.MaxHeight := 0;
Constraints.MinHeight := 0;
end;
end;
end;
@ -507,24 +518,58 @@ procedure TMainIDEBar.DoShow;
begin
inherited DoShow;
RefreshCoolbar;
ComponentPageControl.OnChange(Self);//refresh component palette with button reposition
end;
function TMainIDEBar.CalcNonClientHeight: Integer;
{$IF DEFINED(LCLWin32) OR DEFINED(LCLGtk2)}
var
WindowRect, WindowClientRect: TRect;
{$ENDIF}
begin
if Showing then
begin
LclIntf.GetWindowRect(Handle, WindowRect{%H-});
LclIntf.GetClientRect(Handle, WindowClientRect{%H-});
LclIntf.ClientToScreen(Handle, WindowClientRect.TopLeft);
{
This function is a bug-workaround for various LCL widgetsets.
Every widgetset handles constrained height differently.
In an ideal word (when the bugs are fixed), this function shouldn't be
needed at all - it should return always 0.
Result := WindowClientRect.Top - WindowRect.Top;
Currently tested: Win32, Gtk2, Carbon.
if Pos('Win32', WidgetSet.ClassName) > 0 then//TWin32WidgetSet widgetset bug -> the constrained height has to be without SM_CYSIZEFRAME and SM_CYMENU (Gtk2 works fine)
Result := Result - (LCLIntf.GetSystemMetrics(SM_CYSIZEFRAME) + LCLIntf.GetSystemMetrics(SM_CYMENU));
end else
Result := 0;
List of bugs related to this workaround:
http://bugs.freepascal.org/view.php?id=28033
http://bugs.freepascal.org/view.php?id=28034
http://bugs.freepascal.org/view.php?id=28036
}
if not Showing then
Exit(0);
{$IF DEFINED(LCLWin32) OR DEFINED(LCLGtk2)}
//Gtk2 + Win32
//retrieve real main menu height because
// - Win32: multi-line is possible (SM_CYMENU reflects only single line)
// - Gtk2: SM_CYMENU does not work
LclIntf.GetWindowRect(Handle, WindowRect{%H-});
LclIntf.GetClientRect(Handle, WindowClientRect{%H-});
LclIntf.ClientToScreen(Handle, WindowClientRect.TopLeft);
Result := WindowClientRect.Top - WindowRect.Top;
{$IFDEF LCLWin32}
//Win32 the constrained height has to be without SM_CYSIZEFRAME and SM_CYMENU
Result := Result - (LCLIntf.GetSystemMetrics(SM_CYSIZEFRAME) + LCLIntf.GetSystemMetrics(SM_CYMENU));
{$ENDIF LCLWin32}
{$ELSE}
//other widgetsets
//Carbon & Qt tested - they behave correctly
Result := 0;
{$ENDIF}
end;
procedure TMainIDEBar.SetMainIDEHeightEvent(Sender: TObject);
begin
SetMainIDEHeight;
end;
procedure TMainIDEBar.WndProc(var Message: TLMessage);
@ -671,21 +716,27 @@ begin
end;
end;
if EnvironmentOptions.ComponentPaletteVisible then
if EnvironmentOptions.ComponentPaletteVisible and Assigned(ComponentPageControl.ActivePage) then
begin
for I := 0 to ComponentPageControl.PageCount-1 do
if (ComponentPageControl.Page[I].ControlCount > 0) and (ComponentPageControl.Page[I].Controls[0] is TScrollBox) then
ComponentScrollBox := nil;
for I := 0 to ComponentPageControl.ActivePage.ControlCount-1 do
if (ComponentPageControl.ActivePage.Controls[I] is TScrollBox) then
begin
ComponentScrollBox := TScrollBox(ComponentPageControl.Page[I].Controls[0]);
if ComponentScrollBox.ControlCount > 0 then
begin
SBControl := ComponentScrollBox.Controls[0];
NewHeight :=
SBControl.Top + SBControl.Height + //button height
ComponentPageControl.Height - ComponentScrollBox.ClientHeight; //page control non-client height (tabs, borders).
Result := Max(Result, NewHeight);
ComponentScrollBox := TScrollBox(ComponentPageControl.ActivePage.Controls[I]);
Break;
end;
if Assigned(ComponentScrollBox) then
for I := 0 to ComponentScrollBox.ControlCount-1 do
begin
SBControl := ComponentScrollBox.Controls[I];
NewHeight :=
SBControl.Top + SBControl.Height + //button height
ComponentPageControl.Height - ComponentScrollBox.ClientHeight; //page control non-client height (tabs, borders).
Result := Max(Result, NewHeight);
if not EnvironmentOptions.AutoAdjustIDEHeightFullComponentPalette then
Break; //we need only one button (we calculate one line only)
end;
end;
end;
end;
@ -717,21 +768,5 @@ begin
DoSetMainIDEHeight(WindowState = wsMaximized);
end;
function TMainIDEBar.IsDefaultIDE: Boolean;
var
I: Integer;
begin
Result := True;
for I := 0 to MainIDEBar.ControlCount - 1 do
begin
if (MainIDEBar.Controls[I] as TControl).Tag <> 112 then
begin
Result := False;
Break;
end;
end;
end;
end.