DockedFormEditor: Solve the unrecoverable loop differently. Add a new handler for it. Issue #39288.

This commit is contained in:
Juha 2023-07-20 23:11:07 +03:00
parent ae1c9e4710
commit 5a647cd4e1
5 changed files with 41 additions and 36 deletions

View File

@ -22,8 +22,10 @@ uses
Classes, SysUtils, fgl,
// LCL
LMessages, Forms, LCLType, LCLIntf, Controls,
// LazUtils
LazLoggerBase,
// IDEIntf
SrcEditorIntf, LazIDEIntf, ProjectIntf,
SrcEditorIntf,
// DockedFormEditor
DockedFormAccesses, DockedBasicAnchorDesigner;
@ -42,12 +44,14 @@ type
FHiding: Boolean;
FOnAdjustPageNeeded: TNotifyEvent;
FWndMethod: TWndMethod;
class var FNewForm: TCustomForm;
procedure FixF12_ActiveEditor;
procedure FormChangeBounds(Sender: TObject);
procedure WndMethod(var Msg: TLMessage);
public
constructor Create(AForm: TCustomForm); override;
destructor Destroy; override;
class procedure Screen_NewFormCreated(Sender: TObject; AForm: TCustomForm);
public
property Hiding: Boolean read FHiding write FHiding;
property OnAdjustPageNeeded: TNotifyEvent read FOnAdjustPageNeeded write FOnAdjustPageNeeded;
@ -56,10 +60,7 @@ type
{ TDesignForms }
TDesignForms = class(specialize TFPGList<TDesignForm>)
private
FProjectOpening: Boolean;
public
constructor Create;
destructor Destroy; override;
function Add(const Item: TDesignForm): Integer;
procedure DeleteDesignForm(AIndex: Integer);
@ -68,9 +69,6 @@ type
function IndexOf(AForm: TCustomForm): Integer; overload;
procedure Remove(AForm: TCustomForm); overload;
procedure RemoveAllAnchorDesigner;
// Project state change event handlers.
function ProjOpening(Sender: TObject; AProject: TLazProject): TModalResult;
function ProjOpened(Sender: TObject; AProject: TLazProject): TModalResult;
end;
var
@ -80,20 +78,24 @@ implementation
{ TDesignForm }
class procedure TDesignForm.Screen_NewFormCreated(Sender: TObject; AForm: TCustomForm);
begin
FNewForm := AForm;
//DebugLn(['TDesignForm.Screen_NewFormCreated! Self=', Self,
// ', FNewForm=', FNewForm.Name,':',FNewForm.ClassName]);
end;
procedure TDesignForm.FixF12_ActiveEditor;
var
i: Integer;
begin
// Don't get a form's designer while project opens.
// A read error would lead to an eternal loop.
Assert(Assigned(FContainer), 'TDesignForm.FixF12_ActiveEditor: FContainer=Nil');
if FContainer.FProjectOpening then Exit;
//DebugLn(['TDesignForm.FixF12_ActiveEditor: Self=', Self, ', FNewForm=', FNewForm, ', Form=', Form]);
if FNewForm = Nil then exit;
FNewForm := Nil;
//DebugLn([' TDesignForm.FixF12_ActiveEditor: Passed']);
// 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.
// Without this, button F12 don't work after creating a new form.
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
@ -175,17 +177,8 @@ end;
{ TDesignForms }
constructor TDesignForms.Create;
begin
inherited;
LazarusIDE.AddHandlerOnProjectOpening(@ProjOpening);
LazarusIDE.AddHandlerOnProjectOpened(@ProjOpened);
end;
destructor TDesignForms.Destroy;
begin
//LazarusIDE.RemoveHandlerOnProjectOpened(@ProjOpened); // Causes a crash.
//LazarusIDE.RemoveHandlerOnProjectOpening(@ProjOpening);
while Count > 0 do
DeleteDesignForm(0);
inherited Destroy;
@ -264,17 +257,5 @@ begin
end;
end;
function TDesignForms.ProjOpening(Sender: TObject; AProject: TLazProject): TModalResult;
begin
FProjectOpening := True;
Result := mrOK;
end;
function TDesignForms.ProjOpened(Sender: TObject; AProject: TLazProject): TModalResult;
begin
FProjectOpening := False;
Result := mrOK;
end;
end.

