|
@@ -1314,6 +1314,7 @@ type
|
|
|
FFont: IFresnelFont;
|
|
|
FLayoutNode: TFresnelLayoutNode;
|
|
|
FFontDesc: TFresnelFontDesc;
|
|
|
+ FNodeIndex: integer;
|
|
|
FRendered: boolean;
|
|
|
FScrollBarHorizontal: TPseudoElScrollBar;
|
|
|
FScrollBarVertical: TPseudoElScrollBar;
|
|
@@ -1363,10 +1364,8 @@ type
|
|
|
procedure SetCSSPseudoClass(Pseudo: TFresnelCSSPseudoClass; const AValue: boolean);
|
|
|
class constructor InitFresnelElementClass;
|
|
|
class destructor FinalFresnelElementClass;
|
|
|
- procedure Notification(AComponent: TComponent; Operation: TOperation);
|
|
|
- override;
|
|
|
function CSSReadNextValue(const aValue: string; var p: integer): string; // read e.g. url("bla")
|
|
|
- function CSSReadNextToken(const aValue: string; var p: integer): string; // read e.g. linear-gradient without the brackets
|
|
|
+ function CSSReadNextToken(const aValue: string; var p: integer): string; // read e.g. url of url(), without the brackets
|
|
|
function GetDPI(IsHorizontal: boolean): TFresnelLength; virtual;
|
|
|
procedure SetViewportConnected(AValue: boolean); virtual;
|
|
|
function GetFont: IFresnelFont; virtual;
|
|
@@ -1397,6 +1396,7 @@ type
|
|
|
function GetPath: string; virtual;
|
|
|
function AcceptChildrenAtDesignTime: boolean; virtual;
|
|
|
function Contains(aChild: TFresnelElement): boolean; overload;
|
|
|
+ function InsertBefore(NewChild, RefChild: TFresnelElement): TFresnelElement;
|
|
|
|
|
|
// Can this widget handle focus ?
|
|
|
class function HandleFocus : Boolean; virtual;
|
|
@@ -1413,6 +1413,7 @@ type
|
|
|
property Parent: TFresnelElement read FParent write SetParent;
|
|
|
property NodeCount: integer read GetNodeCount;
|
|
|
property Nodes[Index: integer]: TFresnelElement read GetNodes; default;
|
|
|
+ property NodeIndex: integer read FNodeIndex;
|
|
|
property PseudoNodeCount: integer read GetPeudoNodeCount;
|
|
|
property PseudoNodes[Index: integer]: TPseudoElement read GetPseudoNodes;
|
|
|
// CSS
|
|
@@ -1825,6 +1826,7 @@ type
|
|
|
procedure ReleasePointerCapture(El: TFresnelElement; const aPointerId: TFreHandle); virtual; overload;
|
|
|
procedure ReleasePointerCaptures(El: TFresnelElement); virtual;
|
|
|
procedure WSMouseXY(WSData: TFresnelMouseEventInit; MouseEventId: TEventID); virtual;
|
|
|
+ procedure WriteTreeAndClasses; virtual;
|
|
|
// Return true if default was prevented
|
|
|
function WSKey(WSData: TFresnelKeyEventInit; KeyEventId: TEventID) : boolean; virtual;
|
|
|
function WSInput(WSData: TFresnelInputEventInit) : boolean; virtual;
|
|
@@ -7692,6 +7694,24 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+procedure TFresnelViewport.WriteTreeAndClasses;
|
|
|
+
|
|
|
+ procedure W(Prefix: string; El: TFresnelElement);
|
|
|
+ var
|
|
|
+ i: Integer;
|
|
|
+ begin
|
|
|
+ El.CSSClasses.Delimiter:=',';
|
|
|
+ writeln(Prefix,'Name="',El.Name,'":',El.ClassName,' Classes="',El.CSSClasses.DelimitedText,'"');
|
|
|
+ for i:=0 to El.NodeCount-1 do
|
|
|
+ W(Prefix+' ',El.Nodes[i]);
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+ writeln('TFresnelViewport.WriteTreeAndClasses START');
|
|
|
+ W('',Self);
|
|
|
+ writeln('TFresnelViewport.WriteTreeAndClasses END');
|
|
|
+end;
|
|
|
+
|
|
|
procedure TFresnelViewport.Bubble(El : TFresnelElement; aEvt : TFresnelEvent);
|
|
|
|
|
|
begin
|
|
@@ -8046,34 +8066,46 @@ begin
|
|
|
end;
|
|
|
|
|
|
procedure TFresnelElement.SetParent(const AValue: TFresnelElement);
|
|
|
+var
|
|
|
+ List: TFPList;
|
|
|
+ IsPseudo: Boolean;
|
|
|
+ i: Integer;
|
|
|
begin
|
|
|
if FParent=AValue then Exit;
|
|
|
if AValue=Self then
|
|
|
raise Exception.Create('cycle');
|
|
|
|
|
|
+ IsPseudo:=fesPseudoElement in FStates;
|
|
|
if FParent<>nil then
|
|
|
begin
|
|
|
ViewportConnected:=false;
|
|
|
FResolver:=nil;
|
|
|
FViewPort:=nil;
|
|
|
- if fesPseudoElement in FStates then
|
|
|
- Parent.FPseudoChildren.Remove(Self)
|
|
|
- else begin
|
|
|
- Parent.FChildren.Remove(Self);
|
|
|
+ if IsPseudo then
|
|
|
+ List:=Parent.FPseudoChildren
|
|
|
+ else
|
|
|
+ List:=Parent.FChildren;
|
|
|
+ List.Delete(FNodeIndex);
|
|
|
+ for i:=FNodeIndex to List.Count-1 do
|
|
|
+ TFresnelElement(List[i]).FNodeIndex:=i;
|
|
|
+ FNodeIndex:=-1;
|
|
|
+ if not IsPseudo then
|
|
|
Parent.DomChanged;
|
|
|
- end;
|
|
|
end;
|
|
|
+
|
|
|
FParent:=AValue;
|
|
|
+
|
|
|
if FParent<>nil then
|
|
|
begin
|
|
|
- if fesPseudoElement in FStates then
|
|
|
- Parent.FPseudoChildren.Add(Self)
|
|
|
+ if IsPseudo then
|
|
|
+ List:=Parent.FPseudoChildren
|
|
|
else
|
|
|
- Parent.FChildren.Add(Self);
|
|
|
- FreeNotification(FParent);
|
|
|
+ List:=Parent.FChildren;
|
|
|
+ FNodeIndex:=List.Count;
|
|
|
+ List.Add(Self);
|
|
|
FResolver:=Parent.Resolver;
|
|
|
- FViewPort:=Parent.FViewPort;
|
|
|
- Parent.DomChanged;
|
|
|
+ FViewPort:=Parent.Viewport;
|
|
|
+ DomChanged;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -8096,22 +8128,6 @@ begin
|
|
|
FStyleElement:=Resolver.ParseInlineStyle(FStyle);
|
|
|
end;
|
|
|
|
|
|
-procedure TFresnelElement.Notification(AComponent: TComponent;
|
|
|
- Operation: TOperation);
|
|
|
-begin
|
|
|
- inherited Notification(AComponent, Operation);
|
|
|
- if AComponent=Self then exit;
|
|
|
- if Operation=opRemove then
|
|
|
- begin
|
|
|
- if FParent=AComponent then
|
|
|
- FParent:=nil;
|
|
|
- if FChildren<>nil then
|
|
|
- FChildren.Remove(AComponent);
|
|
|
- if FPseudoChildren<>nil then
|
|
|
- FPseudoChildren.Remove(AComponent);
|
|
|
- end;
|
|
|
-end;
|
|
|
-
|
|
|
function TFresnelElement.CSSReadNextValue(const aValue: string; var p: integer
|
|
|
): string;
|
|
|
var
|
|
@@ -9878,6 +9894,7 @@ constructor TFresnelElement.Create(AOwner: TComponent);
|
|
|
begin
|
|
|
inherited Create(AOwner);
|
|
|
FChildren:=TFPList.Create;
|
|
|
+ FNodeIndex:=-1;
|
|
|
FPseudoChildren:=TFPList.Create;
|
|
|
FCSSClasses:=TStringList.Create;
|
|
|
FCSSClasses.Delimiter:=' ';
|
|
@@ -9889,6 +9906,8 @@ destructor TFresnelElement.Destroy;
|
|
|
var
|
|
|
i: Integer;
|
|
|
begin
|
|
|
+ if FParent<>nil then
|
|
|
+ FParent.ChildDestroying(Self);
|
|
|
Parent:=nil;
|
|
|
Clear;
|
|
|
for i:=PseudoNodeCount-1 downto 0 do
|
|
@@ -9899,8 +9918,6 @@ begin
|
|
|
FreeAndNil(FCSSValues);
|
|
|
FreeAndNil(FCSSClasses);
|
|
|
FreeAndNil(FEventDispatcher);
|
|
|
- if FParent<>nil then
|
|
|
- FParent.ChildDestroying(Self);
|
|
|
|
|
|
inherited Destroy;
|
|
|
end;
|
|
@@ -9958,6 +9975,87 @@ begin
|
|
|
Result:=false;
|
|
|
end;
|
|
|
|
|
|
+function TFresnelElement.InsertBefore(NewChild, RefChild: TFresnelElement): TFresnelElement;
|
|
|
+var
|
|
|
+ List: TFPList;
|
|
|
+ FromIndex, ToIndex, i: Integer;
|
|
|
+ IsPseudo: Boolean;
|
|
|
+begin
|
|
|
+ Result:=NewChild;
|
|
|
+ if NewChild=nil then
|
|
|
+ raise EFresnel.Create('20250914123316');
|
|
|
+ IsPseudo:=fesPseudoElement in NewChild.FStates;
|
|
|
+ if IsPseudo then
|
|
|
+ List:=FPseudoChildren
|
|
|
+ else
|
|
|
+ List:=FChildren;
|
|
|
+ if RefChild<>nil then
|
|
|
+ begin
|
|
|
+ if RefChild.Parent<>Self then
|
|
|
+ raise EFresnel.Create('20250914125844');
|
|
|
+ if IsPseudo <> (fesPseudoElement in RefChild.FStates) then
|
|
|
+ raise EFresnel.Create('20250914124539');
|
|
|
+ end;
|
|
|
+
|
|
|
+ if NewChild.Parent=Self then
|
|
|
+ begin
|
|
|
+ // just change the NodeIndex
|
|
|
+ FromIndex:=NewChild.NodeIndex;
|
|
|
+ if RefChild<>nil then
|
|
|
+ begin
|
|
|
+ if RefChild=NewChild then
|
|
|
+ raise EFresnel.Create('20250914131753');
|
|
|
+ ToIndex:=RefChild.NodeIndex;
|
|
|
+ if ToIndex>FromIndex then dec(ToIndex);
|
|
|
+ end else begin
|
|
|
+ // move to end
|
|
|
+ ToIndex:=List.Count;
|
|
|
+ end;
|
|
|
+ //writeln('TFresnelElement.InsertBefore SAME PARENT Self=',Name,' NewChild=',NewChild.Name,' From=',NewChild.NodeIndex,' To=',ToIndex);
|
|
|
+ if FromIndex=ToIndex then
|
|
|
+ exit; // already there
|
|
|
+ if FromIndex>=0 then
|
|
|
+ begin
|
|
|
+ List.Move(FromIndex,ToIndex);
|
|
|
+ if FromIndex<ToIndex then
|
|
|
+ for i:=FromIndex to ToIndex do
|
|
|
+ TFresnelElement(List[i]).FNodeIndex:=i
|
|
|
+ else
|
|
|
+ for i:=ToIndex to FromIndex do
|
|
|
+ TFresnelElement(List[i]).FNodeIndex:=i;
|
|
|
+ end else begin
|
|
|
+ List.Insert(ToIndex,NewChild);
|
|
|
+ for i:=ToIndex to List.Count-1 do
|
|
|
+ TFresnelElement(List[i]).FNodeIndex:=i
|
|
|
+ end;
|
|
|
+ end else begin
|
|
|
+ // move to a new parent
|
|
|
+ //writeln('TFresnelElement.InsertBefore NEW PARENT Self=',Name,' NewChild=',NewChild.Name,' From=',NewChild.NodeIndex);
|
|
|
+ NewChild.Parent:=nil;
|
|
|
+
|
|
|
+ NewChild.FParent:=Self;
|
|
|
+ NewChild.FResolver:=Resolver;
|
|
|
+ NewChild.FViewPort:=ViewPort;
|
|
|
+
|
|
|
+ if RefChild<>nil then
|
|
|
+ begin
|
|
|
+ ToIndex:=RefChild.NodeIndex;
|
|
|
+ List.Insert(ToIndex,NewChild);
|
|
|
+ for i:=ToIndex to List.Count-1 do
|
|
|
+ TFresnelElement(List[i]).FNodeIndex:=i;
|
|
|
+ end
|
|
|
+ else begin
|
|
|
+ List:=FChildren;
|
|
|
+ NewChild.FNodeIndex:=List.Count;
|
|
|
+ List.Add(Self);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ //writeln('TFresnelElement.InsertBefore Self=',Name,' NewChild=',NewChild.Name,' Index=',NewChild.NodeIndex);
|
|
|
+
|
|
|
+ DomChanged;
|
|
|
+end;
|
|
|
+
|
|
|
class function TFresnelElement.HandleFocus: Boolean;
|
|
|
begin
|
|
|
Result:=False;
|