Today we populate our calendar grid with actual dates, and hook the navigation up to show changing months in the grid
A Grid Of Dates
Before we just had a bunch of numbers in our calendar grid, but now we want real dates. So, without further ado, here is the code to populate our calendar with real dates based on the working date.
CalendarAgent>>currentMonthModel
| model firstDayOfMonth weekdayIndex gridDate |
model := ObservedTwoDList columns: 7 rows: 6.
firstDayOfMonth := Date newDay: 1 monthNumber: workingDate monthIndex year: workingDate year.
weekdayIndex := firstDayOfMonth weekdayIndex.
gridDate := Date fromDays: firstDayOfMonth asDays - weekdayIndex.
1 to: 42 do:
[:index |
model at: index put: gridDate.
gridDate := gridDate addDays: 1].
^model
There are probably better algorithms than this, but here is what we did: First, we get the first day of the current month. Once we know this, we can find out what the weekday index is. From there we play a bit of a trick using the fact that the weekdayIndex answers 1 for Monday, 2 for Tuesday and so on. Since our grid starts on Sunday, by subtracting the weekday index, we will always find the first Sunday for our grid. Then it is just a matter of iterating over all of the elements in the model, like last time, and giving each the grid date, incrementing the date after each assignment.
If we open our grid now (CalendarTest new openWindowWithCalendar then press the drop down button), we'll see a grid filled with the first characters of each date string. Remember, we set up our columns to send the column index and by default it then sends printString to the result. To have it instead answer the day of the month, we need to change our column definitions:
Here, we have just told to send the message #dayOfMonth, to the result of sending the column index to each item. Now if we open our popup, the grid looks really nice.
Changing the Grid when Navigating
If we open our grid, we see that if we click on the navigation buttons (prior and next year/month) the date grid doesn't change. Let's fix that:
Surprisingly, it's quite simple. We already have a method that gets called every time one of the navigation buttons gets pressed, so we piggyback the updating the model in the list. We don't have to do anything else special, since Pollock's framework takes care that whenever the list (or a list item) is changed, that the grid holding it is updated.
Visual Spiffery
If we look at our grid now, it surely fills in the right values for the days, and updates properly for navigation, but... it's pretty hard to see the demarcation between this month and the prior and next months begins/ends. Let's add a bit of code that makes prior and next months days be blue, where this months days are black.
We start off by giving the grid a block that we want to be called to get the foreground color for a cell:
This block will be called to get the foreground color for each cell. This block is a one argument block, that takes as a parameter the current cell. We of course now need to write a method named #foregroundColorFor: to answer back a color appropriate for the cell:
A bit of explanation about the Cell object. The Cell object is made up specially for each cell in a grid whenever there is a callback of this kind. It contains the Row (which is a Row object), the Column (the one you created to display the target column for this row) as well as a location, which is a Point object. By sending #value to a Cell object, you will get the value that is displayed in the grid for that Cell. In this case, if we sent #value to the Cell, it would send us back a string with the day of month number in it. That does us no good. Having to play with Row objects or Columns would be rather ugly and require heavy coupling of our code to the Cell.
But Cell also has a convenience method, called #rowItem. What this answers is an ObservedList with the raw model objects in it for this row. Then, by using the location (and then using the x value since that is all we care about), we can get the current date object in our model that is being dealt with. From there, it's a simple hop skip and a jump to answering a ColorValue for the foreground of the cell.
Heck, while we're at it, let's make today's date red, to make that even more visible:
Note here that we use the pane's model instead of the working date, since we change the working date when we navigate, but the model's date (as yet) remains unchanged. If you want, you can get even more fancy, by using the Grid's #backgroundColorAction: to maybe change the background color of non current month cells to gray, and maybe today's date background color to something really outstanding, like yellow.
The above is published as version 1.14 in the Package named "Pollock-Calendar" on the Cincom public repository.
Next time we'll make selecting a date in our grid actually change the model, and also close the popup