Location: Unit1.pas:180-273This is the most complex procedure, responsible for rendering the contribution graph:
procedure TForm1.DrawChart;var targetYear, tmpWeek, tmpDay, tmpIntensity: Integer; tmpYear: Word; tmpDate: TDateTime; tmpDateStr, tmpIntensityStr: string; contributions: TJSONArray; iterator: TJSONIterator; tmpFormatSettings: TFormatSettings;begin Series1.Clear; Series1.Visible := False; // Configure date format for parsing tmpFormatSettings := FormatSettings; tmpFormatSettings.ShortDateFormat := 'yyyy-mm-dd'; // Validate data if (gitHubContributions = nil) or (not gitHubContributions.TryGetValue<TJSONArray>('contributions', contributions)) then Exit; if not TryStrToInt(CBYears.Items[CBYears.ItemIndex], targetYear) then Exit; // Iterate through contributions iterator := TJSONIterator.Create(TJsonObjectReader.Create(contributions)); while iterator.Next do begin iterator.Recurse; tmpDateStr := ''; tmpIntensityStr := ''; // Extract date and intensity from each contribution while iterator.Next do begin if iterator.Key = 'date' then tmpDateStr := iterator.AsString else if iterator.Key = 'intensity' then tmpIntensityStr := iterator.AsString; end; iterator.Return; // Parse and validate if (tmpDateStr = '') or not TryStrToDate(tmpDateStr, tmpDate, tmpFormatSettings) then Continue; if (tmpIntensityStr = '') or not TryStrToInt(tmpIntensityStr, tmpIntensity) then Continue; if YearOf(tmpDate) <> targetYear then Continue; // Calculate week and day position CustomWeekDayOfTheYear(tmpDate, CBFirstDayOfWeek.ItemIndex, tmpWeek, tmpDay); // Add point to series Series1.AddXY(tmpWeek, 7-tmpDay, FormatMark(tmpDate), IntensityThemeColor(tmpIntensity)); end; Series1.Visible := True; Chart1.Show; Chart1.Draw; // Position month labels for var m := 0 to Length(monthTitles)-1 do begin tmpDate := EncodeDate(targetYear, m+1, 1); with monthTitles[m] do begin Active := True; Text := TFormatSettings.Invariant.ShortMonthNames[MonthOf(tmpDate)]; Top := 8; tmpWeek := WeekOfTheYear(tmpDate, tmpYear); if tmpYear = targetYear-1 then tmpWeek := 1; Left := Chart1.Axes.Bottom.CalcPosValue(tmpWeek); end; end; // Position day labels for var d := 0 to Length(dayTitles)-1 do begin with dayTitles[d] do begin Active := True; Text := TFormatSettings.Invariant.ShortDayNames[(d+1)*2 + 1-CBFirstDayOfWeek.ItemIndex]; Left := 10; Top := Chart1.Axes.Left.CalcPosValue(6-(d*2) -1) - Abs(Font.Height div 2); end; end;end;
The Y-axis is inverted (7-tmpDay) to match GitHub’s visual layout where Sunday/Monday appears at the top.
procedure TForm1.BThemeClick(Sender: TObject);begin // Toggle theme if BTheme.Caption = 'Dark' then begin currentTheme := GithubDarkTheme; BTheme.Caption := 'Light'; end else begin currentTheme := StandardTheme; BTheme.Caption := 'Dark'; end; // Apply theme to form Self.Color := currentTheme.Background; Self.Font.Color := currentTheme.Text; EUsername.Color := currentTheme.Background; CBYears.Color := currentTheme.Background; CBFirstDayOfWeek.Color := currentTheme.Background; Chart1.Color := currentTheme.Background; // Update label colors for var i := 0 to High(monthTitles) do monthTitles[i].Shape.Font.Color := currentTheme.Text; for var i := 0 to High(dayTitles) do dayTitles[i].Shape.Font.Color := currentTheme.Text; DrawChart; // Redraw with new colorsend;
var gitHubContributions: TJSONObject; // Cached API response monthTitles: TArray<TAnnotationTool>; // Month labels (12 items) dayTitles: TArray<TAnnotationTool>; // Day labels (3 items) currentTheme: TTheme; // Active theme
These module-level variables maintain state across the application lifetime. The gitHubContributions object should be freed when the form closes to prevent memory leaks.