{*******************************************************************} { } { ExpressWeb Framework by Developer Express } { Web Data Library } { } { Copyright (c) 2000-2008 Developer Express Inc. } { ALL RIGHTS RESERVED } { } { The entire contents of this file is protected by U.S. and } { International Copyright Laws. Unauthorized reproduction, } { reverse-engineering, and distribution of all or any portion of } { the code contained in this file is strictly prohibited and may } { result in severe civil and criminal penalties and will be } { prosecuted to the maximum extent possible under the law. } { } { RESTRICTIONS } { } { THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES } { (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE } { SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS } { LICENSED TO DISTRIBUTE THE EXPRESSWEB FRAMEWORK AND ALL } { ACCOMPANYING VCL CLASSES AS PART OF AN EXECUTABLE WEB } { APPLICATION ONLY. } { } { THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED } { FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE } { COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE } { AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT } { AND PERMISSION FROM DEVELOPER EXPRESS INC. } { } { CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON } { ADDITIONAL RESTRICTIONS. } { } {*******************************************************************} unit cxWebData; {$I cxVer.inc} interface uses Classes, TypInfo, SysUtils, DB, {$IFDEF VCL} Graphics, {$ENDIF} cxWebIntf, cxWebClasses, cxWebTypes, cxWebRender; const scxSortingAction = 'SORT'; scxGroupingAction = 'GROUP'; scxUnGroupingAction = 'UNGROUP'; scxExpandingAction = 'EXPAND'; scxDeleteAction = 'DELETE'; scxStartEditAction = 'STARTEDIT'; scxPostEditAction = 'POSTEDIT'; scxCancelEditAction = 'CANCELEDIT'; scxCancelInsertAction = 'CANCELINSERT'; scxInsertAction = 'INSERT'; scxRefreshAction = 'REFRESH'; scxMoveToAction = 'MOVETO'; scxMoveByAction = 'MOVEBY'; scxInfoDelimiter = ';'; type TcxGridDataControllerChange = (dccGlobal, dccItemAdded, dccItemRemoved, dccIndexesChanged); TcxCustomWebDataField = class; TcxStdWebDataField = class; TcxCustomWebDataSource = class; TcxStdWebDataSource = class; IcxWebDataSourceSupport = interface ['{48715446-DDBD-4F20-BF6E-7332FF53B112}'] function GetDataSource: TcxCustomWebDataSource; procedure SetDataSource(Value: TcxCustomWebDataSource); procedure ChangedDataLayout(Sender: TcxCustomWebDataSource); procedure UpdateData(Sender: TcxCustomWebDataSource); property DataSource: TcxCustomWebDataSource read GetDataSource write SetDataSource; end; IcxDataSetSupport = interface ['{94D3826C-84A4-4535-8D51-7951A06C533A}'] function GetDataSet: TDataSet; procedure SetDataSet(Value: TDataSet); property DataSet: TDataSet read GetDataSet write SetDataSet; end; IcxWebViewDataSupport = interface ['{66CB3E4C-915D-4479-ACFE-BC9CB4104216}'] function GetFirstVisibleRow: Integer; function GetPageSize: Integer; procedure SetData(Value: Variant; DisplayText: string); end; TcxWebDataType = (dtValue, dtText, dtKey); TcxWebDataTypes = set of TcxWebDataType; IcxWebUpdateDataSupport = interface ['{C104D95D-C04B-4E35-949A-96EFF281A711}'] function CanGetData: Boolean; function GetData: Variant; function GetDataTypes: TcxWebDataTypes; end; TcxAbstractWebDataBinding = class(TPersistent) private FComponent: TComponent; protected function GetDataSource: TcxCustomWebDataSource; virtual; abstract; public constructor Create(AComponent: TComponent); virtual; procedure Assign(Source: TPersistent); override; property Component: TComponent read FComponent; property DataSource: TcxCustomWebDataSource read GetDataSource; end; TcxCustomWebDataBinding = class(TcxAbstractWebDataBinding) private FDataSource: TcxCustomWebDataSource; protected function GetFieldIndex: Integer; virtual; { IcxWebViewDataSupport } function GetFirstVisibleRow: Integer; virtual; function GetPageSize: Integer; virtual; { Data control render } procedure WriteControlScripts(HTMLTextBuilder: TcxHTMLTextBuilder; AControlClass: string); virtual; { IcxWebDataSourceSupport } function GetDataSource: TcxCustomWebDataSource; override; procedure SetDataSource(Value: TcxCustomWebDataSource); virtual; procedure ChangedDataLayout(Sender: TcxCustomWebDataSource); virtual; procedure UpdateData(Sender: TcxCustomWebDataSource); virtual; public destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure Loaded; virtual; procedure Notification(AComponent: TComponent; Operation: TOperation); virtual; published property DataSource: TcxCustomWebDataSource read GetDataSource write SetDataSource; end; TcxDataFieldHelper = class private FField: TcxCustomWebDataField; function GetDataSource: TcxCustomWebDataSource; function GetIndex: Integer; protected function GetScriptData(ARecord: Integer): string; virtual; function ValidateValue(var Value: Variant): Boolean; virtual; function ValidateValueType(AType: TcxWebDataTypes): Boolean; virtual; public constructor Create(AField: TcxCustomWebDataField); property DataSource: TcxCustomWebDataSource read GetDataSource; property Field: TcxCustomWebDataField read FField; property Index: Integer read GetIndex; end; TcxDataFieldHelperClass = class of TcxDataFieldHelper; TcxStringFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; end; TcxIntegerFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; end; TcxCurrencyFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; end; TcxFloatFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; end; TcxDateTimeFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; end; TcxBooleanFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; end; TcxImageFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; function ValidateValueType(AType: TcxWebDataTypes): Boolean; override; end; TcxMemoFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; function ValidateValueType(AType: TcxWebDataTypes): Boolean; override; end; TcxBinaryFieldHelper = class(TcxDataFieldHelper) protected function GetScriptData(ARecord: Integer): string; override; function ValidateValue(var Value: Variant): Boolean; override; function ValidateValueType(AType: TcxWebDataTypes): Boolean; override; end; TcxCustomWebDataField = class(TCollectionItem) private FDisplayLabel: string; FFieldHelper: TcxDataFieldHelper; FName: string; FRequired: Boolean; procedure SetName(Value: string); protected function UniqueName: string; function GetDisplayName: string; override; function DataSource: TcxCustomWebDataSource; overload; virtual; public constructor Create(Collection: TCollection); override; destructor Destroy; override; function FieldHelper: TcxDataFieldHelper; function GetScriptData(ARecord: Integer): string; function ValidateValue(var AValue: Variant): Boolean; function ValidateValueType(AType: TcxWebDataTypes): Boolean; published property DisplayLabel: string read FDisplayLabel write FDisplayLabel; property Name: string read FName write SetName; property Required: Boolean read FRequired write FRequired; end; TcxCustomWebDataFieldClass = class of TcxCustomWebDataField; TcxCustomWebDataFields = class(TCollection) private FDataSource: TcxCustomWebDataSource; function GetItem(Index: Integer): TcxCustomWebDataField; procedure SetItem(Index: Integer; Value: TcxCustomWebDataField); protected function GetOwner: TPersistent; override; class function FieldClass: TcxCustomWebDataFieldClass; virtual; public constructor Create(ADataSource: TcxCustomWebDataSource); function Add: TcxCustomWebDataField; function DataSource: TcxCustomWebDataSource; overload; virtual; property Items[Index: Integer]: TcxCustomWebDataField read GetItem write SetItem; default; end; TcxStdWebDataField = class(TcxCustomWebDataField) private FFieldName: string; function GetDataSet: TDataSet; procedure SetFieldName(const Value: string); protected function DataSource: TcxStdWebDataSource; reintroduce; overload; public property DataSet: TDataSet read GetDataSet; property FieldName: string read FFieldName write SetFieldName; end; TcxStdWebDataFields = class(TcxCustomWebDataFields) private function GetItem(Index: Integer): TcxStdWebDataField; procedure SetItem(Index: Integer; Value: TcxStdWebDataField); protected class function FieldClass: TcxCustomWebDataFieldClass; override; public function Add: TcxStdWebDataField; function DataSource: TcxStdWebDataSource; reintroduce; overload; property Items[Index: Integer]: TcxStdWebDataField read GetItem write SetItem; default; end; TcxWebDataSourceEvent = (dseOnAfterSort, dseOnAfterGroup, dseOnAfterUngroup, dseOnAfterExpand, dseOnAfterMove, dseOnBeforeSort, dseOnBeforeGroup, dseOnBeforeUngroup, dseOnBeforeExpand, dseOnBeforeMove, dseOnBeforeDelete, dseOnBeforeInsert, dseOnBeforeStartEdit, dseOnBeforePostEdit, dseOnBeforeCancelEdit, dseOnBeforeRefresh); TcxWebDataSourceEventsHelper = class(TcxWebScriptEventsHelper) protected function EventName(const AEvent: Integer): string; override; function EventProcParams(const AEvent: Integer): string; override; function ScriptObject: string; override; public function EventTypeInfo: PTypeInfo; override; end; TcxWebDataSortOrder = (wsoNone, wsoAscending, wsoDescending); TcxUpdateType = (utLayout, utData); TcxWebDataSourceState = (browsing, editing, inserting); TcxAllowingDataEvent = procedure (Sender: TObject; ARowIndex: Integer; var AllowAction: Boolean) of object; TcxDataEvent = procedure (Sender: TObject; ARowIndex: Integer) of object; TcxSetInsertValueEvent = procedure(Sender: TObject; AItemIndex, ARowIndex: Integer; var AValue: Variant; var CanSet: Boolean) of object; TcxSetEditValueEvent = procedure (Sender: TObject; AItemIndex, ARowIndex: Integer; var AValue: Variant; var CanSet: Boolean) of object; TcxCustomWebDataSource = class(TcxWebComponent) private FAllowEditing: Boolean; FFields: TcxCustomWebDataFields; FInsertingValues: array of Variant; FIsEditing: Boolean; FIsInserting: Boolean; FKeyFieldName: string; FLoadAllRecords: Boolean; FUpdateLock: Integer; FClientsList: TList; FOnAfterPost: TcxDataEvent; FOnBeforePost: TcxAllowingDataEvent; FOnCancelEdit: TcxDataEvent; FOnDeleted: TcxDataEvent; FOnDeleting: TcxAllowingDataEvent; FOnInserted: TcxDataEvent; FOnInserting: TcxAllowingDataEvent; FOnScrolled: TcxDataEvent; FOnScrolling: TcxAllowingDataEvent; FOnSetInsertValue: TcxSetInsertValueEvent; FOnSetEditValue: TcxSetEditValueEvent; FOnStartEdit: TcxAllowingDataEvent; function GetClient(Index: Integer): TComponent; function GetClientCount: Integer; function GetFullName: string; function GetState: TcxWebDataSourceState; procedure SetAllowEditing(Value: Boolean); procedure SetIsEditing(Value: Boolean); procedure SetIsInserting(Value: Boolean); procedure SetKeyFieldName(Value: string); { Action operations } procedure WebDelete(const AParameters: TcxActionParameters); virtual; procedure WebStartEdit(const AParameters: TcxActionParameters); virtual; procedure WebPostEdit(const AParameters: TcxActionParameters); virtual; procedure WebCancelEdit(const AParameters: TcxActionParameters); virtual; procedure WebInsert(const AParameters: TcxActionParameters); virtual; procedure WebRefresh(const AParameters: TcxActionParameters); virtual; procedure WebMoveTo(const AParameters: TcxActionParameters); virtual; procedure WebMoveBy(const AParameters: TcxActionParameters); virtual; protected procedure Loaded; override; function CanEdit: Boolean; virtual; function GetAllowEditing: Boolean; virtual; function GetAllowExpanding: Boolean; virtual; function GetAllowGrouping: Boolean; virtual; function GetAllowSorting: Boolean; virtual; function GetKeyFieldName: string; virtual; { actions } procedure DoAfterPerformActions; override; procedure RegisterActions; override; { events } function GetWebEventsHelper: TcxWebDataSourceEventsHelper; class function GetWebEventsHelperClass: TcxWebEventsHelperClass; override; property WebEventsHelper: TcxWebDataSourceEventsHelper read GetWebEventsHelper; { values } function CanSetValues: Boolean; override; procedure DoAfterSetValues; override; procedure DoSetValues; override; procedure RegisterValues; override; procedure SynchronizeSelection; virtual; procedure SynchronizeInsertingValues; virtual; { Renderers } procedure RegisterRenderers; override; { Fields } function GetFields: TcxCustomWebDataFields; overload; virtual; procedure SetFields(Value: TcxCustomWebDataFields); { Notification } procedure BeginUpdate; procedure CancelUpdate; procedure EndUpdate; property UpdateLock: Integer read FUpdateLock; procedure DataNotification(AUpdateType: TcxUpdateType); virtual; function NeedUpdateFields: Boolean; virtual; procedure UpdateDefaultFields; virtual; procedure UpdateDataLayout; virtual; procedure ChangedData(AClientName: string); virtual; { Data layout } function GetFocusedRowIndex: Integer; virtual; function GetRecordCount: Integer; virtual; function GetRowCount: Integer; virtual; function GetDisplayText(ARecordIndex, AItemIndex: Integer): string; virtual; function GetValue(ARecordIndex, AItemIndex: Integer): Variant; virtual; procedure SetFocusedRowIndex(Value: Integer); virtual; procedure SetRecordCount(Value: Integer); virtual; procedure SetValue(ARecordIndex, AItemIndex: Integer; const Value: Variant); virtual; { Inserting values } procedure StoreInsertingValues; virtual; procedure RestoreInsertingValues; virtual; function GetInsertingValue(Index: Integer): Variant; procedure SetInsertingValue(Index: Integer; Value: Variant); function InsertingValuesCount: Integer; { Key field} function KeyField: TcxCustomWebDataField; function CheckKey(ARowIndex: Integer; AKey: string; ALevel: Integer): Boolean; function FindKey(AKey: string; ALevel: Integer): Integer; function RecordKeyValue(ARecord: Integer): string; function IsKeyNeeded(ARowIndex: Integer): Boolean; function IsDesigning: Boolean; property IsEditing: Boolean read FIsEditing write SetIsEditing; property IsInserting: Boolean read FIsInserting write SetIsInserting; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; { Data layout } function CheckRowIndex(ARowIndex: Integer): Boolean; function ItemHelperClass(AItemIndex: Integer): TcxDataFieldHelperClass; virtual; function FieldByName(const Name: string): TcxCustomWebDataField; virtual; function GetRowDisplayText(RowIndex: Integer; ItemIndex: Integer): string; virtual; function GetRowValue(RowIndex: Integer; ItemIndex: Integer): Variant; virtual; function GetRowExpanded(RowIndex: Integer): Boolean; virtual; function GetRowLevel(RowIndex: Integer): Integer; virtual; function GetRowRecord(RowIndex: Integer): Integer; virtual; function GetGroupingItemCount: Integer; virtual; function GetSortingItemCount: Integer; virtual; function GetItemGroupIndex(ItemIndex: Integer): Integer; virtual; function GetItemSortOrder(ItemIndex: Integer): TcxWebDataSortOrder; virtual; function GetGroupingItemIndex(Item: Integer): Integer; virtual; function GetSortingItemIndex(Item: Integer): Integer; virtual; procedure ClearGrouping; virtual; procedure ClearSorting; virtual; procedure FullCollapse; virtual; procedure FullExpand; virtual; property DisplayTexts[RecordIndex, ItemIndex: Integer]: string read GetDisplayText; property FocusedRowIndex: Integer read GetFocusedRowIndex write SetFocusedRowIndex; property RecordCount: Integer read GetRecordCount; property RowCount: Integer read GetRowCount; property Values[RecordIndex, ItemIndex: Integer]: Variant read GetValue write SetValue; { Data clients } procedure RegisterClient(Client: TComponent); procedure UnRegisterClient(Client: TComponent); property ClientCount: Integer read GetClientCount; property Clients[Index: Integer]: TComponent read GetClient; { Data operations } procedure CancelEdit; virtual; procedure DeleteRecord(ARowIndex: Integer); virtual; procedure InsertRecord(ARowIndex: Integer); virtual; procedure EditRecord(ARowIndex: Integer); virtual; procedure Expand(ARowIndex: Integer; AExpanded, ARecursive: Boolean); virtual; procedure Group(GroupField, GroupIndex: Integer); virtual; procedure PostEdit(APriorControlName: string); virtual; procedure SetEditValue(AItemIndex: Integer; AValue: Variant; AType: TcxWebDataTypes); virtual; procedure Sort(SortIndex: Integer; SortOrder: TcxWebDataSortOrder); virtual; procedure UnGroup(UnGroupIndex: Integer); virtual; procedure Refresh; virtual; property AllowExpanding: Boolean read GetAllowExpanding; property AllowGrouping: Boolean read GetAllowGrouping; property AllowSorting: Boolean read GetAllowSorting; property Fields: TcxCustomWebDataFields read GetFields write SetFields; property FullName: string read GetFullName; property State: TcxWebDataSourceState read GetState; published property AllowEditing: Boolean read GetAllowEditing write SetAllowEditing default True; property KeyFieldName: string read GetKeyFieldName write SetKeyFieldName; property LoadAllRecords: Boolean read FLoadAllRecords write FLoadAllRecords default False; // Event properties property OnAfterPost: TcxDataEvent read FOnAfterPost write FOnAfterPost; property OnBeforePost: TcxAllowingDataEvent read FOnBeforePost write FOnBeforePost; property OnCancelEdit: TcxDataEvent read FOnCancelEdit write FOnCancelEdit; property OnDeleted: TcxDataEvent read FOnDeleted write FOnDeleted; property OnDeleting: TcxAllowingDataEvent read FOnDeleting write FOnDeleting; property OnInserted: TcxDataEvent read FOnInserted write FOnInserted; property OnInserting: TcxAllowingDataEvent read FOnInserting write FOnInserting; property OnScrolled: TcxDataEvent read FOnScrolled write FOnScrolled; property OnScrolling: TcxAllowingDataEvent read FOnScrolling write FOnScrolling; property OnSetInsertValue: TcxSetInsertValueEvent read FOnSetInsertValue write FOnSetInsertValue; property OnSetEditValue: TcxSetEditValueEvent read FOnSetEditValue write FOnSetEditValue; property OnStartEdit: TcxAllowingDataEvent read FOnStartEdit write FOnStartEdit; end; TcxCustomWebDataSourceRenderer = class(TcxWebComponentRenderer) protected function GetWebDataSource: TcxCustomWebDataSource; overload; virtual; function IsLoadAllRecordsMode: Boolean; virtual; procedure WriteData; virtual; procedure WriteHandlers; virtual; procedure WriteKeys; virtual; public class procedure GetScriptFiles(AList: TStrings); override; procedure WriteHiddenFormElements; override; procedure WriteScripts; override; class procedure WriteClassScripts(AHTMLTextBuilder: TcxHTMLTextBuilder); override; property WebDataSource: TcxCustomWebDataSource read GetWebDataSource; end; TcxCustomWebDataSourceNS4Renderer = class(TcxCustomWebDataSourceRenderer) protected function IsLoadAllRecordsMode: Boolean; override; public class function IsBrowserSupported(AWebBrowser: TcxWebBrowserClass): Boolean; override; end; TcxCustomWebDataSourceOperaRenderer = class(TcxCustomWebDataSourceNS4Renderer) public class function IsBrowserSupported(AWebBrowser: TcxWebBrowserClass): Boolean; override; end; TcxWebDataLink = class(TDataLink) private FWebDataSource: TcxCustomWebDataSource; protected procedure ActiveChanged; override; procedure DataSetChanged; override; public property WebDataSource: TcxCustomWebDataSource read FWebDataSource; end; TcxStdWebDataSource = class(TcxCustomWebDataSource, IcxDataSetSupport) private FDataSource: TDataSource; FDataLink: TcxWebDataLink; protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; function CanEdit: Boolean; override; function GetItemField(AItemName: string): TField; { IcxDataSetSupport } function GetDataSet: TDataSet; procedure SetDataSet(Value: TDataSet); { fields } function GetFields: TcxStdWebDataFields; reintroduce; overload; procedure SetFields(Value: TcxStdWebDataFields); { values } procedure DoSetValues; override; procedure RegisterValues; override; { actions } procedure RegisterActions; override; { renderes } procedure RegisterRenderers; override; { values } procedure SynchronizeSelection; override; { Data notification } procedure DataNotification(AUpdateType: TcxUpdateType); override; function NeedUpdateFields: Boolean; override; procedure UpdateDefaultFields; override; { Data layout } function GetFocusedRowIndex: Integer; override; function GetDisplayText(ARecordIndex, AItemIndex: Integer): string; override; function GetRecordCount: Integer; override; function GetValue(ARecordIndex, AItemIndex: Integer): Variant; override; procedure SetFocusedRowIndex(Value: Integer); override; procedure SetValue(ARecordIndex, AItemIndex: Integer; const Value: Variant); override; property DataSource: TDataSource read FDataSource; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; { Data operations } procedure DeleteRecord(ARowIndex: Integer); override; procedure InsertRecord(ARowIndex: Integer); override; procedure EditRecord(ARowIndex: Integer); override; procedure PostEdit(APriorControlName: string); override; procedure SetEditValue(AItemIndex: Integer; AValue: Variant; AType: TcxWebDataTypes); override; { Data layout } function ItemHelperClass(AItemIndex: Integer): TcxDataFieldHelperClass; override; property Fields: TcxStdWebDataFields read GetFields write SetFields; published property DataSet: TDataSet read GetDataSet write SetDataSet; end; implementation uses DateUtils, StrUtils, Math, Variants, cxWebDataCtrls, cxWebUtils, cxWebDataUtils, cxWebFileCacheManager, cxWebStrs, cxWebConsts; { TcxAbstractWebDataBinding } constructor TcxAbstractWebDataBinding.Create(AComponent: TComponent); begin inherited Create; FComponent := AComponent; end; procedure TcxAbstractWebDataBinding.Assign(Source: TPersistent); begin if not (Source is TcxAbstractWebDataBinding) then inherited; end; { TcxCustomWebDataBinding } destructor TcxCustomWebDataBinding.Destroy; begin DataSource := nil; inherited Destroy; end; function TcxCustomWebDataBinding.GetFieldIndex: Integer; begin Result := -1; end; function TcxCustomWebDataBinding.GetFirstVisibleRow: Integer; begin Result := -1; end; function TcxCustomWebDataBinding.GetPageSize: Integer; begin Result := -1; end; procedure TcxCustomWebDataBinding.WriteControlScripts(HTMLTextBuilder: TcxHTMLTextBuilder; AControlClass: string); begin HTMLTextBuilder.WriteText(Format('_DataControl = %s()', [AControlClass])); HTMLTextBuilder.WriteText(Format(' _DataControl.Name = "%s";', [Component.Name])); HTMLTextBuilder.WriteText(Format(' _DataControl.DataControllerName = "%s";', [DataSource.FullName])); HTMLTextBuilder.WriteText(Format(' _DataControl.FieldIndex = %d;', [GetFieldIndex])); HTMLTextBuilder.WriteText(Format(' _DataControl.PageSize = %d;', [GetPageSize])); HTMLTextBuilder.WriteText(Format(' _DataControl.FirstVisibleRow = %d;', [GetFirstVisibleRow])); end; function TcxCustomWebDataBinding.GetDataSource: TcxCustomWebDataSource; begin Result := FDataSource; end; procedure TcxCustomWebDataBinding.SetDataSource(Value: TcxCustomWebDataSource); begin if FDataSource <> Value then begin if (FDataSource <> nil) and not (csDestroying in FDataSource.ComponentState) then begin FDataSource.UnRegisterClient(Component); FDataSource.RemoveFreeNotification(Component); end; FDataSource := Value; if FDataSource <> nil then begin FDataSource.FreeNotification(Component); FDataSource.RegisterClient(Component); end; if not (csDestroying in Component.ComponentState) then ChangedDataLayout(FDataSource); end; end; procedure TcxCustomWebDataBinding.ChangedDataLayout(Sender: TcxCustomWebDataSource); begin end; procedure TcxCustomWebDataBinding.UpdateData(Sender: TcxCustomWebDataSource); begin end; procedure TcxCustomWebDataBinding.Assign(Source: TPersistent); begin if Source is TcxCustomWebDataBinding then DataSource := TcxCustomWebDataBinding(Source).DataSource else inherited; end; procedure TcxCustomWebDataBinding.Loaded; begin if DataSource = nil then ChangedDataLayout(DataSource); end; procedure TcxCustomWebDataBinding.Notification(AComponent: TComponent; Operation: TOperation); begin if (Operation = opRemove) and (AComponent = DataSource) then DataSource := nil; end; { TcxDataFieldHelper } constructor TcxDataFieldHelper.Create(AField: TcxCustomWebDataField); begin FField := AField; end; function TcxDataFieldHelper.GetDataSource: TcxCustomWebDataSource; begin Result := Field.DataSource; end; function TcxDataFieldHelper.GetIndex: Integer; begin Result := Field.Index; end; function TcxDataFieldHelper.ValidateValue(var Value: Variant): Boolean; begin Result := True; end; function TcxDataFieldHelper.ValidateValueType(AType: TcxWebDataTypes): Boolean; begin Result := dtText in AType; end; function TcxDataFieldHelper.GetScriptData(ARecord: Integer): string; begin Result := '"Unknown format"'; end; { TcxStringFieldHelper } function TcxStringFieldHelper.ValidateValue(var Value: Variant): Boolean; begin if VarIsType(Value, varString) then Result := True else Result := False; end; function TcxStringFieldHelper.GetScriptData(ARecord: Integer): string; begin Result := Format('["%s"]', [ScriptString(DataSource.DisplayTexts[ARecord, Index])]); end; { TcxIntegerFieldHelper } function TcxIntegerFieldHelper.ValidateValue(var Value: Variant): Boolean; var Dummy: Integer; begin if VarIsType(Value, [varInteger, varShortInt, varByte, varWord, varLongWord, varInt64]) then Result := True else if VarIsType(Value, varString) then begin if TryStrToInt(Value, Dummy) then Result := True else if Value = '' then begin Value := 0; Result := True; end else Result := False; end else Result := False; end; function TcxIntegerFieldHelper.GetScriptData(ARecord: Integer): string; begin Result := Format('[%s]', [DataSource.DisplayTexts[ARecord, Index]]); end; { TcxCurrencyFieldHelper } function TcxCurrencyFieldHelper.ValidateValue(var Value: Variant): Boolean; var Dummy: Currency; begin if VarIsType(Value, [varDouble, varSingle, varCurrency]) then Result := True else if VarIsType(Value, varString) then begin if TryStrToCurr(Value, Dummy) then Result := True else if Value = '' then begin Value := 0; Result := True; end else Result := False; end else Result := False; end; function TcxCurrencyFieldHelper.GetScriptData(ARecord: Integer): string; begin Result := Format('[%s, "%s"]', [ScriptValue(DataSource.Values[ARecord, Index]), DataSource.DisplayTexts[ARecord, Index]]); end; { TcxFloatFieldHelper } function TcxFloatFieldHelper.ValidateValue(var Value: Variant): Boolean; var Dummy: Double; begin if VarIsType(Value, [varDouble, varSingle, varCurrency]) then Result := True else if VarIsType(Value, varString) then begin if TryStrToFloat(Value, Dummy) then Result := True else if Value = '' then begin Value := 0; Result := True; end else Result := False; end else Result := False; end; function TcxFloatFieldHelper.GetScriptData(ARecord: Integer): string; var SaveDecimalSeparator: Char; Value: Variant; begin Value := DataSource.Values[ARecord, Index]; if VarIsType(Value, [varDouble, varSingle, varCurrency]) then begin SaveDecimalSeparator := DecimalSeparator; try DecimalSeparator := '.'; try Result := Format('[eval("%g")]', [Extended(Value)]) except Result := '[null]'; end finally DecimalSeparator := SaveDecimalSeparator; end end else Result := '[null]'; end; { TcxDateTimeFieldHelper } function TcxDateTimeFieldHelper.ValidateValue(var Value: Variant): Boolean; var Dummy: TDateTime; begin if VarIsType(Value, varDate) then Result := True else if VarIsType(Value, varString) then begin if TryStrToDateTime(Value, Dummy) then Result := True else if Value = '' then begin Value := 0; Result := True; end else Result := False; end else Result := False; end; function TcxDateTimeFieldHelper.GetScriptData(ARecord: Integer): string; var Date: Variant; AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word; begin Date := DataSource.Values[ARecord, Index]; if VarIsType(Date, varDate) then begin try DecodeDateTime(TDateTime(Date), AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond); Result := Format('[new Date(%d, %d, %d, %d, %d), "%s"]', [AYear, AMonth - 1, ADay, AHour, AMinute, DataSource.DisplayTexts[ARecord, Index]]); except Result := '[null]'; end; end else Result := '[null]'; end; { TcxBooleanFieldHelper } function TcxBooleanFieldHelper.ValidateValue(var Value: Variant): Boolean; var Dummy: Boolean; begin if VarIsType(Value, varBoolean) then Result := True else if VarIsType(Value, varString) then begin if TryStrToBool(Value, Dummy) then Result := True else if Value = '' then begin Value := False; Result := True; end else Result := False; end else Result := False; end; function TcxBooleanFieldHelper.GetScriptData(ARecord: Integer): string; begin Result := Format('[%s, "%s"]', [LowerCase(DataSource.DisplayTexts[ARecord, Index]), DataSource.DisplayTexts[ARecord, Index]]); end; { TcxImageFieldHelper } function TcxImageFieldHelper.ValidateValue(var Value: Variant): Boolean; begin Result := False; end; function TcxImageFieldHelper.ValidateValueType(AType: TcxWebDataTypes): Boolean; begin Result := dtValue in AType; end; function TcxImageFieldHelper.GetScriptData(ARecord: Integer): string; begin Result := '[null, "(GRAPHICS)"]'; end; { TcxMemoFieldHelper } function TcxMemoFieldHelper.ValidateValue(var Value: Variant): Boolean; begin if VarIsType(Value, varString) then Result := True else Result := False; end; function TcxMemoFieldHelper.ValidateValueType(AType: TcxWebDataTypes): Boolean; begin Result := dtValue in AType; end; function TcxMemoFieldHelper.GetScriptData(ARecord: Integer): string; begin Result := Format('["%s", "(MEMO)"]', [ScriptValue(DataSource.Values[ARecord, Index])]); end; { TcxBinaryFieldHelper } function TcxBinaryFieldHelper.ValidateValue(var Value: Variant): Boolean; begin Result := False; end; function TcxBinaryFieldHelper.ValidateValueType(AType: TcxWebDataTypes): Boolean; begin Result := dtValue in AType; end; function TcxBinaryFieldHelper.GetScriptData(ARecord: Integer): string; begin Result := '[null, "(BINARY)"]'; end; { TcxCustomWebDataField } constructor TcxCustomWebDataField.Create(Collection: TCollection); begin inherited; FName := UniqueName; end; destructor TcxCustomWebDataField.Destroy; begin FreeAndNil(FFieldHelper); inherited; end; function TcxCustomWebDataField.DataSource: TcxCustomWebDataSource; begin Result := Collection.Owner as TcxCustomWebDataSource; end; function TcxCustomWebDataField.GetScriptData(ARecord: Integer): string; begin Result := FieldHelper.GetScriptData(ARecord); end; function TcxCustomWebDataField.ValidateValue(var AValue: Variant): Boolean; begin Result := FieldHelper.ValidateValue(AValue); end; function TcxCustomWebDataField.ValidateValueType(AType: TcxWebDataTypes): Boolean; begin Result := FieldHelper.ValidateValueType(AType); end; procedure TcxCustomWebDataField.SetName(Value: string); begin if FName <> Value then begin if (DataSource <> nil) and (DataSource.FieldByName(Value) = nil) then FName := Value; end; end; function TcxCustomWebDataField.UniqueName: string; var I: Integer; begin if DataSource <> nil then begin I := 0; while True do begin Result := 'dcfField' + IntToStr(I); if DataSource.FieldByName(Result) = nil then break else Inc(I); end; end else Result := 'dcfField' + IntToStr(Index); end; function TcxCustomWebDataField.FieldHelper: TcxDataFieldHelper; var HelperClass: TcxDataFieldHelperClass; begin if FFieldHelper = nil then begin HelperClass := DataSource.ItemHelperClass(Index); if HelperClass <> nil then FFieldHelper := HelperClass.Create(Self) else FFieldHelper := TcxDataFieldHelper.Create(Self); end; Result := FFieldHelper; end; function TcxCustomWebDataField.GetDisplayName: string; begin Result := Name; end; { TcxCustomWebDataFields } constructor TcxCustomWebDataFields.Create(ADataSource: TcxCustomWebDataSource); begin inherited Create(FieldClass); FDataSource := ADataSource; end; function TcxCustomWebDataFields.Add: TcxCustomWebDataField; begin Result := TcxCustomWebDataField(inherited Add); end; function TcxCustomWebDataFields.DataSource: TcxCustomWebDataSource; begin Result := FDataSource; end; function TcxCustomWebDataFields.GetItem(Index: Integer): TcxCustomWebDataField; begin Result := TcxCustomWebDataField(inherited Items[Index]); end; function TcxCustomWebDataFields.GetOwner: TPersistent; begin Result := FDataSource; end; class function TcxCustomWebDataFields.FieldClass: TcxCustomWebDataFieldClass; begin Result := TcxCustomWebDataField; end; procedure TcxCustomWebDataFields.SetItem(Index: Integer; Value: TcxCustomWebDataField); begin Items[Index].Assign(Value); end; { TcxStdWebDataField } function TcxStdWebDataField.DataSource: TcxStdWebDataSource; begin Result := Collection.Owner as TcxStdWebDataSource; end; function TcxStdWebDataField.GetDataSet: TDataSet; begin if (Collection as TcxStdWebDataFields).DataSource <> nil then Result := (Collection as TcxStdWebDataFields).DataSource.DataSet else Result := nil; end; procedure TcxStdWebDataField.SetFieldName(const Value: string); begin if FFieldName <> Value then begin FFieldName := Value; end; end; { TcxStdWebDataFields } function TcxStdWebDataFields.GetItem(Index: Integer): TcxStdWebDataField; begin Result := TcxStdWebDataField(inherited Items[Index]); end; procedure TcxStdWebDataFields.SetItem(Index: Integer; Value: TcxStdWebDataField); begin Items[Index].Assign(Value); end; class function TcxStdWebDataFields.FieldClass: TcxCustomWebDataFieldClass; begin Result := TcxStdWebDataField; end; function TcxStdWebDataFields.Add: TcxStdWebDataField; begin Result := TcxStdWebDataField(inherited Add); end; function TcxStdWebDataFields.DataSource: TcxStdWebDataSource; begin Result := inherited DataSource as TcxStdWebDataSource; end; { TcxWebDataSourceEventsHelper } function TcxWebDataSourceEventsHelper.EventName(const AEvent: Integer): string; const cxHTMLEvent: array[TcxWebDataSourceEvent] of string = ('OnAfterSort', 'OnAfterGroup', 'OnAfterUngroup', 'OnAfterExpand', 'OnAfterMove', 'OnBeforeSort', 'OnBeforeGroup', 'OnBeforeUngroup', 'OnBeforeExpand', 'OnBeforeMove', 'OnBeforeDelete', 'OnBeforeInsert', 'OnBeforeStartEdit', 'OnBeforePostEdit', 'OnBeforeCancelEdit', 'OnBeforeRefresh'); begin Result := cxHTMLEvent[TcxWebDataSourceEvent(AEvent)]; end; function TcxWebDataSourceEventsHelper.EventProcParams(const AEvent: Integer): string; const cxHTMLEventProcParams: array[TcxWebDataSourceEvent] of string = ('(Sender, ColumnIndex)', '(Sender, ColumnIndex, GroupIndex)', '(Sender, ColumnIndex)', '(Sender, RowIndex)', '(Sender, RowIndex)', '(Sender, ColumnIndex)', '(Sender, ColumnIndex, GroupIndex)', '(Sender, ColumnIndex)', '(Sender, RowIndex)', '(Sender, RowIndex)', '(Sender, RowIndex)', '(Sender, RowIndex)', '(Sender, RowIndex)', '(Sender)', '(Sender)', '(Sender)'); begin Result := cxHTMLEventProcParams[TcxWebDataSourceEvent(AEvent)]; end; function TcxWebDataSourceEventsHelper.ScriptObject: string; begin Result := '_DataController'; end; function TcxWebDataSourceEventsHelper.EventTypeInfo: PTypeInfo; begin Result := TypeInfo(TcxWebDataSourceEvent); end; { TcxCustomWebDataSource } constructor TcxCustomWebDataSource.Create(AOwner: TComponent); begin inherited; FClientsList := TList.Create; FAllowEditing := True; end; destructor TcxCustomWebDataSource.Destroy; begin FClientsList.Free; inherited; end; function TcxCustomWebDataSource.CheckRowIndex(ARowIndex: Integer): Boolean; begin Result := ((0 <= ARowIndex) and (ARowIndex < RowCount)); end; function TcxCustomWebDataSource.GetFocusedRowIndex: Integer; begin Result := -1; end; function TcxCustomWebDataSource.ItemHelperClass(AItemIndex: Integer): TcxDataFieldHelperClass; begin Result := TcxDataFieldHelper; end; function TcxCustomWebDataSource.GetValue(ARecordIndex, AItemIndex: Integer): Variant; begin Result := VarEmpty; end; procedure TcxCustomWebDataSource.Loaded; begin inherited; DataNotification(utData); end; function TcxCustomWebDataSource.CanEdit: Boolean; begin Result := AllowEditing; end; function TcxCustomWebDataSource.GetAllowEditing: Boolean; begin Result := FAllowEditing; end; function TcxCustomWebDataSource.GetAllowExpanding: Boolean; begin Result := False; end; function TcxCustomWebDataSource.GetAllowGrouping: Boolean; begin Result := False; end; function TcxCustomWebDataSource.GetAllowSorting: Boolean; begin Result := False; end; function TcxCustomWebDataSource.GetKeyFieldName: string; begin Result := FKeyFieldName; end; procedure TcxCustomWebDataSource.SetAllowEditing(Value: Boolean); begin if FAllowEditing <> Value then begin FAllowEditing := Value; if not Value then CancelEdit; end; end; procedure TcxCustomWebDataSource.SetIsEditing(Value: Boolean); begin if FIsEditing <> Value then begin FIsEditing := Value; end; end; procedure TcxCustomWebDataSource.SetIsInserting(Value: Boolean); begin if FIsInserting <> Value then begin FIsInserting := Value; end; end; procedure TcxCustomWebDataSource.SetKeyFieldName(Value: string); begin if FKeyFieldName <> Value then begin FKeyFieldName := Value; end; end; procedure TcxCustomWebDataSource.SetEditValue(AItemIndex: Integer; AValue: Variant; AType: TcxWebDataTypes); begin end; procedure TcxCustomWebDataSource.SetFocusedRowIndex(Value: Integer); begin end; procedure TcxCustomWebDataSource.SetRecordCount(Value: Integer); begin end; procedure TcxCustomWebDataSource.SetValue(ARecordIndex, AItemIndex: Integer; const Value: Variant); begin end; procedure TcxCustomWebDataSource.StoreInsertingValues; var I: Integer; AValue: Variant; ACanSet: Boolean; begin SetLength(FInsertingValues, Fields.Count); for I := 0 to Fields.Count - 1 do begin AValue := Null; ACanSet := True; if(Assigned(OnSetInsertValue)) then OnSetInsertValue(Self, I, FocusedRowIndex, AValue, ACanSet); if not ACanSet then AValue := Null; SetInsertingValue(I, AValue); end; end; procedure TcxCustomWebDataSource.RestoreInsertingValues; var I: Integer; begin if Fields.Count = InsertingValuesCount then for I := 0 to Fields.Count - 1 do if FInsertingValues[I] <> Null then SetEditValue(I, FInsertingValues[I], [dtText, dtValue]); end; function TcxCustomWebDataSource.GetInsertingValue(Index: Integer): Variant; begin Result := FInsertingValues[Index]; end; procedure TcxCustomWebDataSource.SetInsertingValue(Index: Integer; Value: Variant); begin FInsertingValues[Index] := Value; end; function TcxCustomWebDataSource.InsertingValuesCount: Integer; begin Result := Length(FInsertingValues) end; function TcxCustomWebDataSource.KeyField: TcxCustomWebDataField; begin Result := FieldByName(KeyFieldName); end; function TcxCustomWebDataSource.CheckKey(ARowIndex: Integer; AKey: string; ALevel: Integer): Boolean; begin if not CheckRowIndex(ARowIndex) then Result := False else begin if KeyField <> nil then Result := (AKey = DisplayTexts[GetRowRecord(ARowIndex), KeyField.Index]) and (ALevel = GetRowLevel(ARowIndex)) else Result := True; end; end; function TcxCustomWebDataSource.FindKey(AKey: string; ALevel: Integer): Integer; var I: Integer; begin Result := -1; if KeyField <> nil then for I := 0 to RowCount - 1 do if (AKey = DisplayTexts[GetRowRecord(I), KeyField.Index]) and (ALevel = GetRowLevel(I)) then begin Result := I; break; end; end; function TcxCustomWebDataSource.RecordKeyValue(ARecord: Integer): string; begin if KeyField <> nil then Result := DisplayTexts[ARecord, KeyField.Index] else Result := ''; end; function TcxCustomWebDataSource.IsKeyNeeded(ARowIndex: Integer): Boolean; var I: Integer; ViewIntf: IcxWebViewDataSupport; begin Result := False; for I := 0 to ClientCount - 1 do if Supports(Clients[I], IcxWebViewDataSupport, ViewIntf) then if (ARowIndex >= ViewIntf.GetFirstVisibleRow) and (ARowIndex < ViewIntf.GetFirstVisibleRow + ViewIntf.GetPageSize) then begin Result := True; break; end; end; procedure TcxCustomWebDataSource.ClearGrouping; begin end; procedure TcxCustomWebDataSource.ClearSorting; begin end; procedure TcxCustomWebDataSource.FullCollapse; begin end; procedure TcxCustomWebDataSource.FullExpand; begin end; procedure TcxCustomWebDataSource.WebDelete(const AParameters: TcxActionParameters); var ARowIndex, AKeyLevel: Integer; AKeyValue: string; begin try ARowIndex := StrToInt(GetActionParameter(AParameters.ParamString, 0)); AKeyValue := GetActionParameter(AParameters.ParamString, 1); AKeyLevel := StrToInt(GetActionParameter(AParameters.ParamString, 2)); except on EConvertError do begin ARowIndex := -1; AKeyValue := ''; AKeyLevel := 0; end else raise; end; if not CheckKey(ARowIndex, AKeyValue, AKeyLevel) then ARowIndex := FindKey(AKeyValue, AKeyLevel); if CheckRowIndex(ARowIndex) then DeleteRecord(ARowIndex); end; procedure TcxCustomWebDataSource.WebStartEdit(const AParameters: TcxActionParameters); var ARowIndex, AKeyLevel: Integer; AKeyValue: string; begin try ARowIndex := StrToInt(GetActionParameter(AParameters.ParamString, 0)); AKeyValue := GetActionParameter(AParameters.ParamString, 1); AKeyLevel := StrToInt(GetActionParameter(AParameters.ParamString, 2)); except on EConvertError do begin ARowIndex := -1; AKeyValue := ''; AKeyLevel := 0; end else raise; end; if not CheckKey(ARowIndex, AKeyValue, AKeyLevel) then ARowIndex := FindKey(AKeyValue, AKeyLevel); if CheckRowIndex(ARowIndex) then EditRecord(ARowIndex); end; procedure TcxCustomWebDataSource.WebPostEdit(const AParameters: TcxActionParameters); var ARowIndex, AKeyLevel: Integer; ADataControlName, AKeyValue: string; begin try AKeyValue := GetActionParameter(AParameters.ParamString, 1); AKeyLevel := StrToInt(GetActionParameter(AParameters.ParamString, 2)); except on EConvertError do begin AKeyValue := ''; AKeyLevel := 0; end else raise; end; ARowIndex := FocusedRowIndex; if not CheckKey(ARowIndex, AKeyValue, AKeyLevel) then ARowIndex := FindKey(AKeyValue, AKeyLevel); if CheckRowIndex(ARowIndex) then begin ADataControlName := GetActionParameter(AParameters.ParamString, 0); PostEdit(ADataControlName); end; end; procedure TcxCustomWebDataSource.WebCancelEdit(const AParameters: TcxActionParameters); begin CancelEdit; end; procedure TcxCustomWebDataSource.WebInsert(const AParameters: TcxActionParameters); var ARowIndex, AKeyLevel: Integer; AKeyValue: string; begin try ARowIndex := StrToInt(GetActionParameter(AParameters.ParamString, 0)); AKeyValue := GetActionParameter(AParameters.ParamString, 1); AKeyLevel := StrToInt(GetActionParameter(AParameters.ParamString, 2)); except on EConvertError do begin ARowIndex := -1; AKeyValue := ''; AKeyLevel := 0; end else raise; end; if not CheckKey(ARowIndex, AKeyValue, AKeyLevel) then ARowIndex := FindKey(AKeyValue, AKeyLevel); if CheckRowIndex(ARowIndex) then InsertRecord(ARowIndex) else InsertRecord(-1); end; procedure TcxCustomWebDataSource.WebRefresh(const AParameters: TcxActionParameters); begin Refresh; end; procedure TcxCustomWebDataSource.WebMoveTo(const AParameters: TcxActionParameters); var ARowIndex: Integer; begin try ARowIndex := StrToInt(GetActionParameter(AParameters.ParamString, 0)); except on EConvertError do ARowIndex := -1; else raise; end; if ARowIndex < 0 then ARowIndex := 0; if ARowIndex >= RowCount then ARowIndex := RowCount - 1; FocusedRowIndex := ARowIndex; end; procedure TcxCustomWebDataSource.WebMoveBy(const AParameters: TcxActionParameters); var ARowIndex, OldRowIndex, Delta: Integer; begin OldRowIndex := GetFocusedRowIndex; try Delta := StrToInt(GetActionParameter(AParameters.ParamString, 0)); except on EConvertError do Delta := 0; else raise; end; ARowIndex := OldRowIndex + Delta; if ARowIndex < 0 then ARowIndex := 0; if ARowIndex >= RowCount then ARowIndex := RowCount - 1; FocusedRowIndex := ARowIndex; end; procedure TcxCustomWebDataSource.SynchronizeSelection; var ARowIndex: Integer; begin try ARowIndex := StrToInt(WebValuesHelper.Values.Values[FullName + 'FocusedRow']); except on EConvertError do ARowIndex := 0; else raise; end; if (ARowIndex < 0) then ARowIndex := 0; if (ARowIndex >= RowCount) then ARowIndex := RowCount - 1; FocusedRowIndex := ARowIndex; end; procedure TcxCustomWebDataSource.SynchronizeInsertingValues; var I, DelimiterPos: Integer; S, AValue: string; begin S := WebValuesHelper.Values.Values[FullName + 'InsertingValues']; SetLength(FInsertingValues, Fields.Count); for I := 0 to InsertingValuesCount - 1 do begin FInsertingValues[I] := Null; DelimiterPos := Pos(scxInfoDelimiter, S); if DelimiterPos = 0 then break; try AValue := LeftStr(S, DelimiterPos - 1); if AValue <> '' then FInsertingValues[I] := AValue; except on EConvertError do FInsertingValues[I] := Null; else raise; end; S := RightStr(S, Length(S) - DelimiterPos); end; end; { Actions } procedure TcxCustomWebDataSource.DoAfterPerformActions; begin if not IsEditing then UpdateDataLayout; end; procedure TcxCustomWebDataSource.RegisterActions; begin WebActionsHelper.RegisterAction(scxDeleteAction, WebDelete); WebActionsHelper.RegisterAction(scxStartEditAction, WebStartEdit); WebActionsHelper.RegisterAction(scxPostEditAction, WebPostEdit); WebActionsHelper.RegisterAction(scxCancelEditAction, WebCancelEdit); WebActionsHelper.RegisterAction(scxInsertAction, WebInsert); WebActionsHelper.RegisterAction(scxRefreshAction, WebRefresh); WebActionsHelper.RegisterAction(scxMoveToAction, WebMoveTo); WebActionsHelper.RegisterAction(scxMoveByAction, WebMoveBy); end; { events } function TcxCustomWebDataSource.GetWebEventsHelper: TcxWebDataSourceEventsHelper; begin Result := inherited GetWebEventsHelper as TcxWebDataSourceEventsHelper; end; class function TcxCustomWebDataSource.GetWebEventsHelperClass: TcxWebEventsHelperClass; begin Result := TcxWebDataSourceEventsHelper; end; { Values } function TcxCustomWebDataSource.CanSetValues: Boolean; begin Result := True; end; procedure TcxCustomWebDataSource.DoAfterSetValues; begin end; procedure TcxCustomWebDataSource.DoSetValues; begin IsEditing := SameText(WebValuesHelper.Values.Values[FullName + 'IsEditing'], 'true'); IsInserting := SameText(WebValuesHelper.Values.Values[FullName + 'IsInserting'], 'true'); if IsInserting then SynchronizeInsertingValues; end; procedure TcxCustomWebDataSource.RegisterValues; begin WebValuesHelper.RegisterValue(FullName + 'IsEditing', cxWebUtils.BoolToStr(IsEditing)); WebValuesHelper.RegisterValue(FullName + 'IsInserting', cxWebUtils.BoolToStr(IsInserting)); WebValuesHelper.RegisterValue(FullName + 'InsertingValues', ''); WebValuesHelper.RegisterValue(FullName + 'FocusedRow', IntToStr(FocusedRowIndex)); end; procedure TcxCustomWebDataSource.RegisterRenderers; begin WebRenderHelper.RegisterRenderer(TcxCustomWebDataSourceRenderer); WebRenderHelper.RegisterRenderer(TcxCustomWebDataSourceNS4Renderer); WebRenderHelper.RegisterRenderer(TcxCustomWebDataSourceOperaRenderer); end; function TcxCustomWebDataSource.GetRowDisplayText(RowIndex: Integer; ItemIndex: Integer): string; begin Result := DisplayTexts[RowIndex, ItemIndex]; end; function TcxCustomWebDataSource.GetRowValue(RowIndex: Integer; ItemIndex: Integer): Variant; begin Result := Values[RowIndex, ItemIndex]; end; function TcxCustomWebDataSource.GetRowExpanded(RowIndex: Integer): Boolean; begin Result := False; end; function TcxCustomWebDataSource.GetRowLevel(RowIndex: Integer): Integer; begin Result := 0; end; function TcxCustomWebDataSource.GetRowRecord(RowIndex: Integer): Integer; begin Result := RowIndex; end; function TcxCustomWebDataSource.GetGroupingItemCount: Integer; begin Result := 0; end; function TcxCustomWebDataSource.GetSortingItemCount: Integer; begin Result := 0; end; function TcxCustomWebDataSource.GetItemGroupIndex(ItemIndex: Integer): Integer; begin Result := -1; end; function TcxCustomWebDataSource.GetItemSortOrder(ItemIndex: Integer): TcxWebDataSortOrder; begin Result := wsoNone; end; function TcxCustomWebDataSource.GetGroupingItemIndex(Item: Integer): Integer; begin Result := -1; end; function TcxCustomWebDataSource.GetSortingItemIndex(Item: Integer): Integer; begin Result := -1; end; procedure TcxCustomWebDataSource.BeginUpdate; begin Inc(FUpdateLock); end; procedure TcxCustomWebDataSource.CancelUpdate; begin Dec(FUpdateLock); end; procedure TcxCustomWebDataSource.EndUpdate; begin Dec(FUpdateLock); if FUpdateLock = 0 then UpdateDataLayout; end; function TcxCustomWebDataSource.FieldByName(const Name: string): TcxCustomWebDataField; var I: Integer; begin Result := nil; for I := 0 to Fields.Count - 1 do if SameText(Fields[I].Name, Name) then begin Result := Fields[I]; break; end; end; procedure TcxCustomWebDataSource.RegisterClient(Client: TComponent); begin if FClientsList.IndexOf(Client) = -1 then FClientsList.Add(Client); end; procedure TcxCustomWebDataSource.UnRegisterClient(Client: TComponent); begin if FClientsList.IndexOf(Client) <> -1 then FClientsList.Remove(Client); end; function TcxCustomWebDataSource.GetClient(Index: Integer): TComponent; begin Result := TComponent(FClientsList.Items[Index]); end; function TcxCustomWebDataSource.GetClientCount: Integer; begin Result := FClientsList.Count; end; function TcxCustomWebDataSource.GetFullName: string; begin Result := Format('%s_%s', [Owner.Name, Name]); end; function TcxCustomWebDataSource.GetState: TcxWebDataSourceState; begin if IsInserting then Result := inserting else if IsEditing then Result := editing else Result := browsing; end; procedure TcxCustomWebDataSource.DataNotification(AUpdateType: TcxUpdateType); begin end; function TcxCustomWebDataSource.NeedUpdateFields: Boolean; begin Result := False; end; procedure TcxCustomWebDataSource.UpdateDefaultFields; begin end; procedure TcxCustomWebDataSource.UpdateDataLayout; var I: Integer; DataSourceIntf: IcxWebDataSourceSupport; begin if FUpdateLock > 0 then exit; BeginUpdate; try for I := 0 to ClientCount - 1 do begin if (Clients[I] <> nil) and not (csDestroying in Clients[I].ComponentState) then begin if Supports(Clients[I], IcxWebDataSourceSupport, DataSourceIntf) then DataSourceIntf.ChangedDataLayout(Self); end; end; finally CancelUpdate; end; end; procedure TcxCustomWebDataSource.ChangedData(AClientName: string); var I: Integer; DataSourceIntf: IcxWebDataSourceSupport; begin if IsLoading then exit; BeginUpdate; try for I := 0 to ClientCount - 1 do begin if Supports(Clients[I], IcxWebDataSourceSupport, DataSourceIntf) then DataSourceIntf.UpdateData(Self); if Clients[I].Name = AClientName then break; end; finally EndUpdate; end; end; { Data operations } procedure TcxCustomWebDataSource.CancelEdit; begin BeginUpdate; try IsInserting := False; IsEditing := False; if Assigned(OnCancelEdit) then OnCancelEdit(self, FocusedRowIndex); finally EndUpdate; end; end; procedure TcxCustomWebDataSource.DeleteRecord(ARowIndex: Integer); begin end; procedure TcxCustomWebDataSource.InsertRecord(ARowIndex: Integer); begin end; procedure TcxCustomWebDataSource.EditRecord(ARowIndex: Integer); begin end; procedure TcxCustomWebDataSource.Expand(ARowIndex: Integer; AExpanded, ARecursive: Boolean); begin end; procedure TcxCustomWebDataSource.Group(GroupField, GroupIndex: Integer); begin end; procedure TcxCustomWebDataSource.PostEdit(APriorControlName: string); begin end; procedure TcxCustomWebDataSource.Sort(SortIndex: Integer; SortOrder: TcxWebDataSortOrder); begin end; procedure TcxCustomWebDataSource.UnGroup(UnGroupIndex: Integer); begin end; procedure TcxCustomWebDataSource.Refresh; begin UpdateDataLayout; end; function TcxCustomWebDataSource.GetFields: TcxCustomWebDataFields; begin Result := FFields; end; procedure TcxCustomWebDataSource.SetFields(Value: TcxCustomWebDataFields); begin FFields := Value; end; function TcxCustomWebDataSource.GetDisplayText(ARecordIndex, AItemIndex: Integer): string; begin Result := ''; end; function TcxCustomWebDataSource.GetRecordCount: Integer; begin Result := 0; end; function TcxCustomWebDataSource.GetRowCount: Integer; begin Result := RecordCount; end; function TcxCustomWebDataSource.IsDesigning: Boolean; begin Result := (csDesigning in ComponentState) or ((Owner <> nil) and (csDesigning in Owner.ComponentState)); end; { TcxCustomWebDataSourceRenderer } function TcxCustomWebDataSourceRenderer.GetWebDataSource: TcxCustomWebDataSource; begin Result := Component as TcxCustomWebDataSource; end; function TcxCustomWebDataSourceRenderer.IsLoadAllRecordsMode: Boolean; begin Result := WebDataSource.LoadAllRecords and not WebDataSource.IsDesigning and not WebDataSource.IsInserting; end; class procedure TcxCustomWebDataSourceRenderer.GetScriptFiles(AList: TStrings); begin AList.Add(scxCommonScriptName); AList.Add(scxDataEngineScriptName); AList.Add(scxDataControllerScriptName); AList.Add(scxDataControlsScriptName); end; procedure TcxCustomWebDataSourceRenderer.WriteHandlers; begin HTMLTextBuilder.WriteText(Format(' _DataController.AssignOnChangeFocus = %s;', [cxWebUtils.BoolToStr(Assigned(WebDataSource.OnScrolling) or Assigned(WebDataSource.OnScrolled))])); HTMLTextBuilder.WriteText(' _DataController.AssignOnGroup = false;'); HTMLTextBuilder.WriteText(' _DataController.AssignOnUnGroup = false;'); HTMLTextBuilder.WriteText(' _DataController.AssignOnSort = false;'); HTMLTextBuilder.WriteText(' _DataController.AssignOnExpand = false;'); HTMLTextBuilder.WriteText(Format(' _DataController.AssignOnEdit = %s;', [cxWebUtils.BoolToStr(Assigned(WebDataSource.OnStartEdit))])); HTMLTextBuilder.WriteText(Format(' _DataController.AssignOnCancelEdit = %s;', [cxWebUtils.BoolToStr(Assigned(WebDataSource.OnCancelEdit))])); end; procedure TcxCustomWebDataSourceRenderer.WriteKeys; var I, ARecordIndex: Integer; begin if not WebDataSource.IsDesigning and not IsLoadAllRecordsMode and (WebDataSource.KeyField <> nil) then begin for I := 0 to WebDataSource.RowCount - 1 do if WebDataSource.IsKeyNeeded(I) then begin ARecordIndex := WebDataSource.GetRowRecord(I); HTMLTextBuilder.WriteText(Format(' _DataController.AddKey(%d, "%s", %d);', [I, WebDataSource.RecordKeyValue(ARecordIndex), WebDataSource.GetRowLevel(I)])); end; end; end; procedure TcxCustomWebDataSourceRenderer.WriteData; var I, J: Integer; S: string; begin if IsLoadAllRecordsMode then begin for I := 0 to WebDataSource.RecordCount - 1 do begin S := ''; for J := 0 to WebDataSource.Fields.Count - 1 do begin S := S + WebDataSource.Fields[J].GetScriptData(I); if J <> WebDataSource.Fields.Count - 1 then S := S + ', '; end; HTMLTextBuilder.WriteText(Format(' _DataController.AddRecord("%s", [%s]);', [WebDataSource.RecordKeyValue(I), S])); end; end else begin HTMLTextBuilder.WriteText(Format(' _DataController.RowCount = %d;', [WebDataSource.RowCount])); HTMLTextBuilder.WriteText(Format(' _DataController.SortingItemCount = %d;', [WebDataSource.GetSortingItemCount])); HTMLTextBuilder.WriteText(Format(' _DataController.GroupingItemCount = %d;', [WebDataSource.GetGroupingItemCount])); WriteKeys; end; end; procedure TcxCustomWebDataSourceRenderer.WriteHiddenFormElements; var I: Integer; S: string; begin WriteHiddenField(WebDataSource.FullName + 'FocusedRow', IntToStr(WebDataSource.FocusedRowIndex)); WriteHiddenField(WebDataSource.FullName + 'IsEditing', cxWebUtils.BoolToStr(WebDataSource.IsEditing)); WriteHiddenField(WebDataSource.FullName + 'IsInserting', cxWebUtils.BoolToStr(WebDataSource.IsInserting)); if WebDataSource.IsInserting then begin S := ''; for I := 0 to WebDataSource.InsertingValuesCount - 1 do S := S + VarToStr(WebDataSource.GetInsertingValue(I)) + scxInfoDelimiter; WriteHiddenField(WebDataSource.FullName + 'InsertingValues', S); end; end; procedure TcxCustomWebDataSourceRenderer.WriteScripts; begin WriteEventsScript; HTMLTextBuilder.WriteText(Format('_DataController = CreateDataController();', [])); HTMLTextBuilder.WriteText(Format(' _DataController.Name = "%s";', [WebDataSource.FullName])); HTMLTextBuilder.WriteText(Format(' _DataController.ItemCount = %d;', [WebDataSource.Fields.Count])); HTMLTextBuilder.WriteText(Format(' _DataController.AllowEditing = %s;', [cxWebUtils.BoolToStr(WebDataSource.AllowEditing)])); HTMLTextBuilder.WriteText(Format(' _DataController.AllowGrouping = %s;', [cxWebUtils.BoolToStr(WebDataSource.AllowGrouping)])); HTMLTextBuilder.WriteText(Format(' _DataController.AllowSorting = %s;', [cxWebUtils.BoolToStr(WebDataSource.AllowSorting)])); HTMLTextBuilder.WriteText(Format(' _DataController.AllowExpanding = %s;', [cxWebUtils.BoolToStr(WebDataSource.AllowExpanding)])); HTMLTextBuilder.WriteText(Format(' _DataController.LoadAllRecords = %s;', [cxWebUtils.BoolToStr(IsLoadAllRecordsMode)])); WriteEvents; WriteData; WriteHandlers; end; class procedure TcxCustomWebDataSourceRenderer.WriteClassScripts(AHTMLTextBuilder: TcxHTMLTextBuilder); begin AHTMLTextBuilder.WriteText(Format('var scxDeleteConfirmText = "%s";', [scxDeleteConfirmText])); end; { TcxCustomWebDataSourceNS4Renderer } class function TcxCustomWebDataSourceNS4Renderer.IsBrowserSupported(AWebBrowser: TcxWebBrowserClass): Boolean; begin Result := AWebBrowser = TcxWebBrowserNS4; end; function TcxCustomWebDataSourceNS4Renderer.IsLoadAllRecordsMode: Boolean; begin Result := False; end; { TcxCustomWebDataSourceOperaRenderer } class function TcxCustomWebDataSourceOperaRenderer.IsBrowserSupported(AWebBrowser: TcxWebBrowserClass): Boolean; begin Result := AWebBrowser = TcxWebBrowserOpera; end; { TcxStdDataLink } procedure TcxWebDataLink.ActiveChanged; begin if WebDataSource <> nil then WebDataSource.DataNotification(utLayout); end; procedure TcxWebDataLink.DataSetChanged; begin if WebDataSource <> nil then WebDataSource.DataNotification(utData); end; { TcxStdWebDataSource } constructor TcxStdWebDataSource.Create(AOwner: TComponent); begin inherited; Fields := TcxStdWebDataFields.Create(Self); FDataSource := TDataSource.Create(nil); FDataLink := TcxWebDataLink.Create; FDataLink.FWebDataSource := Self; FDataLink.DataSource := FDataSource; end; destructor TcxStdWebDataSource.Destroy; begin FDataSource.Free; FDataLink.Free; if Fields <> nil then Fields.Clear; Fields.Free; inherited; end; procedure TcxStdWebDataSource.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if csDestroying in ComponentState then exit; if (Operation = opRemove) and (AComponent = DataSet) then DataSet := nil; end; function TcxStdWebDataSource.GetDataSet: TDataSet; begin Result := DataSource.DataSet; end; type TDataSetAccess = class(TDataSet); function TcxStdWebDataSource.CanEdit: Boolean; begin Result := AllowEditing and (DataSource.DataSet <> nil) and DataSource.DataSet.Active and TDataSetAccess(DataSource.DataSet).CanModify; end; function TcxStdWebDataSource.GetItemField(AItemName: string): TField; var AFieldName: string; begin AFieldName := FieldByName(AItemName).Name; Result := DataSource.DataSet.FieldByName(AFieldName); end; function TcxStdWebDataSource.GetFields: TcxStdWebDataFields; begin Result := inherited GetFields as TcxStdWebDataFields; end; procedure TcxStdWebDataSource.SetDataSet(Value: TDataSet); begin if DataSource.DataSet <> Value then begin Fields.Clear; DataSource.DataSet := Value; if (Value <> nil) and Value.Active then DataNotification(utLayout); end; end; procedure TcxStdWebDataSource.SetFields(Value: TcxStdWebDataFields); begin inherited SetFields(Value); end; { values } procedure TcxStdWebDataSource.DoSetValues; begin BeginUpdate; try SynchronizeSelection; inherited DoSetValues; finally CancelUpdate; end; end; procedure TcxStdWebDataSource.RegisterValues; begin inherited; end; { actions } procedure TcxStdWebDataSource.RegisterActions; begin inherited; WebActionsHelper.RegisterAction(scxDeleteAction, WebDelete); WebActionsHelper.RegisterAction(scxStartEditAction, WebStartEdit); WebActionsHelper.RegisterAction(scxPostEditAction, WebPostEdit); WebActionsHelper.RegisterAction(scxCancelEditAction, WebCancelEdit); WebActionsHelper.RegisterAction(scxInsertAction, WebInsert); WebActionsHelper.RegisterAction(scxRefreshAction, WebRefresh); WebActionsHelper.RegisterAction(scxMoveToAction, WebMoveTo); WebActionsHelper.RegisterAction(scxMoveByAction, WebMoveBy); end; procedure TcxStdWebDataSource.RegisterRenderers; begin WebRenderHelper.RegisterRenderer(TcxCustomWebDataSourceRenderer); WebRenderHelper.RegisterRenderer(TcxCustomWebDataSourceNS4Renderer); end; procedure TcxStdWebDataSource.SynchronizeSelection; var RowIndex: Integer; begin try RowIndex := StrToInt(WebValuesHelper.Values.Values[FullName + 'FocusedRow']); except on EConvertError do RowIndex := 0; else raise; end; if RowIndex < 0 then RowIndex := 0; if (DataSet <> nil) and (DataSet.Active) then begin if RowIndex >= DataSet.RecordCount then RowIndex := DataSet.RecordCount - 1; DataSet.MoveBy(RowIndex - DataSet.RecNo + 1); end; end; procedure TcxStdWebDataSource.DataNotification(AUpdateType: TcxUpdateType); begin if csDestroying in ComponentState then exit; if AUpdateType = utLayout then UpdateDefaultFields; UpdateDataLayout; end; function TcxStdWebDataSource.NeedUpdateFields: Boolean; var I: Integer; begin if DataSet = nil then begin if Fields.Count > 0 then Result := True else Result := False; end else if (DataSet.FieldCount = 0) and (DataSet.FieldDefs.Count <> Fields.Count) then Result := True else if DataSet.FieldCount = Fields.Count then begin Result := False; for I := 0 to Fields.Count - 1 do if DataSet.FindField(Fields[I].FieldName) = nil then begin Result := True; break; end; end else Result := True; end; procedure TcxStdWebDataSource.UpdateDefaultFields; var I: Integer; AField: TField; begin if Fields = nil then exit; if UpdateLock > 0 then exit; if (DataSet <> nil) and (csDesigning in DataSet.ComponentState) and not (csLoading in DataSet.ComponentState) and not DataSet.Active and (DataSet.FieldDefs.Count = 0) then TDataSetAccess(DataSet).InitFieldDefs; BeginUpdate; try if DataSet <> nil then begin if NeedUpdateFields then begin Fields.Clear; if DataSet.Fields.Count > 0 then for I := 0 to DataSet.FieldCount - 1 do begin AField := DataSet.Fields[I]; with Fields.Add do begin Name := AField.FieldName; FieldName := AField.FieldName; DisplayLabel := AField.DisplayLabel; end; end else for I := 0 to DataSet.FieldDefs.Count - 1 do begin with Fields.Add do begin Name := DataSet.FieldDefs[I].Name; FieldName := DataSet.FieldDefs[I].Name; DisplayLabel := DataSet.FieldDefs[I].DisplayName; end; end; end; end else Fields.Clear; finally CancelUpdate; end; end; procedure TcxStdWebDataSource.DeleteRecord(ARowIndex: Integer); var Processed: Boolean; begin if IsEditing then CancelEdit; if AllowEditing then begin BeginUpdate; try Processed := True; if Assigned(FOnDeleting) then FOnDeleting(self, ARowIndex, Processed); if Processed and CanEdit then begin DataSet.MoveBy(ARowIndex - DataSet.RecNo + 1); DataSet.Delete; if Assigned(FOnDeleted) then FOnDeleted(self, ARowIndex); end; finally EndUpdate; end; end; end; procedure TcxStdWebDataSource.InsertRecord(ARowIndex: Integer); var Processed: Boolean; begin if IsEditing then CancelEdit; if AllowEditing then begin BeginUpdate; try Processed := True; if Assigned(FOnInserting) then FOnInserting(self, ARowIndex, Processed); if Processed and CanEdit then begin if not CheckRowIndex(ARowIndex) then DataSet.MoveBy(RowCount - DataSet.RecNo); StoreInsertingValues; IsInserting := True; IsEditing := True; if Assigned(FOnInserted) then FOnInserted(self, ARowIndex); end; finally EndUpdate; end; end; end; procedure TcxStdWebDataSource.EditRecord(ARowIndex: Integer); var Processed: Boolean; begin if AllowEditing then begin BeginUpdate; try Processed := True; if Assigned(OnStartEdit) then OnStartEdit(Self, ARowIndex, Processed); if Processed and CanEdit then begin DataSet.MoveBy(ARowIndex - DataSet.RecNo + 1); IsEditing := True; end; finally EndUpdate; end; end; end; procedure TcxStdWebDataSource.PostEdit(APriorControlName: string); var Processed: Boolean; SavedIsInserting: Boolean; begin if AllowEditing then begin BeginUpdate; try Processed := True; if Assigned(FOnBeforePost) then FOnBeforePost(self, FocusedRowIndex, Processed); if Processed and CanEdit then begin SavedIsInserting := IsInserting; if IsInserting then begin ChangedData(APriorControlName); DataSet.Insert; IsInserting := False; RestoreInsertingValues; end else begin DataSet.Edit; ChangedData(APriorControlName); end; try DataSet.Post; except if SavedIsInserting then IsInserting := True; raise; end; IsEditing := False; if Assigned(FOnAfterPost) then FOnAfterPost(self, FocusedRowIndex); end; finally EndUpdate; end; end; end; function TcxStdWebDataSource.GetFocusedRowIndex: Integer; begin if (DataSet = nil) or (not DataSet.Active) then Result := -1 else begin Result := DataSet.RecNo - 1; if (DataSet.State = dsInsert) and (Result < 0) then Result := 0; end; end; function TcxStdWebDataSource.ItemHelperClass(AItemIndex: Integer): TcxDataFieldHelperClass; var AField: TField; begin Result := TcxDataFieldHelper; AField := DataSet.Fields.FieldByName(Fields[AItemIndex].FieldName); if AField <> nil then begin case AField.DataType of ftString, ftWideString: Result := TcxStringFieldHelper; ftSmallint, ftInteger, ftAutoInc, ftWord, ftLargeint: Result := TcxIntegerFieldHelper; ftBCD: if (AField as TBCDField).currency then Result := TcxCurrencyFieldHelper else Result := TcxIntegerFieldHelper; ftFMTBcd: if (AField as TFMTBCDField).currency then Result := TcxCurrencyFieldHelper else Result := TcxIntegerFieldHelper; ftCurrency, ftFloat: if (AField as TFloatField).currency then Result := TcxCurrencyFieldHelper else Result := TcxFloatFieldHelper; ftBoolean: Result := TcxBooleanFieldHelper; ftDate, ftTime, ftDateTime: Result := TcxDateTimeFieldHelper; else if AField is TBlobField then begin if (TBlobField(AField).BlobType = ftGraphic) or (TBlobField(AField).BlobType = ftTypedBinary) then Result := TcxImageFieldHelper else if TBlobField(AField).BlobType = ftMemo then Result := TcxMemoFieldHelper else Result := TcxBinaryFieldHelper; end; end; end; end; function TcxStdWebDataSource.GetValue(ARecordIndex, AItemIndex: Integer): Variant; var FieldName: string; CurrentRecord: Integer; begin if (DataSet = nil) or (not DataSet.Active) then Result := Null else if IsInserting and (DataSet.RecordCount = 0) then Result := Null else if IsInserting and (ARecordIndex = FocusedRowIndex) then Result := GetInsertingValue(AItemIndex) else begin if IsInserting and (ARecordIndex > FocusedRowIndex) then Dec(ARecordIndex); BeginUpdate; try CurrentRecord := DataSet.RecNo - 1; FieldName := Fields[AItemIndex].FieldName; if CurrentRecord <> ARecordIndex then DataSet.MoveBy(ARecordIndex - CurrentRecord); Result := DataSet.Fields.FieldByName(FieldName).AsVariant; if CurrentRecord <> ARecordIndex then DataSet.MoveBy(CurrentRecord - ARecordIndex); finally CancelUpdate; end; end; end; function TcxStdWebDataSource.GetDisplayText(ARecordIndex, AItemIndex: Integer): string; var FieldName: string; CurrentRecord: Integer; begin if (DataSet = nil) or (not DataSet.Active) then Result := '' else if IsInserting and (DataSet.RecordCount = 0) then Result := '' else if IsInserting and (ARecordIndex = FocusedRowIndex) then Result := VarToStr(GetInsertingValue(AItemIndex)) else begin if IsInserting and (ARecordIndex > FocusedRowIndex) then Dec(ARecordIndex); BeginUpdate; try CurrentRecord := DataSet.RecNo - 1; FieldName := Fields[AItemIndex].FieldName; if CurrentRecord <> ARecordIndex then DataSet.MoveBy(ARecordIndex - CurrentRecord); Result := DataSet.Fields.FieldByName(FieldName).DisplayText; if CurrentRecord <> ARecordIndex then DataSet.MoveBy(CurrentRecord - ARecordIndex); finally CancelUpdate; end; end; end; function TcxStdWebDataSource.GetRecordCount: Integer; begin if (DataSet = nil) or (not DataSet.Active) then Result := 0 else begin Result := DataSet.RecordCount; if IsInserting then Inc(Result); end; end; procedure TcxStdWebDataSource.SetEditValue(AItemIndex: Integer; AValue: Variant; AType: TcxWebDataTypes); var Field: TField; ACanSet: Boolean; begin BeginUpdate; try DataSet.Edit; try Field := GetItemField(Fields[AItemIndex].Name); ACanSet := True; if Assigned(OnSetEditValue) then OnSetEditValue(Self, AItemIndex, FocusedRowIndex, AValue, ACanSet); if ACanSet and Fields[AItemIndex].ValidateValueType(AType) and Fields[AItemIndex].ValidateValue(AValue) then if IsInserting then SetInsertingValue(AItemIndex, AValue) else if dtValue in AType then Field.AsVariant := AValue else Field.AsString := AValue; except DataSet.Cancel; raise; end; finally EndUpdate; end; end; procedure TcxStdWebDataSource.SetFocusedRowIndex(Value: Integer); var Processed: Boolean; begin if IsEditing then CancelEdit; Processed := True; if Assigned(OnScrolling) then OnScrolling(self, DataSet.RecNo, Processed); if Processed then begin if Value < 0 then Value := 0; if (DataSet <> nil) and (DataSet.Active) then begin if Value >= DataSet.RecordCount then Value := DataSet.RecordCount - 1; DataSet.MoveBy(Value - DataSet.RecNo + 1); end; if Assigned(OnScrolled) then OnScrolled(self, DataSet.RecNo); end; end; procedure TcxStdWebDataSource.SetValue(ARecordIndex, AItemIndex: Integer; const Value: Variant); var FieldName: string; CurrentRecord: Integer; begin if (DataSet <> nil) and (DataSet.Active) then begin CurrentRecord := DataSet.RecNo - 1; FieldName := Fields[AItemIndex].FieldName; DataSet.MoveBy(ARecordIndex - CurrentRecord); DataSet.Fields.FieldByName(FieldName).AsVariant := Value; DataSet.MoveBy(CurrentRecord - ARecordIndex); end; end; initialization RegisterClasses([TcxAbstractWebDataBinding, TcxCustomWebDataBinding, TcxCustomWebDataField, TcxStdWebDataField, TcxStdWebDataSource]); end.