diff --git a/components/jvcllaz/design/JvCustomControls/images/images.txt b/components/jvcllaz/design/JvCustomControls/images/images.txt
index 0d5fe15ef..9890e700d 100644
--- a/components/jvcllaz/design/JvCustomControls/images/images.txt
+++ b/components/jvcllaz/design/JvCustomControls/images/images.txt
@@ -1,7 +1,9 @@
tjvtabbar.bmp
tjvmoderntabbarpainter.bmp
Tjvtabbarxppainter.bmp
-tjvoutlookbar.bmp
+tjvoutlookbar.png
+tjvoutlookbar_150.png
+tjvoutlookbar_200.png
tjvtimeline.png
tjvtimeline_150.png
tjvtimeline_200.png
@@ -26,3 +28,6 @@ tjvimagesviewer_200.png
tjvownerdrawviewer.png
tjvownerdrawviewer_150.png
tjvownerdrawviewer_200.png
+tjvvalidateedit.png
+tjvvalidateedit_150.png
+tjvvalidateedit_200.png
diff --git a/components/jvcllaz/design/JvCustomControls/images/tjvvalidateedit.png b/components/jvcllaz/design/JvCustomControls/images/tjvvalidateedit.png
new file mode 100644
index 000000000..2124d3e73
Binary files /dev/null and b/components/jvcllaz/design/JvCustomControls/images/tjvvalidateedit.png differ
diff --git a/components/jvcllaz/design/JvCustomControls/images/tjvvalidateedit_150.png b/components/jvcllaz/design/JvCustomControls/images/tjvvalidateedit_150.png
new file mode 100644
index 000000000..2a3dd81ee
Binary files /dev/null and b/components/jvcllaz/design/JvCustomControls/images/tjvvalidateedit_150.png differ
diff --git a/components/jvcllaz/design/JvCustomControls/jvcustomreg.pas b/components/jvcllaz/design/JvCustomControls/jvcustomreg.pas
index da64f4e80..2baa734a9 100644
--- a/components/jvcllaz/design/JvCustomControls/jvcustomreg.pas
+++ b/components/jvcllaz/design/JvCustomControls/jvcustomreg.pas
@@ -16,6 +16,7 @@ implementation
uses
Classes, ImgList, Controls, LResources, PropEdits, GraphPropEdits, ComponentEditors,
JvDsgnConsts,
+ JvValidateEdit,
JvOutlookBar, JvOutlookBarEditors,
// JvTabBar, JvTabBarXPPainter,
JvThumbImage, JvThumbnails, JvThumbViews,
@@ -25,6 +26,7 @@ uses
procedure Register;
begin
RegisterComponents(RsPaletteJvcl, [
+ TJvValidateEdit,
// TJvTabBar, TJvModernTabBarPainter, TJvTabBarXPPainter, // moved to PageComps
TJvOutlookBar,
TJvThumbView, TJvThumbnail, TJvThumbImage,
diff --git a/components/jvcllaz/packages/jvcustomlazd.lpk b/components/jvcllaz/packages/jvcustomlazd.lpk
index d719bec68..18b06bfe3 100644
--- a/components/jvcllaz/packages/jvcustomlazd.lpk
+++ b/components/jvcllaz/packages/jvcustomlazd.lpk
@@ -39,7 +39,7 @@
-
+
@@ -49,9 +49,6 @@
-
-
-
diff --git a/components/jvcllaz/packages/jvcustomlazr.lpk b/components/jvcllaz/packages/jvcustomlazr.lpk
index 1ae0d2a39..addca88ee 100644
--- a/components/jvcllaz/packages/jvcustomlazr.lpk
+++ b/components/jvcllaz/packages/jvcustomlazr.lpk
@@ -19,7 +19,7 @@
"/>
-
+
@@ -64,6 +64,10 @@
+
+
+
+
diff --git a/components/jvcllaz/resource/jvctrlsreg.res b/components/jvcllaz/resource/jvctrlsreg.res
index d06eb1fa9..ba8b2b0a3 100644
Binary files a/components/jvcllaz/resource/jvctrlsreg.res and b/components/jvcllaz/resource/jvctrlsreg.res differ
diff --git a/components/jvcllaz/resource/jvcustomreg.res b/components/jvcllaz/resource/jvcustomreg.res
index 08b3f324c..90fc54cae 100644
Binary files a/components/jvcllaz/resource/jvcustomreg.res and b/components/jvcllaz/resource/jvcustomreg.res differ
diff --git a/components/jvcllaz/run/JvCore/JvJCLUtils.pas b/components/jvcllaz/run/JvCore/JvJCLUtils.pas
index ea55072f0..91cdf0a9a 100644
--- a/components/jvcllaz/run/JvCore/JvJCLUtils.pas
+++ b/components/jvcllaz/run/JvCore/JvJCLUtils.pas
@@ -46,8 +46,9 @@ interface
// the JCL has the same problem with CLX it should not make any difference.
uses
- Classes, Graphics, LCLIntf, LCLType;
-
+ LCLIntf, LCLType,
+ SysUtils, Classes, Graphics;
+
const
(******************** NOT CONVERTED
{$IFDEF MSWINDOWS}
@@ -69,14 +70,15 @@ const
BOM_LSB_FIRST = WideChar($FEFF);
BOM_MSB_FIRST = WideChar($FFFE);
-{$IF FPC_FullVersion < 30000}
+
type
+{$IF FPC_FullVersion < 30000}
TSysCharSet = set of AnsiChar;
{$ENDIF}
+ EJvConvertError = Class(EConvertError); { subclass EConvertError raised by some non-Def versions of floating point conversion routine }
-(******************** NOT CONVERTED
+ (******************** NOT CONVERTED
{$IFDEF UNIX}
-type
TFileTime = Integer;
{$ENDIF UNIX}
@@ -90,7 +92,12 @@ const
DefaultDateOrder = doDMY;
CenturyOffset: Byte = 60;
NullDate: TDateTime = {-693594} 0;
+ *)
+function JvSafeStrToFloatDef(const Str: string; Def: Extended; aDecimalSeparator: Char): Extended;
+function JvSafeStrToFloat(const Str: string; aDecimalSeparator: Char): Extended;
+
+(******************* NOT CONVERTED ******
function USToLocalFloatStr(const Text: string): string;
function StrToFloatUS(const Text: string): Extended;
// StrToFloatUS uses US '.' as decimal seperator and ',' as thousand separator
@@ -292,6 +299,15 @@ function CopyDir(const SourceDir, DestDir: TFileName): Boolean;
//function FileTimeToDateTime(const FT: TFileTime): TDateTime;
procedure FileTimeToDosDateTimeDWord(const FT: TFileTime; out Dft: DWORD);
function MakeValidFileName(const FileName: TFileName; ReplaceBadChar: Char): TFileName;
+***)
+
+function StrEnsureNoPrefix(const Prefix, Text: string): string;
+function StrEnsureNoSuffix(const Suffix, Text: string): string;
+function IsCharAlpha(Key: Char): Boolean;
+function IsCharAlphaNumeric(Key: Char): Boolean;
+
+
+(******************** NOT CONVERTED ***
{**** Graphic routines }
@@ -844,9 +860,10 @@ function IntToExtended(I: Integer): Extended;
It is not very useful in other contexts,
but it is in this unit as it is needed in both MemoEx and TypedEdit }
function GetChangedText(const Text: string; SelStart, SelLength: Integer; Key: Char): string;
-
+*)
function MakeYear4Digit(Year, Pivot: Integer): Integer;
+(********************** NOT CONVERTED ***
function StrIsInteger(const S: string): Boolean;
function StrIsFloatMoney(const Ps: string): Boolean;
function StrIsDateTime(const Ps: string): Boolean;
@@ -1233,7 +1250,7 @@ function FindUnusedFileName(FileName: string; const FileExt: string; NumberPrefi
implementation
uses
- Math, SysUtils, LazFileUtils,
+ Math, LazFileUtils, LclStrConsts,
JvConsts;
(******************** NOT CONVERTED
@@ -1265,12 +1282,15 @@ const
RC_ShellName = 'Shell_TrayWnd';
RC_DefaultIcon = 'DefaultIcon';
{$ENDIF MSWINDOWS}
+********************)
resourcestring
+ RsEPivotLessThanZero = 'JvJCLUtils.MakeYear4Digit: Pivot < 0';
+
+(******************* NOT CONVERTED ****
// (p3) duplicated from JvConsts since this unit should not rely on JVCL at all
RsEPropertyNotExists = 'Property "%s" does not exist';
RsEInvalidPropertyType = 'Property "%s" has invalid type';
- RsEPivotLessThanZero = 'JvJCLUtils.MakeYear4Digit: Pivot < 0';
{$IFDEF NO_JCL}
@@ -1506,7 +1526,56 @@ begin
Result := StrToFloat(Text); // try it with local settings
end;
end;
+**********)
+{ JvStrConvertErrorFmt used from JvSafeStrToFloat }
+procedure JvStrConvertErrorFmt(ResString: PResStringRec; const Args: array of const);
+begin
+ raise EJvConvertError.CreateResFmt(ResString, Args); { will be also caught if you catch E:EConvertERror }
+end;
+
+function _JvSafeStrToFloat(const Str: String; aDecimalSeparator: Char; out AValue: Extended): Boolean;
+var
+ LocalFormatSettings: TFormatSettings;
+begin
+ Result := false;
+ if Str = '' then
+ Exit; { how's this for a nice optimization? WPostma. }
+
+ LocalFormatSettings := FormatSettings;
+ if aDecimalSeparator = ' ' then
+ LocalFormatSettings.DecimalSeparator := FormatSettings.DecimalSeparator
+ else
+ LocalFormatSettings.DecimalSeparator := aDecimalSeparator;
+
+ { Cross-codepage safety feature: Handed '1.2', a string without a comma,
+ but which is obviously a floating point number, convert it properly also.
+ This functionality is important for JvCsvDataSet and may be important in other
+ places. }
+ if (Pos(USDecimalSeparator, Str) > 0) and (Pos(ADecimalSeparator, Str) = 0) then
+ LocalFormatSettings.DecimalSeparator := USDecimalSeparator;
+
+ Result := TryStrToFloat(Str, AValue, LocalFormatSettings);
+end;
+
+function JvSafeStrToFloatDef(const Str: string; Def: Extended; aDecimalSeparator: Char): Extended;
+begin
+ { one handy dandy api expects a Default value returned instead }
+ if not _JvSafeStrToFloat(Str, aDecimalSeparator, Result) then
+ Result := Def; { failed, use default }
+end;
+
+// New routine, same as JvSafeStrToFloatDef but it will raise a conversion exception,
+// for cases when you actually want to handle an EConvertError yourself and where
+// there is no convenient or possible float value for your case.
+function JvSafeStrToFloat(const Str: string; aDecimalSeparator: Char): Extended;
+begin
+ { the other handy dandy api style expects us to raise an EConvertError. }
+ if not _JvSafeStrToFloat(Str, aDecimalSeparator, Result) then
+ JvStrConvertErrorFmt(@SParInvalidFloat, [Str]); {failed, raise exception }
+end;
+
+(******************** NOT CONVERTED ***
function StrToFloatUSDef(const Text: string; Default: Extended): Extended;
begin
Result := StrToFloatDef(USToLocalFloatStr(Text), Default);
@@ -3162,6 +3231,45 @@ function StrToBool(const S: string): Boolean;
begin
Result := (S = '1') or SameText(S, 'True') or SameText(S, 'yes');
end;
+**********)
+
+function StrEnsureNoPrefix(const Prefix, Text: string): string;
+var
+ PrefixLen: SizeInt;
+begin
+ PrefixLen := Length(Prefix);
+ if Copy(Text, 1, PrefixLen) = Prefix then
+ Result := Copy(Text, PrefixLen + 1, Length(Text))
+ else
+ Result := Text;
+end;
+
+function StrEnsureNoSuffix(const Suffix, Text: string): string;
+var
+ SuffixLen: SizeInt;
+ StrLength: SizeInt;
+begin
+ SuffixLen := Length(Suffix);
+ StrLength := Length(Text);
+ if Copy(Text, StrLength - SuffixLen + 1, SuffixLen) = Suffix then
+ Result := Copy(Text, 1, StrLength - SuffixLen)
+ else
+ Result := Text;
+end;
+
+// Laz workaround for Windows function --- probably not complete...
+function IsCharAlpha(Key: Char): Boolean;
+begin
+ Result := Key in ['a'..'z', 'A'..'Z'];
+end;
+
+// Laz workaround for Windows function --- probably not complete...
+function IsCharAlphaNumeric(Key: Char): Boolean;
+begin
+ Result := Key in ['0'..'9', 'a'..'z', 'A'..'Z'];
+end;
+
+(********************** NOT CONVERTED ***
function RATextOutEx(Canvas: TCanvas; const R, RClip: TRect; const S: string;
const CalcHeight: Boolean): Integer;
@@ -7921,6 +8029,7 @@ begin
if Key <> #0 then
Insert(Key, Result, SelStart + 1);
end;
+****************)
{ "window" technique for years to translate 2 digits to 4 digits.
The window is 100 years wide
@@ -7974,6 +8083,7 @@ begin
Result := Year;
end;
+(*********************
function StrIsInteger(const S: string): Boolean;
var
I: Integer;
diff --git a/components/jvcllaz/run/JvCustomControls/jvvalidateedit.pas b/components/jvcllaz/run/JvCustomControls/jvvalidateedit.pas
new file mode 100644
index 000000000..fc6c33916
--- /dev/null
+++ b/components/jvcllaz/run/JvCustomControls/jvvalidateedit.pas
@@ -0,0 +1,1780 @@
+{-----------------------------------------------------------------------------
+The contents of this file are subject to the Mozilla Public License
+Version 1.1 (the "License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/MPL-1.1.html
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
+the specific language governing rights and limitations under the License.
+The Original Code is JvValidateEdit, released on 20 February 2003,
+ by Christopher Latta
+Portions created by Christopher Latta are Copyright (C) 2003 Christopher Latta.
+All Rights Reserved.
+Contributor(s): Peter Thornqvist
+ Peter Schraut (http://www.console-dev.de)
+You may retrieve the latest version of this file at the Project JEDI's JVCL
+home page, located at http://jvcl.delphi-jedi.org
+Known Issues:
+TJvValidateFormat uses the SysUtils.Format function to format numeric values.
+While this uses the Windows regional settings for the currency symbol, decimal
+separator and thousands separator, it does not format using the negative symbol,
+negative number format, negative currency format and positive currency format.
+This could be rectified by a custom-written formatting routine.
+-----------------------------------------------------------------------------}
+// $Id$
+
+unit JvValidateEdit;
+
+{$MODE OBJFPC}{$H+}
+
+interface
+
+uses
+ LCLIntf, LCLType, LMessages,
+ Controls, Graphics, SysUtils, Classes, StdCtrls, FMTBcd;
+// JvEdit, JvDataSourceIntf;
+
+type
+ TJvValidateEditDisplayFormat = (dfAlphabetic, dfAlphaNumeric, dfBinary,
+ dfCheckChars, dfCurrency, dfCustom, dfFloat, dfFloatGeneral, dfHex, dfInteger,
+ dfNonCheckChars, dfNone, dfOctal, dfPercent, dfScientific, dfYear, dfDecimal,
+ dfIdentifier, dfFloatFixed, dfBcd);
+
+ TJvValidateEditCriticalPointsCheck = (cpNone, cpMinValue, cpMaxValue, cpBoth);
+
+ TJvCustomValidateEdit = class;
+
+ (******************* NOT CONVERTED ***
+ TJvValidateEditDataConnector = class(TJvFieldDataConnector)
+ private
+ FEdit: TJvCustomValidateEdit;
+ FNullValue: Variant;
+ procedure SetNullValue(const Value: Variant);
+ function IsNullValueStored: Boolean;
+ protected
+ procedure RecordChanged; override;
+ procedure UpdateData; override;
+ public
+ constructor Create(AEdit: TJvCustomValidateEdit);
+ procedure Assign(Source: TPersistent); override;
+ property Control: TJvCustomValidateEdit read FEdit;
+ published
+ property NullValue: Variant read FNullValue write SetNullValue stored IsNullValueStored;
+ end;
+ **********************************)
+
+ TJvValidateEditCriticalPoints = class(TPersistent)
+ private
+ FCheckPoints: TJvValidateEditCriticalPointsCheck;
+ FColorAbove: TColor;
+ FColorBelow: TColor;
+ FMaxValue: Double;
+ FMinValue: Double;
+ FMaxValueIncluded: Boolean;
+ FMinValueIncluded: Boolean;
+ FOnChange: TNotifyEvent;
+ FDefCheckPoints: TJvValidateEditCriticalPointsCheck;
+ FDefColorAbove: TColor;
+ FDefColorBelow: TColor;
+ procedure DoChanged;
+ procedure SetMinValue(NewValue: Double);
+ procedure SetMaxValue(NewValue: Double);
+ procedure SetColorAbove(NewValue: TColor);
+ procedure SetColorBelow(NewValue: TColor);
+ procedure SetCheckPoints(NewValue: TJvValidateEditCriticalPointsCheck);
+ function IsCheckPointsStored: Boolean;
+ function IsColorAboveStored: Boolean;
+ function IsColorBelowStored: Boolean;
+ public
+ procedure Assign(Source: TPersistent); override;
+ procedure SetDefaults(ACheckPoints: TJvValidateEditCriticalPointsCheck;
+ AColorAbove, AColorBelow: TColor);
+ constructor Create;
+ published
+ property CheckPoints: TJvValidateEditCriticalPointsCheck read FCheckPoints
+ write SetCheckPoints stored IsCheckPointsStored;
+ property ColorAbove: TColor read FColorAbove write SetColorAbove stored IsColorAboveStored;
+ property ColorBelow: TColor read FColorBelow write SetColorBelow stored IsColorBelowStored;
+ property MaxValue: Double read FMaxValue write SetMaxValue;
+ property MinValue: Double read FMinValue write SetMinValue;
+ property MaxValueIncluded: Boolean read FMaxValueIncluded write FMaxValueIncluded;
+ property MinValueIncluded: Boolean read FMinValueIncluded write FMinValueIncluded;
+ property OnChange: TNotifyEvent read FOnChange write FOnChange;
+ end;
+
+ TJvCustomTextValidateEvent = procedure(Sender: TObject; Key: Char;
+ const AText: string; const Pos: Integer; var IsValid: Boolean) of object;
+ TJvCustomIsValidEvent = procedure(Sender: TObject; var IsValid: Boolean) of object;
+ TJvCustomDecimalRoundingEvent = procedure(Sender: TObject; var DecimalRoundedValue: Double;
+ const Value: Double) of object;
+
+ TJvCustomValidateEdit = class(TCustomEdit) //TJvCustomEdit)
+ private
+ FSelfChange: Boolean;
+ FCheckChars: string;
+ FDecimalPlaces: Cardinal;
+ FDisplayFormat: TJvValidateEditDisplayFormat;
+ FEditText: string;
+ FHasMaxValue: Boolean;
+ FHasMinValue: Boolean;
+ FMaxValue: Double;
+ FMinValue: Double;
+ FOnCustomValidate: TJvCustomTextValidateEvent;
+ FOnValueChanged: TNotifyEvent;
+ FZeroEmpty: Boolean;
+ FEmptyValue: string;
+ FIsEmptyValue: Boolean;
+ FEnterText: string;
+ FDisplayPrefix: string;
+ FDisplaySuffix: string;
+ FCriticalPoints: TJvValidateEditCriticalPoints;
+ FStandardFontColor: TColor;
+ FAutoAlignment: Boolean;
+ FTrimDecimals: Boolean;
+ FOldFontChange: TNotifyEvent;
+ FOnIsValid: TJvCustomIsValidEvent;
+ FOnDecimalRounding: TJvCustomDecimalRoundingEvent;
+ FAllowEmpty: Boolean;
+ FEnforcingMinMaxValue: Boolean;
+ FForceDecimalSeparatorInput: Boolean;
+ FKeepPrefixSuffixIntact: Boolean;
+ FHidePrefixSuffixIfEmpty: Boolean;
+ FLastDownKey: Word;
+ FIsLoaded: Boolean;
+ procedure DisplayText;
+ function ScientificStrToFloat(SciString: string): Double;
+ procedure SetHasMaxValue(NewValue: Boolean);
+ procedure SetHasMinValue(NewValue: Boolean);
+ procedure SetMaxValue(NewValue: Double);
+ procedure SetMinValue(NewValue: Double);
+ procedure SetDecimalPlaces(NewValue: Cardinal);
+ procedure SetDisplayFormat(NewValue: TJvValidateEditDisplayFormat);
+ procedure SetZeroEmpty(NewValue: Boolean);
+ function GetAsInteger: Int64;
+ procedure SetAsInteger(NewValue: Int64);
+ function GetAsCurrency: Currency;
+ procedure SetAsCurrency(NewValue: Currency);
+ function GetAsFloat: Double;
+ procedure SetAsFloat(NewValue: Double);
+ function GetAsBcd: TBcd;
+ procedure SetAsBcd(const NewValue: TBcd);
+ function GetValue: Variant;
+ procedure SetValue(NewValue: Variant);
+ procedure SetCheckChars(const NewValue: string);
+ function IsCheckCharsStored: Boolean;
+ function CurrRangeValue(CheckValue: Currency): Currency;
+ function FloatRangeValue(CheckValue: Double): Double;
+ function IntRangeValue(CheckValue: Int64): Int64;
+ function BcdRangeValue(const CheckValue: TBcd): TBcd;
+ function GetEditText: string;
+ procedure SetEditText(const NewValue: string);
+ procedure ChangeText(const NewValue: string);
+ function BaseToInt(const BaseValue: string; Base: Byte): Int64;
+ function IntToBase(NewValue: Int64; Base: Byte): string;
+ procedure DoValueChanged;
+ procedure SetDisplayPrefix(const NewValue: string);
+ procedure SetDisplaySuffix(const NewValue: string);
+ procedure CriticalPointsChange(Sender: TObject);
+ procedure SetFontColor;
+ procedure FontChange(Sender: TObject);
+ procedure EnforceMaxValue;
+ procedure EnforceMinValue;
+ procedure SetTrimDecimals(const Value: Boolean);
+ function GetUnprefixedUnsuffixedText(const Value: string): string;
+
+ function GetText: TCaption;
+ procedure SetText(const NewValue: TCaption);
+ procedure SetEmptyValue(const AValue: String);
+
+ protected
+ function IsValidChar(const S: string; var Key: Char; Posn: Integer): Boolean; virtual;
+ function MakeValid(const ParseString: string): string;virtual;
+ procedure Change; override;
+ procedure DoEnter; override;
+ procedure DoExit; override;
+ function DoValidate(const Key: Char; const AText: string; const Posn: Integer): Boolean;
+ procedure Loaded; override;
+ procedure KeyDown(var Key: Word; Shift: TShiftState); override;
+ procedure KeyPress(var Key: Char); override;
+ procedure KeyUp(var Key: Word; Shift: TShiftState); override;
+ procedure WMPaste(var Msg: TLMessage); message LM_PASTE;
+
+ procedure DoEmptyValueEnter; virtual;
+ procedure DoEmptyValueExit; virtual;
+
+ (************************** NOT CONVERTED ***
+ function CreateDataConnector: TJvFieldDataConnector; override;
+ ********************************************)
+
+ property CheckChars: string read FCheckChars write SetCheckChars stored IsCheckCharsStored;
+ property TrimDecimals: Boolean read FTrimDecimals write SetTrimDecimals;
+ property DecimalPlaces: Cardinal read FDecimalPlaces write SetDecimalPlaces;
+ property DisplayFormat: TJvValidateEditDisplayFormat read FDisplayFormat write SetDisplayFormat;
+ property EditText: string read GetEditText write SetEditText;
+ property HasMaxValue: Boolean read FHasMaxValue write SetHasMaxValue;
+ property HasMinValue: Boolean read FHasMinValue write SetHasMinValue;
+ property MaxValue: Double read FMaxValue write SetMaxValue;
+ property MinValue: Double read FMinValue write SetMinValue;
+ property Text: TCaption read GetText write SetText;
+ property OnCustomValidate: TJvCustomTextValidateEvent read FOnCustomValidate write FOnCustomValidate;
+ property OnValueChanged: TNotifyEvent read FOnValueChanged write FOnValueChanged;
+ property OnDecimalRounding: TJvCustomDecimalRoundingEvent read FOnDecimalRounding write FOnDecimalRounding;
+ property Value: Variant read GetValue write SetValue stored False;
+ property AllowEmpty: Boolean read FAllowEmpty write FAllowEmpty;
+ property ZeroEmpty: Boolean read FZeroEmpty write SetZeroEmpty;
+ property EmptyValue: string read FEmptyValue write SetEmptyValue;
+ property DisplayPrefix: string read FDisplayPrefix write SetDisplayPrefix;
+ property DisplaySuffix: string read FDisplaySuffix write SetDisplaySuffix;
+ property KeepPrefixSuffixIntact: Boolean read FKeepPrefixSuffixIntact write FKeepPrefixSuffixIntact default False;
+ property HidePrefixSuffixIfEmpty: Boolean read FHidePrefixSuffixIfEmpty write FHidePrefixSuffixIfEmpty default True;
+ property CriticalPoints: TJvValidateEditCriticalPoints read FCriticalPoints write FCriticalPoints;
+ property AutoAlignment: Boolean read FAutoAlignment write FAutoAlignment;
+ property OnIsValid: TJvCustomIsValidEvent read FOnIsValid write FOnIsValid;
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ function IsValid: Boolean; virtual; // fires OnIsValid if assigned
+ function IsEmpty: Boolean; virtual; // override;
+
+ // When the DecimalSeparator variable has changed, one should call
+ // RecalcCheckChars to ensure that it contains the new value (Mantis 4682)
+ procedure RecalcCheckChars;
+
+ procedure Assign(Source: TPersistent); override;
+ property AsInteger: Int64 read GetAsInteger write SetAsInteger;
+ property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;
+ property AsFloat: Double read GetAsFloat write SetAsFloat;
+ property AsBcd: TBcd read GetAsBcd write SetAsBcd;
+
+ // If true and the user presses the VK_DECIMAL key, the key read in KeyPress
+ // will always be replaced by the value of DecimalSeparator. This is made
+ // to overcome the problem where some keyboard layouts send "." instead of
+ // the decimal separator when using the decimal key on the numerical keypad.
+ // The most commonly encountered layout is the French AZERTY one.
+ // Note that this property will be set automatically to True by the
+ // constructor when the conversion of VK_DECIMAL into a character does not
+ // return the DecimalSeparator value
+ property ForceDecimalSeparatorInput: Boolean read FForceDecimalSeparatorInput write FForceDecimalSeparatorInput;
+ end;
+
+ TJvValidateEdit = class(TJvCustomValidateEdit)
+ published
+ property AllowEmpty default False;
+ property Align;
+ property Alignment default taRightJustify;
+ property Anchors;
+ property AutoAlignment default True;
+
+ property AutoSelect;
+ property AutoSize;
+ property BiDiMode;
+ property DragCursor;
+ property DragKind;
+ property ParentBiDiMode;
+ property OnEndDock;
+ property OnStartDock;
+ property BorderSpacing;
+ property BorderStyle;
+ property CheckChars;
+ property CharCase;
+ property Color;
+ property Constraints;
+ property CriticalPoints;
+ property TrimDecimals default False;
+ property DisplayFormat default dfInteger;
+ property DecimalPlaces default 0;
+ property DisplayPrefix;
+ property DisplaySuffix;
+ property DragMode;
+ property EditText;
+ property Enabled;
+ property Font;
+ property HasMaxValue default False;
+ property HasMinValue default False;
+ property HideSelection;
+ property MaxLength;
+ property MaxValue;
+ property MinValue;
+ property ParentColor;
+ property ParentFont;
+ property ParentShowHint;
+ property PasswordChar;
+ property PopupMenu;
+ property ReadOnly;
+ property ShowHint;
+ property TabOrder;
+ property TabStop;
+ property Text stored False;
+ property Value;
+ property Visible;
+ property ZeroEmpty default False;
+ property OnChange;
+ property OnClick;
+ property OnContextPopup;
+ property OnCustomValidate;
+ property OnDblClick;
+ property OnDragDrop;
+ property OnDragOver;
+ 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 OnValueChanged;
+ property OnIsValid;
+ property OnDecimalRounding;
+ property KeepPrefixSuffixIntact;
+ property HidePrefixSuffixIfEmpty;
+
+ {$IFDEF COMPILER12_UP}
+ //property NumbersOnly;
+ {$ENDIF}
+ {$IFDEF COMPILER14_UP}
+ property Touch;
+ {$ENDIF COMPILER14_UP}
+ property TextHint;
+
+ (************ NOT CONVERTED ***
+ property Flat;
+ property ImeMode;
+ property ImeName;
+ property OEMConvert;
+ property ParentFlat;
+ property BevelEdges;
+ property BevelInner;
+ property BevelKind default bkNone;
+ property BevelOuter;
+ property Caret;
+ property ClipboardCommands;
+ property DisabledColor;
+ property DisabledTextColor;
+ property DataConnector;
+ ****************************)
+
+ end;
+
+
+implementation
+
+uses
+ Math, StrUtils, VarUtils, Variants,
+ JvJCLUtils, JvResources;
+
+// JclStrings, JvJCLUtils, JvResources, JclSysUtils;
+
+function IsGreater(Value, MaxValue: Double; MaxValueIncluded: Boolean): Boolean;
+begin
+ if MaxValueIncluded then
+ Result := Value >= MaxValue
+ else
+ Result := Value > MaxValue;
+end;
+
+function IsLower(Value, MinValue: Double; MinValueIncluded: Boolean): Boolean;
+begin
+ if MinValueIncluded then
+ Result := Value <= MinValue
+ else
+ Result := Value < MinValue;
+end;
+
+function BcdToStrFDefault(const Bcd: TBcd; DecimalPlaces: Integer): string;
+begin
+ Result := BcdToStrF(Bcd, ffNumber, 64, DecimalPlaces);
+end;
+
+function BcdToInt64(const Bcd: TBcd; Truncate: Boolean = False): Int64;
+var
+ ABcd: TBcd;
+begin
+ if Truncate and (BcdScale(Bcd) > 0) then
+ NormalizeBcd(Bcd, ABcd, Bcd.Precision, 0)
+ else
+ ABcd := Bcd;
+ Result := StrToInt64(BcdToStr(ABcd));
+end;
+
+function IsBcdZero(const Bcd: TBcd): Boolean;
+var
+ I, Precision: Integer;
+begin
+ Result := False;
+ I := 0;
+ Precision := Bcd.Precision;
+ while I < Precision div 2 do
+ begin
+ if Byte(Bcd.Fraction[I]) <> 0 then
+ Exit;
+ Inc(I);
+ end;
+ Result := (Precision mod 2 = 0) or (Byte(Bcd.Fraction[I]) shr 4 = 0);
+end;
+
+procedure ZeroBcd(var Bcd: TBcd);
+var
+ I: Integer;
+begin
+ Bcd.Precision := 10;
+ Bcd.SignSpecialPlaces := 2;
+ for I := 0 to 31 do
+ Bcd.Fraction[I] := 0;
+end;
+
+(************************** NOT CONVERTED ***
+//=== { TJvValidateEditDataConnector } =======================================
+
+procedure TJvValidateEditDataConnector.Assign(Source: TPersistent);
+begin
+ inherited Assign(Source);
+ if Source is TJvFieldDataConnector then
+ begin
+ NullValue := TJvValidateEditDataConnector(Source).NullValue;
+ end;
+end;
+
+constructor TJvValidateEditDataConnector.Create(AEdit: TJvCustomValidateEdit);
+begin
+ inherited Create;
+ FEdit := AEdit;
+ VarClear(FNullValue);
+end;
+
+function TJvValidateEditDataConnector.IsNullValueStored: Boolean;
+begin
+ Result := not VarIsClear(NullValue);
+end;
+
+procedure TJvValidateEditDataConnector.RecordChanged;
+begin
+ if Field.IsValid then
+ begin
+ FEdit.ReadOnly := not Field.CanModify;
+ if not Field.IsNull then
+ FEdit.Value := Field.Value
+ else
+ if NullValue <> Null then
+ FEdit.Value := NullValue
+ else
+ FEdit.Text := '';
+ end
+ else
+ begin
+ FEdit.Text := '';
+ FEdit.ReadOnly := False;
+ end;
+end;
+
+procedure TJvValidateEditDataConnector.SetNullValue(const Value: Variant);
+begin
+ if Value <> FNullValue then
+ begin
+ FNullValue := Value;
+ Reset;
+ end;
+end;
+
+procedure TJvValidateEditDataConnector.UpdateData;
+begin
+ if Field.CanModify and Field.IsValid then
+ begin
+ if FEdit.Value <> Null then
+ Field.Value := FEdit.Value
+ else
+ if NullValue <> Null then
+ Field.Value := FNullValue
+ else
+ RecordChanged;
+ end;
+end;
+*************************************)
+
+//=== { TJvCustomValidateEdit } ==============================================
+
+constructor TJvCustomValidateEdit.Create(AOwner: TComponent);
+var
+ MappedDecimal: Cardinal;
+const
+ MAPVK_VK_TO_CHAR = 2;
+begin
+ inherited Create(AOwner);
+ FSelfChange := False;
+ FAutoAlignment := True;
+ FCriticalPoints := TJvValidateEditCriticalPoints.Create;
+ FCriticalPoints.OnChange := @CriticalPointsChange;
+ FDisplayFormat := dfInteger;
+ FCheckChars := '01234567890';
+ Alignment := taRightJustify;
+ FEditText := '';
+ Text := ''; // doesn't trigger OnChange because FEnterText = ''. That's what we want.
+ AutoSize := True;
+ FMinValue := 0;
+ FMaxValue := 0;
+ FHasMinValue := False;
+ FHasMaxValue := False;
+ FZeroEmpty := False;
+ FHidePrefixSuffixIfEmpty := True;
+ FStandardFontColor := Font.Color;
+ FOldFontChange := Font.OnChange;
+ Font.OnChange := @FontChange;
+
+ (******************** To DO ***********
+ MappedDecimal := MapVirtualKey(VK_DECIMAL, MAPVK_VK_TO_CHAR);
+ if MappedDecimal <> 0 then
+ FForceDecimalSeparatorInput := Char(MappedDecimal) <> JclFormatSettings.DecimalSeparator;
+ **********************************)
+end;
+
+destructor TJvCustomValidateEdit.Destroy;
+begin
+ FreeAndNil(FCriticalPoints);
+ inherited Destroy;
+end;
+
+procedure TJvCustomValidateEdit.Assign(Source: TPersistent);
+var
+ lcSource: TJvCustomValidateEdit;
+begin
+ if Source is TJvCustomValidateEdit then
+ begin
+ lcSource := TJvCustomValidateEdit(Source);
+ CriticalPoints.Assign(lcSource.CriticalPoints);
+ DisplayFormat := lcSource.DisplayFormat;
+ DecimalPlaces := lcSource.DecimalPlaces;
+ MinValue := lcSource.MinValue;
+ MaxValue := lcSource.MaxValue;
+ HasMinValue := lcSource.HasMinValue;
+ HasMaxValue := lcSource.HasMaxValue;
+ ZeroEmpty := lcSource.ZeroEmpty;
+ AllowEmpty := lcSource.AllowEmpty;
+ end
+ else
+ inherited Assign(Source);
+end;
+
+procedure TJvCustomValidateEdit.Loaded;
+begin
+ EditText := FEditText;
+ inherited Loaded;
+ FIsLoaded := True;
+ (**************** NOT CONVERTED ***
+ FOldFontColor := Font.Color;
+ SelStart := FStreamedSelStart;
+ SelLength := FStreamedSelLength;
+ **********************)
+end;
+
+(****************************** NOT CONVERTED ***
+function TJvCustomValidateEdit.CreateDataConnector: TJvFieldDataConnector;
+begin
+ Result := TJvValidateEditDataConnector.Create(Self);
+end;
+*******************************************************)
+
+procedure TJvCustomValidateEdit.SetHasMaxValue(NewValue: Boolean);
+begin
+ if FHasMaxValue <> NewValue then
+ begin
+ FHasMaxValue := NewValue;
+ if not (csLoading in ComponentState) then
+ EnforceMaxValue;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.SetHasMinValue(NewValue: Boolean);
+begin
+ if FHasMinValue <> NewValue then
+ begin
+ FHasMinValue := NewValue;
+ if not (csLoading in ComponentState) then
+ EnforceMinValue;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.SetMaxValue(NewValue: Double);
+begin
+ if FMaxValue <> NewValue then
+ begin
+ FMaxValue := NewValue;
+ { make MinValue consistent }
+ if FMinValue > FMaxValue then
+ FMinValue := FMaxValue;
+ if not (csLoading in ComponentState) then
+ EnforceMaxValue;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.SetMinValue(NewValue: Double);
+begin
+ if FMinValue <> NewValue then
+ begin
+ FMinValue := NewValue;
+ { make MaxValue consistent }
+ if FMaxValue < FMinValue then
+ FMaxValue := FMinValue;
+ if not (csLoading in ComponentState) then
+ EnforceMinValue;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.SetTrimDecimals(const Value: Boolean);
+begin
+ if Value <> FTrimDecimals then
+ begin
+ FTrimDecimals := Value;
+ if not (csLoading in ComponentState) then
+ EditText := FEditText;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.SetDecimalPlaces(NewValue: Cardinal);
+begin
+ if ControlState = [csReadingState] then
+ FDecimalPlaces := NewValue
+ else
+ if FDisplayFormat in [dfCurrency, dfFloat, dfFloatGeneral, dfScientific, dfPercent, dfFloatFixed, dfBcd] then
+ FDecimalPlaces := NewValue;
+ if not (csLoading in ComponentState) then
+ EditText := FEditText;
+end;
+
+procedure TJvCustomValidateEdit.SetDisplayFormat(NewValue: TJvValidateEditDisplayFormat);
+var
+ OldFormat: TJvValidateEditDisplayFormat;
+begin
+ if FDisplayFormat <> NewValue then
+ begin
+ OldFormat := FDisplayFormat;
+ FDisplayFormat := NewValue;
+
+ RecalcCheckChars;
+
+ case FDisplayFormat of
+ dfAlphabetic, dfAlphaNumeric, dfIdentifier,
+ dfCheckChars, dfNonCheckChars, dfCustom, dfNone:
+ if FAutoAlignment then
+ Alignment := taLeftJustify;
+ dfCurrency:
+ begin
+ if FAutoAlignment then
+ Alignment := taRightJustify;
+ if not (csLoading in ComponentState) then
+ if FDecimalPlaces = 0 then
+ FDecimalPlaces := FormatSettings.CurrencyDecimals;
+ end;
+ dfBinary, dfFloat, dfFloatGeneral, dfPercent, dfDecimal, dfHex,
+ dfInteger, dfOctal, dfScientific, dfFloatFixed, dfBcd:
+ if FAutoAlignment then
+ Alignment := taRightJustify;
+ dfYear:
+ begin
+ if FAutoAlignment then
+ Alignment := taRightJustify;
+ MaxLength := 4;
+ end;
+ end;
+
+ if OldFormat = dfYear then
+ MaxLength := 0;
+
+ if not IsEmpty then
+ begin
+ // Convert non-base 10 numbers to base 10 and base-10 numbers to non-base 10
+ if (OldFormat = dfBinary) and
+ (NewValue in [dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfHex, dfInteger, dfOctal, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd]) then
+ SetAsInteger(BaseToInt(FEditText, 2))
+ else
+ if (OldFormat in [dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfPercent, dfFloatFixed, dfBcd]) and
+ (NewValue in [dfBinary, dfHex, dfOctal])
+ then
+ SetAsfloat(StrToFloatDef(FEditText, 0))
+// SetAsFloat(JvSafeStrToFloatDef(FEditText, 0))
+ else
+ if (OldFormat = dfHex) and
+ (NewValue in [dfBinary, dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfInteger, dfOctal, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd]) then
+ SetAsInteger(BaseToInt(FEditText, 16))
+ else
+ if (OldFormat in [dfInteger, dfYear]) and
+ (NewValue in [dfBinary, dfHex, dfOctal]) then
+ SetAsInteger(StrToIntDef(FEditText, 0))
+ else
+ if (OldFormat = dfOctal) and
+ (NewValue in [dfBinary, dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfHex, dfInteger, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd]) then
+ SetAsInteger(BaseToInt(FEditText, 8))
+ else
+ begin
+ // ...or just display the value
+ if not (csLoading in ComponentState) then
+ EditText := FEditText;
+ end;
+ end;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.SetZeroEmpty(NewValue: Boolean);
+begin
+ if FZeroEmpty <> NewValue then
+ begin
+ FZeroEmpty := NewValue;
+ if not (csLoading in ComponentState) then
+ EditText := FEditText;
+ end;
+end;
+
+function TJvCustomValidateEdit.GetAsInteger: Int64;
+begin
+ case FDisplayFormat of
+ dfBinary:
+ Result := BaseToInt(FEditText, 2);
+ dfHex:
+ Result := BaseToInt(FEditText, 16);
+ dfOctal:
+ Result := BaseToInt(FEditText, 8);
+ else
+ Result := StrToInt64Def(FEditText, 0);
+ end;
+ Result := IntRangeValue(Result);
+end;
+
+procedure TJvCustomValidateEdit.SetAsInteger(NewValue: Int64);
+begin
+ case FDisplayFormat of
+ dfAlphabetic, dfAlphaNumeric, dfCheckChars, dfIdentifier, dfCustom,
+ dfNonCheckChars, dfNone:
+ EditText := IntToStr(NewValue);
+ dfBinary:
+ EditText := IntToBase(NewValue, 2);
+ dfHex:
+ EditText := IntToBase(NewValue, 16);
+ dfOctal:
+ EditText := IntToBase(NewValue, 8);
+ dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfInteger, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd:
+ EditText := IntToStr(IntRangeValue(NewValue));
+ end;
+end;
+
+function TJvCustomValidateEdit.GetAsCurrency: Currency;
+begin
+ case FDisplayFormat of
+ dfBinary:
+ Result := BaseToInt(FEditText, 2);
+ dfHex:
+ Result := BaseToInt(FEditText, 16);
+ dfOctal:
+ Result := BaseToInt(FEditText, 8);
+ else
+ Result := StrToCurrDef(FEditText, 0);
+ end;
+ Result := CurrRangeValue(Result);
+end;
+
+procedure TJvCustomValidateEdit.SetAsCurrency(NewValue: Currency);
+begin
+ case FDisplayFormat of
+ dfAlphabetic, dfAlphaNumeric, dfCheckChars, dfIdentifier, dfCustom,
+ dfNonCheckChars, dfNone:
+ EditText := CurrToStr(NewValue);
+ dfBinary:
+ EditText := IntToBase(Trunc(NewValue), 2);
+ dfHex:
+ EditText := IntToBase(Trunc(NewValue), 16);
+ dfOctal:
+ EditText := IntToBase(Trunc(NewValue), 8);
+ dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfInteger, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd:
+ EditText := CurrToStr(CurrRangeValue(NewValue));
+ end;
+end;
+
+function TJvCustomValidateEdit.GetAsFloat: Double;
+var
+ Cur: Currency;
+begin
+ case FDisplayFormat of
+ dfBinary:
+ Result := BaseToInt(FEditText, 2);
+ dfHex:
+ Result := BaseToInt(FEditText, 16);
+ dfOctal:
+ Result := BaseToInt(FEditText, 8);
+ dfScientific:
+ Result := ScientificStrToFloat(FEditText);
+ dfCurrency:
+ begin
+ // Mantis 3494: The Edit text may contain extra characters such as
+ // parenthesis that indicate the amount is negative. Using StrToFloatDef
+ // would not catch the negative part, hence the need to use a function
+ // that knows how to do the conversion.
+
+ //VarCyFromStr({$IFDEF RTL240_UP}PChar{$ENDIF RTL240_UP}(FEditText), LOCALE_USER_DEFAULT, 0, Cur);
+ //Result := Cur;
+
+ { Laz workaround...}
+ Result := StrToCurrDef(FEditText, 0);
+ end;
+ dfBcd:
+ Result := BcdToDouble(AsBcd);
+ else
+ Result := StrToFloatDef(FEditText, 0); //, JvSafeStrToFloatDef(FEditText, 0);
+ end;
+ Result := FloatRangeValue(Result);
+end;
+
+procedure TJvCustomValidateEdit.SetAsFloat(NewValue: Double);
+begin
+ case FDisplayFormat of
+ dfAlphabetic, dfAlphaNumeric, dfCheckChars, dfIdentifier, dfCustom,
+ dfNonCheckChars, dfNone:
+ EditText := FloatToStr(NewValue);
+ dfBinary:
+ EditText := IntToBase(Trunc(NewValue), 2);
+ dfHex:
+ EditText := IntToBase(Trunc(NewValue), 16);
+ dfOctal:
+ EditText := IntToBase(Trunc(NewValue), 8);
+ dfInteger, dfYear:
+ EditText := IntToStr(IntRangeValue(Trunc(NewValue)));
+ dfCurrency:
+ EditText := Format('%.*m', [FDecimalPlaces, FloatRangeValue(NewValue)]);
+ dfFloat, dfPercent:
+ EditText := Format('%.*n', [FDecimalPlaces, FloatRangeValue(NewValue)]);
+ dfFloatGeneral:
+ EditText := Format('%.*g', [FDecimalPlaces, FloatRangeValue(NewValue)]);
+ dfFloatFixed:
+ EditText := Format('%.*f', [FDecimalPlaces, FloatRangeValue(NewValue)]);
+ dfDecimal:
+ EditText := FloatToStr(FloatRangeValue(NewValue));
+ dfScientific:
+ EditText := Format('%e', [FloatRangeValue(NewValue)]);
+ dfBcd:
+ EditText := BcdToStrFDefault(DoubleToBcd(FloatRangeValue(NewValue)), FDecimalPlaces);
+ end;
+end;
+
+function TJvCustomValidateEdit.GetAsBcd: TBcd;
+var
+ IntValue: Int64;
+begin
+ case FDisplayFormat of
+ dfBinary, dfHex, dfOctal:
+ begin
+ IntValue := GetAsInteger;
+ if Abs(IntValue) < MaxInt then
+ Result := IntegerToBcd(IntValue)
+ else
+ Result := StrToBcd(IntToStr(IntValue));
+ end;
+ dfScientific:
+ Result := DoubleToBcd(ScientificStrToFloat(FEditText));
+ dfCurrency:
+ CurrToBCD(GetAsCurrency, Result);
+ dfFloat, dfFloatGeneral, dfFloatFixed:
+ Result := DoubleToBcd(AsFloat);
+ else
+ if not TryStrToBcd(FEditText, Result) then
+ ZeroBcd(Result);
+ end;
+ Result := BcdRangeValue(Result);
+end;
+
+procedure TJvCustomValidateEdit.SetAsBcd(const NewValue: TBcd);
+begin
+ case FDisplayFormat of
+ dfAlphabetic, dfAlphaNumeric, dfCheckChars, dfIdentifier, dfCustom,
+ dfNonCheckChars, dfNone:
+ EditText := BcdToStrFDefault(NewValue, FDecimalPlaces);
+ dfBinary:
+ EditText := IntToBase(BcdToInt64(NewValue), 2);
+ dfHex:
+ EditText := IntToBase(BcdToInt64(NewValue), 16);
+ dfOctal:
+ EditText := IntToBase(BcdToInt64(NewValue), 8);
+ dfInteger, dfYear:
+ EditText := IntToStr(IntRangeValue(BcdToInt64(NewValue)));
+ dfCurrency:
+ EditText := Format('%.*m', [FDecimalPlaces, FloatRangeValue(BcdToDouble(NewValue))]);
+ dfFloat, dfPercent:
+ EditText := Format('%.*n', [FDecimalPlaces, FloatRangeValue(BcdToDouble(NewValue))]);
+ dfFloatGeneral:
+ EditText := Format('%.*g', [FDecimalPlaces, FloatRangeValue(BcdToDouble(NewValue))]);
+ dfFloatFixed:
+ EditText := Format('%.*f', [FDecimalPlaces, FloatRangeValue(BcdToDouble(NewValue))]);
+ dfDecimal:
+ EditText := FloatToStr(FloatRangeValue(BcdToDouble(NewValue)));
+ dfScientific:
+ EditText := Format('%e', [FloatRangeValue(BcdToDouble(NewValue))]);
+ dfBcd:
+ EditText := BcdToStrFDefault(BcdRangeValue(NewValue), FDecimalPlaces);
+ end;
+end;
+
+function TJvCustomValidateEdit.GetValue: Variant;
+var
+ DisplayedText: string;
+ Cur: Currency;
+ Bcd: TBcd;
+begin
+ case FDisplayFormat of
+ dfCurrency:
+ begin
+ // Mantis 3494: The Edit text may contain extra characters such as
+ // parenthesis that indicate the amount is negative. Using StrToFloatDef
+ // would not catch the negative part, hence the need to use a function
+ // that knows how to do the conversion.
+ //VarCyFromStr({$IFDEF RTL240_UP}PChar{$ENDIF RTL240_UP}(FEditText), LOCALE_USER_DEFAULT, 0, Cur);
+ //Result := CurrRangeValue(Cur);
+
+ // Laz work-around
+ Result := CurrRangeValue(StrToCurrDef(FEditText, 0));
+ end;
+ dfFloat, dfFloatGeneral, dfDecimal, dfPercent, dfScientific, dfFloatFixed:
+ Result := FloatRangeValue(StrToFloatDef(FEditText, 0));
+// Result := FloatRangeValue(JvSafeStrToFloatDef(FEditText, 0));
+ dfInteger, dfYear:
+ Result := IntRangeValue(StrToIntDef(FEditText, 0));
+ dfHex:
+ Result := IntRangeValue(StrToIntDef('$' + FEditText, 0));
+ dfBcd:
+ if TryStrToBcd(FEditText, Bcd) then
+ Result := VarFMTBcdCreate(Bcd)
+ else
+ Result := VarFMTBcdCreate; // Null
+ else
+ DisplayedText := inherited Text;
+
+ // Remove DisplayPrefix and DisplaySuffix
+ DisplayedText := StrEnsureNoPrefix(DisplayPrefix, DisplayedText);
+ DisplayedText := StrEnsureNoSuffix(DisplaySuffix, DisplayedText);
+ Result := DisplayedText;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.SetValue(NewValue: Variant);
+begin
+ if AllowEmpty and (VarIsNull(NewValue) or VarIsEmpty(NewValue)) then
+ Clear
+ else
+ case FDisplayFormat of
+ dfAlphabetic, dfAlphaNumeric, dfCheckChars, dfNonCheckChars, dfIdentifier, dfNone, dfCustom:
+ EditText := NewValue;
+ dfBinary, dfHex, dfInteger, dfOctal, dfYear:
+ SetAsInteger(NewValue);
+ dfCurrency, dfFloat, dfDecimal, dfFloatGeneral, dfPercent, dfScientific, dfFloatFixed:
+ SetAsFloat(NewValue);
+ dfBcd:
+ if VarIsFMTBcd(NewValue) then
+ SetAsBcd(VarToBcd(NewValue))
+ else
+ SetAsBcd(StrToBcd(VarToStr(NewValue)));
+ end;
+end;
+
+procedure TJvCustomValidateEdit.SetCheckChars(const NewValue: string);
+begin
+ if (csLoading in ComponentState) or
+ ((FDisplayFormat in [dfNone, dfCheckChars, dfNonCheckChars]) and
+ (FCheckChars <> NewValue)) then
+ begin
+ FCheckChars := NewValue;
+ EditText := MakeValid(FEditText);
+ end;
+end;
+
+function TJvCustomValidateEdit.IsCheckCharsStored: Boolean;
+begin
+ Result := (FDisplayFormat in [dfNone, dfCheckChars, dfNonCheckChars]);
+end;
+
+procedure TJvCustomValidateEdit.KeyPress(var Key: Char);
+var
+ StrippedText: string;
+begin
+ // Mantis 4952:
+ // - Must not take the prefix/suffix into account when checking a character's validity
+ // - Must not take into account the CurrencyString into account when checking a character's validity
+ StrippedText := GetUnprefixedUnsuffixedText(Text);
+
+ if not IsValidChar(StrippedText, Key, SelStart + 1) and (Key >= #32) then
+ Key := #0;
+ inherited KeyPress(Key);
+end;
+
+procedure TJvCustomValidateEdit.KeyUp(var Key: Word; Shift: TShiftState);
+begin
+ FLastDownKey := 0;
+ inherited KeyUp(Key, Shift);
+end;
+
+procedure TJvCustomValidateEdit.WMPaste(var Msg: TLMessage);
+begin
+ inherited;
+ EditText := MakeValid(GetUnprefixedUnsuffixedText(inherited Text));
+end;
+
+function TJvCustomValidateEdit.MakeValid(const ParseString: string): string;
+var
+ C: Char;
+ I: Integer;
+ L: Integer;
+begin
+ SetLength(Result, Length(ParseString));
+ L := 0;
+ for I := 1 to Length(ParseString) do
+ begin
+ C := ParseString[I];
+ if IsValidChar(Copy(ParseString, 1, I - 1), C, I) then
+ begin
+ Result[L + 1] := C;
+ Inc(L);
+ end;
+ end;
+ SetLength(Result, L);
+end;
+
+procedure TJvCustomValidateEdit.RecalcCheckChars;
+const
+ Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+ Numbers = '0123456789';
+begin
+ case FDisplayFormat of
+ dfAlphabetic:
+ FCheckChars := Alphabet;
+ dfAlphaNumeric:
+ FCheckChars := Alphabet + Numbers;
+ dfIdentifier:
+ FCheckChars := Alphabet + Numbers + '_';
+ dfBinary:
+ FCheckChars := '01';
+ dfCustom, dfNone:
+ if (FDisplayFormat = dfCustom) or not (csLoading in ComponentState) then
+ FCheckChars := '';
+ dfCurrency,
+ dfFloat, dfFloatGeneral, dfPercent, dfDecimal, dfFloatFixed, dfBcd:
+ FCheckChars := Numbers + FormatSettings.DecimalSeparator;
+ dfHex:
+ FCheckChars := Numbers + 'ABCDEFabcdef';
+ dfInteger, dfYear:
+ FCheckChars := Numbers;
+ dfOctal:
+ FCheckChars := '01234567';
+ dfScientific:
+ FCheckChars := Numbers + 'Ee' + FormatSettings.DecimalSeparator;
+ end;
+end;
+
+function TJvCustomValidateEdit.IsValidChar(const S: string;
+ var Key: Char; Posn: Integer): Boolean;
+var
+ iPosE: Integer;
+ ExpectedNegPos: Integer;
+ ExpectedNegChar: Char;
+begin
+ if (FLastDownKey = VK_DECIMAL) and ForceDecimalSeparatorInput then
+ Key := FormatSettings.DecimalSeparator;
+
+ case FDisplayFormat of
+ dfBinary, dfCheckChars, dfHex, dfOctal, dfYear:
+ Result := Pos(Key, FCheckChars) > 0;
+ dfAlphabetic:
+ Result := IsCharAlpha(Key);
+ dfAlphaNumeric:
+ Result := IsCharAlphaNumeric(Key);
+ dfCustom:
+ Result := DoValidate(Key, S, Posn);
+ dfInteger:
+ Result := (Pos(Key, FCheckChars) > 0) or
+ ((Key = '+') and (Posn = 1) and ((Pos('+', S) = 0) or (SelLength > 0))) or
+ ((Key = '-') and (Posn = 1) and ((Pos('-', S) = 0) or (SelLength > 0)));
+ dfFloat, dfFloatGeneral, dfDecimal, dfPercent, dfFloatFixed, dfBcd:
+ Result := ((Pos(Key, FCheckChars) > 0) and
+ (((Key = FormatSettings.DecimalSeparator) and (Pos(FormatSettings.DecimalSeparator, S) = 0)) or (Key <> FormatSettings.DecimalSeparator))) or
+ ((Key = '+') and (Posn = 1) and ((Pos('+', S) = 0) or (SelLength > 0))) or
+ ((Key = '-') and (Posn = 1) and ((Pos('-', S) = 0) or (SelLength > 0)));
+ dfCurrency:
+ begin
+ // The currency negative format can be quite complicated. The current
+ // one is indicated by the value of NegCurrFormat, and can have any
+ // value from 0 to 15 according to the MSDN and Delphi's help.
+ // So we must take into account that some format require the negative
+ // sign to be at the end, while some others replace it by parenthesis.
+ // See http://www.delphibasics.co.uk/RTL.asp?Name=NegCurrFormat for
+ // an online version of Delphi's help.
+ // If we were not to use this, it would trigger Mantis 3494, where
+ // the number would go from negative to positive simply by focusing out
+ // of the control.
+ ExpectedNegChar := '-';
+ ExpectedNegPos := 1;
+ case FormatSettings.NegCurrFormat of
+ 0, 4, 14, 15:
+ begin
+ ExpectedNegPos := 1;
+ ExpectedNegChar := '(';
+ end;
+ 1, 5, 8, 9:
+ ExpectedNegPos := 1;
+ 2:
+ ExpectedNegPos := 2;
+ 3, 7, 10, 11:
+ ExpectedNegPos := Length(S);
+ 6:
+ ExpectedNegPos := Length(S) - 1;
+ 12:
+ ExpectedNegPos := 3;
+ 13:
+ ExpectedNegPos := Length(S) - 2;
+ end;
+
+ if (Key = '(') and (Posn = 1) and (FormatSettings.NegCurrFormat in [0, 4, 14, 15]) then
+ Key := '-';
+
+ Result := ((Pos(Key, FCheckChars) > 0) and
+ (((Key = FormatSettings.DecimalSeparator) and (Pos(FormatSettings.DecimalSeparator, S) = 0)) or
+ (Key <> FormatSettings.DecimalSeparator))) or
+ ((Key = '+') and (Posn = 1) and ((Pos('+', S) = 0) or (SelLength > 0))) or
+ ((Key = '-') and (Posn = ExpectedNegPos) and ((Pos(ExpectedNegChar, S) = 0) or
+ (SelLength > 0)));
+ end;
+ dfNonCheckChars:
+ Result := Pos(Key, FCheckChars) = 0;
+ dfNone:
+ Result := True;
+ dfScientific:
+ begin
+ Result := (Pos(Key, FCheckChars) > 0) or CharInSet(Key, ['+', '-']);
+ if Result then
+ begin
+ iPosE := Pos('e', LowerCase(S));
+ if Key = FormatSettings.DecimalSeparator then
+ begin
+ if iPosE = 0 then
+ Result := (Pos(FormatSettings.DecimalSeparator, S) = 0)
+ else
+ Result := ((Posn <= iPosE) and (Pos(FormatSettings.DecimalSeparator, Copy(S, 1, iPosE - 1)) = 0));
+ //or ((Posn > iPosE) and (Pos(DecimalSeparator, Copy(S, iPosE + 1, Length(S))) = 0));
+ // (outchy) XXXeY,YY are not valid scientific numbers, Y must be an integer value
+ end
+ else
+ if CharInSet(Key, ['E', 'e']) then
+ Result := (iPosE = 0) and (Posn > 1)
+ else
+ if Key = '+' then
+ Result := (Posn = 1) or (Posn = iPosE + 1)
+ else
+ if Key = '-' then
+ Result := (Posn = 1) or (Posn = iPosE + 1);
+ end;
+ end;
+ dfIdentifier:
+ begin
+ if Posn = 1 then
+ Result := (Key = '_') or (IsCharAlpha(Key))
+ else
+ Result := Pos(Key, FCheckChars) > 0;
+ end
+ else
+ Result := False;
+ end;
+end;
+
+function TJvCustomValidateEdit.DoValidate(const Key: Char;
+ const AText: string; const Posn: Integer): Boolean;
+begin
+ Result := True;
+ if Assigned(FOnCustomValidate) then
+ FOnCustomValidate(Self, Key, AText, Posn, Result);
+end;
+
+procedure TJvCustomValidateEdit.KeyDown(var Key: Word; Shift: TShiftState);
+begin
+ FLastDownKey := Key;
+// if Key = VK_DELETE then EditText := MakeValid(inherited Text);
+ if Key = VK_ESCAPE then
+ begin
+ Key := 0;
+ EditText := FEnterText;
+ SelStart := 0;
+ SelLength := Length(FEditText);
+ end;
+ inherited KeyDown(Key, Shift);
+end;
+
+function TJvCustomValidateEdit.CurrRangeValue(CheckValue: Currency): Currency;
+begin
+ Result := CheckValue;
+ if FHasMaxValue and (CheckValue > FMaxValue) then
+ Result := FMaxValue
+ else
+ if FHasMinValue and (CheckValue < FMinValue) then
+ Result := FMinValue;
+end;
+
+function TJvCustomValidateEdit.FloatRangeValue(CheckValue: Double): Double;
+begin
+ Result := CheckValue;
+ if FHasMaxValue and (CheckValue > FMaxValue) then
+ Result := FMaxValue
+ else
+ if FHasMinValue and (CheckValue < FMinValue) then
+ Result := FMinValue;
+end;
+
+function TJvCustomValidateEdit.IntRangeValue(CheckValue: Int64): Int64;
+begin
+ Result := CheckValue;
+ if FHasMaxValue and (CheckValue > FMaxValue) then
+ Result := Trunc(FMaxValue)
+ else
+ if FHasMinValue and (CheckValue < FMinValue) then
+ Result := Trunc(FMinValue);
+end;
+
+function TJvCustomValidateEdit.BcdRangeValue(const CheckValue: TBcd): TBcd;
+begin
+ Result := CheckValue;
+ if FHasMaxValue and (BcdCompare(CheckValue, DoubleToBcd(FMaxValue)) = 1) then // CheckValue > FMaxValue
+ Result := DoubleToBcd(FMaxValue)
+ else
+ if FHasMinValue and (BcdCompare(CheckValue, DoubleToBcd(FMinValue)) = -1) then // CheckValue < FMinValue
+ Result := DoubleToBcd(FMinValue);
+end;
+
+function TJvCustomValidateEdit.GetEditText: string;
+begin
+ Result := FEditText;
+end;
+
+function TJvCustomValidateEdit.GetUnprefixedUnsuffixedText(const Value: string): string;
+begin
+ if not FKeepPrefixSuffixIntact then
+ begin
+ Result := StrEnsureNoPrefix(DisplayPrefix, StrEnsureNoSuffix(DisplaySuffix, Value));
+ Result := StrEnsureNoPrefix(FormatSettings.CurrencyString, StrEnsureNoSuffix(FormatSettings.CurrencyString, Result));
+ end
+ else
+ Result := Value;
+end;
+
+procedure TJvCustomValidateEdit.SetEditText(const NewValue: string);
+begin
+ FEditText := MakeValid(GetUnprefixedUnsuffixedText(NewValue));
+ if (FDisplayFormat = dfYear) and ((not FHasMaxValue) or
+ (FHasMaxValue and (FMaxValue > 2000 + FormatSettings.TwoDigitYearCenturyWindow))) and
+ ((MaxLength = 0) or (MaxLength > 3)) then
+ FEditText := IntToStr(MakeYear4Digit(StrToIntDef(FEditText, 0), FormatSettings.TwoDigitYearCenturyWindow));
+ if (FDisplayFormat in [dfBinary, dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfHex, dfInteger,
+ dfOctal, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd]) then
+ begin
+ EnforceMaxValue;
+ EnforceMinValue;
+ end;
+// ChangeText(FEditText);
+ DisplayText;
+ DoValueChanged;
+end;
+
+procedure TJvCustomValidateEdit.DoEnter;
+//procedure TJvCustomValidateEdit.FocusSet(PrevWnd: THandle);
+begin
+ DisplayText;
+ inherited;
+end;
+
+procedure TJvCustomValidateEdit.DoExit;
+//procedure TJvCustomValidateEdit.FocusKilled(NextWnd: THandle);
+var
+ DisplayedText: string;
+begin
+ if not (csDestroying in ComponentState) then
+ begin
+ DisplayedText := inherited Text;
+ EditText := GetUnprefixedUnsuffixedText(DisplayedText);
+ end;
+ inherited;
+end;
+
+procedure TJvCustomValidateEdit.ChangeText(const NewValue: string);
+var
+ S, Exponent, DisplayValue: string;
+ Ps, I: Integer;
+begin
+ FSelfChange := True;
+ try
+ Ps := 0;
+ if TrimDecimals then
+ begin
+ I := Pos('e', LowerCase(NewValue));
+ if (DisplayFormat = dfScientific) and (I <> 0) then
+ begin
+ Exponent := Copy(NewValue, I, Length(NewValue));
+ Dec(I);
+ end
+ else
+ begin
+ Exponent := '';
+ I := Length(NewValue);
+ end;
+ Ps := Pos(FormatSettings.DecimalSeparator, NewValue);
+ if Ps > 0 then
+ begin
+ while (I > Ps) and (NewValue[I] = '0') do
+ Dec(I);
+ if Ps = I then
+ Dec(I); // skip decimal separator (Ivo Bauer)
+ S := FDisplayPrefix + Copy(NewValue, 1, I) + Exponent + FDisplaySuffix;
+
+ DisplayValue := Copy(NewValue, 1, I);
+ if HidePrefixSuffixIfEmpty and (DisplayValue = '') and (Exponent = '') then
+ S := ''
+ else
+ S := FDisplayPrefix + DisplayValue + Exponent + FDisplaySuffix;
+ end;
+ end;
+ if Ps = 0 then
+ begin
+ if HidePrefixSuffixIfEmpty and (NewValue = '') and (Exponent = '') then
+ S := ''
+ else
+ S := FDisplayPrefix + NewValue + FDisplaySuffix;
+ end;
+ if S <> inherited Text then
+ SetText(S);
+// inherited SetText(S);
+ finally
+ FSelfChange := False;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.DisplayText;
+
+ function FormatedValue(Value: Double): Double;
+ begin
+ if Assigned(FOnDecimalRounding) then
+ FOnDecimalRounding(Self, Result, Value)
+ else
+ Result := Value;
+ end;
+
+begin
+ // The number types need to be formatted
+ if FAllowEmpty and (FEditText = '') then
+ ChangeText('')
+ else
+ if (FDisplayFormat in [dfBinary, dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfInteger, dfOctal,
+ dfPercent, dfScientific, dfYear, dfFloatFixed]) and
+ (AsFloat = 0) and FZeroEmpty then
+ ChangeText('')
+ else if (FDisplayFormat = dfBcd) and FZeroEmpty and IsBcdZero(AsBcd) then
+ ChangeText('')
+ else
+ begin
+ case FDisplayFormat of
+ dfCurrency:
+ ChangeText(Format('%.*m', [FDecimalPlaces, AsCurrency]));
+ dfInteger:
+ ChangeText(IntToStr(AsInteger));
+ dfFloat:
+ ChangeText(Format('%.*n', [FDecimalPlaces, FormatedValue(AsFloat)]));
+ dfFloatGeneral:
+ ChangeText(Format('%.*g', [FDecimalPlaces, FormatedValue(AsFloat)]));
+ dfFloatFixed:
+ ChangeText(Format('%.*f', [FDecimalPlaces, FormatedValue(AsFloat)]));
+ dfScientific:
+ ChangeText(Format('%.*e', [FDecimalPlaces, FormatedValue(AsFloat)]));
+ dfPercent:
+ ChangeText(Format('%.*n%', [FDecimalPlaces, FormatedValue(AsFloat)]));
+ dfBcd:
+ ChangeText(BcdToStrFDefault(AsBcd, FDecimalPlaces));
+ else
+ ChangeText(FEditText);
+ end;
+
+ // This needs to be done AFTER the text has been changed so that the color
+ // is directly shown correctly. (Mantis 3493)
+ if (FCriticalPoints.CheckPoints <> cpNone) and
+ (FDisplayFormat in [dfBinary, dfCurrency, dfFloat, dfFloatGeneral, dfDecimal, dfHex, dfInteger,
+ dfOctal, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd]) then
+ SetFontColor;
+ end;
+end;
+
+function TJvCustomValidateEdit.ScientificStrToFloat(SciString: string): Double;
+var
+ I: Cardinal;
+ sMantissa, sExponent: string;
+ bInExp: Boolean;
+begin
+ if Pos('E', UpperCase(SciString)) = 0 then
+ Result := StrToFloatDef(SciString, 0)
+// Result := JvSafeStrToFloatDef(SciString, 0)
+ else
+ begin
+ sMantissa := '';
+ sExponent := '';
+ bInExp := False;
+ for I := 1 to Length(SciString) do
+ begin
+ if UpperCase(SciString[I]) = 'E' then
+ bInExp := True
+ else
+ begin
+ if bInExp then
+ sExponent := sExponent + SciString[I]
+ else
+ sMantissa := sMantissa + SciString[I];
+ end;
+ end;
+ // NOTE: StrToFloatDefIgnoreInvalidCharacters now called JvSafeStrToFloatDef:
+ Result := StrToFloatDef(sMantissa, 0) * Power(10, StrToFloatDef(sExponent, 0));
+// Result := JvSafeStrToFloatDef(sMantissa, 0) * Power(10, JvSafeStrToFloatDef(sExponent, 0));
+ end;
+end;
+
+function TJvCustomValidateEdit.BaseToInt(const BaseValue: string; Base: Byte): Int64;
+begin
+ Assert(Base <= 36, RsEBaseTooBig);
+ Assert(Base > 1, RsEBaseTooSmall);
+ Result := Numb2Dec(BaseValue, Base);
+end;
+
+function TJvCustomValidateEdit.IntToBase(NewValue: Int64; Base: Byte): string;
+begin
+ Assert(Base <= 36, RsEBaseTooBig);
+ Assert(Base > 1, RsEBaseTooSmall);
+ Result := Dec2Numb(NewValue, 0, Base);
+end;
+
+procedure TJvCustomValidateEdit.DoValueChanged;
+begin
+ try
+ if Assigned(FOnValueChanged) and not (csLoading in ComponentState) and (FEnterText <> FEditText) then
+ FOnValueChanged(Self);
+ finally
+ FEnterText := FEditText;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.Change;
+var
+ DisplayedText: string;
+begin
+ // Update FEditText for User changes, so that the AsInteger, etc,
+ // functions work while editing
+ if not FSelfChange then
+ begin
+ DisplayedText := inherited Text;
+ FEditText := GetUnprefixedUnsuffixedText(DisplayedText);
+ end;
+ inherited Change;
+end;
+
+function TJvCustomValidateEdit.GetText: TCaption;
+begin
+ if (Result = EmptyValue) and (EmptyValue <> '') then
+ Result := ''
+ else
+ Result := inherited Text;
+end;
+
+procedure TJvCustomValidateEdit.SetText(const NewValue: TCaption);
+begin
+ // If we are actually changing our value ourselves, there is no need
+ // to do it again. This may even trigger an infinite recursion, especially
+ // when in a derived component the display format is set in the constructor.
+ // In that case, the recursion would kill Delphi almost instantly.
+ if not FSelfChange then
+ begin
+ EditText := NewValue;
+ DoValueChanged;
+ end else
+ inherited Text := NewValue;
+end;
+
+procedure TJvCustomValidateEdit.SetEmptyValue(const AValue: string);
+begin
+ FEmptyValue := AValue;
+ if HandleAllocated then
+ if Focused then
+ DoEmptyValueEnter
+ else
+ DoEmptyValueExit;
+end;
+
+procedure TJvCustomValidateEdit.DoEmptyValueEnter;
+begin
+ if (csDesigning in ComponentState) or not FIsLoaded or (EmptyValue = '') then
+ Exit;
+ if EmptyValue <> '' then
+ begin
+ if (inherited Text) = EmptyValue then
+ begin
+ inherited Text := '';
+ FIsEmptyValue := False;
+ (***************** NOT CONVERTED ****
+ if not (csDesigning in ComponentState) then
+ Font.Color := FOldFontColor;
+ *************************************)
+ end;
+ end
+ (****************** NOT CONVERTED ***
+ else
+ if not (csDesigning in ComponentState) then
+ Font.Color := FOldFontColor;
+ ***********************************)
+end;
+
+procedure TJvCustomValidateEdit.DoEmptyValueExit;
+begin
+ if (csDesigning in ComponentState) or not FIsLoaded or (EmptyValue = '') then
+ Exit;
+ if EmptyValue <> '' then
+ begin
+ if Text = '' then
+ begin
+ Text := EmptyValue;
+ FIsEmptyValue := True;
+ (****************************** NOT CONVERTED **********
+ if not (csDesigning in ComponentState) then
+ begin
+ FOldFontColor := Font.Color;
+ Font.Color := FEmptyFontColor;
+ end;
+ *******************************************************)
+ end;
+ end
+ (**************************** NOT CONVERTED *************
+ else
+ if not (csDesigning in ComponentState) then
+ Font.Color := FOldFontColor;
+ *******************************************************)
+end;
+
+procedure TJvCustomValidateEdit.SetDisplayPrefix(const NewValue: string);
+begin
+ FDisplayPrefix := NewValue;
+ DisplayText;
+end;
+
+procedure TJvCustomValidateEdit.SetDisplaySuffix(const NewValue: string);
+begin
+ FDisplaySuffix := NewValue;
+ DisplayText;
+end;
+
+procedure TJvCustomValidateEdit.CriticalPointsChange(Sender: TObject);
+begin
+ SetFontColor;
+ Invalidate;
+end;
+
+function TJvCustomValidateEdit.IsValid: Boolean;
+begin
+ Result := True;
+ case FCriticalPoints.CheckPoints of
+ cpMaxValue:
+ Result := IsLower(AsFloat, FCriticalPoints.MaxValue, FCriticalPoints.MaxValueIncluded);
+ cpMinValue:
+ Result := IsGreater(AsFloat, FCriticalPoints.MinValue, FCriticalPoints.MinValueIncluded);
+ cpBoth:
+ Result := IsLower(AsFloat, FCriticalPoints.MaxValue, FCriticalPoints.MaxValueIncluded) and
+ IsGreater(AsFloat, FCriticalPoints.MinValue, FCriticalPoints.MinValueIncluded);
+ end;
+ if Assigned(FOnIsValid) then
+ FOnIsValid(Self, Result);
+end;
+
+function TJvCustomValidateEdit.IsEmpty: Boolean;
+var
+ s: String;
+begin
+ s := GetUnprefixedUnsuffixedText(Text);
+ Result := s = '';
+end;
+
+procedure TJvCustomValidateEdit.SetFontColor;
+begin
+ if not (csDesigning in ComponentState) and not (csLoading in ComponentState) then
+ begin
+ Font.OnChange := nil;
+ case FCriticalPoints.CheckPoints of
+ cpNone:
+ Font.Color := FStandardFontColor;
+ cpMinValue:
+ if IsLower(AsFloat, FCriticalPoints.MinValue, not FCriticalPoints.MinValueIncluded) then
+ Font.Color := FCriticalPoints.ColorBelow
+ else
+ Font.Color := FStandardFontColor;
+ cpMaxValue:
+ if IsGreater(AsFloat, FCriticalPoints.MaxValue, not FCriticalPoints.MaxValueIncluded) then
+ Font.Color := FCriticalPoints.ColorAbove
+ else
+ Font.Color := FStandardFontColor;
+ cpBoth:
+ if IsGreater(AsFloat, FCriticalPoints.MaxValue, not FCriticalPoints.MaxValueIncluded) then
+ Font.Color := FCriticalPoints.ColorAbove
+ else if IsLower(AsFloat, FCriticalPoints.MinValue, not FCriticalPoints.MinValueIncluded) then
+ Font.Color := FCriticalPoints.ColorBelow
+ else
+ Font.Color := FStandardFontColor;
+ end;
+ Font.OnChange := @FontChange;
+ end;
+ Invalidate;
+end;
+
+procedure TJvCustomValidateEdit.FontChange(Sender: TObject);
+begin
+ FStandardFontColor := Font.Color;
+ if Assigned(FOldFontChange) then
+ FOldFontChange(Sender);
+end;
+
+procedure TJvCustomValidateEdit.EnforceMaxValue;
+begin
+ { Check the Value is within this range }
+ if FHasMaxValue and (FDisplayFormat in [dfBinary, dfCurrency, dfFloat, dfFloatGeneral,
+ dfDecimal, dfHex, dfInteger, dfOctal, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd]) and
+ (AsFloat > FMaxValue) and not FEnforcingMinMaxValue then
+ begin
+ if not (AllowEmpty and IsEmpty) then
+ begin
+ FEnforcingMinMaxValue := True;
+ try
+ SetAsFloat(FMaxValue);
+ finally
+ FEnforcingMinMaxValue := False;
+ end;
+ end;
+ end;
+end;
+
+procedure TJvCustomValidateEdit.EnforceMinValue;
+begin
+ { Check the Value is within this range }
+ if FHasMinValue and (FDisplayFormat in [dfBinary, dfCurrency, dfFloat, dfFloatGeneral,
+ dfDecimal, dfHex, dfInteger, dfOctal, dfPercent, dfScientific, dfYear, dfFloatFixed, dfBcd]) and
+ (AsFloat < FMinValue) and not FEnforcingMinMaxValue then
+ begin
+ if not (AllowEmpty and IsEmpty) then
+ begin
+ FEnforcingMinMaxValue := True;
+ try
+ SetAsFloat(FMinValue);
+ finally
+ FEnforcingMinMaxValue := False;
+ end;
+ end;
+ end;
+end;
+
+//=== { TJvValidateEditCriticalPoints } ======================================
+
+constructor TJvValidateEditCriticalPoints.Create;
+begin
+ inherited Create;
+ SetDefaults(cpNone, clBlue, clRed);
+ FMaxValueIncluded := False;
+ FMinValueIncluded := False;
+end;
+
+procedure TJvValidateEditCriticalPoints.SetCheckPoints(NewValue: TJvValidateEditCriticalPointsCheck);
+begin
+ if FCheckPoints <> NewValue then
+ begin
+ FCheckPoints := NewValue;
+ DoChanged;
+ end;
+end;
+
+procedure TJvValidateEditCriticalPoints.SetColorAbove(NewValue: TColor);
+begin
+ if FColorAbove <> NewValue then
+ begin
+ FColorAbove := NewValue;
+ DoChanged;
+ end;
+end;
+
+procedure TJvValidateEditCriticalPoints.SetColorBelow(NewValue: TColor);
+begin
+ if FColorBelow <> NewValue then
+ begin
+ FColorBelow := NewValue;
+ DoChanged;
+ end;
+end;
+
+procedure TJvValidateEditCriticalPoints.SetMaxValue(NewValue: Double);
+begin
+ if FMaxValue <> NewValue then
+ begin
+ FMaxValue := NewValue;
+ DoChanged;
+ end;
+end;
+
+procedure TJvValidateEditCriticalPoints.SetMinValue(NewValue: Double);
+begin
+ if FMinValue <> NewValue then
+ begin
+ FMinValue := NewValue;
+ DoChanged;
+ end;
+end;
+
+procedure TJvValidateEditCriticalPoints.DoChanged;
+begin
+ if Assigned(FOnChange) then
+ FOnChange(Self);
+end;
+
+procedure TJvValidateEditCriticalPoints.Assign(Source: TPersistent);
+var
+ LocalSource: TJvValidateEditCriticalPoints;
+begin
+ if Source is TJvValidateEditCriticalPoints then
+ begin
+ LocalSource := TJvValidateEditCriticalPoints(Source);
+ CheckPoints := LocalSource.CheckPoints;
+ ColorAbove := LocalSource.ColorAbove;
+ ColorBelow := LocalSource.ColorBelow;
+ MaxValue := LocalSource.MaxValue;
+ MinValue := LocalSource.MinValue;
+ end
+ else
+ inherited Assign(Source);
+end;
+
+function TJvValidateEditCriticalPoints.IsCheckPointsStored: Boolean;
+begin
+ Result := (FCheckPoints <> FDefCheckPoints);
+end;
+
+function TJvValidateEditCriticalPoints.IsColorAboveStored: Boolean;
+begin
+ Result := (FColorAbove <> FDefColorAbove);
+end;
+
+function TJvValidateEditCriticalPoints.IsColorBelowStored: Boolean;
+begin
+ Result := (FColorBelow <> FDefColorBelow);
+end;
+
+procedure TJvValidateEditCriticalPoints.SetDefaults(ACheckPoints: TJvValidateEditCriticalPointsCheck;
+ AColorAbove, AColorBelow: TColor);
+begin
+ FDefCheckPoints := ACheckPoints;
+ FCheckPoints := ACheckPoints;
+ FDefColorAbove := AColorAbove;
+ FColorAbove := AColorAbove;
+ FDefColorBelow := AColorBelow;
+ FColorBelow := AColorBelow;
+end;
+
+
+end.