|
@@ -66,7 +66,6 @@ type
|
|
|
FAttributeValues: array[TDemoNodeAttribute] of string;
|
|
|
FNodes: TFPObjectList; // list of TDemoNode
|
|
|
FCSSClasses: TStrings;
|
|
|
- FID: string;
|
|
|
FParent: TDemoNode;
|
|
|
FStyleElements: TCSSElement;
|
|
|
FStyle: string;
|
|
@@ -74,7 +73,6 @@ type
|
|
|
function GetNodeCount: integer;
|
|
|
function GetNodes(Index: integer): TDemoNode;
|
|
|
procedure SetAttribute(AIndex: TDemoNodeAttribute; const AValue: string);
|
|
|
- procedure SetID(const AValue: string);
|
|
|
procedure SetParent(const AValue: TDemoNode);
|
|
|
procedure SetStyleElements(const AValue: TCSSElement);
|
|
|
procedure SetStyle(const AValue: string);
|
|
@@ -85,14 +83,15 @@ type
|
|
|
constructor Create(AOwner: TComponent); override;
|
|
|
destructor Destroy; override;
|
|
|
procedure Clear;
|
|
|
- class function CSSClassName: string; virtual;
|
|
|
- function GetCSSClassName: string;
|
|
|
+ function GetCSSID: TCSSString; virtual;
|
|
|
+ class function CSSTypeName: TCSSString; virtual;
|
|
|
+ function GetCSSTypeName: TCSSString;
|
|
|
class function CSSTypeID: TCSSNumericalID; virtual;
|
|
|
function GetCSSTypeID: TCSSNumericalID;
|
|
|
class function GetAttributeInitialValue(Attr: TDemoNodeAttribute): string; virtual;
|
|
|
- function HasCSSClass(const aClassName: string): boolean; virtual;
|
|
|
+ function HasCSSClass(const aClassName: TCSSString): boolean; virtual;
|
|
|
procedure SetCSSValue(AttrID: TCSSNumericalID; Value: TCSSElement); virtual;
|
|
|
- property ID: string read FID write SetID;
|
|
|
+ function GetCSSParent: TCSSNode; virtual;
|
|
|
property Parent: TDemoNode read FParent write SetParent;
|
|
|
property NodeCount: integer read GetNodeCount;
|
|
|
property Nodes[Index: integer]: TDemoNode read GetNodes; default;
|
|
@@ -109,12 +108,21 @@ type
|
|
|
property Color: string index naColor read GetAttribute write SetAttribute;
|
|
|
property Attribute[Attr: TDemoNodeAttribute]: string read GetAttribute write SetAttribute;
|
|
|
end;
|
|
|
+ TDemoNodeClass = class of TDemoNode;
|
|
|
+
|
|
|
+ { TDemoDiv }
|
|
|
+
|
|
|
+ TDemoDiv = class(TDemoNode)
|
|
|
+ public
|
|
|
+ class function CSSTypeName: TCSSString; override;
|
|
|
+ class function CSSTypeID: TCSSNumericalID; override;
|
|
|
+ end;
|
|
|
|
|
|
{ TDemoButton }
|
|
|
|
|
|
TDemoButton = class(TDemoNode)
|
|
|
public
|
|
|
- class function CSSClassName: string; override;
|
|
|
+ class function CSSTypeName: TCSSString; override;
|
|
|
class function CSSTypeID: TCSSNumericalID; override;
|
|
|
end;
|
|
|
|
|
@@ -162,14 +170,21 @@ type
|
|
|
|
|
|
TTestCSSResolver = class(TCustomTestCSSResolver)
|
|
|
published
|
|
|
- procedure Test_Universal;
|
|
|
+ procedure Test_Selector_Universal;
|
|
|
+ procedure Test_Selector_Type;
|
|
|
+ procedure Test_Selector_Id;
|
|
|
+ procedure Test_Selector_Class;
|
|
|
+ procedure Test_Selector_ClassClass; // and operator
|
|
|
+ procedure Test_Selector_ClassSpaceClass; // descendant combinator
|
|
|
+ procedure Test_Selector_TypeCommaType; // or operator
|
|
|
+ procedure Test_Selector_ClassGTClass; // child combinator
|
|
|
end;
|
|
|
|
|
|
-function LinesToStr(Args: array of const): string;
|
|
|
+function LinesToStr(const Args: array of const): string;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
-function LinesToStr(Args: array of const): string;
|
|
|
+function LinesToStr(const Args: array of const): string;
|
|
|
var
|
|
|
s: String;
|
|
|
i: Integer;
|
|
@@ -205,24 +220,167 @@ end;
|
|
|
|
|
|
{ TTestCSSResolver }
|
|
|
|
|
|
-procedure TTestCSSResolver.Test_Universal;
|
|
|
+procedure TTestCSSResolver.Test_Selector_Universal;
|
|
|
begin
|
|
|
Doc.Root:=TDemoNode.Create(nil);
|
|
|
Doc.Style:='* { left: 10px; }';
|
|
|
Doc.ApplyStyle;
|
|
|
- AssertEquals('left','10px',Doc.Root.Left);
|
|
|
+ AssertEquals('Root.left','10px',Doc.Root.Left);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TTestCSSResolver.Test_Selector_Type;
|
|
|
+var
|
|
|
+ Button: TDemoButton;
|
|
|
+begin
|
|
|
+ Doc.Root:=TDemoNode.Create(nil);
|
|
|
+ Button:=TDemoButton.Create(Doc);
|
|
|
+ Button.Parent:=Doc.Root;
|
|
|
+ Doc.Style:='button { left: 11px; }';
|
|
|
+ Doc.ApplyStyle;
|
|
|
+ AssertEquals('Root.left','',Doc.Root.Left);
|
|
|
+ AssertEquals('Button.left','11px',Button.Left);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TTestCSSResolver.Test_Selector_Id;
|
|
|
+var
|
|
|
+ Button1: TDemoButton;
|
|
|
+begin
|
|
|
+ Doc.Root:=TDemoNode.Create(nil);
|
|
|
+ Button1:=TDemoButton.Create(Doc);
|
|
|
+ Button1.Name:='Button1';
|
|
|
+ Button1.Parent:=Doc.Root;
|
|
|
+ Doc.Style:='#Button1 { left: 12px; }';
|
|
|
+ Doc.ApplyStyle;
|
|
|
+ AssertEquals('Root.left','',Doc.Root.Left);
|
|
|
+ AssertEquals('Button1.left','12px',Button1.Left);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TTestCSSResolver.Test_Selector_Class;
|
|
|
+var
|
|
|
+ Button1: TDemoButton;
|
|
|
+begin
|
|
|
+ Doc.Root:=TDemoNode.Create(nil);
|
|
|
+ Button1:=TDemoButton.Create(Doc);
|
|
|
+ Button1.CSSClasses.Add('west');
|
|
|
+ Button1.Parent:=Doc.Root;
|
|
|
+ Doc.Style:='.west { left: 13px; }';
|
|
|
+ Doc.ApplyStyle;
|
|
|
+ AssertEquals('Root.left','',Doc.Root.Left);
|
|
|
+ AssertEquals('Button1.left','13px',Button1.Left);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TTestCSSResolver.Test_Selector_ClassClass;
|
|
|
+var
|
|
|
+ Button1, Button2: TDemoButton;
|
|
|
+begin
|
|
|
+ Doc.Root:=TDemoNode.Create(nil);
|
|
|
+
|
|
|
+ Button1:=TDemoButton.Create(Doc);
|
|
|
+ Button1.CSSClasses.Add('west');
|
|
|
+ Button1.Parent:=Doc.Root;
|
|
|
+
|
|
|
+ Button2:=TDemoButton.Create(Doc);
|
|
|
+ Button2.CSSClasses.Add('west south');
|
|
|
+ Button2.Parent:=Doc.Root;
|
|
|
+
|
|
|
+ Doc.Style:='.west.south { left: 10px; }';
|
|
|
+ Doc.ApplyStyle;
|
|
|
+ AssertEquals('Root.left','',Doc.Root.Left);
|
|
|
+ AssertEquals('Button1.left','',Button1.Left);
|
|
|
+ AssertEquals('Button2.left','10px',Button2.Left);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TTestCSSResolver.Test_Selector_ClassSpaceClass;
|
|
|
+var
|
|
|
+ Button1: TDemoButton;
|
|
|
+begin
|
|
|
+ Doc.Root:=TDemoNode.Create(nil);
|
|
|
+ Doc.Root.CSSClasses.Add('bird');
|
|
|
+
|
|
|
+ Button1:=TDemoButton.Create(Doc);
|
|
|
+ Button1.CSSClasses.Add('west');
|
|
|
+ Button1.Parent:=Doc.Root;
|
|
|
+
|
|
|
+ Doc.Style:='.bird .west { left: 10px; }';
|
|
|
+ Doc.ApplyStyle;
|
|
|
+ AssertEquals('Root.left','',Doc.Root.Left);
|
|
|
+ AssertEquals('Button1.left','10px',Button1.Left);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TTestCSSResolver.Test_Selector_TypeCommaType;
|
|
|
+var
|
|
|
+ Button1: TDemoButton;
|
|
|
+ Div1: TDemoDiv;
|
|
|
+begin
|
|
|
+ Doc.Root:=TDemoNode.Create(nil);
|
|
|
+
|
|
|
+ Button1:=TDemoButton.Create(Doc);
|
|
|
+ Button1.Parent:=Doc.Root;
|
|
|
+
|
|
|
+ Div1:=TDemoDiv.Create(Doc);
|
|
|
+ Div1.Parent:=Doc.Root;
|
|
|
+
|
|
|
+ Doc.Style:='div, button { left: 10px; }';
|
|
|
+ Doc.ApplyStyle;
|
|
|
+ AssertEquals('Root.left','',Doc.Root.Left);
|
|
|
+ AssertEquals('Button1.left','10px',Button1.Left);
|
|
|
+ AssertEquals('Div1.left','10px',Div1.Left);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TTestCSSResolver.Test_Selector_ClassGTClass;
|
|
|
+var
|
|
|
+ Div1, Div2: TDemoDiv;
|
|
|
+begin
|
|
|
+ Doc.Root:=TDemoNode.Create(nil);
|
|
|
+ Doc.Root.CSSClasses.Add('lvl1');
|
|
|
+
|
|
|
+ Div1:=TDemoDiv.Create(Doc);
|
|
|
+ Div1.CSSClasses.Add('lvl2');
|
|
|
+ Div1.Parent:=Doc.Root;
|
|
|
+
|
|
|
+ Div2:=TDemoDiv.Create(Doc);
|
|
|
+ Div2.CSSClasses.Add('lvl3');
|
|
|
+ Div2.Parent:=Div1;
|
|
|
+
|
|
|
+ Doc.Style:=LinesToStr([
|
|
|
+ '.lvl1>.lvl2 { left: 10px; }',
|
|
|
+ '.lvl1>.lvl3 { top: 11px; }',
|
|
|
+ '.lvl2>.lvl3 { width: 12px; }',
|
|
|
+ '']);
|
|
|
+ Doc.ApplyStyle;
|
|
|
+ AssertEquals('Root.left','',Doc.Root.Left);
|
|
|
+ AssertEquals('Root.top','',Doc.Root.Top);
|
|
|
+ AssertEquals('Root.width','',Doc.Root.Width);
|
|
|
+ AssertEquals('Div1.left','10px',Div1.Left);
|
|
|
+ AssertEquals('Div1.top','',Div1.Top);
|
|
|
+ AssertEquals('Div1.width','',Div1.Width);
|
|
|
+ AssertEquals('Div2.left','',Div2.Left);
|
|
|
+ AssertEquals('Div2.top','',Div2.Top);
|
|
|
+ AssertEquals('Div2.width','12px',Div2.Width);
|
|
|
+end;
|
|
|
+
|
|
|
+{ TDemoDiv }
|
|
|
+
|
|
|
+class function TDemoDiv.CSSTypeName: TCSSString;
|
|
|
+begin
|
|
|
+ Result:='div';
|
|
|
+end;
|
|
|
+
|
|
|
+class function TDemoDiv.CSSTypeID: TCSSNumericalID;
|
|
|
+begin
|
|
|
+ Result:=101;
|
|
|
end;
|
|
|
|
|
|
{ TDemoButton }
|
|
|
|
|
|
-class function TDemoButton.CSSClassName: string;
|
|
|
+class function TDemoButton.CSSTypeName: TCSSString;
|
|
|
begin
|
|
|
Result:='button';
|
|
|
end;
|
|
|
|
|
|
class function TDemoButton.CSSTypeID: TCSSNumericalID;
|
|
|
begin
|
|
|
- Result:=101;
|
|
|
+ Result:=102;
|
|
|
end;
|
|
|
|
|
|
{ TDemoDocument }
|
|
@@ -279,8 +437,9 @@ begin
|
|
|
if TypeIDs['*']<>CSSTypeIDUniversal then
|
|
|
raise Exception.Create('20220909004740');
|
|
|
|
|
|
- TypeIDs[TDemoNode.CSSClassName]:=TDemoNode.CSSTypeID;
|
|
|
- TypeIDs[TDemoButton.CSSClassName]:=TDemoButton.CSSTypeID;
|
|
|
+ TypeIDs[TDemoNode.CSSTypeName]:=TDemoNode.CSSTypeID;
|
|
|
+ TypeIDs[TDemoDiv.CSSTypeName]:=TDemoDiv.CSSTypeID;
|
|
|
+ TypeIDs[TDemoButton.CSSTypeName]:=TDemoButton.CSSTypeID;
|
|
|
|
|
|
AttributeIDs:=FNumericalIDs[nikAttribute];
|
|
|
AttributeIDs['all']:=CSSAttributeIDAll;
|
|
@@ -352,12 +511,6 @@ begin
|
|
|
FAttributeValues[AIndex]:=AValue;
|
|
|
end;
|
|
|
|
|
|
-procedure TDemoNode.SetID(const AValue: string);
|
|
|
-begin
|
|
|
- if FID=AValue then Exit;
|
|
|
- FID:=AValue;
|
|
|
-end;
|
|
|
-
|
|
|
procedure TDemoNode.SetParent(const AValue: TDemoNode);
|
|
|
begin
|
|
|
if FParent=AValue then Exit;
|
|
@@ -441,7 +594,12 @@ begin
|
|
|
FNodes.Clear;
|
|
|
end;
|
|
|
|
|
|
-class function TDemoNode.CSSClassName: string;
|
|
|
+function TDemoNode.GetCSSID: TCSSString;
|
|
|
+begin
|
|
|
+ Result:=Name;
|
|
|
+end;
|
|
|
+
|
|
|
+class function TDemoNode.CSSTypeName: TCSSString;
|
|
|
begin
|
|
|
Result:='node';
|
|
|
end;
|
|
@@ -460,7 +618,7 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-function TDemoNode.HasCSSClass(const aClassName: string): boolean;
|
|
|
+function TDemoNode.HasCSSClass(const aClassName: TCSSString): boolean;
|
|
|
var
|
|
|
i: Integer;
|
|
|
begin
|
|
@@ -485,9 +643,14 @@ begin
|
|
|
Attribute[Attr]:=s;
|
|
|
end;
|
|
|
|
|
|
-function TDemoNode.GetCSSClassName: string;
|
|
|
+function TDemoNode.GetCSSParent: TCSSNode;
|
|
|
+begin
|
|
|
+ Result:=Parent;
|
|
|
+end;
|
|
|
+
|
|
|
+function TDemoNode.GetCSSTypeName: TCSSString;
|
|
|
begin
|
|
|
- Result:=CSSClassName;
|
|
|
+ Result:=CSSTypeName;
|
|
|
end;
|
|
|
|
|
|
class function TDemoNode.CSSTypeID: TCSSNumericalID;
|