
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@963 8e941d3f-bd1b-0410-a28a-d453659cc2b4
1129 lines
33 KiB
ObjectPascal
1129 lines
33 KiB
ObjectPascal
{*********************************************************}
|
|
{* OVCEDCAL.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 ovcedcal;
|
|
{-date edit field with popup calendar}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFNDEF LCL} Windows, Messages, {$ELSE} LclIntf, LMessages, LclType, MyMisc, {$ENDIF}
|
|
Buttons, Classes, Controls, Forms, Graphics, Menus,
|
|
StdCtrls, SysUtils, {$IFNDEF LCL} {$IFDEF VERSION4} MultiMon, {$ENDIF} {$ENDIF} OvcBase, OvcCal,
|
|
OvcConst, OvcData, OvcEdPop, OvcExcpt, OvcIntl, OvcMisc, OvcEditF, OvcDate;
|
|
|
|
type
|
|
TOvcDateOrder = (doMDY, doDMY, doYMD);
|
|
TOvcRequiredDateField = (rfYear, rfMonth, rfDay);
|
|
TOvcRequiredDateFields = set of TOvcRequiredDateField;
|
|
|
|
{Events}
|
|
TOvcGetDateEvent = procedure(Sender : TObject; var Value : string) of object;
|
|
TOvcPreParseDateEvent = procedure(Sender : TObject; var Value : string)
|
|
of object;
|
|
TOvcGetDateMaskEvent = procedure(Sender : TObject; var Mask : string)
|
|
of object;
|
|
|
|
TOvcCustomDateEdit = class(TOvcEdPopup)
|
|
protected {private}
|
|
{property variables}
|
|
FAllowIncDec : Boolean;
|
|
FCalendar : TOvcCalendar;
|
|
FDate : TDateTime;
|
|
FEpoch : Integer;
|
|
FForceCentury : Boolean;
|
|
FRequiredFields : TOvcRequiredDateFields;
|
|
FTodayString : string;
|
|
|
|
{event variables}
|
|
FOnGetDate : TOvcGetDateEvent;
|
|
FOnGetDateMask : TOvcGetDateMaskEvent;
|
|
FOnPreParseDate : TOvcPreParseDateEvent;
|
|
FOnSetDate : TNotifyEvent;
|
|
|
|
{internal variables}
|
|
DateOrder : TOvcDateOrder;
|
|
HoldCursor : TCursor;
|
|
PopupClosing : Boolean;
|
|
WasAutoScroll : Boolean;
|
|
|
|
{property methods}
|
|
function GetDate : TDateTime;
|
|
function GetEpoch : Integer;
|
|
function GetPopupColors : TOvcCalColors;
|
|
function GetPopupFont : TFont;
|
|
function GetPopupHeight : Integer;
|
|
function GetPopupDateFormat : TOvcDateFormat;
|
|
function GetPopupDayNameWidth : TOvcDayNameWidth;
|
|
function GetPopupOptions : TOvcCalDisplayOptions;
|
|
function GetPopupWeekStarts : TOvcDayType;
|
|
function GetPopupWidth : Integer;
|
|
function GetReadOnly : Boolean;
|
|
procedure SetEpoch(Value : Integer);
|
|
procedure SetForceCentury(Value : Boolean);
|
|
procedure SetPopupColors(Value : TOvcCalColors);
|
|
procedure SetPopupFont(Value : TFont);
|
|
procedure SetPopupHeight(Value : Integer);
|
|
procedure SetPopupWidth(Value : Integer);
|
|
procedure SetPopupDateFormat(Value : TOvcDateFormat);
|
|
procedure SetPopupDayNameWidth(Value : TOvcDayNameWidth);
|
|
procedure SetPopupOptions(Value : TOvcCalDisplayOptions);
|
|
procedure SetPopupWeekStarts(Value : TOvcDayType);
|
|
procedure SetReadOnly(Value : Boolean);
|
|
|
|
{internal methods}
|
|
function ParseDate(const Value : string) : string;
|
|
procedure PopupDateChange(Sender : TObject; Date : TDateTime);
|
|
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;
|
|
procedure SetDate(Value : TDateTime);
|
|
|
|
{protected properties}
|
|
property AllowIncDec : Boolean read FAllowIncDec write FAllowIncDec;
|
|
property Epoch : Integer read GetEpoch write SetEpoch;
|
|
property ForceCentury : Boolean read FForceCentury write SetForceCentury;
|
|
property PopupColors : TOvcCalColors read GetPopupColors
|
|
write SetPopupColors;
|
|
property PopupFont : TFont read GetPopupFont write SetPopupFont;
|
|
property PopupHeight : Integer read GetPopupHeight write SetPopupHeight;
|
|
property PopupWidth : Integer read GetPopupWidth write SetPopupWidth;
|
|
property PopupDateFormat : TOvcDateFormat read GetPopupDateFormat
|
|
write SetPopupDateFormat;
|
|
property PopupDayNameWidth : TOvcDayNameWidth read GetPopupDayNameWidth
|
|
write SetPopupDayNameWidth;
|
|
property PopupOptions : TOvcCalDisplayOptions read GetPopupOptions
|
|
write SetPopupOptions;
|
|
property PopupWeekStarts : TOvcDayType read GetPopupWeekStarts
|
|
write SetPopupWeekStarts;
|
|
property ReadOnly : Boolean read GetReadOnly write SetReadOnly;
|
|
property RequiredFields : TOvcRequiredDateFields read FRequiredFields
|
|
write FRequiredFields;
|
|
property TodayString : string read FTodayString write FTodayString;
|
|
|
|
{protected events}
|
|
property OnGetDate : TOvcGetDateEvent read FOnGetDate write FOnGetDate;
|
|
property OnGetDateMask : TOvcGetDateMaskEvent read FOnGetDateMask
|
|
write FOnGetDateMask;
|
|
property OnPreParseDate : TOvcPreParseDateEvent read FOnPreParseDate
|
|
write FOnPreParseDate;
|
|
property OnSetDate : TNotifyEvent read FOnSetDate write FOnSetDate;
|
|
|
|
public
|
|
constructor Create(AOwner : TComponent); override;
|
|
function DateString(const Mask : string) : string;
|
|
function FormatDate(Value : TDateTime) : string; dynamic;
|
|
procedure PopupClose(Sender : TObject); override;
|
|
procedure PopupOpen; override;
|
|
procedure SetDateText(Value : string); dynamic;
|
|
{public properties}
|
|
property Calendar : TOvcCalendar read FCalendar;
|
|
property Date: TDateTime read GetDate write SetDate;
|
|
end;
|
|
|
|
|
|
TOvcDateEdit = class(TOvcCustomDateEdit)
|
|
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 CharCase;
|
|
property Color;
|
|
property Controller;
|
|
property Ctl3D;
|
|
property Cursor;
|
|
property DragCursor;
|
|
property DragMode;
|
|
property Enabled;
|
|
property Epoch;
|
|
property Font;
|
|
property ForceCentury;
|
|
{$IFNDEF LCL}
|
|
property HideSelection;
|
|
{$ENDIF}
|
|
property LabelInfo;
|
|
property ParentColor;
|
|
{$IFNDEF LCL}
|
|
property ParentCtl3D;
|
|
{$ENDIF}
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupAnchor;
|
|
property PopupColors;
|
|
property PopupDateFormat;
|
|
property PopupDayNameWidth;
|
|
property PopupFont;
|
|
property PopupHeight;
|
|
property PopupMenu;
|
|
property PopupOptions;
|
|
property PopupWidth;
|
|
property PopupWeekStarts;
|
|
property ReadOnly;
|
|
property RequiredFields;
|
|
property ShowButton;
|
|
property ShowHint;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property TodayString;
|
|
property Visible;
|
|
|
|
{inherited events}
|
|
property OnChange;
|
|
property OnClick;
|
|
property OnDblClick;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnGetDate;
|
|
property OnGetDateMask;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnPopupClose;
|
|
property OnPopupOpen;
|
|
property OnPreParseDate;
|
|
property OnSetDate;
|
|
property OnStartDrag;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{*** TOvcCustomDateEdit ***}
|
|
|
|
constructor TOvcCustomDateEdit.Create(AOwner : TComponent);
|
|
var
|
|
C : array[0..1] of Char;
|
|
begin
|
|
inherited Create(AOwner);
|
|
|
|
ControlStyle := ControlStyle - [csSetCaption];
|
|
|
|
FAllowIncDec := True;
|
|
FForceCentury := False;
|
|
FRequiredFields := [rfMonth, rfDay];
|
|
FTodayString := DateSeparator;
|
|
|
|
{get the date order from windows}
|
|
C[0] := '0'; {default}
|
|
|
|
GetProfileString('intl', 'iDate', '0', C, 2);
|
|
DateOrder := TOvcDateOrder(Ord(C[0])-Ord('0'));
|
|
|
|
{load button glyph}
|
|
{$IFNDEF LCL}
|
|
FButtonGlyph.Handle := LoadBaseBitmap('ORBTNCAL');
|
|
{$ELSE}
|
|
FButtonGlyph.LoadFromLazarusResource('ORBTNCAL');
|
|
{$ENDIF}
|
|
FButton.Glyph.Assign(FButtonGlyph);
|
|
|
|
FCalendar := TOvcCalendar.CreateEx(Self, True);
|
|
FCalendar.OnChange := PopupDateChange;
|
|
FCalendar.OnExit := PopupClose;
|
|
FCalendar.OnKeyDown := PopupKeyDown;
|
|
FCalendar.OnKeyPress := PopupKeyPress;
|
|
FCalendar.OnMouseDown := PopupMouseDown;
|
|
FCalendar.Visible := False; {to avoid flash at 0,0}
|
|
FCalendar.BorderStyle := bsSingle;
|
|
FCalendar.ParentFont := False;
|
|
FCalendar.Parent := GetImmediateParentForm(Self);
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.DoExit;
|
|
begin
|
|
try
|
|
SetDateText(Text);
|
|
except
|
|
SetFocus;
|
|
raise;
|
|
end;
|
|
|
|
if not PopupActive then
|
|
inherited DoExit;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.DateString(const Mask : string) : string;
|
|
begin
|
|
Result := OvcIntlSup.DateToDateString(Mask, DateTimeToSTDate(Date), False);
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.FormatDate(Value : TDateTime) : string;
|
|
var
|
|
DateMask : string;
|
|
Mask : string;
|
|
begin
|
|
DateMask := OvcIntlSup.InternationalDate(FForceCentury);
|
|
if Assigned(FOnGetDateMask) then begin
|
|
FOnGetDateMask(Self, DateMask);
|
|
{see if the date order needs to be changed}
|
|
Mask := AnsiUpperCase(DateMask);
|
|
if (Pos('M', Mask) > Pos('Y', Mask)) or
|
|
(Pos('N', Mask) > Pos('Y', Mask)) then
|
|
DateOrder := doYMD
|
|
else if (Pos('M', Mask) > Pos('D', Mask)) or
|
|
(Pos('N', Mask) > Pos('D', Mask)) then
|
|
DateOrder := doDMY
|
|
else
|
|
DateOrder := doMDY;
|
|
end;
|
|
Result := OvcIntlSup.DateToDateString(DateMask, DateTimeToSTDate(Value), False);
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetDate : TDateTime;
|
|
begin
|
|
SetDateText(Text);
|
|
Result := FDate;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetEpoch : Integer;
|
|
begin
|
|
Result := FEpoch;
|
|
|
|
if (csWriting in ComponentState) then
|
|
Exit;
|
|
|
|
if (Result = 0) and ControllerAssigned then
|
|
Result := Controller.Epoch;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetPopupColors : TOvcCalColors;
|
|
begin
|
|
Result := FCalendar.Colors;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetPopupDateFormat : TOvcDateFormat;
|
|
begin
|
|
Result := FCalendar.DateFormat;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetPopupDayNameWidth : TOvcDayNameWidth;
|
|
begin
|
|
Result := FCalendar.DayNameWidth;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetPopupFont : TFont;
|
|
begin
|
|
Result := FCalendar.Font;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetPopupHeight : Integer;
|
|
begin
|
|
Result := FCalendar.Height;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetPopupOptions: TOvcCalDisplayOptions;
|
|
begin
|
|
Result := FCalendar.Options;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetPopupWeekStarts: TOvcDayType;
|
|
begin
|
|
Result := FCalendar.WeekStarts;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetPopupWidth : Integer;
|
|
begin
|
|
Result := FCalendar.Width;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.GetReadOnly : Boolean;
|
|
begin
|
|
Result := inherited ReadOnly;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.GlyphChanged;
|
|
begin
|
|
inherited GlyphChanged;
|
|
|
|
if FButtonGlyph.Empty then
|
|
{$IFNDEF LCL}
|
|
FButtonGlyph.Handle := LoadBaseBitmap('ORBTNCAL');
|
|
{$ELSE}
|
|
FButtonGlyph.LoadFromLazarusResource('ORBTNCAL');
|
|
{$ENDIF}
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.KeyDown(var Key : Word; Shift : TShiftState);
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
|
|
if ShowButton and (Key = VK_DOWN) and (ssAlt in Shift) then
|
|
PopupOpen;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.KeyPress(var Key : Char);
|
|
var
|
|
D : Word;
|
|
M : Word;
|
|
Y : Word;
|
|
begin
|
|
inherited KeyPress(Key);
|
|
|
|
if (ReadOnly) then Exit;
|
|
|
|
if FAllowIncDec and (Key in ['+', '-']) then begin
|
|
{accept current date}
|
|
DoExit;
|
|
if FDate = 0 then
|
|
DecodeDate(SysUtils.Date, Y, M, D)
|
|
else
|
|
DecodeDate(FDate, Y, M, D);
|
|
if Key = '+' then begin
|
|
Inc(D);
|
|
if D > DaysInMonth(M, Y, Epoch) then begin
|
|
D := 1;
|
|
Inc(M);
|
|
if M > 12 then begin
|
|
Inc(Y);
|
|
M := 1;
|
|
end;
|
|
end;
|
|
end else begin
|
|
{Key = '-'}
|
|
Dec(D);
|
|
if D < 1 then begin
|
|
Dec(M);
|
|
if M < 1 then begin
|
|
M := 12;
|
|
Dec(Y);
|
|
end;
|
|
D := DaysInMonth(M, Y, Epoch);
|
|
end;
|
|
end;
|
|
SetDate(STDateToDateTime(DMYToSTDate(D, M, Y, Epoch)));
|
|
|
|
{clear}
|
|
Key := #0;
|
|
end;
|
|
end;
|
|
|
|
function TOvcCustomDateEdit.ParseDate(const Value : string) : string;
|
|
var
|
|
S : string;
|
|
ThisYear : Word;
|
|
ThisMonth : Word;
|
|
ThisDay : Word;
|
|
DefaultDate : TStDate;
|
|
Increment : Integer;
|
|
Occurrence : Integer;
|
|
StartDate : TStDate;
|
|
|
|
procedure DoSetDate;
|
|
var
|
|
I : integer;
|
|
D : TStDate;
|
|
DOW : TStDayType;
|
|
begin
|
|
D := StartDate;
|
|
DOW := DayofWeek(DateTimeToStDate(SysUtils.Date));
|
|
if Pos(AnsiUppercase(Copy(LongDayNames[1],1,3)), S) > 0 then begin
|
|
DOW := Sunday;
|
|
end else if Pos(AnsiUppercase(Copy(LongDayNames[2],1,3)), S) > 0 then begin
|
|
DOW := Monday;
|
|
end else if Pos(AnsiUppercase(Copy(LongDayNames[3],1,3)), S) > 0 then begin
|
|
DOW := Tuesday;
|
|
end else if Pos(AnsiUppercase(Copy(LongDayNames[4],1,3)), S) > 0 then begin
|
|
DOW := Wednesday;
|
|
end else if Pos(AnsiUppercase(Copy(LongDayNames[5],1,3)), S) > 0 then begin
|
|
DOW := Thursday;
|
|
end else if Pos(AnsiUppercase(Copy(LongDayNames[6],1,3)), S) > 0 then begin
|
|
DOW := Friday;
|
|
end else if Pos(AnsiUppercase(Copy(LongDayNames[7],1,3)), S) > 0 then begin
|
|
DOW := Saturday;
|
|
end else begin
|
|
if DefaultDate > 0 then begin
|
|
D := DefaultDate;
|
|
Occurrence := 0;
|
|
end else if DefaultDate < 0 then begin
|
|
Result := S;
|
|
exit;
|
|
end;
|
|
end;
|
|
I := 0;
|
|
while I < Occurrence do begin
|
|
D := D + Increment;
|
|
if DayOfWeek(D) = DOW then begin
|
|
inc(I);
|
|
end;
|
|
end;
|
|
Result := FormatDate(StDateToDateTime(D));
|
|
end;
|
|
|
|
begin
|
|
{The following code provides the user the ability to enter dates
|
|
using text descriptions. All descriptions assume the current
|
|
date as a reference date. The following descriptions are currently
|
|
supported:
|
|
<day of week> Next is assumed; may be abbreviated -- 1st 3 chars
|
|
Next <day of week>
|
|
Last current day of week is assumed
|
|
Last <day of week>
|
|
First | 1st current day of week is assumed
|
|
First | 1st <day of week>
|
|
Second | 2nd current day of week is assumed
|
|
Second | 2nd <day of week>
|
|
Third | 3rd current day of week is assumed
|
|
Third | 3rd <day of week>
|
|
Fourth | 4th current day of week is assumed
|
|
Fourth | 4th <day of week>
|
|
Final | lst current day of week is assumed
|
|
Final | lst <day of week>
|
|
BOM | Begin returns first day of current month
|
|
EOM | End returns last day of current month
|
|
Yesterday returns yesterday's date
|
|
Today returns today's date
|
|
Tomorrow returns tomorrow's date}
|
|
|
|
S := AnsiUppercase(Value);
|
|
if Pos(GetOrphStr(SCCalYesterday), S) > 0 then begin
|
|
Result := FormatDate(StDateToDateTime(DateTimeToStDate(SysUtils.Date) - 1));
|
|
end else if Pos(GetOrphStr(SCCalToday), S) > 0 then begin
|
|
Result := FormatDate(StDateToDateTime(DateTimeToStDate(SysUtils.Date)));
|
|
end else if Pos(GetOrphStr(SCCalTomorrow), S) > 0 then begin
|
|
Result := FormatDate(StDateToDateTime(DateTimeToStDate(SysUtils.Date) + 1));
|
|
end else if Pos(GetOrphStr(SCCalNext), S) > 0 then begin
|
|
Increment := 1;
|
|
Occurrence := 1;
|
|
StartDate := DateTimeToStDate(SysUtils.Date);
|
|
DefaultDate := StartDate + 7;
|
|
DoSetDate;
|
|
end else if Pos(GetOrphStr(SCCalLast), S) > 0 then begin
|
|
Increment := -1;
|
|
Occurrence := 1;
|
|
StartDate := DateTimeToStDate(SysUtils.Date);
|
|
DefaultDate := StartDate - 7;
|
|
DoSetDate;
|
|
end else if Pos(GetOrphStr(SCCalPrev), S) > 0 then begin
|
|
Increment := -1;
|
|
Occurrence := 1;
|
|
StartDate := DateTimeToStDate(SysUtils.Date);
|
|
DefaultDate := StartDate - 7;
|
|
DoSetDate;
|
|
end else if (Pos(GetOrphStr(SCCalFirst), S) > 0)
|
|
or (Pos(GetOrphStr(SCCal1st), S) > 0) then begin
|
|
Increment := 1;
|
|
Occurrence := 1;
|
|
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
|
|
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch) - 1;
|
|
DefaultDate := 0;
|
|
DoSetDate;
|
|
end else if (Pos(GetOrphStr(SCCalSecond), S) > 0)
|
|
or (Pos(GetOrphStr(SCCal2nd), S) > 0) then begin
|
|
Increment := 1;
|
|
Occurrence := 2;
|
|
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
|
|
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch) - 1;
|
|
DefaultDate := 0;
|
|
DoSetDate;
|
|
end else if (Pos(GetOrphStr(SCCalThird), S) > 0)
|
|
or (Pos(GetOrphStr(SCCal3rd), S) > 0) then begin
|
|
Increment := 1;
|
|
Occurrence := 3;
|
|
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
|
|
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch) - 1;
|
|
DefaultDate := 0;
|
|
DoSetDate;
|
|
end else if (Pos(GetOrphStr(SCCalFourth), S) > 0)
|
|
or (Pos(GetOrphStr(SCCal4th), S) > 0) then begin
|
|
Increment := 1;
|
|
Occurrence := 4;
|
|
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
|
|
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch) - 1;
|
|
DefaultDate := 0;
|
|
DoSetDate;
|
|
end else if Pos(GetOrphStr(SCCalFinal), S) > 0 then begin
|
|
Increment := -1;
|
|
Occurrence := 1;
|
|
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
|
|
StartDate := DMYToStDate(DaysInMonth(ThisMonth,
|
|
ThisYear, Epoch),
|
|
ThisMonth, ThisYear, Epoch) + 1;
|
|
DefaultDate := 0;
|
|
DoSetDate;
|
|
end else if (Pos(GetOrphStr(SCCalBOM), S) > 0)
|
|
or (Pos(GetOrphStr(SCCalBegin), S) > 0) then begin
|
|
Increment := 0;
|
|
Occurrence := 0;
|
|
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
|
|
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch);
|
|
DefaultDate := StartDate;
|
|
DoSetDate;
|
|
end else if (Pos(GetOrphStr(SCCalEOM), S) > 0)
|
|
or (Pos(GetOrphStr(SCCalEnd), S) > 0) then begin
|
|
Increment := 0;
|
|
Occurrence := 0;
|
|
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
|
|
StartDate := DMYToStDate(DaysInMonth(ThisMonth,
|
|
ThisYear, Epoch),
|
|
ThisMonth, ThisYear, Epoch);
|
|
DefaultDate := StartDate;
|
|
DoSetDate;
|
|
end else begin
|
|
Increment := 1;
|
|
Occurrence := 1;
|
|
StartDate := DateTimeToStDate(SysUtils.Date);
|
|
DefaultDate := -1;
|
|
DoSetDate;
|
|
end;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.PopupClose(Sender : TObject);
|
|
begin
|
|
if not FCalendar.Visible then
|
|
{already closed, exit}
|
|
Exit;
|
|
|
|
if PopupClosing then
|
|
Exit;
|
|
|
|
{avoid recursion}
|
|
PopupClosing := True;
|
|
|
|
try
|
|
inherited PopupClose(Sender);
|
|
|
|
if GetCapture = FCalendar.Handle then
|
|
ReleaseCapture;
|
|
|
|
SetFocus;
|
|
{hide the Calendar}
|
|
FCalendar.Hide;
|
|
if FCalendar.Parent is TForm then
|
|
TForm(FCalendar.Parent).AutoScroll := WasAutoScroll;
|
|
|
|
Cursor := HoldCursor;
|
|
|
|
{change parentage so that we control the window handle destruction}
|
|
FCalendar.Parent := Self;
|
|
finally
|
|
PopupClosing := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.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 :
|
|
begin
|
|
if Shift = [ssAlt] then begin
|
|
PopupClose(Sender);
|
|
X := SelStart;
|
|
SetFocus;
|
|
SelStart := X;
|
|
SelLength := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.PopupKeyPress(Sender : TObject; var Key : Char);
|
|
var
|
|
X : Integer;
|
|
begin
|
|
case Key of
|
|
#13,
|
|
#32,
|
|
#27 :
|
|
begin
|
|
PopupClose(Sender);
|
|
X := SelStart;
|
|
SetFocus;
|
|
SelStart := X;
|
|
SelLength := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.PopupMouseDown(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
|
|
var
|
|
P : TPoint;
|
|
I : Integer;
|
|
begin
|
|
P := Point(X,Y);
|
|
if not PtInRect(FCalendar.ClientRect, P) then
|
|
PopUpClose(Sender);
|
|
|
|
{convert to our coordinate system}
|
|
P := ScreenToClient(FCalendar.ClientToScreen(P));
|
|
|
|
if PtInRect(ClientRect, P) then begin
|
|
I := SelStart;
|
|
SetFocus;
|
|
SelStart := I;
|
|
SelLength := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.PopupOpen;
|
|
var
|
|
P : TPoint;
|
|
R : TRect;
|
|
{$IFDEF VERSION4}
|
|
{$IFNDEF LCL}
|
|
F : TCustomForm;
|
|
MonInfo : TMonitorInfo;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
begin
|
|
if FCalendar.Visible then
|
|
{already popped up, exit}
|
|
Exit;
|
|
|
|
inherited PopupOpen;
|
|
|
|
{force update of date}
|
|
DoExit;
|
|
|
|
FCalendar.Parent := GetParentForm(Self);
|
|
if FCalendar.Parent is TForm then begin
|
|
WasAutoScroll := TForm(FCalendar.Parent).AutoScroll;
|
|
TForm(FCalendar.Parent).AutoScroll := False;
|
|
end;
|
|
|
|
{set 3d to be the same as our own}
|
|
{$IFNDEF LCL}
|
|
FCalendar.ParentCtl3D := False;
|
|
{$ENDIF}
|
|
FCalendar.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-FCalendar.Width-1, Height-2));
|
|
if not Ctl3D then begin
|
|
Inc(P.X, 3);
|
|
Inc(P.Y, 3);
|
|
end;
|
|
if P.Y + FCalendar.Height >= R.Bottom then
|
|
P.Y := P.Y - FCalendar.Height - Height;
|
|
if P.X + FCalendar.Width >= R.Right then
|
|
P.X := R.Right - FCalendar.Width - 1;
|
|
if P.X <= R.Left then
|
|
P.X := R.Left + 1;
|
|
|
|
MoveWindow(FCalendar.Handle, P.X, P.Y, FCalendar.Width, FCalendar.Height, False);
|
|
|
|
if Text = '' then
|
|
FCalendar.Date := SysUtils.Date
|
|
else
|
|
FCalendar.Date := FDate;
|
|
|
|
HoldCursor := Cursor;
|
|
Cursor := crArrow;
|
|
FCalendar.Show;
|
|
FCalendar.SetFocus;
|
|
|
|
SetCapture(FCalendar.Handle);
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.PopupDateChange(Sender : TObject; Date : TDateTime);
|
|
begin
|
|
{get the current value}
|
|
SetDate(FCalendar.Date);
|
|
Modified := True;
|
|
|
|
if FCalendar.Browsing then
|
|
Exit;
|
|
|
|
{hide the Calendar}
|
|
PopupClose(Sender);
|
|
SetFocus;
|
|
SelStart := Length(Text);
|
|
SelLength := 0;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetDate(Value : TDateTime);
|
|
begin
|
|
FDate := Value;
|
|
Modified := True;
|
|
|
|
if FDate = 0 then
|
|
Text := ''
|
|
else
|
|
Text := FormatDate(FDate);
|
|
|
|
if Assigned(FOnSetDate) then
|
|
FOnSetDate(Self);
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetDateText(Value : string);
|
|
var
|
|
Field : Integer;
|
|
I1 : Integer;
|
|
I2 : Integer;
|
|
Error : Integer;
|
|
ThisYear : Word;
|
|
ThisMonth : Word;
|
|
ThisDay : Word;
|
|
Year : Word;
|
|
Month : Word;
|
|
Day : Word;
|
|
EpochYear : Integer;
|
|
EpochCent : Integer;
|
|
StringList : TStringList;
|
|
FieldOrder : string[3];
|
|
S : string;
|
|
begin
|
|
if Assigned(FOnPreParseDate) then
|
|
FOnPreParseDate(Self, Value);
|
|
Value := ParseDate(Value);
|
|
|
|
if Assigned(FOnGetDate) then
|
|
FOnGetDate(Self, Value);
|
|
|
|
if (Value = '') and (FRequiredFields <> []) then begin
|
|
FDate := 0;
|
|
Text := '';
|
|
Exit;
|
|
end;
|
|
|
|
if AnsiCompareText(Value, TodayString) = 0 then begin
|
|
SetDate(SysUtils.Date);
|
|
Text := FormatDate(FDate);
|
|
end else begin
|
|
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
|
|
Value := AnsiUpperCase(Value);
|
|
StringList := TStringList.Create;
|
|
try
|
|
{parse the string into subfields using a string list to hold the parts}
|
|
I1 := 1;
|
|
while (I1 <= Length(Value)) and not (Value[I1] in ['0'..'9', 'A'..'Z']) do
|
|
Inc(I1);
|
|
while I1 <= Length(Value) do begin
|
|
I2 := I1;
|
|
while (I2 <= Length(Value)) and (Value[I2] in ['0'..'9', 'A'..'Z']) do
|
|
Inc(I2);
|
|
StringList.Add(Copy(Value, I1, I2-I1));
|
|
while (I2 <= Length(Value)) and not (Value[I2] in ['0'..'9', 'A'..'Z']) do
|
|
Inc(I2);
|
|
I1 := I2;
|
|
end;
|
|
|
|
case DateOrder of
|
|
doMDY : FieldOrder := 'MDY';
|
|
doDMY : FieldOrder := 'DMY';
|
|
doYMD : FieldOrder := 'YMD';
|
|
end;
|
|
|
|
Year := 0;
|
|
Month := 0;
|
|
Day := 0;
|
|
Error := 0;
|
|
for Field := 1 to Length(FieldOrder) do begin
|
|
if StringList.Count > 0 then
|
|
S := StringList[0]
|
|
else
|
|
S := '';
|
|
|
|
case FieldOrder[Field] of
|
|
'M' :
|
|
begin
|
|
if (S = '') or (S[1] in ['0'..'9']) then begin
|
|
{numeric month}
|
|
try
|
|
if S = '' then
|
|
Month := 0
|
|
else
|
|
Month := StrToInt(S);
|
|
except
|
|
Month := 0;
|
|
{error converting month number}
|
|
Error := SCMonthConvertError;
|
|
end;
|
|
if not (Month in [1..12]) then
|
|
Month := 0;
|
|
end else begin
|
|
{one or more letters in month}
|
|
Month := 0;
|
|
I1 := 1;
|
|
S := Copy(S, 1, 3);
|
|
{error converting month name}
|
|
Error := SCMonthNameConvertError;
|
|
repeat
|
|
if S = AnsiUpperCase(Copy(ShortMonthNames[I1], 1, Length(S))) then begin
|
|
Month := I1;
|
|
I1 := 13;
|
|
Error := 0;
|
|
end else
|
|
Inc(I1);
|
|
until I1 = 13;
|
|
end;
|
|
|
|
if Month = 0 then begin
|
|
if rfMonth in FRequiredFields then
|
|
{month required}
|
|
Error := SCMonthRequired
|
|
else
|
|
Month := ThisMonth;
|
|
end else if StringList.Count > 0 then
|
|
StringList.Delete(0);
|
|
|
|
if Error > 0 then
|
|
Break;
|
|
end;
|
|
'Y' :
|
|
begin
|
|
try
|
|
if S = '' then
|
|
Year := 0
|
|
else
|
|
Year := StrToInt(S);
|
|
except
|
|
Year := 0;
|
|
{error converting year}
|
|
Error := SCYearConvertError;
|
|
end;
|
|
if (Epoch = 0) and (Year < 100) and (S <> '') then
|
|
{default to current century if Epoch is zero}
|
|
Year := Year + (ThisYear div 100 * 100)
|
|
else if (Epoch > 0) and (Year < 100) and (S <> '') then begin
|
|
{use epoch}
|
|
EpochYear := Epoch mod 100;
|
|
EpochCent := (Epoch div 100) * 100;
|
|
if (Year < EpochYear) then
|
|
Inc(Year,EpochCent+100)
|
|
else
|
|
Inc(Year,EpochCent);
|
|
end;
|
|
if Year = 0 then begin
|
|
if rfYear in FRequiredFields then
|
|
{year is required}
|
|
Error := SCYearRequired
|
|
else
|
|
Year := ThisYear;
|
|
end else if StringList.Count > 0 then
|
|
StringList.Delete(0);
|
|
if Error > 0 then
|
|
Break;
|
|
end;
|
|
'D' :
|
|
begin
|
|
try
|
|
if S = '' then
|
|
Day := 0
|
|
else
|
|
Day := StrToInt(S);
|
|
except
|
|
Day := 0;
|
|
{error converting day}
|
|
Error := SCDayConvertError;
|
|
end;
|
|
if not (Day in [1..31]) then
|
|
Day := 0;
|
|
if Day = 0 then begin
|
|
if rfDay in FRequiredFields then
|
|
{day is required}
|
|
Error := SCDayRequired
|
|
else
|
|
Day := ThisDay;
|
|
end
|
|
else if StringList.Count > 0 then
|
|
StringList.Delete(0);
|
|
|
|
if Error > 0 then
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
case Error of
|
|
SCDayConvertError :
|
|
if S = '' then
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidDay) + ' "' + Value + '"')
|
|
else
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidDay) + ' "' + S + '"');
|
|
SCMonthConvertError :
|
|
if S = '' then
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidMonth) + ' "' + Value + '"')
|
|
else
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidMonth) + ' "' + S + '"');
|
|
SCMonthNameConvertError :
|
|
if S = '' then
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidMonthName) + ' "' + Value + '"')
|
|
else
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidMonthName) + ' "' + S + '"');
|
|
SCYearConvertError :
|
|
if S = '' then
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidYear) + ' "' + Value + '"')
|
|
else
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidYear) + ' "' + S + '"');
|
|
SCDayRequired :
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCDayRequired));
|
|
SCMonthRequired :
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCMonthRequired));
|
|
SCYearRequired :
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCYearRequired));
|
|
end;
|
|
|
|
try
|
|
SetDate(STDatetoDateTime(DMYToStDate(Day, Month, Year, Epoch)));
|
|
Text := FormatDate(FDate);
|
|
except
|
|
raise EOvcException.Create(
|
|
GetOrphStr(SCInvalidDate) + ' "' + Value + '"');
|
|
end;
|
|
|
|
finally
|
|
StringList.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetEpoch(Value : Integer);
|
|
begin
|
|
if Value <> FEpoch then
|
|
if (Value = 0) or ((Value >= MinYear) and (Value <= MaxYear)) then
|
|
FEpoch := Value;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetForceCentury(Value : Boolean);
|
|
begin
|
|
if Value <> FForceCentury then begin
|
|
FForceCentury := Value;
|
|
SetDate(FCalendar.Date);
|
|
end;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetPopupColors(Value : TOvcCalColors);
|
|
begin
|
|
FCalendar.Colors := Value;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetPopupDateFormat(Value : TOvcDateFormat);
|
|
begin
|
|
FCalendar.DateFormat := Value;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetPopupFont(Value : TFont);
|
|
begin
|
|
if Assigned(Value) then
|
|
FCalendar.Font.Assign(Value);
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetPopupHeight(Value : Integer);
|
|
begin
|
|
FCalendar.Height := Value;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetPopupDayNameWidth(Value : TOvcDayNameWidth);
|
|
begin
|
|
FCalendar.DayNameWidth := Value;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetPopupOptions(Value : TOvcCalDisplayOptions);
|
|
begin
|
|
FCalendar.Options := Value;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetPopupWidth(Value : Integer);
|
|
begin
|
|
FCalendar.Width := Value;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetPopupWeekStarts(Value : TOvcDayType);
|
|
begin
|
|
FCalendar.WeekStarts := Value;
|
|
end;
|
|
|
|
procedure TOvcCustomDateEdit.SetReadOnly(Value : Boolean);
|
|
begin
|
|
inherited ReadOnly := Value;
|
|
|
|
FButton.Enabled := not ReadOnly;
|
|
end;
|
|
|
|
end.
|