View File

@ -37,6 +37,7 @@ procedure Register;
begin
Screen.AddHandlerFormAdded(TDockedMainIDE.Screen_FormAdded);
Screen.AddHandlerRemoveForm(TDockedMainIDE.Screen_FormDel);
Screen.AddHandlerNewFormCreated(TDesignForm.Screen_NewFormCreated);
SourceEditorManagerIntf.RegisterChangeEvent(semWindowCreate, TDockedMainIDE.WindowCreate);
SourceEditorManagerIntf.RegisterChangeEvent(semWindowDestroy, TDockedMainIDE.WindowDestroy);
SourceEditorManagerIntf.RegisterChangeEvent(semWindowShow, TDockedMainIDE.WindowShow);
@ -65,6 +66,7 @@ begin
end;
finalization
Screen.RemoveHandlerNewFormCreated(TDesignForm.Screen_NewFormCreated);
Screen.RemoveHandlerFormAdded(TDockedMainIDE.Screen_FormAdded);
Screen.RemoveHandlerRemoveForm(TDockedMainIDE.Screen_FormDel);
FreeAndNil(DesignForms);

View File

@ -4606,6 +4606,7 @@ begin
Project1.AddCreateFormToProjectFile(NewComponent.ClassName,
NewComponent.Name);
end;
Screen.NewFormWasCreated(TCustomForm(NewComponent));
Result:=mrOk;
end;

View File

@ -1103,6 +1103,7 @@ type
LastControl: TControl) of object;
TScreenNotification = (
snNewFormCreated,
snFormAdded,
snRemoveForm,
snActiveControlChanged,
@ -1210,6 +1211,7 @@ type
function CustomFormZIndex(AForm: TCustomForm): Integer;
procedure MoveFormToFocusFront(ACustomForm: TCustomForm);
procedure MoveFormToZFront(ACustomForm: TCustomForm);
procedure NewFormWasCreated(AForm: TCustomForm);
function GetCurrentModalForm: TCustomForm;
function GetCurrentModalFormZIndex: Integer;
function CustomFormBelongsToActiveGroup(AForm: TCustomForm): Boolean;
@ -1221,6 +1223,9 @@ type
procedure UpdateScreen;
// handler
procedure RemoveAllHandlersOfObject(AnObject: TObject); override;
procedure AddHandlerNewFormCreated(OnNewFormCreated: TScreenFormEvent;
AsFirst: Boolean=false);
procedure RemoveHandlerNewFormCreated(OnNewFormCreated: TScreenFormEvent);
procedure AddHandlerFormAdded(OnFormAdded: TScreenFormEvent;
AsFirst: Boolean=false);
procedure RemoveHandlerFormAdded(OnFormAdded: TScreenFormEvent);

View File

@ -178,6 +178,11 @@ begin
end;
end;
procedure TScreen.NewFormWasCreated(AForm: TCustomForm);
begin
NotifyScreenFormHandler(snNewFormCreated,AForm);
end;
function TScreen.GetCurrentModalForm: TCustomForm;
var
i: Integer;
@ -280,6 +285,17 @@ begin
inherited RemoveAllHandlersOfObject(AnObject);
end;
procedure TScreen.AddHandlerNewFormCreated(OnNewFormCreated: TScreenFormEvent;
AsFirst: Boolean);
begin
AddHandler(snNewFormCreated,TMethod(OnNewFormCreated),AsFirst);
end;
procedure TScreen.RemoveHandlerNewFormCreated(OnNewFormCreated: TScreenFormEvent);
begin
RemoveHandler(snNewFormCreated,TMethod(OnNewFormCreated));
end;
procedure TScreen.AddHandlerFormAdded(OnFormAdded: TScreenFormEvent;
AsFirst: Boolean);
begin