Componentes.Terceros.DevExp.../official/x.42/ExpressSpreadSheet/Sources/cxSSViewInfo.pas
2009-02-27 12:02:10 +00:00

1366 lines
45 KiB
ObjectPascal

{*******************************************************************}
{ }
{ Developer Express Cross platform Visual Component Library }
{ ExpressSpreadSheet }
{ }
{ Copyright (c) 2001-2009 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSSPREADSHEET AND ALL }
{ ACCOMPANYING VCL AND CLX CONTROLS AS PART OF AN EXECUTABLE }
{ PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{*******************************************************************}
unit cxSSViewInfo;
{$I cxVer.inc}
interface
uses
Classes, Math, SysUtils,
Windows, Graphics, cxGraphics, cxExcelConst, cxSSTypes, cxSSStyles,
cxSSData, cxSSHeaders, cxSSFormulas, cxSSUtils, cxSSPainterWrapper;
type
TcxSSheetViewInfoClass = class of TcxSSheetViewInfo;
TcxSSNavigatorBtnStates = set of TcxSSNavigatorBtn;
TcxSSCaptionHitTest = (htNone, htCaption, htButton);
TcxSSCaptionStates = set of (csCurrent, csHidden);
TcxSSCaptionInfoBrick = record
State: TcxSSCaptionStates;
DisplayText: TcxString;
BoundsRect: TRect;
end;
TcxSSBookCaptionViewInfo = record
Bounds: TRect;
FillColor: TColor;
Font: TFont;
PageCount: Byte;
IsButtonDown: Boolean;
BtnDown: ShortInt;
Enabled: TcxSSNavigatorBtnStates;
FirstVisibleCaption: Integer;
BtnBricks: array[TcxSSNavigatorBtn] of TRect;
Bricks: array of TcxSSCaptionInfoBrick;
end;
PcxEdgeVertex = ^TcxEdgeVertex;
TcxEdgeVertex = packed array[0..2] of TRect;
PcxSSInfoBrick = ^TcxSSInfoBrick;
TcxSSInfoBrick = packed record
Col, Row : Integer;
DisplayRect : TRect;
TextRect : TRect;
BrushStyle : TcxSSFillStyle;
BrushBkColor : Word;
BrushFGColor : Word;
Edges: TcxSSBordersStyle;
TopEdgeVertex: TcxEdgeVertex;
LeftEdgeVertex: TcxEdgeVertex;
TextSettings : TcxTextParameters;
IsSelected: Boolean;
case IsMerge: Boolean of
True: (UnionIndex: Integer);
False: ();
end;
TcxSSUnionInfoBrick = packed record
UnionRange: TRect;
BrushStyle : TcxSSFillStyle;
BrushBkColor : Word;
BrushFGColor : Word;
TextRect : TRect;
DisplayRect : TRect;
IsSelected : Boolean;
TextSettings : TcxTextParameters;
end;
TcxSSViewInfoData = packed record
DisplayRect: TRect;
Bounds : TRect;
DrawHeaders: Boolean;
Selection : TRect;
SelectedBricks: TRect;
HeaderColor: Integer;
HeaderFontColor: Integer;
IsSelectionVisible: Boolean;
UnionBricks: array of TcxSSUnionInfoBrick;
Bricks : array of array of TcxSSInfoBrick;
end;
TcxSSHitTestState = (htCell, htRowHeader, htColHeader, htResize, htUpperLeft);
TcxSSHitTestStates = set of TcxSSHitTestState;
TcxSSheetViewInfo = class
private
FDrawGrid: Boolean;
FInfoData: TcxSSViewInfoData;
FInfoChanged: Boolean;
FOwner: TObject;
FShowFormulas: Boolean;
function GetBottomRow: Integer;
function GetBottomRight: TPoint;
function GetCanvas: TcxCanvasWrapper;
function GetClientRect: TRect;
function GetColHeaderHeight: Integer;
function GetDataStorage: TcxSSDataStorage;
function GetFloatDigits: Byte;
function GetFormulasCache: TcxSSFormulasCache;
function GetHeader(AType: TcxSSHeaderType): TcxSSHeader;
function GetLeftCol: Integer;
function GetMergeCellBorders(ACol, ARow: Integer): TcxSSEdgeBorders;
function GetRowHeaderWidth: Integer;
function GetRightCol: Integer;
function GetTopLeft: TPoint;
function GetTopRow: Integer;
procedure SetBottomRight(const Value: TPoint);
procedure SetBottomRow(const Value: Integer);
procedure SetInfoChanged(const Value: Boolean);
procedure SetLeftCol(const Value: Integer);
procedure SetRightCol(const Value: Integer);
procedure SetTopLeft(Value: TPoint);
procedure SetTopRow(const Value: Integer);
protected
function AddUnionBrick(ACol, ARow: Integer): Integer; virtual;
procedure CalculateViewInfo; virtual;
procedure CheckSelectionVisibility;
function ConvertCellRecToDisplayText(const ACellRec: TcxSSCellRec;
var AColor: Word): TcxString;
procedure InvalidateRect(ARect: TRect); virtual;
function GetCellIndexes(ACol, ARow: Integer; var AColPos, ARowPos: Integer): Boolean;
function GetCellsRectIndexes(const ASelRect: TRect): TRect;
function GetCellTextAlignment(const ACell: TcxSSCellRec): TcxHorzTextAlign;
procedure InvalidateBrick(AColPos, ARowPos: Integer); virtual;
procedure InvalidateCells; virtual;
procedure SetBrickInfo(AColPos, ARowPos: Integer); virtual;
property Canvas: TcxCanvasWrapper read GetCanvas;
property ClipRect: TRect read GetClientRect;
property DataStorage: TcxSSDataStorage read GetDataStorage;
property Headers[AType: TcxSSHeaderType]: TcxSSHeader read GetHeader;
property FormulasCache: TcxSSFormulasCache read GetFormulasCache;
property FloatDigits: Byte read GetFloatDigits;
public
constructor Create(AOwner: TObject); virtual;
procedure ClearBrickText(ACol, ARow: Integer);
function HitTest(X, Y: Integer; var ACol, ARow: Integer): TcxSSHitTestStates;
procedure UpdateCellInfo(const ACol, ARow: Integer);
procedure UpdateCellsInfo(const ACellRect: TRect);
procedure UpdateOnChangeSelection;
procedure UpdateOnCancelMode;
procedure UpdateOnResize;
procedure UpdateOnResizeColumn(const ACol: Integer);
procedure UpdateOnResizeRow(const ARow: Integer);
procedure UpdateViewInfo;
property BottomRight: TPoint read GetBottomRight write SetBottomRight;
property BottomRow: Integer read GetBottomRow write SetBottomRow;
property ColHeaderHeight: Integer read GetColHeaderHeight;
property InfoData: TcxSSViewInfoData read FInfoData;
property InfoChanged: Boolean read FInfoChanged write SetInfoChanged;
property LeftCol: Integer read GetLeftCol write SetLeftCol;
property Owner: TObject read FOwner;
property RightCol: Integer read GetRightCol write SetRightCol;
property RowHeaderWidth: Integer read GetRowHeaderWidth;
property TopLeft: TPoint read GetTopLeft write SetTopLeft;
property TopRow: Integer read GetTopRow write SetTopRow;
end;
implementation
uses
cxSSheet;
type
TcxDataStorageAccess = class(TcxSSDataStorage);
TcxHeaderAccess = class(TcxSSHeader);
TcxBookAccess = class(TcxCustomSpreadSheetBook);
TcxBookSubControlAccess = class(TcxWorkBookSubControl);
TcxSheetAccess = class(TcxSSBookSheet);
TcxListenerAccess = class(TcxSSListener);
{ TcxSSViewInfo }
constructor TcxSSheetViewInfo.Create(AOwner: TObject);
begin
FOwner := AOwner;
end;
procedure TcxSSheetViewInfo.ClearBrickText(ACol, ARow: Integer);
begin
with FInfoData do
begin
if not Bricks[ACol, ARow].IsMerge then
SetLength(Bricks[ACol, ARow].TextSettings.TextBricks, 0)
else
SetLength(UnionBricks[Bricks[ACol, ARow].UnionIndex].TextSettings.TextBricks, 0);
end;
InvalidateBrick(ACol, ARow)
end;
function TcxSSheetViewInfo.HitTest(X, Y: Integer; var ACol, ARow: Integer): TcxSSHitTestStates;
var
I, J: Integer;
begin
Result := [];
with FInfoData do
begin
X := TcxSSUtils.CheckValue(X, 0, ClipRect.Right);
Y := TcxSSUtils.CheckValue(Y, 0, ClipRect.Bottom);
for I := Length(Bricks) - 1 downto 0 do
if (X >= Bricks[I, 0].DisplayRect.Left) and (X < Bricks[I, 0].DisplayRect.Right) then
begin
for J := Length(Bricks[0]) - 1 downto 0 do
if (Y >= FInfoData.Bricks[0, J].DisplayRect.Top) and
(Y < FInfoData.Bricks[0, J].DisplayRect.Bottom) then
begin
ACol := I - 1;
ARow := J - 1;;
if (ACol >= 0) and (ARow >= 0)then
begin
ACol := FInfoData.Bricks[I, J].Col;
ARow := FInfoData.Bricks[I, J].Row;
Include(Result, htCell)
end
else
begin
if (ACol < 0) and (ARow < 0) then
Include(Result, htUpperLeft)
else
if ACol < 0 then
begin
Include(Result, htRowHeader);
ARow := Bricks[0, J].Row;
if (ARow > 0) and (((Y + 4) >= Bricks[0, J].DisplayRect.Top) and
((Y - 4) <= Bricks[0, J].DisplayRect.Top)) then
begin
Include(Result, htResize);
if ARow > 0 then Dec(ARow);
end;
while (ARow > 0) and not Headers[htRow].Visible[ARow] do Dec(ARow);
end
else
if ARow < 0 then
begin
Include(Result, htColHeader);
ACol := Bricks[I, 0].Col;
if (ACol > 0) and ((X + 4) > Bricks[I, 0].DisplayRect.Left) and
((X - 4) < Bricks[I, 0].DisplayRect.Left) then
begin
Include(Result, htResize);
Dec(ACol);
end;
while (ACol > 0) and not Headers[htCol].Visible[ACol] do Dec(ACol);
end;
end;
Break;
end;
if Result <> [] then Break;
end;
end;
end;
procedure TcxSSheetViewInfo.UpdateCellInfo(const ACol, ARow: Integer);
begin
CalculateViewInfo;
with FInfoData.DisplayRect do
InvalidateRect(Rect(RowHeaderWidth, ColHeaderHeight, Right, Bottom));
end;
procedure TcxSSheetViewInfo.UpdateCellsInfo(const ACellRect: TRect);
begin
UpdateViewInfo;
Exit;
end;
procedure TcxSSheetViewInfo.UpdateOnResize;
var
AOldRect, ARect: TRect;
begin
AOldRect := FInfoData.DisplayRect;
try
CalculateViewInfo;
finally
ARect := FInfoData.DisplayRect;
if not EqualRect(AOldRect, ARect) then
begin
if AOldRect.Right < ARect.Right then
begin
ARect.TopLeft := Point(AOldRect.Right, 0);
InflateRect(ARect, 2, 2);
InvalidateRect(ARect);
end;
end;
end;
end;
procedure TcxSSheetViewInfo.UpdateOnCancelMode;
var
I, J: Integer;
begin
for I := 0 to Length(FInfoData.Bricks) - 1 do
for J := 0 to Length(FInfoData.Bricks[0]) - 1 do
with FInfoData.Bricks[I, J] do
if IsSelected then
InvalidateRect(DisplayRect);
for I := 0 to Length(FInfoData.UnionBricks) - 1 do
with FInfoData.UnionBricks[I] do
if IsSelected then
InvalidateRect(DisplayRect);
with FInfoData.SelectedBricks do
if (Left >= 1) and (Left < Length(FInfoData.Bricks)) and
(Top >= 1) and (Top < Length(FInfoData.Bricks[0])) then
if FInfoData.Bricks[Left, Top].IsMerge then
InvalidateRect(FInfoData.UnionBricks[FInfoData.Bricks[Left, Top].UnionIndex].DisplayRect)
else
InvalidateRect(FInfoData.Bricks[Left, Top].DisplayRect);
CheckSelectionVisibility;
end;
procedure TcxSSheetViewInfo.UpdateOnResizeColumn(const ACol: Integer);
var
I, J, K: Integer;
R, ARect: TRect;
begin
K := 0;
if (Length(FInfoData.Bricks) = 0) or (Length(FInfoData.Bricks[0]) = 0) then Exit;
while (K < Length(FInfoData.Bricks)) and (FInfoData.Bricks[K, 0].Col < ACol) do Inc(K);
if K >= Length(FInfoData.Bricks) then Exit;
for I := 0 to Length(FInfoData.Bricks[K]) - 1 do
InvalidateBrick(K, I);
CalculateViewInfo;
K := 0;
while FInfoData.Bricks[K, 0].Col < ACol do Inc(K);
ARect.TopLeft := Point(FInfoData.Bricks[K, 0].DisplayRect.Left, 0);
ARect.BottomRight := FInfoData.DisplayRect.BottomRight;
for I := 0 to Length(FInfoData.Bricks[K]) - 1 do
InvalidateBrick(K, I);
InvalidateRect(ARect);
for I := 0 to K do
for J := 0 to Length(FInfoData.Bricks[I]) - 1 do
if IntersectRect(R, ARect, FInfoData.Bricks[I, J].TextRect) then
InvalidateBrick(I, J);
for I := 0 to Length(FInfoData.UnionBricks) - 1 do
if IntersectRect(R, FInfoData.UnionBricks[I].TextRect, ARect) then
InvalidateRect(FInfoData.UnionBricks[I].TextRect);
end;
procedure TcxSSheetViewInfo.UpdateOnResizeRow(const ARow: Integer);
var
K: Integer;
R, ARect: TRect;
begin
with FInfoData do
if (Length(Bricks) = 0) or (Length(Bricks[0]) = 0) then Exit;
CalculateViewInfo;
K := 0;
while (K < Length(FInfoData.Bricks[0])) and (FInfoData.Bricks[0, K].Row < ARow) do Inc(K);
if K >= Length(FInfoData.Bricks[0]) then Exit;
ARect.TopLeft := Point(0, FInfoData.Bricks[0, K].DisplayRect.Top);
ARect.BottomRight := FInfoData.DisplayRect.BottomRight;
InvalidateRect(ARect);
for K := 0 to Length(FInfoData.UnionBricks) - 1 do
if IntersectRect(R, FInfoData.UnionBricks[K].TextRect, ARect) then
InvalidateRect(FInfoData.UnionBricks[K].TextRect);
end;
procedure TcxSSheetViewInfo.UpdateViewInfo;
begin
try
CalculateViewInfo;
CheckSelectionVisibility;
finally
(FOwner as TcxSSBookSheet).Invalidate;
end;
end;
procedure TcxSSheetViewInfo.UpdateOnChangeSelection;
procedure UpdateBrickSelection(ABrickCol, ABrickRow: Integer; AIsSelected: Boolean);
var
K, L: Integer;
ARange: TRect;
begin
with FInfoData do
begin
if Bricks[ABrickCol, ABrickRow].IsMerge then
begin
with UnionBricks[Bricks[ABrickCol, ABrickRow].UnionIndex] do
begin
ARange := GetCellsRectIndexes(UnionRange);
for K := ARange.Left to ARange.Right do
for L := ARange.Top to ARange.Bottom do
if ((K > 0) and (K < Length(Bricks))) and
((L > 0) and (L < Length(Bricks[0]))) then
begin
FInfoData.Bricks[K, L].IsSelected := AIsSelected;
InvalidateRect(FInfoData.Bricks[K, L].DisplayRect);
end;
IsSelected := AIsSelected;
end;
end
else
begin
Bricks[ABrickCol, ABrickRow].IsSelected := AIsSelected;
InvalidateRect(Bricks[ABrickCol, ABrickRow].DisplayRect);
end;
end;
end;
var
AOldRect, ANewRect: TRect;
I, J: Integer;
ACol, ARow: Integer;
IsCurrent, IsColSelected, IsRowSelected: Boolean;
ASelected: Boolean;
begin
InfoChanged := True;
ANewRect := DataStorage.Selection;
AOldRect := FInfoData.Selection;
if EqualRect(AOldRect, ANewRect) then Exit;
FInfoData.Selection := ANewRect;
for I := 1 to Length(FInfoData.Bricks) - 1 do
begin
ACol := FInfoData.Bricks[I, 0].Col;
IsColSelected := (ACol >= ANewRect.Left) and (ACol <= ANewRect.Right);
if FInfoData.Bricks[I, 0].IsSelected <> IsColSelected then
begin
FInfoData.Bricks[I, 0].IsSelected := IsColSelected;
InvalidateRect(FInfoData.Bricks[I, 0].DisplayRect);
end;
for J := 1 to Length(FInfoData.Bricks[0]) - 1 do
begin
ARow := FInfoData.Bricks[0, J].Row;
IsRowSelected := (ARow >= ANewRect.Top) and (ARow <= ANewRect.Bottom);
if FInfoData.Bricks[0, J].IsSelected <> IsRowSelected then
begin
FInfoData.Bricks[0, J].IsSelected := IsRowSelected;
InvalidateRect(FInfoData.Bricks[0, J].DisplayRect);
end;
with FInfoData.Bricks[I, J] do
begin
IsCurrent := (ACol = ANewRect.Left) and (ARow = ANewRect.Top);
ASelected := IsColSelected and IsRowSelected and not IsCurrent;
with FInfoData.SelectedBricks do
if IsCurrent and ((I <> Left) or (J <> Top)) then
begin
UpdateBrickSelection(I, J, not IsCurrent);
if (Left >= 0) and (Left <= Length(FInfoData.Bricks)) and
(Top >= 0) and (Top <= Length(FinfoData.Bricks[0])) then
UpdateBrickSelection(Left, Top, FinfoData.Bricks[Left, Top].IsSelected);
end;
if (ASelected <> IsSelected) then
begin
if not FInfoData.Bricks[I, J].IsMerge then
UpdateBrickSelection(I, J, ASelected)
else
with FInfoData.UnionBricks[FInfoData.Bricks[I, J].UnionIndex] do
if (UnionRange.Top <> ANewRect.Top) or (UnionRange.Left <> ANewRect.Left) then
UpdateBrickSelection(I, J, ASelected);
end;
end;
end;
end;
FInfoData.SelectedBricks := GetCellsRectIndexes(FInfoData.Selection);
CheckSelectionVisibility;
end;
function TcxSSheetViewInfo.AddUnionBrick(ACol, ARow: Integer): Integer;
function IndexOfRect(const ARect: TRect): Integer;
var
I: Integer;
begin
Result := -1;
with FInfoData do
begin
for I := 0 to Length(UnionBricks) - 1 do
if EqualRect(UnionBricks[I].UnionRange, ARect) then
begin
Result := I;
Break;
end;
end;
end;
var
ARect: TRect;
ACellRec: TcxSSCellRec;
AHorzAlign: TcxHorzTextAlign;
AText: TcxString;
AColor: Word;
begin
Result := -1;
if not DataStorage.CheckInMergeRange(Point(ACol, ARow), ARect) then Exit;
Result := IndexOfRect(ARect);
begin
if Result = -1 then
begin
Result := Length(FInfoData.UnionBricks);
SetLength(FInfoData.UnionBricks, Result + 1);
with FInfoData.UnionBricks[Result] do
begin
ACellRec := DataStorage[ARect.Left, ARect.Top];
AColor := 0;
AText := ConvertCellRecToDisplayText(ACellRec, AColor);
IsSelected := (Int64(ARect.TopLeft) <> Int64(FInfoData.Selection.TopLeft)) and
(TcxSSUtils.PointInRect(FInfoData.Selection, ARect.TopLeft) and
TcxSSUtils.PointInRect(FInfoData.Selection, ARect.BottomRight));
DisplayRect := DataStorage.CellRect(FInfoData.Bricks[1, 0].Col,
FInfoData.Bricks[0, 1].Row, ACol, ARow, True);
UnionRange := ARect;
BrushStyle := ACellRec.StylePtr^.BrushStyle;
BrushBkColor := ACellRec.StylePtr^.BrushBkColor;
BrushFgColor := ACellRec.StylePtr^.BrushFgColor;
OffsetRect(DisplayRect, RowHeaderWidth, ColHeaderHeight);
TextRect := DisplayRect;
InflateRect(TextRect, -1, 0);
OffsetRect(TextRect, 0, 2);
Dec(TextRect.Right, 2);
Dec(TextRect.Bottom, 2);
AHorzALign := GetCellTextAlignment(ACellRec);
with ACellRec.StylePtr^ do
begin
if AColor = 0 then
TextSettings.FontColor := FontPtr^.FontColor
else
TextSettings.FontColor := AColor;
if (ACellRec.StylePtr^.FormatIndex <> $31) and cxTryStrToFloat(AText) then
AText := TcxSSUtils.FormatText(StrToFloat(AText),
ACellRec.StylePtr^.FormatIndex, FloatDigits, TextSettings.FontColor);
Canvas.SelectFont(FontPtr^.FontHandle);
Canvas.CalculateTextExtents(AText, TextRect, AHorzAlign, VertAlign,
WordBreak, TextSettings);
end;
if DisplayRect.Top < ColHeaderHeight then
begin
DisplayRect.Top := ColHeaderHeight;
TextRect.Top := ColHeaderHeight;
end;
if DisplayRect.Left < RowHeaderWidth then
begin
DisplayRect.Left := RowHeaderWidth;
TextRect.Left := RowHeaderWidth;
end;
Inc(TextRect.Right);
end;
end;
end;
end;
procedure TcxSSheetViewInfo.CalculateViewInfo;
procedure GetHeaderBrickInfo(var ABrick: TcxSSInfoBrick; ACol, ARow: Integer;
const ADisplayRect: TRect; const ADisplayText: TcxString; IsColHeader: Boolean = True);
begin
with ABrick do
begin
Col := ACol;
Row := ARow;
DisplayRect := ADisplayRect;
Canvas.SetSingleText(ADisplayText, ADisplayRect, TextSettings, IsColHeader);
Inc(TextSettings.TextBricks[0].YPos, 2);
TextSettings.FontColor := $FFFF;
with FInfoData.Selection do
if IsColHeader then
IsSelected := (ACol >= Left) and (ACol <= Right)
else
IsSelected := (ARow >= Top) and (ARow <= Bottom);
end;
end;
function GetItemsCount(AFrom, ASize: Integer; AType: TcxSSHeaderType): Integer;
var
AItem, AItemsSize, AItemSize: Integer;
AHeader: TcxSSHeader;
begin
AHeader := Headers[AType];
Result := 0;
AItem := AFrom;
AItemsSize := 0;
while ASize > AItemsSize do
begin
AItemSize := AHeader[AItem];
if AItemSize > 0 then Inc(Result);
Inc(AItemsSize, AItemSize);
Inc(AItem);
end;
end;
procedure CheckTextExtentAndCorrectBorders(ARow: Integer);
procedure ClearBorder(J: Integer);
begin
FInfoData.Bricks[J, ARow].Edges[eLeft].Style := lsNone;
if (J - 1) > 0 then
FInfoData.Bricks[J - 1, ARow].Edges[eRight].Style := lsNone;
end;
function BrickIsEmpty(J: Integer): Boolean;
begin
with FInfoData.Bricks[J, ARow] do
Result := (Length(TextSettings.TextBricks) = 0) and (not IsMerge);
end;
var
I, J: Integer;
begin
for I := Length(FInfoData.Bricks) - 1 downto 1 do
with FInfoData.Bricks[I, ARow] do
if not IsMerge and not BrickIsEmpty(I) and not TextSettings.WordBreak then
begin
if TextRect.Left < DisplayRect.Left then
for J := I - 1 downto 1 do
if BrickIsEmpty(J) then
begin
ClearBorder(J + 1);
if TextRect.Left > FInfoData.Bricks[J, ARow].DisplayRect.Left then
Break;
end
else
begin
TextRect.Left := FInfoData.Bricks[J, ARow].DisplayRect.Right + 2;
Break;
end;
if TextRect.Left < FInfoData.Bricks[0, ARow].DisplayRect.Right then
TextRect.Left := FInfoData.Bricks[0, ARow].DisplayRect.Right;
if TextRect.Right > DisplayRect.Right then
for J := I + 1 to Length(FInfoData.Bricks) - 1 do
if BrickIsEmpty(J) then
begin
ClearBorder(J);
if TextRect.Right < FInfoData.Bricks[J, ARow].DisplayRect.Right then
Break;
end
else
begin
TextRect.Right := FInfoData.Bricks[J, ARow].DisplayRect.Left - 2;
Break;
end;
end;
end;
procedure CorrectBordersAndDisplayRect(AColPos, ARowPos: Integer);
var
ATopLeft, ALeftTop: PcxEdgeVertex;
ASide: TcxSSEdgeBorder;
const
cxHalfWidth: array[TcxSSEdgeLineStyle] of Byte =
(1, 1, 2, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 0);
DxDy: array[Boolean] of Byte = (1, 2);
begin
with FInfoData.Bricks[AColPos, ARowPos] do
begin
if (ARowPos > 1) and
(FInfoData.Bricks[AColPos, ARowPos - 1].Edges[eLeft].Style = lsDouble) then
ATopLeft := @FInfoData.Bricks[AColPos, ARowPos - 1].LeftEdgeVertex
else
ATopLeft := nil;
if (AColPos > 1) and
(FInfoData.Bricks[AColPos - 1, ARowPos].Edges[eTop].Style = lsDouble) then
ALeftTop := @FInfoData.Bricks[AColPos - 1, ARowPos].TopEdgeVertex
else
ALeftTop := nil;
for ASide := eLeft to eBottom do
if Edges[ASide].Style <> lsNone then
begin
if ASide in [eLeft, eTop] then
Inc(PIntArray(@DisplayRect)^[Byte(ASide)],
cxHalfWidth[Edges[ASide].Style])
else
Dec(PIntArray(@DisplayRect)^[Byte(ASide)],
DxDy[cxLineWidth[Edges[ASide].Style] = 3]);
end;
if Edges[eTop].Style = lsDouble then
begin
if Edges[eLeft].Style = lsDouble then
begin
Inc(TopEdgeVertex[2].Left);
Inc(LeftEdgeVertex[2].Top);
if ATopLeft = ALeftTop then
begin
Dec(TopEdgeVertex[0].Left);
Dec(LeftEdgeVertex[0].Top);
end
else
if ATopLeft <> nil then
begin
Inc(TopEdgeVertex[0].Left);
Dec(ATopLeft^[2].Bottom);
end
end
else
begin
if ATopLeft <> ALeftTop then
begin
Inc(TopEdgeVertex[0].Left);
if ATopLeft <> nil then
begin
Dec(TopEdgeVertex[2].Left);
Inc(ATopLeft[0].Bottom);
end;
end;
end;
end;
if Edges[eLeft].Style = lsDouble then
begin
if ALeftTop <> nil then
begin
Inc(LeftEdgeVertex[0].Top);
if (Edges[eTop].Style <> lsDouble) and (ATopLeft = nil) then
begin
Inc(ALeftTop^[0].Right);
Dec(LeftEdgeVertex[2].Top);
end;
end
end
else
if (ALeftTop <> nil) and (ATopLeft <> nil) and
(Edges[eTop].Style <> lsDouble) then
begin
Inc(ALeftTop^[2].Right);
Inc(ATopLeft^[2].Bottom, 2);
end;
if Edges[eTop].Style = lsThick then
begin
Dec(TopEdgeVertex[0].Left);
Inc(TopEdgeVertex[0].Right, 2);
end;
if Edges[eLeft].Style = lsThick then
begin
Dec(LeftEdgeVertex[0].Top);
Inc(LeftEdgeVertex[0].Bottom, 2);
end
end;
end;
var
I, J, K: Integer;
ASize: TcxSSSize;
ATop, ALeft: Integer;
ARowCount, AColCount: Integer;
AColHeaderHeight: Integer;
ARowHeaderWidth: Integer;
ARange: TRect;
begin
InfoChanged := True;
if not TcxSheetAccess(Owner).Owner.HandleAllocated then Exit;
CheckSelectionVisibility;
Canvas.BeginPaint(TcxSheetAccess(Owner).ControlCanvas);
FShowFormulas := TcxSheetAccess(Owner).ShowFormulas;
FInfoData.DisplayRect := ClipRect;
AColHeaderHeight := ColHeaderHeight;
ARowHeaderWidth := RowHeaderWidth;
FDrawGrid := TcxSheetAccess(Owner).ShowGrid;
AColCount := GetItemsCount(FInfoData.Bounds.Left,
ClipRect.Right - ARowHeaderWidth, htCol) + 2;
ARowCount := GetItemsCount(FInfoData.Bounds.Top,
ClipRect.Bottom - AColHeaderHeight, htRow) + 2;
SetLength(FInfoData.UnionBricks, 0);
SetLength(FInfoData.Bricks, AColCount, ARowCount);
FInfoData.Selection := DataStorage.Selection;
FInfoData.DrawHeaders := TcxSheetAccess(Owner).ShowHeaders;
I := 1;
J := FInfoData.Bounds.Top;
ATop := AColHeaderHeight;
with TcxBookAccess(TcxBookSubControlAccess(Owner).Owner) do
begin
FInfoData.HeaderColor := Canvas.GetNativeColor(HeaderColor);
FInfoData.HeaderFontColor := Canvas.GetNativeColor(HeaderFont.Color);
Canvas.SelectFont(HeaderFont);
end;
while I < ARowCount do
begin
ASize := Headers[htRow][J];
Inc(J);
if ASize > 0 then
begin
GetHeaderBrickInfo(FInfoData.Bricks[0, I], 0, J - 1,
Rect(0, ATop, ARowHeaderWidth, ATop + ASize), IntToStr(J), False);
Inc(ATop, ASize);
Inc(I);
end;
end;
I := 1;
J := FInfoData.Bounds.Left;
ALeft := ARowHeaderWidth;
while I < AColCount do
begin
ASize := Headers[htCol][J];
Inc(J);
if ASize > 0 then
begin
GetHeaderBrickInfo(FInfoData.Bricks[I, 0], J - 1, 0,
Rect(ALeft, 0, ALeft + ASize, AColHeaderHeight),
TcxSSUtils.ColumnNameByIndex(J - 1,
TcxSheetAccess(Owner).Owner.R1C1ReferenceStyle));
Inc(ALeft, ASize);
Inc(I);
end;
end;
FInfoData.Bounds.BottomRight := Point(AColCount, ARowCount);
GetHeaderBrickInfo(FInfoData.Bricks[0, 0], -1, -1,
Rect(0, 0, ARowHeaderWidth, AColHeaderHeight), '');
for I := 1 to ARowCount - 1 do
begin
for J := 1 to AColCount - 1 do SetBrickInfo(J, I);
CheckTextExtentAndCorrectBorders(I);
end;
for I := 0 to Length(FInfoData.UnionBricks) - 1 do
begin
with FInfoData.UnionBricks[I] do
begin
ARange := GetCellsRectIndexes(UnionRange);
for J := ARange.Left to ARange.Right do
for K := ARange.Top to ARange.Bottom do
if ((J >= 1) and (J < Length(FInfoData.Bricks))) and
((K >= 1) and (K < Length(FInfoData.Bricks[0]))) then
with FInfoData.Bricks[J, K] do
begin
if J > ARange.Left then Edges[eLeft].Style := lsNone;
if J < ARange.Right then Edges[eRight].Style := lsNone;
if K > ARange.Top then Edges[eTop].Style := lsNone;
if K < ARange.Bottom then Edges[eBottom].Style := lsNone;
end;
end;
end;
for I := 1 to AColCount - 1 do
for J := 1 to ARowCount - 1 do CorrectBordersAndDisplayRect(I, J);
FInfoData.SelectedBricks := GetCellsRectIndexes(FInfoData.Selection);
TcxSheetAccess(Owner).InitScrollBars;
CheckSelectionVisibility;
end;
procedure TcxSSheetViewInfo.CheckSelectionVisibility;
var
R: TRect;
begin
with InfoData do
begin
R := DataStorage.Selection;
IsSelectionVisible := (R.Left <= (RightCol + 1)) and (R.Right >= LeftCol) and
(R.Top <= (BottomRow + 1)) and (R.Bottom >= TopRow);
end;
end;
function TcxSSheetViewInfo.ConvertCellRecToDisplayText(
const ACellRec: TcxSSCellRec; var AColor: Word): TcxString;
var
AValue: Double;
begin
AValue := 0;
case ACellRec.DataType of
dtFunction:
Result := FormulasCache.FuncRecToDisplayText(ACellRec.FuncRecPtr, AColor);
dtDateTime:
Result := TcxSSUtils.FormatText(ACellRec.DateTime,
ACellRec.StylePtr^.FormatIndex, FloatDigits, AColor);
else
if (ACellRec.StylePtr^.FormatIndex <> $31) and cxTryStrToFloat(ACellRec.Text, AValue) then
Result := TcxSSUtils.FormatText(AValue, ACellRec.StylePtr^.FormatIndex,
FloatDigits, AColor)
else
Result := ACellRec.Text;
end;
end;
function TcxSSheetViewInfo.GetCellIndexes(ACol, ARow: Integer;
var AColPos, ARowPos: Integer): Boolean;
var
I: Integer;
begin
I := 1;
while (I < Length(FInfoData.Bricks)) and (FInfoData.Bricks[I, 0].Col < ACol) do Inc(I);
Result := (I < Length(FInfoData.Bricks)) and (FInfoData.Bricks[I, 0].Col >= ACol);
if Result then
AColPos := I
else
AColPos := -1;
I := 1;
while (I < Length(FInfoData.Bricks[0])) and (FInfoData.Bricks[0, I].Row < ARow) do Inc(I);
if (I < Length(FInfoData.Bricks[0])) and (FInfoData.Bricks[0, I].Row >= ARow) then
ARowPos := I
else
ARowPos := -1;
Result := Result or (ARowPos <> -1);
end;
procedure TcxSSheetViewInfo.InvalidateRect(ARect: TRect);
begin
InflateRect(ARect, 5, 5);
TcxBookSubControlAccess(FOwner).InvalidateRect(ARect);
end;
function TcxSSheetViewInfo.GetCellsRectIndexes(const ASelRect: TRect): TRect;
var
I: Integer;
ARect: TRect;
begin
Result := Rect(-1, -1, -1, -1);
if Length(FInfoData.Bricks) = 0 then Exit;
with FInfoData do
ARect := Rect(Bricks[1, 1].Col, Bricks[1, 1].Row,
Bricks[Length(Bricks) - 1, 1].Col, Bricks[1, Length(Bricks[0]) - 1].Row);
if (ASelRect.Left >= ARect.Left) and (ASelRect.Left <= ARect.Right) then
for I := 1 to Length(FInfoData.Bricks) - 1 do
if FInfoData.Bricks[I, 0].Col > ASelRect.Left then
begin
if (Result.Left >=0) and (FInfoData.Bricks[Result.Left, 0].Col <> ASelRect.Left) then
Result.Left := I;
Break;
end
else
Result.Left := I;
if (ASelRect.Right >= ARect.Left) and (ASelRect.Right <= ARect.Right) then
for I := 1 to Length(FInfoData.Bricks) - 1 do
if FInfoData.Bricks[I, 0].Col > ASelRect.Right then
Break
else
Result.Right := I;
if (ASelRect.Top >= ARect.Top) and (ASelRect.Top <= ARect.Bottom) then
for I := 1 to Length(FInfoData.Bricks[0]) - 1 do
if FInfoData.Bricks[0, I].Row > ASelRect.Top then
begin
if FInfoData.Bricks[0, Result.Top].Row <> ASelRect.Top then
Result.Top := I;
Break;
end
else
Result.Top := I;
if (ASelRect.Bottom >= ARect.Top) and (ASelRect.Bottom <= ARect.Bottom) then
for I := 1 to Length(FInfoData.Bricks[0]) - 1 do
if FInfoData.Bricks[0, I].Row > ASelRect.Bottom then
Break
else
Result.Bottom := I;
if (Result.Left >= 0) and (Result.Right < 0) then
Result.Right := Length(FInfoData.Bricks) - 1;
if (Result.Top >= 0) and (Result.Bottom < 0) then
Result.Bottom := Length(FInfoData.Bricks[0]) - 1;
end;
function TcxSSheetViewInfo.GetCellTextAlignment(
const ACell: TcxSSCellRec): TcxHorzTextAlign;
var
S: string;
C: Word;
begin
with ACell do
begin
Result := ACell.StylePtr^.HorzAlign;
if Result = haGeneral then
begin
if DataType = dtFunction then
S := FormulasCache.FuncRecToDisplayText(ACell.FuncRecPtr, C, False)
else
S := Text;
Result := haLeft;
if StylePtr^.FormatIndex <> $31 then
begin
if cxTryStrToFloat(S) then
Result := haRight
else
if cxTryStrToBool(S) then
Result := haCenter
end;
end;
end;
end;
procedure TcxSSheetViewInfo.InvalidateBrick(AColPos, ARowPos: Integer);
var
ARect, ARect1: TRect;
begin
if (AColPos < 0) or (ARowPos < 0) then Exit;
ARect := FInfoData.Bricks[AColPos, ARowPos].DisplayRect;
ARect1 := FInfoData.Bricks[AColPos, ARowPos].TextRect;
UnionRect(ARect, ARect1, ARect);
InflateRect(ARect, 3, 3);
InvalidateRect(ARect);
end;
procedure TcxSSheetViewInfo.InvalidateCells;
var
ARect: TRect;
begin
ARect.TopLeft := FInfoData.Bricks[0, 0].DisplayRect.BottomRight;
ARect.BottomRight := ClipRect.BottomRight;
InflateRect(ARect, 3, 3);
InvalidateRect(ARect);
end;
procedure TcxSSheetViewInfo.SetBrickInfo(AColPos, ARowPos: Integer);
var
AColor: Word;
ACell: TcxSSCellRec;
AStyle: PcxSSCellStyleRec;
ABorderState: TcxSSEdgeBorders;
AHorzAlign: TcxHorzTextAlign;
AText: TcxString;
AWidth: Integer;
ASide: TcxSSEdgeBorder;
procedure SetEdgeVertex(const ARect: TRect; var AStyle: TcxSSEdgeLineStyle;
var AVertex: TcxEdgeVertex; AOrient: TcxOrientation);
var
I: Byte;
const
AOfs: array[TcxOrientation, 0..1] of Byte = ((0, 1), (1, 0));
begin
if (AStyle = lsDefault) and not FDrawGrid then
AStyle := lsNone;
if AStyle = lsNone then Exit;
with ARect do
if AOrient = oHorz then
AVertex[0] := Rect(Left, Top, Right - 1, Top)
else
AVertex[0] := Rect(Left, Top, Left, Bottom - 1);
if cxLineWidth[AStyle] = 3 then
OffsetRect(AVertex[0], -AOfs[AOrient, 0], -AOfs[AOrient, 1]);
if AStyle = lsDouble then
for I := 1 to 2 do
begin
AVertex[I] := AVertex[0];
OffsetRect(AVertex[I], AOfs[AOrient, 0] * I, AOfs[AOrient, 1] * I);
end
else
begin
if AOrient = oHorz then
Inc(AVertex[0].Bottom, cxLineWidth[AStyle] - 1)
else
Inc(AVertex[0].Right, cxLineWidth[AStyle] - 1);
end;
end;
begin
with FInfoData.Bricks[AColPos, ARowPos] do
begin
Col := FInfoData.Bricks[AColPos, 0].Col;
Row := FInfoData.Bricks[0, ARowPos].Row;
ACell := DataStorage[Col, Row];
AStyle := ACell.StylePtr;
with FInfoData.Bricks[AColPos, 0].DisplayRect do
begin
DisplayRect.Left := Left;
DisplayRect.Right := Right;
end;
with FInfoData.Bricks[0, ARowPos].DisplayRect do
begin
DisplayRect.Top := Top;
DisplayRect.Bottom := Bottom;
end;
BrushStyle := AStyle^.BrushStyle;
BrushBkColor := AStyle^.BrushBkColor;
BrushFgColor := AStyle^.BrushFgColor;
for ASide := eLeft to eBottom do
begin
if ASide = eRight then
Edges[ASide].Style := DataStorage[Col + 1, Row].StylePtr^.Borders[eLeft].Style
else
if ASide = eBottom then
Edges[ASide].Style := DataStorage[Col, Row + 1].StylePtr^.Borders[eTop].Style
else
Edges[ASide].Style := AStyle^.Borders[ASide].Style;
if (Edges[ASide].Style = lsDefault) and (not FDrawGrid) then
Edges[ASide].Style := lsNone;
Edges[ASide].Color := AStyle^.Borders[ASide].Color;
end;
IsMerge := cMerge in AStyle^.CellState;
if not IsMerge then
begin
with FInfoData.Selection do
IsSelected := (not ((Col = Left) and (Row = Top))) and (Col >= Left) and
(Col <= Right) and (Row >= Top) and (Row <= Bottom);
AColor := 0;
AText := ConvertCellRecToDisplayText(ACell, AColor);
TextRect := DisplayRect;
InflateRect(TextRect, -2, 0);
OffsetRect(TextRect, 0, 2);
Dec(TextRect.Bottom, 2);
if AText <> '' then
begin
Canvas.SelectFont(AStyle^.FontPtr^.FontHandle);
if AColor = 0 then
TextSettings.FontColor := AStyle^.FontPtr^.FontColor
else
TextSettings.FontColor := AColor;
AHorzAlign := GetCellTextAlignment(ACell);
if not AStyle^.WordBreak then
begin
AWidth := Canvas.TextWidth(AText) - (TextRect.Right - TextRect.Left) + 4;
if AWidth > 0 then
begin
case AHorzAlign of
haLeft:
Inc(TextRect.Right, AWidth);
haRight:
Dec(TextRect.Left, AWidth);
haCenter:
begin
Dec(TextRect.Left, AWidth shr 1);
Inc(TextRect.Right, AWidth shr 1);
end;
end;
end;
end;
Canvas.CalculateTextExtents(AText, TextRect, AHorzAlign,
AStyle.VertAlign, AStyle.WordBreak, TextSettings);
end
else
SetLength(TextSettings.TextBricks, 0);
end;
if IsMerge then
begin
ABorderState := GetMergeCellBorders(Col, Row);
UnionIndex := AddUnionBrick(Col, Row);
if UnionIndex >= 0 then
begin
BrushStyle := FInfoData.UnionBricks[UnionIndex].BrushStyle;
BrushBkColor := FInfoData.UnionBricks[UnionIndex].BrushBkColor;
BrushFgColor := FInfoData.UnionBricks[UnionIndex].BrushFgColor;
IsSelected := FInfoData.UnionBricks[UnionIndex].IsSelected;
end;
end
else
ABorderState := [eLeft, eTop];
SetEdgeVertex(DisplayRect, Edges[eTop].Style, TopEdgeVertex, oHorz);
SetEdgeVertex(DisplayRect, Edges[eLeft].Style, LeftEdgeVertex, oVert);
end;
end;
function TcxSSheetViewInfo.GetBottomRow: Integer;
begin
Result := GetBottomRight.Y;
end;
function TcxSSheetViewInfo.GetBottomRight: TPoint;
procedure GetLastVisible(AHeader: TcxSSHeader; ALen: Integer; var AIndex: Integer);
var
ACalcLen: Integer;
begin
ACalcLen := 0;
while ACalcLen < ALen do
begin
ACalcLen := ACalcLen + AHeader.Size[AIndex];
if ACalcLen <= ALen then
Inc(AIndex);
end;
Dec(AIndex);
while not AHeader.Visible[AIndex] do Dec(AIndex);
end;
var
ARect: TRect;
ASize: Integer;
begin
ARect := ClipRect;
Result := FInfoData.Bounds.TopLeft;
ASize := ARect.Right - ARect.Left - RowHeaderWidth;
GetLastVisible(Headers[htCol], ASize, Result.X);
ASize := ARect.Bottom - ARect.Top - ColHeaderHeight;
GetLastVisible(Headers[htRow], ASize, Result.Y);
end;
function TcxSSheetViewInfo.GetCanvas: TcxCanvasWrapper;
begin
Result := TcxBookSubControlAccess(Owner).Canvas;
end;
function TcxSSheetViewInfo.GetClientRect: TRect;
begin
with TcxBookAccess(TcxBookSubControlAccess(Owner).Owner) do
begin
Result := ClientBounds;
if (CaptionBar <> nil) and TcxBookSubControlAccess(CaptionBar).Visible then
Result.Bottom := TcxBookSubControlAccess(CaptionBar).Top;
end;
end;
function TcxSSheetViewInfo.GetColHeaderHeight: Integer;
begin
if TcxSheetAccess(Owner).ShowHeaders then
Result := TcxBookAccess(TcxSheetAccess(Owner).Owner).ColHeaderHeight
else
Result := 0;
end;
function TcxSSheetViewInfo.GetDataStorage: TcxSSDataStorage;
begin
Result := TcxSheetAccess(Owner).DataStorage;
end;
function TcxSSheetViewInfo.GetFloatDigits: Byte;
begin
Result := TcxBookAccess(TcxSheetAccess(Owner).Owner).Precision;
end;
function TcxSSheetViewInfo.GetFormulasCache: TcxSSFormulasCache;
begin
Result := TcxBookAccess(TcxSheetAccess(Owner).Owner).FormulasCache;
end;
function TcxSSheetViewInfo.GetHeader(AType: TcxSSHeaderType): TcxSSHeader;
begin
Result := DataStorage.Headers[AType];
end;
function TcxSSheetViewInfo.GetLeftCol: Integer;
begin
Result := TopLeft.X;
end;
function TcxSSheetViewInfo.GetMergeCellBorders(ACol, ARow: Integer): TcxSSEdgeBorders;
var
ARect: TRect;
begin
Result := [];
if DataStorage.CheckInMergeRange(Point(ACol, ARow), ARect) then
begin
if ACol = ARect.Left then Include(Result, eLeft);
if ARow = ARect.Top then Include(Result, eTop);
end;
end;
function TcxSSheetViewInfo.GetRowHeaderWidth: Integer;
begin
with TcxBookAccess(TcxSheetAccess(Owner).Owner) do
if ShowHeaders then
Result := RowHeaderWidth
else
Result := 0;
end;
function TcxSSheetViewInfo.GetTopLeft: TPoint;
begin
Result := FInfoData.Bounds.TopLeft;
end;
function TcxSSheetViewInfo.GetTopRow: Integer;
begin
Result := GetTopLeft.Y;
end;
function TcxSSheetViewInfo.GetRightCol: Integer;
begin
Result := GetBottomRight.X;
end;
procedure TcxSSheetViewInfo.SetBottomRight(const Value: TPoint);
function CalculateTopLeft: TPoint;
var
ARect: TRect;
ASize: Integer;
begin
Result := Value;
ARect := ClipRect;
ASize := ARect.Right - ARect.Left - RowHeaderWidth;
Result.X := Result.X +
TcxHeaderAccess(DataStorage.Headers[htCol]).GetCountItems(Result.X, ASize, False) + 1;
ASize := ARect.Bottom - ARect.Top - ColHeaderHeight;
Result.Y := Result.Y +
TcxHeaderAccess(DataStorage.Headers[htRow]).GetCountItems(Result.Y, ASize, False) + 1;
end;
begin
SetTopLeft(CalculateTopLeft);
end;
procedure TcxSSheetViewInfo.SetBottomRow(const Value: Integer);
begin
SetBottomRight(Point(GetBottomRight.X, Value));
end;
procedure TcxSSheetViewInfo.SetInfoChanged(const Value: Boolean);
begin
if FInfoChanged <> Value then
begin
FInfoChanged := Value;
if Value then
if TcxSheetAccess(Owner).Owner.BufferedPaint then
TcxSheetAccess(Owner).Invalidate;
end;
end;
procedure TcxSSheetViewInfo.SetLeftCol(const Value: Integer);
begin
SetTopLeft(Point(Value, TopRow));
end;
procedure TcxSSheetViewInfo.SetRightCol(const Value: Integer);
begin
SetBottomRight(Point(Value, GetBottomRight.Y));
end;
procedure TcxSSheetViewInfo.SetTopLeft(Value: TPoint);
function CheckValue: Boolean;
begin
with FInfoData.Bounds do
Result := (Left = Value.X) and (Top = Value.Y);
if not Result then
begin
if Value.Y < 0 then Value.Y := 0;
if Value.X < 0 then Value.X := 0;
end;
end;
var
AListener: TcxListenerAccess;
begin
if CheckValue then Exit;
AListener := TcxListenerAccess(TcxBookAccess(TcxSheetAccess(Owner).Owner).Listener);
AListener.OnTopLeftChanging(TcxSSBookSheet(Owner), Value);
if not CheckValue then
begin
FInfoData.Bounds.TopLeft := Value;
CalculateViewInfo;
TcxSheetAccess(FOwner).Invalidate;
end;
end;
procedure TcxSSheetViewInfo.SetTopRow(const Value: Integer);
begin
SetTopLeft(Point(LeftCol, Value));
end;
end.