GuiObjects.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:20k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit GuiObjects;
  2. //---------------------------------------------------------------------------
  3. // GuiObjects.pas                                       Modified: 03-Mar-2007
  4. // The basic self-contained GUI object implementation             Version 1.0
  5. //---------------------------------------------------------------------------
  6. // Important Notice:
  7. //
  8. // If you modify/use this code or one of its parts either in original or
  9. // modified form, you must comply with Mozilla Public License v1.1,
  10. // specifically section 3, "Distribution Obligations". Failure to do so will
  11. // result in the license breach, which will be resolved in the court.
  12. // Remember that violating author's rights is considered a serious crime in
  13. // many countries. Thank you!
  14. //
  15. // !! Please *read* Mozilla Public License 1.1 document located at:
  16. //  http://www.mozilla.org/MPL/
  17. //
  18. // If you require any clarifications about the license, feel free to contact
  19. // us or post your question on our forums at: http://www.afterwarp.net
  20. //---------------------------------------------------------------------------
  21. // The contents of this file are subject to the Mozilla Public License
  22. // Version 1.1 (the "License"); you may not use this file except in
  23. // compliance with the License. You may obtain a copy of the License at
  24. // http://www.mozilla.org/MPL/
  25. //
  26. // Software distributed under the License is distributed on an "AS IS"
  27. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  28. // License for the specific language governing rights and limitations
  29. // under the License.
  30. //
  31. // The Original Code is GuiObjects.pas.
  32. //
  33. // The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
  34. // Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
  35. // Afterwarp Interactive. All Rights Reserved.
  36. //---------------------------------------------------------------------------
  37. interface
  38. //---------------------------------------------------------------------------
  39. uses
  40.  Types, SysUtils, Vectors2px, AsphyreXML, AsphyreTypes, MediaUtils, GuiTypes,
  41.  AsphyreFonts;
  42. //---------------------------------------------------------------------------
  43. type
  44.  PGuiProperty = ^TGuiProperty;
  45.  TGuiProperty = record
  46.   Code : Cardinal;
  47.   Name : string;
  48.   DType: TGuiDataType;
  49.  end;
  50. //---------------------------------------------------------------------------
  51.  TGuiCustomObject = class
  52.  private
  53.   Properties: array of TGuiProperty;
  54.   procedure SortProperties(Left, Right: Integer);
  55.  protected
  56.   function IndexOfProperty(const Name: string): Integer;
  57.   function GetProperty(Index: Integer): PGuiProperty;
  58.   procedure Describe(Code: Cardinal; const Name: string; DType: TGuiDataTYpe);
  59.   procedure DoDescribe(); virtual;
  60.   procedure WriteProperty(Code: Cardinal; Source: Pointer); virtual;
  61.  public
  62.   constructor Create();
  63.  end;
  64. //---------------------------------------------------------------------------
  65.  TGuiObject = class(TGuiCustomObject)
  66.  private
  67.   FOwner: TGuiObject;
  68.   FName : string;
  69.   Children : array of TGuiObject;
  70.   NoExclude: Boolean;
  71.   SearchDirty: Boolean;
  72.   SearchIndex: array of Integer;
  73.   function GetChildCount(): Integer;
  74.   function GetChild(Index: Integer): TGuiObject;
  75.   function Insert(Component: TGuiObject): Integer;
  76.   procedure Remove(Index: Integer);
  77.   procedure SetName(const Value: string);
  78.   function GetCtrl(const Name: string): TGuiObject;
  79.   procedure FillSearchIndex();
  80.   procedure SortSearchIndex(Left, Right: Integer);
  81.   procedure MakeSearchIndex();
  82.   function Include(Obj: TGuiObject): Integer;
  83.   procedure Exclude(Obj: TGuiObject);
  84.   function GetRootNode(): TGuiObject;
  85.  protected
  86.   procedure MarkSearchDirty();
  87.   procedure MoveToFront(Index: Integer); virtual;
  88.   procedure MoveToBack(Index: Integer); virtual;
  89.   procedure DoDestroy(); virtual;
  90.   procedure DoObjectLinked(Index: Integer; Obj: TGuiObject); virtual;
  91.   procedure DoObjectUnlinked(Index: Integer; Obj: TGuiObject); virtual;
  92.   procedure DoDescribe(); override;
  93.   procedure WriteProperty(Code: Cardinal; Source: Pointer); override;
  94.  public
  95.   property Owner: TGuiObject read FOwner;
  96.   property Name : string read FName write SetName;
  97.   property ChildCount: Integer read GetChildCount;
  98.   property Child[Index: Integer]: TGuiObject read GetChild;
  99.   property RootNode: TGuiObject read GetRootNode;
  100.   property Ctrl[const Name: string]: TGuiObject read GetCtrl; default;
  101.   function IndexOf(Obj: TGuiObject): Integer; overload;
  102.   function IndexOf(Name: string): Integer; overload;
  103.   procedure RemoveAll();
  104.   procedure LoadFromXML(Parent: TXMLNode);
  105.   procedure ParseLink(const Link: string);
  106.   constructor Create(AOwner: TGuiObject); virtual;
  107.   destructor Destroy(); override;
  108.  end;
  109. //---------------------------------------------------------------------------
  110. implementation
  111. //---------------------------------------------------------------------------
  112. uses
  113.  GuiSkins, GuiRegistry;
  114. //---------------------------------------------------------------------------
  115. const
  116.  PropInc  = 16;
  117.  PropBase = $10;
  118. //---------------------------------------------------------------------------
  119. function ParseFontOptions(Node: TXMLNode): TFontOptions;
  120. var
  121.  Aux: TXMLNode;
  122. begin
  123.  Result.Reset();
  124.  // -> "shadow" node
  125.  Aux:= Node.ChildNode['shadow'];
  126.  if (Aux <> nil) then
  127.   begin
  128.    Result.ShowShadow   := ParseBoolean(LowerCase(Aux.FieldValue['show']), False);
  129.    Result.ShadowAlpha  := ParseInt(Aux.FieldValue['alpha'], 128);
  130.    Result.ShadowDepth.x:= ParseInt(Aux.FieldValue['dx'], 2);
  131.    Result.ShadowDepth.y:= ParseInt(Aux.FieldValue['dy'], 2);
  132.   end;
  133.  // -> "text" node
  134.  Aux:= Node.ChildNode['text'];
  135.  if (Aux <> nil) then
  136.   begin
  137.    Result.Kerning:= ParseInt(Aux.FieldValue['kerning'], 0);
  138.    Result.Scale  := ParseInt(Aux.FieldValue['scale'], 65536);
  139.    Result.Shift.x:= ParseInt(Aux.FieldValue['dx'], 0);
  140.    Result.Shift.y:= ParseInt(Aux.FieldValue['dy'], 0);
  141.   end;
  142. end;
  143. //---------------------------------------------------------------------------
  144. constructor TGuiCustomObject.Create();
  145. begin
  146.  inherited;
  147.  DoDescribe();
  148.  if (Length(Properties) > 0) then SortProperties(0, Length(Properties) - 1);
  149. end;
  150. //---------------------------------------------------------------------------
  151. function TGuiCustomObject.GetProperty(Index: Integer): PGuiProperty;
  152. begin
  153.  if (Index >= 0)and(Index < Length(Properties)) then
  154.   Result:= @Properties[Index] else Result:= nil;
  155. end;
  156. //---------------------------------------------------------------------------
  157. procedure TGuiCustomObject.Describe(Code: Cardinal; const Name: string;
  158.  DType: TGuiDataTYpe);
  159. var
  160.  Index: Integer;
  161. begin
  162.  Index:= Length(Properties);
  163.  SetLength(Properties, Index + 1);
  164.  Properties[Index].Code := Code;
  165.  Properties[Index].Name := Name;
  166.  Properties[Index].DType:= DType;
  167. end;
  168. //---------------------------------------------------------------------------
  169. procedure TGuiCustomObject.DoDescribe();
  170. begin
  171.  // no code
  172. end;
  173. //---------------------------------------------------------------------------
  174. procedure TGuiCustomObject.WriteProperty(Code: Cardinal; Source: Pointer);
  175. begin
  176.  // no code
  177. end;
  178. //---------------------------------------------------------------------------
  179. procedure TGuiCustomObject.SortProperties(Left, Right: Integer);
  180. var
  181.  Lo, Hi  : Integer;
  182.  TempProp: TGuiProperty;
  183.  MidValue: string;
  184. begin
  185.  Lo:= Left;
  186.  Hi:= Right;
  187.  MidValue:= Properties[(Left + Right) div 2].Name;
  188.  repeat
  189.   while (CompareText(Properties[Lo].Name, MidValue) < 0) do Inc(Lo);
  190.   while (CompareText(Properties[Hi].Name, MidValue) > 0) do Dec(Hi);
  191.   if (Lo <= Hi) then
  192.    begin
  193.     TempProp:= Properties[Lo];
  194.     Properties[Lo]:= Properties[Hi];
  195.     Properties[Hi]:= TempProp;
  196.     Inc(Lo);
  197.     Dec(Hi);
  198.    end;
  199.  until (Lo > Hi);
  200.  if (Left < Hi) then SortProperties(Left, Hi);
  201.  if (Lo < Right) then SortProperties(Lo, Right);
  202. end;
  203. //---------------------------------------------------------------------------
  204. function TGuiCustomObject.IndexOfProperty(const Name: string): Integer;
  205. var
  206.  Lo, Hi, Mid, CompRes: Integer;
  207. begin
  208.  Result:= -1;
  209.  Lo:= 0;
  210.  Hi:= Length(Properties) - 1;
  211.  while (Lo <= Hi) do
  212.   begin
  213.    Mid:= (Lo + Hi) div 2;
  214.    CompRes:= CompareText(Properties[Mid].Name, Name);
  215.    if (CompRes = 0) then
  216.     begin
  217.      Result:= Mid;
  218.      Break;
  219.     end;
  220.    if (CompRes > 0) then Hi:= Mid - 1 else Lo:= Mid + 1;
  221.  end;
  222. end;
  223. //---------------------------------------------------------------------------
  224. constructor TGuiObject.Create(AOwner: TGuiObject);
  225. begin
  226.  inherited Create();
  227.  NoExclude  := False;
  228.  SearchDirty:= False;
  229.  FOwner:= AOwner;
  230.  if (FOwner <> nil) then FOwner.Include(Self);
  231. end;
  232. //---------------------------------------------------------------------------
  233. destructor TGuiObject.Destroy();
  234. begin
  235.  RemoveAll();
  236.  DoDestroy();
  237.  if (FOwner <> nil)and(not NoExclude) then FOwner.Exclude(Self);
  238.  inherited;
  239. end;
  240. //---------------------------------------------------------------------------
  241. procedure TGuiObject.DoDestroy();
  242. begin
  243.  // no code
  244. end;
  245. //---------------------------------------------------------------------------
  246. procedure TGuiObject.DoObjectLinked(Index: Integer; Obj: TGuiObject);
  247. begin
  248.  // no code
  249. end;
  250. //---------------------------------------------------------------------------
  251. procedure TGuiObject.DoObjectUnlinked(Index: Integer; Obj: TGuiObject);
  252. begin
  253.  // no code
  254. end;
  255. //---------------------------------------------------------------------------
  256. function TGuiObject.GetChildCount(): Integer;
  257. begin
  258.  Result:= Length(Children);
  259. end;
  260. //---------------------------------------------------------------------------
  261. function TGuiObject.GetChild(Index: Integer): TGuiObject;
  262. begin
  263.  if (Index >= 0)and(Index < Length(Children)) then
  264.   Result:= Children[Index] else Result:= nil;
  265. end;
  266. //---------------------------------------------------------------------------
  267. function TGuiObject.IndexOf(Obj: TGuiObject): Integer;
  268. var
  269.  i: Integer;
  270. begin
  271.  Result:= -1;
  272.  for i:= 0 to Length(Children) - 1 do
  273.   if (Children[i] = Obj) then
  274.    begin
  275.     Result:= i;
  276.     Break;
  277.    end;
  278. end;
  279. //---------------------------------------------------------------------------
  280. function TGuiObject.Insert(Component: TGuiObject): Integer;
  281. var
  282.  Index: Integer;
  283. begin
  284.  Index:= Length(Children);
  285.  SetLength(Children, Index + 1);
  286.  Children[Index]:= Component;
  287.  Result:= Index;
  288. end;
  289. //---------------------------------------------------------------------------
  290. function TGuiObject.Include(Obj: TGuiObject): Integer;
  291. begin
  292.  Result:= IndexOf(Obj);
  293.  if (Result = -1) then
  294.   begin
  295.    Result:= Insert(Obj);
  296.    DoObjectLinked(Result, Obj);
  297.   end;
  298. end;
  299. //---------------------------------------------------------------------------
  300. procedure TGuiObject.Remove(Index: Integer);
  301. var
  302.  i: Integer;
  303. begin
  304.  if (Index < 0)or(Index >= Length(Children)) then Exit;
  305.  for i:= Index to Length(Children) - 2 do
  306.   Children[i]:= Children[i + 1];
  307.  SetLength(Children, Length(Children) - 1);
  308. end;
  309. //---------------------------------------------------------------------------
  310. procedure TGuiObject.Exclude(Obj: TGuiObject);
  311. var
  312.  Index: Integer;
  313. begin
  314.  Index:= IndexOf(Obj);
  315.  if (Index <> -1) then
  316.   begin
  317.    Remove(Index);
  318.    DoObjectUnlinked(Index, Obj);
  319.   end;
  320. end;
  321. //---------------------------------------------------------------------------
  322. procedure TGuiObject.RemoveAll();
  323. var
  324.  i: Integer;
  325. begin
  326.  for i:= 0 to Length(Children) - 1 do
  327.   if (Children[i] <> nil) then
  328.    begin
  329.     Children[i].NoExclude:= True;
  330.     Children[i].Free();
  331.     Children[i]:= nil;
  332.    end;
  333.  SetLength(Children, 0);
  334. end;
  335. //---------------------------------------------------------------------------
  336. procedure TGuiObject.SetName(const Value: string);
  337. begin
  338.  FName:= Value;
  339.  if (FOwner <> nil) then FOwner.MarkSearchDirty();
  340. end;
  341. //---------------------------------------------------------------------------
  342. procedure TGuiObject.MoveToBack(Index: Integer);
  343. var
  344.  Temp: TGuiObject;
  345.  i: Integer;
  346. begin
  347.  Temp:= Children[Index];
  348.  for i:= Index to Length(Children) - 2 do
  349.   Children[i]:= Children[i + 1];
  350.  Children[Length(Children) - 1]:= Temp;
  351. end;
  352. //---------------------------------------------------------------------------
  353. procedure TGuiObject.MoveToFront(Index: Integer);
  354. var
  355.  Temp: TGuiObject;
  356.  i: Integer;
  357. begin
  358.  Temp:= Children[Index];
  359.  for i:= Index downto 1 do
  360.   Children[i]:= Children[i - 1];
  361.  Children[0]:= Temp;
  362. end;
  363. //---------------------------------------------------------------------------
  364. procedure TGuiObject.MarkSearchDirty();
  365. begin
  366.  SearchDirty:= Length(Children) > 1;
  367. end;
  368. //---------------------------------------------------------------------------
  369. procedure TGuiObject.FillSearchIndex();
  370. var
  371.  i: Integer;
  372. begin
  373.  SetLength(SearchIndex, Length(Children));
  374.  for i:= 0 to Length(SearchIndex) - 1 do
  375.   SearchIndex[i]:= i;
  376. end;
  377. //---------------------------------------------------------------------------
  378. procedure TGuiObject.SortSearchIndex(Left, Right: Integer);
  379. var
  380.  Lo, Hi: Integer;
  381.  TempIndex: Integer;
  382.  MidValue: string;
  383. begin
  384.  Lo:= Left;
  385.  Hi:= Right;
  386.  MidValue:= Children[SearchIndex[(Left + Right) shr 1]].Name;
  387.  repeat
  388.   while (CompareText(Children[SearchIndex[Lo]].Name, MidValue) < 0) do Inc(Lo);
  389.   while (CompareText(Children[SearchIndex[Hi]].Name, MidValue) > 0) do Dec(Hi);
  390.   if (Lo <= Hi) then
  391.    begin
  392.     TempIndex:= SearchIndex[Lo];
  393.     SearchIndex[Lo]:= SearchIndex[Hi];
  394.     SearchIndex[Hi]:= TempIndex;
  395.     Inc(Lo);
  396.     Dec(Hi);
  397.    end;
  398.  until (Lo > Hi);
  399.  if (Left < Hi) then SortSearchIndex(Left, Hi);
  400.  if (Lo < Right) then SortSearchIndex(Lo, Right);
  401. end;
  402. //---------------------------------------------------------------------------
  403. procedure TGuiObject.MakeSearchIndex();
  404. begin
  405.  FillSearchIndex();
  406.  if (Length(SearchIndex) > 1) then
  407.   SortSearchIndex(0, Length(SearchIndex) - 1);
  408.  SearchDirty:= False;
  409. end;
  410. //---------------------------------------------------------------------------
  411. function TGuiObject.IndexOf(Name: string): Integer;
  412. var
  413.  Lo, Hi, Mid, CompRes: Integer;
  414. begin
  415.  if (SearchDirty) then MakeSearchIndex();
  416.  Name  := LowerCase(Name);
  417.  Result:= -1;
  418.  Lo:= 0;
  419.  Hi:= Length(SearchIndex) - 1;
  420.  while (Lo <= Hi) do
  421.   begin
  422.    Mid:= (Lo + Hi) div 2;
  423.    CompRes:= CompareText(Children[SearchIndex[Mid]].Name, Name);
  424.    if (CompRes = 0) then
  425.     begin
  426.      Result:= SearchIndex[Mid];
  427.      Break;
  428.     end;
  429.    if (CompRes > 0) then Hi:= Mid - 1 else Lo:= Mid + 1;
  430.  end;
  431. end;
  432. //---------------------------------------------------------------------------
  433. function TGuiObject.GetCtrl(const Name: string): TGuiObject;
  434. var
  435.  i, Index: Integer;
  436. begin
  437.  if (CompareText(FName, Name) = 0) then
  438.   begin
  439.    Result:= Self;
  440.    Exit;
  441.   end;
  442.  Index:= IndexOf(Name);
  443.  if (Index <> -1) then
  444.   begin
  445.    Result:= Children[Index];
  446.    Exit;
  447.   end;
  448.  Result:= nil;
  449.  for i:= 0 to Length(Children) - 1 do
  450.   begin
  451.    Result:= Children[i].Ctrl[Name];
  452.    if (Result <> nil) then Break;
  453.   end;
  454. end;
  455. //---------------------------------------------------------------------------
  456. function TGuiObject.GetRootNode(): TGuiObject;
  457. begin
  458.  Result:= Self;
  459.  while (Result.Owner <> nil) do Result:= Result.Owner;
  460. end;
  461. //---------------------------------------------------------------------------
  462. procedure TGuiObject.DoDescribe();
  463. begin
  464.  Describe(PropBase + $0, 'Name', gdtString);
  465. end;
  466. //---------------------------------------------------------------------------
  467. procedure TGuiObject.WriteProperty(Code: Cardinal; Source: Pointer);
  468. begin
  469.  case Code of
  470.   PropBase + $0:
  471.    FName:= PChar(Source);
  472.  end;
  473. end;
  474. //---------------------------------------------------------------------------
  475. procedure TGuiObject.LoadFromXML(Parent: TXMLNode);
  476. var
  477.  i: Integer;
  478.  NodeName: string;
  479.  Ctrl : TGuiObject;
  480.  Node: TXMLNode;
  481.  Prop: PGuiProperty;
  482.  Value : Integer;
  483.  VReal : Real;
  484.  VText : string;
  485.  VPoint: TPoint2px;
  486.  VSize : TPoint2px;
  487.  VRect : TRect;
  488.  VCol2 : TColor2;
  489.  VFOpt : TFontOptions;
  490.  VSkin : TGuiSkin;
  491.  VFCol : TGuiFontCol;
  492. begin
  493.  FName:= Parent.FieldValue['name'];
  494.  for i:= 0 to Parent.ChildCount - 1 do
  495.   begin
  496.    Node:= Parent.Child[i];
  497.    NodeName:= LowerCase(Node.Name);
  498.    if (NodeName = 'property') then
  499.     begin
  500.      Prop:= GetProperty(IndexOfProperty(Node.FieldValue['name']));
  501.      if (Prop = nil) then Continue;
  502.      case Prop.DType of
  503.       gdtInteger:
  504.        begin
  505.         Value:= ParseInt(Node.FieldValue['value'], 0);
  506.         WriteProperty(Prop.Code, @Value);
  507.        end;
  508.       gdtCardinal:
  509.        begin
  510.         Value:= Integer(ParseCardinal(Node.FieldValue['value'], 0));
  511.         WriteProperty(Prop.Code, @Value);
  512.        end;
  513.       gdtReal:
  514.        begin
  515.         VReal:= ParseFloat(Node.FieldValue['value'], 0.0);
  516.         WriteProperty(Prop.Code, @VReal);
  517.        end;
  518.       gdtString:
  519.        begin
  520.         VText:= Node.FieldValue['text'];
  521.         WriteProperty(Prop.Code, PChar(VText));
  522.        end;
  523.       gdtBoolean:
  524.        begin
  525.         Value:= Integer(ParseBoolean(Node.FieldValue['value']));
  526.         WriteProperty(Prop.Code, @Value);
  527.        end;
  528.       gdtPoint:
  529.        begin
  530.         VPoint.x:= ParseInt(Node.FieldValue['x'], 0);
  531.         VPoint.y:= ParseInt(Node.FieldValue['y'], 0);
  532.         WriteProperty(Prop.Code, @VPoint);
  533.        end;
  534.       gdtRect:
  535.        begin
  536.         VPoint.x:= ParseInt(Node.FieldValue['x'], 0);
  537.         VPoint.y:= ParseInt(Node.FieldValue['y'], 0);
  538.         VSize.x := ParseInt(Node.FieldValue['width'], 0);
  539.         VSize.y := ParseInt(Node.FieldValue['height'], 0);
  540.         VRect   := Bounds(VPoint.x, VPoint.y, VSize.x, VSize.y);
  541.         WriteProperty(Prop.Code, @VRect);
  542.        end;
  543.       gdtColor:
  544.        begin
  545.         Value:= Integer(ParseColorField(Node));
  546.         WriteProperty(Prop.Code, @Value);
  547.        end;
  548.       gdtColor2:
  549.        begin
  550.         VCol2:= ParseColor2Field(Node);
  551.         WriteProperty(Prop.Code, @VCol2);
  552.        end;
  553.       gdtHAlign:
  554.        begin
  555.         Value:= Integer(ParseHAlign(LowerCase(Node.FieldValue['align'])));
  556.         WriteProperty(Prop.Code, @Value);
  557.        end;
  558.       gdtVAlign:
  559.        begin
  560.         Value:= Integer(ParseVAlign(LowerCase(Node.FieldValue['align'])));
  561.         WriteProperty(Prop.Code, @Value);
  562.        end;
  563.       gdtFontOpt:
  564.        begin
  565.         VFOpt:= ParseFontOptions(Node);
  566.         WriteProperty(Prop.Code, @VFOpt);
  567.        end;
  568.      gdtSkin:
  569.       begin
  570.        VSkin:= TGuiSkin.Create();
  571.        VSkin.LoadFromXML(Node);
  572.        WriteProperty(Prop.Code, VSkin);
  573.        VSkin.Free();
  574.       end;
  575.      gdtFontColor:
  576.       begin
  577.        VFCol:= TGuiFontCol.Create();
  578.        VFCol.LoadFromXML(Node);
  579.        WriteProperty(Prop.Code, VFCol);
  580.        VFCol.Free();
  581.       end;
  582.      end; // case
  583.     end; // if Property
  584.    if (NodeName = 'control') then
  585.     begin
  586.      Ctrl:= CreateGuiClass(LowerCase(Node.FieldValue['class']), Self);
  587.      if (Ctrl <> nil) then Ctrl.LoadFromXML(Node);
  588.     end;
  589.   end;
  590. end;
  591. //---------------------------------------------------------------------------
  592. procedure TGuiObject.ParseLink(const Link: string);
  593. var
  594.  NodeName: string;
  595.  Root : TXMLNode;
  596.  Child: TXMLNode;
  597.  Ctrl : TGuiObject;
  598.  Text : string;
  599.  i, j: Integer;
  600. begin
  601.  Root:= LoadLinkXML(Link);
  602.  if (Root = nil) then Exit;
  603.  if (LowerCase(Root.Name) <> 'unires')  then
  604.   begin
  605.    Root.Free();
  606.    Exit;
  607.   end;
  608.  for i:= 0 to Root.ChildCount - 1 do
  609.   begin
  610.    NodeName:= LowerCase(Root.Child[i].Name);
  611.    if (NodeName = 'agui') then
  612.     for j:= 0 to Root.Child[i].ChildCount - 1 do
  613.      begin
  614.       Child:= Root.Child[i].Child[j];
  615.       if (LowerCase(Child.Name) = 'control') then
  616.        begin
  617.         Ctrl:= CreateGuiClass(LowerCase(Child.FieldValue['class']), Self);
  618.         if (Ctrl <> nil) then Ctrl.LoadFromXML(Child);
  619.        end;
  620.      end;
  621.    if (NodeName = 'resource') then
  622.     begin
  623.      Text:= Root.Child[i].FieldValue['source'];
  624.      if (Length(Text) > 0) then ParseLink(Text);
  625.     end;
  626.   end;
  627.  Root.Free();
  628. end;
  629. //---------------------------------------------------------------------------
  630. end.