lazarus/components/sparta/mdi/source/sparta_basicfakecustom.pas
2020-01-29 23:43:04 +00:00

558 lines
15 KiB
ObjectPascal

unit sparta_BasicFakeCustom;
{$mode delphi}{$H+}
interface
uses
Classes, SysUtils,
LCLType, LCLIntf, Controls, Forms,
sparta_InterfacesMDI, sparta_FormBackgroundForMDI;
type
{ TFormImpl }
TFormImpl = class(TComponent, IDesignedRealFormHelper, IDesignedForm)
private
FDesignedRealForm: IDesignedRealForm;
FHackLeft: Integer;
FHackTop: Integer;
FHackWidth: Integer;
FHackHeight: Integer;
FOnChangeHackedBounds: TNotifyEvent;
protected
FForm: TCustomForm;
FUpdate: boolean;
procedure SetOnChangeHackedBounds(const AValue: TNotifyEvent);
function GetOnChangeHackedBounds: TNotifyEvent;
function PositionDelta: TPoint;
function GetRealBounds(AIndex: Integer): Integer; virtual;
procedure SetRealBounds(AIndex: Integer; AValue: Integer); virtual;
function GetPublishedBounds(AIndex: Integer): Integer; virtual;
procedure SetPublishedBounds(AIndex: Integer; AValue: Integer); virtual;
procedure SetHorzScrollPosition(AValue: Integer); virtual;
procedure SetVertScrollPosition(AValue: Integer); virtual;
// own custom form scrool system
function GetHorzScrollPosition: Integer; virtual;
function GetVertScrollPosition: Integer; virtual;
procedure SetRealBorderStyle(AVal: TFormBorderStyle); virtual;
procedure SetRealBorderIcons(AVal: TBorderIcons); virtual;
procedure SetRealFormStyle(AVal: TFormStyle); virtual;
procedure SetRealPopupMode(AVal: TPopupMode); virtual;
procedure SetRealPopupParent(AVal: TCustomForm); virtual;
function GetRealBorderStyle: TFormBorderStyle; virtual;
function GetRealBorderIcons: TBorderIcons; virtual;
function GetRealFormStyle: TFormStyle; virtual;
function GetRealPopupMode: TPopupMode; virtual;
function GetRealPopupParent: TCustomForm; virtual;
function GetForm: TCustomForm; virtual;
function GetUpdate: Boolean; virtual;
procedure DoChangeHackedBounds; virtual;
function GetLogicalClientRect(ALogicalClientRect: TRect): TRect; virtual;
public
property RealLeft: Integer index 0 read GetRealBounds write SetRealBounds;
property RealTop: Integer index 1 read GetRealBounds write SetRealBounds;
property RealWidth: Integer index 2 read GetRealBounds write SetRealBounds;
property RealHeight: Integer index 3 read GetRealBounds write SetRealBounds;
property RealBorderStyle: TFormBorderStyle read GetRealBorderStyle write SetRealBorderStyle;
property RealBorderIcons: TBorderIcons read GetRealBorderIcons write SetRealBorderIcons;
property RealFormStyle: TFormStyle read GetRealFormStyle write SetRealFormStyle;
constructor Create(AOwner: TComponent; AForm: TCustomForm); virtual; reintroduce;
destructor Destroy; override;
procedure BeginUpdate; virtual;
procedure EndUpdate({%H-}AModified: Boolean = False); virtual;
procedure ShowWindow; virtual;
procedure HideWindow; virtual;
property Update: Boolean read GetUpdate;
public
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;
public
function QueryInterface(constref IID: TGUID; out Obj): HResult; override;
end;
{ TFormContainer }
TFormContainer = class(TCustomForm, IDesignedRealForm, IDesignedForm, IDesignedFormBackground)
private
FDesignedForm: TFormImpl;
function GetDesignedForm: TFormImpl;
protected
property DesignedForm: TFormImpl read GetDesignedForm implements IDesignedForm;
function GetLogicalClientRect: TRect; override;
protected
function GetRealBounds(AIndex: Integer): Integer; virtual;
procedure SetRealBounds(AIndex: Integer; AValue: Integer); virtual;
function GetPublishedBounds(AIndex: Integer): Integer; virtual;
procedure SetPublishedBounds(AIndex: Integer; AValue: Integer); virtual;
procedure SetRealBorderStyle(AVal: TFormBorderStyle); virtual;
procedure SetRealBorderIcons(AVal: TBorderIcons); virtual;
procedure SetRealFormStyle(AVal: TFormStyle); virtual;
procedure SetRealPopupMode(AVal: TPopupMode); virtual;
procedure SetRealPopupParent(AVal: TCustomForm); virtual;
function GetRealBorderStyle: TFormBorderStyle; virtual;
function GetRealBorderIcons: TBorderIcons; virtual;
function GetRealFormStyle: TFormStyle; virtual;
function GetRealPopupMode: TPopupMode; virtual;
function GetRealPopupParent: TCustomForm; virtual;
protected
FHandledForm: TCustomForm;
FBackground: IDesignedFormBackground;
procedure SetHandledForm(AForm: TCustomForm);
public
constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override;
destructor Destroy; override;
property HandledForm: TCustomForm read FHandledForm write SetHandledForm;
property Background: IDesignedFormBackground read FBackground implements IDesignedFormBackground;
published
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 ClientWidth: Integer index 2 read GetPublishedBounds write SetPublishedBounds;
property ClientHeight: Integer index 3 read GetPublishedBounds write SetPublishedBounds;
end;
implementation
type
TFormAccess = class(TForm);
{ TDesignedFormImpl }
function TFormImpl.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;
//case AIndex of
// 0: Result := FHackLeft;
// 1: Result := FHackTop;
// 2: Result := FHackWidth;
// 3: Result := FHackHeight;
//end;
end;
procedure TFormImpl.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;
case AIndex of
0: FHackLeft := AValue;
1: FHackTop := AValue;
2: FHackWidth := AValue;
3: FHackHeight := AValue;
end;
DoChangeHackedBounds;
end;
{-----------------------------------------------
Real values inherited for design form
{----------------------------------------------}
function TFormImpl.GetRealBounds(AIndex: Integer): Integer;
begin
case AIndex of
0: Result := FForm.Left;
1: Result := FForm.Top;
2: Result := FForm.Width;
3: Result := FForm.Height;
end;
//FForm.;
//Result := 0;// FDesignedRealForm.GetRealBounds(AIndex);
end;
procedure TFormImpl.SetRealBounds(AIndex: Integer; AValue: Integer);
procedure AdjustSize;
var
LFormRect: TRect;
LRealValue, LValue: Integer;
begin
LFormRect := Rect(0, 0, 0, 0);;
LCLIntf.GetClientRect(GetForm.Handle, LFormRect);
LRealValue := GetRealBounds(AIndex);
{$IF FPC_FULLVERSION < 30101}
case AIndex of
0: LValue := LFormRect.Left;
1: LValue := LFormRect.Top;
2: LValue := LFormRect.Right;
3: LValue := LFormRect.Bottom;
end;
{$ELSE}
LValue := LFormRect.Vector[AIndex];
{$ENDIF}
if LValue <> LRealValue then
FDesignedRealForm.SetRealBounds(AIndex, AValue - (LRealValue - LValue));
end;
begin
{FDesignedRealForm.SetRealBounds(AIndex, AValue);
if AIndex = 2 then
AdjustSize;}
end;
procedure TFormImpl.SetRealBorderStyle(AVal: TFormBorderStyle);
begin
//FDesignedRealForm.SetRealBorderStyle(AVal);
end;
procedure TFormImpl.SetRealBorderIcons(AVal: TBorderIcons);
begin
//FDesignedRealForm.SetRealBorderIcons(AVal);
end;
procedure TFormImpl.SetRealFormStyle(AVal: TFormStyle);
begin
//FDesignedRealForm.SetRealFormStyle(AVal);
end;
procedure TFormImpl.SetRealPopupMode(AVal: TPopupMode);
begin
//FDesignedRealForm.SetRealPopupMode(AVal);
end;
procedure TFormImpl.SetRealPopupParent(AVal: TCustomForm);
begin
//FDesignedRealForm.SetRealPopupParent(AVal);
end;
function TFormImpl.GetRealBorderStyle: TFormBorderStyle;
begin
Result := bsNone;//FDesignedRealForm.GetRealBorderStyle;
end;
function TFormImpl.GetRealBorderIcons: TBorderIcons;
begin
Result := [];//FDesignedRealForm.GetRealBorderIcons;
end;
function TFormImpl.GetRealFormStyle: TFormStyle;
begin
Result := fsNormal;//FDesignedRealForm.GetRealFormStyle;
end;
function TFormImpl.GetRealPopupMode: TPopupMode;
begin
Result := pmNone//FDesignedRealForm.GetRealPopupMode;
end;
function TFormImpl.GetRealPopupParent: TCustomForm;
begin
Result := nil//FDesignedRealForm.GetRealPopupParent;
end;
//////
function TFormImpl.GetForm: TCustomForm;
begin
Result := FForm;
end;
function TFormImpl.GetUpdate: Boolean;
begin
Result := FUpdate;
end;
function TFormImpl.GetOnChangeHackedBounds: TNotifyEvent;
begin
Result := FOnChangeHackedBounds;
end;
function TFormImpl.PositionDelta: TPoint;
procedure FormBorderDelta;
begin
Result.X := GetSystemMetrics(SM_CXSIZEFRAME);
Result.Y := GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
end;
begin
Result := Point(0, 0);
{$IFDEF WINDOWS}
FormBorderDelta;
{$ENDIF}
end;
procedure TFormImpl.SetOnChangeHackedBounds(const AValue: TNotifyEvent);
begin
FOnChangeHackedBounds := AValue;
end;
/////// positions
procedure TFormImpl.SetHorzScrollPosition(AValue: Integer);
begin
RealLeft := -PositionDelta.x - AValue;
// ! must. resize problem for controls with Align = Top, Right etc.
RealWidth := Width;
RealHeight := Height;
end;
procedure TFormImpl.SetVertScrollPosition(AValue: Integer);
begin
RealTop := -PositionDelta.y - AValue;
// ! must. resize problem for controls with Align = Top, Right etc.
RealWidth := Width;
RealHeight := Height;
end;
function TFormImpl.GetHorzScrollPosition: Integer;
begin
Result := -(RealLeft {+ PositionDelta.x});
end;
function TFormImpl.GetVertScrollPosition: Integer;
begin
Result := -(RealTop {+ PositionDelta.y});
end;
procedure TFormImpl.BeginUpdate;
begin
FUpdate := True;
end;
procedure TFormImpl.EndUpdate(AModified: Boolean);
begin
FUpdate := False;
end;
procedure TFormImpl.ShowWindow;
begin
if FForm.Parent = nil then
LCLIntf.ShowWindow(FForm.Handle, SW_SHOW);
end;
procedure TFormImpl.HideWindow;
begin
if FForm.Parent = nil then
LCLIntf.ShowWindow(FForm.Handle, SW_HIDE);
end;
function TFormImpl.QueryInterface(constref IID: TGUID; out Obj
): HResult;
begin
Result := inherited QueryInterface(IID, Obj);
if Result <> S_OK then
Result := TFormAccess(FForm).QueryInterface(IID, Obj);
end;
procedure TFormImpl.DoChangeHackedBounds;
begin
if not FUpdate and Assigned(FOnChangeHackedBounds) then
FOnChangeHackedBounds(FForm);
end;
function TFormImpl.GetLogicalClientRect(ALogicalClientRect: TRect): TRect;
begin
Result:=ALogicalClientRect;
end;
constructor TFormImpl.Create(AOwner: TComponent; AForm: TCustomForm);
begin
inherited Create(AOwner);
FForm := AForm;
FDesignedRealForm := Self as IDesignedRealForm;
end;
destructor TFormImpl.Destroy;
begin
Pointer(FDesignedRealForm) := nil;
inherited Destroy;
end;
{ TFakeCustomForm }
function TFormContainer.GetDesignedForm: TFormImpl;
begin
if not Assigned(FDesignedForm) then
FDesignedForm := TFormImpl.Create(Self, Self);
Result := FDesignedForm;
end;
function TFormContainer.GetLogicalClientRect: TRect;
begin
Result := DesignedForm.GetLogicalClientRect(inherited GetLogicalClientRect);
end;
function TFormContainer.GetRealBounds(AIndex: Integer): Integer;
begin
case AIndex of
0: Result := inherited Left;
1: Result := inherited Top;
2: Result := inherited Width;
3: Result := inherited Height;
end;
end;
procedure TFormContainer.SetRealBounds(AIndex: Integer; AValue: Integer);
begin
case AIndex of
0: inherited Left := AValue;
1: inherited Top := AValue;
2:
begin
inherited Width := AValue;
if FHandledForm <> nil then
FHandledForm.Width := AValue;
end;
3:
begin
inherited Height := AValue;
if FHandledForm <> nil then
FHandledForm.Height := AValue;
end;
end;
end;
function TFormContainer.GetPublishedBounds(AIndex: Integer): Integer;
begin
Result := DesignedForm.GetPublishedBounds(AIndex);
end;
procedure TFormContainer.SetPublishedBounds(AIndex: Integer; AValue: Integer);
begin
case AIndex of
0, 1: DesignedForm.SetPublishedBounds(AIndex, AValue);
2, 3:
begin
DesignedForm.SetPublishedBounds(AIndex, AValue);
SetRealBounds(AIndex, DesignedForm.GetPublishedBounds(AIndex));
end;
end;
end;
constructor TFormContainer.CreateNew(AOwner: TComponent; Num: Integer);
begin
FBackground := TfrFormBackgroundForMDI.Create(DesignedForm);
FBackground._AddRef;
inherited CreateNew(AOwner, Num);
Left := inherited Left;
Top := inherited Top;
Width := inherited Width;
Height := inherited Height;
end;
destructor TFormContainer.Destroy;
var
I: IInterfaceComponentReference;
begin
// we need to call "Screen.RemoveForm" to perform
// references back to nil by IDesignedForm to FDesignedForm
inherited Destroy;
FBackground.QueryInterface(IInterfaceComponentReference, I); // only way to omit SIGSEGV
I.GetComponent.Free;
Pointer(I) := nil; // omit _Release (Free is above)
Pointer(FBackground) := nil; // omit _Release (Free is above)
if Assigned(FDesignedForm) then
FreeAndNil(FDesignedForm);
end;
procedure TFormContainer.SetRealBorderStyle(AVal: TFormBorderStyle);
begin
inherited BorderStyle := AVal;
end;
procedure TFormContainer.SetRealBorderIcons(AVal: TBorderIcons);
begin
inherited BorderIcons := AVal;
end;
procedure TFormContainer.SetRealFormStyle(AVal: TFormStyle);
begin
inherited FormStyle := AVal;
end;
procedure TFormContainer.SetRealPopupMode(AVal: TPopupMode);
begin
inherited PopupMode := AVal;
end;
procedure TFormContainer.SetRealPopupParent(AVal: TCustomForm);
begin
inherited PopupParent := AVal;
end;
function TFormContainer.GetRealBorderStyle: TFormBorderStyle;
begin
Result := inherited BorderStyle;
end;
function TFormContainer.GetRealBorderIcons: TBorderIcons;
begin
Result := inherited BorderIcons;
end;
function TFormContainer.GetRealFormStyle: TFormStyle;
begin
Result := inherited FormStyle;
end;
function TFormContainer.GetRealPopupMode: TPopupMode;
begin
Result := inherited PopupMode;
end;
function TFormContainer.GetRealPopupParent: TCustomForm;
begin
Result := inherited PopupParent;
end;
procedure TFormContainer.SetHandledForm(AForm: TCustomForm);
begin
if FHandledForm = AForm then
Exit;
if FHandledForm <> nil then
FHandledForm.Parent := nil;
FHandledForm := AForm;
if FHandledForm <> nil then
FHandledForm.Parent := Self;
end;
end.