7807 lines
207 KiB
ObjectPascal
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ rxdbgrid unit
Copyright (C) 2005-2017 Lagunov Aleksey alexs75@yandex.ru and Lazarus team
original conception from rx library for Delphi (c)
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,and
to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a
module which is not derived from or based on this library. If you modify
this library, you may extend this exception to your version of the library,
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
for more details.
You should have received a copy of the GNU Library General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}
{$I rx.inc}
unit rxdbgrid;
interface
uses
Classes, SysUtils, LResources, LCLType, LCLIntf, Forms, Controls, Buttons,
Graphics, Dialogs, Grids, rxdbutils, DBGrids, DB, PropertyStorage, rxlclutils,
LMessages, types, StdCtrls, Menus, rxspin, LCLVersion;
const
CBadQuickSearchSymbols = [VK_UNKNOWN..VK_HELP] + [VK_LWIN..VK_SLEEP] +
[VK_NUMLOCK..VK_SCROLL] + [VK_LSHIFT..VK_OEM_102] + [VK_PROCESSKEY] +
[VK_ATTN..VK_UNDEFINED];
CCancelQuickSearchKeys = [VK_ESCAPE, VK_CANCEL, VK_DELETE, VK_INSERT,
VK_DOWN, VK_UP, VK_NEXT, VK_PRIOR, VK_TAB, VK_RETURN, VK_HOME,
VK_END, VK_SPACE, VK_MULTIPLY];
type
//forward declarations
TRxDBGrid = class;
TRxColumn = class;
TRxDBGridAbstractTools = class;
TRxDbGridColumnsEnumerator = class;
TRxColumnFooterItemsEnumerator = class;
TRxQuickSearchNotifyEvent = procedure(Sender: TObject; Field: TField;
var AValue: string) of object;
TSortMarker = (smNone, smDown, smUp);
TGetBtnParamsEvent = procedure(Sender: TObject; Field: TField;
AFont: TFont; var Background: TColor; var SortMarker: TSortMarker;
IsDown: boolean) of object;
TGetCellPropsEvent = procedure(Sender: TObject; Field: TField;
AFont: TFont; var Background: TColor) of object;
TRxDBGridDataHintShowEvent = procedure(Sender: TObject; CursorPos: TPoint;
Cell: TGridCoord; Column: TRxColumn; var HintStr: string;
var Processed: boolean) of object;
TRxDBGridCalcRowHeight = procedure(Sender: TRxDBGrid; var ARowHegth:integer) of object;
TRxDBGridMergeCellsEvent = procedure (Sender: TObject; ACol : Integer;
var ALeft, ARight : Integer; var ADisplayColumn: TRxColumn) of object;
//Freeman35 added
TOnRxCalcFooterValues = procedure(Sender: TObject; Column: TRxColumn; var AValue : Variant) of object;
TOnRxColumnFooterDraw = procedure(Sender: TObject; ABrush: TBrush; AFont : TFont;
const Rect: TRect; Column: TRxColumn; var AText :String) of object;
TRxColumnOption = (coCustomizeVisible, coCustomizeWidth, coFixDecimalSeparator, coDisableDialogFind);
TRxColumnOptions = set of TRxColumnOption;
TRxColumnEditButtonStyle = (ebsDropDownRx, ebsEllipsisRx, ebsGlyphRx, ebsUpDownRx,
ebsPlusRx, ebsMinusRx);
TFooterValueType = (fvtNon, fvtSum, fvtAvg, fvtCount, fvtFieldValue,
fvtStaticText, fvtMax, fvtMin, fvtRecNo);
TOptionRx = (rdgAllowColumnsForm,
rdgAllowDialogFind,
rdgHighlightFocusCol, //TODO:
rdgHighlightFocusRow, //TODO:
rdgDblClickOptimizeColWidth,
rdgFooterRows,
rdgXORColSizing,
rdgFilter,
rdgMultiTitleLines,
rdgMrOkOnDblClik,
rdgAllowQuickSearch,
rdgAllowQuickFilter,
rdgAllowFilterForm,
rdgAllowSortForm,
rdgAllowToolMenu,
rdgCaseInsensitiveSort,
rdgWordWrap,
rdgDisableWordWrapTitles,
rdgColSpanning
);
TOptionsRx = set of TOptionRx;
TCreateLookup = TNotifyEvent;
TDisplayLookup = TNotifyEvent;
TRxDBGridCommand = (rxgcNone, rxgcShowFindDlg, rxgcShowColumnsDlg,
rxgcShowFilterDlg, rxgcShowSortDlg, rxgcShowQuickFilter,
rxgcHideQuickFilter, rxgcSelectAll, rxgcDeSelectAll, rxgcInvertSelection,
rxgcOptimizeColumnsWidth, rxgcCopyCellValue
);
TRxFilterOpCode = (fopEQ, fopNotEQ, fopStartFrom, fopEndTo, fopLike, fopNotLike);
{ TRxDBGridKeyStroke }
TRxDBGridKeyStroke = class(TCollectionItem)
private
FCommand: TRxDBGridCommand;
FEnabled: boolean;
FShortCut: TShortCut;
FKey: word; // Virtual keycode, i.e. VK_xxx
FShift: TShiftState;
procedure SetCommand(const AValue: TRxDBGridCommand);
procedure SetShortCut(const AValue: TShortCut);
protected
function GetDisplayName: string; override;
public
procedure Assign(Source: TPersistent); override;
published
property Command: TRxDBGridCommand read FCommand write SetCommand;
property ShortCut: TShortCut read FShortCut write SetShortCut;
property Enabled: boolean read FEnabled write FEnabled;
end;
{ TRxDBGridKeyStrokes }
TRxDBGridKeyStrokes = class(TOwnedCollection)
private
function GetItem(Index: integer): TRxDBGridKeyStroke;
procedure SetItem(Index: integer; const AValue: TRxDBGridKeyStroke);
protected
procedure Update(Item: TCollectionItem); override;
public
constructor Create(AOwner: TPersistent);
procedure Assign(Source: TPersistent); override;
function Add: TRxDBGridKeyStroke;
function AddE(ACommand: TRxDBGridCommand; AShortCut: TShortCut): TRxDBGridKeyStroke;
procedure ResetDefaults;
function FindRxCommand(AKey: word; AShift: TShiftState): TRxDBGridCommand;
function FindRxKeyStrokes(ACommand: TRxDBGridCommand): TRxDBGridKeyStroke;
public
property Items[Index: integer]: TRxDBGridKeyStroke read GetItem write SetItem; default;
end;
{ TRxDBGridSearchOptions }
TRxDBGridSearchOptions = class(TPersistent)
private
FFromStart: boolean;
FOwner:TRxDBGrid;
FQuickSearchOptions: TLocateOptions;
protected
procedure AssignTo(Dest: TPersistent); override;
public
constructor Create(AOwner: TRxDBGrid);
published
property QuickSearchOptions:TLocateOptions read FQuickSearchOptions write FQuickSearchOptions;
property FromStart:boolean read FFromStart write FFromStart;
end;
{ TRxDBGridCollumnConstraint }
TRxDBGridCollumnConstraints = class(TPersistent)
private
FMaxWidth: integer;
FMinWidth: integer;
FOwner: TPersistent;
procedure SetMaxWidth(AValue: integer);
procedure SetMinWidth(AValue: integer);
protected
procedure AssignTo(Dest: TPersistent); override;
public
constructor Create(AOwner: TPersistent);
published
property MinWidth:integer read FMinWidth write SetMinWidth default 0;
property MaxWidth:integer read FMaxWidth write SetMaxWidth default 0;
end;
{ TRxDBGridFooterOptions }
TRxDBGridFooterOptions = class(TPersistent)
private
FActive: boolean;
FColor: TColor;
FDrawFullLine: boolean;
FOwner: TRxDBGrid;
FRowCount: integer;
FStyle: TTitleStyle;
procedure SetActive(AValue: boolean);
procedure SetColor(AValue: TColor);
procedure SetDrawFullLine(AValue: boolean);
procedure SetRowCount(AValue: integer);
procedure SetStyle(AValue: TTitleStyle);
protected
procedure AssignTo(Dest: TPersistent); override;
public
constructor Create(Owner: TRxDBGrid);
destructor Destroy; override;
published
property Active: boolean read FActive write SetActive default false;
property Color: TColor read FColor write SetColor default clWindow;
property RowCount: integer read FRowCount write SetRowCount default 0;
property Style: TTitleStyle read FStyle write SetStyle default tsLazarus;
property DrawFullLine: boolean read FDrawFullLine write SetDrawFullLine;
end;
{ TRxDBGridColumnDefValues }
TRxDBGridColumnDefValues = class(TPersistent)
private
FBlobText: string;
FOwner: TRxDBGrid;
protected
procedure AssignTo(Dest: TPersistent); override;
public
constructor Create(AOwner: TRxDBGrid);
destructor Destroy; override;
published
property BlobText:string read FBlobText write FBlobText;
end;
{ TRxDBGridSortEngine }
TRxSortEngineOption = (seoCaseInsensitiveSort);
TRxSortEngineOptions = set of TRxSortEngineOption;
TRxDBGridSortEngine = class
protected
FGrid:TRxDBGrid;
public
procedure Sort(FieldName: string; ADataSet: TDataSet; Asc: boolean; SortOptions: TRxSortEngineOptions); virtual; abstract;
procedure SortList(ListField: string; ADataSet: TDataSet; Asc: array of boolean; SortOptions: TRxSortEngineOptions); virtual;
end;
TRxDBGridSortEngineClass = class of TRxDBGridSortEngine;
TMLCaptionItem = class
Caption: string;
Width: integer;
Height: integer;
Next: TMLCaptionItem;
Prior: TMLCaptionItem;
FInvalidDraw:integer;
Col: TGridColumn;
end;
{ TRxColumnTitle }
TRxColumnTitle = class(TColumnTitle)
private
FHint: string;
FOrientation: TTextOrientation;
FShowHint: boolean;
FCaptionLines: TFPList;
function GetCaptionLinesCount: integer;
procedure SetOrientation(const AValue: TTextOrientation);
procedure ClearCaptionML;
protected
procedure SetCaption(const AValue: TCaption); override;
public
constructor Create(TheColumn: TGridColumn); override;
destructor Destroy; override;
property CaptionLinesCount: integer read GetCaptionLinesCount;
function CaptionLine(ALine: integer): TMLCaptionItem;
published
property Orientation: TTextOrientation read FOrientation write SetOrientation;
property Hint: string read FHint write FHint;
property ShowHint: boolean read FShowHint write FShowHint default False;
end;
{ TRxColumnFooterItem }
TRxColumnFooterItem = class(TCollectionItem)
private
FColor: TColor;
FIsDefaultFont: boolean;
FLayout: TTextLayout;
FOwner: TRxColumn;
FAlignment: TAlignment;
FDisplayFormat: string;
FFieldName: string;
FField:TField;
FFont: TFont;
FValue: string;
FValueType: TFooterValueType;
FTestValue: double;
FCountRec:integer;
procedure FontChanged(Sender: TObject);
function GetFont: TFont;
function IsFontStored: Boolean;
procedure SetAlignment(AValue: TAlignment);
procedure SetColor(AValue: TColor);
procedure SetDisplayFormat(AValue: string);
procedure SetFieldName(AValue: string);
procedure SetFont(AValue: TFont);
procedure SetLayout(AValue: TTextLayout);
procedure SetValue(AValue: string);
procedure SetValueType(AValue: TFooterValueType);
function GetFieldValue: string;
function GetRecordsCount: string;
function GetRecNo: string;
function GetStatTotal: string;
procedure ResetTestValue;
procedure UpdateTestValue;
function DeleteTestValue: boolean;
function PostTestValue: boolean;
function ErrorTestValue: boolean;
protected
procedure UpdateTestValueFromVar(AValue:Variant);
property IsDefaultFont: boolean read FIsDefaultFont;
public
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
function DisplayText: string;
procedure FillDefaultFont;
property Owner: TRxColumn read FOwner;
property NumericValue: double read FTestValue;
property CountRec:integer read FCountRec;
published
property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
property Layout: TTextLayout read FLayout write SetLayout default tlCenter;
property DisplayFormat: string read FDisplayFormat write SetDisplayFormat;
property FieldName: string read FFieldName write SetFieldName;
property Value: string read FValue write SetValue;
property ValueType: TFooterValueType read FValueType write SetValueType default fvtNon;
property Font: TFont read GetFont write SetFont stored IsFontStored;
property Color : TColor read FColor write SetColor stored IsFontStored default clNone;
end;
{ TRxColumnFooterItems }
TRxColumnFooterItems = class(TOwnedCollection)
private
function GetItem(Index: integer): TRxColumnFooterItem;
procedure SetItem(Index: integer; const AValue: TRxColumnFooterItem);
protected
procedure Update(Item: TCollectionItem); override;
public
constructor Create(AOwner: TPersistent);
function GetEnumerator: TRxColumnFooterItemsEnumerator;
public
property Items[Index: integer]: TRxColumnFooterItem read GetItem write SetItem; default;
end;
{ TRxColumnFooterItemsEnumerator }
TRxColumnFooterItemsEnumerator = class
private
FList: TRxColumnFooterItems;
FPosition: Integer;
public
constructor Create(AList: TRxColumnFooterItems);
function GetCurrent: TRxColumnFooterItem;
function MoveNext: Boolean;
property Current: TRxColumnFooterItem read GetCurrent;
end;
{ TRxColumnFilter }
TRxFilterState = (rxfsAll, rxfsEmpty, rxfsNonEmpty, rxfsFilter{, rxfsTopXXXX});
TRxFilterStyle = (rxfstSimple, rxfstDialog, rxfstManualEdit, rxfstBoth);
TRxColumnFilter = class(TPersistent)
private
FIsFontStored:Boolean;
FIsEmptyFontStored:Boolean;
FAllValue: string;
FCurrentValues: TStringList;
FEnabled: boolean;
FManulEditValue: string;
FNotEmptyValue: string;
FOwner: TRxColumn;
FState: TRxFilterState;
FStyle: TRxFilterStyle;
FValueList: TStringList;
FEmptyValue: string;
FEmptyFont: TFont;
FFont: TFont;
FAlignment: TAlignment;
FDropDownRows: integer;
FColor: TColor;
function GetDisplayFilterValue: string;
function GetItemIndex: integer;
function IsEmptyFontStored: Boolean;
function IsFontStored: Boolean;
procedure FontChanged(Sender: TObject);
procedure SetColor(const AValue: TColor);
procedure SetEmptyFont(AValue: TFont);
procedure SetFont(const AValue: TFont);
procedure SetItemIndex(const AValue: integer);
public
constructor Create(Owner: TRxColumn); virtual;
destructor Destroy; override;
procedure ClearFilter;
property State:TRxFilterState read FState write FState;
property CurrentValues : TStringList read FCurrentValues;
property ManulEditValue : string read FManulEditValue write FManulEditValue;
property DisplayFilterValue:string read GetDisplayFilterValue;
published
property Font: TFont read FFont write SetFont stored IsFontStored;
property Alignment: TAlignment read FAlignment write FAlignment default
taLeftJustify;
property DropDownRows: integer read FDropDownRows write FDropDownRows;
property Color: TColor read FColor write SetColor default clWhite;
property ValueList: TStringList read FValueList;
property EmptyValue: string read FEmptyValue write FEmptyValue;
property NotEmptyValue: string read FNotEmptyValue write FNotEmptyValue;
property AllValue: string read FAllValue write FAllValue;
property EmptyFont: TFont read FEmptyFont write SetEmptyFont stored IsEmptyFontStored;
property ItemIndex: integer read GetItemIndex write SetItemIndex;
property Enabled:boolean read FEnabled write FEnabled default true;
property Style : TRxFilterStyle read FStyle write FStyle default rxfstSimple;
end;
{ TRxColumnEditButton }
TRxColumnEditButton = class(TCollectionItem)
private
FEnabled: Boolean;
FShortCut: TShortCut;
FStyle: TRxColumnEditButtonStyle;
FButton:TSpeedButton;
FVisible: Boolean;
//
FSpinBtn:TRxSpinButton;
function GetGlyph: TBitmap;
function GetHint: String;
function GetNumGlyphs: Integer;
function GetOnButtonClick: TNotifyEvent;
function GetWidth: Integer;
procedure SetGlyph(AValue: TBitmap);
procedure SetHint(AValue: String);
procedure SetNumGlyphs(AValue: Integer);
procedure SetOnButtonClick(AValue: TNotifyEvent);
procedure SetStyle(AValue: TRxColumnEditButtonStyle);
procedure SetVisible(AValue: Boolean);
procedure SetWidth(AValue: Integer);
procedure DoBottomClick(Sender: TObject);
procedure DoTopClick(Sender: TObject);
protected
function GetDisplayName: string; override;
public
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
published
property Enabled: Boolean read FEnabled write FEnabled default true;
property Glyph: TBitmap read GetGlyph write SetGlyph;
property Hint: String read GetHint write SetHint;
property NumGlyphs: Integer read GetNumGlyphs write SetNumGlyphs default 1;
property ShortCut: TShortCut read FShortCut write FShortCut default scNone;
property Style: TRxColumnEditButtonStyle read FStyle write SetStyle default ebsDropDownRx;
property Visible: Boolean read FVisible write SetVisible default true;
property Width: Integer read GetWidth write SetWidth default 15;
property OnClick: TNotifyEvent read GetOnButtonClick write SetOnButtonClick;
end;
TRxColumnEditButtons = class(TCollection)
private
FOwner: TPersistent;
function GetItem(Index: integer): TRxColumnEditButton;
procedure SetItem(Index: integer; AValue: TRxColumnEditButton);
protected
procedure Update(Item: TCollectionItem); override;
public
constructor Create(AOwner: TPersistent);
function Add: TRxColumnEditButton;
public
property Items[Index: integer]: TRxColumnEditButton read GetItem write SetItem; default;
end;
TColumnGroupItemValue = class
FieldName:string;
GroupValue:Double;
end;
{ TColumnGroupItem }
TColumnGroupItem = class
private
FValues:TFPList;
RecBookMark:TBookMark;
FieldValue:string;
RecordCount:integer;
RecordNo:integer;
function GetItems(FieldName: string): TColumnGroupItemValue;
procedure ClearValues;
function AddItem(AFieldName:string):TColumnGroupItemValue;
public
constructor Create;
destructor Destroy; override;
property Items[FieldName:string]:TColumnGroupItemValue read GetItems;
end;
{ TColumnGroupItems }
TColumnGroupItems = class
private
FColor: TColor;
//for calc
FGroupField:TField;
FCurItem:TColumnGroupItem;
FCurrentValue:String;
//params
FActive: boolean;
FGroupFieldName: string;
FList:TFPList;
FRxDBGrid:TRxDBGrid;
procedure SetActive(AValue: boolean);
procedure SetColor(AValue: TColor);
protected
function AddGroupItem:TColumnGroupItem;
procedure InitGroup;
procedure DoneGroup;
public
constructor Create(ARxDBGrid:TRxDBGrid);
destructor Destroy; override;
procedure Clear;
procedure UpdateValues;
function FindGroupItem(ARecBookMark: TBookMark): TColumnGroupItem;
property GroupFieldName:string read FGroupFieldName write FGroupFieldName;
published
property Active:boolean read FActive write SetActive;
property Color:TColor read FColor write SetColor;
end;
{ TRxColumnGroupParam }
TRxColumnGroupParam = class
private
FAlignment: TAlignment;
FColor: TColor;
FDisplayFormat: string;
FLayout: TTextLayout;
FStaticText: string;
FValueType: TFooterValueType;
FColumn:TRxColumn;
FIsDefaultFont: boolean;
FFont: TFont;
procedure FontChanged(Sender: TObject);
function GetDisplayText: string;
function GetFont: TFont;
function IsFontStored: Boolean;
procedure SetAlignment(AValue: TAlignment);
procedure SetColor(AValue: TColor);
procedure SetDisplayFormat(AValue: string);
procedure SetFont(AValue: TFont);
procedure SetLayout(AValue: TTextLayout);
procedure SetStaticText(AValue: string);
protected
function GetGroupItems:TColumnGroupItem;
function GetGroupItem:TColumnGroupItemValue;
function GetRecordsCount: string;
function GetGroupTotal: string;
function GetGroupValue: string;
function GetRecNo: string;
public
constructor Create(AColumn:TRxColumn);
destructor Destroy; override;
procedure FillDefaultFont;
procedure UpdateValues;
property DisplayText:string read GetDisplayText;
published
property ValueType:TFooterValueType read FValueType write FValueType default fvtNon;
property Alignment:TAlignment read FAlignment write SetAlignment default taLeftJustify;
property Layout: TTextLayout read FLayout write SetLayout default tlCenter;
property DisplayFormat: string read FDisplayFormat write SetDisplayFormat;
property StaticText: string read FStaticText write SetStaticText;
property Font: TFont read GetFont write SetFont stored IsFontStored;
property Color : TColor read FColor write SetColor stored IsFontStored default clNone;
end;
{ TRxColumn }
TRxColumn = class(TColumn)
private
FDirectInput: boolean;
FEditButtons: TRxColumnEditButtons;
FFooter: TRxColumnFooterItem;
FConstraints:TRxDBGridCollumnConstraints;
FFilter: TRxColumnFilter;
FGroupParam: TRxColumnGroupParam;
FImageList: TImageList;
FKeyList: TStrings;
FNotInKeyListIndex: integer;
FOnDrawColumnCell: TDrawColumnCellEvent;
FOptions: TRxColumnOptions;
FSortFields: string;
FSortOrder: TSortMarker;
FSortPosition: integer;
FWordWrap: boolean;
FFooters: TRxColumnFooterItems;
function GetConstraints: TRxDBGridCollumnConstraints;
function GetFooter: TRxColumnFooterItem;
function GetFooters: TRxColumnFooterItems;
function GetKeyList: TStrings;
function GetSortFields:string;
procedure SetConstraints(AValue: TRxDBGridCollumnConstraints);
procedure SetEditButtons(AValue: TRxColumnEditButtons);
procedure SetFilter(const AValue: TRxColumnFilter);
procedure SetFooter(const AValue: TRxColumnFooterItem);
procedure SetFooters(AValue: TRxColumnFooterItems);
procedure SetImageList(const AValue: TImageList);
procedure SetKeyList(const AValue: TStrings);
procedure SetNotInKeyListIndex(const AValue: integer);
procedure SetWordWrap(AValue: boolean);
protected
function CreateTitle: TGridColumnTitle; override;
procedure ColumnChanged; override;
public
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
procedure OptimizeWidth;
property SortOrder: TSortMarker read FSortOrder write FSortOrder;
property SortPosition: integer read FSortPosition;
property GroupParam:TRxColumnGroupParam read FGroupParam;
published
property Constraints:TRxDBGridCollumnConstraints read GetConstraints write SetConstraints;
property DirectInput : boolean read FDirectInput write FDirectInput default true;
property EditButtons:TRxColumnEditButtons read FEditButtons write SetEditButtons;
property Filter: TRxColumnFilter read FFilter write SetFilter;
property Footer: TRxColumnFooterItem read GetFooter write SetFooter;
property Footers: TRxColumnFooterItems read GetFooters write SetFooters;
property ImageList: TImageList read FImageList write SetImageList;
property KeyList: TStrings read GetKeyList write SetKeyList;
property NotInKeyListIndex: integer read FNotInKeyListIndex write SetNotInKeyListIndex default -1;
property Options:TRxColumnOptions read FOptions write FOptions default [coCustomizeVisible, coCustomizeWidth];
property SortFields: string read FSortFields write FSortFields;
property WordWrap:boolean read FWordWrap write SetWordWrap default false;
property OnDrawColumnCell: TDrawColumnCellEvent read FOnDrawColumnCell write FOnDrawColumnCell;
end;
{ TRxDbGridColumns }
TRxDbGridColumns = class(TDbGridColumns)
private
function GetColumn(Index: Integer): TRxColumn;
procedure SetColumn(Index: Integer; AValue: TRxColumn);
protected
procedure Notify(Item: TCollectionItem;Action: TCollectionNotification); override;
public
function Add: TRxColumn;
function GetEnumerator: TRxDbGridColumnsEnumerator;
property Items[Index: Integer]: TRxColumn read GetColumn write SetColumn; default;
end;
{ TRxDbGridColumnsEnumerator }
TRxDbGridColumnsEnumerator = class
private
FList: TRxDbGridColumns;
FPosition: Integer;
public
constructor Create(AList: TRxDbGridColumns);
function GetCurrent: TRxColumn;
function MoveNext: Boolean;
property Current: TRxColumn read GetCurrent;
end;
{ TRxDbGridColumnsSortList }
TRxDbGridColumnsSortList = class(TFPList)
private
function GetCollumn(Index: Integer): TRxColumn;
public
property Collumn[Index: Integer]: TRxColumn read GetCollumn; default;
end;
{ TFilterListCellEditor }
TFilterListCellEditor = class(TComboBox)
private
FGrid: TCustomGrid;
FCol: integer;
FMouseFlag: boolean;
protected
procedure WndProc(var TheMessage: TLMessage); override;
procedure KeyDown(var Key: word; Shift: TShiftState); override;
public
procedure Show(Grid: TCustomGrid; Col: integer);
property Grid: TCustomGrid read FGrid;
property Col: integer read FCol;
property MouseFlag: boolean read FMouseFlag write FMouseFlag;
end;
{ TFilterColDlgButton }
TFilterColDlgButton = class(TSpeedButton)
private
FGrid: TRxDBGrid;
FCol: integer;
public
procedure Show(AGrid: TRxDBGrid; Col: integer);
property Col: integer read FCol;
end;
{ TFilterSimpleEdit }
TFilterSimpleEdit = class(TEdit)
private
FGrid: TCustomGrid;
FCol: integer;
FMouseFlag: boolean;
protected
procedure WndProc(var TheMessage: TLMessage); override;
procedure KeyDown(var Key: word; Shift: TShiftState); override;
public
procedure Show(Grid: TCustomGrid; Col: integer);
property Grid: TCustomGrid read FGrid;
property Col: integer read FCol;
property MouseFlag: boolean read FMouseFlag write FMouseFlag;
end;
{ TRxDBGrid }
TRxDBGrid = class(TCustomDBGrid)
private
FColumnDefValues: TRxDBGridColumnDefValues;
FIsSelectedDefaultFont:boolean;
FFooterOptions: TRxDBGridFooterOptions;
FOnCalcRowHeight: TRxDBGridCalcRowHeight;
FSearchOptions: TRxDBGridSearchOptions;
FSelectedFont: TFont;
FSortColumns: TRxDbGridColumnsSortList;
FSortingNow:Boolean;
FInProcessCalc: integer;
FOnMergeCells: TRxDBGridMergeCellsEvent;
FMergeLock: Integer;
//
FKeyStrokes: TRxDBGridKeyStrokes;
FOnGetCellProps: TGetCellPropsEvent;
FOptionsRx: TOptionsRx;
FOnGetBtnParams: TGetBtnParamsEvent;
FOnFiltred: TNotifyEvent;
FOnRxCalcFooterValues :TOnRxCalcFooterValues;
FOnRxColumnFooterDraw :TOnRxColumnFooterDraw;
//auto sort support
FAutoSort : boolean;
FSortEngine : TRxDBGridSortEngine;
FPressedCol : TRxColumn;
//
FPressed: boolean;
FSwapButtons: boolean;
FTracking: boolean;
F_Clicked: boolean;
F_PopupMenu: TPopupMenu;
F_MenuBMP: TBitmap;
F_EventOnFilterRec: TFilterRecordEvent;
F_EventOnBeforeDelete: TDataSetNotifyEvent;
F_EventOnBeforePost: TDataSetNotifyEvent;
F_EventOnDeleteError: TDataSetErrorEvent;
F_EventOnPostError: TDataSetErrorEvent;
F_LastFilter: TStringList;
F_CreateLookup: TCreateLookup;
F_DisplayLookup: TDisplayLookup;
//storage
//Column resize
FColumnResizing: boolean;
FFilterListEditor: TFilterListCellEditor;
FFilterColDlgButton: TFilterColDlgButton;
FFilterSimpleEdit:TFilterSimpleEdit;
// FOldPosition: Integer;
FVersion: integer;
FPropertyStorageLink: TPropertyStorageLink;
FAfterQuickSearch: TRxQuickSearchNotifyEvent;
FBeforeQuickSearch: TRxQuickSearchNotifyEvent;
FQuickUTF8Search: string;
FOldDataSetState:TDataSetState;
FToolsList:TFPList;
FOnSortChanged: TNotifyEvent;
FOnDataHintShow:TRxDBGridDataHintShowEvent;
FSaveOnDataSetScrolled: TDataSetScrolledEvent;
//Group data suppert
FGroupItems:TColumnGroupItems;
procedure DoCreateJMenu;
function GetColumns: TRxDbGridColumns;
function GetFooterColor: TColor;
function GetFooterRowCount: integer;
function GetPropertyStorage: TCustomPropertyStorage;
function GetSortField: string;
function GetSortOrder: TSortMarker;
function GetTitleButtons: boolean;
function IsColumnsStored: boolean;
procedure SelectedFontChanged(Sender: TObject);
function IsSelectedFontStored: Boolean;
procedure SetAutoSort(const AValue: boolean);
procedure SetColumnDefValues(AValue: TRxDBGridColumnDefValues);
procedure SetColumns(const AValue: TRxDbGridColumns);
procedure SetFooterColor(const AValue: TColor);
procedure SetFooterOptions(AValue: TRxDBGridFooterOptions);
procedure SetFooterRowCount(const AValue: integer);
procedure SetKeyStrokes(const AValue: TRxDBGridKeyStrokes);
procedure SetOptionsRx(const AValue: TOptionsRx);
procedure SetPropertyStorage(const AValue: TCustomPropertyStorage);
procedure SetSearchOptions(AValue: TRxDBGridSearchOptions);
procedure SetSelectedFont(AValue: TFont);
procedure SetTitleButtons(const AValue: boolean);
procedure TrackButton(X, Y: integer);
function GetDrawFullLine: boolean;
procedure SetDrawFullLine(Value: boolean);
procedure StopTracking;
procedure CalcTitle;
procedure ClearMLCaptionPointers;
procedure FillDefaultFonts;
function getFilterRect(bRect: TRect): TRect;
function getTitleRect(bRect: TRect): TRect;
procedure OutCaptionCellText(aCol, aRow: integer; const aRect: TRect;
aState: TGridDrawState; const ACaption: string);
procedure OutCaptionCellText90(aCol, aRow: integer; const aRect: TRect;
aState: TGridDrawState; const ACaption: string;
const TextOrient: TTextOrientation);
procedure OutCaptionSortMarker(const aRect: TRect; ASortMarker: TSortMarker; ASortPosition:integer);
procedure OutCaptionMLCellText(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState; MLI: TMLCaptionItem);
procedure UpdateJMenuStates;
procedure UpdateJMenuKeys;
function SortEngineOptions: TRxSortEngineOptions;
procedure GetScrollbarParams(out aRange, aPage, aPos: Integer);
procedure RestoreEditor;
//storage
procedure OnIniSave(Sender: TObject);
procedure OnIniLoad(Sender: TObject);
procedure CleanDSEvent;
function UpdateRowsHeight:integer;
procedure ResetRowHeght;
procedure DoClearInvalidTitle;
procedure DoDrawInvalidTitle;
procedure DoSetColEdtBtn;
procedure AddTools(ATools:TRxDBGridAbstractTools);
procedure RemoveTools(ATools:TRxDBGridAbstractTools);
procedure UpdateToolsState(ATools:TRxDBGridAbstractTools);
procedure OnDataSetScrolled(aDataSet:TDataSet; Distance: Integer);
procedure FillFilterData;
protected
FRxDbGridLookupComboEditor: TCustomControl;
FRxDbGridDateEditor: TWinControl;
FGroupItemDrawCur:TColumnGroupItem;
procedure CollumnSortListUpdate;
procedure CollumnSortListClear;
procedure CollumnSortListApply;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
function DatalinkActive: boolean;
procedure AdjustEditorBounds(NewCol,NewRow:Integer); override;
procedure LinkActive(Value: Boolean); override;
function GetFieldDisplayText(AField:TField; ACollumn:TRxColumn):string;
procedure DefaultDrawCellA(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState);
procedure DefaultDrawTitle(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState);
procedure DefaultDrawFilter(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState);
procedure DefaultDrawCellData(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState);
procedure DrawCell(aCol, aRow: integer; aRect: TRect; aState: TGridDrawState);
override;
procedure SetDBHandlers(Value: boolean);virtual;
procedure DrawRow(ARow: Integer); override;
procedure DrawFocusRect(aCol,aRow:Integer; ARect:TRect); override;
procedure DrawFooterRows; virtual;
procedure DrawCellBitmap(RxColumn: TRxColumn; aRect: TRect;
aState: TGridDrawState; AImageIndex: integer); virtual;
procedure DoTitleClick(ACol: longint; ACollumn: TRxColumn; Shift: TShiftState); virtual;
procedure MouseMove(Shift: TShiftState; X, Y: integer); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override;
procedure KeyDown(var Key: word; Shift: TShiftState); override;
procedure KeyPress(var Key: char); override;
procedure UTF8KeyPress(var UTF8Key: TUTF8Char); override;
function CreateColumns: TGridColumns; override;
procedure SetEditText(ACol, ARow: longint; const Value: string); override;
procedure ColRowMoved(IsColumn: boolean; FromIndex, ToIndex: integer); override;
procedure Paint; override;
procedure MoveSelection; override;
function GetBufferCount: integer; override;
procedure CMHintShow(var Message: TLMessage); message CM_HINTSHOW;
procedure FFilterListEditorOnChange(Sender: TObject);
procedure FFilterListEditorOnCloseUp(Sender: TObject);
procedure FFilterColDlgButtonOnClick(Sender: TObject);
procedure FFilterSimpleEditOnChange(Sender: TObject);
procedure InternalOptimizeColumnsWidth(AColList: TList);
procedure VisualChange; override;
procedure EditorWidthChanged(aCol,aWidth: Integer); override;
procedure SetQuickUTF8Search(AValue: string);
procedure BeforeDel(DataSet: TDataSet);
procedure BeforePo(DataSet: TDataSet);
procedure ErrorDel(DataSet: TDataSet; E: EDatabaseError; var DataAction: TDataAction);
procedure ErrorPo(DataSet: TDataSet; E: EDatabaseError; var DataAction: TDataAction);
procedure OnFind(Sender: TObject);
procedure OnFilterBy(Sender: TObject);
procedure OnFilter(Sender: TObject);
procedure OnFilterClose(Sender: TObject);
procedure OnSortBy(Sender: TObject);
procedure OnChooseVisibleFields(Sender: TObject);
procedure OnSelectAllRows(Sender: TObject);
procedure OnCopyCellValue(Sender: TObject);
procedure OnOptimizeColWidth(Sender: TObject);
procedure Loaded; override;
procedure UpdateFooterRowOnUpdateActive;
procedure DoEditorHide; override;
procedure DoEditorShow; override;
procedure CheckNewCachedSizes(var AGCache:TGridDataCache); override;
function GetEditMask(aCol, aRow: Longint): string; override;
function GetEditText(aCol, aRow: Longint): string; override;
function GetDefaultEditor(Column: Integer): TWinControl; override;
procedure PrepareCanvas(aCol, aRow: Integer; AState: TGridDrawState); override;
{$IFDEF DEVELOPER_RX}
procedure InternalAdjustRowCount(var RecCount:integer); override;
{$ENDIF}
property Editor;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure EraseBackground(DC: HDC); override;
procedure FilterRec(DataSet: TDataSet; var Accept: boolean);
function EditorByStyle(Style: TColumnButtonStyle): TWinControl; override;
procedure LayoutChanged; override;
procedure SetFocus; override;
procedure ShowFindDialog;
procedure ShowColumnsDialog;
procedure ShowSortDialog;
procedure ShowFilterDialog;
function ColumnByFieldName(AFieldName: string): TRxColumn;
function ColumnByCaption(ACaption: string): TRxColumn;
procedure CalcStatTotals;
procedure OptimizeColumnsWidth(AColList: string);
procedure OptimizeColumnsWidthAll;
procedure UpdateTitleHight;
procedure GetOnCreateLookup;
procedure GetOnDisplayLookup;
procedure SelectAllRows;
procedure DeSelectAllRows;
procedure InvertSelection;
procedure CopyCellValue;
function CreateToolMenuItem(ShortCut: char; const ACaption: string; MenuAction: TNotifyEvent):TMenuItem;
procedure RemoveToolMenuItem(MenuAction: TNotifyEvent);
procedure CalcCellExtent(ACol, ARow: Integer; var ARect: TRect);
function IsMerged(ACol : Integer): Boolean; overload;
function IsMerged(ACol : Integer; out ALeft, ARight: Integer; out AColumn: TRxColumn): Boolean; overload;
procedure SetSort(AFields: array of String; ASortMarkers: array of TSortMarker; PreformSort: Boolean = False);
property Canvas;
property DefaultTextStyle;
property EditorBorderStyle;
property EditorMode;
property ExtendedColSizing;
property FastEditing;
property FocusRectVisible;
property SelectedRows;
property QuickUTF8Search: string read FQuickUTF8Search write SetQuickUTF8Search;
property SortField:string read GetSortField;
property SortOrder:TSortMarker read GetSortOrder;
property SortColumns:TRxDbGridColumnsSortList read FSortColumns;
property GroupItems:TColumnGroupItems read FGroupItems;
published
property AfterQuickSearch: TRxQuickSearchNotifyEvent read FAfterQuickSearch write FAfterQuickSearch;
property ColumnDefValues:TRxDBGridColumnDefValues read FColumnDefValues write SetColumnDefValues;
property BeforeQuickSearch: TRxQuickSearchNotifyEvent read FBeforeQuickSearch write FBeforeQuickSearch;
property OnGetBtnParams: TGetBtnParamsEvent read FOnGetBtnParams write FOnGetBtnParams;
property TitleButtons: boolean read GetTitleButtons write SetTitleButtons;
property AutoSort: boolean read FAutoSort write SetAutoSort;
property OnGetCellProps: TGetCellPropsEvent read FOnGetCellProps write FOnGetCellProps;
property Columns: TRxDbGridColumns read GetColumns write SetColumns stored IsColumnsStored;
property KeyStrokes: TRxDBGridKeyStrokes read FKeyStrokes write SetKeyStrokes;
property FooterOptions:TRxDBGridFooterOptions read FFooterOptions write SetFooterOptions;
property SearchOptions:TRxDBGridSearchOptions read FSearchOptions write SetSearchOptions;
property OnCalcRowHeight:TRxDBGridCalcRowHeight read FOnCalcRowHeight write FOnCalcRowHeight;
property SelectedFont:TFont read FSelectedFont write SetSelectedFont stored IsSelectedFontStored;
//storage
property PropertyStorage: TCustomPropertyStorage read GetPropertyStorage write SetPropertyStorage;
property Version: integer read FVersion write FVersion default 0;
property OptionsRx: TOptionsRx read FOptionsRx write SetOptionsRx;
property FooterColor: TColor read GetFooterColor write SetFooterColor default clWindow; deprecated;
property FooterRowCount: integer read GetFooterRowCount write SetFooterRowCount default 0; deprecated;
property OnFiltred: TNotifyEvent read FOnFiltred write FOnFiltred;
property OnSortChanged: TNotifyEvent read FOnSortChanged write FOnSortChanged;
property OnDataHintShow: TRxDBGridDataHintShowEvent read FOnDataHintShow write FOnDataHintShow;
//from DBGrid
property Align;
property AlternateColor;
property Anchors;
property AutoAdvance default aaRightDown;
property AutoFillColumns;
property AutoEdit;
property BiDiMode;
property BorderSpacing;
property BorderStyle;
property Color;
property CellHintPriority;
property BorderColor;
property DrawFullLine: boolean read GetDrawFullLine write SetDrawFullLine; deprecated;
property FocusColor;
property FixedHotColor;
property SelectedColor;
property GridLineColor;
property GridLineStyle;
property Constraints;
property DataSource;
property DefaultDrawing;
property DefaultRowHeight;
property DefaultColWidth;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property FixedColor;
property FixedCols;
property Flat;
property Font;
property HeaderHotZones;
property HeaderPushZones;
//property ImeMode;
//property ImeName;
property Options;
property OptionsExtra;
property ParentBiDiMode;
property ParentColor default false;
//property ParentCtl3D;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ReadOnly;
property Scrollbars default ssBoth;
property ShowHint;
property TabOrder;
property TabStop;
property TabAdvance;
property TitleFont;
property TitleImageList;
property TitleStyle;
property UseXORFeatures;
property Visible;
property OnCellClick;
property OnColEnter;
property OnColExit;
property OnColumnMoved;
property OnColumnSized;
property OnContextPopup;
property OnDragDrop;
property OnDragOver;
property OnDrawColumnCell;
property OnDblClick;
property OnEditButtonClick;
property OnEditingDone;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnFieldEditMask;
property OnGetCellHint;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnPrepareCanvas;
property OnSelectEditor;
property OnStartDock;
property OnStartDrag;
property OnTitleClick;
property OnRxCalcFooterValues: TOnRxCalcFooterValues read FOnRxCalcFooterValues write FOnRxCalcFooterValues;
property OnRxColumnFooterDraw: TOnRxColumnFooterDraw read FOnRxColumnFooterDraw write FOnRxColumnFooterDraw;
property OnUserCheckboxBitmap;
property OnUserCheckboxState;
property OnUTF8KeyPress;
property OnCreateLookup: TCreateLookup read F_CreateLookup write F_CreateLookup;
property OnDisplayLookup: TDisplayLookup read F_DisplayLookup write F_DisplayLookup;
property OnMergeCells:TRxDBGridMergeCellsEvent read FOnMergeCells write FOnMergeCells;
end;
{ TRxDBGridAbstractTools }
TRxDBGridToolsEvent = (rxteMouseDown, rxteMouseUp, rxteMouseMove, rxteKeyDown, rxteKeyUp);
TRxDBGridToolsEvents = set of TRxDBGridToolsEvent;
TRxDBGridAbstractTools = class(TComponent)
private
FEnabled: boolean;
FOnAfterExecute: TNotifyEvent;
FOnBeforeExecute: TNotifyEvent;
FShowSetupForm: boolean;
procedure ExecTools(Sender:TObject);
procedure SetEnabled(AValue: boolean);
protected
FRxDBGrid: TRxDBGrid;
FCaption:string;
FToolsEvents:TRxDBGridToolsEvents;
procedure SetRxDBGrid(AValue: TRxDBGrid);
function DoExecTools:boolean; virtual;
function DoSetupTools:boolean; virtual;
function MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: integer):boolean; virtual;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Execute:boolean;
published
property RxDBGrid:TRxDBGrid read FRxDBGrid write SetRxDBGrid;
property Caption:string read FCaption write FCaption;
property ShowSetupForm:boolean read FShowSetupForm write FShowSetupForm default false;
property OnBeforeExecute:TNotifyEvent read FOnBeforeExecute write FOnBeforeExecute;
property OnAfterExecute:TNotifyEvent read FOnAfterExecute write FOnAfterExecute;
property Enabled:boolean read FEnabled write SetEnabled default true;
end;
procedure RegisterRxDBGridSortEngine(RxDBGridSortEngineClass: TRxDBGridSortEngineClass;
DataSetClassName: string);
implementation
uses Math, rxdateutil, rxdconst, rxstrutils, rxutils, strutils, rxdbgrid_findunit, Themes,
rxdbgrid_columsunit, RxDBGrid_PopUpFilterUnit, rxlookup, rxtooledit, LCLProc,
Clipbrd, rxfilterby, rxsortby, variants, LazUTF8, DateUtils;
{$R rxdbgrid.res}
const
EditorCommandStrs: array[rxgcNone .. High(TRxDBGridCommand)] of TIdentMapEntry =
(
(Value: Ord(rxgcNone); Name: 'rxcgNone'),
(Value: Ord(rxgcShowFindDlg); Name: 'rxgcShowFindDlg'),
(Value: Ord(rxgcShowColumnsDlg); Name: 'rxgcShowColumnsDlg'),
(Value: Ord(rxgcShowFilterDlg); Name: 'rxgcShowFilterDlg'),
(Value: Ord(rxgcShowSortDlg); Name: 'rxgcShowSortDlg'),
(Value: Ord(rxgcShowQuickFilter); Name: 'rxgcShowQuickFilter'),
(Value: Ord(rxgcHideQuickFilter); Name: 'rxgcHideQuickFilter'),
(Value: Ord(rxgcSelectAll); Name: 'rxgcSelectAll'),
(Value: Ord(rxgcDeSelectAll); Name: 'rxgcDeSelectAll'),
(Value: Ord(rxgcInvertSelection); Name: 'rxgcInvertSelection'),
(Value: Ord(rxgcOptimizeColumnsWidth); Name: 'rxgcOptimizeColumnsWidth'),
(Value: Ord(rxgcCopyCellValue); Name: 'rxgcCopyCellValue')
);
var
RxDBGridSortEngineList: TStringList;
FMarkerUp : TBitmap = nil;
FMarkerDown : TBitmap = nil;
FEllipsisRxBMP: TBitmap = nil;
FGlyphRxBMP: TBitmap = nil;
FUpDownRxBMP: TBitmap = nil;
FPlusRxBMP: TBitmap = nil;
FMinusRxBMP: TBitmap = nil;
procedure RegisterRxDBGridSortEngine(
RxDBGridSortEngineClass: TRxDBGridSortEngineClass; DataSetClassName: string);
var
Pos: integer;
RxDBGridSortEngine: TRxDBGridSortEngine;
begin
if not RxDBGridSortEngineList.Find(DataSetClassName, Pos) then
begin
RxDBGridSortEngine := RxDBGridSortEngineClass.Create;
RxDBGridSortEngineList.AddObject(DataSetClassName, RxDBGridSortEngine);
end;
end;
procedure GridInvalidateRow(Grid: TRxDBGrid; Row: longint);
var
I: longint;
begin
for I := 0 to Grid.ColCount - 1 do
Grid.InvalidateCell(I, Row);
end;
type
THackDataSet = class(TDataSet);
type
{ TRxDBGridLookupComboEditor }
TRxDBGridLookupComboEditor = class(TRxCustomDBLookupCombo)
private
FGrid: TRxDBGrid;
FCol, FRow: integer;
FLDS: TDataSource;
protected
procedure WndProc(var TheMessage: TLMessage); override;
procedure KeyDown(var Key: word; Shift: TShiftState); override;
procedure msg_SetGrid(var Msg: TGridMessage); message GM_SETGRID;
procedure msg_SetValue(var Msg: TGridMessage); message GM_SETVALUE;
procedure msg_GetValue(var Msg: TGridMessage); message GM_GETVALUE;
procedure OnInternalClosePopup(AResult:boolean);override;
procedure ShowList; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
{ TRxDBGridDateEditor }
TRxDBGridDateEditor = class(TCustomRxDateEdit)
private
FGrid: TRxDBGrid;
FCol, FRow: integer;
protected
procedure EditChange; override;
procedure KeyDown(var Key: word; Shift: TShiftState); override;
procedure WndProc(var TheMessage: TLMessage); override;
procedure msg_SetGrid(var Msg: TGridMessage); message GM_SETGRID;
procedure msg_SetValue(var Msg: TGridMessage); message GM_SETVALUE;
procedure msg_GetValue(var Msg: TGridMessage); message GM_GETVALUE;
procedure msg_SelectAll(var Msg: TGridMessage); message GM_SELECTALL;
public
constructor Create(Aowner : TComponent); override;
procedure EditingDone; override;
end;
{ TFilterSimpleEdit }
procedure TFilterSimpleEdit.WndProc(var TheMessage: TLMessage);
begin
if TheMessage.msg = LM_KILLFOCUS then
begin
Change;
Hide;
if HWND(TheMessage.WParam) = HWND(Handle) then
begin
// lost the focus but it returns to ourselves
// eat the message.
TheMessage.Result := 0;
exit;
end;
end;
inherited WndProc(TheMessage);
end;
procedure TFilterSimpleEdit.KeyDown(var Key: word; Shift: TShiftState);
begin
inherited KeyDown(Key, Shift);
case Key of
VK_RETURN:
begin
Change;
Hide;
end;
end;
end;
procedure TFilterSimpleEdit.Show(Grid: TCustomGrid; Col: integer);
begin
FGrid := Grid;
FCol := Col;
Visible := True;
SetFocus;
end;
{ TRxColumnGroupParam }
procedure TRxColumnGroupParam.FontChanged(Sender: TObject);
begin
FisDefaultFont := FFont.IsDefault;
FColumn.ColumnChanged;
end;
function TRxColumnGroupParam.GetDisplayText: string;
begin
case FValueType of
fvtCount : Result := GetRecordsCount;
fvtSum,
fvtAvg,
fvtMax,
fvtMin : Result := GetGroupTotal;
fvtRecNo : Result := GetRecNo;
fvtStaticText:Result := FStaticText;
fvtFieldValue:Result := GetGroupValue;
else
//fvtNon,
Result:='';
end;
end;
function TRxColumnGroupParam.GetFont: TFont;
begin
Result := FFont;
end;
function TRxColumnGroupParam.IsFontStored: Boolean;
begin
Result := not FisDefaultFont;
end;
procedure TRxColumnGroupParam.SetAlignment(AValue: TAlignment);
begin
if FAlignment=AValue then Exit;
FAlignment:=AValue;
end;
procedure TRxColumnGroupParam.SetColor(AValue: TColor);
begin
if FColor=AValue then Exit;
FColor:=AValue;
end;
procedure TRxColumnGroupParam.SetDisplayFormat(AValue: string);
begin
if FDisplayFormat=AValue then Exit;
FDisplayFormat:=AValue;
end;
procedure TRxColumnGroupParam.SetFont(AValue: TFont);
begin
if not FFont.IsEqual(AValue) then
FFont.Assign(AValue);
end;
procedure TRxColumnGroupParam.SetLayout(AValue: TTextLayout);
begin
if FLayout=AValue then Exit;
FLayout:=AValue;
end;
procedure TRxColumnGroupParam.SetStaticText(AValue: string);
begin
if FStaticText=AValue then Exit;
FStaticText:=AValue;
end;
function TRxColumnGroupParam.GetGroupItems: TColumnGroupItem;
begin
Result:=nil;
if TRxDBGrid(FColumn.Grid).DatalinkActive then
Result:=TRxDBGrid(FColumn.Grid).FGroupItemDrawCur;
end;
function TRxColumnGroupParam.GetGroupItem: TColumnGroupItemValue;
var
FCGDI: TColumnGroupItem;
begin
Result:=nil;
if TRxDBGrid(FColumn.Grid).DatalinkActive then
begin
FCGDI:=TRxDBGrid(FColumn.Grid).FGroupItemDrawCur;
if Assigned(FCGDI) then
Result:=FCGDI.GetItems(FColumn.FieldName);
end
end;
function TRxColumnGroupParam.GetRecordsCount: string;
var
V: TColumnGroupItem;
begin
V:=GetGroupItems;
if Assigned(V) then
begin
if DisplayFormat <> '' then
Result := Format(DisplayFormat, [V.RecordCount])
else
Result := IntToStr(V.RecordCount);
end
else
Result := '';
end;
function TRxColumnGroupParam.GetGroupTotal: string;
var
V: TColumnGroupItemValue;
F: TField;
begin
V:=GetGroupItem;
if Assigned(V) then
begin
F := TRxDBGrid(FColumn.Grid).DataSource.DataSet.FieldByName(FColumn.FieldName);
if Assigned(F) then
begin
if F.DataType in [ftSmallint, ftInteger, ftWord, ftFloat, ftCurrency,
ftDate, ftTime, ftDateTime, ftTimeStamp, ftLargeint, ftBCD] then
begin
if F.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
begin
if FValueType in [fvtSum, fvtAvg] then
Result := ''
else
if V.GroupValue = 0 then
Result := ''
else
if FDisplayFormat = '' then
Result := DateToStr(V.GroupValue)
else
Result := FormatDateTime(FDisplayFormat, V.GroupValue);
end
else
if F.DataType in [ftSmallint, ftInteger, ftWord, ftLargeint] then
begin
if FDisplayFormat = '' then
Result := IntToStr(Round(V.GroupValue))
else
Result := FormatFloat(FDisplayFormat, V.GroupValue);
end
else
begin
if FDisplayFormat <> '' then
Result := FormatFloat(FDisplayFormat, V.GroupValue)
else
if F.DataType = ftCurrency then
Result := FloatToStrF(V.GroupValue, ffCurrency, 12, 2)
else
Result := FloatToStr(V.GroupValue);
end;
end
else
Result := '';
end
else
Result := '';
end
else
Result := '';
end;
function TRxColumnGroupParam.GetGroupValue: string;
var
V: TColumnGroupItem;
begin
V:=GetGroupItems;
if Assigned(V) then
Result := V.FieldValue
else
Result := '';
end;
function TRxColumnGroupParam.GetRecNo: string;
var
V: TColumnGroupItem;
begin
V:=GetGroupItems;
if Assigned(V) then
begin
if DisplayFormat <> '' then
Result := Format(DisplayFormat, [V.RecordNo])
else
Result := IntToStr(V.RecordNo);
end
else
Result := '';
end;
constructor TRxColumnGroupParam.Create(AColumn: TRxColumn);
begin
inherited Create;
FColumn:=AColumn;
FValueType:=fvtNon;
FAlignment:=taLeftJustify;
FLayout := tlCenter;
FColor:=clNone;
FFont := TFont.Create;
FillDefaultFont;
FFont.OnChange := @FontChanged;
end;
destructor TRxColumnGroupParam.Destroy;
begin
FreeAndNil(FFont);
inherited Destroy;
end;
procedure TRxColumnGroupParam.FillDefaultFont;
var
AGrid: TCustomGrid;
begin
if not Assigned(FColumn) then exit;
AGrid := FColumn.Grid;
if (AGrid<>nil) then
begin
FFont.Assign(AGrid.Font);
FIsDefaultFont := True;
end;
end;
procedure TRxColumnGroupParam.UpdateValues;
var
F: TField;
V: TColumnGroupItemValue;
begin
if (ValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and (FColumn.FieldName <> '') then
begin
F := TRxDBGrid(FColumn.Grid).DataSource.DataSet.FindField(FColumn.FieldName);
V:=TRxDBGrid(FColumn.Grid).FGroupItems.FCurItem.Items[FColumn.FieldName];
if not Assigned(V) then
V:=TRxDBGrid(FColumn.Grid).FGroupItems.FCurItem.AddItem(FColumn.FieldName);
if Assigned(F) and Assigned(V) then
begin
if F.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
begin
case FValueType of
fvtMax: V.GroupValue := Max(V.GroupValue, F.AsDateTime);
fvtMin: V.GroupValue := Min(V.GroupValue, F.AsDateTime);
end;
end
else
begin
case FValueType of
fvtAvg,
fvtSum: V.GroupValue := V.GroupValue + F.AsFloat;
fvtMax: V.GroupValue := Max(V.GroupValue, F.AsFloat);
fvtMin: V.GroupValue := Min(V.GroupValue, F.AsFloat);
end;
end;
end;
end;
end;
{ TRxColumnFooterItemsEnumerator }
constructor TRxColumnFooterItemsEnumerator.Create(AList: TRxColumnFooterItems);
begin
FList := AList;
FPosition := -1;
end;
function TRxColumnFooterItemsEnumerator.GetCurrent: TRxColumnFooterItem;
begin
Result := FList[FPosition];
end;
function TRxColumnFooterItemsEnumerator.MoveNext: Boolean;
begin
Inc(FPosition);
Result := FPosition < FList.Count;
end;
{ TColumnGroupItems }
procedure TColumnGroupItems.SetActive(AValue: boolean);
begin
if FActive=AValue then Exit;
FActive:=AValue;
if FActive then
begin
FRxDBGrid.CalcStatTotals;
end
else
FRxDBGrid.UpdateRowsHeight;
FRxDBGrid.VisualChange;
end;
procedure TColumnGroupItems.SetColor(AValue: TColor);
begin
if FColor=AValue then Exit;
FColor:=AValue;
FRxDBGrid.Invalidate;
end;
constructor TColumnGroupItems.Create(ARxDBGrid: TRxDBGrid);
begin
inherited Create;
FActive:=false;
FList:=TFPList.Create;
FRxDBGrid:=ARxDBGrid;
end;
destructor TColumnGroupItems.Destroy;
begin
Clear;
FreeAndNil(FList);
inherited Destroy;
end;
function TColumnGroupItems.FindGroupItem(ARecBookMark: TBookMark
): TColumnGroupItem;
var
S, E, i: Integer;
begin
Result:=nil;
if FList.Count = 0 then exit;
S:=0;
E:=FList.Count - 1;
{
while (S<=E) do
begin
i:=(E+S) div 2;
if (TColumnGroupItem(FList[i]).RecordNo = ARecordNo) then
begin
Result:=TColumnGroupItem(FList[i]);
Exit;
end
else
if (TColumnGroupItem(FList[i]).RecordNo > ARecordNo) then E:=i-1
else S:=i+1;
end; }
for i:=0 to FList.Count-1 do
if FRxDBGrid.DataSource.DataSet.CompareBookmarks(TColumnGroupItem(FList[i]).RecBookMark, ARecBookMark) = 0 then
exit(TColumnGroupItem(FList[i]))
end;
procedure TColumnGroupItems.Clear;
var
i: Integer;
begin
for i:=0 to FList.Count-1 do
TColumnGroupItem(FList[i]).Free;
FList.Clear;
end;
procedure TColumnGroupItems.UpdateValues;
begin
if not Assigned(FGroupField) then Exit;
if (FCurrentValue <> FGroupField.DisplayText) or (not Assigned(FCurItem)) then
begin
DoneGroup;
FCurItem:=AddGroupItem;
FCurrentValue:=FGroupField.DisplayText;
FCurItem.RecordCount:=1;
FCurItem.RecordNo:=FRxDBGrid.DataSource.DataSet.RecNo;
FCurItem.RecBookMark:=FRxDBGrid.DataSource.DataSet.Bookmark;
FCurItem.FieldValue:=FCurrentValue;
end
else
begin
Inc(FCurItem.RecordCount);
FCurItem.RecordNo:=FRxDBGrid.DataSource.DataSet.RecNo;
FCurItem.RecBookMark:=FRxDBGrid.DataSource.DataSet.Bookmark;
end;
end;
function TColumnGroupItems.AddGroupItem: TColumnGroupItem;
begin
Result:=TColumnGroupItem.Create;
FList.Add(Result);
end;
procedure TColumnGroupItems.InitGroup;
begin
if (FRxDBGrid.DataSource.DataSet.RecordCount > 0) and (FGroupFieldName <> '') then
begin
FGroupField:=FRxDBGrid.DataSource.DataSet.FieldByName(FGroupFieldName);
FCurrentValue:=FGroupField.DisplayText;
end;
end;
procedure TColumnGroupItems.DoneGroup;
begin
{ TODO : Необходимо список закладок отсортировать }
if Assigned(FCurItem) then
begin
//FCurItem.RecordNo:=FRxDBGrid.DataSource.DataSet.RecNo;
//FCurItem.RecordNo:=PtrInt(FRxDBGrid.DataSource.DataSet.ActiveBuffer);
//FList.Sort(@DoListSortCompare);
//FCurItem.RecordNo:=FRxDBGrid.DataSource.DataSet.Bookmark;
end;
FCurItem:=nil;
end;
{ TColumnGroupItem }
function TColumnGroupItem.GetItems(FieldName: string): TColumnGroupItemValue;
var
i: Integer;
begin
Result:=nil;
for i:=0 to FValues.Count-1 do
if TColumnGroupItemValue(FValues[i]).FieldName = FieldName then
Exit(TColumnGroupItemValue(FValues[i]));
end;
procedure TColumnGroupItem.ClearValues;
var
i: Integer;
begin
for i:=0 to FValues.Count-1 do
TColumnGroupItemValue(FValues[i]).Free;
FValues.Clear;
end;
function TColumnGroupItem.AddItem(AFieldName: string): TColumnGroupItemValue;
begin
Result:=TColumnGroupItemValue.Create;
FValues.Add(Result);
Result.FieldName:=AFieldName;
end;
constructor TColumnGroupItem.Create;
begin
inherited Create;
FValues:=TFPList.Create;
end;
destructor TColumnGroupItem.Destroy;
begin
ClearValues;
FreeAndNil(FValues);
inherited Destroy;
end;
{ TRxDbGridColumnsEnumerator }
constructor TRxDbGridColumnsEnumerator.Create(AList: TRxDbGridColumns);
begin
FList := AList;
FPosition := -1;
end;
function TRxDbGridColumnsEnumerator.GetCurrent: TRxColumn;
begin
Result := FList[FPosition];
end;
function TRxDbGridColumnsEnumerator.MoveNext: Boolean;
begin
Inc(FPosition);
Result := FPosition < FList.Count;
end;
{ TFilterColDlgButton }
procedure TFilterColDlgButton.Show(AGrid: TRxDBGrid; Col: integer);
begin
FGrid := AGrid;
FCol := Col;
Visible := True;
end;
{ TRxDBGridSearchOptions }
procedure TRxDBGridSearchOptions.AssignTo(Dest: TPersistent);
begin
if Dest is TRxDBGridSearchOptions then
begin
TRxDBGridSearchOptions(Dest).FQuickSearchOptions:=FQuickSearchOptions;
TRxDBGridSearchOptions(Dest).FFromStart:=FFromStart;
end
else
inherited AssignTo(Dest);
end;
constructor TRxDBGridSearchOptions.Create(AOwner: TRxDBGrid);
begin
inherited Create;
FOwner:=AOwner;
FQuickSearchOptions:=[loPartialKey, loCaseInsensitive];
FFromStart:=false;
end;
{ TRxDBGridColumnDefValues }
procedure TRxDBGridColumnDefValues.AssignTo(Dest: TPersistent);
begin
if Dest is TRxDBGridColumnDefValues then
begin
TRxDBGridColumnDefValues(Dest).FBlobText:=FBlobText;
end
else
inherited AssignTo(Dest);
end;
constructor TRxDBGridColumnDefValues.Create(AOwner: TRxDBGrid);
begin
inherited Create;
FOwner:=AOwner;
FBlobText:=sBlobText;
end;
destructor TRxDBGridColumnDefValues.Destroy;
begin
inherited Destroy;
end;
{ TRxColumnFooterItem }
procedure TRxColumnFooterItem.FontChanged(Sender: TObject);
begin
FisDefaultFont := Font.IsDefault;
FOwner.ColumnChanged;
end;
function TRxColumnFooterItem.GetFont: TFont;
begin
Result := FFont;
end;
function TRxColumnFooterItem.IsFontStored: Boolean;
begin
Result := not FisDefaultFont;
end;
procedure TRxColumnFooterItem.SetAlignment(AValue: TAlignment);
begin
if FAlignment = AValue then exit;
FAlignment := AValue;
FOwner.ColumnChanged;
end;
procedure TRxColumnFooterItem.SetColor(AValue: TColor);
begin
if FColor=AValue then Exit;
FColor:=AValue;
FOwner.ColumnChanged;
end;
procedure TRxColumnFooterItem.SetDisplayFormat(AValue: string);
begin
if FDisplayFormat=AValue then Exit;
FDisplayFormat:=AValue;
FOwner.ColumnChanged;
end;
procedure TRxColumnFooterItem.SetFieldName(AValue: string);
begin
if FFieldName=AValue then Exit;
FFieldName:=AValue;
FOwner.ColumnChanged;
end;
procedure TRxColumnFooterItem.SetFont(AValue: TFont);
begin
if not FFont.IsEqual(AValue) then
FFont.Assign(AValue);
end;
procedure TRxColumnFooterItem.SetLayout(AValue: TTextLayout);
begin
if FLayout=AValue then Exit;
FLayout:=AValue;
FOwner.ColumnChanged;
end;
procedure TRxColumnFooterItem.SetValue(AValue: string);
begin
if FValue=AValue then Exit;
FValue:=AValue;
FOwner.ColumnChanged;
end;
procedure TRxColumnFooterItem.SetValueType(AValue: TFooterValueType);
begin
if FValueType=AValue then Exit;
FValueType:=AValue;
FOwner.ColumnChanged;
end;
function TRxColumnFooterItem.GetFieldValue: string;
begin
if (FFieldName <> '') and TRxDBGrid(FOwner.Grid).DatalinkActive then
Result := TRxDBGrid(FOwner.Grid).DataSource.DataSet.FieldByName(FFieldName).AsString
else
Result := '';
end;
function TRxColumnFooterItem.GetRecordsCount: string;
begin
if TRxDBGrid(FOwner.Grid).DatalinkActive then
begin
if DisplayFormat <> '' then
Result := Format(DisplayFormat, [FCountRec])
else
Result := IntToStr(FCountRec);
end
else
Result := '';
end;
function TRxColumnFooterItem.GetRecNo: string;
begin
if TRxDBGrid(FOwner.Grid).DatalinkActive then
begin
if DisplayFormat <> '' then
Result := Format(DisplayFormat, [TRxDBGrid(FOwner.Grid).DataSource.DataSet.RecNo])
else
Result := IntToStr(TRxDBGrid(FOwner.Grid).DataSource.DataSet.RecNo);
end
else
Result := '';
end;
function TRxColumnFooterItem.GetStatTotal: string;
var
F: TField;
begin
if (FFieldName <> '') and TRxDBGrid(FOwner.Grid).DatalinkActive and
(TRxDBGrid(FOwner.Grid).DataSource.DataSet.RecordCount <> 0) then
begin
F := TRxDBGrid(FOwner.Grid).DataSource.DataSet.FieldByName(FFieldName);
if Assigned(F) then
begin
if F.DataType in [ftSmallint, ftInteger, ftWord, ftFloat, ftCurrency,
ftDate, ftTime, ftDateTime, ftTimeStamp, ftLargeint, ftBCD] then
begin
if F.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
begin
if FValueType in [fvtSum, fvtAvg] then
Result := ''
else
if FTestValue = 0 then
Result := ''
else
if FDisplayFormat = '' then
Result := DateToStr(FTestValue)
else
Result := FormatDateTime(FDisplayFormat, FTestValue);
end
else
if F.DataType in [ftSmallint, ftInteger, ftWord, ftLargeint] then
begin
if FDisplayFormat = '' then
Result := IntToStr(Round(FTestValue))
else
Result := FormatFloat(FDisplayFormat, FTestValue);
end
else
begin
if FDisplayFormat <> '' then
Result := FormatFloat(FDisplayFormat, FTestValue)
else
if F.DataType = ftCurrency then
Result := FloatToStrF(FTestValue, ffCurrency, 12, 2)
else
Result := FloatToStr(FTestValue);
end;
end
else
Result := '';
end
else
Result := '';
end
else
Result := '';
end;
procedure TRxColumnFooterItem.ResetTestValue;
var
F: TField;
begin
FTestValue := 0;
FCountRec:=0;
if (ValueType in [fvtMin, fvtMax]) and (TRxDBGrid(
FOwner.Grid).DataSource.DataSet.RecordCount <> 0) and (FFieldName<>'') then
begin
F := TRxDBGrid(FOwner.Grid).DataSource.DataSet.FieldByName(FFieldName);
if (Assigned(F)) and not (F.IsNull) then
if F.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
FTestValue := F.AsDateTime
else
FTestValue := F.AsFloat;
end;
end;
procedure TRxColumnFooterItem.UpdateTestValue;
var
F: TField;
begin
if (ValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and (FFieldName<>'') then
begin
F := TRxDBGrid(FOwner.Grid).DataSource.DataSet.FindField(FFieldName);
if Assigned(F) then
begin
if F.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
begin
case FValueType of
fvtMax: FTestValue := Max(FTestValue, F.AsDateTime);
fvtMin: FTestValue := Min(FTestValue, F.AsDateTime);
end;
end
else
begin
case FValueType of
fvtSum: FTestValue := FTestValue + F.AsFloat;
// fvtAvg:
fvtMax: FTestValue := Max(FTestValue, F.AsFloat);
fvtMin: FTestValue := Min(FTestValue, F.AsFloat);
end;
end;
end;
end;
end;
function TRxColumnFooterItem.DeleteTestValue: boolean;
var
F: TField;
begin
Result := True;
if (ValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and (FFieldName<>'') then
begin
F := TRxDBGrid(FOwner.Grid).DataSource.DataSet.FieldByName(FFieldName);
if (Assigned(F)) and not (F.IsNull) then
if F.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
Result := not ((FValueType in [fvtMax, fvtMin]) and (FTestValue = F.AsDateTime))
else
if FValueType in [fvtMax, fvtMin] then
Result := (FTestValue <> F.AsFloat)
else
FTestValue := FTestValue - F.AsFloat;
end;
end;
function TRxColumnFooterItem.PostTestValue: boolean;
var
F: TField;
begin
Result := True;
if (ValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and (FFieldName<>'') then
begin
F := TRxDBGrid(FOwner.Grid).DataSource.DataSet.FieldByName(FFieldName);
if Assigned(F) then
if F.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
begin
if FValueType in [fvtMax, fvtMin] then
if F.DataSet.State = dsinsert then
begin
if not (F.IsNull) then
case FValueType of
fvtMax: FTestValue := Max(FTestValue, F.AsDateTime);
fvtMin: FTestValue := Min(FTestValue, F.AsDateTime);
end;
end
else
if (F.OldValue <> null) and (FTestValue = TDateTime(F.OldValue)) then
Result := False
else
if not F.IsNull then
case FValueType of
fvtMax: FTestValue := Max(FTestValue, F.AsDateTime);
fvtMin: FTestValue := Min(FTestValue, F.AsDateTime);
end;
end
else
if F.DataSet.State = dsinsert then
begin
if not F.IsNull then
case FValueType of
fvtSum: FTestValue := FTestValue + F.AsFloat;
fvtMax: FTestValue := Max(FTestValue, F.AsFloat);
fvtMin: FTestValue := Min(FTestValue, F.AsFloat);
end;
end
else
if (FValueType in [fvtMax, fvtMin]) and (F.OldValue <> null) and
(FTestValue = Float(F.OldValue)) then
Result := False
else
case FValueType of
fvtSum:
begin
if not F.IsNull then
begin
if F.OldValue <> null then
FTestValue := FTestValue - Float(F.OldValue);
FTestValue := FTestValue + F.AsFloat;
end;
end;
fvtMax: if not F.IsNull then
FTestValue := Max(FTestValue, F.AsFloat);
fvtMin: if not F.IsNull then
FTestValue := Min(FTestValue, F.AsFloat);
end;
end;
end;
function TRxColumnFooterItem.ErrorTestValue: boolean;
var
F: TField;
begin
Result := True;
if (ValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and (FFieldName<>'') then
begin
F := TRxDBGrid(FOwner.Grid).DataSource.DataSet.FieldByName(FFieldName);
if Assigned(F) then
begin
if F.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
begin
if (FValueType in [fvtMax, fvtMin]) and not (F.IsNull) then
begin
if not (F.IsNull) and (FTestValue = F.AsDateTime) then
Result := False
else
if (F.DataSet.RecordCount <> 0) and (F.OldValue <> null) then
begin
case FValueType of
fvtMax: FTestValue := Max(FTestValue, TDateTime(F.OldValue));
fvtMin: FTestValue := Min(FTestValue, TDateTime(F.OldValue));
end;
end;
end;
end
else
if (FValueType in [fvtMax, fvtMin]) and not (F.IsNull) and (FTestValue = F.AsFloat) then
Result := False
else
begin
case FValueType of
fvtSum:
if F.DataSet.RecordCount = 0 then
begin
{ if not F.IsNull then
FTestValue := FTestValue - F.AsFloat;}
{ TODO -oalexs : need rewrite this code - where difficult! }
end
else
begin
if F.OldValue <> null then
FTestValue := FTestValue + Float(F.OldValue);
if not F.IsNull then
FTestValue := FTestValue - F.AsFloat;
end;
fvtMax:
if (F.DataSet.RecordCount <> 0) and (F.OldValue <> null) then
FTestValue := Max(FTestValue, Float(F.OldValue));
fvtMin:
if (F.DataSet.RecordCount <> 0) and (F.OldValue <> null) then
FTestValue := Min(FTestValue, Float(F.OldValue));
end;
end;
end;
end;
end;
procedure TRxColumnFooterItem.UpdateTestValueFromVar(AValue: Variant);
begin
if FValueType in [fvtSum, fvtAvg, fvtMax, fvtMin] then
begin
if (not VarIsEmpty(AValue)) and (AValue <> null) and Assigned(FField) then
begin
if FField.DataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
begin
case FValueType of
fvtMax: FTestValue := Max(FTestValue, AValue);
fvtMin: FTestValue := Min(FTestValue, AValue);
end;
end
else
begin
case FValueType of
fvtSum,
fvtAvg: FTestValue := FTestValue + AValue;
fvtMax: FTestValue := Max(FTestValue, AValue);
fvtMin: FTestValue := Min(FTestValue, AValue);
end;
end;
end;
end;
end;
constructor TRxColumnFooterItem.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
if Assigned(ACollection) then
FOwner := TRxColumn(TRxColumnFooterItems(ACollection).Owner);
FTestValue := 0;
FLayout := tlCenter;
FColor:=clNone;
FFont := TFont.Create;
FillDefaultFont;
FFont.OnChange := @FontChanged;
end;
destructor TRxColumnFooterItem.Destroy;
begin
FreeAndNil(FFont);
inherited Destroy;
end;
function TRxColumnFooterItem.DisplayText: string;
begin
case FValueType of
fvtSum,
fvtAvg,
fvtMax,
fvtMin: Result := GetStatTotal;
fvtCount: Result := GetRecordsCount;
fvtFieldValue: Result := GetFieldValue;
fvtStaticText: Result := FValue;
fvtRecNo: Result := GetRecNo;
else
Result := '';
end;
end;
procedure TRxColumnFooterItem.FillDefaultFont;
var
AGrid: TCustomGrid;
begin
if not Assigned(FOwner) then exit;
AGrid := FOwner.Grid;
if (AGrid<>nil) then
begin
FFont.Assign(AGrid.Font);
FIsDefaultFont := True;
end;
end;
{ TRxColumnFooterItems }
function TRxColumnFooterItems.GetItem(Index: integer): TRxColumnFooterItem;
begin
Result := TRxColumnFooterItem(inherited GetItem(Index));
end;
procedure TRxColumnFooterItems.SetItem(Index: integer;
const AValue: TRxColumnFooterItem);
begin
inherited SetItem(Index, AValue);
end;
procedure TRxColumnFooterItems.Update(Item: TCollectionItem);
begin
inherited Update(Item);
end;
constructor TRxColumnFooterItems.Create(AOwner: TPersistent);
begin
inherited Create(AOwner, TRxColumnFooterItem);
end;
function TRxColumnFooterItems.GetEnumerator: TRxColumnFooterItemsEnumerator;
begin
Result:=TRxColumnFooterItemsEnumerator.Create(Self);
end;
{ TRxDBGridAbstractTools }
procedure TRxDBGridAbstractTools.SetRxDBGrid(AValue: TRxDBGrid);
begin
if FRxDBGrid=AValue then Exit;
if Assigned(FRxDBGrid) then
FRxDBGrid.RemoveTools(Self);
FRxDBGrid:=AValue;
if Assigned(FRxDBGrid) then
FRxDBGrid.AddTools(Self);
end;
function TRxDBGridAbstractTools.DoExecTools: boolean;
begin
Result:=false;
end;
function TRxDBGridAbstractTools.DoSetupTools: boolean;
begin
Result:=true;
end;
function TRxDBGridAbstractTools.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: integer): boolean;
begin
Result:=false;
end;
procedure TRxDBGridAbstractTools.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = FRxDBGrid) and (Operation = opRemove) then
FRxDBGrid := nil;
end;
procedure TRxDBGridAbstractTools.ExecTools(Sender: TObject);
begin
Execute;
end;
procedure TRxDBGridAbstractTools.SetEnabled(AValue: boolean);
begin
if FEnabled=AValue then Exit;
FEnabled:=AValue;
FRxDBGrid.UpdateToolsState(Self);
end;
constructor TRxDBGridAbstractTools.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FToolsEvents:=[];
FCaption:=Name;
FShowSetupForm:=false;
FEnabled:=true;
end;
destructor TRxDBGridAbstractTools.Destroy;
begin
SetRxDBGrid(nil);
inherited Destroy;
end;
function TRxDBGridAbstractTools.Execute: boolean;
begin
Result:=true;
if Assigned(FOnBeforeExecute) then
FOnBeforeExecute(Self);
if FShowSetupForm then
Result:=DoSetupTools;
if Result then
Result:=DoExecTools;
if Assigned(FOnAfterExecute) then
FOnAfterExecute(Self);
end;
{ TRxDBGridCollumnConstraint }
procedure TRxDBGridCollumnConstraints.SetMaxWidth(AValue: integer);
begin
if FMaxWidth=AValue then Exit;
if (FMinWidth<>0) and (AValue<>0) and (AValue < FMinWidth) then exit;
FMaxWidth:=AValue;
end;
procedure TRxDBGridCollumnConstraints.SetMinWidth(AValue: integer);
begin
if FMinWidth=AValue then Exit;
if (FMaxWidth<>0) and (AValue<>0) and (AValue > FMaxWidth) then exit;
FMinWidth:=AValue;
end;
procedure TRxDBGridCollumnConstraints.AssignTo(Dest: TPersistent);
begin
if Dest is TRxDBGridCollumnConstraints then
begin
TRxDBGridCollumnConstraints(Dest).FMinWidth:=FMinWidth;
TRxDBGridCollumnConstraints(Dest).FMaxWidth:=FMaxWidth;
end
else
inherited AssignTo(Dest);
end;
constructor TRxDBGridCollumnConstraints.Create(AOwner: TPersistent);
begin
inherited Create;
FOwner:=AOwner;
end;
{ TRxDbGridColumnsSortList }
function TRxDbGridColumnsSortList.GetCollumn(Index: Integer): TRxColumn;
begin
Result:=TRxColumn(Items[Index]);
end;
{ TRxColumnEditButton }
function TRxColumnEditButton.GetGlyph: TBitmap;
begin
Result:=FButton.Glyph;
end;
function TRxColumnEditButton.GetHint: String;
begin
Result:=FButton.Hint;
end;
function TRxColumnEditButton.GetNumGlyphs: Integer;
begin
Result:=FButton.NumGlyphs;
end;
function TRxColumnEditButton.GetOnButtonClick: TNotifyEvent;
begin
Result:=FButton.OnClick;
end;
function TRxColumnEditButton.GetWidth: Integer;
begin
Result:=FButton.Width;
end;
procedure TRxColumnEditButton.SetGlyph(AValue: TBitmap);
begin
FButton.Glyph.Assign(AValue);
if not (csLoading in TRxDBGrid(TRxColumnEditButtons(Collection).Owner).ComponentState) then
FStyle:=ebsGlyphRx;
end;
procedure TRxColumnEditButton.SetHint(AValue: String);
begin
FButton.Hint:=AValue;
FSpinBtn.Hint:=AValue;
end;
procedure TRxColumnEditButton.SetNumGlyphs(AValue: Integer);
begin
FButton.NumGlyphs:=AValue;
end;
procedure TRxColumnEditButton.SetOnButtonClick(AValue: TNotifyEvent);
begin
FButton.OnClick:=AValue;
end;
procedure TRxColumnEditButton.SetStyle(AValue: TRxColumnEditButtonStyle);
begin
if FStyle=AValue then Exit;
FStyle:=AValue;
case FStyle of
ebsDropDownRx:FButton.Glyph.Assign(FMarkerDown);
ebsEllipsisRx:FButton.Glyph.Assign(FEllipsisRxBMP);
ebsGlyphRx:FButton.Glyph.Assign(FGlyphRxBMP);
ebsUpDownRx:FButton.Glyph.Assign(FUpDownRxBMP);
ebsPlusRx:FButton.Glyph.Assign(FPlusRxBMP);
ebsMinusRx:FButton.Glyph.Assign(FMinusRxBMP);
else
FButton.Glyph.Assign(nil);
end;
end;
procedure TRxColumnEditButton.SetVisible(AValue: Boolean);
begin
FVisible:=AValue;
if AValue then
begin
if Style = ebsUpDownRx then
begin
FSpinBtn.Visible:=AValue;
FButton.Visible:=false;
end
else
begin
FButton.Visible:=AValue;
FSpinBtn.Visible:=false;
end;
end
else
begin
FButton.Visible:=AValue;
FSpinBtn.Visible:=AValue;
end;
end;
procedure TRxColumnEditButton.SetWidth(AValue: Integer);
begin
FButton.Width:=AValue;
FSpinBtn.Width:=AValue;
end;
procedure TRxColumnEditButton.DoBottomClick(Sender: TObject);
var
F:TField;
Col:TRxColumn;
msg: TGridMessage;
begin
Col:=TRxColumnEditButtons(Collection).FOwner as TRxColumn;
F:=Col.Field;
if Assigned(F) and (F.DataType in NumericDataTypes) then
begin
if not (F.DataSet.State in dsEditModes) then
F.DataSet.Edit;
if F.IsNull then
F.Value:=0;
F.Value:=F.Value - 1;
Msg.LclMsg.msg:=GM_SETVALUE;
Msg.Grid:=Col.Grid;
Msg.Value:=F.DisplayText;
TRxDBGrid(Col.Grid).Editor.Dispatch(Msg);
end;
end;
procedure TRxColumnEditButton.DoTopClick(Sender: TObject);
var
F:TField;
Col:TRxColumn;
msg: TGridMessage;
begin
Col:=TRxColumnEditButtons(Collection).FOwner as TRxColumn;
F:=Col.Field;
if Assigned(F) and (F.DataType in NumericDataTypes) then
begin
if not (F.DataSet.State in dsEditModes) then
F.DataSet.Edit;
if F.IsNull then
F.Value:=0;
F.Value:=F.Value + 1;
Msg.LclMsg.msg:=GM_SETVALUE;
Msg.Grid:=Col.Grid;
Msg.Value:=F.DisplayText;
TRxDBGrid(Col.Grid).Editor.Dispatch(Msg);
end;
end;
function TRxColumnEditButton.GetDisplayName: string;
begin
if Hint<>'' then
Result:=Hint
else
Result:='TRxColumnEditButton';
end;
constructor TRxColumnEditButton.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FButton:=TSpeedButton.Create(nil);
FSpinBtn:=TRxSpinButton.Create(nil);
FSpinBtn.OnBottomClick:=@DoBottomClick;
FSpinBtn.OnTopClick:=@DoTopClick;
FVisible:=true;
FEnabled:=true;
Width:=15;
end;
destructor TRxColumnEditButton.Destroy;
begin
FreeAndNil(FButton);
FreeAndNil(FSpinBtn);
inherited Destroy;
end;
{ TRxColumnEditButtons }
function TRxColumnEditButtons.GetItem(Index: integer): TRxColumnEditButton;
begin
Result:= TRxColumnEditButton(inherited Items[Index]);
end;
procedure TRxColumnEditButtons.SetItem(Index: integer;
AValue: TRxColumnEditButton);
begin
inherited SetItem(Index, AValue);
end;
procedure TRxColumnEditButtons.Update(Item: TCollectionItem);
begin
inherited Update(Item);
end;
constructor TRxColumnEditButtons.Create(AOwner: TPersistent);
begin
inherited Create(TRxColumnEditButton);
FOwner:=AOwner;
end;
function TRxColumnEditButtons.Add: TRxColumnEditButton;
begin
Result := TRxColumnEditButton(inherited Add);
end;
{ TRxDBGridFooterOptions }
procedure TRxDBGridFooterOptions.SetActive(AValue: boolean);
begin
if FActive=AValue then Exit;
FActive:=AValue;
{ TODO : Устаревший код - в следующей версии необходимо убрать }
if FActive then
FOwner.FOptionsRx:=FOwner.FOptionsRx + [rdgFooterRows]
else
FOwner.FOptionsRx:=FOwner.FOptionsRx - [rdgFooterRows];
if FActive then
FOwner.CalcStatTotals;
FOwner.VisualChange;
end;
procedure TRxDBGridFooterOptions.SetColor(AValue: TColor);
begin
if FColor=AValue then Exit;
FColor:=AValue;
FOwner.Invalidate;
end;
procedure TRxDBGridFooterOptions.SetDrawFullLine(AValue: boolean);
begin
if FDrawFullLine=AValue then Exit;
FDrawFullLine:=AValue;
FOwner.VisualChange;
end;
procedure TRxDBGridFooterOptions.SetRowCount(AValue: integer);
begin
if FRowCount=AValue then Exit;
FRowCount:=AValue;
FOwner.VisualChange;
end;
procedure TRxDBGridFooterOptions.SetStyle(AValue: TTitleStyle);
begin
if FStyle=AValue then Exit;
FStyle:=AValue;
end;
procedure TRxDBGridFooterOptions.AssignTo(Dest: TPersistent);
var
FO:TRxDBGridFooterOptions absolute Dest;
begin
if Dest is TRxDBGridFooterOptions then
begin
FO.Active:=Active;
FO.Color:=Color;
FO.RowCount:=RowCount;
FO.Style:=Style;
end
else
inherited AssignTo(Dest);
end;
constructor TRxDBGridFooterOptions.Create(Owner: TRxDBGrid);
begin
inherited Create;
FOwner:=Owner;
FColor := clWindow;
FRowCount := 0;
FStyle := tsLazarus;
end;
destructor TRxDBGridFooterOptions.Destroy;
begin
inherited Destroy;
end;
{ TRxDBGridDateEditor }
procedure TRxDBGridDateEditor.EditChange;
var
D:TDateTime;
begin
inherited EditChange;
if Assigned(FGrid) and FGrid.DatalinkActive and not FGrid.EditorIsReadOnly then
begin
if not (FGrid.DataSource.DataSet.State in dsEditModes) then
FGrid.DataSource.Edit;
if Self.Text <> '' then
FGrid.SelectedField.AsDateTime := Self.Date
else
FGrid.SelectedField.Clear;
if FGrid <> nil then
begin
if TryStrToDate(Text, D) then
FGrid.SetEditText(FCol, FRow, Text)
else
FGrid.SetEditText(FCol, FRow, '');
end;
end;
end;
procedure TRxDBGridDateEditor.KeyDown(var Key: word; Shift: TShiftState);
function AllSelected: boolean;
begin
Result := (SelLength > 0) and (SelLength = UTF8Length(Text));
end;
function AtStart: boolean;
begin
Result := (SelStart = 0);
end;
function AtEnd: boolean;
begin
Result := ((SelStart + 1) > UTF8Length(Text)) or AllSelected;
end;
procedure doEditorKeyDown;
begin
if FGrid <> nil then
FGrid.EditorkeyDown(Self, key, shift);
end;
procedure doGridKeyDown;
begin
if FGrid <> nil then
FGrid.KeyDown(Key, shift);
end;
function GetFastEntry: boolean;
begin
if FGrid <> nil then
Result := FGrid.FastEditing
else
Result := False;
end;
procedure CheckEditingKey;
begin
if (FGrid = nil) or FGrid.EditorIsReadOnly then
Key := 0;
end;
var
IntSel: boolean;
begin
inherited KeyDown(Key, Shift);
case Key of
VK_F2:
if AllSelected then
begin
SelLength := 0;
SelStart := Length(Text);
end;
VK_DELETE:
CheckEditingKey;
VK_UP, VK_DOWN:
doGridKeyDown;
VK_LEFT, VK_RIGHT:
if GetFastEntry then
begin
IntSel :=
((Key = VK_LEFT) and not AtStart) or ((Key = VK_RIGHT) and not AtEnd);
if not IntSel then
begin
doGridKeyDown;
end;
end;
VK_END, VK_HOME:
;
else
doEditorKeyDown;
end;
end;
procedure TRxDBGridDateEditor.WndProc(var TheMessage: TLMessage);
begin
if FGrid<>nil then
case TheMessage.Msg of
LM_CLEAR,
LM_CUT,
LM_PASTE:
begin
if FGrid.EditorIsReadOnly then
exit;
end;
end;
if TheMessage.msg = LM_KILLFOCUS then
begin
if HWND(TheMessage.WParam) = HWND(Handle) then
begin
// lost the focus but it returns to ourselves
// eat the message.
TheMessage.Result := 0;
exit;
end;
end;
inherited WndProc(TheMessage);
end;
procedure TRxDBGridDateEditor.msg_SetGrid(var Msg: TGridMessage);
begin
FGrid := Msg.Grid as TRxDBGrid;
Msg.Options := EO_AUTOSIZE or EO_SELECTALL
{or EO_HOOKEXIT or EO_HOOKKEYPRESS or EO_HOOKKEYUP};
end;
procedure TRxDBGridDateEditor.msg_SetValue(var Msg: TGridMessage);
var
D: TDateTime;
begin
if FGrid.SelectedField.DataType in [ftDate, ftDateTime] then
Self.Date := FGrid.SelectedField.AsDateTime
else
if TryStrToDateTime(FGrid.SelectedField.AsString, D) then
Self.Date := D
else
Self.Clear;
end;
procedure TRxDBGridDateEditor.msg_GetValue(var Msg: TGridMessage);
var
sText: string;
begin
sText := Text;
Msg.Value := sText;
end;
procedure TRxDBGridDateEditor.msg_SelectAll(var Msg: TGridMessage);
begin
SelectAll;
end;
constructor TRxDBGridDateEditor.Create(Aowner: TComponent);
begin
inherited Create(Aowner);
AutoSize := false;
Spacing:=0;
UpdateMask;
end;
procedure TRxDBGridDateEditor.EditingDone;
begin
inherited EditingDone;
if FGrid <> nil then
FGrid.EditingDone;
end;
{ TRxDBGridLookupComboEditor }
procedure TRxDBGridLookupComboEditor.WndProc(var TheMessage: TLMessage);
begin
if TheMessage.msg = LM_KILLFOCUS then
begin
if HWND(TheMessage.WParam) = HWND(Handle) then
begin
// lost the focus but it returns to ourselves
// eat the message.
TheMessage.Result := 0;
exit;
end;
end;
inherited WndProc(TheMessage);
end;
procedure TRxDBGridLookupComboEditor.KeyDown(var Key: word; Shift: TShiftState);
procedure doGridKeyDown;
begin
if Assigned(FGrid) then
FGrid.KeyDown(Key, shift);
end;
procedure doEditorKeyDown;
begin
if FGrid <> nil then
FGrid.EditorkeyDown(Self, key, shift);
end;
function GetFastEntry: boolean;
begin
if FGrid <> nil then
Result := FGrid.FastEditing
else
Result := False;
end;
procedure CheckEditingKey;
begin
if (FGrid=nil) or FGrid.EditorIsReadOnly then
Key := 0;
end;
begin
CheckEditingKey;
case Key of
VK_UP,
VK_DOWN:
if (not PopupVisible) and (not (ssAlt in Shift)) then
begin
doGridKeyDown;
Key:=0;
exit;
end;
VK_LEFT, VK_RIGHT:
if GetFastEntry then
begin
doGridKeyDown;
exit;
end;
else
begin
inherited KeyDown(Key, Shift);
doEditorKeyDown;
exit;
end;
end;
inherited KeyDown(Key, Shift);
end;
procedure TRxDBGridLookupComboEditor.msg_SetGrid(var Msg: TGridMessage);
begin
FGrid := Msg.Grid as TRxDBGrid;
Msg.Options := EO_AUTOSIZE;
end;
procedure TRxDBGridLookupComboEditor.msg_SetValue(var Msg: TGridMessage);
var
F: TField;
begin
FCol := Msg.Col;
FRow := Msg.Row;
F := FGrid.SelectedField;
DataSource := FGrid.DataSource;
if Assigned(F) then
begin
DataField := F.KeyFields;
LookupDisplay := F.LookupResultField;
LookupField := F.LookupKeyFields;
FLDS.DataSet := F.LookupDataSet;
FGrid.GetOnCreateLookup;
end;
end;
procedure TRxDBGridLookupComboEditor.msg_GetValue(var Msg: TGridMessage);
var
sText: string;
F:TField;
begin
if Assigned(FGrid.SelectedField) and Assigned(FLDS.DataSet) then
begin
F:=FLDS.DataSet.FieldByName(LookupDisplay);
if Assigned(F) then
begin
sText := F.DisplayText;
Msg.Value := sText;
end;
end;
end;
procedure TRxDBGridLookupComboEditor.ShowList;
begin
FGrid.GetOnDisplayLookup;
inherited ShowList;
end;
procedure TRxDBGridLookupComboEditor.OnInternalClosePopup(AResult: boolean);
procedure CheckEditingKey;
begin
if (FGrid=nil) or FGrid.EditorIsReadOnly then
// Key := 0;
end;
var
F:TField;
begin
inherited OnInternalClosePopup(AResult);
CheckEditingKey;
if (AResult) and Assigned(FGrid.SelectedField) and Assigned(FLDS.DataSet) then
begin
F:=FLDS.DataSet.FieldByName(LookupDisplay);
if Assigned(F) then
begin
if (FGrid<>nil) and Visible then begin
FGrid.SetEditText(FCol, FRow, F.DisplayText);
end;
end;
end;
end;
constructor TRxDBGridLookupComboEditor.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLDS := TDataSource.Create(nil);
LookupSource := FLDS;
AutoSize := false;
Style:=rxcsDropDownList;
end;
destructor TRxDBGridLookupComboEditor.Destroy;
begin
FreeAndNil(FLDS);
inherited Destroy;
end;
{ TRxDBGrid }
procedure TRxDBGrid.SetTitleButtons(const AValue: boolean);
begin
if AValue then
Options := Options + [dgHeaderPushedLook]
else
Options := Options - [dgHeaderPushedLook];
end;
procedure TRxDBGrid.GetScrollbarParams(out aRange, aPage, aPos: Integer);
begin
if (DataSource.DataSet<>nil) and DataSource.DataSet.Active then begin
if DataSource.DataSet.IsSequenced then begin
aRange := DataSource.DataSet.RecordCount + VisibleRowCount - 1;
aPage := VisibleRowCount;
if aPage<1 then aPage := 1;
if DataSource.DataSet.BOF then aPos := 0 else
if DataSource.DataSet.EOF then aPos := aRange
else
aPos := DataSource.DataSet.RecNo - 1; // RecNo is 1 based
if aPos<0 then aPos:=0;
end else begin
aRange := 6;
aPage := 2;
if DataSource.DataSet.EOF then aPos := 4 else
if DataSource.DataSet.BOF then aPos := 0
else aPos := 2;
end;
end else begin
aRange := 0;
aPage := 0;
aPos := 0;
end;
end;
procedure TRxDBGrid.RestoreEditor;
begin
if EditorMode then
begin
EditorMode := False;
EditorMode := True;
end;
end;
procedure TRxDBGrid.SetAutoSort(const AValue: boolean);
var
S: string;
Pos: integer;
begin
if FAutoSort = AValue then
exit;
FAutoSort := AValue;
if Assigned(DataSource) and Assigned(DataSource.DataSet) and
DataSource.DataSet.Active then
begin
S := DataSource.DataSet.ClassName;
if RxDBGridSortEngineList.Find(S, Pos) then
FSortEngine := RxDBGridSortEngineList.Objects[Pos] as TRxDBGridSortEngine
else
FSortEngine := nil;
FSortColumns.Clear;
end;
end;
procedure TRxDBGrid.SetColumnDefValues(AValue: TRxDBGridColumnDefValues);
begin
FColumnDefValues.AssignTo(AValue);
end;
function TRxDBGrid.GetColumns: TRxDbGridColumns;
begin
Result := TRxDbGridColumns(inherited Columns);
end;
function TRxDBGrid.GetFooterColor: TColor;
begin
Result:=FFooterOptions.FColor;
end;
function TRxDBGrid.GetFooterRowCount: integer;
begin
Result:=FFooterOptions.RowCount;
end;
function TRxDBGrid.GetDrawFullLine: boolean;
begin
Result := FFooterOptions.FDrawFullLine;
end;
procedure TRxDBGrid.SetDrawFullLine(Value: boolean);
begin
FFooterOptions.DrawFullLine := Value;
end;
function TRxDBGrid.CreateToolMenuItem(ShortCut: char; const ACaption: string;
MenuAction: TNotifyEvent): TMenuItem;
begin
Result := TMenuItem.Create(F_PopupMenu);
F_PopupMenu.Items.Add(Result);
Result.Caption := ACaption;
if ShortCut <> #0 then
Result.ShortCut := KeyToShortCut(Ord(ShortCut), [ssCtrl]);
Result.OnClick := MenuAction;
end;
procedure TRxDBGrid.RemoveToolMenuItem(MenuAction: TNotifyEvent);
var
R: TMenuItem;
I: Integer;
begin
if not Assigned(MenuAction) then Exit;
for I:=F_PopupMenu.Items.Count-1 downto 0 do
begin
R:=F_PopupMenu.Items[I];
if R.OnClick = MenuAction then
begin
F_PopupMenu.Items.Delete(i);
R.Free;
end;
end;
end;
procedure TRxDBGrid.DoCreateJMenu;
begin
F_PopupMenu := TPopupMenu.Create(Self);
F_PopupMenu.Name := 'OptionsMenu';
CreateToolMenuItem('F', sRxDBGridFind, @OnFind);
CreateToolMenuItem('T', sRxDBGridFilter, @OnFilterBy);
CreateToolMenuItem('E', sRxDBGridFilterSimple, @OnFilter);
CreateToolMenuItem('Q', sRxDBGridFilterClear, @OnFilterClose);
CreateToolMenuItem(#0, '-', nil);
CreateToolMenuItem('C', sRxDBGridSortByColumns, @OnSortBy);
CreateToolMenuItem('W', sRxDBGridSelectColumns, @OnChooseVisibleFields);
CreateToolMenuItem('A', sRxDBGridSelectAllRows, @OnSelectAllRows);
CreateToolMenuItem(#0, sRxDBGridCopyCellValue, @OnCopyCellValue);
CreateToolMenuItem(#0, sRxDBGridOptimizeColWidth, @OnOptimizeColWidth);
end;
function TRxDBGrid.GetPropertyStorage: TCustomPropertyStorage;
begin
Result := FPropertyStorageLink.Storage;
end;
function TRxDBGrid.GetSortField: string;
begin
if FSortColumns.Count > 0 then
Result:=FSortColumns[0].GetSortFields
else
Result:='';
end;
function TRxDBGrid.GetSortOrder: TSortMarker;
begin
if FSortColumns.Count > 0 then
Result:=FSortColumns[0].SortOrder
else
Result:=smNone;
end;
function TRxDBGrid.GetTitleButtons: boolean;
begin
Result := dgHeaderPushedLook in Options;
end;
function TRxDBGrid.IsColumnsStored: boolean;
begin
Result := TRxDbGridColumns(TCustomDrawGrid(Self).Columns).Enabled;
end;
procedure TRxDBGrid.SelectedFontChanged(Sender: TObject);
begin
FIsSelectedDefaultFont:=FSelectedFont.IsDefault;
VisualChange;
end;
function TRxDBGrid.IsSelectedFontStored: Boolean;
begin
Result:=not FIsSelectedDefaultFont
end;
procedure TRxDBGrid.SetColumns(const AValue: TRxDbGridColumns);
begin
inherited Columns := TDBGridColumns(AValue);
end;
procedure TRxDBGrid.SetFooterColor(const AValue: TColor);
begin
FFooterOptions.Color := AValue;
end;
procedure TRxDBGrid.SetFooterOptions(AValue: TRxDBGridFooterOptions);
begin
FFooterOptions.AssignTo(AValue);
end;
procedure TRxDBGrid.SetFooterRowCount(const AValue: integer);
begin
FFooterOptions.RowCount:=AValue;
end;
procedure TRxDBGrid.SetKeyStrokes(const AValue: TRxDBGridKeyStrokes);
begin
if Assigned(AValue) then
FKeyStrokes.Assign(AValue)
else
FKeyStrokes.Clear;
UpdateJMenuKeys;
end;
procedure TRxDBGrid.SetOptionsRx(const AValue: TOptionsRx);
var
OldOpt: TOptionsRx;
begin
if FOptionsRx = AValue then
exit;
BeginUpdate;
OldOpt := FOptionsRx;
FOptionsRx := AValue;
UseXORFeatures := rdgXORColSizing in AValue;
if (rdgFilter in AValue) and not (rdgFilter in OldOpt) then
begin
FillFilterData;
LayoutChanged;
end
else
if rdgFilter in OldOpt then
begin
FFilterListEditor.Hide;
FFilterColDlgButton.Hide;
FFilterSimpleEdit.Hide;
LayoutChanged;
end;
FFooterOptions.FActive:=rdgFooterRows in FOptionsRx;
if (rdgWordWrap in OldOpt) and not (rdgWordWrap in FOptionsRx) then
ResetRowHeght;
EndUpdate;
end;
procedure TRxDBGrid.SetPropertyStorage(const AValue: TCustomPropertyStorage);
begin
FPropertyStorageLink.Storage := AValue;
end;
procedure TRxDBGrid.SetSearchOptions(AValue: TRxDBGridSearchOptions);
begin
FSearchOptions.Assign(AValue);
end;
procedure TRxDBGrid.SetSelectedFont(AValue: TFont);
begin
if not FSelectedFont.IsEqual(AValue) then
FSelectedFont.Assign(AValue);
end;
function TRxDBGrid.DatalinkActive: boolean;
begin
Result := Assigned(DataSource) and Assigned(DataSource.DataSet) and
DataSource.DataSet.Active;
end;
procedure TRxDBGrid.AdjustEditorBounds(NewCol, NewRow: Integer);
begin
inherited AdjustEditorBounds(NewCol, NewRow);
if EditorMode then
begin
DoSetColEdtBtn;
end;
end;
procedure TRxDBGrid.TrackButton(X, Y: integer);
var
Cell: TGridCoord;
NewPressed: boolean;
I, Offset: integer;
begin
Cell := MouseCoord(X, Y);
Offset := RowCount;
NewPressed := PtInRect(Rect(0, 0, ClientWidth, ClientHeight), Point(X, Y)) and
(FPressedCol = TColumn(ColumnFromGridColumn(Cell.X))) and (Cell.Y < Offset);
if FPressed <> NewPressed then
begin
FPressed := NewPressed;
for I := 0 to Offset - 1 do
GridInvalidateRow(Self, I);
end;
end;
procedure TRxDBGrid.StopTracking;
begin
if FTracking then
begin
TrackButton(-1, -1);
FTracking := False;
MouseCapture := False;
end;
end;
procedure TRxDBGrid.CalcTitle;
var
i, j: integer;
H, H1, W, W1, FDefRowH: integer;
rxCol, rxColNext: TRxColumn;
rxTit, rxTitleNext: TRxColumnTitle;
MLRec1, P: TMLCaptionItem;
MLRec2: TMLCaptionItem;
tmpCanvas: TCanvas;
FWC: SizeInt;
begin
FDefRowH:=GetDefaultRowHeight;
{ TODO -oalexs : need rewrite code - split to 2 step:
1. make links between column
2. calc title width for all linked column series }
if RowCount = 0 then
exit;
tmpCanvas := GetWorkingCanvas(Canvas);
try
ClearMLCaptionPointers;
for i := 0 to Columns.Count - 1 do
begin
rxCol := TRxColumn(Columns[i]);
if Assigned(rxCol) and rxCol.Visible then
begin
rxTit := TRxColumnTitle(rxCol.Title);
if Assigned(rxTit) then
begin
if rxTit.Orientation in [toVertical270, toVertical90] then
// H := Max((tmpCanvas.TextWidth(Columns[i].Title.Caption) + tmpCanvas.TextWidth('W')*2) div DefaultRowHeight, H)
else
begin
rxColNext := nil;
rxTitleNext := nil;
if i < Columns.Count - 1 then
begin
rxColNext := TRxColumn(Columns[i + 1]);
rxTitleNext := TRxColumnTitle(rxColNext.Title);
end;
// W := Max(rxCol.Width - 6, 1);
if rxTit.CaptionLinesCount > 0 then
begin
// H2 := 0;
// H1 := 0;
for j := 0 to rxTit.CaptionLinesCount - 1 do
begin
MLRec1 := rxTit.CaptionLine(j);
if Assigned(rxTitleNext) and (rxTitleNext.CaptionLinesCount > j) then
begin
//make links to next column - and in the next column set link to prior-current
MLRec2 := rxTitleNext.CaptionLine(j);
if MLRec1.Caption = MLRec2.Caption then
begin
MLRec1.Next := MLRec2;
MLRec2.Prior := MLRec1;
end
else
break;
end;
MLRec1.Width := tmpCanvas.TextWidth(MLRec1.Caption) + 2;
{ if W > MLRec1.Width then
H2 := 1
else
H2 := MLRec1.Width div W + 1;
if H2 > WordCount(MLRec1.Caption, [' ']) then
H2 := WordCount(MLRec1.Caption, [' ']);
H1 := H1 + H2;}
end;
end
{ else
begin
H1 := Max((tmpCanvas.TextWidth(rxTit.Caption) + 2) div W + 1, H);
if H1 > WordCount(rxTit.Caption, [' ']) then
H1 := WordCount(rxTit.Caption, [' ']);
end;
H := Max(H1, H); }
end;
for j := 0 to rxTit.CaptionLinesCount - 1 do
begin
MLRec1 := rxTit.CaptionLine(j);
if MLRec1.Width < rxTit.Column.Width then
MLRec1.Width := rxTit.Column.Width;
end;
end;
end;
end;
//Тут расчёт высоты заголовка каждой колонки - надо обработать слитые заголовки
H := 1;
for i := 0 to Columns.Count - 1 do
begin
rxCol := TRxColumn(Columns[i]);
rxTit := TRxColumnTitle(rxCol.Title);
H1 := 0;
W := Max(rxCol.Width - 6, 1);
//Не забудем про вертикальную ориентацию
if Assigned(rxCol) and rxCol.Visible and Assigned(rxTit) then
begin
if rxTit.Orientation in [toVertical270, toVertical90] then
H1 := Max((tmpCanvas.TextWidth(Columns[i].Title.Caption) +
tmpCanvas.TextWidth('W')) div FDefRowH, H)
else
begin
if rxTit.CaptionLinesCount = 0 then
begin
H1 := Max((tmpCanvas.TextWidth(rxTit.Caption) + 2) div W + 1, H);
FWC:=WordCount(rxTit.Caption, [' ']);
if H1 > FWC then H1 := FWC;
end
else
begin
if rxTit.CaptionLinesCount > H then
H := rxTit.CaptionLinesCount;
for j := 0 to rxTit.CaptionLinesCount - 1 do
begin
MLRec1 := rxTit.CaptionLine(j);
//S := MLRec1.Caption;
if not Assigned(MLRec1.Prior) then
begin
W := rxCol.Width;
P := MLRec1.Next;
while Assigned(P) do
begin
Inc(W, P.Col.Width);
P := P.Next;
end;
W1 := tmpCanvas.TextWidth(MLRec1.Caption) + 2;
if W1 > W then
MLRec1.Height := Min(W1 div Max(W, 1) + 1, UTF8Length(MLRec1.Caption))
else
MLRec1.Height := 1;
P := MLRec1.Next;
while Assigned(P) do
begin
P.Height := MLRec1.Height;
P := P.Next;
end;
end;
H1 := H1 + MLRec1.Height;
end;
end;
end;
end;
if H1 > H then
H := H1;
end;
if not (rdgDisableWordWrapTitles in OptionsRx) then
RowHeights[0] := FDefRowH * H
else
RowHeights[0] := FDefRowH;
if rdgFilter in OptionsRx then
begin
H:=FDefRowH;
if Assigned(FFilterListEditor) then
H:=Max(H, FFilterListEditor.Height);
if Assigned(FFilterSimpleEdit) then
H:=Max(H, FFilterSimpleEdit.Height);
RowHeights[0] := RowHeights[0] + H;
end;
finally
if TmpCanvas <> Canvas then
FreeWorkingCanvas(tmpCanvas);
end;
end;
procedure TRxDBGrid.ClearMLCaptionPointers;
var
i, j: integer;
rxCol: TRxColumn;
rxTit: TRxColumnTitle;
begin
for i := 0 to Columns.Count - 1 do
begin
rxCol := TRxColumn(Columns[i]);
if Assigned(rxCol) then
begin
rxTit := TRxColumnTitle(rxCol.Title);
if Assigned(rxTit) then
begin
for j := 0 to rxTit.CaptionLinesCount - 1 do
begin
rxTit.CaptionLine(j).Next := nil;
rxTit.CaptionLine(j).Prior := nil;
end;
end;
end;
end;
end;
procedure TRxDBGrid.FillDefaultFonts;
begin
FSelectedFont.Assign(Font);
//FSelectedFont.Color:=clHighlightText;
FIsSelectedDefaultFont := True;
end;
function TRxDBGrid.getFilterRect(bRect: TRect): TRect;
begin
Result := bRect;
if Assigned(FFilterListEditor) then
Result.Top := bRect.Bottom - FFilterListEditor.Height
else
Result.Top := bRect.Bottom - GetDefaultRowHeight;
end;
function TRxDBGrid.getTitleRect(bRect: TRect): TRect;
begin
Result := bRect;
if Assigned(FFilterListEditor) then
Result.Bottom := bRect.Bottom - FFilterListEditor.Height
else
Result.Bottom := bRect.Bottom - GetDefaultRowHeight;
end;
procedure TRxDBGrid.OutCaptionCellText(aCol, aRow: integer; const aRect: TRect;
aState: TGridDrawState; const ACaption: string);
begin
if (TitleStyle = tsNative) then
DrawThemedCell(aCol, aRow, aRect, aState)
else
begin
Canvas.FillRect(aRect);
DrawCellGrid(aCol, aRow, aRect, aState);
end;
if ACaption <> '' then
begin
if not (rdgDisableWordWrapTitles in OptionsRx) then
WriteTextHeader(Canvas, aRect, ACaption, GetColumnAlignment(aCol, True))
else
DrawCellText(aCol, aRow, aRect, aState, ACaption);
end;
end;
procedure TRxDBGrid.OutCaptionCellText90(aCol, aRow: integer;
const aRect: TRect; aState: TGridDrawState; const ACaption: string;
const TextOrient: TTextOrientation);
var
dW, dY: integer;
begin
if (TitleStyle = tsNative) then
DrawThemedCell(aCol, aRow, aRect, aState)
else
begin
Canvas.FillRect(aRect);
DrawCellGrid(aCol, aRow, aRect, aState);
end;
if TextOrient in [toVertical90, toVertical270] then
begin
dW := ((aRect.Bottom - aRect.Top) - Canvas.TextWidth(ACaption)) div 2;
dY := ((aRect.Right - aRect.Left) - Canvas.TextHeight(ACaption)) div 2;
end
else
begin
dW := 0;
dY := 0;
end;
OutTextXY90(Canvas, aRect.Left + dY, aRect.Top + dw, ACaption, TextOrient);
end;
procedure TRxDBGrid.OutCaptionSortMarker(const aRect: TRect;
ASortMarker: TSortMarker; ASortPosition: integer);
var
X, Y, W: integer;
S:string;
F:TFont;
begin
if (dgHeaderPushedLook in Options) then
begin
if (ASortMarker <> smNone) and (ASortPosition>0) then
begin
F:=TFont.Create;
F.Assign(Font);
if Font.Size = 0 then
Font.Size:=7
else
Font.Size:=Font.Size-2;
S:='('+IntToStr(ASortPosition)+')';
W:=Canvas.TextWidth(S) + 10;
end
else
begin
W:=6;
F:=nil;
end;
if ASortMarker = smDown then
begin
X := aRect.Right - FMarkerDown.Width - W;
Y := Trunc((aRect.Top + aRect.Bottom - FMarkerDown.Height) / 2);
Canvas.Draw(X, Y, FMarkerDown);
end
else
if ASortMarker = smUp then
begin
X := aRect.Right - FMarkerUp.Width - W;
Y := Trunc((aRect.Top + aRect.Bottom - FMarkerUp.Height) / 2);
Canvas.Draw(X, Y, FMarkerUp);
end;
if Assigned(F) then
begin
Canvas.TextOut( X + FMarkerDown.Width, Y, S);
Font.Assign(F);
FreeAndNil(F);
end;
end;
end;
procedure TRxDBGrid.OutCaptionMLCellText(aCol, aRow: integer;
aRect: TRect; aState: TGridDrawState; MLI: TMLCaptionItem);
var
MLINext: TMLCaptionItem;
Rgn: HRGN;
begin
MLINext := MLI.Next;
while Assigned(MLINext) do
begin
aRect.Right := aRect.Right + MLINext.Col.Width;
MLINext := MLINext.Next;
end;
Rgn := CreateRectRgn(aRect.Left, aRect.Top, aRect.Right, aRect.Bottom);
SelectClipRgn(Canvas.Handle, Rgn);
OutCaptionCellText(aCol, aRow, aRect, aState, MLI.Caption);
SelectClipRgn(Canvas.Handle, 0);
DeleteObject(Rgn);
end;
procedure TRxDBGrid.UpdateJMenuStates;
begin
F_PopupMenu.Items[0].Visible := rdgAllowDialogFind in FOptionsRx;
F_PopupMenu.Items[1].Visible := rdgAllowFilterForm in FOptionsRx;
F_PopupMenu.Items[2].Visible := rdgAllowQuickFilter in FOptionsRx;
F_PopupMenu.Items[3].Visible :=
(rdgFilter in FOptionsRx) or (rdgAllowFilterForm in FOptionsRx);
F_PopupMenu.Items[5].Visible := rdgAllowSortForm in FOptionsRx;
F_PopupMenu.Items[6].Visible := rdgAllowColumnsForm in FOptionsRx;
F_PopupMenu.Items[7].Visible := dgMultiselect in Options;
end;
procedure TRxDBGrid.UpdateJMenuKeys;
function DoShortCut(Cmd: TRxDBGridCommand): TShortCut;
var
K: TRxDBGridKeyStroke;
begin
K := FKeyStrokes.FindRxKeyStrokes(Cmd);
if Assigned(K) and K.Enabled then
Result := K.ShortCut
else
Result := 0;
end;
begin
F_PopupMenu.Items[0].ShortCut := DoShortCut(rxgcShowFindDlg);
F_PopupMenu.Items[1].ShortCut := DoShortCut(rxgcShowFilterDlg);
F_PopupMenu.Items[2].ShortCut := DoShortCut(rxgcShowQuickFilter);
F_PopupMenu.Items[3].ShortCut := DoShortCut(rxgcHideQuickFilter);
F_PopupMenu.Items[5].ShortCut := DoShortCut(rxgcShowSortDlg);
F_PopupMenu.Items[6].ShortCut := DoShortCut(rxgcShowColumnsDlg);
F_PopupMenu.Items[7].ShortCut := DoShortCut(rxgcSelectAll);
end;
function TRxDBGrid.SortEngineOptions: TRxSortEngineOptions;
begin
Result := [];
if rdgCaseInsensitiveSort in FOptionsRx then
Include(Result, seoCaseInsensitiveSort);
end;
procedure TRxDBGrid.OnIniSave(Sender: TObject);
var
i: integer;
S, S1: string;
C: TRxColumn;
begin
S := Owner.Name + '.' + Name;
FPropertyStorageLink.Storage.WriteInteger(S + sVersion, FVersion);
FPropertyStorageLink.Storage.WriteInteger(S + sCount, Columns.Count);
S := S + sItem;
for i := 0 to Columns.Count - 1 do
begin
S1 := S + IntToStr(i);
C := TRxColumn(Columns[i]);
FPropertyStorageLink.Storage.WriteString(S1 + sCaption,
StrToHexText(C.Title.Caption));
FPropertyStorageLink.Storage.WriteInteger(S1 + sWidth, C.Width);
FPropertyStorageLink.Storage.WriteInteger(S1 + sIndex, C.Index);
FPropertyStorageLink.Storage.WriteInteger(S1 + sVisible, Ord(C.Visible));
end;
{ TODO : Необходимо подключить сохранение списка колонок сортировки }
{
FSortColumns;
if Assigned(FSortField) then
begin
FPropertyStorageLink.Storage.WriteInteger(S1 + sSortMarker, Ord(FSortOrder));
FPropertyStorageLink.Storage.WriteString(S1 + sSortField, FSortField.FieldName);
end
else
FPropertyStorageLink.Storage.WriteInteger(S1 + sSortMarker, Ord(smNone));
}
end;
procedure TRxDBGrid.OnIniLoad(Sender: TObject);
var
i, ACount: integer;
S, S1, ColumName: string;
C: TRxColumn;
begin
S := Owner.Name + '.' + Name;
ACount := FPropertyStorageLink.Storage.ReadInteger(S + sVersion, FVersion);
//Check cfg version
if ACount = FVersion then
begin
ACount := FPropertyStorageLink.Storage.ReadInteger(S + sCount, 0);
S := S + sItem;
for i := 0 to ACount - 1 do
begin
S1 := S + IntToStr(i);
ColumName := HexTextToStr(FPropertyStorageLink.Storage.ReadString(S1 +
sCaption, ''));
if ColumName <> '' then
begin
C := ColumnByCaption(ColumName);
if Assigned(C) then
begin
{$IFDEF FIX_WIDTH_WIDE_STRING96}
if Screen.PixelsPerInch = 96 then
{$ENDIF}
C.Width := FPropertyStorageLink.Storage.ReadInteger(S1 + sWidth, C.Width);
C.Visible := FPropertyStorageLink.Storage.ReadInteger(S1 + sVisible, Ord(C.Visible)) = 1;
C.Index := Min(FPropertyStorageLink.Storage.ReadInteger(S1 + sIndex, C.Index), Columns.Count - 1);
end;
end;
end;
{ TODO : Необходимо подключить востановление списка колонок сортировки }
{ FSortOrder := TSortMarker(FPropertyStorageLink.Storage.ReadInteger(
S1 + sSortMarker, Ord(smNone)));
if Assigned(FSortEngine) and (FSortOrder <> smNone) and DatalinkActive then
begin
ColumName := FPropertyStorageLink.Storage.ReadString(S1 + sSortField, '');
if ColumName <> '' then
begin
FSortField := DataSource.DataSet.FindField(ColumName);
if Assigned(FSortField) then
FSortEngine.Sort(FSortField, DataSource.DataSet, FSortOrder = smUp,
SortEngineOptions);
end;
end;}
end;
end;
procedure TRxDBGrid.CleanDSEvent;
begin
if Assigned(DataSource) and Assigned(DataSource.DataSet) then
begin
if DataSource.DataSet.OnPostError = @ErrorPo then
DataSource.DataSet.OnPostError := F_EventOnPostError;
if DataSource.DataSet.OnFilterRecord = @FilterRec then
DataSource.DataSet.OnFilterRecord := F_EventOnFilterRec;
if DataSource.DataSet.BeforeDelete = @BeforeDel then
DataSource.DataSet.BeforeDelete := F_EventOnBeforeDelete;
if DataSource.DataSet.BeforePost = @BeforePo then
DataSource.DataSet.BeforePost:=F_EventOnBeforePost;
if DataSource.DataSet.OnDeleteError = @ErrorDel then
DataSource.DataSet.OnDeleteError:=F_EventOnDeleteError;
if DataSource.DataSet.OnPostError = @ErrorPo then
DataSource.DataSet.OnPostError:=F_EventOnPostError;
F_EventOnPostError:=nil;
F_EventOnFilterRec:=nil;
F_EventOnBeforeDelete:=nil;
F_EventOnBeforePost:=nil;
F_EventOnDeleteError:=nil;
F_EventOnPostError:=nil;
end;
end;
procedure TRxDBGrid.CollumnSortListUpdate;
var
i, J:integer;
C:TRxColumn;
begin
FSortColumns.Clear;
for i:=0 to Columns.Count - 1 do
begin
C:=TRxColumn(Columns[i]);
if C.SortOrder <> smNone then
begin
if FSortColumns.Count <> 0 then
begin
for j:=0 to FSortColumns.Count-1 do
if FSortColumns[j].FSortPosition > C.FSortPosition then
begin
FSortColumns.Insert(j, C);
C:=nil;
Break;
end;
end;
if C<>nil then
FSortColumns.Add(C);
end;
end;
for i:=0 to FSortColumns.Count - 1 do
FSortColumns[i].FSortPosition:=i;
end;
procedure TRxDBGrid.CollumnSortListClear;
var
i:integer;
begin
FSortColumns.Clear;
for i:=0 to Columns.Count - 1 do
begin
TRxColumn(Columns[i]).FSortOrder:=smNone;
TRxColumn(Columns[i]).FSortPosition:=0;
end;
end;
procedure TRxDBGrid.CollumnSortListApply;
var
i:integer;
S:string;
Asc:array of boolean;
begin
if (FSortColumns.Count = 0) then exit;
S:='';
FSortingNow:=true;
if (FSortColumns.Count>1) or (Pos(';', FSortColumns[0].GetSortFields)>0) then
begin
SetLength(Asc, FSortColumns.Count);
for i := 0 to FSortColumns.Count - 1 do
begin
Asc[i]:=FSortColumns[i].FSortOrder = smUp;
if S<>'' then
S:=S+';';
S:=S + FSortColumns[i].GetSortFields;
end;
{ TODO : Необходимо добавить опцию регистронезависимого поиска }
FSortEngine.SortList(S, DataSource.DataSet, Asc, SortEngineOptions);
end
else
FSortEngine.Sort(FSortColumns[0].GetSortFields, DataSource.DataSet, FSortColumns[0].FSortOrder = smUp, SortEngineOptions);
FSortingNow:=false;
end;
procedure TRxDBGrid.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if Assigned(Datalink) and (AComponent = DataSource) and (Operation = opRemove) then
begin
ShowMessage('i');
end
else
if (Operation = opRemove) and (AComponent is TRxDBGridAbstractTools) then
RemoveTools(TRxDBGridAbstractTools(AComponent));
end;
function TRxDBGrid.UpdateRowsHeight: integer;
var
i, J, H, H1, H2:integer;
F:TField;
S:string;
CurActiveRecord: Integer;
R:TRxColumn;
P: PtrInt;
begin
Result:=0;
if (not (Assigned(DataLink) and DataLink.Active)) or ((GCache.VisibleGrid.Top=0) and (GCache.VisibleGrid.Bottom=0)) then
exit;
CurActiveRecord:=DataLink.ActiveRecord;
H2:=0;
for i:=GCache.VisibleGrid.Top to GCache.VisibleGrid.Bottom do
begin
DataLink.ActiveRecord:=i - FixedRows;
P:=PtrInt(DataSource.DataSet.ActiveBuffer);
H:=1;
for j:=0 to Columns.Count-1 do
begin
R:=Columns[j] as TRxColumn;;
if R.WordWrap then
begin
F:=R.Field;
if Assigned(F) then
S:=F.DisplayText
else
S:='';
H1 := Max((Canvas.TextWidth(S) + 2) div R.Width + 1, H);
if H1 > WordCount(S, [' ']) then
H1 := WordCount(S, [' ']);
end
else
H1:=1;
H:=Max(H, H1);
end;
if FGroupItems.Active and DatalinkActive then
if Assigned(FGroupItems.FindGroupItem(DataSource.DataSet.Bookmark)) then
Inc(H);
if i<RowCount then
begin
if Assigned(FOnCalcRowHeight) then
FOnCalcRowHeight(Self, H);
RowHeights[i] := GetDefaultRowHeight * H;
H2:=H2 + RowHeights[i];
if H2<=ClientHeight then
Inc(Result);
end;
end;
DataLink.ActiveRecord:=CurActiveRecord;
end;
procedure TRxDBGrid.ResetRowHeght;
var
i:integer;
begin
for i:=1 to RowCount-1 do
RowHeights[i] := GetDefaultRowHeight;
end;
procedure TRxDBGrid.DoClearInvalidTitle;
var
i, j:integer;
FTitle:TRxColumnTitle;
begin
for i:=0 to Columns.Count-1 do
begin
FTitle:=TRxColumnTitle(Columns[i].Title);
for j:=0 to FTitle.CaptionLinesCount-1 do
FTitle.CaptionLine(j).FInvalidDraw:=0;
end;
end;
procedure TRxDBGrid.DoDrawInvalidTitle;
var
i, j:integer;
MLI:TMLCaptionItem;
FTitle:TRxColumnTitle;
begin
for i:=0 to Columns.Count-1 do
begin
FTitle:=TRxColumnTitle(Columns[i].Title);
for j:=0 to FTitle.CaptionLinesCount - 1 do
begin
MLI:=FTitle.CaptionLine(j);
if MLI.FInvalidDraw<0 then
begin
exit;
end;
end;
end;
end;
procedure TRxDBGrid.DoSetColEdtBtn;
var
R:TRxColumn;
i, w:integer;
SB:TGraphicControl;
begin
R:=SelectedColumn as TRxColumn;
if Assigned(Editor) and Assigned(R) then
begin
W:=0;
for i:=0 to R.EditButtons.Count-1 do
begin
if R.EditButtons[i].Visible and R.EditButtons[i].Enabled then
W:=W+R.EditButtons[i].Width;
end;
if W>0 then
begin
if Editor.Name = 'ButtonEditor' then
begin
Editor.Left:=Editor.Left - W;
W:=Editor.Width + Editor.Left;
end
else
begin
Editor.Width:=Editor.Width - W;
W:=Editor.Width + Editor.Left;
end;
for i:=0 to R.EditButtons.Count-1 do
if R.EditButtons[i].Visible and R.EditButtons[i].Enabled then
begin
if R.EditButtons[i].Style = ebsUpDownRx then
begin
SB:=R.EditButtons[i].FSpinBtn;
TRxSpinButton(SB).FocusControl:=Editor;
end
else
SB:=R.EditButtons[i].FButton;
SB.Parent:=Self;
SB.Left:=W;
SB.Top:=Editor.Top;
SB.Height:=Editor.Height;
SB.Visible:=true;
W:=W+R.EditButtons[i].Width;
end;
end;
end;
end;
procedure TRxDBGrid.AddTools(ATools: TRxDBGridAbstractTools);
var
i:integer;
R: TMenuItem;
begin
if not Assigned(ATools) then Exit;
for i:=8 to F_PopupMenu.Items.Count - 1 do
if F_PopupMenu.Items[i].Tag = IntPtr(ATools) then
exit;
R := TMenuItem.Create(F_PopupMenu);
F_PopupMenu.Items.Add(R);
R.Caption := ATools.FCaption;
R.OnClick := @(ATools.ExecTools);
R.Tag:=IntPtr(ATools);
R.Enabled:=ATools.Enabled;
if Assigned(FToolsList) and (FToolsList.IndexOf(ATools)<0) then
FToolsList.Add(ATools);
end;
procedure TRxDBGrid.RemoveTools(ATools: TRxDBGridAbstractTools);
var
i:integer;
R: TMenuItem;
begin
for i:=8 to F_PopupMenu.Items.Count - 1 do
if F_PopupMenu.Items[i].Tag = IntPtr(ATools) then
begin
R:=F_PopupMenu.Items[i];
F_PopupMenu.Items.Delete(i);
R.Free;
exit;
end;
if Assigned(FToolsList) then
FToolsList.Remove(ATools);
end;
procedure TRxDBGrid.UpdateToolsState(ATools: TRxDBGridAbstractTools);
var
i: Integer;
begin
if not Assigned(ATools) then Exit;
for i:=8 to F_PopupMenu.Items.Count - 1 do
if F_PopupMenu.Items[i].Tag = IntPtr(ATools) then
begin
F_PopupMenu.Items[i].Enabled:=ATools.Enabled;
exit;
end;
end;
procedure TRxDBGrid.OnDataSetScrolled(aDataSet: TDataSet; Distance: Integer);
begin
if Assigned(FSaveOnDataSetScrolled) then
FSaveOnDataSetScrolled(aDataSet, Distance);
if (rdgWordWrap in FOptionsRx) or (FGroupItems.Active) then
UpdateRowsHeight;
end;
function TRxDBGrid.GetFieldDisplayText(AField: TField; ACollumn: TRxColumn
): string;
var
J: Integer;
begin
Result:='';
if Assigned(AField) then
begin
if AField.dataType <> ftBlob then
begin
{$IF lcl_fullversion >= 1090000}
if CheckDisplayMemo(AField) then
Result := AField.AsString
else
{$ENDIF}
Result := AField.DisplayText;
if Assigned(ACollumn) and (ACollumn.KeyList.Count > 0) and (ACollumn.PickList.Count > 0) then
begin
J := ACollumn.KeyList.IndexOf(Result);
if (J >= 0) and (J < ACollumn.PickList.Count) then
Result := ACollumn.PickList[j];
end;
end
else
Result := FColumnDefValues.FBlobText;
end
end;
function CompareDates(List: TStringList; Index1, Index: Integer): Integer;
var
d1, d2: TDateTime;
begin
TryStrToDateTime(List[Index1], d1);
TryStrToDateTime(List[Index], d2);
Result := -CompareDate(d1, d2);
end;
(*
function CompareIntegers(List: TStringList; Index1, Index: Integer): Integer;
var
d1, d2: Extended;
begin
TryStrToFloat(List[Index1], d1);
TryStrToFloat(List[Index], d2);
Result := -CompareValue(d1, d2);
end;
*)
procedure TRxDBGrid.FillFilterData;
var
i: Integer;
C: TRxColumn;
FBS, FAS: TDataSetNotifyEvent;
begin
for i := 0 to Columns.Count - 1 do
begin
C := TRxColumn(Columns[i]);
C.Filter.ValueList.SortStyle := sslAuto;
C.Filter.ValueList.Clear;
C.Filter.CurrentValues.Clear;
C.Filter.ManulEditValue:='';
C.Filter.ItemIndex := -1;
end;
if DatalinkActive then
begin
DataSource.DataSet.DisableControls;
DataSource.DataSet.Filtered := True;
FBS:=DataSource.DataSet.BeforeScroll;
FAS:=DataSource.DataSet.AfterScroll;
DataSource.DataSet.BeforeScroll:=nil;
DataSource.DataSet.AfterScroll:=nil;
DataSource.DataSet.First;
while not DataSource.DataSet.EOF do
begin
for i := 0 to Columns.Count - 1 do
begin
C := TRxColumn(Columns[i]);
if C.Filter.Enabled and (C.Field <> nil) and (C.Filter.ValueList.IndexOf(C.Field.DisplayText) < 0) then
C.Filter.ValueList.Add(C.Field.DisplayText);
end;
DataSource.DataSet.Next;
end;
DataSource.DataSet.First;
DataSource.DataSet.BeforeScroll:=FBS;
DataSource.DataSet.AfterScroll:=FAS;
DataSource.DataSet.EnableControls;
end;
for i := 0 to Columns.Count - 1 do
begin
C := TRxColumn(Columns[i]);
if Assigned(C.Field) and (C.Field.DataType in DataTimeTypes) then
begin
C.Filter.ValueList.SortStyle := sslUser;
C.Filter.ValueList.CustomSort(@CompareDates);
end
{ else
if Assigned(C.Field) and (C.Field.DataType in NumericDataTypes) then
begin
C.Filter.ValueList.SortStyle := sslUser;
C.Filter.ValueList.CustomSort(@CompareIntegers);
end};
C.Filter.ValueList.SortStyle := sslNone;
C.Filter.ValueList.Insert(0, C.Filter.AllValue);
C.Filter.ValueList.Insert(0, C.Filter.EmptyValue);
end;
end;
procedure TRxDBGrid.DefaultDrawCellA(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState);
begin
PrepareCanvas(aCol, aRow, aState);
if rdgFilter in OptionsRx then
begin
DefaultDrawFilter(aCol, aRow, getFilterRect(aRect), aState);
DefaultDrawTitle(aCol, aRow, getTitleRect(aRect), aState);
end
else
DefaultDrawTitle(aCol, aRow, aRect, aState);
end;
procedure TRxDBGrid.DefaultDrawTitle(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState);
procedure DoClearMLIInvalid(MLI1: TMLCaptionItem);
begin
while Assigned(MLI1) do
begin
inc(MLI1.FInvalidDraw);
MLI1:=MLI1.Next;
end;
end;
var
ASortMarker: TSortMarker;
ASortPosition: integer;
Background: TColor;
i: integer;
Down: boolean;
aRect2: TRect;
FTitle: TRxColumnTitle;
GrdCol: TRxColumn;
MLI : TMLCaptionItem;
begin
if (dgIndicator in Options) and (aCol = 0) then
begin
Canvas.FillRect(aRect);
if F_Clicked then
aState := aState + [gdPushed];
if (TitleStyle = tsNative) then
DrawThemedCell(aCol, aRow, aRect, aState)
else
DrawCellGrid(aCol, aRow, aRect, aState);
if DatalinkActive and (rdgAllowToolMenu in FOptionsRx) then
Canvas.Draw((ARect.Left + ARect.Right - F_MenuBMP.Width) div 2,
(ARect.Top + ARect.Bottom - F_MenuBMP.Height) div 2, F_MenuBMP);
exit;
end;
GrdCol := TRxColumn(ColumnFromGridColumn(aCol));
Down := FPressed and (dgHeaderPushedLook in Options) and
(FPressedCol = GrdCol);
if Assigned(GrdCol) then
begin
ASortMarker := GrdCol.FSortOrder;
if FSortColumns.Count>1 then
ASortPosition:=GrdCol.FSortPosition
else
ASortPosition:=-1;
end
else
ASortMarker := smNone;
if Assigned(FOnGetBtnParams) and Assigned(GetFieldFromGridColumn(aCol)) then
begin
Background := Canvas.Brush.Color;
FOnGetBtnParams(Self, GetFieldFromGridColumn(aCol), Canvas.Font,
Background, ASortMarker, Down);
Canvas.Brush.Color := Background;
end;
if (gdFixed in aState) and (aRow = 0) and (ACol >= FixedCols) then
begin
//GrdCol := ColumnFromGridColumn(aCol);
if Assigned(GrdCol) then
FTitle := TRxColumnTitle(GrdCol.Title)
else
FTitle := nil;
if Assigned(FTitle) then
begin
if FTitle.Orientation <> toHorizontal then
begin
OutCaptionCellText90(aCol, aRow, aRect, aState, FTitle.Caption,
FTitle.Orientation);
if Down then
aState := aState + [gdPushed];
end
else
if (FTitle.CaptionLinesCount > 0) then
begin
aRect2.Left := aRect.Left;
aRect2.Right := aRect.Right;
aRect2.Top := aRect.Top;
for i := 0 to FTitle.CaptionLinesCount - 1 do
begin
MLI := FTitle.CaptionLine(i);
aRect2.Right := aRect.Right;
if i = FTitle.CaptionLinesCount - 1 then
begin
aRect2.Bottom := aRect.Bottom;
aRect.Top := ARect2.Top;
if Down then
aState := aState + [gdPushed]
else
aState := aState - [gdPushed]
;
end
else
begin
aRect2.Bottom := aRect2.Top + MLI.Height * GetDefaultRowHeight;
aState := aState - [gdPushed];
end;
if Assigned(MLI.Next) then
begin
if Assigned(MLI.Prior) then
begin
if aCol = LeftCol then
begin
OutCaptionMLCellText(aCol, aRow, aRect2, aState, MLI);
DoClearMLIInvalid(MLI);
end
else
Dec(MLI.FInvalidDraw);
end
else
begin
OutCaptionMLCellText(aCol, aRow, aRect2, aState, MLI);
DoClearMLIInvalid(MLI);
end;
end
else
begin
if not Assigned(MLI.Prior) then
begin
OutCaptionCellText(aCol, aRow, aRect2, aState, MLI.Caption);
DoClearMLIInvalid(MLI);
end
else
begin
if aCol = LeftCol then
begin
OutCaptionMLCellText(aCol, aRow, aRect2, aState, MLI);
DoClearMLIInvalid(MLI);
end
else
Dec(MLI.FInvalidDraw);
end;
end;
aRect2.Top := aRect2.Bottom;
end;
end
else
begin
if Down then
aState := aState + [gdPushed];
OutCaptionCellText(aCol, aRow, aRect, aState, FTitle.Caption);
end;
end
else
begin
OutCaptionCellText(aCol, aRow, aRect, aState, GetDefaultColumnTitle(aCol));
end;
OutCaptionSortMarker(aRect, ASortMarker, ASortPosition+1);
end
else
begin
if Down then
aState := aState + [gdPushed];
OutCaptionCellText(aCol, aRow, aRect, aState, '');
end;
end;
procedure TRxDBGrid.DefaultDrawFilter(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState);
var
bg: TColor;
al: TAlignment;
ft: TFont;
MyCol: integer;
TxS: TTextStyle;
S: String;
begin
if (dgIndicator in Options) and (aCol = 0) then
begin
if (TitleStyle = tsNative) then
DrawThemedCell(aCol, aRow, aRect, aState)
else
begin
Canvas.FillRect(aRect);
DrawCellGrid(aCol, aRow, aRect, aState);
end;
exit;
end;
if (TitleStyle = tsNative) then
DrawThemedCell(aCol, aRow, aRect, aState)
else
begin
Canvas.FillRect(aRect);
DrawCellGrid(aCol, aRow, aRect, aState);
end;
Inc(aRect.Left, 1);
Dec(aRect.Right, 1);
Inc(aRect.Top, 1);
Dec(aRect.Bottom, 1);
if Columns.Count > (aCol - ord(dgIndicator in Options)) then
begin
bg := Canvas.Brush.Color;
al := Canvas.TextStyle.Alignment;
// ft := Canvas.Font;
ft:=TFont.Create;
ft.Assign(Canvas.Font);
TxS := Canvas.TextStyle;
MyCol := Columns.RealIndex(aCol - ord(dgIndicator in Options));
with TRxColumn(Columns[MyCol]).Filter do
begin
if (TitleStyle <> tsNative) then
begin
Canvas.Brush.Color := Color;
Canvas.FillRect(aRect);
end;
S:=DisplayFilterValue;
if (aRect.Right - aRect.Left) >= Canvas.TextWidth(S) then
TxS.Alignment := Alignment
else
TxS.Alignment := taLeftJustify;
Canvas.TextStyle := TxS;
if State in [rxfsEmpty, rxfsNonEmpty] then
Canvas.Font := TRxColumn(Columns[MyCol]).Filter.EmptyFont;
DrawCellText(aCol, aRow, aRect, aState, S);
(*
if CurrentValues.Count > 0 then
begin
S:=CurrentValues[0];
if CurrentValues.Count > 1 then
S:=S + '(...)';
Canvas.Font := Font;
if (aRect.Right - aRect.Left) >= Canvas.TextWidth(S) then
TxS.Alignment := Alignment
else
TxS.Alignment := taLeftJustify;
Canvas.TextStyle := TxS;
DrawCellText(aCol, aRow, aRect, aState, S);
end
else
begin
if (Style in (rxfstManualEdit, rxfstBoth)) and (ManulEditValue<>'') then
S:=ManulEditValue
else
if State = rxfsEmpty then
S:=Filter.EmptyValue
else
if State = rxfsNonEmpty then
S:=Filter.NotEmptyValue
else
if State = rxfsAll then
S:=Filter.AllValue
else
S:='';
Canvas.Font := TRxColumn(Columns[MyCol]).Filter.EmptyFont;
if (aRect.Right - aRect.Left) >= Canvas.TextWidth(S) then
TxS.Alignment := Alignment
else
TxS.Alignment := taLeftJustify;
Canvas.TextStyle := TxS;
DrawCellText(aCol, aRow, aRect, aState, S)
end; *)
end;
// Canvas.Font := ft;
Canvas.Font.Assign(ft);
ft.Free;
Canvas.Brush.Color := bg;
// Canvas.TextStyle.Alignment := al;
TxS.Alignment := al;
Canvas.TextStyle := TxS;
end
else
begin
bg := Canvas.Brush.Color;
Canvas.Brush.Color := Color;
Canvas.FillRect(aRect);
Canvas.Brush.Color := bg;
end;
end;
procedure TRxDBGrid.DefaultDrawCellData(aCol, aRow: integer; aRect: TRect;
aState: TGridDrawState);
var
S: string;
F: TField;
C: TRxColumn;
j, DataCol, L, R: integer;
FIsMerged: Boolean;
(*
function CheckBoxHeight(const aState: TCheckboxState):integer;
const
arrtb:array[TCheckboxState] of TThemedButton = (tbCheckBoxUncheckedNormal, tbCheckBoxCheckedNormal, tbCheckBoxMixedNormal);
var
Details: TThemedElementDetails;
CSize: TSize;
ChkBitmap: TBitmap;
begin
if (TitleStyle=tsNative) and not assigned(OnUserCheckboxBitmap) then
begin
Details := ThemeServices.GetElementDetails(arrtb[AState]);
CSize := ThemeServices.GetDetailSize(Details);
//CSize.cx := MulDiv(CSize.cx, Font.PixelsPerInch, Screen.PixelsPerInch);
Result := MulDiv(CSize.cy, Font.PixelsPerInch, Screen.PixelsPerInch);
end
else
begin
ChkBitmap := GetImageForCheckBox(aCol, aRow, AState);
if ChkBitmap<>nil then
Result:=ChkBitmap.Height
else
Result:=DefaultRowHeight;
end;
end;
*)
begin
FIsMerged:=false;
C:=nil;
F:=nil;
if rdgColSpanning in OptionsRx then
if IsMerged(aCol, L, R, C) then
begin
aCol:=L;
FIsMerged:=true;
end;
if Assigned(OnDrawColumnCell) and not (CsDesigning in ComponentState) then
begin
DataCol := ColumnIndexFromGridColumn(aCol);
if not Assigned(C) then
C:=TRxColumn(ColumnFromGridColumn(aCol));
OnDrawColumnCell(Self, aRect, DataCol, C, aState)
end
else
begin
if not Assigned(C) then
C := ColumnFromGridColumn(aCol) as TRxColumn;
if Assigned(C) then
F:=C.Field;
if Assigned(C) and Assigned(C.FOnDrawColumnCell) then
C.OnDrawColumnCell(Self, aRect, aCol, TColumn(ColumnFromGridColumn(aCol)), aState)
else
begin
case ColumnEditorStyle(aCol, F) of
cbsCheckBoxColumn:
(* begin
if C.Layout = tlTop then
aRect.Bottom:=aRect.Top + CheckBoxHeight(cbChecked) + varCellPadding + 1
else
if C.Layout = tlBottom then
aRect.Top:=aRect.Bottom - CheckBoxHeight(cbChecked) - varCellPadding - 1;
DrawCheckBoxBitmaps(aCol, aRect, F);
end*)
DrawCheckBoxBitmaps(aCol, aRect, F);
//DrawGridCheckboxBitmaps(aCol, aRect, F);
else
S:=GetFieldDisplayText(F, C);
if ((rdgWordWrap in FOptionsRx) and Assigned(C) and (C.WordWrap)) or (FIsMerged) then
WriteTextHeader(Canvas, aRect, S, C.Alignment)
else
DrawCellText(aCol, aRow, aRect, aState, S);
end;
end;
end;
end;
procedure TRxDBGrid.DrawCell(aCol, aRow: integer; aRect: TRect; aState: TGridDrawState);
var
RxColumn, C: TRxColumn;
AImageIndex: integer;
FBackground: TColor;
gRect: TRect;
begin
if (gdFixed in aState) and (aRow = 0) then
begin
DefaultDrawCellA(aCol, aRow, aRect, aState);
end
else
if not ((gdFixed in aState) or ((aCol = 0) and (dgIndicator in Options)) or
((aRow = 0) and (dgTitles in Options))) then
begin
if rdgColSpanning in OptionsRx then
CalcCellExtent(acol, arow, aRect);
PrepareCanvas(aCol, aRow, aState);
if FGroupItems.Active and Assigned(FGroupItemDrawCur) then
begin
gRect:=aRect;
aRect.Bottom:=aRect.Bottom - DefaultRowHeight - 1;
gRect.Top:=aRect.Bottom;
gRect.Bottom:=gRect.Bottom - 2;
end;
if Assigned(FOnGetCellProps) and not (gdSelected in aState) then
begin
FBackground := Canvas.Brush.Color;
FOnGetCellProps(Self, GetFieldFromGridColumn(aCol), Canvas.Font, FBackground);
Canvas.Brush.Color := FBackground;
end;
Canvas.FillRect(aRect);
DrawCellGrid(aCol, aRow, aRect, aState);
RxColumn := TRxColumn(ColumnFromGridColumn(aCol));
if Assigned(RxColumn) and Assigned(RxColumn.Field) and
Assigned(RxColumn.ImageList) then
begin
AImageIndex := StrToIntDef(RxColumn.KeyList.Values[RxColumn.Field.AsString],
RxColumn.NotInKeyListIndex);
if (AImageIndex > -1) and (AImageIndex < RxColumn.ImageList.Count) then
DrawCellBitmap(RxColumn, aRect, aState, AImageIndex);
end
else
DefaultDrawCellData(aCol, aRow, aRect, aState)
;
if FGroupItems.Active and Assigned(FGroupItemDrawCur) then
begin
C := ColumnFromGridColumn(aCol) as TRxColumn;
if C.FGroupParam.Color <> clNone then
Canvas.Brush.Color := C.FGroupParam.Color
else
if FGroupItems.Color <> clNone then
Canvas.Brush.Color := FGroupItems.Color
else
Canvas.Brush.Color := Color;
Canvas.Font.Color:=Font.Color;
Canvas.FillRect(gRect);
if C.FGroupParam.FValueType <> fvtNon then
WriteTextHeader(Canvas, gRect, C.FGroupParam.DisplayText, C.FGroupParam.Alignment);
end;
end
else
inherited DrawCell(aCol, aRow, aRect, aState);
end;
procedure TRxDBGrid.LinkActive(Value: Boolean);
var
S: string;
Pos: integer;
begin
if Value then
begin
S := DataSource.DataSet.ClassName;
if RxDBGridSortEngineList.Find(S, Pos) then
FSortEngine := RxDBGridSortEngineList.Objects[Pos] as TRxDBGridSortEngine
else
FSortEngine := nil;
end;
inherited LinkActive(Value);
if not Value then
begin
FSortEngine := nil;
if SelectedRows.Count > 0 then
SelectedRows.Clear;
end;
if not FSortingNow then
CollumnSortListClear;
if not (csDesigning in ComponentState) then
SetDBHandlers(Value);
end;
procedure TRxDBGrid.SetDBHandlers(Value: boolean);
begin
if Value then
begin
if DataSource.DataSet.OnFilterRecord <> @FilterRec then
begin
F_EventOnFilterRec := DataSource.DataSet.OnFilterRecord;
DataSource.DataSet.OnFilterRecord := @FilterRec;
end;
if DataSource.DataSet.BeforeDelete <> @BeforeDel then
begin
F_EventOnBeforeDelete := DataSource.DataSet.BeforeDelete;
DataSource.DataSet.BeforeDelete := @BeforeDel;
end;
if DataSource.DataSet.BeforePost <> @BeforePo then
begin
F_EventOnBeforePost := DataSource.DataSet.BeforePost;
DataSource.DataSet.BeforePost := @BeforePo;
end;
if DataSource.DataSet.OnDeleteError <> @ErrorDel then
begin
F_EventOnDeleteError := DataSource.DataSet.OnDeleteError;
DataSource.DataSet.OnDeleteError := @ErrorDel;
end;
if DataSource.DataSet.OnPostError <> @ErrorPo then
begin
F_EventOnPostError := DataSource.DataSet.OnPostError;
DataSource.DataSet.OnPostError := @ErrorPo;
end;
CalcStatTotals;
if rdgFilter in OptionsRx then
begin
FillFilterData;
//OnFilter(nil);
end;
end
else
begin
if Assigned(DataSource) and Assigned(DataSource.DataSet) then
begin
DataSource.DataSet.OnFilterRecord := F_EventOnFilterRec;
F_EventOnFilterRec := nil;
DataSource.DataSet.BeforeDelete := F_EventOnBeforeDelete;
F_EventOnBeforeDelete := nil;
DataSource.DataSet.BeforePost := F_EventOnBeforePost;
F_EventOnBeforePost := nil;
DataSource.DataSet.OnDeleteError := F_EventOnDeleteError;
F_EventOnDeleteError := nil;
DataSource.DataSet.OnPostError := F_EventOnPostError;
F_EventOnPostError := nil;
if rdgFilter in OptionsRx then
begin
FillFilterData;
//OnFilter(nil);
end;
end;
F_LastFilter.Clear;
end;
end;
procedure TRxDBGrid.DrawRow(ARow: Integer);
var
P: TBookMark;
begin
FGroupItemDrawCur:=nil;
if FGroupItems.Active and DatalinkActive then
begin
if (ARow>=FixedRows) then
begin
DataLink.ActiveRecord:=ARow-FixedRows;
P:=DataSource.DataSet.Bookmark;
FGroupItemDrawCur:=FGroupItems.FindGroupItem(P);
end;
end;
inherited DrawRow(ARow);
end;
procedure TRxDBGrid.DrawFocusRect(aCol, aRow: Integer; ARect: TRect);
begin
CalcCellExtent(acol, arow, aRect);
CalcCellExtent(ACol, ARow, ARect);
if FGroupItems.Active and Assigned(FGroupItemDrawCur) then
ARect.Bottom:=ARect.Bottom - DefaultRowHeight;
inherited DrawFocusRect(aCol, aRow, ARect);
end;
procedure TRxDBGrid.DrawFooterRows;
var
FooterRect: TRect;
R: TRect;
TotalYOffs: integer;
TotalWidth: integer;
i: integer;
C: TRxColumn;
Background: TColor;
ClipArea: Trect;
TxS: TTextStyle;
j: Integer;
FItem: TRxColumnFooterItem;
//FreeMan35 added
AText: String;
ABrush: TBrush;
begin
TotalWidth := GCache.ClientWidth;
//TotalYOffs := GCache.ClientHeight {- (GetDefaultRowHeight * FFooterOptions.RowCount)};
TotalYOffs := GCache.ClientRect.Bottom {- (GetDefaultRowHeight * FFooterOptions.RowCount)};
FooterRect := Rect(0, TotalYOffs, TotalWidth, TotalYOffs + GetDefaultRowHeight * FFooterOptions.RowCount);
Background := Canvas.Brush.Color;
Canvas.Brush.Color := Color;
Canvas.FillRect(FooterRect);
R.Top := TotalYOffs;
R.Bottom := TotalYOffs + GetDefaultRowHeight * FFooterOptions.RowCount;
Canvas.Brush.Color := FFooterOptions.FColor;
if (Columns.Count > 0) then
begin
TxS := Canvas.TextStyle;
if FFooterOptions.FDrawFullLine then
begin
ColRowToOffset(True, True, 0, R.Left, R.Right);
Canvas.Pen.Color := GridLineColor;
Canvas.MoveTo(R.Right - 1, R.Top);
Canvas.LineTo(R.Right - 1, RowHeights[0]);
end;
ABrush := nil;//initialize, no need create everytime.
R.Top := TotalYOffs;
R.Bottom := TotalYOffs + GetDefaultRowHeight;
for j:=0 to FFooterOptions.RowCount-1 do
begin
for i := GCache.VisibleGrid.Left to GCache.VisibleGrid.Right do
begin
ColRowToOffset(True, True, i, R.Left, R.Right);
if FFooterOptions.FDrawFullLine then
begin
Canvas.MoveTo(R.Right - 1, R.Top);
Canvas.LineTo(R.Right - 1, RowHeights[0]);
end;
C := ColumnFromGridColumn(i) as TRxColumn;
if Assigned(C) then
begin
FItem:=nil;
if (J = 0) then
begin
if (C.Footers.Count = 0) then
FItem:=C.Footer
else
FItem:=C.Footers[0];
end
else
if J <= C.Footers.Count-1 then
FItem:=C.Footers[j];
if Assigned(FItem) then
begin
TxS.Alignment := FItem.Alignment;
TxS.Layout := FItem.Layout;
Canvas.TextStyle := TxS;
if not FItem.IsDefaultFont then
Canvas.Font:=FItem.Font
else
Canvas.Font:=Font;
if FItem.Color <> clNone then
Canvas.Brush.Color:=FItem.Color
else
Canvas.Brush.Color:=FFooterOptions.FColor;
if not Assigned(OnRxColumnFooterDraw) then
begin
Canvas.FillRect(R);
DrawCellGrid(i, 0, R, []);
DrawCellText(i, 0, R, [], FItem.DisplayText);
end
else
begin
if not Assigned(ABrush)then
ABrush := TBrush.Create;
ABrush.Assign(Canvas.Brush);//Backup Brush info
AText := FItem.DisplayText;
OnRxColumnFooterDraw(Self, Canvas.Brush, Canvas.Font, R, C, AText);
Canvas.FillRect(R);//need repaint cell
DrawCellGrid(i, 0, R, []);//need reDraw cell
DrawCellText(i, 0, R, [], AText);
Canvas.Brush.Assign(ABrush);//Restore Brush info
end;
end
else
begin
Canvas.FillRect(R);
DrawCellGrid(i, 0, R, []);
end;
end
else
begin
Canvas.FillRect(R);
DrawCellGrid(i, 0, R, []);
end;//Assigned(C)
end;
R.Top := R.Bottom;
R.Bottom := R.Bottom + GetDefaultRowHeight;
end;
if assigned(ABrush)then FreeAndNil(ABrush);
if FFooterOptions.FDrawFullLine then
begin
Canvas.MoveTo(FooterRect.Left, FooterRect.Top);
Canvas.LineTo(R.Right, FooterRect.Top);
end;
ClipArea := Canvas.ClipRect;
for i := 0 to FixedCols - 1 do
begin
ColRowToOffset(True, True, i, R.Left, R.Right);
if FFooterOptions.FStyle = tsNative then
DrawThemedCell(i, 0, R, [gdFixed])
else
DrawCellGrid(i, 0, R, [gdFixed]);
if ((R.Left < ClipArea.Right) and (R.Right > ClipArea.Left)) then
DefaultDrawTitle(i, 0, getTitleRect(R), [gdFixed]);
end;
end;
Canvas.Brush.Color := Background;
end;
procedure TRxDBGrid.DoTitleClick(ACol: longint; ACollumn: TRxColumn;
Shift: TShiftState);
begin
if FAutoSort and (ACollumn.Field <> nil) then
begin
if ssCtrl in Shift then
begin
if ACollumn.FSortOrder <> smNone then
begin
if ACollumn.FSortOrder = smUp then
ACollumn.FSortOrder := smDown
else
begin
ACollumn.FSortOrder := smNone;
ACollumn.FSortPosition:=0;
end;
end
else
begin
ACollumn.FSortOrder := smUp;
ACollumn.FSortPosition:=FSortColumns.Count;
end;
end
else
begin
if (FSortColumns.Count>0) and (FSortColumns[0] = ACollumn) then
begin
if Assigned(FSortEngine) then
begin
if FSortColumns[0].FSortOrder = smUp then
FSortColumns[0].FSortOrder := smDown
else
FSortColumns[0].FSortOrder := smUp;
end
else
begin
case ACollumn.FSortOrder of
smNone: ACollumn.FSortOrder := smUp;
smUp: ACollumn.FSortOrder := smDown;
smDown: ACollumn.FSortOrder := smNone;
end;
end;
end
else
begin
CollumnSortListClear;
ACollumn.FSortOrder := smUp;
end;
end;
CollumnSortListUpdate;
if Assigned(FSortEngine) then
CollumnSortListApply;
if Assigned(FOnSortChanged) then
begin
FSortingNow := True;
FOnSortChanged(Self);
FSortingNow := False;
end;
end
else
HeaderClick(True, ACol);
end;
procedure TRxDBGrid.MouseMove(Shift: TShiftState; X, Y: integer);
var
Cell: TGridCoord;
Rect: TRect;
begin
if FTracking then
TrackButton(X, Y);
inherited MouseMove(Shift, X, Y);
if (rdgFilter in OptionsRx) and (dgColumnResize in Options) and
(Cursor = crHSplit) then
begin
Cell := MouseCoord(X, Y);
Rect := getFilterRect(CellRect(Cell.x, Cell.y));
if (Cell.Y = 0) and (Cell.X >= Ord(dgIndicator in Options)) and (Rect.Top < Y) then
begin
Cursor := crDefault;
end;
end;
if FColumnResizing and (MouseToGridZone(X, Y) = gzFixedCols) then
begin
CalcTitle;
if FFooterOptions.Active and (dgColumnResize in Options) and (FFooterOptions.RowCount > 0) then
DrawFooterRows;
end;
end;
procedure TRxDBGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: integer);
var
Cell: TGridCoord;
Rect: TRect;
C:TRxColumn;
i: Integer;
begin
QuickUTF8Search := '';
Cell := MouseCoord(X, Y);
if FFilterColDlgButton.Visible then
FFilterColDlgButton.Hide;
if (DatalinkActive) and (DataSource.DataSet.State = dsBrowse) and
(Button = mbLeft) and (Cell.X = 0) and (Cell.Y = 0) and
(dgIndicator in Options) and (rdgAllowToolMenu in FOptionsRx) then
begin
F_Clicked := True;
InvalidateCell(0, 0);
end
else
if (Cell.Y = 0) and (Cell.X >= Ord(dgIndicator in Options)) then
begin
if (rdgFilter in OptionsRx) and DatalinkActive then
begin
Cell := MouseCoord(X, Y);
Rect := getFilterRect(CellRect(Cell.x, Cell.y));
if (Cell.Y = 0) and (Cell.X >= Ord(dgIndicator in Options)) and (Rect.Top < Y) then
begin
C:=TRxColumn (Columns[Columns.RealIndex(Cell.x - ord(dgIndicator in Options))]);
if (C.Filter.Enabled) and (C.Filter.ValueList.Count > 0) then
begin
if C.Filter.Style = rxfstSimple then
begin
if FFilterSimpleEdit.Visible then
FFilterSimpleEdit.Hide;
if FFilterColDlgButton.Visible then
FFilterColDlgButton.Hide;
FFilterListEditor.Style := csDropDownList;
if C.Filter.DropDownRows>0 then
FFilterListEditor.DropDownCount := C.Filter.DropDownRows;
FFilterListEditor.Parent := Self;
FFilterListEditor.Width := Rect.Right - Rect.Left;
FFilterListEditor.Height := Rect.Bottom - Rect.Top;
FFilterListEditor.BoundsRect := Rect;
FFilterListEditor.Items.Assign(C.Filter.ValueList);
if C.Filter.CurrentValues.Count>0 then
FFilterListEditor.Text := C.Filter.CurrentValues[0]
else
FFilterListEditor.Text := '';
FFilterListEditor.Show(Self, Cell.x - ord(dgIndicator in Options));
end
else
if C.Filter.Style = rxfstManualEdit then
begin
if FFilterListEditor.Visible then
FFilterListEditor.Hide;
if FFilterColDlgButton.Visible then
FFilterColDlgButton.Hide;
FFilterSimpleEdit.Parent := Self;
FFilterSimpleEdit.Width := Rect.Right - Rect.Left;
FFilterSimpleEdit.Height := Rect.Bottom - Rect.Top;
FFilterSimpleEdit.BoundsRect := Rect;
FFilterSimpleEdit.Show(Self, Cell.x - ord(dgIndicator in Options));
{ if C.Filter.CurrentValues.Count>0 then
FFilterSimpleEdit.Text := C.Filter.CurrentValues[C.Filter.CurrentValues.Count - 1]
else}
FFilterSimpleEdit.Text := C.Filter.ManulEditValue;
end
else
if C.Filter.Style = rxfstDialog then
begin
if FFilterListEditor.Visible then
FFilterListEditor.Hide;
if FFilterSimpleEdit.Visible then
FFilterSimpleEdit.Hide;
FFilterColDlgButton.Parent:=Self;
FFilterColDlgButton.Width := 32;
FFilterColDlgButton.Height := Rect.Bottom - Rect.Top;
FFilterColDlgButton.Top := Rect.Top;
FFilterColDlgButton.Left := Rect.Right - FFilterColDlgButton.Width;
FFilterColDlgButton.Show(Self, Cell.x - ord(dgIndicator in Options));
end
else
if C.Filter.Style = rxfstBoth then
begin
if FFilterListEditor.Visible then
FFilterListEditor.Hide;
FFilterColDlgButton.Parent:=Self;
FFilterColDlgButton.Width := 32;
FFilterColDlgButton.Height := Rect.Bottom - Rect.Top;
FFilterColDlgButton.Top := Rect.Top;
FFilterColDlgButton.Left := Rect.Right - FFilterColDlgButton.Width;
FFilterColDlgButton.Show(Self, Cell.x - ord(dgIndicator in Options));
FFilterSimpleEdit.Parent := Self;
FFilterSimpleEdit.Width := Rect.Right - Rect.Left - FFilterColDlgButton.Width;
FFilterSimpleEdit.Height := Rect.Bottom - Rect.Top;
Rect.Width:=Rect.Width - FFilterColDlgButton.Width;
FFilterSimpleEdit.BoundsRect := Rect;
FFilterSimpleEdit.Show(Self, Cell.x - ord(dgIndicator in Options));
{ if C.Filter.CurrentValues.Count>0 then
FFilterSimpleEdit.Text := C.Filter.CurrentValues[0]
else}
FFilterSimpleEdit.Text := C.Filter.ManulEditValue;
end
end;
exit;
end;
end;
if dgColumnResize in Options then
begin
FColumnResizing := True;
end;
if FAutoSort then
begin
Cell := MouseCoord(X, Y);
if (Cell.Y = 0) and (Cell.X >= Ord(dgIndicator in Options)) then
begin
if (dgColumnResize in Options) and (Button = mbRight) then
begin
Shift := Shift + [ssLeft];
inherited MouseDown(Button, Shift, X, Y);
end
else
if Button = mbLeft then
begin
if (MouseToGridZone(X, Y) = gzFixedCols) and
(dgColumnResize in Options) and (Cursor = crHSplit) then
begin
if (ssDouble in Shift) and (rdgDblClickOptimizeColWidth in FOptionsRx) then
begin
if Assigned(ColumnFromGridColumn(Cell.X)) then
TRxColumn(ColumnFromGridColumn(Cell.X)).OptimizeWidth;
end
else
inherited MouseDown(Button, Shift, X, Y);
end
else
begin
MouseCapture := True;
FTracking := True;
FPressedCol := TRxColumn(ColumnFromGridColumn(Cell.X));
TrackButton(X, Y);
inherited MouseDown(Button, Shift, X, Y);
end;
end;
end
else
begin
inherited MouseDown(Button, Shift, X, Y);
end;
end
else
begin
inherited MouseDown(Button, Shift, X, Y);
end;
end
else
begin
for i:=0 to FToolsList.Count-1 do
if (rxteMouseDown in TRxDBGridAbstractTools(FToolsList[i]).FToolsEvents) then
if TRxDBGridAbstractTools(FToolsList[i]).MouseDown(Button, Shift, X, Y) then
exit;
if rdgMrOkOnDblClik in FOptionsRx then
begin
if (Cell.Y > 0) and (Cell.X >= Ord(dgIndicator in Options)) and
(ssDouble in Shift) then
begin
if Owner is TCustomForm then
TCustomForm(Owner).ModalResult := mrOk;
end;
end;
inherited MouseDown(Button, Shift, X, Y);
end;
end;
procedure TRxDBGrid.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: integer);
var
Cell: TGridCoord;
ACol: longint;
DoClick: boolean;
ShowMenu: boolean;
MPT: TPoint;
Rct: TRect;
begin
ShowMenu := False;
FColumnResizing := False;
if (dgHeaderPushedLook in Options) and FTracking and (FPressedCol <> nil) then
begin
Cell := MouseCoord(X, Y);
DoClick := PtInRect(Rect(0, 0, ClientWidth, ClientHeight), Point(X, Y)) and
(Cell.Y < RowHeights[0]) and (FPressedCol = TRxColumn(ColumnFromGridColumn(Cell.X)));
StopTracking;
if DoClick then
begin
ACol := Cell.X;
if (dgIndicator in Options) then
Dec(ACol);
if DataLinkActive and (ACol >= 0) and (ACol < Columns.Count) then
begin
FPressedCol := TRxColumn(ColumnFromGridColumn(Cell.X));
if Assigned(FPressedCol) then
DoTitleClick(FPressedCol.Index, FPressedCol, Shift);
end;
end;
end
else
if FSwapButtons then
begin
FSwapButtons := False;
MouseCapture := False;
if Button = mbRight then
Button := mbLeft;
end;
if (DatalinkActive) and (DataSource.DataSet.State = dsBrowse) and
(rdgAllowToolMenu in FOptionsRx) then
begin
Cell := MouseCoord(X, Y);
if ((Button = mbLeft) and (Cell.X = 0) and (Cell.Y = 0) and
(dgIndicator in Options)) or (F_Clicked) then
begin
F_Clicked := False;
InvalidateCell(0, 0);
ShowMenu := True;
Button := mbRight;
end;
end;
inherited MouseUp(Button, Shift, X, Y);
if (DatalinkActive) and (DataSource.DataSet.State = dsBrowse) and (ShowMenu) then
begin
Rct := CellRect(0, 0);
MPT.X := Rct.Left;
if rdgFilter in FOptionsRx then
MPT.Y := Rct.Bottom - GetDefaultRowHeight
else
MPT.Y := Rct.Bottom;
MPT := ClientToScreen(MPT);
UpdateJMenuStates;
F_PopupMenu.Popup(MPT.X, MPT.Y);
end;
end;
procedure TRxDBGrid.SetQuickUTF8Search(AValue: string);
var
ClearSearchValue: boolean;
OldSearchString: string;
begin
if (rdgAllowQuickSearch in OptionsRx) then
begin
OldSearchString := Self.FQuickUTF8Search;
if (OldSearchString <> AValue) and Assigned(Self.FBeforeQuickSearch) then
Self.FBeforeQuickSearch(Self, SelectedField, AValue);
if OldSearchString <> AValue then
begin
ClearSearchValue := True;
if (Length(AValue) > 0) and (Self.DatalinkActive) then
begin
if (DataSource.DataSet.State = dsBrowse) and
(not (DataSource.DataSet.EOF and DataSource.DataSet.BOF)) then
begin
//1.Вызываем процедурку поиска...
if DataSetLocateThrough(Self.DataSource.DataSet,
Self.SelectedField.FieldName, AValue, FSearchOptions.FQuickSearchOptions, rsdAll, FSearchOptions.FFromStart) then
Self.FQuickUTF8Search := AValue;
ClearSearchValue := False;
end;
end;
if ClearSearchValue then
begin
Self.FQuickUTF8Search := '';
end;
if (OldSearchString <> Self.FQuickUTF8Search) and
Assigned(Self.FAfterQuickSearch) then
Self.FAfterQuickSearch(Self, SelectedField, OldSearchString);
end;
end;
//TODO: сделать отображение ищущейся буквы/строки.
end;
procedure TRxDBGrid.UTF8KeyPress(var UTF8Key: TUTF8Char);
var
CheckUp: boolean;
begin
inherited UTF8KeyPress(UTF8Key);
if ReadOnly then
begin
//0. Проверяем что это кнопка значащая, увеличиваем "строку поиска"
if Length(UTF8Key) = 1 then
begin
//DebugLn('Ord Of Key:',IntToStr(Ord(UTF8Key[1])));
CheckUp := not (Ord(UTF8Key[1]) in CBadQuickSearchSymbols);
end
else
CheckUp := True;
// DebugLn('RxDBGrid.UTF8KeyPress check',IfThen(CheckUp,'True','False'),'INIT UTF8Key= ',UTF8Key,' Selected Field: ', Self.SelectedField.FieldName);
if CheckUp then
QuickUTF8Search := QuickUTF8Search + Trim(UTF8Key);
end;
end;
procedure TRxDBGrid.KeyDown(var Key: word; Shift: TShiftState);
procedure DoShowFindDlg;
begin
if not (rdgAllowDialogFind in OptionsRx) then
exit;
if Length(QuickUTF8Search) > 0 then
QuickUTF8Search := '';
ShowFindDialog;
end;
procedure DoShowColumnsDlg;
begin
if not (rdgAllowColumnsForm in OptionsRx) then
exit;
if Length(QuickUTF8Search) > 0 then
QuickUTF8Search := '';
ShowColumnsDialog;
end;
procedure DoShowQuickFilter;
begin
if not (rdgAllowQuickFilter in FOptionsRx) then
exit;
OnFilter(Self);
end;
begin
if (Key in CCancelQuickSearchKeys) then
if Length(QuickUTF8Search) > 0 then
QuickUTF8Search := '';
inherited KeyDown(Key, Shift);
if Key <> 0 then
begin
case FKeyStrokes.FindRxCommand(Key, Shift) of
rxgcShowFindDlg: DoShowFindDlg;
rxgcShowColumnsDlg: DoShowColumnsDlg;
rxgcShowFilterDlg: OnFilterBy(Self);
rxgcShowQuickFilter: DoShowQuickFilter;
rxgcHideQuickFilter: OnFilterClose(Self);
rxgcShowSortDlg: OnSortBy(Self);
rxgcSelectAll: SelectAllRows;
rxgcDeSelectAll: DeSelectAllRows;
rxgcInvertSelection:InvertSelection;
rxgcOptimizeColumnsWidth:OptimizeColumnsWidthAll;
rxgcCopyCellValue:OnCopyCellValue(Self);
else
exit;
end;
Key := 0;
end;
end;
procedure TRxDBGrid.KeyPress(var Key: char);
begin
inherited KeyPress(Key);
if Assigned(SelectedColumn) and Assigned(SelectedColumn.Field) and (SelectedColumn.Field.DataType in [ftFloat, ftCurrency]) and
(coFixDecimalSeparator in TRxColumn(SelectedColumn).Options) then
if (Key in [',', '.']) then
Key:=DefaultFormatSettings.DecimalSeparator
end;
function TRxDBGrid.CreateColumns: TGridColumns;
begin
Result := TRxDbGridColumns.Create(Self, TRxColumn);
end;
procedure TRxDBGrid.DrawCellBitmap(RxColumn: TRxColumn; aRect: TRect;
aState: TGridDrawState; AImageIndex: integer);
var
ClientSize: TSize;
H, W: integer;
begin
InflateRect(aRect, -1, -1);
H := RxColumn.ImageList.Height;
W := RxColumn.ImageList.Width;
ClientSize.cx := Min(aRect.Right - aRect.Left, W);
ClientSize.cy := Min(aRect.Bottom - aRect.Top, H);
if ClientSize.cx = W then
begin
aRect.Left := (aRect.Left + aRect.Right - W) div 2;
aRect.Right := aRect.Left + W;
end;
if ClientSize.cy = H then
begin
aRect.Top := (aRect.Top + aRect.Bottom - H) div 2;
aRect.Bottom := aRect.Top + H;
end;
RxColumn.ImageList.Draw(Canvas, aRect.Left, aRect.Top, AImageIndex);
end;
procedure TRxDBGrid.SetEditText(ACol, ARow: longint; const Value: string);
var
C: TRxColumn;
j, L, R: integer;
S: string;
begin
C:=nil;
if (rdgColSpanning in OptionsRx) then
if IsMerged(aCol, L, R, C) then
aCol:=L;
if not Assigned(C) then
C := ColumnFromGridColumn(aCol) as TRxColumn;
S := Value;
if Assigned(C) and (C.KeyList.Count > 0) and (C.PickList.Count > 0) then
begin
J := C.PickList.IndexOf(S);
if (J >= 0) and (J < C.KeyList.Count) then
S := C.KeyList[j];
end;
inherited SetEditText(ACol, ARow, S);
end;
procedure TRxDBGrid.ColRowMoved(IsColumn: boolean; FromIndex, ToIndex: integer);
begin
inherited ColRowMoved(IsColumn, FromIndex, ToIndex);
if IsColumn then
CalcTitle;
end;
procedure TRxDBGrid.Paint;
var
P:TPoint;
begin
Inc(FInProcessCalc);
DoClearInvalidTitle;
inherited Paint;
DoDrawInvalidTitle;
if FFooterOptions.Active and (FFooterOptions.RowCount > 0) then
DrawFooterRows;
Dec(FInProcessCalc);
end;
procedure TRxDBGrid.MoveSelection;
begin
inherited MoveSelection;
(* if Assigned(FFooterOptions) and FFooterOptions.Active and (FFooterOptions.RowCount > 0) then
DrawFooterRows; *)
end;
function TRxDBGrid.GetBufferCount: integer;
var
H, H1:integer;
i: LongInt;
begin
{ Result := ClientHeight div DefaultRowHeight;
if dgTitles in Options then
Dec(Result, 1);}
if GetDefaultRowHeight > 0 then
begin
H:=ClientHeight;
if FFooterOptions.Active then
H:=H - GetDefaultRowHeight * FFooterOptions.RowCount;
Result := H div GetDefaultRowHeight;
if rdgFilter in OptionsRx then
Dec(Result, 1);
if dgTitles in Options then
//Dec(Result, 1);
Result:=Result - RowHeights[0] div GetDefaultRowHeight;
end
else
Result := 1;
end;
procedure TRxDBGrid.CMHintShow(var Message: TLMessage);
var
Cell: TGridCoord;
tCol: TRxColumn;
HintStr_: string;
Processed: boolean;
rec: integer;
CellRect_: TRect;
begin
if Assigned(TCMHintShow(Message).HintInfo) then
begin
with TCMHintShow(Message).HintInfo^ do
begin
Cell := MouseCoord(CursorPos.X, CursorPos.Y);
tCol := TRxColumn(ColumnFromGridColumn(Cell.X));
if (Cell.Y = 0) and (Cell.X >= Ord(dgIndicator in Options)) then
begin
if Assigned(tCol) and (TRxColumnTitle(tCol.Title).Hint <> '') and
(TRxColumnTitle(tCol.Title).FShowHint) then
HintStr := TRxColumnTitle(tCol.Title).Hint;
end
else
if Cell.X >= Ord(dgIndicator in Options) then
begin
CellRect_ := CellRect(Cell.X, Cell.Y);
if (CellRect_.Bottom > CursorPos.Y) and (CellRect_.Right > CursorPos.X) then
if Assigned(FOnDataHintShow) then
begin
rec := DataLink.ActiveRecord;
try
DataLink.ActiveRecord := Cell.y - 1;
HintStr_ := tCol.Field.DisplayText;
finally
DataLink.ActiveRecord := rec;
end;
Processed := False;
FOnDataHintShow(Self, CursorPos, Cell, tCol, HintStr_, Processed);
if Processed then
HintStr := HintStr_;
end;
end;
end;
end;
inherited CMHintShow(Message);
end;
procedure TRxDBGrid.FFilterListEditorOnChange(Sender: TObject);
begin
FFilterListEditor.Hide;
with TRxColumn(Columns[Columns.RealIndex(FFilterListEditor.Col)]).Filter do
begin
if (FFilterListEditor.Text = EmptyValue) then
begin
ClearFilter;
{ CurrentValues.Clear;
State:=rxfsEmpty;}
end
else
if (FFilterListEditor.Text = AllValue) {or (FFilterListEditor.Text = '')} then
begin
ClearFilter;
State:=rxfsAll;
end
else
begin
ClearFilter;
CurrentValues.Add(FFilterListEditor.Text);
State:=rxfsFilter;
end;
end;
DataSource.DataSet.DisableControls;
DataSource.DataSet.Filtered:=false;
DataSource.DataSet.Filtered:=true;
CalcStatTotals;
DataSource.DataSet.EnableControls;
if Assigned(FOnFiltred) then
FOnFiltred(Self);
end;
procedure TRxDBGrid.FFilterListEditorOnCloseUp(Sender: TObject);
begin
FFilterListEditor.Hide;
FFilterListEditor.Changed;
SetFocus;
end;
procedure TRxDBGrid.FFilterColDlgButtonOnClick(Sender: TObject);
var
RxDBGrid_PopUpFilterForm: TRxDBGrid_PopUpFilterForm;
R, P: TPoint;
FRxCol: TRxColumn;
FRect: TRect;
begin
FRxCol:=TRxColumn(Columns[Columns.RealIndex(FFilterColDlgButton.Col)]);
RxDBGrid_PopUpFilterForm:=TRxDBGrid_PopUpFilterForm.CreatePopUpFilterForm(FRxCol);
P:=Point(FFilterColDlgButton.Left, FFilterColDlgButton.Top + FFilterColDlgButton.Width);
if RxDBGrid_PopUpFilterForm.Width < FRxCol.Width then
P.X:=FFilterColDlgButton.Left + FFilterColDlgButton.Width - RxDBGrid_PopUpFilterForm.Width
else
P.X:=FFilterColDlgButton.Left + FFilterColDlgButton.Width - FRxCol.Width;
R:=ClientToScreen(P);
if R.X + RxDBGrid_PopUpFilterForm.Width > Screen.Width then
R.X:=Screen.Width - RxDBGrid_PopUpFilterForm.Width;
RxDBGrid_PopUpFilterForm.Left:=R.X;
RxDBGrid_PopUpFilterForm.Top:=R.Y;
RxDBGrid_PopUpFilterForm.ShowModal;
RxDBGrid_PopUpFilterForm.Free;
end;
procedure TRxDBGrid.FFilterSimpleEditOnChange(Sender: TObject);
begin
with TRxColumn(Columns[Columns.RealIndex(FFilterSimpleEdit.Col)]).Filter do
begin
if (FFilterSimpleEdit.Text = '') and (Style = rxfstManualEdit) then
begin
CurrentValues.Clear;
State:=rxfsAll;
end
else
State:=rxfsFilter;
ManulEditValue:=FFilterSimpleEdit.Text;
end;
DataSource.DataSet.DisableControls;
DataSource.DataSet.Filtered:=false;
DataSource.DataSet.Filtered:=true;
CalcStatTotals;
DataSource.DataSet.EnableControls;
if Assigned(FOnFiltred) then
FOnFiltred(Self);
end;
procedure TRxDBGrid.InternalOptimizeColumnsWidth(AColList: TList);
var
P: TBookmark;
i, W, n: integer;
WA: PIntegerArray;
S: string;
begin
GetMem(WA, SizeOf(integer) * AColList.Count);
for I := 0 to AColList.Count - 1 do
begin
if TRxColumnTitle(TRxColumn(AColList[i]).Title).CaptionLinesCount > 1 then
WA^[i] := Max(Canvas.TextWidth(
TRxColumnTitle(TRxColumn(AColList[i]).Title).CaptionLine(
TRxColumnTitle(TRxColumn(AColList[i]).Title).CaptionLinesCount -
1).Caption) + 8, 20)
else
WA^[i] := Max(Canvas.TextWidth(TRxColumn(AColList[i]).Title.Caption) + 8, 20);
end;
with DataSource.DataSet do
begin
DisableControls;
P := GetBookmark;
First;
try
while not EOF do
begin
for I := 0 to AColList.Count - 1 do
begin
(*
if Assigned(TRxColumn(AColList[i]).Field) then
S := TRxColumn(AColList[i]).Field.DisplayText
else
S:='';
with TRxColumn(AColList[i]) do
if (KeyList.Count > 0) and (PickList.Count > 0) then
begin
n := KeyList.IndexOf(S);
if (n <> -1) and (n < PickList.Count) then
S := PickList.Strings[n];
end; *)
S:=GetFieldDisplayText(TRxColumn(AColList[i]).Field, TRxColumn(AColList[i]));
W := Canvas.TextWidth(S) + 6;
if WA^[i] < W then
WA^[i] := W;
end;
Next;
end;
finally
GotoBookmark(p);
FreeBookmark(p);
EnableControls;
end;
end;
for I := 0 to AColList.Count - 1 do
if WA^[i] > 0 then
TRxColumn(AColList[i]).Width := WA^[i];
FreeMem(WA, SizeOf(integer) * AColList.Count);
end;
procedure TRxDBGrid.VisualChange;
var
P: TPoint;
begin
CalcTitle;
if FFooterOptions.Active and (FFooterOptions.RowCount > 0) then
begin
P:=GCache.MaxClientXY;
with GCache do
MaxClientXY.Y:=MaxClientXY.Y - (GetDefaultRowHeight * FFooterOptions.RowCount + 2);
end;
if ((rdgWordWrap in FOptionsRx) or (Assigned(FGroupItems) and FGroupItems.Active)) and (HandleAllocated) then
UpdateRowsHeight;
inherited VisualChange;
end;
procedure TRxDBGrid.EditorWidthChanged(aCol, aWidth: Integer);
var
R:TRect;
begin
inherited EditorWidthChanged(aCol, aWidth);
if FFilterListEditor.Visible then
begin
R:=CellRect(FFilterListEditor.Col+1,0);
FFilterListEditor.Width:=Columns[FFilterListEditor.Col].Width;
FFilterListEditor.Left:=R.Left;
end
else
if FFilterSimpleEdit.Visible then
begin
R:=CellRect(FFilterSimpleEdit.Col+1,0);
FFilterSimpleEdit.Width:=Columns[FFilterSimpleEdit.Col].Width;
FFilterSimpleEdit.Left:=R.Left;
end
else
if FFilterColDlgButton.Visible then
begin
R:=CellRect(FFilterColDlgButton.Col+1,0);
FFilterColDlgButton.Left := R.Right - FFilterColDlgButton.Width;
end;
end;
function TRxDBGrid.EditorByStyle(Style: TColumnButtonStyle): TWinControl;
var
F: TField;
begin
if Style = cbsAuto then
begin
F := SelectedField;
if Assigned(F) then
begin
if Assigned(F.LookupDataSet) and (F.LookupKeyFields <> '') and
(F.LookupResultField <> '') and (F.KeyFields <> '') then
begin
Result := FRxDbGridLookupComboEditor;
exit;
end
else
if F.DataType in [ftDate, ftDateTime] then
begin
Result := FRxDbGridDateEditor;
exit;
end;
end;
end;
Result := inherited EditorByStyle(Style);
if (Style = cbsPickList) and (Result is TCustomComboBox) then
begin
if TRxColumn(SelectedColumn).DirectInput then
TCustomComboBox(Result).Style:=csDropDown
else
TCustomComboBox(Result).Style:=csDropDownList;
end;
end;
procedure TRxDBGrid.CalcStatTotals;
var
{$IFDEF NoAutomatedBookmark}
P_26: TBookmark;
{$ENDIF}
P: TBookmark;
i, cnt: integer;
APresent: boolean;
DHS:THackDataSet;
SaveState:TDataSetState;
SavePos:integer;
SaveActiveRecord:integer;
SaveAfterScroll:TDataSetNotifyEvent;
SaveBeforeScroll:TDataSetNotifyEvent;
C:TRxColumn;
AValue:Variant;
FCList, FCList2:TFPList;
j: Integer;
F: TRxColumnFooterItem;
S: String;
begin
if (not (DatalinkActive and (FGroupItems.Active or FFooterOptions.Active))) or (Columns.Count = 0) or (gsAddingAutoColumns in GridStatus) then
Exit;
if Assigned(OnRxCalcFooterValues)then
begin
Inc(FInProcessCalc);
for C in Columns do
begin
C.Footer.ResetTestValue;
AValue:=Null;
OnRxCalcFooterValues(Self, C, AValue);
if AValue<>null then C.Footer.FTestValue := AValue;
end;
Dec(FInProcessCalc);
Exit;
end;
APresent := False;
for C in Columns do
begin
APresent := (C.Footer.FValueType in [fvtSum, fvtAvg, fvtMax, fvtMin, fvtCount]) {or (C.FGroupItems.Active)};
if not APresent then
begin
for F in C.Footers do
begin
APresent:=F.FValueType in [fvtSum, fvtAvg, fvtMax, fvtMin, fvtCount];
if APresent then
break;
end;
end
else
break;
end;
if (not APresent) and (not FGroupItems.Active) then Exit;
Inc(FInProcessCalc);
cnt:=0;
if FGroupItems.Active then FGroupItems.Clear;
for C in Columns do
begin
C.Footer.ResetTestValue;
for F in C.Footers do F.ResetTestValue;
end;
if (DataSource.DataSet.RecordCount<=0) then
begin
Dec(FInProcessCalc);
exit;
end;
DHS:=THackDataSet(DataSource.DataSet);
{$IFDEF NoAutomatedBookmark}
P:=DataSource.DataSet.GetBookmark;
{$ELSE}
P := DHS.Bookmark;
{$ENDIF}
SaveState:=DHS.SetTempState(dsBrowse);
SaveAfterScroll:=DHS.AfterScroll;
SaveBeforeScroll:=DHS.BeforeScroll;
DHS.AfterScroll:=nil;
DHS.BeforeScroll:=nil;
SaveActiveRecord:=Datalink.ActiveRecord;
Datalink.ActiveRecord:=0;
SavePos:=DHS.RecNo;
FCList:=TFPList.Create;
FCList2:=TFPList.Create;
for C in Columns do
begin
if (C.Footer.ValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and C.Visible then
begin
FCList.Add(C);
C.Footer.FField:=DHS.FieldByName(C.Footer.FieldName);
end;
for F in C.Footers do
begin
if (F.ValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and C.Visible then
begin
if FCList.IndexOf(C) < 0 then
FCList.Add(C);
F.FField:=DHS.FieldByName(F.FieldName);
end;
end;
if FGroupItems.Active then
if C.FGroupParam.ValueType <> fvtNon then
FCList2.Add(C);
end;
DHS.First;
if FGroupItems.Active then
FGroupItems.InitGroup;
while not DHS.EOF do
begin
for i:=0 to FCList.Count-1 do
begin
C:=TRxColumn(FCList[i]);
if (C.FFooter.FValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and Assigned(C.FFooter.FField) then
C.FFooter.UpdateTestValueFromVar(C.FFooter.FField.AsVariant);
for F in C.FFooters do
begin
if (F.FValueType in [fvtSum, fvtAvg, fvtMax, fvtMin]) and Assigned(F.FField) then
F.UpdateTestValueFromVar( F.FField.AsVariant)
end;
end;
if FGroupItems.Active then
begin
FGroupItems.UpdateValues;
for i:=0 to FCList2.Count-1 do
TRxColumn(FCList2[i]).FGroupParam.UpdateValues;
end;
inc(cnt);
DHS.Next;
end;
//calc agregate values
for C in Columns do
begin
if C.Footer.ValueType = fvtCount then
C.FFooter.FCountRec:=Cnt
else
if C.Footer.ValueType = fvtAvg then
C.FFooter.FTestValue:=C.FFooter.FTestValue / Cnt;
for F in C.Footers do
begin
if F.ValueType = fvtCount then
F.FCountRec:=Cnt
else
if F.ValueType = fvtAvg then
F.FTestValue:=F.FTestValue / Cnt;
end;
end;
if FGroupItems.Active then
FGroupItems.DoneGroup;
FCList2.Free;
FCList.Free;
//Restore cursor position
if Min(Datalink.RecordCount + SavePos - 1, DHS.RecNo) > 0 then
DHS.RecNo := Min(Datalink.RecordCount + SavePos - 1, DHS.RecNo);
while not DHS.BOF do
begin
if SavePos = DHS.RecNo then
break;
DHS.Prior;
end;
for i:=0 to Columns.Count-1 do
TRxColumn(Columns[i]).Footer.FField:=nil;
Datalink.ActiveRecord:=SaveActiveRecord;
DHS.RestoreState(SaveState);
DHS.AfterScroll := SaveAfterScroll;
DHS.BeforeScroll := SaveBeforeScroll;
{$IFDEF NoAutomatedBookmark}
P_26:=DHS.GetBookmark;
if DHS.CompareBookmarks(P_26, P)<>0 then
DHS.GotoBookmark(P); //workaround for fix navigation problem
DHS.FreeBookmark(P);
DHS.FreeBookmark(P_26);
{$ELSE}
if DHS.BookmarkValid(P) and (DHS.CompareBookmarks(DHS.Bookmark, P)<>0) then
DHS.Bookmark:=P; //workaround for fix navigation problem
{$ENDIF}
Dec(FInProcessCalc);
if FInProcessCalc < 0 then
FInProcessCalc := 0;
end;
procedure TRxDBGrid.OptimizeColumnsWidth(AColList: string);
var
ColList: TList;
procedure DoFillColList;
var
L: integer;
begin
L := Pos(';', AColList);
while L > 0 do
begin
if AColList <> '' then
ColList.Add(ColumnByFieldName(Copy(AColList, 1, L - 1)));
Delete(AColList, 1, L);
L := Pos(';', AColList);
end;
if AColList <> '' then
ColList.Add(ColumnByFieldName(AColList));
end;
begin
if (not DatalinkActive) or (Columns.Count = 0) then
Exit;
ColList := TList.Create;
DoFillColList;
InternalOptimizeColumnsWidth(ColList);
ColList.Free;
if Assigned(OnColumnSized) then
OnColumnSized(Self);
end;
procedure TRxDBGrid.OptimizeColumnsWidthAll;
var
ColList: TList;
i: integer;
begin
if (not DatalinkActive) or (Columns.Count = 0) then
Exit;
ColList := TList.Create;
for i := 0 to Columns.Count - 1 do
ColList.Add(Columns[i]);
InternalOptimizeColumnsWidth(ColList);
ColList.Free;
end;
procedure TRxDBGrid.UpdateTitleHight;
begin
CalcTitle;
end;
procedure TRxDBGrid.FilterRec(DataSet: TDataSet; var Accept: boolean);
var
i: integer;
Filter: TRxColumnFilter;
F: TField;
begin
Accept := True;
for i := 0 to Columns.Count - 1 do
begin
Filter:=TRxColumn(Columns[i]).Filter;
F:=TRxColumn(Columns[i]).Field;
if Filter.State = rxfsAll then
Accept:=true
else
if Filter.State = rxfsEmpty then
Accept:=F.IsNull
else
if Filter.State = rxfsNonEmpty then
Accept:=not F.IsNull
else
{ if Filter.State = rxfsTopXXXX then
begin
if DataSet.State = dsFilter then
Accept:=true
else
Accept:=DataSet.RecNo < Filter.TopRecord;
if not Accept then
Break;
end
else}
begin
if Filter.CurrentValues.Count > 0 then
Accept := Filter.CurrentValues.IndexOf(F.DisplayText) >= 0;
if Accept and (Filter.Style in [rxfstBoth, rxfstManualEdit]) and (Filter.ManulEditValue<>'') then
Accept := UTF8Pos(UTF8UpperCase(Filter.ManulEditValue), UTF8UpperCase(F.DisplayText)) > 0;
if not Accept then
Break;
end;
end;
if Assigned(F_EventOnFilterRec) then
F_EventOnFilterRec(DataSet, Accept);
end;
procedure TRxDBGrid.BeforeDel(DataSet: TDataSet);
var
i: integer;
begin
if FFooterOptions.Active and (DatalinkActive) then
for i := 0 to Columns.Count - 1 do
if not TRxColumn(Columns[i]).Footer.DeleteTestValue then
begin
FInProcessCalc := -1;
Break;
end;
if Assigned(F_EventOnBeforeDelete) then
F_EventOnBeforeDelete(DataSet);
end;
procedure TRxDBGrid.BeforePo(DataSet: TDataSet);
var
i: integer;
C:TRxColumn;
begin
if DatalinkActive then
begin
if FooterOptions.Active then
for i := 0 to Columns.Count - 1 do
begin
if not TRxColumn(Columns[i]).Footer.PostTestValue then
begin
FInProcessCalc := -1;
Break;
end;
end;
if rdgFilter in OptionsRx then
for i := 0 to Columns.Count - 1 do
begin
C:=TRxColumn(Columns[i]);
if Assigned(C.Field) and (C.Filter.ValueList.IndexOf(C.Field.DisplayText)< 0) then
C.Filter.ValueList.Add(C.Field.DisplayText);
end;
end;
if Assigned(F_EventOnBeforePost) then
F_EventOnBeforePost(DataSet);
end;
procedure TRxDBGrid.ErrorDel(DataSet: TDataSet; E: EDatabaseError;
var DataAction: TDataAction);
var
i: integer;
begin
if FFooterOptions.Active and (DatalinkActive) then
for i := 0 to Columns.Count - 1 do
if not TRxColumn(Columns[i]).Footer.ErrorTestValue then
begin
FInProcessCalc := -1;
Break;
end;
if Assigned(F_EventOnDeleteError) then
F_EventOnDeleteError(DataSet, E, DataAction);
end;
procedure TRxDBGrid.ErrorPo(DataSet: TDataSet; E: EDatabaseError;
var DataAction: TDataAction);
var
i: integer;
begin
if FFooterOptions.Active and (DatalinkActive) then
for i := 0 to Columns.Count - 1 do
if not TRxColumn(Columns[i]).Footer.ErrorTestValue then
begin
FInProcessCalc := -1;
Break;
end;
if Assigned(F_EventOnPostError) then
F_EventOnPostError(DataSet, E, DataAction);
end;
procedure TRxDBGrid.OnFind(Sender: TObject);
begin
if rdgAllowDialogFind in OptionsRx then
ShowFindDialog;
end;
procedure TRxDBGrid.OnFilterBy(Sender: TObject);
var
NewFilter: string;
begin
if DataLinkActive then
begin
OptionsRx := OptionsRx - [rdgFilter];
rxFilterByForm := TrxFilterByForm.Create(Application);
NewFilter := DataSource.DataSet.Filter;
if rxFilterByForm.Execute(Self, NewFilter, F_LastFilter) then
begin
if NewFilter <> '' then
begin
DataSource.DataSet.Filter := NewFilter;
DataSource.DataSet.Filtered := True;
end
else
begin
DataSource.DataSet.Filtered := False;
end;
CalcStatTotals;
end;
FreeAndNil(rxFilterByForm);
end;
end;
procedure TRxDBGrid.OnFilter(Sender: TObject);
var
C: TRxColumn;
i: integer;
FBS, FAS:TDataSetNotifyEvent;
begin
BeginUpdate;
OptionsRx := OptionsRx + [rdgFilter];
{
for i := 0 to Columns.Count - 1 do
begin
C := TRxColumn(Columns[i]);
C.Filter.ValueList.Clear;
C.Filter.CurrentValues.Clear;
C.Filter.ManulEditValue:='';
C.Filter.ItemIndex := -1;
C.Filter.ValueList.Add(C.Filter.EmptyValue);
C.Filter.ValueList.Add(C.Filter.AllValue);
end;
if DatalinkActive then
begin
DataSource.DataSet.DisableControls;
DataSource.DataSet.Filtered := True;
FBS:=DataSource.DataSet.BeforeScroll;
FAS:=DataSource.DataSet.AfterScroll;
DataSource.DataSet.BeforeScroll:=nil;
DataSource.DataSet.AfterScroll:=nil;
DataSource.DataSet.First;
while not DataSource.DataSet.EOF do
begin
for i := 0 to Columns.Count - 1 do
begin
C := TRxColumn(Columns[i]);
if C.Filter.Enabled and (C.Field <> nil) and (C.Filter.ValueList.IndexOf(C.Field.DisplayText) < 0) then
C.Filter.ValueList.Add(C.Field.DisplayText);
end;
DataSource.DataSet.Next;
end;
DataSource.DataSet.First;
DataSource.DataSet.BeforeScroll:=FBS;
DataSource.DataSet.AfterScroll:=FAS;
DataSource.DataSet.EnableControls;
end;
}
EndUpdate;
end;
procedure TRxDBGrid.OnFilterClose(Sender: TObject);
begin
OptionsRx := OptionsRx - [rdgFilter];
DataSource.DataSet.Filtered := False;
CalcStatTotals;
end;
procedure TRxDBGrid.OnSortBy(Sender: TObject);
var
i: integer;
S1: string;
FSortListField:TStringList;
FColumn:TRxColumn;
begin
if DatalinkActive then
begin
FSortListField:=TStringList.Create;
try
rxSortByForm := TrxSortByForm.Create(Application);
rxSortByForm.CheckBox1.Checked := rdgCaseInsensitiveSort in FOptionsRx;
if rxSortByForm.Execute(Self, FSortListField) then
begin
for i := 0 to FSortListField.Count - 1 do
begin
S1:=FSortListField.Strings[i];
FColumn:=TRxColumn(ColumnByFieldName(Copy(S1, 2, Length(S1))));
if S1[1] = '1' then
FColumn.FSortOrder := smUp
else
FColumn.FSortOrder := smDown;
FColumn.FSortPosition:=i;
end;
CollumnSortListUpdate;
if rxSortByForm.CheckBox1.Checked then
Include(FOptionsRx, rdgCaseInsensitiveSort)
else
Exclude(FOptionsRx, rdgCaseInsensitiveSort);
CollumnSortListApply;
if Assigned(FOnSortChanged) then
begin
FSortingNow := True;
FOnSortChanged(Self);
FSortingNow := False;
end;
end;
finally
FreeAndNil(rxSortByForm);
FreeAndNil(FSortListField);
end;
Invalidate;
end;
end;
procedure TRxDBGrid.OnChooseVisibleFields(Sender: TObject);
begin
if rdgAllowColumnsForm in OptionsRx then
ShowColumnsDialog;
end;
procedure TRxDBGrid.OnSelectAllRows(Sender: TObject);
begin
SelectAllRows;
end;
procedure TRxDBGrid.OnCopyCellValue(Sender: TObject);
var
P:TBookMark;
S:string;
i, k, j:integer;
begin
if DatalinkActive then
begin
if (dgMultiselect in Options) and (SelectedRows.Count>1) then
begin
S:='';
DataSource.DataSet.DisableControls;
{$IFDEF NoAutomatedBookmark}
P:=DataSource.DataSet.GetBookmark;
{$ELSE}
P:=DataSource.DataSet.Bookmark;
{$ENDIF}
try
for j:=0 to SelectedRows.Count-1 do
begin
DataSource.DataSet.Bookmark:=SelectedRows[j];
if S<>'' then
S:=S+LineEnding;
K:=0;
for i:=0 to Columns.Count-1 do
begin
if Assigned(Columns[i].Field) then
begin
if K<>0 then
S:=S+#9;
{$IF lcl_fullversion >= 1090000}
if CheckDisplayMemo(Columns[i].Field) then
S :=S + Columns[i].Field.AsString
else
{$ENDIF}
S:=S+Columns[i].Field.DisplayText;
inc(K);
end;
end;
end;
finally
{$IFDEF NoAutomatedBookmark}
DataSource.DataSet.GotoBookmark(P);
DataSource.DataSet.FreeBookmark(P);
{$ELSE}
DataSource.DataSet.Bookmark:=P;
{$ENDIF}
DataSource.DataSet.EnableControls;
end;
Invalidate;
if S<>'' then
begin
try
Clipboard.Open;
Clipboard.AsText:=S;
finally
Clipboard.Close;
end;
end;
end
(* else
if (dgMultiselect in Options) and (SelectedRows.Count>1) then
begin
S:='';
DataSource.DataSet.DisableControls;
{$IFDEF NoAutomatedBookmark}
P:=DataSource.DataSet.GetBookmark;
{$ELSE}
P:=DataSource.DataSet.Bookmark;
{$ENDIF}
try
DataSource.DataSet.First;
while not DataSource.DataSet.EOF do
begin
if S<>'' then
S:=S+LineEnding;
K:=0;
for i:=0 to Columns.Count-1 do
begin
if Assigned(Columns[i].Field) then
begin
if K<>0 then
S:=S+#9;
S:=S+Columns[i].Field.DisplayText;
inc(K);
end;
end;
DataSource.DataSet.Next;
end;
finally
{$IFDEF NoAutomatedBookmark}
DataSource.DataSet.GotoBookmark(P);
DataSource.DataSet.FreeBookmark(P);
{$ELSE}
DataSource.DataSet.Bookmark:=P;
{$ENDIF}
DataSource.DataSet.EnableControls;
end;
Invalidate;
if S<>'' then
begin
try
Clipboard.Open;
Clipboard.AsText:=S;
finally
Clipboard.Close;
end;
end;
end *)
else
if Assigned(SelectedField) then
try
Clipboard.Open;
{$IF lcl_fullversion >= 1090000}
if CheckDisplayMemo(SelectedField) then
Clipboard.AsText:=SelectedField.AsString
else
{$ENDIF}
Clipboard.AsText:=SelectedField.DisplayText;
finally
Clipboard.Close;
end;
end;
end;
procedure TRxDBGrid.OnOptimizeColWidth(Sender: TObject);
begin
OptimizeColumnsWidthAll;
end;
procedure TRxDBGrid.Loaded;
begin
inherited Loaded;
UpdateJMenuKeys;
end;
procedure TRxDBGrid.UpdateFooterRowOnUpdateActive;
begin
if Assigned(DataSource) then
begin
if DataSource.State <> FOldDataSetState then
begin
if (FOldDataSetState in dsEditModes) and (DataSource.State = dsBrowse) then
CalcStatTotals;
FOldDataSetState:=DataSource.State;
end;
end
else
FOldDataSetState:=dsInactive;
end;
procedure TRxDBGrid.DoEditorHide;
var
R:TRxColumn;
i:integer;
begin
inherited DoEditorHide;
R:=SelectedColumn as TRxColumn;
if Assigned(Editor) and Assigned(R) then
for i:=0 to R.EditButtons.Count-1 do
begin
if R.EditButtons[i].Style = ebsUpDownRx then
R.EditButtons[i].FSpinBtn.Visible:=false
else
R.EditButtons[i].FButton.Visible:=false;
end;
end;
procedure TRxDBGrid.DoEditorShow;
var
R, R1: TRect;
FSaveRow: Integer;
P: TBookMark;
FG: TColumnGroupItem;
begin
inherited DoEditorShow;
{ if FGroupItems.Active then
begin
if (Row>=FixedRows) then
begin
FSaveRow:=DataLink.ActiveRecord;
DataLink.ActiveRecord:=Row-FixedRows;
P:=DataSource.DataSet.Bookmark;
DataLink.ActiveRecord:=FSaveRow;
FG:=FGroupItems.FindGroupItem(P);
if Assigned(FG) then
begin
R:=CellRect(Col, Row);
Editor.SetBounds(R.Left, R.Top, R.Right - R.Left - 1, R.Bottom - R.Top - DefaultRowHeight - 1);
R1:=Editor.BoundsRect;
end;
end;
end; }
if rdgColSpanning in OptionsRx then
begin
if IsMerged(Col) then
begin
CalcCellExtent(Col, Row, R);
Editor.SetBounds(R.Left, R.Top, R.Right-R.Left-1, R.Bottom-R.Top-1);
end;
end;
DoSetColEdtBtn;
end;
procedure TRxDBGrid.CheckNewCachedSizes(var AGCache: TGridDataCache);
begin
inherited CheckNewCachedSizes(AGCache);
if FFooterOptions.Active then
begin
// AGCache.ClientHeight:=AGCache.ClientHeight - DefaultRowHeight * FFooterOptions.RowCount;
AGCache.ScrollHeight:=AGCache.ScrollHeight - DefaultRowHeight * FFooterOptions.RowCount;
AGCache.ClientRect.Bottom:=AGCache.ClientRect.Bottom - DefaultRowHeight * FFooterOptions.RowCount;
end;
end;
procedure TRxDBGrid.CalcCellExtent(ACol, ARow: Integer; var ARect: TRect);
var
L, T, R, B: Integer;
C: TRxColumn;
begin
if IsMerged(ACol, L, R, C) then
begin
ARect.TopLeft := CellRect(L, ARow).TopLeft;
ARect.BottomRight := CellRect(R, ARow).BottomRight;
end;
end;
function TRxDBGrid.IsMerged(ACol: Integer): Boolean;
var
L, R: Integer;
C: TRxColumn;
begin
Result := IsMerged(ACol, L, R, C);
end;
function TRxDBGrid.IsMerged(ACol: Integer; out ALeft, ARight: Integer; out
AColumn: TRxColumn): Boolean;
begin
Result := false;
AColumn:=nil;
ALeft := ACol;
ARight := ACol;
if (rdgColSpanning in OptionsRx) and Assigned(FOnMergeCells) then
begin
inc(FMergeLock);
FOnMergeCells(Self, ACol, ALeft, ARight, AColumn);
if ALeft > ARight then
SwapValues(ALeft, ARight);
Result := (ALeft <> ARight);
dec(FMergeLock);
end;
end;
function TRxDBGrid.GetEditMask(aCol, aRow: Longint): string;
var
L, R: Integer;
C: TRxColumn;
begin
if (rdgColSpanning in OptionsRx) then
if IsMerged(aCol, L, R, C) then
begin
if Assigned(C) then
aCol:=C.Index
else
aCol:=L;
end;
Result:=inherited GetEditMask(aCol, aRow);
end;
function TRxDBGrid.GetEditText(aCol, aRow: Longint): string;
var
R, L: Integer;
C: TRxColumn;
begin
if (rdgColSpanning in OptionsRx) then
if IsMerged(aCol, L, R, C) then
begin
if Assigned(C) then
aCol:=C.Index
else
aCol:=L;
end;
Result:=inherited GetEditText(aCol, aRow);
end;
function TRxDBGrid.GetDefaultEditor(Column: Integer): TWinControl;
var
L, R: Integer;
C: TRxColumn;
begin
if (rdgColSpanning in OptionsRx) then
if IsMerged(Column, L, R, C) then
begin
if Assigned(C) then
Column:=C.Index
else
Column:=L;
end;
Result:=inherited GetDefaultEditor(Column);
end;
procedure TRxDBGrid.PrepareCanvas(aCol, aRow: Integer; AState: TGridDrawState);
function IsCellButtonColumn(ACell: TPoint): boolean;
var
Column: TGridColumn;
begin
Column := ColumnFromGridColumn(ACell.X);
result := (Column<>nil) and (Column.ButtonStyle=cbsButtonColumn) and
(ACell.y>=FixedRows);
end;
var
L, R, RR: Integer;
C: TRxColumn;
begin
if (rdgColSpanning in OptionsRx) then
if not ((gdFixed in aState) and (aRow = 0)) then
if ((Row - FixedRows) = Datalink.ActiveRecord) and IsMerged(ACol, L, R, C) then
if (aCol >= L) and (aCol <= R) then
AState := AState + [gdSelected, gdFocused];
inherited PrepareCanvas(aCol, aRow, AState);
if (gdSelected in AState) then
begin
if not IsCellButtonColumn(point(aCol,aRow)) then
if not FIsSelectedDefaultFont then
begin
Canvas.Font:=FSelectedFont;
if FSelectedFont.Color = clDefault then
Canvas.Font.Color := clHighlightText;
end;
end;
end;
{$IFDEF DEVELOPER_RX}
type
THackDataLink = class(TDataLink)
end;
procedure TRxDBGrid.InternalAdjustRowCount(var RecCount: integer);
var
CurActiveRecord, j, H1, FRec, H, H2: Integer;
i: LongInt;
R: TRxColumn;
F: TField;
S: String;
begin
inherited InternalAdjustRowCount(RecCount);
if (not (Assigned(DataLink) and DataLink.Active)) or ((GCache.VisibleGrid.Top=0) and (GCache.VisibleGrid.Bottom=0)) then
exit;
CurActiveRecord:=DataLink.ActiveRecord;
if dgTitles in Options then
begin
FRec:=1;
H2:=1;
end
else
begin
FRec:=0;
H2:=0;
end;
for i:=GCache.VisibleGrid.Top to GCache.VisibleGrid.Bottom do
begin
DataLink.ActiveRecord:=i - FixedRows;
// P:=PtrInt(DataSource.DataSet.ActiveBuffer);
H:=1;
for j:=0 to Columns.Count-1 do
begin
R:=Columns[j] as TRxColumn;
if R.WordWrap then
begin
F:=R.Field;
if Assigned(F) then
S:=F.DisplayText
else
S:='';
H1 := Max((Canvas.TextWidth(S) + 2) div R.Width + 1, H);
if H1 > WordCount(S, [' ']) then
H1 := WordCount(S, [' ']);
end
else
H1:=1;
H:=Max(H, H1);
end;
{
if FGroupItems.Active and DatalinkActive then
if Assigned(FGroupItems.FindGroupItem(DataSource.DataSet.Bookmark)) then
Inc(H);
if i<RowCount then
begin
if Assigned(FOnCalcRowHeight) then
FOnCalcRowHeight(Self, H);
RowHeights[i] := GetDefaultRowHeight * H;
H2:=H2 + RowHeights[i];
if H2<=ClientHeight then
Inc(Result);
end;}
if H2 + H > RecCount then
begin
// RecCount:=FRec;
if (FRec < FixedRows + CurActiveRecord) {and (CurActiveRecord = DataLink.ActiveRecord)} then
begin
TopRow:=1;
// THackDataLink(DataLink).FirstRecord:=THackDataLink(DataLink).FirstRecord + 1;
{ H:=CurActiveRecord - DataLink.ActiveRecord;
THackDataLink(DataLink).FirstRecord:=THackDataLink(DataLink).FirstRecord + 1;
THackDataSet(DataLink.DataSet).RecalcBufListSize;}
// THackDataLink(DataLink).BufferCount:=FRec;
H:=0;
end;
// DataLink.BufferCount:=FRec;
// break;
end
else
begin
FRec:=FRec + 1;
H2:=H2 + H;
end;
end;
DataLink.ActiveRecord:=CurActiveRecord;
end;
{$ENDIF}
procedure TRxDBGrid.GetOnCreateLookup;
begin
if Assigned(F_CreateLookup) then
F_CreateLookup(FRxDbGridLookupComboEditor);
end;
procedure TRxDBGrid.GetOnDisplayLookup;
begin
if Assigned(F_DisplayLookup) then
F_DisplayLookup(FRxDbGridLookupComboEditor);
end;
procedure TRxDBGrid.SelectAllRows;
var
P:TBookMark;
begin
if DatalinkActive then
begin
DataSource.DataSet.DisableControls;
{$IFDEF NoAutomatedBookmark}
P:=DataSource.DataSet.GetBookmark;
{$ELSE}
P:=DataSource.DataSet.Bookmark;
{$ENDIF}
try
DataSource.DataSet.First;
while not DataSource.DataSet.EOF do
begin
SelectedRows.CurrentRowSelected:=true;
DataSource.DataSet.Next;
end;
finally
{$IFDEF NoAutomatedBookmark}
DataSource.DataSet.GotoBookmark(P);
DataSource.DataSet.FreeBookmark(P);
{$ELSE}
DataSource.DataSet.Bookmark:=P;
{$ENDIF}
DataSource.DataSet.EnableControls;
end;
Invalidate;
end;
end;
procedure TRxDBGrid.DeSelectAllRows;
var
P:TBookMark;
begin
if DatalinkActive then
begin
DataSource.DataSet.DisableControls;
{$IFDEF NoAutomatedBookmark}
P:=DataSource.DataSet.GetBookmark;
{$ELSE}
P:=DataSource.DataSet.Bookmark;
{$ENDIF}
try
DataSource.DataSet.First;
while not DataSource.DataSet.EOF do
begin
SelectedRows.CurrentRowSelected:=false;
DataSource.DataSet.Next;
end;
finally
{$IFDEF NoAutomatedBookmark}
DataSource.DataSet.GotoBookmark(P);
DataSource.DataSet.FreeBookmark(P);
{$ELSE}
DataSource.DataSet.Bookmark:=P;
{$ENDIF}
DataSource.DataSet.EnableControls;
end;
Invalidate;
end;
end;
procedure TRxDBGrid.InvertSelection;
var
P:TBookMark;
begin
if DatalinkActive then
begin
DataSource.DataSet.DisableControls;
{$IFDEF NoAutomatedBookmark}
P:=DataSource.DataSet.GetBookmark;
{$ELSE}
P:=DataSource.DataSet.Bookmark;
{$ENDIF}
try
DataSource.DataSet.First;
while not DataSource.DataSet.EOF do
begin
SelectedRows.CurrentRowSelected:=not SelectedRows.CurrentRowSelected;
DataSource.DataSet.Next;
end;
finally
{$IFDEF NoAutomatedBookmark}
DataSource.DataSet.GotoBookmark(P);
DataSource.DataSet.FreeBookmark(P);
{$ELSE}
DataSource.DataSet.Bookmark:=P;
{$ENDIF}
DataSource.DataSet.EnableControls;
end;
Invalidate;
end;
end;
procedure TRxDBGrid.CopyCellValue;
begin
OnCopyCellValue(Self);
end;
procedure TRxDBGrid.SetSort(AFields: array of String;
ASortMarkers: array of TSortMarker; PreformSort: Boolean);
var
I: Integer;
C: TRxColumn;
begin
CollumnSortListClear;
if (Length(AFields) > 0) and (Length(AFields) = Length(ASortMarkers)) then
begin
for I := 0 to Length(AFields) - 1 do
begin
C := ColumnByFieldName(AFields[I]);
if C <> nil then
begin
C.SortOrder := ASortMarkers[I];
C.FSortPosition := I;
end;
end;
CollumnSortListUpdate;
end;
if PreformSort then
begin
if Assigned(FSortEngine) then
CollumnSortListApply;
if Assigned(FOnSortChanged) then
begin
FSortingNow := True;
FOnSortChanged(Self);
FSortingNow := False;
end;
end;
end;
constructor TRxDBGrid.Create(AOwner: TComponent);
begin
FFooterOptions:=TRxDBGridFooterOptions.Create(Self);
inherited Create(AOwner);
{$IFDEF RXDBGRID_OPTIONS_WO_CANCEL_ON_EXIT}
Options := Options - [dgCancelOnExit];
{$ENDIF}
FSaveOnDataSetScrolled:=Datalink.OnDataSetScrolled;
Datalink.OnDataSetScrolled:=@OnDataSetScrolled;
FToolsList:=TFPList.Create;
FColumnDefValues:=TRxDBGridColumnDefValues.Create(Self);
FSearchOptions:=TRxDBGridSearchOptions.Create(Self);
FSortColumns:=TRxDbGridColumnsSortList.Create;
FGroupItems:=TColumnGroupItems.Create(Self);
F_MenuBMP := CreateResBitmap('rx_menu_grid');
Options := Options - [dgTabs];
// TDrawGrid(Self).Options:=TDrawGrid(Self).Options + [goColSpanning];
OptionsRx := OptionsRx + [rdgAllowColumnsForm, rdgAllowDialogFind, rdgAllowQuickFilter];
FAutoSort := True;
F_Clicked := False;
DoCreateJMenu;
FKeyStrokes := TRxDBGridKeyStrokes.Create(Self);
FKeyStrokes.ResetDefaults;
F_LastFilter := TStringList.Create;
FPropertyStorageLink := TPropertyStorageLink.Create;
FPropertyStorageLink.OnSave := @OnIniSave;
FPropertyStorageLink.OnLoad := @OnIniLoad;
FFilterListEditor := TFilterListCellEditor.Create(nil);
with FFilterListEditor do
begin
Name := 'FilterListEditor';
Visible := False;
Items.Append('');
ReadOnly := True;
AutoComplete := True;
OnChange := @FFilterListEditorOnChange;
OnCloseUp := @FFilterListEditorOnCloseUp;
end;
FFilterColDlgButton:=TFilterColDlgButton.Create(nil);
FFilterColDlgButton.Name := 'FilterColDlgButton';
FFilterColDlgButton.Visible := False;
FFilterColDlgButton.OnClick := @FFilterColDlgButtonOnClick;
FFilterColDlgButton.Glyph.Assign(FEllipsisRxBMP);
FFilterSimpleEdit:=TFilterSimpleEdit.Create(nil);
FFilterSimpleEdit.Name := 'FFilterSimpleEdit';
FFilterSimpleEdit.Visible := False;
FFilterSimpleEdit.OnChange := @FFilterSimpleEditOnChange;
FColumnResizing := False;
FRxDbGridLookupComboEditor := TRxDBGridLookupComboEditor.Create(nil);
FRxDbGridLookupComboEditor.Name := 'RxDBGridLookupComboEditor';
FRxDbGridLookupComboEditor.Visible := False;
FRxDbGridDateEditor := TRxDBGridDateEditor.Create(nil);
FRxDbGridDateEditor.Name := 'RxDbGridDateEditor';
FRxDbGridDateEditor.Visible := False;
FSelectedFont:=TFont.Create;
FSelectedFont.OnChange:=@SelectedFontChanged;
FillDefaultFonts;
UpdateJMenuKeys;
end;
destructor TRxDBGrid.Destroy;
begin
CleanDSEvent;
FreeAndNil(FSelectedFont);
FreeAndNil(FFilterSimpleEdit);
FreeAndNil(FFooterOptions);
FreeAndNil(FRxDbGridLookupComboEditor);
FreeAndNil(FRxDbGridDateEditor);
FreeAndNil(FPropertyStorageLink);
FreeAndNil(FFilterListEditor);
FreeAndNil(FFilterColDlgButton);
FreeAndNil(F_PopupMenu);
FreeAndNil(F_MenuBMP);
FreeAndNil(F_LastFilter);
FreeAndNil(FKeyStrokes);
FreeAndNil(FToolsList);
FreeAndNil(FColumnDefValues);
FreeAndNil(FSearchOptions);
FreeAndNil(FGroupItems);
inherited Destroy;
FreeAndNil(FSortColumns);
end;
procedure TRxDBGrid.LayoutChanged;
begin
if csDestroying in ComponentState then
exit;
inherited LayoutChanged;
if DatalinkActive and (FInProcessCalc = 0) and (Datalink.DataSet.State = dsBrowse) then
CalcStatTotals;
end;
procedure TRxDBGrid.SetFocus;
begin
inherited SetFocus;
if FFilterListEditor.Visible then
FFilterListEditor.Hide;
if FFilterColDlgButton.Visible then
FFilterColDlgButton.Hide;
end;
procedure TRxDBGrid.ShowFindDialog;
begin
ShowRxDBGridFindForm(Self);
end;
procedure TRxDBGrid.ShowColumnsDialog;
begin
ShowRxDBGridColumsForm(Self);
end;
procedure TRxDBGrid.ShowSortDialog;
begin
OnSortBy(nil);
end;
procedure TRxDBGrid.ShowFilterDialog;
begin
OnFilterBy(nil);
end;
function TRxDBGrid.ColumnByFieldName(AFieldName: string): TRxColumn;
var
i: integer;
begin
Result := nil;
AFieldName := UpperCase(AFieldName);
for i := 0 to Columns.Count - 1 do
begin
if UpperCase(Columns[i].FieldName) = AFieldName then
begin
Result := Columns[i] as TRxColumn;
exit;
end;
end;
end;
function TRxDBGrid.ColumnByCaption(ACaption: string): TRxColumn;
var
i: integer;
begin
Result := nil;
ACaption := UpperCase(ACaption);
for i := 0 to Columns.Count - 1 do
if ACaption = UpperCase(Columns[i].Title.Caption) then
begin
Result := TRxColumn(Columns[i]);
exit;
end;
end;
procedure TRxDBGrid.EraseBackground(DC: HDC);
begin
// The correct implementation is doing nothing
end;
function TRxDbGridColumns.GetColumn(Index: Integer): TRxColumn;
begin
Result:=TRxColumn( inherited Items[Index] );
end;
procedure TRxDbGridColumns.SetColumn(Index: Integer; AValue: TRxColumn);
begin
Items[Index].Assign( AValue );
end;
procedure TRxDbGridColumns.Notify(Item: TCollectionItem;
Action: TCollectionNotification);
begin
inherited Notify(Item, Action);
TRxDBGrid(Grid).CollumnSortListUpdate;
end;
{ TRxDbGridColumns }
function TRxDbGridColumns.Add: TRxColumn;
begin
Result := TRxColumn(inherited Add);
end;
function TRxDbGridColumns.GetEnumerator: TRxDbGridColumnsEnumerator;
begin
Result:=TRxDbGridColumnsEnumerator.Create(Self);
end;
{ TRxColumn }
function TRxColumn.GetKeyList: TStrings;
begin
if FKeyList = nil then
FKeyList := TStringList.Create;
Result := FKeyList;
end;
function TRxColumn.GetSortFields: string;
begin
if FSortFields = '' then
Result:=FieldName
else
Result:=FSortFields;
end;
procedure TRxColumn.SetConstraints(AValue: TRxDBGridCollumnConstraints);
begin
FConstraints.Assign(AValue);
end;
procedure TRxColumn.SetEditButtons(AValue: TRxColumnEditButtons);
begin
FEditButtons.Assign(AValue);
end;
procedure TRxColumn.SetFilter(const AValue: TRxColumnFilter);
begin
FFilter.Assign(AValue);
end;
function TRxColumn.GetFooter: TRxColumnFooterItem;
begin
Result := FFooter;
end;
function TRxColumn.GetFooters: TRxColumnFooterItems;
begin
Result:=FFooters;
end;
function TRxColumn.GetConstraints: TRxDBGridCollumnConstraints;
begin
Result:=FConstraints;
end;
procedure TRxColumn.SetFooter(const AValue: TRxColumnFooterItem);
begin
FFooter.Assign(AValue);
end;
procedure TRxColumn.SetFooters(AValue: TRxColumnFooterItems);
begin
FFooters.Assign(AValue);
end;
procedure TRxColumn.SetImageList(const AValue: TImageList);
begin
if FImageList = AValue then
exit;
FImageList := AValue;
if Grid <> nil then
Grid.Invalidate;
end;
procedure TRxColumn.SetKeyList(const AValue: TStrings);
begin
if AValue = nil then
begin
if FKeyList <> nil then
FKeyList.Clear;
end
else
KeyList.Assign(AValue);
end;
procedure TRxColumn.SetNotInKeyListIndex(const AValue: integer);
begin
if FNotInKeyListIndex = AValue then
exit;
FNotInKeyListIndex := AValue;
if Grid <> nil then
Grid.Invalidate;
end;
procedure TRxColumn.SetWordWrap(AValue: boolean);
begin
if FWordWrap=AValue then Exit;
FWordWrap:=AValue;
end;
function TRxColumn.CreateTitle: TGridColumnTitle;
begin
Result := TRxColumnTitle.Create(Self);
end;
procedure TRxColumn.ColumnChanged;
begin
inherited ColumnChanged;
if Assigned(FConstraints) and (FConstraints.MinWidth <> 0) and (FConstraints.MinWidth > Width) then
Width:=FConstraints.MinWidth;
if Assigned(FConstraints) and (FConstraints.MaxWidth <> 0) and (FConstraints.MaxWidth < Width) then
Width:=FConstraints.MaxWidth;
end;
constructor TRxColumn.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FNotInKeyListIndex := -1;
FConstraints:=TRxDBGridCollumnConstraints.Create(Self);
FFooter := TRxColumnFooterItem.Create(nil);
FFooter.FOwner:=Self;
FFooter.FillDefaultFont;
FFilter := TRxColumnFilter.Create(Self);
FDirectInput := true;
FEditButtons:=TRxColumnEditButtons.Create(Self);
FOptions:=[coCustomizeVisible, coCustomizeWidth];
FFooters:=TRxColumnFooterItems.Create(Self);
FGroupParam:=TRxColumnGroupParam.Create(Self);
end;
destructor TRxColumn.Destroy;
begin
FreeAndNil(FGroupParam);
FreeAndNil(FFooters);
FreeAndNil(FEditButtons);
if FKeyList <> nil then
begin
FKeyList.Free;
FKeyList := nil;
end;
FreeAndNil(FFooter);
FreeAndNil(FFilter);
FreeAndNil(FConstraints);
inherited Destroy;
end;
procedure TRxColumn.OptimizeWidth;
begin
if Grid <> nil then
TRxDBGrid(Grid).OptimizeColumnsWidth(FieldName);
end;
{ TRxColumnTitle }
procedure TRxColumnTitle.SetOrientation(const AValue: TTextOrientation);
begin
if FOrientation = AValue then
exit;
FOrientation := AValue;
TRxDBGrid(TRxColumn(Column).Grid).CalcTitle;
TRxColumn(Column).ColumnChanged;
end;
function TRxColumnTitle.GetCaptionLinesCount: integer;
begin
if Assigned(FCaptionLines) then
Result := FCaptionLines.Count
else
Result := 0;
end;
function TRxColumnTitle.CaptionLine(ALine: integer): TMLCaptionItem;
begin
if Assigned(FCaptionLines) and (FCaptionLines.Count > 0) and
(ALine >= 0) and (FCaptionLines.Count > ALine) then
Result := TMLCaptionItem(FCaptionLines[ALine])
else
Result := nil;
end;
procedure TRxColumnTitle.ClearCaptionML;
var
i: integer;
R: TMLCaptionItem;
begin
for i := 0 to FCaptionLines.Count - 1 do
begin
R := TMLCaptionItem(FCaptionLines[i]);
R.Free;
end;
FCaptionLines.Clear;
end;
procedure TRxColumnTitle.SetCaption(const AValue: TCaption);
var
c: integer;
s: string;
procedure AddMLStr(AStr: string);
var
R: TMLCaptionItem;
begin
R := TMLCaptionItem.Create;
R.Caption := AStr;
R.Col := Column;
FCaptionLines.Add(R);
end;
begin
inherited SetCaption(AValue);
ClearCaptionML;
c := Pos('|', AValue);
if C > 0 then
begin
S := AValue;
while C > 0 do
begin
AddMLStr(Copy(S, 1, C - 1));
System.Delete(S, 1, C);
c := Pos('|', S);
end;
if S <> '' then
AddMLStr(S);
end;
if not (csLoading in Column.Grid.ComponentState) and Column.Grid.HandleAllocated then
TRxDBGrid(Column.Grid).CalcTitle;
end;
constructor TRxColumnTitle.Create(TheColumn: TGridColumn);
begin
inherited Create(TheColumn);
{$IFDEF NEW_STYLE_TITLE_ALIGNMENT_RXDBGRID}
Alignment := taCenter;
{$ENDIF}
FCaptionLines := TFPList.Create;
end;
destructor TRxColumnTitle.Destroy;
begin
ClearCaptionML;
FreeAndNil(FCaptionLines);
inherited Destroy;
end;
{ TFilterListCellEditor }
procedure TFilterListCellEditor.WndProc(var TheMessage: TLMessage);
begin
if TheMessage.msg = LM_KILLFOCUS then
begin
Change;
Hide;
if HWND(TheMessage.WParam) = HWND(Handle) then
begin
// lost the focus but it returns to ourselves
// eat the message.
TheMessage.Result := 0;
exit;
end;
end;
inherited WndProc(TheMessage);
end;
procedure TFilterListCellEditor.KeyDown(var Key: word; Shift: TShiftState);
begin
inherited KeyDown(Key, Shift);
case Key of
VK_RETURN:
begin
DroppedDown := False;
Change;
Hide;
end;
end;
end;
procedure TFilterListCellEditor.Show(Grid: TCustomGrid; Col: integer);
begin
FGrid := Grid;
FCol := Col;
Visible := True;
SetFocus;
end;
{ TRxColumnFilter }
function TRxColumnFilter.GetItemIndex: integer;
begin
if CurrentValues.Count > 0 then
Result := FValueList.IndexOf(CurrentValues[0])
else
Result := -1;
end;
function TRxColumnFilter.IsEmptyFontStored: Boolean;
begin
Result:=FIsEmptyFontStored;
end;
function TRxColumnFilter.IsFontStored: Boolean;
begin
Result:=FIsFontStored;
end;
procedure TRxColumnFilter.FontChanged(Sender: TObject);
begin
if Sender = FFont then
FIsFontStored:=not FFont.IsDefault
else
FIsEmptyFontStored:=not FEmptyFont.IsDefault;
FOwner.ColumnChanged;
end;
function TRxColumnFilter.GetDisplayFilterValue: string;
begin
Result:='';
if CurrentValues.Count > 0 then
begin
Result:=CurrentValues[0];
if CurrentValues.Count > 1 then
Result:=Result + '(...)';
end
else
if (Style in [rxfstManualEdit, rxfstBoth]) and (ManulEditValue<>'') then
Result:=ManulEditValue
else
if State = rxfsEmpty then
Result:=EmptyValue
else
if State = rxfsNonEmpty then
Result:=NotEmptyValue
else
if State = rxfsAll then
Result:=AllValue;
end;
procedure TRxColumnFilter.SetColor(const AValue: TColor);
begin
if FColor = AValue then
exit;
FColor := AValue;
FOwner.ColumnChanged;
end;
procedure TRxColumnFilter.SetEmptyFont(AValue: TFont);
begin
if not FEmptyFont.IsEqual(AValue) then
FEmptyFont.Assign(AValue);
end;
procedure TRxColumnFilter.SetFont(const AValue: TFont);
begin
if not FFont.IsEqual(AValue) then
FFont.Assign(AValue);
end;
procedure TRxColumnFilter.SetItemIndex(const AValue: integer);
begin
if (AValue >= -1) and (AValue < FValueList.Count) then
begin
CurrentValues.Clear;
if AValue > -1 then
CurrentValues.Add(FValueList[AValue]);
FOwner.ColumnChanged;
end;
end;
constructor TRxColumnFilter.Create(Owner: TRxColumn);
begin
inherited Create;
FOwner := Owner;
FFont := TFont.Create;
FFont.OnChange:=@FontChanged;
FEmptyFont := TFont.Create;
FEmptyFont.OnChange:=@FontChanged;
FValueList := TStringList.Create;
FValueList.Sorted := True;
FCurrentValues:=TStringList.Create;
FCurrentValues.Sorted:=true;
FColor := clWhite;
State:=rxfsAll;
Style:=rxfstSimple;
FEmptyFont.Style := [fsItalic];
FEmptyValue := sRxDBGridEmptyFilter;
FAllValue := sRxDBGridAllFilter;
FNotEmptyValue:=sRxDBGridNotEmptyFilter;
FEnabled:=true;
end;
destructor TRxColumnFilter.Destroy;
begin
FreeAndNil(FFont);
FreeAndNil(FEmptyFont);
FreeAndNil(FValueList);
FreeAndNil(FCurrentValues);
inherited Destroy;
end;
procedure TRxColumnFilter.ClearFilter;
begin
CurrentValues.Clear;
FManulEditValue:='';
FState:=rxfsEmpty;
end;
{ TExDBGridSortEngine }
procedure TRxDBGridSortEngine.SortList(ListField: string; ADataSet: TDataSet;
Asc: array of boolean; SortOptions: TRxSortEngineOptions);
begin
end;
{ TRxDBGridKeyStroke }
procedure TRxDBGridKeyStroke.SetCommand(const AValue: TRxDBGridCommand);
begin
if FCommand = AValue then
exit;
FCommand := AValue;
Changed(False);
end;
procedure TRxDBGridKeyStroke.SetShortCut(const AValue: TShortCut);
begin
if FShortCut = AValue then
exit;
FShortCut := AValue;
Menus.ShortCutToKey(FShortCut, FKey, FShift);
Changed(False);
end;
function TRxDBGridKeyStroke.GetDisplayName: string;
begin
IntToIdent(Ord(FCommand), Result, EditorCommandStrs);
Result := Result + ' - ' + ShortCutToText(FShortCut);
end;
procedure TRxDBGridKeyStroke.Assign(Source: TPersistent);
begin
if Source is TRxDBGridKeyStroke then
begin
Command := TRxDBGridKeyStroke(Source).Command;
ShortCut := TRxDBGridKeyStroke(Source).ShortCut;
Enabled := TRxDBGridKeyStroke(Source).Enabled;
end
else
inherited Assign(Source);
end;
{ TRxDBGridKeyStrokes }
function TRxDBGridKeyStrokes.GetItem(Index: integer): TRxDBGridKeyStroke;
begin
Result := TRxDBGridKeyStroke(inherited GetItem(Index));
end;
procedure TRxDBGridKeyStrokes.SetItem(Index: integer; const AValue: TRxDBGridKeyStroke);
begin
inherited SetItem(Index, AValue);
end;
procedure TRxDBGridKeyStrokes.Update(Item: TCollectionItem);
begin
inherited Update(Item);
if (UpdateCount = 0) and Assigned(Owner) and Assigned(TRxDBGrid(Owner).FKeyStrokes) then
TRxDBGrid(Owner).UpdateJMenuKeys;
end;
constructor TRxDBGridKeyStrokes.Create(AOwner: TPersistent);
begin
inherited Create(AOwner, TRxDBGridKeyStroke);
end;
procedure TRxDBGridKeyStrokes.Assign(Source: TPersistent);
var
i: integer;
begin
if Source is TRxDBGridKeyStrokes then
begin
Clear;
for i := 0 to TRxDBGridKeyStrokes(Source).Count-1 do
begin
with Add do
Assign(TRxDBGridKeyStrokes(Source)[i]);
end;
end
else
inherited Assign(Source);
end;
function TRxDBGridKeyStrokes.Add: TRxDBGridKeyStroke;
begin
Result := TRxDBGridKeyStroke(inherited Add);
Result.Enabled := True;
end;
function TRxDBGridKeyStrokes.AddE(ACommand: TRxDBGridCommand;
AShortCut: TShortCut): TRxDBGridKeyStroke;
begin
Result := nil;
Result := Add;
Result.FShortCut := AShortCut;
Result.FCommand := ACommand;
end;
procedure TRxDBGridKeyStrokes.ResetDefaults;
begin
Clear;
AddE(rxgcShowFindDlg, Menus.ShortCut(Ord('F'), [ssCtrl]));
AddE(rxgcShowColumnsDlg, Menus.ShortCut(Ord('W'), [ssCtrl]));
AddE(rxgcShowFilterDlg, Menus.ShortCut(Ord('T'), [ssCtrl]));
AddE(rxgcShowSortDlg, Menus.ShortCut(Ord('S'), [ssCtrl]));
AddE(rxgcShowQuickFilter, Menus.ShortCut(Ord('Q'), [ssCtrl]));
AddE(rxgcHideQuickFilter, Menus.ShortCut(Ord('H'), [ssCtrl]));
AddE(rxgcSelectAll, Menus.ShortCut(Ord('A'), [ssCtrl]));
AddE(rxgcDeSelectAll, Menus.ShortCut(Ord('-'), [ssCtrl]));
AddE(rxgcInvertSelection, Menus.ShortCut(Ord('*'), [ssCtrl]));
AddE(rxgcOptimizeColumnsWidth, Menus.ShortCut(Ord('+'), [ssCtrl]));
AddE(rxgcCopyCellValue, Menus.ShortCut(Ord('C'), [ssCtrl]));
end;
function TRxDBGridKeyStrokes.FindRxCommand(AKey: word;
AShift: TShiftState): TRxDBGridCommand;
var
i: integer;
K: TRxDBGridKeyStroke;
begin
Result := rxgcNone;
for i := 0 to Count - 1 do
begin
K := Items[i];
if (K.FKey = AKey) and (K.FShift = AShift) and (K.FEnabled) then
begin
Result := K.FCommand;
exit;
end;
end;
end;
function TRxDBGridKeyStrokes.FindRxKeyStrokes(ACommand: TRxDBGridCommand):
TRxDBGridKeyStroke;
var
i: integer;
begin
Result := nil;
for i := 0 to Count - 1 do
begin
if (Items[i].Command = ACommand) then
begin
Result := Items[i];
exit;
end;
end;
end;
initialization
RegisterPropertyToSkip( TRxDBGrid, 'AllowedOperations', 'This property duplicated standart DBGrid.Options', '');
RegisterPropertyToSkip( TRxColumnFilter, 'IsNull', 'depricated property', '');
RegisterPropertyToSkip( TRxColumnFilter, 'IsAll', 'depricated property', '');
RegisterPropertyToSkip( TRxColumnFilter, 'Value', 'depricated property', '');
RxDBGridSortEngineList := TStringList.Create;
RxDBGridSortEngineList.Sorted := True;
FMarkerUp := CreateResBitmap('rx_markerup');
FMarkerDown := CreateResBitmap('rx_markerdown');
FEllipsisRxBMP:=CreateResBitmap('rx_Ellipsis');
FGlyphRxBMP:=CreateResBitmap('rx_Glyph');
FUpDownRxBMP:=CreateResBitmap('rx_UpDown');
FPlusRxBMP:=CreateResBitmap('rx_plus');
FMinusRxBMP:=CreateResBitmap('rx_minus');
finalization
while (RxDBGridSortEngineList.Count > 0) do
begin
RxDBGridSortEngineList.Objects[0].Free;
RxDBGridSortEngineList.Delete(0);
end;
RxDBGridSortEngineList.Free;
FreeAndNil(FMarkerUp);
FreeAndNil(FMarkerDown);
FreeAndNil(FEllipsisRxBMP);
FreeAndNil(FGlyphRxBMP);
FreeAndNil(FUpDownRxBMP);
FreeAndNil(FPlusRxBMP);
FreeAndNil(FMinusRxBMP);
end.