{********************************************************************}
{ written by TMS Software                                            }
{            COPYRIGHT © 2014                                        }
{            Email : info@tmssoftware.com                            }
{            Web : http://www.tmssoftware.com                        }
{                                                                    }
{ The source code is given as is. The author is not responsible      }
{ for any possible damage done due to the use of this code.          }
{ The complete source code remains property of the author and may    }
{ not be distributed, published, given or sold in any form as such.  }
{ No parts of the source code can be included in any other component }
{ or application without written authorization of the author.        }
{********************************************************************}
//{$DEFINE COMPILEFMI}
unit FMX.TMSGridCell;

interface

{$I TMSDEFS.INC}

uses
  {$IFNDEF IOS}
  {$IFNDEF MACOS}
  {$IFNDEF ANDROID}
  Windows,
  {$ENDIF}
  {$ENDIF}
  {$ENDIF}
  Classes, SysUtils, FMX.Types, UITypes, Types, FMX.TMSHTMLText, Variants,
  FMX.TMSBitmapContainer, FMX.TMSHTMLEngine, FMX.Controls, FMX.ExtCtrls, FMX.TMSBarButton,
  FMX.Objects, FMX.TMSBitmap, FMX.Edit, FMX.TMSProgressBar, FMX.TMSBaseControl, FMX.ANI
  , FMX.StdCtrls, UIConsts
  {$IFDEF DELPHIXE5_LVL}
  , FMX.Graphics
  {$ENDIF}
  {$IFDEF DELPHIXE6_LVL}
  , System.Math.Vectors
  {$ENDIF}
  ;

type
  TTMSFMXCustomGridCellData = class(TTMSFMXBaseControl);

  TTMSFMXFixedGridCell = class;

  TNodeState = (nsClosed, nsOpen);

  TCommentShape = class(TTMSFMXBaseShape)
  public
    procedure Paint; override;
  end;

  TSortShape = class(TTMSFMXBaseShape)
  private
    FOwner: TTMSFMXFixedGridCell;
  public
    constructor Create(AOwner: TComponent); override;
    procedure Paint; override;
  end;

  TTMSFMXCheckBox = class(TCheckBox)
  private
    function GetIsCheckedProg: Boolean;
    procedure SetIsCheckedProg(const Value: Boolean);
  public
    property IsCheckedProg: Boolean read GetIsCheckedProg write SetIsCheckedProg;
  end;

  TTMSFMXRadioButton = class(TRadioButton)
  private
    function GetIsCheckedProg: Boolean;
    procedure SetIsCheckedProg(const Value: Boolean);
  public
    property IsCheckedProg: Boolean read GetIsCheckedProg write SetIsCheckedProg;
  end;

  TSortKind = (skNone, skAscending, skDescending);

  TTMSFMXGridCellLayout = class(TPersistent)
  private
    FOwner: TComponent;
    FFontFill: TBrush;
    FStrokeJoin: TStrokeJoin;
    FStrokeThickness: Single;
    FStrokeCap: TStrokeCap;
    FSides: TSides;
    FStrokeDash: TStrokeDash;
    FFill: TBrush;
    FStroke: TBrush;
    FOnChange: TNotifyEvent;
    FFontFlags: TFillTextFlags;
    FVerticalTextAlign: TTextAlign;
    FFont: TFont;
    FTextAlign: TTextAlign;
    FWordWrapping: Boolean;
    procedure SetFill(const Value: TBrush);
    procedure SetFontFill(const Value: TBrush);
    procedure SetSides(const Value: TSides);
    procedure SetStroke(const Value: TBrush);
    procedure SetStrokeCap(const Value: TStrokeCap);
    procedure SetStrokeDash(const Value: TStrokeDash);
    procedure SetStrokeJoin(const Value: TStrokeJoin);
    procedure SetStrokeThickness(const Value: Single);
    procedure SetFont(const Value: TFont);
    procedure SetFontFlags(const Value: TFillTextFlags);
    procedure SetTextAlign(const Value: TTextAlign);
    procedure SetVerticalTextAlign(const Value: TTextAlign);
    procedure SetWordWrapping(const Value: Boolean);
  protected
    procedure Changed(Sender: TObject);
  public
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    property Owner: TComponent read FOwner write FOwner;
  published
    {$IFDEF DELPHIXE6_LVL}
    property Sides: TSides read FSides write SetSides default [TSide.Top, TSide.Left, TSide.Bottom, TSide.Right];
    {$ELSE}
    property Sides: TSides read FSides write SetSides default [TSide.sdTop, TSide.sdLeft, TSide.sdBottom, TSide.sdRight];
    {$ENDIF}
    property Fill: TBrush read FFill write SetFill;
    property Stroke: TBrush read FStroke write SetStroke;
    property StrokeThickness: Single read FStrokeThickness write SetStrokeThickness;
    property FontFill: TBrush read FFontFill write SetFontFill;
    property Font: TFont read FFont write SetFont;
    property FontFlags: TFillTextFlags read FFontFlags write SetFontFlags default [];
    {$IFDEF DELPHIXE6_LVL}
    property StrokeCap: TStrokeCap read FStrokeCap write SetStrokeCap default TStrokeCap.Flat;
    property StrokeDash: TStrokeDash read FStrokeDash write SetStrokeDash default TStrokeDash.Solid;
    property StrokeJoin: TStrokeJoin read FStrokeJoin write SetStrokeJoin default TStrokeJoin.Miter;
    property TextAlign: TTextAlign read FTextAlign write SetTextAlign default TTextAlign.Leading;
    property VerticalTextAlign: TTextAlign read FVerticalTextAlign write SetVerticalTextAlign default TTextAlign.Center;
    {$ELSE}
    property StrokeCap: TStrokeCap read FStrokeCap write SetStrokeCap default TStrokeCap.scFlat;
    property StrokeDash: TStrokeDash read FStrokeDash write SetStrokeDash default TStrokeDash.sdSolid;
    property StrokeJoin: TStrokeJoin read FStrokeJoin write SetStrokeJoin default TStrokeJoin.sjMiter;
    property TextAlign: TTextAlign read FTextAlign write SetTextAlign default TTextAlign.taLeading;
    property VerticalTextAlign: TTextAlign read FVerticalTextAlign write SetVerticalTextAlign default TTextAlign.taCenter;
    {$ENDIF}
    property WordWrapping: Boolean read FWordWrapping write SetWordWrapping default False;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

  TTMSFMXCellBeforeDraw = procedure(Sender: TObject; ACanvas: TCanvas; var ARect: TRectF;
    var ATextRect: TRectF; var ADrawText: Boolean; var ADrawBackGround: Boolean; var AllowDraw: Boolean) of object;

  TTMSFMXCellAfterDraw = procedure(Sender: TObject; ACanvas: TCanvas; ARect: TRectF) of object;

  TControlProtected = class(TControl);

  TTMSFMXGridCell = class(TControl)
  private
    FText: String;
    FLayout: TTMSFMXGridCellLayout;
    FBitmapContainer: TTMSFMXBitmapContainer;
    FOnAfterDraw: TTMSFMXCellAfterDraw;
    FOnBeforeDraw: TTMSFMXCellBeforeDraw;
    procedure SetText(const Value: String); virtual;
    procedure SetBitmapContainer(const Value: TTMSFMXBitmapContainer); virtual;
    procedure SetLayout(const Value: TTMSFMXGridCellLayout); virtual;
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure Changed(Sender: TObject);
  public
    function GetTextRect: TRectF; virtual;
    function GetTextRectBase(ARect: TRectF): TRectF; virtual;
    function GetControl: TControl; virtual;
    function GetPrintControl: TControl; virtual;
    procedure HTMLDraw(ACanvas: TCanvas; ARect: TRectF; TestAnchor: boolean; X,Y: single; var Anchor: string);
    function IsHTML: boolean;
    function GetTextWidth: Single;
    function GetTextHeight: Single;
    function GetTextSize: TSizeF;
    function GetStrippedHTMLText: String;
    function XYToAnchor(X, Y: Single): String;
    procedure Paint; override;
    procedure Print(ACanvas: TCanvas; ARect, ATextRect: TRectF; ADrawText: Boolean; ADrawBackGround: Boolean; sx, sy: Single);
    procedure Draw(ACanvas: TCanvas; ARect, ATextRect: TRectF; ADrawText: Boolean; ADrawBackGround: Boolean);
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    procedure AssignLayout(Source: TTMSFMXGridCellLayout);
  published
    property Position;
    property Width;
    property Height;
    property Visible;
    property Text: String read FText write SetText;
    property Layout: TTMSFMXGridCellLayout read FLayout write SetLayout;
    property BitmapContainer: TTMSFMXBitmapContainer read FBitmapContainer write SetBitmapContainer;
    property OnBeforeDraw: TTMSFMXCellBeforeDraw read FOnBeforeDraw write FOnBeforeDraw;
    property OnAfterDraw: TTMSFMXCellAfterDraw read FOnAfterDraw write FOnAfterDraw;
  end;

  TTMSFMXRadioGridCell = class(TTMSFMXGridCell)
  private
    FRadioButton: TTMSFMXRadioButton;
    function GetRadioButton: TTMSFMXRadioButton;
    procedure SetRadioButton(const Value: TTMSFMXRadioButton);
  public
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property RadioButton: TTMSFMXRadioButton read GetRadioButton write SetRadioButton;
  end;

  TTMSFMXCheckGridCell = class(TTMSFMXGridCell)
  private
    FCheckBox: TTMSFMXCheckBox;
    function GetCheckBox: TTMSFMXCheckBox;
    procedure SetCheckBox(const Value: TTMSFMXCheckBox);
  public
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property CheckBox: TTMSFMXCheckBox read GetCheckBox write SetCheckBox;
  end;

  TTMSFMXButtonGridCell = class(TTMSFMXGridCell)
  private
    FButton: TButton;
    function GetButton: TButton;
    procedure SetButton(const Value: TButton);
  public
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Button: TButton read GetButton write SetButton;
  end;

  TTMSFMXProgressGridCell = class(TTMSFMXGridCell)
  private
    FProgressBar: TTMSFMXProgressBar;
    function GetProgressBar: TTMSFMXProgressBar;
    procedure SetProgressBar(const Value: TTMSFMXProgressBar);
  public
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Paint; override;
    property ProgressBar: TTMSFMXProgressBar read GetProgressBar write SetProgressBar;
  end;

  TTMSFMXCommentGridCell = class(TTMSFMXGridCell)
  private
    FCommentPanel: TCalloutRectangle;
    FCommentText: TLabel;
    FComment: TCommentShape;
    FPopup: TPopup;
    FPopupControl: TControl;
    FOnShowPopup: TNotifyEvent;
    FOnHidePopup: TNotifyEvent;
    function GetComment: TCommentShape;
    procedure SetComment(const Value: TCommentShape);
    procedure SetPopup(const Value: TPopup);
  protected
    procedure ClosePopup(Sender: TObject);
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    function IsPopupOpen: Boolean;
    procedure ShowPopup;
    procedure HidePopup;
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property CommentPanel: TCalloutRectangle read FCommentPanel write FCommentPanel;
    property Comment: TCommentShape read GetComment write SetComment;
    property CommentText: TLabel read FCommentText write FCommentText;
    property Popup: TPopup read FPopup write SetPopup;
    property PopupControl: TControl read FPopupControl write FPopupControl;
    procedure Resize; override;

    property OnShowPopup: TNotifyEvent read FOnShowPopup write FOnShowPopup;
    property OnHidePopup: TNotifyEvent read FOnHidePopup write FOnHidePopup;
  end;

  TTMSFMXFixedGridCell = class(TTMSFMXGridCell)
  private
    FSortShape: TSortShape;
    FSortKind: TSortKind;
    FSortIndex: Integer;
    FSortFill: TBrush;
    FSortStroke: TBrush;
    FSortFontFill: TBrush;
    FSortFont: TFont;
    FCheckBox: TTMSFMXCheckBox;
    FBitmap: TTMSFMXBitmap;
    FButton: TButton;
    FSpinBox: TSpinBox;
    FShowButton: Boolean;
    FShowBitmap: Boolean;
    FShowSpinBox: Boolean;
    FShowCheckBox: Boolean;
    FOnShowPopup: TNotifyEvent;
    FPopup: TPopup;
    FShowDropDownButton: Boolean;
    FOnHidePopup: TNotifyEvent;
    FPopupControl: TControl;
    FDropDownButton: TCornerButton;
    procedure SetSortKind(const Value: TSortKind);
    function GetSortShape: TSortShape;
    procedure SetSortShape(const Value: TSortShape);
    procedure SetSortIndex(const Value: Integer);
    procedure SetSortFill(const Value: TBrush);
    procedure SetSortStroke(const Value: TBrush);
    procedure SetSortFont(const Value: TFont);
    procedure SetSortFontFill(const Value: TBrush);
    procedure SetShowBitmap(const Value: Boolean);
    procedure SetShowButton(const Value: Boolean);
    procedure SetShowCheckBox(const Value: Boolean);
    procedure SetShowSpinBox(const Value: Boolean);
    procedure SetBitmap(const Value: TTMSFMXBitmap);
    procedure SetButton(const Value: TButton);
    procedure SetCheckBox(const Value: TTMSFMXCheckBox);
    procedure SetSpinBox(const Value: TSpinBox);
    procedure SetPopup(const Value: TPopup);
    procedure SetShowDropDownButton(const Value: Boolean);
    procedure SetDropDownButton(const Value: TCornerButton);
  protected
    procedure ClosePopup(Sender: TObject);
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  public
    function DropDownButtonHasBitmap: Boolean;
    property ShowCheckBox: Boolean read FShowCheckBox write SetShowCheckBox default False;
    property ShowBitmap: Boolean read FShowBitmap write SetShowBitmap default False;
    property ShowSpinBox: Boolean read FShowSpinBox write SetShowSpinBox default False;
    property ShowButton: Boolean read FShowButton write SetShowButton default False;
    property ShowDropDownButton: Boolean read FShowDropDownButton write SetShowDropDownButton default False;

    property Popup: TPopup read FPopup write SetPopup;
    property PopupControl: TControl read FPopupControl write FPopupControl;
    function IsPopupOpen: Boolean;
    procedure ShowPopup;
    procedure HidePopup;
    property CheckBox: TTMSFMXCheckBox read FCheckBox write SetCheckBox;
    property Bitmap: TTMSFMXBitmap read FBitmap write SetBitmap;
    property SpinBox: TSpinBox read FSpinBox write SetSpinBox;
    property Button: TButton read FButton write SetButton;
    property DropDownButton: TCornerButton read FDropDownButton write SetDropDownButton;
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property SortKind: TSortKind read FSortKind write SetSortKind default skDescending;
    property SortIndex: Integer read FSortIndex write SetSortIndex default -1;
    property SortFill: TBrush read FSortFill write SetSortFill;
    property SortFont: TFont read FSortFont write SetSortFont;
    property SortFontFill: TBrush read FSortFontFill write SetSortFontFill;
    property SortStroke: TBrush read FSortStroke write SetSortStroke;
    property SortShape: TSortShape read GetSortShape write SetSortShape;
    procedure Resize; override;

    property OnShowPopup: TNotifyEvent read FOnShowPopup write FOnShowPopup;
    property OnHidePopup: TNotifyEvent read FOnHidePopup write FOnHidePopup;
  end;

  TTMSFMXRotatedTextGridCell = class(TTMSFMXFixedGridCell)
  private
    FRotatedText: TTMSFMXHTMLText;
    procedure SetText(const Value: String); override;
    procedure SetLayout(const Value: TTMSFMXGridCellLayout); override;
    function GetRotatedText: TTMSFMXHTMLText;
    procedure SetRotatedText(const Value: TTMSFMXHTMLText);
  public
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Paint; override;
    procedure Resize; override;
    property RotatedText: TTMSFMXHTMLText read GetRotatedText write SetRotatedText;
  end;

  TTMSFMXNodeGridCell = class(TTMSFMXGridCell)
  private
    FNodeShapeOpen, FNodeShapeClosed: TTMSFMXBitmap;
    FState: TNodeState;
    function GetNodeShapeOpen: TTMSFMXBitmap;
    procedure SetNodeShapeOpen(const Value: TTMSFMXBitmap);
    function GetNodeShapeClosed: TTMSFMXBitmap;
    procedure SetNodeShapeClosed(const Value: TTMSFMXBitmap);
    procedure SetBitmapContainer(const Value: TTMSFMXBitmapContainer); override;
    procedure SetState(const Value: TNodeState);
  public
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property NodeShapeOpen: TTMSFMXBitmap read GetNodeShapeOpen write SetNodeShapeOpen;
    property NodeShapeClosed: TTMSFMXBitmap read GetNodeShapeClosed write SetNodeShapeClosed;
    procedure Resize; override;
    property State: TNodeState read FState write SetState default nsClosed;
  end;

  TTMSFMXContainerGridCell = class(TTMSFMXGridCell);

  TTMSFMXBitmapGridCell = class(TTMSFMXGridCell)
  private
    FBitmap: TTMSFMXBitmap;
    function GetBitmap: TTMSFMXBitmap;
    procedure SetBitmap(const Value: TTMSFMXBitmap);
    procedure SetBitmapContainer(const Value: TTMSFMXBitmapContainer); override;
  public
    function GetControl: TControl; override;
    function GetPrintControl: TControl; override;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Bitmap: TTMSFMXBitmap read GetBitmap write SetBitmap;
  end;


implementation

{$R FMX.TMSGridCell.res}

function GetResourceStream(AResourceName: String): TResourceStream;
var
  hst: NativeUInt;
begin
  Result := nil;
  hst := HInstance;
  if FindRCData(hst, AResourceName) then
    Result := TResourceStream.Create(hst, AResourceName, RT_RCDATA);
end;

{ TTMSFMXGridCellLayout }

procedure TTMSFMXGridCellLayout.Assign(Source: TPersistent);
begin
  if Source is TTMSFMXGridCellLayout then
  begin
    FFill.Assign((Source as TTMSFMXGridCellLayout).Fill);
    FFontFill.Assign((Source as TTMSFMXGridCellLayout).FontFill);
    FStroke.Assign((Source as TTMSFMXGridCellLayout).Stroke);
    FStrokeJoin := (Source as TTMSFMXGridCellLayout).StrokeJoin;
    FStrokeThickness := (Source as TTMSFMXGridCellLayout).StrokeThickness;
    FStrokeCap := (Source as TTMSFMXGridCellLayout).StrokeCap;
    FStrokeDash := (Source as TTMSFMXGridCellLayout).StrokeDash;
    FSides := (Source as TTMSFMXGridCellLayout).Sides;
    FFont.Assign((Source as TTMSFMXGridCellLayout).Font);
    FTextAlign := (Source as TTMSFMXGridCellLayout).TextAlign;
    FVerticalTextAlign := (Source as TTMSFMXGridCellLayout).VerticalTextAlign;
    FFontFlags := (Source as TTMSFMXGridCellLayout).FontFlags;
    FWordWrapping := (Source as TTMSFMXGridCellLayout).WordWrapping;
  end;
end;

procedure TTMSFMXGridCellLayout.Changed(Sender: TObject);
begin
  if Assigned(OnChange) then
    OnChange(Self);
end;

constructor TTMSFMXGridCellLayout.Create(AOwner: TComponent);
begin
  FOwner := AOwner;
  {$IFDEF DELPHIXE6_LVL}
  FFill := TBrush.Create(TBrushKind.Solid, claWhite);
  FStroke := TBrush.Create(TBrushKind.Solid, claSilver);
  {$ELSE}
  FFill := TBrush.Create(TBrushKind.bkSolid, claWhite);
  FStroke := TBrush.Create(TBrushKind.bkSolid, claSilver);
  {$ENDIF}
  FFill.OnChanged := Changed;
  FStroke.OnChanged := Changed;
  FStrokeThickness := 1;
  {$IFDEF DELPHIXE6_LVL}
  FStrokeCap := TStrokeCap.Flat;
  FStrokeDash := TStrokeDash.Solid;
  FStrokeJoin := TStrokeJoin.Miter;
  FFontFill := TBrush.Create(TBrushKind.Solid, claBlack);
  {$ELSE}
  FStrokeCap := TStrokeCap.scFlat;
  FStrokeDash := TStrokeDash.sdSolid;
  FStrokeJoin := TStrokeJoin.sjMiter;
  FFontFill := TBrush.Create(TBrushKind.bkSolid, claBlack);
  {$ENDIF}
  FFontFill.OnChanged := Changed;
  FSides := AllSides;
  FFont := TFont.Create;
  FFont.OnChanged := Changed;
  FFontFlags := [];
  {$IFDEF DELPHIXE6_LVL}
  FTextAlign := TTextAlign.Leading;
  FVerticalTextAlign := TTextAlign.Center;
  {$ELSE}
  FTextAlign := TTextAlign.taLeading;
  FVerticalTextAlign := TTextAlign.taCenter;
  {$ENDIF}
  FWordWrapping := False;
end;

destructor TTMSFMXGridCellLayout.Destroy;
begin
  FFont.Free;
  FFill.Free;
  FFontFill.Free;
  FStroke.Free;
  inherited;
end;

procedure TTMSFMXGridCellLayout.SetFill(const Value: TBrush);
begin
  if FFill <> Value then
  begin
    FFill.Assign(Value);
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetFont(const Value: TFont);
begin
  if FFont <> Value then
  begin
    FFont.Assign(Value);
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetFontFill(const Value: TBrush);
begin
  if FFontFill <> Value then
  begin
    FFontFill.Assign(Value);
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetFontFlags(const Value: TFillTextFlags);
begin
  if FFontFlags <> Value then
  begin
    FFontFlags := Value;
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetSides(const Value: TSides);
begin
  if FSides <> Value then
  begin
    FSides := Value;
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetStroke(const Value: TBrush);
begin
  if FStroke <> Value then
  begin
    FStroke.Assign(Value);
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetStrokeCap(const Value: TStrokeCap);
begin
  if FStrokeCap <> Value then
  begin
    FStrokeCap := Value;
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetStrokeDash(const Value: TStrokeDash);
begin
  if FStrokeDash <> Value then
  begin
    FStrokeDash := Value;
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetStrokeJoin(const Value: TStrokeJoin);
begin
  if FStrokeJoin <> Value then
  begin
    FStrokeJoin := Value;
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetStrokeThickness(const Value: Single);
begin
  if FStrokeThickness <> Value then
  begin
    FStrokeThickness := Value;
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetTextAlign(const Value: TTextAlign);
begin
  if FTextAlign <> Value then
  begin
    FTextAlign := Value;
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetVerticalTextAlign(const Value: TTextAlign);
begin
  if FVerticalTextAlign <> Value then
  begin
    FVerticalTextAlign := Value;
    Changed(Self);
  end;
end;

procedure TTMSFMXGridCellLayout.SetWordWrapping(const Value: Boolean);
begin
  if FWordWrapping <> Value then
  begin
    FWordWrapping := Value;
    Changed(Self);
  end;
end;

{ TTMSFMXGridCell }

procedure TTMSFMXGridCell.Assign(Source: TPersistent);
begin
  if (Source is TTMSFMXGridCell) then
  begin
    FText := (Source as TTMSFMXGridCell).Text;
    FLayout.Assign((Source as TTMSFMXGridCell).Layout);
  end
  else
    inherited;
end;

procedure TTMSFMXGridCell.AssignLayout(Source: TTMSFMXGridCellLayout);
begin
  if (Source is TTMSFMXGridCellLayout) then
    Layout := Source;
end;

procedure TTMSFMXGridCell.Changed(Sender: TObject);
begin
  Repaint;
end;

constructor TTMSFMXGridCell.Create(AOwner: TComponent);
begin
  inherited;
  FLayout := TTMSFMXGridCellLayout.Create(Self);
  FLayout.OnChange := Changed;
end;

destructor TTMSFMXGridCell.Destroy;
begin
  FLayout.Free;
  inherited;
end;

procedure TTMSFMXGridCell.Draw(ACanvas: TCanvas; ARect, ATextRect: TRectF; ADrawText: Boolean; ADrawBackGround: Boolean);
var
  r: TRectF;
  str: String;
  rt: TRectF;
  AllowDraw: Boolean;
begin
  inherited;

  r := ARect;

  ACanvas.BeginScene;

  AllowDraw := True;
  if Assigned(OnBeforeDraw) then
    OnBeforeDraw(Self, ACanvas, ARect, ATextRect, ADrawTExt, ADrawBackGround, AllowDraw);

  ACanvas.Stroke.Assign(Layout.Stroke);
  ACanvas.StrokeThickness := Layout.StrokeThickness;
  ACanvas.StrokeCap := Layout.StrokeCap;
  ACanvas.StrokeDash := Layout.StrokeDash;
  ACanvas.StrokeJoin := Layout.StrokeJoin;
  ACanvas.Fill.Assign(Layout.Fill);

  if AllowDraw then
  begin
    if ADrawBackGround then
      ACanvas.FillRect(r, 0, 0, AllCorners, AbsoluteOpacity);

    str := Text;
    if (str <> '') and ADrawText then
    begin
      ACanvas.Fill.Assign(Layout.FontFill);
      ACanvas.Font.Assign(Layout.Font);

      rt := ATextRect;
      rt.Left := rt.Left + 2;
      rt.Right := rt.Right - 2;
      rt.Top := rt.Top + 2;
      rt.Bottom := rt.Bottom - 2;

      if IsHTML then
        HTMLDraw(ACanvas, rt, false,-1,-1,str)
      else
      begin
        ACanvas.FillText(rt, str, Layout.WordWrapping, AbsoluteOpacity, Layout.FontFlags, Layout.TextAlign, Layout.VerticalTextAlign);
      end;
    end;

    R.Left := R.Left + 0.5;
    R.Right := R.Right - 0.5;
    R.Top := R.Top + 0.5;
    R.Bottom := R.Bottom - 0.5;


    {$IFDEF DELPHIXE6_LVL}
    if TSide.Top in Layout.Sides then
      ACanvas.DrawLine(PointF(r.Left, r.Top), PointF(r.Right, r.Top), AbsoluteOpacity);
    if TSide.Left in Layout.Sides then
      ACanvas.DrawLine(PointF(r.Left, r.Top), PointF(r.Left, r.Bottom), AbsoluteOpacity);
    if TSide.Bottom in Layout.Sides then
      ACanvas.DrawLine(PointF(r.Left, r.Bottom), PointF(r.Right, r.Bottom), AbsoluteOpacity);
    if TSide.Right in Layout.Sides then
      ACanvas.DrawLine(PointF(r.Right, r.Top), PointF(r.Right, r.Bottom), AbsoluteOpacity);
    {$ELSE}
    if TSide.sdTop in Layout.Sides then
      ACanvas.DrawLine(PointF(r.Left, r.Top), PointF(r.Right, r.Top), AbsoluteOpacity);
    if TSide.sdLeft in Layout.Sides then
      ACanvas.DrawLine(PointF(r.Left, r.Top), PointF(r.Left, r.Bottom), AbsoluteOpacity);
    if TSide.sdBottom in Layout.Sides then
      ACanvas.DrawLine(PointF(r.Left, r.Bottom), PointF(r.Right, r.Bottom), AbsoluteOpacity);
    if TSide.sdRight in Layout.Sides then
      ACanvas.DrawLine(PointF(r.Right, r.Top), PointF(r.Right, r.Bottom), AbsoluteOpacity);
    {$ENDIF}
  end;

  if Assigned(OnAfterDraw) then
    OnAfterDraw(Self, ACanvas, ARect);

  ACanvas.EndScene;
end;

function TTMSFMXGridCell.GetControl: TControl;
begin
  Result := nil;
end;

function TTMSFMXGridCell.GetPrintControl: TControl;
begin
  Result := nil;
end;

function TTMSFMXGridCell.GetStrippedHTMLText: String;
var
  r: TRectF;
  a, s, fa: String;
  XSize, YSize: Single;
  hl, ml: Integer;
  hr: TRectF;
  str: String;
begin
  str := Text;
  r := BoundsRect;
  if IsHTML then
  begin
    HTMLDrawEx(Canvas,str, r,0,0,-1,-1,0,False,True,False,False,False,False,Layout.WordWrapping,1.0,claBlue,
      claNull,claNull,claNull,a,s,fa,XSize,YSize,hl,ml,hr,0, BitmapContainer, AbsoluteOpacity);
    Result := s;
  end
  else
    Result := str;
end;

function TTMSFMXGridCell.GetTextHeight: Single;
var
  r: TRectF;
  a, s, fa: String;
  XSize, YSize: Single;
  hl, ml: Integer;
  hr: TRectF;
  str: String;
begin
  str := Text;
  Result := 0;
  if str <> '' then
  begin
    Canvas.Font.Assign(Layout.Font);
    r := GetTextRect;
    if IsHTML then
    begin
      HTMLDrawEx(Canvas,str, r,0,0,-1,-1,0,False,True,False,False,False,False,Layout.WordWrapping,1.0,claBlue,
        claNull,claNull,claNull,a,s,fa,XSize,YSize,hl,ml,hr,0, BitmapContainer, AbsoluteOpacity);
      Result := YSize + 4;  // accomodate for top & bottom text margin
    end
    else
    begin
      Canvas.MeasureText(r,str,Layout.WordWrapping,Layout.FontFlags,Layout.TextAlign, Layout.VerticalTextAlign);
      Result := r.Bottom - r.Top;
    end;
  end;
end;

function TTMSFMXGridCell.GetTextRect: TRectF;
var
  r: TRectF;
  c: TControl;
begin
  r := BoundsRect;
  c := GetControl;
  if Assigned(c) then
  begin
    {$IFDEF DELPHIXE6_LVL}
    case c.Align of
      TAlignLayout.Left: Result := RectF(c.Margins.Left + c.Width + c.Margins.Right + r.Left, r.Top, r.Width, r.Height);
      TAlignLayout.Right:  Result := RectF(r.Left, r.Top, r.Width - c.Width - c.Margins.Right - c.Margins.Left , r.Height);
      else Result := BoundsRect;
    end;
    {$ELSE}
    case c.Align of
      TAlignLayout.alLeft: Result := RectF(c.Margins.Left + c.Width + c.Margins.Right + r.Left, r.Top, r.Width, r.Height);
      TAlignLayout.alRight:  Result := RectF(r.Left, r.Top, r.Width - c.Width - c.Margins.Right - c.Margins.Left , r.Height);
      else Result := BoundsRect;
    end;
    {$ENDIF}
  end
  else
    Result := BoundsRect;
end;

function TTMSFMXGridCell.GetTextRectBase(ARect: TRectF): TRectF;
var
  r: TRectF;
  c: TControl;
begin
  r := ARect;
  c := GetControl;
  if Assigned(c) then
  begin
    {$IFDEF DELPHIXE6_LVL}
    case c.Align of
      TAlignLayout.Left: Result := RectF(c.Margins.Left + c.Width + c.Margins.Right + r.Left, r.Top, c.Margins.Left + c.Width + c.Margins.Right + r.Left + r.Width, r.Top + r.Height);
      TAlignLayout.Right:  Result := RectF(r.Left, r.Top, r.Width - c.Width - c.Margins.Right - c.Margins.Left , r.Top + r.Height);
      else Result := ARect;
    end;
    {$ELSE}
    case c.Align of
      TAlignLayout.alLeft: Result := RectF(c.Margins.Left + c.Width + c.Margins.Right + r.Left, r.Top, c.Margins.Left + c.Width + c.Margins.Right + r.Left + r.Width, r.Top + r.Height);
      TAlignLayout.alRight:  Result := RectF(r.Left, r.Top, r.Width - c.Width - c.Margins.Right - c.Margins.Left , r.Top + r.Height);
      else Result := ARect;
    end;
    {$ENDIF}
  end
  else
    Result := ARect;
end;

function TTMSFMXGridCell.GetTextSize: TSizeF;
var
  r: TRectF;
  a, s, fa: String;
  XSize, YSize: Single;
  hl, ml: Integer;
  hr: TRectF;
  str: String;
  sz: TSizeF;
begin
  str := Text;
  Canvas.Font.Assign(Layout.Font);
  r := GetTextRect;
  if IsHTML then
  begin
    HTMLDrawEx(Canvas,str, r,0,0,-1,-1,0,False,True,False,False,False,False,Layout.WordWrapping,1.0,claBlue,
      claNull,claNull,claNull,a,s,fa,XSize,YSize,hl,ml,hr,0, BitmapContainer, AbsoluteOpacity);

    sz.cx := XSize;
    sz.cy := YSize;
  end
  else
  begin
    Canvas.MeasureText(r,str,true,Layout.FontFlags,Layout.TextAlign, Layout.VerticalTextAlign);
    sz.cx := r.Right - r.Left;
    sz.cy := r.Bottom - r.Top;
  end;

  Result := sz;
end;

function TTMSFMXGridCell.GetTextWidth: Single;
var
  r: TRectF;
  a, s, fa: String;
  XSize, YSize: Single;
  hl, ml: Integer;
  hr: TRectF;
  str: String;
  evnt: TNotifyEvent;
  rt: TRectF;
begin
  str := Text;
  Result := 0;
  evnt := nil;
  if str <> '' then
  begin
    evnt := Canvas.Font.OnChanged;
    Canvas.Font.OnChanged := nil;
    Canvas.Font.Assign(Layout.Font);

    r := GetTextRect;
    rt := r;
    if IsHTML then
    begin
      HTMLDrawEx(Canvas,str, r,0,0,-1,-1,0,False,True,False,False,False,False,Layout.WordWrapping,1.0,claBlue,
        claNull,claNull,claNull,a,s,fa,XSize,YSize,hl,ml,hr,0, BitmapContainer, AbsoluteOpacity);
      Result := XSize;
    end
    else
      Result := Canvas.TextWidth(str);

    Canvas.Font.OnChanged := evnt;
  end;
end;

procedure TTMSFMXGridCell.Paint;
begin
  Draw(Canvas, BoundsRect, GetTextRect, True, True);
end;

procedure TTMSFMXGridCell.Print(ACanvas: TCanvas; ARect, ATextRect: TRectF;
  ADrawText, ADrawBackGround: Boolean; sx, sy: Single);
var
  ctl: TControl;
  r: TRectF;
  m: TMatrix;
begin
  Draw(ACanvas, ARect, ATextRect, ADrawText, ADrawBackGround);
  ctl := GetPrintControl;
  if Assigned(ctl) then
  begin
    r.Left := (ARect.Left + ctl.Position.X) * sx;
    r.Top := (ARect.Top + ctl.Position.Y) * sy;
    r.Right := r.Left + ctl.Width * sx;
    r.Bottom := r.Top + ctl.Height * sy;
    m := ACanvas.Matrix;
    TControlProtected(ctl).Scale.X := sx;
    TControlProtected(ctl).Scale.Y := sy;
    ctl.PaintTo(ACanvas, r);
    ACanvas.SetMatrix(m);
  end;
end;

procedure TTMSFMXGridCell.HTMLDraw(ACanvas: TCanvas; ARect: TRectF; TestAnchor: boolean; X,Y: single; var Anchor: string);
var
  a, s, fa: String;
  XSize, YSize: Single;
  hl, ml: Integer;
  hr: TRectF;
  r: TRectF;
  w, h: Single;
begin
  r := ARect;

  HTMLDrawEx(ACanvas,Text, r,0,0,-1,-1,0,False,True,False,False,False,False,Layout.WordWrapping,1.0,claBlue,
    claNull,claNull,claNull,a,s,fa,XSize,YSize,hl,ml,hr,0, BitmapContainer, AbsoluteOpacity);

  w := r.Width;
  h := r.Height;

  {$IFDEF DELPHIXE6_LVL}
  case Layout.VerticalTextAlign of
    TTextAlign.Center: r.Top := r.Top + (r.Height - YSize) / 2;
    TTextAlign.Trailing: r.Top := r.Top + r.Height - YSize;
  end;

  case Layout.TextAlign of
    TTextAlign.Center: r.Left := r.Left + (r.Width - XSize) / 2;
    TTextAlign.Trailing: r.Left := r.Left + r.Width - XSize;
  end;
  {$ELSE}
  case Layout.VerticalTextAlign of
    TTextAlign.taCenter: r.Top := r.Top + (r.Height - YSize) / 2;
    TTextAlign.taTrailing: r.Top := r.Top + r.Height - YSize;
  end;

  case Layout.TextAlign of
    TTextAlign.taCenter: r.Left := r.Left + (r.Width - XSize) / 2;
    TTextAlign.taTrailing: r.Left := r.Left + r.Width - XSize;
  end;
  {$ENDIF}

  r.Width := w;
  r.Height := h;

  HTMLDrawEx(ACanvas,Text, r, Round(X), Round(Y) ,-1,-1,0,TestAnchor,False,False,False,False,False,Layout.WordWrapping,1.0,claBlue,
    claNull,claNull,claNull,a,s,fa,XSize,YSize,hl,ml,hr,0, BitmapContainer, AbsoluteOpacity);

  Anchor := a;
end;

function TTMSFMXGridCell.IsHTML: boolean;
begin
  Result := (AnsiPos('</', Text) > 0) or (AnsiPos('/>', Text)  > 0) or (AnsiPos('<BR>', UpperCase(Text)) > 0);
end;

procedure TTMSFMXGridCell.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  if (Operation = opRemove) and (AComponent = FBitmapContainer) then
    FBitmapContainer := nil;
  inherited;
end;

procedure TTMSFMXGridCell.SetBitmapContainer(
  const Value: TTMSFMXBitmapContainer);
begin
  FBitmapContainer := Value;
end;

procedure TTMSFMXGridCell.SetLayout(const Value: TTMSFMXGridCellLayout);
begin
  if FLayout <> Value then
  begin
    FLayout.Assign(Value);
    Repaint;
  end;
end;

procedure TTMSFMXGridCell.SetText(const Value: String);
begin
  if FText <> Value then
  begin
    FText := Value;
    Repaint;
  end;
end;

function TTMSFMXGridCell.XYToAnchor(X, Y: Single): String;
var
  Anchor: string;
begin
  Result := '';
  if IsHTML then
  begin
    HTMLDraw(Canvas, GetTextRect, True, X, Y, Anchor);
    Result := Anchor;
  end;
end;

{ TTMSFMXCheckGridCell }

constructor TTMSFMXCheckGridCell.Create(AOwner: TComponent);
begin
  inherited;
  FCheckBox := TTMSFMXCheckBox.Create(Self);
  FCheckBox.CanFocus := False;
  {$IFDEF DELPHIXE6_LVL}
  FCheckBox.Align := TAlignLayout.Left;
  {$ELSE}
  FCheckBox.Align := TAlignLayout.alLeft;
  {$ENDIF}
  FCheckBox.Margins.Left := 2;
  FCheckBox.Margins.Top := 2;
  FCheckBox.Margins.Bottom := 2;
  FCheckBox.Margins.Right := 2;
  FCheckBox.Width := 17;
  FCheckBox.Text := '';
  FCheckBox.Height := 17;
  AddObject(FCheckBox);
end;

destructor TTMSFMXCheckGridCell.Destroy;
begin
  FCheckBox.Free;
  inherited;
end;

function TTMSFMXCheckGridCell.GetCheckBox: TTMSFMXCheckBox;
begin
  Result := FCheckBox;
end;

function TTMSFMXCheckGridCell.GetControl: TControl;
begin
  Result := FCheckBox;
end;

function TTMSFMXCheckGridCell.GetPrintControl: TControl;
begin
  Result := CheckBox;
end;

procedure TTMSFMXCheckGridCell.SetCheckBox(const Value: TTMSFMXCheckBox);
begin
  FCheckBox.Assign(Value);
end;

{ TTMSFMXRadioGridCell }

constructor TTMSFMXRadioGridCell.Create(AOwner: TComponent);
begin
  inherited;
  FRadioButton := TTMSFMXRadioButton.Create(Self);
  FRadioButton.CanFocus := False;
  {$IFDEF DELPHIXE6_LVL}
  FRadioButton.Align := TAlignLayout.Left;
  {$ELSE}
  FRadioButton.Align := TAlignLayout.alLeft;
  {$ENDIF}
  FRadioButton.Margins.Left := 2;
  FRadioButton.Margins.Top := 2;
  FRadioButton.Margins.Bottom := 2;
  FRadioButton.Margins.Right := 2;
  FRadioButton.Width := 17;
  FRadioButton.Text := '';
  FRadioButton.Height := 17;
  AddObject(FRadioButton);
end;

destructor TTMSFMXRadioGridCell.Destroy;
begin
  FRadioButton.Free;
  inherited;
end;

function TTMSFMXRadioGridCell.GetControl: TControl;
begin
  Result := FRadioButton;
end;

function TTMSFMXRadioGridCell.GetPrintControl: TControl;
begin
  Result := RadioButton;
end;

function TTMSFMXRadioGridCell.GetRadioButton: TTMSFMXRadioButton;
begin
  Result := FRadioButton;
end;

procedure TTMSFMXRadioGridCell.SetRadioButton(const Value: TTMSFMXRadioButton);
begin
  FRadioButton.Assign(Value);
end;

{ TTMSFMXButtonGridCell }

constructor TTMSFMXButtonGridCell.Create(AOwner: TComponent);
begin
  inherited;
  FButton := TButton.Create(Self);
  {$IFDEF DELPHIXE6_LVL}
  FButton.Align := TAlignLayout.Left;
  {$ELSE}
  FButton.Align := TAlignLayout.alLeft;
  {$ENDIF}
  FButton.CanFocus := False;
  FButton.Margins.Left := 2;
  FButton.Margins.Top := 2;
  FButton.Margins.Bottom := 2;
  FButton.Margins.Right := 2;
  FButton.Width := 25;
  FButton.Text := 'Button';
  FButton.Height := 15;
  AddObject(FButton);
end;

destructor TTMSFMXButtonGridCell.Destroy;
begin
  FButton.Free;
  inherited;
end;

function TTMSFMXButtonGridCell.GetButton: TButton;
begin
  Result := FButton;
end;

function TTMSFMXButtonGridCell.GetControl: TControl;
begin
  Result := FButton;
end;

function TTMSFMXButtonGridCell.GetPrintControl: TControl;
begin
  Result := Button;
end;

procedure TTMSFMXButtonGridCell.SetButton(const Value: TButton);
begin
  FButton.Assign(Value);
end;

{ TTMSFMXBitmapGridCell }

constructor TTMSFMXBitmapGridCell.Create(AOwner: TComponent);
begin
  inherited;
  FBitmap := TTMSFMXBitmap.Create(Self);
  FBitmap.CanFocus := False;
  {$IFDEF DELPHIXE6_LVL}
  FBitmap.Align := TAlignLayout.Left;
  {$ELSE}
  FBitmap.Align := TAlignLayout.alLeft;
  {$ENDIF}
  FBitmap.Margins.Left := 2;
  FBitmap.Margins.Top := 2;
  FBitmap.Margins.Bottom := 2;
  FBitmap.Margins.Right := 2;
  FBitmap.Width := 18;
  FBitmap.Height := 18;
  AddObject(FBitmap);
end;

destructor TTMSFMXBitmapGridCell.Destroy;
begin
  FBitmap.Free;
  inherited;
end;

function TTMSFMXBitmapGridCell.GetBitmap: TTMSFMXBitmap;
begin
  Result := FBitmap;
end;

function TTMSFMXBitmapGridCell.GetControl: TControl;
begin
  Result := FBitmap;
end;

function TTMSFMXBitmapGridCell.GetPrintControl: TControl;
begin
  Result := Bitmap;
end;

procedure TTMSFMXBitmapGridCell.SetBitmap(const Value: TTMSFMXBitmap);
begin
  FBitmap.Assign(Value);
end;

procedure TTMSFMXBitmapGridCell.SetBitmapContainer(
  const Value: TTMSFMXBitmapContainer);
begin
  inherited;
  if Assigned(Bitmap) then
    Bitmap.BitmapContainer := BitmapContainer;
end;

{ TCommentShape }

procedure TCommentShape.Paint;
var
  pth: TPathData;
begin
  inherited;
  pth := TPathData.Create;
  pth.MoveTo(PointF(0.5, 0.5));
  pth.LineTo(PointF(Width - 0.5, 0.5));
  pth.LineTo(PointF(Width - 0.5, Height - 0.5));
  pth.ClosePath;
  Canvas.FillPath(pth, AbsoluteOpacity);
  Canvas.DrawPath(pth, AbsoluteOpacity);
  pth.Free;
end;

{ TTMSFMXCommentGridCell }

procedure TTMSFMXCommentGridCell.ClosePopup(Sender: TObject);
begin
  if Assigned(OnHidePopup) then
    OnHidePopup(Self);
end;

constructor TTMSFMXCommentGridCell.Create(AOwner: TComponent);
var
  ctl: TControl;
begin
  inherited;
  if AOwner is TControl then
  begin
    ctl := AOwner as TControl;
    if Assigned(ctl) then
    begin
      FComment := TCommentShape.Create(Self);
      FComment.CanFocus := False;
      FComment.Cursor := crHandPoint;
      FComment.Width := 7;
      FComment.Height := 7;
      FComment.Position.X := Width - FComment.Width;
      FComment.Position.Y := 0;
      FComment.Fill.Color := claRed;
      FComment.Stroke.Color := claRed;
      AddObject(FComment);

      FPopup := TPopup.Create(Self);
      FPopup.OnClosePopup := ClosePopup;
      FPopup.StyleLookup := 'tmsfmxcommentgridcellpopup';
      {$IFDEF DELPHIXE6_LVL}
      FPopup.Placement := TPlacement.TopCenter;
      {$ELSE}
      FPopup.Placement := TPlacement.plTopCenter;
      {$ENDIF}
      FPopup.PlacementTarget := FComment;
      {$IFNDEF DELPHIXE5_LVL}
      FPopup.StaysOpen := False;
      {$ENDIF}
      FPopup.Stored := False;
      FPopup.Parent := Self;
      FPopup.Locked := True;
      FPopup.DragWithParent := True;
      FPopup.DesignVisible:= False;

      FCommentText := TLabel.Create(Self);
      FCommentText.AutoSize := True;
      {$IFDEF DELPHIXE6_LVL}
      FCommentText.Align := TAlignLayout.Client;
      FCommentText.TextAlign := TTextAlign.Center;
      FCommentText.VertTextAlign := TTextAlign.Leading;
      {$ELSE}
      FCommentText.Align := TAlignLayout.alClient;
      FCommentText.TextAlign := TTextAlign.taCenter;
      FCommentText.VertTextAlign := TTextAlign.taLeading;
      {$ENDIF}

      FCommentText.Margins.Left := 3;
      FCommentText.Margins.Top := 3;
      FCommentText.Margins.Bottom := 3;
      FCommentText.Margins.Right := 3;

      FCommentPanel := TCalloutRectangle.Create(Self);
      FcommentPanel.Fill.Color := claLightyellow;
      FCommentPanel.CalloutWidth := 15;
      FCommentPanel.AddObject(FCommentText);
      {$IFDEF DELPHIXE6_LVL}
      FCommentPanel.CalloutPosition := TCalloutPosition.Bottom;
      {$ELSE}
      FCommentPanel.CalloutPosition := TCalloutPosition.cpBottom;
      {$ENDIF}
      FCommentPanel.Width := 50;
      FCommentPanel.Height := 40;
    end;
  end;
end;

destructor TTMSFMXCommentGridCell.Destroy;
begin
  if Assigned(FPopupControl) then
    FPopupControl.Parent := nil;

  FCommentText.Free;
  FCommentPanel.Free;
  FPopup.Free;
  FComment.Free;
  inherited;
end;

function TTMSFMXCommentGridCell.GetComment: TCommentShape;
begin
  Result := FComment;
end;

function TTMSFMXCommentGridCell.GetControl: TControl;
begin
  Result := nil;
end;

function TTMSFMXCommentGridCell.GetPrintControl: TControl;
begin
  Result := Comment;
end;

procedure TTMSFMXCommentGridCell.ShowPopup;
var
  ctl: TControl;
begin
  ctl := nil;
  if Assigned(CommentText) and (CommentText.Text <> '') then
  begin
    {$IFDEF DELPHIXE6_LVL}
    CommentText.Align := TAlignLayout.None;
    {$ELSE}
    CommentText.Align := TAlignLayout.alNone;
    {$ENDIF}
    CommentText.NeedStyleLookUp;
    CommentText.ApplyStyleLookup;
    FCommentPanel.Width := CommentText.Width + 4;
    FCommentPanel.Height := CommentText.Height + 4 + FCommentPanel.CalloutLength;
    {$IFDEF DELPHIXE6_LVL}
    CommentText.Align := TAlignLayout.Client;
    {$ELSE}
    CommentText.Align := TAlignLayout.alClient;
    {$ENDIF}
    ctl := FCommentPanel
  end
  else if Assigned(PopupControl) then
    ctl := PopupControl;

  if Assigned(ctl) then
  begin
    if not FPopup.IsOpen then
    begin
      FPopup.Width := ctl.Width;
      FPopup.Height := ctl.Height;
      ctl.Parent := FPopup;
      {$IFDEF DELPHIXE6_LVL}
      ctl.Align := TAlignLayout.Client;
      {$ELSE}
      ctl.Align := TAlignLayout.alClient;
      {$ENDIF}
      ctl.Visible := True;
      FPopup.IsOpen := True;

      if Assigned(OnShowPopup) then
        OnShowPopup(Self);
    end
  end;
end;

procedure TTMSFMXCommentGridCell.Resize;
begin
  inherited;
  if Assigned(Comment) then
  begin
    Comment.Position.X := Width - Comment.Width;
    Comment.Position.Y := 0;
  end;
end;

procedure TTMSFMXCommentGridCell.SetComment(const Value: TCommentShape);
begin
  FComment.Assign(Value);
end;

procedure TTMSFMXCommentGridCell.SetPopup(const Value: TPopup);
begin
  FPopup.Assign(Value);
end;

procedure TTMSFMXCommentGridCell.HidePopup;
var
  ctl: TControl;
begin
  ctl := nil;
  if Assigned(CommentText) and (CommentText.Text <> '') then
    ctl := FCommentText
  else if Assigned(PopupControl) then
    ctl := PopupControl;

  if Assigned(ctl) then
  begin
    FPopup.IsOpen := False;
    ctl.Visible := False;
    if Assigned(OnHidePopup) then
      OnHidePopup(Self);
  end;
end;

function TTMSFMXCommentGridCell.IsPopupOpen: Boolean;
begin
  Result := False;
  if Assigned(Popup) then
    Result := Popup.IsOpen;
end;

procedure TTMSFMXCommentGridCell.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  if (Operation = opRemove) and (AComponent = FPopupControl) then
    FPopupControl := nil;
  inherited;
end;

{ TTMSFMXNodeGridCell }

constructor TTMSFMXNodeGridCell.Create(AOwner: TComponent);
var
  ctl: TControl;
  R: TResourceStream;
begin
  inherited;
  FState := nsClosed;
  if AOwner is TControl then
  begin
    ctl := AOwner as TControl;
    if Assigned(ctl) then
    begin
      FNodeShapeOpen := TTMSFMXBitmap.Create(Self);
      FNodeShapeOpen.CanFocus := False;
      FNodeShapeOpen.Cursor := crHandPoint;
      {$IFDEF DELPHIXE6_LVL}
      FNodeShapeOpen.Align := TAlignLayout.Left;
      {$ELSE}
      FNodeShapeOpen.Align := TAlignLayout.alLeft;
      {$ENDIF}
      FNodeShapeOpen.Width := 14;
      FNodeShapeOpen.Height := 14;
      FNodeShapeOpen.Margins.Left := 4;
      FNodeShapeOpen.Margins.Right := 2;
      FNodeShapeOpen.Visible := False;
      R := GetResourceStream('closed');
      if Assigned(R) then
      begin
        FNodeShapeOpen.Bitmap.LoadFromStream(R);
        R.free;
      end;
      AddObject(FNodeShapeOpen);

      FNodeShapeClosed := TTMSFMXBitmap.Create(Self);
      {$IFDEF DELPHIXE6_LVL}
      FNodeShapeClosed.Align := TAlignLayout.Left;
      {$ELSE}
      FNodeShapeClosed.Align := TAlignLayout.alLeft;
      {$ENDIF}
      FNodeShapeClosed.CanFocus := False;
      FNodeShapeClosed.Cursor := crHandPoint;
      FNodeShapeClosed.Width := 14;
      FNodeShapeClosed.Height := 14;
      FNodeShapeClosed.Margins.Left := 4;
      FNodeShapeClosed.Margins.Right := 2;
      R := GetResourceStream('open');
      if Assigned(R) then
      begin
        FNodeShapeClosed.Bitmap.LoadFromStream(R);
        R.free;
      end;
      AddObject(FNodeShapeClosed);
    end;
  end;
end;

destructor TTMSFMXNodeGridCell.Destroy;
begin
  FNodeShapeOpen.Free;
  FNodeShapeClosed.Free;
  inherited;
end;

function TTMSFMXNodeGridCell.GetNodeShapeClosed: TTMSFMXBitmap;
begin
  Result := FNodeShapeClosed;
end;

function TTMSFMXNodeGridCell.GetNodeShapeOpen: TTMSFMXBitmap;
begin
  Result := FNodeShapeOpen;
end;

function TTMSFMXNodeGridCell.GetPrintControl: TControl;
begin
  Result := nil;
end;

procedure TTMSFMXNodeGridCell.Resize;
begin
  inherited;
  if Assigned(NodeShapeOpen) then
  begin
    NodeShapeOpen.Position.X := 4;
    NodeShapeOpen.Position.Y := (Height - NodeShapeOpen.Height) / 2;
  end;

  if Assigned(NodeShapeClosed) then
  begin
    NodeShapeClosed.Position.X := 4;
    NodeShapeClosed.Position.Y := (Height - NodeShapeClosed.Height) / 2;
  end;
end;

function TTMSFMXNodeGridCell.GetControl: TControl;
begin
  Result := FNodeShapeOpen;
end;

procedure TTMSFMXNodeGridCell.SetBitmapContainer(
  const Value: TTMSFMXBitmapContainer);
begin
  inherited;
  if Assigned(NodeShapeOpen) then
    NodeShapeOpen.BitmapContainer := BitmapContainer;

  if Assigned(NodeShapeClosed) then
    NodeShapeClosed.BitmapContainer := BitmapContainer;
end;

procedure TTMSFMXNodeGridCell.SetNodeShapeClosed(const Value: TTMSFMXBitmap);
begin
  FNodeShapeOpen.Assign(Value);
end;

procedure TTMSFMXNodeGridCell.SetNodeShapeOpen(const Value: TTMSFMXBitmap);
begin
  FNodeShapeOpen.Assign(Value);
end;

procedure TTMSFMXNodeGridCell.SetState(const Value: TNodeState);
begin
  FState := Value;
  if Assigned(NodeShapeClosed) then NodeShapeClosed.Visible := FState = nsClosed;
  if Assigned(NodeShapeOpen) then NodeShapeOpen.Visible := FState = nsOpen;
end;

{ TTMSFMXFixedGridCell }

procedure TTMSFMXFixedGridCell.ClosePopup(Sender: TObject);
begin
  if Assigned(OnHidePopup) then
    OnHidePopup(Self);
end;

constructor TTMSFMXFixedGridCell.Create(AOwner: TComponent);
var
  ctl: TControl;
begin
  inherited;
  FSortKind := skNone;
  FSortIndex := -1;
  {$IFDEF DELPHIXE6_LVL}
  FSortFill := TBrush.Create(TBrushKind.Solid, claLightsteelblue);
  FSortStroke := TBrush.Create(TBrushKind.Solid, claSteelblue);
  FSortFontFill := TBrush.Create(TBrushKind.Solid, claBlack);
  {$ELSE}
  FSortFill := TBrush.Create(TBrushKind.bkSolid, claLightsteelblue);
  FSortStroke := TBrush.Create(TBrushKind.bkSolid, claSteelblue);
  FSortFontFill := TBrush.Create(TBrushKind.bkSolid, claBlack);
  {$ENDIF}
  FSortFont := TFont.Create;
  FPopupControl := nil;

  if AOwner is TControl then
  begin
    ctl := AOwner as TControl;
    if Assigned(ctl) then
    begin
      FSortShape := TSortShape.Create(Self);
      FSortShape.CanFocus := False;
      FSortShape.HitTest := False;
      FSortShape.Width := 12;
      FSortShape.Height := 12;
      FSortShape.Position.X := Width - SortShape.Width - 4;
      FSortShape.Position.Y := (Height - SortShape.Height) / 2;
      FSortShape.Visible := False;
      AddObject(FSortShape);

      FCheckBox := TTMSFMXCheckBox.Create(Self);
      FCheckBox.CanFocus := False;
      {$IFDEF DELPHIXE6_LVL}
      FCheckBox.Align := TAlignLayout.Left;
      {$ELSE}
      FCheckBox.Align := TAlignLayout.alLeft;
      {$ENDIF}
      FCheckBox.Margins.Left := 2;
      FCheckBox.Margins.Top := 2;
      FCheckBox.Margins.Bottom := 2;
      FCheckBox.Margins.Right := 2;
      FCheckBox.Width := 17;
      FCheckBox.Text := '';
      FCheckBox.Height := 17;

      FBitmap := TTMSFMXBitmap.Create(Self);
      FBitmap.CanFocus := False;
      {$IFDEF DELPHIXE6_LVL}
      FBitmap.Align := TAlignLayout.Left;
      {$ELSE}
      FBitmap.Align := TAlignLayout.alLeft;
      {$ENDIF}
      FBitmap.Margins.Left := 2;
      FBitmap.Margins.Top := 2;
      FBitmap.Margins.Bottom := 2;
      FBitmap.Margins.Right := 2;
      FBitmap.Width := 18;
      FBitmap.Height := 18;

      FButton := TButton.Create(Self);
      FButton.CanFocus := False;
      {$IFDEF DELPHIXE6_LVL}
      FButton.Align := TAlignLayout.Left;
      {$ELSE}
      FButton.Align := TAlignLayout.alLeft;
      {$ENDIF}
      FButton.Margins.Left := 2;
      FButton.Margins.Top := 2;
      FButton.Margins.Bottom := 2;
      FButton.Margins.Right := 2;
      FButton.Width := 25;
      FButton.Text := 'Button';
      FButton.Height := 15;

      FSpinBox := TSpinBox.Create(Self);
      FSpinBox.CanFocus := False;
      {$IFDEF DELPHIXE6_LVL}
      FSpinBox.Align := TAlignLayout.Left;
      {$ELSE}
      FSpinBox.Align := TAlignLayout.alLeft;
      {$ENDIF}
      FSpinBox.Margins.Left := 2;
      FSpinBox.Margins.Top := 2;
      FSpinBox.Margins.Bottom := 2;
      FSpinBox.Margins.Right := 2;
      FSpinBox.Width := 35;
      FSpinBox.Height := 15;

      FDropDownButton := TCornerButton.Create(Self);
      FDropDownButton.CanFocus := False;
      FDropDownButton.DisableFocusEffect := True;
      {$IFDEF DELPHIXE6_LVL}
      FDropDownButton.Align := TAlignLayout.Right;
      {$ELSE}
      FDropDownButton.Align := TAlignLayout.alRight;
      {$ENDIF}
      FDropDownButton.Margins.Left := 3;
      FDropDownButton.Margins.Top := 3;
      FDropDownButton.Margins.Bottom := 3;
      FDropDownButton.Margins.Right := 3;
      FDropDownButton.Width := 15;
      FDropDownButton.Text := '';
      FDropDownButton.Height := 15;

      FPopup := TPopup.Create(Self);
      FPopup.OnClosePopup := ClosePopup;
      FPopup.StyleLookup := 'tmsfmxfixedgridcellpopup';
      {$IFDEF DELPHIXE6_LVL}
      FPopup.Placement := TPlacement.Bottom;
      {$ELSE}
      FPopup.Placement := TPlacement.plBottom;
      {$ENDIF}
      FPopup.PlacementTarget := FDropDownButton;
      {$IFNDEF DELPHIXE5_LVL}
      FPopup.StaysOpen := False;
      {$ENDIF}
      FPopup.Stored := False;
      FPopup.Parent := Self;
      FPopup.Locked := True;
      FPopup.DragWithParent := True;
      FPopup.DesignVisible:= False;
    end;
  end;
end;

destructor TTMSFMXFixedGridCell.Destroy;
begin
  if Assigned(FPopupControl) then
    FPopupControl.Parent := nil;

  FPopup.Free;
  FBitmap.Free;
  FButton.Free;
  FCheckBox.Free;
  FSpinBox.Free;
  FDropDownButton.Free;

  FSortShape.Free;
  FSortFill.Free;
  FSortStroke.Free;
  FSortFontFill.Free;
  FSortFont.Free;
  inherited;
end;

function TTMSFMXFixedGridCell.GetControl: TControl;
begin
  Result := nil;
  if CheckBox.Parent = Self then
    Result := CheckBox
  else if Bitmap.Parent = Self then
    Result := Bitmap
  else if Button.Parent = Self then
    Result := Button
  else if SpinBox.Parent = Self then
    Result := SpinBox;
end;

function TTMSFMXFixedGridCell.GetPrintControl: TControl;
begin
  Result := nil
end;

function TTMSFMXFixedGridCell.GetSortShape: TSortShape;
begin
  Result := FSortShape;
end;

function TTMSFMXFixedGridCell.DropDownButtonHasBitmap: Boolean;
var
  i: Integer;
begin
  Result := False;
  if assigned(DropDownButton) then
  begin
    for I := 0 to DropDownButton.ComponentCount -  1 do
    begin
      if DropDownButton.components[I] is TTMSFMXBitmap then
      begin
        Result := True;
        Exit;
      end;
    end;
  end;
end;

procedure TTMSFMXFixedGridCell.HidePopup;
begin
  if Assigned(PopupControl) then
  begin
    FPopup.IsOpen := False;
    PopupControl.Visible := False;
    if Assigned(OnHidePopup) then
      OnHidePopup(Self);
  end;
end;

function TTMSFMXFixedGridCell.IsPopupOpen: Boolean;
begin
  Result := False;
  if Assigned(Popup) then
    Result := Popup.IsOpen;
end;

procedure TTMSFMXFixedGridCell.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  if (Operation = opRemove) and (AComponent = FPopupControl) then
    FPopupControl := nil;
  inherited;
end;

procedure TTMSFMXFixedGridCell.Resize;
begin
  inherited;
  if Assigned(SortShape) then
  begin
    if ShowDropDownButton and Assigned(DropDownButton) then
      SortShape.Position.X := Width - SortShape.Width - 4 - DropDownButton.Width
    else
      SortShape.Position.X := Width - SortShape.Width - 4;

    SortShape.Position.Y := (Height - SortShape.Height) / 2;
  end;
end;

procedure TTMSFMXFixedGridCell.SetShowBitmap(const Value: Boolean);
begin
  if FShowBitmap <> Value then
  begin
    FShowBitmap := Value;
    if Assigned(Bitmap) then
    begin
      if ShowBitmap then
        AddObject(Bitmap)
      else
        RemoveObject(Bitmap);
    end;
  end;
end;

procedure TTMSFMXFixedGridCell.SetShowButton(const Value: Boolean);
begin
  if FShowButton <> Value then
  begin
    FShowButton := Value;
    if Assigned(Button) then
    begin
      if ShowButton then
        AddObject(Button)
      else
        RemoveObject(Button);
    end;
  end;
end;

procedure TTMSFMXFixedGridCell.SetBitmap(const Value: TTMSFMXBitmap);
begin
  if FBitmap <> Value then
    FBitmap.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.SetButton(const Value: TButton);
begin
  if FButton <> Value then
    FButton.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.SetCheckBox(const Value: TTMSFMXCheckBox);
begin
  if FCheckBox <> Value then
    FCheckBox.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.SetDropDownButton(const Value: TCornerButton);
begin
  FDropDownButton.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.SetPopup(const Value: TPopup);
begin
  FPopup.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.SetSpinBox(const Value: TSpinBox);
begin
  if FSpinBox <> Value then
    FSpinBox.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.ShowPopup;
begin
  if Assigned(PopupControl) then
  begin
    if not FPopup.IsOpen then
    begin
      FPopup.Width := PopupControl.Width;
      FPopup.Height := PopupControl.Height;
      PopupControl.Parent := FPopup;
      {$IFDEF DELPHIXE6_LVL}
      PopupControl.Align := TAlignLayout.Client;
      {$ELSE}
      PopupControl.Align := TAlignLayout.alClient;
      {$ENDIF}
      PopupControl.Visible := True;
      FPopup.IsOpen := True;

      if Assigned(OnShowPopup) then
        OnShowPopup(Self);
    end
  end;
end;

procedure TTMSFMXFixedGridCell.SetShowCheckBox(const Value: Boolean);
begin
  if FShowCheckBox <> Value then
  begin
    FShowCheckBox := Value;
    if Assigned(CheckBox) then
    begin
      if ShowCheckBox then
        AddObject(CheckBox)
      else
        RemoveObject(CheckBox);
    end;
  end;
end;

procedure TTMSFMXFixedGridCell.SetShowDropDownButton(const Value: Boolean);
begin
  if FShowDropDownButton <> Value then
  begin
    FShowDropDownButton := Value;
    if Assigned(DropDownButton) then
    begin
      if ShowDropDownButton then
        AddObject(DropDownButton)
      else
        RemoveObject(DropDownButton);

      Resize;
    end;
  end;
end;

procedure TTMSFMXFixedGridCell.SetSortFill(const Value: TBrush);
begin
  if FSortFill <> Value then
  begin
    FSortFill := Value;
    Repaint;
  end;
end;

procedure TTMSFMXFixedGridCell.SetSortFont(const Value: TFont);
begin
  FSortFont.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.SetSortFontFill(const Value: TBrush);
begin
  FSortFontFill.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.SetSortIndex(const Value: Integer);
begin
  if FSortIndex <> Value then
  begin
    FSortIndex := Value;
    Repaint;
  end;
end;

procedure TTMSFMXFixedGridCell.SetSortKind(const Value: TSortKind);
begin
  if FSortKind <> Value then
  begin
    FSortKind := Value;
    if Assigned(SortShape) then
      SortShape.Visible := FSortKind <> skNone;
    Repaint;
  end;
end;

procedure TTMSFMXFixedGridCell.SetSortShape(const Value: TSortShape);
begin
  FSortShape.Assign(Value);
end;

procedure TTMSFMXFixedGridCell.SetSortStroke(const Value: TBrush);
begin
  if FSortStroke <> Value then
  begin
    FSortStroke.Assign(Value);
    Repaint;
  end;
end;

procedure TTMSFMXFixedGridCell.SetShowSpinBox(const Value: Boolean);
begin
  if FShowSpinBox <> value then
  begin
    FShowSpinBox  := Value;
    if Assigned(SpinBox) then
    begin
      if ShowSpinBox then
        AddObject(SpinBox)
      else
        RemoveObject(SpinBox);
    end;
  end;
end;

{ TSortShape }

constructor TSortShape.Create(AOwner: TComponent);
begin
  inherited;
  if AOwner is TTMSFMXFixedGridCell then
    FOwner := (AOwner as TTMSFMXFixedGridCell);
end;

procedure TSortShape.Paint;
var
  pth: TPathData;
  vertt: TTextAlign;
begin
  inherited;
  if Assigned(FOwner) then
  begin
    Canvas.Fill.Assign(FOwner.SortFill);
    Canvas.Stroke.Assign(FOwner.SortStroke);
    if FOwner.SortKind <> skNone then
    begin
      {$IFDEF DELPHIXE6_LVL}
      vertt := TTextAlign.Center;
      {$ELSE}
      vertt := TTextAlign.taCenter;
      {$ENDIF}
      pth := TPathData.Create;
      case FOwner.SortKind of
        skAscending:
        begin
          {$IFDEF DELPHIXE6_LVL}
          vertt := TTextAlign.Leading;
          {$ELSE}
          vertt := TTextAlign.taLeading;
          {$ENDIF}
          pth.MoveTo(PointF(Width / 2, 0.5));
          pth.LineTo(PointF(Width - 0.5, Height - 0.5));
          pth.LineTo(PointF(0.5, Height - 0.5));
        end;
        skDescending:
        begin
          {$IFDEF DELPHIXE6_LVL}
          vertt := TTextAlign.Trailing;
          {$ELSE}
          vertt := TTextAlign.taTrailing;
          {$ENDIF}
          pth.MoveTo(PointF(0.5, 0.5));
          pth.LineTo(PointF(Width - 0.5, 0.5));
          pth.LineTo(PointF(Width / 2, Height - 0.5));
        end;
      end;
      pth.ClosePath;
      Canvas.FillPath(pth, AbsoluteOpacity);
      Canvas.DrawPath(pth, AbsoluteOpacity);
      pth.Free;

      if FOwner.SortIndex <> -1 then
      begin
        Canvas.Fill.Assign(FOwner.SortFontFill);
        Canvas.Font.Assign(FOwneR.SortFont);
        {$IFDEF DELPHIXE6_LVL}
        Canvas.FillText(RectF(1, 0.5, Width - 2, Height - 1), inttostr(FOwner.SortIndex), False, AbsoluteOpacity, [], TTextAlign.Center, vertt);
        {$ELSE}
        Canvas.FillText(RectF(1, 0.5, Width - 2, Height - 1), inttostr(FOwner.SortIndex), False, AbsoluteOpacity, [], TTextAlign.taCenter, vertt);
        {$ENDIF}
      end;
    end;
  end;
end;

{ TTMSFMXProgressGridCell }

constructor TTMSFMXProgressGridCell.Create(AOwner: TComponent);
begin
  inherited;
  FProgressBar := TTMSFMXProgressBar.Create(Self);
  FProgressBar.CanFocus := False;
  FProgressBar.HitTest := False;
  {$IFDEF DELPHIXE6_LVL}
  FProgressBar.Align := TAlignLayout.Client;
  {$ELSE}
  FProgressBar.Align := TAlignLayout.alClient;
  {$ENDIF}
  FProgressBar.Margins.Left := 4;
  FProgressBar.Margins.Top := 4;
  FProgressBar.Margins.Bottom := 4;
  FProgressBar.Margins.Right := 4;
  AddObject(FProgressBar);
end;

destructor TTMSFMXProgressGridCell.Destroy;
begin
  FProgressBar.Free;
  inherited;
end;

function TTMSFMXProgressGridCell.GetControl: TControl;
begin
  Result := nil;
end;

function TTMSFMXProgressGridCell.GetPrintControl: TControl;
begin
  Result := ProgressBar;
end;

function TTMSFMXProgressGridCell.GetProgressBar: TTMSFMXProgressBar;
begin
  Result := FProgressBar
end;

procedure TTMSFMXProgressGridCell.Paint;
begin
  Draw(Canvas, BoundsRect, GetTextRect, False, True);
end;

procedure TTMSFMXProgressGridCell.SetProgressBar(const Value: TTMSFMXProgressBar);
begin
  FProgressBar.Assign(Value);
end;

{ TTMSFMXRotatedTextGridCell }

constructor TTMSFMXRotatedTextGridCell.Create(AOwner: TComponent);
var
  ctl: TControl;
begin
  inherited;
  ClipChildren := True;
  if AOwner is TControl then
  begin
    ctl := AOwner as TControl;
    if Assigned(ctl) then
    begin
      FRotatedText := TTMSFMXHTMLText.Create(Self);
      FRotatedText.HitTest := False;
      FRotatedText.CanFocus := False;
      FRotatedText.AutoSize := True;
      {$IFDEF DELPHIXE6_LVL}
      FRotatedText.Align := TAlignLayout.Center;
      {$ELSE}
      FRotatedText.Align := TAlignLayout.alCenter;
      {$ENDIF}
      FRotatedText.Text := '';
      AddObject(FRotatedText);
    end;
  end;
end;

destructor TTMSFMXRotatedTextGridCell.Destroy;
begin
  FRotatedText.Free;
  inherited;
end;

function TTMSFMXRotatedTextGridCell.GetRotatedText: TTMSFMXHTMLText;
begin
  Result := FRotatedText;
end;

procedure TTMSFMXRotatedTextGridCell.Paint;
begin
  Draw(Canvas, BoundsRect, GetTextRect, False, True);
end;

procedure TTMSFMXRotatedTextGridCell.Resize;
begin
  inherited;
  if Assigned(RotatedText) then
  begin
  end;
end;

function TTMSFMXRotatedTextGridCell.GetControl: TControl;
begin
  Result := nil;
end;

function TTMSFMXRotatedTextGridCell.GetPrintControl: TControl;
begin
  Result := RotatedText;
end;

procedure TTMSFMXRotatedTextGridCell.SetLayout(
  const Value: TTMSFMXGridCellLayout);
begin
  inherited;
  if Assigned(RotatedText) then
  begin
    RotatedText.Font.Assign(Layout.Font);
    RotatedText.Fill.Assign(Layout.FontFill);
    RotatedText.VertTextAlign := Layout.VerticalTextAlign;
    RotatedText.HorzTextAlign := Layout.TextAlign;
    RotatedText.WordWrap := Layout.WordWrapping;
    RotatedText.BitmapContainer := BitmapContainer;
    Resize;
  end;
end;

procedure TTMSFMXRotatedTextGridCell.SetRotatedText(const Value: TTMSFMXHTMLText);
begin
  FRotatedText.Assign(Value);
end;


procedure TTMSFMXRotatedTextGridCell.SetText(const Value: String);
begin
  inherited;
  if Assigned(RotatedText) then
    RotatedText.Text := Value;
end;

function TTMSFMXCheckBox.GetIsCheckedProg: Boolean;
begin
  Result := IsChecked;
end;

procedure TTMSFMXCheckBox.SetIsCheckedProg(const Value: Boolean);
begin
  IsChecked := Value;
end;

{ TTMSFMXRadioButton }
function TTMSFMXRadioButton.GetIsCheckedProg: Boolean;
begin
  Result := IsChecked;
end;

procedure TTMSFMXRadioButton.SetIsCheckedProg(const Value: Boolean);
begin
  IsChecked := Value;
end;


initialization
  RegisterFmxClasses([TTMSFMXGridCell, TCornerButton]);

end.
