|
@@ -16,11 +16,11 @@ interface
|
|
|
|
|
|
uses
|
|
|
LCLProc, LCLType, Classes, SysUtils, FormEditingIntf, PropEdits, LazIDEIntf,
|
|
|
- ComponentEditors, LCLIntf, Graphics, Controls, Forms, ProjectIntf,
|
|
|
- PackageIntf, LazLoggerBase, CodeToolManager, CodeCache,
|
|
|
+ ComponentEditors, IDEOptEditorIntf, LCLIntf, Graphics, Controls, Forms, ProjectIntf,
|
|
|
+ PackageIntf, IDEOptionsIntf, LazLoggerBase, CodeToolManager, CodeCache,
|
|
|
StdCodeTools, Fresnel.DOM, Fresnel.Controls, Fresnel.Forms,
|
|
|
Fresnel.Renderer, Fresnel.Classes, Fresnel.LCLApp, Fresnel.LCL,
|
|
|
- Fresnel.DsgnStrConsts, Fresnel.StylePropEdit;
|
|
|
+ Fresnel.DsgnStrConsts, Fresnel.StylePropEdit, Fresnel.DsgnOptsFrame, Fresnel.DsgnOptions;
|
|
|
|
|
|
const
|
|
|
ProjDescNameFresnelApplication = 'Fresnel Application';
|
|
@@ -57,6 +57,7 @@ type
|
|
|
procedure GetBounds(AComponent: TComponent; out CurBounds: TRect); override;
|
|
|
procedure GetClientArea(AComponent: TComponent; out
|
|
|
CurClientArea: TRect; out ScrollOffset: TPoint); override;
|
|
|
+ procedure InitComponent(AComponent, NewParent: TComponent; NewBounds: TRect); override;
|
|
|
procedure Paint; override;
|
|
|
procedure SetBounds(AComponent: TComponent; NewBounds: TRect); override;
|
|
|
public
|
|
@@ -121,6 +122,9 @@ var
|
|
|
FileDescFresnelForm: TFileDescFresnelForm;
|
|
|
ProjDescFresnelApplication: TProjDescFresnelApplication;
|
|
|
|
|
|
+var
|
|
|
+ FresnelOptionsFrameID: integer = 1000;
|
|
|
+
|
|
|
procedure Register;
|
|
|
|
|
|
implementation
|
|
@@ -129,21 +133,32 @@ implementation
|
|
|
|
|
|
procedure Register;
|
|
|
begin
|
|
|
+ FresnelOptions:=TFresnelDsgnOptions.Create(nil);
|
|
|
+
|
|
|
+ // register mediator for designer forms
|
|
|
FormEditingHook.RegisterDesignerMediator(TFresnelFormMediator);
|
|
|
FormEditingHook.SetDesignerBaseClassCanAppCreateForm(TFresnelCustomForm,true);
|
|
|
|
|
|
+ // register elements
|
|
|
RegisterComponents('Fresnel',[TDiv,TSpan,TLabel,TButton,TImage,TBody]);
|
|
|
RegisterComponentRequirements([TDiv,TSpan,TLabel,TButton,TImage,TBody],TFresnelComponentRequirements);
|
|
|
|
|
|
+ // register fresnel form as new file type
|
|
|
FileDescFresnelForm:=TFileDescFresnelForm.Create;
|
|
|
RegisterProjectFileDescriptor(FileDescFresnelForm,FileDescGroupName);
|
|
|
|
|
|
+ // register fresnel application as new project type
|
|
|
ProjDescFresnelApplication:=TProjDescFresnelApplication.Create;
|
|
|
RegisterProjectDescriptor(ProjDescFresnelApplication);
|
|
|
|
|
|
+ // register property editors
|
|
|
RegisterPropertyEditor(TypeInfo(String), TFresnelElement, 'Style', TFresnelStylePropertyEditor);
|
|
|
RegisterPropertyEditor(TypeInfo(String), TFresnelCustomForm, 'Style', THiddenPropertyEditor);
|
|
|
RegisterPropertyEditor(TypeInfo(TStrings), TFresnelCustomForm, 'Stylesheet', TFresnelStyleSheetPropertyEditor);
|
|
|
+
|
|
|
+ // register IDE options frame
|
|
|
+ FresnelOptionsFrameID:=RegisterIDEOptionsEditor(GroupEnvironment,TFresnelOptionsFrame,
|
|
|
+ FresnelOptionsFrameID)^.Index;
|
|
|
end;
|
|
|
|
|
|
{ TFresnelFormMediator }
|
|
@@ -215,8 +230,9 @@ begin
|
|
|
CurBounds:=FDsgnForm.FormBounds.GetRect;
|
|
|
end else if AComponent is TFresnelElement then
|
|
|
begin
|
|
|
+ // return borderbox
|
|
|
El:=TFresnelElement(AComponent);
|
|
|
- aBox:=El.GetBoundingClientRect;
|
|
|
+ aBox:=El.RenderedBorderBox;
|
|
|
FresnelRectToRect(aBox,CurBounds);
|
|
|
end else
|
|
|
inherited GetBounds(AComponent,CurBounds);
|
|
@@ -225,6 +241,11 @@ end;
|
|
|
|
|
|
procedure TFresnelFormMediator.SetBounds(AComponent: TComponent;
|
|
|
NewBounds: TRect);
|
|
|
+var
|
|
|
+ El: TFresnelElement;
|
|
|
+ OldStyle: String;
|
|
|
+ NewBorderBox: TFresnelRect;
|
|
|
+ NewLeft, NewTop, NewWidth, NewHeight: TFresnelLength;
|
|
|
begin
|
|
|
//debugln(['TFresnelFormMediator.SetBounds ',DbgSName(AComponent),' ',dbgs(NewBounds)]);
|
|
|
if AComponent=FDsgnForm then
|
|
@@ -232,8 +253,50 @@ begin
|
|
|
FDsgnForm.WSResize(TFresnelRect.Create(NewBounds),NewBounds.Width,NewBounds.Height);
|
|
|
end else if AComponent is TFresnelElement then
|
|
|
begin
|
|
|
- // bounds are controlled by CSS
|
|
|
- // todo: absolute, fixed
|
|
|
+ // an element (bounds are controlled by CSS)
|
|
|
+ El:=TFresnelElement(AComponent);
|
|
|
+ if El.ComputedPosition in [CSSRegistry.kwAbsolute,CSSRegistry.kwFixed] then
|
|
|
+ begin
|
|
|
+ // NewBounds is borderbox
|
|
|
+ with El.LayoutNode do begin
|
|
|
+ NewBorderBox.SetRect(NewBounds);
|
|
|
+ NewLeft:=NewBorderBox.Left-MarginLeft;
|
|
|
+ NewTop:=NewBorderBox.Top-MarginTop;
|
|
|
+ NewWidth:=NewBorderBox.Width;
|
|
|
+ NewHeight:=NewBorderBox.Height;
|
|
|
+
|
|
|
+ // todo: if parent position is static, use the nearest parent with non static
|
|
|
+ // todo: right and bottom aligned
|
|
|
+
|
|
|
+ OldStyle:=El.Style;
|
|
|
+ case El.ComputedBoxSizing of
|
|
|
+ CSSRegistry.kwBorderBox:
|
|
|
+ begin
|
|
|
+
|
|
|
+ end;
|
|
|
+ CSSRegistry.kwPaddingBox:
|
|
|
+ begin
|
|
|
+ NewWidth:=NewWidth-BorderLeft-BorderRight;
|
|
|
+ NewHeight:=NewHeight-BorderTop-BorderBottom;
|
|
|
+ end;
|
|
|
+ CSSRegistry.kwContentBox:
|
|
|
+ begin
|
|
|
+ NewWidth:=NewWidth-BorderLeft-BorderRight-PaddingLeft-PaddingRight;
|
|
|
+ NewHeight:=NewHeight-BorderTop-BorderBottom-PaddingTop-PaddingBottom;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if El.GetStyleAttr('left')<>'' then
|
|
|
+ El.SetStyleAttr('left',FloatToCSSPx(NewLeft));
|
|
|
+ if El.GetStyleAttr('top')<>'' then
|
|
|
+ El.SetStyleAttr('top',FloatToCSSPx(NewTop));
|
|
|
+ if El.GetStyleAttr('width')<>'' then
|
|
|
+ El.SetStyleAttr('width',FloatToCSSPx(NewWidth));
|
|
|
+ if El.GetStyleAttr('height')<>'' then
|
|
|
+ El.SetStyleAttr('height',FloatToCSSPx(NewHeight));
|
|
|
+ debugln(['TFresnelFormMediator.SetBounds AComponent=',DbgSName(AComponent),' OldStyle=[',OldStyle,'] OldBorderBox=',FloatToCSSStr(El.RenderedBorderBox.Left),',',FloatToCSSStr(El.RenderedBorderBox.Top),' w=',FloatToCSSStr(El.RenderedBorderBox.Width),',h=',FloatToCSSStr(El.RenderedBorderBox.Height),' box-sizing=',CSSRegistry.Keywords[El.ComputedBoxSizing],' NewLeft,Top=',FloatToCSSStr(NewLeft),',',FloatToCSSStr(NewTop),' NewWH=',FloatToCSSStr(NewWidth),'x',FloatToCSSStr(NewHeight)]);
|
|
|
+ end;
|
|
|
end else begin
|
|
|
inherited SetBounds(AComponent, NewBounds);
|
|
|
end;
|
|
@@ -241,14 +304,57 @@ end;
|
|
|
|
|
|
procedure TFresnelFormMediator.GetClientArea(AComponent: TComponent; out
|
|
|
CurClientArea: TRect; out ScrollOffset: TPoint);
|
|
|
+var
|
|
|
+ El: TFresnelElement;
|
|
|
+ Box, BorderBox: TFresnelRect;
|
|
|
begin
|
|
|
if AComponent=FDsgnForm then
|
|
|
begin
|
|
|
CurClientArea:=Rect(0,0,round(FDsgnForm.Width),round(FDsgnForm.Height));
|
|
|
ScrollOffset:=Point(0,0);
|
|
|
- end else begin
|
|
|
- inherited GetClientArea(AComponent, CurClientArea, ScrollOffset);
|
|
|
- end;
|
|
|
+ end else if AComponent is TFresnelElement then begin
|
|
|
+ // return contentbox inside the borderbox
|
|
|
+ El:=TFresnelElement(AComponent);
|
|
|
+ BorderBox:=El.RenderedBorderBox;
|
|
|
+ Box:=El.RenderedContentBox;
|
|
|
+ Box.Offset(-BorderBox.Left,-BorderBox.Top);
|
|
|
+ FresnelRectToRect(Box,CurClientArea);
|
|
|
+ end else
|
|
|
+ inherited;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFresnelFormMediator.InitComponent(AComponent, NewParent: TComponent; NewBounds: TRect);
|
|
|
+var
|
|
|
+ El: TFresnelElement;
|
|
|
+ BorderBox: TFresnelRect;
|
|
|
+begin
|
|
|
+ if AComponent is TFresnelElement then
|
|
|
+ begin
|
|
|
+ // set parentcomponent, needed for streaming
|
|
|
+ TFresnelFormMediator(AComponent).SetParentComponent(NewParent);
|
|
|
+ El:=TFresnelElement(AComponent);
|
|
|
+ debugln(['TFresnelFormMediator.InitComponent AComponent=',DbgSName(AComponent),' NewParent=',DbgSName(NewParent),' Bounds=',dbgs(NewBounds)]);
|
|
|
+ if FresnelOptions.PositionAbsolute then
|
|
|
+ begin
|
|
|
+ // todo: if parent position is static, use the nearest parent with non static
|
|
|
+ BorderBox.SetRect(NewBounds);
|
|
|
+ // todo: compute margins via resolver
|
|
|
+ El.SetStyleAttr('position','absolute');
|
|
|
+ El.SetStyleAttr('box-sizing','border-box');
|
|
|
+ El.SetStyleAttr('left',FloatToCSSPx(BorderBox.Left));
|
|
|
+ El.SetStyleAttr('top',FloatToCSSPx(BorderBox.Top));
|
|
|
+ if not (El is TReplacedElement) then
|
|
|
+ begin
|
|
|
+ if NewBounds.Width<=0 then
|
|
|
+ NewBounds.Width:=50;
|
|
|
+ if NewBounds.Height<=0 then
|
|
|
+ NewBounds.Height:=50;
|
|
|
+ El.SetStyleAttr('width',FloatToCSSPx(BorderBox.Width));
|
|
|
+ El.SetStyleAttr('height',FloatToCSSPx(BorderBox.Height));
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end else
|
|
|
+ inherited;
|
|
|
end;
|
|
|
|
|
|
function TFresnelFormMediator.GetComponentOriginOnForm(AComponent: TComponent
|
|
@@ -265,7 +371,7 @@ begin
|
|
|
El:=TFresnelElement(AComponent);
|
|
|
if not El.Rendered then
|
|
|
exit(Point(0,0));
|
|
|
- BorderBox:=El.GetBoundingClientRect;
|
|
|
+ BorderBox:=El.GetBorderBoxOnViewport;
|
|
|
Result.X:=round(BorderBox.Left);
|
|
|
Result.Y:=round(BorderBox.Top);
|
|
|
end else
|