{*******************************************************************} { } { Developer Express Visual Component Library } { ExpressPrinting System(tm) COMPONENT SUITE } { } { Copyright (C) 1998-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 EXPRESSPRINTINGSYSTEM AND } { ALL ACCOMPANYING VCL 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 dxPScxSSLnk; interface {$I cxVer.inc} {$IFDEF CBUILDER5} (*$HPPEMIT '#define HRGN unsigned'*) {$ELSE} (*$HPPEMIT '#define HRGN int'*) {$ENDIF} uses Windows, Classes, Graphics, Controls, StdCtrls, ExtCtrls, ComCtrls, Dialogs, cxSSTypes, cxSSData, cxSSStyles, cxSSheet, cxExcelConst, dxPSCore, dxPSForm, dxPSGlbl, dxPSBaseGridLnk, dxPSExcelEdgePatterns, dxPSExcelFillPatterns, dxPSEdgePatterns, dxPSFillPatterns, cxDrawTextUtils; type PdxPSCellBorder = ^TdxPSCellBorder; TdxPSCellBorder = record Color: TColor; Pattern: TdxPSEdgePatternClass; end; PdxPSCellBorders = ^TdxPSCellBorders; TdxPSCellBorders = array[TdxCellSide] of TdxPSCellBorder; TdxPSCellBorderCorner = (cbcTopLeft, cbcTopRight, cbcBottomRight, cbcBottomLeft); TdxPSCellBorderCorners = set of TdxPSCellBorderCorner; TdxPSCellBorderEnd = (cbsTopLeft, cbsBottomRight); TdxPSCellBorderEnds = set of TdxPSCellBorderEnd; TdxPSCellBorderSub = 0..3; TdxPSCellCorner = (ccTopLeft, ccTopRight, ccBottomRight, ccBottomLeft); TdxPSCellPatternsBorderPainter = class; TdxPSGridCellsAdapter = class; TdxReportCellSSString = class(TdxReportCellString) private FBorders: TdxPSCellBorders; FBorderSlants: DWORD; FBorderSubs: DWORD; FContentBkColor: TColor; FContentPattern: TdxPSFillPatternClass; FRealCol: Integer; FRealRow: Integer; FTextExtentLeft: Integer; FTextExtentRight: Integer; function GetBorder(ASide: TdxCellSide): TdxPSCellBorder; function GetBordersBkColor: TColor; function GetBorderSlant(ASide: TdxCellSide; ACorner: TdxPSCellBorderCorner): Integer; function GetBorderSlantOffset(ASide: TdxCellSide; ACorner: TdxPSCellBorderCorner): TDWORDBits; function GetBorderSub(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd): TdxPSCellBorderSub; function GetBorderSubMask(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd): DWORD; function GetBorderSubOffset(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd): TDWORDBits; function GetClipContent: Boolean; function GetCol: Integer; function GetFill: Boolean; function GetIsFixed: Boolean; function GetIsMerged: Boolean; function GetIsNearMostLeft: Boolean; function GetIsNearMostTop: Boolean; function GetIsNearMostTopOrLeft: Boolean; function GetIsVirtual: Boolean; function GetRow: Integer; procedure SetBorder(ASide: TdxCellSide; Value: TdxPSCellBorder); procedure SetBorderSlant(ASide: TdxCellSide; ACorner: TdxPSCellBorderCorner; Value: Integer); procedure SetBorderSub(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd; Value: TdxPSCellBorderSub); procedure SetClipConent(Value: Boolean); procedure SetFill(Value: Boolean); procedure SetIsFixed(Value: Boolean); procedure SetIsMerged(Value: Boolean); procedure SetIsNearMostLeft(Value: Boolean); procedure SetIsNearMostTop(Value: Boolean); procedure SetIsVirtual(Value: Boolean); protected procedure CalcBorderSubs(AnAdapter: TdxPSGridCellsAdapter); procedure CalcDoubleBorderSlants(AnAdapter: TdxPSGridCellsAdapter); procedure ConvertCoords(APixelsNumerator, APixelsDenominator: Integer); override; function GetBackgroundBounds(DC: HDC): TRect; override; function GetBorderEdgeBounds(ASide: TdxCellSide; const AOuterRect: TRect): TRect; override; function GetBorderBrush(ASide: TdxCellSide): HBRUSH; function GetBorderEdgeClass(ASide: TdxCellSide): TdxPSCellBorderClass; override; function GetEffectiveBounds(DC: HDC; AStage: TdxPSRenderStages): TRect; override; function GetTextBounds(DC: HDC): TRect; override; function IsDrawn(DC: HDC; AStage: TdxPSRenderStages; const ARect: TRect): Boolean; override; function GetBorderPainterClass: TdxPSCellBorderPainterClass; override; procedure InitBorderPainter(ABordersPainter: TdxPSCellBorderPainter); override; function GetContentBkColor: TColor; override; function GetContentPattern: TdxPSFillPatternClass; override; procedure SetContentBkColor(Value: TColor); override; procedure SetContentPattern(Value: TdxPSFillPatternClass); override; procedure ReadBorders(AReader: TdxPSDataReader); procedure ReadData(AReader: TdxPSDataReader); override; procedure WriteBorders(AWriter: TdxPSDataWriter); procedure WriteData(AWriter: TdxPSDataWriter); override; function GetAbsoluteInnerBounds(DC: HDC): TRect; function GetDoubleBorderRgn(ASide: TdxCellSide; const R: TRect): HRGN; function IsDoubleLineBorderPattern(ABorder: TdxPSCellBorder): Boolean; overload; function IsDoubleLineBorderPattern(ASide: TdxCellSide): Boolean; overload; function NullBorder: TdxPSCellBorder; public constructor Create(AParent: TdxReportCell); override; procedure Assign(Source: TPersistent); override; procedure SetBorders(AColor: TColor; APattern: TdxPSEdgePatternClass); procedure DrawContent(DC: HDC; AStage: TdxPSRenderStages); override; property Borders[ASide: TdxCellSide]: TdxPSCellBorder read GetBorder write SetBorder; property BordersBkColor: TColor read GetBordersBkColor; property BorderSlants[ASide: TdxCellSide; ACorner: TdxPSCellBorderCorner]: Integer read GetBorderSlant write SetBorderSlant; property BorderSubs[ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd]: TdxPSCellBorderSub read GetBorderSub write SetBorderSub; property ClipContent: Boolean read GetClipContent write SetClipConent; property Col: Integer read GetCol; property Fill: Boolean read GetFill write SetFill; property IsFixed: Boolean read GetIsFixed write SetIsFixed; property IsMerged: Boolean read GetIsMerged write SetIsMerged; property IsNearMostLeft: Boolean read GetIsNearMostLeft write SetIsNearMostLeft; property IsNearMostTop: Boolean read GetIsNearMostTop write SetIsNearMostTop; property IsNearMostTopOrLeft: Boolean read GetIsNearMostTopOrLeft; property IsVirtual: Boolean read GetIsVirtual write SetIsVirtual; property RealCol: Integer read FRealCol write FRealCol; property RealRow: Integer read FRealRow write FRealRow; property Row: Integer read GetRow; property TextExtentLeft: Integer read FTextExtentLeft write FTextExtentLeft; property TextExtentRight: Integer read FTextExtentRight write FTextExtentRight; end; TdxPSCellPatternsBorderPainter = class(TdxPSCellBorderPainter) private FGridAdapter: TdxPSGridCellsAdapter; protected function ClipItemBounds(DC: HDC; AOuterRect: TRect): HRGN; procedure DrawBorder(DC: HDC; const R: TRect; AForeColor, ABkColor: TColor; ABrush: HBRUSH); overload; procedure DrawBorder(DC: HDC; ABorderRgn: HRGN; AForeColor, ABkColor: TColor; ABrush: HBRUSH); overload; public function Item: TdxReportCellSSString; reintroduce; overload; procedure Paint(DC: HDC); override; property GridAdapter: TdxPSGridCellsAdapter read FGridAdapter; end; TdxPSGridCellsAdapter = class private FReportCells: TdxReportCells; function GetCell(Col, Row: Integer): TdxReportCellSSString; function GetColCount: Integer; function GetColOffset(Index: Integer): Integer; function GetColWidth(Index: Integer): Integer; function GetRow(Index: Integer): TdxReportCell; function GetRowCount: Integer; function GetRowHeight(Index: Integer): Integer; function GetRowIndex(Index: Integer): Integer; function GetRowOffset(Index: Integer): Integer; public constructor Create(AReportCells: TdxReportCells); function GetNeighborCell(AItem: TdxReportCellSSString; ASide: TdxCellSide): TdxReportCellSSString; property Cells[Col, Row: Integer]: TdxReportCellSSString read GetCell; default; property ColCount: Integer read GetColCount; property ColOffsets[Index: Integer]: Integer read GetColOffset; property ColWidths[Index: Integer]: Integer read GetColWidth; property RowCount: Integer read GetRowCount; property RowHeights[Index: Integer]: Integer read GetRowHeight; property RowIndexes[Index: Integer]: Integer read GetRowIndex; property RowOffsets[Index: Integer]: Integer read GetRowOffset; property Rows[Index: Integer]: TdxReportCell read GetRow; end; TdxPSSSStringGridCellDataMap = class(TdxPSTextGridCellDataMap) protected class procedure InitializeCellData(ACol, ARow: Integer; ADataItem: TAbstractdxReportCellData; AReportLink: TAbstractdxGridReportLink); override; class function DataClass: TdxReportCellDataClass; override; end; TdxPSSpreadSheetReportLinkOptionView = (ssovRowAndColumnHeadings, ssovGridLines, ssovSuppressSourceFormats); TdxPSSpreadSheetReportLinkOptionsView = set of TdxPSSpreadSheetReportLinkOptionView; TCustomdxSpreadSheetReportLink = class(TAbstractdxGridReportLink) private FAppendingExtraColumns: Boolean; FColCount: Integer; FCellObjects: TList; FExtraColumnCount: Integer; FGridAdapter: TdxPSGridCellsAdapter; FOptionsView: TdxPSSpreadSheetReportLinkOptionsView; FPrintArea: TRect; FProcessingMerges: Boolean; FRowCount: Integer; FTempFont: TFont; function GetBookSheet: TcxSSBookSheet; function GetCustomSpreadSheetBook: TcxCustomSpreadSheetBook; function GetMeaningColCount: Integer; function GetMeaningRowCount: Integer; function GetMergedCells: TcxSSMergedCellsStorage; procedure SetOptionsView(Value: TdxPSSpreadSheetReportLinkOptionsView); procedure SetPrintArea(Value: TRect); function GetSSCellObject(ACol, ARow: Integer): TcxSSCellObject; function GetSSCellStyle(ACol, ARow: Integer): TcxSSCellStyle; function GetSSColorPalette: PcxExcelPalette; function GetSSDataStorage: TcxSSDataStorage; function GetSSDefaultCellSideColor(ASide: TdxCellSide): TColor; function GetSSDefaultStyle: TcxSSCellStyle; function GetFlatIndex(ACol, ARow: Integer): Integer; function GetRealColor(AColorIndex: Integer; ADefaultColor: TColor): TColor; function IsSSDefaultStyle(AStyle: TcxSSCellStyle): Boolean; protected FSourceHeaderFontIndex: Integer; function CannotActivateReportErrorString: string; override; procedure DoChangeComponent; override; procedure InternalRestoreDefaults; override; procedure InternalRestoreFromOriginal; override; function IsScaleGridLines: Boolean; override; function NeedTwoPassRendering: Boolean; override; function GetDataItemClass(ACol: Integer; ARow: Integer = 0): TdxReportCellDataClass; override; function GetColCount: Integer; override; function GetFixedColCount: Integer; override; function GetFixedRowCount: Integer; override; function GetRowCount: Integer; override; function GetCellSides(ACol, ARow: Integer): TdxCellSides; override; function GetCellText(ACol, ARow: Integer): string; override; function GetCellTextAlignY(ACol, ARow: Integer): TcxTextAlignY; override; function GetMinRowHeight(DC: HDC; AFont: TFont): Integer; override; function GetSelectionRect: TRect; override; function GetSourceCellColor(ACol, ARow: Integer): TColor; override; function GetSourceCellContentBkColor(ACol, ARow: Integer): TColor; override; function GetSourceCellContentPattern(ACol, ARow: Integer): TdxPSFillPatternClass; override; function GetSourceCellEdge3DSoft(ACol, ARow: Integer): Boolean; override; function GetSourceCellEdgeMode(ACol, ARow: Integer): TdxCellEdgeMode; override; function GetSourceCellFontIndex(ACol, ARow: Integer): Integer; override; function GetSourceCellMultiline(ACol, ARow: Integer): Boolean; override; function GetSourceCellTextAlignX(ACol, ARow: Integer): TcxTextAlignX; override; function GetSourceCellTextAlignY(ACol, ARow: Integer): TcxTextAlignY; override; function GetSourceCellTransparent(ACol, ARow: Integer): Boolean; override; function GetSourceColWidth(ACol: Integer): Integer; override; function GetSourceRowHeight(ARow: Integer): Integer; override; function HasSelection: Boolean; override; function IsDrawBorder: Boolean; override; function IsDrawHorzLines: Boolean; override; function IsDrawVertLines: Boolean; override; function IsProcessedCol(ACol: Integer): Boolean; override; function IsProcessedRow(ARow: Integer): Boolean; override; procedure AfterConstruct(AReportCells: TdxReportCells); override; procedure PrepareConstruct(AReportCells: TdxReportCells); override; procedure UnprepareConstruct(AReportCells: TdxReportCells); override; procedure AddMerges(AReportCells: TdxReportCells); procedure AppendAdditionalColumns(AnAdapter: TdxPSGridCellsAdapter); procedure CalcTextExtents(AnAdapter: TdxPSGridCellsAdapter); procedure DeleteCellObjects; procedure DeleteUnneededCellSides(AnAdapter: TdxPSGridCellsAdapter); procedure FixupRowWidths(AnAdapter: TdxPSGridCellsAdapter); function HasMerges: Boolean; function IsEmptyCell(const ACell: TcxSSCellRec): Boolean; function OnlyEdgeIsAssigned(const ACell: TcxSSCellRec; AEdge: TcxSSEdgeBorder): Boolean; function OnlyLeftEdgeIsAssigned(ACell: TcxSSCellRec): Boolean; function OnlyTopEdgeIsAssigned(ACell: TcxSSCellRec): Boolean; procedure PostProcessItems(AnAdapter: TdxPSGridCellsAdapter); procedure SetupCellBorders(ACol, ARow: Integer; ADataItem: TAbstractdxReportCellData); virtual; procedure CheckPrintAreaBounds(var R: TRect); function GetColumnOffset(ACol: Integer): Integer; function GetRowOffset(ARow: Integer): Integer; function IsMergedBorder(ACol, ARow: Integer; ASide: TdxCellSide): Boolean; function IsMergedCell(ACol, ARow: Integer): Boolean; virtual; function IsNearMostLeftCell(ACol, ARow: Integer): Boolean; virtual; function IsNearMostTopCell(ACol, ARow: Integer): Boolean; virtual; function IsShowGridLines: Boolean; function IsShowRowAndColumnHeadings: Boolean; function IsSuppressSourceFormats: Boolean; property ColCount: Integer read GetColCount; property ExtraColumnCount: Integer read FExtraColumnCount; property MeaningColCount: Integer read GetMeaningColCount; property MeaningRowCount: Integer read GetMeaningRowCount; property MergedCells: TcxSSMergedCellsStorage read GetMergedCells; property RowCount: Integer read GetRowCount; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure ClearPrintArea; function DataProviderPresent: Boolean; override; function DataToPrintExist: Boolean; virtual; function PrintAreaExists: Boolean; virtual; property BookSheet: TcxSSBookSheet read GetBookSheet; property CustomSpreadSheetBook: TcxCustomSpreadSheetBook read GetCustomSpreadSheetBook; property PrintArea: TRect read FPrintArea write SetPrintArea; published property Color; property Effects3D; property FixedColor; property FixedFont; property FixedTransparent; property Font; property GridLineColor; property HeadersOnEveryPage; property OnlySelected; property OptionsView: TdxPSSpreadSheetReportLinkOptionsView read FOptionsView write SetOptionsView default [ssovRowAndColumnHeadings]; property RowAutoHeight; property ScaleFonts; property Soft3D; property Transparent; property UseCustomPageBreaks; property UseHorzDelimiters; property UseVertDelimiters; property OnGetCustomPageBreaks; property OnInitializeItem; end; TdxSpreadSheetBookReportLink = class(TCustomdxSpreadSheetReportLink) private function GetSpreadSheetBook: TcxSpreadSheetBook; public property SpreadSheetBook: TcxSpreadSheetBook read GetSpreadSheetBook; end; TdxSpreadSheetReportLink = class(TCustomdxSpreadSheetReportLink) private function GetSpreadSheet: TcxSpreadSheet; public property SpreadSheet: TcxSpreadSheet read GetSpreadSheet; end; TfmdxSpreadSheetDesignWindow = class(TStandarddxReportLinkDesignWindow) pnlPreview: TPanel; pgctrlMain: TPageControl; tshOptions: TTabSheet; pnlOptions: TPanel; lblShow: TLabel; Bevel11: TBevel; lblMiscellaneous: TLabel; Bevel4: TBevel; Image5: TImage; imgGrid: TImage; chbxRowAutoHeight: TCheckBox; tshColor: TTabSheet; pnlColor: TPanel; lblGridLinesColor: TLabel; bvlLineColorHolder: TBevel; gbxFixedTransparent: TGroupBox; lblFixedColor: TLabel; bvlFixedColorHolder: TBevel; gbxTransparent: TGroupBox; lblColor: TLabel; bvlColorHolder: TBevel; chbxTransparent: TCheckBox; chbxFixedTransparent: TCheckBox; tshFont: TTabSheet; pnlFont: TPanel; btnFont: TButton; edFont: TEdit; btnFixedFont: TButton; edFixedFont: TEdit; tshBehaviors: TTabSheet; Panel1: TPanel; Image3: TImage; lblSelection: TLabel; Bevel3: TBevel; lblOnEveryPage: TLabel; Image1: TImage; Bevel10: TBevel; chbxOnlySelected: TCheckBox; chbxFixedRowsOnEveryPage: TCheckBox; chbxShowRowAndColumnHeadings: TCheckBox; chbxShowGridLines: TCheckBox; chbxSuppressSourceFormats: TCheckBox; lblPreview: TStaticText; stTransparent: TStaticText; stFixedTransparent: TStaticText; procedure chbxFixedRowsOnEveryPageClick(Sender: TObject); procedure chbxOnlySelectedClick(Sender: TObject); procedure btnFixedFontClick(Sender: TObject); procedure chbxRowAutoHeightClick(Sender: TObject); procedure chbxSuppressSourceFormatsClick(Sender: TObject); procedure chbxShowRowAndColumnHeadingsClick(Sender: TObject); procedure chbxShowGridLinesClick(Sender: TObject); procedure chbxFixedTransparentClick(Sender: TObject); procedure ccbxColorChange(Sender: TObject); procedure pbxPreviewPaint(Sender: TObject); procedure lblColorClick(Sender: TObject); procedure pgctrlMainChange(Sender: TObject); procedure stTransparentClick(Sender: TObject); procedure stFixedTransparentClick(Sender: TObject); private FccbxColor: TCustomComboBox; FccbxFixedColor: TCustomComboBox; FccbxGridLineColor: TCustomComboBox; FPreviewBox: TCustomControl; function GetReportLink: TCustomdxSpreadSheetReportLink; procedure SetReportLink(Value: TCustomdxSpreadSheetReportLink); procedure CreateControls; procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR; protected procedure DoInitialize; override; {$IFDEF DELPHI7} function GetPreviewHost: TCustomPanel; override; {$ENDIF} procedure LoadStrings; override; procedure PaintPreview(ACanvas: TCanvas; R: TRect); override; procedure UpdateControlsState; override; procedure UpdatePreview; override; public constructor Create(AOwner: TComponent); override; property ReportLink: TCustomdxSpreadSheetReportLink read GetReportLink write SetReportLink; end; const dxPSEmptySSPrintArea: TRect = (Left: -1; Top: -1; Right: -1; Bottom: -1); dxPSCellSideMap: array[TcxSSEdgeBorder] of TdxCellSide = (csLeft, csTop, csRight, csBottom); cxSSEdgeBorderMap: array[TdxCellSide] of TcxSSEdgeBorder = (eLeft, eTop, eRight, eBottom); dxCellEdgeSideOrientation: array[TdxCellSide] of TdxPSCellEdgePatternOrientation = (cepoVertical, cepoHorizontal, cepoVertical, cepoHorizontal); dxPSEdgePatternClassMap: array[TcxSSEdgeLineStyle] of TdxPSEdgePatternClass = (TdxPSSolidEdgePattern, TdxPSSolidEdgePattern, TdxPSMediumSolidEdgePattern, TdxPSDashedEdgePattern, TdxPSDottedEdgePattern, TdxPSThickSolidEdgePattern, TdxPSDoubleLineSolidEdgePattern, TdxPSHairEdgePattern, TdxPSMediumDashedEdgePattern, TdxPSDashDotEdgePattern, TdxPSMediumDashDotEdgePattern, TdxPSDashDotDotEdgePattern, TdxPSMediumDashDotDotEdgePattern, TdxPSSlantedDashDotEdgePattern, TdxPSSolidEdgePattern); dxPSFillPatternClassMap: array[TcxSSFillStyle] of TdxPSFillPatternClass = (TdxPSSolidFillPattern, TdxPSGray75FillPattern, TdxPSGray50FillPattern, TdxPSGray25FillPattern, TdxPSGray125FillPattern, TdxPSGray625FillPattern, TdxPSHorizontalStripeFillPattern, TdxPSVerticalStripeFillPattern, TdxPSDiagonalStripeFillPattern, TdxPSReverseDiagonalStripeFillPattern, TdxPSDiagonalCrossHatchFillPattern, TdxPSThickCrossHatchFillPattern, TdxPSThinHorizontalStripeFillPattern, TdxPSThinVerticalStripeFillPattern, TdxPSThinDiagonalStripeFillPattern, TdxPSThinReverseDiagonalStripeFillPattern, TdxPSThinHorizontalCrossHatchFillPattern, TdxPSThinDiagonalCrossHatchFillPattern); dxPSTextAlignXMap: array[TcxDisplayTextAlignment] of TcxTextAlignX = (taLeft, taCenterX, taRight, taLeft, taDistributeX); dxPSTextAlignYMap: array[TcxVertTextAlign] of TcxTextAlignY = (taTop, taCenterY, taBottom, taDistributeY); implementation {$R *.DFM} uses SysUtils, Forms, cxSSUtils, cxClasses, dxPSRes, dxPSUtl, dxExtCtrls, dxPrnDev; const { Since we don't use following Format Bits in TdxReportCellSSString we are allowed to safely override them } dxFormatClipContent = dxPSGlbl.dxFormatMakeSpaceForEmptyImage; dxFormatFill = dxPSGlbl.dxFormatCheckEnabled; dxFormatFixed = dxPSGlbl.dxFormatCheckBold; dxFormatMerged = dxPSGlbl.dxFormatImageTransparent; dxFormatNearMostLeft = dxPSGlbl.dxFormatCheckFlat; dxFormatNearMostTop = dxPSGlbl.dxFormatCheckChecked; dxFormatVirtual = dxPSGlbl.dxFormatImageTransparent; SubEndMask = $00000003; SubBitsPerEnd = 2; SubBitsPerSide = SubBitsPerEnd * (Integer(High(TdxPSCellBorderEnd)) + 1); SlantBitsPerSide = 4; SlantMask = $00000001; { from SS } SystemColorStart = 55; type TcxCustomSpreadSheetBookAccess = class(TcxCustomSpreadSheetBook); TcxSSBookSheetAccess = class(TcxSSBookSheet); TcxSSDataStorageAccess = class(TcxSSDataStorage); TcxSSCellStyleAccess = class(TcxSSCellStyle); function AreBackgroundsEqual(AStyle1, AStyle2: TcxSSCellStyleRec): Boolean; begin Result := (AStyle1.BrushStyle = AStyle2.BrushStyle) and (AStyle1.BrushBkColor = AStyle2.BrushBkColor) and (AStyle1.BrushFgColor = AStyle2.BrushFgColor); end; function AreEdgesEqual(AEdge1, AEdge2: TcxSSEdgeStyleRec): Boolean; begin Result := (AEdge1.Color = AEdge2.Color) and (AEdge1.Style = AEdge2.Style); end; function AreBordersEqual(ABorders1, ABorders2: TcxSSBordersStyle; AExclusion: TcxSSEdgeBorders = []): Boolean; var Edge: TcxSSEdgeBorder; begin for Edge := eLeft to eBottom do begin if Edge in AExclusion then Result := not AreEdgesEqual(ABorders1[Edge], ABorders2[Edge]) else Result := AreEdgesEqual(ABorders1[Edge], ABorders2[Edge]); if not Result then Break; end; end; function AreStylesEqual(AStyle1, AStyle2: TcxSSCellStyleRec; AExclusion: TcxSSEdgeBorders = []): Boolean; begin Result := AreBackgroundsEqual(AStyle1, AStyle2) and AreBordersEqual(AStyle1.Borders, AStyle2.Borders, AExclusion); end; function IsCellDataEmpty(const ACell: TcxSSCellRec): Boolean; begin Result := (ACell.Text = '') and (ACell.DateTime = 0); end; function ExposeBookSheet(ASpreadSheet: TcxSSBookSheet): TcxSSBookSheetAccess; begin Result := TcxSSBookSheetAccess(ASpreadSheet); end; function ExposeDataStorage(ADataStorage: TcxSSDataStorage): TcxSSDataStorageAccess; begin Result := TcxSSDataStorageAccess(ADataStorage); end; function ExposeSpreadSheetBook(ASpreadSheetBook: TcxCustomSpreadSheetBook): TcxCustomSpreadSheetBookAccess; begin Result := TcxCustomSpreadSheetBookAccess(ASpreadSheetBook); end; function ExposeActiveSpreadSheet(ASpreadSheetBook: TcxCustomSpreadSheetBook): TcxSSBookSheetAccess; begin Result := ExposeBookSheet(ExposeSpreadSheetBook(ASpreadSheetBook).ActiveSheet); end; function ExposeStyle(AStyle: TcxSSCellStyle): TcxSSCellStyleAccess; begin Result := TcxSSCellStyleAccess(AStyle); end; function GetTextWidth(DC: HDC; AFont: HFONT; const S: string): Integer; var Size: TSize; begin AFont := SelectObject(DC, AFont); GetTextExtentPoint32(DC, PChar(S), Length(S), Size); SelectObject(DC, AFont); Result := Size.cx; end; { TdxReportCellSSString } constructor TdxReportCellSSString.Create(AParent: TdxReportCell); begin inherited Create(AParent); PreventLeftTextExceed := False; TextAlignY := taBottom; end; procedure TdxReportCellSSString.Assign(Source: TPersistent); begin inherited Assign(Source); if Source is TdxReportCellSSString then begin FBorders := TdxReportCellSSString(Source).FBorders; FBorderSlants := TdxReportCellSSString(Source).FBorderSlants; FBorderSubs := TdxReportCellSSString(Source).FBorderSubs; FContentBkColor := TdxReportCellSSString(Source).FContentBkColor; FContentPattern := TdxReportCellSSString(Source).FContentPattern; FRealCol := TdxReportCellSSString(Source).FRealCol; FRealRow := TdxReportCellSSString(Source).FRealRow; FTextExtentLeft := TdxReportCellSSString(Source).FTextExtentLeft; FTextExtentRight := TdxReportCellSSString(Source).FTextExtentRight; end; end; procedure TdxReportCellSSString.SetBorders(AColor: TColor; APattern: TdxPSEdgePatternClass); var Side: TdxCellSide; begin for Side := csLeft to csBottom do with Borders[Side] do begin Color := AColor; Pattern := APattern; end; end; procedure TdxReportCellSSString.DrawContent(DC: HDC; AStage: TdxPSRenderStages); begin if rsFirstPass in AStage then if IsBackgroundDrawn then DrawBackground(DC); if rsSecondPass in AStage then begin if IsTextDrawn then DrawText(DC); if IsBordersDrawn then DrawBorders(DC); end; end; procedure TdxReportCellSSString.CalcBorderSubs(AnAdapter: TdxPSGridCellsAdapter); function GetNeighborCell(ASide: TdxCellSide): TdxReportCellSSString; begin Result := AnAdapter.GetNeighborCell(Self, ASide); end; function GetNeighborCellBorder(ASide, ABorderSide: TdxCellSide): TdxPSCellBorder; var Neighbor: TdxReportCellSSString; begin Neighbor := GetNeighborCell(ASide); if Neighbor <> nil then Result := Neighbor.Borders[ABorderSide] else Result := NullBorder; end; function GetNeighborCellBorderSalient(ASide, ABorderSide: TdxCellSide; ASalient: TdxPSCellBorderSalientType): Integer; var Neighbor: TdxReportCellSSString; begin Neighbor := GetNeighborCell(ASide); if Neighbor <> nil then Result := Neighbor.BorderEdgeSalients[ABorderSide, ASalient] else Result := 0; end; procedure GetBordersAtCorner(ACorner: TdxPSCellCorner; out ABorders: TdxPSCellBorders); begin case ACorner of ccTopLeft: begin ABorders[csLeft] := GetNeighborCellBorder(csLeft, csTop); ABorders[csTop] := GetNeighborCellBorder(csTop, csLeft); ABorders[csRight] := Borders[csTop]; ABorders[csBottom] := Borders[csLeft]; end; ccTopRight: begin ABorders[csLeft] := Borders[csTop]; ABorders[csTop] := GetNeighborCellBorder(csTop, csRight); ABorders[csRight] := GetNeighborCellBorder(csRight, csTop); ABorders[csBottom] := Borders[csRight]; end; ccBottomRight: begin ABorders[csLeft] := Borders[csBottom]; ABorders[csTop] := Borders[csRight]; ABorders[csRight] := GetNeighborCellBorder(csRight, csBottom); ABorders[csBottom] := GetNeighborCellBorder(csBottom, csRight); end; ccBottomLeft: begin ABorders[csLeft] := GetNeighborCellBorder(csLeft, csBottom); ABorders[csTop] := Borders[csLeft]; ABorders[csRight] := Borders[csBottom]; ABorders[csBottom] := GetNeighborCellBorder(csBottom, csLeft); end; end; end; function DontNeedCornerSubsCalculation(ACorner: TdxPSCellCorner; ABorders: TdxPSCellBorders): Boolean; var BorderCount, DblCount: Integer; Color: TColor; Side: TdxCellSide; Border: TdxPSCellBorder; begin BorderCount := 0; DblCount := 0; Color := clBlack; Result := False; for Side := csLeft to csBottom do begin Border := ABorders[Side]; if Border.Pattern = nil then Continue; Inc(BorderCount); if IsDoubleLineBorderPattern(Border) then Inc(DblCount); if (DblCount <> 0) and (DblCount <> BorderCount) then Exit; if BorderCount = 1 then Color := Border.Color else if Color <> Border.Color then Exit; end; Result := True; end; function GetFavoriteSides(ACorner: TdxPSCellCorner; const ABorders: TdxPSCellBorders): TdxCellSides; const CornerSideMaps: array[TdxPSCellCorner, TdxCellSide] of TdxCellSides = (([], [], [csTop], [csLeft]), ([csTop], [], [], [csRight]), ([csBottom], [csRight], [], []), ([], [csLeft], [csBottom], [])); var StartSide, FavoriteSide, Side: TdxCellSide; DblCount: Integer; DblCandidates: TdxCellSides; Border, FavoriteBorder: TdxPSCellBorder; begin StartSide := csLeft; while (StartSide < csBottom) and (ABorders[StartSide].Pattern = nil) do Inc(StartSide); FavoriteSide := StartSide; FavoriteBorder := ABorders[FavoriteSide]; DblCount := 0; DblCandidates := []; for Side := StartSide to csBottom do begin Border := ABorders[Side]; if Border.Pattern = nil then Continue; if IsDoubleLineBorderPattern(Border) then begin Inc(DblCount); DblCandidates := DblCandidates + CornerSideMaps[ACorner, Side]; end; if Side > StartSide then if not IsDoubleLineBorderPattern(Border) and (IsDoubleLineBorderPattern(FavoriteBorder) or (Border.Pattern.Thickness > FavoriteBorder.Pattern.Thickness) or ((Border.Pattern.Thickness = FavoriteBorder.Pattern.Thickness) and (Border.Color < FavoriteBorder.Color))) then begin FavoriteBorder := Border; FavoriteSide := Side; end; end; if DblCount > 1 then Result := DblCandidates else Result := CornerSideMaps[ACorner, FavoriteSide]; end; function CalcBorderSub(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd): Integer; const ConcurSides: array[TdxCellSide, TdxPSCellBorderEnd] of TdxCellSide = ((csTop, csBottom), (csLeft, csRight), (csTop, csBottom), (csLeft, csRight)); var ConcurSide: TdxCellSide; begin ConcurSide := ConcurSides[ASide, AEnd]; Result := BorderEdgeSalients[ConcurSide, bstOuter] + Max(BorderEdgeSalients[ConcurSide, bstInner], GetNeighborCellBorderSalient(ASide, ConcurSide, bstInner)); end; const BorderEnds: array[TdxPSCellCorner, TdxCellSide] of TdxPSCellBorderEnd = ((cbsTopLeft, cbsTopLeft, cbsTopLeft, cbsTopLeft), (cbsTopLeft, cbsBottomRight, cbsTopLeft, cbsTopLeft), (cbsBottomRight, cbsBottomRight, cbsBottomRight, cbsBottomRight), (cbsBottomRight, cbsTopLeft, cbsTopLeft, cbsTopLeft)); CornerSides: array[TdxPSCellCorner] of TdxCellSides = ([csLeft, csTop], [csTop, csRight], [csRight, csBottom], [csBottom, csLeft]); var Corner: TdxPSCellCorner; Borders: TdxPSCellBorders; UnfavorableSides: TdxCellSides; Side: TdxCellSide; BorderEnd: TdxPSCellBorderEnd; begin for Corner := ccTopLeft to ccBottomLeft do begin GetBordersAtCorner(Corner, Borders); if DontNeedCornerSubsCalculation(Corner, Borders) then Continue; UnfavorableSides := CornerSides[Corner] - GetFavoriteSides(Corner, Borders); for Side := csLeft to csBottom do if Side in UnfavorableSides then begin BorderEnd := BorderEnds[Corner, Side]; BorderSubs[Side, BorderEnd] := CalcBorderSub(Side, BorderEnd); end; end; end; procedure TdxReportCellSSString.CalcDoubleBorderSlants(AnAdapter: TdxPSGridCellsAdapter); var Neighbor: TdxReportCellSSString; begin if IsDoubleLineBorderPattern(csLeft) then begin Neighbor := AnAdapter.GetNeighborCell(Self, csLeft); BorderSlants[csLeft, cbcTopLeft] := Ord((Neighbor <> nil) and Neighbor.IsDoubleLineBorderPattern(csTop)); BorderSlants[csLeft, cbcTopRight] := Ord(IsDoubleLineBorderPattern(csTop)); BorderSlants[csLeft, cbcBottomRight] := Ord(IsDoubleLineBorderPattern(csBottom)); BorderSlants[csLeft, cbcBottomLeft] := Ord((Neighbor <> nil) and Neighbor.IsDoubleLineBorderPattern(csBottom)); end; if IsDoubleLineBorderPattern(csTop) then begin Neighbor := AnAdapter.GetNeighborCell(Self, csTop); BorderSlants[csTop, cbcTopLeft] := Ord((Neighbor <> nil) and Neighbor.IsDoubleLineBorderPattern(csLeft)); BorderSlants[csTop, cbcTopRight] := Ord((Neighbor <> nil) and Neighbor.IsDoubleLineBorderPattern(csRight)); BorderSlants[csTop, cbcBottomRight] := Ord(IsDoubleLineBorderPattern(csRight)); BorderSlants[csTop, cbcBottomLeft] := Ord(IsDoubleLineBorderPattern(csLeft)); end; if IsDoubleLineBorderPattern(csRight) then begin Neighbor := AnAdapter.GetNeighborCell(Self, csRight); BorderSlants[csRight, cbcTopLeft] := Ord(IsDoubleLineBorderPattern(csTop)); BorderSlants[csRight, cbcTopRight] := Ord((Neighbor <> nil) and Neighbor.IsDoubleLineBorderPattern(csTop)); BorderSlants[csRight, cbcBottomRight] := Ord((Neighbor <> nil) and Neighbor.IsDoubleLineBorderPattern(csBottom)); BorderSlants[csRight, cbcBottomLeft] := Ord(IsDoubleLineBorderPattern(csBottom)); end; if IsDoubleLineBorderPattern(csBottom) then begin Neighbor := AnAdapter.GetNeighborCell(Self, csBottom); BorderSlants[csBottom, cbcTopLeft] := Ord(IsDoubleLineBorderPattern(csLeft)); BorderSlants[csBottom, cbcTopRight] := Ord(IsDoubleLineBorderPattern(csRight)); BorderSlants[csBottom, cbcBottomRight] := Ord((Neighbor <> nil) and Neighbor.IsDoubleLineBorderPattern(csRight)); BorderSlants[csBottom, cbcBottomLeft] := Ord((Neighbor <> nil) and Neighbor.IsDoubleLineBorderPattern(csLeft)); end; end; procedure TdxReportCellSSString.ConvertCoords(APixelsNumerator, APixelsDenominator: Integer); begin inherited ConvertCoords(APixelsNumerator, APixelsDenominator); TextExtentLeft := MulDiv(TextExtentLeft, APixelsNumerator, APixelsDenominator); TextExtentRight := MulDiv(TextExtentRight, APixelsNumerator, APixelsDenominator); end; function TdxReportCellSSString.GetBackgroundBounds(DC: HDC): TRect; var LineThickness: Integer; begin Result := inherited GetBackgroundBounds(DC); if not IsFixed then begin LineThickness := Self.LineThickness; if BorderEdgeSalients[csLeft, bstOuter] > 0 then Dec(Result.Left, LineThickness); if BorderEdgeSalients[csTop, bstOuter] > 0 then Dec(Result.Top, LineThickness); if BorderEdgeSalients[csRight, bstOuter] > 0 then Inc(Result.Right, LineThickness); if BorderEdgeSalients[csBottom, bstOuter] > 0 then Inc(Result.Bottom, LineThickness); FixupRect(DC, Result); end; end; function TdxReportCellSSString.GetBorderEdgeBounds(ASide: TdxCellSide; const AOuterRect: TRect): TRect; begin Result := inherited GetBorderEdgeBounds(ASide, AOuterRect); with Result do if ASide in csLeftRight then begin Inc(Top, LineThickness * BorderSubs[ASide, cbsTopLeft]); Dec(Bottom, LineThickness * BorderSubs[ASide, cbsBottomRight]); end else begin Inc(Left, LineThickness * BorderSubs[ASide, cbsTopLeft]); Dec(Right, LineThickness * BorderSubs[ASide, cbsBottomRight]); end; end; function TdxReportCellSSString.GetBorderBrush(ASide: TdxCellSide): HBRUSH; begin Result := dxPSEdgePatternFactory.Items[TdxPSEdgePatternClass(BorderEdgeClasses[ASide]), IsPrinting].Brushes[dxCellEdgeSideOrientation[ASide]].Handle; end; function TdxReportCellSSString.GetBorderEdgeClass(ASide: TdxCellSide): TdxPSCellBorderClass; begin Result := Borders[ASide].Pattern; if Result = nil then Result := TdxPSSolidEdgePattern; end; function TdxReportCellSSString.GetEffectiveBounds(DC: HDC; AStage: TdxPSRenderStages): TRect; begin if rsFirstPass in AStage then Result := inherited GetEffectiveBounds(DC, AStage) else UnionRect(Result, GetOuterBounds(DC), GetTextBounds(DC)); end; function TdxReportCellSSString.GetTextBounds(DC: HDC): TRect; begin Result := inherited GetTextBounds(DC); if TextExtentLeft <> 0 then Result.Left := TextExtentLeft; if TextExtentRight <> 0 then Result.Right := TextExtentRight; end; function TdxReportCellSSString.IsDrawn(DC: HDC; AStage: TdxPSRenderStages; const ARect: TRect): Boolean; var R: TRect; begin Result := IntersectRect(R, GetAbsoluteInnerBounds(DC), ARect); end; function TdxReportCellSSString.GetBorderPainterClass: TdxPSCellBorderPainterClass; begin if IsFixed then Result := inherited GetBorderPainterClass else Result := TdxPSCellPatternsBorderPainter; end; procedure TdxReportCellSSString.InitBorderPainter(ABordersPainter: TdxPSCellBorderPainter); begin inherited InitBorderPainter(ABordersPainter); if not IsFixed then TdxPSCellPatternsBorderPainter(ABordersPainter).FGridAdapter := TCustomdxSpreadSheetReportLink(ReportCells.ReportLink).FGridAdapter; end; function TdxReportCellSSString.GetContentBkColor: TColor; begin Result := FContentBkColor; end; function TdxReportCellSSString.GetContentPattern: TdxPSFillPatternClass; begin Result := FContentPattern; end; procedure TdxReportCellSSString.SetContentBkColor(Value: TColor); begin FContentBkColor := Value; end; procedure TdxReportCellSSString.SetContentPattern(Value: TdxPSFillPatternClass); begin FContentPattern := Value; end; procedure TdxReportCellSSString.ReadBorders(AReader: TdxPSDataReader); var Side: TdxCellSide; Border: TdxPSCellBorder; begin for Side := csLeft to csBottom do begin Border.Color := AReader.ReadInteger; Border.Pattern := TdxPSEdgePatternClass(AReader.ReadCellBorderClass); Borders[Side] := Border; end; end; procedure TdxReportCellSSString.ReadData(AReader: TdxPSDataReader); begin inherited ReadData(AReader); with AReader do begin ReadBorders(AReader); FBorderSlants := ReadInteger; FBorderSubs := ReadInteger; RealCol := ReadInteger; RealRow := ReadInteger; TextExtentLeft := ReadInteger; TextExtentRight := ReadInteger; end; end; procedure TdxReportCellSSString.WriteBorders(AWriter: TdxPSDataWriter); var Side: TdxCellSide; begin for Side := csLeft to csBottom do begin AWriter.WriteInteger(Borders[Side].Color); AWriter.WriteClassName(Borders[Side].Pattern); end; end; procedure TdxReportCellSSString.WriteData(AWriter: TdxPSDataWriter); begin inherited WriteData(AWriter); with AWriter do begin WriteBorders(AWriter); WriteInteger(FBorderSlants); WriteInteger(FBorderSubs); WriteInteger(RealCol); WriteInteger(RealRow); WriteInteger(TextExtentLeft); WriteInteger(TextExtentRight); end; end; function TdxReportCellSSString.GetAbsoluteInnerBounds(DC: HDC): TRect; begin Result := GetInnerBounds(DC); if Parent <> nil then with Parent.AbsoluteOrigin do OffsetRect(Result, X, Y); end; function TdxReportCellSSString.GetDoubleBorderRgn(ASide: TdxCellSide; const R: TRect): HRGN; const VertexCount = 4; type PdxPSCellEdgeCoords = ^TdxPSCellEdgeCoords; TdxPSCellEdgeCoords = record case Byte of 0: (TopLeft, TopRight, BottomRight, BottomLeft: TPoint); 1: (Points: array[0..VertexCount - 1] of TPoint); end; var EdgeCoords: TdxPSCellEdgeCoords; Thickness: Integer; begin with EdgeCoords do begin TopLeft := R.TopLeft; TopRight := Point(R.Right, R.Top); BottomRight := R.BottomRight; BottomLeft := Point(R.Left, R.Bottom); end; Thickness := LineThickness * (TdxPSDoubleLineSolidEdgePattern.Thickness - 1); with EdgeCoords do case ASide of csLeft: begin Inc(TopLeft.Y, Thickness * BorderSlants[ASide, cbcTopLeft]); Inc(TopRight.Y, Thickness * BorderSlants[ASide, cbcTopRight]); Dec(BottomRight.Y, Thickness * BorderSlants[ASide, cbcBottomRight]); Dec(BottomLeft.Y, Thickness * BorderSlants[ASide, cbcBottomLeft]); end; csTop: begin Inc(TopLeft.X, Thickness * BorderSlants[ASide, cbcTopLeft]); Dec(TopRight.X, Thickness * BorderSlants[ASide, cbcTopRight]); Dec(BottomRight.X, Thickness * BorderSlants[ASide, cbcBottomRight]); Inc(BottomLeft.X, Thickness * BorderSlants[ASide, cbcBottomLeft]); end; csRight: begin Inc(TopLeft.Y, Thickness * BorderSlants[ASide, cbcTopLeft]); Inc(TopRight.Y, Thickness * BorderSlants[ASide, cbcTopRight]); Dec(BottomRight.Y, Thickness * BorderSlants[ASide, cbcBottomRight]); Dec(BottomLeft.Y, Thickness * BorderSlants[ASide, cbcBottomLeft]); end; csBottom: begin Inc(TopLeft.X, Thickness * BorderSlants[ASide, cbcTopLeft]); Dec(TopRight.X, Thickness * BorderSlants[ASide, cbcTopRight]); Dec(BottomRight.X, Thickness * BorderSlants[ASide, cbcBottomRight]); Inc(BottomLeft.X, Thickness * BorderSlants[ASide, cbcBottomLeft]); end; end; Result := CreatePolygonRgn(EdgeCoords.Points, SizeOf(TdxPSCellEdgeCoords) div SizeOf(TPoint), Windows.WINDING); end; function TdxReportCellSSString.IsDoubleLineBorderPattern(ABorder: TdxPSCellBorder): Boolean; begin with ABorder do Result := (Pattern <> nil) and Pattern.InheritsFrom(TdxPSDoubleLineSolidEdgePattern); end; function TdxReportCellSSString.IsDoubleLineBorderPattern(ASide: TdxCellSide): Boolean; begin Result := (ASide in CellSides) and IsDoubleLineBorderPattern(Self.Borders[ASide]); end; function TdxReportCellSSString.NullBorder: TdxPSCellBorder; begin FillChar(Result, SizeOf(TdxPSCellBorder), 0); end; function TdxReportCellSSString.GetBorder(ASide: TdxCellSide): TdxPSCellBorder; begin Result := FBorders[ASide]; end; function TdxReportCellSSString.GetBordersBkColor: TColor; begin if Transparent then Result := ColorToRGB(clWindow) else Result := Color; end; function TdxReportCellSSString.GetBorderSlant(ASide: TdxCellSide; ACorner: TdxPSCellBorderCorner): Integer; begin Result := (FBorderSlants shr GetBorderSlantOffset(ASide, ACorner)) and SlantMask; end; function TdxReportCellSSString.GetBorderSlantOffset(ASide: TdxCellSide; ACorner: TdxPSCellBorderCorner): TDWORDBits; begin Result := Integer(ASide) * SlantBitsPerSide + Integer(ACorner); end; function TdxReportCellSSString.GetBorderSub(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd): TdxPSCellBorderSub; begin Result := (FBorderSubs shr GetBorderSubOffset(ASide, AEnd)) and SubEndMask; end; function TdxReportCellSSString.GetBorderSubMask(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd): DWORD; begin Result := 0 or (SubEndMask shl GetBorderSubOffset(ASide, AEnd)); end; function TdxReportCellSSString.GetBorderSubOffset(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd): TDWORDBits; begin Result := Integer(ASide) * SubBitsPerSide + SubBitsPerEnd * Integer(AEnd); end; function TdxReportCellSSString.GetClipContent: Boolean; begin Result := (Format and dxFormatClipContent) = dxFormatClipContent; end; function TdxReportCellSSString.GetCol: Integer; begin Result := Index; end; function TdxReportCellSSString.GetFill: Boolean; begin Result := (Format and dxFormatFill) = dxFormatFill; end; function TdxReportCellSSString.GetIsFixed: Boolean; begin Result := (Format and dxFormatFixed) = dxFormatFixed; end; function TdxReportCellSSString.GetIsMerged: Boolean; begin Result := (Format and dxFormatMerged) = dxFormatMerged; end; function TdxReportCellSSString.GetIsNearMostLeft: Boolean; begin Result := (Format and dxFormatNearMostLeft) = dxFormatNearMostLeft; end; function TdxReportCellSSString.GetIsNearMostTop: Boolean; begin Result := (Format and dxFormatNearMostTop) = dxFormatNearMostTop; end; function TdxReportCellSSString.GetIsNearMostTopOrLeft: Boolean; begin Result := GetIsNearMostLeft or GetIsNearMostTop; end; function TdxReportCellSSString.GetIsVirtual: Boolean; begin Result := GetFormatBit(dxFormatVirtual); end; function TdxReportCellSSString.GetRow: Integer; begin Result := Parent.Index; end; procedure TdxReportCellSSString.SetBorder(ASide: TdxCellSide; Value: TdxPSCellBorder); begin FBorders[ASide] := Value; end; procedure TdxReportCellSSString.SetBorderSlant(ASide: TdxCellSide; ACorner: TdxPSCellBorderCorner; Value: Integer); var Mask: DWORD; begin Mask := 1 shl GetBorderSlantOffset(ASide, ACorner); FBorderSlants := FBorderSlants and not Mask; if Value <> 0 then FBorderSlants := FBorderSlants or Mask; end; procedure TdxReportCellSSString.SetBorderSub(ASide: TdxCellSide; AEnd: TdxPSCellBorderEnd; Value: TdxPSCellBorderSub); begin FBorderSubs := FBorderSubs and not GetBorderSubMask(ASide, AEnd) or (Value shl GetBorderSubOffset(ASide, AEnd)); end; procedure TdxReportCellSSString.SetClipConent(Value: Boolean); const dxClipContent: array[Boolean] of DWORD = (0, dxFormatClipContent); begin Format := Format and not dxFormatClipContent or dxClipContent[Value]; end; procedure TdxReportCellSSString.SetFill(Value: Boolean); const dxFill: array[Boolean] of DWORD = (0, dxFormatFill); begin Format := Format and not dxFormatFill or dxFill[Value]; end; procedure TdxReportCellSSString.SetIsFixed(Value: Boolean); const dxFixed: array[Boolean] of DWORD = (0, dxFormatFixed); begin Format := Format and not dxFormatFixed or dxFixed[Value]; end; procedure TdxReportCellSSString.SetIsMerged(Value: Boolean); const dxMerged: array[Boolean] of DWORD = (0, dxFormatMerged); begin Format := Format and not dxFormatMerged or dxMerged[Value]; end; procedure TdxReportCellSSString.SetIsNearMostLeft(Value: Boolean); const dxIsNearMostLeft: array[Boolean] of DWORD = (0, dxFormatNearMostLeft); begin Format := Format and not dxFormatNearMostLeft or dxIsNearMostLeft[Value]; end; procedure TdxReportCellSSString.SetIsNearMostTop(Value: Boolean); const dxIsNearMostTop: array[Boolean] of DWORD = (0, dxFormatNearMostTop); begin Format := Format and not dxFormatNearMostTop or dxIsNearMostTop[Value]; end; procedure TdxReportCellSSString.SetIsVirtual(Value: Boolean); begin SetFormatBit(dxFormatVirtual, Value); end; { TdxPSCellPatternsBorderPainter } function TdxPSCellPatternsBorderPainter.Item: TdxReportCellSSString; begin Result := inherited Item as TdxReportCellSSString; end; function TdxPSCellPatternsBorderPainter.ClipItemBounds(DC: HDC; AOuterRect: TRect): HRGN; begin with Item do begin if IsNearMostTop then Inc(AOuterRect.Top, LineThickness * BorderEdgeSalients[csTop, bstOuter]); if IsNearMostLeft then Inc(AOuterRect.Left, LineThickness * BorderEdgeSalients[csLeft, bstOuter]); end; Result := Renderer.IntersectClipRect(AOuterRect); end; procedure TdxPSCellPatternsBorderPainter.DrawBorder(DC: HDC; const R: TRect; AForeColor, ABkColor: TColor; ABrush: HBRUSH); begin ABkColor := SetBkColor(DC, ABkColor); AForeColor := SetTextColor(DC, AForeColor); FillRect(DC, R, ABrush); SetTextColor(DC, AForeColor); SetBkColor(DC, ABkColor); end; procedure TdxPSCellPatternsBorderPainter.DrawBorder(DC: HDC; ABorderRgn: HRGN; AForeColor, ABkColor: TColor; ABrush: HBRUSH); begin ABkColor := SetBkColor(DC, ABkColor); AForeColor := SetTextColor(DC, AForeColor); FillRgn(DC, ABorderRgn, ABrush); SetTextColor(DC, AForeColor); SetBkColor(DC, ABkColor); end; procedure TdxPSCellPatternsBorderPainter.Paint(DC: HDC); var R: TRect; Rgn: HRGN; Side: TdxCellSide; BorderRect: TRect; BorderBr: HBRUSH; BrushOrg: TPoint; BorderRgn: HRGN; Border: TdxPSCellBorder; begin with Item do begin R := GetOuterBounds(DC); Rgn := 0; if IsNearMostTopOrLeft then Rgn := ClipItemBounds(DC, R); for Side := csLeft to csBottom do if Side in CellSides then begin BorderRect := GetBorderEdgeBounds(Side, R); if RectVisible(DC, BorderRect) then begin BorderBr := GetBorderBrush(Side); Border := Borders[Side]; GetBrushOrgEx(DC, BrushOrg); if (Border.Pattern <> nil) and Border.Pattern.RequiredBrushOrigin then begin UnrealizeObject(BorderBrush); BrushOrg := BorderRect.TopLeft; LPToDP(DC, BrushOrg, 1); SetBrushOrgEx(DC, BrushOrg.X mod 2{Border.Pattern.Thickness}, BrushOrg.Y mod 2{Border.Pattern.Thickness}, nil); end; FixupRect(DC, BorderRect); if IsDoubleLineBorderPattern(Side) then begin BorderRgn := GetDoubleBorderRgn(Side, BorderRect); DrawBorder(DC, BorderRgn, Border.Color, BordersBkColor, BorderBr); DeleteObject(BorderRgn); end else DrawBorder(DC, BorderRect, Border.Color, BordersBkColor, BorderBr); if (Border.Pattern <> nil) and Border.Pattern.RequiredBrushOrigin then SetBrushOrgEx(DC, BrushOrg.X, BrushOrg.Y, nil); end; end; if IsNearMostTopOrLeft then Renderer.RestoreClipRgn(Rgn); end; end; { TdxPSGridCellsAdapter } constructor TdxPSGridCellsAdapter.Create(AReportCells: TdxReportCells); begin inherited Create; FReportCells := AReportCells; end; function TdxPSGridCellsAdapter.GetNeighborCell(AItem: TdxReportCellSSString; ASide: TdxCellSide): TdxReportCellSSString; begin Result := nil; case ASide of csLeft: if AItem.Col > 0 then Result := Cells[AItem.Col - 1, AItem.Row]; csTop: if AItem.Row > 0 then Result := Cells[AItem.Col, AItem.Row - 1]; csRight: if AItem.Col + 1 < ColCount then Result := Cells[AItem.Col + 1, AItem.Row]; csBottom: if AItem.Row + 1 < RowCount then Result := Cells[AItem.Col, AItem.Row + 1]; end; end; function TdxPSGridCellsAdapter.GetCell(Col, Row: Integer): TdxReportCellSSString; begin Result := FReportCells.Cells[Row].DataItems[Col] as TdxReportCellSSString; end; function TdxPSGridCellsAdapter.GetColCount: Integer; begin with FReportCells do if Cells.CellCount > 0 then Result := Cells[0].DataItemCount else Result := 0; end; function TdxPSGridCellsAdapter.GetColOffset(Index: Integer): Integer; begin if Index < ColCount then Result := Cells[Index, 0].Left else Result := Cells[ColCount - 1, 0].Left + Cells[ColCount - 1, 0].Width; end; function TdxPSGridCellsAdapter.GetColWidth(Index: Integer): Integer; begin Result := Cells[Index, 0].Width; end; function TdxPSGridCellsAdapter.GetRow(Index: Integer): TdxReportCell; begin Result := FReportCells.Cells[Index]; end; function TdxPSGridCellsAdapter.GetRowCount: Integer; begin Result := FReportCells.Cells.CellCount; end; function TdxPSGridCellsAdapter.GetRowHeight(Index: Integer): Integer; begin Result := Cells[0, Index].Height; end; function TdxPSGridCellsAdapter.GetRowIndex(Index: Integer): Integer; begin Result := Rows[Index].Data; end; function TdxPSGridCellsAdapter.GetRowOffset(Index: Integer): Integer; begin if Index < RowCount then Result := Cells[0, Index].Top else Result := Cells[0, RowCount - 1].Top + Cells[0, RowCount - 1].Height; end; { TdxPSSSStringGridCellDataMap } class procedure TdxPSSSStringGridCellDataMap.InitializeCellData(ACol, ARow: Integer; ADataItem: TAbstractdxReportCellData; AReportLink: TAbstractdxGridReportLink); begin inherited; with TCustomdxSpreadSheetReportLink(AReportLink) do begin TdxReportCellSSString(ADataItem).Fill := not IsFixedCell(ACol, ARow) and (GetSSCellObject(ACol, ARow).DisplayTextAlignment = dtaFILL); TdxReportCellSSString(ADataItem).IsFixed := IsFixedCell(ACol, ARow); TdxReportCellSSString(ADataItem).IsMerged := IsMergedCell(ACol, ARow); TdxReportCellSSString(ADataItem).IsNearMostLeft := IsNearMostLeftCell(ACol, ARow); TdxReportCellSSString(ADataItem).IsNearMostTop := IsNearMostTopCell(ACol, ARow); TdxReportCellSSString(ADataItem).RealCol := ACol; TdxReportCellSSString(ADataItem).RealRow := ARow; SetupCellBorders(ACol, ARow, ADataItem); end; end; class function TdxPSSSStringGridCellDataMap.DataClass: TdxReportCellDataClass; begin Result := TdxReportCellSSString; end; { TCustomdxSpreadSheetReportLink } constructor TCustomdxSpreadSheetReportLink.Create(AOwner: TComponent); begin inherited; FColCount := -1; FRowCount := -1; FCellObjects := TList.Create; FGridAdapter := TdxPSGridCellsAdapter.Create(nil); FTempFont := TFont.Create; end; destructor TCustomdxSpreadSheetReportLink.Destroy; begin FTempFont.Free; FGridAdapter.Free; DeleteCellObjects; FCellObjects.Free; inherited; end; procedure TCustomdxSpreadSheetReportLink.Assign(Source: TPersistent); begin inherited; if Source is TCustomdxSpreadSheetReportLink then with TCustomdxSpreadSheetReportLink(Source) do begin Self.OptionsView := OptionsView; Self.PrintArea := PrintArea; end; end; procedure TCustomdxSpreadSheetReportLink.ClearPrintArea; begin PrintArea := dxPSEmptySSPrintArea; end; function TCustomdxSpreadSheetReportLink.DataProviderPresent: Boolean; begin Result := inherited DataProviderPresent and DataToPrintExist; end; function TCustomdxSpreadSheetReportLink.DataToPrintExist: Boolean; begin Result := (MeaningColCount > 0) and (MeaningRowCount > 0); end; function TCustomdxSpreadSheetReportLink.PrintAreaExists: Boolean; begin Result := not EqualRect(PrintArea, dxPSEmptySSPrintArea); end; function TCustomdxSpreadSheetReportLink.CannotActivateReportErrorString: string; begin if not inherited DataProviderPresent then Result := inherited CannotActivateReportErrorString else Result := cxGetResourceString(@sdxDataToPrintDoesNotExist); end; procedure TCustomdxSpreadSheetReportLink.DoChangeComponent; begin ClearPrintArea; inherited; end; procedure TCustomdxSpreadSheetReportLink.InternalRestoreDefaults; begin inherited; EndEllipsis := False; Soft3D := True; FPrintArea := dxPSEmptySSPrintArea; OptionsView := [ssovRowAndColumnHeadings]; end; procedure TCustomdxSpreadSheetReportLink.InternalRestoreFromOriginal; begin inherited; FixedFont := ExposeSpreadSheetBook(CustomSpreadSheetBook).HeaderFont; end; function TCustomdxSpreadSheetReportLink.IsScaleGridLines: Boolean; begin Result := False; end; function TCustomdxSpreadSheetReportLink.NeedTwoPassRendering: Boolean; begin Result := True; end; function TCustomdxSpreadSheetReportLink.GetDataItemClass(ACol: Integer; ARow: Integer = 0): TdxReportCellDataClass; begin Result := TdxReportCellSSString; end; function TCustomdxSpreadSheetReportLink.GetColCount: Integer; var BeginCol, BeginRow, EndRow: Integer; begin if FColCount <= 0 then if HasSelection then begin GetSelectedRange(BeginCol, FColCount, BeginRow, EndRow); Inc(FColCount); end else FColCount := MeaningColCount + 1; Result := FColCount; end; function TCustomdxSpreadSheetReportLink.GetFixedColCount: Integer; begin Result := 1; end; function TCustomdxSpreadSheetReportLink.GetFixedRowCount: Integer; begin Result := 1; end; function TCustomdxSpreadSheetReportLink.GetRowCount: Integer; var BeginCol, EndCol, BeginRow: Integer; begin if FRowCount <= 0 then if HasSelection then begin GetSelectedRange(BeginCol, EndCol, BeginRow, FRowCount); Inc(FRowCount); end else FRowCount := MeaningRowCount + 1; Result := FRowCount; end; function TCustomdxSpreadSheetReportLink.GetCellSides(ACol, ARow: Integer): TdxCellSides; function AreNeigborhoodsTransparent(ASide: TdxCellSide): Boolean; begin case ASide of csLeft: Result := IsNearMostLeftCell(ACol, ARow) or (GetCellTransparent(ACol - 1, ARow) and GetCellTransparent(ACol, ARow)); csTop: Result := IsNearMostTopCell(ACol, ARow) or (GetCellTransparent(ACol, ARow - 1) and GetCellTransparent(ACol, ARow)); csRight: Result := ((ACol = GetColCount - 1) {and not FAppendingExtraColumns}) or (GetCellTransparent(ACol + 1, ARow) and GetCellTransparent(ACol, ARow)); else // csBottom Result := ((ARow = GetRowCount - 1) {and not FAppendingExtraColumns}) or (GetCellTransparent(ACol, ARow + 1) and GetCellTransparent(ACol, ARow)); end; end; var Style: TcxSSCellStyle; Side: TdxCellSide; BorderStyle: TcxSSEdgeLineStyle; begin if IsFixedCell(ACol, ARow) or IsSuppressSourceFormats then Result := inherited GetCellSides(ACol, ARow) else begin Result := csAll; Style := GetSSCellStyle(ACol, ARow); for Side := Low(TdxCellSide) to High(TdxCellSide) do begin if Style <> nil then BorderStyle := Style.Borders.Edges[cxSSEdgeBorderMap[Side]].Style else BorderStyle := lsDefault; if (BorderStyle in [lsNone, lsDefault]) and (not IsShowGridLines or not AreNeigborhoodsTransparent(Side) or (IsMergedCell(ACol, ARow) and not IsMergedBorder(ACol, ARow, Side))) then Exclude(Result, Side); end; end; end; function TCustomdxSpreadSheetReportLink.GetCellText(ACol, ARow: Integer): string; begin if IsFixedCell(ACol, ARow) then begin if (ACol = 0) and (ARow <> 0) then Result := TcxSSUtils.RowNameByIndex(ARow - 1, CustomSpreadSheetBook.R1C1ReferenceStyle); if (ARow = 0) and (ACol <> 0) then Result := TcxSSUtils.ColumnNameByIndex(ACol - 1, CustomSpreadSheetBook.R1C1ReferenceStyle); end else if (FProcessingMerges or not IsMergedCell(ACol, ARow)) and not FAppendingExtraColumns then Result := GetSSCellObject(ACol, ARow).DisplayText else Result := ''; end; function TCustomdxSpreadSheetReportLink.GetCellTextAlignY(ACol, ARow: Integer): TcxTextAlignY; begin if (DrawMode <> gdmBorrowSource) and not IsFixedCell(ACol, ARow) then Result := taBottom else Result := inherited GetCellTextAlignY(ACol, ARow); end; function TCustomdxSpreadSheetReportLink.GetMinRowHeight(DC: HDC; AFont: TFont): Integer; begin Result := 1; end; function TCustomdxSpreadSheetReportLink.GetSelectionRect: TRect; begin if OnlySelected then Result := ExposeBookSheet(BookSheet).SelectionRect else Result := PrintArea; OffsetRect(Result, 1, 1); end; function TCustomdxSpreadSheetReportLink.GetSourceCellColor(ACol, ARow: Integer): TColor; begin if IsFixedCell(ACol, ARow) then Result := ColorToRGB(ExposeSpreadSheetBook(CustomSpreadSheetBook).HeaderColor) else if GetSourceCellContentPattern(ACol, ARow).InheritsFrom(TdxPSSolidFillPattern) then Result := GetRealColor(GetSSCellStyle(ACol, ARow).Brush.BackgroundColor, clWindow) else Result := GetRealColor(GetSSCellStyle(ACol, ARow).Brush.ForegroundColor, clWindow); end; function TCustomdxSpreadSheetReportLink.GetSourceCellContentBkColor(ACol, ARow: Integer): TColor; begin if IsFixedCell(ACol, ARow) then Result := ColorToRGB(ExposeSpreadSheetBook(CustomSpreadSheetBook).HeaderColor) else Result := GetRealColor(GetSSCellStyle(ACol, ARow).Brush.BackgroundColor, clWindow); end; function TCustomdxSpreadSheetReportLink.GetSourceCellContentPattern(ACol, ARow: Integer): TdxPSFillPatternClass; begin if IsFixedCell(ACol, ARow) then Result := TdxPSSolidFillPattern else Result := dxPSFillPatternClassMap[GetSSCellStyle(ACol, ARow).Brush.Style]; end; function TCustomdxSpreadSheetReportLink.GetSourceCellEdge3DSoft(ACol, ARow: Integer): Boolean; begin Result := True; end; function TCustomdxSpreadSheetReportLink.GetSourceCellEdgeMode(ACol, ARow: Integer): TdxCellEdgeMode; const FixedEdgeModes: array[Boolean] of TdxCellEdgeMode = (cem3DEffects, cemPattern); begin if IsFixedCell(ACol, ARow) then Result := FixedEdgeModes[ExposeSpreadSheetBook(CustomSpreadSheetBook).PainterType = ptOfficeXPStyle] else Result := cemPattern; end; function TCustomdxSpreadSheetReportLink.GetSourceCellFontIndex(ACol, ARow: Integer): Integer; procedure SetupFont(AFontRec: PcxSSFontRec; AFont: TFont); begin with AFont do begin Name := AFontRec.Name; Color := GetRealColor(AFontRec.FontColor, Self.Font.Color); Style := AFontRec.Style; Charset := AFontRec.Charset; Size := AFontRec.Size; end; if not dxIsTrueTypeFont(AFont) then AFont.Name := Self.Font.Name; end; begin if not IsFixedCell(ACol, ARow) then begin SetupFont(ExposeStyle(GetSSCellStyle(ACol, ARow)).StylePtr^.FontPtr, FTempFont); Result := AddFontToPool(FTempFont); end else Result := FSourceHeaderFontIndex; end; function TCustomdxSpreadSheetReportLink.GetSourceCellMultiline(ACol, ARow: Integer): Boolean; begin Result := not IsFixedCell(ACol, ARow) and GetSSCellStyle(ACol, ARow).WordBreak; end; function TCustomdxSpreadSheetReportLink.GetSourceCellTextAlignX(ACol, ARow: Integer): TcxTextAlignX; begin if IsFixedCell(ACol, ARow) then Result := taCenterX else Result := dxPSTextAlignXMap[GetSSCellObject(ACol, ARow).DisplayTextAlignment]; end; function TCustomdxSpreadSheetReportLink.GetSourceCellTextAlignY(ACol, ARow: Integer): TcxTextAlignY; begin if IsFixedCell(ACol, ARow) then Result := taBottom else Result := dxPSTextAlignYMap[GetSSCellStyle(ACol, ARow).VertTextAlign]; end; function TCustomdxSpreadSheetReportLink.GetSourceCellTransparent(ACol, ARow: Integer): Boolean; begin if not IsFixedCell(ACol, ARow) then begin Result := inherited GetSourceCellTransparent(ACol, ARow); if Result then Result := (GetSSCellStyle(ACol, ARow).Brush.Style = fsSolid) and (GetSourceCellColor(ACol, ARow) = ColorToRGB(clWindow)); end else Result := FixedTransparent; end; function TCustomdxSpreadSheetReportLink.GetSourceColWidth(ACol: Integer): Integer; begin with ExposeSpreadSheetBook(CustomSpreadSheetBook) do if IsFixedCol(ACol) then Result := RowHeaderWidth else Result := ActiveSheet.Cols.Size[ACol - 1]; Result := MulDiv(Result, Screen.PixelsPerInch, 96); end; function TCustomdxSpreadSheetReportLink.GetSourceRowHeight(ARow: Integer): Integer; begin with ExposeSpreadSheetBook(CustomSpreadSheetBook) do if IsFixedRow(ARow) then Result := ColHeaderHeight else begin Result := ActiveSheet.Rows.Size[ARow - 1]; Result := MulDiv(Result, 96, Screen.PixelsPerInch); end; if Result > 3 then Inc(Result, 3); Result := MulDiv(Result, Screen.PixelsPerInch, 96); end; function TCustomdxSpreadSheetReportLink.HasSelection: Boolean; begin Result := inherited HasSelection or PrintAreaExists; end; function TCustomdxSpreadSheetReportLink.IsDrawBorder: Boolean; begin Result := True;//ssovGridLines in OptionsView; end; function TCustomdxSpreadSheetReportLink.IsDrawHorzLines: Boolean; begin Result := ssovGridLines in OptionsView; end; function TCustomdxSpreadSheetReportLink.IsDrawVertLines: Boolean; begin Result := ssovGridLines in OptionsView; end; function TCustomdxSpreadSheetReportLink.IsProcessedCol(ACol: Integer): Boolean; begin Result := inherited IsProcessedCol(ACol); if Result then if IsFixedCol(ACol) then Result := IsShowRowAndColumnHeadings else Result := ExposeSpreadSheetBook(CustomSpreadSheetBook).ActiveSheet.Cols.Visible[ACol - 1]; end; function TCustomdxSpreadSheetReportLink.IsProcessedRow(ARow: Integer): Boolean; begin Result := inherited IsProcessedRow(ARow); if Result then if IsFixedRow(ARow) then Result := IsShowRowAndColumnHeadings else with ExposeSpreadSheetBook(CustomSpreadSheetBook) do Result := ActiveSheet.Rows.Visible[ARow - 1]; end; procedure TCustomdxSpreadSheetReportLink.AfterConstruct(AReportCells: TdxReportCells); begin FColCount := -1; FRowCount := -1; FGridAdapter.FReportCells := nil; DeleteCellObjects; inherited; end; procedure TCustomdxSpreadSheetReportLink.PrepareConstruct(AReportCells: TdxReportCells); begin FExtraColumnCount := 0; FCellObjects.Count := ColCount * RowCount - 1; FGridAdapter.FReportCells := AReportCells; FSourceHeaderFontIndex := AddFontToPool(ExposeSpreadSheetBook(CustomSpreadSheetBook).HeaderFont); inherited; end; procedure TCustomdxSpreadSheetReportLink.UnprepareConstruct(AReportCells: TdxReportCells); begin if not AbortBuilding then begin if HasMerges then AddMerges(AReportCells); CalcTextExtents(FGridAdapter); if not HasSelection then AppendAdditionalColumns(FGridAdapter); DeleteUnneededCellSides(FGridAdapter); PostProcessItems(FGridAdapter); FixupRowWidths(FGridAdapter); end; inherited; end; procedure TCustomdxSpreadSheetReportLink.AddMerges(AReportCells: TdxReportCells); function IntersectRect(R1, R2: TRect): Boolean; begin Inc(R1.Right); Inc(R1.Bottom); Inc(R2.Right); Inc(R2.Bottom); Result := Windows.IntersectRect(R1, R1, R2); end; var SelRect, R: TRect; LeftOffset, TopOffset, I, ACol, ARow: Integer; Overlay, Cell: TdxReportCell; DataClass: TdxReportCellDataClass; DataItem: TAbstractdxReportCellData; begin FProcessingMerges := True; try SelRect := Rect(0, 0, 0, 0); LeftOffset := 0; TopOffset := 0; if HasSelection then begin SelRect := GetSelectionRect; LeftOffset := GetColumnOffset(SelRect.Left); TopOffset := GetRowOffset(SelRect.Top); if IsShowRowAndColumnHeadings then begin Dec(LeftOffset, ColumnWidths[0]); if not HeadersOnEveryPage then Dec(TopOffset, RowHeights[0]); end; end else if not IsShowRowAndColumnHeadings then begin Inc(LeftOffset, ColumnWidths[0]); Inc(TopOffset, RowHeights[0]); end else if HeadersOnEveryPage then Inc(TopOffset, RowHeights[0]); Overlay := AReportCells.AddOverlay; for I := 0 to MergedCells.Count - 1 do begin R := MergedCells.MergedAsRect[I]; OffsetRect(R, 1, 1); if HasSelection and not IntersectRect(R, SelRect) then Continue; ACol := R.Left; ARow := R.Top; R.Left := GetColumnOffset(R.Left); R.Top := GetRowOffset(R.Top); R.Right := GetColumnOffset(R.Right + 1); R.Bottom := GetRowOffset(R.Bottom + 1); OffsetRect(R, -LeftOffset, -TopOffset); Cell := TdxReportCell.Create(Overlay); Cell.BoundsRect := R; Cell.Transparent := True; Cell.CellSides := []; DataClass := GetDataItemClass(ACol); if DataClass <> nil then begin DataItem := DataClass.Create(Cell); OffsetRect(R, -R.Left, -R.Top); DataItem.BoundsRect := R; AssignData(ACol, ARow, DataItem); DataItem.CellSides := []; //DataItem.Transparent := False;//True; end; end; finally FProcessingMerges := False; end; end; procedure TCustomdxSpreadSheetReportLink.CheckPrintAreaBounds(var R: TRect); begin if not EqualRect(R, dxPSEmptySSPrintArea) then with R do begin if Left < 0 then Left :=0; if Top < 0 then Top := 0; if Right < Left then Right := Left; if Bottom < Top then Bottom := Top; end; end; function TCustomdxSpreadSheetReportLink.GetColumnOffset(ACol: Integer): Integer; var I: Integer; begin Result := 0; for I := 0 to ACol - 1 do Inc(Result, ColumnWidths[I]); end; function TCustomdxSpreadSheetReportLink.GetRowOffset(ARow: Integer): Integer; var I: Integer; begin Result := 0; for I := 0 to ARow - 1 do Inc(Result, RowHeights[I]); end; function TCustomdxSpreadSheetReportLink.IsMergedBorder(ACol, ARow: Integer; ASide: TdxCellSide): Boolean; function CellInRect(const R: TRect; X, Y: Integer): Boolean; begin Result := (X >= R.Left) and (X <= R.Right) and (Y >= R.Top) and (Y <= R.Bottom); end; var I: Integer; R: TRect; begin Result := IsMergedCell(ACol, ARow); if Result then for I := 0 to MergedCells.Count - 1 do begin R := MergedCells.MergedAsRect[I]; OffsetRect(R, 1, 1); if CellInRect(R, ACol, ARow) then begin case ASide of csLeft: Result := ACol = R.Left; csTop: Result := ARow = R.Top; csRight: Result := ACol = R.Right; csBottom: Result := ARow = R.Bottom; end; if Result then Exit; end; //Result := (ACol = R.Left) or (ACol = R.Right) or (ARow = R.Top) or (ARow = R.Bottom); end; end; function TCustomdxSpreadSheetReportLink.IsMergedCell(ACol, ARow: Integer): Boolean; begin Result := not IsFixedCell(ACol, ARow) and ExposeStyle(GetSSCellStyle(ACol, ARow)).Merge; end; function TCustomdxSpreadSheetReportLink.IsNearMostLeftCell(ACol, ARow: Integer): Boolean; var R: TRect; begin if IsShowRowAndColumnHeadings then begin if HasSelection then begin R := GetSelectionRect; Dec(R.Left); Dec(ACol, R.Left); end; Result := ACol = 1 end else Result := False;//ACol = 0; end; function TCustomdxSpreadSheetReportLink.IsNearMostTopCell(ACol, ARow: Integer): Boolean; var R: TRect; begin if IsShowRowAndColumnHeadings then begin if HasSelection then begin R := GetSelectionRect; Dec(R.Top); Dec(ARow, R.Top); end; Result := ARow = 1 end else Result := False;//ARow = 0; end; function TCustomdxSpreadSheetReportLink.IsShowGridLines: Boolean; begin Result := ssovGridLines in OptionsView; end; function TCustomdxSpreadSheetReportLink.IsShowRowAndColumnHeadings: Boolean; begin Result := ssovRowAndColumnHeadings in OptionsView; end; function TCustomdxSpreadSheetReportLink.IsSuppressSourceFormats: Boolean; begin Result := ssovSuppressSourceFormats in OptionsView; end; procedure TCustomdxSpreadSheetReportLink.AppendAdditionalColumns(AnAdapter: TdxPSGridCellsAdapter); function DoCalcExtraColumnCount(AnAdapter: TdxPSGridCellsAdapter; ADefaultColumnWidth: Integer): Integer; var Col, Row, Index, CurrentColumnOffset: Integer; Item: TdxReportCellSSString; begin Result := AnAdapter.ColCount; for Row := 0 to AnAdapter.RowCount - 1 do for Col := 0 to AnAdapter.ColCount - 1 do begin Item := AnAdapter[Col, Row]; if Item.TextExtentRight <> 0 then begin Index := Col; CurrentColumnOffset := AnAdapter.ColOffsets[Index]; while Item.TextExtentRight > CurrentColumnOffset do begin Inc(Index); if Index <= AnAdapter.ColCount then CurrentColumnOffset := AnAdapter.ColOffsets[Index] else Inc(CurrentColumnOffset, ADefaultColumnWidth); end; if Index > Result then Result := Index; end; end; Dec(Result, AnAdapter.ColCount); end; function FindNearestVisibleColIndex(AStartIndex: Integer): Integer; begin Result := AStartIndex; with ExposeSpreadSheetBook(CustomSpreadSheetBook).ActiveSheet.Cols do while not Visible[Result - 1] do Inc(Result); end; procedure DoAppendExtraColumns(AnAdapter: TdxPSGridCellsAdapter; AExtraColumnCount, ADefaultColumnWidth: Integer); var L, Row, Col, StartRealCol, RealCol: Integer; Item: TdxReportCellSSString; Cell: TdxReportCell; R: TRect; begin L := AnAdapter.ColOffsets[AnAdapter.ColCount]; StartRealCol := AnAdapter.Cells[AnAdapter.ColCount - 1, 0].RealCol; for Row := 0 to AnAdapter.RowCount - 1 do begin Item := nil; Cell := AnAdapter.Rows[Row]; R := Bounds(L, 0, 0, Cell.Height); RealCol := StartRealCol; for Col := 0 to AExtraColumnCount - 1 do begin R.Left := R.Right; R.Right := R.Left + ADefaultColumnWidth; Item := TdxReportCellSSString.Create(Cell); Item.BoundsRect := R; Item.IsVirtual := True; RealCol := FindNearestVisibleColIndex(RealCol + 1); AssignData(RealCol, AnAdapter.RowIndexes[Row], Item); if Item.IsFixed then Item.Text := TcxSSUtils.ColumnNameByIndex(RealCol - 1, CustomSpreadSheetBook.R1C1ReferenceStyle); end; Cell.Width := Item.BoundsRect.Right; end; end; var DefaultColumnWidth: Integer; begin FAppendingExtraColumns := True; try DefaultColumnWidth := ExposeSpreadSheetBook(CustomSpreadSheetBook).DefaultColWidth; FExtraColumnCount := DoCalcExtraColumnCount(FGridAdapter, DefaultColumnWidth); if ExtraColumnCount <> 0 then DoAppendExtraColumns(FGridAdapter, ExtraColumnCount, DefaultColumnWidth); finally FAppendingExtraColumns := False; end; end; procedure TCustomdxSpreadSheetReportLink.PostProcessItems(AnAdapter: TdxPSGridCellsAdapter); var Col, Row: Integer; begin for Col := 0 to AnAdapter.ColCount - 1 do for Row := 0 to AnAdapter.RowCount - 1 do with AnAdapter.Cells[Col, Row] do if not IsFixed and not IsVirtual then begin CalcBorderSubs(AnAdapter); CalcDoubleBorderSlants(AnAdapter); end; end; procedure TCustomdxSpreadSheetReportLink.CalcTextExtents(AnAdapter: TdxPSGridCellsAdapter); function NeedCalcItemTextExtents(AItem: TdxReportCellSSString): Boolean; begin with AItem do Result := not IsMerged and not IsFixed and not Multiline and not Fill and (Text <> '') and (TextAlignX in [taLeft, taCenterX, taRight]); end; procedure DoCalcItemTextExtents(AItem: TdxReportCellSSString; Col, Row: Integer); function CalcTextRightExtent(ATextWidth, ACol, ARow: Integer): Integer; var OriginalColumnOffset, CurrentColumnOffset, EndOfTextOffset, I: Integer; Item: TdxReportCellSSString; begin OriginalColumnOffset := AnAdapter.ColOffsets[ACol]; EndOfTextOffset := OriginalColumnOffset + ATextWidth; Result := 0; CurrentColumnOffset := AnAdapter.ColOffsets[ACol + 1]; for I := ACol + 1 to AnAdapter.ColCount do begin CurrentColumnOffset := AnAdapter.ColOffsets[I]; if CurrentColumnOffset > EndOfTextOffset then Break; if I < AnAdapter.ColCount then Item := AnAdapter[I, ARow] else Item := nil; if (Item <> nil) and (Item.IsMerged or (Item.Text <> '')) then begin Result := CurrentColumnOffset; Break; end end; if Result = 0 then begin Result := EndOfTextOffset; if (Result > CurrentColumnOffset) and HasSelection then Result := CurrentColumnOffset + dxTextSpace; if Result < AnAdapter.ColOffsets[ACol + 1] then Result := 0; end; end; function CalcTextLeftExtent(ATextWidth, ACol, ARow: Integer): Integer; var TextLeftEdge, I, CurrentColumnOffset: Integer; Item: TdxReportCellSSString; begin TextLeftEdge := AnAdapter.ColOffsets[ACol + 1] - ATextWidth; if TextLeftEdge < 0 then TextLeftEdge := 0; Result := 0; for I := ACol downto 0 do begin if I > 0 then Item := AnAdapter[I - 1, ARow] else Item := nil; CurrentColumnOffset := AnAdapter.ColOffsets[I]; if CurrentColumnOffset < TextLeftEdge then Break; if (Item = nil) or Item.IsFixed or Item.IsMerged or (Item.Text <> '') then begin Result := CurrentColumnOffset; Break; end end; if Result = 0 then begin Result := TextLeftEdge; if Result > AnAdapter.ColOffsets[ACol] then Result := 0; end; end; var TextWidth: Integer; begin TextWidth := GetTextWidth(ScreenDC, AItem.Font.Handle, AItem.Text); case AItem.TextAlignX of taLeft: AItem.TextExtentRight := CalcTextRightExtent(TextWidth + 3 * dxTextSpace, Col, Row); taCenterX: begin Dec(TextWidth, (TextWidth - AItem.Width) div 2); AItem.TextExtentRight := CalcTextRightExtent(TextWidth + 1 * dxTextSpace, Col, Row); AItem.TextExtentLeft := CalcTextLeftExtent(TextWidth + 1 * dxTextSpace, Col, Row); end; taRight: AItem.TextExtentLeft := CalcTextLeftExtent(TextWidth + 3 * dxTextSpace, Col, Row); end; end; var Font: HFONT; Col, Row: Integer; Item: TdxReportCellSSString; begin Font := GetCurrentObject(ScreenDC, OBJ_FONT); for Col := 0 to AnAdapter.ColCount - 1 do for Row := 0 to AnAdapter.RowCount - 1 do begin Item := AnAdapter[Col, Row]; if NeedCalcItemTextExtents(Item) then DoCalcItemTextExtents(Item, Col, Row); end; SelectObject(ScreenDC, Font); end; procedure TCustomdxSpreadSheetReportLink.DeleteCellObjects; var I: Integer; begin for I := 0 to FCellObjects.Count - 1 do TObject(FCellObjects[I]).Free; FCellObjects.Clear; end; procedure TCustomdxSpreadSheetReportLink.DeleteUnneededCellSides(AnAdapter: TdxPSGridCellsAdapter); procedure DoDeleteUnneededCellSidesFromRightSide(AItem: TdxReportCellSSString; ACol: Integer); var TextRightExtent, Col, CurrentColumnOffset: Integer; begin TextRightExtent := AItem.TextExtentRight; for Col := ACol + 1 to AnAdapter.ColCount - 1 do begin CurrentColumnOffset := AnAdapter.ColOffsets[Col]; if CurrentColumnOffset < TextRightExtent then begin AItem.CellSides := AItem.CellSides - [csRight]; AItem := TdxReportCellSSString(AItem.GetNextSibling); if AItem = nil then Break; AItem.CellSides := AItem.CellSides - [csLeft]; end; end; end; procedure DoDeleteUnneededCellSidesFromLeftSide(AItem: TdxReportCellSSString; ACol: Integer); var TextLeftExtent, Col, CurrentColumnOffset: Integer; begin TextLeftExtent := AItem.TextExtentLeft; for Col := ACol downto 0 do begin CurrentColumnOffset := AnAdapter.ColOffsets[Col]; if CurrentColumnOffset > TextLeftExtent then begin AItem.CellSides := AItem.CellSides - [csLeft]; AItem := TdxReportCellSSString(AItem.GetPrevSibling); if (AItem = nil) or AItem.IsFixed then Break; AItem.CellSides := AItem.CellSides - [csRight]; end; end; end; var Col, Row: Integer; Item: TdxReportCellSSString; begin for Row := 0 to AnAdapter.RowCount - 1 do for Col := 0 to AnAdapter.ColCount - 1 do begin Item := AnAdapter[Col, Row]; if Item.TextExtentRight <> 0 then DoDeleteUnneededCellSidesFromRightSide(Item, Col); if Item.TextExtentLeft <> 0 then DoDeleteUnneededCellSidesFromLeftSide(Item, Col); end; end; procedure TCustomdxSpreadSheetReportLink.FixupRowWidths(AnAdapter: TdxPSGridCellsAdapter); var MaxWidth, I: Integer; begin with AnAdapter do begin MaxWidth := 0; for I := 0 to ColCount - 1 do Inc(MaxWidth, ColWidths[I]); for I := 0 to RowCount - 1 do Rows[I].Width := MaxWidth; end; end; function TCustomdxSpreadSheetReportLink.HasMerges: Boolean; begin Result := MergedCells.Count <> 0; end; function TCustomdxSpreadSheetReportLink.IsEmptyCell(const ACell: TcxSSCellRec): Boolean; var DefaultStyle: TcxSSCellStyleRec; begin DefaultStyle := ExposeDataStorage(GetSSDataStorage).DefaultCellRec.StylePtr^; Result := IsCellDataEmpty(ACell) and AreStylesEqual(DefaultStyle, ACell.StylePtr^); end; function TCustomdxSpreadSheetReportLink.OnlyEdgeIsAssigned(const ACell: TcxSSCellRec; AEdge: TcxSSEdgeBorder): Boolean; var DefaultStyle: TcxSSCellStyleRec; begin DefaultStyle := ExposeDataStorage(GetSSDataStorage).DefaultCellRec.StylePtr^; Result := IsCellDataEmpty(ACell) and AreStylesEqual(DefaultStyle, ACell.StylePtr^, [AEdge]); end; function TCustomdxSpreadSheetReportLink.OnlyLeftEdgeIsAssigned(ACell: TcxSSCellRec): Boolean; begin Result := OnlyEdgeIsAssigned(ACell, eLeft); end; function TCustomdxSpreadSheetReportLink.OnlyTopEdgeIsAssigned(ACell: TcxSSCellRec): Boolean; begin Result := OnlyEdgeIsAssigned(ACell, eTop); end; procedure TCustomdxSpreadSheetReportLink.SetupCellBorders(ACol, ARow: Integer; ADataItem: TAbstractdxReportCellData); var DefaultAutoColor, DefaultColor: TColor; Style: TcxSSCellStyle; Side: TdxCellSide; Border: TdxPSCellBorder; begin if not IsFixedCell(ACol, ARow) then begin DefaultAutoColor := ColorToRGB(clWindowText); DefaultColor := ColorToRGB(ExposeSpreadSheetBook(CustomSpreadSheetBook).GridColor); if IsSuppressSourceFormats then Style := nil else Style := GetSSCellStyle(ACol, ARow); for Side := csLeft to csBottom do if Side in ADataItem.CellSides then begin if Style <> nil then begin with Style.Borders.Edges[cxSSEdgeBorderMap[Side]] do begin Border.Pattern := dxPSEdgePatternClassMap[Style]; if Style = lsDefault then Border.Color := GetRealColor(Color, DefaultColor) else Border.Color := GetRealColor(Color, DefaultAutoColor); end; if IsSSDefaultStyle(Style) then Border.Color := GetRealColor(GetSSDefaultCellSideColor(Side), DefaultColor); end else if not IsMergedCell(ACol, ARow) then begin Border.Color := GetRealColor(GetSSDefaultCellSideColor(Side), ColorToRGB(GridLineColor)); Border.Pattern := TdxPSSolidEdgePattern; end else Border.Pattern := nil; TdxReportCellSSString(ADataItem).Borders[Side] := Border; end; end end; function TCustomdxSpreadSheetReportLink.GetBookSheet: TcxSSBookSheet; begin if CustomSpreadSheetBook = nil then Result := nil else Result := ExposeSpreadSheetBook(CustomSpreadSheetBook).ActiveSheet; end; function TCustomdxSpreadSheetReportLink.GetCustomSpreadSheetBook: TcxCustomSpreadSheetBook; begin Result := TcxCustomSpreadSheetBook(Component); end; function TCustomdxSpreadSheetReportLink.GetMeaningColCount: Integer; var Storage: TcxSSDataStorageAccess; Col, Row, CandidateCol: Integer; Cell: TcxSSCellRec; R: TRect; begin Result := -1; CandidateCol := 0; Storage := ExposeDataStorage(GetSSDataStorage); for Row := 0 to Storage.Capacity.cY - 1 do begin for Col := Storage.Capacity.cX - 1 downto 0 do begin Cell := Storage.Cells[Col, Row]; if not IsEmptyCell(Cell) then begin CandidateCol := Col; if (CandidateCol > 0) and OnlyLeftEdgeIsAssigned(Cell) then Dec(CandidateCol); Break; end; end; if CandidateCol > Result then Result := CandidateCol; end; for Col := 0 to MergedCells.Count - 1 do begin R := Storage.MergedCells.MergedAsRect[Col]; if R.Right > Result then Result := R.Right; end; if Result > -1 then Inc(Result); end; function TCustomdxSpreadSheetReportLink.GetMeaningRowCount: Integer; var Storage: TcxSSDataStorageAccess; CandidateRow, Col, Row: Integer; Cell: TcxSSCellRec; IsBreaked: Boolean; R: TRect; begin Storage := ExposeDataStorage(GetSSDataStorage); CandidateRow := -1; for Row := Storage.Capacity.cY - 1 downto 0 do begin IsBreaked := False; for Col := 0 to Storage.Capacity.cX - 1 do begin Cell := Storage.Cells[Col, Row]; if not IsEmptyCell(Cell) then begin CandidateRow := Row; if (CandidateRow = 0) or not OnlyTopEdgeIsAssigned(Cell) then begin IsBreaked := True; Break; end; end; end; if CandidateRow <> -1 then begin if not IsBreaked then Dec(CandidateRow); Break; end; end; Result := CandidateRow; for Col := 0 to Storage.MergedCells.Count - 1 do begin R := Storage.MergedCells.MergedAsRect[Col]; if R.Bottom > Result then Result := R.Bottom; end; Result := Min(Result, Storage.MaxRow + 1); if Result > -1 then Inc(Result); end; function TCustomdxSpreadSheetReportLink.GetMergedCells: TcxSSMergedCellsStorage; begin Result := ExposeDataStorage(ExposeBookSheet(BookSheet).DataStorage).MergedCells; end; procedure TCustomdxSpreadSheetReportLink.SetOptionsView(Value: TdxPSSpreadSheetReportLinkOptionsView); begin if FOptionsView <> Value then begin FOptionsView := Value; if ssovSuppressSourceFormats in FOptionsView then DrawMode := gdmStrict else DrawMode := gdmBorrowSource; LinkModified(True); end; end; procedure TCustomdxSpreadSheetReportLink.SetPrintArea(Value: TRect); begin CheckPrintAreaBounds(Value); if not EqualRect(Value, FPrintArea) then begin FPrintArea := Value; LinkModified(True); end; end; function TCustomdxSpreadSheetReportLink.GetSSCellObject(ACol, ARow: Integer): TcxSSCellObject; var Index: Integer; begin Index := GetFlatIndex(ACol - 1, ARow - 1); if Index > FCellObjects.Count - 1 then // ExtraColumns Result := nil else Result := FCellObjects.List^[Index]; if Result = nil then begin Result := ExposeActiveSpreadSheet(CustomSpreadSheetBook).GetCellObject(ACol - 1, ARow - 1); if Index > FCellObjects.Count - 1 then FCellObjects.Count := Index + 1; FCellObjects.List^[Index] := Result; end; end; function TCustomdxSpreadSheetReportLink.GetSSCellStyle(ACol, ARow: Integer): TcxSSCellStyle; var CellObject: TcxSSCellObject; begin if not FAppendingExtraColumns then begin CellObject := GetSSCellObject(ACol, ARow); if (CellObject <> nil) and CellObject.StyleExist then Result := CellObject.Style else Result := GetSSDefaultStyle; end else Result := GetSSDefaultStyle; end; function TCustomdxSpreadSheetReportLink.GetSSColorPalette: PcxExcelPalette; begin Result := ExposeSpreadSheetBook(CustomSpreadSheetBook).Palette; end; function TCustomdxSpreadSheetReportLink.GetSSDataStorage: TcxSSDataStorage; begin Result := ExposeBookSheet(BookSheet).DataStorage; end; function TCustomdxSpreadSheetReportLink.GetSSDefaultCellSideColor(ASide: TdxCellSide): TColor; begin with ExposeSpreadSheetBook(CustomSpreadSheetBook), DefaultStyle.Borders do if ASide in csLeftRight then if VerticalBorders.Style <> lsDefault then Result := VerticalBorders.Color else Result := ColorToRGB(GridColor) else if HorizontalBorders.Style <> lsDefault then Result := HorizontalBorders.Color else Result := ColorToRGB(GridColor); end; function TCustomdxSpreadSheetReportLink.GetSSDefaultStyle: TcxSSCellStyle; begin Result := ExposeSpreadSheetBook(CustomSpreadSheetBook).StyleCache.DefaultStyle; end; function TCustomdxSpreadSheetReportLink.GetFlatIndex(ACol, ARow: Integer): Integer; begin Result := ARow * (ColCount - 1) + ACol; end; function TCustomdxSpreadSheetReportLink.GetRealColor(AColorIndex: Integer; ADefaultColor: TColor): TColor; begin if AColorIndex > SystemColorStart then Result := ADefaultColor else Result := GetSSColorPalette^[AColorIndex]; Result := ColorToRGB(Result); end; function TCustomdxSpreadSheetReportLink.IsSSDefaultStyle(AStyle: TcxSSCellStyle): Boolean; begin Result := AStyle = GetSSDefaultStyle; end; { TdxSpreadSheetBookReportLink } function TdxSpreadSheetBookReportLink.GetSpreadSheetBook: TcxSpreadSheetBook; begin Result := TcxSpreadSheetBook(Component); end; { TdxSpreadSheetReportLink } function TdxSpreadSheetReportLink.GetSpreadSheet: TcxSpreadSheet; begin Result := TcxSpreadSheet(Component); end; { TfmdxSpreadSheetDesignWindow } constructor TfmdxSpreadSheetDesignWindow.Create(AOwner: TComponent); begin HelpContext := dxhccxSpreadSheetReportLinkDesigner; inherited; CreateControls; pgctrlMain.ActivePage := pgctrlMain.Pages[0]; end; procedure TfmdxSpreadSheetDesignWindow.DoInitialize; begin inherited; chbxShowRowAndColumnHeadings.Checked := ssovRowAndColumnHeadings in ReportLink.OptionsView; chbxShowGridLines.Checked := ssovGridLines in ReportLink.OptionsView; // chbxAutoWidth.Checked := ReportLink.AutoWidth; chbxRowAutoHeight.Checked := ReportLink.RowAutoHeight; chbxSuppressSourceFormats.Checked := ssovSuppressSourceFormats in ReportLink.OptionsView; chbxTransparent.Checked := ReportLink.Transparent; TdxPSColorCombo(FccbxColor).ColorValue := ReportLink.Color; chbxFixedTransparent.Checked := ReportLink.FixedTransparent; TdxPSColorCombo(FccbxFixedColor).ColorValue := ReportLink.FixedColor; TdxPSColorCombo(FccbxGridLineColor).ColorValue := ReportLink.GridLineColor; FontInfoToText(ReportLink.Font, edFont); FontInfoToText(ReportLink.FixedFont, edFixedFont); chbxFixedRowsOnEveryPage.Checked := ReportLink.HeadersOnEveryPage; chbxOnlySelected.Checked := ReportLink.OnlySelected; end; {$IFDEF DELPHI7} function TfmdxSpreadSheetDesignWindow.GetPreviewHost: TCustomPanel; begin Result := pnlPreview; end; {$ENDIF} procedure TfmdxSpreadSheetDesignWindow.LoadStrings; begin inherited; tshOptions.Caption := cxGetResourceString(@sdxOptions); tshFont.Caption := cxGetResourceString(@sdxFonts); tshColor.Caption := cxGetResourceString(@sdxColors); tshBehaviors.Caption := cxGetResourceString(@sdxBehaviors); lblPreview.Caption := DropAmpersand(cxGetResourceString(@sdxPreview)); lblShow.Caption := cxGetResourceString(@sdxShow); chbxShowRowAndColumnHeadings.Caption := cxGetResourceString(@sdxShowRowAndColumnHeadings); chbxShowGridLines.Caption := cxGetResourceString(@sdxShowGridLines); lblMiscellaneous.Caption := cxGetResourceString(@sdxMiscellaneous); //chbxAutoWidth.Caption := cxGetResourceString(@sdxAutoWidth); chbxRowAutoHeight.Caption := cxGetResourceString(@sdxRowAutoHeight); chbxSuppressSourceFormats.Caption := cxGetResourceString(@sdxSuppressSourceFormats); stTransparent.Caption := ' ' + cxGetResourceString(@sdxTransparent) + ' '; lblColor.Caption := cxGetResourceString(@sdxColor); stFixedTransparent.Caption := ' ' + cxGetResourceString(@sdxFixedTransparent) + ' '; lblFixedColor.Caption := cxGetResourceString(@sdxFixedColor); lblGridLinesColor.Caption := cxGetResourceString(@sdxGridLinesColor); btnFont.Caption := cxGetResourceString(@sdxBtnFont); btnFixedFont.Caption := cxGetResourceString(@sdxBtnFixedFont); lblOnEveryPage.Caption := cxGetResourceString(@sdxOnEveryPage); chbxFixedRowsOnEveryPage.Caption := cxGetResourceString(@sdxRepeatHeaderRowAtTop); lblSelection.Caption := cxGetResourceString(@sdxSelection); chbxOnlySelected.Caption := cxGetResourceString(@sdxOnlySelected); end; procedure TfmdxSpreadSheetDesignWindow.PaintPreview(ACanvas: TCanvas; R: TRect); begin inherited; dxPSBaseGridLnk.dxPSDrawGridPreview(ACanvas, R, ReportLink, ReportLink.IsShowRowAndColumnHeadings, ReportLink.IsShowRowAndColumnHeadings); end; procedure TfmdxSpreadSheetDesignWindow.UpdateControlsState; begin inherited; FccbxColor.Enabled := not chbxTransparent.Checked; lblColor.Enabled := FccbxColor.Enabled; FccbxFixedColor.Enabled := not chbxFixedTransparent.Checked; lblFixedColor.Enabled := FccbxFixedColor.Enabled; chbxFixedRowsOnEveryPage.Enabled := not ReportLink.IsAggregated; end; procedure TfmdxSpreadSheetDesignWindow.UpdatePreview; begin FPreviewBox.Invalidate; end; function TfmdxSpreadSheetDesignWindow.GetReportLink: TCustomdxSpreadSheetReportLink; begin Result := inherited ReportLink as TCustomdxSpreadSheetReportLink; end; procedure TfmdxSpreadSheetDesignWindow.SetReportLink(Value: TCustomdxSpreadSheetReportLink); begin inherited ReportLink := Value; end; procedure TfmdxSpreadSheetDesignWindow.CreateControls; function CreateColorCombo(AHost: TBevel; ALabel: TLabel; ATag: Integer; AnAutoColor: TColor): TdxPSColorCombo; begin Result := TdxPSColorCombo.Create(Self); with Result do begin BoundsRect := AHost.BoundsRect; Tag := ATag; Parent := AHost.Parent; ColorTypes := [ctPure]; ShowColorName := True; ShowAutoColor := True; AutoColor := AnAutoColor; OnChange := ccbxColorChange; end; ALabel.FocusControl := Result; end; function CreatePreviewBox(AParent: TWinControl) : TdxPSPaintPanel; begin Result := TdxPSPaintPanel.Create(Self); with Result do begin Parent := AParent; Align := alClient; EdgeInner := esNone; EdgeOuter := esNone; OnPaint := pbxPreviewPaint; end; end; begin FccbxColor := CreateColorCombo(bvlColorHolder, lblColor, 0, dxDefaultColor); FccbxFixedColor := CreateColorCombo(bvlFixedColorHolder, lblFixedColor, 1, dxDefaultFixedColor); FccbxGridLineColor := CreateColorCombo(bvlLineColorHolder, lblGridLinesColor, 2, dxDefaultGridLineColor); FPreviewBox := CreatePreviewBox(pnlPreview); end; procedure TfmdxSpreadSheetDesignWindow.CMDialogChar(var Message: TCMDialogChar); var I: Integer; begin inherited; with pgctrlMain do for I := 0 to PageCount - 1 do if IsAccel(Message.CharCode, Pages[I].Caption) then begin Message.Result := 1; ActivePage := Pages[I]; Exit; end; end; procedure TfmdxSpreadSheetDesignWindow.pbxPreviewPaint(Sender: TObject); begin with TdxPSPaintPanel(Sender) do PaintPreview(Canvas, ClientRect); end; procedure TfmdxSpreadSheetDesignWindow.chbxFixedRowsOnEveryPageClick(Sender: TObject); begin if LockControlsUpdate then Exit; ReportLink.HeadersOnEveryPage := TCheckBox(Sender).Checked; Modified := True; end; procedure TfmdxSpreadSheetDesignWindow.chbxOnlySelectedClick(Sender: TObject); begin if LockControlsUpdate then Exit; ReportLink.OnlySelected := TCheckBox(Sender).checked; Modified := True; end; procedure TfmdxSpreadSheetDesignWindow.ccbxColorChange(Sender: TObject); var Color: TColor; begin if LockControlsUpdate then Exit; Color := TdxPSColorCombo(Sender).ColorValue; case TdxPSColorCombo(Sender).Tag of 0: ReportLink.Color := Color; 1: ReportLink.FixedColor := Color; 2: ReportLink.GridLineColor := Color; end; Modified := True; UpdatePreview; end; procedure TfmdxSpreadSheetDesignWindow.btnFixedFontClick(Sender: TObject); function GetEdit: TEdit; begin if TButton(Sender).Tag = 0 then Result := edFont else Result := edFixedFont; end; begin if LockControlsUpdate then Exit; with dxPSGlbl.FontDialog do begin case TButton(Sender).Tag of 0: Font := ReportLink.Font; 1: Font := ReportLink.FixedFont; end; if Execute then begin case TButton(Sender).Tag of 0: ReportLink.Font := Font; 1: ReportLink.FixedFont := Font; end; FontInfoToText(Font, GetEdit); Modified := True; UpdatePreview; end; end; end; procedure TfmdxSpreadSheetDesignWindow.chbxRowAutoHeightClick( Sender: TObject); begin if LockControlsUpdate then Exit; ReportLink.RowAutoHeight := TCheckBox(Sender).Checked; Modified := True; end; procedure TfmdxSpreadSheetDesignWindow.chbxSuppressSourceFormatsClick( Sender: TObject); begin if LockControlsUpdate then Exit; with ReportLink do if TCheckBox(Sender).Checked then OptionsView := OptionsView + [ssovSuppressSourceFormats] else OptionsView := OptionsView - [ssovSuppressSourceFormats]; Modified := True; UpdatePreview; end; procedure TfmdxSpreadSheetDesignWindow.chbxShowRowAndColumnHeadingsClick( Sender: TObject); begin if LockControlsUpdate then Exit; with ReportLink do if TCheckBox(Sender).Checked then OptionsView := OptionsView + [ssovRowAndColumnHeadings] else OptionsView := OptionsView - [ssovRowAndColumnHeadings]; Modified := True; UpdatePreview; end; procedure TfmdxSpreadSheetDesignWindow.chbxShowGridLinesClick( Sender: TObject); begin if LockControlsUpdate then Exit; with ReportLink do if TCheckBox(Sender).Checked then OptionsView := OptionsView + [ssovGridLines] else OptionsView := OptionsView - [ssovGridLines]; Modified := True; UpdatePreview; end; procedure TfmdxSpreadSheetDesignWindow.chbxFixedTransparentClick( Sender: TObject); begin if LockControlsUpdate then Exit; case TCheckBox(Sender).Tag of 0: ReportLink.Transparent := TCheckBox(Sender).checked; 1: ReportLink.FixedTransparent := TCheckBox(Sender).checked; end; Modified := True; UpdatePreview; end; procedure TfmdxSpreadSheetDesignWindow.stTransparentClick(Sender: TObject); begin if chbxTransparent.CanFocus then ActiveControl := chbxTransparent; chbxTransparent.Checked := not chbxTransparent.Checked; end; procedure TfmdxSpreadSheetDesignWindow.stFixedTransparentClick(Sender: TObject); begin if chbxFixedTransparent.CanFocus then ActiveControl := chbxFixedTransparent; chbxFixedTransparent.Checked := not chbxFixedTransparent.Checked; end; procedure TfmdxSpreadSheetDesignWindow.lblColorClick(Sender: TObject); begin ActiveControl := TLabel(Sender).FocusControl; TCustomComboBox(ActiveControl).DroppedDown := True; end; procedure TfmdxSpreadSheetDesignWindow.pgctrlMainChange(Sender: TObject); begin lblPreview.Parent := TPageControl(Sender).ActivePage; end; procedure RegisterItems; begin TdxReportCellSSString.Register; end; procedure UnregisterItems; begin TdxReportCellSSString.Unregister; end; procedure RegisterAssistants; begin TdxPSSSStringGridCellDataMap.Register; end; procedure UnregisterAssistants; begin TdxPSSSStringGridCellDataMap.Unregister; end; initialization RegisterAssistants; RegisterItems; dxPSRegisterReportLink(TdxSpreadSheetBookReportLink, TcxSpreadSheetBook, TfmdxSpreadSheetDesignWindow); dxPSRegisterReportLink(TdxSpreadSheetReportLink, TcxSpreadSheet, TfmdxSpreadSheetDesignWindow); finalization dxPSUnregisterReportLink(TdxSpreadSheetReportLink, TcxSpreadSheet, TfmdxSpreadSheetDesignWindow); dxPSUnregisterReportLink(TdxSpreadSheetBookReportLink, TcxSpreadSheetBook, TfmdxSpreadSheetDesignWindow); UnregisterItems; UnregisterAssistants; end.