RxFPC:TCurrencyEdit - full rewrite, now working

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3612 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
alexs75
2014-09-30 04:34:09 +00:00
parent 5b4317a706
commit 5a79fc8458

View File

@ -1,6 +1,6 @@
{ curredit unit { curredit unit
Copyright (C) 2005-2010 Lagunov Aleksey alexs@yandex.ru and Lazarus team Copyright (C) 2005-2014 Lagunov Aleksey alexs@yandex.ru and Lazarus team
original conception from rx library for Delphi (c) original conception from rx library for Delphi (c)
This library is free software; you can redistribute it and/or modify it This library is free software; you can redistribute it and/or modify it
@ -36,8 +36,8 @@ unit curredit;
interface interface
uses uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, {StdCtrls,} Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, LMessages,
LMessages, MaskEdit; MaskEdit;
type type
@ -45,13 +45,12 @@ type
TCustomNumEdit = class(TCustomMaskEdit) TCustomNumEdit = class(TCustomMaskEdit)
private private
FCanvas: TControlCanvas; FFocusedDisplay: boolean;
FAlignment: TAlignment;
FBeepOnError: Boolean; FBeepOnError: Boolean;
FCheckOnExit: Boolean; FCheckOnExit: Boolean;
FDecimalPlaces: Cardinal; FDecimalPlaces: Cardinal;
FDisplayFormat: string; FDisplayFormat: string;
FFormatOnEditing: Boolean; // FFormatOnEditing: Boolean;
FFormatting: Boolean; FFormatting: Boolean;
FMaxValue: Extended; FMaxValue: Extended;
FMinValue: Extended; FMinValue: Extended;
@ -61,13 +60,11 @@ type
function GetAsInteger: Longint; function GetAsInteger: Longint;
function GetText: string; function GetText: string;
function GetValue: Extended; function GetValue: Extended;
function IsFormatStored: boolean;
procedure SetAlignment(const AValue: TAlignment);
procedure SetAsInteger(const AValue: Longint); procedure SetAsInteger(const AValue: Longint);
procedure SetBeepOnError(const AValue: Boolean); procedure SetBeepOnError(const AValue: Boolean);
procedure SetDecimalPlaces(const AValue: Cardinal); procedure SetDecimalPlaces(const AValue: Cardinal);
procedure SetDisplayFormat(const AValue: string); procedure SetDisplayFormat(const AValue: string);
procedure SetFormatOnEditing(const AValue: Boolean); // procedure SetFormatOnEditing(const AValue: Boolean);
procedure SetMaxValue(const AValue: Extended); procedure SetMaxValue(const AValue: Extended);
procedure SetMinValue(const AValue: Extended); procedure SetMinValue(const AValue: Extended);
procedure SetText(const AValue: string); procedure SetText(const AValue: string);
@ -75,24 +72,27 @@ type
procedure SetZeroEmpty(const AValue: Boolean); procedure SetZeroEmpty(const AValue: Boolean);
function TextToValText(const AValue: string): string; function TextToValText(const AValue: string): string;
function CheckValue(NewValue: Extended; RaiseOnError: Boolean): Extended; function CheckValue(NewValue: Extended; RaiseOnError: Boolean): Extended;
procedure SetFocused(Value: Boolean); // procedure SetFocused(Value: Boolean);
protected protected
//messages //messages
procedure CMEnabledChanged(var Message: TLMessage); message CM_ENABLEDCHANGED; { procedure CMEnabledChanged(var Message: TLMessage); message CM_ENABLEDCHANGED;
procedure CMEnter(var Message: TLMEnter); message LM_ENTER; procedure CMEnter(var Message: TLMEnter); message LM_ENTER;
procedure WMExit(var Message: TLMExit); message LM_EXIT; procedure WMExit(var Message: TLMExit); message LM_EXIT; }
procedure CMFontChanged(var Message: TLMessage); message CM_FONTCHANGED;
procedure WMPaint(var Message: TLMPaint); message LM_PAINT; procedure WMSetFocus(var Message: TLMSetFocus); message LM_SETFOCUS;
procedure WMKillFocus(var Message: TLMKillFocus); message LM_KILLFOCUS;
// procedure CMFontChanged(var Message: TLMessage); message CM_FONTCHANGED;
// procedure WMPaint(var Message: TLMPaint); message LM_PAINT;
procedure WMPaste(var Message: TLMessage); message LM_PASTE; procedure WMPaste(var Message: TLMessage); message LM_PASTE;
procedure GetSel(var ASelStart: Integer; var SelStop: Integer); // procedure GetSel(var ASelStart: Integer; var SelStop: Integer);
procedure DoEnter; override; { procedure DoEnter; override;
procedure DoExit; override; procedure DoExit; override;}
// procedure AcceptValue(const Value: Variant); override; // procedure AcceptValue(const Value: Variant); override;
procedure Change; override; // procedure Change; override;
procedure ReformatEditText; dynamic; // procedure ReformatEditText; dynamic;
procedure DataChanged; virtual; procedure DataChanged; virtual;
function DefaultDisplayFormat: string; virtual;
procedure KeyPress(var Key: Char); override; procedure KeyPress(var Key: Char); override;
function IsValidChar(Key: Char): Boolean; virtual; function IsValidChar(Key: Char): Boolean; virtual;
function FormatDisplayText(Value: Extended): string; function FormatDisplayText(Value: Extended): string;
@ -100,24 +100,21 @@ type
procedure Reset; override; procedure Reset; override;
procedure CheckRange; procedure CheckRange;
procedure UpdateData; procedure UpdateData;
property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
property Formatting: Boolean read FFormatting; property Formatting: Boolean read FFormatting;
property BeepOnError: Boolean read FBeepOnError write SetBeepOnError property BeepOnError: Boolean read FBeepOnError write SetBeepOnError
default True; default True;
property CheckOnExit: Boolean read FCheckOnExit write FCheckOnExit default False; property CheckOnExit: Boolean read FCheckOnExit write FCheckOnExit default False;
property DecimalPlaces: Cardinal read FDecimalPlaces write SetDecimalPlaces property DecimalPlaces: Cardinal read FDecimalPlaces write SetDecimalPlaces
default 2; default 2;
property DisplayFormat: string read FDisplayFormat write SetDisplayFormat stored IsFormatStored; property DisplayFormat: string read FDisplayFormat write SetDisplayFormat;
property MaxValue: Extended read FMaxValue write SetMaxValue; property MaxValue: Extended read FMaxValue write SetMaxValue;
property MinValue: Extended read FMinValue write SetMinValue; property MinValue: Extended read FMinValue write SetMinValue;
property FormatOnEditing: Boolean read FFormatOnEditing // property FormatOnEditing: Boolean read FFormatOnEditing write SetFormatOnEditing default False;
write SetFormatOnEditing default False;
property Text: string read GetText write SetText stored False; property Text: string read GetText write SetText stored False;
property MaxLength default 0; property MaxLength default 0;
property ZeroEmpty: Boolean read FZeroEmpty write SetZeroEmpty default True; property ZeroEmpty: Boolean read FZeroEmpty write SetZeroEmpty default True;
public public
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Clear; procedure Clear;
property AsInteger: Longint read GetAsInteger write SetAsInteger; property AsInteger: Longint read GetAsInteger write SetAsInteger;
property DisplayText: string read GetDisplayText; property DisplayText: string read GetDisplayText;
@ -130,9 +127,7 @@ type
TCurrencyEdit = class(TCustomNumEdit) TCurrencyEdit = class(TCustomNumEdit)
protected protected
function DefaultDisplayFormat: string; override;
public public
constructor Create(AOwner: TComponent); override;
published published
property Alignment; property Alignment;
property AutoSelect; property AutoSelect;
@ -148,7 +143,7 @@ type
property DragMode; property DragMode;
property Enabled; property Enabled;
property Font; property Font;
property FormatOnEditing; // property FormatOnEditing;
property HideSelection; property HideSelection;
property Anchors; property Anchors;
property BiDiMode; property BiDiMode;
@ -201,7 +196,7 @@ type
end; end;
implementation implementation
uses {rxstrutils, } strutils, Math, tooledit, rxconst; uses strutils, Math, tooledit, rxconst;
function IsValidFloat(const Value: string; var RetValue: Extended): Boolean; function IsValidFloat(const Value: string; var RetValue: Extended): Boolean;
var var
@ -279,32 +274,17 @@ begin
ControlStyle := ControlStyle - [csSetCaption]; ControlStyle := ControlStyle - [csSetCaption];
MaxLength := 0; MaxLength := 0;
FBeepOnError := True; FBeepOnError := True;
FAlignment := taRightJustify;
FDisplayFormat := DefaultDisplayFormat;
FDecimalPlaces := 2; FDecimalPlaces := 2;
FZeroEmpty := True; FZeroEmpty := True;
inherited Text := ''; inherited Text := '';
inherited Alignment := taLeftJustify; Alignment := taRightJustify;
// FDefNumGlyphs := 2;
{ forces update }
DataChanged; DataChanged;
ControlState := ControlState + [csCreating]; ControlState := ControlState + [csCreating];
end; end;
destructor TCustomNumEdit.Destroy;
begin
FCanvas.Free;
{ if FPopup <> nil then begin
TPopupWindow(FPopup).OnCloseUp := nil;
FPopup.Free;
FPopup := nil;
end;}
inherited Destroy;
end;
function TCustomNumEdit.GetText: string; function TCustomNumEdit.GetText: string;
begin begin
Result := inherited Text; Result := FloatToStr(FValue);
end; end;
function TCustomNumEdit.GetValue: Extended; function TCustomNumEdit.GetValue: Extended;
@ -318,18 +298,6 @@ begin
Result := FValue; Result := FValue;
end; end;
function TCustomNumEdit.IsFormatStored: boolean;
begin
Result := (DisplayFormat <> DefaultDisplayFormat);
end;
procedure TCustomNumEdit.SetAlignment(const AValue: TAlignment);
begin
if FAlignment=AValue then exit;
FAlignment:=AValue;
Invalidate;
end;
procedure TCustomNumEdit.SetAsInteger(const AValue: Longint); procedure TCustomNumEdit.SetAsInteger(const AValue: Longint);
begin begin
SetValue(AValue); SetValue(AValue);
@ -353,18 +321,14 @@ procedure TCustomNumEdit.SetDisplayFormat(const AValue: string);
begin begin
if FDisplayFormat=AValue then exit; if FDisplayFormat=AValue then exit;
FDisplayFormat:=AValue; FDisplayFormat:=AValue;
Invalidate;
DataChanged; DataChanged;
end; end;
{
procedure TCustomNumEdit.SetFormatOnEditing(const AValue: Boolean); procedure TCustomNumEdit.SetFormatOnEditing(const AValue: Boolean);
begin begin
if FFormatOnEditing=AValue then exit; if FFormatOnEditing=AValue then exit;
FFormatOnEditing:=AValue; FFormatOnEditing:=AValue;
if FFormatOnEditing then
// FAlignment := AValue
else
FAlignment := taLeftJustify;
if FFormatOnEditing and FFocused then if FFormatOnEditing and FFocused then
ReformatEditText ReformatEditText
else else
@ -374,7 +338,7 @@ begin
DataChanged; DataChanged;
end; end;
end; end;
}
procedure TCustomNumEdit.SetMaxValue(const AValue: Extended); procedure TCustomNumEdit.SetMaxValue(const AValue: Extended);
begin begin
if FMaxValue=AValue then exit; if FMaxValue=AValue then exit;
@ -451,7 +415,7 @@ begin
[DecimalPlaces, FMinValue, DecimalPlaces, FMaxValue]); [DecimalPlaces, FMinValue, DecimalPlaces, FMaxValue]);
end; end;
end; end;
{
procedure TCustomNumEdit.SetFocused(Value: Boolean); procedure TCustomNumEdit.SetFocused(Value: Boolean);
begin begin
if FFocused <> Value then if FFocused <> Value then
@ -466,7 +430,31 @@ begin
end; end;
end; end;
end; end;
}
procedure TCustomNumEdit.WMSetFocus(var Message: TLMSetFocus);
begin
inherited WMSetFocus(Message);
// some widgetsets do not notify clipboard actions properly. Put at edit state at entry
if FFocusedDisplay then
exit;
FFocusedDisplay := true;
Reset;
{ if WidgetSet.GetLCLCapability(lcReceivesLMClearCutCopyPasteReliably) = LCL_CAPABILITY_YES then
FDataLink.Reset
else
FDataLink.Edit;}
end;
procedure TCustomNumEdit.WMKillFocus(var Message: TLMKillFocus);
begin
inherited WMKillFocus(Message);
FFocusedDisplay := False;
UpdateData;
if not Focused then
DisableMask(GetDisplayText);
end;
{
procedure TCustomNumEdit.CMEnabledChanged(var Message: TLMessage); procedure TCustomNumEdit.CMEnabledChanged(var Message: TLMessage);
begin begin
inherited; inherited;
@ -509,10 +497,10 @@ begin
S := GetDisplayText; S := GetDisplayText;
// if not FFocused then // if not FFocused then
// else // else
if not PaintComboEdit(Self, S, FAlignment, FFocused {and not PopupVisible}, FCanvas, Message) then // if not PaintComboEdit(Self, S, FAlignment, FFocused {and not PopupVisible}, FCanvas, Message) then
inherited WMPaint(Message); inherited WMPaint(Message);
end; end;
}
procedure TCustomNumEdit.WMPaste(var Message: TLMessage); procedure TCustomNumEdit.WMPaste(var Message: TLMessage);
var var
S: string; S: string;
@ -528,13 +516,14 @@ begin
// if BeepOnError then MessageBeep(0); // if BeepOnError then MessageBeep(0);
end; end;
end; end;
{
procedure TCustomNumEdit.GetSel(var ASelStart: Integer; var SelStop: Integer); procedure TCustomNumEdit.GetSel(var ASelStart: Integer; var SelStop: Integer);
begin begin
ASelStart:=SelStart; ASelStart:=SelStart;
SelStop:=SelStart + SelLength; SelStop:=SelStart + SelLength;
end; end;
procedure TCustomNumEdit.DoEnter; procedure TCustomNumEdit.DoEnter;
begin begin
SetFocused(True); SetFocused(True);
@ -559,10 +548,10 @@ begin
Invalidate; Invalidate;
end; end;
{procedure TCustomNumEdit.AcceptValue(const Value: Variant); procedure TCustomNumEdit.AcceptValue(const Value: Variant);
begin begin
inherited AcceptValue(Value); inherited AcceptValue(Value);
end;} end;
procedure TCustomNumEdit.Change; procedure TCustomNumEdit.Change;
begin begin
@ -598,34 +587,17 @@ begin
FFormatting := False; FFormatting := False;
end; end;
end; end;
}
procedure TCustomNumEdit.DataChanged; procedure TCustomNumEdit.DataChanged;
var
EditFormat: string;
begin begin
EditFormat := '0'; if FFocusedDisplay then
if FDecimalPlaces > 0 then RestoreMask(GetText)
EditFormat := EditFormat + '.' + DupeString('#', FDecimalPlaces);
if (FValue = 0.0) and FZeroEmpty then
EditText := ''
else else
EditText := FormatFloat(EditFormat, FValue); DisableMask(GetDisplayText)
end;
function TCustomNumEdit.DefaultDisplayFormat: string;
begin
Result := ',0.##';
end; end;
procedure TCustomNumEdit.KeyPress(var Key: Char); procedure TCustomNumEdit.KeyPress(var Key: Char);
begin begin
{ if PopupVisible and (UpCase(Key) in ['0'..'9', DecimalSeparator, '.', ',',
'+', '-', '*', '/', '_', '=', 'C', 'R', 'Q', '%', #8, #13] -
[ThousandSeparator]) then
begin
THack(FPopup).KeyPress(Key);
Key := #0;
end;}
if Key in ['.', ','] - [DefaultFormatSettings.ThousandSeparator] then if Key in ['.', ','] - [DefaultFormatSettings.ThousandSeparator] then
Key := DefaultFormatSettings.DecimalSeparator; Key := DefaultFormatSettings.DecimalSeparator;
inherited KeyPress(Key); inherited KeyPress(Key);
@ -635,7 +607,8 @@ begin
Key := #0; Key := #0;
end end
else else
if Key = #27 then begin if Key = #27 then
begin
Reset; Reset;
Key := #0; Key := #0;
end; end;
@ -673,11 +646,16 @@ begin
end; end;
function TCustomNumEdit.FormatDisplayText(Value: Extended): string; function TCustomNumEdit.FormatDisplayText(Value: Extended): string;
var
Digits : integer;
begin begin
if DisplayFormat <> '' then if DisplayFormat <> '' then
Result:=FormatFloat(DisplayFormat, Value) Result:=FormatFloat(DisplayFormat, Value)
else else
Result := FloatToStr(Value); begin
Digits := DefaultFormatSettings.CurrencyDecimals;
Result:=FloatToStrF(Value, ffCurrency, DecimalPlaces, Digits);
end;
end; end;
procedure TCustomNumEdit.Clear; procedure TCustomNumEdit.Clear;
@ -685,44 +663,6 @@ begin
end; end;
{ TCurrencyEdit } initialization
RegisterPropertyToSkip( TCustomNumEdit, 'FormatOnEditing', 'This property depricated', '');
function TCurrencyEdit.DefaultDisplayFormat: string;
var
CurrStr: string;
I: Integer;
C: Char;
begin
Result := ',0.' + DupeString('0', DefaultFormatSettings.CurrencyDecimals);
CurrStr := '';
for I := 1 to Length(DefaultFormatSettings.CurrencyString) do
begin
C := DefaultFormatSettings.CurrencyString[I];
if C in [',', '.'] then
begin
CurrStr := CurrStr + '''' + C + ''''
end
else CurrStr := CurrStr + C;
end;
if Length(CurrStr) > 0 then
case DefaultFormatSettings.CurrencyFormat of
0: Result := CurrStr + Result; { '$1' }
1: Result := Result + CurrStr; { '1$' }
2: Result := CurrStr + ' ' + Result; { '$ 1' }
3: Result := Result + ' ' + CurrStr; { '1 $' }
end;
Result := Format('%s;-%s', [Result, Result]);
end;
constructor TCurrencyEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlState := ControlState + [csCreating];
try
// ButtonWidth := 0;
finally
ControlState := ControlState - [csCreating];
end;
end;
end. end.