{ ***************************************************************************** See the file COPYING.modifiedLGPL.txt, included in this distribution, for details about the license. ***************************************************************************** Author: Maciej Izak DaThoX 2004-2015 FreeSparta.com } unit DockedFormAccesses; {$mode objfpc}{$H+} interface uses Classes, SysUtils, // LCL Forms, Controls, LCLIntf, LCLType, // IdeIntf FormEditingIntf, SrcEditorIntf, ObjectInspector, ComponentEditors, // DockedFormEditor DockedBasicAnchorDesigner; type { TFormAccess } TFormAccess = class private FForm: TCustomForm; FOnChangeHackedBounds: TNotifyEvent; FUpdate: Boolean; protected function GetPublishedBounds(AIndex: Integer): Integer; procedure SetPublishedBounds(AIndex: Integer; AValue: Integer); procedure DoChangeHackedBounds; public constructor Create(AForm: TCustomForm); virtual; procedure BeginUpdate; virtual; function ClientOffset: TPoint; procedure EndUpdate({%H-}AModified: Boolean = False); virtual; procedure HideWindow; procedure ShowWindow; public property Form: TCustomForm read FForm; property Left: Integer index 0 read GetPublishedBounds write SetPublishedBounds; property Top: Integer index 1 read GetPublishedBounds write SetPublishedBounds; property Width: Integer index 2 read GetPublishedBounds write SetPublishedBounds; property Height: Integer index 3 read GetPublishedBounds write SetPublishedBounds; property OnChangeHackedBounds: TNotifyEvent read FOnChangeHackedBounds write FOnChangeHackedBounds; property Update: Boolean read FUpdate; end; { TDesignFormIDE } TDesignFormIDE = class(TFormAccess) private FAnchorDesigner: TBasicAnchorDesigner; FLastActiveSourceWindow: TSourceEditorWindowInterface; FSelectedControl: TControl; function GetCurrentObjectInspector: TObjectInspectorDlg; function GetDesigner: TIDesigner; function GetDesignWinControl: TWinControl; public constructor Create(AForm: TCustomForm); override; destructor Destroy; override; procedure BeginUpdate; override; procedure EndUpdate(AModified: Boolean = False); override; function IsAnchorDesign: Boolean; function MainMenuFaked: Boolean; function MainMenuHeight: Integer; public property AnchorDesigner: TBasicAnchorDesigner read FAnchorDesigner write FAnchorDesigner; property CurrentObjectInspector: TObjectInspectorDlg read GetCurrentObjectInspector; property Designer: TIDesigner read GetDesigner; property DesignWinControl: TWinControl read GetDesignWinControl; property LastActiveSourceWindow: TSourceEditorWindowInterface read FLastActiveSourceWindow write FLastActiveSourceWindow; property SelectedControl: TControl read FSelectedControl write FSelectedControl; end; implementation type THackForm = class(TForm); { TDesignFormIDE } function TFormAccess.GetPublishedBounds(AIndex: Integer): Integer; begin case AIndex of 0: Result := FForm.Left; 1: Result := FForm.Top; 2: Result := FForm.Width; 3: Result := FForm.Height; end; end; procedure TFormAccess.SetPublishedBounds(AIndex: Integer; AValue: Integer); const cMinWidth = 135; cMaxWidth = 5*1024; // huge Mac monitors have 5K pixels width begin if AIndex = 2 then if AValue < cMinWidth then AValue := cMinWidth; if AIndex in [2, 3] then if AValue > cMaxWidth then AValue := cMaxWidth; DoChangeHackedBounds; end; procedure TFormAccess.DoChangeHackedBounds; begin if not FUpdate and Assigned(FOnChangeHackedBounds) then FOnChangeHackedBounds(FForm); end; constructor TFormAccess.Create(AForm: TCustomForm); begin FForm := AForm; FUpdate := False; end; procedure TFormAccess.BeginUpdate; begin FUpdate := True; end; function TFormAccess.ClientOffset: TPoint; begin Result := Point(0, 0); {$IFDEF LCLWin32} Result.X := GetSystemMetrics(SM_CXSIZEFRAME); Result.Y := GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION); {$ENDIF} end; procedure TFormAccess.EndUpdate(AModified: Boolean); begin FUpdate := False; end; procedure TFormAccess.HideWindow; begin if FForm.Parent = nil then LCLIntf.ShowWindow(FForm.Handle, SW_HIDE); end; procedure TFormAccess.ShowWindow; begin if FForm.Parent = nil then LCLIntf.ShowWindow(FForm.Handle, SW_SHOW); end; { TDesignFormIDE } function TDesignFormIDE.GetDesigner: TIDesigner; begin Result := FForm.Designer; end; function TDesignFormIDE.GetCurrentObjectInspector: TObjectInspectorDlg; begin if Assigned(FormEditingHook) and (FormEditingHook.GetCurrentDesigner = Designer) then Result := FormEditingHook.GetCurrentObjectInspector else Result := nil; end; function TDesignFormIDE.GetDesignWinControl: TWinControl; begin Result := Form; if Form is TNonFormProxyDesignerForm then if TNonFormProxyDesignerForm(Form).LookupRoot is TWinControl then Result := TWinControl(TNonFormProxyDesignerForm(Form).LookupRoot) else Result := nil; end; constructor TDesignFormIDE.Create(AForm: TCustomForm); begin inherited Create(AForm); FAnchorDesigner := nil; FLastActiveSourceWindow := nil; end; destructor TDesignFormIDE.Destroy; begin FreeAndNil(FAnchorDesigner); inherited Destroy; end; procedure TDesignFormIDE.BeginUpdate; begin THackForm(FForm).SetDesigning(False, False); if Assigned(FAnchorDesigner) then FAnchorDesigner.BeginUpdate; inherited BeginUpdate; end; procedure TDesignFormIDE.EndUpdate(AModified: Boolean); begin THackForm(FForm).SetDesigning(True, False); if Assigned(FAnchorDesigner) then FAnchorDesigner.EndUpdate; inherited EndUpdate(AModified); if AModified and Assigned(CurrentObjectInspector) then CurrentObjectInspector.RefreshPropertyValues; end; function TDesignFormIDE.IsAnchorDesign: Boolean; begin Result := Assigned(DesignWinControl); end; function TDesignFormIDE.MainMenuFaked: Boolean; var i: Integer; begin Result := False; // {$IF DEFINED(LCLWin32) OR DEFINED(LCLGtk2) OR DEFINED(LCLQt) OR DEFINED(LCLQt5)} {$IF DEFINED(LCLQt) OR DEFINED(LCLQt5)} // Menu is already shown in designer Exit; {$ENDIF} if Assigned(Form.Menu) and not (csDestroying in Form.Menu.ComponentState) and (Form.Menu.Items.Count > 0) then for i := 0 to Form.Menu.Items.Count - 1 do if Form.Menu.Items[i].Visible then Exit(True); end; function TDesignFormIDE.MainMenuHeight: Integer; begin // some WS (Gtk2) return too big SM_CYMENU, just set it according to font height // no problem, it is used only for the fake main menu {$IFDEF LCLWin32} Result := lclintf.GetSystemMetrics(SM_CYMENU); {$ELSE} if Form.HandleAllocated then Result := Form.Canvas.TextHeight('Hg') * 4 div 3 else Result := 20; {$ENDIF} end; end.