summaryrefslogtreecommitdiff
path: root/src/gui/fpg_spinedit.pas
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/fpg_spinedit.pas')
-rw-r--r--src/gui/fpg_spinedit.pas881
1 files changed, 881 insertions, 0 deletions
diff --git a/src/gui/fpg_spinedit.pas b/src/gui/fpg_spinedit.pas
new file mode 100644
index 00000000..19b36a84
--- /dev/null
+++ b/src/gui/fpg_spinedit.pas
@@ -0,0 +1,881 @@
+{
+ fpGUI - Free Pascal GUI Toolkit
+
+ Copyright (C) 2006 - 2008 See the file AUTHORS.txt, included in this
+ distribution, for details of the copyright.
+
+ See the file COPYING.modifiedLGPL, included in this distribution,
+ for details about redistributing fpGUI.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Description:
+ Defines a spinedit control.
+}
+
+unit fpg_spinedit;
+
+{$mode objfpc}{$H+}
+
+{
+ *****************************************************************
+ ********** This is still under heavy development! ***********
+ *****************************************************************
+}
+
+{ TODO : Base classes need to be abstracted from final classes. }
+{ TODO : Up/Down keyboard input needs to be corrected. }
+{ TODO : Step size needs to be implemented (small and large) }
+{ TODO : PgUp/PgDn keyboard needs to be supported. }
+{ TODO : Improve Timer and Step support. If the mouse is kept down on
+ a button, it should increment by small steps. After as certain
+ period, it should start inrementing by large steps. }
+{ TODO : Text cursor positioning should be fixed. }
+
+interface
+
+uses
+ Classes,
+ SysUtils,
+ fpg_base,
+ fpg_main,
+ fpg_widget,
+ fpg_panel,
+ fpg_edit,
+ fpg_button;
+
+type
+
+ { TfpgSpinEdit }
+
+ TfpgAbstractSpinEdit = class(TfpgBevel)
+ private
+ FButtonUp: TfpgButton;
+ FButtonDown: TfpgButton;
+ FArrowUpColor: Tfpgcolor;
+ FArrowDownColor: Tfpgcolor;
+ FTimer: TfpgTimer;
+ FUp: Boolean;
+ FDown: Boolean;
+ protected
+ FButtonWidth: integer;
+ function GetButtonsBackgroundColor: TfpgColor;
+ procedure SetButtonsBackgroundColor(const AValue: Tfpgcolor);
+ procedure SetArrowUpColor(const AValue: Tfpgcolor);
+ procedure SetArrowDownColor(const AValue: Tfpgcolor);
+ procedure ButtonUpPaint(Sender: TObject);
+ procedure ButtonDownPaint(Sender: TObject);
+ property ButtonsBackgroundColor: Tfpgcolor read GetButtonsBackgroundColor write SetButtonsBackgroundColor default clButtonFace;
+ property ArrowUpColor: TfpgColor read FArrowUpColor write SetArrowUpColor;
+ property ArrowDownColor: TfpgColor read FArrowDownColor write SetArrowDownColor;
+ public
+ constructor Create(AOwner: TComponent); override;
+ end;
+
+
+ TfpgSpinEditFloat = class(TfpgAbstractSpinEdit)
+ private
+ FEdit: TfpgEditFloat;
+ FMaxValue: extended;
+ FMinValue: extended;
+ FIncrement: extended;
+ FValue: extended;
+ procedure EnableButtons;
+ protected
+ function GetEditBackgroundColor: TfpgColor;
+ function GetTextColor: TfpgColor;
+ function GetNegativeColor: TfpgColor;
+ function GetFontDesc: string;
+ function GetDecimals: integer;
+ function GetFixedDecimals: Boolean;
+ procedure SetEditBackgroundColor(const AValue: Tfpgcolor);
+ procedure SetTextColor(const AValue: Tfpgcolor);
+ procedure SetNegativeColor(const AValue: Tfpgcolor);
+ procedure SetFontDesc(const AValue: string);
+ procedure SetMaxValue(const AValue: extended);
+ procedure SetMinValue(const AValue: extended);
+ procedure SetIncrement(const AValue: extended);
+ procedure SetValue(const AValue: extended);
+ procedure SetDecimals(const AValue: integer);
+ procedure SetFixedDecimals(const AValue: Boolean);
+ procedure ButtonUpClick(Sender: TObject);
+ procedure ButtonDownClick(Sender: TObject);
+ procedure ButtonUpMouseDown(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+ procedure ButtonUpMouseUp(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+ procedure ButtonDownMouseDown(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+ procedure ButtonDownMouseUp(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+ procedure EditKeyPress(Sender: TObject; var keycode: word; var shiftstate: TShiftState; var consumed: Boolean);
+ procedure EditExit(Sender: TObject);
+ procedure TimerStep(Sender: TObject);
+ public
+ constructor Create(AOwner: TComponent); override;
+ published
+ property EditBackgroundColor: Tfpgcolor read GetEditBackgroundColor write SetEditBackgroundColor default clBoxColor;
+ property ButtonsBackgroundColor;
+ property TextColor: Tfpgcolor read GetTextColor write SetTextColor;
+ property NegativeColor: TfpgColor read GetNegativeColor write SetNegativeColor;
+ property ArrowUpColor;
+ property ArrowDownColor;
+ property FontDesc: string read GetFontDesc write SetFontDesc;
+ property MaxValue: extended read FMaxValue write SetMaxValue;
+ property MinValue: extended read FMinValue write SetMinValue;
+ property Increment: extended read FIncrement write SetIncrement;
+ property Value: extended read FValue write SetValue;
+ property Decimals: integer read GetDecimals write SetDecimals;
+ property FixedDecimals: Boolean read GetFixedDecimals write SetFixedDecimals;
+ end;
+
+
+ TfpgSpinEdit = class(TfpgAbstractSpinEdit)
+ private
+ FEdit: TfpgEditInteger;
+ FMaxValue: integer;
+ FMinValue: integer;
+ FIncrement: integer;
+ FValue: integer;
+ procedure EnableButtons;
+ protected
+ function GetEditBackgroundColor: TfpgColor;
+ function GetTextColor: TfpgColor;
+ function GetNegativeColor: TfpgColor;
+ function GetFontDesc: string;
+ procedure SetEditBackgroundColor(const AValue: Tfpgcolor);
+ procedure SetTextColor(const AValue: Tfpgcolor);
+ procedure SetNegativeColor(const AValue: Tfpgcolor);
+ procedure SetFontDesc(const AValue: string);
+ procedure SetMaxValue(const AValue: integer);
+ procedure SetMinValue(const AValue: integer);
+ procedure SetIncrement(const AValue: integer);
+ procedure SetValue(const AValue: integer);
+ procedure ButtonUpClick(Sender: TObject);
+ procedure ButtonDownClick(Sender: TObject);
+ procedure ButtonUpMouseDown(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+ procedure ButtonUpMouseUp(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+ procedure ButtonDownMouseDown(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+ procedure ButtonDownMouseUp(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+ procedure EditKeyPress(Sender: TObject; var keycode: word; var shiftstate: TShiftState; var consumed: Boolean);
+ procedure EditExit(Sender: TObject);
+ procedure TimerStep(Sender: TObject);
+ public
+ constructor Create(AOwner: TComponent); override;
+ published
+ property EditBackgroundColor: Tfpgcolor read GetEditBackgroundColor write SetEditBackgroundColor default clBoxColor;
+ property ButtonsBackgroundColor;
+ property TextColor: Tfpgcolor read GetTextColor write SetTextColor;
+ property NegativeColor: TfpgColor read GetNegativeColor write SetNegativeColor;
+ property ArrowUpColor;
+ property ArrowDownColor;
+ property FontDesc: string read GetFontDesc write SetFontDesc;
+ property MaxValue: integer read FMaxValue write SetMaxValue;
+ property MinValue: integer read FMinValue write SetMinValue;
+ property Increment: integer read FIncrement write SetIncrement;
+ property Value: integer read FValue write SetValue;
+ end;
+
+
+function CreateSpinEditFloat(AOwner: TComponent; x, y, w, h: TfpgCoord; AMinValue: extended = 0; AMaxValue: extended = 100; AIncrement: extended = 1; ADecimals: integer = 1; AValue: extended = 0): TfpgSpinEditFloat;
+function CreateSpinEdit(AOwner: TComponent; x, y, w, h: TfpgCoord; AMinValue: integer = 0; AMaxValue: integer = 100; AIncrement: integer = 1; AValue: integer = 0): TfpgSpinEdit;
+
+
+implementation
+
+
+function CreateSpinEditFloat(AOwner: TComponent; x, y, w, h: TfpgCoord; AMinValue: extended = 0; AMaxValue: extended = 100; AIncrement: extended = 1; ADecimals: integer = 1; AValue: extended = 0): TfpgSpinEditFloat;
+begin
+ Result := TfpgSpinEditFloat.Create(AOwner);
+ Result.Left := x;
+ Result.Top := y;
+ Result.Width := w;
+ if h < Result.FEdit.Font.Height + 6 then
+ Result.Height := Result.FEdit.Font.Height + 6
+ else
+ Result.Height := h;
+ Result.FEdit.Height := Result.Height;
+ Result.FEdit.Width := Result.Width - Result.FButtonWidth;
+ Result.FButtonUp.Left := Result.Width - Result.FButtonWidth;
+ Result.FButtonDown.Left := Result.Width - Result.FButtonWidth;
+ if AMaxValue > AMinValue then
+ begin
+ Result.MinValue := AMinValue;
+ Result.MaxValue := AMaxValue;
+ end;
+ Result.Increment := AIncrement;
+ Result.FEdit.Decimals := ADecimals;
+ if (AValue <= Result.MaxValue) and (AValue >= Result.MinValue) then
+ Result.Value := AValue;
+end;
+
+function CreateSpinEdit(AOwner: TComponent; x, y, w, h: TfpgCoord; AMinValue: integer = 0; AMaxValue: integer = 100; AIncrement: integer = 1; AValue: integer = 0): TfpgSpinEdit;
+begin
+ Result := TfpgSpinEdit.Create(AOwner);
+ Result.Left := x;
+ Result.Top := y;
+ Result.Width := w;
+ if h < Result.FEdit.Font.Height + 6 then
+ Result.Height := Result.FEdit.Font.Height + 6
+ else
+ Result.Height := h;
+ Result.FEdit.Height := Result.Height;
+ Result.FEdit.Width := Result.Width - Result.FButtonWidth;
+ Result.FButtonUp.Left := Result.Width - Result.FButtonWidth;
+ Result.FButtonDown.Left := Result.Width - Result.FButtonWidth;
+ if AMaxValue > AMinValue then
+ begin
+ Result.MinValue := AMinValue;
+ Result.MaxValue := AMaxValue;
+ end;
+ Result.Increment := AIncrement;
+ if (AValue <= Result.MaxValue) and (AValue >= Result.MinValue) then
+ Result.Value := AValue;
+end;
+
+
+{ TfpgAbstractSpinEdit }
+
+function TfpgAbstractSpinEdit.GetButtonsBackgroundColor: TfpgColor;
+begin
+ Result := FButtonUp.BackgroundColor;
+end;
+
+procedure TfpgAbstractSpinEdit.SetButtonsBackgroundColor(const AValue: Tfpgcolor);
+begin
+ if FButtonUp.BackgroundColor <> AValue then
+ begin
+ FButtonUp.BackgroundColor := AValue;
+ FButtonDown.BackgroundColor := AValue;
+ end;
+end;
+
+procedure TfpgAbstractSpinEdit.SetArrowUpColor(const AValue: Tfpgcolor);
+begin
+ if FArrowUpColor <> AValue then
+ FArrowUpColor := AValue;
+end;
+
+procedure TfpgAbstractSpinEdit.SetArrowDownColor(const AValue: Tfpgcolor);
+begin
+ if FArrowDownColor <> AValue then
+ FArrowDownColor := AValue;
+end;
+
+procedure TfpgAbstractSpinEdit.ButtonUpPaint(Sender: TObject);
+begin
+ if TfpgButton(Sender).Enabled then
+ TfpgButton(Sender).Canvas.SetColor(FArrowUpColor)
+ else
+ TfpgButton(Sender).Canvas.SetColor(clShadow1);
+
+ fpgStyle.DrawDirectionArrow(TfpgButton(Sender).Canvas, 0, 0, TfpgButton(Sender).Width - 3, TfpgButton(Sender).Height, adUp);
+end;
+
+procedure TfpgAbstractSpinEdit.ButtonDownPaint(Sender: TObject);
+begin
+ if TfpgButton(Sender).Enabled then
+ TfpgButton(Sender).Canvas.SetColor(FArrowDownColor)
+ else
+ TfpgButton(Sender).Canvas.SetColor(clShadow1);
+
+ fpgStyle.DrawDirectionArrow(TfpgButton(Sender).Canvas, 0, 0, TfpgButton(Sender).Width - 3, TfpgButton(Sender).Height, adDown);
+end;
+
+constructor TfpgAbstractSpinEdit.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FButtonWidth := 13; // width of spin buttons
+ Shape := bsSpacer;
+
+ FButtonUp := TfpgButton.Create(Self);
+ with FButtonUp do
+ begin
+ SetPosition(Width - FButtonWidth, 0, FButtonWidth, Height div 2);
+ Text := '';
+ BackgroundColor := clButtonFace;
+ Focusable := False;
+ OnPaint := @ButtonUpPaint;
+ end;
+ FArrowUpColor := clText1;
+ FButtonDown := TfpgButton.Create(Self);
+ with FButtonDown do
+ begin
+ SetPosition(Width - FButtonWidth, (Height div 2) + 1, FButtonWidth, (Height div 2) - 1);
+ Text := '';
+ BackgroundColor := clButtonFace;
+ Focusable := False;
+ OnPaint := @ButtonDownPaint;
+ end;
+ FArrowDownColor := clText1;
+ FTimer := TfpgTimer.Create(200);
+ FTimer.Enabled := False;
+end;
+
+
+{ TfpgSpinEditFloat }
+
+procedure TfpgSpinEditFloat.EnableButtons;
+begin
+ if FValue + FIncrement < FMaxValue then
+ FButtonUp.Enabled := True
+ else
+ begin
+ FUp := False;
+ if Assigned(FTimer) then
+ FTimer.Enabled := False;
+ end;
+ if FValue - FIncrement > FMinValue then
+ FButtonDown.Enabled := True
+ else
+ begin
+ FDown := False;
+ if Assigned(FTimer) then
+ FTimer.Enabled := False;
+ end;
+end;
+
+function TfpgSpinEditFloat.GetEditBackgroundColor: TfpgColor;
+begin
+ Result := FEdit.BackgroundColor;
+end;
+
+function TfpgSpinEditFloat.GetTextColor: TfpgColor;
+begin
+ Result := FEdit.TextColor;
+end;
+
+function TfpgSpinEditFloat.GetNegativeColor: TfpgColor;
+begin
+ Result := FEdit.NegativeColor;
+end;
+
+function TfpgSpinEditFloat.GetFontDesc: string;
+begin
+ Result := FEdit.FontDesc;
+end;
+
+function TfpgSpinEditFloat.GetDecimals: integer;
+begin
+ Result := FEdit.Decimals;
+end;
+
+function TfpgSpinEditFloat.GetFixedDecimals: Boolean;
+begin
+ Result := FEdit.FixedDecimals;
+end;
+
+procedure TfpgSpinEditFloat.SetEditBackgroundColor(const AValue: Tfpgcolor);
+begin
+ if FEdit.BackgroundColor <> AValue then
+ FEdit.BackgroundColor := AValue;
+end;
+
+procedure TfpgSpinEditFloat.SetTextColor(const AValue: Tfpgcolor);
+begin
+ if FEdit.OldColor <> AValue then
+ FEdit.OldColor := AValue;
+end;
+
+procedure TfpgSpinEditFloat.SetNegativeColor(const AValue: Tfpgcolor);
+begin
+ if FEdit.NegativeColor <> AValue then
+ FEdit.NegativeColor := AValue;
+end;
+
+procedure TfpgSpinEditFloat.SetFontDesc(const AValue: string);
+begin
+ if FEdit.FontDesc <> AValue then
+ begin
+ FEdit.FontDesc := AValue;
+ if Height < FEdit.Height then
+ begin
+ Height := FEdit.Height;
+ FButtonUp.Height := Height div 2;
+ FButtonDown.Height := Height div 2;
+ FButtonDown.Top := FButtonUp.Height + 1;
+ end;
+ end;
+end;
+
+procedure TfpgSpinEditFloat.SetMaxValue(const AValue: extended);
+begin
+ if (FMaxValue <> AValue) and (AValue > FMinValue) then
+ begin
+ FMaxValue := AValue;
+ if FValue > FMaxValue then
+ begin
+ FValue := FMaxValue;
+ FEdit.Value := FValue;
+ end;
+ EnableButtons;
+ end;
+end;
+
+procedure TfpgSpinEditFloat.SetMinValue(const AValue: extended);
+begin
+ if (FMinValue <> AValue) and (AValue < FMinValue) then
+ begin
+ FMinValue := AValue;
+ if FValue < FMinValue then
+ begin
+ FValue := FMinValue;
+ FEdit.Value := FValue;
+ end;
+ EnableButtons;
+ end;
+end;
+
+procedure TfpgSpinEditFloat.SetIncrement(const AValue: extended);
+begin
+ if FIncrement <> AValue then
+ FIncrement := AValue;
+end;
+
+procedure TfpgSpinEditFloat.SetValue(const AValue: extended);
+begin
+ if (FValue <> AValue) and (AValue <= FMaxValue) and (AValue >= FMinValue) then
+ begin
+ FValue := AValue;
+ FEdit.Value := FValue;
+ EnableButtons;
+ end;
+end;
+
+procedure TfpgSpinEditFloat.SetDecimals(const AValue: integer);
+begin
+ if AValue < 0 then
+ Exit; // =>
+ if FEdit.Decimals <> AValue then
+ FEdit.Decimals := AValue;
+end;
+
+procedure TfpgSpinEditFloat.SetFixedDecimals(const AValue: Boolean);
+begin
+ if FEdit.FixedDecimals <> AValue then
+ FEdit.FixedDecimals := AValue;
+end;
+
+procedure TfpgSpinEditFloat.ButtonUpClick(Sender: TObject);
+begin
+ if FValue + FIncrement <= FMaxValue then
+ begin
+ FValue := FValue + FIncrement;
+ FEdit.Value := FValue;
+ end;
+ EnableButtons;
+end;
+
+procedure TfpgSpinEditFloat.ButtonDownClick(Sender: TObject);
+begin
+ if FValue - FIncrement >= FMinValue then
+ begin
+ FValue := FValue - FIncrement;
+ FEdit.Value := FValue;
+ end;
+ EnableButtons;
+end;
+
+procedure TfpgSpinEditFloat.ButtonUpMouseDown(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+begin
+ FUp := True;
+ FTimer.Enabled := True;
+end;
+
+procedure TfpgSpinEditFloat.ButtonUpMouseUp(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+begin
+ FUp := False;
+ if Assigned(FTimer) then
+ FTimer.Enabled := False;
+ if (FEdit.Value + FIncrement) > FMaxValue then
+ FButtonUp.Enabled := False;
+end;
+
+procedure TfpgSpinEditFloat.ButtonDownMouseDown(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+begin
+ FDown := True;
+ FTimer.Enabled := True;
+end;
+
+procedure TfpgSpinEditFloat.ButtonDownMouseUp(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+begin
+ FDown := False;
+ if Assigned(FTimer) then
+ FTimer.Enabled := False;
+ if (FEdit.Value - FIncrement) < FMinValue then
+ FButtonDown.Enabled := False;
+end;
+
+procedure TfpgSpinEditFloat.EditKeyPress(Sender: TObject; var keycode: word; var shiftstate: TShiftState; var consumed: Boolean);
+begin
+ if (KeyCode = KeyReturn) or (KeyCode = KeyPEnter) then
+ if FEdit.Text = '' then
+ begin
+ FValue := 0.0;
+ FEdit.Value := FValue;
+ end
+ else if (StrToFloat(FEdit.Text) <= FMaxValue) and (StrToFloat(FEdit.Text) >= FMinValue) then
+ FValue := StrToFloat(FEdit.Text)
+ else
+ FEdit.Value := FValue;
+
+ if KeyCode = KeyUp then
+ if FEdit.Value + Increment <= FMaxValue then
+ begin
+ FValue := FValue + FIncrement;
+ FEdit.Value := FValue;
+ end;
+
+ if KeyCode = KeyDown then
+ if FEdit.Value - Increment >= FMinValue then
+ begin
+ FValue := FValue - FIncrement;
+ FEdit.Value := FValue;
+ end;
+
+ if KeyCode = KeyPageUp then
+ begin
+ FValue := FMaxValue;
+ FEdit.Value := FValue;
+ end;
+
+ if KeyCode = KeyPageDown then
+ begin
+ FValue := FMinValue;
+ FEdit.Value := FValue;
+ end;
+
+ EnableButtons;
+end;
+
+procedure TfpgSpinEditFloat.EditExit(Sender: TObject);
+begin
+ if FEdit.Text = '' then
+ begin
+ FValue := 0.0;
+ FEdit.Value := FValue;
+ end
+ else if (StrToFloat(FEdit.Text) <= FMaxValue) and (StrToFloat(FEdit.Text) >= FMinValue) then
+ FValue := StrToFloat(FEdit.Text)
+ else
+ FEdit.Value := FValue;
+ EnableButtons;
+end;
+
+procedure TfpgSpinEditFloat.TimerStep(Sender: TObject);
+begin
+ if FUp then
+ if FValue + FIncrement <= FMaxValue then
+ begin
+ Value := FValue + FIncrement;
+ FEdit.Value := FValue;
+ end;
+ if FDown then
+ if FValue - FIncrement >= FMinValue then
+ begin
+ FValue := FValue - FIncrement;
+ FEdit.Value := FValue;
+ end;
+ EnableButtons;
+end;
+
+constructor TfpgSpinEditFloat.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ FEdit := CreateEditFloat(Self, 0, 0, Width - FButtonWidth, Height, False, 2);
+
+ FMaxValue := 100.0;
+ FMinValue := 0.0;
+ FIncrement := 1.0;
+ FValue := FMinValue;
+ FUp := False;
+ FDown := False;
+
+ FEdit.Decimals := 1;
+ FEdit.Value := FValue;
+
+ FButtonUp.OnClick := @ButtonUpClick;
+ FButtonDown.OnClick := @ButtonDownClick;
+ FButtonUp.OnMouseDown := @ButtonUpMouseDown;
+ FButtonUp.OnMouseUp := @ButtonUpMouseUp;
+ FButtonDown.OnMouseDown := @ButtonDownMouseDown;
+ FButtonDown.OnMouseUp := @ButtonDownMouseUp;
+ FEdit.OnKeyPress := @EditKeyPress;
+ FEdit.OnExit := @EditExit;
+ FTimer.OnTimer := @TimerStep;
+ EnableButtons;
+end;
+
+
+{ TfpgSpinEdit }
+
+procedure TfpgSpinEdit.EnableButtons;
+begin
+ if FValue + FIncrement < FMaxValue then
+ FButtonUp.Enabled := True
+ else
+ begin
+ FUp := False;
+ if Assigned(FTimer) then
+ FTimer.Enabled := False;
+ end;
+ if FValue - FIncrement > FMinValue then
+ FButtonDown.Enabled := True
+ else
+ begin
+ FDown := False;
+ if Assigned(FTimer) then
+ FTimer.Enabled := False;
+ end;
+end;
+
+function TfpgSpinEdit.GetEditBackgroundColor: TfpgColor;
+begin
+ Result := FEdit.BackgroundColor;
+end;
+
+function TfpgSpinEdit.GetTextColor: TfpgColor;
+begin
+ Result := FEdit.TextColor;
+end;
+
+function TfpgSpinEdit.GetNegativeColor: TfpgColor;
+begin
+ Result := FEdit.NegativeColor;
+end;
+
+function TfpgSpinEdit.GetFontDesc: string;
+begin
+ Result := FEdit.FontDesc;
+end;
+
+procedure TfpgSpinEdit.SetEditBackgroundColor(const AValue: Tfpgcolor);
+begin
+ if FEdit.BackgroundColor <> AValue then
+ FEdit.BackgroundColor := AValue;
+end;
+
+procedure TfpgSpinEdit.SetTextColor(const AValue: Tfpgcolor);
+begin
+ if FEdit.OldColor <> AValue then
+ FEdit.OldColor := AValue;
+end;
+
+procedure TfpgSpinEdit.SetNegativeColor(const AValue: Tfpgcolor);
+begin
+ if FEdit.NegativeColor <> AValue then
+ FEdit.NegativeColor := AValue;
+end;
+
+procedure TfpgSpinEdit.SetFontDesc(const AValue: string);
+begin
+ if FEdit.FontDesc <> AValue then
+ begin
+ FEdit.FontDesc := AValue;
+ if Height < FEdit.Height then
+ begin
+ Height := FEdit.Height;
+ FButtonUp.Height := Height div 2;
+ FButtonDown.Height := Height div 2;
+ FButtonDown.Top := FButtonUp.Height + 1;
+ end;
+ end;
+end;
+
+procedure TfpgSpinEdit.SetMaxValue(const AValue: integer);
+begin
+ if (FMaxValue <> AValue) and (AValue > FMinValue) then
+ begin
+ FMaxValue := AValue;
+ if FValue > FMaxValue then
+ begin
+ FValue := FMaxValue;
+ FEdit.Value := FValue;
+ ;
+ end;
+ EnableButtons;
+ end;
+end;
+
+procedure TfpgSpinEdit.SetMinValue(const AValue: integer);
+begin
+ if (FMinValue <> AValue) and (AValue < FMaxValue) then
+ begin
+ FMinValue := AValue;
+ if FValue < FMinValue then
+ begin
+ FValue := FMinValue;
+ FEdit.Value := FValue;
+ ;
+ end;
+ EnableButtons;
+ end;
+end;
+
+procedure TfpgSpinEdit.SetIncrement(const AValue: integer);
+begin
+ if FIncrement <> AValue then
+ FIncrement := AValue;
+end;
+
+procedure TfpgSpinEdit.SetValue(const AValue: integer);
+begin
+ if (FValue <> AValue) and (AValue <= FMaxValue) and (AValue >= FMinValue) then
+ begin
+ FValue := AValue;
+ FEdit.Value := FValue;
+ EnableButtons;
+ end;
+end;
+
+procedure TfpgSpinEdit.ButtonUpClick(Sender: TObject);
+begin
+ if FValue + FIncrement <= FMaxValue then
+ begin
+ Inc(FValue, FIncrement);
+ FEdit.Value := FValue;
+ end;
+ EnableButtons;
+end;
+
+procedure TfpgSpinEdit.ButtonDownClick(Sender: TObject);
+begin
+ if FValue - FIncrement >= FMinValue then
+ begin
+ Dec(FValue, FIncrement);
+ FEdit.Value := FValue;
+ end;
+ EnableButtons;
+end;
+
+procedure TfpgSpinEdit.ButtonUpMouseDown(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+begin
+ FUp := True;
+ FTimer.Enabled := True;
+end;
+
+procedure TfpgSpinEdit.ButtonUpMouseUp(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+begin
+ FUp := False;
+ if Assigned(FTimer) then
+ FTimer.Enabled := False;
+ if (FEdit.Value + FIncrement) > FMaxValue then
+ FButtonUp.Enabled := False;
+end;
+
+procedure TfpgSpinEdit.ButtonDownMouseDown(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+begin
+ FDown := True;
+ FTimer.Enabled := True;
+end;
+
+procedure TfpgSpinEdit.ButtonDownMouseUp(Sender: TObject; AButton: TMouseButton; AShift: TShiftState; const AMousePos: TPoint);
+begin
+ FDown := False;
+ if Assigned(FTimer) then
+ FTimer.Enabled := False;
+ if (FEdit.Value - FIncrement) < FMinValue then
+ FButtonDown.Enabled := False;
+end;
+
+procedure TfpgSpinEdit.EditKeyPress(Sender: TObject; var keycode: word; var shiftstate: TShiftState; var consumed: Boolean);
+begin
+ if (KeyCode = KeyReturn) or (KeyCode = KeyPEnter) then
+ if FEdit.Text = '' then
+ begin
+ FValue := 0;
+ FEdit.Value := FValue;
+ end
+ else if (StrToInt(FEdit.Text) <= FMaxValue) and (StrToInt(FEdit.Text) >= FMinValue) then
+ FValue := FEdit.Value
+ else
+ FEdit.Value := FValue;
+
+ if KeyCode = KeyUp then
+ if FEdit.Value + Increment <= FMaxValue then
+ begin
+ Inc(FValue, FIncrement);
+ FEdit.Value := FValue;
+ end;
+
+ if KeyCode = KeyDown then
+ if FEdit.Value - Increment >= FMinValue then
+ begin
+ Dec(FValue, FIncrement);
+ FEdit.Value := FValue;
+ end;
+
+ if KeyCode = KeyPageUp then
+ begin
+ FValue := FMaxValue;
+ FEdit.Value := FValue;
+ end;
+
+ if KeyCode = KeyPageDown then
+ begin
+ FValue := FMinValue;
+ FEdit.Value := FValue;
+ end;
+
+ EnableButtons;
+end;
+
+procedure TfpgSpinEdit.EditExit(Sender: TObject);
+begin
+ if FEdit.Text = '' then
+ begin
+ FValue := 0;
+ FEdit.Value := FValue;
+ end
+ else if (StrToInt(FEdit.Text) <= FMaxValue) and (StrToInt(FEdit.Text) >= FMinValue) then
+ FValue := FEdit.Value
+ else
+ FEdit.Value := FValue;
+ EnableButtons;
+end;
+
+procedure TfpgSpinEdit.TimerStep(Sender: TObject);
+begin
+ if FUp then
+ if FValue + FIncrement <= FMaxValue then
+ begin
+ Inc(FValue, FIncrement);
+ FEdit.Value := FValue;
+ end;
+ if FDown then
+ if FValue - FIncrement >= FMinValue then
+ begin
+ Dec(FValue, FIncrement);
+ FEdit.Value := FValue;
+ end;
+ EnableButtons;
+end;
+
+constructor TfpgSpinEdit.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ FEdit := CreateEditInteger(Self, 0, 0, Width - FButtonWidth, Height);
+
+ FMaxValue := 100;
+ FMinValue := 0;
+ FIncrement := 1;
+ FValue := FMinValue;
+ FUp := False;
+ FDown := False;
+
+ FEdit.Value := FValue;
+
+ FButtonUp.OnClick := @ButtonUpClick;
+ FButtonDown.OnClick := @ButtonDownClick;
+ FButtonUp.OnMouseDown := @ButtonUpMouseDown;
+ FButtonUp.OnMouseUp := @ButtonUpMouseUp;
+ FButtonDown.OnMouseDown := @ButtonDownMouseDown;
+ FButtonDown.OnMouseUp := @ButtonDownMouseUp;
+ FEdit.OnKeyPress := @EditKeyPress;
+ FEdit.OnExit := @EditExit;
+ FTimer.OnTimer := @TimerStep;
+ EnableButtons;
+end;
+
+end.
+