home *** CD-ROM | disk | FTP | other *** search
- { Turbo Calendar }
- { Copyright (c) 1990 by Borland International, Inc. }
-
- {$F+,O+,X+}
- Unit CalUnit;
-
- { This unit provide a objects for creating a simple calendar. Common
- usage in a aplication would be:
-
- Procedure ShowCalendar;
- Var
- CalendarWindow: PCalendarWindow;
- Begin
- CalendarWindow := New(PCalendarWindow, Init(New(PDayDialog,Init)));
- DeskTop^.Insert(CalendarWindow);
- End;
-
- The DayDialog object has four virtual methods that me wish to be change
- to fit the needs of a specific users application.
-
- Function IsSpecial(Day, Month, Year: Word): Boolean;
- Procedure GetActiveDays;
- Function ReadDay: PCollection;
- Procedure WriteDay(Collection: PCollection);
-
- }
- Interface
- uses Drivers, Objects, App, Views, Dos, Dialogs;
- Const
- { Default file name use to hold appointments. }
- CalendarFile = 'Calendar.Dat';
- DaysInMonth:Array[1..12] of byte =
- (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
- MonthStr:Array[1..12] of String =
- ('January ',
- 'February ',
- 'March ',
- 'April ',
- 'May ',
- 'June ',
- 'July ',
- 'August ',
- 'September ',
- 'October ',
- 'November ',
- 'December ');
- BaseCommand = 150;
- brHourFocused = 1 + BaseCommand;
- brMessageSelect = 2 + BaseCommand;
- Type
- St = String[80];
- TString = ^St;
- RDate = Record
- KeyDate: String[10];
- Message: Array[1..24] of String[80];
- End;
-
- PMessageInputLine = ^TMessageInputLine;
- TMessageInputLine = Object(TInputLine)
- Constructor Init(var R: Trect; AMaxLen: Integer; Parent: PDialog);
- Procedure HandleEvent(var Event: TEvent); Virtual;
- End;
-
- PHourCollection = ^THourCollection;
- THourCollection = Object(TCollection)
- Constructor Init;
- Procedure FreeItem(Item: Pointer); Virtual;
- End;
-
- PHourListBox = ^THourListBox;
- THourListBox = Object(TListBox)
- Procedure FocusItem(Item: Integer); Virtual;
- Procedure HandleEvent(var Event: TEvent); Virtual;
- Destructor Done; Virtual;
- End;
-
- PDayDialog = ^TDayDialog;
- TDayDialog = Object(TDialog)
- { ActiveCollection hold all dates that have appointments. }
- ActiveCollection: PStringCollection;
-
- HourListBox: PHourListBox;
- MessageInputLine: PMessageInputLine;
- Constructor Init;
- Destructor Done; Virtual;
-
- { IsSpecial returns true if there is a appointment associated with }
- { the date. }
- Function IsSpecial(Day, Month, Year: Word): Boolean; Virtual;
-
- { GetActiveDays enters all active days into ActiveCollections. }
- Procedure GetActiveDays; Virtual;
-
- { ReadDay reads all appointments for one day into a Collection. }
- { ReadDay is called by SetNewDay. }
- Function ReadDay: PCollection; Virtual;
-
- Procedure SetNewDay(Day, Month, Year: Word);
-
- { WriteDay saves all appointments for one day to Calendar.Dat}
- Procedure WriteDay(Collection: PCollection); Virtual;
-
- Private
- Function FStr(I: Integer): String;
- End;
-
- PCalendarView = ^TCalendarView;
- TCalendarView = object(TView)
- Year, Month, Days : Word;
- CurYear, CurMonth, CurDay : Word;
- DayDialog: PDayDialog;
- Constructor Init(Bounds: TRect; D: PDayDialog);
- Destructor Done; Virtual;
- procedure HandleEvent(var Event: TEvent); Virtual;
- Procedure Draw; Virtual;
- end;
-
- PCalendarWindow = ^TCalendarWindow;
- TCalendarWindow = object(TWindow)
- CalendarView: PCalendarView;
- Constructor Init(DayDialog:PDayDialog);
- End;
-
- Implementation
-
- {-------------- TMessageInputLine ------}
- Constructor TMessageInputLine.Init(var R: Trect; AMaxLen: Integer; Parent: PDialog);
- Begin
- Inc(R.A.X,5);
- TInputLine.Init(R, AMaxLen);
- GrowMode := gfGrowHiX;
- EventMask := EventMask or evBroadcast;
- End;
-
- Procedure TMessageInputLine.HandleEvent(var Event: TEvent);
- Const
- UpOrDown = [80, 81, 72, 73]; {A set of UP, PgUp, Down, PgDn}
- Begin
- if ((Event.What = evBroadcast) and (Event.Command = brHourFocused)) or
- ((Event.What = evKeyDown) and ((Event.KeyCode = kbEnter) or (Event.ScanCode in UpOrDown))) then
- Begin
- Message(Owner, evBroadcast, brMessageSelect, Data);
- Owner^.Delete(@Self); {Remove Self from the Dialog Box}
- If (Event.What = evKeyDown) and (Event.ScanCode in UpOrDown) then
- Message(TopView, Event.What, Event.Command, Event.InfoPtr);
- End;
- TInputLine.HandleEvent(Event);
- End;
-
- {-------------- THourCollection --------}
- Constructor THourCollection.Init;
- Begin
- TCollection.Init(24,1);
- End;
-
- Procedure THourCollection.FreeItem(Item: Pointer);
- Begin
- Dispose(TString(Item)); {This procedure must be used if using a }
- End; {collection on non Objects. }
-
- {-------------- THourListBox -----------}
- Destructor THourListBox.Done;
- Begin
- If List<>Nil then
- Dispose(List, Done);
- TListBox.Done;
- End;
-
- Procedure THourListBox.FocusItem(Item: Integer);
- Begin
- { Send message to notify TMessageInputLine that an item has been }
- { focused. (see TMessageInputLine.HandleEvent) }
- Message(Owner, evBroadcast, brHourFocused, List^.At(Item));
- TListBox.FocusItem(Item);
- End;
-
- Procedure THourListBox.HandleEvent(var Event: TEvent);
- Const
- LeftOrRight = [75, 77]; {Set of Left and Right arrow keys }
- Var
- R, R1: TRect;
- Begin
- If (Event.What=evKeyDown) and ((Event.CharCode<>#0) or (Event.ScanCode in LeftOrRight)) then
- Begin
- GetBounds(R);
- With PDayDialog(Owner)^.MessageInputLine^ do
- Begin
- { Assign the inputline with the data in the collection of }
- { the listbox. The copy is used to ignore the first 6 }
- { charaters. }
- Data^ := Copy(TString(List^.At(Focused))^, 6, 80);
- { Change the location of the inputline to be at the same }
- { position as the highlight bar of the listbox. }
- R.A.Y:=Focused-TopItem+1;
- R.B.Y:=R.A.Y+1;
- R.A.X:=R.A.X+5;
- ChangeBounds(R);
- end;
- If (Event.ScanCode in LeftOrRight) or (Event.KeyCode=KbEnter) then
- Event.KeyCode:=kbHome;
- { Display the inputline by inserting it into the dialog box }
- Owner^.Insert(PDayDialog(Owner)^.MessageInputLine);
- { Send the message whether to inputline }
- Message(TopView, Event.What, Event.Command, Event.InfoPtr);
- Exit;
- End;
- TListBox.HandleEvent(Event);
- If (Event.What=evBroadCast) and (Event.Command=brMessageSelect) then
- Begin
- { If the inputline is finish replace the currently focused }
- { item with the newly enter information from the inputline. }
- { see TMessageInputLine.HandleEvent for the sending of this }
- { message. }
- TString(List^.At(Focused))^:=Copy(TString(List^.At(Focused))^, 1, 5)+TString(Event.InfoPtr)^;
- { Redraw the view after the change. }
- DrawView;
- End;
- End;
-
- {-------------- TDayDialog -------------}
- Constructor TDayDialog.Init;
- Var
- R:TRect;
- ScrollBar: PScrollBar;
- Begin
- R.Assign(10,10,43,21);
- TDialog.Init(R, ' ');
- Flags := Flags or (wfZoom+wfGrow); {Allow dialog to be resizeable}
- GetExtent(R);
- R.A.X:=1;
- R.A.Y:=1;
- R.B.Y:=2;
- Dec(R.B.X,2);
- MessageInputLine:=New(PMessageInputLine, Init(R, 80, @Self));
- GetExtent(R);
- Inc(R.A.Y);
- Dec(R.B.X);
- Dec(R.B.Y);
- R.A.X:=R.B.X-1;
- Scrollbar := New(PScrollBar, Init(R));
- Insert(Scrollbar);
- GetExtent(R);
- Inc(R.A.X);
- Inc(R.A.Y);
- Dec(R.B.X,2);
- Dec(R.B.Y);
- HourListBox := New(PHourListBox, Init(R, 1, ScrollBar));
- HourListBox^.GrowMode:=gfGrowHiX+gfGrowHiY;
- Insert(HourListBox);
- GetActiveDays;
- End;
-
- Destructor TDayDialog.Done;
- Begin
- Dispose(ActiveCollection, Done);
- TDialog.Done;
- End;
-
- Function TDayDialog.IsSpecial(Day, Month, Year: Word): Boolean;
- Var
- DateStr: String;
- Index: Integer;
- Begin
- DateStr:=FStr(Month)+'/'+FStr(Day)+'/'+FStr(Year);
- IsSpecial:= ActiveCollection^.Search(@DateStr, Index);
- End;
-
- Function TDayDialog.FStr(I: Integer): String;
- Var
- S: String;
- Begin
- Str(I:2, S);
- FStr:=S;
- End;
-
- Procedure TDayDialog.SetNewDay(Day, Month, Year: Word);
- Var
- DateTitle: String;
- Hour, Minute, Second, hSecond: Word;
- Begin
- DateTitle:='Day - '+FStr(Month)+'/'+FStr(Day)+'/'+FStr(Year);
- DisposeStr(Title); { DisposeStr and NewStr must be used }
- Title:=NewStr(DateTitle); { when changing the Title of a dialog.}
- GetTime(Hour, Minute, Second, hSecond);
- HourListBox^.NewList(ReadDay);
- HourListBox^.FocusItem(Hour-1); { Focus on current time. }
- DeskTop^.ExecView(@Self);
- WriteDay(HourListBox^.List); { Save the appointments. }
- DeskTop^.Delete(@Self); { Hide the dialog box. }
- End;
-
- Procedure TDayDialog.GetActiveDays;
- Var
- F: File Of RDate;
- Date: RDate;
- Begin
- ActiveCollection:=New(PStringCollection, Init(50,10));
- Assign(F,CalendarFile);
- {$I-}Reset(F);{$I+}
- If IOResult=0 then
- Begin
- While Not Eof(F) do
- Begin
- Read(F, Date);
- ActiveCollection^.Insert(NewStr(Date.KeyDate));
- End;
- System.Close(F);
- End;
- End;
-
- Function TDayDialog.ReadDay: PCollection;
- Var
- F: File Of RDate;
- Date: RDate;
- HourCollection: PHourCollection;
- I: Integer;
- S: TString;
- FileDate: String;
- Begin
- HourCollection:=New(PHourCollection, Init);
- Assign(F,CalendarFile);
- {$I-}Reset(F);{$I+}
- FileDate:=Copy(Title^,7,10);
- { If not dos errors and the data is found in ActiveCollection }
- If (IOResult=0) and (ActiveCollection^.Search(@FileDate, I)) then
- Begin
- Read(F, Date);
- While Date.KeyDate<>FileDate do
- Read(F, Date);
- For I:=1 to 24 do { Insert each hour into the Collections }
- Begin
- New(S);
- S^:=Date.Message[I];
- HourCollection^.Insert(S);
- End;
- End
- Else
- Begin
- For I:=1 to 24 do
- Begin
- New(S);
- FillChar(S^, SizeOf(S^), ' ');
- If I<13 then
- Begin
- Str(I, S^);
- S^:=S^+'am ';
- End
- Else
- Begin
- Str(I-12, S^);
- S^:=S^+'pm ';
- End;
- S^[0]:=#5;
- HourCollection^.Insert(S);
- End;
- End;
- ReadDay:= HourCollection;
- End;
-
- Procedure TDayDialog.WriteDay(Collection: PCollection);
- Var
- F:File of RDate;
- Date, SearchDate: RDate;
- I: Integer;
- S: TString;
- Begin
- Assign(F,CalendarFile);
- {$I-}Reset(F);{$I+}
- If IOResult<>0 then
- ReWrite(F);
- For I:=1 to 24 do { Copy all appointments into a record. }
- Date.Message[I]:=TString(Collection^.At(I-1))^;
- Date.KeyDate:=Copy(Title^,7,10);
- { If the day already existed }
- If ActiveCollection^.Search(@Date.KeyDate, I) then
- Begin
- Read(F, SearchDate);
- { Find entry in file. }
- While SearchDate.KeyDate<>Date.KeyDate do
- Read(F, SearchDate);
- Seek(F,FilePos(F)-1);
- Write(F, Date);
- End
- Else
- Begin
- { Add new entry to file. }
- Seek(F, FileSize(F));
- Write(F, Date);
- New(S);
- S^:=Date.KeyDate;
- ActiveCollection^.Insert(S);
- End;
- System.Close(F);
- End;
- {-------------- TCalendarWindow --------}
- Constructor TCalendarWindow.Init(DayDialog: PDayDialog);
- Var
- R:TRect;
- Begin
- R.Assign(1,1,23,11);
- TWindow.Init(R, 'Calendar', 0);
- Flags := Flags and Not(wfZoom+wfGrow); { Do not allow window to }
- GrowMode :=0; { be resizeable. }
- GetExtent(R);
- Inc(R.A.X);
- Inc(R.A.Y);
- Dec(R.B.X);
- Dec(R.B.Y);
- CalendarView := New(PCalendarView,Init(R, DayDialog));
- Insert(CalendarView);
- End;
-
- {-------------- TCalendarView ----------}
- Constructor TCalendarView.Init(Bounds: TRect; D: PDayDialog);
- Var
- H: Word;
- Begin
- TView.Init(Bounds);
- DayDialog:=D;
- Options := Options or ofSelectable;
- GetDate(CurYear, CurMonth, CurDay, H);
- Year:=CurYear;
- Month:=CurMonth;
- DrawView;
- End;
-
- Destructor TCalendarView.Done;
- Begin
- Dispose(DayDialog, Done);
- TView.Done;
- End;
-
- Function DayOfWeek (day, month, year: integer) : integer;
- var
- century, yr, dw: integer;
- begin
- if month < 3 then
- begin
- Inc(month, 10);
- Dec(year);
- end
- else
- Dec(month, 2);
- century := year div 100;
- yr := year mod 100;
- dw := (((26*month - 2) div 10)+day+yr+(yr div 4)+(century div 4) - (2*century)) mod 7;
- if dw < 0 then
- DayOfWeek := dw + 7
- else
- DayOfWeek := dw;
- end;
-
- Procedure TCalendarView.Draw;
- Const
- Width = 20;
- Var
- i,j,DayOf,CurDays:Integer;
- S: String;
- B: Array[0..Width] of Word;
- Color, BoldColor, SpecialColor: Byte;
-
- Function Num2Str(I :integer): String;
- Var
- S:String;
- Begin
- Str(i:2,S);
- Num2Str := S+' ';
- End;
-
- Begin
- Color:= GetColor($01);
- BoldColor:= GetColor($02);
- SpecialColor:= GetColor($03);
- DayOf:=DayOfWeek(1, Month, Year);
- Days := DaysInMonth[Month] + Byte((Year mod 4=0) and (Month=2));
- Str(Year:4,S);
- MoveChar(B, ' ', Color, Width);
- MoveStr(B, MonthStr[Month]+S+' '#30' '#31,Color);
- WriteLine(0,0,Width,1,B);
- MoveChar(B, ' ', Color, Width);
- MoveStr(B, 'Su Mo Tu We Th Fr Sa', Color);
- WriteLine(0,1,Width,1,B);
- CurDays := 1-DayOf;
- For i:=1 to 6 do
- Begin
- MoveChar(B, ' ', Color, Width);
- For j:=0 to 6 do
- Begin
- If (CurDays<1) or (CurDays>Days) then
- MoveStr(B[J*3],' ',Color)
- else
- { If it is the current day. }
- If (Year=CurYear) and (Month=CurMonth) and (CurDays=CurDay) Then
- MoveStr(B[J*3],Num2Str(CurDays),BoldColor)
- { If there is an appointment for this day. }
- Else If DayDialog^.IsSpecial(CurDays, Month, Year) Then
- MoveStr(B[J*3],Num2Str(CurDays),SpecialColor)
- Else
- MoveStr(B[J*3],Num2Str(CurDays),Color);
- Inc(CurDays);
- End;
- WriteLine(0,i+1, Width,1,B);
- End;
- End;
-
- procedure TCalendarView.HandleEvent(var Event: TEvent);
- Var
- Point:TPoint;
- SelectDay: Word;
- begin
- TView.HandleEvent(Event);
- if (State and sfSelected <> 0) then
- Begin
- if (Event.What=evMouseDown) then
- If Event.Double then
- Begin
- MakeLocal(Event.Where,Point);
- If (Point.Y>1) then
- Begin
- SelectDay :=((Point.X div 3)+1)-DayOfWeek(1, Month, Year)+(Point.Y-2)*7;
- If (SelectDay>0) and (SelectDay-1<Days) then
- Begin
- { Display the dialog box. }
- DayDialog ^.SetNewDay(SelectDay, Month, Year);
- DrawView;
- End;
- End;
- End
- Else
- begin
- MakeLocal(Event.Where,Point);
- If ((Point.X=15) and (Point.Y = 0)) Then
- Begin
- inc(Month);
- If Month>12 then
- Begin
- inc(Year);
- Month :=1;
- End;
- DrawView;
- End;
- If ((Point.X=18) and (Point.Y=0)) Then
- Begin
- dec(Month);
- If Month<1 then
- Begin
- dec(Year);
- Month :=12;
- End;
- DrawView;
- End;
- end
- else if Event.What=evKeyDown then
- Begin
- If (lo(Event.KeyCode) = byte('+')) or
- (Event.KeyCode = kbDown)
- Then
- Begin
- inc(Month);
- If Month>12 then
- Begin
- inc(Year);
- Month :=1;
- End;
- End;
- If (lo(Event.KeyCode) = byte('-')) or
- (Event.KeyCode = kbUp)
- Then
- Begin
- dec(Month);
- If Month<1 then
- Begin
- dec(Year);
- Month :=12;
- End;
- End;
- DrawView;
- End;
- End;
- end;
- End.
-