lazarus-ccr/components/kcontrols/source/kdbgrids.pas
sekelsenmat eb3ecee187 Initial commit of kcontrols
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1732 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2011-07-04 06:24:41 +00:00

1496 lines
48 KiB
ObjectPascal
Executable File

{ @abstract(This unit contains the TKDBGrid component and all supporting classes)
@author(Tomas Krysl (tk@tkweb.eu))
@created(20 Sep 2009)
@lastmod(20 Jun 2010)
Copyright © 2009 Tomas Krysl (tk@@tkweb.eu)<BR><BR>
This unit provides a data aware control for TKGrid.
Note: I am still a newbie to Delphi/Lazarus database solutions. If anything
is totally wrong here please feel free to send a patch or hint to me.
<B>License:</B><BR>
This code is distributed as a freeware. You are free to use it as part
of your application for any purpose including freeware, commercial and
shareware applications. The origin of this source code must not be
misrepresented; you must not claim your authorship. You may modify this code
solely for your own purpose. However, you may distribute only the original
package. The Author accepts no liability for any damage that may result
from using this code. }
unit KDBGrids;
{$include kcontrols.inc}
{$WEAKPACKAGEUNIT ON}
interface
uses
{$IFDEF FPC}
LCLType, LCLIntf, LCLProc, LResources,
{$ELSE}
Windows, Messages,
{$ENDIF}
SysUtils, Classes, Graphics, Controls, Forms, ExtCtrls, DB, DBCtrls,
KFunctions, KGraphics, KGrids;
resourcestring
{ @exclude }
SKDBGridIndex = 'Index';
type
{ Declares possible values for the @link(TKCustomDBGrid.DBOptions) property. }
TKDBGridOption = (
{ Automatically moves current record to edited or selected row. }
dboAutoMoveRecord,
{ Forces the cells with boolean fields to be automatically adjusted to checkbox frame size. }
dboAutoSizeBooleanCells,
{ Forces the cells with image fields to be automatically adjusted to image size. }
dboAutoSizeImageCells,
{ Forces the column names to be assigned to fixed cells in the first fixed row. }
dboColNamesToHeader,
{ Does not clear fixed cell texts if table is closed. }
dboDontClearFixedCells,
{ For all BLOB/image columns, images will be displayed in original size in the cell hint window. }
dboImageHint,
{ Images loaded from database can be modified by user and thus will be
saved into database if this option is included. }
dboImagesWritable,
{ Forces the row indexes to be assigned to fixed cells in the first fixed column. }
dboIndexFixedCol,
{ Indicates the active record row. }
dboIndicateActiveRecord
);
{ Set type for @link(TKDBGridOption) enumeration. }
TKDBGridOptions = set of TKDBGridOption;
const
{ Default value for the @link(TKCustomDBGrid.DBOptions) property. }
cDBOptionsDef = [dboAutoMoveRecord, dboAutoSizeBooleanCells,
dboColNamesToHeader, dboIndexFixedCol, dboIndicateActiveRecord];
{ Default value for the @link(TKDBGridColors.ActiveRecord) property. }
cActiveRecordDef = clCream;
{ Used by default to distinguish image field type. }
cDefaultImageSet = [ftBlob, ftGraphic];
{ Used by default to distinguish string field type. }
cDefaultStringSet = [ftString, ftSmallInt, ftInteger, ftWord, ftBoolean, ftFloat,
ftCurrency, ftBCD, ftDate, ftTime, ftDateTime, ftAutoInc, ftMemo, ftFmtMemo,
ftFixedChar, ftWideString, ftLargeInt, ftGuid, ftTimeStamp, ftFmtBCD
{$IF DEFINED(FPC) OR DEFINED(COMPILER10_UP)}
, ftWideMemo
{$IFEND}
];
{ Index for the @link(TKDBGridColors.ActiveRecord) property. }
ciActiveRecord = TKGridColorIndex(ciGridColorsMax + 1);
{ Maximum color array index }
ciDBGridColorsMax = ciActiveRecord;
{ This internal flag is set if grid is being updated. }
cGF_DBDataUpdating = $00010000;
{ This internal flag is set if data record is being changed. }
cGF_DBInternalChanging = $00020000;
type
TKCustomDBGrid = class;
{ @abstract(Data link override for TKCustomDBGrid)
This class overrides TDataLink to extend behavior for TKCustomDBGrid. }
TKDBGridDataLink = class(TDataLink)
private
FGrid: TKCustomDBGrid;
FModified: Boolean;
procedure SetModified(const Value: Boolean);
protected
{ Called if data set has been opened or closed. }
procedure ActiveChanged; override;
{ Called if data in the data set has been changed. }
procedure DataSetChanged; override;
{ Called if current record has been moved. }
procedure DataSetScrolled(Distance: Integer); override;
{ Called if data set layout has been modified. }
procedure LayoutChanged; override;
{ Called if current record has been modified. }
procedure RecordChanged(Field: TField); override;
{ Called if unsaved data is about to be saved into database. }
procedure UpdateData; override;
public
{ Creates the instance. }
constructor Create(AGrid: TKCustomDBGrid);
{ Specifies the TKCustomDBGrid instance assigned to this TKDBGridDataLink instance. }
property Grid: TKCustomDBGrid read FGrid;
{ Determines if the current record has been modified. }
property Modified: Boolean read FModified write SetModified;
end;
{$IFDEF TKDBGRIDCELL_IS_TKGRIDATTRTEXTCELL}
{ @exclude }
TKDBGridCellAncestor = TKGridAttrTextCell;
{$ELSE}
{ @exclude }
TKDBGridCellAncestor = TKGridTextCell;
{$ENDIF}
{ @abstract(Base cell class for TKDBGrid)
This is the base cell class. It has always a Text property. Descendants can
add other specific data, e.g. BLOB pointers etc. }
TKDBGridCell = class(TKDBGridCellAncestor)
private
FGraphic: TGraphic;
protected
{ Calls @link(TKCustomDBGrid.BeforeCellUpdate). }
procedure BeforeUpdate; override;
{ Loads appropriate image. }
function CreateImageByType(const Header: TKImageHeaderString): TGraphic; virtual;
{ Assigns cell properties to field data. }
procedure FieldFromCell(AField: TField); virtual;
{ Assigns field data to cell properties. }
procedure FieldToCell(AField: TField); virtual;
{ Assigns AField buffer to Graphic property. }
procedure ImageFromField(AField: TField);
{ Assigns Graphic property to AField buffer. }
procedure ImageToField(AField: TField);
{ Initializes the cell data. }
procedure Initialize; override;
{ Assigns AField buffer to Text property. }
procedure TextFromField(AField: TField);
{ Assigns Text property to AField buffer. }
procedure TextToField(AField: TField);
public
{ Creates the instance. }
constructor Create(AGrid: TKCustomGrid); override;
{ Applies TKDBGridCell properties to the cell painter. }
procedure ApplyDrawProperties; override;
{ Returns a pointer to the image read from database. }
property Graphic: TGraphic read FGraphic;
end;
{ @abstract(Column class for TKCustomDBGrid)
This column class implements some extra properties for TKCustomDBGrid. }
TKDBGridCol = class(TKGridCol)
private
FCurrencyFormat: TKCurrencyFormat;
FDataType: TFieldType;
FName: {$IFDEF STRING_IS_UNICODE}string{$ELSE}WideString{$ENDIF};
public
{ Creates the instance. Do not create custom instances. All necessary
TKDBGridCol instances are created automatically by TKCustomDBGrid. }
constructor Create(AGrid: TKCustomGrid); override;
{ Specifies the currency formatting settings if the column has currency data type. }
property CurrencyFormat: TKCurrencyFormat read FCurrencyFormat write FCurrencyFormat;
{ Returns the field data type. It is assigned automatically
by the TKDGGrid's data source. }
property DataType: TFieldType read FDataType;
{ Specifies the database column name. It is assigned automatically
by the TKDGGrid's data source. }
property Name: {$IFDEF STRING_IS_UNICODE}string{$ELSE}WideString{$ENDIF} read FName;
end;
{ @abstract(Metaclass for @link(TKDBGridCol)). }
TKDBGridColClass = class of TKDBGridCol;
{ @abstract(Cell painter class used by TKCustomDBGrid class)
Overrides some TKGridCellPainter methods for usage with TKCustomDBGrid. }
TKDBGridCellPainter = class(TKGridCellPainter)
public
{ Low level method. Prepares default painting attributes. Applies
attributes specific for TKDBGrid. }
procedure DefaultAttributes; override;
end;
{ @abstract(Container for all colors used by TKCustomDBGrid class)
Adds some extra colors used by TKCustomDBGrid. }
TKDBGridColors = class(TKGridColors)
private
function GetColor(Index: TKGridColorIndex): TColor;
procedure SetColor(Index: TKGridColorIndex; Value: TColor);
protected
{ Initializes the color array. }
procedure Initialize; override;
published
{ Specifies the color used to indicate active record. }
property ActiveRecord: TColor index ciActiveRecord read GetColor write SetColor default cActiveRecordDef;
end;
{ @abstract(KGrid data aware base component) This is the class that you use as
the ancestor for your TKCustomDBGrid overrides. }
TKCustomDBGrid = class(TKCustomGrid)
private
FActiveRecord: Integer;
FDBOptions: TKDBGridOptions;
function GetDataSource: TDataSource;
procedure SetDataSource(Value: TDataSource);
procedure SetDBOptions(const Value: TKDBGridOptions);
protected
{ This field represents the internal data link. }
FDataLink: TKDBGridDataLink;
{ Does nothing. Row moving not supported. }
function BeginRowDrag(var Origin: Integer; const MousePt: TPoint): Boolean; override;
{ Fills the grid with data from database and/or updates the grid. }
procedure DataChanged; dynamic;
{ Called if current record has been moved. }
procedure DataSetScrolled; dynamic;
{ Extends TKCustomGrid behavior. Sets the data set into edited state and
informs the data link about cell change. }
procedure Changed; override;
{ Extends TKCustomGrid behavior. Updates the grid if column has been moved. }
procedure ColMoved(FromIndex, ToIndex: Integer); override;
{ Extends TKCustomGrid behavior. Calls the event if data set is active etc. }
function CustomSortRows(ByCol: Integer; var SortMode: TKGridSortMode): Boolean; override;
{ Extends TKCustomGrid behavior. Does not allow to edit if data set is writable
or closed etc. }
function EditorCreate(ACol, ARow: Integer): TWinControl; override;
{ Moves to another record if initiated by the grid. }
procedure InternalSetActiveRecord(Value: Integer); dynamic;
{ Used internally to set column count. }
procedure InternalSetColCount(Value: Integer); override;
{ Used internally to set fixed column count. }
procedure InternalSetFixedCols(Value: Integer); override;
{ Used internally to set fixed row count. }
procedure InternalSetFixedRows(Value: Integer); override;
{ Used internally to set row count. }
procedure InternalSetRowCount(Value: Integer); override;
{ Allows to decide whether the goVirtualGrid option can be modified.
Returns always False as no virtual grid possible in TKDBGrid. }
function InternalUpdateVirtualGrid: Boolean; override;
{ Called if current record has been modified. }
procedure RecordChanged; dynamic;
{ Extends TKCustomGrid behavior. Forces the previous modified record to be
written into database. }
function SelectCell(ACol, ARow: Integer): Boolean; override;
{ Extends TKCustomGrid behavior. Updates the grid if top row or left column has
been changed. }
procedure TopLeftChanged; override;
{ Called if unsaved data is about to be saved into database. }
procedure UpdateData; dynamic;
{ Extends TKCustomGrid Behavior. Updates the grid if control size has
been changed. }
procedure UpdateSize; override;
public
{ Creates the instance. Assigns default values to properties, allocates
default column, row and cell data, constucts a data link. }
constructor Create(AOwner: TComponent); override;
{ Destroys the instance along with all allocated column, row and cell data,
destroys the data link. }
destructor Destroy; override;
{ Notifies the grid that a cell has been modified. }
procedure BeforeCellUpdate(ACol, ARow: Integer); dynamic;
{ Does nothing. Clearing entire column is not supported. }
procedure ClearCol(ACol: Integer); override;
{ Does nothing. Clearing entire grid is not supported. }
procedure ClearGrid; override;
{ Does nothing. Clearing entire row is not supported. }
procedure ClearRow(ARow: Integer); override;
{ Writes any modified data in the current record into database. }
procedure Commit; dynamic;
{ Provides default behavior for the @link(OnEditorCreate) event. }
procedure DefaultEditorCreate(ACol, ARow: Integer;
var AEditor: TWinControl); override;
{ Provides default behavior for the @link(OnEditorDataFromGrid) event. }
procedure DefaultEditorDataFromGrid(AEditor: TWinControl;
ACol, ARow: Integer; var AssignText: Boolean); override;
{ Provides default behavior for the @link(OnEditorDataToGrid) event. }
procedure DefaultEditorDataToGrid(AEditor: TWinControl;
ACol, ARow: Integer; var AssignText: Boolean); override;
{ Provides default behavior for the @link(OnEditorResize) event. }
procedure DefaultEditorResize(AEditor: TWinControl;
ACol, ARow: Integer; var ARect: TRect); override;
{ Provides default behavior for the @link(OnEditorSelect) event. }
procedure DefaultEditorSelect(AEditor: TWinControl;
ACol, ARow: Integer; SelectAll, CaretToLeft, SelectedByMouse: Boolean); override;
{ Provides default cell hint behavior. }
procedure DefaultMouseCellHint(ACol, ARow: Integer; AShow: Boolean); override;
{ Does nothing. Deleting columns not supported. }
procedure DeleteCols(At, Count: Integer); override;
{ Forces the data set to delete record at location At. }
procedure DeleteRow(At: Integer); override;
{ Does nothing. Deleting more rows not supported. }
procedure DeleteRows(At, Count: Integer); override;
{ Does nothing. Inserting columns not supported. }
procedure InsertCols(At, Count: Integer); override;
{ Forces the data set to insert new record at location At. }
procedure InsertRow(At: Integer); override;
{ Does nothing. Inserting more rows not supported. }
procedure InsertRows(At, Count: Integer); override;
{ Does nothing. Inserting sorted columns not supported. }
function InsertSortedCol(out ByRow, ACol: Integer): Boolean; override;
{ Does nothing. Inserting sorted rows not supported. }
function InsertSortedRow(out ByCol, ARow: Integer): Boolean; override;
{ Does nothing. Row moving not supported. }
procedure MoveRow(FromIndex, ToIndex: Integer); override;
{ Specifies the data source. }
property DataSource: TDataSource read GetDataSource write SetDataSource;
{ Specifies various display and behavioral properties of TKDGGrid. }
property DBOptions: TKDBGridOptions read FDBOptions write SetDBOptions default cDBOptionsDef;
end;
{ For backward compatibility. }
TKDBCustomGrid = TKCustomDBGrid;
{ @abstract(KDBGrid design-time component) This is the class you use both
on run-time and design-time. }
TKDBGrid = class(TKCustomDBGrid)
published
{ Inherited property - see Delphi help. }
property Align;
{ Inherited property - see Delphi help. }
property Anchors;
{ See TKCustomGrid.@link(TKCustomControl.BorderStyle) for details. }
property BorderStyle;
{ Inherited property - see Delphi help. }
property BorderWidth;
{ See TKCustomDBGrid.@link(TKCustomDBGrid.DBOptions) for details. }
property DBOptions;
{ See TKCustomGrid.@link(TKCustomGrid.ColCount) for details. }
property ColCount;
{ See TKCustomGrid.@link(TKCustomGrid.Color) for details. }
property Color;
{ See TKCustomGrid.@link(TKCustomGrid.Colors) for details. }
property Colors;
{ Inherited property - see Delphi help. }
property Constraints;
{$IFDEF FPC}
{ See TKCustomGrid.@link(TKCustomGrid.Flat) for details. }
property Flat;
{$ELSE}
{ Inherited property - see Delphi help. }
property Ctl3D;
{$ENDIF}
{ See TKCustomDBGrid.@link(TKCustomDBGrid.DataSource) for details. }
property DataSource;
{ See TKCustomGrid.@link(TKCustomGrid.DefaultColWidth) for details. }
property DefaultColWidth;
{ See TKCustomGrid.@link(TKCustomGrid.DefaultDrawing) for details. }
property DefaultDrawing;
{ See TKCustomGrid.@link(TKCustomGrid.DefaultRowHeight) for details. }
property DefaultRowHeight;
{ See TKCustomGrid.@link(TKCustomGrid.DisabledDrawStyle) for details. }
property DisabledDrawStyle;
{ Inherited property - see Delphi help. }
property DragCursor;
{ Inherited property - see Delphi help. }
property DragKind;
{ Inherited property - see Delphi help. }
property DragMode;
{ See TKCustomGrid.@link(TKCustomGrid.DragStyle) for details. }
property DragStyle;
{ Inherited property - see Delphi help. }
property Enabled;
{ See TKCustomGrid.@link(TKCustomGrid.FixedCols) for details. }
property FixedCols;
{ See TKCustomGrid.@link(TKCustomGrid.FixedRows) for details. }
property FixedRows;
{ Inherited property - see Delphi help. }
property Font;
{ See TKCustomGrid.@link(TKCustomGrid.GridLineWidth) for details. }
property GridLineWidth;
{ See TKCustomGrid.@link(TKCustomGrid.MinColWidth) for details. }
property MinColWidth;
{ See TKCustomGrid.@link(TKCustomGrid.MinRowHeight) for details. }
property MinRowHeight;
{ See TKCustomGrid.@link(TKCustomGrid.MouseCellHintTime) for details. }
property MouseCellHintTime;
{ See TKCustomGrid.@link(TKCustomGrid.MoveDirection) for details. }
property MoveDirection;
{ See TKCustomGrid.@link(TKCustomGrid.Options) for details. }
property Options;
{ Inherited property - see Delphi help. }
property ParentColor;
{ Inherited property - see Delphi help. }
property ParentFont;
{ Inherited property - see Delphi help. }
property ParentShowHint;
{ Inherited property - see Delphi help. }
property PopupMenu;
{ See TKCustomGrid.@link(TKCustomGrid.RangeSelectStyle) for details. }
property RangeSelectStyle;
{ See TKCustomGrid.@link(TKCustomGrid.RowCount) for details. }
property RowCount;
{ See TKCustomGrid.@link(TKCustomGrid.ScrollBars) for details. }
property ScrollBars;
{ See TKCustomGrid.@link(TKCustomGrid.ScrollModeHorz) for details. }
property ScrollModeHorz;
{ See TKCustomGrid.@link(TKCustomGrid.ScrollModeVert) for details. }
property ScrollModeVert;
{ See TKCustomGrid.@link(TKCustomGrid.ScrollSpeed) for details. }
property ScrollSpeed;
{ Inherited property - see Delphi help. }
property ShowHint;
{ See TKCustomGrid.@link(TKCustomGrid.SizingStyle) for details. }
property SizingStyle;
{ See TKCustomGrid.@link(TKCustomGrid.SortStyle) for details. }
property SortStyle;
{ Inherited property - see Delphi help. }
property TabOrder;
{ Inherited property - see Delphi help. }
property TabStop default True;
{ Inherited property - see Delphi help. }
property Visible;
{ See TKCustomGrid.@link(TKCustomGrid.OnBeginColDrag) for details. }
property OnBeginColDrag;
{ See TKCustomGrid.@link(TKCustomGrid.OnBeginColSizing) for details. }
property OnBeginColSizing;
{ See TKCustomGrid.@link(TKCustomGrid.OnBeginRowSizing) for details. }
property OnBeginRowSizing;
{ See TKCustomGrid.@link(TKCustomGrid.OnCellSpan) for details. }
property OnCellSpan;
{ See TKCustomGrid.@link(TKCustomGrid.OnChanged) for details. }
property OnChanged;
{ See TKCustomGrid.@link(TKCustomGrid.OnCheckColDrag) for details. }
property OnCheckColDrag;
{ Inherited property - see Delphi help. }
property OnClick;
{ See TKCustomGrid.@link(TKCustomGrid.OnColumnMoved) for details. }
property OnColumnMoved;
{ See TKCustomGrid.@link(TKCustomGrid.OnColWidthsChanged) for details. }
property OnColWidthsChanged;
{ Inherited property - see Delphi help. }
property OnContextPopup;
{ See TKCustomGrid.@link(TKCustomGrid.OnCustomSortCols) for details. }
property OnCustomSortCols;
{ See TKCustomGrid.@link(TKCustomGrid.OnCustomSortRows) for details. }
property OnCustomSortRows;
{ Inherited property - see Delphi help. }
property OnDblClick;
{ Inherited property - see Delphi help. }
property OnDockDrop;
{ Inherited property - see Delphi help. }
property OnDockOver;
{ Inherited property - see Delphi help. }
property OnDragDrop;
{ Inherited property - see Delphi help. }
property OnDragOver;
{ See TKCustomGrid.@link(TKCustomGrid.OnDrawCell) for details. }
property OnDrawCell;
{ See TKCustomGrid.@link(TKCustomGrid.OnEditorCreate) for details. }
property OnEditorCreate;
{ See TKCustomGrid.@link(TKCustomGrid.OnEditorDataFromGrid) for details. }
property OnEditorDataFromGrid;
{ See TKCustomGrid.@link(TKCustomGrid.OnEditorDataToGrid) for details. }
property OnEditorDataToGrid;
{ See TKCustomGrid.@link(TKCustomGrid.OnEditorDestroy) for details. }
property OnEditorDestroy;
{ See TKCustomGrid.@link(TKCustomGrid.OnEditorKeyPreview) for details. }
property OnEditorKeyPreview;
{ See TKCustomGrid.@link(TKCustomGrid.OnEditorResize) for details. }
property OnEditorResize;
{ See TKCustomGrid.@link(TKCustomGrid.OnEditorSelect) for details. }
property OnEditorSelect;
{ See TKCustomGrid.@link(TKCustomGrid.OnEndColDrag) for details. }
property OnEndColDrag;
{ See TKCustomGrid.@link(TKCustomGrid.OnEndColSizing) for details. }
property OnEndColSizing;
{ Inherited property - see Delphi help. }
property OnEndDock;
{ Inherited property - see Delphi help. }
property OnEndDrag;
{ See TKCustomGrid.@link(TKCustomGrid.OnEndRowSizing) for details. }
property OnEndRowSizing;
{ Inherited property - see Delphi help. }
property OnEnter;
{ Inherited property - see Delphi help. }
property OnExit;
{ See TKCustomGrid.@link(TKCustomGrid.OnExchangeCols) for details. }
property OnExchangeCols;
{ See TKCustomGrid.@link(TKCustomGrid.OnExchangeRows) for details. }
property OnExchangeRows;
{ Inherited property - see Delphi help. }
property OnGetSiteInfo;
{ Inherited property - see Delphi help. }
property OnKeyDown;
{ Inherited property - see Delphi help. }
property OnKeyPress;
{ Inherited property - see Delphi help. }
property OnKeyUp;
{ See TKCustomGrid.@link(TKCustomGrid.OnMouseCellHint) for details. }
property OnMouseCellHint;
{ See TKCustomGrid.@link(TKCustomGrid.OnMouseClickCell) for details. }
property OnMouseClickCell;
{ Inherited property - see Delphi help. }
property OnMouseDown;
{ See TKCustomGrid.@link(TKCustomGrid.OnMouseEnterCell) for details. }
property OnMouseEnterCell;
{ See TKCustomGrid.@link(TKCustomGrid.OnMouseLeaveCell) for details. }
property OnMouseLeaveCell;
{ Inherited property - see Delphi help. }
property OnMouseMove;
{ Inherited property - see Delphi help. }
property OnMouseUp;
{ Inherited property - see Delphi help. }
property OnMouseWheel;
{ Inherited property - see Delphi help. }
property OnMouseWheelDown;
{ Inherited property - see Delphi help. }
property OnMouseWheelUp;
{ Inherited property - see Delphi help. }
property OnResize;
{ See TKCustomGrid.@link(TKCustomGrid.OnRowHeightsChanged) for details. }
property OnRowHeightsChanged;
{ See TKCustomGrid.@link(TKCustomGrid.OnSelectCell) for details. }
property OnSelectCell;
{ See TKCustomGrid.@link(TKCustomGrid.OnSelectionExpand) for details. }
property OnSelectionExpand;
{ See TKCustomGrid.@link(TKCustomGrid.OnSizeChanged) for details. }
property OnSizeChanged;
{ Inherited property - see Delphi help. }
property OnStartDock;
{ Inherited property - see Delphi help. }
property OnStartDrag;
{ See TKCustomGrid.@link(TKCustomGrid.OnTopLeftChanged) for details. }
property OnTopLeftChanged;
{ Inherited property - see Delphi help. }
property OnUnDock;
end;
implementation
uses
Math, Types, ComCtrls, StdCtrls
{$IFDEF FPC}
, EditBtn
{$ENDIF}
;
{ TKDBGridDataLink }
constructor TKDBGridDataLink.Create(AGrid: TKCustomDBGrid);
begin
inherited Create;
FGrid := AGrid;
FModified := False;
VisualControl := True;
end;
procedure TKDBGridDataLink.ActiveChanged;
begin
inherited;
if Assigned(FGrid) then
FGrid.DataChanged;
FModified := False;
end;
procedure TKDBGridDataLink.DataSetChanged;
begin
inherited;
if Assigned(FGrid) then
FGrid.DataChanged;
FModified := False;
end;
procedure TKDBGridDataLink.DataSetScrolled(Distance: Integer);
begin
inherited;
if Assigned(FGrid) then
FGrid.DataSetScrolled;
end;
procedure TKDBGridDataLink.LayoutChanged;
begin
inherited;
if Assigned(FGrid) then
FGrid.DataChanged;
FModified := False;
end;
procedure TKDBGridDataLink.RecordChanged;
begin
inherited;
if Assigned(FGrid) and not FGrid.Flag(cGF_EditorUpdating or cGF_DBDataUpdating) then
begin
FGrid.RecordChanged;
FModified := False;
end;
end;
procedure TKDBGridDataLink.SetModified(const Value: Boolean);
begin
FModified := FModified or Value;
end;
procedure TKDBGridDataLink.UpdateData;
begin
if FModified and Assigned(FGrid) then
FGrid.UpdateData;
FModified := False;
end;
{ TKGridDBCell }
constructor TKDBGridCell.Create(AGrid: TKCustomGrid);
begin
FGraphic := nil;
inherited;
end;
procedure TKDBGridCell.ApplyDrawProperties;
var
ACol: TKDBGridCol;
begin
inherited;
Grid.CellPainter.Graphic := FGraphic;
if not (gdFixed in Grid.CellPainter.State) and (Grid.Cols[Grid.CellPainter.Col] is TKDBGridCol) then
begin
ACol := TKDBGridCol(Grid.Cols[Grid.CellPainter.Col]);
case ACol.DataType of
ftBoolean:
Grid.CellPainter.Text := '';
ftCurrency, ftBcd:
Grid.CellPainter.Text := FormatCurrency(StrToCurrDef(Grid.CellPainter.Text, 0), ACol.CurrencyFormat);
end;
end;
end;
procedure TKDBGridCell.BeforeUpdate;
var
ACol, ARow: Integer;
begin
inherited;
if (Grid is TKDBGrid) and not Grid.Flag(cGF_EditorUpdating or cGF_DBDataUpdating)
and FindCell(ACol, ARow) then
TKDBGrid(Grid).BeforeCellUpdate(ACol, ARow);
end;
function TKDBGridCell.CreateImageByType(const Header: TKImageHeaderString): TGraphic;
begin
Result := ImageByType(Header);
end;
procedure TKDBGridCell.FieldFromCell(AField: TField);
begin
if AField <> nil then
begin
if AField.DataType in cDefaultStringSet then
TextToField(AField)
else if (AField.DataType in cDefaultImageSet) and
(dboImagesWritable in TKCustomDBGrid(Grid).DBOptions) then
ImageToField(AField);
// else - override TKDBGridCell
end;
end;
procedure TKDBGridCell.FieldToCell(AField: TField);
begin
if AField <> nil then
begin
if AField.DataType in cDefaultStringSet then
begin
FreeAndNil(FGraphic);
TextFromField(AField);
end
else if AField.DataType in cDefaultImageSet then
begin
Text := '';
ImageFromField(AField);
end;
// else - override TKDBGridCell
end;
end;
procedure TKDBGridCell.ImageFromField(AField: TField);
var
MS: TMemoryStream;
S: AnsiString;
begin
if AField is TBlobField then
begin
FreeAndNil(FGraphic);
MS := TMemoryStream.Create;
try
TBlobField(AField).SaveToStream(MS);
if MS.Size > SizeOf(TKImageHeaderString) then
begin
MS.Seek(0, soFromBeginning);
SetLength(S, SizeOf(TKImageHeaderString));
MS.Read(S[1], SizeOf(TKImageHeaderString));
FGraphic := CreateImageByType(S);
if Assigned(FGraphic) then
begin
MS.Seek(0, soFromBeginning);
FGraphic.LoadFromStream(MS);
end;
end;
finally
MS.Free;
end;
end;
end;
procedure TKDBGridCell.ImageToField(AField: TField);
var
MS: TMemoryStream;
begin
if (AField is TBlobField) and Assigned(FGraphic) then
begin
MS := TMemoryStream.Create;
try
FGraphic.SaveToStream(MS);
MS.Seek(0, soFromBeginning);
TBlobField(AField).LoadFromStream(MS);
finally
MS.Free;
end;
end;
end;
procedure TKDBGridCell.Initialize;
begin
inherited;
FreeAndNil(FGraphic);
end;
procedure TKDBGridCell.TextFromField(AField: TField);
begin
{$IFDEF STRING_IS_UNICODE}
Text := AField.AsString
{$ELSE}
{$IFDEF COMPILER10_UP}
Text := AField.AsWideString
{$ELSE}
Text := AField.AsString
{$ENDIF}
{$ENDIF}
end;
procedure TKDBGridCell.TextToField(AField: TField);
begin
if not AField.ReadOnly then
try
{$IFDEF STRING_IS_UNICODE}
AField.AsString := Text
{$ELSE}
{$IFDEF COMPILER10_UP}
AField.AsWideString := Text
{$ELSE}
AField.AsString := Text
{$ENDIF}
{$ENDIF}
except
end
end;
{ TKDBGridCol }
constructor TKDBGridCol.Create(AGrid: TKCustomGrid);
begin
inherited;
FCurrencyFormat.CurrencyFormat := SysUtils.CurrencyFormat;
FCurrencyFormat.CurrencyDecimals := SysUtils.CurrencyDecimals;
FCurrencyFormat.CurrencyString := SysUtils.CurrencyString;
FCurrencyFormat.DecimalSep := SysUtils.DecimalSeparator;
FCurrencyFormat.ThousandSep := SysUtils.ThousandSeparator;
FCurrencyFormat.UseThousandSep := True;
FDataType := ftUnknown;
FName := '';
end;
{ TKDBGridCellPainter }
procedure TKDBGridCellPainter.DefaultAttributes;
begin
inherited;
if Assigned(TKCustomDBGrid(Grid).FDataLink) then
begin
if (dboIndicateActiveRecord in TKCustomDBGrid(Grid).DBOptions) and
Assigned(TKCustomDBGrid(Grid).FDataLink.DataSet) and
(TKCustomDBGrid(Grid).FDataLink.ActiveRecord = Row - Grid.FixedRows) and
(State * [gdSelected, gdFocused] = []) then
Canvas.Brush.Color := TKDBGridColors(TKCustomDBGrid(Grid).Colors).ActiveRecord;
if (dboIndexFixedCol in TKCustomDBGrid(Grid).DBOptions) and (Col = 0) and (Grid.FixedCols > 0) then
HAlign := halRight;
if not (gdFixed in State) and (Grid.Cols[Col] is TKDBGridCol) then
case TKDBGridCol(Grid.Cols[Col]).DataType of
ftMemo
{$IF DEFINED(FPC) OR DEFINED(COMPILER10_UP)}
, ftWideMemo
{$IFEND}
:
Attributes := Attributes + [taLineBreak];
ftCurrency, ftBCD, ftFmtBCD:
HAlign := halRight;
ftBoolean:
begin
CheckBox := True;
CheckBoxChecked := LowerCase(Grid.Cells[Col, Row]) = 'true';
end;
end;
end;
end;
{ TKDBGridColors }
function TKDBGridColors.GetColor(Index: TKGridColorIndex): TColor;
begin
Result := InternalGetColor(Index);
end;
procedure TKDBGridColors.Initialize;
begin
inherited;
SetLength(FColors, ciDBGridColorsMax + 1);
SetLength(FBrightColors, ciDBGridColorsMax + 1);
FColors[ciActiveRecord] := cActiveRecordDef;
end;
procedure TKDBGridColors.SetColor(Index: TKGridColorIndex; Value: TColor);
begin
InternalSetColor(Index, Value);
end;
{ TKCustomDBGrid }
constructor TKCustomDBGrid.Create(AOwner: TComponent);
begin
FDataLink := TKDBGridDataLink.Create(Self);
inherited;
FActiveRecord := -1;
FDBOptions := cDBOptionsDef;
FColors.Free;
FColors := TKDBGridColors.Create(Self);
CellClass := TKDBGridCell;
CellPainterClass := TKDBGridCellPainter;
ColClass := TKDBGridCol;
RealizeColClass;
end;
destructor TKCustomDBGrid.Destroy;
begin
inherited;
FDataLink.Free;
end;
function TKCustomDBGrid.BeginRowDrag(var Origin: Integer;
const MousePt: TPoint): Boolean;
begin
// does nothing
Result := False;
end;
procedure TKCustomDBGrid.BeforeCellUpdate(ACol, ARow: Integer);
begin
if FDataLink.Active and not FDataLink.ReadOnly then
begin
InternalSetActiveRecord(ARow - FixedRows);
FDataLink.Edit;
FDataLink.Modified := True;
end;
end;
procedure TKCustomDBGrid.Changed;
begin
inherited;
FDataLink.Edit;
FDataLink.Modified := True;
end;
procedure TKCustomDBGrid.ClearCol(ACol: Integer);
begin
// does nothing
end;
procedure TKCustomDBGrid.ClearGrid;
begin
// does nothing
end;
procedure TKCustomDBGrid.ClearRow(ARow: Integer);
begin
// does nothing
end;
procedure TKCustomDBGrid.ColMoved(FromIndex, ToIndex: Integer);
begin
inherited;
DataChanged;
end;
procedure TKCustomDBGrid.Commit;
begin
if Assigned(FDataLink.DataSet) and FDataLink.Modified then
FDataLink.DataSet.Post;
end;
function TKCustomDBGrid.CustomSortRows(ByCol: Integer; var SortMode: TKGridSortMode): Boolean;
begin
if Assigned(FDataLink.DataSet) and FDataLink.Active then
begin
Commit;
Result := inherited CustomSortRows(ByCol, SortMode);
if Result then
ClearSortModeVert
else
SortMode := smNone;
end else
begin
ClearSortModeHorz;
Result := False;
end;
end;
procedure TKCustomDBGrid.DataChanged;
var
I, Index, J, Tmp, LastRow: Integer;
S: WideString;
ADataType: TFieldType;
Cell: TKGridCell;
begin
if Assigned(FDataLink.DataSet) and not Flag(cGF_DBDataUpdating) then
begin
FlagSet(cGF_DBDataUpdating);
try
if FDataLink.Active then
begin
RowCount := FixedRows + FDataLink.DataSet.RecordCount;
if FixedCols + FDataLink.DataSet.FieldCount <> ColCount then
begin
ClearSortMode;
ColCount := FixedCols + FDataLink.DataSet.FieldCount;
for I := 0 to ColCount - 1 do
Cols[I].InitialPos := I;
end;
if FDataLink.DataSet.RecNo >= 1 then
begin
Tmp := FixedRows + FDataLink.DataSet.RecNo - 1;
if not Flag(cGF_DBInternalChanging) and (Row <> Tmp) then
begin
if dboAutoMoveRecord in FDBOptions then
Row := Tmp
else
EditorMode := False;
end;
end;
LastRow := Min(LastVisibleRow + 1, RowCount - 1);
// here memory only grows. I don't know if it is possible to make this more memory effective
FDataLink.BufferCount := Max(FDataLink.BufferCount, Max(LastRow, FDataLink.DataSet.RecNo - 1) + 1);
if (dboIndexFixedCol in FDBOptions) and (FixedCols > 0) then
begin
Cell := InternalGetCell(0, 0);
if Cell is TKDBGridCell then
TKDBGridCell(Cell).Text := SKDBGridIndex;
end;
Tmp := FDataLink.ActiveRecord;
try
for I := FixedCols to ColCount - 1 do
begin
Index := Cols[I].InitialPos;
if Index < ColCount then
begin
S := FDataLink.DataSet.FieldDefs[Index - FixedCols].Name;
ADataType := FDataLink.DataSet.FieldDefs[Index - FixedCols].DataType;
if Cols[I] is TKDBGridCol then
begin
TKDBGridCol(Cols[I]).FName := S;
TKDBGridCol(Cols[I]).FDataType := ADataType;
end;
if dboColNamesToHeader in FDBOptions then
begin
Cell := InternalGetCell(I, 0);
if Cell is TKDBGridCell then
TKDBGridCell(Cell).Text := S;
end;
if (dboAutoSizeBooleanCells in FDBOptions) and (ADataType = ftBoolean) then
begin
ColWidths[I] := cCheckBoxFrameSize + CellPainter.HPadding * 2;
Cols[I].CanResize := False;
end;
end;
end;
for J := TopRow to LastRow do
begin
FDataLink.ActiveRecord := J - FixedRows;
if (FDataLink.ActiveRecord <> Tmp) or not FDataLink.Modified then
for I := FixedCols to ColCount - 1 do
begin
Index := Cols[I].InitialPos;
if Index < ColCount then
begin
Cell := InternalGetCell(I, J);
if Cell is TKDBGridCell then
begin
TKDBGridCell(Cell).FieldToCell(FDataLink.DataSet.Fields[Index - FixedCols]);
if Assigned(TKDBGridCell(Cell).Graphic) then
begin
if dboAutoSizeImageCells in FDBOptions then
begin
if ColWidths[I] > 0 then
ColWidths[I] := Max(ColWidths[I], TKDBGridCell(Cell).Graphic.Width + CellPainter.GraphicHPadding * 2);
if RowHeights[J] > 0 then
RowHeights[J] := Max(RowHeights[J], TKDBGridCell(Cell).Graphic.Height + CellPainter.GraphicVPadding * 2);
end;
if dboImageHint in FDBOptions then
Cols[I].CellHint := True;
end;
end;
end;
end;
if (dboIndexFixedCol in FDBOptions) and (FixedCols > 0) then
begin
Cell := InternalGetCell(0, J);
if Cell is TKDBGridCell then
begin
TKDBGridCell(Cell).Text := IntToStr(J - FixedRows + 1);
if Cell is TKGridAttrTextCell then
TKGridAttrTextCell(Cell).HAlign := halRight;
end;
end;
end;
finally
FDataLink.ActiveRecord := Tmp;
end;
if dboIndicateActiveRecord in FDBOptions then
begin
if FDataLink.ActiveRecord <> FActiveRecord then
begin
if FActiveRecord >= 0 then
InvalidateRow(FActiveRecord + FixedRows);
FActiveRecord := FDataLink.ActiveRecord;
InvalidateRow(FActiveRecord + FixedRows);
end;
end;
end else
begin
RowCount := FixedRows + 1;
FMaxRow := FixedRows;
if dboDontClearFixedCells in FDBOptions then Tmp := FixedRows else Tmp := 0;
for I := 0 to ColCount - 1 do
begin
Cols[I].InitialPos := I;
if Cols[I] is TKDBGridCol then
begin
TKDBGridCol(Cols[I]).FName := '';
TKDBGridCol(Cols[I]).FDataType := ftUnknown;
end;
if not (dboDontClearFixedCells in FDBOptions) or (I >= FixedCols) then
begin
for J := Tmp to RowCount - 1 do
begin
Cell := InternalGetCell(I, J);
if Cell is TKDBGridCell then
TKDBGridCell(Cell).Clear;
end;
end;
end;
ClearSortMode;
FActiveRecord := -1;
end;
finally
FlagClear(cGF_DBDataUpdating);
end;
end;
end;
procedure TKCustomDBGrid.DataSetScrolled;
begin
DataChanged;
end;
procedure TKCustomDBGrid.DefaultEditorCreate(ACol, ARow: Integer; var AEditor: TWinControl);
begin
// create custom editors according to table column type
if Cols[ACol] is TKDBGridCol then
case TKDBGridCol(Cols[ACol]).DataType of
ftString, ftWideString, ftInteger, ftSmallInt, ftWord, ftLargeInt, ftFloat, ftCurrency, ftBcd:
begin
AEditor := TEdit.Create(nil);
end;
ftMemo
{$IF DEFINED(FPC) OR DEFINED(COMPILER10_UP)}
, ftWideMemo
{$IFEND}
:
begin
AEditor := TMemo.Create(nil);
end;
ftDate, ftTime, ftDateTime:
begin
AEditor := {$IFDEF FPC}TDateEdit{$ELSE}TDateTimePicker{$ENDIF}.Create(nil);
end;
ftBoolean:
begin
AEditor := TCheckBox.Create(nil);
end;
else
AEditor := nil;
end
else
AEditor := nil;
end;
procedure TKCustomDBGrid.DefaultEditorDataFromGrid(AEditor: TWinControl; ACol, ARow: Integer; var AssignText: Boolean);
begin
if Cols[ACol] is TKDBGridCol then
case TKDBGridCol(Cols[ACol]).DataType of
ftDate, ftTime, ftDateTime:
if AEditor is {$IFDEF FPC}TDateEdit{$ELSE}TDateTimePicker{$ENDIF} then
begin
{$IFDEF FPC}
TDateEdit(AEditor).Date :=
{$ELSE}
TDateTimePicker(AEditor).DateTime :=
{$ENDIF}
StrToDateTime(Cells[ACol, ARow]);
AssignText := False;
end;
ftCurrency, ftBcd:
if AEditor is TEdit then
begin
TEdit(AEditor).Text := CurrToStrF(StrToCurrDef(Cells[ACol, ARow], 0),
ffFixed, TKDBGridCol(Cols[ACol]).CurrencyFormat.CurrencyDecimals);
AssignText := False;
end;
ftBoolean:
if AEditor is TCheckBox then
begin
TCheckBox(AEditor).Checked := LowerCase(Cells[ACol, ARow]) = 'true';
AssignText := False;
end;
end;
end;
procedure TKCustomDBGrid.DefaultEditorDataToGrid(AEditor: TWinControl; ACol, ARow: Integer; var AssignText: Boolean);
var
I: Int64;
ADataType: TFieldType;
begin
if Cols[ACol] is TKDBGridCol then
begin
ADataType := TKDBGridCol(Cols[ACol]).DataType;
case ADataType of
ftDate, ftTime, ftDateTime:
if AEditor is {$IFDEF FPC}TDateEdit{$ELSE}TDateTimePicker{$ENDIF} then
begin
Cells[ACol, ARow] := DateTimeToStr(
{$IFDEF FPC}
TDateEdit(AEditor).Date);
{$ELSE}
TDateTimePicker(AEditor).DateTime);
{$ENDIF}
AssignText := False;
end;
ftLargeInt, ftInteger, ftSmallInt, ftWord:
if AEditor is TEdit then
begin
I := StrToInt64Def(TEdit(AEditor).Text, 0);
case ADataType of
ftInteger: I := MinMax(I, -MaxInt - 1, MaxInt);
ftSmallInt: I := MinMax(I, -32768, 32767);
ftWord: I := MinMax(I, 0, 65535);
end;
Cells[ACol, ARow] := IntToStr(I);
AssignText := False;
end;
ftFloat:
if AEditor is TEdit then
begin
Cells[ACol, ARow] := FloatToStr(StrToFloatDef(TEdit(AEditor).Text, 0));
AssignText := False;
end;
ftCurrency, ftBcd:
if AEditor is TEdit then
begin
Cells[ACol, ARow] := CurrToStrF(StrToCurrDef(TEdit(AEditor).Text, 0),
ffFixed, TKDBGridCol(Cols[ACol]).CurrencyFormat.CurrencyDecimals);
AssignText := False;
end;
ftBoolean:
if AEditor is TCheckBox then
begin
if TCheckBox(AEditor).Checked then
Cells[ACol, ARow] := 'True'
else
Cells[ACol, ARow] := 'False';
AssignText := False;
end;
end;
end;
end;
procedure TKCustomDBGrid.DefaultEditorResize(AEditor: TWinControl; ACol, ARow: Integer;
var ARect: TRect);
begin
if Cols[ACol] is TKDBGridCol then
case TKDBGridCol(Cols[ACol]).DataType of
ftBoolean:
{$IFNDEF LCLGTK2}
if AEditor is TCheckBox then
Inc(ARect.Left, 2);
{$ENDIF}
end;
end;
procedure TKCustomDBGrid.DefaultEditorSelect(AEditor: TWinControl;
ACol, ARow: Integer; SelectAll, CaretToLeft, SelectedByMouse: Boolean);
begin
inherited;
if Cols[ACol] is TKDBGridCol then
case TKDBGridCol(Cols[ACol]).DataType of
ftBoolean:
if (AEditor is TCheckBox) and SelectedByMouse then
ThroughClick := True;
end;
end;
procedure TKCustomDBGrid.DefaultMouseCellHint(ACol, ARow: Integer;
AShow: Boolean);
var
R: TRect;
Extent: TPoint;
ACell: TKGridCell;
AGraphic: TGraphic;
begin
if ColValid(ACol) and Cols[ACol].CellHint then
begin
ACell := Cell[ACol, ARow];
if ACell is TKDBGridCell then
begin
AGraphic := TKDBGridCell(ACell).Graphic;
if AGraphic <> nil then
begin
if AShow then
begin
if (ARow >= FixedRows) and ((ARow <> FEditorCell.Row) or (ACol <> FEditorCell.Col) or not EditorMode) and
CellRect(ACol, ARow, R, True) then
begin
Extent := MeasureCell(ACol, ARow, R, GetDrawState(ACol, ARow, HasFocus), mpCellExtent);
if (Extent.X > R.Right - R.Left) or (Extent.Y > R.Bottom - R.Top) then
begin
FreeAndNil(FHint);
FHint := TKGraphicHint.Create(nil);
TKGraphicHint(FHint).Graphic := AGraphic;
Inc(R.Left, 10);
Inc(R.Top, 10);
FHint.ShowAt(ClientToScreen(R.TopLeft));
end;
end;
end else
FreeAndNil(FHint);
end else
inherited;
end else
inherited;
end else
FreeAndNil(FHint);
end;
procedure TKCustomDBGrid.DeleteCols(At, Count: Integer);
begin
// does nothing
end;
procedure TKCustomDBGrid.DeleteRow(At: Integer);
begin
if Assigned(FDataLink.DataSet) and RowValid(At) then
begin
InternalSetActiveRecord(At - FixedRows);
FDataLink.DataSet.Delete;
end;
end;
procedure TKCustomDBGrid.DeleteRows(At, Count: Integer);
begin
// does nothing
end;
function TKCustomDBGrid.EditorCreate(ACol, ARow: Integer): TWinControl;
begin
if Assigned(FDataLink.DataSet) and FDataLink.Active and
not FDataLink.ReadOnly and (FDataLink.ActiveRecord = ARow - FixedRows) then
Result := inherited EditorCreate(ACol, ARow)
else
Result := nil;
end;
function TKCustomDBGrid.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
procedure TKCustomDBGrid.InsertCols(At, Count: Integer);
begin
// does nothing
end;
procedure TKCustomDBGrid.InsertRow(At: Integer);
begin
if Assigned(FDataLink.DataSet) and RowValid(At) then
begin
InternalSetActiveRecord(At - FixedRows);
FDataLink.DataSet.Insert;
end;
end;
procedure TKCustomDBGrid.InsertRows(At, Count: Integer);
begin
// does nothing
end;
function TKCustomDBGrid.InsertSortedCol(out ByRow, ACol: Integer): Boolean;
begin
// does nothing
Result := False;
end;
function TKCustomDBGrid.InsertSortedRow(out ByCol, ARow: Integer): Boolean;
begin
// does nothing
Result := False;
end;
procedure TKCustomDBGrid.InternalSetActiveRecord(Value: Integer);
var
IsEditorMode, IsEditorModeActive: Boolean;
begin
if Assigned(FDataLink.DataSet) and (Value <> FDataLink.ActiveRecord) and
not Flag(cGF_EditorUpdating or cGF_DBInternalChanging) then
begin
FlagSet(cGF_DBInternalChanging);
try
IsEditorMode := EditorMode;
IsEditorModeActive := Flag(cGF_EditorModeActive);
EditorMode := False;
Commit;
FDataLink.MoveBy(Value - FDataLink.ActiveRecord);
EditorMode := IsEditorMode;
if IsEditorModeActive then FlagSet(cGF_EditorModeActive);
finally
FlagClear(cGF_DBInternalChanging);
end;
end;
end;
procedure TKCustomDBGrid.InternalSetColCount(Value: Integer);
begin
if not FDataLink.Active or Flag(cGF_DBDataUpdating) then
inherited;
end;
procedure TKCustomDBGrid.InternalSetFixedCols(Value: Integer);
begin
if not FDataLink.Active and not Flag(cGF_DBDataUpdating) then
begin
FlagSet(cGF_DBDataUpdating);
try
inherited;
finally
FlagClear(cGF_DBDataUpdating);
end;
end;
end;
procedure TKCustomDBGrid.InternalSetFixedRows(Value: Integer);
begin
if not FDataLink.Active and not Flag(cGF_DBDataUpdating) then
begin
FlagSet(cGF_DBDataUpdating);
try
inherited;
finally
FlagClear(cGF_DBDataUpdating);
end;
end;
end;
procedure TKCustomDBGrid.InternalSetRowCount(Value: Integer);
begin
if not FDataLink.Active or Flag(cGF_DBDataUpdating) then
inherited;
end;
function TKCustomDBGrid.InternalUpdateVirtualGrid: Boolean;
begin
Result := False;
end;
procedure TKCustomDBGrid.MoveRow(FromIndex, ToIndex: Integer);
begin
// does nothing
end;
procedure TKCustomDBGrid.RecordChanged;
var
ARow, I, Index: Integer;
Cell: TKGridCell;
begin
if Assigned(FDataLink.DataSet) and not Flag(cGF_DBDataUpdating) then
begin
FlagSet(cGF_DBDataUpdating);
try
ARow := FDataLink.ActiveRecord + FixedRows;
if Assigned(FDataLink.DataSet) and (ARow < RowCount) then
begin
for I := FixedCols to ColCount - 1 do
begin
Index := Cols[I].InitialPos;
Cell := InternalGetCell(I, ARow);
if Cell is TKDBGridCell then
TKDBGridCell(Cell).FieldToCell(FDataLink.DataSet.Fields[Index - FixedCols]);
end;
end;
finally
FlagClear(cGF_DBDataUpdating);
end;
end;
end;
function TKCustomDBGrid.SelectCell(ACol, ARow: Integer): Boolean;
begin
Result := inherited SelectCell(ACol, ARow);
if Result and (dboAutoMoveRecord in FDBOptions) then
InternalSetActiveRecord(ARow - FixedRows);
end;
procedure TKCustomDBGrid.SetDataSource(Value: TDataSource);
begin
if Assigned(FDataLink.DataSource) then FDataLink.DataSource.FreeNotification(Self);
FDataLink.DataSource := Value;
end;
procedure TKCustomDBGrid.SetDBOptions(const Value: TKDBGridOptions);
begin
if Value <> FDBOptions then
begin
FDBOptions := Value;
DataChanged;
end;
end;
procedure TKCustomDBGrid.TopLeftChanged;
begin
inherited;
DataChanged;
end;
procedure TKCustomDBGrid.UpdateData;
var
ARow, I, Index: Integer;
Cell: TKGridCell;
begin
if Assigned(FDataLink.DataSet) and FDataLink.Modified and not Flag(cGF_DBDataUpdating) then
begin
FlagSet(cGF_DBDataUpdating);
try
ARow := FDataLink.ActiveRecord + FixedRows;
for I := FixedCols to ColCount - 1 do
begin
Index := Cols[I].InitialPos;
Cell := InternalGetCell(I, ARow);
if Cell is TKDBGridCell then
TKDBGridCell(Cell).FieldFromCell(FDataLink.DataSet.Fields[Index - FixedCols]);
end;
finally
FlagClear(cGF_DBDataUpdating);
end;
end;
end;
procedure TKCustomDBGrid.UpdateSize;
begin
inherited;
DataChanged;
end;
end.