mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-12 04:02:31 +02:00
246 lines
6.1 KiB
ObjectPascal
246 lines
6.1 KiB
ObjectPascal
{
|
|
*****************************************************************************
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
|
|
Authors: Maciej Izak
|
|
Michael W. Vogel
|
|
|
|
}
|
|
|
|
unit DockedDesignForm;
|
|
|
|
{$mode objfpc}{$H+}
|
|
{$modeswitch advancedrecords}
|
|
{$modeswitch typehelpers}
|
|
|
|
interface
|
|
|
|
uses
|
|
// RTL
|
|
Classes, SysUtils, fgl,
|
|
// LCL
|
|
LMessages, Forms, LCLType, LCLIntf, Controls,
|
|
// IDEIntf
|
|
SrcEditorIntf,
|
|
// DockedFormEditor
|
|
DockedFormAccesses, DockedBasicAnchorDesigner;
|
|
|
|
const
|
|
WM_SETNOFRAME = WM_USER;
|
|
WM_BOUNDTODESIGNTABSHEET = WM_USER + 1;
|
|
|
|
type
|
|
{ TDesignForm }
|
|
|
|
TDesignForm = class(TDesignFormIDE)
|
|
private
|
|
FHiding: Boolean;
|
|
FOnAdjustPageNeeded: TNotifyEvent;
|
|
FWndMethod: TWndMethod;
|
|
procedure FixF12_ActiveEditor;
|
|
procedure FormChangeBounds(Sender: TObject);
|
|
procedure WndMethod(var Msg: TLMessage);
|
|
public
|
|
constructor Create(AForm: TCustomForm); override;
|
|
destructor Destroy; override;
|
|
public
|
|
property Hiding: Boolean read FHiding write FHiding;
|
|
property OnAdjustPageNeeded: TNotifyEvent read FOnAdjustPageNeeded write FOnAdjustPageNeeded;
|
|
end;
|
|
|
|
{ TDesignForms }
|
|
|
|
TDesignForms = class(specialize TFPGList<TDesignForm>)
|
|
public
|
|
destructor Destroy; override;
|
|
procedure DeleteDesignForm(AIndex: Integer);
|
|
function Find(AForm: TCustomForm): TDesignForm; overload;
|
|
function Find(ADesigner: TIDesigner): TDesignForm; overload;
|
|
function IndexOf(AForm: TCustomForm): Integer; overload;
|
|
procedure Remove(AForm: TCustomForm); overload;
|
|
procedure RemoveAllAnchorDesigner;
|
|
end;
|
|
|
|
var
|
|
DesignForms: TDesignForms;
|
|
|
|
implementation
|
|
|
|
{ TDesignForm }
|
|
|
|
procedure TDesignForm.FixF12_ActiveEditor;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
// Without this, button F12 don't work. (after creating new for editor is inactive)
|
|
// Just do it for new created forms or the last loaded form becomes the active
|
|
// source editor after reopening a project.
|
|
if Designer <> SourceEditorManagerIntf.ActiveEditor.GetDesigner(True) then Exit;
|
|
|
|
SourceEditorManagerIntf.ActiveEditor := nil;
|
|
for i := 0 to SourceEditorManagerIntf.UniqueSourceEditorCount - 1 do
|
|
if Designer = SourceEditorManagerIntf.UniqueSourceEditors[i].GetDesigner(True) then
|
|
begin
|
|
SourceEditorManagerIntf.ActiveEditor := SourceEditorManagerIntf.UniqueSourceEditors[i];
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
procedure TDesignForm.FormChangeBounds(Sender: TObject);
|
|
begin
|
|
if not Update then
|
|
SetTimer(Form.Handle, WM_BOUNDTODESIGNTABSHEET, 10, nil);
|
|
end;
|
|
|
|
procedure TDesignForm.WndMethod(var Msg: TLMessage);
|
|
var
|
|
Timer: TLMTimer;
|
|
begin
|
|
if Msg.msg = LM_TIMER then
|
|
begin
|
|
Timer := TLMTimer(Msg);
|
|
case Timer.TimerID of
|
|
WM_SETNOFRAME:
|
|
begin
|
|
KillTimer(Form.Handle, WM_SETNOFRAME);
|
|
LCLIntf.ShowWindow(Form.Handle, SW_HIDE);
|
|
FHiding := False;
|
|
FixF12_ActiveEditor;
|
|
Exit;
|
|
end;
|
|
WM_BOUNDTODESIGNTABSHEET:
|
|
begin
|
|
KillTimer(Form.Handle, WM_BOUNDTODESIGNTABSHEET);
|
|
if Assigned(FOnAdjustPageNeeded) then
|
|
FOnAdjustPageNeeded(Self);
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
case Msg.msg of
|
|
{$IFDEF LCLWin32}
|
|
// we need to correct ActiveEditor to right form
|
|
// this code works correctly on Windows platform
|
|
// (is necessery for selecting controls after form resizing).
|
|
// in Linux platforms below code brings problems with QT (inactive form)
|
|
LM_LBUTTONDOWN, LM_RBUTTONDOWN, LM_MBUTTONDOWN, LM_XBUTTONDOWN:
|
|
if LastActiveSourceWindow <> nil then
|
|
begin
|
|
SourceEditorManagerIntf.ActiveSourceWindow := LastActiveSourceWindow;
|
|
SourceEditorManagerIntf.ActiveEditor := LastActiveSourceWindow.ActiveEditor;
|
|
end;
|
|
{$ENDIF}
|
|
// Prevent usage of parent hint (SourceEditorWindow), see issue #39217
|
|
CM_PARENTSHOWHINTCHANGED:
|
|
begin
|
|
Msg.Result := 0;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
FWndMethod(Msg);
|
|
end;
|
|
|
|
constructor TDesignForm.Create(AForm: TCustomForm);
|
|
begin
|
|
inherited Create(AForm);
|
|
AForm.AddHandlerOnChangeBounds(@FormChangeBounds);
|
|
FWndMethod := Form.WindowProc;
|
|
Form.WindowProc := @WndMethod;
|
|
end;
|
|
|
|
destructor TDesignForm.Destroy;
|
|
begin
|
|
Form.WindowProc := FWndMethod; // ! important risky point :P
|
|
Form.RemoveHandlerOnChangeBounds(@FormChangeBounds);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ TDesignForms }
|
|
|
|
destructor TDesignForms.Destroy;
|
|
begin
|
|
while Count > 0 do
|
|
DeleteDesignForm(0);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TDesignForms.DeleteDesignForm(AIndex: Integer);
|
|
var
|
|
LDesignForm: TDesignForm;
|
|
begin
|
|
LDesignForm := Self[AIndex];
|
|
LDesignForm.Free;
|
|
Delete(AIndex);
|
|
end;
|
|
|
|
function TDesignForms.Find(AForm: TCustomForm): TDesignForm;
|
|
var
|
|
LDesignForm: TDesignForm;
|
|
begin
|
|
// sometimes at some level of initialization form can not contain TIDesigner
|
|
// (during ide run and when is oppened default project with some TForm1)
|
|
Result := nil;
|
|
if AForm = nil then Exit;
|
|
for LDesignForm in Self do
|
|
if LDesignForm.Form = AForm then
|
|
Exit(LDesignForm);
|
|
end;
|
|
|
|
function TDesignForms.Find(ADesigner: TIDesigner): TDesignForm;
|
|
var
|
|
LDesignForm: TDesignForm;
|
|
begin
|
|
Result := nil;
|
|
if ADesigner = nil then Exit;
|
|
for LDesignForm in Self do
|
|
if LDesignForm.Designer = ADesigner then
|
|
Exit(LDesignForm);
|
|
end;
|
|
|
|
function TDesignForms.IndexOf(AForm: TCustomForm): Integer;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
Result := -1;
|
|
for i := 0 to Count - 1 do
|
|
if Items[i].Form = AForm then
|
|
Exit(i);
|
|
end;
|
|
|
|
procedure TDesignForms.Remove(AForm: TCustomForm);
|
|
var
|
|
LIndex: Integer;
|
|
begin
|
|
LIndex := IndexOf(AForm);
|
|
if LIndex < 0 then Exit;
|
|
Items[LIndex].Free;
|
|
Delete(LIndex);
|
|
end;
|
|
|
|
procedure TDesignForms.RemoveAllAnchorDesigner;
|
|
var
|
|
LDesignForm: TDesignForm;
|
|
LAnchorDesigner: TBasicAnchorDesigner;
|
|
begin
|
|
for LDesignForm in Self do
|
|
begin
|
|
LAnchorDesigner := LDesignForm.AnchorDesigner;
|
|
if not Assigned(LAnchorDesigner) then Continue;
|
|
LAnchorDesigner.Free;
|
|
LDesignForm.AnchorDesigner := nil;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
DesignForms := TDesignForms.Create;
|
|
|
|
finalization
|
|
FreeAndNil(DesignForms);
|
|
|
|
end.
|
|
|