home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / kolekce / d56 / DM2KVCL.ZIP / WORKGRID.PAS < prev   
Pascal/Delphi Source File  |  2000-12-31  |  23KB  |  516 lines

  1. {****************************************************************************}
  2. {                            Data Master 2000                                }
  3. {****************************************************************************}
  4. unit WorkGrid;
  5. {$B-,X+}
  6. interface
  7.  
  8. uses
  9.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  10.   Grids, ClipBrd, Common, Data, Math;
  11.  
  12. type
  13.   TWorksheet=class(TDrawGrid)
  14.   private
  15.     FContainer: TContainer;
  16.     FBlockColorF, FBlockColorB: TColor;
  17.     FAlignRight: boolean;                      {align number by right of cell}
  18.     FDrawHeaders: boolean;         {draw or not column headers & line numbers}
  19.     FHeader: TStringList;                               {keeps column headers}
  20.     procedure SetContainer(C: TContainer);           {also updates grid size!}
  21.     procedure SetBlockColorF(C: TColor);                       {refresh cells}
  22.     procedure SetBlockColorB(C: TColor);                                 {-#-}
  23.     procedure SetAlignRight(B: boolean);                                 {-#-}
  24.     procedure SetDrawHeaders(B: boolean);                                {-#-}
  25.     function GetHeader: TStrings;
  26.     procedure SetHeader(const Value: TStrings);
  27.     procedure StringsChanged(Sender: TObject);
  28.   protected
  29.     procedure DrawCell(ACol, ARow: Longint; ARect: TRect;
  30.                        AState: TGridDrawState); override;
  31.     procedure MouseDown(Btn: TMouseButton;                   {added selection}
  32.               Shift: TShiftState; X,Y: Integer); override;
  33.     function SelectCell(ACol, ARow: Longint): Boolean; override;
  34.     function GetEditText(ACol, ARow: Longint): string; override;
  35.     procedure SetEditText(ACol, ARow: Longint; const Value: string); override;
  36.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;     {edit}
  37.   public
  38.     constructor Create(AOwner: TComponent); override;
  39.     procedure UpdateSize;          {update col/row numbers after setcontainer}
  40.     procedure CopyToClipBoard(UseTabs: boolean);      {copy selection as text}
  41.     procedure PasteFromClipBoard(InsertLines,Overwrite: boolean);
  42.     procedure Delete;                                  {delete selected cells}
  43.     procedure AlignTextOut(ARect: TRect; ss: string);   {useful in OnDrawCell}
  44.     destructor Destroy; override;                       {disposes off headers}
  45.     procedure SelectAll;
  46.   published
  47.     property Container: TContainer read FContainer write SetContainer;
  48.     property BlockColorF: TColor read FBlockColorF write SetBlockColorF;
  49.     property BlockColorB: TColor read FBlockColorB write SetBlockColorB;
  50.     property AlignRight: boolean read FAlignRight write SetAlignRight;
  51.     property DrawHeaders: boolean read FDrawHeaders write SetDrawHeaders;
  52.     property Header: TStrings read GetHeader write SetHeader;
  53.   end;
  54.  
  55. procedure Register;        {note that this component requires TDataContainer!}
  56.  
  57. implementation
  58.  
  59. procedure TWorksheet.DrawCell(ACol, ARow: Longint; ARect: TRect;
  60.                              AState: TGridDrawState);
  61. var S: string; D: TData;
  62. begin
  63.   if  (ACol<FixedCols) or (ARow<FixedRows) then              {draw fixed area}
  64.       if FDrawHeaders then                 {if fixed cells used, draw headers}
  65.       begin
  66.         if (ARow=0) and (ACol>=FixedCols)                {draw column headers}
  67.           and (ACol-FixedCols<FHeader.Count) then
  68.         AlignTextOut(ARect, FHeader[ACol-FixedCols]);
  69.         if (Acol=0) and (Arow=0) then               {draw "select all button"}
  70.         begin
  71.           Canvas.Brush.Color:=FBlockColorB;
  72.           ARect.Left:=ARect.Left+2; ARect.Right:=ARect.Right-2;
  73.           ARect.Top:=ARect.Top+2; ARect.Bottom:=ARect.Bottom-2;
  74.           Canvas.FillRect(ARect); Exit;
  75.         end;
  76.         if (ACol=0) and (ARow>=FixedRows) then              {draw line number}
  77.         AlignTextOut(ARect,IntToStr(ARow-FixedRows));
  78.         if (ACol>0) and (ARow>0) then                {draw OTHER fixed cells!}
  79.         inherited DrawCell(ACol, ARow, ARect, AState);
  80.       end
  81.       else inherited DrawCell(ACol, ARow, ARect, AState) else
  82.   begin                                         {draw other (non-fixed) cells}
  83.     if (not Assigned(FContainer)) or (ARow>=FixedRows+FContainer.Items.Count)
  84.     then begin inherited DrawCell(ACol, ARow, ARect, AState); Exit; end;
  85.     D:=FContainer.Items[ARow-FixedRows];                            {get data}
  86.     ACol:=ACol-FixedCols;                               {correct to data area}
  87.     if gdSelected in AState then                              {correct colors}
  88.     begin
  89.       Canvas.Brush.Color:=FBlockColorB; Canvas.FillRect(ARect);
  90.       Canvas.Font.Color:=FBlockColorF;
  91.     end;
  92.     if (D is TFunction) and (ACol<2) then           {function or derivatives:}
  93.     begin
  94.       if ACol=0 then S:=FloatToStr((D as TFunction).X)
  95.       else S:=FloatToStr((D as TFunction).Y);
  96.     end;
  97.     if (D is TRealData) and (ACol<MaxCols) then
  98.     S:=(D as TRealData).GetItemText(ACol+1);   {realdata: ACol m.b. > NumCol!}
  99.     if not ((D is TRealData) or (D is TFunction))
  100.     then S:=WordStr(D.Data, ACol+1);          {other: try to display as words}
  101.     AlignTextOut(ARect,S);
  102.   end;
  103. end;
  104.  
  105. procedure TWorksheet.UpdateSize;                  {updates row/column numbers}
  106. begin
  107.   if Assigned(FContainer) then
  108.   begin
  109.     if FContainer.DataType=dtFunction then ColCount:=FixedCols+2;
  110.     if FContainer.DataType=dtRealData then ColCount:=FixedCols+MaxCols;
  111.     RowCount:=FContainer.Items.Count+1+FixedRows;    {one extra line for edit}
  112.   end;
  113.   Invalidate;
  114. end;
  115.  
  116. constructor TWorksheet.Create(AOwner: TComponent);           {init new fields}
  117. begin
  118.   inherited Create(AOwner);
  119.   Options:=[goFixedVertLine,goFixedHorzLine,goVertLine,goHorzLine,
  120.   goThumbTracking,goColSizing{,goRowSelect,goEditing},goRangeSelect];
  121.   FBlockColorF:=clYellow; FBlockColorB:=Color;
  122.   DefaultDrawing:=true; FAlignRight:=false; DrawHeaders:=false;
  123.   FHeader:=TStringList.Create; FHeader.OnChange:=StringsChanged; 
  124. end;
  125.  
  126. destructor TWorksheet.Destroy;
  127. begin if Assigned(FHeader) then FHeader.Free; inherited; end;
  128.  
  129. procedure TWorksheet.SetDrawHeaders(B: boolean);
  130. begin if B<>FDrawHeaders then begin FDrawHeaders:=B; Invalidate; end; end;
  131.  
  132. function TWorksheet.GetHeader: TStrings;
  133. begin Result:=FHeader; end;
  134.  
  135. procedure TWorksheet.SetHeader(const Value: TStrings);
  136. begin if Assigned(FHeader) then FHeader.Assign(Value); end;
  137.  
  138. procedure TWorksheet.StringsChanged(Sender: TObject);
  139. begin if Sender=FHeader then Invalidate; end;
  140.  
  141. procedure TWorksheet.CopyToClipBoard(UseTabs: boolean);
  142. var
  143.   D: TData; S,Ss: string; SL: TStringList; LC,CC,Btm: integer;
  144.   Data: pointer; HData: THandle; MS: TMemoryStream; L,R,N,I: integer; X:TReal;
  145. begin
  146.   if not Assigned(FContainer) or (FContainer.Items.Count<1) then Exit;
  147.   Btm:=Selection.Bottom; if Btm=RowCount-1 then Btm:=RowCount-2;     {correct}
  148.   Screen.Cursor:=crHourGlass;
  149.   SL:=TStringList.Create;                          {allocate and clear buffer}
  150.   MS:=TMemoryStream.Create;                 {create buffer for RealDataFormat}
  151.   try
  152.     LC:=0; MS.Write(LC, SizeOf(LC));                      {write line counter}
  153.     for LC:=Selection.Top to Btm do                                {row cycle}
  154.     begin
  155.       S:='';
  156.       if Btm>Selection.Top then                             {may be one cell!}
  157.       FContainer.ShowProgress(Round((LC-Selection.Top)*100
  158.         /(Btm-Selection.Top)));                        {show progress of copy}
  159.       D:=FContainer.Items[LC-FixedRows];
  160.       if D is TRealData then                   {add realdata to buffer stream}
  161.       begin
  162.         L:=Selection.Left-FixedCols+1; R:=Selection.Right-FixedCols+1;
  163.         if (D as TRealData).Size>R then N:=R else N:=(D as TRealData).Size;
  164.         I:=N-L+1; MS.Write(I, SizeOf(I));
  165.         for CC:=L to N do
  166.         begin X:=(D as TRealData).RData[CC]; MS.Write(X, SizeOf(X)); end;
  167.         integer(MS.Memory^):=integer(MS.Memory^)+1;   {increment line counter}
  168.       end;
  169.       for CC:=Selection.Left to Selection.Right do              {column cycle}
  170.       begin
  171.         if D is TRealData then
  172.         SS:=(D as TRealData).GetItemText(CC-FixedCols+1);
  173.         if D is TFunction then if CC=FixedCols
  174.         then SS:=FloatToStr((D as TFunction).X)
  175.         else SS:=FloatToStr((D as TFunction).Y);
  176.         if not ((D is TRealData) or (D is TFunction)) then
  177.         begin S:=D.Data; Break; end;                           {no columns!!!}
  178.         if SS<>'' then if S<>'' then     {Tabs for Origin, spaces for Grapher}
  179.            if UseTabs then S:=S+#9+Ss else S:=S+' '+Ss else S:=SS;
  180.       end;                                             {now in S-data string!}
  181.       SL.Add(S);                                               {add to buffer}
  182.     end;
  183.     ClipBoard.Open;                                        {copy to clipboard}
  184.     try
  185.       ClipBoard.AsText:=SL.Text;
  186.       if integer(MS.Memory^)>0 then
  187.       begin
  188.         HData:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE, MS.Size);
  189.         try
  190.           Data:=GlobalLock(HData);
  191.           try
  192.             Move(MS.Memory^, Data^, MS.Size);
  193.             SetClipboardData(TRealData.GetClipboardFormat, HData);
  194.           finally
  195.             GlobalUnlock(HData);
  196.           end;
  197.         except
  198.           GlobalFree(HData); raise;
  199.         end;
  200.       end;
  201.     finally
  202.       ClipBoard.Close;
  203.     end;
  204.   finally
  205.     MS.Free; SL.Free;
  206.     Screen.Cursor:=crDefault;
  207.   end;
  208. end;
  209.  
  210. procedure TWorksheet.PasteFromClipBoard(InsertLines,Overwrite: boolean);
  211. var H: THandle; Buf: PChar; S: TStringList; I,J,N,N1,SL: integer; D: TData;
  212.     s1,s2,s3: string; R,R1: TRealArray;
  213.     {$ifndef PasteRowCol}Row,Col: integer;{$endif}
  214.     MS: TMemoryStream; NN,Mn: integer;
  215. begin
  216.   {$ifndef PasteRowCol}Row:=Selection.Top; Col:=Selection.Left;{$endif}
  217.   if Clipboard.HasFormat(TRealData.GetClipboardFormat)
  218.      and (Container.DataType=dtRealData) then
  219.   begin{first try "native" RealDataFormat-only for appropriate container type}
  220.     Clipboard.Open;
  221.     try
  222.       H:=GetClipboardData(TRealData.GetClipboardFormat);
  223.       if H=0 then Exit; Buf:=GlobalLock(H); if Buf=nil then Exit;
  224.       try
  225.         MS:=TMemoryStream.Create;
  226.         try
  227.           MS.WriteBuffer(Buf^, GlobalSize(H));
  228.           MS.Position:=0; MS.Read(NN, SizeOf(NN));
  229.           if NN>0 then
  230.           begin
  231.             Screen.Cursor:=crHourGlass;
  232.             try
  233.               for I:=0 to NN-1 do
  234.               begin
  235.                 if NN>1 then Container.ShowProgress(Round(I/(NN-1)*100));
  236.                 MS.Read(N, SizeOf(N));
  237.                 for J:=1 to N do MS.Read(R[J], SizeOf(R[J]));
  238.                 if InsertLines then
  239.                 begin
  240.                   D:=Container.InitItem; (D as TRealData).SetRData(N,R);
  241.                   if Row-FixedRows<Container.Items.Count then
  242.                   Container.Items.Insert(Row+I-FixedRows, D)
  243.                   else Container.Items.Add(D);
  244.                   RowCount:=RowCount+1;
  245.                 end else
  246.                 if (Row-FixedRows<Container.Items.Count) and
  247.                    (I<Container.Items.Count-Row+FixedRows) then
  248.                 begin
  249.                   D:=FContainer.Items[Row-FixedRows+I]; SL:=Col-FixedCols;
  250.                   N1:=(D as TRealData).GetRData(R1);
  251.                   if Overwrite then
  252.                   begin
  253.                     Mn:=Min(N,MaxCols-SL);
  254.                     for J:=1 to Mn do R1[J+SL]:=R[J];
  255.                     (D as TRealData).SetRData(Max(Mn+SL,N1),R1);
  256.                   end else
  257.                   begin
  258.                     for J:=Min(N1, MaxCols-N-SL) downto SL+1 do
  259.                     R1[J+N]:=R1[J];
  260.                     for J:=1 to Min(N, MaxCols-SL) do R1[J+SL]:=R[J];
  261.                     (D as TRealData).SetRData(Min(N+N1,MaxCols),R1);
  262.                   end
  263.                 end else
  264.                 begin     {the end of container reached or last cell selected}
  265.                   D:=FContainer.InitItem; (D as TRealData).SetRData(N,R);
  266.                   FContainer.Items.Add(D); RowCount:=RowCount+1;
  267.                 end;
  268.               end;
  269.             finally
  270.               Screen.Cursor:=crDefault; ReFresh; Container.Modified:=true;
  271.             end;
  272.           end;
  273.         finally
  274.           MS.Free;
  275.         end;
  276.       finally
  277.         GlobalUnlock(H);
  278.       end;
  279.     finally
  280.       Clipboard.Close;
  281.     end;
  282.     Exit;
  283.   end;
  284.   if not Clipboard.HasFormat(CF_TEXT) then Exit;       {no text in clipboard!}
  285.   Clipboard.Open; H:=GetClipboardData(CF_TEXT);         {get clp data handler}
  286.   Buf:=GlobalLock(H);                                         {must be locked}
  287.   S:=TStringList.Create; Screen.Cursor:=crHourGlass;
  288.   try
  289.     S.SetText(Buf);                  {copy to stringlist (divide into lines!)}
  290.     for I:=0 to S.Count-1 do
  291.     begin
  292.       if S.Count>1 then FContainer.ShowProgress(Round(I/(S.Count-1)*100));
  293.       if InsertLines then                    {insert all lines into container}
  294.       begin
  295.         D:=FContainer.InitItem; D.Data:=S[I];
  296.         if Row-FixedRows<FContainer.Items.Count then
  297.         FContainer.Items.Insert(Row+I-FixedRows, D)
  298.         else FContainer.Items.Add(D);
  299.         RowCount:=RowCount+1;
  300.       end else
  301.       if (Row-FixedRows<FContainer.Items.Count) and
  302.          (I<FContainer.Items.Count-Row+FixedRows) then
  303.       begin
  304.         D:=FContainer.Items[Row-FixedRows+I]; SL:=Col-FixedCols;   {SL: 0..n!}
  305.         if D is TRealData then {avoid precision loss due to string conversion}
  306.         begin
  307.           N:=Str2Real(S[I], R1);
  308.           if ((not Overwrite) and ((D as TRealData).Size+N>MaxCols)) or
  309.              (Overwrite and (SL+N>MaxCols)) then
  310.           raise ERealDataError.Create(errInsItem);   {check for number count!}
  311.           N1:=(D as TRealData).GetRData(R);
  312.           for J:=1 to N do R[SL+J]:=R1[J];
  313.           if not Overwrite then
  314.           for J:=SL+1 to N1 do R[J+N]:=(D as TRealData).RData[J];
  315.           if Overwrite then (D as TRealData).SetRData(Max(SL+N,N1),R)
  316.           else (D as TRealData).SetRData((D as TRealData).Size+N,R);
  317.         end else
  318.         begin                         {convert data to string and insert S[I]}
  319.           s1:=D.Data; s2:=''; s3:='';
  320.           for J:=1 to SL do s2:=s2+' '+WordStr(s1, J);
  321.           for J:=SL+1 to NumWords(s1) do s3:=s3+' '+WordStr(s1, J);
  322.           if Overwrite then
  323.           begin
  324.             s2:=s2+' '+S[I];
  325.             for J:=NumWords(s2)+1 to NumWords(s1) do s2:=s2+' '+WordStr(s1,J);
  326.             D.Data:=s2;
  327.           end else D.Data:=s2+' '+S[I]+' '+s3;
  328.         end;
  329.       end else
  330.       begin               {the end of container reached or last cell selected}
  331.         D:=FContainer.InitItem; D.Data:=S[I];
  332.         FContainer.Items.Add(D); RowCount:=RowCount+1; {=> we should add data}
  333.       end;                  {parasitic scroll^ may be here if lines inserted!}
  334.     end;{for I:=...}
  335.   finally
  336.     GlobalUnlock(H); S.Free; Clipboard.Close;                 {free resources}
  337.     Screen.Cursor:=crDefault; ReFresh; FContainer.Modified:=true;
  338.   end;
  339. end;
  340.  
  341. procedure TWorksheet.SetContainer(C: TContainer);
  342. begin FContainer:=C; UpdateSize; end;
  343.  
  344. procedure TWorksheet.SetBlockColorF(C: TColor);
  345. begin FBlockColorF:=C; Invalidate; end;
  346.  
  347. procedure TWorksheet.SetBlockColorB(C: TColor);
  348. begin FBlockColorB:=C; Invalidate; end;
  349.  
  350. procedure TWorksheet.SetAlignRight(B: boolean);
  351. begin FAlignRight:=B; Invalidate; end;
  352.  
  353. function TWorksheet.SelectCell(ACol, ARow: Longint): Boolean;
  354. var D: TData;
  355. begin
  356.   Result:=true; if not Assigned(FContainer) then                     {no data}
  357.   begin Result:=inherited SelectCell(ACol, ARow); Exit; end;
  358.   ACol:=ACol-FixedCols; ARow:=ARow-FixedRows;               {data area coords}
  359.   if ARow>FContainer.Items.Count-1
  360.   then Result:=ACol<1 else                             {last row (for insert)}
  361.   begin
  362.     D:=FContainer.Items[ARow];
  363.     if D is TFunction then Result:=ACol<2;
  364.     if D is TRealData then Result:=ACol<=(D as TRealData).Size;
  365.   end;
  366. end;
  367.  
  368. function TWorksheet.GetEditText(ACol, ARow: Longint): string;
  369. var D: TData;
  370. begin                                                  {NOTE: support events!}
  371.   if not Assigned(FContainer) or (ARow-FixedRows>FContainer.Items.Count-1)
  372.   then Result:=inherited GetEditText(ACol, ARow) else
  373.   begin
  374.     D:=FContainer.Items[ARow-FixedRows];
  375.     if not ((D is TRealData) or (D is TFunction)) then
  376.     Result:=inherited GetEditText(ACol, ARow);
  377.     ACol:=ACol-FixedCols;                           {if D - func or arrray...}
  378.     if D is TFunction then
  379.        if ACol=0 then Result:=FloatToStr((D as TFunction).X)
  380.        else Result:=FloatToStr((D as TFunction).Y);
  381.     if D is TRealData then Result:=(D as TRealData).GetItemText(ACol+1);
  382.   end;
  383. end;
  384.  
  385. procedure TWorksheet.SetEditText(ACol, ARow: Longint; const Value: string);
  386. var R: TReal; Flag: integer; D: TData;
  387. begin                                                  {NOTE: support events!}
  388.   if not Assigned(FContainer) or (ARow-FixedRows>FContainer.Items.Count-1)
  389.   then inherited SetEditText(ACol, ARow, Value) else
  390.   begin
  391.     Val(Value, R, Flag); if Flag<>0 then Exit;         {unable digitize text!}
  392.     D:=FContainer.Items[ARow-FixedRows];
  393.     if not ((D is TRealData) or (D is TFunction)) then
  394.     inherited SetEditText(ACol, ARow, Value);
  395.     ACol:=ACol-FixedCols;                        {Note: ACol points data area}
  396.     try                                              {WARNING: may be errors!}
  397.       if D is TFunction then
  398.          if ACol=0 then (D as TFunction).X:=R else (D as TFunction).Y:=R;
  399.       if D is TRealData then with (D as TRealData) do
  400.          if ACol<Size then SetItem(ACol+1, R) else InsItem(R);
  401.     finally
  402.       FContainer.Modified:=true;                 {NOTE: editing CHANGES data!}
  403.     end;{try}
  404.   end;
  405. end;
  406.  
  407. procedure TWorksheet.KeyDown(var Key: Word; Shift: TShiftState);
  408. var D: TRealData;  // this method extends functions of built-in inplace editor
  409. begin
  410.   if not (Assigned(FContainer) and (goEditing in Options)) then
  411.   begin inherited KeyDown(Key, Shift); Exit; end; {no edition if no container}
  412.   case Key of
  413.     vk_Delete: if (Row<FContainer.Items.Count+FixedRows)      {not last cell!}
  414.                then if ssShift in Shift then            {Shift+DEL-delete row}
  415.                     begin
  416.                       if FContainer.Items.Count=0 then Exit;  {list is empty!}
  417.                       D:=FContainer.Items[Row-FixedRows];
  418.                       D.Free; FContainer.Items.Remove(D);
  419.                       RowCount:=RowCount-1;
  420.                     end else                             {Alt+DEL delete item}
  421.                     begin
  422.                       D:=FContainer.Items[Row-FixedRows];
  423.                       if not (D is TRealData) then Exit;     {only TRealData!}
  424.                       try
  425.                         if (ssAlt in Shift) then D.DelItem(Col+1-FixedCols);
  426.                       except
  427.                         raise; Exit;
  428.                       end;
  429.                     end
  430.                else Exit;
  431.     vk_Insert: if ssShift in Shift then begin         {Shift+INS - insert row}
  432.                  if Row-FixedRows<FContainer.Items.Count then
  433.                  FContainer.Items.Insert(Row-FixedRows, FContainer.InitItem)
  434.                  else FContainer.Items.Add(FContainer.InitItem);
  435.                  RowCount:=RowCount+1;
  436.                end else Exit;
  437.   else begin inherited KeyDown(Key, Shift); Exit; end;       {allow inherited}
  438.   end;{case}                                     {note: Exit-no modification!}
  439.   Invalidate; FContainer.Modified:=true;
  440. end;
  441. procedure TWorksheet.MouseDown(Btn: TMouseButton; Shift: TShiftState;
  442.   X,Y: Integer);
  443. var Col, Row: longint;
  444. begin
  445.   inherited MouseDown(Btn,Shift,X,Y);               {allow inherited behavior}
  446.   if (not FDrawHeaders) or (not Assigned(FContainer)) or (FixedCols=0)
  447.      or (FixedRows=0) then Exit;                {unable or nothing to select!}
  448.   MouseToCell(X,Y,Col,Row);                               {what cell clicked?}
  449.   if (Col=0) and (Row=0) then SelectAll;
  450. end;
  451.  
  452. procedure TWorksheet.AlignTextOut(ARect: TRect; ss: string);
  453. var X,Y,L: integer;                           {makes textout using AlignRight}
  454. begin
  455.   if ss='' then Exit;                                     {nothing to output!}
  456.   X:=ARect.Left+GridLineWidth-Font.Height div 2;               {calc position}
  457.   Y:=ARect.Top+(RowHeights[Row]+Font.Height) div 2;
  458.   if AlignRight then
  459.   begin
  460.     L:=Canvas.TextWidth(Ss);
  461.     if ARect.Right-X-L>0 then X:=ARect.Right-X-L+ARect.Left;
  462.   end;
  463.   Canvas.TextOut(X, Y, Ss);
  464. end;
  465.  
  466. procedure TWorksheet.Delete;
  467. var BegItem,EndItem,Item,N,J,SL,SR,SR1: integer; s1,s2,s3: string; D: TData;
  468. begin
  469.   if not Assigned(FContainer) or (FContainer.Items.Count<1) then Exit;
  470.   Screen.Cursor:=crHourGlass;
  471.   try
  472.     BegItem:=Selection.Top-FixedRows; EndItem:=Selection.Bottom-FixedRows;
  473.     SL:=Selection.Left-FixedCols+1; SR:=Selection.Right-FixedCols+1;   {1..N!}
  474.     Item:=BegItem; if EndItem>FContainer.Items.Count-1
  475.     then EndItem:=FContainer.Items.Count-1;                          {correct}
  476.     while Item<=EndItem do
  477.     begin
  478.       D:=Container.Items[Item];
  479.      if D is TRealData then N:=(D as TRealData).Size else N:=NumWords(D.Data);
  480.       if (SL=1) and (SR>=N) then {all item data selected => delete whole item}
  481.       begin Container.Items.Delete(Item); Dec(EndItem); end else
  482.       begin
  483.         if D is TRealData then
  484.         begin {real data:}
  485.           if SR>N then SR1:=N else SR1:=SR;
  486.           for J:=1 to SR1-SL+1 do (D as TRealData).DelItem(SL);
  487.         end else
  488.         begin {string:}
  489.           s1:=D.Data; s2:=''; s3:='';
  490.           for J:=1 to SL-1 do s2:=s2+' '+WordStr(s1, J);
  491.           for J:=SR+1 to N do s3:=s3+' '+WordStr(s1, J);
  492.           D.Data:=s2+' '+s3;
  493.         end;
  494.         Inc(Item);
  495.       end;
  496.     end;
  497.     UpdateSize; LeftCol:=FixedCols; {here - clear selection?}
  498.   finally
  499.     Screen.Cursor:=crDefault; FContainer.Modified:=true;
  500.   end;
  501. end;
  502.  
  503. procedure TWorksheet.SelectAll;
  504. var R: TGridRect;           // select all container items like in spreadsheets
  505. begin
  506.   R.Left:=FixedCols; R.Right:=ColCount-1; R.Top:=FixedRows;
  507.   R.Bottom:=FContainer.Items.Count+FixedRows-1;
  508.   if Assigned(FContainer) and (FContainer.Items.Count>0) then Selection:=R;{!}
  509. end;
  510.  
  511. {component registration - this unit may be used separately from dm2000}
  512. procedure Register;
  513. begin RegisterComponents('DM2000', [TWorksheet]); end;
  514.  
  515. end.
  516.