{********************************************************************} { } { Developer Express Visual Component Library } { ExpressScheduler } { } { Copyright (c) 2003-2009 Developer Express Inc. } { ALL RIGHTS RESERVED } { } { The entire contents of this file is protected by U.S. and } { International Copyright Laws. Unauthorized reproduction, } { reverse-engineering, and distribution of all or any portion of } { the code contained in this file is strictly prohibited and may } { result in severe civil and criminal penalties and will be } { prosecuted to the maximum extent possible under the law. } { } { RESTRICTIONS } { } { THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES } { (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE } { SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS } { LICENSED TO DISTRIBUTE THE EXPRESSSCHEDULER AND ALL ACCOMPANYING } { VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. } { } { THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED } { FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE } { COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE } { AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT } { AND PERMISSION FROM DEVELOPER EXPRESS INC. } { } { CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON } { ADDITIONAL RESTRICTIONS. } { } {********************************************************************} unit cxSchedulerRecurrenceEditor; {$I cxVer.inc} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, cxStyles, cxGraphics, cxEdit, cxControls, cxContainer, cxTextEdit, cxMaskEdit, cxDropDownEdit, cxCalendar, ComCtrls, cxLookAndFeelPainters, cxButtons, cxCheckBox, cxRadioGroup, cxSpinEdit, cxTimeEdit, cxGroupBox, cxSchedulerStorage, cxLookAndFeels, cxSchedulerUtils, cxDateUtils, cxSchedulerEventEditor, Menus; type { TcxSchedulerCustomRecurrenceEventEditor } TcxSchedulerCustomRecurrenceEventEditor = class(TcxSchedulerCustomEditorForm) private FNeedCheckLossOfExceptions: Boolean; procedure SetNeedCheckLossOfExceptions(AValue: Boolean); protected procedure SaveChanges; virtual; public constructor CreateEx(AEvent: TcxSchedulerControlEvent); override; property NeedCheckLossOfExceptions: Boolean read FNeedCheckLossOfExceptions write SetNeedCheckLossOfExceptions; end; { TcxSchedulerRecurrenceEventEditor } TcxSchedulerRecurrenceEventEditorForm = class(TcxSchedulerCustomRecurrenceEventEditor) gbTime: TcxGroupBox; lbStart: TLabel; lbEnd: TLabel; teStart: TcxTimeEdit; teEnd: TcxTimeEdit; gbPattern: TcxGroupBox; Bevel1: TBevel; pnlPeriodicity: TPanel; rbDaily: TcxRadioButton; rbWeekly: TcxRadioButton; rbMonthly: TcxRadioButton; rbYearly: TcxRadioButton; lbOfEvery: TLabel; lbMonths: TLabel; lbOfEvery1: TLabel; lbMonths1: TLabel; rbDay: TcxRadioButton; rbThe: TcxRadioButton; cbWeek: TcxComboBox; cbDay: TcxComboBox; lbWeeksOn: TLabel; lbRecurEvery: TLabel; cbDayOfWeek1: TcxCheckBox; cbDayOfWeek2: TcxCheckBox; cbDayOfWeek3: TcxCheckBox; cbDayOfWeek4: TcxCheckBox; cbDayOfWeek5: TcxCheckBox; cbDayOfWeek6: TcxCheckBox; cbDayOfWeek7: TcxCheckBox; lbOf: TLabel; rbEvery1: TcxRadioButton; rbThe1: TcxRadioButton; cbMonths: TcxComboBox; cbWeek1: TcxComboBox; cbDay1: TcxComboBox; cbMonths1: TcxComboBox; rbEvery: TcxRadioButton; rbEveryWeekday: TcxRadioButton; gbRange: TcxGroupBox; lbStart1: TLabel; lbOccurrences: TLabel; deStart: TcxDateEdit; rbNoEndDate: TcxRadioButton; rbEndAfter: TcxRadioButton; rbEndBy: TcxRadioButton; deEndBy: TcxDateEdit; btnOk: TcxButton; btnCancel: TcxButton; btnRemove: TcxButton; pcPattern: TPageControl; tsDaily: TTabSheet; lbDay: TLabel; tsYearly: TTabSheet; tsWeekly: TTabSheet; tsMonthly: TTabSheet; meDay: TcxMaskEdit; meNumOfWeek: TcxMaskEdit; meNumMonth1: TcxMaskEdit; meNumMonth: TcxMaskEdit; meDayOfMonth: TcxMaskEdit; meEndAfter: TcxMaskEdit; meNumOfDay: TcxMaskEdit; procedure SelectPeriodicityClick(Sender: TObject); procedure meEndAfterPropertiesChange(Sender: TObject); procedure deEndByPropertiesChange(Sender: TObject); procedure rbNoEndDateClick(Sender: TObject); procedure meEndAfterExit(Sender: TObject); procedure ValidateNumber(Sender: TObject); procedure meDayPropertiesChange(Sender: TObject); procedure rbEveryWeekdayClick(Sender: TObject); procedure SetDayRadioButtonChecked(Sender: TObject); procedure SetTheRadioButtonChecked(Sender: TObject); procedure deStartPropertiesEditValueChanged(Sender: TObject); procedure DoChange(Sender: TObject); procedure cbMonthsPropertiesChange(Sender: TObject); procedure cbWeek1PropertiesChange(Sender: TObject); procedure btnOkClick(Sender: TObject); procedure deEndByPropertiesEditValueChanged(Sender: TObject); procedure meEndAfterPropertiesEditValueChanged(Sender: TObject); private FLocked: Boolean; procedure FillDays; procedure FillMonths; procedure FillWeeks; function GetActivePattern: TcxRecurrence; function GetRecurrenceInfo: TcxSchedulerEventRecurrenceInfo; function GetDayOfWeekIndex: Integer; function GetMonthIndex: Integer; function GetNumber(const S: string): Integer; function GetWeekIndex: Integer; function IsValidDailyPattern: Boolean; function IsValidMonthlyPattern: Boolean; function IsValidWeeklyPattern: Boolean; function IsValidYearlyPattern: Boolean; procedure ResetDailyTab; procedure ResetMonthlyTab; procedure ResetWeeklyTab; procedure ResetYearlyTab; procedure SelectDaysOfWeek(ADays: TDays); procedure SetActivePattern(Value: TcxRecurrence); procedure SetDailyPatternFromEvent; procedure SetDateWithoutChangeEvent(AEdit: TcxDateEdit; ADate: TDateTime); procedure SetItemIndexWithoutChangeEvent(AEdit: TcxComboBox; AIndex: Integer); procedure SetMonthlyPatternFromEvent; procedure SetPatternFromEvent; procedure SetTextWithoutChangeEvent(AEdit: TcxMaskEdit; const AText: string); procedure SetupDaysOfWeek; procedure SetWeeklyPatternFromEvent; procedure SetYearlyPatternFromEvent; protected procedure ApplyChanges; override; function CheckLostExceptions: Boolean; procedure FillCombos; virtual; function GetFormColor: TColor; override; function GetRecurrenceInfoValidStatus: TcxRecurrenceValidStatus; procedure InitializeControls; override; function IsValid: Boolean; procedure LoadEventValuesIntoControls; override; procedure SaveEvent(AEvent: TcxSchedulerControlEvent); procedure SaveRecurrenceInfo(AInfo: TcxSchedulerEventRecurrenceInfo); virtual; procedure SaveDailyParams(AInfo: TcxSchedulerEventRecurrenceInfo); procedure SaveWeeklyParams(AInfo: TcxSchedulerEventRecurrenceInfo); procedure SaveMonthlyParams(AInfo: TcxSchedulerEventRecurrenceInfo); procedure SaveYearlyParams(AInfo: TcxSchedulerEventRecurrenceInfo); procedure SetCaptions; virtual; procedure SetEndAfter; procedure SetEndDate; procedure SetEventRecurrenceFinish; procedure SetReadOnly(AValue: Boolean); override; procedure UpdateEventValuesFromControls; override; procedure UpdateRange; property ActivePattern: TcxRecurrence read GetActivePattern write SetActivePattern; property Info: TcxSchedulerEventRecurrenceInfo read GetRecurrenceInfo; property Locked: Boolean read FLocked write FLocked; public property Event; property Modified; property NeedCheckLossOfExceptions; property ReadOnly; end; TcxSchedulerRecurrenceEventEditor = TcxSchedulerRecurrenceEventEditorForm; //workaround for Delphi 2005 TcxSchedulerRecurrenceEventEditorClass = class of TcxSchedulerCustomRecurrenceEventEditor; implementation uses cxSchedulerStrs, cxClasses, {$IFDEF DELPHI6}Variants, DateUtils, {$ENDIF} cxSchedulerDialogs; {$R *.dfm} function cxDayTypeFromType(AIndex: Integer): TcxDayType; begin if AIndex < 0 then AIndex := 0; Inc(AIndex); if AIndex >= Byte(cxdtSaturday) then Result := cxdtSaturday else Result := TcxDayType(AIndex); end; function cxDayNumberFromRange(AIndex: Integer): Integer; begin Result := AIndex + 1; end; { TcxSchedulerCustomRecurrenceEventEditor } constructor TcxSchedulerCustomRecurrenceEventEditor.CreateEx( AEvent: TcxSchedulerControlEvent); begin inherited CreateEx(AEvent); FNeedCheckLossOfExceptions := (Event.Pattern <> nil) and Event.Pattern.HasExceptions; end; procedure TcxSchedulerCustomRecurrenceEventEditor.SaveChanges; begin if Event.Pattern = nil then begin Event.EventType := etPattern; FModified := True; end else Event.EventType := etCustom; UpdateEventValuesFromControls; end; procedure TcxSchedulerCustomRecurrenceEventEditor.SetNeedCheckLossOfExceptions( AValue: Boolean); begin FNeedCheckLossOfExceptions := FNeedCheckLossOfExceptions and AValue; end; { TcxSchedulerRecurrenceEventEditor } procedure TcxSchedulerRecurrenceEventEditorForm.SelectPeriodicityClick( Sender: TObject); begin ActivePattern := TcxRecurrence(TcxRadioButton(Sender).Tag); end; procedure TcxSchedulerRecurrenceEventEditorForm.ApplyChanges; begin case ModalResult of mrOk: if not ReadOnly then SaveChanges; mrAbort: begin if not IsInternalActivate and (Event.Pattern <> nil) then Event.Pattern.DeleteExceptions; Event.EventType := etNone; FModified := True; end; mrCancel: if Event.Source = nil then Event.EventType := etNone; end; end; function TcxSchedulerRecurrenceEventEditorForm.CheckLostExceptions: Boolean; begin Result := not FNeedCheckLossOfExceptions or (MessageDlg(cxGetResourceString(@scxConfirmLostExceptions), mtWarning, [mbOK, mbCancel], 0) = mrOk); end; procedure TcxSchedulerRecurrenceEventEditorForm.FillCombos; begin FillDays; FillMonths; FillWeeks; end; function TcxSchedulerRecurrenceEventEditorForm.GetFormColor: TColor; begin Result := teStart.Style.LookAndFeel.Painter.DefaultSchedulerControlColor; end; function TcxSchedulerRecurrenceEventEditorForm.GetRecurrenceInfoValidStatus: TcxRecurrenceValidStatus; var AEvent: TcxSchedulerControlEvent; begin AEvent := TcxSchedulerControlEvent.Create(Event.Storage); try SaveEvent(AEvent); AEvent.EventType := etPattern; Result := AEvent.RecurrenceInfo.GetValidStatus; finally AEvent.Free; end; end; procedure TcxSchedulerRecurrenceEventEditorForm.InitializeControls; begin SetCaptions; FillCombos; FLocked := True; LoadEventValuesIntoControls; FLocked := False; end; function TcxSchedulerRecurrenceEventEditorForm.IsValid: Boolean; begin case ActivePattern of cxreDaily: Result := IsValidDailyPattern; cxreWeekly: Result := IsValidWeeklyPattern; cxreMonthly: Result := IsValidMonthlyPattern; else //cxreYearly Result := IsValidYearlyPattern; end; end; procedure TcxSchedulerRecurrenceEventEditorForm.LoadEventValuesIntoControls; function GetRecurrenceStartTime: TDateTime; begin if Event.Pattern <> nil then Result := TimeOf(Event.Pattern.Start) else Result := TimeOf(Event.Start); end; function GetRecurrenceEndTime: TDateTime; begin if Event.Pattern <> nil then Result := TimeOf(Event.Pattern.Finish) else Result := TimeOf(Event.Finish); end; function GetRecurrenceStartDate: TDateTime; begin if Event.Pattern <> nil then Result := DateOf(Event.Pattern.RecurrenceInfo.Start) else Result := DateOf(Event.RecurrenceInfo.Start); end; begin teStart.Time := GetRecurrenceStartTime; teEnd.Time := GetRecurrenceEndTime; SetDateWithoutChangeEvent(deStart, GetRecurrenceStartDate); SetPatternFromEvent; SetEventRecurrenceFinish; end; procedure TcxSchedulerRecurrenceEventEditorForm.SaveEvent( AEvent: TcxSchedulerControlEvent); begin if AEvent <> Event then AEvent.Assign(Event); SaveRecurrenceInfo(AEvent.RecurrenceInfo); end; procedure TcxSchedulerRecurrenceEventEditorForm.SaveRecurrenceInfo( AInfo: TcxSchedulerEventRecurrenceInfo); begin AInfo.Start := deStart.Date + teStart.Time; //correct finish time with AInfo.Event do Finish := DateOf(Finish) + teEnd.Time; AInfo.Recurrence := ActivePattern; if rbNoEndDate.Checked then AInfo.Count := -1 else if rbEndAfter.Checked then AInfo.Count := GetNumber(meEndAfter.Text) else begin AInfo.Count := 0; AInfo.Finish := deEndBy.Date; end; case ActivePattern of cxreDaily: SaveDailyParams(AInfo); cxreWeekly: SaveWeeklyParams(AInfo); cxreMonthly: SaveMonthlyParams(AInfo); cxreYearly: SaveYearlyParams(AInfo); end; if not Locked then AInfo.Validate; end; procedure TcxSchedulerRecurrenceEventEditorForm.SaveDailyParams( AInfo: TcxSchedulerEventRecurrenceInfo); begin if rbEvery.Checked then begin AInfo.DayType := cxdtEveryDay; AInfo.Periodicity := GetNumber(meDay.Text); end else begin AInfo.DayType := cxdtWeekDay; AInfo.Periodicity := 1; end; end; procedure TcxSchedulerRecurrenceEventEditorForm.SaveWeeklyParams( AInfo: TcxSchedulerEventRecurrenceInfo); procedure Check(ACheckBox: TcxCheckBox; var AOccurDays: TDays); begin if ACheckBox.Checked then Include(AOccurDays, TDay(ACheckBox.Tag - 1)); end; var AOccurDays: TDays; begin AInfo.Periodicity := GetNumber(meNumOfWeek.Text); AOccurDays := []; Check(cbDayOfWeek1, AOccurDays); Check(cbDayOfWeek2, AOccurDays); Check(cbDayOfWeek3, AOccurDays); Check(cbDayOfWeek4, AOccurDays); Check(cbDayOfWeek5, AOccurDays); Check(cbDayOfWeek6, AOccurDays); Check(cbDayOfWeek7, AOccurDays); AInfo.OccurDays := AOccurDays; end; procedure TcxSchedulerRecurrenceEventEditorForm.SaveMonthlyParams( AInfo: TcxSchedulerEventRecurrenceInfo); begin if rbDay.Checked then begin AInfo.DayType := cxdtDay; AInfo.DayNumber := GetNumber(meNumOfDay.Text); AInfo.Periodicity := GetNumber(meNumMonth.Text);; end else begin AInfo.DayType := cxDayTypeFromType(cbDay.ItemIndex); AInfo.DayNumber := cxDayNumberFromRange(cbWeek.ItemIndex); AInfo.Periodicity := GetNumber(meNumMonth1.Text); end; end; procedure TcxSchedulerRecurrenceEventEditorForm.SaveYearlyParams( AInfo: TcxSchedulerEventRecurrenceInfo); begin if rbEvery1.Checked then begin AInfo.DayType := cxdtDay; AInfo.Periodicity := cbMonths.ItemIndex + 1; AInfo.DayNumber := GetNumber(meDayOfMonth.Text); end else begin AInfo.DayType := cxDayTypeFromType(cbDay1.ItemIndex); AInfo.DayNumber := cxDayNumberFromRange(cbWeek1.ItemIndex); AInfo.Periodicity := cbMonths1.ItemIndex + 1; end; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetCaptions; begin Caption := cxGetResourceString(@scxRecurrenceCaption); // time gbTime.Caption := cxGetResourceString(@scxEventTime); lbStart.Caption := cxGetResourceString(@scxStart); lbEnd.Caption := cxGetResourceString(@scxEnd); // pattern gbPattern.Caption := cxGetResourceString(@scxRecurrencePattern); rbDaily.Caption := cxGetResourceString(@scxDaily); rbWeekly.Caption := cxGetResourceString(@scxWeekly); rbMonthly.Caption := cxGetResourceString(@scxMonthly); rbYearly.Caption := cxGetResourceString(@scxYearly); // daily rbEvery.Caption := cxGetResourceString(@scxEvery); rbEveryWeekday.Caption := cxGetResourceString(@scxEveryWeekDay); lbDay.Caption := cxGetResourceString(@scxDay1); // weekly lbRecurEvery.Caption := cxGetResourceString(@scxRecurEvery); lbWeeksOn.Caption := cxGetResourceString(@scxWeeksOn); SetupDaysOfWeek; // mothly lbOfEvery.Caption := cxGetResourceString(@scxOfEvery); lbOfEvery1.Caption := lbOfEvery.Caption; lbMonths.Caption := cxGetResourceString(@scxMonths); lbMonths1.Caption := lbMonths.Caption; rbDay.Caption := cxGetResourceString(@scxDay); rbThe.Caption := cxGetResourceString(@scxThe); // yearly rbEvery1.Caption := rbEvery.Caption; rbThe1.Caption := rbThe.Caption; lbOf.Caption := cxGetResourceString(@scxOf); // range of recurrence gbRange.Caption := cxGetResourceString(@scxRangeOfRecurrence); lbStart1.Caption := cxGetResourceString(@scxStart1); rbNoEndDate.Caption := cxGetResourceString(@scxNoEndDate); rbEndAfter.Caption := cxGetResourceString(@scxEndAfter); rbEndBy.Caption := cxGetResourceString(@scxEndBy); lbOccurrences.Caption := cxGetResourceString(@scxOccurences); // buttons btnOk.Caption := cxGetResourceString(@scxOk); btnCancel.Caption := cxGetResourceString(@scxCancel); btnRemove.Caption := cxGetResourceString(@scxRemoveRecur); end; procedure TcxSchedulerRecurrenceEventEditorForm.SetEndAfter; var ACount: Integer; AEvent: TcxSchedulerControlEvent; begin AEvent := TcxSchedulerControlEvent.Create(Event.Storage); try SaveEvent(AEvent); with TcxSchedulerOccurrenceCalculator.Create(AEvent, 0, 0) do try ACount := GetOccurrenceCount(deEndBy.Date + TimeOf(teEnd.Time)); finally Free; end; finally AEvent.Free; end; if ACount < 1 then ACount := 1; SetTextWithoutChangeEvent(meEndAfter, IntToStr(ACount)); end; procedure TcxSchedulerRecurrenceEventEditorForm.SetEndDate; var ADate: TDateTime; AEvent: TcxSchedulerControlEvent; begin AEvent := TcxSchedulerControlEvent.Create(Event.Storage); try SaveEvent(AEvent); with TcxSchedulerOccurrenceCalculator.Create(AEvent, 0, 0) do try CalcOccurrence(GetNumber(meEndAfter.Text)); ADate := DateOf(OccurrenceFinish); finally Free; end; finally AEvent.Free; end; SetDateWithoutChangeEvent(deEndBy, ADate); end; procedure TcxSchedulerRecurrenceEventEditorForm.SetEventRecurrenceFinish; var ACount: Integer; begin with TcxSchedulerOccurrenceCalculator.Create(Event, 0, 0) do try ACount := Info.Count; if ACount < 0 then ACount := 10; if ACount > 0 then begin if Info.Count < 0 then rbNoEndDate.Checked := True else rbEndAfter.Checked := True; CalcOccurrence(ACount); SetDateWithoutChangeEvent(deEndBy, DateOf(OccurrenceFinish)); end else begin rbEndBy.Checked := True; SetDateWithoutChangeEvent(deEndBy, DateOf(Info.Finish)); ACount := GetOccurrenceCount(Info.Finish); if ACount < 1 then ACount := 1; end; SetTextWithoutChangeEvent(meEndAfter, IntToStr(ACount)); finally Free; end; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetReadOnly( AValue: Boolean); begin inherited; gbTime.Enabled := not AValue; gbPattern.Enabled := not AValue; gbRange.Enabled := not AValue; btnCancel.Enabled := not AValue; btnRemove.Enabled := not AValue; end; procedure TcxSchedulerRecurrenceEventEditorForm.UpdateEventValuesFromControls; begin SaveEvent(Event); end; procedure TcxSchedulerRecurrenceEventEditorForm.UpdateRange; begin if rbEndBy.Checked then SetEndAfter else SetEndDate; end; procedure TcxSchedulerRecurrenceEventEditorForm.FillDays; var S: TStrings; I: Integer; begin S := cbDay.Properties.Items; S.BeginUpdate; try S.Add(cxGetResourceString(@scxDay1)); S.Add(cxGetResourceString(@scxWeekday)); S.Add(cxGetResourceString(@scxWeekendday)); for I := 1 to 7 do S.Add(LongDayNames[I]); finally S.EndUpdate; end; cbDay1.Properties.Items.Assign(S); end; procedure TcxSchedulerRecurrenceEventEditorForm.FillMonths; var S: TStrings; I: Integer; begin S := cbMonths.Properties.Items; S.BeginUpdate; try for I := 1 to 12 do S.Add(LongMonthNames[I]); finally S.EndUpdate; end; cbMonths1.Properties.Items.Assign(S); end; procedure TcxSchedulerRecurrenceEventEditorForm.FillWeeks; var S: TStrings; I: Integer; begin S := cbWeek.Properties.Items; S.BeginUpdate; try for I := 0 to 4 do S.Add(cxGetResourceString(sRangeNames[I])); finally S.EndUpdate; end; cbWeek1.Properties.Items.Assign(S); end; function TcxSchedulerRecurrenceEventEditorForm.GetActivePattern: TcxRecurrence; begin Result := TcxRecurrence(pcPattern.ActivePageIndex); end; function TcxSchedulerRecurrenceEventEditorForm.GetRecurrenceInfo: TcxSchedulerEventRecurrenceInfo; begin Result := Event.RecurrenceInfo; end; function TcxSchedulerRecurrenceEventEditorForm.GetDayOfWeekIndex: Integer; begin Result := DayOfWeek(Info.Start) + 2; end; function TcxSchedulerRecurrenceEventEditorForm.GetMonthIndex: Integer; begin Result := MonthOf(Info.Start) - 1; end; function TcxSchedulerRecurrenceEventEditorForm.GetNumber(const S: string): Integer; begin Result := StrToIntDef(Trim(S), 1); end; function TcxSchedulerRecurrenceEventEditorForm.GetWeekIndex: Integer; var Y, M, D: Word; begin DecodeDate(Info.Start, Y, M, D); Result := D div 7; end; function TcxSchedulerRecurrenceEventEditorForm.IsValidDailyPattern: Boolean; begin Result := GetNumber(meDay.Text) >= 1; if not Result then begin ActiveControl := meDay; Exit; end; end; function TcxSchedulerRecurrenceEventEditorForm.IsValidMonthlyPattern: Boolean; begin Result := False; if not GetNumber(meNumOfDay.Text) in [1..31] then begin ActiveControl := meNumOfDay; Exit; end; if GetNumber(meNumMonth.Text) < 1 then begin ActiveControl := meNumMonth; Exit; end; if GetNumber(meNumMonth1.Text) < 1 then begin ActiveControl := meNumMonth1; Exit; end; Result := True; end; function TcxSchedulerRecurrenceEventEditorForm.IsValidWeeklyPattern: Boolean; begin Result := False; if GetNumber(meNumOfWeek.Text) < 1 then begin ActiveControl := meNumOfWeek; Exit; end; if not (cbDayOfWeek1.Checked or cbDayOfWeek2.Checked or cbDayOfWeek3.Checked or cbDayOfWeek4.Checked or cbDayOfWeek5.Checked or cbDayOfWeek6.Checked or cbDayOfWeek7.Checked) then begin ActiveControl := cbDayOfWeek1; Exit; end; Result := True; end; function TcxSchedulerRecurrenceEventEditorForm.IsValidYearlyPattern: Boolean; var ADay: Integer; begin ADay := GetNumber(meDayOfMonth.Text); Result := (ADay >=1) and (ADay <= DaysPerMonth(2000, cbMonths.ItemIndex + 1)); if not Result then ActiveControl := meDayOfMonth; end; procedure TcxSchedulerRecurrenceEventEditorForm.ResetDailyTab; begin SetTextWithoutChangeEvent(meDay, '1'); rbEvery.Checked := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.ResetMonthlyTab; begin SetTextWithoutChangeEvent(meNumOfDay, IntToStr(DayOf(Info.Start))); SetTextWithoutChangeEvent(meNumMonth, '1'); SetTextWithoutChangeEvent(meNumMonth1, '1'); cbWeek.ItemIndex := GetWeekIndex; cbDay.ItemIndex := GetDayOfWeekIndex; rbDay.Checked := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.ResetWeeklyTab; begin SetTextWithoutChangeEvent(meNumOfWeek, '1'); SelectDaysOfWeek([TDay(DayOfWeek(Info.Start) - 1)]); end; procedure TcxSchedulerRecurrenceEventEditorForm.ResetYearlyTab; begin cbDay1.ItemIndex := GetDayOfWeekIndex; meDayOfMonth.Text := IntToStr(DayOf(Info.Start)); cbWeek1.ItemIndex := GetWeekIndex; cbMonths.ItemIndex := GetMonthIndex; cbMonths1.ItemIndex := GetMonthIndex; rbEvery1.Checked := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.SelectDaysOfWeek(ADays: TDays); procedure Check(ACheckBox: TcxCheckBox); begin ACheckBox.Checked := TDay(ACheckBox.Tag - 1) in ADays; end; begin Check(cbDayOfWeek1); Check(cbDayOfWeek2); Check(cbDayOfWeek3); Check(cbDayOfWeek4); Check(cbDayOfWeek5); Check(cbDayOfWeek6); Check(cbDayOfWeek7); end; procedure TcxSchedulerRecurrenceEventEditorForm.SetActivePattern( Value: TcxRecurrence); begin pcPattern.ActivePageIndex := Integer(Value); case Value of cxreDaily: ResetDailyTab; cxreWeekly: ResetWeeklyTab; cxreMonthly: ResetMonthlyTab; cxreYearly: ResetYearlyTab; end; UpdateRange; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetDailyPatternFromEvent; begin rbDaily.Checked := True; if Info.DayType = cxdtWeekDay then begin rbEveryWeekday.Checked := True; SetTextWithoutChangeEvent(meDay, '1'); end else begin rbEvery.Checked := True; SetTextWithoutChangeEvent(meDay, IntToStr(Info.Periodicity)); end; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetDateWithoutChangeEvent( AEdit: TcxDateEdit; ADate: TDateTime); var AOnChange, AOnEditValueChanged: TNotifyEvent; begin AOnChange := AEdit.Properties.OnChange; AOnEditValueChanged := AEdit.Properties.OnEditValueChanged; AEdit.Properties.OnChange := nil; AEdit.Properties.OnEditValueChanged := nil; AEdit.Date := ADate; AEdit.Properties.OnChange := AOnChange; AEdit.Properties.OnEditValueChanged := AOnEditValueChanged; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetItemIndexWithoutChangeEvent( AEdit: TcxComboBox; AIndex: Integer); var AOnChange: TNotifyEvent; begin AOnChange := AEdit.Properties.OnChange; AEdit.Properties.OnChange := nil; AEdit.ItemIndex := AIndex; AEdit.Properties.OnChange := AOnChange; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetMonthlyPatternFromEvent; var AType: TcxDayType; ANum: Integer; begin rbMonthly.Checked := True; AType := Info.DayType; if AType = cxdtDay then begin rbDay.Checked := True; SetTextWithoutChangeEvent(meNumOfDay, IntToStr(Info.DayNumber)); SetTextWithoutChangeEvent(meNumMonth, IntToStr(Info.Periodicity)); end else begin rbThe.Checked := True; SetTextWithoutChangeEvent(meNumMonth1, IntToStr(Info.Periodicity)); ANum := Info.DayNumber; if Integer(AType) >= 1 then Dec(Byte(AType)); SetItemIndexWithoutChangeEvent(cbWeek, ANum - 1); SetItemIndexWithoutChangeEvent(cbDay, Byte(AType)); end; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetPatternFromEvent; begin ActivePattern := Info.Recurrence; case Info.Recurrence of cxreDaily: SetDailyPatternFromEvent; cxreWeekly: SetWeeklyPatternFromEvent; cxreMonthly: SetMonthlyPatternFromEvent; cxreYearly: SetYearlyPatternFromEvent; end; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetupDaysOfWeek; procedure SetDayCheckBox(ACheck: TcxCheckBox); var AIndex: Integer; begin AIndex := ACheck.Tag; Inc(AIndex, TcxSchedulerDateTimeHelper.StartOfWeek); if AIndex > 7 then Dec(AIndex, 7); ACheck.Caption := LongDayNames[AIndex]; ACheck.Tag := AIndex; end; begin SetDayCheckBox(cbDayOfWeek1); SetDayCheckBox(cbDayOfWeek2); SetDayCheckBox(cbDayOfWeek3); SetDayCheckBox(cbDayOfWeek4); SetDayCheckBox(cbDayOfWeek5); SetDayCheckBox(cbDayOfWeek6); SetDayCheckBox(cbDayOfWeek7); end; procedure TcxSchedulerRecurrenceEventEditorForm.SetTextWithoutChangeEvent( AEdit: TcxMaskEdit; const AText: string); var AOnChange, AOnEditValueChanged: TNotifyEvent; begin AOnChange := AEdit.Properties.OnChange; AOnEditValueChanged := AEdit.Properties.OnEditValueChanged; AEdit.Properties.OnChange := nil; AEdit.Properties.OnEditValueChanged := nil; AEdit.Text := AText; AEdit.Properties.OnChange := AOnChange; AEdit.Properties.OnEditValueChanged := AOnEditValueChanged; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetWeeklyPatternFromEvent; begin rbWeekly.Checked := True; meNumOfWeek.Text := IntToStr(Info.Periodicity); if Event.IsRecurring and (Event.Source <> nil) then SelectDaysOfWeek(Info.OccurDays) else SelectDaysOfWeek([TDay(DayOfWeek(Event.Start) - 1)]); end; procedure TcxSchedulerRecurrenceEventEditorForm.SetYearlyPatternFromEvent; var AType: TcxDayType; ANum: Integer; begin rbYearly.Checked := True; AType := Info.DayType; ANum := Info.DayNumber; if AType = cxdtDay then begin rbEvery1.Checked := True; cbMonths.ItemIndex := Info.Periodicity - 1; SetTextWithoutChangeEvent(meDayOfMonth, IntToStr(ANum)); end else begin rbThe1.Checked := True; cbMonths1.ItemIndex := Info.Periodicity - 1; if Integer(AType) >= 1 then Dec(Byte(AType)); SetItemIndexWithoutChangeEvent(cbWeek1, ANum - 1); SetItemIndexWithoutChangeEvent(cbDay1, Byte(AType)); end; end; procedure TcxSchedulerRecurrenceEventEditorForm.meEndAfterPropertiesChange( Sender: TObject); begin rbEndAfter.Checked := True; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.deEndByPropertiesChange( Sender: TObject); begin rbEndBy.Checked := True; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.rbNoEndDateClick( Sender: TObject); begin meEndAfter.Text := '10'; SetEndDate; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.meEndAfterExit( Sender: TObject); begin ValidateNumber(Sender); SetEndDate; end; procedure TcxSchedulerRecurrenceEventEditorForm.ValidateNumber( Sender: TObject); begin with TcxMaskEdit(Sender) do Text := IntToStr(GetNumber(Text)); end; procedure TcxSchedulerRecurrenceEventEditorForm.meDayPropertiesChange( Sender: TObject); begin rbEvery.Checked := True; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.rbEveryWeekdayClick( Sender: TObject); begin SetTextWithoutChangeEvent(meDay, '1'); FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetDayRadioButtonChecked( Sender: TObject); begin rbDay.Checked := True; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.SetTheRadioButtonChecked( Sender: TObject); begin rbThe.Checked := True; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.deStartPropertiesEditValueChanged( Sender: TObject); begin UpdateRange; end; procedure TcxSchedulerRecurrenceEventEditorForm.DoChange(Sender: TObject); begin FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.cbMonthsPropertiesChange( Sender: TObject); begin rbEvery1.Checked := True; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.cbWeek1PropertiesChange( Sender: TObject); begin rbThe1.Checked := True; FModified := True; end; procedure TcxSchedulerRecurrenceEventEditorForm.btnOkClick(Sender: TObject); begin if IsValid then begin case GetRecurrenceInfoValidStatus of rvsValid: if CheckLostExceptions then ModalResult := mrOk; rvsReplaceOccurrenceDate: if CheckLostExceptions and (MessageDlg(Format(cxGetResourceString(@scxReplaceOccurrenceDate), [meNumOfDay.Text]), mtWarning, [mbOK,mbCancel], 0) = mrOk) then ModalResult := mrOk; rvsInvalidDuration: MessageDlg(cxGetResourceString(@scxInvalidRecurrenceDuration), mtWarning, [mbOK], 0); else MessageDlg(cxGetResourceString(@scxWrongPattern), mtWarning, [mbOK], 0); end end else MessageDlg(cxGetResourceString(@scxWrongPattern), mtWarning, [mbOK], 0); end; procedure TcxSchedulerRecurrenceEventEditorForm.deEndByPropertiesEditValueChanged( Sender: TObject); begin if Locked then Exit; SetEndAfter; end; procedure TcxSchedulerRecurrenceEventEditorForm.meEndAfterPropertiesEditValueChanged( Sender: TObject); begin if Locked then Exit; SetEndDate; end; end.