lazarus-ccr/components/orpheus/ovcedclc.pas

604 lines
15 KiB
ObjectPascal

{*********************************************************}
{* OVCEDCLC.PAS 4.06 *}
{*********************************************************}
{* ***** BEGIN LICENSE BLOCK ***** *}
{* Version: MPL 1.1 *}
{* *}
{* 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/ *}
{* *}
{* Software distributed under the License is distributed on an "AS IS" basis, *}
{* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *}
{* for the specific language governing rights and limitations under the *}
{* License. *}
{* *}
{* The Original Code is TurboPower Orpheus *}
{* *}
{* The Initial Developer of the Original Code is TurboPower Software *}
{* *}
{* Portions created by TurboPower Software Inc. are Copyright (C)1995-2002 *}
{* TurboPower Software Inc. All Rights Reserved. *}
{* *}
{* Contributor(s): *}
{* *}
{* ***** END LICENSE BLOCK ***** *}
{$I OVC.INC}
{$B-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{.W-} {Windows Stack Frame}
{$X+} {Extended Syntax}
unit ovcedclc;
{-numeric edit field with popup calculator}
interface
uses
{$IFNDEF LCL} Windows, Messages, {$ELSE} LclIntf, LMessages, LclType, MyMisc, {$ENDIF}
Buttons, Classes, Controls, Forms, Graphics, Menus,
StdCtrls, SysUtils, {$IFDEF VERSION4}{$IFNDEF LCL} MultiMon, {$ENDIF}{$ENDIF}
OvcBase, OvcCalc, OvcEdPop, OvcMisc;
type
TOvcCustomNumberEdit = class(TOvcEdPopup)
{.Z+}
protected {private}
FAllowIncDec : Boolean;
FCalculator : TOvcCalculator;
{internal variables}
PopupClosing : Boolean;
HoldCursor : TCursor;
WasAutoScroll : Boolean;
{property methods}
function GetAsFloat : Double;
function GetAsInteger : LongInt;
function GetAsString : string;
function GetPopupColors : TOvcCalcColors;
function GetPopupDecimals : Integer;
function GetPopupFont : TFont;
function GetPopupHeight : Integer;
function GetPopupWidth : Integer;
function GetReadOnly : Boolean;
procedure SetAsFloat(Value : Double);
procedure SetAsInteger(Value : LongInt);
procedure SetAsString(const Value : string);
procedure SetPopupColors(Value : TOvcCalcColors);
procedure SetPopupDecimals(Value : Integer);
procedure SetPopupFont(Value : TFont);
procedure SetPopupHeight(Value : Integer);
procedure SetPopupWidth(Value : Integer);
procedure SetReadOnly(Value : Boolean);
{internal methods}
procedure PopupButtonPressed(Sender : TObject; Button : TOvcCalculatorButton);
procedure PopupKeyDown(Sender : TObject; var Key : Word; Shift : TShiftState);
procedure PopupKeyPress(Sender : TObject; var Key : Char);
procedure PopupMouseDown(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
protected
procedure DoExit;
override;
procedure GlyphChanged;
override;
procedure KeyDown(var Key : Word; Shift : TShiftState);
override;
procedure KeyPress(var Key : Char);
override;
{.Z-}
property AllowIncDec : Boolean
read FAllowIncDec write FAllowIncDec;
property PopupColors : TOvcCalcColors
read GetPopupColors write SetPopupColors;
property PopupDecimals : Integer
read GetPopupDecimals write SetPopupDecimals;
property PopupFont : TFont
read GetPopupFont write SetPopupFont;
property PopupHeight : Integer
read GetPopupHeight write SetPopupHeight;
property PopupWidth : Integer
read GetPopupWidth write SetPopupWidth;
property ReadOnly : Boolean
read GetReadOnly write SetReadOnly;
public
{.Z+}
constructor Create(AOwner : TComponent);
override;
{.Z-}
procedure PopupClose(Sender : TObject);
override;
procedure PopupOpen;
override;
property AsInteger : LongInt
read GetAsInteger
write SetAsInteger;
{public properties}
property Calculator : TOvcCalculator
read FCalculator;
property AsFloat : Double
read GetAsFloat write SetAsFloat;
property AsString : string
read GetAsString write SetAsString;
end;
TOvcNumberEdit = class(TOvcCustomNumberEdit)
published
{properties}
{$IFDEF VERSION4}
property Anchors;
property Constraints;
property DragKind;
{$ENDIF}
property About;
property AllowIncDec;
{$IFNDEF LCL}
property AutoSelect;
{$ENDIF}
property AutoSize;
property BorderStyle;
property ButtonGlyph;
property Color;
property Ctl3D;
property Cursor;
property DragCursor;
property DragMode;
property Enabled;
property Font;
{$IFNDEF LCL}
property HideSelection;
{$ENDIF}
property LabelInfo;
property ParentColor;
{$IFNDEF LCL}
property ParentCtl3D;
{$ENDIF}
property ParentFont;
property ParentShowHint;
property PopupAnchor;
property PopupColors;
property PopupDecimals;
property PopupFont;
property PopupHeight;
property PopupWidth;
property PopupMenu;
property ReadOnly;
property ShowHint;
property ShowButton;
property TabOrder;
property TabStop;
property Visible;
{events}
property OnChange;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnPopupClose;
property OnPopupOpen;
property OnStartDrag;
end;
implementation
{*** TOvcCustomNumberEdit ***}
constructor TOvcCustomNumberEdit.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle - [csSetCaption];
FAllowIncDec := False;
{load button glyph}
{$IFNDEF LCL}
FButtonGlyph.Handle := LoadBaseBitmap('ORBTNCLC');
{$ELSE}
FButtonGlyph.LoadFromLazarusResource('ORBTNCLC');
{$ENDIF}
FButton.Glyph.Assign(FButtonGlyph);
FCalculator := TOvcCalculator.CreateEx(Self, True);
FCalculator.OnButtonPressed := PopupButtonPressed;
FCalculator.OnExit := PopupClose;
FCalculator.OnKeyDown := PopupKeyDown;
FCalculator.OnKeyPress := PopupKeyPress;
FCalculator.OnMouseDown := PopupMouseDown;
FCalculator.Visible := False; {to avoid flash at 0,0}
FCalculator.Options := [coShowItemCount];
FCalculator.BorderStyle := bsSingle;
FCalculator.ParentFont := False;
end;
procedure TOvcCustomNumberEdit.DoExit;
begin
if not PopupActive then
inherited DoExit;
end;
function TOvcCustomNumberEdit.GetAsFloat : Double;
var
I : Integer;
S : string;
begin
S := Text;
for I := Length(S) downto 1 do
if not (S[I] in ['0'..'9', '+', '-', DecimalSeparator]) then
Delete(S, I, 1);
Result := StrToFloat(S);
end;
function TOvcCustomNumberEdit.GetAsInteger : LongInt;
begin
Result := Round(GetAsFloat);
end;
function TOvcCustomNumberEdit.GetAsString : string;
begin
Result := Text;
end;
function TOvcCustomNumberEdit.GetPopupColors : TOvcCalcColors;
begin
Result := FCalculator.Colors;
end;
function TOvcCustomNumberEdit.GetPopupDecimals : Integer;
begin
Result := FCalculator.Decimals;
end;
function TOvcCustomNumberEdit.GetPopupFont : TFont;
begin
Result := FCalculator.Font;
end;
function TOvcCustomNumberEdit.GetPopupHeight : Integer;
begin
Result := FCalculator.Height;
end;
function TOvcCustomNumberEdit.GetPopupWidth : Integer;
begin
Result := FCalculator.Width;
end;
function TOvcCustomNumberEdit.GetReadOnly : Boolean;
begin
Result := inherited ReadOnly;
end;
procedure TOvcCustomNumberEdit.GlyphChanged;
begin
inherited GlyphChanged;
if FButtonGlyph.Empty then
{$IFNDEF LCL}
FButtonGlyph.Handle := LoadBaseBitmap('ORBTNCLC');
{$ELSE}
FButtonGlyph.LoadFromLazarusResource('ORBTNCLC');
{$ENDIF}
end;
procedure TOvcCustomNumberEdit.KeyDown(var Key : Word; Shift : TShiftState);
begin
inherited KeyDown(Key, Shift);
if (Key = VK_DOWN) and (ssAlt in Shift) then
PopupOpen;
end;
procedure TOvcCustomNumberEdit.KeyPress(var Key : Char);
var
D : Double;
X : Integer;
L : Integer;
begin
inherited KeyPress(Key);
if not ((Key = #22) or (Key = #3) or (Key = #24)) then begin
if not (Key in [#27, '0'..'9', '.', DecimalSeparator,
#8, '+', '-', '*', '/']) then begin
Key := #0;
{$IFNDEF LCL}
MessageBeep(0);
{$ENDIF}
Exit;
end;
{Disallow more than one DecimalSeparator in the number}
if (SelLength <> Length(Text))
and (Key = DecimalSeparator) and (Pos(DecimalSeparator, Text) > 0)
then begin
Key := #0;
{$IFNDEF LCL}
MessageBeep(0);
{$ENDIF}
Exit;
end;
if FAllowIncDec and (Key in ['+', '-']) then begin
if Text = '' then
Text := '0';
D := StrToFloat(Text);
X := SelStart;
L := SelLength;
if Key = '+' then
Text := FloatToStr(D+1)
else {'-'}
Text := FloatToStr(D-1);
SelStart := X;
SelLength := L;
Key := #0; {clear key}
end;
if (Key in ['+', '*', '/']) then begin
PopUpOpen;
FCalculator.KeyPress(Key);
Key := #0; {clear key}
end;
end;
end;
procedure TOvcCustomNumberEdit.PopupButtonPressed(Sender : TObject;
Button : TOvcCalculatorButton);
begin
case Button of
cbEqual :
begin
{get the current value}
Text := FloatToStr(FCalculator.DisplayValue);
Modified := True;
{hide the calculator}
PopupClose(Sender);
SetFocus;
SelStart := Length(Text);
SelLength := 0;
end;
end;
end;
procedure TOvcCustomNumberEdit.PopupClose(Sender : TObject);
begin
if not FCalculator.Visible then
Exit; {already closed, exit}
if PopupClosing then
Exit;
PopupClosing := True; {avoid recursion}
try
inherited PopupClose(Sender);
if GetCapture = FCalculator.Handle then
ReleaseCapture;
SetFocus;
FCalculator.Hide; {hide the calculator}
TForm(FCalculator.Parent).AutoScroll := WasAutoScroll;
Cursor := HoldCursor;
{change parentage so that we control the window handle destruction}
FCalculator.Parent := Self;
finally
PopupClosing := False;
end;
end;
procedure TOvcCustomNumberEdit.PopupKeyDown(Sender : TObject; var Key : Word; Shift : TShiftState);
var
X : Integer;
begin
case Key of
VK_TAB :
begin
if Shift = [ssShift] then begin
PopupClose(Sender);
PostMessage(Handle, WM_KeyDown, VK_TAB, Integer(ssShift));
end else if Shift = [] then begin
PopupClose(Sender);
PostMessage(Handle, WM_KeyDown, VK_TAB, 0);
end;
end;
VK_UP : if Shift = [ssAlt] then begin
PopupClose(Sender);
X := SelStart;
SetFocus;
SelStart := X;
SelLength := 0;
end;
end;
end;
procedure TOvcCustomNumberEdit.PopupKeyPress(Sender : TObject; var Key : Char);
var
X : Integer;
begin
case Key of
#27 :
begin
PopupClose(Sender);
X := SelStart;
SetFocus;
SelStart := X;
SelLength := 0;
end;
end;
end;
procedure TOvcCustomNumberEdit.PopupMouseDown(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
var
P : TPoint;
I : Integer;
begin
P := Point(X,Y);
if not PtInRect(FCalculator.ClientRect, P) then
PopUpClose(Sender);
{convert to our coordinate system}
P := ScreenToClient(FCalculator.ClientToScreen(P));
if PtInRect(ClientRect, P) then begin
I := SelStart;
SetFocus;
SelStart := I;
SelLength := 0;
end;
end;
procedure TOvcCustomNumberEdit.PopupOpen;
var
P : TPoint;
R : TRect;
{$IFDEF VERSION4}
{$IFNDEF LCL}
F : TCustomForm;
MonInfo : TMonitorInfo;
{$ENDIF}
{$ENDIF}
begin
if FCalculator.Visible then
Exit; {already popped up, exit}
inherited PopupOpen;
FCalculator.Parent := GetImmediateParentForm(Self);
if FCalculator.Parent is TForm then begin
WasAutoScroll := TForm(FCalculator.Parent).AutoScroll;
TForm(FCalculator.Parent).AutoScroll := False;
end;
{set 3d to be the same as our own}
{$IFNDEF LCL}
FCalculator.ParentCtl3D := False;
{$ENDIF}
FCalculator.Ctl3D := False;
{determine the proper position}
SystemParametersInfo(SPI_GETWORKAREA, 0, @R, 0);
{$IFDEF VERSION4}
{$IFNDEF LCL}
F := GetParentForm(Self);
if Assigned(F) then begin
FillChar(MonInfo, SizeOf(MonInfo), #0);
MonInfo.cbSize := SizeOf(MonInfo);
GetMonitorInfo(F.Monitor.Handle, @MonInfo);
R := MonInfo.rcWork;
end;
{$ENDIF}
{$ENDIF}
if FPopupAnchor = paLeft then
P := ClientToScreen(Point(-3, Height-4))
else {paRight}
P := ClientToScreen(Point(Width-FCalculator.Width-1, Height-2));
if not Ctl3D then begin
Inc(P.X, 3);
Inc(P.Y, 3);
end;
if P.Y + FCalculator.Height >= R.Bottom then
P.Y := P.Y - FCalculator.Height - Height;
if P.X + FCalculator.Width >= R.Right then
P.X := R.Right - FCalculator.Width - 1;
if P.X <= R.Left then
P.X := R.Left + 1;
{$IFNDEF LCL}
MoveWindow(FCalculator.Handle, P.X, P.Y, FCalculator.Width, FCalculator.Height, False);
{$ENDIF}
HoldCursor := Cursor;
Cursor := crArrow;
FCalculator.PressButton(cbClear);
FCalculator.Show;
FCalculator.Visible := True;
if Text <> '' then
FCalculator.PushOperand(AsFloat)
else
FCalculator.PushOperand(0);
FCalculator.SetFocus;
SetCapture(FCalculator.Handle);
end;
procedure TOvcCustomNumberEdit.SetAsFloat(Value : Double);
begin
Text := FloatToStr(Value);
end;
procedure TOvcCustomNumberEdit.SetAsInteger(Value : LongInt);
begin
Text := IntToStr(Value);
end;
procedure TOvcCustomNumberEdit.SetAsString(const Value : string);
begin
Text := Value;
end;
procedure TOvcCustomNumberEdit.SetPopupColors(Value : TOvcCalcColors);
begin
FCalculator.Colors := Value;
end;
procedure TOvcCustomNumberEdit.SetPopupDecimals(Value : Integer);
begin
FCalculator.Decimals := Value;
end;
procedure TOvcCustomNumberEdit.SetPopupFont(Value : TFont);
begin
if Assigned(Value) then
FCalculator.Font.Assign(Value);
end;
procedure TOvcCustomNumberEdit.SetPopupHeight(Value : Integer);
begin
FCalculator.Height := Value;
end;
procedure TOvcCustomNumberEdit.SetPopupWidth(Value : Integer);
begin
FCalculator.Width := Value;
end;
procedure TOvcCustomNumberEdit.SetReadOnly(Value : Boolean);
begin
inherited ReadOnly := Value;
FButton.Enabled := not ReadOnly;
end;
end.