git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@38 05c56307-c608-d34a-929d-697000501d7a
3218 lines
80 KiB
ObjectPascal
3218 lines
80 KiB
ObjectPascal
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressEditors }
|
|
{ }
|
|
{ Copyright (c) 1998-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSEDITORS AND ALL }
|
|
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
unit cxMaskEdit;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
Variants,
|
|
{$ENDIF}
|
|
Windows,
|
|
Messages,
|
|
SysUtils, Classes, Controls, StdCtrls, Clipbrd, cxClasses, cxControls, cxContainer,
|
|
cxDataStorage, cxDataUtils, cxEdit, cxTextEdit, cxEditConsts, cxRegExpr,
|
|
cxStandardMask, cxFilterControlUtils;
|
|
|
|
type
|
|
TcxEditMask = type string;
|
|
TcxEditMaskKind = (emkStandard, emkRegExpr, emkRegExprEx);
|
|
|
|
TcxCustomMaskEdit = class;
|
|
TcxCustomMaskEditProperties = class;
|
|
|
|
{ EcxMaskEditError }
|
|
|
|
EcxMaskEditError = class(EcxEditError);
|
|
|
|
{ TcxMaskEditCustomMode }
|
|
|
|
TcxMaskEditCustomMode = class
|
|
private
|
|
FCharCase: TEditCharCase;
|
|
FEchoMode: TcxEditEchoMode;
|
|
FEditMask: string;
|
|
FProperties: TcxCustomMaskEditProperties;
|
|
function GetProperties: TcxCustomMaskEditProperties;
|
|
protected
|
|
FClipboardTextLength: Integer;
|
|
FEdit: TcxCustomMaskEdit;
|
|
FNeedUpdateEditValue: Boolean;
|
|
procedure ClearText;
|
|
function GetMaskKind: TcxEditMaskKind; virtual;
|
|
function HasEdit: Boolean;
|
|
property CharCase: TEditCharCase read FCharCase write FCharCase;
|
|
property EchoMode: TcxEditEchoMode read FEchoMode write FEchoMode;
|
|
property EditMask: string read FEditMask;
|
|
property Properties: TcxCustomMaskEditProperties read GetProperties;
|
|
public
|
|
constructor Create(AEdit: TcxCustomMaskEdit; AProperties: TcxCustomMaskEditProperties); virtual;
|
|
procedure AfterPasteFromClipboard; virtual; abstract;
|
|
procedure BeepOnError;
|
|
procedure Compile(AMask: string); virtual; abstract;
|
|
function GetEmptyString: string; virtual; abstract;
|
|
function GetFormattedText(AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string; virtual; abstract;
|
|
procedure GotoEnd; virtual; abstract;
|
|
function IsCursorBegin: Boolean; virtual; abstract;
|
|
function IsCursorEnd: Boolean; virtual; abstract;
|
|
function IsFullValidText(AText: string): Boolean; virtual; abstract;
|
|
procedure LMouseDown; virtual; abstract;
|
|
procedure PrePasteFromClipboard; virtual; abstract;
|
|
function PressBackSpace: Boolean; virtual; abstract;
|
|
function PressDelete: Boolean; virtual; abstract;
|
|
function PressEnd: Boolean; virtual; abstract;
|
|
function PressHome: Boolean; virtual; abstract;
|
|
function PressLeft: Boolean; virtual; abstract;
|
|
function PressRight: Boolean; virtual; abstract;
|
|
function PressSymbol(var ASymbol: Char): Boolean; virtual; abstract;
|
|
procedure SetText(AText: string); virtual; abstract;
|
|
procedure SynchronizeEditValue; virtual;
|
|
procedure UpdateEditValue; virtual; abstract;
|
|
function GetUpdatedText(const AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string; virtual; abstract;
|
|
property ClipboardTextLength: Integer read FClipboardTextLength write FClipboardTextLength;
|
|
end;
|
|
|
|
TcxMaskEditCustomModeClass = class of TcxMaskEditCustomMode;
|
|
|
|
{ TcxMaskEditStandardMode }
|
|
|
|
TcxMaskEditStandardMode = class(TcxMaskEditCustomMode)
|
|
protected
|
|
FMask: TcxStandardMask;
|
|
FSelStart: Integer;
|
|
function GetBlank(APos: Integer): Char; virtual;
|
|
public
|
|
constructor Create(AEdit: TcxCustomMaskEdit; AProperties: TcxCustomMaskEditProperties); override;
|
|
destructor Destroy; override;
|
|
procedure AfterPasteFromClipboard; override;
|
|
procedure Compile(AMask: string); override;
|
|
function GetEmptyString: string; override;
|
|
function GetFormattedText(AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string; override;
|
|
procedure GotoEnd; override;
|
|
function IsCursorBegin: Boolean; override;
|
|
function IsCursorEnd: Boolean; override;
|
|
function IsFullValidText(AText: string): Boolean; override;
|
|
procedure LMouseDown; override;
|
|
procedure PrePasteFromClipboard; override;
|
|
function PressBackSpace: Boolean; override;
|
|
function PressDelete: Boolean; override;
|
|
function PressEnd: Boolean; override;
|
|
function PressHome: Boolean; override;
|
|
function PressLeft: Boolean; override;
|
|
function PressRight: Boolean; override;
|
|
function PressSymbol(var ASymbol: Char): Boolean; override;
|
|
procedure SetText(AText: string); override;
|
|
procedure SynchronizeEditValue; override;
|
|
procedure UpdateEditValue; override;
|
|
function GetUpdatedText(const AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string; override;
|
|
end;
|
|
|
|
{ TcxMaskEditRegExprMode }
|
|
|
|
TcxMaskEditRegExprMode = class(TcxMaskEditCustomMode)
|
|
protected
|
|
FBeginCursor: Boolean;
|
|
FHead: string;
|
|
FRegExpr: TcxRegExpr;
|
|
FSelect: string;
|
|
FTail: string;
|
|
FMouseAction: Boolean;
|
|
procedure ClearTail;
|
|
function CompileRegExpr(ARegExpr: TcxRegExpr): Boolean;
|
|
procedure CursorCorrection;
|
|
procedure DeleteSelection; virtual;
|
|
function GetMaskKind: TcxEditMaskKind; override;
|
|
function NextTail: Boolean;
|
|
procedure RestoreSelection; virtual;
|
|
public
|
|
constructor Create(AEdit: TcxCustomMaskEdit; AProperties: TcxCustomMaskEditProperties); override;
|
|
destructor Destroy; override;
|
|
procedure AfterPasteFromClipboard; override;
|
|
procedure Compile(AMask: string); override;
|
|
function GetEmptyString: string; override;
|
|
function GetFormattedText(AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string; override;
|
|
procedure GotoEnd; override;
|
|
function IsCursorBegin: Boolean; override;
|
|
function IsCursorEnd: Boolean; override;
|
|
function IsFullValidText(AText: string): Boolean; override;
|
|
procedure LMouseDown; override;
|
|
procedure PrePasteFromClipboard; override;
|
|
function PressBackSpace: Boolean; override;
|
|
function PressDelete: Boolean; override;
|
|
function PressEnd: Boolean; override;
|
|
function PressHome: Boolean; override;
|
|
function PressLeft: Boolean; override;
|
|
function PressRight: Boolean; override;
|
|
function PressSymbol(var ASymbol: Char): Boolean; override;
|
|
procedure SetText(AText: string); override;
|
|
procedure SetRegExprCaseInsensitive;
|
|
procedure SynchronizeEditValue; override;
|
|
procedure UpdateEditValue; override;
|
|
function GetUpdatedText(const AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string; override;
|
|
end;
|
|
|
|
{ TcxMaskEditRegExprExMode }
|
|
|
|
TcxMaskEditRegExprExMode = class(TcxMaskEditRegExprMode)
|
|
private
|
|
FInternalUpdate: string;
|
|
procedure InternalSymbolUpdate(ASymbol: Char);
|
|
protected
|
|
FDeleteNumber: Integer;
|
|
FNewCursorPos: Integer;
|
|
FUpdate: string;
|
|
procedure Clear;
|
|
procedure CursorCorrection;
|
|
procedure DeleteSelection; override;
|
|
function GetMaskKind: TcxEditMaskKind; override;
|
|
procedure RestoreSelection; override;
|
|
procedure SymbolDelete;
|
|
procedure SymbolUpdate(ASymbol: Char);
|
|
procedure UpdateTail;
|
|
public
|
|
constructor Create(AEdit: TcxCustomMaskEdit; AProperties: TcxCustomMaskEditProperties); override;
|
|
destructor Destroy; override;
|
|
procedure AfterPasteFromClipboard; override;
|
|
procedure Compile(AMask: string); override;
|
|
function GetEmptyString: string; override;
|
|
function GetFormattedText(AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string; override;
|
|
procedure GotoEnd; override;
|
|
function IsFullValidText(AText: string): Boolean; override;
|
|
procedure PrePasteFromClipboard; override;
|
|
function PressBackSpace: Boolean; override;
|
|
function PressDelete: Boolean; override;
|
|
function PressEnd: Boolean; override;
|
|
function PressHome: Boolean; override;
|
|
function PressLeft: Boolean; override;
|
|
function PressRight: Boolean; override;
|
|
function PressSymbol(var ASymbol: Char): Boolean; override;
|
|
procedure SetText(AText: string); override;
|
|
procedure UpdateEditValue; override;
|
|
end;
|
|
|
|
{ TcxCustomMaskEditProperties }
|
|
|
|
TcxCustomMaskEditProperties = class(TcxCustomTextEditProperties)
|
|
private
|
|
FAlwaysShowBlanksAndLiterals: Boolean;
|
|
FCaseInsensitive: Boolean;
|
|
FEditMask: TcxEditMask;
|
|
FEmptyString: string;
|
|
FIgnoreMaskBlank: Boolean;
|
|
FMaskKind: TcxEditMaskKind;
|
|
FMaxLengthSetting: Boolean;
|
|
FTempMode: TcxMaskEditCustomMode;
|
|
function CreateMode: TcxMaskEditCustomMode;
|
|
function CreateMode1: TcxMaskEditCustomMode;
|
|
function GetEditMask: TcxEditMask;
|
|
function GetIsMasked: Boolean;
|
|
procedure SetAlwaysShowBlanksAndLiterals(AValue: Boolean);
|
|
procedure SetCaseInsensitive(AValue: Boolean);
|
|
procedure SetEditMask(Value: TcxEditMask);
|
|
procedure SetMaskKind(Value: TcxEditMaskKind);
|
|
function SpaceToken(AToken: Char): Boolean;
|
|
function TestTempEditMask: Boolean;
|
|
function TestTempMaskKind: Boolean;
|
|
protected
|
|
function EmptyMask(AMask: string): Boolean;
|
|
function GetEmptyString: string;
|
|
procedure SetCharCase(Value: TEditCharCase); override;
|
|
function GetDisplayFormatOptions: TcxEditDisplayFormatOptions; override;
|
|
function GetModeClass(AMaskKind: TcxEditMaskKind): TcxMaskEditCustomModeClass; virtual;
|
|
procedure MaxLengthChanged; override;
|
|
function UseLookupData: Boolean; override;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure Changed; override;
|
|
class function GetContainerClass: TcxContainerClass; override;
|
|
// function GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource; override;
|
|
function IsEditValueValid(var EditValue: TcxEditValue; AEditFocused: Boolean): Boolean; override;
|
|
procedure PrepareDisplayValue(const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue;
|
|
AEditFocused: Boolean); override;
|
|
procedure ValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption;
|
|
var Error: Boolean; AEdit: TcxCustomEdit); override;
|
|
public
|
|
property IsMasked: Boolean read GetIsMasked;
|
|
// !!!
|
|
property AlwaysShowBlanksAndLiterals: Boolean
|
|
read FAlwaysShowBlanksAndLiterals write SetAlwaysShowBlanksAndLiterals
|
|
default False;
|
|
property CaseInsensitive: Boolean read FCaseInsensitive
|
|
write SetCaseInsensitive default True;
|
|
property EditMask: TcxEditMask read GetEditMask write SetEditMask;
|
|
property IgnoreMaskBlank: Boolean read FIgnoreMaskBlank
|
|
write FIgnoreMaskBlank default False;
|
|
property MaskKind: TcxEditMaskKind read FMaskKind write SetMaskKind
|
|
default emkStandard;
|
|
property ValidateOnEnter default True;
|
|
end;
|
|
|
|
TcxMaskEditProperties = class;
|
|
|
|
{ TcxCustomMaskEdit }
|
|
|
|
TcxCustomMaskEdit = class(TcxCustomTextEdit)
|
|
private
|
|
FInternalTextSelection: Boolean;
|
|
FMode: TcxMaskEditCustomMode;
|
|
FMyMessage: Boolean;
|
|
FShiftOn: Boolean;
|
|
FText: string;
|
|
function GetEditText: TCaption;
|
|
function GetProperties: TcxCustomMaskEditProperties;
|
|
function GetActiveProperties: TcxCustomMaskEditProperties;
|
|
function InternalGetEmptyString: string;
|
|
procedure InternalSetValue(AValue: string);
|
|
function IsCursorBegin: Boolean;
|
|
function IsCursorEnd: Boolean;
|
|
procedure SetEditText(AValue: TCaption);
|
|
procedure SetProperties(Value: TcxCustomMaskEditProperties);
|
|
procedure SendMyKeyDown(Key: Word; Shift: TShiftState);
|
|
procedure SendMyKeyPress(AKey: Char);
|
|
protected
|
|
procedure ChangeHandler(Sender: TObject); override;
|
|
procedure DblClick; override;
|
|
procedure DoEnter; override;
|
|
procedure DoEditKeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure DoEditKeyPress(var Key: Char); override;
|
|
procedure DoEditKeyUp(var Key: Word; Shift: TShiftState); override;
|
|
procedure Initialize; override;
|
|
function InternalGetText: string; override;
|
|
procedure InternalSetDisplayValue(const Value: TcxEditValue); override;
|
|
function InternalSetText(const Value: string): Boolean; override;
|
|
function IsTextInputMode: Boolean; override;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
|
|
procedure Loaded; override;
|
|
procedure LockInnerEditRepainting; override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure PropertiesChanged(Sender: TObject); override;
|
|
procedure SelChange(Sender: TObject); override;
|
|
procedure SetSelText(const Value: TCaption); override;
|
|
procedure SynchronizeDisplayValue; override;
|
|
procedure UndoPerformed; override;
|
|
procedure UnlockInnerEditRepainting; override;
|
|
function CanSynchronizeModeText: Boolean; virtual;
|
|
procedure DirectSetSelLength(AValue: Integer);
|
|
procedure DirectSetSelStart(AValue: Integer);
|
|
function IsCharValidForPos(var AChar: Char; APos: Integer): Boolean; virtual;
|
|
procedure UpdateTextFormatting; virtual;
|
|
property Mode: TcxMaskEditCustomMode read FMode;
|
|
public
|
|
{$IFDEF CBUILDER10}
|
|
constructor Create(AOwner: TComponent); override;
|
|
{$ENDIF}
|
|
destructor Destroy; override;
|
|
procedure CutToClipboard; override;
|
|
class function GetPropertiesClass: TcxCustomEditPropertiesClass; override;
|
|
procedure PasteFromClipboard; override;
|
|
procedure PrepareEditValue(const ADisplayValue: TcxEditValue;
|
|
out EditValue: TcxEditValue; AEditFocused: Boolean); override;
|
|
property ActiveProperties: TcxCustomMaskEditProperties read GetActiveProperties;
|
|
property EditText: TCaption read GetEditText write SetEditText;
|
|
property Properties: TcxCustomMaskEditProperties read GetProperties
|
|
write SetProperties;
|
|
end;
|
|
|
|
{ TcxMaskEditProperties }
|
|
|
|
TcxMaskEditProperties = class(TcxCustomMaskEditProperties)
|
|
published
|
|
property Alignment;
|
|
property AlwaysShowBlanksAndLiterals;
|
|
property AssignedValues;
|
|
property AutoSelect;
|
|
property BeepOnError;
|
|
property CaseInsensitive;
|
|
property CharCase;
|
|
property ClearKey;
|
|
property EchoMode;
|
|
property HideSelection;
|
|
property IgnoreMaskBlank;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property IncrementalSearch;
|
|
property LookupItems;
|
|
property LookupItemsSorted;
|
|
property MaskKind;
|
|
property EditMask;
|
|
property MaxLength;
|
|
property OEMConvert;
|
|
property PasswordChar;
|
|
property ReadOnly;
|
|
property UseLeftAlignmentOnEditing;
|
|
property ValidateOnEnter;
|
|
property OnChange;
|
|
property OnEditValueChanged;
|
|
property OnNewLookupDisplayText;
|
|
property OnValidate;
|
|
end;
|
|
|
|
{ TcxMaskEdit }
|
|
|
|
TcxMaskEdit = class(TcxCustomMaskEdit)
|
|
private
|
|
function GetActiveProperties: TcxMaskEditProperties;
|
|
function GetProperties: TcxMaskEditProperties;
|
|
procedure SetProperties(Value: TcxMaskEditProperties);
|
|
public
|
|
function SupportsSpelling: Boolean; override;
|
|
class function GetPropertiesClass: TcxCustomEditPropertiesClass; override;
|
|
property ActiveProperties: TcxMaskEditProperties read GetActiveProperties;
|
|
published
|
|
property Anchors;
|
|
property AutoSize;
|
|
property BeepOnEnter;
|
|
property Constraints;
|
|
property DragMode;
|
|
property Enabled;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property Properties: TcxMaskEditProperties read GetProperties write SetProperties;
|
|
property ShowHint;
|
|
property Style;
|
|
property StyleDisabled;
|
|
property StyleFocused;
|
|
property StyleHot;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Text;
|
|
{$IFDEF DELPHI12}
|
|
property TextHint;
|
|
{$ENDIF}
|
|
property Visible;
|
|
property DragCursor;
|
|
property DragKind;
|
|
property ImeMode;
|
|
property ImeName;
|
|
property OnClick;
|
|
{$IFDEF DELPHI5}
|
|
property OnContextPopup;
|
|
{$ENDIF}
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEditing;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseEnter;
|
|
property OnMouseLeave;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDrag;
|
|
property OnEndDock;
|
|
property OnStartDock;
|
|
end;
|
|
|
|
{ TcxFilterMaskEditHelper }
|
|
|
|
TcxFilterMaskEditHelper = class(TcxFilterTextEditHelper)
|
|
public
|
|
class function GetFilterEditClass: TcxCustomEditClass; override;
|
|
class function GetSupportedFilterOperators(
|
|
AProperties: TcxCustomEditProperties;
|
|
AValueTypeClass: TcxValueTypeClass;
|
|
AExtendedSet: Boolean = False): TcxFilterControlOperators; override;
|
|
class procedure InitializeProperties(AProperties,
|
|
AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean); override;
|
|
end;
|
|
|
|
function IsAlphaChar(ch: Char): Boolean;
|
|
//function GetSaveLiteralChars(AMaskEdit: TcxCustomMaskEdit): Boolean;
|
|
|
|
implementation
|
|
|
|
uses
|
|
cxVariants;
|
|
|
|
function IsAlphaChar(ch: Char): Boolean;
|
|
begin
|
|
Result := IsCharAlpha(ch);
|
|
end;
|
|
|
|
{function GetSaveLiteralChars(AMaskEdit: TcxCustomMaskEdit): Boolean;
|
|
begin
|
|
Result := False;
|
|
if AMaskEdit.Mode is TcxMaskEditStandardMode then
|
|
if TcxMaskEditStandardMode(AMaskEdit.Mode).FMask <> nil then
|
|
Result := TcxMaskEditStandardMode(AMaskEdit.Mode).FMask.SaveLiteralCharacters;
|
|
end;}
|
|
|
|
{ TcxMaskEditCustomMode }
|
|
|
|
constructor TcxMaskEditCustomMode.Create(AEdit: TcxCustomMaskEdit;
|
|
AProperties: TcxCustomMaskEditProperties);
|
|
begin
|
|
inherited Create;
|
|
FEdit := AEdit;
|
|
if FEdit = nil then
|
|
FProperties := AProperties;
|
|
FClipboardTextLength := 0;
|
|
FNeedUpdateEditValue := False;
|
|
FCharCase := ecNormal;
|
|
FEchoMode := eemNormal;
|
|
end;
|
|
|
|
procedure TcxMaskEditCustomMode.BeepOnError;
|
|
begin
|
|
if Properties.BeepOnError then
|
|
Beep;
|
|
end;
|
|
|
|
procedure TcxMaskEditCustomMode.SynchronizeEditValue;
|
|
var
|
|
ADisplayValue: Variant;
|
|
begin
|
|
if HasEdit then
|
|
begin
|
|
with FEdit do
|
|
begin
|
|
if ModifiedAfterEnter then
|
|
begin
|
|
ADisplayValue := FEdit.DisplayValue;
|
|
ADisplayValue := GetFormattedText(ADisplayValue);
|
|
end
|
|
else
|
|
ActiveProperties.PrepareDisplayValue(EditValue, ADisplayValue, Focused);
|
|
end;
|
|
FEdit.SetInternalDisplayValue(ADisplayValue);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditCustomMode.ClearText;
|
|
begin
|
|
if HasEdit then
|
|
FEdit.DataBinding.UpdateNotConnectedDBEditDisplayValue;
|
|
end;
|
|
|
|
function TcxMaskEditCustomMode.GetMaskKind: TcxEditMaskKind;
|
|
begin
|
|
Result := emkStandard;
|
|
end;
|
|
|
|
function TcxMaskEditCustomMode.HasEdit: Boolean;
|
|
begin
|
|
Result := (FEdit <> nil) and not FEdit.PropertiesChangeLocked;
|
|
end;
|
|
|
|
function TcxMaskEditCustomMode.GetProperties: TcxCustomMaskEditProperties;
|
|
begin
|
|
if FEdit <> nil then
|
|
Result := FEdit.ActiveProperties
|
|
else
|
|
Result := FProperties;
|
|
end;
|
|
|
|
{ TcxMaskEditStandardMode }
|
|
|
|
constructor TcxMaskEditStandardMode.Create(AEdit: TcxCustomMaskEdit;
|
|
AProperties: TcxCustomMaskEditProperties);
|
|
begin
|
|
inherited Create(AEdit, AProperties);
|
|
|
|
FMask := TcxStandardMask.Create;
|
|
end;
|
|
|
|
destructor TcxMaskEditStandardMode.Destroy;
|
|
begin
|
|
FMask.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxMaskEditStandardMode.AfterPasteFromClipboard;
|
|
var
|
|
AText: string;
|
|
begin
|
|
AText := Clipboard.AsText;
|
|
FEdit.SelStart := FSelStart + Length(AText);
|
|
if FEdit.SelStart >= Length(FEdit.EditText) then
|
|
FEdit.SelStart := Length(FEdit.EditText) - 1;
|
|
if FEdit.SelStart < 0 then
|
|
FEdit.SelStart := 0;
|
|
if FMask.Items[FEdit.SelStart] is TcxStandardMaskLiteralItem then
|
|
begin
|
|
FEdit.FShiftOn := False;
|
|
PressRight;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditStandardMode.Compile(AMask: string);
|
|
begin
|
|
FEditMask := AMask;
|
|
if Properties.EmptyMask(AMask) then
|
|
Exit;
|
|
|
|
FMask.Compile(AMask);
|
|
|
|
FNeedUpdateEditValue := not HasEdit;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.GetEmptyString: string;
|
|
begin
|
|
Result := FMask.EmptyString;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.GetFormattedText(AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string;
|
|
begin
|
|
FMask.Format(AText, True, AMatchForBlanksAndLiterals);
|
|
Result := AText;
|
|
end;
|
|
|
|
procedure TcxMaskEditStandardMode.GotoEnd;
|
|
begin
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.IsCursorBegin: Boolean;
|
|
var
|
|
I: Integer;
|
|
ACount: Integer;
|
|
begin
|
|
ACount := 0;
|
|
for I := 0 to FMask.Count - 1 do
|
|
begin
|
|
if FMask.Items[I] is TcxStandardMaskLiteralItem then
|
|
Inc(ACount)
|
|
else
|
|
Break;
|
|
end;
|
|
Result := (FEdit.SelStart <= ACount) and (FEdit.SelLength <= 1) or
|
|
(FEdit.SelStart <= ACount) and (FEdit.CursorPos = FEdit.SelStart);
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.IsCursorEnd: Boolean;
|
|
begin
|
|
Result := FEdit.SelStart = Length(FEdit.EditText);
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.IsFullValidText(AText: string): Boolean;
|
|
begin
|
|
Result := FMask.IsFullValid(AText);
|
|
if not Result and Properties.IgnoreMaskBlank then
|
|
Result := AText = GetFormattedText('');
|
|
end;
|
|
|
|
procedure TcxMaskEditStandardMode.LMouseDown;
|
|
begin
|
|
if FEdit.HandleAllocated and Properties.IsMasked then
|
|
begin
|
|
if FEdit.SelLength = 0 then
|
|
FEdit.DirectSetSelLength(1);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditStandardMode.PrePasteFromClipboard;
|
|
var
|
|
AText: string;
|
|
begin
|
|
AText := Clipboard.AsText;
|
|
FSelStart := FEdit.SelStart;
|
|
FEdit.DirectSetSelStart(FSelStart);
|
|
FEdit.DirectSetSelLength(Length(AText));
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.PressBackSpace: Boolean;
|
|
begin
|
|
Result := False;
|
|
|
|
if FEdit.SelLength <= 1 then
|
|
PressLeft;
|
|
PressDelete;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.PressDelete: Boolean;
|
|
var
|
|
ABlank: Char;
|
|
ASelStart: Integer;
|
|
AText: string;
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
|
|
AText := FEdit.EditText;
|
|
ASelStart := FEdit.SelStart;
|
|
for I := FEdit.SelStart to FEdit.SelStart + FEdit.SelLength - 1 do
|
|
begin
|
|
if FMask.Items[I] is TcxStandardMaskManyItem then
|
|
begin
|
|
ABlank := GetBlank(I + 1);
|
|
if ABlank <> #0 then
|
|
begin
|
|
Delete(AText, I + 1, 1);
|
|
Insert(ABlank, AText, I + 1);
|
|
FEdit.SetInternalDisplayValue(AText);
|
|
FEdit.SelStart := ASelStart;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.PressEnd: Boolean;
|
|
begin
|
|
if FEdit.FShiftOn then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end
|
|
else
|
|
Result := False;
|
|
|
|
FEdit.SelStart := Length(FEdit.EditText);
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.PressHome: Boolean;
|
|
begin
|
|
if FEdit.FShiftOn then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end
|
|
else
|
|
Result := False;
|
|
|
|
FEdit.SelStart := 0;
|
|
if FMask.Count > 0 then
|
|
if FMask.Items[FEdit.SelStart] is TcxStandardMaskLiteralItem then
|
|
PressRight;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.PressLeft: Boolean;
|
|
function GetSelStart: Integer;
|
|
var
|
|
I: Integer;
|
|
AReset: Boolean;
|
|
AEnd: Integer;
|
|
begin
|
|
Result := 0;
|
|
AReset := True;
|
|
AEnd := FEdit.SelStart + FEdit.SelLength;
|
|
if AEnd >= Length(FEdit.EditText) then
|
|
Dec(AEnd);
|
|
if AEnd < 0 then
|
|
AEnd := 0;
|
|
for I := FEdit.SelStart to AEnd do
|
|
begin
|
|
if FMask.Items[I] is TcxStandardMaskLiteralItem then
|
|
Inc(Result)
|
|
else
|
|
begin
|
|
AReset := False;
|
|
Break;
|
|
end;
|
|
end;
|
|
if AReset then
|
|
begin
|
|
if FEdit.SelStart + FEdit.SelLength >= Length(FEdit.EditText) then
|
|
begin
|
|
Result := AEnd - FEdit.SelStart;
|
|
Inc(Result);
|
|
end
|
|
else
|
|
Result := 0;
|
|
end;
|
|
end;
|
|
var
|
|
ADec: Integer;
|
|
ALeftLiteralCount: Integer;
|
|
I: Integer;
|
|
begin
|
|
if FEdit.FShiftOn then
|
|
begin
|
|
if FEdit.SelLength = 1 then
|
|
begin
|
|
FEdit.SelStart := FEdit.SelStart + 1;
|
|
FEdit.SelLength := 0;
|
|
FEdit.SendMyKeyDown(VK_LEFT, []);
|
|
FEdit.SendMyKeyDown(VK_LEFT, []);
|
|
end;
|
|
|
|
Result := True;
|
|
Exit;
|
|
end
|
|
else
|
|
Result := False;
|
|
|
|
if FEdit.SelLength > 1 then
|
|
begin
|
|
I := FEdit.SelStart + GetSelStart;
|
|
FEdit.SelStart := 0;
|
|
FEdit.SelStart := I;
|
|
Exit;
|
|
end;
|
|
|
|
ALeftLiteralCount := 0;
|
|
for I := FEdit.SelStart - 1 downto 0 do
|
|
begin
|
|
if FMask.Items[I] is TcxStandardMaskLiteralItem then
|
|
Inc(ALeftLiteralCount)
|
|
else
|
|
Break;
|
|
end;
|
|
|
|
ADec := ALeftLiteralCount + 1;
|
|
if FEdit.SelStart - ADec < 0 then
|
|
ADec := 0;
|
|
|
|
if FEdit.SelStart > 0 then
|
|
FEdit.SelStart := FEdit.SelStart - ADec;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.PressRight: Boolean;
|
|
function GetSelStart(AI: Integer): Integer;
|
|
var
|
|
I: Integer;
|
|
AReset: Boolean;
|
|
begin
|
|
Result := 0;
|
|
AReset := True;
|
|
for I := AI downto FEdit.SelStart do
|
|
begin
|
|
if FMask.Items[I] is TcxStandardMaskLiteralItem then
|
|
Inc(Result)
|
|
else
|
|
begin
|
|
AReset := False;
|
|
Break;
|
|
end;
|
|
end;
|
|
if AReset then
|
|
Result := 0;
|
|
end;
|
|
var
|
|
AInc: Integer;
|
|
ARightLiteralCount: Integer;
|
|
I: Integer;
|
|
begin
|
|
if FEdit.FShiftOn then
|
|
begin
|
|
if (FEdit.SelLength = 1) and (FEdit.SelStart = FEdit.CursorPos) then
|
|
FEdit.SelLength := 0;
|
|
|
|
Result := True;
|
|
Exit;
|
|
end
|
|
else
|
|
Result := False;
|
|
|
|
if FEdit.SelLength > 1 then
|
|
begin
|
|
I := FEdit.SelStart + FEdit.SelLength;
|
|
if I < Length(FEdit.EditText) then
|
|
begin
|
|
Dec(I);
|
|
Dec(I, GetSelStart(I));
|
|
end;
|
|
FEdit.SelStart := 0;
|
|
FEdit.SelStart := I;
|
|
Exit;
|
|
end;
|
|
|
|
ARightLiteralCount := 0;
|
|
for I := FEdit.SelStart + 1 to FMask.Count - 1 do
|
|
begin
|
|
if FMask.Items[I] is TcxStandardMaskLiteralItem then
|
|
Inc(ARightLiteralCount)
|
|
else
|
|
Break;
|
|
end;
|
|
|
|
AInc := ARightLiteralCount + 1;
|
|
if FEdit.SelStart + AInc > Length(FEdit.EditText) then
|
|
AInc := 0;
|
|
|
|
FEdit.SelStart := FEdit.SelStart + AInc;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.PressSymbol(var ASymbol: Char): Boolean;
|
|
var
|
|
AText: string;
|
|
ASelStart: Integer;
|
|
begin
|
|
Result := False;
|
|
if Length(FEdit.EditText) <= 0 then
|
|
Exit;
|
|
if FEdit.SelStart >= Length(FEdit.EditText) then
|
|
Exit;
|
|
if FMask.Items[FEdit.SelStart] is TcxStandardMaskLiteralItem then
|
|
begin
|
|
FEdit.FShiftOn := False;
|
|
if FEdit.SelLength > 1 then
|
|
PressDelete;
|
|
ASelStart := FEdit.SelStart;
|
|
PressRight;
|
|
if FEdit.SelStart > ASelStart then
|
|
PressSymbol(ASymbol);
|
|
end
|
|
else
|
|
begin
|
|
if FMask.Items[FEdit.SelStart].Check(ASymbol) and
|
|
FEdit.IsCharValidForPos(ASymbol, FEdit.SelStart + 1) then
|
|
if ASymbol <> #0 then
|
|
begin
|
|
if FEdit.SelLength > 1 then
|
|
PressDelete;
|
|
AText := FEdit.EditText;
|
|
ASelStart := FEdit.SelStart;
|
|
Delete(AText, FEdit.SelStart + 1 , 1);
|
|
Insert(ASymbol, AText, FEdit.SelStart + 1);
|
|
FEdit.SetInternalDisplayValue(AText);
|
|
FEdit.SelStart := ASelStart;
|
|
FEdit.FShiftOn := False;
|
|
PressRight;
|
|
end
|
|
else
|
|
BeepOnError;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditStandardMode.SetText(AText: string);
|
|
begin
|
|
LMouseDown;
|
|
end;
|
|
|
|
procedure TcxMaskEditStandardMode.SynchronizeEditValue;
|
|
begin
|
|
inherited SynchronizeEditValue;
|
|
LMouseDown;
|
|
end;
|
|
|
|
procedure TcxMaskEditStandardMode.UpdateEditValue;
|
|
begin
|
|
if FNeedUpdateEditValue then
|
|
begin
|
|
FEdit.InternalEditValue := FMask.EmptyString;
|
|
FNeedUpdateEditValue := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.GetUpdatedText(const AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string;
|
|
begin
|
|
Result := AText;
|
|
if FMask.Count > 0 then
|
|
begin
|
|
FMask.Format(Result, Properties.CharCase = ecNormal, AMatchForBlanksAndLiterals);
|
|
FMask.Format2(Result);
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditStandardMode.GetBlank(APos: Integer): Char;
|
|
begin
|
|
Result := FMask.Blank;
|
|
end;
|
|
|
|
{ TcxMaskEditRegExprMode }
|
|
|
|
constructor TcxMaskEditRegExprMode.Create(AEdit: TcxCustomMaskEdit;
|
|
AProperties: TcxCustomMaskEditProperties);
|
|
begin
|
|
inherited Create(AEdit, AProperties);
|
|
|
|
FRegExpr := TcxRegExpr.Create;
|
|
FRegExpr.CaseInsensitive := Properties.CaseInsensitive;
|
|
FMouseAction := False;
|
|
end;
|
|
|
|
destructor TcxMaskEditRegExprMode.Destroy;
|
|
begin
|
|
FRegExpr.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.AfterPasteFromClipboard;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.Compile(AMask: string);
|
|
var
|
|
I: Integer;
|
|
AStream: TStringStream;
|
|
AStr: string;
|
|
begin
|
|
FEditMask := AMask;
|
|
if Properties.EmptyMask(AMask) then
|
|
Exit;
|
|
|
|
AStream := TStringStream.Create(AMask);
|
|
try
|
|
try
|
|
FRegExpr.Compile(AStream);
|
|
except
|
|
on E: EcxRegExprError do
|
|
begin
|
|
AStr := cxGetResourceString(@scxMaskEditRegExprError);
|
|
for I := 0 to E.Errors.Count - 1 do
|
|
AStr := AStr + #13#10 + E.Errors[I].FullMessage;
|
|
raise EcxMaskEditError.Create(AStr);
|
|
end;
|
|
end;
|
|
finally
|
|
AStream.Free;
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.PressDelete: Boolean;
|
|
begin
|
|
CursorCorrection;
|
|
if FEdit.SelLength <= 0 then
|
|
begin
|
|
if FTail <> '' then
|
|
begin
|
|
FSelect := FTail[1];
|
|
Delete(FTail, 1, 1);
|
|
|
|
if not NextTail then
|
|
begin
|
|
ClearTail;
|
|
if FEdit.SelStart > 0 then
|
|
FEdit.DirectSetSelStart(FEdit.SelStart - 1);
|
|
end;
|
|
end;
|
|
|
|
Result := True;
|
|
end
|
|
else
|
|
begin
|
|
DeleteSelection;
|
|
if NextTail then
|
|
Result := True
|
|
else
|
|
begin
|
|
FEdit.SendMyKeyDown(VK_DELETE, []);
|
|
ClearTail;
|
|
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
FSelect := '';
|
|
|
|
if not Result then
|
|
BeepOnError;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.PressEnd: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
CursorCorrection;
|
|
Result := True;
|
|
|
|
if FTail <> '' then
|
|
begin
|
|
for I := 1 to Length(FTail) do
|
|
begin
|
|
FRegExpr.Next(FTail[I]);
|
|
end;
|
|
FHead := FHead + FTail;
|
|
FTail := '';
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.PressHome: Boolean;
|
|
begin
|
|
CursorCorrection;
|
|
Result := True;
|
|
|
|
if FHead <> '' then
|
|
begin
|
|
FTail := FHead + FTail;
|
|
FHead := '';
|
|
FRegExpr.Reset;
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.GetEmptyString: string;
|
|
begin
|
|
Result := '';
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.GetFormattedText(AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if not FRegExpr.IsCompiled then
|
|
begin
|
|
Result := '';
|
|
Exit;
|
|
end;
|
|
FRegExpr.Reset;
|
|
Result := '';
|
|
for I := 1 to Length(AText) do
|
|
begin
|
|
if FRegExpr.Next(AText[I]) then
|
|
Result := Result + AText[I];
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.GotoEnd;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
CursorCorrection;
|
|
if FTail = '' then
|
|
Exit;
|
|
|
|
for I := 1 to Length(FTail) do
|
|
begin
|
|
FRegExpr.Next(FTail[I]);
|
|
end;
|
|
|
|
FHead := FHead + FTail;
|
|
FTail := '';
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.IsCursorBegin: Boolean;
|
|
begin
|
|
Result := FEdit.SelStart = 0;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.IsCursorEnd: Boolean;
|
|
begin
|
|
Result := FEdit.SelStart = Length(FEdit.Text);
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.IsFullValidText(AText: string): Boolean;
|
|
var
|
|
ARegExpr: TcxRegExpr;
|
|
I: Integer;
|
|
begin
|
|
Result := AText = '';
|
|
|
|
if not Result then
|
|
begin
|
|
ARegExpr := TcxRegExpr.Create;
|
|
ARegExpr.CaseInsensitive := Properties.CaseInsensitive;
|
|
|
|
Result := CompileRegExpr(ARegExpr);
|
|
if Result then
|
|
begin
|
|
for I := 1 to Length(AText) do
|
|
begin
|
|
if not ARegExpr.Next(AText[I]) then
|
|
begin
|
|
Result := False;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
if Result then
|
|
if not Properties.IgnoreMaskBlank then
|
|
Result := ARegExpr.IsFinal;
|
|
end;
|
|
|
|
ARegExpr.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.LMouseDown;
|
|
begin
|
|
FMouseAction := True;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.PrePasteFromClipboard;
|
|
begin
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.PressBackSpace: Boolean;
|
|
begin
|
|
CursorCorrection;
|
|
if FEdit.SelLength <= 0 then
|
|
begin
|
|
if FHead <> '' then
|
|
begin
|
|
FRegExpr.Prev;
|
|
if NextTail then
|
|
Delete(FHead, Length(FHead), 1)
|
|
else
|
|
ClearTail;
|
|
end;
|
|
|
|
Result := True;
|
|
end
|
|
else
|
|
begin
|
|
DeleteSelection;
|
|
if NextTail then
|
|
Result := True
|
|
else
|
|
begin
|
|
FEdit.SendMyKeyPress(#8);
|
|
|
|
ClearTail;
|
|
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
FSelect := '';
|
|
|
|
if not Result then
|
|
BeepOnError;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.PressLeft: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
CursorCorrection;
|
|
Result := True;
|
|
|
|
if FHead <> '' then
|
|
begin
|
|
if FEdit.SelLength > 0 then
|
|
begin
|
|
if (FEdit.CursorPos = FEdit.SelStart + FEdit.SelLength) and
|
|
not FEdit.FShiftOn then
|
|
begin
|
|
for I := 0 to FEdit.SelLength - 1 do
|
|
begin
|
|
FRegExpr.Prev;
|
|
FTail := FHead[Length(FHead)] + FTail;
|
|
Delete(FHead, Length(FHead), 1);
|
|
end;
|
|
|
|
Exit;
|
|
end
|
|
else if (FEdit.CursorPos = FEdit.SelStart) and not FEdit.FShiftOn then
|
|
Exit;
|
|
end;
|
|
|
|
FRegExpr.Prev;
|
|
FTail := FHead[Length(FHead)] + FTail;
|
|
Delete(FHead, Length(FHead), 1);
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.PressRight: Boolean;
|
|
|
|
procedure GetTailFirstChar;
|
|
begin
|
|
FRegExpr.Next(FTail[1]);
|
|
FHead := FHead + FTail[1];
|
|
Delete(FTail, 1, 1);
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
CursorCorrection;
|
|
Result := True;
|
|
|
|
if FTail <> '' then
|
|
begin
|
|
if FEdit.SelLength > 0 then
|
|
begin
|
|
if (FEdit.CursorPos = FEdit.SelStart) and
|
|
not FEdit.FShiftOn then
|
|
begin
|
|
for I := 0 to FEdit.SelLength - 1 do
|
|
GetTailFirstChar;
|
|
Exit;
|
|
end
|
|
else if (FEdit.CursorPos = FEdit.SelStart + FEdit.SelLength) and
|
|
not FEdit.FShiftOn then
|
|
Exit;
|
|
end;
|
|
|
|
GetTailFirstChar;
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.PressSymbol(var ASymbol: Char): Boolean;
|
|
begin
|
|
CursorCorrection;
|
|
if FEdit.SelLength > 0 then
|
|
DeleteSelection;
|
|
|
|
if FRegExpr.Next(ASymbol) then
|
|
begin
|
|
FHead := FHead + ASymbol;
|
|
if not NextTail then
|
|
begin
|
|
if FSelect <> '' then
|
|
begin
|
|
FEdit.SendMyKeyDown(VK_DELETE, []);
|
|
FEdit.SendMyKeyPress(ASymbol);
|
|
Result := False;
|
|
end
|
|
else
|
|
Result := True;
|
|
|
|
ClearTail;
|
|
end
|
|
else
|
|
Result := True;
|
|
end
|
|
else
|
|
begin
|
|
RestoreSelection;
|
|
Result := False;
|
|
end;
|
|
|
|
FSelect := '';
|
|
|
|
if not Result then
|
|
BeepOnError;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.SetText(AText: string);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FRegExpr.Reset;
|
|
|
|
if (ClipboardTextLength > 0) and (Length(AText) > 0) then
|
|
begin
|
|
FRegExpr.Reset;
|
|
for I := 1 to FEdit.SelStart + ClipboardTextLength do
|
|
begin
|
|
FRegExpr.Next(AText[I]);
|
|
end;
|
|
|
|
FHead := Copy(AText, 1, FEdit.SelStart + ClipboardTextLength);
|
|
FTail := Copy(AText, FEdit.SelStart + ClipboardTextLength + 1, Length(AText));
|
|
|
|
ClipboardTextLength := 0;
|
|
end
|
|
else
|
|
begin
|
|
FHead := '';
|
|
FTail := AText;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.SetRegExprCaseInsensitive;
|
|
begin
|
|
FRegExpr.CaseInsensitive := Properties.CaseInsensitive;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.UpdateEditValue;
|
|
begin
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.GetUpdatedText(const AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string;
|
|
begin
|
|
Result := AText;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.ClearTail;
|
|
var
|
|
AStr: string;
|
|
begin
|
|
AStr := FEdit.DataBinding.DisplayValue;
|
|
Delete(AStr, FEdit.SelStart + 1, Length(FTail));
|
|
FEdit.DataBinding.DisplayValue := AStr;
|
|
FEdit.DirectSetSelStart(Length(AStr));
|
|
FTail := '';
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.CompileRegExpr(
|
|
ARegExpr: TcxRegExpr): Boolean;
|
|
begin
|
|
if FRegExpr.Stream = nil then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
|
|
Result := True;
|
|
try
|
|
ARegExpr.Compile(FRegExpr.Stream);
|
|
except
|
|
on EcxMaskEditError do
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.CursorCorrection;
|
|
var
|
|
I: Integer;
|
|
ASymbol: Char;
|
|
begin
|
|
if ((FHead = '') and (FTail = '') and (FEdit.Text <> '')) or FMouseAction then
|
|
begin
|
|
FMouseAction := False;
|
|
FRegExpr.Reset;
|
|
FTail := FEdit.Text;
|
|
FHead := '';
|
|
for I := 0 to FEdit.CursorPos - 1 do
|
|
begin
|
|
if Length(FEdit.Text) > I then
|
|
begin
|
|
ASymbol := Char(FEdit.Text[I + 1]);
|
|
FRegExpr.Next(ASymbol);
|
|
FHead := FHead + FTail[1];
|
|
Delete(FTail, 1, 1);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.DeleteSelection;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if FEdit.SelStart = Length(FHead) then // Begin cursor
|
|
begin
|
|
FSelect := Copy(FTail, 1, FEdit.SelLength);
|
|
Delete(FTail, 1, FEdit.SelLength);
|
|
|
|
FBeginCursor := True;
|
|
end
|
|
else if (FEdit.SelStart + FEdit.SelLength) = Length(FHead) then // End cursor
|
|
begin
|
|
FSelect := Copy(FHead, FEdit.SelStart + 1, FEdit.SelLength);
|
|
Delete(FHead, FEdit.SelStart + 1, FEdit.SelLength);
|
|
for I := 1 to Length(FSelect) do
|
|
FRegExpr.Prev;
|
|
|
|
FBeginCursor := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.GetMaskKind: TcxEditMaskKind;
|
|
begin
|
|
Result := emkRegExpr;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprMode.NextTail: Boolean;
|
|
var
|
|
AIsCharValid: Boolean;
|
|
I, J, NextNumber: Integer;
|
|
begin
|
|
NextNumber := 0;
|
|
|
|
for I := 1 to Length(FTail) do
|
|
begin
|
|
AIsCharValid := FRegExpr.Next(FTail[I]);
|
|
if AIsCharValid then
|
|
Inc(NextNumber)
|
|
else
|
|
begin
|
|
for J := 0 to NextNumber - 1 do
|
|
FRegExpr.Prev;
|
|
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
for I := 1 to Length(FTail) do
|
|
FRegExpr.Prev;
|
|
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.RestoreSelection;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if FBeginCursor then
|
|
FTail := FSelect + FTail
|
|
else
|
|
begin
|
|
FHead := FHead + FSelect;
|
|
for I := 1 to Length(FSelect) do
|
|
begin
|
|
FRegExpr.Next(FSelect[I]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprMode.SynchronizeEditValue;
|
|
begin
|
|
inherited SynchronizeEditValue;
|
|
FEdit.SelStart := Length(FEdit.Text);
|
|
FHead := FEdit.Text;
|
|
FTail := '';
|
|
FRegExpr.Reset;
|
|
FRegExpr.NextEx(FHead);
|
|
end;
|
|
|
|
{ TcxMaskEditRegExprExMode }
|
|
|
|
constructor TcxMaskEditRegExprExMode.Create(AEdit: TcxCustomMaskEdit;
|
|
AProperties: TcxCustomMaskEditProperties);
|
|
begin
|
|
inherited Create(AEdit, AProperties);
|
|
|
|
FRegExpr.OnSymbolUpdate := SymbolUpdate;
|
|
FRegExpr.OnSymbolDelete := SymbolDelete;
|
|
FRegExpr.UpdateOn := True;
|
|
FNewCursorPos := -1;
|
|
Clear;
|
|
end;
|
|
|
|
destructor TcxMaskEditRegExprExMode.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.Clear;
|
|
begin
|
|
FUpdate := '';
|
|
FDeleteNumber := 0;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.RestoreSelection;
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
inherited RestoreSelection;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
|
|
if FUpdate <> '' then
|
|
begin
|
|
FRegExpr.Prev;
|
|
Clear;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.SymbolDelete;
|
|
begin
|
|
Inc(FDeleteNumber);
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.SymbolUpdate(ASymbol: Char);
|
|
begin
|
|
FUpdate := FUpdate + ASymbol;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.AfterPasteFromClipboard;
|
|
begin
|
|
if FNewCursorPos < 0 then
|
|
Exit;
|
|
|
|
FEdit.DirectSetSelStart(FNewCursorPos);
|
|
FNewCursorPos := -1;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.Compile(AMask: string);
|
|
var
|
|
I: Integer;
|
|
AStream: TStringStream;
|
|
AStr: string;
|
|
begin
|
|
Clear;
|
|
FEditMask := AMask;
|
|
if Properties.EmptyMask(AMask) then
|
|
Exit;
|
|
|
|
AStream := TStringStream.Create(AMask);
|
|
try
|
|
try
|
|
FRegExpr.Compile(AStream);
|
|
except
|
|
on E: EcxRegExprError do
|
|
begin
|
|
AStr := cxGetResourceString(@scxMaskEditRegExprError);
|
|
for I := 0 to E.Errors.Count - 1 do
|
|
AStr := AStr + #13#10 + E.Errors[I].FullMessage;
|
|
raise EcxMaskEditError.Create(AStr);
|
|
end;
|
|
end;
|
|
finally
|
|
AStream.Free;
|
|
end;
|
|
|
|
FNeedUpdateEditValue := not HasEdit;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.GetEmptyString: string;
|
|
var
|
|
ARegExpr: TcxRegExpr;
|
|
begin
|
|
ARegExpr := TcxRegExpr.Create;
|
|
ARegExpr.CaseInsensitive := Properties.CaseInsensitive;
|
|
ARegExpr.UpdateOn := False;
|
|
|
|
if CompileRegExpr(ARegExpr) then
|
|
begin
|
|
ARegExpr.OnSymbolUpdate := InternalSymbolUpdate;
|
|
FInternalUpdate := '';
|
|
ARegExpr.UpdateOn := True;
|
|
Result := FInternalUpdate;
|
|
end
|
|
else
|
|
Result := '';
|
|
|
|
ARegExpr.Free;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.GetFormattedText(AText: string;
|
|
AMatchForBlanksAndLiterals: Boolean = True): string;
|
|
begin
|
|
if not FRegExpr.IsCompiled then
|
|
begin
|
|
Result := '';
|
|
Exit;
|
|
end;
|
|
|
|
FRegExpr.UpdateOn := False;
|
|
Clear;
|
|
|
|
Result := inherited GetFormattedText(AText, AMatchForBlanksAndLiterals);
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
Result := Result + FUpdate;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.GotoEnd;
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
inherited GotoEnd;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.IsFullValidText(AText: string): Boolean;
|
|
var
|
|
ARegExpr: TcxRegExpr;
|
|
|
|
function IsStart: Boolean;
|
|
begin
|
|
ARegExpr.UpdateOn := True;
|
|
Result := AText = FInternalUpdate;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
ARegExpr := TcxRegExpr.Create;
|
|
ARegExpr.CaseInsensitive := Properties.CaseInsensitive;
|
|
ARegExpr.UpdateOn := False;
|
|
Result := CompileRegExpr(ARegExpr);
|
|
|
|
if Result then
|
|
begin
|
|
ARegExpr.OnSymbolUpdate := InternalSymbolUpdate;
|
|
FInternalUpdate := '';
|
|
if not IsStart then
|
|
begin
|
|
ARegExpr.UpdateOn := False;
|
|
ARegExpr.Reset;
|
|
for I := 1 to Length(AText) do
|
|
begin
|
|
if not ARegExpr.Next(AText[I]) then
|
|
begin
|
|
Result := False;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
if Result then
|
|
if not Properties.IgnoreMaskBlank then
|
|
Result := ARegExpr.IsFinal;
|
|
end;
|
|
end;
|
|
|
|
ARegExpr.Free;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.PrePasteFromClipboard;
|
|
begin
|
|
CursorCorrection;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.PressBackSpace: Boolean;
|
|
var
|
|
ASelLength: Integer;
|
|
I: Integer;
|
|
AText: string;
|
|
ADeletedCharCount: integer;
|
|
begin
|
|
CursorCorrection;
|
|
Clear;
|
|
|
|
if FEdit.SelLength <= 0 then
|
|
begin
|
|
if FHead = '' then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
|
|
FRegExpr.Prev;
|
|
|
|
if FRegExpr.IsStart then
|
|
if FEdit.SelStart = FDeleteNumber then
|
|
begin
|
|
FRegExpr.Next(FHead[1]);
|
|
Result := False;
|
|
BeepOnError;
|
|
Exit;
|
|
end;
|
|
|
|
AText := FEdit.Text;
|
|
for I := 0 to FDeleteNumber do
|
|
FEdit.SendMyKeyPress(#8);
|
|
ADeletedCharCount := Length(AText) - Length(FEdit.Text);
|
|
Delete(FHead, Length(FHead) - ADeletedCharCount + 1, ADeletedCharCount);
|
|
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
if NextTail then
|
|
UpdateTail
|
|
else
|
|
ClearTail;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
end
|
|
else
|
|
begin
|
|
DeleteSelection;
|
|
|
|
if FEdit.SelStart = 0 then
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
FRegExpr.UpdateOn := True;
|
|
if FUpdate <> '' then
|
|
begin
|
|
FHead := FUpdate;
|
|
Clear;
|
|
ASelLength := FEdit.SelLength;
|
|
FEdit.SelStart := Length(FHead);
|
|
FEdit.SelLength := ASelLength - FEdit.SelStart;
|
|
FTail := Copy(FEdit.Text, FEdit.SelStart + 1, FEdit.SelLength) + FTail;
|
|
Result := PressBackSpace;
|
|
Exit;
|
|
end
|
|
end;
|
|
|
|
FEdit.SendMyKeyPress(#8);
|
|
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
if NextTail then
|
|
UpdateTail
|
|
else
|
|
ClearTail;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
end;
|
|
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.PressDelete: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
CursorCorrection;
|
|
Clear;
|
|
|
|
if FEdit.SelLength <= 0 then
|
|
begin
|
|
if FTail = '' then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
|
|
if FEdit.SelStart = 0 then
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
FRegExpr.UpdateOn := True;
|
|
if FUpdate <> '' then
|
|
begin
|
|
FRegExpr.Prev;
|
|
Clear;
|
|
Result := False;
|
|
BeepOnError;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
FRegExpr.Next(FTail[1]);
|
|
for I := 0 to Length(FUpdate) do
|
|
FEdit.SendMyKeyDown(VK_DELETE, []);
|
|
Delete(FTail, 1, Length(FUpdate) + 1);
|
|
FRegExpr.Prev;
|
|
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
if NextTail then
|
|
UpdateTail
|
|
else
|
|
ClearTail;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
end
|
|
else
|
|
PressBackSpace;
|
|
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.PressEnd: Boolean;
|
|
begin
|
|
Result := True;
|
|
|
|
CursorCorrection;
|
|
Clear;
|
|
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
inherited PressEnd;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.PressHome: Boolean;
|
|
begin
|
|
Result := True;
|
|
|
|
CursorCorrection;
|
|
Clear;
|
|
|
|
inherited PressHome;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.PressLeft: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := True;
|
|
|
|
CursorCorrection;
|
|
Clear;
|
|
|
|
if FEdit.SelLength > 0 then
|
|
begin
|
|
if (FEdit.CursorPos = FEdit.SelStart + FEdit.SelLength) and
|
|
not FEdit.FShiftOn then
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
inherited PressLeft;
|
|
Clear;
|
|
FRegExpr.UpdateOn := True;
|
|
if FUpdate <> '' then
|
|
FRegexpr.Prev;
|
|
|
|
Exit;
|
|
end
|
|
else if (FEdit.CursorPos = FEdit.SelStart) and not FEdit.FShiftOn then
|
|
Exit;
|
|
end;
|
|
|
|
inherited PressLeft;
|
|
|
|
if FRegExpr.IsStart then
|
|
if FEdit.SelStart = 0 then
|
|
begin
|
|
if FEdit.SelLength = FDeleteNumber then
|
|
Dec(FDeleteNumber);
|
|
end
|
|
else
|
|
if FEdit.SelStart = FDeleteNumber then
|
|
Dec(FDeleteNumber);
|
|
|
|
if FDeleteNumber > 0 then
|
|
begin
|
|
for I := 0 to FDeleteNumber - 1 do
|
|
begin
|
|
FTail := FHead[Length(FHead) - I] + FTail;
|
|
FEdit.SendMyKeyDown(VK_LEFT, []);
|
|
end;
|
|
Delete(FHead, Length(FHead) - FDeleteNumber + 1, FDeleteNumber);
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.PressRight: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := True;
|
|
|
|
CursorCorrection;
|
|
Clear;
|
|
|
|
if FEdit.SelLength > 0 then
|
|
begin
|
|
if (FEdit.CursorPos = FEdit.SelStart) and
|
|
not FEdit.FShiftOn then
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
inherited PressRight;
|
|
Clear;
|
|
FRegExpr.UpdateOn := True;
|
|
|
|
Exit;
|
|
end
|
|
else if (FEdit.CursorPos = FEdit.SelStart + Fedit.SelLength) and
|
|
not FEdit.FShiftOn then
|
|
Exit;
|
|
end;
|
|
|
|
inherited PressRight;
|
|
|
|
if FUpdate <> '' then
|
|
begin
|
|
for I := 1 to Length(FUpdate) do
|
|
begin
|
|
FHead := FHead + FTail[I];
|
|
FEdit.SendMyKeyDown(VK_RIGHT, []);
|
|
end;
|
|
Delete(FTail, 1, Length(FUpdate));
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.PressSymbol(var ASymbol: Char): Boolean;
|
|
var
|
|
I: Integer;
|
|
ASelLength: Integer;
|
|
begin
|
|
CursorCorrection;
|
|
Clear;
|
|
|
|
if FEdit.SelLength > 0 then
|
|
begin
|
|
DeleteSelection;
|
|
if FEdit.SelStart = 0 then
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
FRegExpr.UpdateOn := True;
|
|
if FUpdate <> '' then
|
|
begin
|
|
FHead := FUpdate;
|
|
Clear;
|
|
ASelLength := FEdit.SelLength;
|
|
FEdit.SelStart := Length(FHead);
|
|
FEdit.SelLength := ASelLength - FEdit.SelStart;
|
|
FTail := Copy(FEdit.Text, FEdit.SelStart + 1, FEdit.SelLength) + FTail;
|
|
Result := PressSymbol(ASymbol);
|
|
Exit;
|
|
end
|
|
end;
|
|
end;
|
|
|
|
if FRegExpr.Next(ASymbol) then
|
|
begin
|
|
FHead := FHead + ASymbol + FUpdate;
|
|
|
|
FEdit.SendMyKeyPress(ASymbol);
|
|
for I := 1 to Length(FUpdate) do
|
|
FEdit.SendMyKeyPress(FUpdate[I]);
|
|
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
if NextTail then
|
|
UpdateTail
|
|
else
|
|
ClearTail;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
end
|
|
else
|
|
begin
|
|
if FEdit.SelLength > 0 then
|
|
RestoreSelection;
|
|
|
|
BeepOnError;
|
|
end;
|
|
|
|
FSelect := '';
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.SetText(AText: string);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
FRegExpr.Reset;
|
|
|
|
for I := 1 to Length(AText) do
|
|
begin
|
|
FRegExpr.Next(AText[I]);
|
|
end;
|
|
|
|
Clear;
|
|
FRegExpr.UpdateOn := True;
|
|
FHead := AText + FUpdate;
|
|
FTail := '';
|
|
|
|
if HasEdit then
|
|
begin
|
|
FMouseAction := True;
|
|
CursorCorrection;
|
|
end;
|
|
|
|
ClipboardTextLength := 0;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.UpdateEditValue;
|
|
begin
|
|
if FNeedUpdateEditValue then
|
|
begin
|
|
FEdit.InternalEditValue := FUpdate;
|
|
FNeedUpdateEditValue := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.CursorCorrection;
|
|
|
|
procedure Next;
|
|
begin
|
|
if FTail <> '' then
|
|
begin
|
|
Clear;
|
|
FRegExpr.Next(FTail[1]);
|
|
FHead := FHead + Copy(FTail, 1, Length(FUpdate) + 1);
|
|
Delete(FTail, 1, Length(FUpdate) + 1);
|
|
end;
|
|
end;
|
|
|
|
procedure Prev;
|
|
begin
|
|
if FHead <> '' then
|
|
begin
|
|
Clear;
|
|
FRegExpr.Prev;
|
|
|
|
FTail := Copy(FHead, Length(FHead) - FDeleteNumber, FDeleteNumber + 1) + FTail;
|
|
|
|
if FRegExpr.IsStart then
|
|
FHead := ''
|
|
else
|
|
Delete(FHead, Length(FHead) - FDeleteNumber, FDeleteNumber + 1);
|
|
end;
|
|
end;
|
|
|
|
procedure CorrectSelLength(ASelEnd: Integer);
|
|
begin
|
|
while True do
|
|
begin
|
|
Next;
|
|
if ASelEnd <= Length(FHead) then
|
|
begin
|
|
FEdit.DirectSetSelLength(Length(FHead) - FEdit.SelStart);
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ASelStart: Integer;
|
|
ASelEnd: Integer;
|
|
begin
|
|
if not HasEdit or not FEdit.HandleAllocated then
|
|
Exit;
|
|
|
|
if (FHead = '') and (FTail = '') and (FEdit.Text <> '') then
|
|
begin
|
|
FTail := FEdit.Text;
|
|
FRegExpr.Reset;
|
|
FMouseAction := True;
|
|
end;
|
|
|
|
if not FMouseAction then
|
|
Exit
|
|
else
|
|
FMouseAction := False;
|
|
|
|
ASelStart := FEdit.SelStart;
|
|
ASelEnd := FEdit.SelStart + FEdit.SelLength;
|
|
|
|
// Correct FEdit.SelStart
|
|
if ASelStart > Length(FHead) then
|
|
while True do
|
|
begin
|
|
Next;
|
|
if ASelStart < Length(FHead) then
|
|
begin
|
|
Prev;
|
|
FEdit.DirectSetSelStart(Length(FHead));
|
|
Break;
|
|
end
|
|
else
|
|
if ASelStart = Length(FHead) then
|
|
Break;
|
|
end
|
|
else
|
|
if ASelStart < Length(FHead) then
|
|
while True do
|
|
begin
|
|
Prev;
|
|
if ASelStart > Length(FHead) then
|
|
begin
|
|
FEdit.DirectSetSelStart(Length(FHead));
|
|
Break;
|
|
end
|
|
else
|
|
if ASelStart = Length(FHead) then
|
|
Break;
|
|
end;
|
|
|
|
// Correct FEdit.SelLength
|
|
if ASelEnd > ASelStart then
|
|
CorrectSelLength(ASelEnd);
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.DeleteSelection;
|
|
begin
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
inherited DeleteSelection;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
|
|
if FUpdate <> '' then
|
|
begin
|
|
FRegExpr.Prev;
|
|
Clear;
|
|
end;
|
|
end;
|
|
|
|
function TcxMaskEditRegExprExMode.GetMaskKind: TcxEditMaskKind;
|
|
begin
|
|
Result := emkRegExprEx;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.UpdateTail;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Clear;
|
|
|
|
if FTail = '' then
|
|
Exit;
|
|
|
|
for I := 1 to Length(FTail) do
|
|
begin
|
|
FRegExpr.Next(FTail[I]);
|
|
FEdit.DirectSetSelStart(FEdit.SelStart + 1);
|
|
end;
|
|
|
|
FRegExpr.UpdateOn := True;
|
|
|
|
if FUpdate <> '' then
|
|
for I := 1 to Length(FUpdate) do
|
|
begin
|
|
FTail := FTail + FUpdate[I];
|
|
FEdit.SendMyKeyPress(FUpdate[I]);
|
|
end;
|
|
|
|
FRegExpr.UpdateOn := False;
|
|
|
|
for I := 1 to Length(FTail) do
|
|
begin
|
|
FRegExpr.Prev;
|
|
FEdit.DirectSetSelStart(FEdit.SelStart - 1);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxMaskEditRegExprExMode.InternalSymbolUpdate(ASymbol: Char);
|
|
begin
|
|
FInternalUpdate := FInternalUpdate + ASymbol;
|
|
end;
|
|
|
|
{ TcxCustomMaskEditProperties }
|
|
|
|
constructor TcxCustomMaskEditProperties.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
|
|
MaskKind := emkStandard;
|
|
FAlwaysShowBlanksAndLiterals := False;
|
|
ValidateOnEnter := True;
|
|
CaseInsensitive := True;
|
|
FTempMode := nil;
|
|
end;
|
|
|
|
destructor TcxCustomMaskEditProperties.Destroy;
|
|
begin
|
|
FTempMode.Free;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxCustomMaskEditProperties then
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
inherited Assign(Source);
|
|
with Source as TcxCustomMaskEditProperties do
|
|
begin
|
|
Self.MaskKind := MaskKind;
|
|
Self.EditMask := EditMask;
|
|
Self.CaseInsensitive := CaseInsensitive;
|
|
Self.IgnoreMaskBlank := IgnoreMaskBlank;
|
|
Self.AlwaysShowBlanksAndLiterals := AlwaysShowBlanksAndLiterals;
|
|
end
|
|
finally
|
|
EndUpdate;
|
|
end
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.Changed;
|
|
begin
|
|
FreeAndNil(FTempMode);
|
|
inherited Changed;
|
|
end;
|
|
|
|
class function TcxCustomMaskEditProperties.GetContainerClass: TcxContainerClass;
|
|
begin
|
|
Result := TcxMaskEdit;
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.UseLookupData: Boolean;
|
|
begin
|
|
Result := not IsMasked and inherited UseLookupData;
|
|
end;
|
|
|
|
{function TcxCustomMaskEditProperties.GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource;
|
|
begin
|
|
if IsMasked then
|
|
Result := evsValue
|
|
else
|
|
Result := inherited GetEditValueSource(AEditFocused);
|
|
end;}
|
|
|
|
function TcxCustomMaskEditProperties.IsEditValueValid(var EditValue: TcxEditValue;
|
|
AEditFocused: Boolean): Boolean;
|
|
begin
|
|
Result := IsMasked or inherited IsEditValueValid(EditValue, AEditFocused);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.PrepareDisplayValue(
|
|
const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue; AEditFocused: Boolean);
|
|
var
|
|
AText: string;
|
|
begin
|
|
if IsMasked and not (not AEditFocused and (IDefaultValuesProvider <> nil) and
|
|
IDefaultValuesProvider.IsDisplayFormatDefined(True)) then
|
|
begin
|
|
AText := VarToStr(AEditValue);
|
|
if (FTempMode = nil) or not TestTempMaskKind or not TestTempEditMask then
|
|
begin
|
|
FreeAndNil(FTempMode);
|
|
FTempMode := CreateMode;
|
|
end;
|
|
if FTempMode <> nil then
|
|
begin
|
|
if not AEditFocused and (FTempMode is TcxMaskEditStandardMode) then
|
|
begin
|
|
if not FAlwaysShowBlanksAndLiterals then
|
|
DisplayValue := FTempMode.GetUpdatedText(AText, False)
|
|
else
|
|
DisplayValue := FTempMode.GetFormattedText(AText, False);
|
|
end
|
|
else
|
|
DisplayValue := FTempMode.GetFormattedText(AText, False);
|
|
end;
|
|
end
|
|
else
|
|
inherited PrepareDisplayValue(AEditValue, DisplayValue, AEditFocused);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.ValidateDisplayValue(var ADisplayValue: TcxEditValue;
|
|
var AErrorText: TCaption; var Error: Boolean; AEdit: TcxCustomEdit);
|
|
var
|
|
AText: string;
|
|
begin
|
|
if not Error then
|
|
begin
|
|
if not IsMasked{ or IgnoreMaskBlank }then
|
|
Error := False
|
|
else
|
|
begin
|
|
AText := VarToStr(ADisplayValue);
|
|
|
|
Error := not TcxCustomMaskEdit(AEdit).Mode.IsFullValidText(AText);
|
|
|
|
if Error then
|
|
AErrorText := cxGetResourceString(@scxMaskEditInvalidEditValue);
|
|
end;
|
|
end;
|
|
|
|
inherited ValidateDisplayValue(ADisplayValue, AErrorText, Error, AEdit);
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.CreateMode: TcxMaskEditCustomMode;
|
|
begin
|
|
Result := nil;
|
|
if not EmptyMask(EditMask) then
|
|
begin
|
|
Result := GetModeClass(FMaskKind).Create(nil, Self);
|
|
Result.Compile(EditMask);
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.CreateMode1: TcxMaskEditCustomMode;
|
|
begin
|
|
Result := GetModeClass(MaskKind).Create(nil, Self);
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.EmptyMask(AMask: string): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := AMask = '';
|
|
|
|
if not Result then
|
|
begin
|
|
for I := 1 to Length(AMask) do
|
|
if not SpaceToken(AMask[I]) then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
|
|
Result := True;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.GetEditMask: TcxEditMask;
|
|
begin
|
|
if FMaskKind <> emkStandard then
|
|
Result := FEditMask
|
|
else
|
|
begin
|
|
if EmptyMask(FEditMask) then
|
|
begin
|
|
if IDefaultValuesProvider <> nil then
|
|
Result := IDefaultValuesProvider.DefaultEditMask
|
|
else
|
|
Result := '';
|
|
end
|
|
else
|
|
Result := FEditMask
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.GetIsMasked: Boolean;
|
|
begin
|
|
Result := not EmptyMask(EditMask);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.SetAlwaysShowBlanksAndLiterals(AValue: Boolean);
|
|
begin
|
|
if AValue <> FAlwaysShowBlanksAndLiterals then
|
|
begin
|
|
FAlwaysShowBlanksAndLiterals := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.SetCaseInsensitive(AValue: Boolean);
|
|
begin
|
|
if CharCase = ecNormal then
|
|
FCaseInsensitive := AValue
|
|
else
|
|
FCaseInsensitive := True;
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.SetEditMask(Value: TcxEditMask);
|
|
var
|
|
AMode: TcxMaskEditCustomMode;
|
|
begin
|
|
if EditMask = Value then
|
|
FEditMask := Value
|
|
else
|
|
begin
|
|
AMode := CreateMode1;
|
|
try
|
|
AMode.Compile(Value);
|
|
FEditMask := Value;
|
|
Changed;
|
|
finally
|
|
AMode.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.SetMaskKind(Value: TcxEditMaskKind);
|
|
begin
|
|
if Value <> FMaskKind then
|
|
begin
|
|
FMaskKind := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.GetDisplayFormatOptions: TcxEditDisplayFormatOptions;
|
|
begin
|
|
if not IsMasked then
|
|
Result := [dfoSupports]
|
|
else
|
|
Result := [];
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.GetModeClass(
|
|
AMaskKind: TcxEditMaskKind): TcxMaskEditCustomModeClass;
|
|
begin
|
|
case AMaskKind of
|
|
emkStandard:
|
|
Result := TcxMaskEditStandardMode;
|
|
emkRegExpr:
|
|
Result := TcxMaskEditRegExprMode;
|
|
else
|
|
Result := TcxMaskEditRegExprExMode;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.MaxLengthChanged;
|
|
begin
|
|
if IsMasked then
|
|
begin
|
|
if FMaxLengthSetting then
|
|
Exit;
|
|
FMaxLengthSetting := True;
|
|
BeginUpdate;
|
|
try
|
|
MaxLength := 0;
|
|
finally
|
|
FMaxLengthSetting := False;
|
|
EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
inherited MaxLengthChanged;
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.SpaceToken(AToken: Char): Boolean;
|
|
begin
|
|
Result := IsSpaceChar(AToken);
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.GetEmptyString: string;
|
|
begin
|
|
Result := FEmptyString;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEditProperties.SetCharCase(Value: TEditCharCase);
|
|
begin
|
|
if Value in [ecLowerCase, ecUpperCase] then
|
|
FCaseInsensitive := True;
|
|
|
|
inherited SetCharCase(Value);
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.TestTempEditMask: Boolean;
|
|
begin
|
|
Result := FTempMode.EditMask = EditMask;
|
|
end;
|
|
|
|
function TcxCustomMaskEditProperties.TestTempMaskKind: Boolean;
|
|
begin
|
|
Result := False;
|
|
case FMaskKind of
|
|
emkStandard:
|
|
Result := FTempMode is TcxMaskEditStandardMode;
|
|
emkRegExpr:
|
|
Result := FTempMode is TcxMaskEditRegExprMode;
|
|
emkRegExprEx:
|
|
Result := FTempMode is TcxMaskEditRegExprExMode;
|
|
end;
|
|
end;
|
|
|
|
{ TcxCustomMaskEdit }
|
|
|
|
{$IFDEF CBUILDER10}
|
|
constructor TcxCustomMaskEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
destructor TcxCustomMaskEdit.Destroy;
|
|
begin
|
|
FreeAndNil(FMode);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.CutToClipboard;
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
begin
|
|
if not Focused or DoEditing then
|
|
begin
|
|
CopyToClipboard;
|
|
if Mode.PressDelete then
|
|
SendMyKeyPress(Char(VK_BACK));
|
|
end
|
|
end
|
|
else
|
|
inherited CutToClipBoard;
|
|
end;
|
|
|
|
class function TcxCustomMaskEdit.GetPropertiesClass: TcxCustomEditPropertiesClass;
|
|
begin
|
|
Result := TcxCustomMaskEditProperties;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.SendMyKeyDown(Key: Word; Shift: TShiftState);
|
|
begin
|
|
FMyMessage := True;
|
|
try
|
|
SendKeyDown(Self, Key, Shift);
|
|
finally
|
|
FMyMessage := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.SendMyKeyPress(AKey: Char);
|
|
begin
|
|
FMyMessage := True;
|
|
try
|
|
SendKeyPress(Self, AKey);
|
|
finally
|
|
FMyMessage := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.ChangeHandler(Sender: TObject);
|
|
begin
|
|
FText := FMode.GetUpdatedText(InnerEdit.EditValue);
|
|
|
|
inherited ChangeHandler(Sender);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.DblClick;
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
Mode.GotoEnd;
|
|
|
|
inherited DblClick;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.DoEnter;
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
if ActiveProperties.AutoSelect then
|
|
Mode.GotoEnd;
|
|
|
|
inherited DoEnter;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.DoEditKeyDown(var Key: Word; Shift: TShiftState);
|
|
var
|
|
AAfterKeyDownNeed: Boolean;
|
|
begin
|
|
if not ActiveProperties.IsMasked or IsSpecialKey(Key, Shift) then
|
|
begin
|
|
inherited DoEditKeyDown(Key, Shift);
|
|
Exit;
|
|
end;
|
|
|
|
if not ValidateKeyDown(Key, Shift) then
|
|
begin
|
|
DoAfterKeyDown(Key, Shift);
|
|
Key := 0;
|
|
Exit;
|
|
end;
|
|
|
|
if Key = VK_TAB then
|
|
begin
|
|
inherited DoEditKeyDown(Key, Shift);
|
|
Exit;
|
|
end;
|
|
|
|
FShiftOn := ssShift in Shift;
|
|
|
|
if ((Key = VK_UP) or (Key = VK_DOWN)) and not HasPopupWindow then
|
|
begin
|
|
DoAfterKeyDown(Key, Shift);
|
|
Key := 0;
|
|
end
|
|
else if Key = VK_LEFT then
|
|
begin
|
|
if ssCtrl in Shift then
|
|
begin
|
|
SendMyKeyDown(VK_HOME, Shift);
|
|
if not Mode.PressHome then
|
|
Key := 0;
|
|
end
|
|
else
|
|
begin
|
|
AAfterKeyDownNeed := IsCursorBegin;
|
|
if not Mode.PressLeft then
|
|
begin
|
|
if AAfterKeyDownNeed then
|
|
DoAfterKeyDown(Key, Shift);
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
end
|
|
else if Key = VK_RIGHT then
|
|
begin
|
|
if ssCtrl in Shift then
|
|
begin
|
|
SendMyKeyDown(VK_END, Shift);
|
|
if not Mode.PressEnd then
|
|
Key := 0;
|
|
end
|
|
else
|
|
begin
|
|
AAfterKeyDownNeed := IsCursorEnd;
|
|
if not Mode.PressRight then
|
|
begin
|
|
if AAfterKeyDownNeed then
|
|
DoAfterKeyDown(Key, Shift);
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
end
|
|
else if Key = VK_DELETE then
|
|
begin
|
|
if ssShift in Shift then
|
|
begin
|
|
if SelLength = 0 then
|
|
if not Mode.PressBackSpace then
|
|
Key := 0;
|
|
end
|
|
else
|
|
if not Mode.PressDelete then
|
|
Key := 0;
|
|
end
|
|
else if Key = VK_HOME then
|
|
begin
|
|
if not Mode.PressHome then
|
|
Key := 0;
|
|
end
|
|
else if Key = VK_END then
|
|
begin
|
|
if not Mode.PressEnd then
|
|
Key := 0;
|
|
end;
|
|
|
|
if Key <> 0 then
|
|
inherited DoEditKeyDown(Key, Shift);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.DoEditKeyPress(var Key: Char);
|
|
begin
|
|
if not ActiveProperties.IsMasked then
|
|
begin
|
|
inherited DoEditKeyPress(Key);
|
|
Exit;
|
|
end;
|
|
|
|
if (Key = #9) or (Key = #27) then
|
|
Key := #0
|
|
else if not ValidateKeyPress(Key) then
|
|
Key := #0
|
|
else
|
|
begin
|
|
if Key <> #13 then
|
|
begin
|
|
if not ActiveProperties.IsMasked then
|
|
inherited DoEditKeyPress(Key)
|
|
else
|
|
begin
|
|
if (Key = #3) or (Key = #22) or (Key = #24) then // ^c ^v ^x
|
|
begin
|
|
inherited DoEditKeyPress(Key);
|
|
end
|
|
else
|
|
begin
|
|
if Key = #8 then // Backspace
|
|
begin
|
|
if not Mode.PressBackSpace then
|
|
Key := #0;
|
|
end
|
|
else
|
|
if not Mode.PressSymbol(Key) then
|
|
Key := #0;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.GetEditText: TCaption;
|
|
begin
|
|
Result := InnerEdit.EditValue;
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.GetProperties: TcxCustomMaskEditProperties;
|
|
begin
|
|
Result := TcxCustomMaskEditProperties(FProperties);
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.GetActiveProperties: TcxCustomMaskEditProperties;
|
|
begin
|
|
Result := TcxCustomMaskEditProperties(InternalGetActiveProperties);
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.InternalGetEmptyString: string;
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
begin
|
|
if Mode <> nil then
|
|
Result := Mode.GetEmptyString
|
|
else
|
|
Result := '';
|
|
end
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.InternalSetValue(AValue: string);
|
|
begin
|
|
if ActiveProperties.IsMasked and CanSynchronizeModeText then
|
|
Mode.SetText(AValue);
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.IsCursorBegin: Boolean;
|
|
begin
|
|
Result := FMode.IsCursorBegin;
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.IsCursorEnd: Boolean;
|
|
begin
|
|
Result := FMode.IsCursorEnd;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.SetEditText(AValue: TCaption);
|
|
var
|
|
AEditText: string;
|
|
begin
|
|
if not Focused and (Mode is TcxMaskEditStandardMode) then
|
|
begin
|
|
if not ActiveProperties.AlwaysShowBlanksAndLiterals then
|
|
AEditText := Mode.GetUpdatedText(AValue)
|
|
else
|
|
AEditText := Mode.GetFormattedText(AValue);
|
|
end
|
|
else
|
|
AEditText := Mode.GetFormattedText(AValue);
|
|
InnerEdit.EditValue := AEditText;
|
|
FEditValue := FText;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.SetProperties(Value: TcxCustomMaskEditProperties);
|
|
begin
|
|
FProperties.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.DoEditKeyUp(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if not ActiveProperties.IsMasked then
|
|
begin
|
|
inherited DoEditKeyUp(Key, Shift);
|
|
Exit;
|
|
end;
|
|
|
|
inherited DoEditKeyUp(Key, Shift);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.Initialize;
|
|
begin
|
|
inherited Initialize;
|
|
FMode := ActiveProperties.GetModeClass(emkStandard).Create(Self, ActiveProperties);
|
|
FShiftOn := False;
|
|
ActiveProperties.FEmptyString := InternalGetEmptyString;
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.InternalGetText: string;
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
Result := FText
|
|
else
|
|
Result := inherited InternalGetText;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.InternalSetDisplayValue(const Value: TcxEditValue);
|
|
var
|
|
AText: string;
|
|
begin
|
|
if ActiveProperties.IsMasked and not IsLoading then
|
|
begin
|
|
AText := VarToStr(Value);
|
|
|
|
if not Focused and (Mode is TcxMaskEditStandardMode) then
|
|
begin
|
|
if not ActiveProperties.AlwaysShowBlanksAndLiterals then
|
|
inherited InternalSetDisplayValue(Mode.GetUpdatedText(AText))
|
|
else
|
|
inherited InternalSetDisplayValue(Mode.GetFormattedText(AText));
|
|
end
|
|
else
|
|
inherited InternalSetDisplayValue(Mode.GetFormattedText(AText));
|
|
|
|
InternalSetValue(Text);
|
|
end
|
|
else
|
|
inherited InternalSetDisplayValue(Value);
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.InternalSetText(const Value: string): Boolean;
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
begin
|
|
Result := True;
|
|
InternalEditValue := Value;
|
|
FEditValue := FText;
|
|
end
|
|
else
|
|
Result := inherited InternalSetText(Value);
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.IsTextInputMode: Boolean;
|
|
begin
|
|
Result := (ActiveProperties.EditMask = '') and inherited IsTextInputMode;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if not FMyMessage then
|
|
inherited KeyDown(Key, Shift);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.KeyPress(var Key: Char);
|
|
begin
|
|
if not FMyMessage then
|
|
inherited KeyPress(Key);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.KeyUp(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if not FMyMessage then
|
|
inherited KeyUp(Key, Shift);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
if ActiveProperties.IsMasked then
|
|
begin
|
|
LockChangeEvents(True, False);
|
|
try
|
|
UpdateTextFormatting;
|
|
finally
|
|
LockChangeEvents(False, False);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.LockInnerEditRepainting;
|
|
begin
|
|
if HasInnerEdit then
|
|
if ActiveProperties.IsMasked then
|
|
SendMessage(InnerEdit.Control.Handle, WM_SETREDRAW, 0, 0)
|
|
else
|
|
inherited LockInnerEditRepainting;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.MouseDown(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
if Button = mbLeft then
|
|
Mode.LMouseDown;
|
|
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
AShiftOn: Boolean;
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
if ssLeft in Shift then
|
|
begin
|
|
AShiftOn := FShiftOn;
|
|
FShiftOn := True;
|
|
Mode.LMouseDown;
|
|
FShiftOn := AShiftOn;
|
|
end;
|
|
|
|
inherited MouseMove(Shift, X, Y);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.PropertiesChanged(Sender: TObject);
|
|
var
|
|
AEditMask: string;
|
|
ASelStart: Integer;
|
|
ASelLength: Integer;
|
|
AEditMaskCleared: Boolean;
|
|
|
|
procedure DoMaskChanged;
|
|
begin
|
|
ActiveProperties.MaxLength := 0;
|
|
|
|
FMode.Compile(AEditMask);
|
|
if AEditMaskCleared then
|
|
ActiveProperties.FEditMask := AEditMask;
|
|
if not ActiveProperties.EmptyMask(AEditMask) then
|
|
FMode.SynchronizeEditValue
|
|
else
|
|
begin
|
|
if FMode is TcxMaskEditStandardMode then
|
|
begin
|
|
if HandleAllocated and (SelLength = 1) then
|
|
begin
|
|
ASelStart := SelStart;
|
|
SelLength := 0;
|
|
SelStart := ASelStart;
|
|
end;
|
|
end;
|
|
end;
|
|
ActiveProperties.FEmptyString := InternalGetEmptyString;
|
|
end;
|
|
|
|
procedure DoMaskKindChanged;
|
|
var
|
|
APrevMaskKind: TcxEditMaskKind;
|
|
APrevEditMask: string;
|
|
begin
|
|
APrevMaskKind := FMode.GetMaskKind;
|
|
APrevEditMask := FMode.EditMask;
|
|
FreeAndNil(FMode);
|
|
|
|
if ActiveProperties.MaskKind = emkRegExpr then
|
|
begin
|
|
if APrevMaskKind = emkStandard then
|
|
begin
|
|
ActiveProperties.FEditMask := '';
|
|
AEditMaskCleared := True;
|
|
end;
|
|
FMode := ActiveProperties.GetModeClass(emkRegExpr).Create(Self, ActiveProperties)
|
|
end
|
|
else if ActiveProperties.MaskKind = emkRegExprEx then
|
|
begin
|
|
if APrevMaskKind = emkStandard then
|
|
begin
|
|
ActiveProperties.FEditMask := '';
|
|
AEditMaskCleared := True;
|
|
end;
|
|
FMode := ActiveProperties.GetModeClass(emkRegExprEx).Create(Self, ActiveProperties)
|
|
end
|
|
else if ActiveProperties.MaskKind = emkStandard then
|
|
begin
|
|
if (APrevMaskKind = emkRegExpr) or (APrevMaskKind = emkRegExprEx) then
|
|
begin
|
|
ActiveProperties.FEditMask := '';
|
|
AEditMaskCleared := True;
|
|
end;
|
|
FMode := ActiveProperties.GetModeClass(emkStandard).Create(Self, ActiveProperties)
|
|
end;
|
|
|
|
FMode.Compile(ActiveProperties.EditMask);
|
|
if not ActiveProperties.EmptyMask(ActiveProperties.EditMask) then
|
|
FMode.SynchronizeEditValue;
|
|
|
|
ActiveProperties.FEmptyString := InternalGetEmptyString;
|
|
end;
|
|
|
|
procedure DoCharCaseChanged;
|
|
begin
|
|
if ActiveProperties.CharCase = ecNormal then
|
|
begin
|
|
if HasInnerEdit then
|
|
InnerTextEdit.CharCase := ecNormal;
|
|
FMode.SynchronizeEditValue;
|
|
end;
|
|
FMode.CharCase := ActiveProperties.CharCase;
|
|
end;
|
|
|
|
procedure SaveSels;
|
|
begin
|
|
ASelStart := SelStart;
|
|
ASelLength := SelLength;
|
|
end;
|
|
|
|
procedure LoadSels;
|
|
begin
|
|
SelStart := ASelStart;
|
|
SelLength := ASelLength;
|
|
end;
|
|
|
|
var
|
|
AEditMaskChanged: Boolean;
|
|
AEditMaskKindChanged: Boolean;
|
|
ACharCaseChanged: Boolean;
|
|
begin
|
|
AEditMaskCleared := False;
|
|
ActiveProperties.LockUpdate(True);
|
|
|
|
AEditMask := ActiveProperties.EditMask;
|
|
AEditMaskChanged := (FMode.EditMask <> ActiveProperties.EditMask) or ActiveProperties.FormatChanging;
|
|
AEditMaskKindChanged := FMode.GetMaskKind <> ActiveProperties.MaskKind;
|
|
ACharCaseChanged := ActiveProperties.CharCase <> FMode.CharCase;
|
|
if AEditMaskKindChanged then
|
|
DoMaskKindChanged;
|
|
if AEditMaskChanged then
|
|
DoMaskChanged;
|
|
if ACharCaseChanged then
|
|
DoCharCaseChanged;
|
|
if (ActiveProperties.EchoMode <> FMode.EchoMode) and HandleAllocated then
|
|
SaveSels;
|
|
|
|
if not(not PropertiesChangeLocked and VarIsNull(EditValue)) and ActiveProperties.IsMasked then
|
|
FMode.UpdateEditValue;
|
|
|
|
ActiveProperties.LockUpdate(False);
|
|
|
|
if FMode is TcxMaskEditRegExprMode then
|
|
TcxMaskEditRegExprMode(FMode).SetRegExprCaseInsensitive;
|
|
|
|
inherited PropertiesChanged(Sender);
|
|
|
|
if ActiveProperties.EchoMode <> FMode.EchoMode then
|
|
begin
|
|
if HandleAllocated then
|
|
LoadSels;
|
|
FMode.EchoMode := ActiveProperties.EchoMode;
|
|
end;
|
|
|
|
if ACharCaseChanged or AEditMaskKindChanged or AEditMaskChanged then
|
|
FText := FMode.GetUpdatedText(InnerEdit.EditValue);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.PrepareEditValue(const ADisplayValue: TcxEditValue;
|
|
out EditValue: TcxEditValue; AEditFocused: Boolean);
|
|
begin
|
|
if ActiveProperties.IsMasked then
|
|
if not AEditFocused and (Mode is TcxMaskEditStandardMode) and
|
|
(TcxMaskEditStandardMode(Mode).FMask.SaveLiteralCharacters or not ActiveProperties.AlwaysShowBlanksAndLiterals) then
|
|
inherited PrepareEditValue(ADisplayValue, EditValue, AEditFocused)
|
|
else
|
|
EditValue := Mode.GetUpdatedText(ADisplayValue)
|
|
else
|
|
inherited PrepareEditValue(ADisplayValue, EditValue, AEditFocused);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.PasteFromClipboard;
|
|
begin
|
|
if not Clipboard.HasFormat(CF_TEXT) then
|
|
Exit;
|
|
|
|
if not ActiveProperties.IsMasked then
|
|
begin
|
|
inherited PasteFromClipboard;
|
|
Exit;
|
|
end;
|
|
|
|
Mode.ClipboardTextLength := Length(Clipboard.AsText);
|
|
Mode.PrePasteFromClipboard;
|
|
|
|
// inherited PasteFromClipboard;
|
|
SelText := Clipboard.AsText; // TODO
|
|
|
|
Mode.AfterPasteFromClipboard;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.SelChange(Sender: TObject);
|
|
begin
|
|
inherited SelChange(Sender);
|
|
if not FInternalTextSelection then
|
|
Mode.LMouseDown;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.SetSelText(const Value: TCaption);
|
|
begin
|
|
if not ActiveProperties.IsMasked then
|
|
inherited SetSelText(Value)
|
|
else
|
|
begin
|
|
Mode.ClipboardTextLength := Length(Value);
|
|
Mode.PrePasteFromClipboard;
|
|
|
|
inherited SetSelText(Value);
|
|
|
|
Mode.AfterPasteFromClipboard;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.SynchronizeDisplayValue;
|
|
begin
|
|
inherited SynchronizeDisplayValue;
|
|
|
|
if ActiveProperties.IsMasked then
|
|
InternalSetValue(Text);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.UndoPerformed;
|
|
begin
|
|
InternalSetValue(Text);
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.UnlockInnerEditRepainting;
|
|
begin
|
|
if HasInnerEdit then
|
|
if ActiveProperties.IsMasked then
|
|
begin
|
|
SendMessage(InnerEdit.Control.Handle, WM_SETREDRAW, 1, 0);
|
|
InnerEdit.Control.Invalidate;
|
|
end
|
|
else
|
|
inherited UnlockInnerEditRepainting;
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.CanSynchronizeModeText: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.DirectSetSelLength(AValue: Integer);
|
|
begin
|
|
FInternalTextSelection := True;
|
|
try
|
|
SelLength := AValue;
|
|
finally
|
|
FInternalTextSelection := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.DirectSetSelStart(AValue: Integer);
|
|
begin
|
|
FInternalTextSelection := True;
|
|
try
|
|
SelStart := AValue;
|
|
finally
|
|
FInternalTextSelection := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomMaskEdit.IsCharValidForPos(var AChar: Char;
|
|
APos: Integer): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomMaskEdit.UpdateTextFormatting;
|
|
begin
|
|
InternalSetDisplayValue(Text);
|
|
end;
|
|
|
|
{ TcxMaskEdit }
|
|
|
|
function TcxMaskEdit.SupportsSpelling: Boolean;
|
|
begin
|
|
Result := IsTextInputMode;
|
|
end;
|
|
|
|
class function TcxMaskEdit.GetPropertiesClass: TcxCustomEditPropertiesClass;
|
|
begin
|
|
Result := TcxMaskEditProperties;
|
|
end;
|
|
|
|
function TcxMaskEdit.GetActiveProperties: TcxMaskEditProperties;
|
|
begin
|
|
Result := TcxMaskEditProperties(InternalGetActiveProperties);
|
|
end;
|
|
|
|
function TcxMaskEdit.GetProperties: TcxMaskEditProperties;
|
|
begin
|
|
Result := TcxMaskEditProperties(FProperties);
|
|
end;
|
|
|
|
procedure TcxMaskEdit.SetProperties(Value: TcxMaskEditProperties);
|
|
begin
|
|
FProperties.Assign(Value);
|
|
end;
|
|
|
|
{ TcxFilterMaskEditHelper }
|
|
|
|
class function TcxFilterMaskEditHelper.GetFilterEditClass: TcxCustomEditClass;
|
|
begin
|
|
Result := TcxMaskEdit;
|
|
end;
|
|
|
|
class function TcxFilterMaskEditHelper.GetSupportedFilterOperators(
|
|
AProperties: TcxCustomEditProperties;
|
|
AValueTypeClass: TcxValueTypeClass;
|
|
AExtendedSet: Boolean = False): TcxFilterControlOperators;
|
|
begin
|
|
Result := [fcoEqual, fcoNotEqual, fcoLess, fcoLessEqual,
|
|
fcoGreater, fcoGreaterEqual, fcoBlanks, fcoNonBlanks];
|
|
if not TcxCustomMaskEditProperties(AProperties).IsMasked and
|
|
((AValueTypeClass <> nil) and AValueTypeClass.IsString) then
|
|
Result := Result + [fcoLike, fcoNotLike];
|
|
if AExtendedSet then
|
|
Result := Result + [fcoBetween..fcoNotInList];
|
|
end;
|
|
|
|
class procedure TcxFilterMaskEditHelper.InitializeProperties(AProperties,
|
|
AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean);
|
|
begin
|
|
inherited InitializeProperties(AProperties, AEditProperties, AHasButtons);
|
|
with TcxCustomMaskEditProperties(AProperties) do
|
|
begin
|
|
if TcxCustomMaskEditProperties(AEditProperties).MaskKind =
|
|
emkRegExpr then
|
|
MaskKind := emkRegExprEx;
|
|
AutoSelect := not IsMasked;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
GetRegisteredEditProperties.Register(TcxMaskEditProperties, scxSEditRepositoryMaskItem);
|
|
FilterEditsController.Register(TcxMaskEditProperties, TcxFilterMaskEditHelper);
|
|
|
|
finalization
|
|
FilterEditsController.Unregister(TcxMaskEditProperties, TcxFilterMaskEditHelper);
|
|
|
|
end.
|