drawCalendar
Back to ListDescription: A function to draw a calendar image using the Image Drawing capabilities.
FileMaker Prototype:
Set Variable [$res; ACF_Run("drawCalendar"; date_month; float_width; float_dpi; int_displayDays)]
Category: IMAGES
Dependencies
- NorwegianHolidaysEN: Creating a JSON array with Norwegian holidays
Function source:
Function drawCalendar ( date month, float width, float dpi, int displayDays )
// ------------------------------------------------------------------
// Basic date info
// ------------------------------------------------------------------
string ys = string (month, "%Y");
string ms = string (month, "%m");
int ims = int(ms);
JSON holidays;
holidays["a"] = NorwegianHolidaysEN(int(ys));
JSON holidayExtra;
int hdaysEx = 0;
if (ims == 1) then
holidayExtra["a"] = NorwegianHolidaysEN(int(ys)-1);
hdaysEx = sizeof (holidayExtra["a"]);
elseif (ims == 12) then
holidayExtra["a"] = NorwegianHolidaysEN(int(ys)+1);
hdaysEx = sizeof (holidayExtra["a"]);
end if
float fontScale = width / 1024.0;
int hdays = sizeof (holidays["a"]);
// Normalise displayDays: 5 (Mon–Fri), 6 (Mon–Sat), 7 (Mon–Sun)
if (displayDays <= 0 || displayDays > 7) then
displayDays = 7;
end if
// Month and weekday names
array string mnd = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
array string sWeekDay = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
array string WeekDay = {"Monday", "Tuesday", "Wednessday", "Thursday", "Friday", "Saturday"};
// Find first of month
date dt1th = date( int(ms),1, int(ys));
print format ("\dt1th: %s", string(dt1th));
// ACF %w: 0 = Sunday, 1 = Monday, ... 6 = Saturday
int dow1th = int (string(dt1th, "%w"));
if (dow1th == 0) then dow1th = 7; end if // make Monday=1 ... Sunday=7
// First Monday shown in the calendar grid
date calFrom = dt1th - dow1th + 1;
// Last day in grid: start with 5 weeks, then trim if the last week is fully next month
date calTo;
if (ms == "12") then
calTo = date(12,31,int(ys));
else
calTo = date(int(ms)+1, 1, int(ys))-1;
end if
int dowLast = int (string(calTo, "%w"));
if (dowLast == 0) then dowLast = 7; end if // make Monday=1 ... Sunday=7
// Last sunday shown in the calendar grid
calTo = calTo + (7-dowLast);
print format ("\nCalTo(1): %s", string(calTo));
if (int(string(calTo, "%d")) > 7 && int(string(calTo, "%m"))!=int(ms)) then
calTo = calTo - 7;
end if
print format ("\nFrom: %s, To:%s, mnt:%s, %s, %s", string(calfrom), string(calTo), string(month, "%d.%m.%Y"), ys, ms);
// Number of rows (weeks) in grid
int calRows = (calTo - calFrom + 1) / 7;
// ------------------------------------------------------------------
// Geometry
// ------------------------------------------------------------------
// Margins as 5% of width
float lm = width * 0.05;
float rm = lm;
float tm = lm;
float bm = lm;
// Cell width/height (square-ish cells)
float cellWidth = (width - lm - rm) / displayDays;
float cellHeight = cellWidth*0.8;
if (calRows == 6) then
cellHeight = cellHeight*0.9;
end if
// Header areas
float hdsize = 36*fontScale;
float wdheight = 22*fontScale;
float monthHeaderHeight = hdsize*1.2; // Month title
float weekdayHeaderHeight = wdheight*1.2; // Weekday row
float gridTop = tm + monthHeaderHeight + weekdayHeaderHeight;
float gridHeight = calRows * cellHeight;
float height = gridTop + gridHeight + bm;
// ------------------------------------------------------------------
// Create image JSON
// ------------------------------------------------------------------
JSON img = NewImage ( width, height, JSON("color", "white", "dpi", dpi) );
// ------------------------------------------------------------------
// Fonts
// ------------------------------------------------------------------
JSON fontTitle = JSON("name", "Helvetica", "size", hdsize, "color", "black",
"style", JSONarray("bold"));
JSON fontWeek = JSON("name", "Helvetica", "size", wdheight, "color", "black",
"style", JSONarray("bold"));
JSON fontDay = JSON("name", "Helvetica", "size", 18*fontScale, "color", "black");
JSON fontDayDim = JSON("name", "Helvetica", "size", 18*fontScale, "color", "grey", "alpha", 0.6);
JSON fontHoliday = JSON("name", "Helvetica", "size", 18*fontScale, "color", "red", "alpha", 1.0);
// ------------------------------------------------------------------
// Month title
// ------------------------------------------------------------------
ImageSetFont (img, fontTitle);
string title = format("%s %s", mnd[int(ms)], ys);
ImageDrawTextBox (
img,
lm, tm,
width - lm - rm, monthHeaderHeight,
title,
JSON("align", "center", "valign", "middle")
);
// ------------------------------------------------------------------
// Weekday headers
// ------------------------------------------------------------------
ImageSetFont (img, fontWeek);
int i, j, k;
float x, y;
for (i = 1, displayDays)
x = lm + (i - 1) * cellWidth;
ImageDrawTextBox (
img,
x, tm + monthHeaderHeight,
cellWidth, weekdayHeaderHeight,
sWeekDay[i],
JSON("align", "center", "valign", "middle")
);
end for
// ------------------------------------------------------------------
// Shading
// ------------------------------------------------------------------
x = lm + 5 * cellWidth;
y = gridTop;
JSON shading = json("color", "grey", "alpha", 0.1);
JSON shadingOpts = json("line", "none", "fill", shading);
if (displayDays == 7) then
ImageRect(img, x, y, cellWidth*2, cellHeight*calRows, shadingOpts);
elseif (displaydays == 6) then
ImageRect(img, x, y, cellWidth, cellHeight*calRows, shadingOpts);
end if
// ------------------------------------------------------------------
// Grid lines
// ------------------------------------------------------------------
ImageSetLineStyle (img, JSON("color", "black", "width", 1.0*fontScale, "alpha", 0.8));
// Vertical lines
for (i = 0, displayDays)
x = lm + i * cellWidth;
ImageLine (img, x, gridTop, x, gridTop + gridHeight);
end for
// Horizontal lines
for (j = 0, calRows)
y = gridTop + j * cellHeight;
ImageLine (img, lm, y, lm + displayDays * cellWidth, y);
end for
// ------------------------------------------------------------------
// Fill in the day numbers
// ------------------------------------------------------------------
date curDate;
string curDayStr;
int curDay;
JSON styleDay;
for (j = 1, calRows) // rows
for (i = 1, displayDays) // columns
// Column index (Mon–Sun) is 0..6
int colIndex = i - 1;
// Date for this cell: always based on full week (7 days),
// then we skip actually *displaying* Sat/Sun when displayDays < 7.
curDate = calFrom + colIndex + (j - 1) * 7;
curDay = int(string(curDate, "%d"));
bool isHoliday = false;
string holidayName = "";
for (k = 1 , hdays)
if ( curDate == date (holidays["a["+k+"].date"],"%Y-%m-%d")) then
isHoliday = true;
holidayName = holidays["a["+k+"].name"];
break;
end if
end for
if (! isHoliday) then
for (k = 1 , hdaysEx)
if ( curDate == date (holidayExtra["a["+k+"].date"],"%Y-%m-%d")) then
isHoliday = true;
holidayName = holidayExtra["a["+k+"].name"];
break;
end if
end for
end if
// Only show the date if the column is within displayDays
// (for 5 or 6 day weeks, last columns are simply not drawn)
if (colIndex < displayDays) then
curDayStr = string(curDay);
float cellX = lm + colIndex * cellWidth;
float cellY = gridTop + (j - 1) * cellHeight;
// Decide style: grey if outside current month
if (isHoliday) then
ImageSetFont (img, fontHoliday);
styleDay = JSON("align", "left", "valign", "top");
curDayStr += "\n"+holidayName;
elseif (int(string(curDate, "%m")) == int(ms)) then
ImageSetFont (img, fontDay);
styleDay = JSON("align", "left", "valign", "top");
else
ImageSetFont (img, fontDayDim);
styleDay = JSON("align", "left", "valign", "top");
end if
if (i>5) then
styleDay["color"] = "grey";
styleDay["alpha"] = 0.0;
end if
// Small inset inside the cell
float insetX = cellWidth * 0.08;
float insetY = cellHeight * 0.08;
ImageDrawTextBox (
img,
cellX + insetX, cellY + insetY,
cellWidth - insetX * 2, cellHeight * 0.9,
curDayStr,
styleDay
);
end if
end for
end for
// ------------------------------------------------------------------
// Save the final image
// ------------------------------------------------------------------
string outPathDir = documents_directory() + "/Calendars";
// (You might want to ensure directory exists using your filesystem utils.)
string res = create_directory(outPathDir);
string outPath = outPathDir + format("/Calendar-%s-%s-%d.png",
mnd[int(ms)], ys, int(width));
SaveImage ( img, outPath );
$$ImgPath = outPath;
$$MndName = mnd[int(ms)];
return string (img);
end
The drawCalendar Function
This function requires at least Plugin version 1.7.8.6
