home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / Chip_2003-01_cd1.bin / zkuste / delphi / kolekce / d567 / FLEXCEL.ZIP / FlexCel / UFlexCelGrid.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-10-14  |  42.5 KB  |  1,326 lines

  1. unit UFlexCelGrid;
  2.  
  3. //Comment / uncomment the $DEFINE USPNGLIB to use Png support 
  4. {$IFDEF WIN32}
  5.   {$DEFINE USEPNGLIB}
  6. {$ENDIF}
  7.  
  8. interface
  9. uses
  10.   {$IFDEF WIN32}
  11.     Windows, Graphics, Grids, JPEG, Messages,
  12.     {$IFDEF USEPNGLIB}
  13.       //////////////////////////////// IMPORTANT ///////////////////////////////////////
  14.       //To be able to display PNG images and WMFs, you have to install TPNGImage from http://pngdelphi.sourceforge.net/
  15.       //If you don't want to install it, delete the "{$DEFINE USEPNGLIB}" at the top of this file
  16.       //Note that this is only needed on Windows, CLX has native support for PNG
  17.       ///////////////////////////////////////////////////////////////////////////////////
  18.         pngimage, pngzlib, dialogs,
  19.       ///////////////////////////////////////////////////////////////////////////////////
  20.       //If you are getting an error here, please read the note above.
  21.       ///////////////////////////////////////////////////////////////////////////////////
  22.     {$ENDIF}
  23.   {$ENDIF}
  24.   {$IFDEF LINUX}
  25.     Qt, QGraphics, QGrids, Types, QControls,
  26.   {$ENDIF}
  27.   {$IFDEF ConditionalExpressions}{$if CompilerVersion >= 14} variants, {$IFEND}{$ENDIF} //Delphi 6 or above
  28.  
  29.   SysUtils, Classes, UExcelAdapter, UFlexCelImport, Contnrs,
  30.   UFlxFormats, UFlxMessages, Math, UFlxNumberFormat;
  31.  
  32. const
  33. {$IFDEF WIN32}
  34.   AL_LEFT=DT_LEFT;
  35.   AL_BOTTOM=DT_BOTTOM;
  36.   AL_CENTER=DT_CENTER;
  37.   AL_RIGHT=DT_RIGHT;
  38.   AL_TOP=DT_TOP;
  39.   AL_VCENTER=DT_VCENTER;
  40. {$ENDIF}
  41. {$IFDEF LINUX}
  42.   AL_LEFT=integer(AlignmentFlags_AlignLeft);
  43.   AL_BOTTOM=integer(AlignmentFlags_AlignBottom);
  44.   AL_CENTER=integer(AlignmentFlags_AlignHCenter);
  45.   AL_RIGHT=integer(AlignmentFlags_AlignRight);
  46.   AL_TOP=integer(AlignmentFlags_AlignTop);
  47.   AL_VCENTER=integer(AlignmentFlags_AlignVCenter);
  48. {$ENDIF}
  49.  
  50. type
  51.   TFlexCelGrid=class;
  52.  
  53.   TFlxInPlaceEdit=class(TInPlaceEdit)
  54.   public
  55.     property Font;
  56.   end;
  57.  
  58.   TOnGetFontNameEvent=procedure(Sender: TObject; var FontName: TFontName) of object;
  59.   TOnFormatPictureEvent=procedure(Sender: TObject; const InData: TStream;const PicType: TXlsImgTypes; const OutPicture: TPicture) of object;
  60.   TWideSetEditEvent = procedure (Sender: TObject; ACol, ARow: Longint; const Value: Widestring) of object;
  61.   TOnAllowEditCellEvent = procedure (Sender: TObject; ACol, ARow: Longint; var AllowEdit: boolean) of object;
  62.  
  63.   TPictureData= class
  64.     Col1,Row1,Dx1, DY1, Width, Height: integer;
  65.     IsRectangular: boolean;
  66.     Data: TPicture;
  67.     constructor Create;
  68.     destructor Destroy; override;
  69.   end;
  70.  
  71.   TPictureDataList= class(TObjectList)
  72.     {$INCLUDE TPictureDataListHdr.inc}
  73.   end;
  74.  
  75.   TFlexCelGrid = class(TCustomGrid)
  76.   private
  77.     FFlexCelImport: TFlexCelImport;
  78.     FFormulaReadOnly: boolean;
  79.     FFullWorksheet: boolean;
  80.     FReadOnly: boolean;
  81.     FHideCursor: boolean;
  82.  
  83.     FDrawGridLines: boolean;
  84.     SheetLoaded: boolean;
  85.  
  86.     InPlaceFont: TFont;
  87.  
  88.     LastRow, LastCol: integer;
  89.     FZoom: integer;
  90.     Zoom100: extended;
  91.     UpdatingGridSize: boolean;
  92.  
  93.     PaintClipRect:TRect;
  94.  
  95.     FOnGetFontName: TOnGetFontNameEvent;
  96.     FOnFormatPicture: TOnFormatPictureEvent;
  97.     FOnSelectCell: TSelectCellEvent;
  98.  
  99.     PictureDataList:TPictureDataList;
  100.     FOnSetEditText: TWideSetEditEvent;
  101.     FOnAllowEditCell: TOnAllowEditCellEvent;
  102.  
  103.     procedure SetFlexCelImport(const Value: TFlexCelImport);
  104.     function ColTitle(const i:integer):string;
  105.     function IsEmptyCell(const ARow, ACol: integer): boolean;
  106.     procedure MyDrawCell(ACol, ARow: Integer; ClipRect, CellRect: TRect; AState: TGridDrawState; const First: boolean; const CanSpawnL, CanSpawnR: boolean; const RightCol, BottomRow: integer);
  107.     procedure SetReadOnly(const Value: boolean);
  108.     procedure SetZoom(const Value: integer);
  109.     procedure ResizeRowsAndCols;
  110.  
  111.     procedure WriteText(const Rect: TRect; const X,Y: integer; const OutText: Widestring);
  112.     procedure WrapText(Rect: TRect; const OutText: Widestring; const HAlign, VAlign: Cardinal; const AutoFit: boolean);
  113.     function CalcTextExtent(const OutText: Widestring): TSize;
  114.  
  115.     function CalcAcumRowHeightZoom100(const R1, R2: integer): integer;
  116.     function CalcAcumColWidthZoom100(const C1, C2: integer): integer;
  117.     function CalcAcumRowHeight(const R1, R2: integer): integer;
  118.     function CalcAcumColWidth(const C1, C2: integer): integer;
  119.  
  120.     function CalcPictureRect(const i: integer; const DrawInfo: TGridDrawInfo; var R1: TRect; const All: boolean): boolean;
  121.     procedure ResetClipRgn;
  122.     procedure SetClipRect(const aRect: TRect);
  123.  
  124.     function GetColor(const index: integer): TColor;
  125.     function CellCanSpawnLeft(const aRow, aCol: integer): boolean;
  126.     function CellCanSpawnRight(const aRow, aCol: integer): boolean;
  127.     { Private declarations }
  128.   protected
  129.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  130.     procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
  131.     function SelectCell(ACol, ARow: Longint): Boolean; override;
  132.  
  133.     procedure SizeChanged(OldColCount, OldRowCount: Longint); override;
  134.  
  135.     function CreateEditor: TInplaceEdit; override;
  136.  
  137.  
  138.     {$IFDEF WIN32}
  139.       procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
  140.  
  141.       function GetEditText(ACol, ARow: Longint): string; override;
  142.       procedure SetEditText(ACol, ARow: Longint; const Value: string); override;
  143.     {$ENDIF}
  144.     {$IFDEF LINUX}
  145.       function GetEditText(ACol, ARow: Longint): widestring; override;
  146.       procedure SetEditText(ACol, ARow: Longint; const Value: widestring); override;
  147.     {$ENDIF}
  148.  
  149.     function CanEditShow: Boolean; override;
  150.  
  151.     procedure ColWidthsChanged; override;
  152.     procedure RowHeightsChanged; override;
  153.  
  154.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  155.  
  156.     procedure Paint; override;
  157.     procedure Loaded; override;
  158.    { Protected declarations }
  159.   public
  160.     constructor Create(AOwner: TComponent); override;
  161.     destructor Destroy; override;
  162.     procedure LoadSheet;
  163.     procedure ApplySheet;
  164.  
  165.     property Row;
  166.     property Col;
  167.     property CanEdit: boolean read CanEditShow;
  168.  
  169.     {$IFDEF WIN32}
  170.     function BorderSize: integer;
  171.     {$ENDIF}
  172.  
  173.     procedure SetCell(const aRow, aCol: integer; const Text: widestring);
  174.     { Public declarations }
  175.   published
  176.     property FlexCelImport: TFlexCelImport read FFlexCelImport write SetFlexCelImport;
  177.     property ReadOnly: boolean read FReadOnly write SetReadOnly;
  178.     property HideCursor: boolean read FHideCursor write FHideCursor;
  179.     property FormulaReadOnly: boolean read FFormulaReadOnly write FFormulaReadOnly;
  180.     property FullWorksheet: boolean read FFullWorksheet write FFullWorksheet;
  181.  
  182.     property Zoom: integer read FZoom write SetZoom default 100;
  183.  
  184.     property Align;
  185.     property Anchors;
  186.     property Enabled;
  187.     property Font;
  188.     property Color;
  189.     property FixedColor;
  190.     property ParentFont;
  191.     property ParentColor;
  192.     property PopupMenu;
  193.     property ShowHint;
  194.     property TabOrder;
  195.     property TabStop;
  196.     property Visible;
  197.  
  198.     property BorderStyle;
  199.  
  200.     property OnClick;
  201.     property OnContextPopup;
  202.     property OnDblClick;
  203.     property OnDragDrop;
  204.     property OnDragOver;
  205.     property OnEnter;
  206.     property OnExit;
  207.     property OnKeyDown;
  208.     property OnKeyPress;
  209.     property OnKeyUp;
  210.     property OnMouseDown;
  211.     property OnMouseMove;
  212.     property OnMouseUp;
  213.     property OnMouseWheelDown;
  214.     property OnMouseWheelUp;
  215.     property OnStartDrag;
  216.  
  217.     //EVENTS
  218.     property OnSelectCell: TSelectCellEvent read FOnSelectCell write FOnSelectCell;
  219.     property OnSetEditText: TWideSetEditEvent read FOnSetEditText write FOnSetEditText;
  220.     property OnGetFontName: TOnGetFontNameEvent read FOnGetFontName write FOnGetFontName;
  221.     property OnFormatPicture: TOnFormatPictureEvent read FOnFormatPicture write FOnFormatPicture;
  222.     property OnAllowEditCell: TOnAllowEditCellEvent read FOnAllowEditCell write FOnAllowEditCell;
  223.     { Published declarations }
  224.   end;
  225.  
  226. procedure Register;
  227.  
  228. implementation
  229. {$INCLUDE TPictureDataListImp.inc}
  230.  
  231. {$R IFlexCelGrid.res}
  232. procedure Register;
  233. begin
  234.   RegisterComponents('FlexCel', [TFlexCelGrid]);
  235. end;
  236.  
  237. { TFlexCelGrid }
  238.  
  239. procedure TFlexCelGrid.ApplySheet;
  240. var
  241.   i: integer;
  242. begin
  243.   //Cancel editor
  244.    DoExit;
  245.   //We only modify rows wich have changed size, so we don't loose autofit.
  246.   //Rows in excel by default adapt to the font size. If you manually set the row height to a value, you loose that behaviour
  247.   //We should call AutoRowHeight to restore it.
  248.   if Assigned(FlexCelImport)and(FlexCelImport.IsLoaded)and(SheetLoaded)  then
  249.   begin
  250.     for i:=1 to RowCount-1 do if RowHeights[i]<> Round(FlexCelImport.RowHeight[i]/RowMult*Zoom100) then
  251.       FlexCelImport.RowHeight[i]:=Round(RowHeights[i]*RowMult/Zoom100);
  252.  
  253.     for i:=1 to ColCount-1 do if ColWidths[i]<> Round(FlexCelImport.ColumnWidth[i]/ColMult*Zoom100) then
  254.       FlexCelImport.ColumnWidth[i]:=Round(ColWidths[i]*ColMult/Zoom100);
  255.   end;
  256. end;
  257.  
  258. function TFlexCelGrid.CanEditShow: Boolean;
  259. begin
  260.   if not Assigned(FFlexCelImport) or not FFlexCelImport.IsLoaded or FReadOnly
  261.   or (FFormulaReadOnly and FlexCelImport.IsFormula[Row, Col])
  262.   or (FlexCelImport.CellMergedBounds[Row, Col].Top<>Row)
  263.   or (FlexCelImport.CellMergedBounds[Row, Col].Left<>Col) then
  264.     Result:=False
  265.   else
  266.   begin
  267.     Result:= inherited CanEditShow;
  268.     if Assigned(OnAllowEditCell) then OnAllowEditCell(Self, Col, Row, Result);
  269.   end;
  270.  
  271. end;
  272.  
  273. function TFlexCelGrid.ColTitle(const i: integer): string;
  274. const
  275.   Z=ord('Z');
  276.   A=ord('A');
  277. begin
  278. if i<=Z-A+1 then Result:= chr(A+i-1) else
  279.   Result:= chr(A+(i-1) div (Z-A+1)-1)+chr(A+ (i-1) mod (Z-A+1));
  280. end;
  281.  
  282. function TFlexCelGrid.CalcAcumRowHeight(const R1, R2: integer): integer;
  283. var
  284.   i: integer;
  285. begin
  286.   Result:=0;
  287.   for i:=R1 to R2-1 do Inc(Result, RowHeights[i]);
  288.   for i:=R1-1 downto R2 do Dec(Result, RowHeights[i]);
  289. end;
  290.  
  291. function TFlexCelGrid.CalcAcumRowHeightZoom100(const R1, R2: integer): integer;
  292. var
  293.   i: integer;
  294. begin
  295.   Result:=0;
  296.   for i:=R1 to R2-1 do Inc(Result, FlexCelImport.RowHeight[i]);
  297.   for i:=R1-1 downto R2 do Dec(Result, FlexCelImport.RowHeight[i]);
  298.   Result:=Round(Result/RowMult);
  299. end;
  300.  
  301. function TFlexCelGrid.CalcAcumColWidth(const C1, C2: integer): integer;
  302. var
  303.   i: integer;
  304. begin
  305.   Result:=0;
  306.   for i:=C1 to C2-1 do Inc(Result, ColWidths[i]);
  307.   for i:=C1-1 downto C2 do Dec(Result, ColWidths[i]);
  308. end;
  309.  
  310. function TFlexCelGrid.CalcAcumColWidthZoom100(const C1, C2: integer): integer;
  311. var
  312.   i: integer;
  313. begin
  314.   Result:=0;
  315.   for i:=C1 to C2-1 do Inc(Result, FlexCelImport.ColumnWidth[i]);
  316.   for i:=C1-1 downto C2 do Dec(Result, FlexCelImport.ColumnWidth[i]);
  317.   Result:=Round(Result/ColMult);
  318. end;
  319.  
  320. procedure TFlexCelGrid.ColWidthsChanged;
  321. begin
  322.   if UpdatingGridsize then exit;
  323.   inherited;
  324.   ApplySheet;
  325. end;
  326.  
  327. constructor TFlexCelGrid.Create(AOwner: TComponent);
  328. begin
  329.   inherited;
  330.   Font.Name:='Arial';
  331.   DefaultDrawing:=False;
  332.   Options := [goRowSizing, goColSizing, goEditing, goThumbTracking];
  333.   LastRow:=-1;
  334.   LastCol:=-1;
  335.   FZoom:=100;
  336.   Zoom100:=1;
  337.   UpdatingGridsize:=false;
  338.   FDrawGridLines:=true;
  339.   PictureDataList:=TPictureDataList.Create;
  340.   SheetLoaded:=false;
  341. end;
  342.  
  343. destructor TFlexCelGrid.Destroy;
  344. begin
  345.   FreeAndNil(PictureDataList);
  346.   inherited;
  347. end;
  348.  
  349. function TFlexCelGrid.IsEmptyCell(const ARow, ACol: integer): boolean;
  350. var
  351.   v: variant;
  352. begin
  353.   if (aRow<=0) or (aCol<=0) or (ACol>=ColCount)or (ARow>=RowCount) then Result:=false
  354.   else if not FlexCelImport.IsLoaded then Result:= true
  355.   else
  356.   begin
  357.     v:=FlexCelImport.CellValue[aRow, aCol];
  358.     Result:=VarIsEmpty(v)or VarIsNull(v) or ((VarType(v)=vtString) and (v=''));
  359.   end;
  360. end;
  361.  
  362. function Intersect(const Rect1, Rect2: TRect; var OutRect: TRect): boolean;
  363. begin
  364.   OutRect.Left:=Max(Rect1.Left, Rect2.Left);
  365.   OutRect.Top:=Max(Rect1.Top, Rect2.Top);
  366.   OutRect.Right:=Min(Rect1.Right, Rect2.Right);
  367.   OutRect.Bottom:=Min(Rect1.Bottom, Rect2.Bottom);
  368.   Result:=(OutRect.Left<OutRect.Right)and(OutRect.Top<OutRect.Bottom);
  369. end;
  370.  
  371. procedure TFlexCelGrid.WriteText(const Rect: TRect; const X,Y: integer; const OutText: Widestring);
  372. {$IFDEF WIN32}
  373. var
  374.   Options: Longint;
  375. {$ENDIF}
  376.  
  377. begin
  378. {$IFDEF LINUX} //Linux canvas has support for widestrings
  379.   Canvas.TextRect(Rect, X, Y, OutText);
  380. {$ENDIF}
  381. {$IFDEF WIN32} //If we use Canvas.textrect we loose widestrings
  382.   Options := ETO_CLIPPED or Canvas.TextFlags or ETO_OPAQUE;
  383.   Windows.ExtTextOutW(Canvas.Handle, X, Y, Options, @Rect, PWideChar(OutText),
  384.     Length(OutText), nil);
  385. {$ENDIF}
  386.  
  387. end;
  388.  
  389. procedure TFlexCelGrid.WrapText(Rect: TRect; const OutText: Widestring; const HAlign, VAlign: Cardinal; const AutoFit: boolean);
  390. var
  391.   Options: Int64; //So it works in linux and windows
  392.  
  393. begin
  394. {$IFDEF LINUX}
  395.   Options:=HAlign+VAlign;
  396.   if AutoFit then Options:=Options+integer(AlignmentFlags_WordBreak) else Options:=Options+integer(AlignmentFlags_SingleLine);
  397.   Canvas.TextRect(Rect, Rect.Left , Rect.Top , OutText, Options);
  398. {$ENDIF}
  399. {$IFDEF WIN32}
  400.   Options:=HAlign+VAlign ;
  401.   if AutoFit then Options:=Options+DT_WORDBREAK else Options:=Options+DT_SINGLELINE;
  402.   InflateRect(Rect, -1, -1);
  403.   Windows.DrawTextW(Canvas.Handle, PWideChar(OutText), Length(OutText), Rect, Options);
  404. {$ENDIF}
  405.  
  406. end;
  407.  
  408. function TFlexCelGrid.CalcTextExtent(const OutText: Widestring): TSize;
  409. begin
  410. {$IFDEF LINUX} //Linux canvas has support for widestrings
  411.   Result:=Canvas.TextExtent(OutText);
  412. {$ENDIF}
  413. {$IFDEF WIN32} //If we use Canvas.textrect we loose widestrings
  414.   GetTextExtentPoint32W(Canvas.Handle, PWideChar(OutText), Length(OutText), Result);
  415. {$ENDIF}
  416. end;
  417.  
  418. function TFlexCelGrid.GetColor(const index: integer): TColor;
  419. begin
  420.   if (Index>0) and (Index<=FlexCelImport.ColorPaletteCount) then
  421.   Result:=FlexCelImport.ColorPalette[Index]
  422.   else Result:=clBlack;
  423. end;
  424.  
  425. function TFlexCelGrid.CellCanSpawnRight(const aRow, aCol: integer): boolean;
  426. var
  427.   Fm: TFlxFormat;
  428.   Mb: TXlsCellRange;
  429. begin
  430.   Result:=False;
  431.   Fm:=FFlexCelImport.CellFormatDef[aRow, aCol];
  432.   if (Fm.HAlignment= fha_Right) or (Fm.WrapText) then exit;
  433.   Mb:=FFlexCelImport.CellMergedBounds[aRow, aCol];
  434.   Result:= (Mb.Left=aCol) and (Mb.Right= aCol) and (Mb.Top=aRow) and (Mb.Bottom=aRow);
  435. end;
  436.  
  437. function TFlexCelGrid.CellCanSpawnLeft(const aRow, aCol: integer): boolean;
  438. var
  439.   Fm: TFlxFormat;
  440.   Mb: TXlsCellRange;
  441. begin
  442.   Result:=False;
  443.   Fm:=FFlexCelImport.CellFormatDef[aRow, aCol];
  444.   if (Fm.HAlignment= fha_Left) or (Fm.WrapText) then exit;
  445.   Mb:=FFlexCelImport.CellMergedBounds[aRow, aCol];
  446.   Result:= (Mb.Left=aCol) and (Mb.Right= aCol) and (Mb.Top=aRow) and (Mb.Bottom=aRow);
  447. end;
  448.  
  449. procedure TFlexCelGrid.MyDrawCell(ACol, ARow: Integer; ClipRect, CellRect: TRect; AState: TGridDrawState; const First: boolean; const CanSpawnL, CanSpawnR: boolean; const RightCol, BottomRow: integer);
  450. var
  451.   ColorIndex: integer;
  452.   Fm, Fm1: TFlxFormat;
  453.   HAlign, VAlign: Cardinal;
  454.   TextRect, FinalRect: TRect;
  455.   OutValue: variant;
  456.   OutText: widestring;
  457.   i, k: integer;
  458.   X, Y, Clp: integer;
  459.   FontName: TFontName;
  460.   TextExtent: TSize;
  461.   BottomColor, RightColor: TColor;
  462.   Dg, DBottom, DRight: boolean;
  463.   Corner: byte;
  464.   FontColor: integer;
  465.   MergedBounds: TXlsCellRange;
  466.   MultiLine: boolean;
  467. begin
  468.   if FZoom<=50 then Clp:=0 else if FZoom<=90 then Clp:=1 else Clp:=2; //Do not use margins around the cell if zoom is small
  469.   MultiLine:=false;
  470.   //Reset Style
  471.   Canvas.Font:=Font;
  472.   Canvas.Font.Size:=Round(Canvas.Font.Size*Zoom100);
  473.   BottomColor:=clLtGray;
  474.   RightColor:=clLtGray;
  475.   DBottom:=false; DRight:=false;
  476.  
  477.   if First then
  478.   begin
  479.     Canvas.Brush.Color:=Color;
  480.     Canvas.Pen.Width:=1;
  481.   end;
  482.  
  483.  
  484.   HAlign:=AL_LEFT;
  485.   VAlign:=AL_BOTTOM;
  486.   OutText:='';
  487.  
  488.   if not Assigned(FlexCelImport) then exit;
  489.  
  490.   if FlexCelImport.IsLoaded and (aRow>0) and (aCol>0) then
  491.   begin
  492.     //MERGED CELLS
  493.     //We see this before anything else, because if it's merged, we have to exit
  494.     MergedBounds:= FFlexCelImport.CellMergedBounds[aRow, aCol];
  495.     if aCol < MergedBounds.Right then CellRect.Right:=CellRect.Left+CalcAcumColWidth(aCol, MergedBounds.Right+1);
  496.     if aRow < MergedBounds.Bottom then CellRect.Bottom:=CellRect.Top+CalcAcumRowHeight(aRow, MergedBounds.Bottom+1);
  497.  
  498.     if (aCol > MergedBounds.Left) or (aRow > MergedBounds.Top) then
  499.     begin
  500.       MyDrawCell(MergedBounds.Left, MergedBounds.Top, ClipRect,
  501.                  Rect(ClipRect.Left+CalcAcumColWidth(aCol, MergedBounds.Left),
  502.                       ClipRect.Top+CalcAcumRowHeight(aRow, MergedBounds.Top),
  503.                       ClipRect.Left+CalcAcumColWidth(aCol, MergedBounds.Left+1), //This is TopLeft cell
  504.                       ClipRect.Top+CalcAcumRowHeight(aRow, MergedBounds.Top+1)),
  505.                  AState, True, False, False, MergedBounds.Right, MergedBounds.Bottom);
  506.       exit;
  507.     end;
  508.  
  509.     //Value
  510.     OutValue:=FlexCelImport.CellValue[aRow, aCol];
  511.     if VarType(OutValue)=VarBoolean then HAlign:=AL_CENTER else
  512.       if (VarType(OutValue)<>VarOleStr)and(VarType(OutValue)<>VarString) then HAlign:=AL_RIGHT;
  513.  
  514.     Fm:=FlexCelImport.CellFormatDef[aRow, aCol];
  515.     //MULTILINE
  516.     MultiLine:=Fm.WrapText;
  517.     //PATTERN
  518.     if First then
  519.     begin
  520.       ColorIndex:=Fm.FillPattern.fgColorIndex;
  521.       if (ColorIndex>0)and(ColorIndex<=56) then
  522.       begin
  523.         Canvas.Brush.Color:= FlexCelImport.ColorPalette[ColorIndex];
  524.         BottomColor:=Canvas.Brush.Color;
  525.         RightColor:=BottomColor;
  526.         DBottom:=true; DRight:=true;
  527.       end;
  528.     end;
  529.     //FONT
  530.     if (Fm.Font.ColorIndex>0)and (integer(Fm.Font.ColorIndex)<FlexCelImport.ColorPaletteCount) then
  531.       Canvas.Font.Color:=FlexCelImport.ColorPalette[Fm.Font.ColorIndex];
  532.  
  533.     FontName:=Fm.Font.Name;
  534.     if Assigned(OnGetFontName) then OnGetFontName(Self, FontName);
  535.     Canvas.Font.Name:=FontName;
  536.     Canvas.Font.Size:=Round(Fm.Font.Size20 / 20 * Zoom100);
  537.     if Fm.Font.Underline <> fu_None then
  538.       Canvas.Font.Style:=Canvas.Font.Style+[fsUnderline];
  539.  
  540.     if flsBold in Fm.Font.Style then Canvas.Font.Style:=Canvas.Font.Style+[fsBold];
  541.     if flsItalic in Fm.Font.Style then Canvas.Font.Style:=Canvas.Font.Style+[fsItalic];
  542.     if flsStrikeOut in Fm.Font.Style then Canvas.Font.Style:=Canvas.Font.Style+[fsStrikeOut];
  543.     //BORDERS
  544.     if (RightCol<>ACol)or (BottomRow<>aRow) then
  545.       Fm1:=FlexCelImport.CellFormatDef[BottomRow, RightCol]
  546.     else
  547.       Fm1:=Fm;
  548.  
  549.     if Fm1.Borders.Bottom.Style <> fbs_None then
  550.     begin
  551.       BottomColor:=GetColor(Fm1.Borders.Bottom.ColorIndex);
  552.       DBottom:=true;
  553.     end;
  554.     if Fm1.Borders.Right.Style <> fbs_None then
  555.     begin
  556.       RightColor:=GetColor(Fm1.Borders.Bottom.ColorIndex);
  557.       DRight:=true;
  558.     end;
  559.     //Search for the other 2 borders
  560.     if RightCol<ColCount-1 then
  561.     begin
  562.       Fm1:=FlexCelImport.CellFormatDef[BottomRow, RightCol+1];
  563.       if Fm1.Borders.Left.Style <> fbs_None then
  564.       begin
  565.         RightColor:=GetColor(Fm1.Borders.Left.ColorIndex);
  566.         DRight:=true;
  567.       end;
  568.     end;
  569.     if BottomRow<RowCount-1 then
  570.     begin
  571.       Fm1:=FlexCelImport.CellFormatDef[BottomRow+1, RightCol];
  572.       if Fm1.Borders.Top.Style <> fbs_None then
  573.       begin
  574.         BottomColor:=GetColor(Fm1.Borders.Top.ColorIndex);
  575.         DBottom:=true;
  576.       end;
  577.     end;
  578.  
  579.     //ALIGN
  580.     case Fm.HAlignment of
  581.       fha_left: HAlign:=AL_LEFT;
  582.       fha_center:HAlign:=AL_CENTER;
  583.       fha_right: HAlign:=AL_RIGHT;
  584.     end;//case
  585.  
  586.     case Fm.VAlignment of
  587.       fva_top: VAlign:=AL_TOP;
  588.       fva_center: VAlign:=AL_VCENTER;
  589.       fva_bottom: VAlign:=AL_BOTTOM ;
  590.     end; //case
  591.  
  592.     //FORMULA
  593.     if FFormulaReadOnly and FlexCelImport.IsFormula[aRow, aCol] then
  594.       Canvas.Brush.Color := clsilver;
  595.  
  596.     if (aRow=Row)and(aCol=Col) then
  597.       if (InPlaceEditor<>nil) then (InplaceEditor as TFlxInPlaceEdit).Font:=Canvas.Font
  598.       else InPlaceFont:=Canvas.Font;
  599.  
  600.     //NUMERIC FORMAT
  601.     FontColor:=Canvas.Font.Color;
  602.     OutText:=XlsFormatValue(OutValue, Fm.Format, FontColor);
  603.     Canvas.Font.Color:=FontColor;
  604.   end;
  605.  
  606.   if FlexCelImport.IsLoaded and (ACol=0)and(ARow>0) and not FlexCelImport.AutoRowHeight[aRow] then
  607.   begin
  608.     Canvas.Font.Style:=Canvas.Font.Style+[fsBold];
  609.     Canvas.Font.Color:=clNavy;
  610.   end;
  611.  
  612.   if (ACol=0)or(ARow=0)  then
  613.   begin
  614.     HAlign:=AL_CENTER;
  615.     Canvas.Brush.Color := FixedColor;
  616.     BottomColor:=clGray;
  617.     RightColor:=BottomColor;
  618.     if not HideCursor then
  619.       if (aRow=Row)or (aCol=Col) then Canvas.Brush.Color:= $00F2BEAA;
  620.  
  621.       if (aRow=0) and (aCol<>0) then OutText:=ColTitle(aCol)
  622.         else if aRow<>0 then OutText:=IntToStr(aRow);
  623.   end;
  624.  
  625.   if First then
  626.   begin
  627.   //Draw Grid lines and clear cell
  628.     Canvas.FillRect(ClipRect);
  629.     Dg:=((Zoom>=50) and (FDrawGridLines))or(ARow=0) or (ACol=0);
  630.     Canvas.Pen.Color:=BottomColor;
  631.     if (BottomColor=RightColor)and (Dg or (DBottom and DRight)) then
  632.         Canvas.Polyline([Point(CellRect.Left,CellRect.Bottom-1),
  633.                          Point(CellRect.Right-1,CellRect.Bottom-1),
  634.                          Point(CellRect.Right-1,CellRect.Top-1)])
  635.     else
  636.     begin
  637.       if DBottom then Corner:=0 else Corner:=1;
  638.       if Dg or DBottom then
  639.         Canvas.Polyline([Point(CellRect.Left-1+Corner,CellRect.Bottom-1),
  640.                          Point(CellRect.Right-Corner,CellRect.Bottom-1)]);
  641.       Canvas.Pen.Color:=RightColor;
  642.       if DRight then Corner:=0 else Corner:=1;
  643.       if Dg or DRight then
  644.         Canvas.Polyline([Point(CellRect.Right-1,CellRect.Bottom-1-Corner),
  645.                          Point(CellRect.Right-1,CellRect.Top-1+Corner)]);
  646.     end;
  647.   end;
  648.  
  649.   //Support for drawing a continued cell on an empty one
  650.   if IsEmptyCell(ARow, ACol) and FFlexCelImport.IsLoaded and not (EditorMode)then
  651.   begin
  652.     if Zoom<=25 then exit; //Optimize for small zoom
  653.     //Search for the previous non empty cell
  654.     i:=FFlexCelImport.ColIndex[aRow,aCol]-1;
  655.     while (i>0)and(IsEmptyCell(aRow,FlexCelImport.ColByIndex[aRow,i])) do dec(i);
  656.     if i>0 then
  657.     begin
  658.       k:=FFlexCelImport.ColByIndex[aRow, i];
  659.       if CellCanSpawnRight(aRow, k) then
  660.         MyDrawCell(k, ARow, ClipRect, Rect(CellRect.Left+CalcAcumColWidth(aCol,k), CellRect.Top, CellRect.Left+CalcAcumColWidth(aCol,k+1), CellRect.Bottom),  AState, False, True, IsEmptyCell(aRow, aCol+1), k, ARow);
  661.     end;
  662.     //Search for next non empty cell
  663.     i:=FFlexCelImport.ColIndex[aRow,aCol];
  664.     while (i>0) and(i<=FFlexCelImport.ColIndexCount[aRow])and(IsEmptyCell(aRow,FlexCelImport.ColByIndex[aRow,i])) do inc(i);
  665.     if (i>0)and(i<=FFlexCelImport.ColIndexCount[aRow]) then
  666.     begin
  667.       k:=FFlexCelImport.ColByIndex[aRow, i];
  668.       if CellCanSpawnLeft(aRow, k) then
  669.         MyDrawCell(k, ARow, ClipRect, Rect(CellRect.Left+CalcAcumColWidth(aCol,k), CellRect.Top, CellRect.Left+CalcAcumColWidth(aCol,k+1), CellRect.Bottom), AState,False, IsEmptyCell(aRow, aCol-1), True, k, ARow);
  670.     end;
  671.  
  672.     exit; //nothing to draw
  673.   end;
  674.  
  675.   TextRect:=Classes.Rect(ClipRect.Left+Clp, ClipRect.Top+Clp, ClipRect.Right-Clp, ClipRect.Bottom-Clp);
  676.   TextExtent:=CalcTextExtent(OutText);
  677.  
  678.   case VAlign of
  679.     AL_TOP: Y:=CellRect.Top+Clp;
  680.     AL_VCENTER: Y:=(CellRect.Top+CellRect.Bottom-TextExtent.cy) div 2;
  681.     else Y:=CellRect.Bottom-Clp-TextExtent.cy;
  682.   end; //case
  683.  
  684.   case HAlign of
  685.     AL_RIGHT: X:=CellRect.Right-Clp-TextExtent.cx;
  686.     AL_CENTER: X:=(CellRect.Left+CellRect.Right-TextExtent.cx) div 2;
  687.     else X:=CellRect.Left+Clp;
  688.   end; //case
  689.  
  690.   FinalRect:=ClipRect;
  691.   if FinalRect.Right>ClientWidth+BorderSize then FinalRect.Right:=ClientWidth+BorderSize; //This is for kylix not writing past the scrollbar
  692.   SetClipRect(FinalRect);
  693.  
  694.     //Clear grid lines if spawning the cell
  695.     if First then
  696.     begin
  697.       //If it's a merged cell, draw on all the cell
  698.       if (CellRect.Top<>ClipRect.Top) or (CellRect.Left<>ClipRect.Left)
  699.       or (CellRect.Bottom<>ClipRect.Bottom) or (CellRect.Right<>ClipRect.Right) then
  700.       begin
  701.         inc(TextRect.Right,Clp);
  702.         dec(TextRect.Left,Clp);
  703.       end
  704.       else
  705.       if not MultiLine then
  706.       begin
  707.         if IsEmptyCell(aRow, aCol+1) then
  708.         begin
  709.           inc(TextRect.Right,Clp);
  710.           if (X+TextExtent.cx>= TextRect.Right) and (X<TextRect.Right) then  //Clear right grid line
  711.             Canvas.FillRect(Rect(ClipRect.Right-1,ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom-1))
  712.         end;
  713.         if IsEmptyCell(aRow, aCol-1) then
  714.         begin
  715.           dec(TextRect.Left,Clp);
  716.         end;
  717.       end;
  718.     end else
  719.     begin
  720.       if CanSpawnL then dec(TextRect.Left,Clp);
  721.       if CanSpawnR then inc(TextRect.Right,Clp);
  722.  
  723.       if CanSpawnR and (X+TextExtent.cx>= TextRect.Right) and (X<TextRect.Right) then  //Clear right grid line
  724.         Canvas.FillRect(Rect(ClipRect.Right-1,ClipRect.Top, ClipRect.Right+1, ClipRect.Bottom-1))
  725.     end;
  726.  
  727.     if MultiLine or
  728.         First and
  729.         (    (CellRect.Top<>ClipRect.Top) or (CellRect.Left<>ClipRect.Left)  //Merged Cell
  730.           or (CellRect.Bottom<>ClipRect.Bottom) or (CellRect.Right<>ClipRect.Right)
  731.          ) then
  732.           WrapText(CellRect, OutText, HAlign, VAlign, MultiLine)
  733.             else
  734.           if Intersect(TextRect, Rect(X,Y,X+TextExtent.cx,Y+TextExtent.cy), FinalRect) then
  735.             WriteText(FinalRect, X, Y, OutText);
  736.             
  737.   ResetClipRgn;
  738. end;
  739.  
  740. {$IFDEF WIN32}
  741. function TFlexCelGrid.GetEditText(ACol, ARow: Integer): string;
  742. begin
  743.   if not Assigned(FFlexCelImport) or not FFlexCelImport.IsLoaded then Result:='' else
  744.   Result:=FFlexCelImport.CellValue[ARow, ACol];
  745. end;
  746. {$ENDIF}
  747. {$IFDEF LINUX}
  748. function TFlexCelGrid.GetEditText(ACol, ARow: Integer): widestring;
  749. begin
  750.   if not Assigned(FFlexCelImport) or not FFlexCelImport.IsLoaded then Result:='' else
  751.   Result:=FFlexCelImport.CellValue[ARow, ACol];
  752. end;
  753. {$ENDIF}
  754.  
  755. procedure TFlexCelGrid.Loaded;
  756. begin
  757.   inherited;
  758.   DefaultColWidth:=220;
  759.   DefaultRowHeight:=16;
  760.   ColWidths[0]:=48;
  761. end;
  762.  
  763. procedure TFlexCelGrid.ResizeRowsAndCols;
  764. var
  765.   i:integer;
  766. begin
  767.   UpdatingGridsize:=true;
  768.   try
  769.     DefaultRowHeight:=Round(FlexCelImport.DefaultRowHeight/RowMult*Zoom100);
  770.     for i:=1 to Min(RowCount-1, FlexCelImport.MaxRow) do
  771.       if not(FlexCelImport.IsEmptyRow(i)) then RowHeights[i]:= Round(FlexCelImport.RowHeight[i]/RowMult*Zoom100);
  772.  
  773.     DefaultColWidth:=Round(FlexCelImport.DefaultColWidth/ColMult*Zoom100);
  774.     for i:=1 to ColCount-1 do ColWidths[i]:= Round(FlexCelImport.ColumnWidth[i]/ColMult*Zoom100);
  775.     ColWidths[0]:=Round(48*Zoom100);
  776.   finally
  777.     UpdatingGridsize:=false;
  778.     ColWidthsChanged;
  779.     RowHeightsChanged;
  780.   end; //finally
  781. end;
  782.  
  783. {$IFDEF USEPNGLIB}
  784. type
  785.   TSmallRect=packed record
  786.     Left,
  787.     Top,
  788.     Right,
  789.     Bottom: SmallInt;
  790.   end;
  791.  
  792. //WMF Header
  793.   TMetafileHeader = packed record
  794.     Key: Longint;
  795.     Handle: SmallInt;
  796.     Rect: TSmallRect;
  797.  
  798.     Inch: Word;
  799.     Reserved: Longint;
  800.     CheckSum: Word;
  801.   end;
  802.  
  803. function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;
  804. type
  805.   PWord = ^Word;
  806. var
  807.   pW: PWord;
  808.   pEnd: PWord;
  809. begin
  810.   Result := 0;
  811.   pW := @WMF;
  812.   pEnd := @WMF.CheckSum;
  813.   while Longint(pW) < Longint(pEnd) do
  814.   begin
  815.     Result := Result xor pW^;
  816.     Inc(Longint(pW), SizeOf(Word));
  817.   end;
  818. end;
  819.  
  820. procedure LoadWmf(const OutPicture: TPicture; const InStream: TStream; const PicType: TXlsImgTypes);
  821. const
  822.   Z_OK=0;
  823.   Z_STREAM_END=1;
  824. var
  825.   WmfHead: TMetafileHeader;
  826.   MemStream, CompressedStream: TMemoryStream;
  827.   ZL: TZStreamRec;
  828.   Buff: Array of char;
  829.   Res, LastOut: integer;
  830.   BoundRect: TRect;
  831.   IsCompressed: byte;
  832. begin
  833.   MemStream:=TMemoryStream.Create;
  834.   try
  835.     if PicType=xli_wmf then
  836.     begin
  837.       //Write Metafile Header
  838.       FillChar(WmfHead, SizeOf(WmfHead), 0);
  839.       WmfHead.Key:=Integer($9AC6CDD7);
  840.       InStream.Position:=4;
  841.  
  842.       //We can't just read into WmfHead.Rect, beacuse this is small ints, not ints
  843.       InStream.ReadBuffer(BoundRect, SizeOf(BoundRect));
  844.       WmfHead.Rect.Left:=BoundRect.Left;
  845.       WmfHead.Rect.Top:=BoundRect.Top;
  846.       WmfHead.Rect.Right:=BoundRect.Right;
  847.       WmfHead.Rect.Bottom:=BoundRect.Bottom;
  848.  
  849.       WmfHead.Inch:=96;
  850.       WmfHead.CheckSum:=ComputeAldusChecksum(WmfHead);
  851.       MemStream.WriteBuffer(WmfHead, SizeOf(WmfHead));
  852.     end;
  853.  
  854.     InStream.Position:=32;
  855.     InStream.Read(IsCompressed, SizeOf(IsCompressed));
  856.     InStream.Position:=34;
  857.  
  858.     if IsCompressed=0 then //Data is compressed
  859.     begin
  860.       //Uncompress Data
  861.       Fillchar(ZL, SIZEOF(TZStreamRec), #0);
  862.  
  863.       CompressedStream:=TMemoryStream.Create;
  864.       try
  865.         CompressedStream.CopyFrom(InStream, InStream.Size- InStream.Position);
  866.         CompressedStream.Position:=0;
  867.         FillChar(Zl, SizeOf(Zl), #0);
  868.         Zl.next_in:=CompressedStream.Memory;
  869.         Zl.avail_in:=CompressedStream.Size;
  870.         SetLength(Buff, 2048);     //Arbitrary block size
  871.         Zl.next_out:=@Buff[0];
  872.         Zl.avail_out:=Length(Buff);
  873.         LastOut:=0;
  874.         try
  875.           if InflateInit_(ZL, zlib_version, SIZEOF(TZStreamRec))<> Z_OK then
  876.             raise Exception.Create(ErrInvalidWmf);
  877.           repeat
  878.             Res:=Inflate(ZL,0);
  879.             if (Res<> Z_OK) and (Res<>Z_STREAM_END) then
  880.               raise Exception.Create(ErrInvalidWmf);
  881.  
  882.             MemStream.WriteBuffer(Buff[0], Zl.Total_Out-LastOut);
  883.             LastOut:=Zl.Total_Out;
  884.             Zl.next_out:=@Buff[0];
  885.             Zl.avail_out:=Length(Buff);
  886.           until Res= Z_STREAM_END;
  887.         finally
  888.           InflateEnd(ZL);
  889.         end; //Finally
  890.       finally
  891.         FreeAndNil(CompressedStream);
  892.       end;
  893.     end else
  894.     begin
  895.       MemStream.CopyFrom(InStream, InStream.Size-InStream.Position);
  896.     end;
  897.  
  898.     MemStream.Position:=0;
  899.     OutPicture.Graphic.LoadFromStream(MemStream);
  900.   finally
  901.     FreeAndNil(MemStream);
  902.   end; //Finally
  903. end;
  904.  
  905. {$ENDIF}
  906.  
  907. procedure TFlexCelGrid.LoadSheet;
  908. var
  909.   i: integer;
  910.   Pic: TStream;
  911.   PicType: TXlsImgTypes;
  912.   Anchor: TClientAnchor;
  913.   PicDat: TPictureData;
  914.   Bmp:TBitmap;
  915.   {$IFDEF WIN32}
  916.   Jpeg: TJpegImage;
  917.   {$ENDIF}
  918.   {$IFDEF USEPNGLIB}
  919.     Png: TPNGObject;
  920.     Wmf: TMetafile;
  921.   {$ENDIF}
  922. begin
  923.   DoExit;
  924.   if not Assigned(FFlexcelImport)or not FFlexCelImport.IsLoaded then exit;
  925.   if not FFlexCelImport.CanOptimizeRead then Raise Exception.Create(ErrUseFasterAdapter);
  926.   if FFullWorksheet then
  927.   begin
  928.     RowCount:= 65536+1;
  929.     ColCount:= 256+1;
  930.   end else
  931.   begin
  932.     if FlexCelImport.MaxRow+1 >2 then RowCount:=FlexCelImport.MaxRow+1 else RowCount:=2;
  933.     if FlexCelImport.MaxCol+1 >2 then ColCount:=FlexCelImport.MaxCol+1 else ColCount:=2;
  934.   end;
  935.   // FixedRows:=3;
  936.   // FixedCols:=2;
  937.   Row:=FixedRows;
  938.   Col:=FixedCols;
  939.   FDrawGridLines:=FlexCelImport.ShowGridLines;
  940.  
  941.   SheetLoaded:=true;
  942.   ResizeRowsAndCols;
  943.  
  944.   PictureDataList.Clear;
  945.   for i:=0 to FlexCelImport.PicturesCount-1 do
  946.   begin
  947.     Pic:=TMemoryStream.Create;
  948.     try
  949.       FlexCelImport.GetPicture(i, Pic, PicType, Anchor);
  950.       PicDat:= TPictureData.Create;
  951.       try
  952.         //We save it this way so image does not get resized when resizing cols or rows
  953.         PicDat.Col1:= Anchor.Col1;
  954.         PicDat.Row1:= Anchor.Row1;
  955.         PicDat.Dx1:=Round(Anchor.Dx1*FlexCelImport.ColumnWidth[Anchor.Col1]/ColMult/1024);
  956.         PicDat.Dy1:=Round(Anchor.Dy1*FlexCelImport.RowHeight[Anchor.Row1]/RowMult/255);
  957.         PicDat.Width:= CalcAcumColWidthZoom100(Anchor.Col1, Anchor.Col2)+Round(Anchor.Dx2*FlexCelImport.ColumnWidth[Anchor.Col2]/ColMult/1024)-PicDat.Dx1;
  958.         PicDat.Height:= CalcAcumRowHeightZoom100(Anchor.Row1, Anchor.Row2)+Round(Anchor.Dy2*FlexCelImport.RowHeight[Anchor.Row2]/RowMult/255)-PicDat.Dy1;
  959.  
  960.         PicDat.IsRectangular:= PicType in [xli_Bmp, xli_Jpeg, xli_Png];
  961.  
  962.         Pic.Position:=0;
  963.         case PicType of
  964.           {$IFDEF WIN32}
  965.              xli_Jpeg:
  966.              begin
  967.                Jpeg:=TJPEGImage.Create;
  968.                try
  969.                  PicDat.Data.Graphic:=Jpeg;
  970.                finally
  971.                  FreeAndNil(Jpeg); //Remember TPicture.Graphic keeps a COPY of the TGraphic
  972.                end;
  973.                (PicDat.Data.Graphic as TJPEGImage).Performance:=jpBestQuality;
  974.                PicDat.Data.Graphic.LoadFromStream(Pic);
  975.              end;
  976.             xli_Bmp:
  977.             begin
  978.               Bmp:=TBitmap.Create;
  979.               try
  980.                 PicDat.Data.Graphic:=Bmp;
  981.                finally
  982.                  FreeAndNil(Bmp); //Remember TPicture.Graphic keeps a COPY of the TGraphic
  983.                end;
  984.               PicDat.Data.Graphic.LoadFromStream(Pic);
  985.             end;
  986.             //There is no direct support for PNG, because there is not a standard Delphi class to support it.
  987.             //No direct support for wmf/emf, because it uses zlib and it would have to be added to the package list.
  988.             //To support it define USEPNGLIB at the top of this file
  989.  
  990.             {$IFDEF USEPNGLIB}
  991.               xli_png:
  992.               begin
  993.                 Png:=TPNGObject.Create;
  994.                 try
  995.                   PicDat.Data.Graphic:=Png;
  996.                  finally
  997.                    FreeAndNil(Png); //Remember TPicture.Graphic keeps a COPY of the TGraphic
  998.                  end;
  999.                 PicDat.Data.Graphic.LoadFromStream(Pic);
  1000.               end;
  1001.  
  1002.               xli_wmf, xli_emf:
  1003.               begin
  1004.                 Wmf:=TMetaFile.Create;
  1005.                 try
  1006.                   PicDat.Data.Graphic:=Wmf;
  1007.                 finally
  1008.                   FreeAndNil(Wmf);
  1009.                 end; //finally
  1010.                 LoadWmf(PicDat.Data, Pic, PicType);
  1011.               end;
  1012.             {$ENDIF}
  1013.  
  1014.           {$ENDIF}
  1015.           {$IFDEF LINUX}
  1016.           //Here png is directly supported. Not metafiles...
  1017.             xli_Bmp, xli_Jpeg, xli_Png:
  1018.             begin
  1019.               Bmp:=TBitmap.Create;
  1020.               try
  1021.                 PicDat.Data.Graphic:=Bmp;
  1022.                finally
  1023.                  FreeAndNil(Bmp); //Remember TPicture.Graphic keeps a COPY of the TGraphic
  1024.                end;
  1025.               PicDat.Data.Graphic.LoadFromStream(Pic);
  1026.             end;
  1027.           {$ENDIF}
  1028.  
  1029.           else if Assigned (OnFormatPicture) then OnFormatPicture(Self, Pic, PicType, PicDat.Data);
  1030.         end; //case
  1031.  
  1032.       PictureDataList.Add(PicDat);
  1033.       except
  1034.         FreeAndNil(PicDat);
  1035.         //Dont raise... is not a major error;
  1036.       end;    //finally
  1037.     finally
  1038.       FreeAndNil(Pic);
  1039.     end; //Finally
  1040.   end;
  1041.   Invalidate;
  1042. end;
  1043.  
  1044. procedure TFlexCelGrid.Notification(AComponent: TComponent; Operation: TOperation);
  1045. begin
  1046.   inherited Notification(AComponent, Operation);
  1047.   if Operation = opRemove then
  1048.   begin
  1049.     if AComponent = FFlexCelImport then
  1050.         FFlexCelImport:= nil;
  1051.   end;
  1052. end;
  1053.  
  1054. function TFlexCelGrid.CalcPictureRect(const i: integer; const DrawInfo: TGridDrawInfo; var R1: TRect;const All: boolean): boolean;
  1055. var
  1056.   Row1,Col1, w, h: integer;
  1057. begin
  1058.   Result:=false;
  1059.   Col1:=PictureDataList[i].Col1; Row1:=PictureDataList[i].Row1;
  1060.   if Col1> DrawInfo.Horz.LastFullVisibleCell+1 then exit;
  1061.   if Row1> DrawInfo.Vert.LastFullVisibleCell+1 then exit;
  1062.   w:=Round(PictureDataList[i].Width*Zoom100)+Round(PictureDataList[i].Dx1*Zoom100); //Separated rounds so we don't have rouding errors
  1063.   while (Col1<LeftCol-FixedCols+1)and (w>0) do
  1064.   begin
  1065.     dec(w, ColWidths[Col1]);
  1066.     inc(Col1);
  1067.   end;
  1068.   if w<=0 then exit;
  1069.  
  1070.   h:=Round(PictureDataList[i].Height*Zoom100)+Round(PictureDataList[i].Dy1*Zoom100);
  1071.   while (Row1<TopRow-FixedRows+1)and (h>0) do
  1072.   begin
  1073.     dec(h, RowHeights[Row1]);
  1074.     inc(Row1);
  1075.   end;
  1076.   if h<=0 then exit;
  1077.  
  1078.   if All then
  1079.   begin
  1080.     R1.Left:=Round(BorderSize+ColWidths[0]+CalcAcumColWidth(LeftCol-FixedCols+1, PictureDataList[i].Col1)+PictureDataList[i].Dx1*Zoom100);
  1081.     R1.Top:=Round(BorderSize+RowHeights[0]+CalcAcumRowHeight(TopRow-FixedRows+1, PictureDataList[i].Row1)+PictureDataList[i].Dy1*Zoom100);
  1082.     R1.Right:=R1.Left+Round(PictureDataList[i].Width*Zoom100);
  1083.     R1.Bottom:=R1.Top+Round(PictureDataList[i].Height*Zoom100);
  1084.   end else
  1085.   begin
  1086.     R1.Left:=Round(BorderSize+ColWidths[0]+CalcAcumColWidth(LeftCol-FixedCols+1, Col1));
  1087.     R1.Top:=Round(BorderSize+RowHeights[0]+CalcAcumRowHeight(TopRow-FixedRows+1, Row1));
  1088.     R1.Right:=R1.Left+w;
  1089.     R1.Bottom:=R1.Top+h;
  1090.     if PictureDataList[i].Col1>= LeftCol-FixedCols+1 then inc(R1.Left, Round(PictureDataList[i].Dx1*Zoom100));
  1091.     if PictureDataList[i].Row1>= TopRow-FixedRows+1 then inc(R1.Top, Round(PictureDataList[i].Dy1*Zoom100));
  1092.   end;
  1093.   Result:=true;
  1094. end;
  1095.  
  1096. procedure TFlexCelGrid.ResetClipRgn;
  1097. begin
  1098. {$IFDEF WIN32}
  1099.   SelectClipRgn(Canvas.Handle,0);
  1100.   IntersectClipRect(Canvas.Handle, PaintClipRect.Left, PaintClipRect.Top, PaintClipRect.Right, PaintClipRect.Bottom);
  1101. {$ENDIF}
  1102. {$IFDEF LINUX}
  1103.   Canvas.SetClipRect(PaintClipRect);
  1104. {$ENDIF}
  1105. end;
  1106.  
  1107. procedure TFlexCelGrid.SetClipRect(const aRect: TRect);
  1108. begin
  1109.   {$IFDEF WIN32}
  1110.     IntersectClipRect(Canvas.Handle, aRect.Left, aRect.Top, aRect.Right, aRect.Bottom);
  1111.   {$ENDIF}
  1112.   {$IFDEF LINUX}
  1113.     Canvas.SetClipRect(aRect);
  1114.   {$ENDIF}
  1115. end;
  1116.  
  1117. procedure TFlexCelGrid.Paint;
  1118. var
  1119.   FocRect, R1: TRect;
  1120.   i: integer;
  1121.   DrawInfo: TGridDrawInfo;
  1122. begin
  1123.   try
  1124.     {$IFDEF WIN32}
  1125.     PaintClipRect:=Canvas.ClipRect;
  1126.     {$ENDIF}
  1127.     {$IFDEF LINUX}
  1128.     PaintClipRect:=Rect(BorderSize, BorderSize, BorderSize+ClientWidth, BorderSize+ClientHeight);  //QT bug?
  1129.     {$ENDIF}
  1130.     CalcDrawInfo(DrawInfo);
  1131.  
  1132.     {$IFDEF WIN32}
  1133.     //This is to avoid flicker drawing the image. Only implemented on windows because i can't get it only with TCanvas.SetClipRect
  1134.       for i:=0 to PictureDataList.Count-1 do
  1135.         if CalcPictureRect(i, DrawInfo, R1, False) and PictureDataList[i].IsRectangular then
  1136.           ExcludeClipRect(Canvas.Handle, R1.Left, R1.Top, R1.Right, R1.Bottom);
  1137.     {$ENDIF}
  1138.  
  1139.     inherited;
  1140.  
  1141.     if (LastCol<>Col)or (LastRow<>Row) then
  1142.     begin
  1143.       //InvalidateCell(LastRow, LastCol);
  1144.       LastRow:=Row;
  1145.       LastCol:=Col;
  1146.     end;
  1147.     Canvas.Pen.Width:=1;
  1148.     Canvas.Pen.Color:=clBlack;
  1149.     if not (csDesigning in ComponentState) and not HideCursor then
  1150.     begin
  1151.       FocRect:=CellRect(Col,Row);
  1152.       for i:=0 to 1 do
  1153.         Canvas.Polyline([Point(FocRect.Left+i, FocRect.Top+i), Point(FocRect.Right-i-1, FocRect.Top+i), Point(FocRect.Right-i-1, FocRect.Bottom-i-1), Point(FocRect.Left+i, FocRect.Bottom-i-1),Point(FocRect.Left+i, FocRect.Top+i)]);
  1154.     end;
  1155.     if not Assigned(FFlexCelImport) then exit;
  1156.  
  1157.     ResetClipRgn;
  1158.  
  1159.     Canvas.Brush.Color:=clWhite; Canvas.Pen.Color:=clBlack;
  1160.     SetClipRect(Rect(BorderSize+ColWidths[0], BorderSize+RowHeights[0], BorderSize+ClientWidth, BorderSize+ClientHeight));
  1161.     //Draw images
  1162.     for i:=0 to PictureDataList.Count-1 do
  1163.       if CalcPictureRect(i, DrawInfo, R1, True) then
  1164.       begin
  1165.         if (PictureDataList[i].Data.Graphic=nil) then Canvas.Rectangle(R1) else
  1166.           Canvas.StretchDraw(R1, PictureDataList[i].Data.Graphic);
  1167.       end;
  1168.  
  1169.     ResetClipRgn;
  1170.   except
  1171.     //No exceptions on paint...
  1172.   end;
  1173. end;
  1174.  
  1175. procedure TFlexCelGrid.RowHeightsChanged;
  1176. begin
  1177.   if not UpdatingGridSize then
  1178.   begin
  1179.     inherited;
  1180.     ApplySheet;
  1181.   end;
  1182. end;
  1183.  
  1184. function TFlexCelGrid.SelectCell(ACol, ARow: Integer): Boolean;
  1185. begin
  1186.   InvalidateCell(0, Row);
  1187.   InvalidateCell(Col, 0);
  1188.   InvalidateCell(0, ARow);
  1189.   InvalidateCell(ACol, 0);
  1190.   Result := True;
  1191.   if Assigned(FFlexCelImport) and (FFLexCelImport.IsLoaded) and  Assigned(FOnSelectCell) then
  1192.     FOnSelectCell(Self, ACol, ARow, Result);
  1193. end;
  1194.  
  1195. {$IFDEF WIN32}
  1196.   procedure TFlexCelGrid.SetEditText(ACol, ARow: Longint; const Value: string);
  1197.   var
  1198.     w: WideString;
  1199.   begin
  1200.     SetCell(ARow, ACol, Value);
  1201.     w:=Value;
  1202.     if Assigned(FOnSetEditText) then FOnSetEditText(Self, ACol, ARow, w);
  1203.   end;
  1204. {$ENDIF}
  1205. {$IFDEF LINUX}
  1206.   procedure TFlexCelGrid.SetEditText(ACol, ARow: Longint; const Value: widestring);
  1207.   begin
  1208.     SetCell(ARow, ACol, Value);
  1209.     if Assigned(FOnSetEditText) then FOnSetEditText(Self, ACol, ARow, Value);
  1210.   end;
  1211. {$ENDIF}
  1212.  
  1213. procedure TFlexCelGrid.SetFlexCelImport(const Value: TFlexCelImport);
  1214. begin
  1215.   FFlexCelImport := Value;
  1216.   Invalidate;
  1217. end;
  1218.  
  1219. procedure TFlexCelGrid.SizeChanged(OldColCount, OldRowCount: Integer);
  1220. begin
  1221. end;
  1222.  
  1223. procedure TFlexCelGrid.DrawCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState);
  1224. begin
  1225.   MyDrawCell(ACol, ARow, ARect, ARect, AState, True, False, False, ACol, ARow);
  1226. end;
  1227.  
  1228. procedure TFlexCelGrid.SetReadOnly(const Value: boolean);
  1229. begin
  1230.   FReadOnly := Value;
  1231.   if FReadOnly then Options:=Options - [goEditing] else Options:= Options + [goEditing];
  1232. end;
  1233.  
  1234. procedure TFlexCelGrid.KeyDown(var Key: Word; Shift: TShiftState);
  1235. begin
  1236.   inherited;
  1237. {$IFDEF WIN32}
  1238.   if (Key = VK_DELETE) then
  1239. {$ENDIF}
  1240. {$IFDEF LINUX}
  1241.   if (Key = KEY_DELETE) then
  1242. {$ENDIF}
  1243.  
  1244.   begin
  1245.     if Assigned(FlexCelImport)and FlexCelImport.IsLoaded then
  1246.       FlexCelImport.CellValue[Row,Col]:=unassigned;
  1247.     //InvalidateRow(aRow) doesnt work if the grid is scrolled horizontally... on D5 at least;
  1248.     Invalidate;
  1249.     Key := 0;
  1250.   end;
  1251.  
  1252. {$IFDEF WIN32}
  1253.   if (Key = VK_ESCAPE) then
  1254. {$ENDIF}
  1255. {$IFDEF LINUX}
  1256.   if (Key = KEY_ESCAPE) then
  1257. {$ENDIF}
  1258.     DoExit;
  1259. end;
  1260.  
  1261. procedure TFlexCelGrid.SetZoom(const Value: integer);
  1262. begin
  1263.   ApplySheet;
  1264.   if Value>400 then FZoom := 400
  1265.   else if Value<10 then FZoom:=10
  1266.   else FZoom:=Value;
  1267.   Zoom100:=FZoom/100;
  1268.   ResizeRowsAndCols;
  1269. end;
  1270.  
  1271. function TFlexCelGrid.CreateEditor: TInplaceEdit;
  1272. begin
  1273.   Result := TFlxInplaceEdit.Create(Self);
  1274.   if InPlaceFont<>nil then (Result as TFlxInplaceEdit).Font:= InPlaceFont;
  1275. end;
  1276.  
  1277. procedure TFlexCelGrid.SetCell(const aRow, aCol: integer; const Text: widestring);
  1278. var
  1279.   e:extended;
  1280.   s: string;
  1281. begin
  1282.   if not Assigned(FFlexCelImport) or not FFlexCelImport.IsLoaded then exit;
  1283.  
  1284.   //try to convert to number
  1285.   s:=Text; //for if value is a widestring
  1286.   if TextToFloat(PChar(s), e, fvExtended) then  //Dont use val because it doesnt handle locales
  1287.     FlexCelImport.CellValue[ARow, ACol]:=e else
  1288.   //try to convert to boolean
  1289.     if UpperCase(s)=TxtFalse then FlexCelImport.CellValue[ARow, ACol]:=false  else
  1290.     if UpperCase(s)=TxtTrue then FlexCelImport.CellValue[ARow, ACol]:=true else
  1291.  
  1292.     FlexCelImport.CellValue[ARow, ACol]:=Text;
  1293.  
  1294.   //InvalidateRow(aRow) doesnt work if the grid is scrolled horizontally... on D5 at least;
  1295.   Invalidate;
  1296. end;
  1297.  
  1298. {$IFDEF WIN32}
  1299. procedure TFlexCelGrid.WMEraseBkgnd(var Message: TWmEraseBkgnd);
  1300. begin
  1301.   //This is to avoid flicker when we scroll
  1302.   Message.Result := 1;
  1303. end;
  1304.  
  1305. function TFlexCelGrid.BorderSize: integer;
  1306. begin
  1307.   BorderSize:=0;
  1308. end;
  1309. {$ENDIF}
  1310.  
  1311. { TPictureData }
  1312.  
  1313. constructor TPictureData.Create;
  1314. begin
  1315.   Data:=TPicture.Create;
  1316. end;
  1317.  
  1318. destructor TPictureData.Destroy;
  1319. begin
  1320.   FreeAndNil(Data);
  1321.   inherited;
  1322. end;
  1323.  
  1324. end.
  1325.  
  1326.