DIRECTORY
Buttons USING [ Button, SetDisplayStyle],
BasicTime USING [ GMT, Unpacked, Unpack, DayOfWeek, MonthOfYear, Now, Update],
Calendar USING [ Days, Weekdays, Months, Years, Date, ZoomLevel],
CalBrowser,
CalForm USING [ CreateCalForm],
CalNuts USING [ ResetNutInfo],
CalStorage USING [ protData, GetEventsOfDay, StoreViewer, RetrieveViewer, Mode, FindEvent],
CalSupport USING [ MakeMenu, DisplayMsg, PreviousDay, NextDay, GetMonthInfo, GetMonthName, FormWidth, FormHeight, CharWidth, RowHeight, I2M, GetRowCol, CreateTextViewer, ExtractDate, M2I, GetDayName, CreateButton, ClearButton, GetIconFlavor],
CalWalnut USING [ DisplayMessage],
Containers USING [ Create, Container],
Hickory USING [ EventList, Event, Reason, EventTuple, ForgetEvent],
IO USING [ int, rope, PutFR],
Labels USING [ Label, SetDisplayStyle, Create],
Menus USING [ MenuProc],
Rope USING [ ROPE, Concat, Length, FromChar, Substr, Equal],
RopeSets USING [ RopeSet],
ViewerClasses USING [ Viewer, ViewerRec],
ViewerOps USING [ DestroyViewer, PaintViewer, MoveViewer, SetMenu],
VTables USING [ VTable, Create, SetTableEntry, Install, NullBorder, FullBorder, Border, GetTableEntry],
ViewerTools USING [ SetContents]
;
Menu prcodedures ( are EXTERNAL)
Enter: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to enter CalForm...
IF mouseButton = red THEN DoCmd[ Enter];
END; -- Reset
ShowMsg: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to enter CalForm...
IF mouseButton = red THEN DoCmd[ ShowMsg];
END; -- Reset
Edit: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to edit a specific event through CalForm...
IF mouseButton = red THEN DoCmd[ Edit]
END; -- Reset
Forget: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to forget a specific event ...
IF mouseButton = red THEN DoCmd[ Forget];
END; -- Reset
Print: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to print the current contents of the calendar viewer onto hard press
IF mouseButton = red THEN CalSupport.DisplayMsg[ "Print: Not yet implemented!"];
END; -- Print
Next: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to move to next day, month or year
IF mouseButton = red THEN ShowNextOrPrevious[ TRUE];
END; -- Next
Previous: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to move to previous day, month or year
IF mouseButton = red THEN ShowNextOrPrevious[ FALSE];
END; -- Previous
ZoomOut: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to either pass from day -> month or month -> year
zoom: REF ZoomLevel = NARROW[ clientData];
IF mouseButton = red THEN DoZoomOut[ zoom^]; -- ISTYPE[ clientData, ZoomLevel]....
END; -- ZoomOut
ZoomIn: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
to either pass from month -> day or year -> month
IF mouseButton = yellow THEN DoZoomIn[ clientData]; -- can't NARROW here because it's either Days or Months
END; -- ZoomIn
SelectEvent: Menus.MenuProc
-- [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] -- =
BEGIN
To select an event from day viewer
index: REF CARDINAL ← NARROW[ clientData];
IF mouseButton = red THEN DoSelection[ index^];
END; -- SelectEvent
DisplayEvents and its numerous supporters ( all INTERNAL to monitor)
DisplayEvents:
PUBLIC
INTERNAL
PROCEDURE [ zoom: ZoomLevel, date: Calendar.Date] =
BEGIN
this is the big one: we attempt to create a nice viewer depending on the zooming
level and fill it with info from the events cached in calendar
curMode ← Browse;
ResetIcon[ curMode, date, zoomLevel, zoom];
CalNuts.ResetNutInfo[ zoom, Browse];
curDate ← date;
selectedEvent ← NIL;
AdjustCaption[ zoom, date];
SetMenu[ zoom, calViewer];
cont ← RetrieveCalBrowser[ zoom, zoomLevel, date, cont];
zoomLevel ← zoom;
IF cont =
NIL
THEN
BEGIN
SELECT zoom
FROM
Day =>
BEGIN
cont ← CreateContainer[ calViewer, TRUE];
DisplayDay[ cont, date];
END;
Month =>
BEGIN
cont ← CreateContainer[ myParent: calViewer];
DisplayMonth[ cont, date];
CalStorage.StoreViewer[ date, Month, cont];
END;
Year =>
BEGIN
cont ← CreateContainer[ myParent: calViewer];
DisplayYear[ cont, date];
CalStorage.StoreViewer[ date, Year, cont];
END;
ENDCASE => ERROR;
ViewerOps.PaintViewer[ viewer: calViewer, hint: all];
END
ELSE
--remember calViewer is top level viewer....! It also appears that moving calViewer
maintains coord appropriately
ViewerOps.MoveViewer[ viewer: cont, x: cont.wx-Delta, y: cont.wy-Delta, w: cont.ww, h: cont.wh, paint: TRUE];
END; -- DisplayEvents
RetrieveCalBrowser:
INTERNAL
PROCEDURE [ newZoom, oldZoom: ZoomLevel, date: Date, oldViewer: ViewerClasses.Viewer]
RETURNS [ newViewer: ViewerClasses.Viewer] =
BEGIN
IF oldViewer #
NIL
THEN
IF oldZoom # Day
THEN
-- hide it away
ViewerOps.MoveViewer[ viewer: oldViewer, x: oldViewer.wx+Delta, y: oldViewer.wy+Delta, w: oldViewer.ww, h: oldViewer.wh]
ELSE
BEGIN
ViewerOps.DestroyViewer[ oldViewer, FALSE]; -- don't bother saving it
dayGrid.buttons ← NIL;
END;
SELECT newZoom
FROM
Day => newViewer ← NIL;
Month => newViewer ← CalStorage.RetrieveViewer[ date, Month];
Year => newViewer ← CalStorage.RetrieveViewer[ date, Year];
ENDCASE;
RETURN[ newViewer];
END; -- RetrieveCalBrowser
SetMenu:
INTERNAL
PROCEDURE[ zoomLevel: ZoomLevel, viewer: ViewerClasses.Viewer] =
BEGIN
here we set the menu of calViewer according to zoom level
SELECT zoomLevel
FROM
Day =>
BEGIN
rz: REF ZoomLevel ← NEW[ ZoomLevel ← Month];
ViewerOps.SetMenu[ viewer: viewer, menu: CalSupport.MakeMenu[ LIST[ "Next", "Previous", "Month", "Print", "Forget", "Edit", "Enter", "ShowMsg"], LIST[ Next, Previous, ZoomOut, Print, Forget, Edit, Enter, ShowMsg], LIST[ NIL, NIL, rz, NIL, NIL, NIL, NIL, NIL]], paint: TRUE];
END; -- Day
Month =>
BEGIN
rz: REF ZoomLevel ← NEW[ ZoomLevel ← Year];
ViewerOps.SetMenu[ viewer: viewer, menu: CalSupport.MakeMenu[ LIST[ "Next", "Previous", "Year", "Print", "Enter"], LIST[ Next, Previous, ZoomOut, Print, Enter], LIST[ NIL, NIL, rz, NIL, NIL]], paint: FALSE];
END; -- Month
Year =>
BEGIN
ViewerOps.SetMenu[ viewer: viewer, menu: CalSupport.MakeMenu[ LIST[ "Next", "Previous", "Print", "Enter"], LIST[ Next, Previous, Print, Enter], LIST[ NIL, NIL, NIL, NIL]], paint: FALSE];
END; -- Year
ENDCASE;
END; -- SetMenu
AdjustCaption:
INTERNAL
PROCEDURE [ zoomLevel: ZoomLevel, curDate: Date] =
BEGIN
here we change the title of the viewer a bit
newTitle: Rope.ROPE ← "Calendar: ";
now: BasicTime.GMT ← BasicTime.Now[];
time: BasicTime.Unpacked ← BasicTime.Unpack[ now];
SELECT zoomLevel
FROM
Day =>
newTitle ← Rope.Concat[ newTitle, IO.PutFR[ "%g, %g %2g, %4g", IO.rope[ CalSupport.GetDayName[ curDate]], IO.rope[ CalSupport.GetMonthName[ curDate.Month]], IO.int[ curDate.Day], IO.int[ curDate.Year]]];
Month =>
newTitle ← Rope.Concat[ newTitle, IO.PutFR[ "%g %4g", IO.rope[ CalSupport.GetMonthName[ curDate.Month]], IO.int[ curDate.Year]]];
Year =>
newTitle ← Rope.Concat[ newTitle, IO.PutFR[ "%4g", IO.int[ curDate.Year]]];
ENDCASE;
calViewer.name ← newTitle;
END; -- AdjustCaption
DisplayDay:
INTERNAL
PROCEDURE [ cont: ViewerClasses.Viewer, date: Date] =
BEGIN
list all the events of the day in the text viewer, container is clean
OPEN dayGrid;
evl: EventList ← NIL;
rowCount: CARDINAL ← 0;
but: Buttons.Button;
msg, txtRope, tr, plRope: Rope.ROPE;
time: BasicTime.Unpacked;
buttonLabel: Rope.ROPE;
IF cont = NIL THEN RETURN;
evl ← CalStorage.GetEventsOfDay[ date, Day];
IF evl =
NIL
THEN
BEGIN
[] ← CreateLabel[ myParent: cont, hi: ButtonHeight, wi: cont.cw, title: "Sorry, no events on this day...", displayStyle: $BlackOnWhite];
RETURN;
END;
buttons ← NIL;
FOR l: EventList ← evl, l.rest
UNTIL l =
NIL
DO
time ← BasicTime.Unpack[ l.first.EventTime];
txtRope ← l.first.Text;
plRope ← l.first.Place;
IF l.first.Duration # 0
THEN
BEGIN
duration: LONG CARDINAL ← l.first.Duration;
endTime: BasicTime.Unpacked;
duration ← duration*60;
endTime ← BasicTime.Unpack[ BasicTime.Update[ l.first.EventTime, duration]];
tr ← IO.PutFR[ TimeFormat, IO.int[ time.hour], IO.int[ time.minute], IO.int[ endTime.hour], IO.int[ endTime.minute]];
END
ELSE tr ← IO.PutFR[ TimeFormat2, IO.int[ time.hour], IO.int[ time.minute]];
IF l.first.Message # NIL THEN msg ← " M" ELSE msg ← " ";
IF Rope.Length[ txtRope] > TextWidth THEN txtRope ← Rope.Substr[ txtRope, 0, TextWidth];
IF Rope.Length[ plRope] > PlaceWidth THEN plRope ← Rope.Substr[ plRope, 0, PlaceWidth];
buttonLabel ← IO.PutFR[ Format, IO.rope[ tr], IO.rope[ msg], IO.rope[ txtRope], IO.rope[ plRope]];
but ← CalSupport.CreateButton[ myParent: cont, hi: ButtonHeight, wi: cont.cw, yOff: rowCount*ButtonHeight, xOff: 0, proc: SelectEvent, clientData: NEW[ CARDINAL ← rowCount], title: buttonLabel, displayStyle: $BlackOnWhite];
buttons ← CONS[ [ rowCount, l.first.Key, but], buttons];
rowCount ← rowCount + 1;
ENDLOOP;
END; -- DisplayDay
TitleMonthGrid:
INTERNAL
PROCEDURE [ monthTable: VTables.VTable]
RETURNS [ newMonthTable: VTables.VTable] =
BEGIN
to label the first row of the month grid when we build the monthly grid for a year.
OPEN monthGrid;
width: INT← monthTable.cw/Cols;
newMonthTable ← monthTable;
FOR d: Weekdays
IN [ Monday..Sunday]
DO
dr: Rope.ROPE; col: NAT;
SELECT d
FROM
Monday => BEGIN dr ← "Mo"; col ← 1; END;
Tuesday => BEGIN dr ← "Tu"; col ← 2; END;
Wednesday => BEGIN dr ← "We"; col ← 3; END;
Thursday => BEGIN dr ← "Th"; col ← 4; END;
Friday => BEGIN dr ← "Fr"; col ← 5 ;END;
Saturday => BEGIN dr ← "Sa"; col ← 6; END;
Sunday => BEGIN dr ← "Su"; col ← 0; END;
ENDCASE;
VTables.SetTableEntry[ table: newMonthTable, row: 0, column: col, name: dr, border: [ FALSE, TRUE, FALSE, TRUE], w: width];
ENDLOOP;
END; -- TitleMonthGrid
CreateDayViewer:
INTERNAL
PROCEDURE [ width, height:
INT, myParent: ViewerClasses.Viewer, butLabel: Rope.
ROPE, butProc: Menus.MenuProc, dayOfMonth: Days, contents: Rope.
ROPE]
RETURNS [ table: VTables.VTable] =
BEGIN
build a table with 2 rows: the first is a button and labeled with the name and date of the
day. Second row is a text viewer, whose content are all the event texts... of that day
button, txtViewer: ViewerClasses.Viewer;
table ← VTables.Create[ rows: 2, columns: 1, parent: myParent, w: width, h: height];
VTables.SetTableEntry[ table: table, row: 0, column: 0, flavor: $Button, proc: butProc, clientData: NEW[ Days ← dayOfMonth], name: butLabel, w: width, border: [ FALSE, TRUE, FALSE, FALSE]];
VTables.Install[ table, FALSE];
button ← VTables.GetTableEntry[ table, 0, 0];
txtViewer ← CalSupport.CreateTextViewer[ width: width, height: height - button.wh, myParent: table, scrolling: TRUE, cont: contents, edit: FALSE];
VTables.SetTableEntry[ table: table, row: 1, column: 0, flavor: $Viewer, clientData: txtViewer, border: [ TRUE, TRUE, FALSE, TRUE], h: height - button.wh, w: width]; -- ouff
VTables.Install[ table, FALSE];
FillInDayGrid:
INTERNAL
PROCEDURE [ table: VTables.VTable, date: Date]
RETURNS [ newTable: VTables.VTable] =
BEGIN
to fill a monthly grid with the day viewers
OPEN monthGrid;
width, height: INT;
nbrOfDays: Days;
firstDay: Weekdays;
cont: Rope.ROPE;
DayName:
INTERNAL
PROCEDURE [ col:
INT, i: Days]
RETURNS [ namedDay: Rope.
ROPE] =
INLINE
BEGIN
r: Rope.ROPE;
SELECT col
FROM
1 => r ← "Mon";
2 => r ← "Tue";
3 => r ← "Wed";
4 => r ← "Thu";
5 => r ← "Fri";
6 => r ← "Sat";
0 => r ← "Sun";
ENDCASE;
RETURN[ IO.PutFR[ monthGrid.DateFormat, IO.rope[ r], IO.int[ i]]];
END; -- DayName
[ nbrOfDays, firstDay] ← CalSupport.GetMonthInfo[ curDate.Month, curDate.Year];
width ← table.cw/Cols;
height ← table.ch/Rows;
FOR d: Days
IN [ 1.. nbrOfDays]
DO
row, col: INT;
dayViewer: ViewerClasses.Viewer;
[ row, col] ← CalSupport.GetRowCol[ d, firstDay];
cont ← DayContents[ [ d, date.Month, date.Year], width];
dayViewer ← CreateDayViewer[ width, height, table, DayName[ col, d], ZoomIn, d, cont];
monthGrid.DayViewers[ d] ← dayViewer;
ENDLOOP;
RETURN[ table];
END; -- FillInDayGrid
CreateMonthGrid:
INTERNAL
PROCEDURE [ myParent: ViewerClasses.Viewer, height, width:
INT, zoom: ZoomLevel, date: Date]
RETURNS [ table: VTables.VTable] =
BEGIN
we create a table to display the month. If zoom = Year we must include a title row for the
days. Monthly grids don't have the title row to make all table entries of same height.
monthTable: VTables.VTable;
IF zoomLevel = Year
THEN
monthTable ← VTables.Create[ columns: monthGrid.Cols, rows: monthGrid.Rows+1, parent: myParent, h: height, w: width]
ELSE
monthTable ← VTables.Create[ columns: monthGrid.Cols, rows: monthGrid.Rows, parent: myParent, h: height, w: width];
IF monthTable =
NIL
THEN
BEGIN
CalSupport.DisplayMsg[ "Failure to create month grid!"];
RETURN;
END;
IF zoomLevel = Year THEN monthTable ← TitleMonthGrid[ monthTable]
ELSE monthTable ← FillInDayGrid[ monthTable, date];
VTables.Install[ monthTable, FALSE];
RETURN[ monthTable];
END; -- CreateMonthGrid
DayContents:
INTERNAL
PROCEDURE [ date: Date, fieldWidth: INT ← 0] RETURNS [ entry: Rope.ROPE] =
BEGIN
depending on zooomLevel, we fill in the day entry. Currently when at zoom = Month
we show all event texts. If at zoom = Year, simply put a '*' if some event scheduled on
that day.
fieldWidth is in Pixels!
OPEN monthGrid;
evl: EventList ← CalStorage.GetEventsOfDay[ date, Day];
length: INT ← fieldWidth/CharWidth-2; -- estimate how many chars fit on a line
IF evl = NIL THEN RETURN[ NIL];
IF evl = NIL THEN RETURN[ NIL];
entry ← Rope.Concat[ entry, " "]; -- text viewer's first char...
FOR l: EventList ← evl, l.rest
UNTIL l =
NIL
DO
IF fieldWidth = 0
THEN
entry ← Rope.Concat[ entry, l.first.Text]
ELSE
IF Rope.Length[ l.first.Text] > length
THEN
BEGIN
entry ← Rope.Concat[ entry, Rope.Substr[ base: l.first.Text, len: length]];
entry ← Rope.Concat[ entry, "..."];
END
ELSE entry ← Rope.Concat[ entry, l.first.Text];
entry ← Rope.Concat[ entry, Rope.FromChar[ '\n]];
ENDLOOP;
RETURN[ entry];
END; -- DayContents
FillMonthGrid:
INTERNAL
PROCEDURE [ date: Date, monthTable: VTables.VTable, zoom: ZoomLevel] =
BEGIN
to fill in the computed contents into the monthly grid table
OPEN monthGrid;
wid, hi: INT; -- h, w for entry
row, col: INTEGER;
noLeftBorder: VTables.Border ← [ TRUE, TRUE, FALSE, TRUE];
noRightBorder: VTables.Border ← [ TRUE, TRUE, TRUE, FALSE];
firstDay: Weekdays;
GetBorder:
INTERNAL
PROCEDURE [ index:
INT]
RETURNS [ border: VTables.Border] =
INLINE
BEGIN
IF index = 0 THEN RETURN[ noLeftBorder]
ELSE IF index = Rows-1 THEN RETURN[ noRightBorder]
ELSE RETURN[ VTables.FullBorder];
END; -- GetBorder
IF zoom = Year
THEN
BEGIN
wid ← monthTable.cw/monthGrid.Cols;
hi ← RowHeight;
END
ELSE
BEGIN
OPEN monthGrid;
wid ← FormWidth/Cols;
hi ← FormHeight/Rows;
END;
[ nbrOfDays, firstDay] ← CalSupport.GetMonthInfo[ date.Month, date.Year];
[ row, col] ← CalSupport.GetRowCol[ 1, firstDay];
IF col # 0
THEN
-- fill first row partially
FOR c:
INT
IN [ 0..col-1]
DO
VTables.SetTableEntry[ table: monthTable, row: IF zoom = Year THEN 1 ELSE 0, column: c, w: wid, h: hi, border: GetBorder[ c]];
ENDLOOP;
[ row, col] ← CalSupport.GetRowCol[ nbrOfDays, firstDay];
IF col # 6
THEN
-- fill last row partially
FOR c:
INT
IN [ col+1..monthGrid.Cols)
DO
VTables.SetTableEntry[ table: monthTable, row: IF zoom = Year THEN row + 1 ELSE row, column: c, w: wid, h: hi, border: GetBorder[ c]];
ENDLOOP;
VTables.Install[ monthTable, FALSE];
FOR i: Days
IN [ 1..nbrOfDays]
DO
[ row, col] ← CalSupport.GetRowCol[ i, firstDay];
remember title is row 0 when we have zoom = Year
IF zoomLevel = Month
THEN
BEGIN
simply insert day viewers, whose contents is already set!
dayViewer: VTables.VTable ← monthGrid.DayViewers[ i];
VTables.SetTableEntry[ table: monthTable, row: row, column: col, flavor: $Viewer, w: wid, h: hi, clientData: dayViewer, border: GetBorder[ col]];
END
ELSE
BEGIN
-- zoomLevel = Year; proc registered with title table...
evl: EventList ← CalStorage.GetEventsOfDay[ [ i, date.Month, date.Year], Year];
VTables.SetTableEntry[ table: monthTable, row: row+1, column: col, name: IO.PutFR[ "%02g", IO.int[ i]], w: wid, h: hi, border: GetBorder[ col], proc: NIL, displayStyle: IF evl = NIL THEN $BlackOnWhite ELSE $BlackOnGrey];
END;
VTables.Install[ monthTable, FALSE];
ENDLOOP;
END; -- FillMonthGrid
DisplayMonth:
INTERNAL
PROCEDURE [ cont: ViewerClasses.Viewer, date: Date] =
BEGIN
displays the month into container.
OPEN monthGrid;
table : VTables.VTable ← CreateMonthGrid[ cont, cont.ch, cont.cw, Month, date];
-- above call sets monthGrid.dayViewers
FillMonthGrid[ date, table, Month];
END; -- DisplayMonth
CreateTitleTable:
INTERNAL
PROCEDURE [ myParent: ViewerClasses.Viewer, height, width:
INT, mo: Months]
RETURNS [ table: VTables.VTable] =
BEGIN
creates a month title table to be contained in the year table and installs it
table ← VTables.Create[ columns: 1, rows: 1, parent: myParent, w: width, h: height];
VTables.SetTableEntry[ table: table, row: 0, column: 0, name: CalSupport.GetMonthName[ mo], proc: ZoomIn, clientData: NEW[ Months ← mo], w: width, h: height, border: VTables.NullBorder];
VTables.Install[ table, FALSE];
END; -- CreateTitleTable
CreateYearGrid:
INTERNAL
PROCEDURE [ myParent: ViewerClasses.Viewer, date: Date]
RETURNS [ yearTable: VTables.VTable] =
BEGIN
create the year grid i..e a table [ 4, 3] of tables [ 6, 7]
OPEN yearGrid;
table: VTables.VTable;
wid: INT; -- height is constant
yearTable ← VTables.Create[ columns: Cols, rows: Rows, parent: myParent, h: myParent.ch, w: myParent.cw];
wid ← yearTable.cw/Cols; -- width of a month table within year grid.
FOR l:
INT
IN [ 0..Rows-1]
DO
FOR k:
INT
IN [ 0..Cols-1]
DO
OPEN yearGrid;
mo: Months ← CalSupport.I2M[ (l/2)*Cols+k];
IF l MOD 2 = 0 THEN table ← CreateTitleTable[ yearTable, RowHeight, wid, mo]
ELSE
BEGIN
table ← CreateMonthGrid[ yearTable, ( monthGrid.Rows+1)*RowHeight, wid, Year, [ date.Day, mo, date.Year]];
yearGrid.MonthViewers[ mo] ← table;
END;
VTables.SetTableEntry[ table: yearTable, row: l, column: k, flavor: $Viewer, clientData: table, proc: NIL];
VTables.Install[ table, FALSE];
ENDLOOP;
ENDLOOP;
VTables.Install[ table: yearTable, paint: FALSE];
RETURN[ yearTable];
END; -- CreateYearGrid
DisplayYear:
INTERNAL
PROCEDURE [ cont: ViewerClasses.Viewer, date: Date] =
BEGIN
display the year in yearly grid...
table: VTables.VTable ← CreateYearGrid[ cont, date];
FOR curMonth: Months IN [ January..December]
DO
curMonthTable: VTables.VTable ← yearGrid.MonthViewers[ curMonth];
FillMonthGrid[ [ date.Day, curMonth, date.Year], curMonthTable, Year];
ENDLOOP;
VTables.Install[ table: table, paint: FALSE];
END; -- DisplayYear
Updating the browser viewers when hickory changes.
HickoryChange:
PUBLIC
INTERNAL
PROCEDURE [ reason: Hickory.Reason, oldEvl, newEvl: Hickory.EventList, data: RopeSets.RopeSet] =
BEGIN
having updated calStorage, we now update the viewers of the browser...
evl is the list of all events that have somehow changed. Assume that calStorage
is up to date, except viewer contents.
prevDate: Date ← [ 0, January, 1968]; -- fix same day only once
dayViewerFixed: BOOLEAN ← FALSE;
IF calViewer = NIL OR calViewer.destroyed THEN RETURN;
IF reason = Edit
OR reason = Destroy
OR reason = Forget
THEN
-- get rid of old stuff
FOR l: Hickory.EventList ← oldEvl, l.rest
UNTIL l =
NIL
DO
date: Date ← CalSupport.ExtractDate[ l.first.EventTime];
viewer: ViewerClasses.Viewer;
IF date # prevDate
THEN
BEGIN
viewer ← CalStorage.RetrieveViewer[ date, Month];
IF viewer # NIL THEN CleanMonthViewer[ viewer, date];
IF curDate = date
AND zoomLevel = Day
AND curMode = Browse
THEN
BEGIN
we should be having a day viewer on the screen..
FixDayViewer[ date]; dayViewerFixed ← TRUE;
END;
END;
prevDate ← date;
ENDLOOP;
IF reason = Edit
OR reason = NewEvent
OR reason = UnForget
THEN
-- insert new stuff
FOR l: Hickory.EventList ← newEvl, l.rest
UNTIL l =
NIL
DO
date: Date ← CalSupport.ExtractDate[ l.first.EventTime];
viewer: ViewerClasses.Viewer;
IF date # prevDate
THEN
BEGIN
viewer ← CalStorage.RetrieveViewer[ date, Month];
IF viewer # NIL THEN FixMonthViewer[ viewer, date];
viewer ← CalStorage.RetrieveViewer[ date, Year];
IF viewer # NIL THEN FixYearViewer[ viewer, date];
IF NOT dayViewerFixed AND curDate = date AND zoomLevel = Day
AND curMode = Browse
THEN
BEGIN
we should be having a day viewer on the screen..
FixDayViewer[ date];
END;
END;
prevDate ← date;
ENDLOOP;
END; -- HickoryChange
CleanMonthViewer:
INTERNAL
PROCEDURE [ monthViewer: Containers.Container, date: Date] =
BEGIN
here we clean the day viewers of the month of events that are no longer scheduled.
monthTable: VTables.VTable ← monthViewer^.child; -- there ought to be only one
row, col: CARDINAL;
firstDay: Weekdays;
nbrOfDays: Days;
dayViewer, txtViewer: ViewerClasses.Viewer;
IF monthTable = NIL THEN RETURN;
[ nbrOfDays, firstDay] ← CalSupport.GetMonthInfo[ date.Month, date.Year];
[ row, col] ← CalSupport.GetRowCol[ date.Day, firstDay];
dayViewer ← VTables.GetTableEntry[ table: monthTable, row: row, column: col];
txtViewer ← VTables.GetTableEntry[ table: dayViewer, row: 1, column: 0];
ViewerTools.SetContents[ viewer: txtViewer, contents: DayContents[ date, dayViewer.cw]];
END; -- FixMonthViewer
FixMonthViewer:
INTERNAL
PROCEDURE [ monthViewer: Containers.Container, date: Date] =
BEGIN
here we insert newly schedule events into the day viewers of the month.
monthTable: VTables.VTable ← monthViewer^.child; -- there ought to be only one
row, col: CARDINAL;
firstDay: Weekdays;
nbrOfDays: Days;
dayViewer, txtViewer: ViewerClasses.Viewer;
IF monthTable = NIL THEN RETURN;
[ nbrOfDays, firstDay] ← CalSupport.GetMonthInfo[ date.Month, date.Year];
[ row, col] ← CalSupport.GetRowCol[ date.Day, firstDay];
dayViewer ← VTables.GetTableEntry[ table: monthTable, row: row, column: col];
txtViewer ← VTables.GetTableEntry[ table: dayViewer, row: 1, column: 0];
ViewerTools.SetContents[ viewer: txtViewer, contents: DayContents[ date, dayViewer.cw]];
END; -- FixMonthViewer
FixYearViewer:
INTERNAL
PROCEDURE [ yearViewer: Containers.Container, date: Date] =
BEGIN
and here the year viewer is updated
yearTable: VTables.VTable ← yearViewer^.child; -- there ought to be only one
row, col: CARDINAL;
firstDay: Weekdays;
nbrOfDays: Days;
label: Labels.Label;
monthTable: VTables.VTable;
evl: Hickory.EventList;
IF yearTable = NIL THEN RETURN;
[ nbrOfDays, firstDay] ← CalSupport.GetMonthInfo[ date.Month, date.Year];
row ← ( CalSupport.M2I[ date.Month])/yearGrid.Cols;
col ← ( CalSupport.M2I[ date.Month]) MOD yearGrid.Cols;
row ← 2*row + 1; -- month button rows...
monthTable ← VTables.GetTableEntry[ table: yearTable, row: row, column: col];
[ row, col] ← CalSupport.GetRowCol[ date.Day, firstDay];
row ← row + 1; -- day title row
label ← VTables.GetTableEntry[ table: monthTable, row: row, column: col];
evl ← CalStorage.GetEventsOfDay[ date, Day];
IF evl = NIL THEN Labels.SetDisplayStyle[ label: label, style: $BlackOnWhite]
ELSE Labels.SetDisplayStyle[ label: label, style: $BlackOnGrey];
END; -- FixYearViewer
FixDayViewer:
INTERNAL
PROCEDURE [ date: Date] =
BEGIN
assume that day viewer is visible on screen. Day viewer is top level container
For now we destroy entire viewer and recreate it. It's hard to get repeated events right,
that's why. But there might be smarter and faster ways..
IF cont #
NIL
THEN
BEGIN
ViewerOps.DestroyViewer[ viewer: cont, paint: TRUE];
cont ← NIL; dayGrid.buttons ← NIL;
END;
cont ← CreateContainer[ calViewer, TRUE];
DisplayDay[ cont, date];
ViewerOps.PaintViewer[ cont, all];
END; -- FixDayViewer
INITIALLY
zoomLevel ← unspecified;
END.utto