{********************************************************************} { } { Developer Express Visual Component Library } { ExpressPivotGrid } { } { Copyright (c) 2005-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 EXPRESSPIVOTGRID 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 cxCustomPivotGrid; {$I cxVer.inc} interface uses Classes, SysUtils, Windows, Messages, Forms, StdCtrls, Graphics, Controls, cxContainer, Types, dxCore, cxClasses, cxControls, cxGraphics, cxCustomData, cxDataStorage, cxDataUtils, cxEdit, cxStyles, cxLookAndFeels, cxLookAndFeelPainters, cxGeometry, cxDrawTextUtils, cxVariants, Math, cxDropDownEdit, cxButtons, cxCheckListBox, cxCheckBox, cxFormats, cxStorage, Variants, {$IFDEF DELPHI6} DateUtils, {$IFNDEF NONDB} FMTBcd, SqlTimSt, {$ENDIF} {$ENDIF} cxDateUtils, Menus, Clipbrd, ExtCtrls, ImgList, dxOffice11, cxFilterControl, cxFilter, cxFilterControlDialog, cxNavigator; const // styles constants gs_Background = 0; gs_ColumnHeader = 1; gs_ColumnHeaderArea = 2; gs_Content = 3; gs_DataHeaderArea = 4; gs_FieldHeader = 5; gs_FilterHeaderArea = 6; gs_FilterSeparator = 7; gs_HeaderBackground = 8; gs_Inactive = 9; gs_RowHeader = 10; gs_RowHeaderArea = 11; gs_Selected = 12; gs_Total = 13; gs_Prefilter = 14; gs_ColumnMaximumValue = 15; gs_ColumnMinimumValue = 16; gs_MaximumValue = 17; gs_MinimumValue = 18; gs_RowMaximumValue = 19; gs_RowMinimumValue = 20; gs_MaxStyleIndex = gs_RowMinimumValue; // hit test constants htcButton = 1; htcDataCell = 2; htcDataHeader = 3; htcFieldHeader = 4; htcHeaderArea = 5; htcFilter = 6; htcGroupHeader = 7; htcHorzSizingEdge = 8; htcVertSizingEdge = 9; htcPrefilter = 10; htcPrefilterCloseButton = 11; htcPrefilterActivateButton = 12; htcPrefilterCustomizationButton = 13; htcPrefilterDropDownButton = 14; htcPrefilterCaption = 15; // popup menu commands // Field commands pgcmHide = 0; pgcmMoveToBeginning = 1; pgcmMoveToEnd = 2; pgcmMoveToLeft = 3; pgcmMoveToRight = 4; // pgcmExpand = 5; pgcmCollapse = 6; pgcmExpandAll = 7; pgcmCollapseAll = 8; // Misc. commands pgcmShowCustomization = 9; pgcmHideCustomization = 10; // Prefilter commands pgcmShowPrefilterDialog = 11; cxPivotGridFilterSeparatorHeight: Integer = 1; cxPivotGridDefaultFieldWidth = 105; cxPivotGridDefaultFieldMinWidth = 20; cxPivotGridFilterPopupMinWidth = 150; cxPivotGridFilterPopupMinHeight = 15; cxPivotGridFilterPopupDefaultWidth = 150; cxPivotGridFilterPopupDefaultHeight = 150; cxPivotGridFilterMinSysPanelHeight = 26; cxPivotGridDropDownWidth = 0; cxPivotGridDropDownMaxItemCount = 15; cxPivotGridSpace = 5; cxPivotGridHorzSpace = 3; cxPivotGridHalfSpace = cxPivotGridHorzSpace div 2; cxPivotGridDoubleSpace = cxTextOffset * 2; cxPivotGridSizeAreaDelta = 3; cxPivotGridSizeMarkWidth = 2; cxPivotGridOthersRecordIndex = -2; cxPivotGridInvalidIndex = -1; cxPivotGridDefaultFieldFloatFormat: string = '0.00'; cxPivotGridDefaultFieldIntFormat: string = '0'; cxPivotGridDefaultFieldPercentFormat: string = '0.00%'; cxPivotGridDefaultGroupIntervalRange = 10; cxPivotPatternChar: Char = '#'; // cxPivotGridDropArrowColor = $00FF00; cxPivotGridAutoScrollInterval: Integer = 50; cxPivotGridAutoScrollAreaWidth: Integer = 10; // customiaztion form cxPivotGridControlsIndent = 8; cxPivotGridCustomizationMinWidth = 180; cxPivotGridCustomizationMinHeight = 180; cxPivotGridCustomizationDefaultHeight = 200; cxPivotGridCustomizationDefaultWidth = 200; WM_REFRESHCUSTOMIZATION = WM_DX + 75; type EcxPivotGrid = class(EdxException); TcxCustomPivotGrid = class; TcxPivotGridViewData = class; TcxPivotGridFilterMRUItem = class; TcxPivotGridPopupMenus = class; TcxPivotGridDataController = class; TcxPivotGridStyles = class; IcxPivotGridBaseStyles = interface; TcxPivotGridOptionsView = class; TcxPivotGridFieldGroup = class; TcxPivotGridFieldGroupCollection = class; TcxPivotGridCustomTotal = class; TcxPivotGridCustomTotalCollection = class; TcxPivotGridGroupItem = class; TcxPivotGridGroupItemClass = class of TcxPivotGridGroupItem; TcxPivotGridDataBuilder = class; TcxPivotGridCrossCell = class; TcxPivotGridCrossCellClass = class of TcxPivotGridCrossCell; TcxPivotGridCrossCellSummary = class; TcxPivotGridField = class; TcxPivotGridFieldClass = class of TcxPivotGridField; TcxPivotGridFieldFilter = class; TcxPivotGridHitTest = class; TcxPivotGridController = class; TcxPivotGridChange = (gcLayout, gcData, gcView, gcSelection); TcxPivotGridChanges = set of TcxPivotGridChange; TcxPivotGridCustomCellViewInfo = class; TcxPivotGridHeaderBackgroundCellViewInfo = class; TcxPivotGridHeaderCellViewInfo = class; TcxPivotGridFieldHeaderCellViewInfo = class; TcxPivotGridDragDropAreaInfo = class; TcxPivotGridPrefilterViewInfo = class; TcxPivotGridOptionsSelection = class; TcxPivotGridCustomOLAPDataSource = class; TcxPivotGridFieldArea = (faColumn, faRow, faFilter, faData); TcxPivotGridFieldAreas = set of TcxPivotGridFieldArea; TcxPivotGridDataFieldArea = (dfaNone, dfaColumn, dfaRow); TcxPivotGridDataFieldAreas = set of TcxPivotGridDataFieldArea; TcxPivotGridGroupInterval = (giDefault, giDate, giDateDay, giDateDayOfWeek, giDateDayOfYear, giDateWeekOfMonth, giDateWeekOfYear, giDateMonth, giDateQuarter, giDateYear, giYearAge, giMonthAge, giWeekAge, giDayAge, giAlphabetical, giNumeric, giCustom); TcxPivotGridTotalsLocation = (tlFar, tlNear, tlCustom); TcxPivotGridSummaryType = (stCount, stSum, stMin, stMax, stAverage, stStdDev, stStdDevP, stVariance, stVarianceP, stCustom); TcxPivotGridTotalsVisibility = (tvAutomatic, tvCustom, tvNone); TcxPivotGridCalculationBaseType = (cbRawData, cbVisibleData); { IcxPivotGridListener } IcxPivotGridListener = interface ['{34D8F0E7-C4E2-4F82-A85E-6EE378E7E8FA}'] procedure DataChanged(Sender: TcxCustomPivotGrid); procedure LayoutChanged(Sender: TcxCustomPivotGrid); procedure PivotRemoved(Sender: TcxCustomPivotGrid); procedure SelectionChanged(Sender: TcxCustomPivotGrid); end; {$IFNDEF DELPHI6} TListAssignOp = (laCopy, laAnd, laOr, laXor, laSrcUnique, laDestUnique); {$ENDIF} TcxList = class(TList) private public procedure Assign(AListA: TList; AOperator: TListAssignOp = laCopy; AListB: TList = nil); end; { TcxPivotGridVariantList } TcxPivotGridVariantValue = class protected FValue: Variant; FUnUsed: Boolean; public constructor Create(const AValue: Variant); function IsEqual(AValue: TcxPivotGridVariantValue): Boolean; function Compare(const AValue: Variant): Integer; property Value: Variant read FValue; end; TcxPivotGridVariantList = class private FLockCount: Integer; FModified: Boolean; FOnChange: TNotifyEvent; function GetCount: Integer; function GetItem(AIndex: Integer): TcxPivotGridVariantValue; function GetValue(AIndex: Integer): Variant; procedure SetValue(AIndex: Integer; AValue: Variant); protected FItems: TcxObjectList; Sorted: Boolean; procedure Changed; procedure MakeSorted; property OnChange: TNotifyEvent read FOnChange write FOnChange; public constructor Create; virtual; destructor Destroy; override; function Add(const AValue: Variant): Integer; function AddUnique(const AValue: Variant): Integer; procedure Clear; procedure Delete(AIndex: Integer); function IndexOf(const AValue: Variant): Integer; procedure MakeUnique; function Remove(const AValue: Variant): Integer; procedure BeginUpdate; procedure EndUpdate(AForceUpdate: Boolean = True); property Count: Integer read GetCount; property Items[Index: Integer]: TcxPivotGridVariantValue read GetItem; property Values[Index: Integer]: Variant read GetValue write SetValue; default; end; { TcxPivotGridRecords } TcxPivotGridRecords = class(TcxList) private FSorted: Boolean; function GetItem(AIndex: Integer): Integer; procedure SetItem(AIndex, AValue: Integer); protected procedure CreateIntersection(AListA, AListB: TcxPivotGridRecords); property Sorted: Boolean read FSorted write FSorted; public procedure Add(ARecordIndex: Integer); procedure MakeSorted; procedure MakeUnique; property Items[Index: Integer]: Integer read GetItem write SetItem; default; end; { TcxPivotGridFields } TcxPivotGridFields = class(TcxList) private function GetField(Index: Integer): TcxPivotGridField; function GetFirstField: TcxPivotGridField; public procedure ArrangeFields; property Fields[Index: Integer]: TcxPivotGridField read GetField; default; end; { TcxPivotGridCells } TcxPivotGridCustomDrawEvent = procedure(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean) of object; TcxPivotGridCells = class(TcxObjectList) private function GetItem(AIndex: Integer): TcxPivotGridCustomCellViewInfo; protected procedure CorrectBoundsForPrinting(ABounds: TRect); public procedure BeforePaint; function CalculateHitTest(AHitTest: TcxPivotGridHitTest): Boolean; procedure DeleteAll; procedure ExcludeFromClipping(ACanvas: TcxCanvas); procedure Paint(ACanvas: TcxCanvas; AHandler: TcxPivotGridCustomDrawEvent); virtual; property Items[Index: Integer]: TcxPivotGridCustomCellViewInfo read GetItem; default; end; TcxPivotGridPrefilterPosition = (pfpTop, pfpBottom); TcxPivotGridPrefilter = class(TcxPivotGridCells) private FPivotGrid: TcxCustomPivotGrid; function GetCanMRUPopupShow: Boolean; function GetCustomizeButtonVisible: Boolean; function GetFilter: TcxDataFilterCriteria; function GetPosition: TcxPivotGridPrefilterPosition; function GetViewInfo: TcxPivotGridPrefilterViewInfo; function GetVisible: Boolean; protected procedure Calculate(var AClientBounds: TRect); public constructor Create(APivotGrid: TcxCustomPivotGrid); procedure ShowPrefilterDialog; property CanMRUPopupShow: Boolean read GetCanMRUPopupShow; property CustomizeButtonVisible: Boolean read GetCustomizeButtonVisible; property Filter: TcxDataFilterCriteria read GetFilter; property Position: TcxPivotGridPrefilterPosition read GetPosition; property ViewInfo: TcxPivotGridPrefilterViewInfo read GetViewInfo; property Visible: Boolean read GetVisible; end; // PivotGrid DataBuilder { TcxPivotGridGroupItem } TcxPivotGridGroupItem = class private FDataController: TcxCustomDataController; FDisplayText: string; FExpanded: Boolean; FField: TcxPivotGridField; FHasChildren: Boolean; FItems: TcxObjectList; FIndex: Integer; FMemberIndex: Integer; FParent: TcxPivotGridGroupItem; FRecordIndex: Integer; FRecords: TcxPivotGridRecords; FUniqueName: WideString; function GetDisplayText: string; function GetDisplayValue: Variant; function GetExpanded: Boolean; function GetHasChildren: Boolean; function getNextSibling: TcxPivotGridGroupItem; function GetIsHierarchy: Boolean; function GetItem(AIndex: Integer): TcxPivotGridGroupItem; function GetItemCount: Integer; function GetLevel: Integer; function GetPivotGrid: TcxCustomPivotGrid; function getPrevSibling: TcxPivotGridGroupItem; // for Builder procedure SetExpanded(AValue: Boolean); procedure SetHasChildren(AValue: Boolean); protected FInternalValue: Variant; FIsValueAsssigned: Boolean; FSortingValid: Boolean; FSummaryValue: Variant; function GetCrossCellClass: TcxPivotGridCrossCellClass; virtual; function GetIsCollapsed: Boolean; function GetIsRow: Boolean; virtual; function GetItemAlwaysExpanded: Boolean; virtual; function GetSize: Integer; virtual; function GetSingleItemSize: Integer; virtual; function GetTotalsCount: Integer; virtual; function GetUniqueValue: string; function GetValue: Variant; virtual; procedure CheckExpanding; function ChildItemsClass: TcxPivotGridGroupItemClass; virtual; procedure CollapseField(AField: TcxPivotGridField); procedure ExpandField(AField: TcxPivotGridField); function FieldProcessTopValues: Boolean; function FieldSortedBySummary: Boolean; procedure InitSummaryValue(ACrossTotal: TcxPivotGridGroupItem); virtual; procedure PostProcessGroup(ACrossTotal: TcxPivotGridGroupItem); virtual; procedure ProcessSortBySummary(ACrossTotal: TcxPivotGridGroupItem); virtual; procedure ProcessTopValues(ACrossTotal: TcxPivotGridGroupItem); virtual; procedure ReIndexChildren(AFullReindex: Boolean = False); procedure SetFieldExpanding(AField: TcxPivotGridField; AExpandState: Boolean); procedure SetSummaryInfoDirty(ACrossTotal: TcxPivotGridGroupItem); virtual; property DisplayValue: Variant read GetDisplayValue; property IsRow: Boolean read GetIsRow; property ItemList: TcxObjectList read FItems; property SummaryValue: Variant read FSummaryValue; public constructor Create(AParent: TcxPivotGridGroupItem; ADataController: TcxCustomDataController; ARecordIndex: Integer; AField: TcxPivotGridField); virtual; destructor Destroy; override; function AddChild(AClass: TcxPivotGridGroupItemClass): TcxPivotGridGroupItem; overload; function AddChild(AIndex, ARecordIndex: Integer; AField: TcxPivotGridField): TcxPivotGridGroupItem; overload; function ChildrenNeeded: Boolean; function Compare(const AValue: Variant): Integer; function CreateSummaryRecords: TcxPivotGridRecords; virtual; procedure DeleteChildren; virtual; function GetCellByCrossItem(AItem: TcxPivotGridGroupItem): TcxPivotGridCrossCell; virtual; function GetPrev: TcxPivotGridGroupItem; procedure InitializeValue(const ADisplayText: string; const AnUniqueName: WideString); procedure MarkDeleted; procedure RemoveChildrenFrom(AItem: TcxPivotGridGroupItem); property DataController: TcxCustomDataController read FDataController; property DisplayText: string read GetDisplayText; property Expanded: Boolean read GetExpanded write SetExpanded; property Index: Integer read FIndex; property Field: TcxPivotGridField read FField; property HasChildren: Boolean read GetHasChildren write SetHasChildren; property ItemCount: Integer read GetItemCount; property Items[Index: Integer]: TcxPivotGridGroupItem read GetItem; property IsCollapsed: Boolean read GetIsCollapsed; property IsHierarchy: Boolean read GetIsHierarchy; property Level: Integer read GetLevel; property MemberIndex: Integer read FMemberIndex write FMemberIndex; property NextSibling: TcxPivotGridGroupItem read getNextSibling; property Parent: TcxPivotGridGroupItem read FParent; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property PrevSibling: TcxPivotGridGroupItem read getPrevSibling; property RecordIndex: Integer read FRecordIndex; property Records: TcxPivotGridRecords read FRecords; property Size: Integer read GetSize; property TotalsCount: Integer read GetTotalsCount; property UniqueName: WideString read FUniqueName; property Value: Variant read GetValue; end; { TcxPivotGridRowItem } TcxPivotGridRowItem = class(TcxPivotGridGroupItem) protected FCrossCells: TcxObjectList; FCachedCrossCell: TcxPivotGridCrossCell; function GetIsRow: Boolean; override; function GetItemAlwaysExpanded: Boolean; override; function GetSingleItemSize: Integer; override; procedure SetSummaryInfoDirty(ACrossTotal: TcxPivotGridGroupItem); override; public constructor Create(AParent: TcxPivotGridGroupItem; ADataController: TcxCustomDataController; ARecordIndex: Integer; AField: TcxPivotGridField); override; destructor Destroy; override; procedure DeleteChildren; override; function GetCellByCrossItem(AItem: TcxPivotGridGroupItem): TcxPivotGridCrossCell; override; end; { TcxPivotGridColumnItem } TcxPivotGridColumnItem = class(TcxPivotGridGroupItem) protected function GetItemAlwaysExpanded: Boolean; override; function GetSingleItemSize: Integer; override; procedure SetSummaryInfoDirty(ACrossTotal: TcxPivotGridGroupItem); override; public function GetCellByCrossItem(AItem: TcxPivotGridGroupItem): TcxPivotGridCrossCell; override; end; { TcxPivotGridDataItem } TcxPivotGridDataItem = class(TcxPivotGridGroupItem) protected function GetSingleItemSize: Integer; override; function GetValue: Variant; override; end; { TcxPivotGridCrossCellDataSource } TcxPivotGridCrossCellDataSource = class(TcxCustomDataSource) protected PivotGrid: TcxCustomPivotGrid; Records: TcxPivotGridRecords; function HasData: Boolean; function GetFieldCount: Integer; virtual; function GetPivotGridField(AIndex: Integer): TcxPivotGridField; virtual; function GetRecordCount: Integer; override; function GetValue(ARecordHandle: TcxDataRecordHandle; AItemHandle: TcxDataItemHandle): Variant; override; public constructor Create(ACell: TcxPivotGridCrossCell); virtual; constructor CreateEx(ACrossCells: TList); virtual; destructor Destroy; override; property FieldCount: Integer read GetFieldCount; property PivotGridFields[AIndex: Integer]: TcxPivotGridField read GetPivotGridField; property RecordCount: Integer read GetRecordCount; property Values[ARecordHandle: TcxDataRecordHandle; AItemHandle: TcxDataItemHandle]: Variant read GetValue; end; { TcxPivotGridCrossCell } TcxPivotGridCrossCell = class private FCalculated: Boolean; FColumn: TcxPivotGridGroupItem; FPrevCrossCell: TcxPivotGridCrossCell; FRecords: TcxPivotGridRecords; FRow: TcxPivotGridGroupItem; FSummaryCells: TcxObjectList; function GetDataController: TcxCustomDataController; function GetPivotGrid: TcxCustomPivotGrid; function GetSummaryCell(AIndex: Integer): TcxPivotGridCrossCellSummary; function GetSummaryCellCount: Integer; function GetUseRawData: Boolean; protected function AddSummaryCell(AField: TcxPivotGridField; ARecords: TcxPivotGridRecords): TcxPivotGridCrossCellSummary; virtual; procedure CalculateVisibleSummary; virtual; function CreateCrossRecords: TcxPivotGridRecords; function CreateCrossCellsList: TList; procedure DoCalculateSummary; virtual; function IsCalculationAvailable: Boolean; virtual; procedure GetDataTypes(ADataField: TcxPivotGridField; var ASourceType, AFloatType: Integer); virtual; function GetIsEmpty: Boolean; virtual; function GetPrevCrossCellInRow: TcxPivotGridCrossCell; virtual; function GetPrevCrossCellInColumn: TcxPivotGridCrossCell; virtual; property Calculated: Boolean read FCalculated write FCalculated; property PrevCrossCell: TcxPivotGridCrossCell read FPrevCrossCell write FPrevCrossCell; property UseRawData: Boolean read GetUseRawData; public constructor Create(ARow, AColumn: TcxPivotGridGroupItem); virtual; destructor Destroy; override; procedure CalculateSummaries; function CreateDrillDownDataSource: TcxCustomDataSource; virtual; function GetSummaryByField(AField: TcxPivotGridField; ASummaryType: TcxPivotGridSummaryType): Variant; virtual; function GetSummaryValue(ASummary: TcxPivotGridCrossCellSummary; AType: TcxPivotGridSummaryType): Variant; virtual; property Column: TcxPivotGridGroupItem read FColumn; property DataController: TcxCustomDataController read GetDataController; property IsEmpty: Boolean read GetIsEmpty; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property Records: TcxPivotGridRecords read FRecords; property Row: TcxPivotGridGroupItem read FRow; property SummaryCellCount: Integer read GetSummaryCellCount; property SummaryCells[AIndex: Integer]: TcxPivotGridCrossCellSummary read GetSummaryCell; default; end; { TcxPivotGridOLAPCrossCell } TcxPivotGridOLAPCrossCell = class(TcxPivotGridCrossCell) private FIsEmpty: Boolean; FNativeValues: Variant; protected procedure GetDataTypes(ADataField: TcxPivotGridField; var ASourceType, AFloatType: Integer); override; function GetIsEmpty: Boolean; override; function IsCalculationAvailable: Boolean; override; public function GetSummaryByField(AField: TcxPivotGridField; ASummaryType: TcxPivotGridSummaryType): Variant; override; function GetSummaryValue(ASummary: TcxPivotGridCrossCellSummary; AType: TcxPivotGridSummaryType): Variant; override; property NativeValues: Variant read FNativeValues write FNativeValues; end; { TcxPivotGridCrossCellSummary } TcxPivotGridGetRecordValueProc = function(const ARecord: Pointer; AIsGroupValue: Boolean): Variant of object; TcxPivotGridCrossCellSummary = class private FDataField: TcxPivotGridField; FOwner: TcxPivotGridCrossCell; FSummaries: array[TcxPivotGridSummaryType] of Variant; FSummaryVariation: Variant; function GetDataController: TcxCustomDataController; function GetSummaryByIndex(AIndex: Integer): Variant; function GetSummaryNullIgnore: Boolean; function GetRecords: TcxPivotGridRecords; function GetVariationNullIgnore: Boolean; protected procedure CalculateCustomSummary; virtual; procedure CalculateSummaryVariation; virtual; procedure CheckValue(var AValue: Variant); virtual; procedure DoCalculateSummary(ARecords: TList; AGetValueProc: TcxPivotGridGetRecordValueProc = nil); virtual; function GetIntermadiateValue(const ACell: Pointer; AIsGroupValue: Boolean): Variant; function GetRecordValue(const ARecord: Pointer; AIsGroupValue: Boolean): Variant; procedure SetSummaryByIndex(AIndex: Integer; AValue: Variant); procedure SetSummaryByType(AType: TcxPivotGridSummaryType; const AValue: Extended; AVarType: Integer); property DataController: TcxCustomDataController read GetDataController; property SummaryNullIgnore: Boolean read GetSummaryNullIgnore; property VariationNullIgnore: Boolean read GetVariationNullIgnore; public constructor Create(AOwner: TcxPivotGridCrossCell; ADataField: TcxPivotGridField); virtual; procedure Clear; virtual; function GetPrevCell(APrevCell: TcxPivotGridCrossCellSummary): TcxPivotGridCrossCellSummary; function GetValue(ARecordIndex: Integer): Variant; virtual; function GetSummaryByType(AType: TcxPivotGridSummaryType): Variant; function GetSummaryValue(AType: TcxPivotGridSummaryType): Variant; property Average: Variant index 4 read GetSummaryByIndex; property Count: Variant index 0 read GetSummaryByIndex; property Custom: Variant index 9 read GetSummaryByIndex write SetSummaryByIndex; property DataField: TcxPivotGridField read FDataField; property Max: Variant index 3 read GetSummaryByIndex; property Min: Variant index 2 read GetSummaryByIndex; property Owner: TcxPivotGridCrossCell read FOwner; property Records: TcxPivotGridRecords read GetRecords; property StdDev: Variant index 5 read GetSummaryByIndex; property StdDevP: Variant index 6 read GetSummaryByIndex; property Sum: Variant index 1 read GetSummaryByIndex; property SummaryVariation: Variant read FSummaryVariation write FSummaryVariation; property Variance: Variant index 7 read GetSummaryByIndex; property VarianceP: Variant index 8 read GetSummaryByIndex; end; TcxPivotGridCrossCellSummaryClass = class of TcxPivotGridCrossCellSummary; { TcxPivotGridDataBuilder } TcxPivotGridDataBuilder = class private FColumnFields: TcxPivotGridFields; FColumns: TcxPivotGridGroupItem; FData: TcxPivotGridGroupItem; FDataController: TcxCustomDataController; FDataFields: TcxPivotGridFields; FExpandingItems: TList; FExpandingLockCount: Integer; FFields: TcxPivotGridFields; FFilteredFields: TcxPivotGridFields; FFilteredIndexes: TcxPivotGridRecords; FFilterFields: TcxPivotGridFields; FOLAPDataSource: TcxPivotGridCustomOLAPDataSource; FPivotGrid: TcxCustomPivotGrid; FRowFields: TcxPivotGridFields; FRows: TcxPivotGridGroupItem; function GetCrossCell(ARow, AColumn: TcxPivotGridGroupItem): TcxPivotGridCrossCell; function GetSummaryFields: TcxPivotGridFields; protected procedure AddSummaryField(AField: TcxPivotGridField); procedure AfterDataChanged; procedure ApplyFilter; virtual; function CanGroupByColumns: Boolean; function CanGroupByRows: Boolean; procedure Clear; virtual; procedure CreateDataCells; procedure GroupBy(AFields: TcxPivotGridFields; ARoot: TcxPivotGridGroupItem); virtual; procedure GroupByColumns; virtual; procedure GroupByRows; virtual; procedure GroupExpandingChanged(AItem: TcxPivotGridGroupItem); procedure LockExpanding; procedure PopulateRecordsList; procedure SplitFieldsByGroups; procedure UnlockExpanding; public constructor Create(AOwner: TcxCustomPivotGrid); destructor Destroy; override; function CanGroup: Boolean; procedure DataChanged; virtual; property ColumnFields: TcxPivotGridFields read FColumnFields; property Columns: TcxPivotGridGroupItem read FColumns; property CrossCells[ARow, AColumn: TcxPivotGridGroupItem]: TcxPivotGridCrossCell read GetCrossCell; property Data: TcxPivotGridGroupItem read FData; property DataController: TcxCustomDataController read FDataController; property DataFields: TcxPivotGridFields read FDataFields; property Fields: TcxPivotGridFields read FFields; property FilteredFields: TcxPivotGridFields read FFilteredFields; property FilteredIndexes: TcxPivotGridRecords read FFilteredIndexes; property FilterFields: TcxPivotGridFields read FFilterFields; property OLAPDataSource: TcxPivotGridCustomOLAPDataSource read FOLAPDataSource; property PivotGrid: TcxCustomPivotGrid read FPivotGrid; property RowFields: TcxPivotGridFields read FRowFields; property Rows: TcxPivotGridGroupItem read FRows; property SummaryFields: TcxPivotGridFields read GetSummaryFields; end; // Pivot ViewData { TcxPivotGridViewDataItem } TcxPivotGridViewDataLimitValue = class protected Field: TcxPivotGridField; MaxValue: Variant; MinValue: Variant; public constructor Create(AField: TcxPivotGridField); procedure Calculate(V: Variant); end; TcxPivotGridViewDataLimitValues = class(TcxObjectList) private function GetItem(Index: Integer): TcxPivotGridViewDataLimitValue; public function Add(AField: TcxPivotGridField): TcxPivotGridViewDataLimitValue; overload; procedure Calculate(AField: TcxPivotGridField; V: Variant); function FindByField(AField: TcxPivotGridField): TcxPivotGridViewDataLimitValue; function GetMaximumValue(AField: TcxPivotGridField): Variant; function GetMinimumValue(AField: TcxPivotGridField): Variant; property Items[Index: Integer]: TcxPivotGridViewDataLimitValue read GetItem; default; end; TcxPivotGridViewDataItem = class private FIndex: Integer; FIsDataField: Boolean; FItems: TcxObjectList; FGroupItem: TcxPivotGridGroupItem; FLimitValues: TcxPivotGridViewDataLimitValues; FParent: TcxPivotGridViewDataItem; FVisibleIndex: Integer; function GetExpanded: Boolean; function GetFirst: TcxPivotGridViewDataItem; function GetHasButton: Boolean; function GetHasChildren: Boolean; function GetItem(AIndex: Integer): TcxPivotGridViewDataItem; function GetItemCount: Integer; function GetIsGrandTotal: Boolean; function GetIsTotalItem: Boolean; function GetLast: TcxPivotGridViewDataItem; function GetLevel: Integer; function GetNextVisible: TcxPivotGridViewDataItem; function GetPrevVisible: TcxPivotGridViewDataItem; function GetPivotGrid: TcxCustomPivotGrid; protected function GetChildLeftVisibleIndex: Integer; virtual; function GetChildRightVisibleIndex: Integer; virtual; function GetField: TcxPivotGridField; virtual; function GetIsTotal: Boolean; virtual; function GetSize: Integer; virtual; function GetValue: string; virtual; property LimitValues: TcxPivotGridViewDataLimitValues read FLimitValues; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; public constructor Create(AParent: TcxPivotGridViewDataItem; AGroupItem: TcxPivotGridGroupItem); virtual; destructor Destroy; override; function Add(AData: TcxPivotGridGroupItem): TcxPivotGridViewDataItem; function AddTotal(AData: TcxPivotGridGroupItem; AIndex: Integer): TcxPivotGridViewDataItem; procedure DeleteChildren; function GetDisplayText: string; function GetGroupItem(var ADataField: TcxPivotGridField): TcxPivotGridGroupItem; function GetGroupItemByField(ADataField: TcxPivotGridField): TcxPivotGridGroupItem; function GetSummaryType(var ASummaryType: TcxPivotGridSummaryType; var ATotal: TcxPivotGridCustomTotal): Boolean; virtual; function MeasureWidth(AField: TPersistent; AIncludeTotals: Boolean): Integer; property Expanded: Boolean read GetExpanded; property Field: TcxPivotGridField read GetField; property First: TcxPivotGridViewDataItem read GetFirst; property HasButton: Boolean read GetHasButton; property HasChildren: Boolean read GetHasChildren; property GroupItem: TcxPivotGridGroupItem read FGroupItem; property Index: Integer read FIndex; property ItemCount: Integer read GetItemCount; property Items[Index: Integer]: TcxPivotGridViewDataItem read GetItem; property IsDataField: Boolean read FIsDataField; property IsGrandTotal: Boolean read GetIsGrandTotal; property IsTotal: Boolean read GetIsTotal; property IsTotalItem: Boolean read GetIsTotalItem; property Last: TcxPivotGridViewDataItem read GetLast; property Level: Integer read GetLevel; property NextVisible: TcxPivotGridViewDataItem read GetNextVisible; property Parent: TcxPivotGridViewDataItem read FParent; property PrevVisible: TcxPivotGridViewDataItem read GetPrevVisible; property Size: Integer read GetSize; property Value: string read GetValue; property VisibleIndex: Integer read FVisibleIndex; end; { TcxPivotGridViewDataTotalItem } TcxPivotGridViewDataTotalItem = class(TcxPivotGridViewDataItem) private FTotal: TcxPivotGridCustomTotal; protected function GetDescription: string; function GetIsTotal: Boolean; override; function GetValue: string; override; procedure SetTotal(AIndex: Integer); public function GetSummaryType(var ASummaryType: TcxPivotGridSummaryType; var ATotal: TcxPivotGridCustomTotal): Boolean; override; property Total: TcxPivotGridCustomTotal read FTotal; end; { TcxPivotGridViewDataSelections } TcxPivotGridViewDataSelection = class(TPersistent) private FAnchorCells: TRect; FFocusedCell: TPoint; FHasTemporarySelection: Boolean; FRegions: array of TRect; FLockCount: Integer; FViewData: TcxPivotGridViewData; function GetCount: Integer; function GetRegion(AIndex: Integer): TRect; function GetMultiSelect: Boolean; function GetTemporarySelection: TRect; function IsTemporarySelected: Boolean; procedure SetFocusedCell(const APoint: TPoint); procedure SetTemporarySelection(const AValue: TRect); protected procedure ApplyTemporarySelection(AIsSet: Boolean); virtual; procedure ChangeSelection(const R: TRect; AShift: TShiftState); virtual; procedure DoChanged; virtual; procedure InnerClear; virtual; procedure InnerSetFocusedCell(const APoint: TPoint); virtual; function IsSelected: Boolean; procedure ValidateFocusedCell; procedure ValidateSelections; property AnchorCells: TRect read FAnchorCells write FAnchorCells; property LockCount: Integer read FLockCount; property MultiSelect: Boolean read GetMultiSelect; property TemporarySelection: TRect read GetTemporarySelection write SetTemporarySelection; property ViewData: TcxPivotGridViewData read FViewData; public constructor Create(AViewData: TcxPivotGridViewData); virtual; destructor Destroy; override; procedure Add(const ARegion: TRect); virtual; procedure BeginUpdate; procedure Clear; virtual; procedure Delete(AIndex: Integer); procedure EndUpdate(ASendNotification: Boolean = True); function GetCombinedSelectionBounds: TRect; virtual; function IsCellSelected(AColumn, ARow: Integer): Boolean; virtual; procedure MakeNew(const ARegion: TRect); virtual; property Count: Integer read GetCount; property FocusedCell: TPoint read FFocusedCell write SetFocusedCell; property Regions[AIndex: Integer]: TRect read GetRegion; default; end; { TcxPivotGridViewData } TcxPivotGridViewData = class private FBookMarkRow: Integer; FCalculatedLimitValues: Boolean; FColumnCount: Integer; FColumnIndex: Integer; FColumns: TcxPivotGridViewDataItem; FColumnsPerPage: Integer; FExpandColumns: Boolean; FExpandRows: Boolean; FLimitValues: TcxPivotGridViewDataLimitValues; FOwner: TcxCustomPivotGrid; FRowCount: Integer; FRowIndex: Integer; FRows: TcxPivotGridViewDataItem; FRowsPerPage: Integer; FSelection: TcxPivotGridViewDataSelection; function GetAnchorCells: TRect; function GetCell(ARow, AColumn: Integer): TcxPivotGridCrossCellSummary; function GetCellAsText(ARow, AColumn: Integer): string; function GetColumn(AIndex: Integer): TcxPivotGridViewDataItem; function GetDataBuilder: TcxPivotGridDataBuilder; function GetFocusedCell: TPoint; function GetOptionsSelection: TcxPivotGridOptionsSelection; function GetOptionsView: TcxPivotGridOptionsView; function GetRow(AIndex: Integer): TcxPivotGridViewDataItem; function NeedCalculateLimitValues: Boolean; procedure SetAnchorCells(const AValue: TRect); procedure SetColumnIndex(AIndex: Integer); procedure SetFocusedCell(const APoint: TPoint); procedure SetRowIndex(AIndex: Integer); protected procedure AdjustCellIndexes(var ARow, AColumn: Integer; AByMouse: Boolean = False); function AdjustCellIndexesPoint(const P: TPoint; AByMouse: Boolean = False): TPoint; procedure Calculate; function CalculateDataWidth(AField: TcxPivotGridField): Integer; procedure CalculateDataFieldInfo(var AFieldIndex: Integer; var AFields: TcxPivotGridGroupItem; AcceptedArea: TcxPivotGridDataFieldArea); procedure CalculateLimitValues; procedure Clear; function CanCellSelect(ARow, AColumn: Integer): Boolean; virtual; procedure DoNextPage(AGoForward: Boolean); function GetItemByIndex(AList: TcxPivotGridViewDataItem; AIndex, ACount: Integer): TcxPivotGridViewDataItem; procedure HeaderCellSelect(ADataItem: TcxPivotGridViewDataItem; AShift: TShiftState); virtual; procedure PopulateSelectedCells(ACells: TList); procedure ProduceColumns; procedure ProduceRows; procedure Scroll(AScrollCode: TScrollCode; AItem: TcxPivotGridViewDataItem; APage, AMax, ASize, AScrollPos: Integer; var APos: Integer); virtual; function ScrollColumns(AScrollCode: TScrollCode; var AScrollPos: Integer): Boolean; function ScrollRows(AScrollCode: TScrollCode; var AScrollPos: Integer): Boolean; procedure ValidateIndexes; procedure ValidateSelection(var ASelection: TRect); property AnchorCells: TRect read GetAnchorCells write SetAnchorCells; property CalculatedLimitValues: Boolean read FCalculatedLimitValues; property ExpandColumns: Boolean read FExpandColumns write FExpandColumns; property ExpandRows: Boolean read FExpandRows write FExpandRows; property LimitValues: TcxPivotGridViewDataLimitValues read FLimitValues; property OptionsSelection: TcxPivotGridOptionsSelection read GetOptionsSelection; public constructor Create(AOwner: TcxCustomPivotGrid); virtual; destructor Destroy; override; function IsCellSelected(ARow, AColumn: Integer): Boolean; function MakeSelectionVisible: Boolean; property Cells[Row, Column: Integer]: TcxPivotGridCrossCellSummary read GetCell; property CellsAsText[Row, Column: Integer]: string read GetCellAsText; property ColumnCount: Integer read FColumnCount; property ColumnIndex: Integer read FColumnIndex write SetColumnIndex; property Columns[AIndex: Integer]: TcxPivotGridViewDataItem read GetColumn; property ColumnsPerPage: Integer read FColumnsPerPage write FColumnsPerPage; property DataBuilder: TcxPivotGridDataBuilder read GetDataBuilder; property FocusedCell: TPoint read GetFocusedCell write SetFocusedCell; property OptionsView: TcxPivotGridOptionsView read GetOptionsView; property PivotGrid: TcxCustomPivotGrid read FOwner; property RowCount: Integer read FRowCount; property RowIndex: Integer read FRowIndex write SetRowIndex; property Rows[AIndex: Integer]: TcxPivotGridViewDataItem read GetRow; property RowsPerPage: Integer read FRowsPerPage write FRowsPerPage; property Selection: TcxPivotGridViewDataSelection read FSelection; end; { IcxPivotGridSizableObject } IcxPivotGridSizableObject = interface ['{CFCAC754-EC31-4A72-8BED-1D9D2715E062}'] procedure ApplyBestFit; function CanResize: Boolean; function GetActualWidth: Integer; function GetMinWidth: Integer; procedure SetWidth(AValue: Integer); end; { IcxPivotGridField } IcxPivotGridField = interface(IcxPivotGridSizableObject) ['{61CC4884-4510-4C28-86DC-EC0B984E56DA}'] function CanDrag: Boolean; function CanDrop(AArea: TcxPivotGridFieldArea): Boolean; function CanRemove: Boolean; procedure ChangeExpanding; procedure ChangeSorting; procedure DragDrop(AArea: TcxPivotGridFieldArea; AIndex: Integer); function GetVisible: Boolean; function GetViewInfo: TcxPivotGridFieldHeaderCellViewInfo; procedure SetState(AState: TcxButtonState); procedure SetVisible(AValue: Boolean); end; { TcxPivotGridCustomOptions } TcxPivotGridCustomOptions = class(TPersistent) private FPivotGrid: TcxCustomPivotGrid; protected function GetOwner: TPersistent; override; procedure Changed; virtual; procedure SetBoolValue(var AFieldValue: Boolean; AValue: Boolean); public constructor Create(AOwner: TcxCustomPivotGrid); virtual; procedure Assign(Source: TPersistent); override; property PivotGrid: TcxCustomPivotGrid read FPivotGrid; end; { TcxPivotGridOptionsBehavior } TcxPivotGridOptionsBehavior = class(TcxPivotGridCustomOptions) private FCellHints: Boolean; FFieldHeaderHints: Boolean; FFocusCellOnCycle: Boolean; FFocusCellOnTab: Boolean; FGroupHeaderHints: Boolean; public constructor Create(AOwner: TcxCustomPivotGrid); override; procedure Assign(Source: TPersistent); override; published property CellHints: Boolean read FCellHints write FCellHints default False; property FieldHeaderHints: Boolean read FFieldHeaderHints write FFieldHeaderHints default True; property FocusCellOnCycle: Boolean read FFocusCellOnCycle write FFocusCellOnCycle default False; property FocusCellOnTab: Boolean read FFocusCellOnTab write FFocusCellOnTab default False; property GroupHeaderHints: Boolean read FGroupHeaderHints write FGroupHeaderHints default True; end; { TcxPivotGridOptionsCustomize } TcxPivotGridOptionsCustomize = class(TcxPivotGridCustomOptions) private FFiltering: Boolean; FFilterResizable: Boolean; FHiding: Boolean; FMoving: Boolean; FQuickCustomization: Boolean; FQuickPrefiltering: Boolean; FSizing: Boolean; FSorting: Boolean; procedure SetFiltering(AValue: Boolean); procedure SetValue(AIndex: Integer; AValue: Boolean); public constructor Create(AOwner: TcxCustomPivotGrid); override; procedure Assign(Source: TPersistent); override; published property Filtering: Boolean index 0 read FFiltering write SetValue default True; property FilterResizable: Boolean index 6 read FFilterResizable write SetValue default True; property Hiding: Boolean index 1 read FHiding write SetValue default True; property Moving: Boolean index 2 read FMoving write SetValue default True; property QuickCustomization: Boolean index 3 read FQuickCustomization write SetValue default True; property QuickPrefiltering: Boolean index 7 read FQuickPrefiltering write SetValue default True; property Sizing: Boolean index 4 read FSizing write SetValue default True; property Sorting: Boolean index 5 read FSorting write SetValue default True; end; { TcxPivotGridOptionsView } TcxPivotGridLines = (pglNone, pglHorz, pglVert, pglBoth); TcxPivotGridOptionsView = class(TcxPivotGridCustomOptions, IUnknown, IcxPivotGridSizableObject) private FColumnFields: Boolean; FColumnGrandTotals: Boolean; FColumnGrandTotalText: string; FColumnTotals: Boolean; FColumnTotalsLocation: TcxPivotGridTotalsLocation; FDataFields: Boolean; FDropArrowColor: TColor; FFilterDropDownMaxItemCount: Integer; FFilterDropDownWidth: Integer; FFilterFields: Boolean; FFilterSeparator: Boolean; FGrandTotalsForSingleValues: Boolean; FGrandTotalWidth: Integer; FGridLineColor: TColor; FGridLines: TcxPivotGridLines; FMarkNarrowCells: Boolean; FRowFields: Boolean; FRowGrandTotals: Boolean; FRowGrandTotalText: string; FRowTotals: Boolean; FRowTotalsLocation: TcxPivotGridTotalsLocation; FTotalsForSingleValues: Boolean; function GetScrollBars: TScrollStyle; function GetTotalsLocation: TcxPivotGridTotalsLocation; procedure SetColumnFields(AValue: Boolean); procedure SetColumnGrandTotals(AValue: Boolean); procedure SetColumnGrandTotalText(const AValue: string); procedure SetColumnTotals(AValue: Boolean); procedure SetColumnTotalsLocation(AValue: TcxPivotGridTotalsLocation); procedure SetDataFields(AValue: Boolean); procedure SetFilterDropDownMaxItemCount(AValue: Integer); procedure SetFilterDropDownWidth(AValue: Integer); procedure SetFilterFields(AValue: Boolean); procedure SetFilterSeparator(AValue: Boolean); procedure SetGrandTotalWidth(AValue: Integer); procedure SetGrandTotalsForSingleValues(AValue: Boolean); procedure SetGridLineColor(AValue: TColor); procedure SetGridLines(AValue: TcxPivotGridLines); procedure SetMarkNarrowCells(AValue: Boolean); procedure SetRowFields(AValue: Boolean); procedure SetRowGrandTotals(AValue: Boolean); procedure SetRowGrandTotalText(const AValue: string); procedure SetRowTotals(AValue: Boolean); procedure SetRowTotalsLocation(AValue: TcxPivotGridTotalsLocation); procedure SetScrollBars(AValue: TScrollStyle); procedure SetTotalsForSingleValues(AValue: Boolean); procedure SetTotalsLocation(const AValue: TcxPivotGridTotalsLocation); protected procedure Changed; override; //IUnknown function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; // IcxPivotGridSizableObject procedure ApplyBestFit; function CanResize: Boolean; function GetActualWidth: Integer; function GetMinWidth: Integer; procedure SetWidth(AValue: Integer); public constructor Create(AOwner: TcxCustomPivotGrid); override; procedure Assign(Source: TPersistent); override; published property ColumnFields: Boolean read FColumnFields write SetColumnFields default True; property ColumnGrandTotals: Boolean read FColumnGrandTotals write SetColumnGrandTotals default True; property ColumnGrandTotalText: string read FColumnGrandTotalText write SetColumnGrandTotalText; property ColumnTotals: Boolean read FColumnTotals write SetColumnTotals default True; property ColumnTotalsLocation: TcxPivotGridTotalsLocation read FColumnTotalsLocation write SetColumnTotalsLocation default tlFar; property DataFields: Boolean read FDataFields write SetDataFields default True; property DropArrowColor: TColor read FDropArrowColor write FDropArrowColor default cxPivotGridDropArrowColor; property FilterDropDownMaxItemCount: Integer read FFilterDropDownMaxItemCount write SetFilterDropDownMaxItemCount default cxPivotGridDropDownMaxItemCount; property FilterDropDownWidth: Integer read FFilterDropDownWidth write SetFilterDropDownWidth default cxPivotGridDropDownWidth; property FilterFields: Boolean read FFilterFields write SetFilterFields default True; property FilterSeparator: Boolean read FFilterSeparator write SetFilterSeparator default True; property GrandTotalWidth: Integer read FGrandTotalWidth write SetGrandTotalWidth default 0; property GrandTotalsForSingleValues: Boolean read FGrandTotalsForSingleValues write SetGrandTotalsForSingleValues default False; property GridLineColor: TColor read FGridLineColor write SetGridLineColor default clDefault; property GridLines: TcxPivotGridLines read FGridLines write SetGridLines default pglBoth; property MarkNarrowCells: Boolean read FMarkNarrowCells write SetMarkNarrowCells default False; property RowFields: Boolean read FRowFields write SetRowFields default True; property RowGrandTotals: Boolean read FRowGrandTotals write SetRowGrandTotals default True; property RowGrandTotalText: string read FRowGrandTotalText write SetRowGrandTotalText; property RowTotals: Boolean read FRowTotals write SetRowTotals default True; property RowTotalsLocation: TcxPivotGridTotalsLocation read FRowTotalsLocation write SetRowTotalsLocation default tlFar; property ScrollBars: TScrollStyle read GetScrollBars write SetScrollBars default ssBoth; property TotalsForSingleValues: Boolean read FTotalsForSingleValues write SetTotalsForSingleValues default False; property TotalsLocation: TcxPivotGridTotalsLocation read GetTotalsLocation write SetTotalsLocation stored False; end; { TcxPivotGridOptionsData } TcxPivotGridOptionsData = class(TcxPivotGridCustomOptions) private FAnsiSort: Boolean; FCalculationBase: TcxPivotGridCalculationBaseType; FSaveExpanding: Boolean; FSummaryNullIgnore: Boolean; FVariationNullIgnore: Boolean; procedure SetAnsiSort(AValue: Boolean); procedure SetCalculationBase(AValue: TcxPivotGridCalculationBaseType); procedure SetSummaryNullIgnore(AValue: Boolean); procedure SetVariationNullIgnore(AValue: Boolean); protected procedure Changed; override; function CompareAsString(const V1, V2: Variant): Integer; public constructor Create(AOwner: TcxCustomPivotGrid); override; procedure Assign(Source: TPersistent); override; published property AnsiSort: Boolean read FAnsiSort write SetAnsiSort default False; property CalculationBase: TcxPivotGridCalculationBaseType read FCalculationBase write SetCalculationBase default cbRawData; property SaveExpanding: Boolean read FSaveExpanding write FSaveExpanding default True; property SummaryNullIgnore: Boolean read FSummaryNullIgnore write SetSummaryNullIgnore default False; property VariationNullIgnore: Boolean read FVariationNullIgnore write SetVariationNullIgnore default True; end; { TcxPivotGridOptionsPrefilter } TcxPivotGridPrefilterVisible = (pfvNever, pfvNonEmpty, pfvAlways); TcxPivotGridOptionsPrefilter = class(TcxPivotGridCustomOptions) private FCustomizeButton: Boolean; FMRUItemsList: Boolean; FMRUItemsListCount: Integer; FMRUItemsListDropDownCount: Integer; FPosition: TcxPivotGridPrefilterPosition; FVisible: TcxPivotGridPrefilterVisible; procedure SetCustomizeButton(AValue: Boolean); procedure SetMRUItemsList(AValue: Boolean); procedure SetMRUItemsListCount(AValue: Integer); procedure SetMRUItemsListDropDownCount(AValue: Integer); procedure SetPosition(AValue: TcxPivotGridPrefilterPosition); procedure SetVisible(AValue: TcxPivotGridPrefilterVisible); public constructor Create(AOwner: TcxCustomPivotGrid); override; procedure Assign(Source: TPersistent); override; published property CustomizeButton: Boolean read FCustomizeButton write SetCustomizeButton default True; property MRUItemsList: Boolean read FMRUItemsList write SetMRUItemsList default True; property MRUItemsListCount: Integer read FMRUItemsListCount write SetMRUItemsListCount default 10; property MRUItemsListDropDownCount: Integer read FMRUItemsListDropDownCount write SetMRUItemsListDropDownCount default 0; property Position: TcxPivotGridPrefilterPosition read FPosition write SetPosition default pfpBottom; property Visible: TcxPivotGridPrefilterVisible read FVisible write SetVisible default pfvNonEmpty; end; { TcxPivotGridOptionsSelection } TcxPivotGridOptionsSelectionInclude = (osiCrossCells, osiGrandTotalCells, osiTotalCells); TcxPivotGridOptionsSelectionIncludes = set of TcxPivotGridOptionsSelectionInclude; TcxPivotGridOptionsSelection = class(TcxPivotGridCustomOptions) private FHideFocusRect: Boolean; FHideSelection: Boolean; FIncludeCells: TcxPivotGridOptionsSelectionIncludes; FMultiSelect: Boolean; procedure SetHideFocusRect(AValue: Boolean); procedure SetHideSelection(AValue: Boolean); procedure SetIncludeCells(const AValue: TcxPivotGridOptionsSelectionIncludes); procedure SetMultiSelect(AValue: Boolean); public constructor Create(AOwner: TcxCustomPivotGrid); override; procedure Assign(Source: TPersistent); override; published property HideFocusRect: Boolean read FHideFocusRect write SetHideFocusRect default False; property HideSelection: Boolean read FHideSelection write SetHideSelection default False; property IncludeCells: TcxPivotGridOptionsSelectionIncludes read FIncludeCells write SetIncludeCells default [osiCrossCells, osiGrandTotalCells, osiTotalCells]; property MultiSelect: Boolean read FMultiSelect write SetMultiSelect default False; end; { TcxPivotGridCustomCustomizationForm } TcxPivotGridCustomCustomizationForm = class(TForm) private FHookTimer: TcxTimer; FPivotGrid: TcxCustomPivotGrid; function GetIsLocked: Boolean; function GetLookAndFeel: TcxLookAndFeel; function GetPainter: TcxCustomLookAndFeelPainterClass; procedure HookTimerHandler(Sender: TObject); protected FontHeight: Integer; procedure CreateControls; virtual; procedure CreateParams(var Params: TCreateParams); override; procedure DoClose(var Action: TCloseAction); override; procedure DoCustomDrawFieldHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); virtual; procedure DoShow; override; function GetDragAndDropObjectClass( AField: TcxPivotGridField): TcxDragAndDropObjectClass; virtual; procedure Init; virtual; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure RefreshList; virtual; property IsLocked: Boolean read GetIsLocked; property LookAndFeel: TcxLookAndFeel read GetLookAndFeel; property Painter: TcxCustomLookAndFeelPainterClass read GetPainter; property PivotGrid: TcxCustomPivotGrid read FPivotGrid; end; TcxPivotGridCustomizationFormClass = class of TcxPivotGridCustomCustomizationForm; { TcxPivotGridCustomization } TcxPivotGridCustomization = class(TcxPivotGridCustomOptions) private FForm: TcxPivotGridCustomCustomizationForm; FFormBounds: TRect; function Getform: TcxPivotGridCustomCustomizationForm; // CBuilder bug! conflict with macro function GetFormBounds: TRect; function GetVisible: Boolean; procedure SetFormBounds(const AValue: TRect); procedure SetVisible(AValue: Boolean); protected procedure CustomizationFormNeeded; procedure CustomizationVisibleChanged; virtual; procedure OnShowCustomization(Sender: TObject); procedure OnHideCustomization(Sender: TObject); procedure Refresh; virtual; public destructor Destroy; override; property Form: TcxPivotGridCustomCustomizationForm read Getform; property FormBounds: TRect read GetFormBounds write SetFormBounds; property Visible: Boolean read GetVisible write SetVisible; end; { TcxPivotGridOptionsDataField } TcxPivotGridOptionsDataField = class(TcxPivotGridCustomOptions, IUnknown, IcxPivotGridSizableObject, IcxPivotGridField) private FArea: TcxPivotGridDataFieldArea; FAreaIndex: Integer; FCaption: string; FIsCaptionAssigned: Boolean; FMoving: Boolean; FViewInfo: TcxPivotGridFieldHeaderCellViewInfo; FMinWidth: Integer; FWidth: Integer; function GetActualWidth: Integer; function GetCaption: string; function GetDataBuilder: TcxPivotGridDataBuilder; function GetHeaderWidth: Integer; procedure SetArea(AValue: TcxPivotGridDataFieldArea); procedure SetAreaIndex(AValue: Integer); procedure SetCaption(const AValue: string); procedure SetWidth(AValue: Integer); // IcxPivotGridField procedure ChangeExpanding; procedure ChangeSorting; function GetMinWidth: Integer; function GetViewInfo: TcxPivotGridFieldHeaderCellViewInfo; function GetVisible: Boolean; procedure SetMinWidth(AValue: Integer); procedure SetState(AState: TcxButtonState); procedure SetVisible(AValue: Boolean); protected function CanDrag: Boolean; virtual; function CanDrop(Area: TcxPivotGridFieldArea): Boolean; virtual; function CanRemove: Boolean; virtual; function CanResize: Boolean; function CheckIndex(AIndex: Integer; AFields: TcxPivotGridFields; AArea: TcxPivotGridFieldArea): Integer; procedure DragDrop(AArea: TcxPivotGridFieldArea; AIndex: Integer); virtual; function GetActualAreaIndex(AInHeaderArea: Boolean = True): Integer; function IsSameArea(AArea: TcxPivotGridFieldArea): Boolean; //IUnknown function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; property ActualWidth: Integer read GetActualWidth; property DataBuilder: TcxPivotGridDataBuilder read GetDataBuilder; property HeaderWidth: Integer read GetHeaderWidth; property ViewInfo: TcxPivotGridFieldHeaderCellViewInfo read FViewInfo; public constructor Create(AOwner: TcxCustomPivotGrid); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure ApplyBestFit; published property Area: TcxPivotGridDataFieldArea read FArea write SetArea default dfaNone; property AreaIndex: Integer read FAreaIndex write SetAreaIndex default -1; property IsCaptionAssigned: Boolean read FIsCaptionAssigned write FIsCaptionAssigned default False; property Caption: string read GetCaption write SetCaption stored FIsCaptionAssigned; property Moving: Boolean read FMoving write FMoving default True; property MinWidth: Integer read GetMinWidth write SetMinWidth default cxPivotGridDefaultFieldMinWidth; property Width: Integer read FWidth write SetWidth default cxPivotGridDefaultFieldWidth; end; // ViewInfo { TcxPivotGridCustomCellViewInfo } TcxPivotGridCustomCellViewInfo = class private function GetBitmap: TBitmap; function GetColor: TColor; function GetFont: TFont; function GetTextColor: TColor; procedure SetBitmap(AValue: TBitmap); procedure SetColor(AValue: TColor); procedure SetTextColor(AValue: TColor); protected FBorders: TcxBorders; FBounds: TRect; FCanvas: TcxCanvas; FClipRect: TRect; FDisplayText: string; FHasClipping: Boolean; FIsHotTrack: Boolean; FPainter: TcxCustomLookAndFeelPainterClass; FTransparent: Boolean; FViewParams: TcxViewParams; FVisible: Boolean; FVisibleInfoCalculated: Boolean; procedure AfterCustomDraw(ACanvas: TcxCanvas); virtual; procedure BeforeCustomDraw(ACanvas: TcxCanvas); virtual; procedure CalculateCellBounds(const ABounds, AVisibleRect: TRect); procedure CalculateVisibleInfo; virtual; function CheckClipping(ANeedClip: Boolean): Boolean; procedure CorrectBoundsForPrinting(ABounds: TRect); virtual; procedure DoDraw; virtual; function ExcludeBorders(const ABounds: TRect; ABorders: TcxBorders): TRect; function ExcludeFromPaint(ACanvas: TcxCanvas): Boolean; virtual; function GetHintText: string; virtual; function GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; virtual; function GetDisplayText: string; virtual; function NeedShowHint(const APoint: TPoint): Boolean; virtual; function SetHotTrack(AHitTest: TcxPivotGridHitTest): Boolean; virtual; property Borders: TcxBorders read FBorders write FBorders; property DisplayText: string read GetDisplayText write FDisplayText; property HintText: string read GetHintText; public constructor Create(APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); virtual; procedure CheckVisibleInfo; procedure Draw(ACanvas: TcxCanvas); virtual; property Bitmap: TBitmap read GetBitmap write SetBitmap; property Bounds: TRect read FBounds; property Canvas: TcxCanvas read FCanvas; property ClipRect: TRect read FClipRect; property Color: TColor read GetColor write SetColor; property Font: TFont read GetFont; property HasClipping: Boolean read FHasClipping; property Painter: TcxCustomLookAndFeelPainterClass read FPainter; property TextColor: TColor read GetTextColor write SetTextColor; property Transparent: Boolean read FTransparent write FTransparent; property ViewParams: TcxViewParams read FViewParams write FViewParams; property Visible: Boolean read FVisible; end; { TcxPivotGridEditContainerViewInfo } TcxPivotGridEditContainerViewInfo = class(TcxPivotGridCustomCellViewInfo) private FUseLocalViewData: Boolean; FUseLocalEditStyle: Boolean; protected FAlignment: TAlignment; FCalculated: Boolean; FEditViewData: TcxCustomEditViewData; FEditViewInfo: TcxCustomEditViewInfo; FDataField: TcxPivotGridField; FEditStyle: TcxEditStyle; FMultiLine: Boolean; FProperties: TcxCustomEditProperties; FShowEndEllipsis: Boolean; FTextBounds: TRect; FValue: Variant; FAlignVert: TcxAlignmentVert; procedure InitEditStyle; procedure CalculateEditViewInfo(AEditViewInfo: TcxCustomEditViewInfo; const AMousePos: TPoint); procedure CalculateVisibleInfo; override; function CreateEditViewInfo: TcxCustomEditViewInfo; procedure CreateEditViewData; procedure DestroyEditViewData; procedure DrawUsingEditProperties; virtual; function GetDisplayText: string; override; procedure InitializeProperties; function OnGetDisplayTextSupported: Boolean; virtual; procedure ReleaseEditStyle; function UseEditProperties: Boolean; virtual; public destructor Destroy; override; property Properties: TcxCustomEditProperties read FProperties; property Value: Variant read FValue; end; { TcxPivotGridHeaderCellViewInfo } TcxPivotGridHeaderCellViewInfo = class(TcxPivotGridEditContainerViewInfo) private procedure SetData(AValue: TObject); protected FBackground: TcxPivotGridHeaderBackgroundCellViewInfo; FButtonRect: TRect; FData: TObject; FExpanded: Boolean; FField: TPersistent; FHasButton: Boolean; FImages: TCustomImageList; FImageAlignHorz: TAlignment; FImageAlignVert: TcxAlignmentVert; FImageIndex: Integer; FImageRect: TRect; FNeighbors: TcxNeighbors; FSizeField: TPersistent; FSortMarkBounds: TRect; FSortOrder: TcxDataSortOrder; FState: TcxButtonState; procedure CalculateImageInfo; virtual; procedure CalculateSortingInfo; virtual; procedure CalculateVisibleInfo; override; function CanDrawBackgroundFirst: Boolean; virtual; procedure CheckSizingArea(AHitTest: TcxPivotGridHitTest); virtual; function DrawBackgroundProc(ACanvas: TcxCanvas; const ABounds: TRect): Boolean; virtual; procedure DoDraw; override; procedure DrawHeaderText; function GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; override; function GetIsLast: Boolean; virtual; function IsSingle: Boolean; virtual; function NeedShowHint(const APoint: TPoint): Boolean; override; function UseEditProperties: Boolean; override; protected function GetDisplayText: string; override; property Data: TObject read FData write SetData; public constructor Create(APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams; const ADisplayText: string); reintroduce; overload; property AlignHorz: TAlignment read FAlignment write FAlignment; property AlignVert: TcxAlignmentVert read FAlignVert write FAlignVert; property Background: TcxPivotGridHeaderBackgroundCellViewInfo read FBackground; property Borders; property ButtonRect: TRect read FButtonRect; property DisplayText; property Expanded: Boolean read FExpanded write FExpanded; property Field: TPersistent read FField; property HasButton: Boolean read FHasButton; property ImageAlignHorz: TAlignment read FImageAlignHorz; property ImageAlignVert: TcxAlignmentVert read FImageAlignVert; property ImageIndex: Integer read FImageIndex; property ImageRect: TRect read FImageRect; property Images: TCustomImageList read FImages; property MultiLine: Boolean read FMultiLine write FMultiLine; property Neighbors: TcxNeighbors read FNeighbors write FNeighbors; property ShowEndEllipsis: Boolean read FShowEndEllipsis write FShowEndEllipsis; property SortMarkBounds: TRect read FSortMarkBounds; property SortOrder: TcxDataSortOrder read FSortOrder write FSortOrder; property State: TcxButtonState read FState write FState; property TextBounds: TRect read FTextBounds; end; { TcxPivotGridFieldHeaderCellViewInfo } TcxPivotGridFieldHeaderCellViewInfo = class(TcxPivotGridHeaderCellViewInfo) private function GetFocused: Boolean; protected FArea: TcxPivotGridFieldArea; FAreaIndex: Integer; FFilterActive: Boolean; FFilterBounds: TRect; FFilterState: TcxButtonState; FFocused: Boolean; FGroup: TcxPivotGridFieldGroup; procedure CalculateFilterInfo; procedure CalculateSortingInfo; override; function CanDrawBackgroundFirst: Boolean; override; procedure DoDraw; override; function ExcludeFromPaint(ACanvas: TcxCanvas): Boolean; override; function GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; override; function GetIsLast: Boolean; override; function IsSingle: Boolean; override; function NeedShowHint(const APoint: TPoint): Boolean; override; function SetHotTrack(AHitTest: TcxPivotGridHitTest): Boolean; override; function SingleOrLeftMostInGroup: Boolean; function SingleOrRightMostInGroup: Boolean; function UseEditProperties: Boolean; override; public constructor CreateEx(AOwner: TPersistent); virtual; procedure Initialize(ACanvas: TcxCanvas; APainter: TcxCustomLookAndFeelPainterClass; const AViewParams: TcxViewParams); function MeasureHeight: Integer; function MeasureWidth: Integer; procedure SetBounds(const ABounds, AClipRect: TRect); procedure PaintTo(ACanvas: TcxCanvas; const ABounds: TRect; AState: TcxButtonState; AHandler: TcxPivotGridCustomDrawEvent); property Area: TcxPivotGridFieldArea read FArea; property AreaIndex: Integer read FAreaIndex; property FilterActive: Boolean read FFilterActive; property FilterBounds: TRect read FFilterBounds; property FilterState: TcxButtonState read FFilterState write FFilterState; property Focused: Boolean read FFocused; property Group: TcxPivotGridFieldGroup read FGroup; end; { TcxPivotGridDataCellViewInfo } TcxPivotGridFocusRectStyle = (frsNone, frsDot, frsLine); TcxPivotGridDataCellLimitValueType = (lvtColumnMaximum, lvtColumnMinimum, lvtRowMaximum, lvtRowMinimum, lvtMaximum, lvtMinimum); TcxPivotGridDataCellLimitValueTypes = set of TcxPivotGridDataCellLimitValueType; TcxPivotGridDataCellViewInfo = class(TcxPivotGridEditContainerViewInfo) private function GetColumnIndex: Integer; function GetDisplayFormat: string; function GetIsGrandTotal: Boolean; function GetIsTotal: Boolean; function GetLimitValueTypes: TcxPivotGridDataCellLimitValueTypes; function GetRowIndex: Integer; protected FBorderColor: Integer; FCellSummary: TcxPivotGridCrossCellSummary; FColumn: TcxPivotGridViewDataItem; FCrossCell: TcxPivotGridCrossCell; FFocusRectStyle: TcxPivotGridFocusRectStyle; FIsTotal: Boolean; FIsTotalAssigned: Boolean; FMarkNarrowCells: Boolean; FRow: TcxPivotGridViewDataItem; FSelected: Boolean; FSummaryType: TcxPivotGridSummaryType; FTotal: TcxPivotGridCustomTotal; procedure CalculateVisibleInfo; override; procedure DoDraw; override; procedure DrawText; procedure FormatDisplayValue; function GetHintText: string; override; function GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; override; function NeedShowHint(const APoint: TPoint): Boolean; override; function OnGetDisplayTextSupported: Boolean; override; function ReplaceDigitsByPattern(const ADisplayText: string): string; property DisplayFormat: string read GetDisplayFormat; public procedure Initialize(ARow, AColumn: TcxPivotGridViewDataItem; ADataField: TcxPivotGridField); function MeasureWidth: Integer; property Align: TAlignment read FAlignment write FAlignment; property BorderColor: Integer read FBorderColor write FBorderColor; property Borders; property CellSummary: TcxPivotGridCrossCellSummary read FCellSummary; property Column: TcxPivotGridViewDataItem read FColumn; property ColumnIndex: Integer read GetColumnIndex; property CrossCell: TcxPivotGridCrossCell read FCrossCell; property DataField: TcxPivotGridField read FDataField; property DisplayText; property FocusRectStyle: TcxPivotGridFocusRectStyle read FFocusRectStyle write FFocusRectStyle; property IsGrandTotal: Boolean read GetIsGrandTotal; property IsTotal: Boolean read GetIsTotal; property LimitValueTypes: TcxPivotGridDataCellLimitValueTypes read GetLimitValueTypes; property MarkNarrowCells: Boolean read FMarkNarrowCells write FMarkNarrowCells; property Row: TcxPivotGridViewDataItem read FRow; property RowIndex: Integer read GetRowIndex; property Selected: Boolean read FSelected; property SummaryType: TcxPivotGridSummaryType read FSummaryType; property TextBounds: TRect read FTextBounds; property Total: TcxPivotGridCustomTotal read FTotal; end; { TcxPivotGridHeaderBackgroundCellViewInfo } TcxPivotGridHeaderBackgroundCellViewInfo = class(TcxPivotGridCustomCellViewInfo) protected FArea: TcxPivotGridFieldArea; FFieldHeadersBounds: TcxRect; FHasFields: Boolean; procedure CorrectBoundsForPrinting(ABounds: TRect); override; procedure DoDraw; override; function GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; override; public property Area: TcxPivotGridFieldArea read FArea; property DisplayText; property FieldHeadersBounds: TcxRect read FFieldHeadersBounds; property HasFields: Boolean read FHasFields; end; TcxPivotGridPrefilterButtonAlignment = (pfbaLeft, pfbaRight); TcxPivotGridPrefilterPartsViewInfo = class; TcxPivotGridPrefilterPartViewInfo = class private FBounds: TRect; FDroppedDown: Boolean; FPartsViewInfo: TcxPivotGridPrefilterPartsViewInfo; FPainter: TcxCustomLookAndFeelPainterClass; FPrefilter: TcxPivotGridPrefilter; FState: TcxButtonState; protected procedure Calculate(ALeftBound, ATopBound: Integer; AWidth: Integer = -1; AHeight: Integer = -1); virtual; function CalculateHeight: Integer; virtual; abstract; function CalculateWidth: Integer; virtual; abstract; procedure Click; virtual; procedure DoDraw(ACanvas: TcxCanvas); virtual; abstract; function GetAlignment: TcxPivotGridPrefilterButtonAlignment; virtual; function GetPartIndex: Integer; virtual; abstract; function GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; virtual; function GetState: TcxButtonState; virtual; function GetVisible: Boolean; virtual; procedure SetDroppedDown(AHitTest: TcxPivotGridHitTest; ADroppedDown: Boolean); virtual; function SetHotTrack(AHitTest: TcxPivotGridHitTest): Boolean; virtual; function SetPressed(AHitTest: TcxPivotGridHitTest; AMouseDown: Boolean): Boolean; virtual; property Alignment: TcxPivotGridPrefilterButtonAlignment read GetAlignment; property Bounds: TRect read FBounds; property State: TcxButtonState read GetState; property Visible: Boolean read GetVisible; public constructor Create(APartsViewInfo: TcxPivotGridPrefilterPartsViewInfo); virtual; procedure Draw(ACanvas: TcxCanvas); end; TcxPivotGridPrefilterPartViewInfoClass = class of TcxPivotGridPrefilterPartViewInfo; TcxPivotGridPrefilterCloseButtonViewInfo = class(TcxPivotGridPrefilterPartViewInfo) protected function CalculateHeight: Integer; override; function CalculateWidth: Integer; override; procedure Click; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetPartIndex: Integer; override; end; TcxPivotGridPrefilterActivateButtonViewInfo = class(TcxPivotGridPrefilterPartViewInfo) protected function CalculateHeight: Integer; override; function CalculateWidth: Integer; override; procedure Click; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetPartIndex: Integer; override; function GetChecked: Boolean; end; TcxPivotGridPrefilterCustomizeButtonViewInfo = class(TcxPivotGridPrefilterPartViewInfo) private function GetFont: TFont; function GetText: string; function GetTextOffset: Integer; protected function CalculateHeight: Integer; override; function CalculateWidth: Integer; override; procedure Click; override; function GetAlignment: TcxPivotGridPrefilterButtonAlignment; override; function GetBorderWidth(AIndex: TcxBorder): Integer; function GetVisible: Boolean; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetPartIndex: Integer; override; end; TcxPivotGridPrefilterDropDownButtonViewInfo = class(TcxPivotGridPrefilterPartViewInfo) protected function CalculateHeight: Integer; override; function CalculateWidth: Integer; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetAlignment: TcxPivotGridPrefilterButtonAlignment; override; function GetPartIndex: Integer; override; function GetVisible: Boolean; override; end; TcxPivotGridPrefilterCaptionViewInfo = class(TcxPivotGridPrefilterPartViewInfo) protected function CalculateHeight: Integer; override; function CalculateWidth: Integer; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetAlignment: TcxPivotGridPrefilterButtonAlignment; override; function GetPartIndex: Integer; override; function GetState: TcxButtonState; override; function GetVisible: Boolean; override; procedure SetDroppedDown(AHitTest: TcxPivotGridHitTest; ADroppedDown: Boolean); override; end; TcxPivotGridPrefilterPartsViewInfo = class private FCaptionViewInfo: TcxPivotGridPrefilterCaptionViewInfo; FDropDownButtonViewInfo: TcxPivotGridPrefilterDropDownButtonViewInfo; FPrefilterViewInfo: TcxPivotGridPrefilterViewInfo; FItems: TcxObjectList; function GetCount: Integer; function GetHeight: Integer; function GetItem(Index: Integer): TcxPivotGridPrefilterPartViewInfo; protected procedure AddItems; virtual; procedure DestroyItems; virtual; function GetDropDownPartBounds: TRect; procedure SetDroppedDown(AHitTest: TcxPivotGridHitTest; ADroppedDown: Boolean); function SetHotTrack(AHitTest: TcxPivotGridHitTest): Boolean; function SetPressed(AHitTest: TcxPivotGridHitTest; AMouseDown: Boolean): Boolean; property PrefilterViewInfo: TcxPivotGridPrefilterViewInfo read FPrefilterViewInfo; public constructor Create(APreFilterViewInfo: TcxPivotGridPrefilterViewInfo); virtual; destructor Destroy; override; function AddItem(AItemClass: TcxPivotGridPrefilterPartViewInfoClass): TcxPivotGridPrefilterPartViewInfo; procedure Calculate(const ABounds: TRect); virtual; procedure DrawParts; function GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; virtual; property Count: Integer read GetCount; property Height: Integer read GetHeight; property Items[Index: Integer]: TcxPivotGridPrefilterPartViewInfo read GetItem; default; end; { TcxPivotGridPrefilterViewInfo } TcxPivotGridPrefilterViewInfo = class(TcxPivotGridCustomCellViewInfo) private FPartsViewInfo: TcxPivotGridPrefilterPartsViewInfo; FPrefilter: TcxPivotGridPrefilter; procedure DrawBackground; protected procedure CalculateVisibleInfo; override; procedure CorrectBoundsForPrinting(ABounds: TRect); override; procedure DoDraw; override; function GetHeight: Integer; function GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; override; function GetTextWidth: Integer; function GetDropDownWindowOwnerBounds: TRect; procedure SetDroppedDown(AHitTest: TcxPivotGridHitTest; ADroppedDown: Boolean); function SetHotTrack(AHitTest: TcxPivotGridHitTest): Boolean; override; function SetPressed(AHitTest: TcxPivotGridHitTest; AMouseDown: Boolean): Boolean; public constructor Create(APrefilter: TcxPivotGridPrefilter; APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); reintroduce; overload; destructor Destroy; override; property DisplayText; property Prefilter: TcxPivotGridPrefilter read FPrefilter; end; { TcxPivotGridFilterSeparatorCellViewInfo } TcxPivotGridFilterSeparatorCellViewInfo = class(TcxPivotGridCustomCellViewInfo) private FIndentSize: Integer; protected procedure DoDraw; override; public constructor Create(APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); override; property IndentSize: Integer read FIndentSize write FIndentSize; end; { TcxPivotGridViewInfo } TcxPivotGridViewInfo = class private FBounds: TRect; FCanvas: TcxCanvas; FColumnHeaders: TcxPivotGridCells; FCommonCells: TcxPivotGridCells; FDataCells: TcxPivotGridCells; FFieldHeaders: TcxPivotGridCells; FPainter: TcxCustomLookAndFeelPainterClass; FPivotGrid: TcxCustomPivotGrid; FPrefilter: TcxPivotGridPrefilter; FRowHeaders: TcxPivotGridCells; function GetColumnFieldsCount: Integer; function GetDataBuilder: TcxPivotGridDataBuilder; function GetFocusedCell: TPoint; function GetIconsSize: TSize; function GetOptionsDataField: TcxPivotGridOptionsDataField; function GetOptionsView: TcxPivotGridOptionsView; function GetRowFieldsCount: Integer; function GetStyles: TcxPivotGridStyles; function GetViewData: TcxPivotGridViewData; protected FBaseStyles: IcxPivotGridBaseStyles; FCellsBounds: TRect; FColStart: TcxPivotGridViewDataItem; FColumnBounds: TRect; FColumnHeadersHeight: Integer; FColumnItems: TcxList; FColumnRowCount: Integer; FDataCellsBounds: TRect; FDataFieldsWidth: Integer; FDragDropAreas: TcxObjectList; FDrawBorders: Boolean; FDrawExpandButtons: Boolean; FFieldHeaderHeight: Integer; FFieldHeadersBounds: TcxRect; FFilterHeight: Integer; FHeaderHeight: Integer; FIsPrinting: Boolean; FNeedCorrectHeaders: Boolean; FRowColumnPos: TcxList; FRowHeadersHeight: Integer; FRowHeadersWidth: Integer; FRowItems: TcxList; FRowsBounds: TRect; FViewParams: TcxViewParams; function AddDragDropAreaInfo(APos: Integer; const ABounds, ADisplayBounds: TRect; AArea: TcxPivotGridFieldArea; AAreaIndex: Integer; AField: TPersistent): TcxPivotGridDragDropAreaInfo; function AddFieldHeader(const ABounds: TRect; AField: TcxPivotGridField; AArea: TcxPivotGridFieldArea; AAreaIndex: Integer): TcxPivotGridFieldHeaderCellViewInfo; function AddFieldsBackground(const ABounds: TRect; const ADescription: string; AHasDescription: Boolean; AArea: TcxPivotGridFieldArea): TcxPivotGridHeaderBackgroundCellViewInfo; function AddFilterSeparator(const ATop: Integer): TcxPivotGridFilterSeparatorCellViewInfo; procedure AfterPaint; virtual; procedure BeforePaint; virtual; function GetDataFieldFromViewData(AItem: TcxPivotGridViewDataItem): TcxPivotGridField; function GetFont(AStyleIndex: Integer): TFont; function GetRowColumnPos(ALevel: Integer; var ALevelField: TPersistent): Integer; function GetRowField(AIndex: Integer): TcxPivotGridField; function GetStartColumnIndex: Integer; virtual; function GetStartRowIndex: Integer; virtual; function GroupHeaderOutOfBounds(AField: TcxPivotGridField; ARight: Integer): Boolean; procedure CalculateCells; procedure CalculateFieldsLayout; procedure CalculateFilterLayout; procedure CheckCellSelection(ACell: TcxPivotGridDataCellViewInfo); virtual; procedure CorrectBackground; procedure DoCalculate; virtual; function GetHeaderDisplayText(ACell: TcxPivotGridHeaderCellViewInfo; AItem: TcxPivotGridViewDataItem): string; virtual; function AddPartBackground(ABounds: TRect): TcxPivotGridCustomCellViewInfo; function AddColumnItem(ABounds: TRect; AItem: TcxPivotGridViewDataItem): TcxPivotGridHeaderCellViewInfo; function AddDataCell(ARow, AColumn: TcxPivotGridViewDataItem; ALeft, ATop: Integer): TcxPivotGridDataCellViewInfo; function AddRowItem(ABounds: TRect; AItem: TcxPivotGridViewDataItem; ASizeField: TPersistent): TcxPivotGridHeaderCellViewInfo; procedure InitCellViewParams(ACell: TcxPivotGridDataCellViewInfo); procedure InitializeFields; virtual; procedure InitHeaderCell(ACell: TcxPivotGridHeaderCellViewInfo; AItem: TcxPivotGridViewDataItem); function IsDataFieldVisible(AArea: TcxPivotGridDataFieldAreas = []): Boolean; procedure CalculateRows; procedure CreateRows(ARows: TcxList); procedure CreateColumns(AColumns: TcxList); procedure CalculateColumns; procedure CalculateColumnsFields; procedure CalculateDataItemsFields; procedure CalculateRowsFields; procedure CreateDragDropAreaInfo(const AAreaBounds: TRect; AStartIndex: Integer; AArea: TcxPivotGridFieldArea); virtual; function IsGroupItemExist(AList: TList; AItem: TcxPivotGridViewDataItem): Boolean; function PrepareViewDataItems(var AList: TcxList; AStartItem: TcxPivotGridViewDataItem; AAvailableSize: Integer; var AStartIndex: Integer): Integer; function SpaceBetween(AItem1, AItem2: TcxPivotGridViewDataItem): Integer; public constructor Create(AOwner: TcxCustomPivotGrid); virtual; destructor Destroy; override; procedure Calculate; virtual; procedure CalculateHitTest(AHitTest: TcxPivotGridHitTest); virtual; procedure Clear; procedure InvalidateRect(const ARect: TRect); procedure SelectionChanged; property Bounds: TRect read FBounds; property BaseStyles: IcxPivotGridBaseStyles read FBaseStyles; property Canvas: TcxCanvas read FCanvas; property CommonCells: TcxPivotGridCells read FCommonCells; property ColumnFieldsCount: Integer read GetColumnFieldsCount; property ColumnsBounds: TRect read FColumnBounds; property ColumnHeaders: TcxPivotGridCells read FColumnHeaders; property ColumnHeadersHeight: Integer read FColumnHeadersHeight; property DataBuilder: TcxPivotGridDataBuilder read GetDataBuilder; property DataCells: TcxPivotGridCells read FDataCells; property DataCellsBounds: TRect read FDataCellsBounds; property DrawBorders: Boolean read FDrawBorders write FDrawBorders; property DrawExpandButtons: Boolean read FDrawExpandButtons write FDrawExpandButtons; property FieldHeaderHeight: Integer read FFieldHeaderHeight; property FieldHeaders: TcxPivotGridCells read FFieldHeaders; property FilterHeight: Integer read FFilterHeight; property FocusedCell: TPoint read GetFocusedCell; property HeaderHeight: Integer read FHeaderHeight; property IsPrinting: Boolean read FIsPrinting; property OptionsDataField: TcxPivotGridOptionsDataField read GetOptionsDataField; property OptionsView: TcxPivotGridOptionsView read GetOptionsView; property Painter: TcxCustomLookAndFeelPainterClass read FPainter; property PivotGrid: TcxCustomPivotGrid read FPivotGrid; property Prefilter: TcxPivotGridPrefilter read FPrefilter; property RowFieldsCount: Integer read GetRowFieldsCount; property RowHeaders: TcxPivotGridCells read FRowHeaders; property RowHeadersWidth: Integer read FRowHeadersWidth; property RowsBounds: TRect read FRowsBounds; property StartColumnIndex: Integer read GetStartColumnIndex; property StartRowIndex: Integer read GetStartRowIndex; property Styles: TcxPivotGridStyles read GetStyles; property ViewData: TcxPivotGridViewData read GetViewData; end; { TcxPivotGridPainter } TcxPivotGridPainter = class private FCanvas: TcxCanvas; FPivotGrid: TcxCustomPivotGrid; FViewInfo: TcxPivotGridViewInfo; protected procedure DoPaint; virtual; procedure DoCustomDrawFieldHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); procedure DoCustomDrawColumnHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); procedure DoCustomDrawPart(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); procedure DoCustomDrawRowHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); procedure DoCustomDrawDataCell(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); public constructor Create(AOwner: TcxCustomPivotGrid); virtual; procedure Paint(ACanvas: TcxCanvas); property Canvas: TcxCanvas read FCanvas; property PivotGrid: TcxCustomPivotGrid read FPivotGrid; property ViewInfo: TcxPivotGridViewInfo read FViewInfo; end; { IcxPivotGridBaseStyles } IcxPivotGridBaseStyles = interface ['{60482E74-4425-4CF0-86A3-818C486E895F}'] function GetColumnHeaderParams(AColumn: TcxPivotGridViewDataItem): TcxViewParams; function GetContentParams(ACell: TcxPivotGridDataCellViewInfo): TcxViewParams; function GetFieldHeaderParams(AField: TcxPivotGridField): TcxViewParams; function GetHeaderBackgroundParams(AArea: TcxPivotGridFieldArea): TcxViewParams; function GetPrefilterParams: TcxViewParams; function GetRowHeaderParams(ARow: TcxPivotGridViewDataItem): TcxViewParams; end; { TcxCustomPivotGridStyles } TcxPivotGridGetContentStyleEvent = procedure(Sender: TcxCustomPivotGrid; ACell: TcxPivotGridDataCellViewInfo; var AStyle: TcxStyle) of object; TcxPivotGridGetHeaderItemStyleEvent = procedure(Sender: TcxCustomPivotGrid; AItem: TcxPivotGridViewDataItem; var AStyle: TcxStyle) of object; TcxPivotGridGetFieldHeaderStyleEvent = procedure(Sender: TcxCustomPivotGrid; AField: TcxPivotGridField; var AStyle: TcxStyle) of object; TcxPivotGridCustomStyles = class(TcxStyles, IcxPivotGridBaseStyles) private FSuppressContentColoration: Boolean; FSuppressBackgroundBitmaps: Boolean; FOnGetColumnHeaderStyle: TcxPivotGridGetHeaderItemStyleEvent; FOnGetContentStyle: TcxPivotGridGetContentStyleEvent; FOnGetFieldHeaderStyle: TcxPivotGridGetFieldHeaderStyleEvent; FOnGetRowHeaderStyle: TcxPivotGridGetHeaderItemStyleEvent; protected procedure Changed(AIndex: Integer); override; procedure CheckViewParams(var AParams: TcxViewParams); function GetContentStyleIndexByCell(ACell: TcxPivotGridDataCellViewInfo): Integer; virtual; procedure GetDefaultHeadersAreaViewParams(out AParams: TcxViewParams); virtual; procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override; function GetPivotGrid: TcxCustomPivotGrid; virtual; property SuppressContentColoration: Boolean read FSuppressContentColoration write FSuppressContentColoration; property SuppressBackgroundBitmaps: Boolean read FSuppressBackgroundBitmaps write FSuppressBackgroundBitmaps; property Background: TcxStyle index gs_Background read GetValue write SetValue; property ColumnHeader: TcxStyle index gs_ColumnHeader read GetValue write SetValue; property ColumnHeaderArea: TcxStyle index gs_ColumnHeaderArea read GetValue write SetValue; property ColumnMaximumValue: TcxStyle index gs_ColumnMaximumValue read GetValue write SetValue; property ColumnMinimumValue: TcxStyle index gs_ColumnMinimumValue read GetValue write SetValue; property Content: TcxStyle index gs_Content read GetValue write SetValue; property DataHeaderArea: TcxStyle index gs_DataHeaderArea read GetValue write SetValue; property FieldHeader: TcxStyle index gs_FieldHeader read GetValue write SetValue; property FilterHeaderArea: TcxStyle index gs_FilterHeaderArea read GetValue write SetValue; property FilterSeparator: TcxStyle index gs_FilterSeparator read GetValue write SetValue; property HeaderBackground: TcxStyle index gs_HeaderBackground read GetValue write SetValue; property Inactive: TcxStyle index gs_Inactive read GetValue write SetValue; property MaximumValue: TcxStyle index gs_MaximumValue read GetValue write SetValue; property MinimumValue: TcxStyle index gs_MinimumValue read GetValue write SetValue; property Prefilter: TcxStyle index gs_Prefilter read GetValue write SetValue; property RowHeader: TcxStyle index gs_RowHeader read GetValue write SetValue; property RowHeaderArea: TcxStyle index gs_RowHeaderArea read GetValue write SetValue; property RowMaximumValue: TcxStyle index gs_RowMaximumValue read GetValue write SetValue; property RowMinimumValue: TcxStyle index gs_RowMinimumValue read GetValue write SetValue; property Selected: TcxStyle index gs_Selected read GetValue write SetValue; property Total: TcxStyle index gs_Total read GetValue write SetValue; property OnGetColumnHeaderStyle: TcxPivotGridGetHeaderItemStyleEvent read FOnGetColumnHeaderStyle write FOnGetColumnHeaderStyle; property OnGetContentStyle: TcxPivotGridGetContentStyleEvent read FOnGetContentStyle write FOnGetContentStyle; property OnGetFieldHeaderStyle: TcxPivotGridGetFieldHeaderStyleEvent read FOnGetFieldHeaderStyle write FOnGetFieldHeaderStyle; property OnGetRowHeaderStyle: TcxPivotGridGetHeaderItemStyleEvent read FOnGetRowHeaderStyle write FOnGetRowHeaderStyle; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; function GetBackgroundParams: TcxViewParams; virtual; function GetColumnHeaderParams(AColumn: TcxPivotGridViewDataItem): TcxViewParams; virtual; function GetColumnMaximumValueParams: TcxViewParams; virtual; function GetColumnMinimumValueParams: TcxViewParams; virtual; function GetContentParams(ACell: TcxPivotGridDataCellViewInfo): TcxViewParams; virtual; function GetFieldHeaderParams(AField: TcxPivotGridField): TcxViewParams; virtual; function GetFilterSeparatorParams: TcxViewParams; virtual; function GetHeaderBackgroundParams(AArea: TcxPivotGridFieldArea): TcxViewParams; virtual; function GetMaximumValueParams: TcxViewParams; virtual; function GetMinimumValueParams: TcxViewParams; virtual; function GetPrefilterParams: TcxViewParams; virtual; function GetRowHeaderParams(ARow: TcxPivotGridViewDataItem): TcxViewParams; virtual; function GetRowMaximumValueParams: TcxViewParams; virtual; function GetRowMinimumValueParams: TcxViewParams; virtual; function GetSelectionParams: TcxViewParams; virtual; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; end; { TcxPivotGridStyles } TcxPivotGridStyles = class(TcxPivotGridCustomStyles) public function GetColumnHeaderParams(AColumn: TcxPivotGridViewDataItem): TcxViewParams; override; function GetContentParams(ACell: TcxPivotGridDataCellViewInfo): TcxViewParams; override; function GetRowHeaderParams(ARow: TcxPivotGridViewDataItem): TcxViewParams; override; published property Background; property ColumnHeader; property ColumnHeaderArea; property ColumnMaximumValue; property ColumnMinimumValue; property Content; property DataHeaderArea; property FieldHeader; property FilterHeaderArea; property FilterSeparator; property HeaderBackground; property Inactive; property MaximumValue; property MinimumValue; property Prefilter; property RowHeader; property RowHeaderArea; property RowMaximumValue; property RowMinimumValue; property Selected; property StyleSheet; property Total; property OnGetColumnHeaderStyle; property OnGetContentStyle; property OnGetFieldHeaderStyle; property OnGetRowHeaderStyle; end; { TcxPivotGridFieldStyles } TcxPivotGridFieldStyles = class(TcxPivotGridCustomStyles) protected procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override; function GetPivotGrid: TcxCustomPivotGrid; override; published property ColumnHeader; property ColumnMaximumValue; property ColumnMinimumValue; property Content; property MaximumValue; property MinimumValue; property RowHeader; property RowMaximumValue; property RowMinimumValue; property Total; property OnGetColumnHeaderStyle; property OnGetContentStyle; property OnGetRowHeaderStyle; end; { TcxPivotGridStyleSheet } TcxPivotGridStyleSheet = class(TcxCustomStyleSheet) private function GetStylesValue: TcxPivotGridStyles; procedure SetStylesValue(AValue: TcxPivotGridStyles); public class function GetStylesClass: TcxCustomStylesClass; override; published property Styles: TcxPivotGridStyles read GetStylesValue write SetStylesValue; end; // PivotGrid Base Classes { TcxPivotGridDataController } TcxPivotGridDataController = class(TcxCustomDataController) private function GetPivotGrid: TcxCustomPivotGrid; protected procedure FilterChanged; override; procedure UpdateControl(AInfo: TcxUpdateControlInfo); override; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; public function GetFilterItemFieldCaption(AItem: TObject): string; override; function GetItem(Index: Integer): TObject; override; function GetItemValueSource(AItemIndex: Integer): TcxDataEditValueSource; override; function GetItemID(AItem: TObject): Integer; override; procedure UpdateData; override; procedure UpdateItemIndexes; override; end; { TcxPivotGridOLAPField } TcxPivotGridOLAPField = class public Caption: WideString; Dimension: IUnknown; DimensionName: WideString; DimensionUniqueName: WideString; GroupIndex: Integer; GroupName: string; Hierarchy: IUnknown; HierarchyName: WideString; HierarchyUniqueName: WideString; IsMeasure: Boolean; Level: IUnknown; UniqueName: WideString; destructor Destroy; override; class function IsFiltered(AField: TcxPivotGridField): Boolean; class function PopulateFilteredValues(AField: TcxPivotGridField; IsExpanding: Boolean = False): TInterfaceList; end; TcxPivotGridInitializeFieldEvent = procedure(Sender: TcxPivotGridCustomOLAPDataSource; AField: TcxPivotGridField) of object; { TcxPivotGridCustomOLAPDataSource } TcxPivotGridCustomOLAPDataSource = class(TComponent) private FActive: Boolean; FListeners: TList; FOnInitializeField: TcxPivotGridInitializeFieldEvent; function GetField(AIndex: Integer): TcxPivotGridOLAPField; function GetFieldCount: Integer; function GetListenerCount: Integer; function GetListener(AIndex: Integer): TcxCustomPivotGrid; function GetMeasure(AIndex: Integer): TcxPivotGridOLAPField; function GetMeasureCount: Integer; procedure SetActive(AValue: Boolean); protected FFields: TcxObjectList; FMeasures: TcxObjectList; procedure AddListener(AListener: TcxCustomPivotGrid); procedure Changed; virtual; procedure Clear; virtual; function CreateDrillDownDataSource(ACell: TcxPivotGridCrossCell; FieldList: TcxObjectList): TcxPivotGridCrossCellDataSource; overload; virtual; function CreateDrillDownDataSource(ACells: TList; FieldList: TcxObjectList): TcxPivotGridCrossCellDataSource; overload; virtual; function CreateField(APivotGrid: TcxCustomPivotGrid; AOLAPField: TcxPivotGridOLAPField): TcxPivotGridField; virtual; procedure CreateFieldsFromFieldsList(APivotGrid: TcxCustomPivotGrid; AOLAPFields: TcxObjectList); procedure CreateMembers(AField: TcxPivotGridField; AParents: TList; AHasChildren: Boolean); virtual; function CreateMembersFromGroup(AItem: TcxPivotGridGroupItem; AIncludeParent: Boolean = True; ACheckExpanding: Boolean = False): TList; procedure CreateRootLayout(APivotGrid: TcxCustomPivotGrid); virtual; procedure DoInitializeField(AField: TcxPivotGridField); virtual; procedure ExpandMember(AField: TcxPivotGridField; AMember: TcxPivotGridGroupItem; AExpandChildren: Boolean); function GetHasData: Boolean; virtual; function GetIsActive: Boolean; virtual; function GetIsTerminated: Boolean; virtual; function GetLinkByUniqueName(const AName: WideString): TcxPivotGridOLAPField; procedure Initialize; virtual; procedure InitializeCrossCells(ARowsGroup, AColumnsGroup: TcxPivotGridGroupItem; ADataFields: TcxPivotGridFields); virtual; procedure InitializeCrossCellsForExpanding(ADataBuilder: TcxPivotGridDataBuilder; AnExpandingItem, ACrossGroup: TcxPivotGridGroupItem; ADataFields: TcxPivotGridFields); virtual; procedure InitializeCrossCellValues(ACell: TcxPivotGridCrossCell; const AFormattedValues, ANativeValues: Variant); procedure InitializeLayout(ARowFields, AColumnFields, ADataFields, AFilterFields: TcxPivotGridFields); virtual; procedure InitializeMembersAndTotalsForExpanding( ADataBuilder: TcxPivotGridDataBuilder; AField: TcxPivotGridField; AMember: TcxPivotGridGroupItem; ADataFields: TcxPivotGridFields); virtual; procedure InitializeMembers(AField: TcxPivotGridOLAPField; AMembers: TcxPivotGridVariantList); virtual; procedure PopulateFilteredUniqueNames(AField: TcxPivotGridOLAPField; AFilter: TcxPivotGridFieldFilter; var AUniqueValues: TStringList); virtual; procedure PopulateFilteredValues(AField: TcxPivotGridOLAPField; AFilter: TcxPivotGridFieldFilter; AValues: TInterfaceList; AUniqueValues: TStringList); virtual; procedure ProcessMembersForExpanding(AField: TcxPivotGridField; AMember: TcxPivotGridGroupItem; AExpandChildren: Boolean); procedure RemoveListener(AListener: TcxCustomPivotGrid); property Active: Boolean read FActive write SetActive default False; property FieldCount: Integer read GetFieldCount; property Fields[Index: Integer]: TcxPivotGridOLAPField read GetField; property HasData: Boolean read GetHasData; property IsActive: Boolean read GetIsActive; property IsTerminated: Boolean read GetIsTerminated; property ListenerCount: Integer read GetListenerCount; property Listeners[Index: Integer]: TcxCustomPivotGrid read GetListener; property MeasureCount: Integer read GetMeasureCount; property Measures[Index: Integer]: TcxPivotGridOLAPField read GetMeasure; property OnInitializeField: TcxPivotGridInitializeFieldEvent read FOnInitializeField write FOnInitializeField; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure RetrieveFields(APivotGrid: TcxCustomPivotGrid); end; { TcxPivotGridHitTest } TcxPivotGridHitTest = class private FField: TPersistent; FHitObject: TcxPivotGridCustomCellViewInfo; FHitPoint: TPoint; FOwner: TcxCustomPivotGrid; FResizeField: IcxPivotGridSizableObject; FResizeFieldStartPos: Integer; FShiftState: TShiftState; function GetBitState(AIndex: Integer): Boolean; function GetGroupItem: TcxPivotGridGroupItem; function GetPosValue(AIndex: Integer): Integer; function GetViewInfo: TcxPivotGridViewInfo; procedure SetBitState(AIndex: Integer; AValue: Boolean); procedure SetPosValue(AIndex, AValue: Integer); procedure SetHitPoint(const AValue: TPoint); protected Flags: Int64; property BitState[AIndex: Integer]: Boolean read GetBitState write SetBitState; property ResizeField: IcxPivotGridSizableObject read FResizeField; property ResizeFieldStartPos: Integer read FResizeFieldStartPos; property ViewInfo: TcxPivotGridViewInfo read GetViewInfo; public constructor Create(AOwner: TcxCustomPivotGrid); virtual; destructor Destroy; override; procedure Clear; procedure Recalculate; property Field: TPersistent read FField; property GroupItem: TcxPivotGridGroupItem read GetGroupItem; property HitAtButton: Boolean index htcButton read GetBitState; property HitAtDataCell: Boolean index htcDataCell read GetBitState; property HitAtDataField: Boolean index htcDataHeader read GetBitState; property HitAtField: Boolean index htcFieldHeader read GetBitState; property HitAtFilter: Boolean index htcFilter read GetBitState; property HitAtGroupHeader: Boolean index htcGroupHeader read GetBitState; property HitAtHeaderArea: Boolean index htcHeaderArea read GetBitState; property HitAtHorzSizingEdge: Boolean index htcHorzSizingEdge read GetBitState; property HitAtPrefilter: Boolean index htcPrefilter read GetBitState; property HitAtPrefilterCloseButton: Boolean index htcPrefilterCloseButton read GetBitState; property HitAtPrefilterActivateButton: Boolean index htcPrefilterActivateButton read GetBitState; property HitAtPrefilterCaption: Boolean index htcPrefilterCaption read GetBitState; property HitAtPrefilterCustomizationButton: Boolean index htcPrefilterCustomizationButton read GetBitState; property HitAtPrefilterDropDownButton: Boolean index htcPrefilterDropDownButton read GetBitState; property HitObject: TcxPivotGridCustomCellViewInfo read FHitObject; property HitPoint: TPoint read FHitPoint write SetHitPoint; property HitX: Integer index 0 read GetPosValue write SetPosValue; property HitY: Integer index 1 read GetPosValue write SetPosValue; property PivotGrid: TcxCustomPivotGrid read FOwner; property ShiftState: TShiftState read FShiftState write FShiftState; end; { TcxPivotGridHotTrackController } TcxPivotGridHotTrackController = class private FCell: TcxPivotGridCustomCellViewInfo; FOwner: TcxPivotGridController; function GetHitTest: TcxPivotGridHitTest; function GetPivotGrid: TcxCustomPivotGrid; protected procedure UpdateState(AObject: TcxPivotGridCustomCellViewInfo); public constructor Create(AOwner: TcxPivotGridController); virtual; procedure Clear; virtual; procedure Update(AObject: TcxPivotGridCustomCellViewInfo); virtual; property Cell: TcxPivotGridCustomCellViewInfo read FCell; property HitTest: TcxPivotGridHitTest read GetHitTest; property Owner: TcxPivotGridController read FOwner; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; end; { TcxPivotGridMRUPrefilterPopup } TcxPivotGridMRUPrefilterPopup = class(TcxCustomComboBox) private function GetPivotGrid: TcxCustomPivotGrid; function GetPrefilter: TcxPivotGridPrefilter; function SelectedMRUItem: TcxPivotGridFilterMRUItem; protected procedure BeforePopup; procedure DoCloseUp; override; procedure InitValues; procedure SetShadowRegion; override; public constructor Create(AOwner: TComponent); override; procedure Popup; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property Prefilter: TcxPivotGridPrefilter read GetPrefilter; end; { TcxPivotGridFilterPopup } TcxPivotGridFilterPopup = class(TcxPopupEdit) private FField: TcxPivotGridField; function GetPivotGrid: TcxCustomPivotGrid; function GetFilter: TcxPivotGridFieldFilter; procedure SetField(AField: TcxPivotGridField); procedure SetShowAllState(AValue: TcxCheckBoxState); function CreateButton(const ACaption: string; ATag: Integer): TcxButton; protected FButtonWidth: Integer; FCancelButton: TcxButton; FFilterModified: Boolean; FLocked: Boolean; FPrevFilterState: TcxButtonState; FOkButton: TcxButton; FShowAllState: TcxCheckBoxState; FValues: TcxCheckListBox; function AddValue(const AValue: TcxPivotGridVariantValue): TcxCheckListBoxItem; procedure BeforePopup; virtual; procedure ButtonClickHandler(ASender: TObject); virtual; procedure CheckButtonsEnabled; procedure CreateControls; virtual; procedure DoCloseUp; override; function GetCheckedCount: Integer; function GetFieldValueByValueIndex(AIndex: Integer): Variant; function GetHeight(AItemCount: Integer): Integer; function GetStateByCount(ACount: Integer): TcxCheckBoxState; procedure InitValues; virtual; procedure SetPopupSize(const AWidth, AHeight: Integer); procedure SetupPopupWindow; override; procedure SetShadowRegion; override; procedure ValuesChanges(Sender: TObject); public constructor Create(AOwner: TComponent); override; procedure Popup; procedure SaveChanges; virtual; property CancelButton: TcxButton read FCancelButton; property Field: TcxPivotGridField read FField write SetField; property Filter: TcxPivotGridFieldFilter read GetFilter; property FilterModified: Boolean read FFilterModified; property OkButton: TcxButton read FOkButton; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property ShowAllState: TcxCheckBoxState read FShowAllState write SetShowAllState; property Values: TcxCheckListBox read FValues; end; { TcxPivotGridCustomDragDropObject } TcxPivotGridCustomDragDropObject = class(TcxDragAndDropObject) private function GetHitTest: TcxPivotGridHitTest; function GetOptionsView: TcxPivotGridOptionsView; function GetPainter: TcxCustomLookAndFeelPainterClass; function GetViewInfo: TcxPivotGridViewInfo; protected function GetPivotGrid: TcxCustomPivotGrid; virtual; // public property HitTest: TcxPivotGridHitTest read GetHitTest; property OptionsView: TcxPivotGridOptionsView read GetOptionsView; property Painter: TcxCustomLookAndFeelPainterClass read GetPainter; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property ViewInfo: TcxPivotGridViewInfo read GetViewInfo; end; { TcxPivotGridResizingObject } TcxPivotGridResizingObject = class(TcxPivotGridCustomDragDropObject) private FSizeCursorPos: Integer; function GetSizeDelta: Integer; function GetSizeMarkBounds: TRect; procedure SetSizeCursorPos(AValue: Integer); protected StartPos, StartPosDelta: Integer; SizingBounds: TRect; SizableObject: IcxPivotGridSizableObject; procedure BeginDragAndDrop; override; procedure DirtyChanged; override; procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); override; function GetDragAndDropCursor(Accepted: Boolean): TCursor; override; function GetImmediateStart: Boolean; override; procedure EndDragAndDrop(Accepted: Boolean); override; procedure SetSizeDelta(ADelta: Integer); public property SizeCursorPos: Integer read FSizeCursorPos write SetSizeCursorPos; property SizeDelta: Integer read GetSizeDelta; property SizeMarkBounds: TRect read GetSizeMarkBounds; end; { TcxPivotGridDragAndDropObject } TcxPivotGridDragDropAreaInfo = class public Area: TcxPivotGridFieldArea; AreaIndex: Integer; Bounds: TRect; DisplayBounds: TRect; Field: TPersistent; end; TcxPivotGridDragAndDropObject = class(TcxPivotGridCustomDragDropObject) private FDragField: IcxPivotGridField; function GetDragDropAreaCount: Integer; function GetDragDropArea(AIndex: Integer): TcxPivotGridDragDropAreaInfo; function GetDragDropArrowColor: TColor; function GetDragImageBounds: TRect; function GetFieldViewInfo: TcxPivotGridFieldHeaderCellViewInfo; protected AAccepted: Boolean; ArrowsLine: TRect; ArrowsSaveBitmap, DragImage, SaveImage, TempImage: TBitmap; DragDropInfo: TcxPivotGridDragDropAreaInfo; DragImageVisible: Boolean; ImageSize: TSize; ImageSizeCalculated: Boolean; TransparentMask: TList; HotSpot: TPoint; // drag drop main function AboveCustomization: Boolean; procedure BeginDragAndDrop; override; function CanRemove: Boolean; virtual; function CheckArea(const P: TPoint; var AInfo: TcxPivotGridDragDropAreaInfo): Boolean; virtual; function CreateDragImage: TBitmap; virtual; procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); override; procedure DragDropField(AArea: TcxPivotGridFieldArea; AAreaIndex: Integer); virtual; procedure EndDragAndDrop(Accepted: Boolean); override; function GetDragAndDropCursor(Accepted: Boolean): TCursor; override; function GetDragImageSize: TSize; virtual; function IsSameDropPlace: Boolean; virtual; function IsPixelTransparent(ALine, APos: Integer): Boolean; procedure TransparentMixDragImage; // drag image helpers procedure ChangeArrowPos(AllowHide: Boolean); procedure CopyIntersectedImage(const ARect, AOldRect, ANewRect: TRect); procedure CopyImage(const AOldRect, ANewRect: TRect); function CreateBitmap(const ASize: TSize): TBitmap; function CreateScreenCanvas: TcxCanvas; procedure DrawArrows; procedure DrawImage(const APos: TPoint); procedure GetArrowRects(out R1, R2: TRect); function GetImageBounds(const APos: TPoint): TRect; procedure GetScreenImage(const APos: TPoint); procedure HideDragImage; procedure RestoreArrows; procedure RestoreScreen(const APos: TPoint); procedure ShowDragImage; public property DragField: IcxPivotGridField read FDragField; property DragDropAreaCount: Integer read GetDragDropAreaCount; property DragDropAreas[Index: Integer]: TcxPivotGridDragDropAreaInfo read GetDragDropArea; property DragDropArrowColor: TColor read GetDragDropArrowColor; property DragImageBounds: TRect read GetDragImageBounds; property DragImageSize: TSize read GetDragImageSize; property FieldViewInfo: TcxPivotGridFieldHeaderCellViewInfo read GetFieldViewInfo; end; { TcxPivotGridHintController } TcxPivotGridHintController = class(TcxIUnknownObject, IcxMouseTrackingCaller) private FHintAreaBounds: TRect; FHintCheckerTimer: TTimer; FHintObject: TObject; FHintText: string; FHintVisible: Boolean; FHintWindow: THintWindow; FOwner: TcxPivotGridController; function GetHitTest: TcxPivotGridHitTest; function GetPivotGrid: TcxCustomPivotGrid; protected function CanShowHint: Boolean; function GetHintInfo(var ABounds, AWindowBounds: TRect): Boolean; virtual; procedure HintCheckerTimerHandler(Sender: TObject); procedure HintWindowNeeded; virtual; function NeedShowHint: Boolean; virtual; procedure MouseLeave; procedure StartHintCheckerTimer; procedure StopHintCheckerTimer; property HintCheckerTimer: TTimer read FHintCheckerTimer write FHintCheckerTimer; property HintObject: TObject read FHintObject write FHintObject; property HintWindow: THintWindow read FHintWindow; public constructor Create(AOwner: TcxPivotGridController); virtual; destructor Destroy; override; procedure HideHint; virtual; procedure ShowHint; virtual; procedure Update; property HintAreaBounds: TRect read FHintAreaBounds write FHintAreaBounds; property HintText: string read FHintText write FHintText; property HintVisible: Boolean read FHintVisible; property HitTest: TcxPivotGridHitTest read GetHitTest; property Owner: TcxPivotGridController read FOwner; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; end; { TcxPivotGridController } TcxPivotGridController = class private FIgnoreSelection: Boolean; FFilterPopup: TcxPivotGridFilterPopup; FHintController: TcxPivotGridHintController; FHotTrackController: TcxPivotGridHotTrackController; FOwner: TcxCustomPivotGrid; FPrefilterPopup: TcxPivotGridMRUPrefilterPopup; FSelectionTimer: TTimer; procedure CalculateIgnoreSelection; function GetFocused: Boolean; function GetFocusedCell: TPoint; function GetHitTest: TcxPivotGridHitTest; function GetIsDesigning: Boolean; function GetOptionsCustomize: TcxPivotGridOptionsCustomize; function GetOptionsSelection: TcxPivotGridOptionsSelection; function GetOptionsView: TcxPivotGridOptionsView; function GetViewData: TcxPivotGridViewData; function GetViewInfo: TcxPivotGridViewInfo; protected DownField: IcxPivotGridField; FilterOpenedBeforeClick: Boolean; PrefilterOpenedBeforeClick: Boolean; SuspendSelectionTimer: Boolean; procedure CalculateAnchor(AShift: TShiftState); function CalculateFilterDropDownSize(AFilter: TcxPivotGridFieldFilter): TSize; procedure CheckSelectionTimer(const X, Y: Integer); function CreateFilterPopup: TcxPivotGridFilterPopup; virtual; function CreateHintController: TcxPivotGridHintController; virtual; function CreateHotTrackController: TcxPivotGridHotTrackController; virtual; procedure DoFieldHeaderClick(AField: TPersistent; AShift: TShiftState); function GetCursor(const X, Y: Integer): TCursor; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; virtual; function IsButtonDown: Boolean; virtual; function IsCellSelected(ACell: TcxPivotGridDataCellViewInfo): Boolean; procedure MakeSelected(AShift: TShiftState; AMouseMove: Boolean = False); virtual; function ProcessNavigationByStep(AGoBackward: Boolean; AShiftState: TShiftState): Boolean; procedure ProcessTabKeyDown(AGoBackward: Boolean); procedure SelectionTimerHandler(Sender: TObject); procedure SetSelection(ACol, ARow: Integer; AShift: TShiftState); procedure SetSelectionInc(const DX, DY: Integer; AShift: TShiftState; AByTimer: Boolean = False); function StartDragAndDrop(const P: TPoint): Boolean; virtual; public constructor Create(AOwner: TcxCustomPivotGrid); virtual; destructor Destroy; override; procedure Clear; virtual; procedure BeforeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure DblClick; virtual; procedure KeyDown(var AKey: Word; AShift: TShiftState); virtual; procedure KeyPress(var AKey: Char); virtual; procedure MakeCellFocused(ACell: TcxPivotGridDataCellViewInfo; AShift: TShiftState); procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure MouseLeave; virtual; procedure MouseMove(Shift: TShiftState; X, Y: Integer); virtual; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure StartSelectionTimer; procedure StopSelectionTimer; procedure Update; virtual; property FilterPopup: TcxPivotGridFilterPopup read FFilterPopup; property Focused: Boolean read GetFocused; property FocusedCell: TPoint read GetFocusedCell; property HitTest: TcxPivotGridHitTest read GetHitTest; property HintController: TcxPivotGridHintController read FHintController; property HotTrackController: TcxPivotGridHotTrackController read FHotTrackController; property IsDesigning: Boolean read GetIsDesigning; property OptionsCustomize: TcxPivotGridOptionsCustomize read GetOptionsCustomize; property OptionsSelection: TcxPivotGridOptionsSelection read GetOptionsSelection; property OptionsView: TcxPivotGridOptionsView read GetOptionsView; property PivotGrid: TcxCustomPivotGrid read FOwner; property PrefilterPopup: TcxPivotGridMRUPrefilterPopup read FPrefilterPopup; property SelectionTimer: TTimer read FSelectionTimer; property ViewData: TcxPivotGridViewData read GetViewData; property ViewInfo: TcxPivotGridViewInfo read GetViewInfo; end; { TcxPivotGridFilterValues } TcxPivotGridFilterType = (ftExcluded, ftIncluded); TcxPivotGridFieldFilter = class(TPersistent) private FField: TcxPivotGridField; FFilterType: TcxPivotGridFilterType; FLockCount: Integer; FModified: Boolean; FValues: TcxPivotGridVariantList; FWindowSize: TSize; FOnChange: TNotifyEvent; function GetHasFilter: Boolean; function GetPivotGrid: TcxCustomPivotGrid; procedure SetFilterType(AFilterType: TcxPivotGridFilterType); protected procedure Changed; virtual; function GetOwner: TPersistent; override; procedure ValuesChanged(ASender: TObject); virtual; procedure BeginUpdate; procedure EndUpdate(AForceUpdate: Boolean = True); procedure ReadData(AStream: TStream); procedure WriteData(AStream: TStream); property WindowSize: TSize read FWindowSize write FWindowSize; public constructor Create(AOwner: TcxPivotGridField); virtual; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure Clear; virtual; function Contains(const AValue: Variant): Boolean; property Field: TcxPivotGridField read FField; property FilterType: TcxPivotGridFilterType read FFilterType write SetFilterType; property HasFilter: Boolean read GetHasFilter; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property Values: TcxPivotGridVariantList read FValues; property OnChange: TNotifyEvent read FOnChange write FOnChange; end; { TcxPivotGridFieldOptions } TcxPivotGridFieldOptions = class(TPersistent) private FField: TcxPivotGridField; FFiltering: Boolean; FMoving: Boolean; FSizing: Boolean; FSorting: Boolean; procedure SetFiltering(AValue: Boolean); procedure SetMoving(AValue: Boolean); procedure SetSizing(AValue: Boolean); procedure SetSorting(AValue: Boolean); protected function CanFiltering: Boolean; function CanSorting: Boolean; procedure Changed; virtual; function GetOwner: TPersistent; override; procedure SetOption(var AOption: Boolean; ANewValue: Boolean); public constructor Create(AOwner: TcxPivotGridField); virtual; procedure Assign(Source: TPersistent); override; property Field: TcxPivotGridField read FField; published property Filtering: Boolean read FFiltering write SetFiltering default True; property Moving: Boolean read FMoving write SetMoving default True; property Sizing: Boolean read FSizing write SetSizing default True; property Sorting: Boolean read FSorting write SetSorting default True; end; { TcxPivotGridCustomTotal } TcxPivotGridCustomTotal = class(TCollectionItem) private FDisplayFormat: string; FSummaryType: TcxPivotGridSummaryType; function GetField: TcxPivotGridField; function GetPivotGrid: TcxCustomPivotGrid; procedure SetDisplayFormat(const AValue: string); procedure SetSummaryType(AValue: TcxPivotGridSummaryType); public constructor Create(Collection: TCollection); override; procedure Assign(Source: TPersistent); override; property Field: TcxPivotGridField read GetField; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; published property SummaryType: TcxPivotGridSummaryType read FSummaryType write SetSummaryType default stSum; property DisplayFormat: string read FDisplayFormat write SetDisplayFormat; end; { TcxPivotGridCustomTotalCollection } TcxPivotGridCustomTotalCollection = class(TCollection) private FOwner: TcxPivotGridField; function GetItem(AIndex: Integer): TcxPivotGridCustomTotal; function GetPivotGrid: TcxCustomPivotGrid; procedure SetItem(AIndex: Integer; AValue: TcxPivotGridCustomTotal); protected function GetOwner: TPersistent; override; procedure Update(Item: TCollectionItem); override; public constructor Create(AOwner: TcxPivotGridField); overload; virtual; function Add(ASummaryType: TcxPivotGridSummaryType): TcxPivotGridCustomTotal; property Field: TcxPivotGridField read FOwner; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property Items[Index: Integer]: TcxPivotGridCustomTotal read GetItem write SetItem; default; end; { TcxPivotGridSortBySummaryInfo } TcxPivotGridSortBySummaryInfo = class(TPersistent) private FField: TcxPivotGridField; FOwner: TcxPivotGridField; FSummaryType: TcxPivotGridSummaryType; function GetPivotGrid: TcxCustomPivotGrid; procedure SetField(AValue: TcxPivotGridField); procedure SetSummaryType(AValue: TcxPivotGridSummaryType); protected procedure Changed; virtual; function GetOwner: TPersistent; override; function ValidateProperties: Boolean; virtual; public constructor Create(AOwner: TcxPivotGridField); virtual; procedure Assign(Source: TPersistent); override; property Owner: TcxPivotGridField read FOwner; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; published property Field: TcxPivotGridField read FField write SetField; property SummaryType: TcxPivotGridSummaryType read FSummaryType write SetSummaryType default stSum; end; { TcxPivotGridDefaultValuesProvider } TcxPivotGridDefaultValuesProvider = class(TcxCustomEditDefaultValuesProvider) public function IsDisplayFormatDefined(AIsCurrencyValueAccepted: Boolean): Boolean; override; end; { TcxPivotGridFieldDataBinding } TcxPivotGridFieldDataBinding = class(TPersistent) private FField: TcxPivotGridField; FValueTypeAssigned: Boolean; function GetPivotGrid: TcxCustomPivotGrid; function GetValueType: string; function GetValueTypeClass: TcxValueTypeClass; procedure SetValueType(AValue: string); procedure SetValueTypeClass(AValue: TcxValueTypeClass); function IsValueTypeStored: Boolean; protected FDefaultValuesProvider: TcxCustomEditDefaultValuesProvider; function GetDefaultValuesProvider: IcxEditDefaultValuesProvider; virtual; function GetDefaultValuesProviderClass: TcxCustomEditDefaultValuesProviderClass; virtual; function GetFilterFieldName: string; virtual; function GetOwner: TPersistent; override; procedure Init; virtual; public constructor Create(AOwner: TcxPivotGridField); virtual; destructor Destroy; override; procedure Assign(Source: TPersistent); override; property Field: TcxPivotGridField read FField; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property ValueTypeAssigned: Boolean read FValueTypeAssigned write FValueTypeAssigned; property ValueTypeClass: TcxValueTypeClass read GetValueTypeClass write SetValueTypeClass; published property ValueType: string read GetValueType write SetValueType stored IsValueTypeStored; end; { TcxPivotGridField } TcxPivotGridSummaryVariation = (svNone, svAbsolute, svPercent, svPercentOfColumn, svPercentOfRow); TcxPivotGridFieldDataVisibility = (dvAllCells, dvCrossAndTotalCells, dvGrandTotalCells); TcxPivotGridCalculateCustomSummaryEvent = procedure(Sender: TcxPivotGridField; ASummary: TcxPivotGridCrossCellSummary) of object; TcxPivotGridGetDisplayTextEvent = procedure(Sender: TcxPivotGridField; ACell: TcxPivotGridDataCellViewInfo; var AText: string) of object; TcxPivotGridGetGroupValueDisplayTextEvent = procedure(Sender: TcxPivotGridField; const AGroupValue: Variant; var AText: string) of object; TcxPivotGridGetGroupValueEvent = procedure(Sender: TcxPivotGridField; ARecordIndex: Integer; var AValue: Variant) of object; TcxPivotGridGetTotalDisplayTextEvent = procedure(Sender: TcxPivotGridField; AGroupItem: TcxPivotGridGroupItem; var AText: string) of object; TcxPivotGridGetPropertiesEvent = procedure(Sender: TcxPivotGridField; ACell: TcxPivotGridCustomCellViewInfo; var AProperties: TcxCustomEditProperties) of object; TcxPivotGridFieldGetGroupImageIndex = procedure(Sender: TcxPivotGridField; const AItem: TcxPivotGridViewDataItem; var AImageIndex: Integer; var AImageAlignHorz: TAlignment; var AImageAlignVert: TcxAlignmentVert) of object; TcxPivotGridField = class(TComponent, IUnknown, IcxPivotGridSizableObject, IcxPivotGridField, IcxStoredObject, IcxEditRepositoryItemListener) private FAllowedAreas: TcxPivotGridFieldAreas; FArea: TcxPivotGridFieldArea; FAreaIndex: Integer; FCaption: string; FCustomTotals: TcxPivotGridCustomTotalCollection; FCurrency: Boolean; FDataBinding: TcxPivotGridFieldDataBinding; FDataVisibility: TcxPivotGridFieldDataVisibility; FDisplayFormat: string; FEditStyle: TcxEditStyle; FEditViewData: TcxCustomEditViewData; FExpandingInfo: TcxPivotGridVariantList; FFilter: TcxPivotGridFieldFilter; FFloat: Boolean; FGroup: TcxPivotGridFieldGroup; FGroupExpanded: Boolean; FGroupValueList: TcxPivotGridVariantList; FGroupValuesValid: Boolean; FGroupInterval: TcxPivotGridGroupInterval; FGroupIntervalRange: Integer; FHidden: Boolean; FImageAlign: TAlignment; FImageIndex: TImageIndex; FIsCaptionAssigned: Boolean; FLastUsedDefaultRepositoryItem: TcxEditRepositoryItem; FLink: TcxPivotGridOLAPField; FMinWidth: Integer; FOptions: TcxPivotGridFieldOptions; FPivotGrid: TcxCustomPivotGrid; FProperties: TcxCustomEditProperties; FPropertiesClass: TcxCustomEditPropertiesClass; FPropertiesValue: TcxCustomEditProperties; FRepositoryItem: TcxEditRepositoryItem; FSortOrder: TcxDataSortOrder; FSortBySummaryInfo: TcxPivotGridSortBySummaryInfo; FStyles: TcxPivotGridFieldStyles; FSubClassEvents: TNotifyEvent; FSummaryIndex: Integer; FSummaryType: TcxPivotGridSummaryType; FSummaryVariation: TcxPivotGridSummaryVariation; FTotalsVisibility: TcxPivotGridTotalsVisibility; FTopValueCount: Integer; FTopValueShowOthers: Boolean; FUniqueName: string; FVisible: Boolean; FVisibleIndex: Integer; FViewInfo: TcxPivotGridFieldHeaderCellViewInfo; FWidth: Integer; FOnCalculateCustomSummary: TcxPivotGridCalculateCustomSummaryEvent; FOnGetDisplayText: TcxPivotGridGetDisplayTextEvent; FOnGetGroupImageIndex: TcxPivotGridFieldGetGroupImageIndex; FOnGetGroupValue: TcxPivotGridGetGroupValueEvent; FOnGetGroupValueDisplayText: TcxPivotGridGetGroupValueDisplayTextEvent; FOnGetProperties: TcxPivotGridGetPropertiesEvent; FOnGetTotalDisplayText: TcxPivotGridGetTotalDisplayTextEvent; // IcxStoredObject events FOnGetStoredProperties: TcxGetStoredPropertiesEvent; FOnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent; FOnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent; function GetAllowedAreas: TcxPivotGridFieldAreas; function GetActualWidth: Integer; function GetController: TcxPivotGridController; function GetDataBuilder: TcxPivotGridDataBuilder; function GetGroupExpanded: Boolean; function GetGroupIndex: Integer; function GetGroupValueList: TcxPivotGridVariantList; function GetHeaderWidth: Integer; function GetHidden: Boolean; function GetIndex: Integer; function GetIsDestroying: Boolean; function GetIsHierarchy: Boolean; function GetMinWidth: Integer; function GetPropertiesClassName: string; function GetRecordCount: Integer; function GetSortedBySummary: Boolean; function GetUniqueName: WideString; function GetValueByRecordIndex(ARecordIndex: Integer): Variant; function GetVisible: Boolean; function GetVisibleInGroup: Boolean; function IsFirstFieldInGroup: Boolean; procedure SetArea(AValue: TcxPivotGridFieldArea); procedure SetAreaIndex(AValue: Integer); procedure SetCaption(const AValue: string); procedure SetCustomTotals(AValue: TcxPivotGridCustomTotalCollection); procedure SetDataBinding(AValue: TcxPivotGridFieldDataBinding); procedure SetDataVisibility(AValue: TcxPivotGridFieldDataVisibility); procedure SetDisplayFormat(const AValue: string); procedure SetGroup(AValue: TcxPivotGridFieldGroup); procedure SetGroupExpanded(AValue: Boolean); procedure SetGroupIndex(AValue: Integer); procedure SetGroupInterval(AValue: TcxPivotGridGroupInterval); procedure SetGroupIntervalRange(AValue: Integer); procedure SetHidden(AValue: Boolean); procedure SetImageAlign(AValue: TAlignment); procedure SetImageIndex(AValue: TImageIndex); procedure SetIndex(AValue: Integer); procedure SetMinWidth(Avalue: Integer); procedure SetOnGetProperties(AValue: TcxPivotGridGetPropertiesEvent); procedure SetOptions(AValue: TcxPivotGridFieldOptions); procedure SetProperties(Value: TcxCustomEditProperties); procedure SetPropertiesClass(Value: TcxCustomEditPropertiesClass); procedure SetPropertiesClassName(const Value: string); procedure SetRepositoryItem(Value: TcxEditRepositoryItem); procedure SetSortOrder(AValue: TcxDataSortOrder); procedure SetSortBySummaryInfo(AValue: TcxPivotGridSortBySummaryInfo); procedure SetStyles(AValue: TcxPivotGridFieldStyles); procedure SetSummaryType(AValue: TcxPivotGridSummaryType); procedure SetSummaryVariation(AValue: TcxPivotGridSummaryVariation); procedure SetTotalsVisibility(AValue: TcxPivotGridTotalsVisibility); procedure SetTopValueCount(AValue: Integer); procedure SetTopValueShowOthers(AValue: Boolean); procedure SetUniqueName(const AValue: WideString); procedure SetValueByRecordIndex(ARecordIndex: Integer; const AValue: Variant); procedure SetVisible(AValue: Boolean); procedure SetWidth(AValue: Integer); // Event Handlers procedure FilterChanged(Sender: TObject); procedure InternalDoGetDisplayText(ACell: TcxPivotGridDataCellViewInfo; var AText: string); // function IsAllowedAreasStored: Boolean; function IsCustomTotalStored: Boolean; // IcxPivotGridField procedure ChangeExpanding; procedure ChangeSorting; function GetViewInfo: TcxPivotGridFieldHeaderCellViewInfo; procedure SetState(AState: TcxButtonState); procedure CreateProperties; procedure DestroyProperties; procedure RecreateProperties; protected function CanDrag: Boolean; virtual; function CanDrop(AArea: TcxPivotGridFieldArea): Boolean; virtual; function CanModifyArea: Boolean; function CanRemove: Boolean; virtual; function CanResize: Boolean; procedure Changed(AIsViewChanged: Boolean = False); virtual; function CreateEditStyle(AProperties: TcxCustomEditProperties): TcxEditStyle; procedure CreateEditViewData; procedure DataChanged; virtual; function DefaultRepositoryItem: TcxEditRepositoryItem; virtual; procedure DestroyEditViewData; procedure DragDrop(AArea: TcxPivotGridFieldArea; AAreaIndex: Integer); virtual; function GetEditViewData: TcxCustomEditViewData; procedure InitGroupValues; procedure InitProperties(AProperties: TcxCustomEditProperties); //Embedded virtual methods procedure DoCalculateCustomSummary(ACell: TcxPivotGridCrossCellSummary); virtual; procedure DoGetDisplayText(ACell: TcxPivotGridDataCellViewInfo); virtual; function DoGetGroupImageIndex(AItem: TcxPivotGridViewDataItem; var AAlignHorz: TAlignment; var AAlignVert: TcxAlignmentVert): Integer; virtual; function DoGetGroupValue(const AValue: Variant; ARecordIndex: Integer): Variant; virtual; function DoGetGroupValueDisplayText(const AValue: Variant): string; virtual; procedure DoFilterChanged; virtual; function DoGetProperties(ACell: TcxPivotGridCustomCellViewInfo): TcxCustomEditProperties; procedure DoGetTotalDisplayText(AGroupItem: TcxPivotGridGroupItem; var AText: string); virtual; //Conditions function IsCurrency(AType: TcxValueTypeClass): Boolean; virtual; function IsItemExpanded(AGroup: TcxPivotGridGroupItem): Boolean; function HasSummaryVariation: Boolean; //Getters function GetActualDisplayFormat: string; virtual; function GetEditProperties: TcxCustomEditProperties; function GetEditStyle(AProperties: TcxCustomEditProperties; ALocal: Boolean): TcxEditStyle; function GetUserEditProperties: TcxCustomEditProperties; function GetPropertiesValue: TcxCustomEditProperties; function GetRepositoryItem: TcxEditRepositoryItem; //EditProperties procedure EditViewDataGetDisplayTextHandler(Sender: TcxCustomEditViewData; var AText: string); procedure PropertiesChanged; procedure PropertiesChangedHandler(Sender: TObject); procedure PropertiesValueChanged; function UseEditProperties: Boolean; // grouping function CreateCustomTotals: TcxPivotGridCustomTotalCollection; virtual; function CreateDataBinding: TcxPivotGridFieldDataBinding; virtual; function CreateFilter: TcxPivotGridFieldFilter; virtual; function CreateOptions: TcxPivotGridFieldOptions; virtual; function CreateSortBySummaryInfo: TcxPivotGridSortBySummaryInfo; virtual; function CreateStyles: TcxPivotGridFieldStyles; virtual; procedure CreateSubClasses; virtual; procedure DestroySubClasses; virtual; procedure GroupCheckExpanding(AGroup: TcxPivotGridGroupItem); procedure GroupExpandingChanged(ASender: TcxPivotGridGroupItem); virtual; // function GetCaption: string; virtual; function GetDataType: TVarType; function GetDisplayTextAssigned: Boolean; function IsRecordVisible(ARecordIndex: Integer): Boolean; procedure SetAreaIndexInternal(AArea: TcxPivotGridFieldArea; AAreaIndex: Integer); procedure SetExpanding(AValue: Boolean); procedure SetParentComponent(Value: TComponent); override; procedure SetPivotGrid(AValue: TcxCustomPivotGrid); procedure SynchronizeUniqueName; // IcxEditRepositoryItemListener procedure ItemRemoved(Sender: TcxEditRepositoryItem); procedure IcxEditRepositoryItemListener.PropertiesChanged = RepositoryItemPropertiesChanged; procedure RepositoryItemPropertiesChanged(Sender: TcxEditRepositoryItem); // IcxStoredObject function GetObjectName: string; function GetProperties(AProperties: TStrings): Boolean; overload; virtual; procedure GetPropertyValue(const AName: string; var AValue: Variant); virtual; procedure SetPropertyValue(const AName: string; const AValue: Variant); virtual; property Controller: TcxPivotGridController read GetController; property Currency: Boolean read FCurrency write FCurrency; property DataBuilder: TcxPivotGridDataBuilder read GetDataBuilder; property ExpandingInfo: TcxPivotGridVariantList read FExpandingInfo; property Float: Boolean read FFloat write FFloat; property GroupValuesValid: Boolean read FGroupValuesValid write FGroupValuesValid; property HeaderWidth: Integer read GetHeaderWidth; property ViewInfo: TcxPivotGridFieldHeaderCellViewInfo read FViewInfo; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure ApplyBestFit; procedure CollapseAll; procedure ExpandAll; function GetGroupValue(ARecordIndex: Integer): Variant; function GetGroupValueDisplayText(const AGroupValue: Variant): string; function GetParentComponent: TComponent; override; function HasParent: Boolean; override; procedure SetAreaPosition(AArea: TcxPivotGridFieldArea; AAreaIndex: Integer); property ActualWidth: Integer read GetActualWidth; property Filter: TcxPivotGridFieldFilter read FFilter; property Group: TcxPivotGridFieldGroup read FGroup write SetGroup; property GroupValueList: TcxPivotGridVariantList read GetGroupValueList; property Index: Integer read GetIndex write SetIndex; property Link: TcxPivotGridOLAPField read FLink; property IsHierarchy: Boolean read GetIsHierarchy; property PivotGrid: TcxCustomPivotGrid read FPivotGrid write SetPivotGrid; property PropertiesClass: TcxCustomEditPropertiesClass read FPropertiesClass write SetPropertiesClass; property RecordCount: Integer read GetRecordCount; property SortedBySummary: Boolean read GetSortedBySummary; property SummaryIndex: Integer read FSummaryIndex; property Values[ARecordIndex: Integer]: Variant read GetValueByRecordIndex write SetValueByRecordIndex; property VisibleInGroup: Boolean read GetVisibleInGroup; property VisibleIndex: Integer read FVisibleIndex; published property Area: TcxPivotGridFieldArea read FArea write SetArea default faFilter; property AreaIndex: Integer read FAreaIndex write SetAreaIndex default cxPivotGridInvalidIndex; property AllowedAreas: TcxPivotGridFieldAreas read GetAllowedAreas write FAllowedAreas stored IsAllowedAreasStored; property IsCaptionAssigned: Boolean read FIsCaptionAssigned write FIsCaptionAssigned default False; property Caption: string read GetCaption write SetCaption stored FIsCaptionAssigned; property CustomTotals: TcxPivotGridCustomTotalCollection read FCustomTotals write SetCustomTotals stored IsCustomTotalStored; property DataBinding: TcxPivotGridFieldDataBinding read FDataBinding write SetDataBinding; property DataVisibility: TcxPivotGridFieldDataVisibility read FDataVisibility write SetDataVisibility default dvAllCells; property DisplayFormat: string read FDisplayFormat write SetDisplayFormat; property Options: TcxPivotGridFieldOptions read FOptions write SetOptions; property PropertiesClassName: string read GetPropertiesClassName write SetPropertiesClassName; property Properties: TcxCustomEditProperties read FProperties write SetProperties; property RepositoryItem: TcxEditRepositoryItem read FRepositoryItem write SetRepositoryItem; property ImageAlign: TAlignment read FImageAlign write SetImageAlign default taLeftJustify; property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default -1; property GroupIndex: Integer read GetGroupIndex write SetGroupIndex default -1; property GroupExpanded: Boolean read GetGroupExpanded write SetGroupExpanded default True; property GroupInterval: TcxPivotGridGroupInterval read FGroupInterval write SetGroupInterval default giDefault; property GroupIntervalRange: Integer read FGroupIntervalRange write SetGroupIntervalRange default cxPivotGridDefaultGroupIntervalRange; property Hidden: Boolean read GetHidden write SetHidden default False; property MinWidth: Integer read GetMinWidth write SetMinWidth default cxPivotGridDefaultFieldMinWidth; property SummaryType: TcxPivotGridSummaryType read FSummaryType write SetSummaryType default stSum; property SortBySummaryInfo: TcxPivotGridSortBySummaryInfo read FSortBySummaryInfo write SetSortBySummaryInfo; property SortOrder: TcxDataSortOrder read FSortOrder write SetSortOrder default soNone; property Styles: TcxPivotGridFieldStyles read FStyles write SetStyles; property SummaryVariation: TcxPivotGridSummaryVariation read FSummaryVariation write SetSummaryVariation default svNone; property TotalsVisibility: TcxPivotGridTotalsVisibility read FTotalsVisibility write SetTotalsVisibility default tvAutomatic; property TopValueCount: Integer read FTopValueCount write SetTopValueCount default 0; property TopValueShowOthers: Boolean read FTopValueShowOthers write SetTopValueShowOthers default False; property UniqueName: WideString read GetUniqueName write SetUniqueName; property Visible: Boolean read GetVisible write SetVisible default False; property Width: Integer read FWidth write SetWidth default 0; // property PropertiesEvents: TNotifyEvent read FSubClassEvents write FSubClassEvents; property OnCalculateCustomSummary: TcxPivotGridCalculateCustomSummaryEvent read FOnCalculateCustomSummary write FOnCalculateCustomSummary; property OnGetDisplayText: TcxPivotGridGetDisplayTextEvent read FOnGetDisplayText write FOnGetDisplayText; property OnGetGroupImageIndex: TcxPivotGridFieldGetGroupImageIndex read FOnGetGroupImageIndex write FOnGetGroupImageIndex; property OnGetGroupValue: TcxPivotGridGetGroupValueEvent read FOnGetGroupValue write FOnGetGroupValue; property OnGetGroupValueDisplayText: TcxPivotGridGetGroupValueDisplayTextEvent read FOnGetGroupValueDisplayText write FOnGetGroupValueDisplayText; property OnGetProperties: TcxPivotGridGetPropertiesEvent read FOnGetProperties write SetOnGetProperties; property OnGetTotalDisplayText: TcxPivotGridGetTotalDisplayTextEvent read FOnGetTotalDisplayText write FOnGetTotalDisplayText; // IcxStoredObject events property OnGetStoredProperties: TcxGetStoredPropertiesEvent read FOnGetStoredProperties write FOnGetStoredProperties; property OnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent read FOnGetStoredPropertyValue write FOnGetStoredPropertyValue; property OnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent read FOnSetStoredPropertyValue write FOnSetStoredPropertyValue; end; { TcxPivotGridFieldGroup } TcxPivotGridFieldGroup = class(TCollectionItem) private FCaption: string; FIsCaptionAssigned: Boolean; function GetArea: TcxPivotGridFieldArea; function GetAreaIndex: Integer; function GetCaption: string; function GetField(AIndex: Integer): TcxPivotGridField; function GetFieldCount: Integer; function GetGroups: TcxPivotGridFieldGroupCollection; function GetIsDestroying: Boolean; function GetPivotGrid: TcxCustomPivotGrid; function GetVisible: Boolean; function GetVisibleCount: Integer; procedure SetArea(AValue: TcxPivotGridFieldArea); procedure SetAreaIndex(AValue: Integer); procedure SetCaption(const AValue: string); procedure SetVisible(AValue: Boolean); protected FieldList: TList; function CanDropTo(AArea: TcxPivotGridFieldArea; AIndex: Integer): Boolean; virtual; function GetLatestIndex: Integer; function GetNextField(AField: TcxPivotGridField): TcxPivotGridField; procedure GroupChanged; virtual; procedure InternalSetArea(AArea: TcxPivotGridFieldArea); function IsSameDropPlace(AIndex: Integer): Boolean; procedure ResetIndexes(var ANewIndex: Integer); procedure SetExpanded(AExpanded: Boolean); property IsDestroying: boolean read GetIsDestroying; public constructor Create(Collection: TCollection); override; destructor Destroy; override; procedure Add(AField: TcxPivotGridField); procedure AddFields(AFields: array of TcxPivotGridField); procedure Clear; procedure FullCollapse; procedure FullExpand; function IndexOf(AField: TcxPivotGridField): Integer; procedure Insert(AIndex: Integer; AField: TcxPivotGridField); function IsFieldVisible(AField: TcxPivotGridField): Boolean; function IsLastVisibleField(AField: TcxPivotGridField): Boolean; procedure Remove(AField: TcxPivotGridField); property FieldCount: Integer read GetFieldCount; property Fields[AIndex: Integer]: TcxPivotGridField read GetField; default; property Groups: TcxPivotGridFieldGroupCollection read GetGroups; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; property VisibleCount: Integer read GetVisibleCount; published property Area: TcxPivotGridFieldArea read GetArea write SetArea stored False; property AreaIndex: Integer read GetAreaIndex write SetAreaIndex stored False; property IsCaptionAssigned: Boolean read FIsCaptionAssigned write FIsCaptionAssigned; property Caption: string read GetCaption write SetCaption stored FIsCaptionAssigned; property Visible: Boolean read GetVisible write SetVisible stored False; end; { TcxPivotGridFieldGroupCollection } TcxPivotGridFieldGroupCollection = class(TCollection) private FOwner: TcxCustomPivotGrid; function GetItem(AIndex: Integer): TcxPivotGridFieldGroup; procedure SetItem(AIndex: Integer; AValue: TcxPivotGridFieldGroup); protected function CanDropTo(AArea: TcxPivotGridFieldArea; AIndex: Integer): Boolean; virtual; function GetOwner: TPersistent; override; procedure Loaded; virtual; procedure Update(Item: TCollectionItem); override; public constructor Create(AOwner: TcxCustomPivotGrid); overload; virtual; function Add: TcxPivotGridFieldGroup; property PivotGrid: TcxCustomPivotGrid read FOwner; property Items[Index: Integer]: TcxPivotGridFieldGroup read GetItem write SetItem; default; end; { TcxPivotGridPopupMenus } TcxPivotGridCustomPopupMenu = class(TPersistent) private FBuiltInMenu: TPopupMenu; FOwner: TcxPivotGridPopupMenus; FPopupMenu: TComponent; FUseBuiltInMenu: Boolean; function GetPivotGrid: TcxCustomPivotGrid; function GetRoot: TMenuItem; procedure SetPopupMenu(AValue: TComponent); protected procedure AssignValues(ASource: TcxPivotGridCustomPopupMenu); virtual; procedure CreateInternalMenu; procedure CreateItems; virtual; function CreateSeparator(AOwner: TMenuItem): TMenuItem; function CreateSubItem(AOwner: TMenuItem; const ACaption: string; ACommand: Integer; AEnabled: Boolean = True): TMenuItem; procedure DoExecute(ACommand: Integer); virtual; procedure ExecuteItem(AItem: TMenuItem); function GetItemByCommand(ACommand: Integer): TMenuItem; function GetOwner: TPersistent; override; procedure MenuItemClickHandler(Sender: TObject); virtual; procedure Notification(AComponent: TComponent; Operation: TOperation); virtual; property Root: TMenuItem read GetRoot; public constructor Create(AOwner: TcxPivotGridPopupMenus); virtual; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure ExecuteCommand(ACommand: Integer); function Popup(X, Y: Integer): Boolean; virtual; property BuiltInMenu: TPopupMenu read FBuiltInMenu; property Owner: TcxPivotGridPopupMenus read FOwner; property PivotGrid: TcxCustomPivotGrid read GetPivotGrid; published property PopupMenu: TComponent read FPopupMenu write SetPopupMenu; property UseBuiltInMenu: Boolean read FUseBuiltInMenu write FUseBuiltInMenu default True; end; { TcxPivotGridFieldHeaderMenu } TcxPivotGridFieldHeaderPopupMenuItem = (fpmiHide, fpmiOrder, fpmiFieldList); TcxPivotGridFieldHeaderPopupMenuItems = set of TcxPivotGridFieldHeaderPopupMenuItem; TcxPivotGridFieldHeaderMenu = class(TcxPivotGridCustomPopupMenu) private FField: TcxPivotGridField; FItems: TcxPivotGridFieldHeaderPopupMenuItems; function GetFieldHeaders: TcxPivotGridCells; function GetFieldViewInfo: TcxPivotGridFieldHeaderCellViewInfo; function GetOptionsDataField: TcxPivotGridOptionsDataField; function IsItemsStored: Boolean; protected procedure AssignValues(ASource: TcxPivotGridCustomPopupMenu); override; procedure CreateItems; override; procedure DoExecute(ACommand: Integer); override; procedure GetIndexes(var AStart, APrev, ANext, AFinish: Integer); property FieldHeaders: TcxPivotGridCells read GetFieldHeaders; property FieldViewInfo: TcxPivotGridFieldHeaderCellViewInfo read GetFieldViewInfo; public constructor Create(AOwner: TcxPivotGridPopupMenus); override; property Field: TcxPivotGridField read FField; property OptionsDataField: TcxPivotGridOptionsDataField read GetOptionsDataField; published property Items: TcxPivotGridFieldHeaderPopupMenuItems read FItems write FItems stored IsItemsStored; end; { TcxPivotGridGroupValueMenu } TcxPivotGridGroupValuePopupMenuItem = (vpmiExpandCollapse, vpmiExpandAll, vpmiCollapseAll); TcxPivotGridGroupValuePopupMenuItems = set of TcxPivotGridGroupValuePopupMenuItem; TcxPivotGridGroupValueMenu = class(TcxPivotGridCustomPopupMenu) private FGroupItem: TcxPivotGridGroupItem; FItems: TcxPivotGridGroupValuePopupMenuItems; function IsItemsStored: Boolean; protected procedure AssignValues(ASource: TcxPivotGridCustomPopupMenu); override; procedure CreateItems; override; procedure DoExecute(ACommand: Integer); override; public constructor Create(AOwner: TcxPivotGridPopupMenus); override; property GroupItem: TcxPivotGridGroupItem read FGroupItem; published property Items: TcxPivotGridGroupValuePopupMenuItems read FItems write FItems stored IsItemsStored; end; { TcxPivotGridHeaderAreaMenu } TcxPivotGridHeaderAreaMenu = class(TcxPivotGridCustomPopupMenu) protected procedure CreateItems; override; procedure DoExecute(ACommand: Integer); override; end; TcxPivotGridPopupMenuClickEvent = procedure(Sender: TcxCustomPivotGrid; AItem: TMenuItem; var AHandled: Boolean) of object; TcxPivotGridPopupMenuPopupEvent = procedure(Sender: TcxCustomPivotGrid; ABuiltInMenu: TcxPivotGridCustomPopupMenu; var AHandled: Boolean) of object; TcxPivotGridPopupMenus = class(TcxPivotGridCustomOptions) private FFieldHeaderMenu: TcxPivotGridFieldHeaderMenu; FGroupValueMenu: TcxPivotGridGroupValueMenu; FHeaderAreaMenu: TcxPivotGridHeaderAreaMenu; FOnClick: TcxPivotGridPopupMenuClickEvent; FOnPopup: TcxPivotGridPopupMenuPopupEvent; function GetHitTest: TcxPivotGridHitTest; procedure SetFieldHeaderMenu(AValue: TcxPivotGridFieldHeaderMenu); procedure SetGroupValueMenu(AValue: TcxPivotGridGroupValueMenu); procedure SetHeaderAreaMenu(AValue: TcxPivotGridHeaderAreaMenu); protected function CreateFieldHeaderMenu: TcxPivotGridFieldHeaderMenu; virtual; function CreateGroupValueMenu: TcxPivotGridGroupValueMenu; virtual; function CreateHeaderAreaMenu: TcxPivotGridHeaderAreaMenu; virtual; procedure CreateMenus; virtual; procedure DestroyMenus; virtual; procedure DoOnClick(AItem: TMenuItem; var AHandled: Boolean); virtual; procedure DoOnPopup(ASender: TcxPivotGridCustomPopupMenu; var AHandled: Boolean); virtual; function DoShowPopupMenu(const P: TPoint): Boolean; virtual; procedure MenuItemClickHandler(Sender: TObject); virtual; procedure Notification(AComponent: TComponent; Operation: TOperation); virtual; property HitTest: TcxPivotGridHitTest read GetHitTest; public constructor Create(AOwner: TcxCustomPivotGrid); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; published property FieldHeaderMenu: TcxPivotGridFieldHeaderMenu read FFieldHeaderMenu write SetFieldHeaderMenu; property GroupValueMenu: TcxPivotGridGroupValueMenu read FGroupValueMenu write SetGroupValueMenu; property HeaderAreaMenu: TcxPivotGridHeaderAreaMenu read FHeaderAreaMenu write SetHeaderAreaMenu; property OnClick: TcxPivotGridPopupMenuClickEvent read FOnClick write FOnClick; property OnPopup: TcxPivotGridPopupMenuPopupEvent read FOnPopup write FOnPopup; end; { IcxPivotGridDesignerIntf } IcxPivotGridDesignerIntf = interface ['{DA451370-2F02-43D0-9F31-C25D7632E004}'] function CanRetrieveFields(var AIsActive: Boolean): Boolean; function CreateField: TcxPivotGridField; procedure DoCreateAllFields; end; { TcxPivotGridExportController } TcxPivotGridExportController = class private FPivotGrid: TcxCustomPivotGrid; function GetExpandColumns: Boolean; function GetExpandRows: Boolean; function GetOptionsView: TcxPivotGridOptionsView; function GetStyles: TcxPivotGridStyles; function GetViewInfo: TcxPivotGridViewInfo; procedure SetExpandColumns(AValue: Boolean); procedure SetExpandRows(AValue: Boolean); protected FSavedBorders: Boolean; FSavedExpandButtons: Boolean; FSavedOptionsView: TcxPivotGridOptionsView; FSavedPrefilterOptions: TcxPivotGridOptionsPrefilter; FSavedStyles: TcxPivotGridStyles; procedure Finalize; virtual; procedure Initialize; virtual; public constructor Create(APivotGrid: TcxCustomPivotGrid); virtual; destructor Destroy; override; function CalculateViewInfo: TcxPivotGridViewInfo; procedure ReplaceStyles(AStyles: IcxPivotGridBaseStyles); property ExpandRows: Boolean read GetExpandRows write SetExpandRows; property ExpandColumns: Boolean read GetExpandColumns write SetExpandColumns; property OptionsView: TcxPivotGridOptionsView read GetOptionsView; property PivotGrid: TcxCustomPivotGrid read FPivotGrid; property Styles: TcxPivotGridStyles read GetStyles; property ViewInfo: TcxPivotGridViewInfo read GetViewInfo; end; { TcxPivotGridFilterMRUItem } TcxPivotGridFilterMRUItem = class(TcxMRUItem) private function GetCaption: string; protected function StreamEquals(AStream: TMemoryStream): Boolean; public Filter: TcxDataFilterCriteria; constructor Create(AFilter: TcxDataFilterCriteria); destructor Destroy; override; procedure AssignTo(AFilter: TcxDataFilterCriteria); function Equals(AItem: TcxMRUItem): Boolean; override; function FilterEquals(AFilter: TcxDataFilterCriteria): Boolean; function GetStream: TMemoryStream; property Caption: string read GetCaption; end; { TcxPivotGridFilterMRUItems } TcxPivotGridFilterMRUItems = class(TcxMRUItems) private FPivotGrid: TcxCustomPivotGrid; FVisibleItems: TList; function GetItem(Index: Integer): TcxPivotGridFilterMRUItem; function GetVisibleCount: Integer; function GetVisibleItem(Index: Integer): TcxPivotGridFilterMRUItem; procedure SetVisibleCount(AValue: Integer); protected procedure RefreshVisibleItemsList; public constructor Create(APivotGrid: TcxCustomPivotGrid); reintroduce; virtual; destructor Destroy; override; procedure Add(AFilter: TcxDataFilterCriteria); property PivotGrid: TcxCustomPivotGrid read FPivotGrid; property Items[Index: Integer]: TcxPivotGridFilterMRUItem read GetItem; default; property VisibleCount: Integer read GetVisibleCount write SetVisibleCount; property VisibleItems[Index: Integer]: TcxPivotGridFilterMRUItem read GetVisibleItem; end; { TcxCustomPivotGrid } TcxPivotGridCompareEvent = procedure(Sender: TcxCustomPivotGrid; AField: TcxPivotGridField; const AValue1, AValue2: Variant; var Compare: Integer) of object; TcxPivotGridCustomDrawFieldHeaderEvent = procedure(Sender: TcxCustomPivotGrid; ACanvas: TcxCanvas; AViewInfo: TcxPivotGridFieldHeaderCellViewInfo; var ADone: Boolean) of object; TcxPivotGridCustomDrawGroupHeaderEvent = procedure(Sender: TcxCustomPivotGrid; ACanvas: TcxCanvas; AViewInfo: TcxPivotGridHeaderCellViewInfo; var ADone: Boolean) of object; TcxPivotGridCustomDrawCellEvent = procedure(Sender: TcxCustomPivotGrid; ACanvas: TcxCanvas; AViewInfo: TcxPivotGridDataCellViewInfo; var ADone: Boolean) of object; TcxPivotGridCustomDrawPartEvent = procedure(Sender: TcxCustomPivotGrid; ACanvas: TcxCanvas; AViewInfo: TcxPivotGridCustomCellViewInfo; var ADone: Boolean) of object; TcxPivotGridFieldChangedEvent = procedure(Sender: TcxCustomPivotGrid; AField: TcxPivotGridField) of object; TcxCustomPivotGrid = class(TcxControl, IUnknown, IcxStoredParent, IcxFilterControl, IcxNavigator, IcxStoredObject, IcxPivotGridDesignerIntf, IdxSkinSupport) private FChanges: TcxPivotGridChanges; FController: TcxPivotGridController; FCustomization: TcxPivotGridCustomization; FCustomSortAssigned: Boolean; FDataBuilder: TcxPivotGridDataBuilder; FDataController: TcxCustomDataController; FFieldHeaderImages: TCustomImageList; FFields: TcxObjectList; FFilterableFields: TcxPivotGridFields; FGroupHeaderImages: TCustomImageList; FGroups: TcxPivotGridFieldGroupCollection; FHasSummaryVariation: Boolean; FHitTest: TcxPivotGridHitTest; FHourglassCursorRefCount: Integer; FImagesListener: TChangeLink; FIsRestoring: Boolean; FListeners: TInterfaceList; FLockCount: Integer; FNavigatorNotifier: TcxNavigatorControlNotifier; FOLAPDataSource: TcxPivotGridCustomOLAPDataSource; FOptionsBehavior: TcxPivotGridOptionsBehavior; FOptionsCustomize: TcxPivotGridOptionsCustomize; FOptionsData: TcxPivotGridOptionsData; FOptionsDataField: TcxPivotGridOptionsDataField; FOptionsPrefilter: TcxPivotGridOptionsPrefilter; FOptionsSelection: TcxPivotGridOptionsSelection; FOptionsView: TcxPivotGridOptionsView; FPainter: TcxPivotGridPainter; FPopupMenus: TcxPivotGridPopupMenus; FPrefilterMRUItems: TcxPivotGridFilterMRUItems; FSummaryFields: TcxPivotGridFields; FStyles: TcxPivotGridStyles; FViewData: TcxPivotGridViewData; FViewInfo: TcxPivotGridViewInfo; // FPopupMenusEvents: TNotifyEvent; FStylesEvents: TNotifyEvent; // FOnCompare: TcxPivotGridCompareEvent; FOnCustomDrawFieldHeader: TcxPivotGridCustomDrawFieldHeaderEvent; FOnCustomDrawColumnHeader: TcxPivotGridCustomDrawGroupHeaderEvent; FOnCustomDrawRowHeader: TcxPivotGridCustomDrawGroupHeaderEvent; FOnCustomDrawCell: TcxPivotGridCustomDrawCellEvent; FOnCustomDrawPart: TcxPivotGridCustomDrawPartEvent; FOnCustomization: TNotifyEvent; FOnFieldPosChanged: TcxPivotGridFieldChangedEvent; FOnFieldSizeChanged: TcxPivotGridFieldChangedEvent; FOnFilterChanged: TNotifyEvent; FOnLayoutChanged: TNotifyEvent; FOnSelectionChanged: TNotifyEvent; // IcxStoredObject events FOnGetStoredProperties: TcxGetStoredPropertiesEvent; FOnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent; FOnInitStoredObject: TcxInitStoredObjectEvent; FOnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent; function GetFieldCount: Integer; function GetField(AIndex: Integer): TcxPivotGridField; function GetIsLocked: Boolean; function GetRecordCount: Integer; procedure SetField(AIndex: Integer; AValue: TcxPivotGridField); procedure SetFieldHeaderImages(AValue: TCustomImageList); procedure SetGroupHeaderImages(AValue: TCustomImageList); procedure SetGroups(AValue: TcxPivotGridFieldGroupCollection); procedure SetImages(var AField: TCustomImageList; ANewValue: TCustomImageList); procedure SetOLAPDataSource(AValue: TcxPivotGridCustomOLAPDataSource); procedure SetOptionsBehavior(AValue: TcxPivotGridOptionsBehavior); procedure SetOptionsCustomize(AValue: TcxPivotGridOptionsCustomize); procedure SetOptionsData(AValue: TcxPivotGridOptionsData); procedure SetOptionsDataField(AValue: TcxPivotGridOptionsDataField); procedure SetOptionsPrefilter(AValue: TcxPivotGridOptionsPrefilter); procedure SetOptionsSelection(AValue: TcxPivotGridOptionsSelection); procedure SetOptionsView(AValue: TcxPivotGridOptionsView); procedure SetPopupMenus(AValue: TcxPivotGridPopupMenus); procedure SetStyles(AValue: TcxPivotGridStyles); procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE; procedure WMRefreshCustomization(var Message: TMessage); message WM_REFRESHCUSTOMIZATION; procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR; // IcxStoredObject redirect function IcxStoredObject.GetObjectName = StoredObject_GetObjectName; function IcxStoredObject.GetProperties = StoredObject_GetProperties; procedure IcxStoredObject.GetPropertyValue = StoredObject_GetPropertyValue; procedure IcxStoredObject.SetPropertyValue = StoredObject_SetPropertyValue; // IcxStoredParent redirect function IcxStoredParent.CreateChild = StoredParent_CreateChild; procedure IcxStoredParent.DeleteChild = StoredParent_DeleteChild; procedure IcxStoredParent.GetChildren = StoredParent_GetChildren; procedure RestoreFrom(AStorageType: TcxStorageType; const AStorageName: string; AStorageStream: TStream; ACreateChildren, ADeleteChildren: Boolean); procedure StoreTo(AStorageType: TcxStorageType; const AStorageName: string; AStorageStream: TStream; AReCreate: Boolean = True); protected NeedUpdateScrollBarsPost: Boolean; RefreshDate: TDateTime; procedure AddField(AField: TcxPivotGridField); procedure RemoveField(AField: TcxPivotGridField); // procedure BeforeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure BoundsChanged; override; procedure CheckChanges; procedure CheckUpdateScrollBars; procedure ClearCacheInformation; virtual; procedure CreateSubClasses; virtual; procedure DestroyEditViewDatas; procedure DestroySubClasses; virtual; procedure DataChanged; virtual; procedure DataSourceChanged; virtual; function DoShowPopupMenu(AMenu: TComponent; X, Y: Integer): Boolean; override; procedure FilterControlDialogApply(Sender: TObject); procedure HideHourglassCursor; procedure ImagesChangeHandler(Sender: TObject); function IsDestroying: Boolean; function IsLoading: Boolean; function IsOLAPActive: Boolean; function IsPrefilterEnabled: Boolean; function IsRestoring: Boolean; procedure InitScrollBarsParameters; override; procedure RefreshFilterableFieldsList; procedure ShowHourglassCursor; procedure SynchronizeUniqueName(AField: TcxPivotGridField); procedure UpdateMRUItems; function GetCursor(X, Y: Integer): TCursor; override; {$IFNDEF DELPHI12} procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; {$ENDIF} function GetDesignHitTest(X, Y: Integer; Shift: TShiftState): Boolean; override; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; override; function GetFieldClass: TcxPivotGridFieldClass; virtual; procedure Loaded; override; function CreateController: TcxPivotGridController; virtual; function CreateCustomization: TcxPivotGridCustomization; virtual; function CreateDataBuilder: TcxPivotGridDataBuilder; virtual; function CreateDataController: TcxCustomDataController; virtual; function CreateGroups: TcxPivotGridFieldGroupCollection; virtual; function CreateHitTest: TcxPivotGridHitTest; virtual; function CreateOptionsBehavior: TcxPivotGridOptionsBehavior; virtual; function CreateOptionsCustomize: TcxPivotGridOptionsCustomize; virtual; function CreateOptionsData: TcxPivotGridOptionsData; virtual; function CreateOptionsDataField: TcxPivotGridOptionsDataField; virtual; function CreateOptionsPrefilter: TcxPivotGridOptionsPrefilter; virtual; function CreateOptionsSelection: TcxPivotGridOptionsSelection; virtual; function CreateOptionsView: TcxPivotGridOptionsView; virtual; function CreatePainter: TcxPivotGridPainter; virtual; function CreatePopupMenus: TcxPivotGridPopupMenus; virtual; function CreateStyles: TcxPivotGridStyles; virtual; function CreateViewData: TcxPivotGridViewData; virtual; function CreateViewInfo: TcxPivotGridViewInfo; virtual; procedure DblClick; override; procedure DoCompare(AField: TcxPivotGridField; const AValue1, AValue2: Variant; var Compare: Integer); virtual; procedure DoCustomDrawFieldHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridFieldHeaderCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawColumnHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridHeaderCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawPart(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawRowHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridHeaderCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawCell(ACanvas: TcxCanvas; ACell: TcxPivotGridDataCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomization; virtual; procedure DoFieldPosChanged(AField: TcxPivotGridField); virtual; procedure DoFieldSizeChanged(AField: TcxPivotGridField); virtual; procedure DoFilterChanged; procedure DoLayoutChanged; virtual; procedure DoPrefilterChanged; procedure DoSelectionChanged; virtual; procedure FocusChanged; override; procedure FontChanged; override; function GetIsFocused: Boolean; override; function IsDesignerAvailable: Boolean; procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure KeyPress(var Key: Char); override; procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseLeave(AControl: TControl); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure Paint; override; procedure RecreatePainter; procedure RecreateViewInfo; procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); override; procedure SelectionChanged; procedure SendNotification(AChanges: TcxPivotGridChanges); virtual; function SetFieldAreaIndex(AField: TPersistent; AArea: TcxPivotGridFieldArea; var AIndex: Integer): Boolean; function StartDragAndDrop(const P: TPoint): Boolean; override; procedure ViewChanged; // data controller notifications function GetItem(Index: Integer): TObject; function GetItemID(AItem: TObject): Integer; function GetItemValueSource(AItemIndex: Integer): TcxDataEditValueSource; virtual; procedure UpdateControl(AInfo: TcxUpdateControlInfo); virtual; procedure UpdateData; virtual; procedure UpdateItemIndexes; virtual; // IcxPivotGridDesigner function CanRetrieveFields(var AIsActive: Boolean): Boolean; virtual; procedure DoCreateAllFields; virtual; // IcxFilterControl function GetCaption(Index: Integer): string; virtual; function GetCount: Integer; function GetCriteria: TcxFilterCriteria; function GetItemLink(Index: Integer): TObject; function GetItemLinkID(Index: Integer): Integer; function GetItemLinkName(Index: Integer): string; function GetFieldName(Index: Integer): string; function GetProperties(Index: Integer): TcxCustomEditProperties; overload; function GetValueType(Index: Integer): TcxValueTypeClass; // IcxNavigator function CanAppend: Boolean; function CanDelete: Boolean; function CanEdit: Boolean; function CanInsert: Boolean; function IsActive: Boolean; function IsBof: Boolean; function IsBookmarkAvailable: Boolean; function IsEditing: Boolean; function IsEof: Boolean; procedure ClearBookmark; procedure DoAction(AButtonIndex: Integer); function GetNotifier: TcxNavigatorControlNotifier; function IsActionSupported(AButtonIndex: Integer): Boolean; // IcxStoredObject function StoredObject_GetObjectName: string; function StoredObject_GetProperties(AProperties: TStrings): Boolean; overload; virtual; procedure StoredObject_GetPropertyValue(const AName: string; var AValue: Variant); virtual; procedure StoredObject_SetPropertyValue(const AName: string; const AValue: Variant); virtual; // IcxStoredParent function StoredParent_CreateChild(const AObjectName, AClassName: string): TObject; virtual; procedure StoredParent_DeleteChild(const AObjectName: string; AObject: TObject); virtual; procedure StoredParent_GetChildren(AChildren: TStringList); virtual; property OLAPDataSource: TcxPivotGridCustomOLAPDataSource read FOLAPDataSource write SetOLAPDataSource; property BorderStyle default cxcbsDefault; property Changes: TcxPivotGridChanges read FChanges write FChanges; property Controller: TcxPivotGridController read FController; property CustomSortAssigned: Boolean read FCustomSortAssigned; property DataBuilder: TcxPivotGridDataBuilder read FDataBuilder; property FieldList: TcxObjectList read FFields; property HasSummaryVariation: Boolean read FHasSummaryVariation write FHasSummaryVariation; property ImagesListener: TChangeLink read FImagesListener; property IsLocked: Boolean read GetIsLocked; property LockCount: Integer read FLockCount write FLockCount; property Painter: TcxPivotGridPainter read FPainter; property PrefilterMRUItems: TcxPivotGridFilterMRUItems read FPrefilterMRUItems; property RecordCount: Integer read GetRecordCount; property ViewInfo: TcxPivotGridViewInfo read FViewInfo; property OnCompare: TcxPivotGridCompareEvent read FOnCompare write FOnCompare; property OnCustomDrawFieldHeader: TcxPivotGridCustomDrawFieldHeaderEvent read FOnCustomDrawFieldHeader write FOnCustomDrawFieldHeader; property OnCustomDrawColumnHeader: TcxPivotGridCustomDrawGroupHeaderEvent read FOnCustomDrawColumnHeader write FOnCustomDrawColumnHeader; property OnCustomDrawRowHeader: TcxPivotGridCustomDrawGroupHeaderEvent read FOnCustomDrawRowHeader write FOnCustomDrawRowHeader; property OnCustomDrawCell: TcxPivotGridCustomDrawCellEvent read FOnCustomDrawCell write FOnCustomDrawCell; property OnCustomDrawPart: TcxPivotGridCustomDrawPartEvent read FOnCustomDrawPart write FOnCustomDrawPart; property OnCustomization: TNotifyEvent read FOnCustomization write FOnCustomization; property OnFieldPosChanged: TcxPivotGridFieldChangedEvent read FOnFieldPosChanged write FOnFieldPosChanged; property OnFieldSizeChanged: TcxPivotGridFieldChangedEvent read FOnFieldSizeChanged write FOnFieldSizeChanged; property OnFilterChanged: TNotifyEvent read FOnFilterChanged write FOnFilterChanged; property OnLayoutChanged: TNotifyEvent read FOnLayoutChanged write FOnLayoutChanged; property OnSelectionChanged: TNotifyEvent read FOnSelectionChanged write FOnSelectionChanged; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure AddListener(AListener: IcxPivotGridListener); procedure ApplyBestFit; procedure BeginUpdate; procedure CopyToClipboard(ACopyAll: Boolean = False); virtual; function CreateDrillDownDataSource: TcxCustomDataSource; virtual; function CreateField: TcxPivotGridField; virtual; procedure DeleteAllFields; procedure EndUpdate; {$IFDEF DELPHI12} procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; {$ENDIF} procedure ShowPrefilterDialog; procedure FullRefresh; function GetFieldByName(const AName: string): TcxPivotGridField; procedure LayoutChanged; procedure RemoveListener(AListener: IcxPivotGridListener); // Store/Restore procedure RestoreFromIniFile(const AStorageName: string; ACreateChildren: Boolean = False; ADeleteChildren: Boolean = False); procedure RestoreFromRegistry(const AStorageName: string; ACreateChildren: Boolean = False; ADeleteChildren: Boolean = False); procedure RestoreFromStream(AStream: TStream; ACreateChildren: Boolean = False; ADeleteChildren: Boolean = False); procedure StoreToIniFile(const AStorageName: string; AReCreate: Boolean = True); procedure StoreToRegistry(const AStorageName: string; AReCreate: Boolean = True); procedure StoreToStream(AStream: TStream); //IdxLocalizerListener procedure TranslationChanged; override; property Customization: TcxPivotGridCustomization read FCustomization; property DataController: TcxCustomDataController read FDataController; property FieldCount: Integer read GetFieldCount; property FieldHeaderImages: TCustomImageList read FFieldHeaderImages write SetFieldHeaderImages; property Fields[Index: Integer]: TcxPivotGridField read GetField write SetField; property Font; property GroupHeaderImages: TCustomImageList read FGroupHeaderImages write SetGroupHeaderImages; property Groups: TcxPivotGridFieldGroupCollection read FGroups write SetGroups; property HitTest: TcxPivotGridHitTest read FHitTest; property LookAndFeel; property LookAndFeelPainter; property OptionsBehavior: TcxPivotGridOptionsBehavior read FOptionsBehavior write SetOptionsBehavior; property OptionsCustomize: TcxPivotGridOptionsCustomize read FOptionsCustomize write SetOptionsCustomize; property OptionsData: TcxPivotGridOptionsData read FOptionsData write SetOptionsData; property OptionsDataField: TcxPivotGridOptionsDataField read FOptionsDataField write SetOptionsDataField; property OptionsPrefilter: TcxPivotGridOptionsPrefilter read FOptionsPrefilter write SetOptionsPrefilter; property OptionsSelection: TcxPivotGridOptionsSelection read FOptionsSelection write SetOptionsSelection; property OptionsView: TcxPivotGridOptionsView read FOptionsView write SetOptionsView; property PopupMenus: TcxPivotGridPopupMenus read FPopupMenus write SetPopupMenus; property Styles: TcxPivotGridStyles read FStyles write SetStyles; property SummaryFields: TcxPivotGridFields read FSummaryFields; property ViewData: TcxPivotGridViewData read FViewData; published property PopupMenusEvents: TNotifyEvent read FPopupMenusEvents write FPopupMenusEvents; property StylesEvents: TNotifyEvent read FStylesEvents write FStylesEvents; // IcxStoredObject events property OnGetStoredProperties: TcxGetStoredPropertiesEvent read FOnGetStoredProperties write FOnGetStoredProperties; property OnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent read FOnGetStoredPropertyValue write FOnGetStoredPropertyValue; property OnInitStoredObject: TcxInitStoredObjectEvent read FOnInitStoredObject write FOnInitStoredObject; property OnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent read FOnSetStoredPropertyValue write FOnSetStoredPropertyValue; end; { IcxPivotGridDesignerHelper } IcxPivotGridDesignerHelper = interface ['{88DE8BF4-DCA9-4E8A-B5FA-B860CD01299C}'] procedure AddListener(APivotGrid: TcxCustomPivotGrid); procedure RemoveListener(APivotGrid: TcxCustomPivotGrid); procedure Select(AObject: TPersistent; AShift: TShiftState); function IsObjectSelected(AObject: TPersistent): Boolean; end; TcxPivotGridCustomDesignHelper = class(TObject) protected procedure RefreshListener(APivotGrid: TcxCustomPivotGrid); end; const DesignerHelper: IcxPivotGridDesignerHelper = nil; cxPivotGridCustomizationFormClass: TcxPivotGridCustomizationFormClass = TcxPivotGridCustomCustomizationForm; PivotGridCrossCellSummaryClass: TcxPivotGridCrossCellSummaryClass = TcxPivotGridCrossCellSummary; cxPivotGridPopupMenuImages: TCustomImageList = nil; procedure PivotGridError(ACondition: Boolean; const AMessage: string); function cxPivotGridHierarchyImages: TImageList; function IsNotLastVisibleOLAPHierarchyItem(AnItem: TcxPivotGridGroupItem): Boolean; implementation {$R *.res} uses cxTextEdit, cxPivotGridCustomization, cxPivotGridStrs, cxLibraryConsts, cxEditDataRegisteredRepositoryItems; const cxInvisiblePos = 30000; OrdinalTypeSet: set of Byte = [varSmallInt, varInteger, varBoolean, varByte {$IFDEF DELPHI6}, varWord, varShortInt, varLongWord, varInt64 {$ENDIF}]; E_NOINTERFACE = HResult($80004002); CustomizationCommand: array[Boolean] of Integer = (pgcmShowCustomization, pgcmHideCustomization); DataAreaToFieldArea: array[TcxPivotGridDataFieldArea] of TcxPivotGridFieldArea = (faFilter, faColumn, faRow); DimensionAllowedAreas: array[Boolean] of TcxPivotGridFieldAreas = ([faColumn, faRow, faFilter], [faData]); PivotGridDefaultStoredProperties: array[0..1] of string = ('Prefilter', 'PrefilterActive'); FieldDefaultStoredProperties: array[0..6] of string = ('SortOrder', 'GroupExpanded', 'Visible', 'Width', 'Area', 'AreaIndex', 'Filter'); FHierarchyImages: TImageList = nil; // prefilter PrefilterButtonsFirstOffset = 4; PrefilterButtonsOffset = 4; PrefilterTextOffset = 3; function IsNotLastVisibleOLAPHierarchyItem(AnItem: TcxPivotGridGroupItem): boolean; function IsOLAPHierarchy: Boolean; begin Result := AnItem.Field.IsHierarchy and (AnItem.Field.Link.GroupIndex >= 0); end; begin Result := (AnItem <> nil) and (AnItem.Field <> nil) and IsOLAPHierarchy and (AnItem.Field.Group.IndexOf(AnItem.Field) < AnItem.Field.Group.VisibleCount - 1); end; function GetPropertyIndex(const AName: string; ANamesMap: array of string): Integer; var I: Integer; begin for I := Low(ANamesMap) to High(ANamesMap) do if SameText(ANamesMap[I], AName) then begin Result := I; Exit; end; Result := -1; end; type TcxEditStyleAccess = class(TcxEditStyle); TcxPivotGridFieldPosition = class protected FAreaIndex: Integer; FField: TPersistent; FIndex: Integer; FVisible: Boolean; FGroup: TcxPivotGridFieldGroup; public constructor Create(AField: TPersistent); procedure SetAreaIndex(var AAreaIndex: Integer); function IsSameGroup(AField: TcxPivotGridField): Boolean; property AreaIndex: Integer read FAreaIndex; property Field: TPersistent read FField; property Group: TcxPivotGridFieldGroup read FGroup; property Index: Integer read FIndex; property Visible: Boolean read FVisible; end; { TcxPivotGridFieldPosition } constructor TcxPivotGridFieldPosition.Create(AField: TPersistent); begin FField := AField; FIndex := MaxInt; FVisible := True; if AField is TcxPivotGridField then begin FAreaIndex := (AField as TcxPivotGridField).AreaIndex; FIndex := (AField as TcxPivotGridField).Index; FVisible := (AField as TcxPivotGridField).Visible; FGroup := (AField as TcxPivotGridField).Group; end else begin FAreaIndex := (AField as TcxPivotGridOptionsDataField).AreaIndex; if FAreaIndex = -1 then FAreaIndex := MaxInt; end; end; procedure TcxPivotGridFieldPosition.SetAreaIndex(var AAreaIndex: Integer); begin if Field is TcxPivotGridField then begin (Field as TcxPivotGridField).FAreaIndex := AAreaIndex; if FGroup <> nil then FGroup.ResetIndexes(AAreaIndex); end else (Field as TcxPivotGridOptionsDataField).FAreaIndex := AAreaIndex; end; function TcxPivotGridFieldPosition.IsSameGroup(AField: TcxPivotGridField): Boolean; begin Result := (AField = FField) or ((AField.Group <> nil) and (AField.Group = FGroup)); end; procedure PivotGridError(ACondition: Boolean; const AMessage: string); begin if not ACondition then raise EcxPivotGrid.Create(AMessage); end; function CompareFieldsOrder(AField1, AField2: TcxPivotGridField): Integer; begin Result := Byte(AField1.Area) - Byte(AField2.Area); if Result = 0 then Result := AField1.AreaIndex - AField2.AreaIndex; if (AField1.AreaIndex = -1) and (AField2.AreaIndex >= 0) then Result := 1; if Result = 0 then Result := AField1.Index - AField2.Index; end; function CompareFieldsOnLoading(AField1, AField2: TcxPivotGridField): Integer; begin Result := AField1.AreaIndex - AField2.AreaIndex; end; function CompareFieldsPosition(AInfo1, AInfo2: TcxPivotGridFieldPosition): Integer; begin Result := AInfo1.AreaIndex - AInfo2.AreaIndex; if (AInfo1.Index = -1) and (AInfo2.Index >= 0) then Result := 1; if Result = 0 then Result := AInfo1.Index - AInfo2.Index; end; function CompareGroupItemsBySummary(AItem1, AItem2: TcxPivotGridGroupItem): Integer; begin if (AItem1 <> AItem2) and (AItem1.RecordIndex = cxPivotGridOthersRecordIndex) then begin // "Others" must be always at down Result := 1; Exit; end; Result := VarCompare(AItem1.SummaryValue, AItem2.SummaryValue); if AItem1.Field.SortOrder = soDescending then Result := -Result; end; function CompareFilterValues(AItem1, AItem2: TcxPivotGridVariantValue): Integer; begin Result := VarCompare(AItem1.Value, AItem2.Value); end; function CompareRecordIndexes(ARecNo1, ARecNo2: Integer): Integer; begin Result := ARecNo1 - ARecNo2; end; function FindItem(AList: TList; const AValue: Variant; var AIndex: Integer; ASortOrder: TcxDataSortOrder): Boolean; var L, H, I, C: Integer; begin Result := False; L := 0; H := AList.Count - 1; while L <= H do begin I := (L + H) shr 1; C := TcxPivotGridGroupItem(AList.List^[I]).Compare(AValue); if ASortOrder = soDescending then C := -C; if C < 0 then L := I + 1 else begin H := I - 1; if C = 0 then begin Result := True; L := I; end; end; end; AIndex := L; end; function GetItemNeighbors(AIsTop, AIsLeft, AIsBottom, AIsRight: Boolean): TcxNeighbors; begin Result := []; if not AIsTop then Include(Result, nTop); if not AIsBottom then Include(Result, nBottom); if not AIsLeft then Include(Result, nLeft); if not AIsRight then Include(Result, nRight); end; procedure SwapImages(var AImage1, AImage2: TBitmap); var ATemp: TBitmap; begin ATemp := AImage1; AImage1 := AImage2; AImage2 := ATemp; end; function VarTypeIsCurrency(VType: Integer): Boolean; begin Result := (VType = varCurrency) {$IFDEF DELPHI6} or (VType = varFMTBCD){$ENDIF} end; function FormatDisplayValue(const AValue: Variant; const ADisplayFormat: string; AIsPercent: Boolean): string; var AFormatStr: string; begin AFormatStr := ADisplayFormat; if AFormatStr = '' then begin if AIsPercent then AFormatStr := cxPivotGridDefaultFieldPercentFormat else if VarTypeIsCurrency(VarType(AValue)) then AFormatStr := cxFormatController.CurrencyFormat else if VarIsFloat(AValue) then AFormatStr := cxPivotGridDefaultFieldFloatFormat else if VarIsOrdinal(AValue) then AFormatStr := cxPivotGridDefaultFieldIntFormat; end; if VarIsNumericEx(AValue) then Result := FormatFloat(AFormatStr, AValue) else Result := VarToStr(AValue); end; { TcxCustomPivotGrid } constructor TcxCustomPivotGrid.Create(AOwner: TComponent); begin inherited Create(AOwner); BeginUpdate; SetBounds(0, 0, 300, 250); Keys := [kArrows, kChars]; BorderStyle := cxcbsDefault; Changes := [gcData]; CreateSubClasses; if DesignerHelper <> nil then DesignerHelper.AddListener(Self); FNavigatorNotifier := TcxNavigatorControlNotifier.Create; EndUpdate; end; destructor TcxCustomPivotGrid.Destroy; begin Inc(FLockCount); FreeAndNil(FNavigatorNotifier); if DesignerHelper <> nil then DesignerHelper.RemoveListener(Self); Customization.Visible := False; DestroySubClasses; inherited Destroy; end; procedure TcxCustomPivotGrid.AddListener(AListener: IcxPivotGridListener); begin if FListeners.IndexOf(AListener) = -1 then FListeners.Add(AListener); end; procedure TcxCustomPivotGrid.ApplyBestFit; var I: Integer; begin CheckChanges; BeginUpdate; try for I := 0 to FieldCount - 1 do Fields[I].ApplyBestFit; finally EndUpdate; end; end; procedure TcxCustomPivotGrid.BeginUpdate; begin Inc(FLockCount); if DataController <> nil then DataController.BeginUpdate; end; procedure TcxCustomPivotGrid.CopyToClipboard(ACopyAll: Boolean = False); var ACopyRect: TRect; ARow, AColumn: Integer; ACopyToClipboardStr, ARowStr: string; const CRLF: string = #13#10; SEPARATOR: string = #9; begin ACopyToClipboardStr := ''; if ACopyAll then ACopyRect := Rect(0, 0, MaxInt, MaxInt) else ACopyRect := ViewData.Selection.GetCombinedSelectionBounds; with ACopyRect do begin BottomRight := Point(Min(Right, ViewData.ColumnCount - 1), Min(Bottom, ViewData.RowCount - 1)); end; ShowHourglassCursor; try for ARow := ACopyRect.Top to ACopyRect.Bottom do begin ARowStr := ''; for AColumn := ACopyRect.Left to ACopyRect.Right do begin if ACopyAll or ViewData.IsCellSelected(ARow, AColumn) then ARowStr := ARowStr + ViewData.CellsAsText[ARow, AColumn]; if AColumn <> ACopyRect.Right then // if not right most column need add column separator ARowStr := ARowStr + SEPARATOR; end; ViewData.Rows[ARow].GroupItem.DeleteChildren; // if not last row need add row separator if ARow <> ACopyRect.Bottom then ARowStr := ARowStr + CRLF; ACopyToClipboardStr := ACopyToClipboardStr + ARowStr; end; Clipboard.AsText := ACopyToClipboardStr; finally HideHourglassCursor; end; end; function TcxCustomPivotGrid.CreateDrillDownDataSource: TcxCustomDataSource; var ACells: TList; begin ACells := TList.Create; try ViewData.PopulateSelectedCells(ACells); if IsOLAPActive then Result := OLAPDataSource.CreateDrillDownDataSource(ACells, FieldList) else Result := TcxPivotGridCrossCellDataSource.CreateEx(ACells) finally ACells.Free; end; TcxPivotGridCrossCellDataSource(Result).PivotGrid := Self; end; function TcxCustomPivotGrid.CreateField: TcxPivotGridField; begin Result := GetFieldClass.Create(Owner); Result.PivotGrid := Self; end; procedure TcxCustomPivotGrid.DeleteAllFields; var I: Integer; begin BeginUpdate; try for I := 0 to FieldList.Count - 1 do TObject(FieldList.Last).Free; Groups.Clear; finally EndUpdate; end; end; procedure TcxCustomPivotGrid.EndUpdate; begin Dec(FLockCount); if DataController.LockCount > 0 then begin ViewInfo.Clear; Include(FChanges, gcLayout); DataController.EndUpdate; end; CheckChanges; end; procedure TcxCustomPivotGrid.ShowPrefilterDialog; begin if IsPrefilterEnabled then ExecuteFilterControlDialog(Self, LookAndFeel, FilterControlDialogApply); end; procedure TcxCustomPivotGrid.FullRefresh; begin DataChanged; end; function TcxCustomPivotGrid.GetFieldByName( const AName: string): TcxPivotGridField; var I: Integer; begin Result := nil; for I := 0 to FieldCount - 1 do if AnsiCompareText(Fields[I].Caption, AName) = 0 then begin Result := Fields[I]; Break; end; end; procedure TcxCustomPivotGrid.LayoutChanged; begin Changes := Changes + [gcLayout]; if IsLocked then Exit; CheckChanges; Invalidate; end; procedure TcxCustomPivotGrid.RemoveListener(AListener: IcxPivotGridListener); begin FListeners.Remove(AListener); end; procedure TcxCustomPivotGrid.RestoreFromIniFile(const AStorageName: string; ACreateChildren, ADeleteChildren: Boolean); begin RestoreFrom(stIniFile, AStorageName, nil, ACreateChildren, ADeleteChildren); end; procedure TcxCustomPivotGrid.RestoreFromRegistry(const AStorageName: string; ACreateChildren, ADeleteChildren: Boolean); begin RestoreFrom(stRegistry, AStorageName, nil, ACreateChildren, ADeleteChildren); end; procedure TcxCustomPivotGrid.RestoreFromStream(AStream: TStream; ACreateChildren, ADeleteChildren: Boolean); begin RestoreFrom(stStream, '', AStream, ACreateChildren, ADeleteChildren); end; procedure TcxCustomPivotGrid.StoreToIniFile( const AStorageName: string; AReCreate: Boolean = True); begin StoreTo(stIniFile, AStorageName, nil, AReCreate); end; procedure TcxCustomPivotGrid.StoreToRegistry( const AStorageName: string; AReCreate: Boolean = True); begin StoreTo(stRegistry, AStorageName, nil, AReCreate); end; procedure TcxCustomPivotGrid.StoreToStream(AStream: TStream); begin StoreTo(stStream, '', AStream); end; procedure TcxCustomPivotGrid.TranslationChanged; begin DataChanged; end; procedure TcxCustomPivotGrid.AddField(AField: TcxPivotGridField); begin if IsDestroying then Exit; FieldList.Add(AField); DataBuilder.DataController.AddItem(AField); DataChanged; Customization.Refresh; RefreshFilterableFieldsList; end; procedure TcxCustomPivotGrid.RemoveField(AField: TcxPivotGridField); begin if IsDestroying then Exit; DataController.BeginUpdate; try DataController.RemoveItem(AField); FFields.Remove(AField); finally DataController.EndUpdate; end; DataChanged; Customization.Refresh; RefreshFilterableFieldsList; end; procedure TcxCustomPivotGrid.BeforeMouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Controller.BeforeMouseDown(Button, Shift, X, Y); inherited BeforeMouseDown(Button, Shift, X, Y); end; procedure TcxCustomPivotGrid.BoundsChanged; begin ViewChanged; inherited BoundsChanged; end; function TcxCustomPivotGrid.CanRetrieveFields(var AIsActive: Boolean): Boolean; begin Result := FOLAPDataSource <> nil; AIsActive := IsOLAPActive; end; procedure TcxCustomPivotGrid.CheckChanges; var AChanges: TcxPivotGridChanges; begin if IsLocked or (Changes = []) then Exit; try FCustomSortAssigned := Assigned(FOnCompare); Controller.Clear; AChanges := Changes; Changes := []; if gcData in AChanges then begin DataBuilder.DataChanged; AChanges := AChanges + Changes + [gcLayout]; Changes := []; end; if gcLayout in AChanges then begin DestroyEditViewDatas; ViewData.Calculate; AChanges := AChanges + Changes + [gcView]; if ViewData.Selection.IsSelected then begin ViewData.Selection.ValidateSelections; AChanges := AChanges + Changes + [gcSelection]; end; Changes := []; end; if gcView in AChanges then begin ViewInfo.Calculate; Invalidate; end; Controller.Update; UpdateMRUItems; if AChanges <> [] then SendNotification(AChanges); if gcLayout in AChanges then DoLayoutChanged; if gcSelection in AChanges then DoSelectionChanged; finally Changes := []; end; end; procedure TcxCustomPivotGrid.CheckUpdateScrollBars; begin NeedUpdateScrollBarsPost := False; UpdateScrollBars; end; procedure TcxCustomPivotGrid.ClearCacheInformation; var I: Integer; begin if IsDestroying then Exit; for I := 0 to FieldCount - 1 do Fields[I].GroupValuesValid := False; end; procedure TcxCustomPivotGrid.CreateSubClasses; begin FListeners := TInterfaceList.Create; FImagesListener := TChangeLink.Create; FImagesListener.OnChange := ImagesChangeHandler; FGroups := CreateGroups; FOptionsView := CreateOptionsView; FController := CreateController; FCustomization := CreateCustomization; FFields := TcxObjectList.Create; FFilterableFields := TcxPivotGridFields.Create; FDataController := CreateDataController; FDataBuilder := CreateDataBuilder; FViewInfo := CreateViewInfo; FViewData := CreateViewData; FPainter := CreatePainter; FOptionsCustomize := CreateOptionsCustomize; FOptionsBehavior := CreateOptionsBehavior; FOptionsData := CreateOptionsData; FOptionsDataField := CreateOptionsDataField; FOptionsPrefilter := CreateOptionsPrefilter; FOptionsSelection := CreateOptionsSelection; FPopupMenus := CreatePopupMenus; FStyles := CreateStyles; FSummaryFields := TcxPivotGridFields.Create; FHitTest := CreateHitTest; FPrefilterMRUItems := TcxPivotGridFilterMRUItems.Create(Self); UpdateMRUItems; end; procedure TcxCustomPivotGrid.DestroyEditViewDatas; var I: Integer; begin for I := 0 to FieldCount - 1 do Fields[I].DestroyEditViewData; end; procedure TcxCustomPivotGrid.DestroySubClasses; begin FreeAndNil(FPrefilterMRUItems); OLAPDataSource := nil; SendNotification([]); FieldHeaderImages := nil; GroupHeaderImages := nil; FViewInfo.FBaseStyles := nil; FreeAndNil(FFilterableFields); FreeAndNil(FHitTest); FreeAndNil(FFields); FreeAndNil(FStyles); FreeAndNil(FDataController); FreeAndNil(FDataBuilder); FreeAndNil(FPainter); FreeAndNil(FSummaryFields); FreeAndNil(FViewData); FreeAndNil(FViewInfo); FreeAndNil(FOptionsCustomize); FreeAndNil(FOptionsBehavior); FreeAndNil(FOptionsData); FreeAndNil(FOptionsDataField); FreeAndNil(FOptionsPrefilter); FreeAndNil(FOptionsSelection); FreeAndNil(FOptionsView); FreeAndNil(FPopupMenus); FreeAndNil(FController); FreeAndNil(FCustomization); FreeAndNil(FGroups); FreeAndNil(FImagesListener); FListeners.Free; end; procedure TcxCustomPivotGrid.DataChanged; begin ClearCacheInformation; Changes := Changes + [gcData]; if IsLocked then Exit; CheckChanges; FNavigatorNotifier.RefreshNavigatorButtons; end; procedure TcxCustomPivotGrid.DataSourceChanged; var I: Integer; begin if IsLoading then Exit; BeginUpdate; try for I := FFields.Count - 1 downto 0 do Fields[I].SynchronizeUniqueName; DataChanged; finally EndUpdate; end; end; function TcxCustomPivotGrid.DoShowPopupMenu( AMenu: TComponent; X, Y: Integer): Boolean; begin Result := PopupMenus.DoShowPopupMenu(Point(X, Y)); if not Result then Result := inherited DoShowPopupMenu(AMenu, X, Y); end; procedure TcxCustomPivotGrid.FilterControlDialogApply(Sender: TObject); begin DataController.Filter.Active := not DataController.Filter.IsEmpty; end; function TcxCustomPivotGrid.IsOLAPActive: Boolean; begin Result := Assigned(FOLAPDataSource) and FOLAPDataSource.GetIsActive; end; function TcxCustomPivotGrid.IsPrefilterEnabled: Boolean; begin Result := not IsOLAPActive; end; function TcxCustomPivotGrid.IsRestoring: Boolean; begin Result := FIsRestoring; end; procedure TcxCustomPivotGrid.InitScrollBarsParameters; begin if ViewData = nil then Exit; with ViewData do begin SetScrollBarInfo(sbHorizontal, 0, ColumnCount - 1, 1, ColumnsPerPage, ColumnIndex, True, True); SetScrollBarInfo(sbVertical, 0, RowCount - 1, 1, RowsPerPage, RowIndex, True, True) end; end; procedure TcxCustomPivotGrid.RefreshFilterableFieldsList; var I: Integer; begin FFilterableFields.Clear; if not OptionsCustomize.Filtering then Exit; for I := 0 to FieldCount - 1 do if Fields[I].Options.Filtering then FFilterableFields.Add(Fields[I]); end; procedure TcxCustomPivotGrid.ShowHourglassCursor; begin if Visible and HandleAllocated then begin if FHourglassCursorRefCount = 0 then cxControls.ShowHourglassCursor; Inc(FHourglassCursorRefCount); end; end; procedure TcxCustomPivotGrid.SynchronizeUniqueName(AField: TcxPivotGridField); begin if IsOLAPActive then AField.FLink := OLAPDataSource.GetLinkByUniqueName(AField.UniqueName) else AField.FLink := nil; if AField.FLink <> nil then AField.FUniqueName := AField.Link.UniqueName; end; procedure TcxCustomPivotGrid.UpdateMRUItems; begin FPrefilterMRUItems.VisibleCount := OptionsPrefilter.MRUItemsListCount; end; procedure TcxCustomPivotGrid.HideHourglassCursor; begin if FHourglassCursorRefCount = 1 then cxControls.HideHourglassCursor; if FHourglassCursorRefCount > 0 then Dec(FHourglassCursorRefCount); end; procedure TcxCustomPivotGrid.ImagesChangeHandler(Sender: TObject); begin LayoutChanged; end; function TcxCustomPivotGrid.IsDestroying: Boolean; begin Result := csDestroying in ComponentState; end; function TcxCustomPivotGrid.IsLoading: Boolean; begin Result := csLoading in ComponentState; end; procedure TcxCustomPivotGrid.GetChildren(Proc: TGetChildProc; Root: TComponent); procedure DoStore(AField: TcxPivotGridField); begin if AField.Owner = Root then Proc(AField); end; var I: Integer; begin inherited GetChildren(Proc, Root); for I := 0 to FieldCount - 1 do DoStore(Fields[I]); end; function TcxCustomPivotGrid.GetCursor( X, Y: Integer): TCursor; begin Result := crDefault; if not IsDesigning then Result := Controller.GetCursor(X, Y); if Result = crDefault then Result := inherited GetCursor(X, Y); end; function TcxCustomPivotGrid.GetDesignHitTest( X, Y: Integer; Shift: TShiftState): Boolean; begin Result := inherited GetDesignHitTest(X, Y, Shift); if not Result then begin HitTest.HitPoint := Point(X, Y); Result := Controller.StartDragAndDrop(Point(X, Y)) or (DragAndDropState <> ddsNone) or HitTest.HitAtButton or HitTest.HitAtField; if not Result then Controller.HotTrackController.Update(nil); end; end; function TcxCustomPivotGrid.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; begin Result := Controller.GetDragAndDropObjectClass; end; function TcxCustomPivotGrid.GetFieldClass: TcxPivotGridFieldClass; begin Result := TcxPivotGridField; end; procedure TcxCustomPivotGrid.Loaded; begin DataController.Loaded; inherited Loaded; if OLAPDataSource <> nil then DataSourceChanged; Groups.Loaded; DataChanged; end; function TcxCustomPivotGrid.CreateController: TcxPivotGridController; begin Result := TcxPivotGridController.Create(Self); end; function TcxCustomPivotGrid.CreateCustomization: TcxPivotGridCustomization; begin Result := TcxPivotGridCustomization.Create(Self); end; function TcxCustomPivotGrid.CreateDataBuilder: TcxPivotGridDataBuilder; begin Result := TcxPivotGridDataBuilder.Create(Self); end; function TcxCustomPivotGrid.CreateDataController: TcxCustomDataController; begin Result := TcxPivotGridDataController.Create(Self); end; function TcxCustomPivotGrid.CreateGroups: TcxPivotGridFieldGroupCollection; begin Result := TcxPivotGridFieldGroupCollection.Create(Self); end; function TcxCustomPivotGrid.CreateHitTest: TcxPivotGridHitTest; begin Result := TcxPivotGridHitTest.Create(Self); end; function TcxCustomPivotGrid.CreateOptionsBehavior: TcxPivotGridOptionsBehavior; begin Result := TcxPivotGridOptionsBehavior.Create(Self); end; function TcxCustomPivotGrid.CreateOptionsCustomize: TcxPivotGridOptionsCustomize; begin Result := TcxPivotGridOptionsCustomize.Create(Self); end; function TcxCustomPivotGrid.CreateOptionsData: TcxPivotGridOptionsData; begin Result := TcxPivotGridOptionsData.Create(Self); end; function TcxCustomPivotGrid.CreateOptionsDataField: TcxPivotGridOptionsDataField; begin Result := TcxPivotGridOptionsDataField.Create(Self); end; function TcxCustomPivotGrid.CreateOptionsPrefilter: TcxPivotGridOptionsPrefilter; begin Result := TcxPivotGridOptionsPrefilter.Create(Self); end; function TcxCustomPivotGrid.CreateOptionsSelection: TcxPivotGridOptionsSelection; begin Result := TcxPivotGridOptionsSelection.Create(Self); end; function TcxCustomPivotGrid.CreateOptionsView: TcxPivotGridOptionsView; begin Result := TcxPivotGridOptionsView.Create(Self); end; function TcxCustomPivotGrid.CreatePainter: TcxPivotGridPainter; begin Result := TcxPivotGridPainter.Create(Self); end; function TcxCustomPivotGrid.CreatePopupMenus: TcxPivotGridPopupMenus; begin Result := TcxPivotGridPopupMenus.Create(Self); end; function TcxCustomPivotGrid.CreateStyles: TcxPivotGridStyles; begin Result := TcxPivotGridStyles.Create(Self); end; function TcxCustomPivotGrid.CreateViewData: TcxPivotGridViewData; begin Result := TcxPivotGridViewData.Create(Self); end; function TcxCustomPivotGrid.CreateViewInfo: TcxPivotGridViewInfo; begin Result := TcxPivotGridViewInfo.Create(Self); end; procedure TcxCustomPivotGrid.DblClick; begin Controller.DblClick; inherited DblClick; end; procedure TcxCustomPivotGrid.DoCompare(AField: TcxPivotGridField; const AValue1, AValue2: Variant; var Compare: Integer); begin if Assigned(FOnCompare) then FOnCompare(Self, AField, AValue1, AValue2, Compare); end; procedure TcxCustomPivotGrid.DoCustomDrawFieldHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridFieldHeaderCellViewInfo; var ADone: Boolean); begin ADone := False; if Assigned(FOnCustomDrawFieldHeader) then FOnCustomDrawFieldHeader(Self, ACanvas, ACell, ADone); end; procedure TcxCustomPivotGrid.DoCustomDrawColumnHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridHeaderCellViewInfo; var ADone: Boolean); begin ADone := False; if Assigned(FOnCustomDrawColumnHeader) then FOnCustomDrawColumnHeader(Self, ACanvas, ACell, ADone); end; procedure TcxCustomPivotGrid.DoCustomDrawPart(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); begin ADone := False; if Assigned(FOnCustomDrawPart) then FOnCustomDrawPart(Self, ACanvas, ACell, ADone); end; procedure TcxCustomPivotGrid.DoCustomDrawRowHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridHeaderCellViewInfo; var ADone: Boolean); begin ADone := False; if Assigned(FOnCustomDrawRowHeader) then FOnCustomDrawRowHeader(Self, ACanvas, ACell, ADone); end; procedure TcxCustomPivotGrid.DoCustomDrawCell(ACanvas: TcxCanvas; ACell: TcxPivotGridDataCellViewInfo; var ADone: Boolean); begin ADone := False; if Assigned(FOnCustomDrawCell) then FOnCustomDrawCell(Self, ACanvas, ACell, ADone); end; procedure TcxCustomPivotGrid.DoCustomization; begin if Assigned(FOnCustomization) then FOnCustomization(Self); end; procedure TcxCustomPivotGrid.DoFieldPosChanged(AField: TcxPivotGridField); begin if Assigned(OnFieldPosChanged) then FOnFieldPosChanged(Self, AField); end; procedure TcxCustomPivotGrid.DoFieldSizeChanged(AField: TcxPivotGridField); begin if Assigned(OnFieldSizeChanged) then OnFieldSizeChanged(Self, AField); end; procedure TcxCustomPivotGrid.DoFilterChanged; begin CallNotify(OnFilterChanged, Self); end; procedure TcxCustomPivotGrid.DoLayoutChanged; begin if Assigned(OnLayoutChanged) then FOnLayoutChanged(Self); end; procedure TcxCustomPivotGrid.DoPrefilterChanged; begin PrefilterMRUItems.Add(DataController.Filter); DoFilterChanged; end; procedure TcxCustomPivotGrid.DoSelectionChanged; begin FNavigatorNotifier.RefreshNavigatorButtons; if Assigned(FOnSelectionChanged) then FOnSelectionChanged(Self); end; procedure TcxCustomPivotGrid.FocusChanged; begin inherited FocusChanged; if not IsLocked then ViewInfo.SelectionChanged; end; procedure TcxCustomPivotGrid.FontChanged; begin inherited FontChanged; LayoutChanged; end; function TcxCustomPivotGrid.GetIsFocused: Boolean; begin Result := inherited GetIsFocused; if not Result and (Controller <> nil) then Result := Controller.FilterPopup.HasPopupWindow; end; function TcxCustomPivotGrid.IsDesignerAvailable: Boolean; begin Result := (DesignerHelper <> nil) and (FindRootDesigner(Self) <> nil); end; procedure TcxCustomPivotGrid.KeyDown(var Key: Word; Shift: TShiftState); begin Controller.KeyDown(Key, Shift); inherited KeyDown(Key, Shift); end; procedure TcxCustomPivotGrid.KeyPress(var Key: Char); begin Controller.KeyPress(Key); inherited KeyPress(Key); end; procedure TcxCustomPivotGrid.LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); begin inherited LookAndFeelChanged(Sender, AChangedValues); LayoutChanged; end; procedure TcxCustomPivotGrid.MouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin HitTest.ShiftState := Shift; HitTest.HitPoint := Point(X, Y); Controller.MouseDown(Button, Shift, X, Y); inherited MouseDown(Button, Shift, X, Y); end; procedure TcxCustomPivotGrid.MouseLeave(AControl: TControl); begin Controller.MouseLeave; end; procedure TcxCustomPivotGrid.MouseMove(Shift: TShiftState; X, Y: Integer); begin HitTest.ShiftState := Shift; HitTest.HitPoint := Point(X, Y); Controller.MouseMove(Shift, X, Y); inherited MouseMove(Shift, X, Y); end; procedure TcxCustomPivotGrid.MouseUp( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin HitTest.ShiftState := Shift; HitTest.HitPoint := Point(X, Y); Controller.MouseUp(Button, Shift, X, Y); inherited MouseUp(Button, Shift, X, Y); end; procedure TcxCustomPivotGrid.Notification( AComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent, Operation); if PopupMenus <> nil then PopupMenus.Notification(AComponent, Operation); if Operation = opRemove then begin if AComponent = FFieldHeaderImages then FFieldHeaderImages := nil; if AComponent = FGroupHeaderImages then FGroupHeaderImages := nil; if AComponent = FOLAPDataSource then OLAPDataSource := nil; end; end; procedure TcxCustomPivotGrid.Paint; begin CheckChanges; if Changes <> [] then Exit; CheckUpdateScrollBars; inherited Paint; Painter.Paint(Canvas); if DragAndDropState = ddsInProcess then TcxPivotGridCustomDragDropObject(DragAndDropObject).DirtyChanged; end; procedure TcxCustomPivotGrid.RecreatePainter; begin FreeAndNil(FPainter); FPainter := CreatePainter; end; procedure TcxCustomPivotGrid.RecreateViewInfo; begin FreeAndNil(FViewInfo); FViewInfo := CreateViewInfo; end; procedure TcxCustomPivotGrid.Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); begin if AScrollCode = scEndScroll then Exit; if AScrollCode = scTrack then AScrollCode := scPosition; if AScrollBarKind = sbHorizontal then begin if ViewData.ScrollColumns(AScrollCode, AScrollPos) then Invalidate; end else if AScrollBarKind = sbVertical then begin if ViewData.ScrollRows(AScrollCode, AScrollPos) then Invalidate; end; end; procedure TcxCustomPivotGrid.SelectionChanged; begin if not IsLocked then ViewInfo.SelectionChanged; Changes := Changes + [gcSelection]; CheckChanges; end; procedure TcxCustomPivotGrid.SendNotification(AChanges: TcxPivotGridChanges); var I: Integer; AIntf: IcxPivotGridListener; begin for I := FListeners.Count - 1 downto 0 do if Supports(FListeners[I], IcxPivotGridListener, AIntf) then begin if gcLayout in AChanges then AIntf.LayoutChanged(Self); if gcData in AChanges then AIntf.DataChanged(Self); if gcSelection in AChanges then AIntf.SelectionChanged(Self); if AChanges = [] then AIntf.PivotRemoved(Self); end; end; function TcxCustomPivotGrid.SetFieldAreaIndex(AField: TPersistent; AArea: TcxPivotGridFieldArea; var AIndex: Integer): Boolean; var I: Integer; AFields: TcxObjectList; ANewField: TcxPivotGridField; APosInfo: TcxPivotGridFieldPosition; begin Result := not IsLoading and not IsRestoring; if not Result then Exit; APosInfo := TcxPivotGridFieldPosition.Create(AField); AFields := TcxObjectList.Create; try for I := 0 to FieldCount - 1 do begin ANewField := Fields[I]; if (ANewField.Group <> nil) and (ANewField.Group[0] <> ANewField) then Continue; if (ANewField.Area = AArea) and not APosInfo.IsSameGroup(ANewField) then AFields.Add(TcxPivotGridFieldPosition.Create(ANewField)); end; if OptionsDataField.IsSameArea(AArea) and (OptionsDataField <> AField) then AFields.Add(TcxPivotGridFieldPosition.Create(OptionsDataField)); AFields.Sort(@CompareFieldsPosition); // correct with invisible indexes if AIndex <> MaxInt then begin for I := 0 to AFields.Count - 1 do begin if I >= AIndex then Break; if not TcxPivotGridFieldPosition(AFields[I]).Visible then Inc(AIndex) else if TcxPivotGridFieldPosition(AFields[I]).Group <> nil then Dec(AIndex, TcxPivotGridFieldPosition(AFields[I]).Group.VisibleCount - 1); end; end; AIndex := Max(0, AIndex); if AIndex >= AFields.Count then AFields.Add(APosInfo) else AFields.Insert(AIndex, APosInfo); AIndex := 0; for I := 0 to AFields.Count - 1 do begin TcxPivotGridFieldPosition(AFields[I]).SetAreaIndex(AIndex); Inc(AIndex); end; finally AFields.Free; end; end; function TcxCustomPivotGrid.StartDragAndDrop(const P: TPoint): Boolean; begin Result := Controller.StartDragAndDrop(P); end; procedure TcxCustomPivotGrid.ViewChanged; begin Changes := Changes + [gcView]; CheckChanges; Invalidate; end; procedure TcxCustomPivotGrid.DoCreateAllFields; begin FOLAPDataSource.RetrieveFields(Self); end; // IcxFilterControl function TcxCustomPivotGrid.GetCaption(Index: Integer): string; begin Result := FFilterableFields[Index].Caption; end; function TcxCustomPivotGrid.GetCount: Integer; begin if IsPrefilterEnabled then Result := FFilterableFields.Count else Result := 0; end; function TcxCustomPivotGrid.GetCriteria: TcxFilterCriteria; begin Result := DataController.Filter; end; function TcxCustomPivotGrid.GetItemLink(Index: Integer): TObject; begin Result := FFilterableFields[Index]; end; function TcxCustomPivotGrid.GetItemLinkID(Index: Integer): Integer; begin Result := Index; end; function TcxCustomPivotGrid.GetItemLinkName(Index: Integer): string; begin Result := FFilterableFields[Index].Name; end; function TcxCustomPivotGrid.GetFieldName(Index: Integer): string; begin Result := FFilterableFields[Index].DataBinding.GetFilterFieldName; end; function TcxCustomPivotGrid.GetProperties(Index: Integer): TcxCustomEditProperties; begin Result := FFilterableFields[Index].GetEditProperties; end; function TcxCustomPivotGrid.GetValueType(Index: Integer): TcxValueTypeClass; begin Result := FFilterableFields[Index].DataBinding.ValueTypeClass; end; function TcxCustomPivotGrid.GetItem(Index: Integer): TObject; begin Result := Fields[Index]; end; function TcxCustomPivotGrid.GetItemID(AItem: TObject): Integer; begin Result := FFields.IndexOf(AItem); end; function TcxCustomPivotGrid.GetItemValueSource( AItemIndex: Integer): TcxDataEditValueSource; begin Result := evsValue; if (Fields[AItemIndex].Area <> faData) and (Fields[AItemIndex].Properties <> nil) then Result := Fields[AItemIndex].Properties.GetEditValueSource(false); end; procedure TcxCustomPivotGrid.UpdateControl(AInfo: TcxUpdateControlInfo); begin if {(AInfo is TcxDataChangedInfo) or} (AInfo is TcxUpdateRecordInfo)then Exit; ClearCacheInformation; DataChanged; end; procedure TcxCustomPivotGrid.UpdateData; begin ClearCacheInformation; DataChanged; end; procedure TcxCustomPivotGrid.UpdateItemIndexes; begin DataChanged; end; // IcxNavigator function TcxCustomPivotGrid.CanAppend: Boolean; begin Result := False; end; function TcxCustomPivotGrid.CanDelete: Boolean; begin Result := False; end; function TcxCustomPivotGrid.CanEdit: Boolean; begin Result := False; end; function TcxCustomPivotGrid.CanInsert: Boolean; begin Result := False; end; function TcxCustomPivotGrid.IsActive: Boolean; begin Result := True; end; function TcxCustomPivotGrid.IsBof: Boolean; begin Result := Controller.FocusedCell.Y = 0; end; function TcxCustomPivotGrid.IsBookmarkAvailable: Boolean; begin Result := ViewData.FBookMarkRow <> -1; end; function TcxCustomPivotGrid.IsEditing: Boolean; begin Result := False; end; function TcxCustomPivotGrid.IsEof: Boolean; begin Result := Controller.FocusedCell.Y >= ViewData.RowCount - 1; end; procedure TcxCustomPivotGrid.ClearBookmark; begin ViewData.FBookMarkRow := -1; end; procedure TcxCustomPivotGrid.DoAction(AButtonIndex: Integer); procedure SetRow(ARow: Integer; AAbsoluteValue: Boolean = False); begin if AAbsoluteValue then Controller.SetSelection(Controller.FocusedCell.X, ARow, []) else Controller.SetSelectionInc(0, ARow, []); ViewData.MakeSelectionVisible; end; begin case AButtonIndex of NBDI_FIRST: SetRow(0, True); NBDI_PRIORPAGE: SetRow(-ViewData.RowsPerPage + 1); NBDI_PRIOR: SetRow(-1); NBDI_NEXT: SetRow(1); NBDI_NEXTPAGE: SetRow(ViewData.RowsPerPage - 1); NBDI_LAST: SetRow(ViewData.RowCount - 1, True); NBDI_SAVEBOOKMARK: ViewData.FBookMarkRow := Controller.FocusedCell.Y; NBDI_GOTOBOOKMARK: SetRow(ViewData.FBookMarkRow, True); NBDI_FILTER: ShowPrefilterDialog; end; end; function TcxCustomPivotGrid.GetNotifier: TcxNavigatorControlNotifier; begin Result := FNavigatorNotifier; end; function TcxCustomPivotGrid.IsActionSupported(AButtonIndex: Integer): Boolean; begin case AButtonIndex of NBDI_FIRST .. NBDI_LAST, NBDI_SAVEBOOKMARK .. NBDI_FILTER: Result := True; else Result := False; end; end; // IcxStoredObject function TcxCustomPivotGrid.StoredObject_GetObjectName: string; begin Result := Name; end; function TcxCustomPivotGrid.StoredObject_GetProperties(AProperties: TStrings): Boolean; var I: Integer; begin for I := Low(PivotGridDefaultStoredProperties) to High(PivotGridDefaultStoredProperties) do AProperties.Add(PivotGridDefaultStoredProperties[I]); if Assigned(OnGetStoredProperties) then OnGetStoredProperties(Self, AProperties); Result := True; end; procedure TcxCustomPivotGrid.StoredObject_GetPropertyValue( const AName: string; var AValue: Variant); function GetFilterValue: Variant; var AStream: TStream; begin AStream := TMemoryStream.Create; try DataController.Filter.WriteData(AStream); Result := StreamToString(AStream); finally AStream.Free; end; end; begin case GetPropertyIndex(AName, PivotGridDefaultStoredProperties) of 0: AValue := GetFilterValue; 1: AValue := DataController.Filter.Active; end; if Assigned(OnGetStoredPropertyValue) then OnGetStoredPropertyValue(Self, AName, AValue); end; procedure TcxCustomPivotGrid.StoredObject_SetPropertyValue( const AName: string; const AValue: Variant); procedure SetFilterValue; var AStream: TStream; begin AStream := TMemoryStream.Create; try StringToStream(dxVariantToAnsiString(AValue), AStream); AStream.Position := 0; DataController.Filter.ReadData(AStream); finally AStream.Free; end; end; begin case GetPropertyIndex(AName, PivotGridDefaultStoredProperties) of 0: SetFilterValue; 1: DataController.Filter.Active := AValue; end; if Assigned(OnSetStoredPropertyValue) then OnSetStoredPropertyValue(Self, AName, AValue); end; // IcxStoredParent function TcxCustomPivotGrid.StoredParent_CreateChild( const AObjectName, AClassName: string): TObject; begin if AClassName = GetFieldClass.ClassName then begin Result := CreateField; TcxPivotGridField(Result).Name := AObjectName; if Assigned(OnInitStoredObject) then FOnInitStoredObject(Self, Result); end else Result := nil; end; procedure TcxCustomPivotGrid.StoredParent_DeleteChild( const AObjectName: string; AObject: TObject); begin AObject.Free; end; procedure TcxCustomPivotGrid.StoredParent_GetChildren(AChildren: TStringList); var I: Integer; begin for I := 0 to FieldCount - 1 do AChildren.AddObject('', Fields[I]); end; function TcxCustomPivotGrid.GetFieldCount: Integer; begin Result := FFields.Count; end; function TcxCustomPivotGrid.GetField(AIndex: Integer): TcxPivotGridField; begin Result := TcxPivotGridField(FieldList.List^[AIndex]); end; function TcxCustomPivotGrid.GetIsLocked: Boolean; begin Result := IsLoading or IsDestroying; if not Result then Result := FLockCount <> 0; end; function TcxCustomPivotGrid.GetRecordCount: Integer; begin Result := DataController.RowCount; end; procedure TcxCustomPivotGrid.SetField( AIndex: Integer; AValue: TcxPivotGridField); begin Fields[AIndex].Assign(AValue); end; procedure TcxCustomPivotGrid.SetFieldHeaderImages(AValue: TCustomImageList); begin SetImages(FFieldHeaderImages, AValue); end; procedure TcxCustomPivotGrid.SetGroupHeaderImages(AValue: TCustomImageList); begin SetImages(FGroupHeaderImages, AValue); end; procedure TcxCustomPivotGrid.SetGroups(AValue: TcxPivotGridFieldGroupCollection); begin FGroups.Assign(AValue); end; procedure TcxCustomPivotGrid.SetImages(var AField: TCustomImageList; ANewValue: TCustomImageList); begin cxSetImageList(ANewValue, AField, ImagesListener, Self); end; procedure TcxCustomPivotGrid.SetOLAPDataSource( AValue: TcxPivotGridCustomOLAPDataSource); begin if AValue <> OLAPDataSource then begin if FOLAPDataSource <> nil then begin FOLAPDataSource.RemoveFreeNotification(Self); FOLAPDataSource.RemoveListener(Self); end; FOLAPDataSource := AValue; if FOLAPDataSource <> nil then begin FOLAPDataSource.FreeNotification(Self); FOLAPDataSource.AddListener(Self); end; DataSourceChanged; end; end; procedure TcxCustomPivotGrid.SetOptionsBehavior( AValue: TcxPivotGridOptionsBehavior); begin FOptionsBehavior.Assign(AValue); end; procedure TcxCustomPivotGrid.SetOptionsCustomize( AValue: TcxPivotGridOptionsCustomize); begin FOptionsCustomize.Assign(AValue) end; procedure TcxCustomPivotGrid.SetOptionsData(AValue: TcxPivotGridOptionsData); begin FOptionsData.Assign(AValue); end; procedure TcxCustomPivotGrid.SetOptionsDataField( AValue: TcxPivotGridOptionsDataField); begin FOptionsDataField.Assign(AValue); end; procedure TcxCustomPivotGrid.SetOptionsPrefilter(AValue: TcxPivotGridOptionsPrefilter); begin FOptionsPrefilter.Assign(AValue); end; procedure TcxCustomPivotGrid.SetOptionsSelection( AValue: TcxPivotGridOptionsSelection); begin FOptionsSelection.Assign(AValue); end; procedure TcxCustomPivotGrid.SetOptionsView(AValue: TcxPivotGridOptionsView); begin FOptionsView.Assign(AValue); end; procedure TcxCustomPivotGrid.SetPopupMenus(AValue: TcxPivotGridPopupMenus); begin FPopupMenus.Assign(AValue); end; procedure TcxCustomPivotGrid.SetStyles(AValue: TcxPivotGridStyles); begin FStyles.Assign(AValue); end; procedure TcxCustomPivotGrid.WMSetCursor(var Message: TWMSetCursor); var P: TPoint; ACursor: TCursor; begin ACursor := crDefault; P := ScreenToClient(GetMouseCursorPos); if IsDesigning and (DragAndDropState = ddsNone) and GetDesignHitTest(P.X, P.Y, [ssLeft]) then ACursor := Controller.GetCursor(P.X, P.Y); if ACursor <> crDefault then SetCursor(Screen.Cursors[ACursor]) else inherited; end; procedure TcxCustomPivotGrid.WMGetDlgCode(var Message: TWMGetDlgCode); begin inherited; if OptionsBehavior.FocusCellOnTab then Message.Result := Message.Result or DLGC_WANTTAB; end; procedure TcxCustomPivotGrid.WMRefreshCustomization(var Message: TMessage); begin Customization.Refresh; end; procedure TcxCustomPivotGrid.RestoreFrom(AStorageType: TcxStorageType; const AStorageName: string; AStorageStream: TStream; ACreateChildren, ADeleteChildren: Boolean); var AStorage: TcxStorage; AModes: TcxStorageModes; begin AStorage := TcxStorage.Create(AStorageName, AStorageStream); try BeginUpdate; try AModes := []; if ACreateChildren then Include(AModes, smChildrenCreating); if ADeleteChildren then Include(AModes, smChildrenDeleting); AStorage.Modes := AModes; FIsRestoring := True; try case AStorageType of stIniFile: AStorage.RestoreFromIni(Self); stRegistry: AStorage.RestoreFromRegistry(Self); stStream: AStorage.RestoreFromStream(Self); end; finally FIsRestoring := False; end; finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomPivotGrid.StoreTo(AStorageType: TcxStorageType; const AStorageName: string; AStorageStream: TStream; AReCreate: Boolean = True); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStorageName, AStorageStream); try BeginUpdate; try AStorage.ReCreate := ARecreate; case AStorageType of stIniFile: AStorage.StoreToIni(Self); stRegistry: AStorage.StoreToRegistry(Self); stStream: AStorage.StoreToStream(Self); end; AStorage.ReCreate := False; finally EndUpdate; end; finally AStorage.Free; end; end; { TcxPivotGridFieldGroup } constructor TcxPivotGridFieldGroup.Create(Collection: TCollection); begin inherited Create(Collection); FieldList := TcxList.Create; end; destructor TcxPivotGridFieldGroup.Destroy; begin if not IsDestroying then Clear; FreeAndNil(FieldList); inherited Destroy; end; procedure TcxPivotGridFieldGroup.Add(AField: TcxPivotGridField); begin if FieldList.IndexOf(AField) <> cxPivotGridInvalidIndex then Exit; PivotGrid.BeginUpdate; try FieldList.Add(AField); AField.Group := Self; AField.FArea := Area; if not PivotGrid.IsLoading then AreaIndex := Max(0, AreaIndex); GroupChanged; finally PivotGrid.EndUpdate; end; end; procedure TcxPivotGridFieldGroup.AddFields(AFields: array of TcxPivotGridField); var I: Integer; begin PivotGrid.BeginUpdate; try for I := Low(AFields) to High(AFields) do Add(AFields[I]); finally PivotGrid.EndUpdate; end; end; procedure TcxPivotGridFieldGroup.Clear; begin PivotGrid.BeginUpdate; try while FieldCount > 0 do Remove(Fields[FieldCount - 1]); finally PivotGrid.EndUpdate; end; end; procedure TcxPivotGridFieldGroup.FullCollapse; begin SetExpanded(False) end; procedure TcxPivotGridFieldGroup.FullExpand; begin SetExpanded(True) end; function TcxPivotGridFieldGroup.IndexOf(AField: TcxPivotGridField): Integer; begin Result := FieldList.IndexOf(AField); end; procedure TcxPivotGridFieldGroup.Insert( AIndex: Integer; AField: TcxPivotGridField); begin PivotGrid.BeginUpdate; try AField.Group := nil; if AIndex >= FieldList.Count then FieldList.Add(AField) else begin if (AIndex = 0) and (FieldCount > 0) then begin AField.FArea := Area; AField.FAreaIndex := AreaIndex; end; FieldList.Insert(AIndex, AField); end; AField.Group := Self; AField.FArea := Area; AreaIndex := Max(0, AreaIndex); GroupChanged; finally PivotGrid.EndUpdate; end; end; function TcxPivotGridFieldGroup.IsFieldVisible( AField: TcxPivotGridField): Boolean; var I: Integer; begin Result := True; for I := 0 to FieldCount - 1 do begin Result := Result and Fields[I].Visible; if not Result or (AField = Fields[I]) then Break; Result := Result and Fields[I].GroupExpanded; end; end; function TcxPivotGridFieldGroup.IsLastVisibleField( AField: TcxPivotGridField): Boolean; var AIndex: Integer; begin Result := True; AIndex := FieldList.IndexOf(AField); if AIndex = -1 then Exit; Inc(AIndex); while Result and (AIndex < FieldCount) do begin Result := not Fields[AIndex].Visible; Inc(AIndex); end; end; procedure TcxPivotGridFieldGroup.Remove(AField: TcxPivotGridField); var I, AIndex: Integer; begin AIndex := FieldList.Remove(AField); if AIndex <> cxPivotGridInvalidIndex then begin PivotGrid.BeginUpdate; try AField.FGroup := nil; if (AIndex > 0) and (AIndex < FieldCount) then begin AField.AreaIndex := GetLatestIndex; for I := AIndex to FieldCount - 1 do Fields[I].AreaIndex := AreaIndex + I; end; GroupChanged; finally PivotGrid.EndUpdate; end; end; end; function TcxPivotGridFieldGroup.CanDropTo( AArea: TcxPivotGridFieldArea; AIndex: Integer): Boolean; begin Result := True; end; function TcxPivotGridFieldGroup.GetLatestIndex: Integer; begin Result := AreaIndex + FieldCount - 1; end; function TcxPivotGridFieldGroup.GetNextField( AField: TcxPivotGridField): TcxPivotGridField; var AIndex: Integer; begin Result := nil; AIndex := FieldList.IndexOf(AField) + 1; if AIndex < FieldCount then Result := Fields[AIndex]; end; procedure TcxPivotGridFieldGroup.GroupChanged; begin Changed(True); PivotGrid.DataChanged; end; procedure TcxPivotGridFieldGroup.InternalSetArea(AArea: TcxPivotGridFieldArea); var I: Integer; begin for I := 0 to FieldCount - 1 do Fields[I].FArea := AArea; end; function TcxPivotGridFieldGroup.IsSameDropPlace(AIndex: Integer): Boolean; begin Dec(AIndex, Fields[0].ViewInfo.AreaIndex); Result := (AIndex >= 0) and (AIndex <= VisibleCount); end; procedure TcxPivotGridFieldGroup.ResetIndexes(var ANewIndex: Integer); var I: Integer; begin for I := 0 to FieldCount - 1 do Fields[I].SetAreaIndexInternal(Area, ANewIndex + I); Inc(ANewIndex, FieldCount - 1); end; procedure TcxPivotGridFieldGroup.SetExpanded(AExpanded: Boolean); var I: Integer; begin PivotGrid.BeginUpdate; try for I := 0 to FieldCount - 1 do Fields[I].GroupExpanded := AExpanded; finally PivotGrid.EndUpdate; end; end; function TcxPivotGridFieldGroup.GetArea: TcxPivotGridFieldArea; begin if FieldCount > 0 then Result := Fields[0].Area else Result := faFilter; end; function TcxPivotGridFieldGroup.GetAreaIndex: Integer; begin if FieldCount > 0 then Result := Fields[0].AreaIndex else Result := -1; end; function TcxPivotGridFieldGroup.GetCaption: string; var I: Integer; begin if FIsCaptionAssigned then Result := FCaption else begin Result := ''; for I := 0 to FieldCount - 1 do if (I = 0) or Fields[I].Visible then Result := Result + '-' + Fields[I].Caption; Delete(Result, 1, 1); end; end; function TcxPivotGridFieldGroup.GetField(AIndex: Integer): TcxPivotGridField; begin Result := TcxPivotGridField(FieldList[AIndex]); end; function TcxPivotGridFieldGroup.GetFieldCount: Integer; begin Result := FieldList.Count; end; function TcxPivotGridFieldGroup.GetIsDestroying: Boolean; begin Result := (Groups = nil) or (PivotGrid = nil) or PivotGrid.IsDestroying; end; function TcxPivotGridFieldGroup.GetPivotGrid: TcxCustomPivotGrid; begin Result := Groups.PivotGrid end; function TcxPivotGridFieldGroup.GetVisible: Boolean; begin Result := (FieldCount > 0) and Fields[0].Visible; end; function TcxPivotGridFieldGroup.GetVisibleCount: Integer; var I: Integer; begin Result := 0; for I := 0 to FieldCount - 1 do begin if Fields[I].VisibleInGroup then Inc(Result) else Break; end; end; function TcxPivotGridFieldGroup.GetGroups: TcxPivotGridFieldGroupCollection; begin Result := TcxPivotGridFieldGroupCollection(Collection); end; procedure TcxPivotGridFieldGroup.SetArea(AValue: TcxPivotGridFieldArea); begin if (FieldCount > 0) and (Area <> AValue) then Fields[0].Area := AValue; end; procedure TcxPivotGridFieldGroup.SetAreaIndex(AValue: Integer); begin if FieldCount > 0 then Fields[0].AreaIndex := AValue; end; procedure TcxPivotGridFieldGroup.SetCaption(const AValue: string); begin if FCaption <> AValue then begin FCaption := AValue; FIsCaptionAssigned := True; GroupChanged; end; end; procedure TcxPivotGridFieldGroup.SetVisible(AValue: Boolean); begin if (Visible <> AValue) and (FieldCount > 0) then begin Fields[0].Visible := AValue; GroupChanged; end; end; { TcxPivotGridFieldGroupCollection } constructor TcxPivotGridFieldGroupCollection.Create(AOwner: TcxCustomPivotGrid); begin inherited Create(TcxPivotGridFieldGroup); FOwner := AOwner; end; function TcxPivotGridFieldGroupCollection.Add: TcxPivotGridFieldGroup; begin Result := inherited Add as TcxPivotGridFieldGroup; end; function TcxPivotGridFieldGroupCollection.CanDropTo( AArea: TcxPivotGridFieldArea; AIndex: Integer): Boolean; var I: Integer; begin Result := True; for I := 0 to Count - 1 do Result := Result and Items[I].CanDropTo(AArea, AIndex); end; function TcxPivotGridFieldGroupCollection.GetOwner: TPersistent; begin Result := FOwner; end; procedure TcxPivotGridFieldGroupCollection.Loaded; var AIndex, I: Integer; begin // sort and reindex after loaded for I := 0 to Count - 1 do with Items[I] do begin FieldList.Sort(@CompareFieldsOnLoading); AIndex := AreaIndex; ResetIndexes(AIndex); end; end; procedure TcxPivotGridFieldGroupCollection.Update(Item: TCollectionItem); begin inherited Update(Item); if PivotGrid <> nil then PivotGrid.DataChanged; end; function TcxPivotGridFieldGroupCollection.GetItem( AIndex: Integer): TcxPivotGridFieldGroup; begin Result := inherited Items[AIndex] as TcxPivotGridFieldGroup; end; procedure TcxPivotGridFieldGroupCollection.SetItem( AIndex: Integer; AValue: TcxPivotGridFieldGroup); begin inherited Items[AIndex] := AValue; end; constructor TcxPivotGridCustomPopupMenu.Create(AOwner: TcxPivotGridPopupMenus); begin FOwner := AOwner; FUseBuiltInMenu := True; end; destructor TcxPivotGridCustomPopupMenu.Destroy; begin PopupMenu := nil; FreeAndNil(FBuiltInMenu); inherited Destroy; end; procedure TcxPivotGridCustomPopupMenu.Assign(Source: TPersistent); begin if Source is TcxPivotGridCustomPopupMenu then begin UseBuiltInMenu := TcxPivotGridCustomPopupMenu(Source).FUseBuiltInMenu; PopupMenu := TcxPivotGridCustomPopupMenu(Source).PopupMenu; AssignValues(TcxPivotGridCustomPopupMenu(Source)); end; end; procedure TcxPivotGridCustomPopupMenu.ExecuteCommand(ACommand: Integer); begin ExecuteItem(GetItemByCommand(ACommand)) end; function TcxPivotGridCustomPopupMenu.Popup(X, Y: Integer): Boolean; begin CreateInternalMenu; Owner.DoOnPopup(Self, Result); if not Result then begin if UseBuiltInMenu then Result := ShowPopupMenu(PivotGrid, FBuiltInMenu, X, Y) else Result := ShowPopupMenu(PivotGrid, FPopupMenu, X, Y); end; end; procedure TcxPivotGridCustomPopupMenu.AssignValues( ASource: TcxPivotGridCustomPopupMenu); begin end; procedure TcxPivotGridCustomPopupMenu.CreateInternalMenu; begin FreeAndNil(FBuiltInMenu); FBuiltInMenu := TPopupMenu.Create(nil); FBuiltInMenu.Images := cxPivotGridPopupMenuImages; CreateItems; end; procedure TcxPivotGridCustomPopupMenu.CreateItems; begin end; function TcxPivotGridCustomPopupMenu.CreateSeparator(AOwner: TMenuItem): TMenuItem; begin Result := CreateSubItem(AOwner, '-', -1); end; function TcxPivotGridCustomPopupMenu.CreateSubItem(AOwner: TMenuItem; const ACaption: string; ACommand: Integer; AEnabled: Boolean): TMenuItem; begin Result := TMenuItem.Create(nil); Result.Caption := ACaption; Result.Enabled := AEnabled; Result.Tag := ACommand; Result.OnClick := MenuItemClickHandler; AOwner.Add(Result); end; procedure TcxPivotGridCustomPopupMenu.DoExecute(ACommand: Integer); begin if (ACommand = pgcmShowCustomization) or (ACommand = pgcmHideCustomization) then PivotGrid.Customization.Visible := ACommand = pgcmShowCustomization; end; procedure TcxPivotGridCustomPopupMenu.ExecuteItem(AItem: TMenuItem); var AHandled: Boolean; begin if AItem = nil then Exit; Owner.DoOnClick(AItem, AHandled); if not AHandled then DoExecute(AItem.Tag); end; function TcxPivotGridCustomPopupMenu.GetItemByCommand(ACommand: Integer): TMenuItem; function CheckItem(AItem: TMenuItem): TMenuItem; var I: Integer; begin Result := nil; if AItem.Tag = ACommand then begin Result := AItem; Exit; end; for I := 0 to AItem.Count - 1 do begin Result := CheckItem(AItem.Items[I]); if Result <> nil then Break; end; end; begin Result := CheckItem(BuiltInMenu.Items); end; function TcxPivotGridCustomPopupMenu.GetOwner: TPersistent; begin Result := FOwner; end; procedure TcxPivotGridCustomPopupMenu.MenuItemClickHandler(Sender: TObject); begin ExecuteItem(TMenuItem(Sender)); end; procedure TcxPivotGridCustomPopupMenu.Notification( AComponent: TComponent; Operation: TOperation); begin if (Operation = opRemove) and (AComponent = PopupMenu) then PopupMenu := nil; end; function TcxPivotGridCustomPopupMenu.GetPivotGrid: TcxCustomPivotGrid; begin Result := Owner.PivotGrid; end; function TcxPivotGridCustomPopupMenu.GetRoot: TMenuItem; begin Result := FBuiltInMenu.Items; end; procedure TcxPivotGridCustomPopupMenu.SetPopupMenu(AValue: TComponent); begin if PopupMenu <> AValue then begin if PopupMenu <> nil then PopupMenu.RemoveFreeNotification(PivotGrid); FPopupMenu := AValue; if PopupMenu <> nil then PopupMenu.FreeNotification(PivotGrid); end; end; { TcxPivotGridCustomTotal } constructor TcxPivotGridCustomTotal.Create(Collection: TCollection); begin inherited Create(Collection); SummaryType := stSum; end; procedure TcxPivotGridCustomTotal.Assign(Source: TPersistent); begin if Source is TcxPivotGridCustomTotal then begin SummaryType := TcxPivotGridCustomTotal(Source).SummaryType; DisplayFormat := TcxPivotGridCustomTotal(Source).DisplayFormat; end; end; function TcxPivotGridCustomTotal.GetField: TcxPivotGridField; begin Result := TcxPivotGridCustomTotalCollection(Collection).Field; end; function TcxPivotGridCustomTotal.GetPivotGrid: TcxCustomPivotGrid; begin Result := Field.PivotGrid; end; procedure TcxPivotGridCustomTotal.SetDisplayFormat(const AValue: string); begin if FDisplayFormat <> AValue then begin FDisplayFormat := AValue; Changed(True); end; end; procedure TcxPivotGridCustomTotal.SetSummaryType(AValue: TcxPivotGridSummaryType); begin if FSummaryType <> AValue then begin FSummaryType := AValue; Changed(True); end; end; { TcxPivotGridCustomTotalCollection } constructor TcxPivotGridCustomTotalCollection.Create(AOwner: TcxPivotGridField); begin inherited Create(TcxPivotGridCustomTotal); FOwner := AOwner; end; function TcxPivotGridCustomTotalCollection.Add( ASummaryType: TcxPivotGridSummaryType): TcxPivotGridCustomTotal; begin PivotGrid.BeginUpdate; try Result := TcxPivotGridCustomTotal(inherited Add); Result.SummaryType := ASummaryType; finally PivotGrid.EndUpdate; end; end; function TcxPivotGridCustomTotalCollection.GetOwner: TPersistent; begin Result := FOwner; end; procedure TcxPivotGridCustomTotalCollection.Update(Item: TCollectionItem); begin inherited Update(Item); if Field <> nil then Field.Changed; end; function TcxPivotGridCustomTotalCollection.GetItem( AIndex: Integer): TcxPivotGridCustomTotal; begin Result := TcxPivotGridCustomTotal(inherited Items[AIndex]); end; function TcxPivotGridCustomTotalCollection.GetPivotGrid: TcxCustomPivotGrid; begin Result := Field.PivotGrid; end; procedure TcxPivotGridCustomTotalCollection.SetItem( AIndex: Integer; AValue: TcxPivotGridCustomTotal); begin Items[AIndex].Assign(AValue); end; { TcxPivotGridDefaultValuesProvider } function TcxPivotGridDefaultValuesProvider.IsDisplayFormatDefined( AIsCurrencyValueAccepted: Boolean): Boolean; begin with TcxPivotGridFieldDataBinding(Owner) do Result := PivotGrid.DataController.IsDisplayFormatDefined( Field.Index, not AIsCurrencyValueAccepted); end; { TcxPivotGridFieldDataBinding } constructor TcxPivotGridFieldDataBinding.Create(AOwner: TcxPivotGridField); begin inherited Create; FField := AOwner; FDefaultValuesProvider := GetDefaultValuesProviderClass.Create(Self); end; destructor TcxPivotGridFieldDataBinding.Destroy; begin FDefaultValuesProvider.Free; inherited; end; procedure TcxPivotGridFieldDataBinding.Assign(Source: TPersistent); begin if Source is TcxPivotGridFieldDataBinding then ValueType := TcxPivotGridFieldDataBinding(Source).ValueType else inherited Assign(Source); end; function TcxPivotGridFieldDataBinding.GetDefaultValuesProvider: IcxEditDefaultValuesProvider; begin Result := FDefaultValuesProvider; Init; end; function TcxPivotGridFieldDataBinding.GetDefaultValuesProviderClass: TcxCustomEditDefaultValuesProviderClass; begin Result := TcxPivotGridDefaultValuesProvider; end; function TcxPivotGridFieldDataBinding.GetFilterFieldName: string; begin Result := ''; end; function TcxPivotGridFieldDataBinding.GetOwner: TPersistent; begin Result := FField; end; procedure TcxPivotGridFieldDataBinding.Init; begin //do nothing end; function TcxPivotGridFieldDataBinding.GetPivotGrid: TcxCustomPivotGrid; begin Result := Field.PivotGrid; end; function TcxPivotGridFieldDataBinding.GetValueType: string; begin if ValueTypeClass <> nil then Result := ValueTypeClass.Caption else Result := ''; end; function TcxPivotGridFieldDataBinding.GetValueTypeClass: TcxValueTypeClass; begin Result := PivotGrid.DataController.GetItemValueTypeClass(Field.Index); end; procedure TcxPivotGridFieldDataBinding.SetValueType(AValue: string); begin ValueTypeClass := cxValueTypeClassList.ItemByCaption(AValue); end; procedure TcxPivotGridFieldDataBinding.SetValueTypeClass(AValue: TcxValueTypeClass); begin FValueTypeAssigned := True; PivotGrid.DataController.ChangeValueTypeClass(Field.Index, AValue); FField.PropertiesValueChanged; end; function TcxPivotGridFieldDataBinding.IsValueTypeStored: Boolean; begin Result := FValueTypeAssigned; end; { TcxPivotGridCustomDragDropObject } function TcxPivotGridCustomDragDropObject.GetPivotGrid: TcxCustomPivotGrid; begin Result := TcxCustomPivotGrid(Control); end; function TcxPivotGridCustomDragDropObject.GetHitTest: TcxPivotGridHitTest; begin Result := PivotGrid.HitTest; end; function TcxPivotGridCustomDragDropObject.GetOptionsView: TcxPivotGridOptionsView; begin Result := PivotGrid.OptionsView; end; function TcxPivotGridCustomDragDropObject.GetPainter: TcxCustomLookAndFeelPainterClass; begin Result := PivotGrid.LookAndFeelPainter; end; function TcxPivotGridCustomDragDropObject.GetViewInfo: TcxPivotGridViewInfo; begin Result := PivotGrid.ViewInfo; end; procedure SetEmptyRegion(AHandle: HWND); var AEmptyRgn: HRGN; begin AEmptyRgn := CreateRectRgn(0, 0, 0, 0); SetWindowRgn(AHandle, AEmptyRgn, True); DeleteObject(AEmptyRgn); end; { TcxPivotGridMRUPrefilterPopup } constructor TcxPivotGridMRUPrefilterPopup.Create(AOwner: TComponent); begin inherited Create(AOwner); Parent := TcxCustomPivotGrid(AOwner); Visible := False; end; procedure TcxPivotGridMRUPrefilterPopup.Popup; begin BeforePopup; DroppedDown := True; end; procedure TcxPivotGridMRUPrefilterPopup.BeforePopup; var ARect: TRect; begin Style.LookAndFeel.NativeStyle := PivotGrid.LookAndFeel.NativeStyle; Visible := False; Prefilter.ViewInfo.SetDroppedDown(PivotGrid.HitTest, True); PivotGrid.InvalidateRect(Prefilter.ViewInfo.Bounds, False); ARect := Prefilter.ViewInfo.GetDropDownWindowOwnerBounds; ARect.Top := ARect.Bottom - Height + 1; ARect.Left := ARect.Left - PopupWindow.ViewInfo.GetClientExtent.Left - cxTextOffset - 1; BoundsRect := ARect; InitValues; if PivotGrid.OptionsPrefilter.MRUItemsListDropDownCount = 0 then Properties.DropDownRows := MaxInt else Properties.DropDownRows := PivotGrid.OptionsPrefilter.MRUItemsListDropDownCount; Visible := True; end; procedure TcxPivotGridMRUPrefilterPopup.DoCloseUp; begin inherited DoCloseUp; PivotGrid.Controller.PreFilterOpenedBeforeClick := (PivotGrid.HitTest.HitAtPrefilterDropDownButton or PivotGrid.HitTest.HitAtPrefilterCaption) and (FCloseUpReason = crUnknown); Prefilter.ViewInfo.SetDroppedDown(PivotGrid.HitTest, False); PivotGrid.InvalidateRect(Prefilter.ViewInfo.Bounds, False); if FCloseUpReason <> crUnknown then SelectedMRUItem.AssignTo(PivotGrid.DataController.Filter); end; procedure TcxPivotGridMRUPrefilterPopup.InitValues; var I: Integer; begin with Properties.Items do begin BeginUpdate; try Clear; with PivotGrid.PrefilterMRUItems do for I := 0 to VisibleCount - 1 do AddObject(VisibleItems[I].Caption, VisibleItems[I]); finally EndUpdate; end; end; end; procedure TcxPivotGridMRUPrefilterPopup.SetShadowRegion; begin SetEmptyRegion(Handle); end; function TcxPivotGridMRUPrefilterPopup.GetPivotGrid: TcxCustomPivotGrid; begin Result := TcxCustomPivotGrid(Parent); end; function TcxPivotGridMRUPrefilterPopup.GetPrefilter: TcxPivotGridPrefilter; begin Result := PivotGrid.ViewInfo.Prefilter; end; function TcxPivotGridMRUPrefilterPopup.SelectedMRUItem: TcxPivotGridFilterMRUItem; begin Result := TcxPivotGridFilterMRUItem(Properties.Items.Objects[SelectedItem]); end; { TcxPivotGridFilterPopup } constructor TcxPivotGridFilterPopup.Create(AOwner: TComponent); begin inherited Create(AOwner); Left := cxInvisiblePos; Top := cxInvisiblePos; Parent := TcxCustomPivotGrid(AOwner); AutoSize := False; Visible := False; Properties.PopupAutoSize := False; Properties.PopupMinWidth := cxPivotGridFilterPopupMinWidth; Properties.PopupMinHeight := cxPivotGridFilterPopupMinHeight; Properties.PopupSysPanelStyle := True; CreateControls; Properties.PopupControl := Values; end; procedure TcxPivotGridFilterPopup.Popup; begin PopupWindow.MinSysPanelHeight := cxPivotGridFilterMinSysPanelHeight; BeforePopup; DroppedDown := True; end; procedure TcxPivotGridFilterPopup.SaveChanges; var I: Integer; AIsInclude: Boolean; const AStates: array[Boolean] of TcxCheckBoxState = (cbsUnchecked, cbsChecked); begin AIsInclude := GetCheckedCount < (Values.Items.Count div 2); Filter.BeginUpdate; try Filter.Clear; Filter.FilterType := TcxPivotGridFilterType(AIsInclude); for I := 1 to Values.Items.Count - 1 do if (Values.Items[I].State = AStates[AIsInclude]) then Filter.Values.Add(GetFieldValueByValueIndex(I)); finally Filter.EndUpdate; end; end; function TcxPivotGridFilterPopup.AddValue( const AValue: TcxPivotGridVariantValue): TcxCheckListBoxItem; begin Result := Values.Items.Add; if Field.UseEditProperties and (Field.SummaryVariation = svNone) and (Field.Area <> faData) then Result.Text := Field.GetUserEditProperties.GetDisplayText(AValue.Value) else Result.Text := Field.GetGroupValueDisplayText(AValue.Value); if AValue.FUnUsed then Result.State := cbsGrayed else Result.State := TcxCheckBoxState(not Filter.HasFilter or Filter.Contains(AValue.Value)); Result.ItemObject := AValue; end; procedure TcxPivotGridFilterPopup.BeforePopup; begin Properties.PopupSizeable := PivotGrid.OptionsCustomize.FilterResizable; Style.LookAndFeel.NativeStyle := PivotGrid.LookAndFeel.NativeStyle; Visible := False; Style.TransparentBorder := False; with Field.ViewInfo do begin BoundsRect := Rect(Bounds.Left, Bounds.Top, Bounds.Right, Bounds.Bottom); FPrevFilterState := FilterState; State := cxbsNormal; FilterState := cxbsPressed; end; with PivotGrid.Controller.CalculateFilterDropDownSize(Filter) do SetPopupSize(cx, cy); BoundsRect := cxRectSetRight(BoundsRect, Field.ViewInfo.Bounds.Right); Properties.PopupAlignment := taRightJustify; Visible := True; end; procedure TcxPivotGridFilterPopup.ButtonClickHandler(ASender: TObject); var AReason: TcxEditCloseUpReason; begin if TComponent(ASender).Tag = 1 then AReason := crClose else AReason := crCancel; CloseUp(AReason); end; procedure TcxPivotGridFilterPopup.CheckButtonsEnabled; begin OkButton.Enabled := ShowAllState <> cbsUnchecked; end; procedure TcxPivotGridFilterPopup.CreateControls; begin // Values - CheckListBox initialize FValues := TcxCheckListBox.Create(Self); FValues.BoundsRect := Rect(cxInvisiblePos, cxInvisiblePos, cxPivotGridFilterPopupMinWidth, cxPivotGridFilterPopupMinHeight); FValues.Visible := False; FValues.Style.LookAndFeel.MasterLookAndFeel := LookAndFeel; FValues.Parent := PivotGrid; FValues.Style.HotTrack := False; FValues.Style.BorderStyle := cbsNone; FValues.Style.TransparentBorder := False; FValues.EditValueFormat := cvfStatesString; FValues.OnEditValueChanged := ValuesChanges; // Buttons intialize FCancelButton := CreateButton(cxGetResourceString(@scxPivotGridCancel), 0); FCancelButton.Cancel := True; FOkButton := CreateButton(cxGetResourceString(@scxPivotGridOk), 1); FButtonWidth := MulDiv(Max(cxTextWidth(PivotGrid.Font, FOkButton.Caption), cxTextWidth(PivotGrid.Font, FCancelButton.Caption)), 3, 2); FOkButton.Default := True; end; procedure TcxPivotGridFilterPopup.DoCloseUp; begin inherited DoCloseUp; if FPrevFilterState = cxbsHot then begin Field.ViewInfo.FilterState := cxbsNormal; PivotGrid.InvalidateRect(Field.ViewInfo.Bounds, False); end; if (FCloseUpReason <> crCancel) and (ShowAllState <> cbsUnchecked) and FilterModified then SaveChanges; Filter.WindowSize := cxSize(PopupWindow.Width, PopupWindow.Height); PivotGrid.Controller.FilterOpenedBeforeClick := (FCloseUpReason = crUnknown) and PivotGrid.HitTest.HitAtFilter and (PivotGrid.HitTest.Field = Field) end; function TcxPivotGridFilterPopup.GetCheckedCount: Integer; var I: Integer; begin Result := 0; for I := 1 to Values.Items.Count - 1 do begin if Values.Items[I].State = cbsChecked then Inc(Result); end; end; function TcxPivotGridFilterPopup.GetFieldValueByValueIndex( AIndex: Integer): Variant; begin Result := TcxPivotGridVariantValue(Values.Items[AIndex].ItemObject).Value; end; function TcxPivotGridFilterPopup.GetHeight(AItemCount: Integer): Integer; begin Result := FValues.GetHeight(AItemCount) + PopupWindow.ViewInfo.GetSysPanelHeight + cxPivotGridDoubleSpace; end; function TcxPivotGridFilterPopup.GetStateByCount( ACount: Integer): TcxCheckBoxState; begin if ACount = 0 then Result := cbsUnchecked else if ACount = Values.Items.Count - 1 then Result := cbsChecked else Result := cbsGrayed; end; procedure TcxPivotGridFilterPopup.InitValues; var I: Integer; AShowAllItem: TcxCheckListBoxItem; begin with Values.Items do begin BeginUpdate; PivotGrid.ShowHourglassCursor; FLocked := True; try Clear; FShowAllState := cbsUnchecked; AShowAllItem := Values.Items.Add; AShowAllItem.Text := cxGetResourceString(@scxPivotGridShowAll); for I := 0 to Field.GroupValueList.Count - 1 do AddValue(Field.GroupValueList.Items[I]); FShowAllState := GetStateByCount(GetCheckedCount);; AShowAllItem.State := FShowAllState; finally FLocked := False; PivotGrid.HideHourglassCursor; CheckButtonsEnabled; EndUpdate; end; end; FFilterModified := False; end; procedure TcxPivotGridFilterPopup.SetPopupSize(const AWidth, AHeight: Integer); begin Values.Width := AWidth - cxTextOffset; Values.Height := AHeight - cxTextOffset; Properties.PopupHeight := AHeight; Properties.PopupWidth := AWidth; end; procedure TcxPivotGridFilterPopup.SetupPopupWindow; var AHeight, ADelta: Integer; R: TRect; begin if FCancelButton = nil then begin inherited SetupPopupWindow; Exit; end; TcxEditStyleAccess(Style).PopupCloseButton := False; inherited SetupPopupWindow; AHeight := FCancelButton.Height; ADelta := FButtonWidth + AHeight div 6; Values.Style.Font := PivotGrid.Font; R := Rect(0, 0, 0, PopupWindow.ViewInfo.GetSysPanelHeight); if PopupWindow.ViewInfo.SizeGripCorner in [ecoBottomLeft, ecoBottomRight] then R := cxRectSetBottom(R, PopupWindow.Height); if PopupWindow.ViewInfo.SizeGripCorner in [ecoTopRight, ecoBottomRight] then begin R := cxRectSetRight(R, PopupWindow.Width - cxRectWidth(PopupWindow.ViewInfo.SizeGripRect)); Inc(ADelta, PopupWindow.Width - R.Left) end else begin Inc(ADelta, AHeight div 6); if ADelta - FButtonWidth < R.Left then ADelta := R.Left + FButtonWidth; end; if PopupWindow.ViewInfo.SizeGripCorner in [ecoTopLeft, ecoTopRight] then FCancelButton.Anchors := [akTop, akRight] else FCancelButton.Anchors := [akBottom, akRight]; FCancelButton.SetBounds(PopupWindow.Width - ADelta, (R.Bottom + R.Top - AHeight) div 2 - 1, FButtonWidth, AHeight); FCancelButton.Font := PivotGrid.Font; if FOkButton <> nil then begin FOkButton.SetBounds(FCancelButton.Left - (FButtonWidth + (AHeight div 3)), FCancelButton.Top, FButtonWidth, AHeight); FOkButton.Anchors := FCancelButton.Anchors; FOkButton.Font := PivotGrid.Font; end; InitValues; end; procedure TcxPivotGridFilterPopup.SetShadowRegion; begin SetEmptyRegion(Handle); end; procedure TcxPivotGridFilterPopup.ValuesChanges(Sender: TObject); begin if FLocked then Exit; FFilterModified := True; if Values.Items[0].State <> FShowAllState then ShowAllState := Values.Items[0].State else begin FLocked := True; try FShowAllState := GetStateByCount(GetCheckedCount); Values.Items[0].State := FShowAllState; finally FLocked := False; end; end; CheckButtonsEnabled; end; function TcxPivotGridFilterPopup.GetPivotGrid: TcxCustomPivotGrid; begin Result := TcxCustomPivotGrid(Parent); end; function TcxPivotGridFilterPopup.CreateButton( const ACaption: string; ATag: Integer): TcxButton; begin Result := TcxButton.Create(Self); Result.Caption := ACaption; Result.Parent := PopupWindow; Result.Height := 20; Result.Tag := ATag; Result.LookAndFeel.MasterLookAndFeel := LookAndFeel; Result.OnClick := ButtonClickHandler; end; function TcxPivotGridFilterPopup.GetFilter: TcxPivotGridFieldFilter; begin Result := Field.Filter; end; procedure TcxPivotGridFilterPopup.SetField(AField: TcxPivotGridField); begin if FField <> AField then begin FField := AField; end; end; procedure TcxPivotGridFilterPopup.SetShowAllState(AValue: TcxCheckBoxState); var I: Integer; begin if (FShowAllState <> AValue) and not FLocked then begin FLocked := True; FShowAllState := AValue; Values.Items.BeginUpdate; try for I := 0 to Values.Items.Count - 1 do Values.Items[I].State := AValue; finally Values.Items.EndUpdate; FLocked := False; end; end; end; { TcxPivotGridVariantValue } constructor TcxPivotGridVariantValue.Create(const AValue: Variant); begin FValue := AValue; end; function TcxPivotGridVariantValue.Compare(const AValue: Variant): Integer; begin Result := VarCompare(FValue, AValue); end; function TcxPivotGridVariantValue.IsEqual(AValue: TcxPivotGridVariantValue): Boolean; begin Result := (AValue <> nil) and ((AValue = Self) or VarEquals(AValue.Value, Value)); end; { TcxPivotGridVariantList } constructor TcxPivotGridVariantList.Create; begin FItems := TcxObjectList.Create; end; destructor TcxPivotGridVariantList.Destroy; begin FItems.Free; inherited Destroy; end; function TcxPivotGridVariantList.Add(const AValue: Variant): Integer; begin Sorted := False; Result := FItems.Add(TcxPivotGridVariantValue.Create(AValue)); Changed; end; function TcxPivotGridVariantList.AddUnique(const AValue: Variant): Integer; begin Result := IndexOf(AValue); if Result < 0 then Result := Add(AValue); end; procedure TcxPivotGridVariantList.Clear; begin FItems.Clear; Changed; end; procedure TcxPivotGridVariantList.Delete(AIndex: Integer); begin FItems.Items[AIndex].Free; FItems.Delete(AIndex); Changed; end; function TcxPivotGridVariantList.IndexOf(const AValue: Variant): Integer; var L, H, I, C: Integer; begin Result := -1; MakeSorted; // binary search L := 0; H := Count - 1; while L <= H do begin I := (L + H) shr 1; C := Items[I].Compare(AValue); if C < 0 then L := I + 1 else begin H := I - 1; if C = 0 then begin Result := I; Break; end; end; end; end; procedure TcxPivotGridVariantList.MakeUnique; var I: Integer; AItem: TcxPivotGridVariantValue; begin I := 0; AItem := nil; MakeSorted; while I < Count do begin if (I > 0) and AItem.IsEqual(Items[I]) then begin AItem.FUnUsed := AItem.FUnUsed and Items[I].FUnUsed; Delete(I); end else begin AItem := Items[I]; Inc(I); end; end; end; function TcxPivotGridVariantList.Remove(const AValue: Variant): Integer; begin Result := IndexOf(AValue); if Result <> cxPivotGridInvalidIndex then Delete(Result); end; procedure TcxPivotGridVariantList.BeginUpdate; begin Inc(FLockCount); end; procedure TcxPivotGridVariantList.EndUpdate(AForceUpdate: Boolean = True); begin if FLockCount > 0 then begin Dec(FLockCount); if AForceUpdate or FModified then Changed; end; end; procedure TcxPivotGridVariantList.Changed; begin if FLockCount = 0 then begin CallNotify(OnChange, Self); FModified := False; end else FModified := True; end; procedure TcxPivotGridVariantList.MakeSorted; begin if not Sorted then begin FItems.Sort(@CompareFilterValues); Sorted := True; end; end; function TcxPivotGridVariantList.GetCount: Integer; begin Result := FItems.Count; end; function TcxPivotGridVariantList.GetItem( AIndex: Integer): TcxPivotGridVariantValue; begin Result := TcxPivotGridVariantValue(FItems[AIndex]); end; function TcxPivotGridVariantList.GetValue(AIndex: Integer): Variant; begin Result := Items[AIndex].Value; end; procedure TcxPivotGridVariantList.SetValue(AIndex: Integer; AValue: Variant); begin Sorted := False; Items[AIndex].FValue := AValue; end; { TcxPivotGridPainter } constructor TcxPivotGridPainter.Create(AOwner: TcxCustomPivotGrid); begin FPivotGrid := AOwner; end; procedure TcxPivotGridPainter.Paint(ACanvas: TcxCanvas); begin FCanvas := ACanvas; FViewInfo := PivotGrid.ViewInfo; FViewInfo.BeforePaint; DoPaint; FViewInfo.AfterPaint; end; procedure TcxPivotGridPainter.DoPaint; begin with ViewInfo do begin Canvas.SaveState; try FieldHeaders.Paint(Canvas, DoCustomDrawFieldHeader); FieldHeaders.ExcludeFromClipping(Canvas); ColumnHeaders.Paint(Canvas, DoCustomDrawColumnHeader); CommonCells.Paint(Canvas, DoCustomDrawPart); RowHeaders.Paint(Canvas, DoCustomDrawRowHeader); DataCells.Paint(Canvas, DoCustomDrawDataCell); Prefilter.Paint(Canvas, DoCustomDrawPart); finally Canvas.RestoreState; end; end; end; procedure TcxPivotGridPainter.DoCustomDrawFieldHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); begin PivotGrid.DoCustomDrawFieldHeader(ACanvas, TcxPivotGridFieldHeaderCellViewInfo(ACell), ADone); end; procedure TcxPivotGridPainter.DoCustomDrawColumnHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); begin PivotGrid.DoCustomDrawColumnHeader(ACanvas, TcxPivotGridHeaderCellViewInfo(ACell), ADone); end; procedure TcxPivotGridPainter.DoCustomDrawPart(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); begin PivotGrid.DoCustomDrawPart(ACanvas, ACell, ADone); end; procedure TcxPivotGridPainter.DoCustomDrawRowHeader(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); begin PivotGrid.DoCustomDrawRowHeader(ACanvas, TcxPivotGridHeaderCellViewInfo(ACell), ADone); end; procedure TcxPivotGridPainter.DoCustomDrawDataCell(ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); begin PivotGrid.DoCustomDrawCell(ACanvas, TcxPivotGridDataCellViewInfo(ACell), ADone); end; { TcxPivotGridDataBuilder } constructor TcxPivotGridDataBuilder.Create(AOwner: TcxCustomPivotGrid); begin FPivotGrid := AOwner; FFields := TcxPivotGridFields.Create; FFilteredFields := TcxPivotGridFields.Create; FDataController := FPivotGrid.DataController; FRowFields := TcxPivotGridFields.Create; FColumnFields := TcxPivotGridFields.Create; FFilterFields := TcxPivotGridFields.Create; FDataFields := TcxPivotGridFields.Create; FData := TcxPivotGridGroupItem.Create(nil, DataController, -1, nil); FColumns := TcxPivotGridColumnItem.Create(nil, DataController, -1, nil); FRows := TcxPivotGridRowItem.Create(nil, DataController, -1, nil); FFilteredIndexes := TcxPivotGridRecords.Create; end; destructor TcxPivotGridDataBuilder.Destroy; begin FreeAndNil(FFilteredFields); FreeAndNil(FFields); FreeAndNil(FData); FreeAndNil(FFilterFields); FreeAndNil(FDataFields); FreeAndNil(FColumns); FreeAndNil(FColumnFields); FreeAndNil(FRows); FreeAndNil(FRowFields); FreeAndNil(FFilteredIndexes); inherited Destroy; end; function TcxPivotGridDataBuilder.CanGroup: Boolean; begin Result := ((PivotGrid.RecordCount > 0) or (OLAPDataSource <> nil)) and (DataFields.Count > 0); end; procedure TcxPivotGridDataBuilder.DataChanged; begin PivotGrid.ShowHourglassCursor; try Clear; FOLAPDataSource := PivotGrid.OLAPDataSource; PivotGrid.RefreshDate := Date; PopulateRecordsList; SplitFieldsByGroups; ApplyFilter; if (FOLAPDataSource <> nil) and FOLAPDataSource.IsActive then begin if not FOLAPDataSource.IsTerminated then begin FOLAPDataSource.InitializeLayout(RowFields, ColumnFields, SummaryFields, FilteredFields); FOLAPDataSource.CreateRootLayout(PivotGrid); end; end else begin GroupByRows; GroupByColumns; end; CreateDataCells; AfterDataChanged; finally PivotGrid.HideHourglassCursor; end; end; procedure TcxPivotGridDataBuilder.AddSummaryField( AField: TcxPivotGridField); begin if PivotGrid.IsOLAPActive and (AField.Link = nil) then Exit; AField.FSummaryIndex := PivotGrid.SummaryFields.IndexOf(AField); if AField.SummaryIndex = cxPivotGridInvalidIndex then AField.FSummaryIndex := PivotGrid.SummaryFields.Add(AField); with PivotGrid do HasSummaryVariation := HasSummaryVariation or AField.HasSummaryVariation; end; procedure TcxPivotGridDataBuilder.AfterDataChanged; procedure PostProcessGroups(AFields: TcxPivotGridFields; ARoot, ACrossTotal: TcxPivotGridGroupItem); var ProcessFieldsCount, I: Integer; begin ARoot.ReIndexChildren(True); ProcessFieldsCount := 0; for I := 0 to AFields.Count - 1 do if AFields[I].SortedBySummary or (AFields[I].TopValueCount > 0) then Inc(ProcessFieldsCount); if ProcessFieldsCount = 0 then Exit; ARoot.PostProcessGroup(ACrossTotal); end; begin PostProcessGroups(RowFields, Rows, Columns); PostProcessGroups(ColumnFields, Columns, Rows); end; procedure TcxPivotGridDataBuilder.ApplyFilter; var ARecordIndex, I, AFilteredFieldCount: Integer; AFilteredList: TcxPivotGridFields; begin AFilteredList := TcxPivotGridFields.Create; try AFilteredList.Assign(Fields); for I := AFilteredList.Count - 1 downto 0 do begin if not AFilteredList[I].Filter.HasFilter then AFilteredList.Delete(I); end; if AFilteredList.Count > 0 then for ARecordIndex := 0 to PivotGrid.RecordCount - 1 do begin AFilteredFieldCount := 0; for I := 0 to AFilteredList.Count - 1 do if not AFilteredList[I].IsRecordVisible(ARecordIndex) then Inc(AFilteredFieldCount); if AFilteredFieldCount > 0 then FilteredIndexes[ARecordIndex] := -AFilteredFieldCount; end; finally AFilteredList.Free; end; end; function TcxPivotGridDataBuilder.CanGroupByColumns: Boolean; begin Result := CanGroup and (ColumnFields.Count > 0); end; function TcxPivotGridDataBuilder.CanGroupByRows: Boolean; begin Result := CanGroup and (RowFields.Count > 0); end; procedure TcxPivotGridDataBuilder.Clear; begin Fields.Clear; FilteredFields.Clear; FilteredIndexes.Clear; Columns.DeleteChildren; Rows.DeleteChildren; ColumnFields.Clear; RowFields.Clear; FilterFields.Clear; Data.DeleteChildren; DataFields.Clear; SummaryFields.Clear; end; procedure TcxPivotGridDataBuilder.CreateDataCells; var I: Integer; begin for I := 0 to DataFields.Count - 1 do FData.ItemList.Add(TcxPivotGridDataItem.Create(FData, DataController, -1, DataFields[I])); end; procedure TcxPivotGridDataBuilder.GroupBy(AFields: TcxPivotGridFields; ARoot: TcxPivotGridGroupItem); var AValue: Variant; AParent: TcxPivotGridGroupItem; I, J, AIndex, AFieldIndex: Integer; begin for I := 0 to PivotGrid.RecordCount - 1 do begin AIndex := 0; AParent := TcxPivotGridGroupItem(ARoot); AFieldIndex := 0; if FilteredIndexes[I] <= -1 then Continue; while AFieldIndex < AFields.Count do begin AValue := AFields[AFieldIndex].GetGroupValue(I); if FindItem(AParent.FItems, AValue, AIndex, AFields[AFieldIndex].SortOrder) then begin AParent := TcxPivotGridGroupItem(AParent.ItemList.List^[AIndex]); Inc(AFieldIndex); AIndex := 0; Continue; end else Break; end; for J := AFieldIndex to AFields.Count - 1 do begin AParent := AParent.AddChild(AIndex, I, AFields[J]); AFields[J].GroupCheckExpanding(AParent); AIndex := 0; end; AParent.Records.Add(I); end; end; procedure TcxPivotGridDataBuilder.GroupByColumns; begin if CanGroupByColumns then GroupBy(ColumnFields, Columns); end; procedure TcxPivotGridDataBuilder.GroupByRows; begin if CanGroupByRows then GroupBy(RowFields, Rows); end; procedure TcxPivotGridDataBuilder.GroupExpandingChanged( AItem: TcxPivotGridGroupItem); begin if FExpandingLockCount > 0 then FExpandingItems.Add(AItem); //todo: need for cumulative expanding OLAPDataSource.ExpandMember(AItem.Field, AItem, False); end; procedure TcxPivotGridDataBuilder.LockExpanding; begin if FExpandingLockCount = 0 then FExpandingItems := TList.Create; Inc(FExpandingLockCount); end; procedure TcxPivotGridDataBuilder.PopulateRecordsList; var I: Integer; begin FilteredIndexes.Count := PivotGrid.RecordCount; for I := 0 to PivotGrid.RecordCount - 1 do FilteredIndexes.List^[I] := Pointer(I); end; procedure TcxPivotGridDataBuilder.SplitFieldsByGroups; var I, AIndex: Integer; AField: TcxPivotGridField; AFields: TcxPivotGridFields; AFieldCount: array[TcxPivotGridFieldArea] of Integer; begin Fields.Assign(PivotGrid.FieldList); Fields.ArrangeFields; FillChar(AFieldCount, SizeOf(AFieldCount), 0); for I := 0 to Fields.Count - 1 do begin AField := Fields[I]; if PivotGrid.IsOLAPActive and (AField.Link = nil) then Continue; if AField.Filter.HasFilter or PivotGrid.IsOLAPActive and TcxPivotGridOLAPField.IsFiltered(AField) then FFilteredFields.Add(AField); AFields := ColumnFields; case AField.Area of faRow: AFields := RowFields; faFilter: AFields := FilterFields; faData: AFields := DataFields; end; // for optimization summary calculation AField.FSummaryIndex := -1; if AField.Area = faData then AddSummaryField(AField); if AField.SortBySummaryInfo.Field <> nil then AddSummaryField(AField.SortBySummaryInfo.Field); AField.FAreaIndex := AFieldCount[AField.Area]; Inc(AFieldCount[AField.Area]); if AField.VisibleInGroup and (AField.FVisibleIndex <> AFields.Add(AField)) then begin AField.FVisibleIndex := AFields.Count - 1; AField.ExpandingInfo.Clear; end; end; // todo: move data field bug fix AIndex := PivotGrid.OptionsDataField.AreaIndex; if PivotGrid.ViewInfo.IsDataFieldVisible([dfaRow, dfaColumn]) and (AIndex >= 0) then begin for I := 0 to Fields.Count - 1 do begin if (Fields[I].Area = DataAreaToFieldArea[PivotGrid.OptionsDataField.Area]) and (Fields[I].AreaIndex >= AIndex) then Inc(Fields[I].FAreaIndex); end; end; end; procedure TcxPivotGridDataBuilder.UnlockExpanding; {var AItem: TcxPivotGridGroupItem;} begin Dec(FExpandingLockCount); if (FExpandingLockCount = 0) then try if (FExpandingItems.Count > 0) then ; // todo: cumulative expanding optimization { AItem := TcxPivotGridGroupItem(FExpandingItems[0]); if AItem.Area = faRow then begin AFields := ADataBuilder.RowFields; ACrossGroup := ADataBuilder.Columns; end; if AField.VisibleIndex + 1 < AFields.Count then AField := AFields[AField.VisibleIndex + 1]; AMembersList := CreateMembersFromGroup(ACrossGroup, False); if AItem.Field.Area = faRow then OLAPDataSource.InitializeMemberExpanding(Self, AItem.Field, AMembersList, AList); OLAPDataSource.InitializeCrossCells(ACrossGroup, AMember, ADataBuilder.SummaryFields);} finally FExpandingItems.Free; end; end; function TcxPivotGridDataBuilder.GetCrossCell( ARow, AColumn: TcxPivotGridGroupItem): TcxPivotGridCrossCell; begin Result := ARow.GetCellByCrossItem(AColumn); end; function TcxPivotGridDataBuilder.GetSummaryFields: TcxPivotGridFields; begin Result := PivotGrid.SummaryFields; end; { TcxPivotGridCustomOptions } constructor TcxPivotGridCustomOptions.Create(AOwner: TcxCustomPivotGrid); begin FPivotGrid := AOwner; end; procedure TcxPivotGridCustomOptions.Assign(Source: TPersistent); begin if Source is TcxPivotGridCustomOptions then else inherited Assign(Source); end; function TcxPivotGridCustomOptions.GetOwner: TPersistent; begin Result := FPivotGrid; end; procedure TcxPivotGridCustomOptions.Changed; begin PivotGrid.LayoutChanged; end; procedure TcxPivotGridCustomOptions.SetBoolValue( var AFieldValue: Boolean; AValue: Boolean); begin if AFieldValue <> AValue then begin AFieldValue := AValue; Changed; end; end; { TcxPivotGridOptionsBehavior } constructor TcxPivotGridOptionsBehavior.Create(AOwner: TcxCustomPivotGrid); begin inherited Create(AOwner); FieldHeaderHints := True; GroupHeaderHints := True; end; procedure TcxPivotGridOptionsBehavior.Assign(Source: TPersistent); begin if Source is TcxPivotGridOptionsBehavior then begin CellHints := TcxPivotGridOptionsBehavior(Source).CellHints; FieldHeaderHints := TcxPivotGridOptionsBehavior(Source).FieldHeaderHints; GroupHeaderHints := TcxPivotGridOptionsBehavior(Source).GroupHeaderHints; end else inherited Assign(Source); end; { TcxPivotGridOptionsCustomize } constructor TcxPivotGridOptionsCustomize.Create(AOwner: TcxCustomPivotGrid); begin inherited Create(AOwner); FFiltering := True; FHiding := True; FMoving := True; FQuickCustomization := True; FQuickPrefiltering := True; FSizing := True; FSorting := True; FilterResizable := True; end; procedure TcxPivotGridOptionsCustomize.Assign(Source: TPersistent); begin if Source is TcxPivotGridOptionsCustomize then begin FFiltering := TcxPivotGridOptionsCustomize(Source).FFiltering; FHiding := TcxPivotGridOptionsCustomize(Source).FHiding; FMoving := TcxPivotGridOptionsCustomize(Source).FMoving; FQuickCustomization := TcxPivotGridOptionsCustomize(Source).FQuickCustomization; FQuickPrefiltering := TcxPivotGridOptionsCustomize(Source).FQuickPrefiltering; FSizing := TcxPivotGridOptionsCustomize(Source).FSizing; FSorting := TcxPivotGridOptionsCustomize(Source).FSorting; FilterResizable := TcxPivotGridOptionsCustomize(Source).FilterResizable; end else inherited Assign(Source); end; procedure TcxPivotGridOptionsCustomize.SetFiltering(AValue: Boolean); begin if FFiltering <> AValue then begin FFiltering := AValue; PivotGrid.RefreshFilterableFieldsList; Changed; end; end; procedure TcxPivotGridOptionsCustomize.SetValue(AIndex: Integer; AValue: Boolean); begin case AIndex of 0: SetFiltering(AValue); 1: SetBoolValue(FHiding, AValue); 2: SetBoolValue(FMoving, AValue); 3: SetBoolValue(FQuickCustomization, AValue); 4: SetBoolValue(FSizing, AValue); 5: SetBoolValue(FSorting, AValue); 6: SetBoolValue(FFilterResizable, AValue); 7: SetBoolValue(FQuickPrefiltering, AValue); end; end; { TcxPivotGridOptionsView } constructor TcxPivotGridOptionsView.Create(AOwner: TcxCustomPivotGrid); begin inherited Create(AOwner); FColumnFields := True; FColumnGrandTotals := True; FColumnTotals := True; FDataFields := True; FDropArrowColor := cxPivotGridDropArrowColor; FFilterFields := True; FFilterSeparator := True; FFilterDropDownMaxItemCount := cxPivotGridDropDownMaxItemCount; FFilterDropDownWidth := cxPivotGridDropDownWidth; FPivotGrid := AOwner; FRowFields := True; FRowGrandTotals := True; FRowTotals := True; FGridLineColor := clDefault; FGridLines := pglBoth; end; procedure TcxPivotGridOptionsView.Assign(Source: TPersistent); var AOptions: TcxPivotGridOptionsView; begin if Source is TcxPivotGridOptionsView then begin AOptions := TcxPivotGridOptionsView(Source); FColumnFields := AOptions.ColumnFields; FColumnGrandTotals := AOptions.ColumnGrandTotals; FColumnTotals := AOptions.ColumnTotals; FDataFields := AOptions.DataFields; FDropArrowColor := AOptions.DropArrowColor; FFilterFields := AOptions.FilterFields; FFilterSeparator := AOptions.FilterSeparator; FFilterDropDownMaxItemCount := AOptions.FilterDropDownMaxItemCount; FFilterDropDownWidth := AOptions.FilterDropDownWidth; FGrandTotalsForSingleValues := AOptions.GrandTotalsForSingleValues; FGridLineColor := AOptions.GridLineColor; FGridLines := AOptions.GridLines; FMarkNarrowCells := AOptions.MarkNarrowCells; FRowFields := AOptions.RowFields; FRowGrandTotals := AOptions.RowGrandTotals; FRowTotals := AOptions.RowTotals; FTotalsForSingleValues := AOptions.TotalsForSingleValues; FColumnGrandTotalText := AOptions.ColumnGrandTotalText; FRowGrandTotalText := AOptions.RowGrandTotalText; FColumnTotalsLocation := AOptions.ColumnTotalsLocation; FRowTotalsLocation := AOptions.RowTotalsLocation; end; inherited Assign(Source); end; procedure TcxPivotGridOptionsView.Changed; begin PivotGrid.DataChanged; end; function TcxPivotGridOptionsView.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end; function TcxPivotGridOptionsView._AddRef: Integer; begin Result := -1; end; function TcxPivotGridOptionsView._Release: Integer; begin Result := -1; end; // IcxPivotGridSizableObject procedure TcxPivotGridOptionsView.ApplyBestFit; begin end; function TcxPivotGridOptionsView.CanResize: Boolean; begin Result := PivotGrid.OptionsCustomize.Sizing; end; function TcxPivotGridOptionsView.GetActualWidth: Integer; begin Result := GrandTotalWidth; if Result = 0 then Result := cxPivotGridDefaultFieldWidth; Result := Max(Result, GetMinWidth); end; function TcxPivotGridOptionsView.GetMinWidth: Integer; begin Result := cxPivotGridDefaultFieldMinWidth; end; procedure TcxPivotGridOptionsView.SetWidth(AValue: Integer); begin GrandTotalWidth := AValue; end; function TcxPivotGridOptionsView.GetScrollBars: TScrollStyle; begin Result := PivotGrid.ScrollBars; end; function TcxPivotGridOptionsView.GetTotalsLocation: TcxPivotGridTotalsLocation; begin if (FColumnTotalsLocation <> FRowTotalsLocation) then Result := tlCustom else Result := FColumnTotalsLocation; end; procedure TcxPivotGridOptionsView.SetColumnFields(AValue: Boolean); begin SetBoolValue(FColumnFields, AValue); end; procedure TcxPivotGridOptionsView.SetColumnGrandTotals(AValue: Boolean); begin SetBoolValue(FColumnGrandTotals, AValue); end; procedure TcxPivotGridOptionsView.SetColumnGrandTotalText(const AValue: string); begin if AnsiCompareStr(FColumnGrandTotalText, AValue) <> 0 then begin FColumnGrandTotalText := AValue; Changed; end; end; procedure TcxPivotGridOptionsView.SetColumnTotals(AValue: Boolean); begin SetBoolValue(FColumnTotals, AValue); end; procedure TcxPivotGridOptionsView.SetColumnTotalsLocation(AValue: TcxPivotGridTotalsLocation); begin if (FColumnTotalsLocation <> AValue) and (AValue <> tlCustom) then begin FColumnTotalsLocation := AValue; Changed; end; end; procedure TcxPivotGridOptionsView.SetDataFields(AValue: Boolean); begin SetBoolValue(FDataFields, AValue); end; procedure TcxPivotGridOptionsView.SetFilterDropDownMaxItemCount(AValue: Integer); begin AValue := Max(1, AValue); if FFilterDropDownMaxItemCount <> AValue then begin FFilterDropDownMaxItemCount := AValue; Changed; end; end; procedure TcxPivotGridOptionsView.SetFilterDropDownWidth(AValue: Integer); begin AValue := Max(AValue, cxPivotGridFilterPopupMinWidth); if FFilterDropDownWidth <> AValue then begin FFilterDropDownWidth := AValue; Changed; end; end; procedure TcxPivotGridOptionsView.SetFilterFields(AValue: Boolean); begin SetBoolValue(FFilterFields, AValue); end; procedure TcxPivotGridOptionsView.SetFilterSeparator(AValue: Boolean); begin SetBoolValue(FFilterSeparator, AValue); end; procedure TcxPivotGridOptionsView.SetGrandTotalWidth(AValue: Integer); begin AValue := Max(AValue, 0); if AValue > 0 then AValue := Max(AValue, cxPivotGridDefaultFieldMinWidth); if FGrandTotalWidth <> AValue then begin FGrandTotalWidth := AValue; Changed; end; end; procedure TcxPivotGridOptionsView.SetGrandTotalsForSingleValues(AValue: Boolean); begin SetBoolValue(FGrandTotalsForSingleValues, AValue); end; procedure TcxPivotGridOptionsView.SetGridLineColor(AValue: TColor); begin if FGridLineColor <> AValue then begin FGridLineColor := AValue; if GridLines <> pglNone then Changed; end; end; procedure TcxPivotGridOptionsView.SetGridLines(AValue: TcxPivotGridLines); begin if FGridLines <> AValue then begin FGridLines := AValue; Changed; end; end; procedure TcxPivotGridOptionsView.SetMarkNarrowCells(AValue: Boolean); begin SetBoolValue(FMarkNarrowCells, AValue); end; procedure TcxPivotGridOptionsView.SetRowFields(AValue: Boolean); begin SetBoolValue(FRowFields, AValue); end; procedure TcxPivotGridOptionsView.SetRowGrandTotals(AValue: Boolean); begin SetBoolValue(FRowGrandTotals, AValue); end; procedure TcxPivotGridOptionsView.SetRowGrandTotalText(const AValue: string); begin if AnsiCompareStr(FRowGrandTotalText, AValue) <> 0 then begin FRowGrandTotalText := AValue; Changed; end; end; procedure TcxPivotGridOptionsView.SetRowTotals(AValue: Boolean); begin SetBoolValue(FRowTotals, AValue); end; procedure TcxPivotGridOptionsView.SetRowTotalsLocation(AValue: TcxPivotGridTotalsLocation); begin if (FRowTotalsLocation <> AValue) and (AValue <> tlCustom) then begin FRowTotalsLocation := AValue; Changed; end; end; procedure TcxPivotGridOptionsView.SetScrollBars(AValue: TScrollStyle); begin if AValue <> ScrollBars then PivotGrid.ScrollBars := AValue; end; procedure TcxPivotGridOptionsView.SetTotalsForSingleValues(AValue: Boolean); begin SetBoolValue(FTotalsForSingleValues, AValue); end; procedure TcxPivotGridOptionsView.SetTotalsLocation( const AValue: TcxPivotGridTotalsLocation); begin if (AValue <> GetTotalsLocation) and (AValue <> tlCustom) then begin FColumnTotalsLocation := AValue; FRowTotalsLocation := AValue; Changed; end; end; { TcxPivotGridOptionsData } constructor TcxPivotGridOptionsData.Create(AOwner: TcxCustomPivotGrid); begin inherited Create(AOwner); FSaveExpanding := True; FVariationNullIgnore := True; end; procedure TcxPivotGridOptionsData.Assign(Source: TPersistent); begin if Source is TcxPivotGridOptionsData then with TcxPivotGridOptionsData(Source) do begin Self.FAnsiSort := AnsiSort; Self.FSummaryNullIgnore := SummaryNullIgnore; Self.FSaveExpanding := SaveExpanding; Self.FVariationNullIgnore := FVariationNullIgnore; end; inherited Assign(Source); end; procedure TcxPivotGridOptionsData.Changed; begin PivotGrid.DataChanged; end; function TcxPivotGridOptionsData.CompareAsString(const V1, V2: Variant): Integer; begin if AnsiSort then Result := AnsiCompareStr(V1, V2) else Result := VarCompare(V1, V2); end; procedure TcxPivotGridOptionsData.SetAnsiSort(AValue: Boolean); begin SetBoolValue(FAnsiSort, AValue); end; procedure TcxPivotGridOptionsData.SetCalculationBase( AValue: TcxPivotGridCalculationBaseType); begin if AValue <> FCalculationBase then begin FCalculationBase := AValue; Changed; end; end; procedure TcxPivotGridOptionsData.SetSummaryNullIgnore(AValue: Boolean); begin SetBoolValue(FSummaryNullIgnore, AValue); end; procedure TcxPivotGridOptionsData.SetVariationNullIgnore(AValue: Boolean); begin SetBoolValue(FVariationNullIgnore, AValue); end; { TcxPivotGridOptionsPrefilter } constructor TcxPivotGridOptionsPrefilter.Create(AOwner: TcxCustomPivotGrid); begin inherited; FCustomizeButton := True; FMRUItemsList := True; FMRUItemsListCount := 10; FPosition := pfpBottom; FVisible := pfvNonEmpty; end; procedure TcxPivotGridOptionsPrefilter.Assign(Source: TPersistent); var AOptions: TcxPivotGridOptionsPrefilter; begin if Source is TcxPivotGridOptionsPrefilter then begin AOptions := TcxPivotGridOptionsPrefilter(Source); CustomizeButton := AOptions.CustomizeButton; MRUItemsList := AOptions.MRUItemsList; MRUItemsListCount := AOptions.MRUItemsListCount; FMRUItemsListDropDownCount := AOptions.MRUItemsListDropDownCount; Position := AOptions.Position; Visible := AOptions.Visible; end; inherited Assign(Source); end; procedure TcxPivotGridOptionsPrefilter.SetCustomizeButton(AValue: Boolean); begin if FCustomizeButton <> AValue then begin FCustomizeButton := AValue; Changed; end; end; procedure TcxPivotGridOptionsPrefilter.SetMRUItemsList(AValue: Boolean); begin if FMRUItemsList <> AValue then begin FMRUItemsList := AValue; Changed; end; end; procedure TcxPivotGridOptionsPrefilter.SetMRUItemsListCount(AValue: Integer); begin AValue := Max(0, AValue); if FMRUItemsListCount <> AValue then begin FMRUItemsListCount := AValue; Changed; end; end; procedure TcxPivotGridOptionsPrefilter.SetMRUItemsListDropDownCount(AValue: Integer); begin AValue := Max(0, AValue); if FMRUItemsListDropDownCount <> AValue then begin FMRUItemsListDropDownCount := AValue; Changed; end; end; procedure TcxPivotGridOptionsPrefilter.SetPosition(AValue: TcxPivotGridPrefilterPosition); begin if FPosition <> AValue then begin FPosition := AValue; Changed; end; end; procedure TcxPivotGridOptionsPrefilter.SetVisible(AValue: TcxPivotGridPrefilterVisible); begin if FVisible <> AValue then begin FVisible := AValue; Changed; end; end; { TcxPivotGridOptionsSelection } constructor TcxPivotGridOptionsSelection.Create(AOwner: TcxCustomPivotGrid); begin inherited Create(AOwner); FIncludeCells := [osiCrossCells, osiGrandTotalCells, osiTotalCells]; end; procedure TcxPivotGridOptionsSelection.Assign(Source: TPersistent); begin if Source is TcxPivotGridOptionsSelection then begin HideFocusRect := TcxPivotGridOptionsSelection(Source).HideFocusRect; HideSelection := TcxPivotGridOptionsSelection(Source).HideSelection; IncludeCells := TcxPivotGridOptionsSelection(Source).IncludeCells; MultiSelect := TcxPivotGridOptionsSelection(Source).MultiSelect; end; inherited Assign(Source) end; procedure TcxPivotGridOptionsSelection.SetHideFocusRect(AValue: Boolean); begin SetBoolValue(FHideFocusRect, AValue); end; procedure TcxPivotGridOptionsSelection.SetHideSelection(AValue: Boolean); begin SetBoolValue(FHideSelection, AValue); end; procedure TcxPivotGridOptionsSelection.SetIncludeCells(const AValue: TcxPivotGridOptionsSelectionIncludes); begin if FIncludeCells <> AValue then begin FIncludeCells := AValue; Changed; end; end; procedure TcxPivotGridOptionsSelection.SetMultiSelect(AValue: Boolean); begin SetBoolValue(FMultiSelect, AValue); end; { TcxPivotGridViewData } constructor TcxPivotGridViewData.Create(AOwner: TcxCustomPivotGrid); begin FOwner := AOwner; FRows := TcxPivotGridViewDataItem.Create(nil, DataBuilder.Rows); FColumns := TcxPivotGridViewDataItem.Create(nil, DataBuilder.Columns); FBookMarkRow := -1; FSelection := TcxPivotGridViewDataSelection.Create(Self); FLimitValues := TcxPivotGridViewDataLimitValues.Create; end; destructor TcxPivotGridViewData.Destroy; begin FRows.Free; FColumns.Free; FLimitValues.Free; FreeAndNil(FSelection); inherited Destroy; end; function TcxPivotGridViewData.IsCellSelected(ARow, AColumn: Integer): Boolean; begin Result := (PivotGrid.IsDesigning and (ARow = 0) and (AColumn = 0)) or (not PivotGrid.IsDesigning and FSelection.IsCellSelected(AColumn, ARow) and CanCellSelect(ARow, AColumn)); end; function TcxPivotGridViewData.MakeSelectionVisible: Boolean; function GetPosValue(AValue, AIndex, APage: Integer): Integer; begin Result := AIndex; if AValue < AIndex then Result := AValue else while AValue - Result >= APage do Inc(Result); end; var ARowIndex, AColIndex: Integer; begin with FocusedCell do begin ARowIndex := GetPosValue(Y, RowIndex, RowsPerPage); AColIndex := GetPosValue(X, ColumnIndex, ColumnsPerPage); end; Result := (ARowIndex <> RowIndex) or (AColIndex <> ColumnIndex); if Result then begin FRowIndex := ARowIndex; FColumnIndex := AColIndex; PivotGrid.ViewChanged; end; end; procedure TcxPivotGridViewData.AdjustCellIndexes(var ARow, AColumn: Integer; AByMouse: Boolean = False); function ValueInRange(AValue, X1, X2: Integer): Boolean; begin Result := (AValue >= Min(X1, X2)) and (AValue <= Max(X1, X2)); end; procedure InnerCalculateDelta(APrevRow, APrevColumn: Integer; var DY, DX: Integer); begin APrevColumn := Min(Max(0, APrevColumn), ColumnCount - 1); DX := AColumn - APrevColumn; if DX > 0 then DX := 1 else if DX < 0 then DX := -1; APrevRow := Min(Max(0, APrevRow), RowCount - 1); DY := ARow - APrevRow; if DY > 0 then DY := 1 else if DY < 0 then DY := -1; end; procedure InnerAdjustCellIndexes(APrevRow, APrevColumn, DY, DX: Integer); var I, J: Integer; begin I := AColumn; J := ARow; while ValueInRange(J, ARow, APrevRow) and not CanCellSelect(J, I) do begin while ValueInRange(I, AColumn, APrevColumn) and not CanCellSelect(J, I) do begin if DX = 0 then Break; Dec(I, DX); end; if not ValueInRange(I, AColumn, APrevColumn) then I := AColumn; if DY = 0 then Break; if not CanCellSelect(J, I) then Dec(J, DY); end; if not ValueInRange(J, ARow, APrevRow) then J := ARow; if CanCellSelect(J, I) then begin ARow := J; AColumn := I; end; end; var DY, DX: Integer; P: TPoint; begin AColumn := Min(Max(0, AColumn), ColumnCount - 1); ARow := Min(Max(0, ARow), RowCount - 1); P := FocusedCell; if not CanCellSelect(ARow, AColumn) then begin InnerCalculateDelta(P.Y, P.X, DY, DX); if ((DX = 0) or (DY = 0)) and not AByMouse then begin if (DX > 0) then InnerAdjustCellIndexes(ARow, ColumnCount - 1, 0, -DX) else if (DX < 0) then InnerAdjustCellIndexes(ARow, 0, 0, -DX) else if (DY > 0) then InnerAdjustCellIndexes(RowCount - 1, AColumn, -DY, 0) else if (DY < 0) then InnerAdjustCellIndexes(0, AColumn, -DY, 0); end; if not CanCellSelect(ARow, AColumn) then InnerAdjustCellIndexes(P.Y, P.X, DY, DX); end; end; function TcxPivotGridViewData.AdjustCellIndexesPoint(const P: TPoint; AByMouse: Boolean = False): TPoint; var AColumn, ARow: Integer; begin AColumn := P.X; ARow := P.Y; AdjustCellIndexes(ARow, AColumn, AByMouse); Result := Point(AColumn, ARow); end; procedure TcxPivotGridViewData.Calculate; begin Clear; ProduceColumns; ProduceRows; ValidateIndexes; FCalculatedLimitValues := False; end; function TcxPivotGridViewData.CalculateDataWidth(AField: TcxPivotGridField): Integer; var ARow, AColumn: TcxPivotGridViewDataItem; APrevCell: TcxPivotGridCrossCellSummary; AFakeCell: TcxPivotGridDataCellViewInfo; begin Result := 0; if not AField.Visible then Exit; AFakeCell := TcxPivotGridDataCellViewInfo.Create(PivotGrid.LookAndFeelPainter, cxSimpleRect, cxSimpleRect, PivotGrid.ViewInfo.FViewParams); try ARow := Rows[0]; while ARow <> nil do begin APrevCell := nil; AColumn := Columns[0]; while AColumn <> nil do begin AFakeCell.Initialize(ARow, AColumn, AField); AFakeCell.CalculateVisibleInfo; if AFakeCell.CellSummary <> APrevCell then begin APrevCell := AFakeCell.CellSummary; if APrevCell.DataField = AField then begin AFakeCell.FViewParams := PivotGrid.Styles.GetContentParams(AFakeCell); Result := Max(Result, AFakeCell.MeasureWidth); end; end; AColumn := AColumn.GetNextVisible; end; ARow := ARow.GetNextVisible; end; finally AFakeCell.Free; end; end; procedure TcxPivotGridViewData.CalculateDataFieldInfo( var AFieldIndex: Integer; var AFields: TcxPivotGridGroupItem; AcceptedArea: TcxPivotGridDataFieldArea); begin AFieldIndex := MaxInt; AFields := nil; with PivotGrid.OptionsDataField do begin if DataBuilder.DataFields.Count <= 1 then Exit; if (Area = AcceptedArea) or ((Area = dfaNone) and (AcceptedArea = dfaColumn)) then begin if (Area <> dfaNone) and (AreaIndex >= 0) then AFieldIndex := PivotGrid.OptionsDataField.AreaIndex; AFields := PivotGrid.DataBuilder.Data; if AcceptedArea = dfaColumn then AFieldIndex := Min(AFieldIndex, DataBuilder.ColumnFields.Count) else AFieldIndex := Min(AFieldIndex, DataBuilder.RowFields.Count); end; end; end; procedure TcxPivotGridViewData.CalculateLimitValues; function GetRootParent(AItem: TcxPivotGridViewDataItem): TcxPivotGridViewDataItem; begin if AItem.Parent <> nil then Result := GetRootParent(AItem.Parent) else Result := AItem; end; procedure InnerCalculateForItem(AItem, ARootCrossItem: TcxPivotGridViewDataItem); var I: Integer; V: Variant; ACrossCell: TcxPivotGridCrossCell; ADataField: TcxPivotGridField; begin if ARootCrossItem.IsTotal or ARootCrossItem.IsGrandTotal then Exit; for I := 0 to ARootCrossItem.ItemCount - 1 do begin if ARootCrossItem.Items[I].IsTotal or ARootCrossItem.Items[I].IsGrandTotal then Continue; if ARootCrossItem.Items[I].ItemCount > 0 then InnerCalculateForItem(AItem, ARootCrossItem.Items[I]) else begin V := Null; ADataField := nil; if AItem.IsDataField then ACrossCell := ARootCrossItem.Items[I].GroupItem.GetCellByCrossItem(AItem.GetGroupItem(ADataField)) else if ARootCrossItem.Items[I].IsDataField then ACrossCell := AItem.GroupItem.GetCellByCrossItem(ARootCrossItem.Items[I].GetGroupItem(ADataField)) else ACrossCell := AItem.GetGroupItem(ADataField).GetCellByCrossItem(ARootCrossItem.Items[I].GroupItem); if ACrossCell <> nil then begin if (ADataField = nil) and (DataBuilder.DataFields.Count = 1) then ADataField := DataBuilder.DataFields[0]; if ADataField <> nil then V := ACrossCell.GetSummaryByField(ADataField, ADataField.SummaryType); end; if VarIsNumericEx(V) then AItem.LimitValues.Calculate(ADataField, V); end; end; end; procedure InnerCalculateLimitValues(AItem, ARootCrossItem: TcxPivotGridViewDataItem); var I: Integer; begin if AItem.ItemCount = 0 then InnerCalculateForItem(AItem, ARootCrossItem) else for I := 0 to AItem.ItemCount - 1 do begin if AItem.Items[I].IsTotal or AItem.Items[I].IsGrandTotal then Continue; AItem.LimitValues.Clear; InnerCalculateLimitValues(AItem.Items[I], ARootCrossItem); end; end; var I, J: Integer; begin if not NeedCalculateLimitValues then Exit; InnerCalculateLimitValues(GetRootParent(Columns[0]), GetRootParent(Rows[0])); InnerCalculateLimitValues(GetRootParent(Rows[0]), GetRootParent(Columns[0])); LimitValues.Clear; for I := 0 to ColumnCount - 1 do for J := 0 to Columns[I].LimitValues.Count - 1 do with Columns[I].LimitValues[J] do begin LimitValues.Calculate(Field, MaxValue); LimitValues.Calculate(Field, MinValue); end; FCalculatedLimitValues := True; end; procedure TcxPivotGridViewData.Clear; begin FRows.DeleteChildren; FColumns.DeleteChildren; end; function TcxPivotGridViewData.CanCellSelect(ARow, AColumn: Integer): Boolean; var AIsTotal: Boolean; AIsGrandTotal: Boolean; AIsCell: Boolean; begin Result := (ARow >= 0) and (ARow < RowCount) and (AColumn >= 0) and (AColumn < ColumnCount); if not Result then Exit; AIsGrandTotal := Columns[AColumn].IsGrandTotal or Rows[ARow].IsGrandTotal; AIsTotal := not AIsGrandTotal and ((Columns[AColumn].IsTotalItem and not Columns[AColumn].IsGrandTotal) or (Rows[ARow].IsTotalItem and not Rows[ARow].IsGrandTotal)); AIsCell := not AIsTotal and not AIsGrandTotal; Result := (AIsTotal and (osiTotalCells in OptionsSelection.IncludeCells)) or (AIsGrandTotal and (osiGrandTotalCells in OptionsSelection.IncludeCells)) or (AIsCell and (osiCrossCells in OptionsSelection.IncludeCells)); end; procedure TcxPivotGridViewData.DoNextPage(AGoForward: Boolean); begin if AGoForward then RowIndex := RowIndex + RowsPerPage else RowIndex := RowIndex - RowsPerPage; end; function TcxPivotGridViewData.GetItemByIndex(AList: TcxPivotGridViewDataItem; AIndex, ACount: Integer): TcxPivotGridViewDataItem; // todo: not optimal recursive algoritm function DoFind(AItem: TcxPivotGridViewDataItem; var AFoundItem: TcxPivotGridViewDataItem): Boolean; var I: Integer; {$IFDEF TESTING} _V: Variant; {$ENDIF} begin Result := False; {$IFDEF TESTING} _V := AItem.Value; {$ENDIF} if AItem.VisibleIndex = AIndex then begin AFoundItem := AItem; Result := True; end else if AItem.ItemCount > 0 then begin for I := 0 to AItem.ItemCount - 1 do begin Result := DoFind(AItem.Items[I], AFoundItem); if Result then Break; end; end; end; begin if not PivotGrid.ViewInfo.IsPrinting then PivotGrid.CheckChanges; if not DoFind(AList, Result) then Result := nil; end; procedure TcxPivotGridViewData.HeaderCellSelect(ADataItem: TcxPivotGridViewDataItem; AShift: TShiftState); var R: TRect; ALeft, ARight: Integer; begin ALeft := ADataItem.GetChildLeftVisibleIndex; ARight := ADataItem.GetChildRightVisibleIndex; R := AnchorCells; if (ADataItem.IsDataField and (ADataItem.Parent.GroupItem is TcxPivotGridColumnItem)) or (ADataItem.GroupItem is TcxPivotGridColumnItem) then begin if Selection.MultiSelect then R.Top := 0 else R.Top := FocusedCell.Y; if AnchorCells.Left > ALeft then R.Left := ALeft; if AnchorCells.Right < ARight then R.Right := ARight; Selection.InnerSetFocusedCell(Point(ALeft, R.Top)); end else begin if Selection.MultiSelect then R.Left := 0 else R.Left := FocusedCell.X; if AnchorCells.Top > ALeft then R.Top := ALeft; if AnchorCells.Bottom < ARight then R.Bottom := ARight; Selection.InnerSetFocusedCell(Point(R.Left, ALeft)); end; if AnchorCells.Top = -1 then R.Bottom := RowCount - 1; if AnchorCells.Left = -1 then R.Right := ColumnCount - 1; ValidateSelection(R); Selection.ChangeSelection(R, AShift); end; type TcxPivotGridItemsProducer = class protected DataLevel: Integer; DataFields: TcxPivotGridGroupItem; Dest: TcxPivotGridViewDataItem; ItemsCount: Integer; Source: TcxPivotGridGroupItem; GrandTotals: Boolean; GrandTotalsForSingleValues: Boolean; Totals: Boolean; TotalsLocation: TcxPivotGridTotalsLocation; TotalsForSingleValues: Boolean; VariationFieldsOnly: Boolean; procedure AddChildren(AItem: TcxPivotGridGroupItem; ALevel: Integer; AParent: TcxPivotGridViewDataItem); virtual; function AddData(AItem: TcxPivotGridGroupItem; ALevel: Integer; AParent: TcxPivotGridViewDataItem): Boolean; virtual; procedure AddTotals(AItem: TcxPivotGridGroupItem; ALevel: Integer; AParent: TcxPivotGridViewDataItem); virtual; procedure DeleteEmptyItems; function IsVariationFieldsOnly: Boolean; function IncCount: Integer; procedure ProcessItem(AItem: TcxPivotGridGroupItem; ALevel: Integer; AParent: TcxPivotGridViewDataItem); virtual; function Produce: Integer; virtual; function SkipFieldProcessing(AParent: TcxPivotGridViewDataItem; AField: TcxPivotGridField): Boolean; function TotalNeeded(AVisible, ASingleVisible: Boolean; AItem: TcxPivotGridGroupItem): Boolean; public constructor Create(ASource: TcxPivotGridGroupItem; ADest: TcxPivotGridViewDataItem; ALocation: TcxPivotGridTotalsLocation; ATotals, ASingleTotals, AGrandTotals, ASingleGrandTotals: Boolean); end; constructor TcxPivotGridItemsProducer.Create(ASource: TcxPivotGridGroupItem; ADest: TcxPivotGridViewDataItem; ALocation: TcxPivotGridTotalsLocation; ATotals, ASingleTotals, AGrandTotals, ASingleGrandTotals: Boolean); begin Dest := ADest; Source := ASource; TotalsLocation := ALocation; Totals := ATotals; TotalsForSingleValues := ASingleTotals; GrandTotals := AGrandTotals; GrandTotalsForSingleValues := ASingleGrandTotals; DataLevel := MaxInt; end; procedure TcxPivotGridItemsProducer.AddChildren(AItem: TcxPivotGridGroupItem; ALevel: Integer; AParent: TcxPivotGridViewDataItem); var I: Integer; begin if (ALevel < 0) and (AItem.ItemCount = 0) and not AItem.HasChildren then Exit; if ALevel >= 0 then AParent := AParent.Add(AItem); if AItem.Expanded and (AItem.ItemCount > 0) then begin if not AddData(AItem, ALevel + 1, AParent) then begin for I := 0 to AItem.ItemCount - 1 do ProcessItem(AItem.Items[I], ALevel + 1, AParent) end end else begin if not AddData(AItem, ALevel + 1, AParent) then AParent.FVisibleIndex := IncCount; end; end; function TcxPivotGridItemsProducer.AddData(AItem: TcxPivotGridGroupItem; ALevel: Integer; AParent: TcxPivotGridViewDataItem): Boolean; var I, J: Integer; ADataItem: TcxPivotGridViewDataItem; V: Variant; begin Result := (ALevel = DataLevel) or (AItem.IsCollapsed and (DataLevel <> MaxInt) and (DataLevel > ALevel)); if Result then begin for I := 0 to DataFields.ItemCount - 1 do begin if SkipFieldProcessing(AParent, DataFields.Items[I].Field) then Continue; ADataItem := AParent.Add(DataFields.Items[I]); ADataItem.FIsDataField := True; V := ADataItem.Value; if AItem.Expanded and not AParent.IsTotal then for J := 0 to AItem.ItemCount - 1 do ProcessItem(AItem.Items[J], ALevel + 1, ADataItem) else ADataItem.FVisibleIndex := IncCount; end; end; end; procedure TcxPivotGridItemsProducer.AddTotals(AItem: TcxPivotGridGroupItem; ALevel: Integer; AParent: TcxPivotGridViewDataItem); var I: Integer; ATotal: TcxPivotGridViewDataItem; begin if ((ALevel = -1) and TotalNeeded(GrandTotals, GrandTotalsForSingleValues, AItem)) or ((ALevel >= 0) and TotalNeeded(Totals, TotalsForSingleValues, AItem)) then begin for I := 0 to AItem.TotalsCount - 1 do begin ATotal := AParent.AddTotal(AItem, I); if (DataLevel <> MaxInt) and (ALevel < DataLevel) then AddData(AItem, DataLevel, ATotal) else ATotal.FVisibleIndex := IncCount; end; end; end; procedure TcxPivotGridItemsProducer.DeleteEmptyItems; procedure ProcessItems(AItem: TcxPivotGridViewDataItem); var I: Integer; begin if (AItem.ItemCount = 0) and (AItem.VisibleIndex < 0) then begin if AItem.Parent <> nil then AItem.Parent.FItems.Remove(AItem); AItem.Free; end else begin for I := AItem.ItemCount - 1 downto 0 do ProcessItems(AItem.Items[I]); for I := 0 to AItem.ItemCount - 1 do AItem.Items[I].FIndex := I; end; end; begin ProcessItems(Dest); end; function TcxPivotGridItemsProducer.IsVariationFieldsOnly; var I: Integer; begin Result := DataFields <> nil; if Result then for I := 0 to DataFields.ItemCount - 1 do Result := Result and DataFields.Items[I].Field.HasSummaryVariation; end; function TcxPivotGridItemsProducer.IncCount: Integer; begin Result := ItemsCount; Inc(ItemsCount); end; procedure TcxPivotGridItemsProducer.ProcessItem(AItem: TcxPivotGridGroupItem; ALevel: Integer; AParent: TcxPivotGridViewDataItem); begin if TotalsLocation = tlNear then begin AddTotals(AItem, ALevel, AParent); AddChildren(AItem, ALevel, AParent); end else begin AddChildren(AItem, ALevel, AParent); AddTotals(AItem, ALevel, AParent); end; end; function TcxPivotGridItemsProducer.Produce: Integer; begin Dest.DeleteChildren; VariationFieldsOnly := IsVariationFieldsOnly; ProcessItem(Source, -1, Dest); DeleteEmptyItems; Result := ItemsCount; end; function TcxPivotGridItemsProducer.SkipFieldProcessing( AParent: TcxPivotGridViewDataItem; AField: TcxPivotGridField): Boolean; begin Result := (AField.SummaryVariation in [svAbsolute, svPercent]) and (AParent.IsGrandTotal or (AParent.Index = 0) or ((AParent.Index = 1) and AParent.IsTotal)); if Result and AParent.IsGrandTotal then Result := (Source.ItemCount > 0) or not VariationFieldsOnly; Result := Result or (not AParent.IsGrandTotal and (AField.DataVisibility = dvGrandTotalCells)) or (AParent.IsGrandTotal and (AField.DataVisibility = dvCrossAndTotalCells)); end; function TcxPivotGridItemsProducer.TotalNeeded( AVisible, ASingleVisible: Boolean; AItem: TcxPivotGridGroupItem): Boolean; begin Result := AVisible and AItem.Expanded and (AItem.ItemCount > 0) and (ASingleVisible or (AItem.ItemCount > 1)); if not Result then Result := (AItem.Level = -1) and (AItem.ItemCount = 0); end; procedure TcxPivotGridViewData.PopulateSelectedCells(ACells: TList); var ACol, ARow: Integer; begin for ACol := 0 to ColumnCount - 1 do for ARow := 0 to RowCount - 1 do if IsCellSelected(ARow, ACol) then ACells.Add(Cells[ARow, ACol].Owner); end; procedure TcxPivotGridViewData.ProduceColumns; var AProducer: TcxPivotGridItemsProducer; begin with OptionsView do begin AProducer := TcxPivotGridItemsProducer.Create(DataBuilder.Columns, FColumns, ColumnTotalsLocation, ColumnTotals, TotalsForSingleValues, ColumnGrandTotals, GrandTotalsForSingleValues); end; try CalculateDataFieldInfo(AProducer.DataLevel, AProducer.DataFields, dfaColumn); FColumnCount := AProducer.Produce; finally AProducer.Free; end; end; procedure TcxPivotGridViewData.ProduceRows; var AProducer: TcxPivotGridItemsProducer; begin with OptionsView do begin AProducer := TcxPivotGridItemsProducer.Create(DataBuilder.Rows, FRows, RowTotalsLocation, RowTotals, TotalsForSingleValues, RowGrandTotals, GrandTotalsForSingleValues); end; try CalculateDataFieldInfo(AProducer.DataLevel, AProducer.DataFields, dfaRow); FRowCount := AProducer.Produce; finally AProducer.Free; end; end; procedure TcxPivotGridViewData.Scroll( AScrollCode: TScrollCode; AItem: TcxPivotGridViewDataItem; APage, AMax, ASize, AScrollPos: Integer; var APos: Integer); begin case AScrollCode of scLineUp, scLineDown: Inc(APos, Byte(AScrollCode) * 2 - 1); scPageUp: while ASize > 0 do begin AItem := AItem.GetPrevVisible; if AItem = nil then Break; Dec(ASize, AItem.Size); if ASize >= 0 then Dec(APos); end; scPosition: APos := AScrollPos; scPageDown: Inc(APos, APage); scTop: APos := 0; scBottom: APos := AMax; end; APos := Max(0, Min(APos, AMax)); end; function TcxPivotGridViewData.ScrollColumns( AScrollCode: TScrollCode; var AScrollPos: Integer): Boolean; var APos: Integer; begin APos := FColumnIndex; Scroll(AScrollCode, Columns[ColumnIndex], ColumnsPerPage, ColumnCount - 1, cxRectWidth(PivotGrid.ViewInfo.DataCellsBounds), AScrollPos, FColumnIndex); PivotGrid.ViewInfo.Calculate; AScrollPos := FColumnIndex; Result := FColumnIndex <> APos; end; function TcxPivotGridViewData.ScrollRows( AScrollCode: TScrollCode; var AScrollPos: Integer): Boolean; var APos: Integer; begin APos := FRowIndex; Scroll(AScrollCode, Rows[RowIndex], RowsPerPage, RowCount - 1, cxRectHeight(PivotGrid.ViewInfo.DataCellsBounds), AScrollPos, FRowIndex); PivotGrid.ViewInfo.Calculate; AScrollPos := FRowIndex; Result := FRowIndex <> APos; end; procedure TcxPivotGridViewData.ValidateIndexes; begin if FColumnIndex >= FColumnCount then FColumnIndex := FColumnCount - 1; if FRowIndex >= FRowCount then FRowIndex := FRowCount - 1; end; procedure TcxPivotGridViewData.ValidateSelection(var ASelection: TRect); begin cxRectAdjust(ASelection); ASelection.Left := Min(Max(0, ASelection.Left), ColumnCount - 1); ASelection.Top := Min(Max(0, ASelection.Top), RowCount - 1); if OptionsSelection.MultiSelect then begin ASelection.Right := Min(Max(0, ASelection.Right), ColumnCount - 1); ASelection.Bottom := Min(Max(0, ASelection.Bottom), RowCount - 1); end else ASelection.BottomRight := ASelection.TopLeft; end; function TcxPivotGridViewData.GetAnchorCells: TRect; begin Result := Selection.AnchorCells; end; function TcxPivotGridViewData.GetCell( ARow, AColumn: Integer): TcxPivotGridCrossCellSummary; var ADataField: TcxPivotGridField; ACrossCell: TcxPivotGridCrossCell; ARowGroup, AColGroup: TcxPivotGridGroupItem; begin ADataField := nil; ARowGroup := Rows[ARow].GetGroupItem(ADataField); AColGroup := Columns[AColumn].GetGroupItem(ADataField); if DataBuilder.DataFields.Count = 1 then ADataField := DataBuilder.DataFields[0]; if (ADataField = nil) and (DataBuilder.DataFields.Count > 0) then ADataField := DataBuilder.DataFields[0]; ACrossCell := ARowGroup.GetCellByCrossItem(AColGroup); if ADataField = nil then Result := nil else Result := ACrossCell.SummaryCells[ADataField.SummaryIndex]; end; function TcxPivotGridViewData.GetCellAsText(ARow, AColumn: Integer): string; var AField: TcxPivotGridField; AFakeCell: TcxPivotGridDataCellViewInfo; ARowItem, AColumnItem: TcxPivotGridViewDataItem; begin Result := ''; ARowItem := Rows[ARow]; AColumnItem := Columns[AColumn]; if PivotGrid.OptionsDataField.Area = dfaRow then AField := PivotGrid.ViewInfo.GetDataFieldFromViewData(ARowItem) else AField := PivotGrid.ViewInfo.GetDataFieldFromViewData(AColumnItem); AFakeCell := TcxPivotGridDataCellViewInfo.Create(PivotGrid.LookAndFeelPainter, cxSimpleRect, cxSimpleRect, PivotGrid.ViewInfo.FViewParams); try AFakeCell.Initialize(ARowItem, AColumnItem, AField); AFakeCell.CalculateVisibleInfo; Result := AFakeCell.DisplayText; finally AFakeCell.Free; end; end; function TcxPivotGridViewData.GetColumn( AIndex: Integer): TcxPivotGridViewDataItem; begin Result := GetItemByIndex(FColumns, AIndex, FColumnCount); end; function TcxPivotGridViewData.GetDataBuilder: TcxPivotGridDataBuilder; begin Result := PivotGrid.DataBuilder; end; function TcxPivotGridViewData.GetFocusedCell: TPoint; begin Result := Selection.FFocusedCell; end; function TcxPivotGridViewData.GetOptionsSelection: TcxPivotGridOptionsSelection; begin Result := PivotGrid.OptionsSelection; end; function TcxPivotGridViewData.GetOptionsView: TcxPivotGridOptionsView; begin Result := PivotGrid.OptionsView; end; function TcxPivotGridViewData.GetRow( AIndex: Integer): TcxPivotGridViewDataItem; begin Result := GetItemByIndex(FRows, AIndex, FRowCount); end; function TcxPivotGridViewData.NeedCalculateLimitValues: Boolean; function NeedCalculateLimitValuesForStyles(AStyles: TcxPivotGridCustomStyles): Boolean; begin with AStyles do Result := Assigned(OnGetContentStyle) or (ColumnMaximumValue <> nil) or (ColumnMinimumValue <> nil) or (RowMaximumValue <> nil) or (RowMinimumValue <> nil) or (MaximumValue <> nil) or (MinimumValue <> nil); end; var I: Integer; begin Result := not FCalculatedLimitValues and (ColumnCount > 0) and (RowCount > 0) and (DataBuilder.DataFields.Count > 0); if Result then begin Result := NeedCalculateLimitValuesForStyles(PivotGrid.Styles) or Assigned(PivotGrid.OnCustomDrawCell); if not Result then for I := 0 to DataBuilder.DataFields.Count - 1 do begin Result := NeedCalculateLimitValuesForStyles(DataBuilder.DataFields[I].Styles); if Result then Break; end; end; end; procedure TcxPivotGridViewData.SetAnchorCells(const AValue: TRect); begin Selection.AnchorCells := AValue; end; procedure TcxPivotGridViewData.SetColumnIndex(AIndex: Integer); begin AIndex := Min(FColumnCount - 1, Max(0, AIndex)); if AIndex <> FColumnIndex then begin FColumnIndex := AIndex; PivotGrid.ViewChanged; end; end; procedure TcxPivotGridViewData.SetFocusedCell(const APoint: TPoint); begin Selection.FocusedCell := AdjustCellIndexesPoint(APoint); end; procedure TcxPivotGridViewData.SetRowIndex(AIndex: Integer); begin AIndex := Min(FRowCount - 1, Max(0, AIndex)); if AIndex <> FRowIndex then begin FRowIndex := AIndex; PivotGrid.ViewChanged; end; end; { TcxPivotGridFieldHeaderMenu } constructor TcxPivotGridFieldHeaderMenu.Create(AOwner: TcxPivotGridPopupMenus); begin inherited Create(AOwner); Items := [fpmiHide, fpmiOrder, fpmiFieldList]; end; procedure TcxPivotGridFieldHeaderMenu.AssignValues( ASource: TcxPivotGridCustomPopupMenu); begin inherited AssignValues(ASource); Items := TcxPivotGridFieldHeaderMenu(ASource).Items; end; procedure TcxPivotGridFieldHeaderMenu.CreateItems; var AItem: TMenuItem; AFirst, APrev, ANext, ALast, AIndex: Integer; begin inherited CreateItems; if fpmiHide in Items then begin CreateSubItem(Root, cxGetResourceString(@scxHide), pgcmHide, (Field <> nil) and PivotGrid.OptionsCustomize.Hiding); CreateSeparator(Root); end; // order if (fpmiOrder in Items) and ((Field = nil) or (Field.GroupIndex <= 0)) then begin AItem := CreateSubItem(Root, cxGetResourceString(@scxOrder), -1); AIndex := FieldViewInfo.AreaIndex; GetIndexes(AFirst, APrev, ANext, ALast); CreateSubItem(AItem, cxGetResourceString(@scxMoveToBeginning), pgcmMoveToBeginning, (AFirst < AIndex) and PivotGrid.OptionsCustomize.Moving); CreateSubItem(AItem, cxGetResourceString(@scxMoveToEnd), pgcmMoveToEnd, (ALast > AIndex) and PivotGrid.OptionsCustomize.Moving); CreateSubItem(AItem, cxGetResourceString(@scxMoveToLeft), pgcmMoveToLeft, (AFirst < AIndex) and PivotGrid.OptionsCustomize.Moving); CreateSubItem(AItem, cxGetResourceString(@scxMoveToRight), pgcmMoveToRight, (ALast > AIndex) and PivotGrid.OptionsCustomize.Moving); end; // field list if fpmiFieldList in Items then begin CreateSeparator(Root); with PivotGrid.Customization do begin CreateSubItem(Root, cxGetResourceString(scxCustomization[Visible]), CustomizationCommand[Visible], PivotGrid.OptionsCustomize.QuickCustomization); end; end; end; procedure TcxPivotGridFieldHeaderMenu.DoExecute(ACommand: Integer); var AIndexes: array[0..3] of Integer; begin case ACommand of pgcmHide: if Field.Group <> nil then Field.Group.Visible := False else Field.Visible := False; pgcmMoveToBeginning..pgcmMoveToRight: begin GetIndexes(AIndexes[0], AIndexes[2], AIndexes[3], AIndexes[1]); if Field <> nil then Field.AreaIndex := AIndexes[ACommand - pgcmMoveToBeginning] else OptionsDataField.AreaIndex := AIndexes[ACommand - pgcmMoveToBeginning]; end; else inherited DoExecute(ACommand); end; end; procedure TcxPivotGridFieldHeaderMenu.GetIndexes( var AStart, APrev, ANext, AFinish: Integer); function GetCell(AIndex: Integer): TcxPivotGridFieldHeaderCellViewInfo; begin Result := TcxPivotGridFieldHeaderCellViewInfo(FieldHeaders[AIndex]); end; function SetPosValue(var APos: Integer; const AValue, ADefValue: Integer): Integer; begin Result := AValue; if APos = ADefValue then APos := AValue; end; procedure IncIndex(var AIndex: Integer; AInc: Integer); begin Inc(AIndex, AInc); if (AIndex > 0) and (AIndex < FieldHeaders.Count) and (GetCell(AIndex).Group <> nil) then Inc(AIndex, AInc * (GetCell(AIndex).Group.VisibleCount - 1)); end; var AIndex, AAreaIndex, ACurIndex: Integer; begin AAreaIndex := FieldViewInfo.AreaIndex; APrev := AAreaIndex; ANext := AAreaIndex; AIndex := FieldHeaders.IndexOf(FieldViewInfo); ACurIndex := AIndex; while (ACurIndex >= 0) and (GetCell(ACurIndex).Area = FieldViewInfo.Area) do begin AStart := SetPosValue(APrev, GetCell(ACurIndex).AreaIndex, AAreaIndex); IncIndex(ACurIndex, -1); end; ACurIndex := AIndex; while (ACurIndex < FieldHeaders.Count) and (GetCell(ACurIndex).Area = FieldViewInfo.Area) do begin AFinish := SetPosValue(ANext, GetCell(ACurIndex).AreaIndex, AAreaIndex); IncIndex(ACurIndex, 1); end; end; function TcxPivotGridFieldHeaderMenu.GetFieldHeaders: TcxPivotGridCells; begin Result := PivotGrid.ViewInfo.FieldHeaders; end; function TcxPivotGridFieldHeaderMenu.GetFieldViewInfo: TcxPivotGridFieldHeaderCellViewInfo; begin if Field <> nil then Result := Field.ViewInfo else Result := PivotGrid.OptionsDataField.ViewInfo; end; function TcxPivotGridFieldHeaderMenu.GetOptionsDataField: TcxPivotGridOptionsDataField; begin Result := PivotGrid.OptionsDataField; end; function TcxPivotGridFieldHeaderMenu.IsItemsStored: Boolean; begin Result := Items <> [fpmiHide, fpmiOrder, fpmiFieldList]; end; { TcxPivotGridGroupValueMenu } constructor TcxPivotGridGroupValueMenu.Create(AOwner: TcxPivotGridPopupMenus); begin inherited Create(AOwner); FItems := [vpmiExpandCollapse..vpmiCollapseAll]; end; procedure TcxPivotGridGroupValueMenu.AssignValues( ASource: TcxPivotGridCustomPopupMenu); begin if ASource is TcxPivotGridGroupValueMenu then Items := TcxPivotGridGroupValueMenu(ASource).Items; inherited AssignValues(ASource); end; procedure TcxPivotGridGroupValueMenu.CreateItems; const ExpandCollapse: array[Boolean] of Integer = (pgcmExpand, pgcmCollapse); begin inherited CreateItems; if vpmiExpandCollapse in Items then begin CreateSubItem(Root, cxGetResourceString( scxExpandCollapse[GroupItem.Expanded]), ExpandCollapse[GroupItem.Expanded]); CreateSeparator(Root); end; if vpmiExpandAll in Items then CreateSubItem(Root, cxGetResourceString(@scxExpandAll), pgcmExpandAll); if vpmiCollapseAll in Items then CreateSubItem(Root, cxGetResourceString(@scxCollapseAll), pgcmCollapseAll); end; procedure TcxPivotGridGroupValueMenu.DoExecute(ACommand: Integer); var AItem: TcxPivotGridGroupItem; begin inherited DoExecute(ACommand); case ACommand of pgcmExpand, pgcmCollapse: GroupItem.Expanded := not GroupItem.Expanded; pgcmExpandAll, pgcmCollapseAll: begin AItem := GroupItem; while AItem.Parent <> nil do AItem := AItem.Parent; AItem.SetFieldExpanding(GroupItem.Field, ACommand = pgcmExpandAll); end; else Exit; end; PivotGrid.LayoutChanged; end; function TcxPivotGridGroupValueMenu.IsItemsStored: Boolean; begin Result := Items <> [vpmiExpandCollapse..vpmiCollapseAll]; end; { TcxPivotGridHeaderAreaMenu } procedure TcxPivotGridHeaderAreaMenu.CreateItems; begin inherited CreateItems; CreateSeparator(Root); with PivotGrid.Customization do CreateSubItem(Root, cxGetResourceString(scxCustomization[Visible]), CustomizationCommand[Visible], PivotGrid.OptionsCustomize.QuickCustomization); if PivotGrid.IsPrefilterEnabled then CreateSubItem(Root, cxGetResourceString(@scxShowPrefilterDialog), pgcmShowPrefilterDialog, PivotGrid.OptionsCustomize.QuickPrefiltering); end; procedure TcxPivotGridHeaderAreaMenu.DoExecute(ACommand: Integer); begin case ACommand of pgcmShowPrefilterDialog: PivotGrid.ShowPrefilterDialog; else inherited DoExecute(ACommand); end; end; { TcxPivotGridPopupMenus } constructor TcxPivotGridPopupMenus.Create(AOwner: TcxCustomPivotGrid); begin inherited Create(AOwner); CreateMenus; end; destructor TcxPivotGridPopupMenus.Destroy; begin DestroyMenus; inherited Destroy; end; procedure TcxPivotGridPopupMenus.Assign(Source: TPersistent); begin if Source is TcxPivotGridPopupMenus then begin FieldHeaderMenu := TcxPivotGridPopupMenus(Source).FieldHeaderMenu; GroupValueMenu := TcxPivotGridPopupMenus(Source).GroupValueMenu; HeaderAreaMenu := TcxPivotGridPopupMenus(Source).HeaderAreaMenu; end; inherited Assign(Source); end; procedure TcxPivotGridPopupMenus.DoOnClick( AItem: TMenuItem; var AHandled: Boolean); begin AHandled := False; if Assigned(FOnClick) then FOnClick(PivotGrid, AItem, AHandled); end; function TcxPivotGridPopupMenus.CreateFieldHeaderMenu: TcxPivotGridFieldHeaderMenu; begin Result := TcxPivotGridFieldHeaderMenu.Create(Self); end; function TcxPivotGridPopupMenus.CreateGroupValueMenu: TcxPivotGridGroupValueMenu; begin Result := TcxPivotGridGroupValueMenu.Create(Self); end; function TcxPivotGridPopupMenus.CreateHeaderAreaMenu: TcxPivotGridHeaderAreaMenu; begin Result := TcxPivotGridHeaderAreaMenu.Create(Self); end; procedure TcxPivotGridPopupMenus.CreateMenus; begin FFieldHeaderMenu := CreateFieldHeaderMenu; FGroupValueMenu := CreateGroupValueMenu; FHeaderAreaMenu := CreateHeaderAreaMenu; end; procedure TcxPivotGridPopupMenus.DestroyMenus; begin FreeAndNil(FFieldHeaderMenu); FreeAndNil(FGroupValueMenu); FreeAndNil(FHeaderAreaMenu); end; procedure TcxPivotGridPopupMenus.DoOnPopup( ASender: TcxPivotGridCustomPopupMenu; var AHandled: Boolean); begin AHandled := False; if Assigned(FOnPopup) then FOnPopup(PivotGrid, ASender, AHandled); end; function TcxPivotGridPopupMenus.DoShowPopupMenu(const P: TPoint): Boolean; begin Result := False; HitTest.HitPoint := PivotGrid.ScreenToClient(P); if HitTest.HitAtField then begin if HitTest.Field is TcxPivotGridField then FieldHeaderMenu.FField := PivotGrid.HitTest.Field as TcxPivotGridField else FieldHeaderMenu.FField := nil; Result := FieldHeaderMenu.Popup(P.X, P.Y) end else if HitTest.HitAtGroupHeader and (HitTest.GroupItem <> nil) and HitTest.GroupItem.HasChildren then begin if HitTest.GroupItem.Field <> nil then begin GroupValueMenu.FGroupItem := HitTest.GroupItem; Result := GroupValueMenu.Popup(P.X, P.Y); end; end else if HitTest.HitAtHeaderArea then Result := HeaderAreaMenu.Popup(P.X, P.Y); end; procedure TcxPivotGridPopupMenus.MenuItemClickHandler(Sender: TObject); begin // DoOnClick((Sender as TMenuItem).Tag); end; procedure TcxPivotGridPopupMenus.Notification( AComponent: TComponent; Operation: TOperation); begin FieldHeaderMenu.Notification(AComponent, Operation); GroupValueMenu.Notification(AComponent, Operation); HeaderAreaMenu.Notification(AComponent, Operation); end; function TcxPivotGridPopupMenus.GetHitTest: TcxPivotGridHitTest; begin Result := PivotGrid.HitTest; end; procedure TcxPivotGridPopupMenus.SetFieldHeaderMenu( AValue: TcxPivotGridFieldHeaderMenu); begin FFieldHeaderMenu.Assign(AValue); end; procedure TcxPivotGridPopupMenus.SetGroupValueMenu( AValue: TcxPivotGridGroupValueMenu); begin GroupValueMenu.Assign(AValue); end; procedure TcxPivotGridPopupMenus.SetHeaderAreaMenu( AValue: TcxPivotGridHeaderAreaMenu); begin HeaderAreaMenu.Assign(AValue); end; { TcxPivotGridFieldOptions } constructor TcxPivotGridFieldOptions.Create(AOwner: TcxPivotGridField); begin FField := AOwner; FFiltering := True; FMoving := True; FSizing := True; FSorting := True; end; procedure TcxPivotGridFieldOptions.Assign(Source: TPersistent); begin if Source is TcxPivotGridFieldOptions then with TcxPivotGridFieldOptions(Source) do begin Self.FFiltering := FFiltering; Self.FMoving := FMoving; Self.FSizing := FSizing; Self.FSorting := FSorting; end else inherited Assign(Source); end; function TcxPivotGridFieldOptions.CanFiltering: Boolean; begin Result := Field.PivotGrid.OptionsCustomize.Filtering and Filtering; end; function TcxPivotGridFieldOptions.CanSorting: Boolean; begin Result := Field.PivotGrid.OptionsCustomize.Sorting and Sorting and (Field.Area in [faColumn, faRow]); end; procedure TcxPivotGridFieldOptions.Changed; begin Field.Changed; end; function TcxPivotGridFieldOptions.GetOwner: TPersistent; begin Result := FField; end; procedure TcxPivotGridFieldOptions.SetOption( var AOption: Boolean; ANewValue: Boolean); begin if AOption <> ANewValue then begin AOption := ANewValue; Changed; end; end; procedure TcxPivotGridFieldOptions.SetFiltering(AValue: Boolean); begin if FFiltering <> AValue then begin FFiltering := AValue; Field.PivotGrid.RefreshFilterableFieldsList; Changed; end; end; procedure TcxPivotGridFieldOptions.SetMoving(AValue: Boolean); begin SetOption(FMoving, AValue); end; procedure TcxPivotGridFieldOptions.SetSizing(AValue: Boolean); begin SetOption(FSizing, AValue); end; procedure TcxPivotGridFieldOptions.SetSorting(AValue: Boolean); begin SetOption(FSorting, AValue); end; { TcxPivotGridViewDataItem } constructor TcxPivotGridViewDataItem.Create( AParent: TcxPivotGridViewDataItem; AGroupItem: TcxPivotGridGroupItem); begin FGroupItem := AGroupItem; FParent := AParent; FItems := TcxObjectList.Create; FVisibleIndex := -1; FLimitValues := TcxPivotGridViewDataLimitValues.Create; end; destructor TcxPivotGridViewDataItem.Destroy; begin FItems.Free; FLimitValues.Free; inherited Destroy; end; function TcxPivotGridViewDataItem.Add( AData: TcxPivotGridGroupItem): TcxPivotGridViewDataItem; begin Result := TcxPivotGridViewDataItem.Create(Self, AData); Result.FIndex := FItems.Add(Result); end; function TcxPivotGridViewDataItem.AddTotal( AData: TcxPivotGridGroupItem; AIndex: Integer): TcxPivotGridViewDataItem; begin Result := TcxPivotGridViewDataTotalItem.Create(Self, AData); Result.FIndex := FItems.Add(Result); TcxPivotGridViewDataTotalItem(Result).SetTotal(AIndex); end; procedure TcxPivotGridViewDataItem.DeleteChildren; begin FItems.Clear; end; function TcxPivotGridViewDataItem.GetDisplayText: string; var AFakeCell: TcxPivotGridHeaderCellViewInfo; begin AFakeCell := TcxPivotGridHeaderCellViewInfo.Create(PivotGrid.LookAndFeelPainter, cxSimpleRect, cxSimpleRect, PivotGrid.ViewInfo.FViewParams); try AFakeCell.Data := Self; PivotGrid.ViewInfo.InitHeaderCell(AFakeCell, Self); Result := AFakeCell.DisplayText; finally AFakeCell.Free; end; end; function TcxPivotGridViewDataItem.GetGroupItem( var ADataField: TcxPivotGridField): TcxPivotGridGroupItem; var AViewData: TcxPivotGridViewDataItem; begin AViewData := Self; while AViewData.IsDataField do begin ADataField := AViewData.Field; AViewData := AViewData.Parent; end; Result := AViewData.GroupItem; AViewData := Self; while (ADataField = nil) and (AViewData <> nil) do begin if AViewData.IsDataField then ADataField := AViewData.Field; AViewData := AViewData.Parent; end; end; function TcxPivotGridViewDataItem.GetGroupItemByField( ADataField: TcxPivotGridField): TcxPivotGridGroupItem; begin Result := nil; if Field = ADataField then Result := GroupItem else if Parent <> nil then Result := Parent.GetGroupItemByField(ADataField); end; function TcxPivotGridViewDataItem.GetSummaryType( var ASummaryType: TcxPivotGridSummaryType; var ATotal: TcxPivotGridCustomTotal): Boolean; begin if Parent <> nil then Result := Parent.GetSummaryType(ASummaryType, ATotal) else Result := False; end; function TcxPivotGridViewDataItem.MeasureWidth( AField: TPersistent; AIncludeTotals: Boolean): Integer; var AParams: TcxViewParams; AAlignHorz: TAlignment; AAlignVert: TcxAlignmentVert; I, AImageIndex: Integer; begin Result := 0; if (Field = AField) and (PivotGrid <> nil) and (not IsTotal or AIncludeTotals) then with PivotGrid do begin AImageIndex := Field.DoGetGroupImageIndex(Self, AAlignHorz, AAlignVert); if AImageIndex > 0 then Inc(Result, GroupHeaderImages.Width + cxPivotGridDoubleSpace); if ItemCount > 0 then Inc(Result, LookAndFeelPainter.ExpandButtonSize + cxPivotGridDoubleSpace); AParams := Styles.GetRowHeaderParams(Self); Inc(Result, cxTextWidth(AParams.Font, Value) + cxPivotGridDoubleSpace); Exit; end; for I := 0 to ItemCount - 1 do Result := Max(Result, Items[I].MeasureWidth(AField, AIncludeTotals)); end; function TcxPivotGridViewDataItem.GetFirst: TcxPivotGridViewDataItem; begin if ItemCount > 0 then Result := Items[0] else Result := nil; end; function TcxPivotGridViewDataItem.GetHasButton: Boolean; begin Result := not IsTotal and ((GroupItem.ItemCount > 0) or GroupItem.HasChildren); end; function TcxPivotGridViewDataItem.GetHasChildren: Boolean; begin Result := (ItemCount > 0) or GroupItem.HasChildren; end; function TcxPivotGridViewDataItem.GetExpanded: Boolean; begin Result := HasButton and GroupItem.Expanded; end; function TcxPivotGridViewDataItem.GetChildLeftVisibleIndex: Integer; var I: Integer; begin Result := MaxInt; if ItemCount > 0 then begin for I := 0 to ItemCount - 1 do Result := Min(Result, Items[I].GetChildLeftVisibleIndex); end else Result := VisibleIndex; end; function TcxPivotGridViewDataItem.GetChildRightVisibleIndex: Integer; var I: Integer; begin Result := 0; if ItemCount > 0 then begin for I := 0 to ItemCount - 1 do Result := Max(Result, Items[I].GetChildRightVisibleIndex); end else Result := VisibleIndex; end; function TcxPivotGridViewDataItem.GetField: TcxPivotGridField; begin Result := GroupItem.Field; end; function TcxPivotGridViewDataItem.GetIsTotal: Boolean; begin Result := False; end; function TcxPivotGridViewDataItem.GetItem( AIndex: Integer): TcxPivotGridViewDataItem; begin Result := TcxPivotGridViewDataItem(FItems[AIndex]); end; function TcxPivotGridViewDataItem.GetItemCount: Integer; begin Result := FItems.Count; end; function TcxPivotGridViewDataItem.GetIsGrandTotal: Boolean; begin Result := IsTotalItem and ((GroupItem.Parent = nil) or ((Parent <> nil) and (Parent.IsGrandTotal))); end; function TcxPivotGridViewDataItem.GetIsTotalItem: Boolean; var AItem: TcxPivotGridViewDataItem; begin AItem := Self; repeat Result := AItem.IsTotal; AItem := AItem.Parent; until Result or (AItem = nil); end; function TcxPivotGridViewDataItem.GetLevel: Integer; var AParent: TcxPivotGridViewDataItem; begin Result := -1; AParent := FParent; while AParent <> nil do begin AParent := AParent.FParent; Inc(Result); end; end; function TcxPivotGridViewDataItem.GetLast: TcxPivotGridViewDataItem; begin if ItemCount > 0 then Result := Items[ItemCount - 1] else Result := nil end; function TcxPivotGridViewDataItem.GetNextVisible: TcxPivotGridViewDataItem; begin Result := Self; while (Result <> nil) and (Result = Result.Parent.Last) do begin Result := Result.Parent; if Result.Parent = nil then Result := nil; end; if Result <> nil then begin Result := Result.Parent.Items[Result.Index + 1]; while Result.ItemCount > 0 do Result := Result.First; end; end; function TcxPivotGridViewDataItem.GetPrevVisible: TcxPivotGridViewDataItem; begin Result := Self; while (Result <> nil) and (Result.Index = 0) do Result := Result.Parent; if Result <> nil then begin Result := Result.Parent.Items[Result.Index - 1]; while Result.ItemCount > 0 do Result := Result.Last; end; end; function TcxPivotGridViewDataItem.GetPivotGrid: TcxCustomPivotGrid; begin if GroupItem = nil then Result := nil else Result := GroupItem.PivotGrid; end; function TcxPivotGridViewDataItem.GetSize: Integer; var I: Integer; begin Result := 0; if ItemCount > 0 then begin for I := 0 to ItemCount - 1 do Inc(Result, Items[I].Size) end else Result := GroupItem.GetSingleItemSize; end; function TcxPivotGridViewDataItem.GetValue: string; begin Result := GroupItem.DisplayText; end; { TcxPivotGridViewDataTotalItem } function TcxPivotGridViewDataTotalItem.GetSummaryType(var ASummaryType: TcxPivotGridSummaryType; var ATotal: TcxPivotGridCustomTotal): Boolean; begin if Total <> nil then begin Result := True; ATotal := Total; ASummaryType := ATotal.SummaryType; end else Result := inherited GetSummaryType(ASummaryType, ATotal); end; function TcxPivotGridViewDataTotalItem.GetDescription: string; begin if Total = nil then Result := cxGetResourceString(@scxGroupTotal) else Result := cxGetResourceString(TotalDescriptions[Total.SummaryType]); end; function TcxPivotGridViewDataTotalItem.GetIsTotal: Boolean; begin Result := True; end; function TcxPivotGridViewDataTotalItem.GetValue: string; begin if IsGrandTotal then Result := cxGetResourceString(@scxGrandTotal) else Result := Format(GetDescription, [inherited GetValue]) end; procedure TcxPivotGridViewDataTotalItem.SetTotal(AIndex: Integer); begin if not IsGrandTotal and (Field.TotalsVisibility = tvCustom) then FTotal := Field.CustomTotals[AIndex]; end; { TcxPivotGridCustomStyles } constructor TcxPivotGridCustomStyles.Create(AOwner: TPersistent); begin inherited Create(AOwner); BitmapInViewParams := True; end; procedure TcxPivotGridCustomStyles.Assign(Source: TPersistent); var I: Integer; begin if Source is TcxPivotGridStyles then begin for I := 0 to gs_MaxStyleIndex do SetValue(I, TcxPivotGridStyles(Source).GetValue(I)); end; inherited Assign(Source); end; function TcxPivotGridCustomStyles.GetBackgroundParams: TcxViewParams; begin GetViewParams(gs_Background, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetColumnHeaderParams( AColumn: TcxPivotGridViewDataItem): TcxViewParams; var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetColumnHeaderStyle) then FOnGetColumnHeaderStyle(PivotGrid, AColumn, AStyle); if AStyle = nil then //todo: optimize get style for fastest working with styles GetViewParams(gs_ColumnHeader, nil, nil, Result) else GetViewParams(gs_ColumnHeader, nil, AStyle, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetColumnMaximumValueParams: TcxViewParams; begin GetViewParams(gs_ColumnMaximumValue, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetColumnMinimumValueParams: TcxViewParams; begin GetViewParams(gs_ColumnMinimumValue, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetContentParams( ACell: TcxPivotGridDataCellViewInfo): TcxViewParams; var AStyle: TcxStyle; ASelParams: TcxViewParams; AStyleIndex: Integer; begin AStyle := nil; if Assigned(FOnGetContentStyle) then begin ACell.CheckVisibleInfo; FOnGetContentStyle(PivotGrid, ACell, AStyle); end; AStyleIndex := GetContentStyleIndexByCell(ACell); GetViewParams(AStyleIndex, ACell, AStyle, Result); if ACell.Selected then begin ASelParams := GetSelectionParams; Result.Bitmap := nil; Result.Color := ASelParams.Color; Result.TextColor := ASelParams.TextColor; end; CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetFieldHeaderParams( AField: TcxPivotGridField): TcxViewParams; var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetFieldHeaderStyle) then FOnGetFieldHeaderStyle(PivotGrid, AField, AStyle); GetViewParams(gs_FieldHeader, AField, AStyle, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetFilterSeparatorParams: TcxViewParams; begin GetViewParams(gs_FilterSeparator, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetHeaderBackgroundParams( AArea: TcxPivotGridFieldArea): TcxViewParams; const AStyleID: array[TcxPivotGridFieldArea] of Integer = (gs_ColumnHeaderArea, gs_RowHeaderArea, gs_FilterHeaderArea, gs_DataHeaderArea); begin GetViewParams(AStyleID[AArea], nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetMaximumValueParams: TcxViewParams; begin GetViewParams(gs_MaximumValue, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetMinimumValueParams: TcxViewParams; begin GetViewParams(gs_MaximumValue, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetPrefilterParams: TcxViewParams; begin GetViewParams(gs_Prefilter, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetRowHeaderParams( ARow: TcxPivotGridViewDataItem): TcxViewParams; var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetRowHeaderStyle) then FOnGetRowHeaderStyle(PivotGrid, ARow, AStyle); if AStyle = nil then //todo: optimize get style for fastest working with styles GetViewParams(gs_RowHeader, nil, nil, Result) else GetViewParams(gs_RowHeader, nil, AStyle, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetRowMaximumValueParams: TcxViewParams; begin GetViewParams(gs_RowMaximumValue, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetRowMinimumValueParams: TcxViewParams; begin GetViewParams(gs_RowMinimumValue, nil, nil, Result); CheckViewParams(Result); end; function TcxPivotGridCustomStyles.GetSelectionParams: TcxViewParams; const AStyleIndex: array[Boolean] of Integer = (gs_Inactive, gs_Selected); begin GetViewParams(AStyleIndex[PivotGrid.Controller.Focused], nil, nil, Result); end; procedure TcxPivotGridCustomStyles.Changed(AIndex: Integer); begin inherited Changed(AIndex); if PivotGrid <> nil then PivotGrid.LayoutChanged; end; procedure TcxPivotGridCustomStyles.CheckViewParams(var AParams: TcxViewParams); begin if SuppressContentColoration then AParams.Color := clWindow; if SuppressBackgroundBitmaps then AParams.Bitmap := nil; end; function TcxPivotGridCustomStyles.GetContentStyleIndexByCell(ACell: TcxPivotGridDataCellViewInfo): Integer; const AStyleID: array[TcxPivotGridDataCellLimitValueType] of Integer = (gs_ColumnMaximumValue, gs_ColumnMinimumValue, gs_RowMaximumValue, gs_RowMinimumValue, gs_MaximumValue, gs_MinimumValue); var ALimitValues: TcxPivotGridDataCellLimitValueTypes; I: TcxPivotGridDataCellLimitValueType; ANeedLimitValues: Boolean; begin if ACell.IsTotal then Result := gs_Total else begin Result := gs_Content; ANeedLimitValues := False; for I := lvtColumnMaximum to lvtMinimum do ANeedLimitValues := ANeedLimitValues or (Values[AStyleID[I]] <> nil); if ANeedLimitValues then begin ALimitValues := ACell.LimitValueTypes; if (lvtMaximum in ALimitValues) and (Values[AStyleID[lvtMaximum]] <> nil) then Result := AStyleID[lvtMaximum]; if (Result = gs_Content) and (lvtMinimum in ALimitValues) and (Values[AStyleID[lvtMinimum]] <> nil) then Result := AStyleID[lvtMinimum]; if (Result = gs_Content) and (lvtColumnMaximum in ALimitValues) and (Values[AStyleID[lvtColumnMaximum]] <> nil) then Result := AStyleID[lvtColumnMaximum]; if (Result = gs_Content) and (lvtColumnMinimum in ALimitValues) and (Values[AStyleID[lvtColumnMinimum]] <> nil) then Result := AStyleID[lvtColumnMinimum]; if (Result = gs_Content) and (lvtRowMaximum in ALimitValues) and (Values[AStyleID[lvtRowMaximum]] <> nil) then Result := AStyleID[lvtRowMaximum]; if (Result = gs_Content) and (lvtRowMinimum in ALimitValues) and (Values[AStyleID[lvtRowMinimum]] <> nil) then Result := AStyleID[lvtRowMinimum]; end; end; end; procedure TcxPivotGridCustomStyles.GetDefaultHeadersAreaViewParams( out AParams: TcxViewParams); var APivotGrid: TcxCustomPivotGrid; APainter: TcxCustomLookAndFeelPainterClass; begin APivotGrid := PivotGrid; APainter := APivotGrid.LookAndFeelPainter; InternalGetViewParams(gs_HeaderBackground, nil, nil, AParams); if AParams.Font = nil then AParams.Font := APivotGrid.Font; if AParams.Color = clDefault then AParams.Color := APainter.PivotGridHeadersAreaColor; if AParams.TextColor = clDefault then AParams.TextColor := APainter.PivotGridHeadersAreaTextColor; end; procedure TcxPivotGridCustomStyles.GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); var APivotGrid: TcxCustomPivotGrid; APainter: TcxCustomLookAndFeelPainterClass; begin APivotGrid := PivotGrid; APainter := APivotGrid.LookAndFeelPainter; AParams.Font := APivotGrid.Font; AParams.TextColor := APivotGrid.Font.Color; AParams.Color := APivotGrid.Color; AParams.Bitmap := nil; case Index of gs_FieldHeader, gs_RowHeader, gs_ColumnHeader: begin AParams.Color := APainter.DefaultHeaderColor; AParams.TextColor := APainter.DefaultHeaderTextColor; if (Index = gs_FieldHeader) and (AData = nil) then AParams.TextColor := clRed; end; gs_HeaderBackground: begin AParams.Color := APainter.DefaultHeaderBackgroundColor; AParams.TextColor := APainter.DefaultHeaderBackgroundTextColor; end; gs_Prefilter: begin AParams.Color := APainter.DefaultHeaderBackgroundColor; AParams.TextColor := APainter.DefaultFilterBoxTextColor; end; gs_ColumnHeaderArea, gs_RowHeaderArea, gs_FilterHeaderArea, gs_DataHeaderArea: GetDefaultHeadersAreaViewParams(AParams); gs_FilterSeparator: begin AParams.TextColor := APainter.DefaultSeparatorColor; AParams.Color := APainter.DefaultHeaderBackgroundColor; end; gs_Content, gs_ColumnMaximumValue, gs_ColumnMinimumValue, gs_MaximumValue, gs_MinimumValue, gs_RowMaximumValue, gs_RowMinimumValue, gs_Background: begin AParams.Color := ColorToRgb(APainter.DefaultContentColor); AParams.TextColor := APainter.DefaultContentTextColor; end; gs_Total: begin AParams.Color := Dark(ColorToRgb(APainter.DefaultContentColor), 90); AParams.TextColor := APainter.DefaultContentTextColor; end; gs_Selected: begin AParams.Color := APainter.DefaultSelectionColor; AParams.TextColor := APainter.DefaultSelectionTextColor; end; gs_Inactive: begin AParams.Color := APainter.DefaultInactiveColor; AParams.TextColor := APainter.DefaultInactiveTextColor; end; else inherited GetDefaultViewParams(Index, AData, AParams); end; end; function TcxPivotGridCustomStyles.GetPivotGrid: TcxCustomPivotGrid; begin if GetOwner is TcxCustomPivotGrid then Result := GetOwner as TcxCustomPivotGrid else Result := nil; end; { TcxPivotGridStyles } function TcxPivotGridStyles.GetColumnHeaderParams(AColumn: TcxPivotGridViewDataItem): TcxViewParams; begin if (AColumn.Field <> nil) and (AColumn.Field.Styles.ColumnHeader <> nil) then Result := AColumn.Field.Styles.GetColumnHeaderParams(AColumn) else Result := inherited GetColumnHeaderParams(AColumn); end; function TcxPivotGridStyles.GetContentParams(ACell: TcxPivotGridDataCellViewInfo): TcxViewParams; var AStyleIndex: Integer; begin AStyleIndex := -1; if (ACell.DataField <> nil) then begin AStyleIndex := ACell.DataField.Styles.GetContentStyleIndexByCell(ACell); if ACell.DataField.Styles.Values[AStyleIndex] <> nil then Result := ACell.DataField.Styles.GetContentParams(ACell) else AStyleIndex := -1; end; if AStyleIndex = -1 then Result := inherited GetContentParams(ACell); end; function TcxPivotGridStyles.GetRowHeaderParams(ARow: TcxPivotGridViewDataItem): TcxViewParams; begin if (ARow.Field <> nil) and (ARow.Field.Styles.RowHeader <> nil) then Result := ARow.Field.Styles.GetRowHeaderParams(ARow) else Result := inherited GetRowHeaderParams(ARow); end; { TcxPivotGridFieldStyles } procedure TcxPivotGridFieldStyles.GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); begin PivotGrid.Styles.GetViewParams(Index, AData, PivotGrid.Styles.Values[Index], AParams) end; function TcxPivotGridFieldStyles.GetPivotGrid: TcxCustomPivotGrid; begin if Owner is TcxCustomPivotGrid then Result := TcxCustomPivotGrid(Owner) else if (Owner is TcxPivotGridField) then Result := TcxPivotGridField(Owner).PivotGrid else Result := nil; end; { TcxPivotGridCells } procedure TcxPivotGridCells.BeforePaint; var I: Integer; begin for I := 0 to Count - 1 do Items[I].CheckVisibleInfo; end; function TcxPivotGridCells.CalculateHitTest(AHitTest: TcxPivotGridHitTest): Boolean; var I: Integer; begin Result := False; for I := 0 to Count - 1 do begin Result := Items[I].GetHitTest(AHitTest); if Result then Exit; end; end; procedure TcxPivotGridCells.DeleteAll; begin SetCount(0); end; procedure TcxPivotGridCells.ExcludeFromClipping(ACanvas: TcxCanvas); var I: Integer; begin for I := 0 to Count - 1 do Items[I].ExcludeFromPaint(ACanvas); end; procedure TcxPivotGridCells.Paint( ACanvas: TcxCanvas; AHandler: TcxPivotGridCustomDrawEvent); procedure DoDrawItem(AItem: TcxPivotGridCustomCellViewInfo); var ADone: Boolean; begin AItem.BeforeCustomDraw(ACanvas); AHandler(ACanvas, AItem, ADone); AItem.AfterCustomDraw(ACanvas); if not ADone then AItem.Draw(ACanvas); end; var I: Integer; AClipRgn: TcxRegion; AItem: TcxPivotGridCustomCellViewInfo; begin for I := 0 to Count - 1 do begin AItem := Items[I]; if (AItem.Visible and RectVisible(ACanvas.Handle, AItem.FClipRect)) then if AItem.HasClipping then begin AClipRgn := ACanvas.GetClipRegion; ACanvas.IntersectClipRect(AItem.ClipRect); DoDrawItem(AItem); ACanvas.SetClipRegion(AClipRgn, roSet); end else DoDrawItem(AItem); end; end; procedure TcxPivotGridCells.CorrectBoundsForPrinting(ABounds: TRect); var I: Integer; begin for I := 0 to Count - 1 do Items[I].CorrectBoundsForPrinting(ABounds); end; function TcxPivotGridCells.GetItem(AIndex: Integer): TcxPivotGridCustomCellViewInfo; begin Result := TcxPivotGridCustomCellViewInfo(List^[AIndex]); end; { TcxPivotGridField } constructor TcxPivotGridField.Create(AOwner: TComponent); begin inherited Create(AOwner); CreateSubClasses; FAllowedAreas := [faColumn..faData]; FArea := faFilter; FAreaIndex := -1; FGroupExpanded := True; FGroupIntervalRange := cxPivotGridDefaultGroupIntervalRange; FImageIndex := -1; FSortOrder := soNone; FSummaryIndex := -1; FSummaryType := stSum; FMinWidth := cxPivotGridDefaultFieldMinWidth; FImageAlign := taLeftJustify; FFilter.OnChange := FilterChanged; end; destructor TcxPivotGridField.Destroy; begin Group := nil; PivotGrid := nil; RepositoryItem := nil; DestroySubClasses; PropertiesValueChanged; DestroyEditViewData; FreeAndNil(FEditStyle); inherited Destroy; end; procedure TcxPivotGridField.Assign(Source: TPersistent); begin if Source is TcxPivotGridField then begin AllowedAreas := TcxPivotGridField(Source).AllowedAreas; Area := TcxPivotGridField(Source).Area; AreaIndex := TcxPivotGridField(Source).AreaIndex; Caption := TcxPivotGridField(Source).Caption; CustomTotals := TcxPivotGridField(Source).CustomTotals; DataBinding := TcxPivotGridField(Source).DataBinding; DisplayFormat := TcxPivotGridField(Source).DisplayFormat; GroupExpanded := TcxPivotGridField(Source).GroupExpanded; GroupInterval := TcxPivotGridField(Source).GroupInterval; GroupIntervalRange := TcxPivotGridField(Source).GroupIntervalRange; Hidden := TcxPivotGridField(Source).Hidden; MinWidth := TcxPivotGridField(Source).MinWidth; ImageAlign := TcxPivotGridField(Source).ImageAlign; ImageIndex := TcxPivotGridField(Source).ImageIndex; Options := TcxPivotGridField(Source).Options; SortBySummaryInfo := TcxPivotGridField(Source).SortBySummaryInfo; SortOrder := TcxPivotGridField(Source).SortOrder; SummaryType := TcxPivotGridField(Source).SummaryType; SummaryVariation := TcxPivotGridField(Source).SummaryVariation; TopValueCount := TcxPivotGridField(Source).TopValueCount; TopValueShowOthers := TcxPivotGridField(Source).TopValueShowOthers; TotalsVisibility := TcxPivotGridField(Source).TotalsVisibility; Width := TcxPivotGridField(Source).Width; DataVisibility := TcxPivotGridField(Source).DataVisibility; end; end; procedure TcxPivotGridField.ApplyBestFit; var AWidth, I: Integer; begin if not VisibleInGroup or (Area = faFilter) then Exit; PivotGrid.CheckChanges; PivotGrid.ShowHourglassCursor; try AWidth := MinWidth; if (Area = faRow) or ((Area = faData) and (PivotGrid.OptionsDataField.Area = dfaRow)) then begin AWidth := Max(ViewInfo.MeasureWidth + cxPivotGridDoubleSpace, PivotGrid.ViewData.FRows.MeasureWidth(Self, False) + cxTextOffset) end else with PivotGrid.ViewData do begin AWidth := Max(AWidth, FColumns.MeasureWidth(Self, True) + cxTextOffset); if Area = faColumn then begin for I := 0 to PivotGrid.SummaryFields.Count - 1 do AWidth := Max(AWidth, CalculateDataWidth(PivotGrid.SummaryFields[I]) + cxTextOffset); end else AWidth := Max(AWidth, CalculateDataWidth(Self) + cxTextOffset); end; Width := AWidth; finally PivotGrid.HideHourglassCursor; end; end; procedure TcxPivotGridField.CollapseAll; begin SetExpanding(False); end; procedure TcxPivotGridField.ExpandAll; begin SetExpanding(True); end; function TcxPivotGridField.GetGroupValue(ARecordIndex: Integer): Variant; var S: string; Negative: Boolean; AGroupInterval: TcxPivotGridGroupInterval; begin Result := Values[ARecordIndex]; AGroupInterval := GroupInterval; if (Area = faData) and (AGroupInterval <> giAlphabetical) then AGroupInterval := giDefault; if AGroupInterval = giDefault then Exit; try case AGroupInterval of giDate: Result := DateOf(VarToDateTime(Result)); giDateDay: Result := DayOfTheMonth(VarToDateTime(Result)); giDateDayOfWeek: Result := DayOfWeek(VarToDateTime(Result)); giDateDayOfYear: Result := DayOfTheYear(VarToDateTime(Result)); giDateWeekOfMonth: Result := WeekOfTheMonth(VarToDateTime(Result)); giDateWeekOfYear: Result := WeekOfTheYear(VarToDateTime(Result)); giDateMonth: Result := MonthOf(VarToDateTime(Result)); giDateQuarter: Result := (MonthOf(VarToDateTime(Result)) - 1) div 3 + 1; giDateYear: Result := YearOf(VarToDateTime(Result)); giYearAge: Result := YearsBetween(VarToDateTime(Result), PivotGrid.RefreshDate); giMonthAge: Result := MonthsBetween(VarToDateTime(Result), PivotGrid.RefreshDate); giWeekAge: Result := WeeksBetween(VarToDateTime(Result), PivotGrid.RefreshDate); giDayAge: Result := DaysBetween(VarToDateTime(Result), PivotGrid.RefreshDate); giAlphabetical: begin S := VarToStr(Result); if Length(S) > 0 then Result := S[1] else Result := ''; end; giCustom: Result := DoGetGroupValue(Result, ARecordIndex); end; if AGroupInterval in [giYearAge, giMonthAge, giWeekAge, giDayAge, giNumeric] then begin if VarIsNumericEx(Result) then begin Negative := Result < 0; Result := Integer(Round(Result) div GroupIntervalRange); if Negative then Dec(Result); end else Result := 0; end; except on EVariantError do Result := Null else raise; end; end; function TcxPivotGridField.GetGroupValueDisplayText( const AGroupValue: Variant): string; begin try case GroupInterval of giDateDayOfWeek: Result := LongDayNames[Integer(AGroupValue)]; giDateMonth: Result := LongMonthNames[Integer(AGroupValue)]; giDateQuarter: Result := Format(cxGetResourceString(@scxQuarterFormat), [Integer(AGroupValue)]); giYearAge, giMonthAge, giWeekAge, giDayAge, giNumeric: begin Result := Format('%d-%d', [Integer(AGroupValue * GroupIntervalRange), Integer((AGroupValue + 1) * GroupIntervalRange - 1)]); end; giCustom: Result := DoGetGroupValueDisplayText(AGroupValue); else Result := VarToStr(AGroupValue); end; except on EVariantError do Result := '' else raise; end; end; function TcxPivotGridField.GetParentComponent: TComponent; begin Result := PivotGrid; end; function TcxPivotGridField.HasParent: Boolean; begin Result := True; end; procedure TcxPivotGridField.SetAreaPosition( AArea: TcxPivotGridFieldArea; AAreaIndex: Integer); begin PivotGrid.BeginUpdate; try Area := AArea; AreaIndex := AAreaIndex; finally PivotGrid.EndUpdate; end; end; function TcxPivotGridField.CanDrag: Boolean; begin Result := Options.Moving and PivotGrid.OptionsCustomize.Moving; end; function TcxPivotGridField.CanDrop(AArea: TcxPivotGridFieldArea): Boolean; begin Result := AArea in AllowedAreas; end; function TcxPivotGridField.CanModifyArea: Boolean; begin Result := (PivotGrid <> nil) and (Group = nil) or IsFirstFieldInGroup; end; function TcxPivotGridField.CanRemove: Boolean; begin Result := True; end; function TcxPivotGridField.CanResize: Boolean; begin Result := Options.Sizing and PivotGrid.OptionsCustomize.Sizing; end; procedure TcxPivotGridField.Changed(AIsViewChanged: Boolean = False); begin if PivotGrid <> nil then begin if AIsViewChanged then PivotGrid.ViewChanged else PivotGrid.LayoutChanged; PivotGrid.Customization.Refresh; end; end; function TcxPivotGridField.CreateEditStyle(AProperties: TcxCustomEditProperties): TcxEditStyle; begin Result := AProperties.GetStyleClass.Create(nil, True) as TcxEditStyle; Result.LookAndFeel.MasterLookAndFeel := PivotGrid.LookAndFeel; end; procedure TcxPivotGridField.CreateEditViewData; begin FEditViewData := GetUserEditProperties.CreateViewData(FEditStyle, True) end; procedure TcxPivotGridField.DataChanged; begin if PivotGrid <> nil then begin PivotGrid.DataChanged; PivotGrid.Customization.Refresh; end; end; function TcxPivotGridField.DefaultRepositoryItem: TcxEditRepositoryItem; begin Result := GetDefaultEditDataRepositoryItems.GetItem(DataBinding.ValueTypeClass); end; procedure TcxPivotGridField.DestroyEditViewData; begin FreeAndNil(FEditViewData); end; procedure TcxPivotGridField.DoCalculateCustomSummary( ACell: TcxPivotGridCrossCellSummary); begin if Assigned(FOnCalculateCustomSummary) then FOnCalculateCustomSummary(Self, ACell); end; procedure TcxPivotGridField.DoGetDisplayText( ACell: TcxPivotGridDataCellViewInfo); begin ACell.FDisplayText := FormatDisplayValue(ACell.Value, ACell.DisplayFormat, (ACell.Total = nil) and (SummaryVariation in [svPercent, svPercentOfColumn, svPercentOfRow])); InternalDoGetDisplayText(ACell, ACell.FDisplayText); end; function TcxPivotGridField.DoGetGroupImageIndex(AItem: TcxPivotGridViewDataItem; var AAlignHorz: TAlignment; var AAlignVert: TcxAlignmentVert): Integer; begin Result := -1; if (PivotGrid.GroupHeaderImages <> nil) and Assigned(FOnGetGroupImageIndex) then begin AAlignHorz := taLeftJustify; AAlignVert := vaTop; FOnGetGroupImageIndex(Self, AItem, Result, AAlignHorz, AAlignVert); if (Result >= PivotGrid.GroupHeaderImages.Count) or (Result < 0) then Result := -1; end; end; function TcxPivotGridField.DoGetGroupValue( const AValue: Variant; ARecordIndex: Integer): Variant; begin Result := AValue; if Assigned(FOngetGroupValue) then FOnGetGroupValue(Self, ARecordIndex, Result); end; function TcxPivotGridField.DoGetGroupValueDisplayText( const AValue: Variant): string; begin Result := VarToStr(AValue); if Assigned(FOnGetGroupValueDisplayText) then FOnGetGroupValueDisplayText(Self, AValue, Result); end; procedure TcxPivotGridField.DoFilterChanged; begin DataChanged; if PivotGrid <> nil then PivotGrid.DoFilterChanged; end; function TcxPivotGridField.DoGetProperties(ACell: TcxPivotGridCustomCellViewInfo): TcxCustomEditProperties; begin Result := GetUserEditProperties; if Assigned(FOnGetProperties) then FOnGetProperties(Self, ACell, Result); end; procedure TcxPivotGridField.DoGetTotalDisplayText(AGroupItem: TcxPivotGridGroupItem; var AText: string); begin if Assigned(FOnGetTotalDisplayText) then FOnGetTotalDisplayText(Self, AGroupItem, AText); end; procedure TcxPivotGridField.DragDrop( AArea: TcxPivotGridFieldArea; AAreaIndex: Integer); var APrevVisible: Boolean; APrevAreaIndex: Integer; begin APrevAreaIndex := AAreaIndex; APrevVisible := Visible; if (Area = AArea) and (AAreaIndex > ViewInfo.AreaIndex) and (AAreaIndex > 0) and Visible then Dec(AAreaIndex); PivotGrid.BeginUpdate; try FVisible := True; if Group <> nil then begin if Group.AreaIndex <> AreaIndex then begin Group.Fields[0].DragDrop(AArea, APrevAreaIndex); Exit; end; if ((AArea <> Group.Area) or not APrevVisible) and (AAreaIndex > ViewInfo.AreaIndex) then Inc(AAreaIndex, Group.VisibleCount - 1); Group.InternalSetArea(AArea); Group.AreaIndex := AAreaIndex; end else begin FArea := AArea; AreaIndex := AAreaIndex; end; finally PivotGrid.DataChanged; PivotGrid.EndUpdate; end; end; function TcxPivotGridField.GetEditViewData: TcxCustomEditViewData; begin if FEditViewData = nil then CreateEditViewData; Result := FEditViewData; end; procedure TcxPivotGridField.InitGroupValues; var I, AGroupValueIndex: Integer; begin if FGroupValuesValid then Exit; FGroupValueList.Clear; if PivotGrid.OLAPDataSource <> nil then PivotGrid.OLAPDataSource.InitializeMembers(FLink, FGroupValueList) else begin for I := 0 to RecordCount - 1 do begin AGroupValueIndex := FGroupValueList.Add(GetGroupValue(I)); FGroupValueList.Items[AGroupValueIndex].FUnUsed := (PivotGrid.DataBuilder.FilteredIndexes[I] <= -2) or ((PivotGrid.DataBuilder.FilteredIndexes[I] = -1) and Filter.Contains(GetGroupValue(I))); end; end; FGroupValueList.MakeUnique; FGroupValuesValid := True; end; procedure TcxPivotGridField.InitProperties(AProperties: TcxCustomEditProperties); begin if AProperties <> nil then with AProperties do begin LockUpdate(True); IDefaultValuesProvider := DataBinding.GetDefaultValuesProvider; LockUpdate(False); end; end; function TcxPivotGridField.IsCurrency(AType: TcxValueTypeClass): Boolean; begin Result := (AType = TcxCurrencyValueType) or (AType = TcxFMTBcdValueType); end; function TcxPivotGridField.IsItemExpanded( AGroup: TcxPivotGridGroupItem): Boolean; begin Result := (ExpandingInfo.Count <> 0) and (ExpandingInfo.IndexOf(AGroup.GetUniqueValue) <> -1); end; function TcxPivotGridField.HasSummaryVariation: Boolean; begin Result := SummaryVariation <> svNone; end; function TcxPivotGridField.GetActualDisplayFormat: string; begin Result := FDisplayFormat; end; function TcxPivotGridField.GetEditProperties: TcxCustomEditProperties; begin Result := FPropertiesValue; InitProperties(Result); end; function TcxPivotGridField.GetEditStyle(AProperties: TcxCustomEditProperties; ALocal: Boolean): TcxEditStyle; begin if ALocal then Result := CreateEditStyle(AProperties) else Result := FEditStyle; end; function TcxPivotGridField.GetUserEditProperties: TcxCustomEditProperties; begin if FRepositoryItem <> nil then Result := FRepositoryItem.Properties else Result := FProperties; InitProperties(Result); end; function TcxPivotGridField.GetPropertiesValue: TcxCustomEditProperties; begin if FLastUsedDefaultRepositoryItem <> nil then begin FLastUsedDefaultRepositoryItem.RemoveListener(Self); FLastUsedDefaultRepositoryItem := nil; end; if FPivotGrid = nil then Result := nil else begin Result := GetUserEditProperties; if (Result = nil) and (GetRepositoryItem <> nil) then Result := GetRepositoryItem.Properties; end; end; function TcxPivotGridField.GetRepositoryItem: TcxEditRepositoryItem; begin Result := FRepositoryItem; if (Result = nil) and not GetIsDestroying then begin Result := DefaultRepositoryItem; if Result <> nil then begin Result.AddListener(Self); FLastUsedDefaultRepositoryItem := Result; end; end; end; procedure TcxPivotGridField.EditViewDataGetDisplayTextHandler(Sender: TcxCustomEditViewData; var AText: string); var ACell: TcxPivotGridDataCellViewInfo; begin if Sender.Data is TcxPivotGridDataCellViewInfo then ACell := TcxPivotGridDataCellViewInfo(Sender.Data) else ACell := nil; InternalDoGetDisplayText(ACell, AText); end; procedure TcxPivotGridField.PropertiesChanged; begin FreeAndNil(FEditStyle); if UseEditProperties and not GetIsDestroying then FEditStyle := CreateEditStyle(GetUserEditProperties); Changed; end; procedure TcxPivotGridField.PropertiesChangedHandler(Sender: TObject); begin PropertiesChanged; end; procedure TcxPivotGridField.PropertiesValueChanged; begin FPropertiesValue := GetPropertiesValue; end; function TcxPivotGridField.UseEditProperties: Boolean; begin Result := (FRepositoryItem <> nil) or (FProperties <> nil); end; function TcxPivotGridField.CreateCustomTotals: TcxPivotGridCustomTotalCollection; begin Result := TcxPivotGridCustomTotalCollection.Create(Self); end; function TcxPivotGridField.CreateDataBinding: TcxPivotGridFieldDataBinding; begin Result := TcxPivotGridFieldDataBinding.Create(Self); end; function TcxPivotGridField.CreateFilter: TcxPivotGridFieldFilter; begin Result := TcxPivotGridFieldFilter.Create(Self); end; function TcxPivotGridField.CreateOptions: TcxPivotGridFieldOptions; begin Result := TcxPivotGridFieldOptions.Create(Self); end; function TcxPivotGridField.CreateSortBySummaryInfo: TcxPivotGridSortBySummaryInfo; begin Result := TcxPivotGridSortBySummaryInfo.Create(Self); end; function TcxPivotGridField.CreateStyles: TcxPivotGridFieldStyles; begin Result := TcxPivotGridFieldStyles.Create(Self); end; procedure TcxPivotGridField.CreateSubClasses; begin FDataBinding := CreateDataBinding; FExpandingInfo := TcxPivotGridVariantList.Create(); FViewInfo := TcxPivotGridFieldHeaderCellViewInfo.CreateEx(Self); FCustomTotals := CreateCustomTotals; FFilter := CreateFilter; FOptions := CreateOptions; FSortBySummaryInfo := CreateSortBySummaryInfo; FStyles := CreateStyles; FGroupValueList := TcxPivotGridVariantList.Create; end; procedure TcxPivotGridField.DestroySubClasses; begin FreeAndNil(FGroupValueList); FreeAndNil(FStyles); FreeAndNil(FCustomTotals); FreeAndNil(FFilter); FreeAndNil(FViewInfo); FreeAndNil(FOptions); FreeAndNil(FSortBySummaryInfo); FreeAndNil(FExpandingInfo); FreeAndNil(FDataBinding); DestroyProperties; end; procedure TcxPivotGridField.GroupCheckExpanding( AGroup: TcxPivotGridGroupItem); begin AGroup.Expanded := IsItemExpanded(AGroup); end; procedure TcxPivotGridField.GroupExpandingChanged( ASender: TcxPivotGridGroupItem); begin try if not PivotGrid.OptionsData.SaveExpanding then Exit; if ASender.FExpanded then ExpandingInfo.Add(ASender.GetUniqueValue) else ExpandingInfo.Remove(ASender.GetUniqueValue); finally if ASender.ChildrenNeeded and (PivotGrid.OLAPDataSource <> nil) then PivotGrid.DataBuilder.GroupExpandingChanged(ASender); end; end; function TcxPivotGridField.GetCaption: string; begin if FIsCaptionAssigned then Result := FCaption else Result := Name; end; function TcxPivotGridField.GetDataType: TVarType; begin if PivotGrid.IsOLAPActive then Result := varString else if DataBinding.ValueTypeClass = nil then Result := varUnknown else Result := DataBinding.ValueTypeClass.GetVarType; end; function TcxPivotGridField.GetDisplayTextAssigned: Boolean; begin Result := Assigned(FOnGetDisplayText); end; function TcxPivotGridField.IsRecordVisible(ARecordIndex: Integer): Boolean; begin Result := not Filter.HasFilter or Filter.Contains(GetGroupValue(ARecordIndex)); end; procedure TcxPivotGridField.SetAreaIndexInternal( AArea: TcxPivotGridFieldArea; AAreaIndex: Integer); begin FArea := AArea; FAreaIndex := AAreaIndex; end; procedure TcxPivotGridField.SetExpanding(AValue: Boolean); begin if Visible then begin PivotGrid.BeginUpdate; try PivotGrid.ShowHourglassCursor; if Area = faRow then PivotGrid.DataBuilder.Rows.SetFieldExpanding(Self, AValue) else if Area = faColumn then PivotGrid.DataBuilder.Columns.SetFieldExpanding(Self, AValue); PivotGrid.LayoutChanged; finally PivotGrid.EndUpdate; PivotGrid.HideHourglassCursor; end; end; end; procedure TcxPivotGridField.SetParentComponent(Value: TComponent); begin PivotGrid := Value as TcxCustomPivotGrid; end; procedure TcxPivotGridField.SetPivotGrid(AValue: TcxCustomPivotGrid); begin if AValue <> FPivotGrid then begin if FPivotGrid <> nil then FPivotGrid.RemoveField(Self); FPivotGrid := AValue; if FPivotGrid <> nil then PivotGrid.AddField(Self); PropertiesValueChanged; end; end; procedure TcxPivotGridField.SynchronizeUniqueName; begin PivotGrid.SynchronizeUniqueName(Self); end; // IcxEditRepositoryItemListener procedure TcxPivotGridField.ItemRemoved(Sender: TcxEditRepositoryItem); begin if Sender = FLastUsedDefaultRepositoryItem then PropertiesValueChanged else RepositoryItem := nil; end; procedure TcxPivotGridField.RepositoryItemPropertiesChanged(Sender: TcxEditRepositoryItem); begin PropertiesChanged; end; // IcxStoredObject function TcxPivotGridField.GetObjectName: string; begin Result := Name; if Result = '' then Result := ClassName + IntToStr(Index); end; function TcxPivotGridField.GetProperties( AProperties: TStrings): Boolean; var I: Integer; begin for I := Low(FieldDefaultStoredProperties) to High(FieldDefaultStoredProperties) do AProperties.Add(FieldDefaultStoredProperties[I]); if Assigned(OnGetStoredProperties) then OnGetStoredProperties(Self, AProperties); Result := True; end; procedure TcxPivotGridField.GetPropertyValue( const AName: string; var AValue: Variant); function GetFilterValue: Variant; var AStream: TStream; begin AStream := TMemoryStream.Create; try Filter.WriteData(AStream); Result := StreamToString(AStream); finally AStream.Free; end; end; begin case GetPropertyIndex(AName, FieldDefaultStoredProperties) of 6: AValue := GetFilterValue; end; if Assigned(OnGetStoredPropertyValue) then OnGetStoredPropertyValue(Self, AName, AValue); end; procedure TcxPivotGridField.SetPropertyValue( const AName: string; const AValue: Variant); procedure SetFilterValue; var AStream: TStream; begin AStream := TMemoryStream.Create; try StringToStream(dxVariantToAnsiString(AValue), AStream); AStream.Position := 0; Filter.ReadData(AStream); finally AStream.Free; end; end; begin case GetPropertyIndex(AName, FieldDefaultStoredProperties) of 6: SetFilterValue; end; if Assigned(OnSetStoredPropertyValue) then OnSetStoredPropertyValue(Self, AName, AValue); end; function TcxPivotGridField.GetAllowedAreas: TcxPivotGridFieldAreas; begin Result := FAllowedAreas; if FLink <> nil then Result := DimensionAllowedAreas[FLink.IsMeasure] end; function TcxPivotGridField.GetActualWidth: Integer; begin Result := FWidth; if Result = 0 then Result := cxPivotGridDefaultFieldWidth; Result := Max(MinWidth, Result); end; function TcxPivotGridField.GetController: TcxPivotGridController; begin Result := PivotGrid.Controller; end; function TcxPivotGridField.GetDataBuilder: TcxPivotGridDataBuilder; begin if PivotGrid <> nil then Result := PivotGrid.DataBuilder else Result := nil; end; function TcxPivotGridField.GetGroupExpanded: Boolean; var ANextField: TcxPivotGridField; begin Result := FGroupExpanded; if Result and (Group <> nil) then begin ANextField := Group.GetNextField(Self); Result := (ANextField <> nil) and ANextField.Visible; end; end; function TcxPivotGridField.GetGroupIndex: Integer; begin Result := -1; if Group <> nil then Result := Group.Index; end; function TcxPivotGridField.GetGroupValueList: TcxPivotGridVariantList; begin InitGroupValues; Result := FGroupValueList; end; function TcxPivotGridField.GetHeaderWidth: Integer; begin Result := ViewInfo.MeasureWidth; end; function TcxPivotGridField.GetHidden: Boolean; begin Result := FHidden or (PivotGrid.IsOLAPActive and (FLink = nil)); end; function TcxPivotGridField.GetIndex: Integer; begin Result := PivotGrid.FieldList.IndexOf(Self) end; function TcxPivotGridField.GetIsDestroying: Boolean; begin Result := csDestroying in ComponentState; end; function TcxPivotGridField.GetIsHierarchy: Boolean; begin Result := (Group <> nil) and (Group.FieldCount > 1); end; function TcxPivotGridField.GetMinWidth: Integer; begin Result := FMinWidth; end; function TcxPivotGridField.GetPropertiesClassName: string; begin if FProperties = nil then Result := '' else Result := FProperties.ClassName; end; function TcxPivotGridField.GetRecordCount: Integer; begin Result := PivotGrid.RecordCount; end; function TcxPivotGridField.GetSortedBySummary: Boolean; begin Result := SortBySummaryInfo.ValidateProperties; end; function TcxPivotGridField.GetUniqueName: WideString; begin Result := FUniqueName; if (Result = '') and Assigned(FLink) then Result := FLink.UniqueName; end; function TcxPivotGridField.GetValueByRecordIndex(ARecordIndex: Integer): Variant; begin ARecordIndex := PivotGrid.DataController.GetRowInfo(ARecordIndex).RecordIndex; if (Area <> faData) and (Properties <> nil) and (Properties.GetEditValueSource(False) = evsText) then Result := PivotGrid.DataController.DisplayTexts[ARecordIndex, Index] else Result := PivotGrid.DataController.Values[ARecordIndex, Index]; end; function TcxPivotGridField.GetVisible: Boolean; begin Result := FVisible and not Hidden; end; function TcxPivotGridField.GetVisibleInGroup: Boolean; begin Result := Visible and ((Group = nil) or (Group.IsFieldVisible(Self))); end; function TcxPivotGridField.IsFirstFieldInGroup: Boolean; begin Result := (Group <> nil) and (Group.Fields[0] = Self); end; procedure TcxPivotGridField.SetArea(AValue: TcxPivotGridFieldArea); begin if not (AValue in AllowedAreas) then AValue := FArea; if CanModifyArea and (FArea <> AValue) then begin FArea := AValue; AreaIndex := MaxInt; if PivotGrid.IsRestoring and IsFirstFieldInGroup then Group.InternalSetArea(FArea); DataChanged; end; end; procedure TcxPivotGridField.SetAreaIndex(AValue: Integer); begin AValue := Max(-1, AValue); if (PivotGrid <> nil) and CanModifyArea then begin if (Group <> nil) and (AValue > ViewInfo.AreaIndex) then Dec(AValue, Max(0, Group.VisibleCount - 1)); if not PivotGrid.SetFieldAreaIndex(Self, Area, AValue) then FAreaIndex := AValue; // clear expanding information because field position changed ExpandingInfo.Clear; if not PivotGrid.IsLocked then PivotGrid.DoFieldPosChanged(Self); DataChanged; end; end; procedure TcxPivotGridField.SetCaption(const AValue: string); begin if AValue <> Caption then begin FCaption := AValue; FIsCaptionAssigned := True; Changed; end; end; procedure TcxPivotGridField.SetCustomTotals( AValue: TcxPivotGridCustomTotalCollection); begin FCustomTotals.Assign(AValue); end; procedure TcxPivotGridField.SetDataBinding(AValue: TcxPivotGridFieldDataBinding); begin FDataBinding.Assign(AValue); end; procedure TcxPivotGridField.SetDataVisibility(AValue: TcxPivotGridFieldDataVisibility); begin if AValue <> FDataVisibility then begin FDataVisibility := AValue; Changed; end; end; procedure TcxPivotGridField.SetDisplayFormat(const AValue: string); begin if FDisplayFormat <> AValue then begin FDisplayFormat := AValue; Changed; end; end; procedure TcxPivotGridField.SetGroup(AValue: TcxPivotGridFieldGroup); begin if (Group = AValue) or (csDestroying in ComponentState) then Exit; PivotGrid.BeginUpdate; try if Group <> nil then Group.Remove(Self); FGroup := AValue; if Group <> nil then Group.Add(Self); Changed; finally PivotGrid.EndUpdate; end; end; procedure TcxPivotGridField.SetGroupExpanded(AValue: Boolean); begin if FGroupExpanded <> AValue then begin FGroupExpanded := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetGroupIndex(AValue: Integer); begin AValue := Min(Max(-1, AValue), PivotGrid.Groups.Count - 1); if AValue < 0 then SetGroup(nil) else SetGroup(PivotGrid.Groups[AValue]); end; procedure TcxPivotGridField.SetGroupInterval( AValue: TcxPivotGridGroupInterval); begin if FGroupInterval <> AValue then begin FGroupInterval := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetGroupIntervalRange(AValue: Integer); begin AValue := Max(1, AValue); if AValue <> FGroupIntervalRange then begin FGroupIntervalRange := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetHidden(AValue: Boolean); begin if AValue <> FHidden then begin FHidden := AValue; Changed; end; end; procedure TcxPivotGridField.SetImageAlign(AValue: TAlignment); begin if FImageAlign <> AValue then begin FImageAlign := AValue; Changed; end; end; procedure TcxPivotGridField.SetImageIndex(AValue: TImageIndex); begin if FImageIndex <> AValue then begin FImageIndex := AValue; Changed; end; end; procedure TcxPivotGridField.SetIndex(AValue: Integer); function ValidateIndex(AValue, AMin, AMax: Integer): Integer; begin Result := AValue; if AValue < AMin then Result := AMin else if AValue > AMax then Result := AMax; end; begin if (Index <> AValue) and (PivotGrid <> nil) then begin with PivotGrid.FieldList do Exchange(ValidateIndex(Index, 0, Count - 1), ValidateIndex(AValue, 0, Count - 1)); PivotGrid.DataController.UpdateItemIndexes; end; end; procedure TcxPivotGridField.SetMinWidth(AValue: Integer); begin AValue := Max(0, AValue); if FMinWidth <> AValue then begin FMinWidth := AValue; Width := Width; Changed; end; end; procedure TcxPivotGridField.SetOnGetProperties(AValue: TcxPivotGridGetPropertiesEvent); begin if @FOnGetProperties <> @AValue then begin FOnGetProperties := AValue; Changed; end; end; procedure TcxPivotGridField.SetOptions(AValue: TcxPivotGridFieldOptions); begin FOptions.Assign(AValue); end; procedure TcxPivotGridField.SetProperties(Value: TcxCustomEditProperties); begin if (FProperties <> nil) and (Value <> nil) then FProperties.Assign(Value); end; procedure TcxPivotGridField.SetPropertiesClass(Value: TcxCustomEditPropertiesClass); begin if FPropertiesClass <> Value then begin FPropertiesClass := Value; RecreateProperties; PropertiesValueChanged; PropertiesChanged; end; end; procedure TcxPivotGridField.SetPropertiesClassName(const Value: string); begin PropertiesClass := TcxCustomEditPropertiesClass(GetRegisteredEditProperties.FindByClassName(Value)); end; procedure TcxPivotGridField.SetRepositoryItem(Value: TcxEditRepositoryItem); begin if FRepositoryItem <> Value then begin if FRepositoryItem <> nil then FRepositoryItem.RemoveListener(Self); FRepositoryItem := Value; if FRepositoryItem <> nil then FRepositoryItem.AddListener(Self); PropertiesValueChanged; PropertiesChanged; end; end; procedure TcxPivotGridField.SetSortOrder(AValue: TcxDataSortOrder); begin if FSortOrder <> AValue then begin FSortOrder := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetSortBySummaryInfo( AValue: TcxPivotGridSortBySummaryInfo); begin FSortBySummaryInfo.Assign(AValue); DataChanged; end; procedure TcxPivotGridField.SetStyles(AValue: TcxPivotGridFieldStyles); begin FStyles.Assign(AValue); end; procedure TcxPivotGridField.SetSummaryType(AValue: TcxPivotGridSummaryType); begin if FSummaryType <> AValue then begin FSummaryType := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetSummaryVariation(AValue: TcxPivotGridSummaryVariation); begin if SummaryVariation <> AValue then begin FSummaryVariation := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetTotalsVisibility( AValue: TcxPivotGridTotalsVisibility); begin if AValue <> FTotalsVisibility then begin FTotalsVisibility := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetTopValueCount(AValue: Integer); begin if AValue <> FTopValueCount then begin FTopValueCount := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetTopValueShowOthers(AValue: Boolean); begin if AValue <> FTopValueShowOthers then begin FTopValueShowOthers := AValue; DataChanged; end; end; procedure TcxPivotGridField.SetUniqueName(const AValue: WideString); begin if FUniqueName <> AValue then begin FUniqueName := AValue; SynchronizeUniqueName; end; end; procedure TcxPivotGridField.SetValueByRecordIndex( ARecordIndex: Integer; const AValue: Variant); begin PivotGrid.DataController.Values[PivotGrid.DataController.GetRowInfo(ARecordIndex).RecordIndex, Index] := AValue; end; procedure TcxPivotGridField.SetVisible(AValue: Boolean); begin if AValue <> FVisible then begin FVisible := AValue; if FAreaIndex = -1 then AreaIndex := MaxInt; FViewInfo.FBackground := nil; DataChanged; end; end; procedure TcxPivotGridField.SetWidth(AValue: Integer); begin if AValue <> 0 then AValue := Max(MinWidth, AValue); if AValue <> FWidth then begin FWidth := AValue; Changed(True); if PivotGrid <> nil then PivotGrid.DoFieldSizeChanged(Self); end; end; procedure TcxPivotGridField.FilterChanged(Sender: TObject); begin DoFilterChanged; end; procedure TcxPivotGridField.InternalDoGetDisplayText(ACell: TcxPivotGridDataCellViewInfo; var AText: string); begin if GetDisplayTextAssigned then FOnGetDisplayText(Self, ACell, AText); end; function TcxPivotGridField.IsAllowedAreasStored: Boolean; begin Result := FAllowedAreas <> [faColumn..faData]; if FLink <> nil then Result := FAllowedAreas <> DimensionAllowedAreas[FLink.IsMeasure]; end; function TcxPivotGridField.IsCustomTotalStored: Boolean; begin Result := CustomTotals.Count > 0; end; procedure TcxPivotGridField.ChangeExpanding; begin GroupExpanded := not GroupExpanded; end; procedure TcxPivotGridField.ChangeSorting; const InvertedSortOrders: array[TcxDataSortOrder] of TcxDataSortOrder = (soDescending, soDescending, soAscending); begin if (ViewInfo.State = cxbsPressed) then begin if not PivotGrid.IsDesigning and Options.CanSorting then begin PivotGrid.ShowHourglassCursor; try SortOrder := InvertedSortOrders[SortOrder]; finally PivotGrid.HideHourglassCursor; end end else SetState(cxbsNormal); end; end; function TcxPivotGridField.GetViewInfo: TcxPivotGridFieldHeaderCellViewInfo; begin Result := ViewInfo; end; procedure TcxPivotGridField.SetState(AState: TcxButtonState); begin ViewInfo.State := AState; PivotGrid.InvalidateRect(ViewInfo.Bounds, False); end; procedure TcxPivotGridField.CreateProperties; begin if FPropertiesClass <> nil then begin FProperties := FPropertiesClass.Create(Self); FProperties.OnPropertiesChanged := PropertiesChangedHandler; end; end; procedure TcxPivotGridField.DestroyProperties; begin FreeAndNil(FProperties); end; procedure TcxPivotGridField.RecreateProperties; begin DestroyProperties; CreateProperties; end; { TcxPivotGridCustomCustomizationForm } constructor TcxPivotGridCustomCustomizationForm.Create(AOwner: TComponent); begin inherited CreateNew(nil); FPivotGrid := AOwner as TcxCustomPivotGrid; Init; CreateControls; RefreshList; Constraints.MinWidth := cxPivotGridCustomizationMinWidth; Constraints.MinHeight := cxPivotGridCustomizationMinHeight; end; destructor TcxPivotGridCustomCustomizationForm.Destroy; begin if not PivotGrid.IsDestroying then begin PivotGrid.Customization.FForm := nil; PivotGrid.Customization.FFormBounds := BoundsRect; end; inherited Destroy; end; procedure TcxPivotGridCustomCustomizationForm.RefreshList; begin end; procedure TcxPivotGridCustomCustomizationForm.CreateControls; begin end; procedure TcxPivotGridCustomCustomizationForm.CreateParams( var Params: TCreateParams); begin inherited; with Params do begin Style := Style or WS_POPUP; if not PivotGrid.IsDestroying then WndParent := PivotGrid.Handle else WndParent := 0; end; end; procedure TcxPivotGridCustomCustomizationForm.DoClose(var Action: TCloseAction); begin {$IFDEF DELPHI10} Hide; {$ENDIF} FreeAndNil(FHookTimer); Action := caFree; end; procedure TcxPivotGridCustomCustomizationForm.DoCustomDrawFieldHeader( ACanvas: TcxCanvas; ACell: TcxPivotGridCustomCellViewInfo; var ADone: Boolean); begin PivotGrid.Painter.DoCustomDrawFieldHeader(ACanvas, ACell, ADone); end; procedure TcxPivotGridCustomCustomizationForm.DoShow; begin if FHookTimer = nil then begin FHookTimer := TcxTimer.Create(nil); with FHookTimer do begin Interval := 100; OnTimer := HookTimerHandler; end; end; inherited DoShow; end; function TcxPivotGridCustomCustomizationForm.GetDragAndDropObjectClass( AField: TcxPivotGridField): TcxDragAndDropObjectClass; begin Result := TcxPivotGridDragAndDropObject; PivotGrid.Controller.DownField := AField; end; procedure TcxPivotGridCustomCustomizationForm.Init; var I: Integer; const UnusedItems: array[0..4, 0..1] of Integer = ((7, MF_BYPOSITION), (5, MF_BYPOSITION), (SC_MAXIMIZE, MF_BYCOMMAND), (SC_MINIMIZE, MF_BYCOMMAND), (SC_RESTORE, MF_BYCOMMAND)); begin Caption := cxGetResourceString(@scxFieldListCaption); BorderStyle := bsSizeToolWin; BorderIcons := [biSystemMenu]; Font.Assign(PivotGrid.Font); Width := cxPivotGridCustomizationDefaultWidth; Height := cxPivotGridCustomizationDefaultHeight; Color := clBtnFace; FontHeight := cxTextHeight(Font); for I := 0 to High(UnusedItems) do DeleteMenu(GetSystemMenu(Handle, False), UnusedItems[I, 0], UnusedItems[I, 1]); end; function TcxPivotGridCustomCustomizationForm.GetIsLocked: Boolean; begin Result := PivotGrid.IsLocked end; function TcxPivotGridCustomCustomizationForm.GetLookAndFeel: TcxLookAndFeel; begin Result := PivotGrid.LookAndFeel; end; function TcxPivotGridCustomCustomizationForm.GetPainter: TcxCustomLookAndFeelPainterClass; begin Result := PivotGrid.LookAndFeelPainter; end; procedure TcxPivotGridCustomCustomizationForm.HookTimerHandler(Sender: TObject); begin if IsIconic(Application.Handle) then Visible := False else if not PivotGrid.Visible or not IsWindowVisible(PivotGrid.Handle) then PivotGrid.Customization.Visible := False else if not Visible then begin ShowWindow(Handle, SW_SHOWNOACTIVATE); Visible := True; end; end; { TcxPivotGridCustomization } destructor TcxPivotGridCustomization.Destroy; begin FreeAndNil(FForm); inherited Destroy; end; procedure TcxPivotGridCustomization.CustomizationFormNeeded; begin if FForm = nil then begin FForm := cxPivotGridCustomizationFormClass.Create(PivotGrid); FForm.OnShow := OnShowCustomization; FForm.OnHide := OnHideCustomization; if IsRectEmpty(FFormBounds) then begin FFormBounds.BottomRight := PivotGrid.ClientToScreen(PivotGrid.ClientRect.BottomRight); FFormBounds.Left := FFormBounds.Right - FForm.Width; FFormBounds.Top := FFormBounds.Bottom - FForm.Height; end end; end; procedure TcxPivotGridCustomization.CustomizationVisibleChanged; begin PivotGrid.DoCustomization; end; procedure TcxPivotGridCustomization.OnShowCustomization(Sender: TObject); begin CustomizationVisibleChanged; end; procedure TcxPivotGridCustomization.OnHideCustomization(Sender: TObject); begin FFormBounds := Form.BoundsRect; CustomizationVisibleChanged; end; procedure TcxPivotGridCustomization.Refresh; begin if Visible then begin if Form.IsLocked then PostMessage(PivotGrid.Handle, WM_REFRESHCUSTOMIZATION, 0, 0) else Form.RefreshList; end; end; function TcxPivotGridCustomization.GetForm: TcxPivotGridCustomCustomizationForm; begin CustomizationFormNeeded; Result := FForm; end; function TcxPivotGridCustomization.GetFormBounds: TRect; begin if Visible then Result := Form.BoundsRect else Result := FFormBounds; end; function TcxPivotGridCustomization.GetVisible: Boolean; begin Result := (FForm <> nil) and Form.Visible; end; procedure TcxPivotGridCustomization.SetVisible(AValue: Boolean); begin if AValue <> Visible then begin CustomizationFormNeeded; if AValue then begin Form.BoundsRect := FFormBounds; Form.RefreshList; end else FreeAndNil(Form.FHookTimer); Form.Visible := AValue; end; end; procedure TcxPivotGridCustomization.SetFormBounds(const AValue: TRect); begin if not Visible then FFormBounds := AValue else FForm.BoundsRect := AValue; end; { TcxPivotGridResizingObject } procedure TcxPivotGridResizingObject.BeginDragAndDrop; begin SizingBounds := ViewInfo.RowsBounds; SizingBounds.Right := ViewInfo.Bounds.Right; if CurMousePos.Y <= SizingBounds.Top then begin with ViewInfo.ColumnsBounds do begin SizingBounds.Left := Left; SizingBounds.Top := Bottom - ViewInfo.HeaderHeight; end; end; StartPos := CurMousePos.X; FSizeCursorPos := CurMousePos.X; SizableObject := HitTest.ResizeField; StartPosDelta := HitTest.ResizeFieldStartPos - StartPos; SizingBounds.Left := CurMousePos.X - SizableObject.GetActualWidth + SizableObject.GetMinWidth; inherited BeginDragAndDrop; end; procedure TcxPivotGridResizingObject.DirtyChanged; begin Canvas.InvertRect(SizeMarkBounds); end; procedure TcxPivotGridResizingObject.DragAndDrop( const P: TPoint; var Accepted: Boolean); begin Accepted := True; SizeCursorPos := P.X; inherited DragAndDrop(P, Accepted); end; function TcxPivotGridResizingObject.GetDragAndDropCursor( Accepted: Boolean): TCursor; begin Result := crcxPivotGridHorzSize; end; function TcxPivotGridResizingObject.GetImmediateStart: Boolean; begin Result := True; end; function TcxPivotGridResizingObject.GetSizeDelta: Integer; begin Result := SizeCursorPos - StartPos; end; function TcxPivotGridResizingObject.GetSizeMarkBounds: TRect; begin Result := cxRectSetWidth(SizingBounds, Min(Max(SizingBounds.Left, StartPos + SizeDelta + StartPosDelta), SizingBounds.Right) - 1, cxPivotGridSizeMarkWidth); end; procedure TcxPivotGridResizingObject.SetSizeCursorPos(AValue: Integer); begin if FSizeCursorPos <> AValue then begin Dirty := True; FSizeCursorPos := AValue; end; end; procedure TcxPivotGridResizingObject.EndDragAndDrop(Accepted: Boolean); begin inherited EndDragAndDrop(Accepted); if Accepted and (SizeDelta <> 0) then SetSizeDelta(SizeDelta); end; procedure TcxPivotGridResizingObject.SetSizeDelta(ADelta: Integer); begin SizableObject.SetWidth(SizableObject.GetActualWidth + ADelta); PivotGrid.Modified; end; { TcxPivotGridFilterMRUItem } function GetFilterStream(AFilter: TcxDataFilterCriteria): TMemoryStream; begin Result := TMemoryStream.Create; AFilter.WriteData(Result); end; constructor TcxPivotGridFilterMRUItem.Create(AFilter: TcxDataFilterCriteria); begin inherited Create; Filter := AFilter.DataController.CreateFilter; Filter.Assign(AFilter); end; destructor TcxPivotGridFilterMRUItem.Destroy; begin Filter.Free; inherited; end; function TcxPivotGridFilterMRUItem.GetCaption: string; begin Result := Filter.FilterCaption; end; function TcxPivotGridFilterMRUItem.StreamEquals(AStream: TMemoryStream): Boolean; var AOwnStream: TMemoryStream; begin AOwnStream := GetStream; try Result := StreamsEqual(AOwnStream, AStream); finally AStream.Free; AOwnStream.Free; end; end; procedure TcxPivotGridFilterMRUItem.AssignTo(AFilter: TcxDataFilterCriteria); begin AFilter.AssignItems(Filter); end; function TcxPivotGridFilterMRUItem.Equals(AItem: TcxMRUItem): Boolean; begin Result := StreamEquals(TcxPivotGridFilterMRUItem(AItem).GetStream); end; function TcxPivotGridFilterMRUItem.FilterEquals(AFilter: TcxDataFilterCriteria): Boolean; begin Result := StreamEquals(GetFilterStream(AFilter)); end; function TcxPivotGridFilterMRUItem.GetStream: TMemoryStream; begin Result := GetFilterStream(Filter); end; { TcxPivotGridFilterMRUItems } constructor TcxPivotGridFilterMRUItems.Create(APivotGrid: TcxCustomPivotGrid); begin inherited Create; FPivotGrid := APivotGrid; FVisibleItems := TList.Create; end; destructor TcxPivotGridFilterMRUItems.Destroy; begin FVisibleItems.Free; inherited; end; function TcxPivotGridFilterMRUItems.GetItem(Index: Integer): TcxPivotGridFilterMRUItem; begin Result := TcxPivotGridFilterMRUItem(inherited Items[Index]); end; function TcxPivotGridFilterMRUItems.GetVisibleCount: Integer; begin Result := FVisibleItems.Count; end; function TcxPivotGridFilterMRUItems.GetVisibleItem(Index: Integer): TcxPivotGridFilterMRUItem; begin Result := TcxPivotGridFilterMRUItem(FVisibleItems[Index]); end; procedure TcxPivotGridFilterMRUItems.SetVisibleCount(AValue: Integer); begin if AValue <> 0 then MaxCount := AValue + 1 else MaxCount := 0; RefreshVisibleItemsList; end; procedure TcxPivotGridFilterMRUItems.RefreshVisibleItemsList; var AFilter: TcxDataFilterCriteria; I: Integer; AItem: TcxPivotGridFilterMRUItem; begin AFilter := PivotGrid.DataController.Filter; FVisibleItems.Clear; for I := 0 to Count - 1 do begin AItem := Items[I]; if not AItem.FilterEquals(AFilter) then FVisibleItems.Add(AItem); end; end; procedure TcxPivotGridFilterMRUItems.Add(AFilter: TcxDataFilterCriteria); begin if not AFilter.IsEmpty then begin inherited Add(TcxPivotGridFilterMRUItem.Create(AFilter)); RefreshVisibleItemsList; end; end; { TcxPivotGridCrossCell } constructor TcxPivotGridCrossCell.Create(ARow, AColumn: TcxPivotGridGroupItem); begin FColumn := AColumn; FRow := ARow; FSummaryCells := TcxObjectList.Create() end; destructor TcxPivotGridCrossCell.Destroy; begin FRecords.Free; FSummaryCells.Free; inherited Destroy; end; procedure TcxPivotGridCrossCell.CalculateSummaries; begin if Calculated then Exit; Calculated := True; FSummaryCells.Clear; DoCalculateSummary; end; function TcxPivotGridCrossCell.CreateDrillDownDataSource: TcxCustomDataSource; begin if PivotGrid.IsOLAPActive then Result := PivotGrid.OLAPDataSource.CreateDrillDownDataSource(Self, PivotGrid.FieldList) else Result := TcxPivotGridCrossCellDataSource.Create(Self); end; function TcxPivotGridCrossCell.GetSummaryByField( AField: TcxPivotGridField; ASummaryType: TcxPivotGridSummaryType): Variant; begin PivotGridError(AField.SummaryIndex <> cxPivotGridInvalidIndex, cxGetResourceString(@scxFieldNotADataField)); Result := SummaryCells[AField.SummaryIndex].GetSummaryByType(ASummaryType); end; function TcxPivotGridCrossCell.GetSummaryValue( ASummary: TcxPivotGridCrossCellSummary; AType: TcxPivotGridSummaryType): Variant; begin Result := ASummary.GetSummaryByType(AType); end; function TcxPivotGridCrossCell.AddSummaryCell(AField: TcxPivotGridField; ARecords: TcxPivotGridRecords): TcxPivotGridCrossCellSummary; begin Result := PivotGridCrossCellSummaryClass.Create(Self, AField); FSummaryCells.Add(Result); if PivotGrid.IsOLAPActive then Exit; if UseRawData or AField.HasSummaryVariation then Result.DoCalculateSummary(ARecords); end; procedure TcxPivotGridCrossCell.CalculateVisibleSummary; var I: Integer; ACells: TList; begin ACells := CreateCrossCellsList; try for I := 0 to SummaryCellCount - 1 do with SummaryCells[I] do begin if not DataField.HasSummaryVariation then DoCalculateSummary(ACells, GetIntermadiateValue); end; finally ACells.Free; end; end; function TcxPivotGridCrossCell.CreateCrossRecords: TcxPivotGridRecords; begin if Column.Parent = nil then Result := Row.CreateSummaryRecords else if Row.Parent = nil then Result := Column.CreateSummaryRecords else begin Result := TcxPivotGridRecords.Create; Result.CreateIntersection(Row.CreateSummaryRecords, Column.CreateSummaryRecords); end; end; function TcxPivotGridCrossCell.CreateCrossCellsList: TList; function GetSubItem(AItem: TcxPivotGridGroupItem; AIndex: Integer): TcxPivotGridGroupItem; begin Result := AItem; if AItem.Expanded and (AItem.ItemCount > 0) then Result := AItem.Items[AIndex]; end; function GetItemCount(AItem: TcxPivotGridGroupItem): Integer; begin Result := 1; if AItem.Expanded and (AItem.ItemCount > 0) then Result := AItem.ItemCount; end; var I, J: Integer; ARow: TcxPivotGridGroupItem; begin Result := TList.Create; for I := 0 to GetItemCount(Row) - 1 do begin ARow := GetSubItem(Row, I); for J := 0 to GetItemCount(Column) - 1 do Result.Add(ARow.GetCellByCrossItem(GetSubItem(Column, J))); end; end; procedure TcxPivotGridCrossCell.DoCalculateSummary; var I: Integer; begin if PivotGrid.HasSummaryVariation then begin if PivotGrid.OptionsDataField.Area = dfaRow then PrevCrossCell := GetPrevCrossCellInColumn else PrevCrossCell := GetPrevCrossCellInRow; end; FRecords.Free; FRecords := CreateCrossRecords; for I := 0 to PivotGrid.SummaryFields.Count - 1 do AddSummaryCell(PivotGrid.SummaryFields[I], FRecords); if not UseRawData or PivotGrid.IsOLAPActive then CalculateVisibleSummary; for I := 0 to SummaryCellCount - 1 do with SummaryCells[I] do begin CalculateSummaryVariation; CalculateCustomSummary; end; end; function TcxPivotGridCrossCell.IsCalculationAvailable: Boolean; begin Result := True; end; procedure TcxPivotGridCrossCell.GetDataTypes( ADataField: TcxPivotGridField; var ASourceType, AFloatType: Integer); var AType: TcxValueTypeClass; begin ASourceType := varCurrency; AFloatType := varCurrency; if ADataField <> nil then begin AType := DataController.GetItemValueTypeClass(ADataField.Index); if (AType <> nil) and not ADataField.IsCurrency(AType) then begin if AType.GetVarType in OrdinalTypeSet then ASourceType := varInteger else ASourceType := varDouble; AFloatType := varDouble; end; end; end; function TcxPivotGridCrossCell.GetIsEmpty: Boolean; begin Result := Records.Count = 0; end; function TcxPivotGridCrossCell.GetPrevCrossCellInRow: TcxPivotGridCrossCell; var APrev: TcxPivotGridGroupItem; begin APrev := Column.GetPrev; if APrev = nil then Result := nil else Result := Row.GetCellByCrossItem(APrev); end; function TcxPivotGridCrossCell.GetPrevCrossCellInColumn: TcxPivotGridCrossCell; var APrev: TcxPivotGridGroupItem; begin APrev := Row.GetPrev; if APrev = nil then Result := nil else Result := APrev.GetCellByCrossItem(Column); end; function TcxPivotGridCrossCell.GetDataController: TcxCustomDataController; begin Result := PivotGrid.DataController; end; function TcxPivotGridCrossCell.GetPivotGrid: TcxCustomPivotGrid; begin Result := Column.PivotGrid; end; function TcxPivotGridCrossCell.GetSummaryCellCount: Integer; begin Result := FSummaryCells.Count; end; function TcxPivotGridCrossCell.GetUseRawData: Boolean; begin Result := not PivotGrid.IsOLAPActive and (PivotGrid.OptionsData.CalculationBase = cbRawData); if not Result then Result := ((Row.ItemCount + Column.ItemCount) = 0) or (not Row.Expanded and not Column.Expanded); end; function TcxPivotGridCrossCell.GetSummaryCell(AIndex: Integer): TcxPivotGridCrossCellSummary; begin Result := TcxPivotGridCrossCellSummary(FSummaryCells.List^[AIndex]); end; { TcxPivotGridOLAPCrossCell } function TcxPivotGridOLAPCrossCell.GetSummaryByField( AField: TcxPivotGridField; ASummaryType: TcxPivotGridSummaryType): Variant; begin Result := Null; PivotGridError(AField.SummaryIndex <> cxPivotGridInvalidIndex, cxGetResourceString(@scxFieldNotADataField)); if IsCalculationAvailable then Result := FNativeValues[AField.SummaryIndex] end; function TcxPivotGridOLAPCrossCell.GetSummaryValue( ASummary: TcxPivotGridCrossCellSummary; AType: TcxPivotGridSummaryType): Variant; begin if IsCalculationAvailable then Result := FNativeValues[ASummary.DataField.SummaryIndex] else Result := inherited GetSummaryValue(ASummary, AType); end; procedure TcxPivotGridOLAPCrossCell.GetDataTypes( ADataField: TcxPivotGridField; var ASourceType, AFloatType: Integer); begin inherited GetDataTypes(ADataField, ASourceType, AFloatType); if not IsCalculationAvailable then Exit; ASourceType := VarType(NativeValues[ADataField.SummaryIndex]); AFloatType := ASourceType; if not VarTypeIsCurrency(ASourceType) then begin if ASourceType in OrdinalTypeSet then ASourceType := varInteger; AFloatType := varDouble; end; end; function TcxPivotGridOLAPCrossCell.GetIsEmpty: Boolean; begin Result := FIsEmpty; end; function TcxPivotGridOLAPCrossCell.IsCalculationAvailable: Boolean; begin Result := VarIsArray(FNativeValues); end; { TcxPivotGridCrossCellSummary } constructor TcxPivotGridCrossCellSummary.Create( AOwner: TcxPivotGridCrossCell; ADataField: TcxPivotGridField); begin FOwner := AOwner; FDataField := ADataField; end; procedure TcxPivotGridCrossCellSummary.Clear; var I: TcxPivotGridSummaryType; begin for I := Low(TcxPivotGridSummaryType) to High(TcxPivotGridSummaryType) do FSummaries[I] := Null; FSummaryVariation := Null; end; function TcxPivotGridCrossCellSummary.GetSummaryByType( AType: TcxPivotGridSummaryType): Variant; begin Result := FSummaries[AType]; end; function TcxPivotGridCrossCellSummary.GetSummaryValue( AType: TcxPivotGridSummaryType): Variant; begin Result := Owner.GetSummaryValue(Self, AType); end; function TcxPivotGridCrossCellSummary.GetValue(ARecordIndex: Integer): Variant; begin Result := DataField.Values[ARecordIndex]; end; procedure TcxPivotGridCrossCellSummary.CalculateCustomSummary; begin DataField.DoCalculateCustomSummary(Self); end; procedure TcxPivotGridCrossCellSummary.CalculateSummaryVariation; procedure CalculateVariation; var APrevCell: TcxPivotGridCrossCellSummary; APrevValue, APrevValueEx, AValue: Variant; begin if Owner.PrevCrossCell <> nil then APrevCell := Owner.PrevCrossCell.SummaryCells[DataField.SummaryIndex] else APrevCell := nil; if APrevCell <> nil then begin // skip null values repeat APrevValue := APrevCell.GetSummaryByType(DataField.SummaryType); APrevValueEx := APrevValue; if not VariationNullIgnore or VarIsNumericEx(APrevValue) then begin if not VarIsNumericEx(APrevValue) then APrevValue := 0; Break; end else APrevCell := GetPrevCell(APrevCell); until APrevCell = nil; if APrevCell = nil then APrevValueEx := Null; AValue := GetSummaryByType(DataField.SummaryType); if VarIsNull(AValue) and VarIsNull(APrevValueEx) then Exit; if not VarIsNumericEx(AValue) and not VariationNullIgnore then AValue := 0; try case DataField.SummaryVariation of svAbsolute: FSummaryVariation := AValue - APrevValue; svPercent: begin if VarIsNull(APrevValue) or (VarIsNumericEx(APrevValue) and (APrevValue = 0)) then FSummaryVariation := Null else begin FSummaryVariation := (AValue - APrevValue) * 100 / APrevValue; if not VarIsNull(FSummaryVariation) then VarCast(FSummaryVariation, FSummaryVariation, varDouble); end; end; end; except on EMathError do FSummaryVariation := Null; on EDivByZero do FSummaryVariation := Null; on EVariantError do FSummaryVariation := Null; else raise; end; end; end; procedure CalculateRelation; var AValue, AOwnerValue: Variant; begin AValue := GetSummaryByType(DataField.SummaryType); try case DataField.SummaryVariation of svPercentOfColumn: if Owner.Row.Parent <> nil then AOwnerValue := Owner.Row.Parent.GetCellByCrossItem(Owner.Column).GetSummaryByField(DataField, DataField.SummaryType) else AOwnerValue := AValue; svPercentOfRow: if Owner.Column.Parent <> nil then AOwnerValue := Owner.Column.Parent.GetCellByCrossItem(Owner.Row).GetSummaryByField(DataField, DataField.SummaryType) else AOwnerValue := AValue; end; FSummaryVariation := AValue / AOwnerValue * 100; except on EMathError do FSummaryVariation := Null; on EDivByZero do FSummaryVariation := Null; on EVariantError do FSummaryVariation := Null; else raise; end; end; begin if not DataField.HasSummaryVariation then Exit; if DataField.SummaryVariation in [svAbsolute, svPercent] then CalculateVariation else CalculateRelation; end; procedure TcxPivotGridCrossCellSummary.CheckValue(var AValue: Variant); {$IFDEF DELPHI6} {$IFNDEF NONDB} var ACurr: Currency; {$ENDIF} {$ENDIF} begin {$IFDEF DELPHI6} {$IFNDEF NONDB} if TVarData(AValue).VType = VarSQLTimeStamp then AValue := TDateTime(AValue) else if TVarData(AValue).VType = VarFMTBcd then begin if BcdToCurr(VarToBcd(AValue), ACurr) then AValue := Currency(ACurr) else AValue := Double(BcdToDouble(VarToBcd(AValue))); end; {$ENDIF} {$ENDIF} end; procedure TcxPivotGridCrossCellSummary.DoCalculateSummary( ARecords: TList; AGetValueProc: TcxPivotGridGetRecordValueProc = nil); var ACount, ANotNumericCount, ASourceType, AFloatType: Integer; AMinV, AMaxV, ASourceValue: Variant; AMin, AMax, ASum, ASumSquares, AValue: Extended; AVarianceP, ATotalVariance, AVariance: Extended; procedure InitializeValues; begin ASum := 0; ACount := 0; ANotNumericCount := 0; AMinV := Null; AMaxV := Null; AMax := MinExtended; AMin := MaxExtended; ASumSquares := 0; Owner.GetDataTypes(DataField, ASourceType, AFloatType); end; procedure BaseCalculation; var I: Integer; begin for I := 0 to ARecords.Count - 1 do begin if DataField.GroupInterval <> giDefault then begin ASourceValue := AGetValueProc(ARecords[I], True); if ACount = 0 then begin AMinV := ASourceValue; AMaxV := ASourceValue; end else begin if VarCompare(AMinV, ASourceValue) > 0 then AMinV := ASourceValue; if VarCompare(AMaxV, ASourceValue) < 0 then AMaxV := ASourceValue; end; if not VarIsNumericEx(ASourceValue) then ASourceValue := 0; end else begin ASourceValue := AGetValueProc(ARecords[I], False); if not VarIsNumericEx(ASourceValue) then begin Inc(ANotNumericCount); if not SummaryNullIgnore or not VarIsNull(ASourceValue) then Inc(ACount); Continue; end; end; CheckValue(ASourceValue); AValue := ASourceValue; Inc(ACount); AMax := Math.Max(AValue, AMax); AMin := Math.Min(AValue, AMin); ASum := ASum + AValue; ASumSquares := ASumSquares + Sqr(AValue); end; end; procedure PostCalculation; begin ATotalVariance := ASumSquares - Sqr(ASum)/ACount; AVarianceP := ATotalVariance / ACount; end; procedure AssignCalculatedValues; begin SetSummaryByType(stCount, ACount, varInteger); if ANotNumericCount = ARecords.Count then Exit; SetSummaryByType(stSum, ASum, ASourceType); if DataField.GroupInterval = giDefault then begin SetSummaryByType(stMax, AMax, ASourceType); SetSummaryByType(stMin, AMin, ASourceType); end else begin FSummaries[stMax] := AMaxV; FSummaries[stMin] := AMinV; end; SetSummaryByType(stAverage, ASum / ACount, AFloatType); SetSummaryByType(stVarianceP, AVarianceP, AFloatType); SetSummaryByType(stStdDevP, Sqrt(Math.Max(0, AVarianceP)), AFloatType); if Count > 1 then begin AVariance := ATotalVariance / (ACount - 1); SetSummaryByType(stVariance, AVariance, AFloatType); SetSummaryByType(stStdDev, Sqrt(Math.Max(0, AVariance)), AFloatType); end; end; begin if not Assigned(AGetValueProc) then AGetValueProc := GetRecordValue; Clear; if not Owner.IsCalculationAvailable then Exit; InitializeValues; BaseCalculation; if ACount <> 0 then begin PostCalculation; AssignCalculatedValues; end; end; function TcxPivotGridCrossCellSummary.GetIntermadiateValue( const ACell: Pointer; AIsGroupValue: Boolean): Variant; begin Result := TcxPivotGridCrossCell(ACell).GetSummaryByField( FDataField, FDataField.SummaryType); end; function TcxPivotGridCrossCellSummary.GetRecordValue( const ARecord: Pointer; AIsGroupValue: Boolean): Variant; begin if AIsGroupValue then Result := DataField.GetGroupValue(Integer(ARecord)) else Result := GetValue(Integer(ARecord)); end; function TcxPivotGridCrossCellSummary.GetPrevCell( APrevCell: TcxPivotGridCrossCellSummary): TcxPivotGridCrossCellSummary; begin if (APrevCell = nil) or (APrevCell.Owner.PrevCrossCell = nil) then Result := nil else Result := APrevCell.Owner.PrevCrossCell.SummaryCells[DataField.SummaryIndex]; end; procedure TcxPivotGridCrossCellSummary.SetSummaryByIndex( AIndex: Integer; AValue: Variant); begin FSummaries[TcxPivotGridSummaryType(AIndex)] := AValue; end; procedure TcxPivotGridCrossCellSummary.SetSummaryByType( AType: TcxPivotGridSummaryType; const AValue: Extended; AVarType: Integer); begin // todo: need check floating point overflow then conversion Extended to Currency if not VarIsNull(AValue) then try if (AVarType = varInteger) and (AValue > MaxInt) then FSummaries[AType] := AValue else VarCast(FSummaries[AType], AValue, AVarType) except on EVariantError do if AVarType = varDouble then VarCast(FSummaries[AType], AValue, varCurrency); end else FSummaries[AType] := AValue; end; function TcxPivotGridCrossCellSummary.GetDataController: TcxCustomDataController; begin Result := Owner.DataController; end; function TcxPivotGridCrossCellSummary.GetSummaryByIndex( AIndex: Integer): Variant; begin Result := GetSummaryByType(TcxPivotGridSummaryType(AIndex)); end; function TcxPivotGridCrossCellSummary.GetSummaryNullIgnore: Boolean; begin Result := Owner.PivotGrid.OptionsData.SummaryNullIgnore; end; function TcxPivotGridCrossCellSummary.GetRecords: TcxPivotGridRecords; begin Result := Owner.Records; end; function TcxPivotGridCrossCellSummary.GetVariationNullIgnore: Boolean; begin Result := Owner.PivotGrid.OptionsData.VariationNullIgnore; end; { TcxPivotGridGroupItem } constructor TcxPivotGridGroupItem.Create(AParent: TcxPivotGridGroupItem; ADataController: TcxCustomDataController; ARecordIndex: Integer; AField: TcxPivotGridField); begin FParent := AParent; FDataController := ADataController; FRecordIndex := ARecordIndex; FField := AField; FItems := TcxObjectList.Create; FRecords := TcxPivotGridRecords.Create; FExpanded := True; end; destructor TcxPivotGridGroupItem.Destroy; begin FreeAndNil(FItems); FreeAndNil(FRecords); inherited Destroy; end; function TcxPivotGridGroupItem.AddChild( AClass: TcxPivotGridGroupItemClass): TcxPivotGridGroupItem; begin Result := AClass.Create(Self, DataController, -1, nil); ItemList.Add(Result); end; function TcxPivotGridGroupItem.AddChild(AIndex, ARecordIndex: Integer; AField: TcxPivotGridField): TcxPivotGridGroupItem; begin Result := ChildItemsClass.Create(Self, DataController, ARecordIndex, AField); ItemList.Insert(AIndex, Result); end; function TcxPivotGridGroupItem.ChildrenNeeded: Boolean; begin Result := not Expanded and HasChildren and (ItemCount = 0); end; function TcxPivotGridGroupItem.Compare(const AValue: Variant): Integer; begin if VarIsStr(Value) and VarIsStr(AValue) then Result := PivotGrid.OptionsData.CompareAsString(Value, AValue) else Result := VarCompare(Value, AValue); if PivotGrid.CustomSortAssigned then PivotGrid.DoCompare(Field, Value, AValue, Result); end; function TcxPivotGridGroupItem.CreateSummaryRecords: TcxPivotGridRecords; procedure ProcessItem(AItem: TcxPivotGridGroupItem); var I, ARecord: Integer; begin if AItem.ItemCount > 0 then for I := 0 to AItem.ItemCount - 1 do ProcessItem(AItem.Items[I]) else for I := 0 to AItem.Records.Count - 1 do begin ARecord := AItem.Records[I]; if PivotGrid.DataBuilder.FilteredIndexes[ARecord] > -1 then Result.Add(ARecord); end; end; var I: Integer; begin Result := TcxPivotGridRecords.Create; if Parent = nil then begin Result.Capacity := PivotGrid.RecordCount; for I := 0 to PivotGrid.RecordCount - 1 do if PivotGrid.DataBuilder.FilteredIndexes[I] > -1 then Result.Add(I); end else //todo: Need non recursive ProcessItem(Self); end; procedure TcxPivotGridGroupItem.DeleteChildren; begin FItems.Clear; end; function TcxPivotGridGroupItem.GetCellByCrossItem( AItem: TcxPivotGridGroupItem): TcxPivotGridCrossCell; begin Result := nil; end; function TcxPivotGridGroupItem.GetPrev: TcxPivotGridGroupItem; var AItem: TcxPivotGridGroupItem; begin Result := nil; AItem := Self; while (AItem.Index = 0) and (AItem.Level > 0) do AItem := AItem.Parent; if AItem.Index = 0 then Exit; AItem := AItem.getPrevSibling; while (AItem.Level > Level) and (AItem.ItemCount > 0) do AItem := AItem.Items[AItem.ItemCount - 1]; if (AItem <> nil) and (AItem.Level = Level) then Result := AItem; end; procedure TcxPivotGridGroupItem.InitializeValue( const ADisplayText: string; const AnUniqueName: WideString); begin FDisplayText := ADisplayText; FUniqueName := AnUniqueName; FInternalValue := FUniqueName; FIsValueAsssigned := True; end; procedure TcxPivotGridGroupItem.MarkDeleted; var I: Integer; AFilteredRecords: TcxPivotGridRecords; begin AFilteredRecords := PivotGrid.DataBuilder.FilteredIndexes; for I := 0 to ItemCount - 1 do Items[I].MarkDeleted; if Records <> nil then begin for I := 0 to Records.Count - 1 do AFilteredRecords[Records[I]] := cxPivotGridInvalidIndex; end; AFilteredRecords[RecordIndex] := cxPivotGridInvalidIndex; end; procedure TcxPivotGridGroupItem.RemoveChildrenFrom(AItem: TcxPivotGridGroupItem); var AIndex, I: Integer; ASubItem: TcxPivotGridGroupItem; begin for I := 0 to AItem.ItemCount - 1 do begin ASubItem := AItem.Items[I]; if not FindItem(ItemList, ASubItem.Value, AIndex, ASubItem.Field.SortOrder) then begin ASubItem.FParent := Self; ItemList.Insert(AIndex, ASubItem) end else begin Items[AIndex].RemoveChildrenFrom(ASubItem); // Items[AIndex].Records.Assign(AItem.Records, laOr); ASubItem.Free; end; end; AItem.ItemList.Count := 0; Records.Assign(AItem.Records, laOr); end; procedure TcxPivotGridGroupItem.CheckExpanding; begin FExpanded := FExpanded or (Field <> nil) and Field.IsItemExpanded(Self); end; function TcxPivotGridGroupItem.ChildItemsClass: TcxPivotGridGroupItemClass; begin Result := TcxPivotGridGroupItemClass(Self.ClassType); end; function TcxPivotGridGroupItem.GetCrossCellClass: TcxPivotGridCrossCellClass; begin Result := TcxPivotGridCrossCell; if (PivotGrid <> nil) and PivotGrid.IsOLAPActive then Result := TcxPivotGridOLAPCrossCell; end; function TcxPivotGridGroupItem.GetIsCollapsed: Boolean; begin Result := not Expanded and HasChildren; end; function TcxPivotGridGroupItem.GetIsRow: Boolean; begin Result := False; end; function TcxPivotGridGroupItem.GetItemAlwaysExpanded: Boolean; begin Result := False; end; function TcxPivotGridGroupItem.GetSize: Integer; var I: Integer; begin Result := 0; if Expanded then begin for I := 0 to ItemCount - 1 do Inc(Result, Items[I].Size) end else Result := GetSingleItemSize; end; function TcxPivotGridGroupItem.GetSingleItemSize: Integer; begin if Field <> nil then Result := Field.ActualWidth else Result := PivotGrid.OptionsView.GetActualWidth; end; function TcxPivotGridGroupItem.GetTotalsCount: Integer; begin Result := 1; if Field <> nil then begin case Field.TotalsVisibility of tvNone: Result := 0; tvCustom: Result := Field.CustomTotals.Count; end; end; end; function TcxPivotGridGroupItem.GetUniqueValue: string; begin Result := DisplayText; if Parent <> nil then Result := Parent.DisplayText + '.' + Result; end; function TcxPivotGridGroupItem.GetValue: Variant; begin if not FIsValueAsssigned then begin if Field <> nil then begin if RecordIndex >= 0 then begin FInternalValue := Field.GetGroupValue(RecordIndex); FDisplayText := Field.GetGroupValueDisplayText(FInternalValue); end else begin if RecordIndex = cxPivotGridOthersRecordIndex then FDisplayText := cxGetResourceString(@scxOthers) else FDisplayText := Field.Caption; FInternalValue := FDisplayText; end; end else FInternalValue := Null; FIsValueAsssigned := True; end; Result := FInternalValue; end; procedure TcxPivotGridGroupItem.InitSummaryValue( ACrossTotal: TcxPivotGridGroupItem); var ACrossCell: TcxPivotGridCrossCell; begin ACrossCell := GetCellByCrossItem(ACrossTotal); PivotGridError(ACrossCell <> nil, scxInvalidLayout); FSummaryValue := ACrossCell.GetSummaryByField( Field.SortBySummaryInfo.Field, Field.SortBySummaryInfo.SummaryType); end; procedure TcxPivotGridGroupItem.PostProcessGroup( ACrossTotal: TcxPivotGridGroupItem); var I: Integer; begin ProcessSortBySummary(ACrossTotal); ProcessTopValues(ACrossTotal); for I := 0 to ItemCount - 1 do Items[I].PostProcessGroup(ACrossTotal); if not FSortingValid then begin if Parent <> nil then Parent.FSortingValid := False; SetSummaryInfoDirty(ACrossTotal); ProcessSortBySummary(ACrossTotal); end; end; procedure TcxPivotGridGroupItem.ProcessSortBySummary( ACrossTotal: TcxPivotGridGroupItem); var I: Integer; begin FSortingValid := True; if (ItemCount > 0) and Items[0].FieldSortedBySummary then begin for I := 0 to ItemCount - 1 do Items[I].InitSummaryValue(ACrossTotal); ItemList.Sort(@CompareGroupItemsBySummary); for I := 0 to ItemCount - 1 do Items[I].FIndex := I; end; end; procedure TcxPivotGridGroupItem.ProcessTopValues( ACrossTotal: TcxPivotGridGroupItem); var I, ACount: Integer; AOthers: TcxPivotGridGroupItem; begin AOthers := nil; FSortingValid := True; if (ItemCount > 0) and Items[0].FieldProcessTopValues then begin ACount := Items[0].Field.TopValueCount; if Items[0].Field.TopValueShowOthers then begin AOthers := ChildItemsClass.Create(Self, DataController, cxPivotGridOthersRecordIndex, Items[0].Field); end else FSortingValid := False; for I := ItemCount - 1 downto ACount do begin if AOthers <> nil then AOthers.RemoveChildrenFrom(Items[I]) else Items[I].MarkDeleted; Items[I].Free; end; ItemList.Count := ACount; if AOthers <> nil then begin AOthers.FIndex := ItemList.Add(AOthers); AOthers.ReIndexChildren; end; end; end; procedure TcxPivotGridGroupItem.CollapseField(AField: TcxPivotGridField); begin SetFieldExpanding(AField, False); end; procedure TcxPivotGridGroupItem.ExpandField(AField: TcxPivotGridField); begin SetFieldExpanding(AField, True); end; function TcxPivotGridGroupItem.FieldProcessTopValues: Boolean; begin Result := (Field.TopValueCount <> 0) and (Field.TopValueCount < Parent.ItemCount); end; function TcxPivotGridGroupItem.FieldSortedBySummary: Boolean; begin Result := (Field <> nil) and Field.SortedBySummary; end; procedure TcxPivotGridGroupItem.ReIndexChildren(AFullReindex: Boolean = False); var I: Integer; begin for I := 0 to ItemCount - 1 do begin Items[I].FIndex := I; if AFullReindex then Items[I].ReIndexChildren(AFullReindex); end; end; procedure TcxPivotGridGroupItem.SetFieldExpanding( AField: TcxPivotGridField; AExpandState: Boolean); var I: Integer; begin PivotGrid.BeginUpdate; try PivotGrid.DataBuilder.LockExpanding; PivotGrid.ShowHourglassCursor; if (Field = AField) and ((ItemCount > 0) or HasChildren) then begin Expanded := AExpandState; if (Field <> nil) then Field.GroupExpandingChanged(Self); end else begin for I := 0 to ItemCount - 1 do Items[I].SetFieldExpanding(AField, AExpandState); end; PivotGrid.DataBuilder.UnLockExpanding; finally PivotGrid.EndUpdate; PivotGrid.HideHourglassCursor; end; end; procedure TcxPivotGridGroupItem.SetSummaryInfoDirty( ACrossTotal: TcxPivotGridGroupItem); begin end; function TcxPivotGridGroupItem.GetDisplayText: string; begin if not FIsValueAsssigned then GetValue; Result := FDisplayText; end; function TcxPivotGridGroupItem.GetDisplayValue: Variant; begin if PivotGrid.IsOLAPActive then Result := DisplayText else Result := Value; end; function TcxPivotGridGroupItem.GetExpanded: Boolean; begin Result := (ItemCount > 0) and (FExpanded or GetItemAlwaysExpanded); end; function TcxPivotGridGroupItem.GetHasChildren: Boolean; begin Result := FHasChildren or (ItemCount <> 0); end; function TcxPivotGridGroupItem.getNextSibling: TcxPivotGridGroupItem; begin if Index < (Parent.ItemCount - 1) then Result := Parent.Items[Index + 1] else Result := nil; end; function TcxPivotGridGroupItem.GetIsHierarchy: Boolean; begin Result := (Field <> nil) and (Field.Group <> nil) and (Field.Group.VisibleCount > 1); end; function TcxPivotGridGroupItem.GetItem(AIndex: Integer): TcxPivotGridGroupItem; begin Result := TcxPivotGridGroupItem(FItems.List^[AIndex]); end; function TcxPivotGridGroupItem.GetItemCount: Integer; begin Result := FItems.Count; end; function TcxPivotGridGroupItem.GetLevel: Integer; var AParent: TcxPivotGridGroupItem; begin Result := 0; AParent := Parent; while AParent <> nil do begin AParent := AParent.Parent; Inc(Result); end; Dec(Result); end; function TcxPivotGridGroupItem.GetPivotGrid: TcxCustomPivotGrid; begin Result := TcxCustomPivotGrid(DataController.GetOwner); end; function TcxPivotGridGroupItem.getPrevSibling: TcxPivotGridGroupItem; begin if Index = 0 then Result := nil else Result := Parent.Items[Index - 1]; end; procedure TcxPivotGridGroupItem.SetExpanded(AValue: Boolean); begin if FExpanded <> AValue then begin PivotGrid.ShowHourglassCursor; try FExpanded := AValue; if Field <> nil then begin Field.GroupExpandingChanged(Self); PivotGrid.Changes := PivotGrid.Changes + [gcLayout]; if PivotGrid.OptionsData.CalculationBase = cbVisibleData then PivotGrid.Changes := PivotGrid.Changes + [gcData]; PivotGrid.Invalidate; end; finally PivotGrid.HideHourglassCursor; end; end; end; procedure TcxPivotGridGroupItem.SetHasChildren(AValue: Boolean); begin if AValue = FHasChildren then Exit; FHasChildren := AValue; FExpanded := FExpanded and not FHasChildren; end; { TcxPivotGridRowItem } constructor TcxPivotGridRowItem.Create( AParent: TcxPivotGridGroupItem; ADataController: TcxCustomDataController; ARecordIndex: Integer; AField: TcxPivotGridField); begin inherited Create(AParent, ADataController, ARecordIndex, AField); FCrossCells := TcxObjectList.Create; end; destructor TcxPivotGridRowItem.Destroy; begin FreeAndNil(FCrossCells); inherited Destroy; end; procedure TcxPivotGridRowItem.DeleteChildren; begin inherited DeleteChildren; FCrossCells.Clear; FCachedCrossCell := nil; end; function TcxPivotGridRowItem.GetCellByCrossItem( AItem: TcxPivotGridGroupItem): TcxPivotGridCrossCell; var I: Integer; ACellFound: Boolean; begin ACellFound := False; Result := FCachedCrossCell; if (FCachedCrossCell = nil) or (FCachedCrossCell.Column <> AItem) then begin for I := 0 to FCrossCells.Count - 1 do begin Result := TcxPivotGridCrossCell(FCrossCells[I]); if Result.Column = AItem then begin ACellFound := True; Break; end; end; if not ACellFound then begin Result := GetCrossCellClass.Create(Self, AItem); FCrossCells.Add(Result); end; FCachedCrossCell := Result; end; Result.CalculateSummaries; end; function TcxPivotGridRowItem.GetIsRow: Boolean; begin Result := True; end; function TcxPivotGridRowItem.GetItemAlwaysExpanded: Boolean; begin Result := PivotGrid.ViewData.ExpandRows; end; function TcxPivotGridRowItem.GetSingleItemSize: Integer; begin Result := PivotGrid.ViewInfo.HeaderHeight; end; procedure TcxPivotGridRowItem.SetSummaryInfoDirty( ACrossTotal: TcxPivotGridGroupItem); var I: Integer; begin for I := 0 to FCrossCells.Count - 1 do TcxPivotGridCrossCell(FCrossCells.Items[I]).Calculated := False; end; { TcxPivotGridColumnItem } function TcxPivotGridColumnItem.GetItemAlwaysExpanded: Boolean; begin Result := PivotGrid.ViewData.ExpandColumns; end; function TcxPivotGridColumnItem.GetSingleItemSize: Integer; begin Result := inherited GetSingleItemSize; end; procedure TcxPivotGridColumnItem.SetSummaryInfoDirty( ACrossTotal: TcxPivotGridGroupItem); begin ACrossTotal.SetSummaryInfoDirty(Self); end; function TcxPivotGridColumnItem.GetCellByCrossItem( AItem: TcxPivotGridGroupItem): TcxPivotGridCrossCell; begin Result := AItem.GetCellByCrossItem(Self); end; { TcxPivotGridDataItem } function TcxPivotGridDataItem.GetSingleItemSize: Integer; begin if PivotGrid.OptionsDataField.Area = dfaRow then Result := PivotGrid.ViewInfo.HeaderHeight else Result := inherited GetSingleItemSize; end; function TcxPivotGridDataItem.GetValue: Variant; begin FDisplayText := Field.Caption; Result := FDisplayText; end; { TcxPivotGridCustomCellViewInfo } constructor TcxPivotGridCustomCellViewInfo.Create(APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); begin CalculateCellBounds(ABounds, AVisibleRect); FPainter := APainter; FViewParams := AViewParams; end; procedure TcxPivotGridCustomCellViewInfo.CheckVisibleInfo; begin if Visible and not FVisibleInfoCalculated then begin CalculateVisibleInfo; FVisibleInfoCalculated := True; end; end; procedure TcxPivotGridCustomCellViewInfo.Draw(ACanvas: TcxCanvas); var FPrevCanvas: TcxCanvas; begin FPrevCanvas := FCanvas; try FCanvas := ACanvas; CheckVisibleInfo; DoDraw; finally FCanvas := FPrevCanvas; end; end; procedure TcxPivotGridCustomCellViewInfo.AfterCustomDraw(ACanvas: TcxCanvas); begin Color := ACanvas.Brush.Color; TextColor := ACanvas.Font.Color; end; procedure TcxPivotGridCustomCellViewInfo.BeforeCustomDraw(ACanvas: TcxCanvas); begin ACanvas.SetParams(FViewParams); end; procedure TcxPivotGridCustomCellViewInfo.CalculateCellBounds( const ABounds, AVisibleRect: TRect); begin FBounds := ABounds; FVisible := cxRectIntersect(FClipRect, ABounds, AVisibleRect); FHasClipping := FVisible and not cxRectIsEqual(FClipRect, ABounds); end; procedure TcxPivotGridCustomCellViewInfo.CalculateVisibleInfo; begin end; function TcxPivotGridCustomCellViewInfo.CheckClipping( ANeedClip: Boolean): Boolean; begin Result := ANeedClip; FHasClipping := FHasClipping or ANeedClip; end; procedure TcxPivotGridCustomCellViewInfo.CorrectBoundsForPrinting(ABounds: TRect); begin //do nothing end; procedure TcxPivotGridCustomCellViewInfo.DoDraw; begin if not Transparent then Canvas.FillRect(ClipRect, FViewParams); end; function TcxPivotGridCustomCellViewInfo.ExcludeBorders( const ABounds: TRect; ABorders: TcxBorders): TRect; begin Result := ABounds; if bLeft in ABorders then Inc(Result.Left); if bTop in ABorders then Inc(Result.Top); if bRight in ABorders then Dec(Result.Right); if bBottom in ABorders then Dec(Result.Bottom); end; function TcxPivotGridCustomCellViewInfo.ExcludeFromPaint( ACanvas: TcxCanvas): Boolean; begin Result := Visible; if Result then ACanvas.ExcludeClipRect(ClipRect); end; function TcxPivotGridCustomCellViewInfo.GetHintText: string; begin Result := DisplayText; end; function TcxPivotGridCustomCellViewInfo.GetHitTest( AHitTest: TcxPivotGridHitTest): Boolean; begin CheckVisibleInfo; Result := Visible and PtInRect(ClipRect, AHitTest.HitPoint); if Result then AHitTest.FHitObject := Self; end; function TcxPivotGridCustomCellViewInfo.GetDisplayText: string; begin Result := FDisplayText; end; function TcxPivotGridCustomCellViewInfo.NeedShowHint(const APoint: TPoint): Boolean; begin Result := False; end; function TcxPivotGridCustomCellViewInfo.SetHotTrack(AHitTest: TcxPivotGridHitTest): Boolean; begin Result := False; end; function TcxPivotGridCustomCellViewInfo.GetBitmap: TBitmap; begin Result := FViewParams.Bitmap; end; function TcxPivotGridCustomCellViewInfo.GetColor: TColor; begin Result := FViewParams.Color; end; function TcxPivotGridCustomCellViewInfo.GetFont: TFont; begin Result := FViewParams.Font; end; function TcxPivotGridCustomCellViewInfo.GetTextColor: TColor; begin Result := FViewParams.TextColor; end; procedure TcxPivotGridCustomCellViewInfo.SetBitmap(AValue: TBitmap); begin FViewParams.Bitmap := AValue; end; procedure TcxPivotGridCustomCellViewInfo.SetColor(AValue: TColor); begin FViewParams.Color := AValue; end; procedure TcxPivotGridCustomCellViewInfo.SetTextColor(AValue: TColor); begin FViewParams.TextColor := AValue; end; { TcxPivotGridEditContainerViewInfo } destructor TcxPivotGridEditContainerViewInfo.Destroy; begin FProperties := nil; FreeAndNil(FEditViewInfo); ReleaseEditStyle; inherited; end; procedure TcxPivotGridEditContainerViewInfo.InitEditStyle; begin if FEditStyle = nil then FEditStyle := FDataField.GetEditStyle(FProperties, FUseLocalEditStyle); FEditStyle.Color := Color; FEditStyle.Font := Font; FEditStyle.StyleData.FontColor := TextColor; FEditStyle.ButtonTransparency := ebtHideInactive; end; procedure TcxPivotGridEditContainerViewInfo.CalculateEditViewInfo(AEditViewInfo: TcxCustomEditViewInfo; const AMousePos: TPoint); begin if FCalculated then Exit; InitEditStyle; CreateEditViewData; try FEditViewData.Data := Self; if OnGetDisplayTextSupported then FEditViewData.OnGetDisplayText := FDataField.EditViewDataGetDisplayTextHandler; FEditViewData.PaintOptions := []; if FShowEndEllipsis then Include(FEditViewData.PaintOptions, epoShowEndEllipsis); if FMultiline then Include(FEditViewData.PaintOptions, epoAutoHeight); AEditViewInfo.Transparent := True; FEditViewData.EditValueToDrawValue(Canvas, FValue, AEditViewInfo); FEditViewData.ContentOffset := cxRect(1, 1, 1, 1); FEditViewData.Calculate(Canvas, cxRectInflate(FTextBounds, cxTextOffset, cxTextOffset), AMousePos, cxmbNone, [], AEditViewInfo, True); FEditViewData.OnGetDisplayText := nil; FEditViewData.Data := nil; finally DestroyEditViewData; end; FCalculated := True; end; procedure TcxPivotGridEditContainerViewInfo.CalculateVisibleInfo; begin FTextBounds := cxTextRect(ExcludeBorders(Bounds, Borders)); end; function TcxPivotGridEditContainerViewInfo.CreateEditViewInfo: TcxCustomEditViewInfo; begin Result := FProperties.GetViewInfoClass.Create as TcxCustomEditViewInfo; end; procedure TcxPivotGridEditContainerViewInfo.CreateEditViewData; begin if FUseLocalViewData then FEditViewData := FProperties.CreateViewData(FEditStyle, True) else FEditViewData := FDataField.GetEditViewData; end; procedure TcxPivotGridEditContainerViewInfo.DestroyEditViewData; begin if FUseLocalViewData then FEditViewData.Free; FEditViewData := nil; end; procedure TcxPivotGridEditContainerViewInfo.DrawUsingEditProperties; begin CalculateEditViewInfo(FEditViewInfo, cxNullPoint); FEditViewInfo.Paint(Canvas); end; function TcxPivotGridEditContainerViewInfo.GetDisplayText: string; begin if FProperties <> nil then Result := FProperties.GetDisplayText(FValue) else Result := inherited GetDisplayText; end; procedure TcxPivotGridEditContainerViewInfo.InitializeProperties; begin if UseEditProperties then FProperties := FDataField.DoGetProperties(Self); if FProperties <> nil then begin FUseLocalViewData := FProperties <> FDataField.GetUserEditProperties; FUseLocalEditStyle := not FDataField.UseEditProperties or (FProperties.GetStyleClass <> FDataField.GetEditStyle(FProperties, False).ClassType); if FEditViewInfo = nil then FEditViewInfo := CreateEditViewInfo; end; end; function TcxPivotGridEditContainerViewInfo.OnGetDisplayTextSupported: Boolean; begin Result := False; end; procedure TcxPivotGridEditContainerViewInfo.ReleaseEditStyle; begin if FUseLocalEditStyle then FEditStyle.Free; FEditStyle := nil; end; function TcxPivotGridEditContainerViewInfo.UseEditProperties: Boolean; begin Result := (FDataField <> nil); end; { TcxPivotGridHeaderCellViewInfo } constructor TcxPivotGridHeaderCellViewInfo.Create( APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams; const ADisplayText: string); begin inherited Create(APainter, ABounds, AVisibleRect, AViewParams); FDisplayText := ADisplayText; FBorders := cxBordersAll; FAlignVert := vaCenter; FShowEndEllipsis := True; end; function TcxPivotGridHeaderCellViewInfo.GetDisplayText: string; begin Result := inherited GetDisplayText; if (FProperties <> nil) and (Data is TcxPivotGridViewDataTotalItem) then Result := Format(TcxPivotGridViewDataTotalItem(Data).GetDescription, [Result]) end; procedure TcxPivotGridHeaderCellViewInfo.CalculateImageInfo; var R: TRect; begin if (ImageIndex = -1) or (Images = nil) or (ImageIndex >= Images.Count) then Exit; FImageRect := cxRectCenter(FTextBounds, Images.Width, Images.Height); FImageRect := cxRectSetTop(FImageRect, Bounds.Top + cxTextOffset); case ImageAlignHorz of taLeftJustify: begin FImageRect := cxRectSetLeft(FImageRect, TextBounds.Left); FTextBounds.Left := FImageRect.Right + cxTextOffset + 1; end; taRightJustify: begin FImageRect := cxRectSetRight(FImageRect, TextBounds.Right); FTextBounds.Right := FImageRect.Left - cxTextOffset + 1; end; end; case ImageAlignVert of vaBottom: FImageRect := cxRectSetBottom(FImageRect, Bounds.Bottom - cxTextOffset); vaCenter: FImageRect := cxRectSetTop(FImageRect, (Bounds.Top + Bounds.Bottom - Images.Height) div 2); end; IntersectRect(R, FImageRect, Bounds); CheckClipping(not EqualRect(R, FImageRect)); end; procedure TcxPivotGridHeaderCellViewInfo.CalculateSortingInfo; var ASize: TPoint; begin if FSortOrder = soNone then Exit; ASize := Painter.SortingMarkAreaSize; with FSortMarkBounds do begin Right := FTextBounds.Right; Top := (FTextBounds.Bottom + FTextBounds.Top - ASize.Y) div 2; Left := Right - ASize.X; Bottom := Top + ASize.Y; CheckClipping(Left < Bounds.Left); end; FTextBounds.Right := FSortMarkBounds.Left; end; procedure TcxPivotGridHeaderCellViewInfo.CalculateVisibleInfo; begin FBorders := Painter.HeaderBorders(Neighbors); inherited CalculateVisibleInfo; if HasButton then begin with Painter do begin FButtonRect := cxRectSetSize(FTextBounds, ExpandButtonSize, ExpandButtonSize); OffsetRect(FButtonRect, 1, 1); end; CheckClipping(Bounds.Right - FButtonRect.Right < cxPivotGridDoubleSpace); FTextBounds.Left := FButtonRect.Right + cxTextOffset; end; CalculateSortingInfo; CalculateImageInfo; // for top/left border scrolled group item FBounds.TopLeft := ClipRect.TopLeft; end; function TcxPivotGridHeaderCellViewInfo.CanDrawBackgroundFirst: Boolean; begin Result := False; end; procedure TcxPivotGridHeaderCellViewInfo.CheckSizingArea( AHitTest: TcxPivotGridHitTest); var R: TRect; begin with ClipRect do begin R := Rect(Right - cxPivotGridSizeAreaDelta, Top, Right + cxPivotGridSizeAreaDelta, Bottom); end; if (FSizeField <> nil) and Visible and PtInRect(R, AHitTest.HitPoint) then begin AHitTest.SetBitState(htcHorzSizingEdge, Supports(FSizeField, IcxPivotGridSizableObject, AHitTest.FResizeField)); if (AHitTest.FResizeField <> nil) and not AHitTest.FResizeField.CanResize then begin AHitTest.FResizeField := nil; AHitTest.SetBitState(htcHorzSizingEdge, False); end; AHitTest.FResizeFieldStartPos := Bounds.Right; end end; function TcxPivotGridHeaderCellViewInfo.DrawBackgroundProc( ACanvas: TcxCanvas; const ABounds: TRect): Boolean; begin Result := (Bitmap <> nil) and not Bitmap.Empty; if Result and not Transparent then ACanvas.FillRect(ABounds, Bitmap) else Result := Transparent; end; procedure TcxPivotGridHeaderCellViewInfo.DoDraw; var R: TRect; AClipRgn: TcxRegion; begin if not Painter.HeaderDrawCellsFirst and CanDrawBackgroundFirst then begin R := ClipRect; if Background = nil then Painter.DrawGroupByBox(Canvas, R, Transparent, clDefault, nil) else begin AClipRgn := Canvas.GetClipRegion(); Canvas.IntersectClipRect(R); Background.Draw(Canvas); Canvas.SetClipRegion(AClipRgn, roSet); end; end; Painter.DrawHeader(Canvas, Bounds, TextBounds, Neighbors, Borders, State, AlignHorz, AlignVert, MultiLine, ShowEndEllipsis, '', Canvas.Font, TextColor, Color, DrawBackgroundProc, GetIsLast, IsSingle); DrawHeaderText; if HasButton then Painter.DrawExpandButton(Canvas, ButtonRect, Expanded); if SortOrder <> soNone then Painter.DrawSortingMark(Canvas, SortMarkBounds, SortOrder = soAscending); if (Images <> nil) and (ImageIndex <> -1) then Canvas.DrawImage(Images, ImageRect.Left, ImageRect.Top, ImageIndex); end; procedure TcxPivotGridHeaderCellViewInfo.DrawHeaderText; procedure InternalDrawHeaderText; const MultiLines: array[Boolean] of Integer = (cxSingleLine, cxWordBreak); ShowEndEllipsises: array[Boolean] of Integer = (0, cxShowEndEllipsis); begin if DisplayText <> '' then begin Canvas.Brush.Style := bsClear; Canvas.Font := Font; Canvas.Font.Color := TextColor; Canvas.DrawText(DisplayText, TextBounds, cxAlignmentsHorz[AlignHorz] or cxAlignmentsVert[AlignVert] or MultiLines[MultiLine] or ShowEndEllipsises[ShowEndEllipsis]); Canvas.Brush.Style := bsSolid; end; end; begin if (FProperties = nil) or (Data is TcxPivotGridViewDataTotalItem ) then InternalDrawHeaderText else DrawUsingEditProperties; end; function TcxPivotGridHeaderCellViewInfo.GetHitTest( AHitTest: TcxPivotGridHitTest): Boolean; begin Result := inherited GetHitTest(AHitTest); CheckSizingArea(AHitTest); if Result then begin AHitTest.SetBitState(htcGroupHeader, True); if HasButton and PtInRect(ButtonRect, AHitTest.HitPoint) then AHitTest.SetBitState(htcButton, True); if Data is TcxPivotGridViewDataItem then AHitTest.FField := TcxPivotGridViewDataItem(Data).Field; end; end; function TcxPivotGridHeaderCellViewInfo.GetIsLast: Boolean; begin Result := False; //not (nRight in Neighbors); end; function TcxPivotGridHeaderCellViewInfo.IsSingle: Boolean; begin Result := False; end; function TcxPivotGridHeaderCellViewInfo.NeedShowHint(const APoint: TPoint): Boolean; begin Result := (not HasButton or (APoint.X > ButtonRect.Right)) and (cxTextWidth(Font, HintText) > cxRectWidth(TextBounds)); end; function TcxPivotGridHeaderCellViewInfo.UseEditProperties: Boolean; begin Result := inherited UseEditProperties and (FDataField.GroupInterval = giDefault) and (FDataField.FArea <> faData); end; procedure TcxPivotGridHeaderCellViewInfo.SetData(AValue: TObject); begin FData := AValue; if FData is TcxPivotGridViewDataItem then begin FDataField := TcxPivotGridViewDataItem(FData).Field; FValue := TcxPivotGridViewDataItem(FData).GroupItem.Value; InitializeProperties; end; end; { TcxPivotGridFieldHeaderCellViewInfo } constructor TcxPivotGridFieldHeaderCellViewInfo.CreateEx(AOwner: TPersistent); begin FField := AOwner; FGroup := nil; end; procedure TcxPivotGridFieldHeaderCellViewInfo.Initialize( ACanvas: TcxCanvas; APainter: TcxCustomLookAndFeelPainterClass; const AViewParams: TcxViewParams); procedure AssignFieldProperties(AField: TcxPivotGridField); const ASortOrders: array[TcxDataSortOrder] of TcxDataSortOrder = (soAscending, soAscending, soDescending); begin FField := AField; FViewParams := AViewParams; FExpanded := AField.GroupExpanded; FImageAlignHorz := AField.ImageAlign; FImageIndex := AField.ImageIndex; FImages := AField.PivotGrid.FieldHeaderImages; FFocused := GetFocused; FGroup := AField.Group; FHasButton := (FGroup <> nil) and not FGroup.IsLastVisibleField(AField); FExpanded := HasButton and AField.GroupExpanded; if not AField.Visible and (Group <> nil) then FDisplayText := Group.Caption else FDisplayText := AField.Caption; if AField.Options.CanFiltering then begin FFilterState := cxbsNormal; FFilterActive := AField.Filter.HasFilter; end; if AField.Options.CanSorting then FSortOrder := ASortOrders[AField.SortOrder]; end; begin FImages := nil; FImageAlignHorz := taLeftJustify; FImageIndex := -1; FCanvas := ACanvas; FVisible := False; FPainter := APainter; FViewParams := AViewParams; FSortOrder := soNone; FState := cxbsNormal; FFilterActive := False; FFilterState := cxbsDisabled; FAreaIndex := -1; FFocused := False; if FField is TcxPivotGridField then AssignFieldProperties(Field as TcxPivotGridField) else FDisplayText := TcxPivotGridOptionsDataField(Field).Caption; Transparent := False; end; function TcxPivotGridFieldHeaderCellViewInfo.MeasureHeight: Integer; begin Result := Painter.HeaderHeight(cxTextHeight(FViewParams.Font)); if SortOrder <> soNone then Result := Max(Result, Painter.SortingMarkAreaSize.X); if FFilterState = cxbsNormal then Result := Max(Result, Painter.FilterDropDownButtonSize.Y + cxPivotGridDoubleSpace); end; function TcxPivotGridFieldHeaderCellViewInfo.MeasureWidth: Integer; begin Result := cxTextWidth(Font, DisplayText); if Result > 0 then Inc(Result, cxPivotGridDoubleSpace); if SortOrder <> soNone then Inc(Result, Painter.SortingMarkAreaSize.X); if FFilterState = cxbsNormal then Inc(Result, Painter.FilterDropDownButtonSize.X + cxTextOffset); if HasButton then Inc(Result, Painter.ExpandButtonSize + cxPivotGridDoubleSpace); if (Images <> nil) and (ImageIndex >= 0) and (ImageIndex < Images.Count) then if ImageAlignHorz <> taCenter then Inc(Result, Images.Width + cxPivotGridDoubleSpace); Inc(Result, cxPivotGridHorzSpace * 2); end; procedure TcxPivotGridFieldHeaderCellViewInfo.SetBounds( const ABounds, AClipRect: TRect); begin FVisibleInfoCalculated := False; CalculateCellBounds(ABounds, AClipRect); end; procedure TcxPivotGridFieldHeaderCellViewInfo.PaintTo( ACanvas: TcxCanvas; const ABounds: TRect; AState: TcxButtonState; AHandler: TcxPivotGridCustomDrawEvent); var ADone: Boolean; APrevState: TcxButtonState; APrevClipRect, APrevBounds: TRect; begin APrevBounds := Bounds; APrevState := State; FVisibleInfoCalculated := False; APrevClipRect := ClipRect; try FBounds := ABounds; FClipRect := ABounds; FState := AState; BeforeCustomDraw(ACanvas); AHandler(ACanvas, Self, ADone); AfterCustomDraw(ACanvas); if not ADone then Draw(ACanvas); finally FState := APrevState; FClipRect := APrevClipRect; FBounds := APrevBounds; Transparent := False; FVisibleInfoCalculated := False; end; end; procedure TcxPivotGridFieldHeaderCellViewInfo.CalculateFilterInfo; var ASize: TPoint; begin if FFilterState = cxbsDisabled then Exit; ASize := Painter.FilterDropDownButtonSize; FFilterBounds := FTextBounds; with FFilterBounds do Left := Right - ASize.X; FTextBounds.Right := FFilterBounds.Left - cxTextOffset; CheckClipping(FFilterBounds.Left < Bounds.Left); end; procedure TcxPivotGridFieldHeaderCellViewInfo.CalculateSortingInfo; begin CalculateFilterInfo; inherited CalculateSortingInfo; end; function TcxPivotGridFieldHeaderCellViewInfo.CanDrawBackgroundFirst: Boolean; begin Result := True; end; procedure TcxPivotGridFieldHeaderCellViewInfo.DoDraw; var R: TRect; begin inherited DoDraw; if FilterState <> cxbsDisabled then Painter.DrawFilterDropDownButton(Canvas, FilterBounds, FilterState, FFilterActive); if HasButton and Expanded then begin Canvas.Brush.Color := clBtnText; with Bounds do Canvas.FillRect(Rect(Right, (Top + Bottom) div 2, Right + cxPivotGridHorzSpace, (Top + Bottom) div 2 + 1), nil); end; if State = cxbsPressed then Painter.DrawHeaderPressed(Canvas, Bounds) else if Focused then begin R := ExcludeBorders(Bounds, Borders); Canvas.DrawFocusRect(R); Canvas.DrawFocusRect(cxRectInflate(R, -1, -1)); end; end; function TcxPivotGridFieldHeaderCellViewInfo.ExcludeFromPaint( ACanvas: TcxCanvas): Boolean; begin Result := inherited ExcludeFromPaint(ACanvas); if Result and Expanded then with Bounds do begin ACanvas.ExcludeClipRect(Rect(Right, (Top + Bottom) div 2, Right + cxPivotGridHorzSpace, (Top + Bottom) div 2 + 1)); end; end; function TcxPivotGridFieldHeaderCellViewInfo.GetHitTest( AHitTest: TcxPivotGridHitTest): Boolean; begin Result := inherited GetHitTest(AHitTest); if Result then begin AHitTest.FField := FField; AHitTest.SetBitState(htcGroupHeader, False); if Field <> nil then AHitTest.SetBitState(htcFieldHeader, True) else AHitTest.SetBitState(htcDataHeader, True); if (FilterState <> cxbsDisabled) and PtInRect(FilterBounds, AHitTest.HitPoint) then AHitTest.SetBitState(htcFilter, True); end; end; function TcxPivotGridFieldHeaderCellViewInfo.GetIsLast: Boolean; begin Result := True; end; function TcxPivotGridFieldHeaderCellViewInfo.IsSingle: Boolean; begin Result := True; end; function TcxPivotGridFieldHeaderCellViewInfo.NeedShowHint( const APoint: TPoint): Boolean; begin Result := ((FilterState = cxbsDisabled) or (APoint.X < FilterBounds.Left)) and inherited NeedShowHint(APoint); end; function TcxPivotGridFieldHeaderCellViewInfo.SetHotTrack( AHitTest: TcxPivotGridHitTest): Boolean; procedure ChangeState(var AState: TcxButtonState; ANewState: TcxButtonState); begin if (AState <> cxbsDisabled) and (AState <> cxbsPressed) then AState := ANewState; end; var APrevState, APrevFilterState: TcxButtonState; begin APrevState := FState; APrevFilterState := FFilterState; if not PtInRect(ClipRect, AHitTest.HitPoint) then begin ChangeState(FFilterState, cxbsNormal); ChangeState(FState, cxbsNormal); end else begin ChangeState(FState, cxbsHot); if PtInRect(FFilterBounds, AHitTest.HitPoint) then ChangeState(FFilterState, cxbsHot) else ChangeState(FFilterState, cxbsNormal); end; Result := (APrevState <> State) or (APrevFilterState <> FFilterState); end; function TcxPivotGridFieldHeaderCellViewInfo.SingleOrLeftMostInGroup: Boolean; begin Result := (Group = nil) or (Group.Fields[0] = Field); end; function TcxPivotGridFieldHeaderCellViewInfo.SingleOrRightMostInGroup: Boolean; begin Result := (Group = nil) or Group.IsLastVisibleField(TcxPivotGridField(Field)); end; function TcxPivotGridFieldHeaderCellViewInfo.UseEditProperties: Boolean; begin Result := False; end; function TcxPivotGridFieldHeaderCellViewInfo.GetFocused: Boolean; begin Result := (Field <> nil) and (DesignerHelper <> nil) and DesignerHelper.IsObjectSelected(Field); end; { TcxPivotGridDataCellViewInfo } procedure TcxPivotGridDataCellViewInfo.Initialize( ARow, AColumn: TcxPivotGridViewDataItem; ADataField: TcxPivotGridField); begin FRow := ARow; FColumn := AColumn; FDataField := ADataField; FValue := Null; InitializeProperties; end; function TcxPivotGridDataCellViewInfo.MeasureWidth: Integer; begin Result := cxTextWidth(Font, FDisplayText) + cxPivotGridDoubleSpace; end; procedure TcxPivotGridDataCellViewInfo.CalculateVisibleInfo; var ACol, ARow: TcxPivotGridGroupItem; begin inherited CalculateVisibleInfo; ARow := Row.GetGroupItem(FDataField); ACol := Column.GetGroupItem(FDataField); if (DataField = nil) or (ARow = nil) or (ACol = nil) then begin FDisplayText := cxGetResourceString(@scxNoDataToDisplay); Exit; end; FCrossCell := ARow.GetCellByCrossItem(ACol); FSummaryType := DataField.SummaryType; if not Row.GetSummaryType(FSummaryType, FTotal) then Column.GetSummaryType(FSummaryType, FTotal); FCellSummary := CrossCell.SummaryCells[DataField.SummaryIndex]; if (Total = nil) and DataField.HasSummaryVariation then FValue := CellSummary.SummaryVariation else FValue := CellSummary.GetSummaryByType(SummaryType); FIsTotal := GetIsTotal; FAlignment := taRightJustify; FAlignVert := vaCenter; FormatDisplayValue; end; procedure TcxPivotGridDataCellViewInfo.DoDraw; begin if not Transparent then Canvas.FillRect(Bounds, FViewParams, Borders, BorderColor); DrawText; if FocusRectStyle = frsLine then Canvas.InvertFrame(ExcludeBorders(Bounds, Borders), 1) else if FocusRectStyle = frsDot then begin Canvas.Brush.Style := bsSolid; Canvas.DrawFocusRect(ExcludeBorders(Bounds, Borders)); end; end; procedure TcxPivotGridDataCellViewInfo.DrawText; var AFlags: Integer; begin if FProperties <> nil then DrawUsingEditProperties else if DisplayText <> '' then begin Canvas.Brush.Style := bsClear; AFlags := cxAlignmentsHorz[Align] or cxAlignmentsVert[FAlignVert]; if MarkNarrowCells and (cxTextWidth(Font, DisplayText) > cxRectWidth(TextBounds)) then Canvas.DrawTexT(ReplaceDigitsByPattern(DisplayText), TextBounds, AFlags) else Canvas.DrawTexT(DisplayText, TextBounds, AFlags); end; end; procedure TcxPivotGridDataCellViewInfo.FormatDisplayValue; begin DataField.DoGetDisplayText(Self); end; function TcxPivotGridDataCellViewInfo.GetHintText: string; begin Result := FDisplayText; end; function TcxPivotGridDataCellViewInfo.GetHitTest( AHitTest: TcxPivotGridHitTest): Boolean; begin Result := inherited GetHitTest(AHitTest); if Result then begin AHitTest.SetBitState(htcDataCell, True); AHitTest.FHitObject := Self; end; end; function TcxPivotGridDataCellViewInfo.NeedShowHint(const APoint: TPoint): Boolean; begin Result := cxTextWidth(Font, HintText) > cxRectWidth(TextBounds); end; function TcxPivotGridDataCellViewInfo.OnGetDisplayTextSupported: Boolean; begin Result := True; end; function TcxPivotGridDataCellViewInfo.ReplaceDigitsByPattern(const ADisplayText: string): string; begin SetLength(Result, Length(ADisplayText)); dxFillChar(Result[1], Length(ADisplayText), cxPivotPatternChar); end; function TcxPivotGridDataCellViewInfo.GetColumnIndex: Integer; begin Result := Column.VisibleIndex; end; function TcxPivotGridDataCellViewInfo.GetDisplayFormat: string; begin Result := ''; if Total <> nil then Result := Total.DisplayFormat else if DataField <> nil then Result := DataField.GetActualDisplayFormat; end; function TcxPivotGridDataCellViewInfo.GetIsGrandTotal: Boolean; function IsGrandTotal(AItem: TcxPivotGridViewDataItem): Boolean; begin Result := AItem.IsGrandTotal; while not Result and (AItem.Parent <> nil) do begin AItem := AItem.Parent; Result := AItem.IsGrandTotal; end; end; begin Result := IsGrandTotal(Column) or IsGrandTotal(Row); end; function TcxPivotGridDataCellViewInfo.GetIsTotal: Boolean; begin if FIsTotalAssigned then Result := FIsTotal else Result := Column.IsTotalItem or Row.IsTotalItem; end; function TcxPivotGridDataCellViewInfo.GetLimitValueTypes: TcxPivotGridDataCellLimitValueTypes; var AViewData: TcxPivotGridViewData; V: Variant; begin Result := []; if Column.IsTotal or Row.IsTotal then Exit; if CrossCell = nil then CalculateVisibleInfo; if CrossCell = nil then Exit; V := CrossCell.GetSummaryByField(DataField, DataField.SummaryType); if not VarIsNumericEx(V) then Exit; Column.PivotGrid.ViewData.CalculateLimitValues; AViewData := nil; if Column <> nil then begin if VarEquals(V, Column.LimitValues.GetMaximumValue(DataField)) then Result := Result + [lvtColumnMaximum]; if VarEquals(V, Column.LimitValues.GetMinimumValue(DataField)) then Result := Result + [lvtColumnMinimum]; AViewData := Column.PivotGrid.ViewData; end; if Row <> nil then begin if VarEquals(V, Row.LimitValues.GetMaximumValue(DataField)) then Result := Result + [lvtRowMaximum]; if VarEquals(V, Row.LimitValues.GetMinimumValue(DataField)) then Result := Result + [lvtRowMinimum]; AViewData := Row.PivotGrid.ViewData; end; if AViewData <> nil then begin if VarEquals(V, AViewData.LimitValues.GetMaximumValue(DataField)) then Result := Result + [lvtMaximum]; if VarEquals(V, AViewData.LimitValues.GetMinimumValue(DataField)) then Result := Result + [lvtMinimum]; end; end; function TcxPivotGridDataCellViewInfo.GetRowIndex: Integer; begin Result := Row.VisibleIndex; end; { TcxPivotGridHeaderBackgroundCellViewInfo } procedure TcxPivotGridHeaderBackgroundCellViewInfo.CorrectBoundsForPrinting(ABounds: TRect); var ACorrectedBounds: TRect; begin if Area in [faColumn, faFilter] then begin ACorrectedBounds := Bounds; ACorrectedBounds.Right := ABounds.Right; CalculateCellBounds(ACorrectedBounds, ACorrectedBounds); end; end; procedure TcxPivotGridHeaderBackgroundCellViewInfo.DoDraw; var R: TRect; ARgn: TcxRegion; ATextFormat: Integer; begin if not Transparent then begin ARgn := FCanvas.GetClipRegion(); FCanvas.IntersectClipRect(Bounds); FPainter.DrawGroupByBox(FCanvas, FieldHeadersBounds.Rect, Bitmap <> nil, Color, Bitmap); FCanvas.SetClipRegion(ARgn, roSet); end; if not HasFields then begin ATextFormat := cxMakeFormat(taLeft, taCenterY) or CXTO_WORDBREAK or CXTO_PREVENT_TOP_EXCEED; R := Bounds; cxTextOut(Canvas.Handle, FDisplayText, R, ATextFormat, nil, 0, cxTextOffset, cxTextOffset); end; end; function TcxPivotGridHeaderBackgroundCellViewInfo.GetHitTest( AHitTest: TcxPivotGridHitTest): Boolean; begin Result := inherited GetHitTest(AHitTest); if Result then AHitTest.SetBitState(htcHeaderArea, True); end; { TcxPivotGridPrefilterPartViewInfo } procedure TcxPivotGridPrefilterPartViewInfo.Calculate(ALeftBound, ATopBound, AWidth, AHeight: Integer); begin if AWidth = -1 then AWidth := CalculateWidth; if AHeight = -1 then AHeight := CalculateHeight; with FBounds do begin Left := ALeftBound; Top := ATopBound; Right := Left + AWidth; Bottom := Top + AHeight; end; end; procedure TcxPivotGridPrefilterPartViewInfo.Click; begin //do nothing end; constructor TcxPivotGridPrefilterPartViewInfo.Create(APartsViewInfo: TcxPivotGridPrefilterPartsViewInfo); begin inherited Create; FPartsViewInfo := APartsViewInfo; FPainter := FPartsViewInfo.PrefilterViewInfo.Painter; FPrefilter := FPartsViewInfo.PrefilterViewInfo.FPrefilter; FState := cxbsNormal; end; procedure TcxPivotGridPrefilterPartViewInfo.Draw(ACanvas: TcxCanvas); begin DoDraw(ACanvas); end; function TcxPivotGridPrefilterPartViewInfo.GetAlignment: TcxPivotGridPrefilterButtonAlignment; begin Result := pfbaLeft; end; function TcxPivotGridPrefilterPartViewInfo.GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; begin Result := Visible and PtInRect(FBounds, AHitTest.HitPoint); if Result then AHitTest.SetBitState(GetPartIndex, True); end; function TcxPivotGridPrefilterPartViewInfo.GetState: TcxButtonState; begin if FDroppedDown then Result := cxbsPressed else Result := FState; end; function TcxPivotGridPrefilterPartViewInfo.GetVisible: Boolean; begin Result := not FPrefilter.Filter.IsEmpty; end; procedure TcxPivotGridPrefilterPartViewInfo.SetDroppedDown(AHitTest: TcxPivotGridHitTest; ADroppedDown: Boolean); begin FDroppedDown := ADroppedDown; end; function TcxPivotGridPrefilterPartViewInfo.SetHotTrack( AHitTest: TcxPivotGridHitTest): Boolean; var APrevState: TcxButtonState; begin APrevState := FState; if APrevState <> cxbsDisabled then if cxRectPtIn(FBounds, AHitTest.HitPoint) then begin if not (ssLeft in AHitTest.ShiftState) then FState := cxbsHot else if FState = cxbsHot then FState := cxbsPressed; end else if not (ssLeft in AHitTest.ShiftState) then FState := cxbsNormal else if FState = cxbsPressed then FState := cxbsHot; Result := APrevState <> FState; end; function TcxPivotGridPrefilterPartViewInfo.SetPressed(AHitTest: TcxPivotGridHitTest; AMouseDown: Boolean): Boolean; begin Result := False; if FState <> cxbsDisabled then if AHitTest.BitState[GetPartIndex] then begin Result := True; if AMouseDown then FState := cxbsPressed else if FState = cxbsPressed then begin FState := cxbsNormal; Click; end; end else FState := cxbsNormal; end; { TcxPivotGridPrefilterCloseButtonViewInfo } function TcxPivotGridPrefilterCloseButtonViewInfo.CalculateHeight: Integer; begin Result := FPainter.FilterCloseButtonSize.Y; end; function TcxPivotGridPrefilterCloseButtonViewInfo.CalculateWidth: Integer; begin Result := FPainter.FilterCloseButtonSize.X; end; procedure TcxPivotGridPrefilterCloseButtonViewInfo.Click; begin inherited; FPrefilter.Filter.Clear; end; procedure TcxPivotGridPrefilterCloseButtonViewInfo.DoDraw( ACanvas: TcxCanvas); begin inherited; FPainter.DrawFilterCloseButton(ACanvas, FBounds, FState); end; function TcxPivotGridPrefilterCloseButtonViewInfo.GetPartIndex: Integer; begin Result := htcPrefilterCloseButton; end; { TcxPivotGridPrefilterActivateButtonViewInfo } function TcxPivotGridPrefilterActivateButtonViewInfo.CalculateHeight: Integer; begin Result := FPainter.FilterActivateButtonSize.Y; end; function TcxPivotGridPrefilterActivateButtonViewInfo.CalculateWidth: Integer; begin Result := FPainter.FilterActivateButtonSize.X; end; procedure TcxPivotGridPrefilterActivateButtonViewInfo.Click; begin inherited; FPrefilter.Filter.Active := not FPrefilter.Filter.Active; end; procedure TcxPivotGridPrefilterActivateButtonViewInfo.DoDraw( ACanvas: TcxCanvas); begin inherited; FPainter.DrawFilterActivateButton(ACanvas, Bounds, FState, GetChecked); end; function TcxPivotGridPrefilterActivateButtonViewInfo.GetPartIndex: Integer; begin Result := htcPrefilterActivateButton; end; function TcxPivotGridPrefilterActivateButtonViewInfo.GetChecked: Boolean; begin Result := FPrefilter.Filter.Active and not FPrefilter.Filter.IsEmpty; end; { TcxPivotGridPrefilterCustomizeButtonViewInfo } function TcxPivotGridPrefilterCustomizeButtonViewInfo.CalculateHeight: Integer; begin Result := GetBorderWidth(bTop) + GetBorderWidth(bBottom) + cxTextHeight(GetFont) + + GetTextOffset; end; function TcxPivotGridPrefilterCustomizeButtonViewInfo.CalculateWidth: Integer; begin Result := GetBorderWidth(bLeft) + GetBorderWidth(bRight) + cxTextWidth(GetFont, GetText) + + GetTextOffset; end; procedure TcxPivotGridPrefilterCustomizeButtonViewInfo.Click; begin inherited; FPrefilter.ShowPrefilterDialog; end; procedure TcxPivotGridPrefilterCustomizeButtonViewInfo.DoDraw( ACanvas: TcxCanvas); begin inherited; FPainter.DrawButton(ACanvas, FBounds, GetText, FState); end; function TcxPivotGridPrefilterCustomizeButtonViewInfo.GetAlignment: TcxPivotGridPrefilterButtonAlignment; begin Result := pfbaRight; end; function TcxPivotGridPrefilterCustomizeButtonViewInfo.GetBorderWidth(AIndex: TcxBorder): Integer; begin Result := FPainter.ButtonBorderSize; end; function TcxPivotGridPrefilterCustomizeButtonViewInfo.GetVisible: Boolean; begin Result := FPrefilter.CustomizeButtonVisible; end; function TcxPivotGridPrefilterCustomizeButtonViewInfo.GetPartIndex: Integer; begin Result := htcPrefilterCustomizationButton; end; function TcxPivotGridPrefilterCustomizeButtonViewInfo.GetFont: TFont; begin Result := FPartsViewInfo.FPrefilterViewInfo.Font; end; function TcxPivotGridPrefilterCustomizeButtonViewInfo.GetText: string; begin Result := cxGetResourceString(@scxPrefilterCustomizeButtonCaption); end; function TcxPivotGridPrefilterCustomizeButtonViewInfo.GetTextOffset: Integer; begin Result := 2 * (cxTextOffset + FPainter.ButtonTextOffset); end; { TcxPivotGridPrefilterDropDownButtonViewInfo } function TcxPivotGridPrefilterDropDownButtonViewInfo.CalculateHeight: Integer; begin Result := FPainter.FilterCloseButtonSize.Y; end; function TcxPivotGridPrefilterDropDownButtonViewInfo.CalculateWidth: Integer; begin Result := FPainter.FilterCloseButtonSize.X; end; procedure TcxPivotGridPrefilterDropDownButtonViewInfo.DoDraw(ACanvas: TcxCanvas); begin FPainter.DrawFilterDropDownButton(ACanvas, Bounds, State, False); end; function TcxPivotGridPrefilterDropDownButtonViewInfo.GetAlignment: TcxPivotGridPrefilterButtonAlignment; begin Result := pfbaLeft; end; function TcxPivotGridPrefilterDropDownButtonViewInfo.GetPartIndex: Integer; begin Result := htcPrefilterDropDownButton; end; function TcxPivotGridPrefilterDropDownButtonViewInfo.GetVisible: Boolean; begin Result := FPrefilter.CanMRUPopupShow; end; { TcxPivotGridPrefilterCaptionViewInfo } function TcxPivotGridPrefilterCaptionViewInfo.CalculateHeight: Integer; begin Result := cxTextHeight(FPrefilter.ViewInfo.Font) + 2 * (PrefilterTextOffset + cxTextOffset); end; function TcxPivotGridPrefilterCaptionViewInfo.CalculateWidth: Integer; begin Result := cxTextWidth(FPrefilter.ViewInfo.Font, FPrefilter.ViewInfo.DisplayText); end; procedure TcxPivotGridPrefilterCaptionViewInfo.DoDraw(ACanvas: TcxCanvas); begin ACanvas.Brush.Style := bsClear; with FPrefilter.ViewInfo do begin ACanvas.Font := Font; ACanvas.Font.Color := TextColor; if State in [cxbsHot, cxbsPressed] then ACanvas.Font.Style := ACanvas.Font.Style + [fsUnderline]; ACanvas.DrawTexT(DisplayText, Self.Bounds, cxAlignLeft or cxAlignVCenter); end; ACanvas.Brush.Style := bsSolid; end; function TcxPivotGridPrefilterCaptionViewInfo.GetAlignment: TcxPivotGridPrefilterButtonAlignment; begin Result := pfbaLeft; end; function TcxPivotGridPrefilterCaptionViewInfo.GetPartIndex: Integer; begin Result := htcPrefilterCaption; end; function TcxPivotGridPrefilterCaptionViewInfo.GetState: TcxButtonState; begin if FPrefilter.CanMRUPopupShow then Result := inherited GetState else Result := cxbsNormal; end; function TcxPivotGridPrefilterCaptionViewInfo.GetVisible: Boolean; begin Result := True; end; procedure TcxPivotGridPrefilterCaptionViewInfo.SetDroppedDown(AHitTest: TcxPivotGridHitTest; ADroppedDown: Boolean); begin if not ADroppedDown or AHitTest.GetBitState(GetPartIndex) then inherited; end; { TcxPivotGridPrefilterPartsViewInfo } constructor TcxPivotGridPrefilterPartsViewInfo.Create(APrefilterViewInfo: TcxPivotGridPrefilterViewInfo); begin inherited Create; FPrefilterViewInfo := APrefilterViewInfo; FItems := TcxObjectList.Create; AddItems; end; destructor TcxPivotGridPrefilterPartsViewInfo.Destroy; begin DestroyItems; FItems.Free; FCaptionViewInfo := nil; FDropDownButtonViewInfo := nil; inherited; end; function TcxPivotGridPrefilterPartsViewInfo.GetCount: Integer; begin Result := FItems.Count; end; function TcxPivotGridPrefilterPartsViewInfo.GetHeight: Integer; var I, AItemHeight: Integer; begin Result := 0; for I := 0 to Count - 1 do if Items[I].Visible then begin AItemHeight := Items[I].CalculateHeight; if Result < AItemHeight then Result := AItemHeight; end; if Result <> 0 then Inc(Result, 2 * PrefilterButtonsFirstOffset); end; function TcxPivotGridPrefilterPartsViewInfo.GetItem(Index: Integer): TcxPivotGridPrefilterPartViewInfo; begin Result := TcxPivotGridPrefilterPartViewInfo(FItems[Index]); end; procedure TcxPivotGridPrefilterPartsViewInfo.AddItems; begin AddItem(TcxPivotGridPrefilterCloseButtonViewInfo); AddItem(TcxPivotGridPrefilterActivateButtonViewInfo); AddItem(TcxPivotGridPrefilterCustomizeButtonViewInfo); FCaptionViewInfo := TcxPivotGridPrefilterCaptionViewInfo( AddItem(TcxPivotGridPrefilterCaptionViewInfo)); FDropDownButtonViewInfo := TcxPivotGridPrefilterDropDownButtonViewInfo( AddItem(TcxPivotGridPrefilterDropDownButtonViewInfo)); end; procedure TcxPivotGridPrefilterPartsViewInfo.DestroyItems; begin FItems.Clear; end; function TcxPivotGridPrefilterPartsViewInfo.GetDropDownPartBounds: TRect; begin Result := FDropDownButtonViewInfo.Bounds; Result.Left := FCaptionViewInfo.Bounds.Left; end; procedure TcxPivotGridPrefilterPartsViewInfo.SetDroppedDown(AHitTest: TcxPivotGridHitTest; ADroppedDown: Boolean); begin FDropDownButtonViewInfo.SetDroppedDown(AHitTest, ADroppedDown); FCaptionViewInfo.SetDroppedDown(AHitTest, ADroppedDown); end; function TcxPivotGridPrefilterPartsViewInfo.SetHotTrack(AHitTest: TcxPivotGridHitTest): Boolean; var I: Integer; begin Result := False; for I := 0 to Count - 1 do Result := Result or Items[I].SetHotTrack(AHitTest); end; function TcxPivotGridPrefilterPartsViewInfo.SetPressed(AHitTest: TcxPivotGridHitTest; AMouseDown: Boolean): Boolean; var I: Integer; begin Result := False; for I := 0 to Count - 1 do begin Result := Items[I].SetPressed(AHitTest, AMouseDown); if Result then Exit; end; end; function TcxPivotGridPrefilterPartsViewInfo.AddItem(AItemClass: TcxPivotGridPrefilterPartViewInfoClass): TcxPivotGridPrefilterPartViewInfo; begin Result := AItemClass.Create(Self); FItems.Add(Result); end; procedure TcxPivotGridPrefilterPartsViewInfo.Calculate(const ABounds: TRect); var ALeftMargin, ARightMargin, ALeft, I: Integer; ARestWidth: Integer; begin ALeftMargin := ABounds.Left + PrefilterButtonsFirstOffset; ARightMargin := ABounds.Right - PrefilterButtonsFirstOffset; for I := 0 to Count - 1 do with Items[I], ABounds do if Visible then begin if Alignment = pfbaLeft then ALeft := ALeftMargin else ALeft := ARightMargin - CalculateWidth; Calculate(ALeft, MulDiv(Top + Bottom - CalculateHeight, 1, 2)); if Alignment = pfbaLeft then ALeftMargin := Items[I].Bounds.Right + PrefilterButtonsOffset else ARightMargin := Items[I].Bounds.Left - PrefilterButtonsOffset; end; ARestWidth := ARightMargin - ALeftMargin + PrefilterButtonsOffset; if ARestWidth < 0 then begin ARestWidth := Min(cxRectWidth(FCaptionViewInfo.Bounds), -ARestWidth); FCaptionViewInfo.FBounds.Right := FCaptionViewInfo.FBounds.Right - ARestWidth; if FDropDownButtonViewInfo.Visible then OffsetRect(FDropDownButtonViewInfo.FBounds, -ARestWidth, 0); end; end; procedure TcxPivotGridPrefilterPartsViewInfo.DrawParts; var I: Integer; begin for I := 0 to Count - 1 do if Items[I].Visible then Items[I].Draw(FPrefilterViewInfo.Canvas); end; function TcxPivotGridPrefilterPartsViewInfo.GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; var I: Integer; begin Result := False; for I := 0 to Count - 1 do begin Result := Items[I].GetHitTest(AHitTest); if Result then Break; end; end; { TcxPivotGridPrefilterViewInfo } constructor TcxPivotGridPrefilterViewInfo.Create(APrefilter: TcxPivotGridPrefilter; APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); begin inherited Create(APainter, ABounds, AVisibleRect, AViewParams); FPrefilter := APrefilter; FPartsViewInfo := TcxPivotGridPrefilterPartsViewInfo.Create(Self); FDisplayText := FPrefilter.Filter.FilterCaption; if FDisplayText = '' then FDisplayText := cxGetResourceString(@scxPrefilterIsEmpty); end; destructor TcxPivotGridPrefilterViewInfo.Destroy; begin FPartsViewInfo.Free; inherited; end; procedure TcxPivotGridPrefilterViewInfo.CalculateVisibleInfo; begin FPartsViewInfo.Calculate(Bounds); end; procedure TcxPivotGridPrefilterViewInfo.CorrectBoundsForPrinting(ABounds: TRect); var ACorrectedBounds: TRect; begin ACorrectedBounds := Bounds; ACorrectedBounds.Right := ABounds.Right; if Prefilter.Position = pfpBottom then ACorrectedBounds := cxRectSetTop(ACorrectedBounds, ABounds.Bottom); CalculateCellBounds(ACorrectedBounds, ACorrectedBounds); end; procedure TcxPivotGridPrefilterViewInfo.DoDraw; begin if not Transparent then DrawBackground; FPartsViewInfo.DrawParts; end; function TcxPivotGridPrefilterViewInfo.GetHeight: Integer; begin Result := FPartsViewInfo.Height; end; function TcxPivotGridPrefilterViewInfo.GetHitTest(AHitTest: TcxPivotGridHitTest): Boolean; begin Result := inherited GetHitTest(AHitTest); if Result then begin AHitTest.SetBitState(htcPrefilter, True); FPartsViewInfo.GetHitTest(AHitTest); end; end; function TcxPivotGridPrefilterViewInfo.GetTextWidth: Integer; begin Result := cxTextWidth(Font, DisplayText); end; function TcxPivotGridPrefilterViewInfo.GetDropDownWindowOwnerBounds: TRect; begin Result := FPartsViewInfo.GetDropDownPartBounds; end; procedure TcxPivotGridPrefilterViewInfo.SetDroppedDown(AHitTest: TcxPivotGridHitTest; ADroppedDown: Boolean); begin FPartsViewInfo.SetDroppedDown(AHitTest, ADroppedDown); end; function TcxPivotGridPrefilterViewInfo.SetHotTrack(AHitTest: TcxPivotGridHitTest): Boolean; begin Result := FPartsViewInfo.SetHotTrack(AHitTest); end; function TcxPivotGridPrefilterViewInfo.SetPressed(AHitTest: TcxPivotGridHitTest; AMouseDown: Boolean): Boolean; begin Result := FPartsViewInfo.SetPressed(AHitTest, AMouseDown); end; procedure TcxPivotGridPrefilterViewInfo.DrawBackground; begin Painter.DrawFilterPanel(Canvas, Bounds, Bitmap <> nil, Color, Bitmap); end; { TcxPivotGridCustomCellViewInfo } constructor TcxPivotGridFilterSeparatorCellViewInfo.Create( APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); begin inherited Create(APainter, ABounds, AVisibleRect, AViewParams); FIndentSize := cxTextOffset; end; procedure TcxPivotGridFilterSeparatorCellViewInfo.DoDraw; begin Painter.DrawHeaderSeparator(Canvas, Bounds, IndentSize, TextColor, ViewParams); end; { TcxPivotGridViewInfo } constructor TcxPivotGridViewInfo.Create(AOwner: TcxCustomPivotGrid); begin FPivotGrid := AOwner; FDrawBorders := True; FDrawExpandButtons := True; FColumnHeaders := TcxPivotGridCells.Create; FFieldHeaders := TcxPivotGridCells.Create; FRowHeaders := TcxPivotGridCells.Create; FCommonCells := TcxPivotGridCells.Create; FDataCells := TcxPivotGridCells.Create; FDragDropAreas := TcxObjectList.Create; FColumnItems := TcxList.Create; FRowColumnPos := TcxList.Create; FRowItems := TcxList.Create; FFieldHeadersBounds := TcxRect.Create(nil); FPrefilter := TcxPivotGridPrefilter.Create(AOwner); end; destructor TcxPivotGridViewInfo.Destroy; begin Clear; FreeAndNil(FPrefilter); FreeAndNil(FFieldHeadersBounds); FreeAndNil(FRowItems); FreeAndNil(FColumnItems); FreeAndNil(FDataCells); FreeAndNil(FColumnHeaders); FreeAndNil(FDragDropAreas); FreeAndNil(FCommonCells); FreeAndNil(FFieldHeaders); FreeAndNil(FRowHeaders); FreeAndNil(FRowColumnPos); inherited Destroy; end; procedure TcxPivotGridViewInfo.Calculate; begin if FBaseStyles = nil then FBaseStyles := PivotGrid.Styles; FCanvas := PivotGrid.Canvas; FPainter := PivotGrid.LookAndFeelPainter; FBounds := PivotGrid.ClientBounds; if IsPrinting then begin FBounds.Right := MaxInt; FBounds.Bottom := MaxInt; end; Clear; DoCalculate; end; procedure TcxPivotGridViewInfo.Clear; begin FRowItems.Clear; FRowColumnPos.Clear; FColumnItems.Clear; FColumnHeaders.Clear; FCommonCells.Clear; FFieldHeaders.DeleteAll; FRowHeaders.Clear; FDataCells.Clear; FDragDropAreas.Clear; FPrefilter.Clear; end; procedure TcxPivotGridViewInfo.InvalidateRect(const ARect: TRect); begin PivotGrid.InvalidateRect(ARect, False); end; procedure TcxPivotGridViewInfo.SelectionChanged; var I: Integer; begin for I := 0 to DataCells.Count - 1 do CheckCellSelection(TcxPivotGridDataCellViewInfo(DataCells[I])); end; function TcxPivotGridViewInfo.AddDragDropAreaInfo(APos: Integer; const ABounds, ADisplayBounds: TRect; AArea: TcxPivotGridFieldArea; AAreaIndex: Integer; AField: TPersistent): TcxPivotGridDragDropAreaInfo; begin Result := TcxPivotGridDragDropAreaInfo.Create(); Result.Area := AArea; Result.AreaIndex := AAreaIndex; Result.Bounds := cxRectSetXPos(ABounds, ADisplayBounds.Left, ADisplayBounds.Right); Result.DisplayBounds := cxRectSetLeft(ADisplayBounds, APos, 1); Result.Field := AField; FDragDropAreas.Add(Result); end; function TcxPivotGridViewInfo.AddFieldHeader( const ABounds: TRect; AField: TcxPivotGridField; AArea: TcxPivotGridFieldArea; AAreaIndex: Integer): TcxPivotGridFieldHeaderCellViewInfo; begin if AField <> nil then Result := AField.ViewInfo else Result := OptionsDataField.ViewInfo; Result.FArea := AArea; Result.FAreaIndex := AAreaIndex; Result.SetBounds(ABounds, FCellsBounds); FieldHeaders.Add(Result); end; function TcxPivotGridViewInfo.AddFieldsBackground( const ABounds: TRect; const ADescription: string; AHasDescription: Boolean; AArea: TcxPivotGridFieldArea): TcxPivotGridHeaderBackgroundCellViewInfo; var AParams: TcxViewParams; begin AParams := BaseStyles.GetHeaderBackgroundParams(AArea); Result := TcxPivotGridHeaderBackgroundCellViewInfo.Create( Painter, ABounds, FCellsBounds, AParams); Result.FHasFields := not AHasDescription; Result.FArea := AArea; Result.DisplayText := ADescription; Result.FFieldHeadersBounds := FFieldHeadersBounds; CommonCells.Add(Result); end; function TcxPivotGridViewInfo.AddFilterSeparator( const ATop: Integer): TcxPivotGridFilterSeparatorCellViewInfo; var ABounds: TRect; begin ABounds := cxRectSetTop(FCellsBounds, ATop, cxPivotGridFilterSeparatorHeight); if PivotGrid.VScrollBarVisible then Inc(ABounds.Right, cxTextOffset); Result := TcxPivotGridFilterSeparatorCellViewInfo.Create(Painter, ABounds, ABounds, Styles.GetFilterSeparatorParams); CommonCells.Add(Result); end; procedure TcxPivotGridViewInfo.AfterPaint; begin end; procedure TcxPivotGridViewInfo.BeforePaint; begin FColumnHeaders.BeforePaint; FCommonCells.BeforePaint; FFieldHeaders.BeforePaint; FRowHeaders.BeforePaint; FDataCells.BeforePaint; end; function TcxPivotGridViewInfo.GetDataFieldFromViewData( AItem: TcxPivotGridViewDataItem): TcxPivotGridField; var I: Integer; begin Result := nil; if DataBuilder.DataFields.Count = 0 then Exit; if DataBuilder.DataFields.Count = 1 then Result := DataBuilder.DataFields[0] else begin while (AItem <> nil) and not AItem.IsDataField do AItem := AItem.Parent; if not ((AItem <> nil) and AItem.IsDataField) then begin for I := 0 to DataBuilder.DataFields.Count - 1 do if not DataBuilder.DataFields[I].HasSummaryVariation then Result := DataBuilder.DataFields[I] end else Result := AItem.Field; // PivotGridError(Result <> nil, scxInvalidLayout); end; end; function TcxPivotGridViewInfo.GetFont(AStyleIndex: Integer): TFont; var AStyle: TcxStyle; begin AStyle := Styles.GetValue(AStyleIndex); if (AStyle = nil) or not (svFont in AStyle.AssignedValues) then Result := PivotGrid.Font else Result := AStyle.Font; end; function TcxPivotGridViewInfo.GetRowColumnPos( ALevel: Integer; var ALevelField: TPersistent): Integer; begin if (ALevel >= 0) and (FRowColumnPos.Count > 0) then begin if ALevel >= FRowColumnPos.Count then begin Result := Bounds.Left + OptionsView.GetActualWidth; if (FRowColumnPos.Count = 1) and (ALevel = 1) and (OptionsDataField.Area = dfaRow) then ALevelField := OptionsDataField; end else begin Result := Integer(FRowColumnPos.List^[ALevel]); ALevelField := GetRowField(ALevel); if ALevelField = nil then ALevelField := OptionsDataField; end; end else Result := Bounds.Left; end; function TcxPivotGridViewInfo.GetRowField(AIndex: Integer): TcxPivotGridField; begin if IsDataFieldVisible([dfaRow]) then begin if AIndex = OptionsDataField.GetActualAreaIndex(False) then begin Result := nil; Exit; end else if AIndex >= OptionsDataField.GetActualAreaIndex(False) then Dec(AIndex); end; Result := DataBuilder.RowFields[AIndex]; end; function TcxPivotGridViewInfo.GetStartColumnIndex: Integer; begin Result := ViewData.ColumnIndex; if IsPrinting then Result := 0; end; function TcxPivotGridViewInfo.GetStartRowIndex: Integer; begin Result := ViewData.RowIndex; if IsPrinting then Result := 0; end; function TcxPivotGridViewInfo.GroupHeaderOutOfBounds( AField: TcxPivotGridField; ARight: Integer): Boolean; var I, AWidth: Integer; begin Result := (AField.Group <> nil) and (AField.Group.Fields[0] = AField); if Result then begin AWidth := 0; for I := 1 to AField.Group.FieldCount - 1 do if not AField.Group[I].VisibleInGroup then Break else Inc(AWidth, AField.Group[I].HeaderWidth + cxPivotGridSpace); Result := ARight + AWidth > Bounds.Right; end else Result := (AField.Group = nil) and (ARight > Bounds.Right); end; function TcxPivotGridViewInfo.AddPartBackground( ABounds: TRect): TcxPivotGridCustomCellViewInfo; begin Result := nil; if IntersectRect(ABounds, ABounds, FCellsBounds) and not IsPrinting then begin Result := TcxPivotGridCustomCellViewInfo.Create(Painter, ABounds, FCellsBounds, FViewParams); CommonCells.Add(Result); end; end; function TcxPivotGridViewInfo.AddColumnItem( ABounds: TRect; AItem: TcxPivotGridViewDataItem): TcxPivotGridHeaderCellViewInfo; begin Result := TcxPivotGridHeaderCellViewInfo.Create( Painter, ABounds, ColumnsBounds, BaseStyles.GetColumnHeaderParams(AItem)); Result.Data := AItem; with AItem do begin Result.Neighbors := GetItemNeighbors(AItem.Level = 0, ABounds.Left <= ColumnsBounds.Left, not AItem.HasChildren, AItem.GetNextVisible = nil); if not AItem.Expanded and (not AItem.HasChildren or (AItem.ItemCount <= 1)) then begin Result.FSizeField := AItem.Field; if AItem.IsGrandTotal and (AItem.Field = nil) then Result.FSizeField := OptionsView; end; end; InitHeaderCell(Result, AItem); ColumnHeaders.Add(Result); end; function TcxPivotGridViewInfo.AddDataCell(ARow, AColumn: TcxPivotGridViewDataItem; ALeft, ATop: Integer): TcxPivotGridDataCellViewInfo; var ABounds: TRect; AField: TcxPivotGridField; const ABorders: array[TcxPivotGridLines] of TcxBorders = ([], [bBottom], [bRight], [bRight, bBottom]); begin ABounds := cxRect(ALeft, ATop, ALeft + AColumn.Size, ATop + ARow.Size); if FNeedCorrectHeaders and (ALeft <= DataCellsBounds.Left) then Inc(ABounds.Left); Result := TcxPivotGridDataCellViewInfo.Create(Painter, ABounds, DataCellsBounds, FViewParams); Result.FBorders := ABorders[OptionsView.GridLines]; if PivotGrid.OptionsView.GridLineColor <> clDefault then Result.FBorderColor := PivotGrid.OptionsView.GridLineColor else Result.FBorderColor := Painter.DefaultGridLineColor; if OptionsDataField.Area = dfaRow then AField := GetDataFieldFromViewData(ARow) else AField := GetDataFieldFromViewData(AColumn); Result.Initialize(ARow, AColumn, AField); Result.MarkNarrowCells := OptionsView.MarkNarrowCells; if IsPrinting and DrawBorders then begin if ARow.VisibleIndex = ViewData.RowCount - 1 then Include(Result.FBorders, bBottom); if AColumn.VisibleIndex = ViewData.ColumnCount - 1 then Include(Result.FBorders, bRight); end; InitCellViewParams(Result); DataCells.Add(Result); end; function TcxPivotGridViewInfo.AddRowItem(ABounds: TRect; AItem: TcxPivotGridViewDataItem; ASizeField: TPersistent): TcxPivotGridHeaderCellViewInfo; begin if FNeedCorrectHeaders and (RowsBounds.Top - ABounds.Top >= -1) then Dec(ABounds.Top); Result := TcxPivotGridHeaderCellViewInfo.Create( Painter, ABounds, RowsBounds, BaseStyles.GetRowHeaderParams(AItem)); Result.Data := AItem; with AItem do begin Result.Neighbors := GetItemNeighbors(ABounds.Top <= RowsBounds.Top, AItem.Level = 0, AItem.GetNextVisible = nil, not AItem.HasChildren); Result.FSizeField := ASizeField; if AItem.IsGrandTotal and (ViewData.RowCount = 1) then Result.FSizeField := OptionsView; end; InitHeaderCell(Result, AItem); RowHeaders.Add(Result); end; procedure TcxPivotGridViewInfo.InitCellViewParams( ACell: TcxPivotGridDataCellViewInfo); var AStyle: TcxPivotGridFocusRectStyle; begin ACell.FSelected := not IsPrinting and not PivotGrid.IsDesigning and ViewData.IsCellSelected(ACell.RowIndex, ACell.ColumnIndex); with FocusedCell do AStyle := TcxPivotGridFocusRectStyle((ACell.RowIndex = Y) and (ACell.ColumnIndex = X) and ACell.FSelected); if (AStyle = frsDot) and not PivotGrid.Controller.Focused then begin if PivotGrid.OptionsSelection.HideFocusRect then AStyle := frsNone else AStyle := frsLine; end; ACell.FFocusRectStyle := AStyle; ACell.FSelected := ACell.FSelected and (PivotGrid.Controller.Focused or not PivotGrid.OptionsSelection.HideSelection); ACell.FViewParams := BaseStyles.GetContentParams(ACell); end; procedure TcxPivotGridViewInfo.InitializeFields; var AField: TcxPivotGridField; I: Integer; begin FFilterHeight := 0; FDataFieldsWidth := 0; FFieldHeaderHeight := Max(Painter.HeaderHeight( cxTextHeight(GetFont(gs_FieldHeader))), GetIconsSize.cx + cxPivotGridDoubleSpace); for I := 0 to PivotGrid.FieldCount - 1 do begin AField := PivotGrid.Fields[I]; AField.ViewInfo.Initialize(Canvas, Painter, BaseStyles.GetFieldHeaderParams(AField)); if (AField.Area = faData) and AField.VisibleInGroup then Inc(FDataFieldsWidth, AField.HeaderWidth); Max(FFieldHeaderHeight, AField.ViewInfo.MeasureHeight); end; OptionsDataField.ViewInfo.Initialize(Canvas, Painter, BaseStyles.GetFieldHeaderParams(nil)); if OptionsDataField.GetActualAreaIndex >= 0 then Max(FFieldHeaderHeight, OptionsDataField.ViewInfo.MeasureHeight); end; procedure TcxPivotGridViewInfo.InitHeaderCell( ACell: TcxPivotGridHeaderCellViewInfo; AItem: TcxPivotGridViewDataItem); begin ACell.DisplayText := GetHeaderDisplayText(ACell, AItem); ACell.FImages := PivotGrid.GroupHeaderImages; ACell.FImageIndex := -1; if (ACell.Images <> nil) and (AItem.Field <> nil) then begin ACell.FImageIndex := AItem.Field.DoGetGroupImageIndex(AItem, ACell.FImageAlignHorz, ACell.FImageAlignVert); end; ACell.FHasButton := AItem.HasButton and DrawExpandButtons; ACell.FExpanded := AItem.Expanded; end; function TcxPivotGridViewInfo.IsDataFieldVisible( AArea: TcxPivotGridDataFieldAreas = []): Boolean; begin Result := (DataBuilder.DataFields.Count > 1); if Result and (AArea <> []) then Result := OptionsDataField.Area in AArea; end; procedure TcxPivotGridViewInfo.CreateRows(ARows: TcxList); function CreateRow(AItem: TcxPivotGridViewDataItem; ATop, ARight: Integer): Integer; var AField: TPersistent; ABounds: TRect; ALevel: Integer; AStartItem: TcxPivotGridViewDataItem; begin Result := AItem.Size; AField := nil; AStartItem := AItem; if AItem.IsDataField then ALevel := FRowColumnPos.Count - 1 else ALevel := AItem.Level; while AItem.Level >= 0 do begin if IsGroupItemExist(RowHeaders, AItem) then Break; ABounds.Top := ATop - SpaceBetween(AItem, AStartItem); ABounds.Bottom := ABounds.Top + AItem.Size; if AItem.IsDataField then ABounds.Left := GetRowColumnPos(Max(ALevel, AItem.Level), AField) else ABounds.Left := GetRowColumnPos(AItem.Level, AField); ABounds.Right := ARight; AddRowItem(ABounds, AItem, AField); Dec(ALevel); ARight := ABounds.Left; AItem := AItem.Parent; end; end; var I: Integer; ATop: Integer; begin ATop := RowsBounds.Top; if FNeedCorrectHeaders then begin Dec(FRowsBounds.Top); Inc(FRowsBounds.Right); end; for I := 0 to ARows.Count - 1 do begin Inc(ATop, CreateRow(TcxPivotGridViewDataItem( ARows.List^[I]), ATop, RowsBounds.Right)); end; end; procedure TcxPivotGridViewInfo.CreateColumns(AColumns: TcxList); function CreateColumn(AItem: TcxPivotGridViewDataItem; ABottom, ALeft: Integer): Integer; var ABounds: TRect; AStartItem: TcxPivotGridViewDataItem; begin Result := AItem.Size; AStartItem := AItem; while AItem.Level >= 0 do begin if IsGroupItemExist(ColumnHeaders, AItem) then Break; ABounds.Left := ALeft - SpaceBetween(AItem, AStartItem); ABounds.Right := ABounds.Left + AItem.Size; ABounds.Bottom := ABottom; if AItem.IsDataField then ABounds.Top := ABottom - HeaderHeight else ABounds.Top := ColumnsBounds.Top + AItem.Level * HeaderHeight; AddColumnItem(ABounds, AItem); ABottom := ABounds.Top; AItem := AItem.Parent; end; end; var I: Integer; ALeft: Integer; begin ALeft := ColumnsBounds.Left; for I := 0 to AColumns.Count - 1 do begin Inc(ALeft, CreateColumn(TcxPivotGridViewDataItem( AColumns.List^[I]), ColumnsBounds.Bottom, ALeft)); end; end; procedure TcxPivotGridViewInfo.CalculateRows; begin with FDataCellsBounds do begin Bottom := Top + PrepareViewDataItems(FRowItems, ViewData.Rows[StartRowIndex], cxRectHeight(DataCellsBounds), ViewData.FRowIndex); ViewData.RowsPerPage := FRowItems.Count; if Bottom > FCellsBounds.Bottom then begin Bottom := FCellsBounds.Bottom; ViewData.RowsPerPage := Max(1, ViewData.RowsPerPage - 1); end else AddPartBackground(cxRectSetTop(FCellsBounds, FDataCellsBounds.Bottom)); end; FRowsBounds := cxRectSetLeft(FDataCellsBounds, FCellsBounds.Left, RowHeadersWidth); CreateRows(FRowItems); end; procedure TcxPivotGridViewInfo.CalculateHitTest(AHitTest: TcxPivotGridHitTest); begin if not FieldHeaders.CalculateHitTest(AHitTest) then if not ColumnHeaders.CalculateHitTest(AHitTest) then if not RowHeaders.CalculateHitTest(AHitTest) then if not CommonCells.CalculateHitTest(AHitTest) then if not DataCells.CalculateHitTest(AHitTest) then Prefilter.CalculateHitTest(AHitTest); end; procedure TcxPivotGridViewInfo.CalculateCells; var I, J, ALeft, ATop: Integer; AColumn, ARow: TcxPivotGridViewDataItem; ACell: TcxPivotGridHeaderBackgroundCellViewInfo; begin ATop := DataCellsBounds.Top; for I := 0 to FRowItems.Count - 1 do begin ARow := TcxPivotGridViewDataItem(FRowItems.List^[I]); ALeft := DataCellsBounds.Left; for J := 0 to FColumnItems.Count - 1 do begin AColumn := TcxPivotGridViewDataItem(FColumnItems.List^[J]); AddDataCell(ARow, AColumn, ALeft, ATop); Inc(ALeft, AColumn.Size); end; Inc(ATop, ARow.Size); end; if DataCells.Count = 0 then begin ACell := AddFieldsBackground(DataCellsBounds, cxGetResourceString(@scxDropDataItems), (DataBuilder.DataFields.Count = 0) and OptionsView.ColumnFields, faData); ACell.FViewParams := FViewParams; end; end; procedure TcxPivotGridViewInfo.CalculateFieldsLayout; var I: Integer; begin InitializeFields; // FFieldHeaderHeight := FFieldHeaderHeight + ; FHeaderHeight := FFieldHeaderHeight; CalculateFilterLayout; FDataCellsBounds := FCellsBounds; // row headers FRowHeadersWidth := 0; for I := 0 to DataBuilder.RowFields.Count - 1 do Inc(FRowHeadersWidth, DataBuilder.RowFields[I].GetActualWidth); if FRowHeadersWidth = 0 then FRowHeadersWidth := OptionsView.GetActualWidth; if IsDataFieldVisible([dfaRow]) then Inc(FRowHeadersWidth, OptionsDataField.GetActualWidth); // cells bounds FDataCellsBounds := cxRect(Point(FCellsBounds.Left + RowHeadersWidth, FCellsBounds.Top + FilterHeight), FCellsBounds.BottomRight); // column rows FColumnRowCount := Max(1, DataBuilder.ColumnFields.Count); if IsDataFieldVisible([dfaNone, dfaColumn]) then Inc(FColumnRowCount); FColumnRowCount := Max(1, FColumnRowCount); FColumnHeadersHeight := FHeaderHeight * FColumnRowCount; // cells bounds with OptionsView do begin Inc(FDataCellsBounds.Top, Max( (Byte(DataFields) + Byte(RowFields)) * (FFieldHeaderHeight + cxPivotGridSpace * 2), Byte(ColumnFields) * (FFieldHeaderHeight + cxPivotGridSpace * 2) + ColumnHeadersHeight)); end; CalculateDataItemsFields; CalculateColumnsFields; CalculateRowsFields; end; procedure TcxPivotGridViewInfo.CalculateFilterLayout; var AField: TcxPivotGridField; AFilterBounds, AFieldBounds: TRect; I, ARowFieldCount, AFirstIndex: Integer; begin if not OptionsView.FilterFields then Exit; FFilterHeight := FFieldHeaderHeight + cxPivotGridSpace * 2; AFieldBounds := cxRectSetTop(FCellsBounds, FCellsBounds.Top + cxPivotGridSpace, FFieldHeaderHeight); Inc(AFieldBounds.Left, cxPivotGridHorzSpace); ARowFieldCount := 0; AFirstIndex := FieldHeaders.Count; for I := 0 to DataBuilder.FilterFields.Count - 1 do begin AField := DataBuilder.FilterFields[I]; AFieldBounds.Right := AFieldBounds.Left + AField.HeaderWidth; if (ARowFieldCount > 0) and GroupHeaderOutOfBounds(AField, AFieldBounds.Right) then begin with AFieldBounds do begin Left := FCellsBounds.Left + cxPivotGridHorzSpace; Right := Left + AField.HeaderWidth; Top := Bottom + cxPivotGridSpace; Bottom := Top + FFieldHeaderHeight; end; Inc(FFilterHeight, FFieldHeaderHeight + cxPivotGridSpace); ARowFieldCount := 1; end else Inc(ARowFieldCount); AFilterBounds := cxRectSetBottom(FCellsBounds, FCellsBounds.Top + FFilterHeight, FFieldHeaderHeight); AddFieldHeader(AFieldBounds, AField, faFilter, I); AFieldBounds.Left := AFieldBounds.Right + cxPivotGridHorzSpace; end; AFilterBounds := cxRectSetHeight(FCellsBounds, FFilterHeight); // filter separator cell if OptionsView.FilterSeparator then begin Inc(FFilterHeight, cxPivotGridDoubleSpace + cxPivotGridFilterSeparatorHeight); AFilterBounds.Bottom := FCellsBounds.Top + FFilterHeight; end; // background cell for filter area fields AddFieldsBackground(AFilterBounds, cxGetResourceString(@scxDropFilterFields), DataBuilder.FilterFields.Count = 0, faFilter); if OptionsView.FilterSeparator then AddFilterSeparator(AFilterBounds.Bottom - cxTextOffset - cxPivotGridFilterSeparatorHeight); CreateDragDropAreaInfo(AFilterBounds, AFirstIndex, faFilter); end; procedure TcxPivotGridViewInfo.CalculateColumns; begin with DataCellsBounds do begin Right := Left + PrepareViewDataItems(FColumnItems, ViewData.Columns[StartColumnIndex], {GetColumnWidth,} cxRectWidth(DataCellsBounds), ViewData.FColumnIndex); ViewData.ColumnsPerPage := FColumnItems.Count; if Right > Bounds.Right then begin Right := Bounds.Right; ViewData.ColumnsPerPage := Max(1, ViewData.ColumnsPerPage - 1); end else AddPartBackground(Rect(Right, Top - FColumnHeadersHeight, Self.Bounds.Right, Bottom)); end; FColumnBounds := cxRectSetBottom(FDataCellsBounds, FDataCellsBounds.Top, FColumnHeadersHeight); CreateColumns(FColumnItems); end; procedure TcxPivotGridViewInfo.CheckCellSelection( ACell: TcxPivotGridDataCellViewInfo); var AIsSelected: Boolean; begin AIsSelected := ACell.Selected; InitCellViewParams(ACell); if (ACell.Selected or AIsSelected) and ACell.Visible then begin ACell.FCalculated := False; InvalidateRect(ACell.ClipRect); end; end; procedure TcxPivotGridViewInfo.CorrectBackground; var ACellIndex, I: Integer; ACell: TcxPivotGridHeaderBackgroundCellViewInfo; AFieldHeader: TcxPivotGridFieldHeaderCellViewInfo; begin for I := 0 to FieldHeaders.Count - 1 do begin AFieldHeader := TcxPivotGridFieldHeaderCellViewInfo(FieldHeaders[I]); for ACellIndex := 0 to CommonCells.Count - 1 do begin if not (CommonCells[ACellIndex] is TcxPivotGridHeaderBackgroundCellViewInfo) then Continue; ACell := TcxPivotGridHeaderBackgroundCellViewInfo(CommonCells[ACellIndex]); if cxRectIntersect(AFieldHeader.Bounds, ACell.Bounds) then begin AFieldHeader.FBackground := ACell; Break; end; end; end; end; procedure TcxPivotGridViewInfo.DoCalculate; begin PivotGrid.Controller.Clear; try FViewParams := Styles.GetBackgroundParams; FNeedCorrectHeaders := not IsPrinting and (Painter.HeaderBorders([nLeft..nBottom]) <> cxBordersAll); FCellsBounds := Bounds; Prefilter.Calculate(FCellsBounds); FDataCellsBounds := FCellsBounds; FFieldHeadersBounds.Rect := FCellsBounds; CalculateFieldsLayout; CalculateColumns; CalculateRows; FFieldHeadersBounds.Bottom := DataCellsBounds.Top; CalculateCells; CorrectBackground; FCellsBounds := Bounds; FCellsBounds.Bottom := DataCellsBounds.Bottom; FCellsBounds.Right := DataCells[DataCells.Count - 1].Bounds.Right; if IsPrinting then begin Prefilter.CorrectBoundsForPrinting(FCellsBounds); CommonCells.CorrectBoundsForPrinting(FCellsBounds); end; PivotGrid.NeedUpdateScrollBarsPost := True; finally PivotGrid.Controller.Update; end; end; function TcxPivotGridViewInfo.GetHeaderDisplayText(ACell: TcxPivotGridHeaderCellViewInfo; AItem: TcxPivotGridViewDataItem): string; function InnerGetCustomizingGrandTotalText: string; begin if AItem.GroupItem is TcxPivotGridColumnItem then Result := PivotGrid.OptionsView.ColumnGrandTotalText else if AItem.GroupItem is TcxPivotGridRowItem then Result := PivotGrid.OptionsView.RowGrandTotalText else Result := ''; end; var S: string; begin Result := VarToStr(AItem.Value); if AItem is TcxPivotGridViewDataTotalItem then begin if not AItem.IsGrandTotal then with TcxPivotGridViewDataTotalItem(AItem) do Field.DoGetTotalDisplayText(GroupItem, Result) else begin S := InnerGetCustomizingGrandTotalText; if Length(S) > 0 then Result := S; end end else Result := AItem.GroupItem.DisplayText; end; procedure TcxPivotGridViewInfo.CalculateColumnsFields; function GetColumnField(AIndex: Integer): TcxPivotGridField; begin if IsDataFieldVisible([dfaColumn]) then begin if AIndex = OptionsDataField.GetActualAreaIndex then begin Result := nil; Exit; end else if AIndex >= OptionsDataField.GetActualAreaIndex then Dec(AIndex); end; Result := DataBuilder.ColumnFields[AIndex]; end; var I, AFirstIndex: Integer; AField: TcxPivotGridField; AAreaBounds, ABounds: TRect; begin ABounds := cxRectSetTop(FCellsBounds, FCellsBounds.Top + FilterHeight); ABounds.Bottom := DataCellsBounds.Top - ColumnHeadersHeight; ABounds.Left := Bounds.Left + RowHeadersWidth; AddFieldsBackground(ABounds, cxGetResourceString(@scxDropColumnFields), (ColumnFieldsCount = 0) and OptionsView.ColumnFields, faColumn); if not OptionsView.ColumnFields then Exit; AAreaBounds := ABounds; AFirstIndex := FieldHeaders.Count; InflateRect(ABounds, 0, -cxPivotGridSpace); ABounds.Bottom := ABounds.Top + FFieldHeaderHeight; for I := 0 to ColumnFieldsCount - 1 do begin AField := GetColumnField(I); if AField = nil then ABounds.Right := ABounds.Left + OptionsDataField.HeaderWidth else ABounds.Right := ABounds.Left + AField.HeaderWidth; AddFieldHeader(ABounds, AField, faColumn, I); ABounds.Left := ABounds.Right + cxPivotGridHorzSpace; end; CreateDragDropAreaInfo(AAreaBounds, AFirstIndex, faColumn); end; procedure TcxPivotGridViewInfo.CalculateDataItemsFields; var AField: TcxPivotGridField; ABounds, AAreaBounds: TRect; I, ACount, AFirstIndex: Integer; begin ACount := DataBuilder.DataFields.Count; ABounds := cxRectSetTop(FCellsBounds, FCellsBounds.Top + FilterHeight, FFieldHeaderHeight + cxPivotGridSpace * 2); if not OptionsView.RowFields then ABounds.Bottom := DataCellsBounds.Top; ABounds.Right := ABounds.Left + RowHeadersWidth; AddFieldsBackground(ABounds, cxGetResourceString(@scxDropDataItems), (DataBuilder.DataFields.Count = 0) and OptionsView.DataFields, faData); if not OptionsView.DataFields then Exit; AAreaBounds := ABounds; AFirstIndex := FieldHeaders.Count; Inc(ABounds.Top, cxPivotGridSpace); Inc(ABounds.Left, cxPivotGridHorzSpace); ABounds.Bottom := ABounds.Top + FFieldHeaderHeight; for I := 0 to ACount - 1 do begin AField := DataBuilder.DataFields[I]; if FDataFieldsWidth > (Bounds.Left + RowHeadersWidth) - cxPivotGridHorzSpace then begin ABounds.Right := ABounds.Left + MulDiv(AField.HeaderWidth, RowHeadersWidth - cxPivotGridHorzSpace, FDataFieldsWidth); ABounds.Right := Min(ABounds.Right, Bounds.Left + RowHeadersWidth); end else ABounds.Right := ABounds.Left + AField.HeaderWidth; Dec(ABounds.Right, cxPivotGridHorzSpace); if ABounds.Right > ABounds.Left then AddFieldHeader(ABounds, AField, faData, I); ABounds.Left := ABounds.Right + cxPivotGridHorzSpace; end; CreateDragDropAreaInfo(AAreaBounds, AFirstIndex, faData); end; procedure TcxPivotGridViewInfo.CalculateRowsFields; var AField: TcxPivotGridField; I, AWidth, ALeft, AFirstIndex: Integer; AreaBounds, ABounds: TRect; begin ABounds := cxRectSetTop(FCellsBounds, FCellsBounds.Top + FilterHeight); ABounds.Bottom := DataCellsBounds.Top; if OptionsView.DataFields then Inc(ABounds.Top, FieldHeaderHeight + cxPivotGridSpace * 2); ABounds.Right := Bounds.Left + RowHeadersWidth; AreaBounds := ABounds; InflateRect(ABounds, 0, -cxPivotGridSpace); ABounds.Top := ABounds.Bottom - FieldHeaderHeight; ABounds.Left := Bounds.Left + cxPivotGridHorzSpace; ALeft := Bounds.Left; AFirstIndex := FieldHeaders.Count; for I := 0 to RowFieldsCount - 1 do begin FRowColumnPos.Add(Pointer(ALeft)); AField := GetRowField(I); if AField = nil then AWidth := OptionsDataField.ActualWidth else AWidth := AField.ActualWidth; Inc(ALeft, AWidth); ABounds.Right := ABounds.Left + AWidth - cxPivotGridHorzSpace; if I = 0 then Dec(ABounds.Right, cxPivotGridHorzSpace); if OptionsView.RowFields then AddFieldHeader(ABounds, AField, faRow, I); ABounds.Left := ABounds.Right + cxPivotGridHorzSpace; end; if OptionsView.RowFields then begin AddFieldsBackground(AreaBounds, cxGetResourceString(@scxDropRowFields), OptionsView.RowFields and (RowFieldsCount = 0), faRow); CreateDragDropAreaInfo(AreaBounds, AFirstIndex, faRow); end; end; procedure TcxPivotGridViewInfo.CreateDragDropAreaInfo(const AAreaBounds: TRect; AStartIndex: Integer; AArea: TcxPivotGridFieldArea); var ABounds, R, R1: TRect; AIsLast: Boolean; I, AIndex, APos, ARowCount, ARow: Integer; ACell: TcxPivotGridFieldHeaderCellViewInfo; begin ARowCount := 1; for I := AStartIndex to FieldHeaders.Count - 2 do if FieldHeaders[I].Bounds.Top <> FieldHeaders[I + 1].Bounds.Top then Inc(ARowCount); ARow := 0; ABounds := AAreaBounds; AIndex := 0; I := AStartIndex; while I < FieldHeaders.Count do begin ACell := TcxPivotGridFieldHeaderCellViewInfo(FieldHeaders[I]); ABounds := ACell.Bounds; while (ACell.Group <> nil) and ACell.Expanded do begin Inc(I); Inc(AIndex); ACell := TcxPivotGridFieldHeaderCellViewInfo(FieldHeaders[I]); ABounds.Right := ACell.Bounds.Right; end; cxRectSplitHorz(ABounds, R, R1); R.Left := Max(R.Left - cxPivotGridHalfSpace - 1, AAreaBounds.Left); R1.Right := Min(R1.Right + cxPivotGridHalfSpace, AAreaBounds.Right); APos := R1.Right; AIsLast := (I = FieldHeaders.Count - 1) or (ACell.Bounds.Top <> FieldHeaders[I + 1].Bounds.Top); ABounds.Top := MulDiv(cxRectHeight(AAreaBounds), ARow, ARowCount); ABounds.Bottom := MulDiv(cxRectHeight(AAreaBounds), ARow + 1, ARowCount); OffsetRect(ABounds, 0, AAreaBounds.Top); AddDragDropAreaInfo(R.Left, ABounds, R, AArea, AIndex, ACell.Field); if AIsLast then begin R1.Right := AAreaBounds.Right; Inc(ARow); end; AddDragDropAreaInfo(APos, ABounds, R1, AArea, AIndex + 1, ACell.Field); Inc(AIndex); Inc(I); end; if AStartIndex = FieldHeaders.Count then begin R := cxRectInflate(AAreaBounds, -cxPivotGridHorzSpace, -cxPivotGridHorzSpace * 2); AddDragDropAreaInfo(R.Left, AAreaBounds, R, AArea, 0, nil); end; end; function TcxPivotGridViewInfo.IsGroupItemExist( AList: TList; AItem: TcxPivotGridViewDataItem): Boolean; var I: Integer; begin Result := False; for I := 0 to AList.Count - 1 do begin Result := TcxPivotGridHeaderCellViewInfo(AList.List^[I]).Data = AItem; if Result then Break; end; end; function TcxPivotGridViewInfo.PrepareViewDataItems( var AList: TcxList; AStartItem: TcxPivotGridViewDataItem; AAvailableSize: Integer; var AStartIndex: Integer): Integer; var AItem: TcxPivotGridViewDataItem; begin AItem := AStartItem; Result := 0; repeat Dec(AAvailableSize, AItem.Size); Inc(Result, AItem.Size); AList.Add(AItem); AItem := AItem.NextVisible; until (AItem = nil) or (AAvailableSize <= 0); AItem := AStartItem.PrevVisible; while (AAvailableSize > 0) and (AItem <> nil) do begin Dec(AAvailableSize, AItem.Size); if AAvailableSize > 0 then begin AList.Insert(0, AItem); Inc(Result, AItem.Size); if not IsPrinting then Dec(AStartIndex); end; AItem := AItem.PrevVisible; end; end; function TcxPivotGridViewInfo.SpaceBetween( AItem1, AItem2: TcxPivotGridViewDataItem): Integer; begin Result := 0; while AItem1.ItemCount > 0 do AItem1 := AItem1.First; while AItem1 <> AItem2 do begin Inc(Result, AItem1.Size); AItem1 := AItem1.GetNextVisible; {$IFDEF TESTING} Assert(AItem1 <> nil, 'Invalid item'); {$ENDIF} end; end; function TcxPivotGridViewInfo.GetDataBuilder: TcxPivotGridDataBuilder; begin Result := PivotGrid.DataBuilder; end; function TcxPivotGridViewInfo.GetColumnFieldsCount: Integer; begin Result := DataBuilder.ColumnFields.Count; if IsDataFieldVisible([dfaColumn]) then Inc(Result); end; function TcxPivotGridViewInfo.GetFocusedCell: TPoint; begin Result := ViewData.FocusedCell; end; function TcxPivotGridViewInfo.GetIconsSize: TSize; begin with PivotGrid do begin if GroupHeaderImages <> nil then Result := Size(GroupHeaderImages.Width, GroupHeaderImages.Height) else Result := Size(0, 0); if FieldHeaderImages <> nil then begin Result.cx := Max(Result.cx, FieldHeaderImages.Width); Result.cy := Max(Result.cy, FieldHeaderImages.Height); end; end; end; function TcxPivotGridViewInfo.GetOptionsDataField: TcxPivotGridOptionsDataField; begin Result := PivotGrid.OptionsDataField; end; function TcxPivotGridViewInfo.GetOptionsView: TcxPivotGridOptionsView; begin Result := PivotGrid.OptionsView; end; function TcxPivotGridViewInfo.GetRowFieldsCount: Integer; begin Result := DataBuilder.RowFields.Count; if IsDataFieldVisible([dfaRow]) then Inc(Result); end; function TcxPivotGridViewInfo.GetStyles: TcxPivotGridStyles; begin Result := PivotGrid.Styles; end; function TcxPivotGridViewInfo.GetViewData: TcxPivotGridViewData; begin Result := PivotGrid.ViewData; end; { TcxPivotGridFieldFilter } constructor TcxPivotGridFieldFilter.Create(AOwner: TcxPivotGridField); begin inherited Create; FField := AOwner; FValues := TcxPivotGridVariantList.Create; FValues.OnChange := ValuesChanged; end; destructor TcxPivotGridFieldFilter.Destroy; begin FValues.Free; inherited Destroy; end; procedure TcxPivotGridFieldFilter.Assign(Source: TPersistent); var I: Integer; begin if Source is TcxPivotGridFieldFilter then begin Clear; FFilterType := TcxPivotGridFieldFilter(Source).FilterType; for I := 0 to TcxPivotGridFieldFilter(Source).Values.Count - 1 do Values.Add(TcxPivotGridFieldFilter(Source).Values[I]); end else inherited Assign(Source); end; procedure TcxPivotGridFieldFilter.Clear; begin FValues.Clear; Changed; end; function TcxPivotGridFieldFilter.Contains(const AValue: Variant): Boolean; begin if FilterType = ftExcluded then Result := Values.IndexOf(AValue) = -1 else Result := Values.IndexOf(AValue) <> -1; end; procedure TcxPivotGridFieldFilter.Changed; begin if FLockCount = 0 then begin CallNotify(OnChange, Self); FModified := False; end else FModified := True; end; function TcxPivotGridFieldFilter.GetOwner: TPersistent; begin Result := Field; end; procedure TcxPivotGridFieldFilter.ValuesChanged(ASender: TObject); begin Changed; end; procedure TcxPivotGridFieldFilter.BeginUpdate; begin Inc(FLockCount); end; procedure TcxPivotGridFieldFilter.EndUpdate(AForceUpdate: Boolean = True); begin if FLockCount > 0 then begin Dec(FLockCount); if AForceUpdate or FModified then Changed; end; end; procedure TcxPivotGridFieldFilter.ReadData(AStream: TStream); var AFilterType: TcxPivotGridFilterType; I: Integer; ACount: Integer; begin AStream.ReadBuffer(AFilterType, SizeOf(AFilterType)); FilterType := AFilterType; AStream.ReadBuffer(ACount, SizeOf(ACount)); Values.BeginUpdate; try Values.Clear; for I := 0 to ACount - 1 do Values.Add(ReadVariantFunc(AStream)); finally Values.EndUpdate; end; end; procedure TcxPivotGridFieldFilter.WriteData(AStream: TStream); var AFilterType: TcxPivotGridFilterType; I: Integer; ACount: Integer; begin AFilterType := FilterType; AStream.WriteBuffer(AFilterType, SizeOf(AFilterType)); ACount := Values.Count; AStream.WriteBuffer(ACount, SizeOf(ACount)); for I := 0 to ACount - 1 do WriteVariantProc(AStream, Values[I]); end; function TcxPivotGridFieldFilter.GetHasFilter: Boolean; begin Result := Values.Count <> 0; end; function TcxPivotGridFieldFilter.GetPivotGrid: TcxCustomPivotGrid; begin Result := Field.PivotGrid; end; procedure TcxPivotGridFieldFilter.SetFilterType( AFilterType: TcxPivotGridFilterType); begin FFilterType := AFilterType; Changed; end; { TcxPivotGridDataController } function TcxPivotGridDataController.GetFilterItemFieldCaption(AItem: TObject): string; begin if AItem is TcxPivotGridField then Result := TcxPivotGridField(AItem).Caption else Result := inherited GetFilterItemFieldCaption(AItem); end; function TcxPivotGridDataController.GetItem(Index: Integer): TObject; begin Result := PivotGrid.GetItem(Index); end; function TcxPivotGridDataController.GetItemID(AItem: TObject): Integer; begin Result := PivotGrid.GetItemID(AItem); end; function TcxPivotGridDataController.GetItemValueSource( AItemIndex: Integer): TcxDataEditValueSource; begin Result := PivotGrid.GetItemValueSource(AItemIndex); end; procedure TcxPivotGridDataController.UpdateData; begin PivotGrid.UpdateData; end; procedure TcxPivotGridDataController.UpdateItemIndexes; begin PivotGrid.UpdateItemIndexes; inherited UpdateItemIndexes; end; procedure TcxPivotGridDataController.FilterChanged; begin inherited; PivotGrid.DoPrefilterChanged; end; procedure TcxPivotGridDataController.UpdateControl(AInfo: TcxUpdateControlInfo); begin PivotGrid.UpdateControl(AInfo); end; function TcxPivotGridDataController.GetPivotGrid: TcxCustomPivotGrid; begin Result := TcxCustomPivotGrid(GetOwner); end; { TcxPivotGridOLAPField } destructor TcxPivotGridOLAPField.Destroy; begin Dimension := nil; Hierarchy := nil; inherited Destroy; end; class function TcxPivotGridOLAPField.IsFiltered(AField: TcxPivotGridField): Boolean; var I: Integer; begin Result := AField.Filter.HasFilter; if not Result and AField.IsHierarchy then begin for I := AField.Group.IndexOf(AField) + 1 to AField.Group.FieldCount - 1 do begin Result := AField.Group.Fields[I].Filter.HasFilter; if Result then Break; end; end; end; class function TcxPivotGridOLAPField.PopulateFilteredValues( AField: TcxPivotGridField; IsExpanding: Boolean = False): TInterfaceList; var I: Integer; AChildField: TcxPivotGridField; AUniqueValues: TStringList; begin Result := TInterfaceList.Create; if (AField = nil) or not IsFiltered(AField) or not AField.PivotGrid.IsOLAPActive then Exit; AUniqueValues := nil; try if not IsExpanding or not AField.IsHierarchy then begin if AField.IsHierarchy then begin for I := AField.Group.FieldCount - 1 downto AField.Group.IndexOf(AField) + 1 do begin AChildField := AField.Group.Fields[I]; AField.PivotGrid.OLAPDataSource.PopulateFilteredUniqueNames( AChildField.Link, AChildField.Filter, AUniqueValues); end; end; AField.PivotGrid.OLAPDataSource.PopulateFilteredValues( AField.Link, AField.Filter, Result, AUniqueValues); end else if AField.IsHierarchy then for I := 0 to AField.Group.IndexOf(AField) do begin AChildField := AField.Group.Fields[I]; if AChildField.Filter.HasFilter then AField.PivotGrid.OLAPDataSource.PopulateFilteredValues( AChildField.Link, AChildField.Filter, Result, nil); end; finally FreeAndNil(AUniqueValues); end; end; { TcxPivotGridCustomOLAPDataSource } constructor TcxPivotGridCustomOLAPDataSource.Create(AOwner: TComponent); begin inherited Create(AOwner); FFields := TcxObjectList.Create; FMeasures := TcxObjectList.Create; FListeners := TList.Create; end; destructor TcxPivotGridCustomOLAPDataSource.Destroy; begin FreeAndNil(FListeners); FreeAndNil(FFields); FreeAndNil(FMeasures); inherited Destroy; end; procedure TcxPivotGridCustomOLAPDataSource.RetrieveFields( APivotGrid: TcxCustomPivotGrid); begin APivotGrid.BeginUpdate; try CreateFieldsFromFieldsList(APivotGrid, FFields); CreateFieldsFromFieldsList(APivotGrid, FMeasures); APivotGrid.DataSourceChanged; finally APivotGrid.EndUpdate; end; end; procedure TcxPivotGridCustomOLAPDataSource.AddListener( AListener: TcxCustomPivotGrid); begin if FListeners.IndexOf(AListener) = -1 then FListeners.Add(AListener); end; procedure TcxPivotGridCustomOLAPDataSource.Changed; var I: Integer; begin Clear; if Active then Initialize; for I := 0 to ListenerCount - 1 do Listeners[I].DataSourceChanged; end; procedure TcxPivotGridCustomOLAPDataSource.Clear; begin FFields.Clear; FMeasures.Clear; end; function TcxPivotGridCustomOLAPDataSource.CreateDrillDownDataSource( ACell: TcxPivotGridCrossCell; FieldList: TcxObjectList): TcxPivotGridCrossCellDataSource; var AList: TList; begin AList := TList.Create; try AList.Add(ACell); Result := CreateDrillDownDataSource(AList, FieldList); finally AList.Free; end; end; function TcxPivotGridCustomOLAPDataSource.CreateDrillDownDataSource( ACells: TList; FieldList: TcxObjectList): TcxPivotGridCrossCellDataSource; begin Result := nil; end; function TcxPivotGridCustomOLAPDataSource.CreateField( APivotGrid: TcxCustomPivotGrid; AOLAPField: TcxPivotGridOLAPField): TcxPivotGridField; function GetUniqueFieldName(S: string; AIndex: Integer = 0): string; var I: Integer; AName: string; begin Result := ''; AName := S; if AIndex <> 0 then AName := AName + IntToStr(AIndex); for I := 0 to APivotGrid.FieldCount - 1 do if APivotGrid.Fields[I].Name = AName then //when owner of PivotGrid is Frame begin Inc(AIndex); Result := GetUniqueFieldName(S, AIndex); Break; end; if Result = '' then Result := AName; end; begin Result := APivotGrid.CreateField; if GetParentForm(APivotGrid) <> nil then Result.Name := GetUniqueFieldName(CreateUniqueName(GetParentForm(APivotGrid), APivotGrid, Result, 'TcxPivotGrid', AOLAPField.Caption)); Result.FLink := AOLAPField; Result.FUniqueName := AOLAPField.UniqueName; Result.Caption := AOLAPField.Caption; Result.FAllowedAreas := DimensionAllowedAreas[AOlapField.IsMeasure]; Result.Visible := False; if AOlapField.IsMeasure then begin Result.Area := faData; Result.Options.Filtering := False; end; end; procedure TcxPivotGridCustomOLAPDataSource.CreateFieldsFromFieldsList( APivotGrid: TcxCustomPivotGrid; AOLAPFields: TcxObjectList); var I: Integer; AField: TcxPivotGridField; AGroup: TcxPivotGridFieldGroup; AOLAPField: TcxPivotGridOLAPField; begin AGroup := nil; for I := 0 to AOLAPFields.Count - 1 do begin AOLAPField := TcxPivotGridOLAPField(AOLAPFields[I]); AField := CreateField(APivotGrid, AOLAPField); if AOLAPField.GroupIndex >= 0 then begin if AOLAPField.GroupIndex = 0 then begin AGroup := APivotGrid.Groups.Add; AGroup.Caption := ''; end; AGroup.Add(AField); AField.GroupExpanded := False; end; DoInitializeField(AField); end; end; procedure TcxPivotGridCustomOLAPDataSource.CreateMembers( AField: TcxPivotGridField; AParents: TList; AHasChildren: Boolean); begin end; function TcxPivotGridCustomOLAPDataSource.CreateMembersFromGroup( AItem: TcxPivotGridGroupItem; AIncludeParent: Boolean = True; ACheckExpanding: Boolean = False): TList; procedure ProcessItems(AItem: TcxPivotGridGroupItem; AIncludeSelf: Boolean); var I: Integer; begin AItem.CheckExpanding; AItem.MemberIndex := -1; if AIncludeSelf then Result.Add(AItem) else if ACheckExpanding and AItem.FExpanded and (AItem.ItemCount = 0) and (AItem.Parent <> nil) then Result.Add(AItem); if not AItem.Expanded then Exit; for I := 0 to AItem.ItemCount - 1 do ProcessItems(AItem.Items[I], not ACheckExpanding); end; begin Result := TList.Create; Result.Capacity := 1024; ProcessItems(AItem, AIncludeParent); end; procedure TcxPivotGridCustomOLAPDataSource.CreateRootLayout( APivotGrid: TcxCustomPivotGrid); var AList: TList; ADataBuilder: TcxPivotGridDataBuilder; begin if csDesigning in ComponentState then Exit; ADataBuilder := APivotGrid.DataBuilder; AList := TList.Create; try AList.Add(ADataBuilder.FRows); CreateMembers(ADataBuilder.RowFields.GetFirstField, AList, ADataBuilder.RowFields.Count > 1); AList[0] := ADataBuilder.FColumns; CreateMembers(ADataBuilder.ColumnFields.GetFirstField, AList, ADataBuilder.ColumnFields.Count > 1); finally AList.Free; end; with ADataBuilder do begin InitializeCrossCells(Rows, Columns, SummaryFields); ProcessMembersForExpanding(ColumnFields.GetFirstField, Columns, True); ProcessMembersForExpanding(RowFields.GetFirstField, Rows, True); end; end; procedure TcxPivotGridCustomOLAPDataSource.DoInitializeField( AField: TcxPivotGridField); begin if Assigned(FOnInitializeField) then FOnInitializeField(Self, AField); end; procedure TcxPivotGridCustomOLAPDataSource.ExpandMember( AField: TcxPivotGridField; AMember: TcxPivotGridGroupItem; AExpandChildren: Boolean); var AFields: TcxPivotGridFields; AList, AMembersList: TList; ADataBuilder: TcxPivotGridDataBuilder; ACrossGroup: TcxPivotGridGroupItem; begin if (AField = nil) or (AExpandChildren and (AField.ExpandingInfo.Count = 0)) then Exit; ADataBuilder := AField.DataBuilder; AMembersList := nil; AFields := ADataBuilder.ColumnFields; ACrossGroup := ADataBuilder.Rows; if AField.Area = faRow then begin AFields := ADataBuilder.RowFields; ACrossGroup := ADataBuilder.Columns; end; if AField.VisibleIndex + 1 < AFields.Count then AField := AFields[AField.VisibleIndex + 1] else Exit; AList := CreateMembersFromGroup(AMember, not AExpandChildren, AExpandChildren); try if AList.Count = 0 then Exit; AMembersList := CreateMembersFromGroup(ACrossGroup, False); try InitializeMembersAndTotalsForExpanding(ADataBuilder, AField, AMember, ADataBuilder.SummaryFields); InitializeCrossCellsForExpanding(ADataBuilder, AMember, ACrossGroup, ADataBuilder.SummaryFields); if AField.VisibleIndex < AFields.Count then ProcessMembersForExpanding(AFields[AField.VisibleIndex], AMember, True); finally FreeAndNil(AMembersList); end; finally AList.Free; end; end; function TcxPivotGridCustomOLAPDataSource.GetHasData: Boolean; begin Result := (FieldCount <> 0) and (MeasureCount <> 0); end; function TcxPivotGridCustomOLAPDataSource.GetIsActive: Boolean; begin Result := FActive; end; function TcxPivotGridCustomOLAPDataSource.GetIsTerminated: Boolean; begin Result := False; end; function TcxPivotGridCustomOLAPDataSource.GetLinkByUniqueName( const AName: WideString): TcxPivotGridOLAPField; var I: Integer; begin Result := nil; for I := 0 to FFields.Count - 1 do if SameText(Fields[I].UniqueName, AName) then begin Result := Fields[I]; Exit; end; for I := 0 to FMeasures.Count - 1 do if SameText(Measures[I].UniqueName, AName) then begin Result := Measures[I]; Exit; end; end; procedure TcxPivotGridCustomOLAPDataSource.Initialize; begin end; procedure TcxPivotGridCustomOLAPDataSource.InitializeCrossCells( ARowsGroup, AColumnsGroup: TcxPivotGridGroupItem; ADataFields: TcxPivotGridFields); begin end; procedure TcxPivotGridCustomOLAPDataSource.InitializeCrossCellsForExpanding( ADataBuilder: TcxPivotGridDataBuilder; AnExpandingItem, ACrossGroup: TcxPivotGridGroupItem; ADataFields: TcxPivotGridFields); begin end; procedure TcxPivotGridCustomOLAPDataSource.InitializeCrossCellValues( ACell: TcxPivotGridCrossCell; const AFormattedValues, ANativeValues: Variant); var I, J: Integer; IsNull: Boolean; begin if VarIsArray(ANativeValues) then IsNull := VarIsNull(ANativeValues[0]) else IsNull := VarIsNull(ANativeValues); TcxPivotGridOLAPCrossCell(ACell).FIsEmpty := IsNull; if not IsNull then begin for I := 0 to ACell.SummaryCellCount - 1 do for J := 0 to Integer(High(TcxPivotGridSummaryType)) do ACell.SummaryCells[I].SetSummaryByIndex(J, AFormattedValues[I]); TcxPivotGridOLAPCrossCell(ACell).NativeValues := ANativeValues; end; end; procedure TcxPivotGridCustomOLAPDataSource.InitializeLayout( ARowFields, AColumnFields, ADataFields, AFilterFields: TcxPivotGridFields); begin end; procedure TcxPivotGridCustomOLAPDataSource.InitializeMembersAndTotalsForExpanding( ADataBuilder: TcxPivotGridDataBuilder; AField: TcxPivotGridField; AMember: TcxPivotGridGroupItem; ADataFields: TcxPivotGridFields); begin end; procedure TcxPivotGridCustomOLAPDataSource.InitializeMembers( AField: TcxPivotGridOLAPField; AMembers: TcxPivotGridVariantList); begin end; procedure TcxPivotGridCustomOLAPDataSource.PopulateFilteredUniqueNames( AField: TcxPivotGridOLAPField; AFilter: TcxPivotGridFieldFilter; var AUniqueValues: TStringList); begin end; procedure TcxPivotGridCustomOLAPDataSource.PopulateFilteredValues( AField: TcxPivotGridOLAPField; AFilter: TcxPivotGridFieldFilter; AValues: TInterfaceList; AUniqueValues: TStringList); begin end; procedure TcxPivotGridCustomOLAPDataSource.ProcessMembersForExpanding( AField: TcxPivotGridField; AMember: TcxPivotGridGroupItem; AExpandChildren: Boolean); var I: Integer; begin for I := 0 to AMember.ItemCount - 1 do ExpandMember(AField, AMember.Items[I], True); end; procedure TcxPivotGridCustomOLAPDataSource.RemoveListener( AListener: TcxCustomPivotGrid); begin FListeners.Remove(AListener); end; function TcxPivotGridCustomOLAPDataSource.GetField( AIndex: Integer): TcxPivotGridOLAPField; begin Result := FFields[AIndex] as TcxPivotGridOLAPField; end; function TcxPivotGridCustomOLAPDataSource.GetFieldCount: Integer; begin Result := FFields.Count end; function TcxPivotGridCustomOLAPDataSource.GetListenerCount: Integer; begin Result := FListeners.Count; end; function TcxPivotGridCustomOLAPDataSource.GetListener( AIndex: Integer): TcxCustomPivotGrid; begin Result := TcxCustomPivotGrid(FListeners[AIndex]); end; function TcxPivotGridCustomOLAPDataSource.GetMeasure( AIndex: Integer): TcxPivotGridOLAPField; begin Result := FMeasures[AIndex] as TcxPivotGridOLAPField; end; function TcxPivotGridCustomOLAPDataSource.GetMeasureCount: Integer; begin Result := FMeasures.Count; end; procedure TcxPivotGridCustomOLAPDataSource.SetActive(AValue: Boolean); begin if FActive <> AValue then begin FActive := AValue; Changed; end; end; { TcxPivotGridViewDataLimitValue } constructor TcxPivotGridViewDataLimitValue.Create(AField: TcxPivotGridField); begin Field := AField; MaxValue := -MaxInt; MinValue := MaxInt; end; procedure TcxPivotGridViewDataLimitValue.Calculate(V: Variant); begin MaxValue := Math.MaxValue([MaxValue, V]); MinValue := Math.MinValue([MinValue, V]); end; { TcxPivotGridViewDataLimitValues } function TcxPivotGridViewDataLimitValues.Add(AField: TcxPivotGridField): TcxPivotGridViewDataLimitValue; begin Result := Items[Add(TcxPivotGridViewDataLimitValue.Create(AField))]; end; procedure TcxPivotGridViewDataLimitValues.Calculate(AField: TcxPivotGridField; V: Variant); var AItem: TcxPivotGridViewDataLimitValue; begin AItem := FindByField(AField); if AItem = nil then AItem := Add(AField); AItem.Calculate(V); end; function TcxPivotGridViewDataLimitValues.FindByField(AField: TcxPivotGridField): TcxPivotGridViewDataLimitValue; var I: Integer; begin Result := nil; for I := 0 to Count - 1 do if Items[I].Field = AField then begin Result := Items[I]; Break; end; end; function TcxPivotGridViewDataLimitValues.GetMaximumValue(AField: TcxPivotGridField): Variant; var AItem: TcxPivotGridViewDataLimitValue; begin AItem := FindByField(AField); if AItem <> nil then Result := AItem.MaxValue else Result := -MaxInt; end; function TcxPivotGridViewDataLimitValues.GetMinimumValue(AField: TcxPivotGridField): Variant; var AItem: TcxPivotGridViewDataLimitValue; begin AItem := FindByField(AField); if AItem <> nil then Result := AItem.MinValue else Result := MaxInt; end; function TcxPivotGridViewDataLimitValues.GetItem( Index: Integer): TcxPivotGridViewDataLimitValue; begin Result := TcxPivotGridViewDataLimitValue(inherited Items[Index]); end; { TcxList } procedure TcxList.Assign( AListA: TList; AOperator: TListAssignOp = laCopy; AListB: TList = nil); var I: Integer; AItem: Pointer; begin if AOperator = laCopy then begin Count := AListA.Count; System.Move(AListA.List^, List^, Count * SizeOf(Integer)); end else if AOperator = laAnd then begin for I := 0 to AListA.Count - 1 do begin AItem := AListA.Items[I]; if AListB.IndexOf(AItem) <> -1 then Add(AItem); end; end else if AOperator = laOr then begin if AListA.Count > 0 then begin Count := Count + AListA.Count; System.Move(AListA.List^, Pointer(@List^[Count - AListA.Count])^, AListA.Count * SizeOf(Pointer)); end; end else {$IFNDEF DELPHI6} PivotGridError(False, scxNotImplemented); {$ELSE} inherited Assign(AListA, AOperator, AListB); {$ENDIF} end; { TcxPivotGridPrefilter } constructor TcxPivotGridPrefilter.Create(APivotGrid: TcxCustomPivotGrid); begin inherited Create; FPivotGrid := APivotGrid; end; procedure TcxPivotGridPrefilter.ShowPrefilterDialog; begin FPivotGrid.ShowPrefilterDialog; end; procedure TcxPivotGridPrefilter.Calculate(var AClientBounds: TRect); var AHeight: Integer; ABounds: TRect; APivotGridViewInfo: TcxPivotGridViewInfo; begin if Visible then begin APivotGridViewInfo := FPivotGrid.ViewInfo; Add(TcxPivotGridPrefilterViewInfo.Create(Self, APivotGridViewInfo.Painter, AClientBounds, AClientBounds, APivotGridViewInfo.BaseStyles.GetPrefilterParams)); AHeight := ViewInfo.GetHeight; if Position = pfpBottom then begin ABounds := cxRectSetBottom(AClientBounds, AClientBounds.Bottom, AHeight); Dec(AClientBounds.Bottom, AHeight); end else begin ABounds := cxRectSetHeight(AClientBounds, AHeight); Inc(AClientBounds.Top, AHeight); end; ViewInfo.CalculateCellBounds(ABounds, ABounds); end; end; function TcxPivotGridPrefilter.GetCanMRUPopupShow: Boolean; begin Result := FPivotGrid.OptionsPrefilter.MRUItemsList and not Filter.IsEmpty and (FPivotGrid.PrefilterMRUItems.VisibleCount > 0) end; function TcxPivotGridPrefilter.GetCustomizeButtonVisible: Boolean; begin Result := FPivotGrid.OptionsPrefilter.CustomizeButton; end; function TcxPivotGridPrefilter.GetFilter: TcxDataFilterCriteria; begin Result := FPivotGrid.DataController.Filter; end; function TcxPivotGridPrefilter.GetPosition: TcxPivotGridPrefilterPosition; begin Result := FPivotGrid.OptionsPrefilter.Position; end; function TcxPivotGridPrefilter.GetViewInfo: TcxPivotGridPrefilterViewInfo; begin if Count > 0 then Result := TcxPivotGridPrefilterViewInfo(Items[0]) else Result := nil; end; function TcxPivotGridPrefilter.GetVisible: Boolean; var AVisible: TcxPivotGridPrefilterVisible; begin AVisible := FPivotGrid.OptionsPrefilter.Visible; Result := (AVisible = pfvAlways) or ((AVisible = pfvNonEmpty) and not Filter.IsEmpty); end; { TcxPivotGridViewDataSelection } constructor TcxPivotGridViewDataSelection.Create(AViewData: TcxPivotGridViewData); begin FViewData := AViewData; SetLength(FRegions, 0); FLockCount := 0; FAnchorCells := cxNullRect; FFocusedCell := cxInvalidPoint; FHasTemporarySelection := False; end; destructor TcxPivotGridViewDataSelection.Destroy; begin SetLength(FRegions, 0); inherited Destroy; end; procedure TcxPivotGridViewDataSelection.Add(const ARegion: TRect); var I: Integer; AFindRegion: Boolean; begin if (Count > 0) and not MultiSelect then Exit; AFindRegion := False; I := 0; while not AFindRegion and (I < Count) do begin AFindRegion := EqualRect(Regions[I], ARegion); Inc(I); end; if not AFindRegion then begin SetLength(FRegions, Count + 1); FRegions[Count - 1] := ARegion; end else begin FRegions[I - 1] := FRegions[Count - 1]; FRegions[Count - 1] := ARegion; end; ApplyTemporarySelection(False); DoChanged; end; procedure TcxPivotGridViewDataSelection.BeginUpdate; begin Inc(FLockCount); end; procedure TcxPivotGridViewDataSelection.Clear; begin BeginUpdate; try InnerClear; InnerSetFocusedCell(cxInvalidPoint); FAnchorCells := Rect(0, 0, 0, 0); finally EndUpdate; end; end; procedure TcxPivotGridViewDataSelection.Delete(AIndex: Integer); var I: Integer; begin BeginUpdate; try if (AIndex < 0) or (AIndex >= Count) then Exit; for I := AIndex + 1 to Count - 1 do FRegions[I - 1] := FRegions[I]; SetLength(FRegions, Count - 1); finally EndUpdate; end; end; procedure TcxPivotGridViewDataSelection.EndUpdate(ASendNotification: Boolean = True); begin Dec(FLockCount); if ASendNotification then DoChanged; end; function TcxPivotGridViewDataSelection.GetCombinedSelectionBounds: TRect; var I: Integer; begin Result := Rect(MaxInt, MaxInt, 0, 0); for I := 0 to Count - 1 do begin if EqualRect(Regions[I], cxInvalidRect) then Continue; with Result do begin Left := Min(Left, Regions[I].Left); Top := Min(Top, Regions[I].Top); Right := Max(Right, Regions[I].Right); Bottom := Max(Bottom, Regions[I].Bottom); end; end; end; function TcxPivotGridViewDataSelection.IsCellSelected(AColumn, ARow: Integer): Boolean; var I: Integer; begin Result := False; for I := 0 to Count - 1 do begin if EqualRect(Regions[I], cxInvalidRect) then Continue; Result := (Regions[I].Left <= AColumn) and (Regions[I].Right >= AColumn) and (Regions[I].Top <= ARow) and (Regions[I].Bottom >= ARow); if Result then Break; end; end; procedure TcxPivotGridViewDataSelection.MakeNew(const ARegion: TRect); begin if EqualRect(ARegion, cxInvalidRect) or ((Count = 1) and EqualRect(ARegion, Regions[0])) then Exit; BeginUpdate; try InnerClear; Add(ARegion); finally EndUpdate; end; end; procedure TcxPivotGridViewDataSelection.ApplyTemporarySelection(AIsSet: Boolean); begin FHasTemporarySelection := False; end; procedure TcxPivotGridViewDataSelection.ChangeSelection(const R: TRect; AShift: TShiftState); begin if MultiSelect and not ([ssShift, ssCtrl] * AShift = [ssShift, ssCtrl]) then begin if not EqualRect(TemporarySelection, R) then begin BeginUpdate; try if not IsTemporarySelected and (not (ssCtrl in AShift) or (ssRight in AShift)) then InnerClear; TemporarySelection := R; finally EndUpdate; end; end; end else MakeNew(R); end; procedure TcxPivotGridViewDataSelection.DoChanged; begin if (LockCount = 0) and (ViewData <> nil) then ViewData.PivotGrid.SelectionChanged; end; procedure TcxPivotGridViewDataSelection.InnerClear; begin SetLength(FRegions, 0); end; procedure TcxPivotGridViewDataSelection.InnerSetFocusedCell(const APoint: TPoint); begin FFocusedCell := APoint; end; function TcxPivotGridViewDataSelection.IsSelected: Boolean; begin Result := Count > 0; end; procedure TcxPivotGridViewDataSelection.ValidateFocusedCell; var R: TRect; ABestRow, ABestColumn: Integer; AOldFocusedCell: TPoint; AMaxIteration: Integer; I: Integer; function FindValidateCell(ADelta: Integer; var ARow, AColumn: Integer): Boolean; function CheckFindValidateCell(Y, X: Integer): Boolean; begin Result := ViewData.CanCellSelect(Y, X); if Result then begin ARow := Y; AColumn := X; end; end; var I: Integer; begin Result := False; for I := 0 to ADelta do begin Result := True; if CheckFindValidateCell(FocusedCell.Y + ADelta, FocusedCell.X + I) then Exit; if CheckFindValidateCell(FocusedCell.Y + ADelta, FocusedCell.X - I) then Exit; if CheckFindValidateCell(FocusedCell.Y - ADelta, FocusedCell.X + I) then Exit; if CheckFindValidateCell(FocusedCell.Y - ADelta, FocusedCell.X - I) then Exit; if CheckFindValidateCell(FocusedCell.Y + I, FocusedCell.X + ADelta) then Exit; if CheckFindValidateCell(FocusedCell.Y + I, FocusedCell.X - ADelta) then Exit; if CheckFindValidateCell(FocusedCell.Y - I, FocusedCell.X + ADelta) then Exit; if CheckFindValidateCell(FocusedCell.Y - I, FocusedCell.X - ADelta) then Exit; Result := False; end; end; begin R := Classes.Rect(FocusedCell, FocusedCell); ViewData.ValidateSelection(R); FFocusedCell := R.TopLeft; AOldFocusedCell := FFocusedCell; if not MultiSelect then begin Clear; FFocusedCell := AOldFocusedCell; end; if not ViewData.CanCellSelect(AOldFocusedCell.Y, AOldFocusedCell.X) then begin ABestRow := AOldFocusedCell.Y; ABestColumn := AOldFocusedCell.X; AMaxIteration := Max(Max(ViewData.RowCount - 1 - AOldFocusedCell.Y, AOldFocusedCell.Y), Max(ViewData.ColumnCount - 1 - AOldFocusedCell.X, AOldFocusedCell.X)); for I := 1 to AMaxIteration do begin if FindValidateCell(I, ABestRow, ABestColumn) then Break; end; FFocusedCell.Y := ABestRow; FFocusedCell.X := ABestColumn; end; if not IsCellSelected(FFocusedCell.X, FFocusedCell.Y) then if not MultiSelect or ((Count = 1) and EqualRect(Classes.Rect(AOldFocusedCell, AOldFocusedCell), Regions[0])) then MakeNew(Classes.Rect(FFocusedCell, FFocusedCell)) else Add(Classes.Rect(FFocusedCell, FFocusedCell)); end; procedure TcxPivotGridViewDataSelection.ValidateSelections; var I: Integer; R: TRect; begin BeginUpdate; try for I := Count - 1 downto 0 do begin R := FRegions[I]; ViewData.ValidateSelection(R); if not EqualRect(R, FRegions[I]) then begin if cxRectContain(FRegions[I], R) then FRegions[I] := R else Delete(I); end; end; ValidateFocusedCell; AnchorCells := Classes.Rect(FocusedCell, FocusedCell); finally EndUpdate(False); end; end; function TcxPivotGridViewDataSelection.GetCount: Integer; begin Result := Length(FRegions); end; function TcxPivotGridViewDataSelection.GetRegion(AIndex: Integer): TRect; begin Result := FRegions[AIndex]; end; function TcxPivotGridViewDataSelection.GetMultiSelect: Boolean; begin Result := ViewData.OptionsSelection.MultiSelect; end; function TcxPivotGridViewDataSelection.GetTemporarySelection: TRect; begin if FHasTemporarySelection and (Count > 0) then Result := Regions[Count - 1] else Result := cxInvalidRect; end; function TcxPivotGridViewDataSelection.IsTemporarySelected: Boolean; begin Result := FHasTemporarySelection and not EqualRect(TemporarySelection, cxInvalidRect); end; procedure TcxPivotGridViewDataSelection.SetFocusedCell(const APoint: TPoint); begin if not cxPointIsEqual(APoint, FFocusedCell) then begin InnerSetFocusedCell(APoint); ChangeSelection(Classes.Rect(APoint, APoint), []); end; end; procedure TcxPivotGridViewDataSelection.SetTemporarySelection(const AValue: TRect); begin if not EqualRect(TemporarySelection, AValue) then begin if FHasTemporarySelection and (Count > 0) then FRegions[Count - 1] := AValue else Add(AValue); FHasTemporarySelection := FHasTemporarySelection or not EqualRect(AValue, cxInvalidRect); DoChanged; end; end; { TcxPivotGridExportController } constructor TcxPivotGridExportController.Create(APivotGrid: TcxCustomPivotGrid); begin FPivotGrid := APivotGrid; Initialize; end; destructor TcxPivotGridExportController.Destroy; begin Finalize; inherited Destroy; end; procedure TcxPivotGridExportController.Finalize; begin ExpandColumns := False; ExpandRows := False; ReplaceStyles(nil); ViewInfo.DrawBorders := FSavedBorders; ViewInfo.DrawExpandButtons := FSavedExpandButtons; PivotGrid.OptionsPrefilter.Assign(FSavedPrefilterOptions); PivotGrid.OptionsView.Assign(FSavedOptionsView); PivotGrid.Styles.Assign(FSavedStyles); PivotGrid.Changes := PivotGrid.Changes + [gcLayout]; PivotGrid.EndUpdate; FSavedStyles.Free; FSavedPrefilterOptions.Free; FSavedOptionsView.Free; end; procedure TcxPivotGridExportController.Initialize; begin FSavedOptionsView := PivotGrid.CreateOptionsView; FSavedOptionsView.Assign(PivotGrid.OptionsView); FSavedPrefilterOptions := PivotGrid.CreateOptionsPrefilter; FSavedPrefilterOptions.Assign(PivotGrid.OptionsPrefilter); FSavedStyles := PivotGrid.CreateStyles; FSavedStyles.Assign(PivotGrid.Styles); FSavedBorders := ViewInfo.DrawBorders; FSavedExpandButtons := ViewInfo.DrawExpandButtons; PivotGrid.BeginUpdate; ExpandRows := True; ExpandColumns := True; end; function TcxPivotGridExportController.CalculateViewInfo: TcxPivotGridViewInfo; var ALockCount: Integer; begin Result := PivotGrid.ViewInfo; ALockCount := PivotGrid.LockCount; try PivotGrid.LockCount := 0; Result.FIsPrinting := True; PivotGrid.ViewData.Calculate; Result.Calculate; Result.BeforePaint; finally Result.FIsPrinting := False; PivotGrid.LockCount := ALockCount; end; end; procedure TcxPivotGridExportController.ReplaceStyles( AStyles: IcxPivotGridBaseStyles); begin if AStyles = nil then PivotGrid.ViewInfo.FBaseStyles := PivotGrid.Styles else PivotGrid.ViewInfo.FBaseStyles := AStyles; end; function TcxPivotGridExportController.GetExpandColumns: Boolean; begin Result := PivotGrid.ViewData.ExpandColumns; end; function TcxPivotGridExportController.GetExpandRows: Boolean; begin Result := PivotGrid.ViewData.ExpandRows; end; function TcxPivotGridExportController.GetOptionsView: TcxPivotGridOptionsView; begin Result := PivotGrid.OptionsView; end; function TcxPivotGridExportController.GetStyles: TcxPivotGridStyles; begin Result := PivotGrid.Styles; end; function TcxPivotGridExportController.GetViewInfo: TcxPivotGridViewInfo; begin Result := PivotGrid.ViewInfo end; procedure TcxPivotGridExportController.SetExpandColumns(AValue: Boolean); begin PivotGrid.ViewData.ExpandColumns := AValue; end; procedure TcxPivotGridExportController.SetExpandRows(AValue: Boolean); begin PivotGrid.ViewData.ExpandRows := AValue; end; { TcxPivotGridRecords } procedure TcxPivotGridRecords.Add(ARecordIndex: Integer); begin inherited Add(Pointer(ARecordIndex)); Sorted := False; end; procedure TcxPivotGridRecords.MakeSorted; begin if not Sorted then begin Sort(@CompareRecordIndexes); Sorted := True; end; end; procedure TcxPivotGridRecords.MakeUnique; var I, J, K: Integer; begin MakeSorted; I := 0; K := 0; while I < Count do begin J := I + 1; while (J < Count) and (Integer(List^[I]) = Integer(List^[J])) do begin Integer(List^[J]) := MaxInt; Inc(J); Inc(K); end; I := J; end; if K > 0 then begin FSorted := False; MakeSorted; Count := Count - K; end; end; procedure TcxPivotGridRecords.CreateIntersection(AListA, AListB: TcxPivotGridRecords); type TIntArray = array[0..MaxInt div SizeOf(Integer) - 1] of Integer; PIntArray = ^TIntArray; var I: Integer; ASourceList: PIntArray; begin Capacity := Max(AListA.Count, AListB.Count); AListA.Assign(AListB, laOr); AListA.MakeSorted; I := 0; ASourceList := Pointer(AListA.List); while I < AListA.Count - 1 do begin Inc(I); if ASourceList^[I - 1] = ASourceList^[I] then begin Add(ASourceList^[I]); Inc(I); end end; FreeAndNil(AListA); FreeAndNil(AListB); end; function TcxPivotGridRecords.GetItem(AIndex: Integer): Integer; begin Result := Integer(inherited Items[AIndex]); end; procedure TcxPivotGridRecords.SetItem(AIndex, AValue: Integer); begin inherited Items[AIndex] := Pointer(AValue); end; { TcxPivotGridFields } function TcxPivotGridFields.GetField(Index: Integer): TcxPivotGridField; begin Result := TcxPivotGridField(inherited Items[Index]); end; function TcxPivotGridFields.GetFirstField: TcxPivotGridField; begin if Count > 0 then Result := TcxPivotGridField(List^[0]) else Result := nil; end; procedure TcxPivotGridFields.ArrangeFields; begin Sort(@CompareFieldsOrder); end; { TcxPivotGridDragAndDropObject } function TcxPivotGridDragAndDropObject.AboveCustomization: Boolean; begin Result := CanRemove; if Result then Result := PtInRect(PivotGrid.Customization.Form.BoundsRect, GetMouseCursorPos); end; procedure TcxPivotGridDragAndDropObject.BeginDragAndDrop; begin FDragField := PivotGrid.Controller.DownField; PivotGrid.Controller.DownField := nil; TransparentMask := TList.Create; if DragField = nil then Control.FinishDragAndDrop(False) else begin DragImage := CreateDragImage; SaveImage := CreateBitmap(GetDragImageSize); TempImage := CreateBitmap(GetDragImageSize); with FieldViewInfo.Bounds do begin if FieldViewInfo.Visible then HotSpot := Point(TopLeft.X - CurMousePos.X, TopLeft.Y - CurMousePos.Y) else HotSpot := cxPointInvert(CurMousePos); end; HotSpot := PivotGrid.ClientToScreen(HotSpot); end; inherited BeginDragAndDrop; end; function TcxPivotGridDragAndDropObject.CanRemove: Boolean; begin Result := PivotGrid.Customization.Visible and DragField.CanRemove; if Result and not PivotGrid.OptionsCustomize.Hiding then Result := PtInRect(PivotGrid.Customization.Form.BoundsRect, GetMouseCursorPos); end; function TcxPivotGridDragAndDropObject.CheckArea(const P: TPoint; var AInfo: TcxPivotGridDragDropAreaInfo): Boolean; var I: Integer; begin Result := False; for I := 0 to DragDropAreaCount - 1 do begin AInfo := DragDropAreas[I]; Result := PtInRect(AInfo.Bounds, P); if Result then Break; end; Result := Result and DragField.CanDrop(AInfo.Area); end; function TcxPivotGridDragAndDropObject.CreateDragImage: TBitmap; var R: TRect; I, J: Integer; AField: TcxPivotGridField; ACanvas: TcxCanvas; AGroup: TcxPivotGridFieldGroup; AViewInfo: TcxPivotGridFieldHeaderCellViewInfo; begin with GetDragImageSize do R := cxRect(0, 0, cx, cy); Result := CreateBitmap(Windows.TSize(R.BottomRight)); ACanvas := TcxCanvas.Create(Result.Canvas); try AViewInfo := FieldViewInfo; TransparentMask.Count := R.Right; if (AViewInfo.Group <> nil) and AViewInfo.Group.Visible then begin AGroup := AViewInfo.Group; for I := 0 to AGroup.FieldCount - 1 do begin AField := AGroup.Fields[I]; R.Right := R.Left + cxRectWidth(AField.ViewInfo.Bounds); if not AField.VisibleInGroup then Break; AField.ViewInfo.PaintTo(ACanvas, R, cxbsNormal, PivotGrid.Painter.DoCustomDrawFieldHeader); R.Left := R.Right + cxPivotGridHorzSpace; for J := R.Right to R.Left - 1 do begin if J < TransparentMask.Count then TransparentMask.List^[J] := Pointer(1); end; end; end else AViewInfo.PaintTo(ACanvas, R, cxbsNormal, PivotGrid.Painter.DoCustomDrawFieldHeader); finally ACanvas.Free; end; end; procedure TcxPivotGridDragAndDropObject.DragAndDrop( const P: TPoint; var Accepted: Boolean); var R, OldR, NewR: TRect; begin Accepted := CheckArea(P, DragDropInfo); if Accepted and not IsSameDropPlace then Accepted := PivotGrid.Groups.CanDropTo(DragDropInfo.Area, DragDropInfo.AreaIndex); inherited DragAndDrop(P, Accepted); NewR := GetImageBounds(P); if not DragImageVisible then ShowDragImage else begin OldR := GetImageBounds(PrevMousePos); if cxRectIntersect(R, NewR, OldR) then CopyIntersectedImage(R, OldR, NewR) else CopyImage(OldR, NewR); end; ChangeArrowPos(not Accepted or IsSameDropPlace); AAccepted := Accepted; end; procedure TcxPivotGridDragAndDropObject.DragDropField( AArea: TcxPivotGridFieldArea; AAreaIndex: Integer); begin PivotGrid.BeginUpdate; PivotGrid.ShowHourglassCursor; try if not IsSameDropPlace then begin DragField.DragDrop(AArea, AAreaIndex); PivotGrid.Modified; end; finally PivotGrid.EndUpdate; if FieldViewInfo.Field is TcxPivotGridField then PivotGrid.DoFieldPosChanged(TcxPivotGridField(FieldViewInfo.Field)) else PivotGrid.DoFieldPosChanged(nil); PivotGrid.HideHourglassCursor; end; end; procedure TcxPivotGridDragAndDropObject.EndDragAndDrop(Accepted: Boolean); begin inherited EndDragAndDrop(Accepted); if DragField <> nil then begin HideDragImage; DragField.SetState(cxbsNormal); RestoreArrows; if Accepted and AAccepted then DragDropField(DragDropInfo.Area, DragDropInfo.AreaIndex) else if Accepted and not AAccepted and CanRemove then begin if FieldViewInfo.Group <> nil then FieldViewInfo.Group.Visible := False else DragField.SetVisible(False); PivotGrid.Modified; end; end; FreeAndNil(TempImage); FreeAndNil(DragImage); FreeAndNil(SaveImage); FreeAndNil(ArrowsSaveBitmap); FreeAndNil(TransparentMask); end; function TcxPivotGridDragAndDropObject.GetDragAndDropCursor( Accepted: Boolean): TCursor; begin if Accepted or AboveCustomization then Result := crcxPivotGridArrow else if CanRemove then Result := crcxPivotGridRemove else Result := crcxPivotGridNoDrop; end; function TcxPivotGridDragAndDropObject.GetDragImageSize: TSize; var I: Integer; AField: TcxPivotGridField; AGroup: TcxPivotGridFieldGroup; AViewInfo: TcxPivotGridFieldHeaderCellViewInfo; begin if not ImageSizeCalculated then begin AViewInfo := FieldViewInfo; ImageSize := cxRectSize(AViewInfo.Bounds); if (AViewInfo.Group <> nil) and AViewInfo.Group.Visible then begin AGroup := AViewInfo.Group; for I := 1 to AGroup.FieldCount - 1 do begin AField := AGroup.Fields[I]; if not AField.VisibleInGroup then Break; Inc(ImageSize.cx, cxRectWidth(AField.ViewInfo.Bounds) + cxPivotGridHorzSpace); end; end; end; Result := ImageSize; end; function TcxPivotGridDragAndDropObject.IsSameDropPlace: Boolean; begin Result := DragField.GetVisible and (DragDropInfo.Area = FieldViewInfo.Area); if Result then begin if FieldViewInfo.Group = nil then begin Result := ((DragDropInfo.AreaIndex - FieldViewInfo.AreaIndex) in [0, 1]) or (FieldViewInfo.Field = DragDropInfo.Field); end else Result := FieldViewInfo.Group.IsSameDropPlace(DragDropInfo.AreaIndex); end; end; function TcxPivotGridDragAndDropObject.IsPixelTransparent( ALine, APos: Integer): Boolean; begin Result := (TransparentMask.List^[APos] <> nil) and (ALine <> ImageSize.cy div 2); end; procedure TcxPivotGridDragAndDropObject.TransparentMixDragImage; var C1, C2: Double; ACount, AHeight, ALine, I: Integer; DstLine, BkSrcLine, SrcLine: PByteArray; const Alpha = 200; begin C1 := Alpha / 255; C2 := 1.0 - C1; with DragImage do begin AHeight := Height; ACount := ((Width * 24 + 31) and not 31) shr 3; BkSrcLine := SaveImage.ScanLine[AHeight - 1]; SrcLine := DragImage.ScanLine[AHeight - 1]; DstLine := TempImage.ScanLine[AHeight - 1]; end; for ALine := 0 to AHeight - 1 do begin I := 0; while I < ACount do begin while (I < ACount - 1) and IsPixelTransparent(ALine, I div 3) do Inc(I, 3); DstLine^[I] := Round(SrcLine^[I] * C1) + Round(BkSrcLine^[I] * C2); Inc(I); end; Inc(Integer(BkSrcLine), ACount); Inc(Integer(SrcLine), ACount); Inc(Integer(DstLine), ACount); end; end; procedure TcxPivotGridDragAndDropObject.ChangeArrowPos(AllowHide: Boolean); var ANewLine: TRect; begin if not AllowHide then begin ANewLine := cxRectOffset(DragDropInfo.DisplayBounds, PivotGrid.ClientToScreen(cxNullPoint)); if cxRectIsEqual(ArrowsLine, ANewLine) and (ArrowsSaveBitmap <> nil) then Exit; end else if (ArrowsSaveBitmap = nil) then Exit; HideDragImage; RestoreArrows; if AllowHide then FreeAndNil(ArrowsSaveBitmap) else begin ArrowsLine := ANewLine; DrawArrows; end; ShowDragImage; end; procedure TcxPivotGridDragAndDropObject.CopyIntersectedImage( const ARect, AOldRect, ANewRect: TRect); procedure IncV(const ARect: TRect; AOfs, Value: Integer; Direct: Boolean; out ARes: TRect); type TR = array[Boolean, 0..1] of Integer; begin ARes := ARect; TR(ARes)[Direct, AOfs] := TR(ARes)[not Direct, AOfs] + Value; end; var R, R1: TRect; I: Integer; ADirect: Boolean; ASize: array[0..1] of Integer; begin with ANewRect do TPoint(ASize) := cxPoint(AOldRect.Right - Right, AOldRect.Bottom - Bottom); cxCopyImage(SaveImage, TempImage, cxPointInvert(ANewRect.TopLeft), cxPointInvert(AOldRect.TopLeft), ARect); with CreateScreenCanvas do try for I := 0 to 1 do begin if ASize[I] <> 0 then begin ADirect := ASize[I] > 0; IncV(ANewRect, I, ASize[I], ADirect, R1); IncV(DragImageBounds, I, ASize[I], ADirect, R); TempImage.Canvas.CopyRect(R, Canvas, R1); IncV(AOldRect, I, -ASize[I], not ADirect, R1); IncV(DragImageBounds, I, -ASize[I], not ADirect, R); Canvas.CopyRect(R1, SaveImage.Canvas, R); end; end; finally Free; end; SwapImages(TempImage, SaveImage); DrawImage(ANewRect.TopLeft); end; procedure TcxPivotGridDragAndDropObject.CopyImage( const AOldRect, ANewRect: TRect); begin RestoreScreen(PrevMousePos); GetScreenImage(CurMousePos); DrawImage(ANewRect.TopLeft); end; function TcxPivotGridDragAndDropObject.CreateBitmap(const ASize: TSize): TBitmap; begin Result := TBitmap.Create; Result.PixelFormat := pf24bit; Result.Width := ASize.cx; Result.Height := ASize.cy; end; function TcxPivotGridDragAndDropObject.CreateScreenCanvas: TcxCanvas; begin Result := TcxScreenCanvas.Create; end; procedure TcxPivotGridDragAndDropObject.DrawArrows; var R: TRect; ScrR: array[0..1] of TRect; I: Integer; begin GetArrowRects(ScrR[0], ScrR[1]); if ArrowsSaveBitmap = nil then ArrowsSaveBitmap := cxCreateBitmap(cxSize(20, 40)); with CreateScreenCanvas do try for I := 0 to 1 do begin R := ScrR[I]; OffsetRect(R, -ScrR[I].Left, -ScrR[I].Top); OffsetRect(R, 0, I * 20); ArrowsSaveBitmap.Canvas.CopyRect(R, Canvas, ScrR[I]); end; cxDrawArrows(Canvas, ArrowsLine, bLeft, DragDropArrowColor, clBtnText); finally Free; end; end; procedure TcxPivotGridDragAndDropObject.DrawImage(const APos: TPoint); begin TransparentMixDragImage; with CreateScreenCanvas do try Draw(APos.X, APos.Y, TempImage); finally Free; end; end; procedure TcxPivotGridDragAndDropObject.GetArrowRects(out R1, R2: TRect); begin with ArrowsLine do begin R1 := Rect(Left - 10, Top - 10, Left + 10, Top); R2 := Rect(Left - 10, Bottom, Left + 10, Bottom + 10); end; end; function TcxPivotGridDragAndDropObject.GetImageBounds(const APos: TPoint): TRect; begin Result := DragImageBounds; OffsetRect(Result, HotSpot.X + APos.X, HotSpot.Y + APos.Y); end; procedure TcxPivotGridDragAndDropObject.GetScreenImage( const APos: TPoint); begin with CreateScreenCanvas do try SaveImage.Canvas.CopyRect(DragImageBounds, Canvas, GetImageBounds(APos)); finally Free; end; end; procedure TcxPivotGridDragAndDropObject.RestoreArrows; var R: TRect; I: Integer; ARects: array[0..1] of TRect; begin if ArrowsSaveBitmap = nil then Exit; GetArrowRects(ARects[0], ARects[1]); with CreateScreenCanvas do try for I := 0 to 1 do begin R := ARects[I]; OffsetRect(R, -ARects[I].Left, -ARects[I].Top + I * 20); Canvas.CopyRect(ARects[I], ArrowsSaveBitmap.Canvas, R); end; finally Free; end; end; procedure TcxPivotGridDragAndDropObject.HideDragImage; begin DragImageVisible := False; RestoreScreen(CurMousePos); end; procedure TcxPivotGridDragAndDropObject.RestoreScreen( const APos: TPoint); begin with CreateScreenCanvas do try with cxPointOffset(APos, HotSpot) do Draw(X, Y, SaveImage); finally Free; end; end; procedure TcxPivotGridDragAndDropObject.ShowDragImage; begin DragImageVisible := True; GetScreenImage(CurMousePos); DrawImage(GetImageBounds(CurMousePos).TopLeft); end; function TcxPivotGridDragAndDropObject.GetDragDropAreaCount: Integer; begin Result := ViewInfo.FDragDropAreas.Count; end; function TcxPivotGridDragAndDropObject.GetDragDropArea( AIndex: Integer): TcxPivotGridDragDropAreaInfo; begin Result := ViewInfo.FDragDropAreas[AIndex] as TcxPivotGridDragDropAreaInfo; end; function TcxPivotGridDragAndDropObject.GetDragDropArrowColor: TColor; begin Result := PivotGrid.OptionsView.DropArrowColor; end; function TcxPivotGridDragAndDropObject.GetDragImageBounds: TRect; begin Result.TopLeft := cxNullPoint; TSize(Result.BottomRight) := GetDragImageSize; end; function TcxPivotGridDragAndDropObject.GetFieldViewInfo: TcxPivotGridFieldHeaderCellViewInfo; begin Result := DragField.GetViewInfo; if Result.Group <> nil then Result := Result.Group.Fields[0].ViewInfo; end; { TcxPivotGridStyleSheet } class function TcxPivotGridStyleSheet.GetStylesClass: TcxCustomStylesClass; begin Result := TcxPivotGridStyles; end; function TcxPivotGridStyleSheet.GetStylesValue: TcxPivotGridStyles; begin Result := GetStyles as TcxPivotGridStyles; end; procedure TcxPivotGridStyleSheet.SetStylesValue(AValue: TcxPivotGridStyles); begin SetStyles(AValue); end; { TcxCustomDesignHelper } procedure TcxPivotGridCustomDesignHelper.RefreshListener( APivotGrid: TcxCustomPivotGrid); begin if not APivotGrid.IsLocked and APivotGrid.HandleAllocated then begin APivotGrid.ViewInfo.Calculate; APivotGrid.Invalidate; end; end; function cxPivotGridHierarchyImages: TImageList; var B: TBitmap; begin if FHierarchyImages = nil then begin FHierarchyImages := TImageList.CreateSize(16, 16); B := TBitmap.Create; try B.LoadFromResourceName(HInstance, 'CXPIVOTGRIDHIERARCHYIMAGES'); FHierarchyImages.AddMasked(B, clFuchsia); finally B.Free; end; end; Result := FHierarchyImages; end; { TcxPivotGridHitTest } constructor TcxPivotGridHitTest.Create(AOwner: TcxCustomPivotGrid); begin FOwner := AOwner; end; destructor TcxPivotGridHitTest.Destroy; begin FResizeField := nil; inherited Destroy; end; procedure TcxPivotGridHitTest.Clear; begin Flags := 0; FField := nil; FHitObject := nil; FResizeField := nil; end; procedure TcxPivotGridHitTest.Recalculate; begin Clear; ViewInfo.CalculateHitTest(Self); end; function TcxPivotGridHitTest.GetBitState(AIndex: Integer): Boolean; begin Result := (Flags and (1 shl AIndex)) <> 0; end; function TcxPivotGridHitTest.GetGroupItem: TcxPivotGridGroupItem; var AObject: TObject; begin Result := nil; AObject := HitObject; if AObject is TcxPivotGridHeaderCellViewInfo then begin AObject := TcxPivotGridHeaderCellViewInfo(HitObject).Data; if AObject is TcxPivotGridViewDataItem then AObject := TcxPivotGridViewDataItem(AObject).GroupItem; if AObject is TcxPivotGridGroupItem then Result := TcxPivotGridGroupItem(AObject); end; end; function TcxPivotGridHitTest.GetPosValue(AIndex: Integer): Integer; begin if AIndex = 0 then Result := FHitPoint.X else Result := FHitPoint.Y end; function TcxPivotGridHitTest.GetViewInfo: TcxPivotGridViewInfo; begin Result := PivotGrid.ViewInfo; end; procedure TcxPivotGridHitTest.SetBitState(AIndex: Integer; AValue: Boolean); begin if AValue then Flags := Flags or (1 shl AIndex) else Flags := Flags and not (1 shl AIndex); end; procedure TcxPivotGridHitTest.SetPosValue(AIndex, AValue: Integer); begin if AIndex = 0 then FHitPoint.X := AValue else FHitPoint.Y := AValue; Recalculate; end; procedure TcxPivotGridHitTest.SetHitPoint(const AValue: TPoint); begin FHitPoint := AValue; Recalculate; end; { TcxPivotGridSortBySummaryInfo } constructor TcxPivotGridSortBySummaryInfo.Create(AOwner: TcxPivotGridField); begin FOwner := AOwner; FSummaryType := stSum; end; procedure TcxPivotGridSortBySummaryInfo.Assign(Source: TPersistent); begin if Source is TcxPivotGridSortBySummaryInfo then begin FField := TcxPivotGridSortBySummaryInfo(Source).Field; FSummaryType := TcxPivotGridSortBySummaryInfo(Source).SummaryType; end; end; procedure TcxPivotGridSortBySummaryInfo.Changed; begin PivotGrid.DataChanged; end; function TcxPivotGridSortBySummaryInfo.GetOwner: TPersistent; begin Result := Owner; end; function TcxPivotGridSortBySummaryInfo.ValidateProperties: Boolean; begin Result := (Field <> nil) and (Field.Area = faData); end; function TcxPivotGridSortBySummaryInfo.GetPivotGrid: TcxCustomPivotGrid; begin Result := Owner.PivotGrid; end; procedure TcxPivotGridSortBySummaryInfo.SetField( AValue: TcxPivotGridField); begin if AValue <> FField then begin FField := AValue; Changed; end; end; procedure TcxPivotGridSortBySummaryInfo.SetSummaryType( AValue: TcxPivotGridSummaryType); begin if AValue <> FSummaryType then begin FSummaryType := AValue; Changed; end; end; { TcxPivotGridOptionsDataField } constructor TcxPivotGridOptionsDataField.Create(AOwner: TcxCustomPivotGrid); begin inherited Create(AOwner); FAreaIndex := -1; FWidth := cxPivotGridDefaultFieldWidth; FMoving := True; FMinWidth := cxPivotGridDefaultFieldMinWidth; FViewInfo := TcxPivotGridFieldHeaderCellViewInfo.CreateEx(Self); end; destructor TcxPivotGridOptionsDataField.Destroy; begin FViewInfo.Free; inherited Destroy; end; procedure TcxPivotGridOptionsDataField.Assign(Source: TPersistent); begin if Source is TcxPivotGridOptionsDataField then begin FArea := TcxPivotGridOptionsDataField(Source).FArea; FAreaIndex := TcxPivotGridOptionsDataField(Source).FAreaIndex; FCaption := TcxPivotGridOptionsDataField(Source).Caption; FMinWidth := TcxPivotGridOptionsDataField(Source).FMinWidth; FMoving := TcxPivotGridOptionsDataField(Source).Moving; FWidth := TcxPivotGridOptionsDataField(Source).FWidth; end; inherited Assign(Source); end; procedure TcxPivotGridOptionsDataField.ApplyBestFit; var AWidth, I: Integer; begin PivotGrid.BeginUpdate; try if Area = dfaRow then begin AWidth := ViewInfo.MeasureWidth; for I := 0 to DataBuilder.DataFields.Count - 1 do AWidth := Max(AWidth, DataBuilder.DataFields[I].ViewInfo.MeasureWidth); Width := AWidth; end else for I := 0 to DataBuilder.DataFields.Count - 1 do DataBuilder.DataFields[I].ApplyBestFit; finally PivotGrid.EndUpdate; end; end; function TcxPivotGridOptionsDataField.CanDrag: Boolean; begin Result := Moving and PivotGrid.OptionsCustomize.Moving; end; function TcxPivotGridOptionsDataField.CanDrop(Area: TcxPivotGridFieldArea): Boolean; begin Result := Area in [faRow, faColumn]; end; function TcxPivotGridOptionsDataField.CanRemove: Boolean; begin Result := False; end; function TcxPivotGridOptionsDataField.CanResize: Boolean; begin Result := PivotGrid.OptionsCustomize.Sizing; end; function TcxPivotGridOptionsDataField.CheckIndex(AIndex: Integer; AFields: TcxPivotGridFields; AArea: TcxPivotGridFieldArea): Integer; var I: Integer; AField: TcxPivotGridField; begin if AIndex < 0 then Result := AFields.Count else begin Result := AIndex; for I := 0 to PivotGrid.FieldCount - 1 do begin AField := PivotGrid.Fields[I]; if AField.Visible or (AField.AreaIndex = -1) or (AField.Area <> AArea) then Continue; if AField.AreaIndex < AIndex then Dec(Result); end; Result := Min(Result, AFields.Count); end; end; procedure TcxPivotGridOptionsDataField.DragDrop( AArea: TcxPivotGridFieldArea; AIndex: Integer); var ANewArea: TcxPivotGridDataFieldArea; begin if not (AArea in [faRow, faColumn]) then Exit; PivotGrid.BeginUpdate; try if AArea = faColumn then ANewArea := dfaColumn else ANewArea := dfaRow; if (ANewArea = Area) and (AreaIndex >= 0) and (AIndex > AreaIndex) then Dec(AIndex); Area := ANewArea; AreaIndex := AIndex; finally PivotGrid.EndUpdate; end; PivotGrid.DoFieldPosChanged(nil); end; function TcxPivotGridOptionsDataField.GetActualAreaIndex( AInHeaderArea: Boolean = True): Integer; begin Result := -1; if (Area = dfaNone) and AInHeaderArea then Exit; if Area = dfaRow then begin if AInHeaderArea and not PivotGrid.OptionsView.RowFields then Result := -1 else Result := CheckIndex(AreaIndex, PivotGrid.DataBuilder.RowFields, faRow) end else begin if AInHeaderArea and not PivotGrid.OptionsView.ColumnFields then Result := -1 else Result := CheckIndex(AreaIndex, PivotGrid.DataBuilder.ColumnFields, faColumn); end; end; function TcxPivotGridOptionsDataField.IsSameArea( AArea: TcxPivotGridFieldArea): Boolean; begin Result := (Area <> dfaNone) and (DataAreaToFieldArea[Area] = AArea); end; function TcxPivotGridOptionsDataField.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end; function TcxPivotGridOptionsDataField._AddRef: Integer; begin Result := -1; end; function TcxPivotGridOptionsDataField._Release: Integer; begin Result := -1; end; function TcxPivotGridOptionsDataField.GetActualWidth: Integer; begin Result := Width; if Result = 0 then Result := ViewInfo.MeasureWidth; Result := Max(Result, cxPivotGridDefaultFieldMinWidth); end; function TcxPivotGridOptionsDataField.GetCaption: string; begin if not IsCaptionAssigned then Result := cxGetResourceString(@scxDataField) else Result := FCaption; end; function TcxPivotGridOptionsDataField.GetDataBuilder: TcxPivotGridDataBuilder; begin Result := PivotGrid.DataBuilder; end; function TcxPivotGridOptionsDataField.GetHeaderWidth: Integer; begin Result := ViewInfo.MeasureWidth; end; procedure TcxPivotGridOptionsDataField.SetArea(AValue: TcxPivotGridDataFieldArea); begin if FArea <> AValue then begin FArea := AValue; Changed; end; end; procedure TcxPivotGridOptionsDataField.SetAreaIndex(AValue: Integer); begin AValue := Max(-1, AValue); if AValue <> FAreaIndex then begin FAreaIndex := AValue; if (AValue <> -1) and (Area <> dfaNone) then if not PivotGrid.SetFieldAreaIndex(Self, DataAreaToFieldArea[Area], AValue) then FAreaIndex := AValue; if not PivotGrid.IsLocked then PivotGrid.DoFieldPosChanged(nil); Changed; end; end; procedure TcxPivotGridOptionsDataField.SetCaption(const AValue: string); begin if FCaption <> AValue then begin FCaption := AValue; FIsCaptionAssigned := cxGetResourceString(@scxDataField) <> FCaption; Changed; end; end; procedure TcxPivotGridOptionsDataField.SetWidth(AValue: Integer); begin AValue := Max(MinWidth, AValue); if FWidth <> AValue then begin FWidth := AValue; Changed; end; end; procedure TcxPivotGridOptionsDataField.ChangeExpanding; begin end; procedure TcxPivotGridOptionsDataField.ChangeSorting; begin SetState(cxbsNormal); end; function TcxPivotGridOptionsDataField.GetMinWidth: Integer; begin Result := FMinWidth; end; function TcxPivotGridOptionsDataField.GetViewInfo: TcxPivotGridFieldHeaderCellViewInfo; begin Result := ViewInfo; end; function TcxPivotGridOptionsDataField.GetVisible: Boolean; begin Result := Area <> dfaNone; end; procedure TcxPivotGridOptionsDataField.SetMinWidth(AValue: Integer); begin AValue := Max(0, AValue); if FMinWidth <> AValue then begin FMinWidth := AValue; Width := Width; Changed; end; end; procedure TcxPivotGridOptionsDataField.SetState(AState: TcxButtonState); begin ViewInfo.State := AState; PivotGrid.InvalidateRect(ViewInfo.Bounds, False); end; procedure TcxPivotGridOptionsDataField.SetVisible(AValue: Boolean); begin end; { TcxPivotGridCrossCellDataSource } constructor TcxPivotGridCrossCellDataSource.Create(ACell: TcxPivotGridCrossCell); begin PivotGrid := ACell.PivotGrid; Records := ACell.CreateCrossRecords; end; constructor TcxPivotGridCrossCellDataSource.CreateEx(ACrossCells: TList); var I: Integer; ACrossRecords: TcxPivotGridRecords; ACell: TcxPivotGridCrossCell; begin for I := 0 to ACrossCells.Count - 1 do begin ACell := TcxPivotGridCrossCell(ACrossCells[I]); if I = 0 then Create(ACell) else begin ACrossRecords := ACell.CreateCrossRecords; try Records.Assign(ACrossRecords, laOr); finally ACrossRecords.Free; end; end; end; if HasData then Records.MakeUnique else Records := TcxPivotGridRecords.Create; end; destructor TcxPivotGridCrossCellDataSource.Destroy; begin FreeAndNil(Records); inherited Destroy; end; function TcxPivotGridCrossCellDataSource.HasData: Boolean; begin Result := (PivotGrid <> nil) and (Records <> nil); end; function TcxPivotGridCrossCellDataSource.GetFieldCount: Integer; begin Result := PivotGrid.FieldCount; end; function TcxPivotGridCrossCellDataSource.GetPivotGridField(AIndex: Integer): TcxPivotGridField; begin Result := PivotGrid.Fields[AIndex]; end; function TcxPivotGridCrossCellDataSource.GetRecordCount: Integer; begin if HasData then Result := Records.Count else Result := 0; end; function TcxPivotGridCrossCellDataSource.GetValue( ARecordHandle: TcxDataRecordHandle; AItemHandle: TcxDataItemHandle): Variant; var ARecordIndex: Integer; AField: TcxPivotGridField; begin if HasData then begin if Provider <> nil then AField := PivotGridFields[TcxPivotGridDataController( DataController).GetItemID(DataController.GetItem(Integer(AItemHandle)))] else with TcxPivotGridDataController(PivotGrid.DataController) do AField := PivotGrid.Fields[GetItemID(GetItem(Integer(AItemHandle)))]; ARecordIndex := Records[Integer(ARecordHandle)]; if AField.GroupInterval = giDefault then Result := AField.Values[ARecordIndex] else Result := AField.GetGroupValue(ARecordIndex); end else Result := Null; end; { TcxPivotGridHotTrackController } constructor TcxPivotGridHotTrackController.Create(AOwner: TcxPivotGridController); begin FOwner := AOwner; end; procedure TcxPivotGridHotTrackController.Clear; begin FCell := nil; end; procedure TcxPivotGridHotTrackController.Update( AObject: TcxPivotGridCustomCellViewInfo); begin if Cell <> AObject then begin UpdateState(Cell); FCell := AObject; end; UpdateState(AObject); end; procedure TcxPivotGridHotTrackController.UpdateState( AObject: TcxPivotGridCustomCellViewInfo); begin if (AObject <> nil) and AObject.SetHotTrack(HitTest) then PivotGrid.InvalidateRect(AObject.ClipRect, False); end; function TcxPivotGridHotTrackController.GetHitTest: TcxPivotGridHitTest; begin Result := Owner.HitTest; end; function TcxPivotGridHotTrackController.GetPivotGrid: TcxCustomPivotGrid; begin Result := Owner.PivotGrid; end; { TcxPivotGridHintController } constructor TcxPivotGridHintController.Create(AOwner: TcxPivotGridController); begin FOwner := AOwner; FHintCheckerTimer := TTimer.Create(nil); end; destructor TcxPivotGridHintController.Destroy; begin HideHint; FreeAndNil(FHintCheckerTimer); inherited Destroy; end; procedure TcxPivotGridHintController.HideHint; begin StopHintCheckerTimer; EndMouseTracking(Self); HintAreaBounds := cxEmptyRect; if HintWindow <> nil then ShowWindow(HintWindow.Handle, SW_HIDE); FreeAndNil(FHintWindow); FHintVisible := False; HintObject := nil; end; procedure TcxPivotGridHintController.ShowHint; var R, R1: TRect; begin HideHint; HintWindowNeeded; if GetHintInfo(R, R1) then begin HintAreaBounds := R; if not IsMouseTracking(Self) then BeginMouseTracking(PivotGrid, HintAreaBounds, Self); FHintVisible := True; StartHintCheckerTimer; cxActivateHint(HintWindow, R1, HintText); end; end; procedure TcxPivotGridHintController.Update; begin if not PtInRect(FHintAreaBounds, HitTest.HitPoint) or HitTest.HitAtFilter or HitTest.HitAtButton then HideHint; if NeedShowHint then ShowHint; end; function TcxPivotGridHintController.CanShowHint: Boolean; begin Result := Application.Active; end; function TcxPivotGridHintController.GetHintInfo( var ABounds, AWindowBounds: TRect): Boolean; begin Result := (HitTest.HitObject <> nil) and CanShowHint; if Result then begin FHintText := HitTest.HitObject.HintText; Result := (Length(FHintText) > 0) and (HintObject <> HitTest.HitObject); if Result then begin ABounds := HitTest.HitObject.ClipRect; AWindowBounds := HintWindow.CalcHintRect(MaxInt, HintText, nil); with PivotGrid.ClientToScreen(ABounds.TopLeft) do OffsetRect(AWindowBounds, X, Y); HintObject := HitTest.HitObject; end; end; end; procedure TcxPivotGridHintController.HintCheckerTimerHandler(Sender: TObject); begin if not CanShowHint then HideHint; end; procedure TcxPivotGridHintController.HintWindowNeeded; begin if (HintWindow = nil) or (HintWindow.ClassType <> HintWindowClass) then begin FreeAndNil(FHintWindow); FHintWindow := HintWindowClass.Create(nil); FHintWindow.Color := Application.HintColor; end; end; function TcxPivotGridHintController.NeedShowHint: Boolean; begin with PivotGrid.OptionsBehavior do begin Result := (HitTest.HitObject <> nil) and (HitTest.HitAtDataCell and CellHints) or (HitTest.HitAtGroupHeader and GroupHeaderHints) or (HitTest.HitAtField and FieldHeaderHints); Result := Result and HitTest.HitObject.NeedShowHint(HitTest.HitPoint) and (HitTest.HitObject <> HintObject); end; end; procedure TcxPivotGridHintController.MouseLeave; begin HideHint; end; procedure TcxPivotGridHintController.StartHintCheckerTimer; begin FHintCheckerTimer.Interval := 100; FHintCheckerTimer.OnTimer := HintCheckerTimerHandler; FHintCheckerTimer.Enabled := True; end; procedure TcxPivotGridHintController.StopHintCheckerTimer; begin FHintCheckerTimer.Enabled := False; FHintCheckerTimer.OnTimer := nil; end; function TcxPivotGridHintController.GetHitTest: TcxPivotGridHitTest; begin Result := PivotGrid.HitTest; end; function TcxPivotGridHintController.GetPivotGrid: TcxCustomPivotGrid; begin Result := Owner.PivotGrid; end; { TcxPivotGridController } constructor TcxPivotGridController.Create(AOwner: TcxCustomPivotGrid); begin FOwner := AOwner; FHintController := CreateHintController; FHotTrackController := CreateHotTrackController; FFilterPopup := CreateFilterPopup; FPrefilterPopup := TcxPivotGridMRUPrefilterPopup.Create(PivotGrid); FPrefilterPopup.LookAndFeel.MasterLookAndFeel := PivotGrid.LookAndFeel; FSelectionTimer := TTimer.Create(nil); FIgnoreSelection := False; end; destructor TcxPivotGridController.Destroy; begin StopSelectionTimer; FHintController.Free; FSelectionTimer.Free; FHotTrackController.Free; FPrefilterPopup.Free; FFilterPopup.Free; inherited Destroy; end; procedure TcxPivotGridController.Clear; begin FHotTrackController.Clear; DownField := nil; end; procedure TcxPivotGridController.BeforeMouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin end; procedure TcxPivotGridController.DblClick; begin CalculateIgnoreSelection; HitTest.Recalculate; with HitTest do begin if HitAtHorzSizingEdge and (ResizeField <> nil) and ResizeField.CanResize then HitTest.ResizeField.ApplyBestFit; end; end; procedure TcxPivotGridController.KeyDown(var AKey: Word; AShift: TShiftState); const Navigation: array[Boolean] of Integer = (-1, 1); begin case AKey of VK_INSERT: if ssCtrl in AShift then PivotGrid.CopyToClipboard(False); VK_UP, VK_DOWN: SetSelectionInc(0, Navigation[AKey = VK_DOWN], AShift); VK_LEFT, VK_RIGHT: ProcessNavigationByStep(AKey = VK_LEFT, AShift); VK_PRIOR, VK_NEXT: begin ViewData.DoNextPage(AKey = VK_NEXT); SetSelectionInc(0, Navigation[AKey = VK_NEXT] * ViewData.RowsPerPage, AShift); end; VK_HOME, VK_END: if ssCtrl in AShift then SetSelection(FocusedCell.X, MaxInt * Navigation[AKey = VK_END], AShift - [ssCtrl]) else SetSelection(MaxInt * Navigation[AKey = VK_END], FocusedCell.Y, AShift); VK_TAB: ProcessTabKeyDown(ssShift in AShift); end; case AKey of VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_PRIOR, VK_NEXT, VK_HOME, VK_END, VK_TAB: begin ViewData.Selection.ApplyTemporarySelection(True); PivotGrid.ViewData.MakeSelectionVisible; end; end; end; procedure TcxPivotGridController.KeyPress(var AKey: Char); begin case AKey of ^C: begin PivotGrid.CopyToClipboard(False); AKey := #0; end; ^A: begin PivotGrid.ViewData.Selection.MakeNew(Rect(0, 0, MaxInt, MaxInt)); AKey := #0; end; #13: AKey := #0; end; end; procedure TcxPivotGridController.MakeCellFocused( ACell: TcxPivotGridDataCellViewInfo; AShift: TShiftState); begin SetSelection(ACell.ColumnIndex, ACell.RowIndex, AShift); end; procedure TcxPivotGridController.MouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin HintController.HideHint; CalculateIgnoreSelection; if HitTest.HitAtField or HitTest.HitAtDataField then DoFieldHeaderClick(HitTest.Field, Shift); if Button = mbLeft then begin if IsButtonDown then PivotGrid.LayoutChanged; if HitTest.HitAtFilter and not FilterOpenedBeforeClick and not IsDesigning then begin FFilterPopup.Field := HitTest.Field as TcxPivotGridField; FFilterPopup.Popup; end; if HitTest.HitAtPrefilter and not PrefilterOpenedBeforeClick and not IsDesigning then begin if TcxPivotGridPrefilterViewInfo(HitTest.HitObject).SetPressed(HitTest, True) then PivotGrid.InvalidateRect(TcxPivotGridPrefilterViewInfo(HitTest.HitObject).Bounds, False); if HitTest.HitAtPrefilterDropDownButton or HitTest.HitAtPrefilterCaption and ViewInfo.Prefilter.CanMRUPopupShow then FPrefilterPopup.Popup; end; end; FilterOpenedBeforeClick := False; PrefilterOpenedBeforeClick := False; if FIgnoreSelection or ((HitTest.HitAtDataCell and IsCellSelected(HitTest.HitObject as TcxPivotGridDataCellViewInfo) and (Button = mbRight))) then Exit; SuspendSelectionTimer := HitTest.HitAtDataCell; MakeSelected(Shift); end; procedure TcxPivotGridController.MouseLeave; begin Update; HotTrackController.Update(HitTest.HitObject); FIgnoreSelection := False; end; procedure TcxPivotGridController.MouseMove(Shift: TShiftState; X, Y: Integer); begin if PivotGrid.DragAndDropState = ddsNone then begin HotTrackController.Update(HitTest.HitObject); if (ssLeft in Shift) then begin MakeSelected(Shift, True); if SuspendSelectionTimer then CheckSelectionTimer(X, Y); end; if [ssLeft, ssRight] * Shift <> [] then HintController.HideHint else HintController.Update; end; end; procedure TcxPivotGridController.MouseUp( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var I: Integer; APrefilter: TcxPivotGridPrefilter; begin SuspendSelectionTimer := False; if (DownField <> nil) and not HitTest.HitAtFilter and not FilterOpenedBeforeClick then DownField.ChangeSorting; for I := 0 to PivotGrid.FieldCount - 1 do begin if PivotGrid.Fields[I].ViewInfo.State = cxbsPressed then PivotGrid.Fields[I].SetState(cxbsNormal); end; APrefilter := PivotGrid.ViewInfo.Prefilter; if APrefilter.Visible then begin APrefilter.ViewInfo.SetPressed(HitTest, False); PivotGrid.InvalidateRect(APrefilter.ViewInfo.Bounds, False); end; StopSelectionTimer; HintController.Update; DownField := nil; if not FIgnoreSelection then ViewData.Selection.ApplyTemporarySelection(False); FIgnoreSelection := False; end; procedure TcxPivotGridController.StartSelectionTimer; begin if SelectionTimer.Enabled then Exit; SelectionTimer.Interval := cxPivotGridAutoScrollInterval; SelectionTimer.Enabled := True; SelectionTimer.OnTimer := SelectionTimerHandler; end; procedure TcxPivotGridController.StopSelectionTimer; begin SelectionTimer.OnTimer := nil; SelectionTimer.Enabled := False; end; procedure TcxPivotGridController.Update; begin if PivotGrid.HandleAllocated then HitTest.HitPoint := PivotGrid.ScreenToClient(GetMouseCursorPos) else HitTest.HitPoint := cxNullPoint; end; procedure TcxPivotGridController.CalculateAnchor(AShift: TShiftState); var ADataItem: TcxPivotGridViewDataItem; begin if not (ssShift in AShift) or (ssCtrl in AShift) or not (ssLeft in AShift) then begin if HitTest.HitAtDataCell then with TcxPivotGridDataCellViewInfo(HitTest.HitObject) do ViewData.AnchorCells := Rect(ColumnIndex, RowIndex, ColumnIndex, RowIndex) else if HitTest.HitAtGroupHeader and (HitTest.HitObject is TcxPivotGridHeaderCellViewInfo) then begin if TcxPivotGridHeaderCellViewInfo(HitTest.HitObject).Data is TcxPivotGridViewDataItem then begin ADataItem := TcxPivotGridHeaderCellViewInfo(HitTest.HitObject).Data as TcxPivotGridViewDataItem; if (ADataItem.IsDataField and (ADataItem.Parent.GroupItem is TcxPivotGridColumnItem)) or (ADataItem.GroupItem is TcxPivotGridColumnItem) then ViewData.AnchorCells := Rect(ADataItem.GetChildLeftVisibleIndex, -1, ADataItem.GetChildRightVisibleIndex, -1) else ViewData.AnchorCells := Rect(-1, ADataItem.GetChildLeftVisibleIndex, -1, ADataItem.GetChildRightVisibleIndex); end; end else ViewData.AnchorCells := cxInvalidRect; end; end; function TcxPivotGridController.CalculateFilterDropDownSize( AFilter: TcxPivotGridFieldFilter): TSize; begin if not OptionsCustomize.FilterResizable then begin Result.cx := Max(cxPivotGridFilterPopupMinWidth, OptionsView.FilterDropDownWidth); Result.cy := Max(cxPivotGridFilterPopupMinHeight, FilterPopup.GetHeight(OptionsView.FilterDropDownMaxItemCount)); end else begin Result := AFilter.WindowSize; if cxSizeIsEqual(Result, cxNullSize) then Result := Size(cxPivotGridFilterPopupDefaultWidth, cxPivotGridFilterPopupDefaultHeight); end; end; procedure TcxPivotGridController.CheckSelectionTimer(const X, Y: Integer); var R: TRect; begin R := ViewInfo.DataCellsBounds; InflateRect(R, -cxPivotGridAutoScrollAreaWidth, -cxPivotGridAutoScrollAreaWidth); if not PtInRect(R, Point(X, Y)) and SuspendSelectionTimer and HitTest.HitAtDataCell then StartSelectionTimer else StopSelectionTimer; end; function TcxPivotGridController.CreateFilterPopup: TcxPivotGridFilterPopup; begin Result := TcxPivotGridFilterPopup.Create(PivotGrid); Result.LookAndFeel.MasterLookAndFeel := PivotGrid.LookAndFeel; end; function TcxPivotGridController.CreateHintController: TcxPivotGridHintController; begin Result := TcxPivotGridHintController.Create(Self); end; function TcxPivotGridController.CreateHotTrackController: TcxPivotGridHotTrackController; begin Result := TcxPivotGridHotTrackController.Create(Self) end; procedure TcxPivotGridController.DoFieldHeaderClick( AField: TPersistent; AShift: TShiftState); var ADownField: IcxPivotGridField; begin if not (ssLeft in AShift) then Exit; if PivotGrid.IsDesignerAvailable and (AField is TcxPivotGridField) or (AField = nil) then DesignerHelper.Select(AField, AShift); if Supports(AField, IcxPivotGridField, DownField) and not HitTest.HitAtFilter then begin ADownField := DownField; if not HitTest.HitAtButton then DownField.SetState(cxbsPressed) else DownField.ChangeExpanding; DownField := ADownField; end; end; function TcxPivotGridController.GetCursor(const X, Y: Integer): TCursor; begin Result := crDefault; HitTest.HitPoint := Point(X, Y); if HitTest.HitAtHorzSizingEdge then Result := crcxPivotGridHorzSize; end; function TcxPivotGridController.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; begin if HitTest.HitAtDataField or HitTest.HitAtField then Result := TcxPivotGridDragAndDropObject else if HitTest.HitAtHorzSizingEdge then Result := TcxPivotGridResizingObject else Result := nil; end; function TcxPivotGridController.IsButtonDown: Boolean; begin Result := HitTest.HitAtButton and (HitTest.GroupItem <> nil); if Result then HitTest.GroupItem.Expanded := not HitTest.GroupItem.Expanded; end; function TcxPivotGridController.IsCellSelected( ACell: TcxPivotGridDataCellViewInfo): Boolean; begin Result := ViewData.IsCellSelected(ACell.RowIndex, ACell.ColumnIndex); end; procedure TcxPivotGridController.MakeSelected(AShift: TShiftState; AMouseMove: Boolean = False); var AObject: TObject; begin if FIgnoreSelection then Exit; if (HitTest.HitAtDataCell and (HitTest.HitObject is TcxPivotGridDataCellViewInfo)) then with HitTest.HitObject as TcxPivotGridDataCellViewInfo do if not ViewData.CanCellSelect(RowIndex, ColumnIndex) then Exit; if not AMouseMove then CalculateAnchor(AShift); if ((ssRight in AShift) or (ssLeft in AShift)) then begin if HitTest.HitAtGroupHeader and (HitTest.HitObject is TcxPivotGridHeaderCellViewInfo) and not FIgnoreSelection then begin AObject := TcxPivotGridHeaderCellViewInfo(HitTest.HitObject).Data; if (AObject is TcxPivotGridViewDataItem) then ViewData.HeaderCellSelect(TcxPivotGridViewDataItem(AObject), AShift); end else if HitTest.HitAtDataCell and (HitTest.HitObject is TcxPivotGridDataCellViewInfo) then MakeCellFocused(TcxPivotGridDataCellViewInfo(HitTest.HitObject), AShift); end; end; function TcxPivotGridController.ProcessNavigationByStep(AGoBackward: Boolean; AShiftState: TShiftState): Boolean; function IsLastCellInLine: Boolean; begin if AGoBackward then Result := FocusedCell.X = 0 else Result := FocusedCell.X = ViewData.ColumnCount - 1; end; function IsLastCellInRow: Boolean; begin if AGoBackward then Result := FocusedCell.Y = 0 else Result := FocusedCell.Y = ViewData.RowCount - 1; end; const Navigation: array[Boolean] of Integer = (1, -1); begin Result := IsLastCellInLine; if not Result then SetSelectionInc(Navigation[AGoBackward], 0, AShiftState) else if PivotGrid.OptionsBehavior.FocusCellOnCycle then begin Result := IsLastCellInRow; if not Result then SetSelectionInc(-Navigation[AGoBackward] * ViewData.ColumnCount, Navigation[AGoBackward], []); end; end; procedure TcxPivotGridController.ProcessTabKeyDown(AGoBackward: Boolean); begin if PivotGrid.OptionsBehavior.FocusCellOnTab then begin if PivotGrid.IsFocused and ProcessNavigationByStep(AGoBackward, []) then PostMessage(GetParentForm(PivotGrid).Handle, WM_NEXTDLGCTL, WPARAM(AGoBackward), 0); end; end; procedure TcxPivotGridController.SelectionTimerHandler(Sender: TObject); var R: TRect; APos: TPoint; DX, DY: Integer; begin R := ViewInfo.DataCellsBounds; InflateRect(R, -cxPivotGridAutoScrollAreaWidth, -cxPivotGridAutoScrollAreaWidth); APos := PivotGrid.ScreenToClient(GetMouseCursorPos); DX := 0; DY := 0; if APos.X < R.Left then DX := -1 else if APos.X > R.Right then DX := 1; if APos.Y < R.Top then DY := -1 else if APos.Y > R.Bottom then DY := 1; SetSelectionInc(DX, DY, [ssLeft], True); if (DX <> 0) or (DY <> 0) then ViewData.MakeSelectionVisible; end; procedure TcxPivotGridController.SetSelection( ACol, ARow: Integer; AShift: TShiftState); var R: TRect; begin ViewData.AdjustCellIndexes(ARow, ACol, (ssLeft in AShift) or (ssRight in AShift)); if PivotGrid.OptionsSelection.MultiSelect and ((ssCtrl in AShift) or (ssLeft in AShift) or (ssShift in AShift)) then with cxRect(Point(ACol, ARow), ViewData.AnchorCells.TopLeft) do R := Rect(Min(Left, Right), Min(Top, Bottom), Max(Left, Right), Max(Top, Bottom)) else R := cxRect(Point(ACol, ARow), Point(ACol, ARow)); ViewData.Selection.InnerSetFocusedCell(Point(ACol, ARow)); ViewData.ValidateSelection(R); ViewData.Selection.ChangeSelection(R, AShift); end; procedure TcxPivotGridController.SetSelectionInc(const DX, DY: Integer; AShift: TShiftState; AByTimer: Boolean = False); var AColumn, ARow: Integer; begin AColumn := FocusedCell.X + DX; ARow := FocusedCell.Y + DY; if ssCtrl in AShift then begin if DX > 0 then for AColumn := FocusedCell.X + DX to ViewData.ColumnCount - 1 do if Length(ViewData.GetCellAsText(FocusedCell.Y, AColumn)) > 0 then Break; if DX < 0 then for AColumn := FocusedCell.X + DX downto 0 do if Length(ViewData.GetCellAsText(FocusedCell.Y, AColumn)) > 0 then Break; if DY > 0 then for ARow := FocusedCell.Y + DY to ViewData.RowCount - 1 do if Length(ViewData.GetCellAsText(ARow, FocusedCell.X)) > 0 then Break; if DY < 0 then for ARow := FocusedCell.Y + DY downto 0 do if Length(ViewData.GetCellAsText(ARow, FocusedCell.X)) > 0 then Break; end; ViewData.AdjustCellIndexes(ARow, AColumn, (ssLeft in AShift) or (ssRight in AShift)); if not AByTimer and not (ssShift in AShift) then ViewData.AnchorCells := Rect(AColumn, ARow, AColumn, ARow); SetSelection(AColumn, ARow, AShift + [ssLeft] - [ssCtrl]); end; function TcxPivotGridController.StartDragAndDrop(const P: TPoint): Boolean; var AField: IcxPivotGridField; begin HitTest.HitPoint := P; Result := (HitTest.HitAtField or HitTest.HitAtDataField) and Supports(HitTest.Field, IcxPivotGridField, AField) and AField.CanDrag; Result := Result or HitTest.HitAtHorzSizingEdge; Result := Result and not (HitTest.HitAtButton or HitTest.HitAtFilter); end; procedure TcxPivotGridController.CalculateIgnoreSelection; begin with HitTest do FIgnoreSelection := FIgnoreSelection or HitAtButton or (HitAtHorzSizingEdge and (ResizeField <> nil) and ResizeField.CanResize); end; function TcxPivotGridController.GetFocused: Boolean; begin Result := PivotGrid.IsFocused; end; function TcxPivotGridController.GetFocusedCell: TPoint; begin Result := PivotGrid.ViewData.FocusedCell; end; function TcxPivotGridController.GetHitTest: TcxPivotGridHitTest; begin Result := PivotGrid.HitTest; end; function TcxPivotGridController.GetIsDesigning: Boolean; begin Result := PivotGrid.IsDesigning; end; function TcxPivotGridController.GetOptionsCustomize: TcxPivotGridOptionsCustomize; begin Result := PivotGrid.OptionsCustomize; end; function TcxPivotGridController.GetOptionsSelection: TcxPivotGridOptionsSelection; begin Result := PivotGrid.OptionsSelection; end; function TcxPivotGridController.GetOptionsView: TcxPivotGridOptionsView; begin Result := PivotGrid.OptionsView; end; function TcxPivotGridController.GetViewData: TcxPivotGridViewData; begin Result := PivotGrid.ViewData; end; function TcxPivotGridController.GetViewInfo: TcxPivotGridViewInfo; begin Result := PivotGrid.ViewInfo; end; initialization crcxPivotGridArrow := crArrow; crcxPivotGridHorzSize := crcxHorzSize; crcxPivotGridNoDrop := crcxNoDrop; crcxPivotGridRemove := crcxRemove; finalization FreeAndNil(FHierarchyImages); end.