1130 lines
47 KiB
C#
1130 lines
47 KiB
C#
///
|
|
/// Copyright (c) 2020 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using Config.CalendarEvent;
|
|
using TBF.Resources;
|
|
|
|
namespace TBF.UI.Calendar
|
|
{
|
|
/// <summary>
|
|
/// An enumeration describing various ways to view the calendar
|
|
/// </summary>
|
|
public enum CalendarViews
|
|
{
|
|
Month = 1, /// Renders the Calendar in a month view
|
|
Day = 2 /// Renders the Calendar in a day view
|
|
}
|
|
|
|
/// <summary>
|
|
/// A Winforms Calendar Control
|
|
/// </summary>
|
|
public class CalendarCtrl : UserControl
|
|
{
|
|
private DateTime _calendarDate;
|
|
private Font _dayOfWeekFont;
|
|
private Font _daysFont;
|
|
private Font _todayFont;
|
|
private Font _dateHeaderFont;
|
|
private Font _dayViewTimeFont;
|
|
private bool _showArrowControls;
|
|
private bool _showTodayButton;
|
|
private bool _showDateInHeader;
|
|
private TodayButtonCtrl _btnToday;
|
|
private NavigateLeftButtonCtrl _btnLeft;
|
|
private NavigateRightButtonCtrl _btnRight;
|
|
private bool _showingToolTip;
|
|
private bool _showEventTooltips;
|
|
private bool _loadPresetHolidays;
|
|
private CalendarEventInstance _clickedEvent;
|
|
private bool _showHiddenEvents;
|
|
private bool _showDashedBorderOnDisabledEvents;
|
|
private bool _dimDisabledEvents;
|
|
private bool _highlightCurrentDay;
|
|
private CalendarViews _calendarView;
|
|
private readonly ScrollPanelCtrl _scrollPanel;
|
|
|
|
private readonly List<ICalendarEvent> _events;
|
|
private readonly List<Rectangle> _rectangles;
|
|
private readonly Dictionary<int, Point> _calendarDays;
|
|
private readonly List<CalendarEventInstance> _eventInstances;
|
|
private readonly EventToolTipCtrl _eventTip;
|
|
private ContextMenuStrip _contextMenuStrip1;
|
|
private System.ComponentModel.IContainer components;
|
|
private ToolStripMenuItem _miProperties;
|
|
|
|
private const int MarginSize = 20;
|
|
|
|
/// <summary>
|
|
/// Indicates the font for the times on the day view
|
|
/// </summary>
|
|
public Font DayViewTimeFont
|
|
{
|
|
get { return _dayViewTimeFont; }
|
|
set
|
|
{
|
|
_dayViewTimeFont = value;
|
|
if (_calendarView == CalendarViews.Day)
|
|
_scrollPanel.Refresh();
|
|
else
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates the type of calendar to render, Month or Day view
|
|
/// </summary>
|
|
public CalendarViews CalendarView
|
|
{
|
|
get { return _calendarView; }
|
|
set
|
|
{
|
|
_calendarView = value;
|
|
_scrollPanel.Visible = value == CalendarViews.Day;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether today's date should be highlighted
|
|
/// </summary>
|
|
public bool HighlightCurrentDay
|
|
{
|
|
get { return _highlightCurrentDay; }
|
|
set
|
|
{
|
|
_highlightCurrentDay = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether events can be right-clicked and edited
|
|
/// </summary>
|
|
public bool AllowEditingEvents
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether disabled events will appear as "dimmed".
|
|
/// This property is only used if <see cref="ShowDisabledEvents"/> is set to true.
|
|
/// </summary>
|
|
public bool DimDisabledEvents
|
|
{
|
|
get { return _dimDisabledEvents; }
|
|
set
|
|
{
|
|
_dimDisabledEvents = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates if a dashed border should show up around disabled events.
|
|
/// This property is only used if <see cref="ShowDisabledEvents"/> is set to true.
|
|
/// </summary>
|
|
public bool ShowDashedBorderOnDisabledEvents
|
|
{
|
|
get { return _showDashedBorderOnDisabledEvents; }
|
|
set
|
|
{
|
|
_showDashedBorderOnDisabledEvents = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether disabled events should show up on the calendar control
|
|
/// </summary>
|
|
public bool ShowDisabledEvents
|
|
{
|
|
get { return _showHiddenEvents; }
|
|
set
|
|
{
|
|
_showHiddenEvents = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether Federal Holidays are automatically preloaded onto the calendar
|
|
/// </summary>
|
|
public bool LoadPresetHolidays
|
|
{
|
|
get { return _loadPresetHolidays; }
|
|
set
|
|
{
|
|
_loadPresetHolidays = value;
|
|
if (_loadPresetHolidays)
|
|
{
|
|
_events.Clear();
|
|
PresetHolidays();
|
|
Refresh();
|
|
}
|
|
else
|
|
{
|
|
_events.Clear();
|
|
Refresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether hovering over an event will display a tooltip of the event
|
|
/// </summary>
|
|
public bool ShowEventTooltips
|
|
{
|
|
get { return _showEventTooltips; }
|
|
set { _showEventTooltips = value; _eventTip.Visible = false; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get or Set this value to the Font you wish to use to render the date in the upper right corner
|
|
/// </summary>
|
|
public Font DateHeaderFont
|
|
{
|
|
get { return _dateHeaderFont; }
|
|
set
|
|
{
|
|
_dateHeaderFont = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether the date should be displayed in the upper right hand corner of the calendar control
|
|
/// </summary>
|
|
public bool ShowDateInHeader
|
|
{
|
|
get { return _showDateInHeader; }
|
|
set
|
|
{
|
|
_showDateInHeader = value;
|
|
if (_calendarView == CalendarViews.Day)
|
|
ResizeScrollPanel();
|
|
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether the calendar control should render the previous/next month buttons
|
|
/// </summary>
|
|
public bool ShowArrowControls
|
|
{
|
|
get { return _showArrowControls; }
|
|
set
|
|
{
|
|
_showArrowControls = value;
|
|
_btnLeft.Visible = value;
|
|
_btnRight.Visible = value;
|
|
if (_calendarView == CalendarViews.Day)
|
|
ResizeScrollPanel();
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates whether the calendar control should render the Today button
|
|
/// </summary>
|
|
public bool ShowTodayButton
|
|
{
|
|
get { return _showTodayButton; }
|
|
set
|
|
{
|
|
_showTodayButton = value;
|
|
_btnToday.Visible = value;
|
|
if (_calendarView == CalendarViews.Day)
|
|
ResizeScrollPanel();
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The font used to render the Today button
|
|
/// </summary>
|
|
public Font TodayFont
|
|
{
|
|
get { return _todayFont; }
|
|
set
|
|
{
|
|
_todayFont = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The font used to render the number days on the calendar
|
|
/// </summary>
|
|
public Font DaysFont
|
|
{
|
|
get { return _daysFont; }
|
|
set
|
|
{
|
|
_daysFont = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The font used to render the days of the week text
|
|
/// </summary>
|
|
public Font DayOfWeekFont
|
|
{
|
|
get { return _dayOfWeekFont; }
|
|
set
|
|
{
|
|
_dayOfWeekFont = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The Date that the calendar is currently showing
|
|
/// </summary>
|
|
public DateTime CalendarDate
|
|
{
|
|
get { return _calendarDate; }
|
|
set
|
|
{
|
|
_calendarDate = value;
|
|
Refresh();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calendar Constructor
|
|
/// </summary>
|
|
public CalendarCtrl()
|
|
{
|
|
InitializeComponent();
|
|
|
|
_events = new List<ICalendarEvent>();
|
|
_rectangles = new List<Rectangle>();
|
|
_calendarDays = new Dictionary<int, Point>();
|
|
_eventInstances = new List<CalendarEventInstance>();
|
|
|
|
_calendarDate = DateTime.Now;
|
|
_dayOfWeekFont = new Font("Verdana", 10, FontStyle.Regular);
|
|
_daysFont = new Font("Verdana", 10, FontStyle.Regular);
|
|
_todayFont = new Font("Verdana", 10, FontStyle.Bold);
|
|
_dateHeaderFont = new Font("Verdana", 12, FontStyle.Bold);
|
|
_dayViewTimeFont = new Font("Verdana", 10, FontStyle.Bold);
|
|
_showArrowControls = true;
|
|
_showDateInHeader = true;
|
|
_showTodayButton = true;
|
|
_showingToolTip = false;
|
|
_clickedEvent = null;
|
|
|
|
_showHiddenEvents = true;
|
|
_showDashedBorderOnDisabledEvents = false;
|
|
_dimDisabledEvents = true;
|
|
|
|
AllowEditingEvents = true;
|
|
_highlightCurrentDay = true;
|
|
_calendarView = CalendarViews.Month;
|
|
_scrollPanel = new ScrollPanelCtrl();
|
|
|
|
_scrollPanel.RightButtonClicked += ScrollPanelRightButtonClicked;
|
|
|
|
_showEventTooltips = true;
|
|
_eventTip = new EventToolTipCtrl { Visible = false };
|
|
|
|
Controls.Add(_eventTip);
|
|
|
|
LoadPresetHolidays = false;
|
|
|
|
_scrollPanel.Visible = false;
|
|
Controls.Add(_scrollPanel);
|
|
|
|
Refresh();
|
|
}
|
|
|
|
private void InitializeComponent()
|
|
{
|
|
this.components = new System.ComponentModel.Container();
|
|
this._contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
|
this._miProperties = new System.Windows.Forms.ToolStripMenuItem();
|
|
this._btnRight = new TBF.UI.Calendar.NavigateRightButtonCtrl();
|
|
this._btnLeft = new TBF.UI.Calendar.NavigateLeftButtonCtrl();
|
|
this._btnToday = new TBF.UI.Calendar.TodayButtonCtrl();
|
|
this._contextMenuStrip1.SuspendLayout();
|
|
this.SuspendLayout();
|
|
//
|
|
// _contextMenuStrip1
|
|
//
|
|
this._contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
|
this._miProperties});
|
|
this._contextMenuStrip1.Name = "_contextMenuStrip1";
|
|
this._contextMenuStrip1.Size = new System.Drawing.Size(137, 26);
|
|
//
|
|
// _miProperties
|
|
//
|
|
this._miProperties.Name = "_miProperties";
|
|
this._miProperties.Size = new System.Drawing.Size(136, 22);
|
|
this._miProperties.Text = "Properties...";
|
|
this._miProperties.Click += new System.EventHandler(this.MenuItemPropertiesClick);
|
|
//
|
|
// _btnRight
|
|
//
|
|
this._btnRight.BackColor = System.Drawing.Color.Transparent;
|
|
this._btnRight.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220)))));
|
|
this._btnRight.ButtonColor = System.Drawing.Color.FromArgb(((int)(((byte)(243)))), ((int)(((byte)(243)))), ((int)(((byte)(243)))));
|
|
this._btnRight.ButtonFont = new System.Drawing.Font("Verdana", 8F, System.Drawing.FontStyle.Bold);
|
|
this._btnRight.ButtonText = ">";
|
|
this._btnRight.FocusColor = System.Drawing.Color.FromArgb(((int)(((byte)(77)))), ((int)(((byte)(144)))), ((int)(((byte)(254)))));
|
|
this._btnRight.HighlightBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(198)))), ((int)(((byte)(198)))), ((int)(((byte)(198)))));
|
|
this._btnRight.HighlightButtonColor = System.Drawing.Color.FromArgb(((int)(((byte)(246)))), ((int)(((byte)(246)))), ((int)(((byte)(246)))));
|
|
this._btnRight.Location = new System.Drawing.Point(138, 20);
|
|
this._btnRight.Name = "_btnRight";
|
|
this._btnRight.Size = new System.Drawing.Size(42, 29);
|
|
this._btnRight.TabIndex = 2;
|
|
this._btnRight.TextColor = System.Drawing.Color.Black;
|
|
this._btnRight.ButtonClicked += new Common.UIControls.CoolButtonCtrl.ButtonClickedArgs(this.BtnRightButtonClicked);
|
|
//
|
|
// _btnLeft
|
|
//
|
|
this._btnLeft.BackColor = System.Drawing.Color.Transparent;
|
|
this._btnLeft.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220)))));
|
|
this._btnLeft.ButtonColor = System.Drawing.Color.FromArgb(((int)(((byte)(243)))), ((int)(((byte)(243)))), ((int)(((byte)(243)))));
|
|
this._btnLeft.ButtonFont = new System.Drawing.Font("Verdana", 8F, System.Drawing.FontStyle.Bold);
|
|
this._btnLeft.ButtonText = "<";
|
|
this._btnLeft.FocusColor = System.Drawing.Color.FromArgb(((int)(((byte)(77)))), ((int)(((byte)(144)))), ((int)(((byte)(254)))));
|
|
this._btnLeft.HighlightBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(198)))), ((int)(((byte)(198)))), ((int)(((byte)(198)))));
|
|
this._btnLeft.HighlightButtonColor = System.Drawing.Color.FromArgb(((int)(((byte)(246)))), ((int)(((byte)(246)))), ((int)(((byte)(246)))));
|
|
this._btnLeft.Location = new System.Drawing.Point(98, 20);
|
|
this._btnLeft.Name = "_btnLeft";
|
|
this._btnLeft.Size = new System.Drawing.Size(42, 29);
|
|
this._btnLeft.TabIndex = 1;
|
|
this._btnLeft.TextColor = System.Drawing.Color.Black;
|
|
this._btnLeft.ButtonClicked += new Common.UIControls.CoolButtonCtrl.ButtonClickedArgs(this.BtnLeftButtonClicked);
|
|
//
|
|
// _btnToday
|
|
//
|
|
this._btnToday.BackColor = System.Drawing.Color.Transparent;
|
|
this._btnToday.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220)))));
|
|
this._btnToday.ButtonColor = System.Drawing.Color.FromArgb(((int)(((byte)(243)))), ((int)(((byte)(243)))), ((int)(((byte)(243)))));
|
|
this._btnToday.ButtonFont = new System.Drawing.Font("Verdana", 8F, System.Drawing.FontStyle.Bold);
|
|
this._btnToday.ButtonText = "Today";
|
|
this._btnToday.FocusColor = System.Drawing.Color.FromArgb(((int)(((byte)(77)))), ((int)(((byte)(144)))), ((int)(((byte)(254)))));
|
|
this._btnToday.HighlightBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(198)))), ((int)(((byte)(198)))), ((int)(((byte)(198)))));
|
|
this._btnToday.HighlightButtonColor = System.Drawing.Color.FromArgb(((int)(((byte)(246)))), ((int)(((byte)(246)))), ((int)(((byte)(246)))));
|
|
this._btnToday.Location = new System.Drawing.Point(19, 20);
|
|
this._btnToday.Name = "_btnToday";
|
|
this._btnToday.Size = new System.Drawing.Size(72, 29);
|
|
this._btnToday.TabIndex = 0;
|
|
this._btnToday.TextColor = System.Drawing.Color.Black;
|
|
this._btnToday.ButtonClicked += new Common.UIControls.CoolButtonCtrl.ButtonClickedArgs(this.BtnTodayButtonClicked);
|
|
//
|
|
// CalendarCtrl
|
|
//
|
|
this.Controls.Add(this._btnRight);
|
|
this.Controls.Add(this._btnLeft);
|
|
this.Controls.Add(this._btnToday);
|
|
this.DoubleBuffered = true;
|
|
this.Name = "CalendarCtrl";
|
|
this.Size = new System.Drawing.Size(512, 512);
|
|
this.Load += new System.EventHandler(this.CalendarLoad);
|
|
this.Paint += new System.Windows.Forms.PaintEventHandler(this.CalendarPaint);
|
|
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.CalendarMouseClick);
|
|
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.CalendarMouseMove);
|
|
this.Resize += new System.EventHandler(this.CalendarResize);
|
|
this._contextMenuStrip1.ResumeLayout(false);
|
|
this.ResumeLayout(false);
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears all calendar events
|
|
/// </summary>
|
|
/// <param name="calendarEvent">The <see cref="ICalendarEvent"/> to add to the calendar</param>
|
|
public void ClearEvents()
|
|
{
|
|
_events.Clear();
|
|
Refresh();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds an event to the calendar
|
|
/// </summary>
|
|
/// <param name="calendarEvent">The <see cref="ICalendarEvent"/> to add to the calendar</param>
|
|
public void AddEvent(ICalendarEvent calendarEvent)
|
|
{
|
|
_events.Add(calendarEvent);
|
|
Refresh();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes an event from the calendar
|
|
/// </summary>
|
|
/// <param name="calendarEvent">The <see cref="ICalendarEvent"/> to remove to the calendar</param>
|
|
public void RemoveEvent(ICalendarEvent calendarEvent)
|
|
{
|
|
_events.Remove(calendarEvent);
|
|
Refresh();
|
|
}
|
|
|
|
private void CalendarLoad(object sender, EventArgs e)
|
|
{
|
|
if (Parent != null)
|
|
Parent.Resize += ParentResize;
|
|
ResizeScrollPanel();
|
|
}
|
|
|
|
private void CalendarPaint(object sender, PaintEventArgs e)
|
|
{
|
|
if (_showingToolTip)
|
|
return;
|
|
|
|
if (_calendarView == CalendarViews.Month)
|
|
{
|
|
RenderMonthCalendar(e);
|
|
}
|
|
else if (_calendarView == CalendarViews.Day)
|
|
{
|
|
RenderDayCalendar(e);
|
|
}
|
|
}
|
|
|
|
private void CalendarMouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (!_showEventTooltips)
|
|
return;
|
|
|
|
foreach (var evInst in _eventInstances)
|
|
{
|
|
if ((evInst.EventArea.Contains(e.X, e.Y) && evInst.Event.TooltipEnabled && _calendarView == CalendarViews.Month) ||
|
|
(_calendarView == CalendarViews.Day && evInst.EventArea.Contains(e.X, e.Y + _scrollPanel.ScrollOffset) && evInst.Event.TooltipEnabled))
|
|
{
|
|
_eventTip.ShouldRender = false;
|
|
_showingToolTip = true;
|
|
_eventTip.EventToolTipText = evInst.Event.ToString();
|
|
if (evInst.Event.AllDay == false)
|
|
_eventTip.EventToolTipText += "\n" + evInst.Event.Date.ToShortTimeString();
|
|
_eventTip.Location = new Point(e.X + 5, e.Y - _eventTip.CalculateSize().Height);
|
|
_eventTip.ShouldRender = true;
|
|
_eventTip.Visible = true;
|
|
|
|
_showingToolTip = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
_eventTip.Visible = false;
|
|
_eventTip.ShouldRender = false;
|
|
}
|
|
|
|
private void ScrollPanelRightButtonClicked(object sender, MouseEventArgs e)
|
|
{
|
|
if (AllowEditingEvents && _calendarView == CalendarViews.Day)
|
|
{
|
|
foreach (var evInst in _eventInstances)
|
|
{
|
|
if (evInst.EventArea.Contains(e.X, e.Y + _scrollPanel.ScrollOffset) && !evInst.Event.ReadOnly)
|
|
{
|
|
_clickedEvent = evInst;
|
|
_contextMenuStrip1.Show(_scrollPanel, new Point(e.X, e.Y));
|
|
_eventTip.Visible = false;
|
|
_eventTip.ShouldRender = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CalendarMouseClick(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Right && AllowEditingEvents && _calendarView == CalendarViews.Month)
|
|
{
|
|
foreach (var evInst in _eventInstances)
|
|
{
|
|
if (evInst.EventArea.Contains(e.X, e.Y) && !evInst.Event.ReadOnly)
|
|
{
|
|
_clickedEvent = evInst;
|
|
_contextMenuStrip1.Show(this, e.Location);
|
|
_eventTip.Visible = false;
|
|
_eventTip.ShouldRender = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void BtnTodayButtonClicked(object sender)
|
|
{
|
|
_calendarDate = DateTime.Now;
|
|
Refresh();
|
|
}
|
|
|
|
private void BtnLeftButtonClicked(object sender)
|
|
{
|
|
if (_calendarView == CalendarViews.Month)
|
|
_calendarDate = _calendarDate.AddMonths(-1);
|
|
else if (_calendarView == CalendarViews.Day)
|
|
_calendarDate = _calendarDate.AddDays(-1);
|
|
Refresh();
|
|
}
|
|
|
|
private void BtnRightButtonClicked(object sender)
|
|
{
|
|
if (_calendarView == CalendarViews.Day)
|
|
_calendarDate = _calendarDate.AddDays(1);
|
|
else if (_calendarView == CalendarViews.Month)
|
|
_calendarDate = _calendarDate.AddMonths(1);
|
|
Refresh();
|
|
}
|
|
|
|
private void MenuItemPropertiesClick(object sender, EventArgs e)
|
|
{
|
|
if (_clickedEvent == null)
|
|
return;
|
|
|
|
var ed = new EventDetailsForm { Event = _clickedEvent.Event };
|
|
|
|
if (ed.ShowDialog(this) == DialogResult.OK)
|
|
{
|
|
_events.Remove(_clickedEvent.Event);
|
|
_events.Add(ed.NewEvent);
|
|
Refresh();
|
|
}
|
|
_clickedEvent = null;
|
|
}
|
|
|
|
private void ParentResize(object sender, EventArgs e)
|
|
{
|
|
ResizeScrollPanel();
|
|
Refresh();
|
|
}
|
|
|
|
private void PresetHolidays()
|
|
{
|
|
var aprilFools = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 4, 1),
|
|
Frequency = Frequency.Yearly,
|
|
Title = "April Fools Day"
|
|
};
|
|
AddEvent(aprilFools);
|
|
|
|
var memorialDay = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 5, 28),
|
|
Frequency = Frequency.Custom,
|
|
Title = "Memorial Day",
|
|
CustomRecurringFunction = MemorialDayHandler
|
|
};
|
|
AddEvent(memorialDay);
|
|
|
|
var newYears = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 1, 1),
|
|
Frequency = Frequency.Yearly,
|
|
Title = "New Years Day"
|
|
};
|
|
AddEvent(newYears);
|
|
|
|
var mlkDay = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 1, 15),
|
|
Frequency = Frequency.Custom,
|
|
Title = "Martin Luther King Jr. Day",
|
|
CustomRecurringFunction = MlkDayHandler
|
|
};
|
|
AddEvent(mlkDay);
|
|
|
|
var presidentsDay = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 2, 15),
|
|
Frequency = Frequency.Custom,
|
|
Title = "President's Day",
|
|
CustomRecurringFunction = MlkDayHandler
|
|
};
|
|
AddEvent(presidentsDay);
|
|
|
|
var independanceDay = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 7, 4),
|
|
Frequency = Frequency.Yearly,
|
|
Title = "Independence Day"
|
|
};
|
|
AddEvent(independanceDay);
|
|
|
|
var laborDay = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 9, 1),
|
|
Frequency = Frequency.Custom,
|
|
Title = "Labor Day",
|
|
CustomRecurringFunction = LaborDayHandler
|
|
};
|
|
AddEvent(laborDay);
|
|
|
|
var columbusDay = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 10, 14),
|
|
Frequency = Frequency.Custom,
|
|
Title = "Columbus Day",
|
|
CustomRecurringFunction = ColumbusDayHandler
|
|
};
|
|
AddEvent(columbusDay);
|
|
|
|
var veteransDay = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 11, 11),
|
|
Frequency = Frequency.Yearly,
|
|
Title = "Veteran's Day"
|
|
};
|
|
AddEvent(veteransDay);
|
|
|
|
var thanksgivingDay = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 11, 11),
|
|
Frequency = Frequency.Custom,
|
|
Title = "Thanksgiving Day",
|
|
CustomRecurringFunction = ThanksgivingDayHandler
|
|
};
|
|
AddEvent(thanksgivingDay);
|
|
|
|
var christmas = new HolidayEvent
|
|
{
|
|
Date = new DateTime(DateTime.Now.Year, 12, 25),
|
|
Frequency = Frequency.Yearly,
|
|
Title = "Christmas Day"
|
|
};
|
|
AddEvent(christmas);
|
|
}
|
|
|
|
[CustomRecurringFunction("Thanksgiving Day Handler", "Selects the fourth Thursday in the month")]
|
|
private bool ThanksgivingDayHandler(ICalendarEvent evnt, DateTime dt)
|
|
{
|
|
if (dt.DayOfWeek == DayOfWeek.Thursday && dt.Day > 21 && dt.Day <= 28 && dt.Month == evnt.Date.Month)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
[CustomRecurringFunction("Columbus Day Handler", "Selects the second Monday in the month")]
|
|
private bool ColumbusDayHandler(ICalendarEvent evnt, DateTime dt)
|
|
{
|
|
if (dt.DayOfWeek == DayOfWeek.Monday && dt.Day > 7 && dt.Day <= 14 && dt.Month == evnt.Date.Month)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
[CustomRecurringFunction("Labor Day Handler", "Selects the first Monday in the month")]
|
|
private bool LaborDayHandler(ICalendarEvent evnt, DateTime dt)
|
|
{
|
|
if (dt.DayOfWeek == DayOfWeek.Monday && dt.Day <= 7 && dt.Month == evnt.Date.Month)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
[CustomRecurringFunction("Martin Luther King Jr. Day Handler", "Selects the third Monday in the month")]
|
|
private bool MlkDayHandler(ICalendarEvent evnt, DateTime dt)
|
|
{
|
|
if (dt.DayOfWeek == DayOfWeek.Monday && dt.Day > 14 && dt.Day <= 21 && dt.Month == evnt.Date.Month)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
[CustomRecurringFunction("Memorial Day Handler", "Selects the last Monday in the month")]
|
|
private bool MemorialDayHandler(ICalendarEvent evnt, DateTime dt)
|
|
{
|
|
DateTime dt2 = LastDayOfWeekInMonth(dt, DayOfWeek.Monday);
|
|
if (dt.Month == evnt.Date.Month && dt2.Day == dt.Date.Day)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
private DateTime LastDayOfWeekInMonth(DateTime day, DayOfWeek dow)
|
|
{
|
|
DateTime lastDay = new DateTime(day.Year, day.Month, 1).AddMonths(1).AddDays(-1);
|
|
DayOfWeek lastDow = lastDay.DayOfWeek;
|
|
|
|
int diff = dow - lastDow;
|
|
|
|
if (diff > 0) diff -= 7;
|
|
|
|
System.Diagnostics.Debug.Assert(diff <= 0);
|
|
|
|
return lastDay.AddDays(diff);
|
|
}
|
|
|
|
private int Max(params float[] value)
|
|
{
|
|
return (int)value.Max(i => Math.Ceiling(i));
|
|
}
|
|
|
|
internal Bitmap RequestImage()
|
|
{
|
|
const int cellHourWidth = 60;
|
|
const int cellHourHeight = 30;
|
|
var bmp = new Bitmap(ClientSize.Width, cellHourWidth * 24);
|
|
Graphics g = Graphics.FromImage(bmp);
|
|
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
|
|
|
|
var dt = new DateTime(_calendarDate.Year, _calendarDate.Month, _calendarDate.Day, 0, 0, 0);
|
|
int xStart = 0;
|
|
int yStart = 0;
|
|
|
|
g.DrawRectangle(Pens.Black, 0, 0, ClientSize.Width - MarginSize * 2 - 2, cellHourHeight * 24);
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
var textWidth = (int)g.MeasureString(dt.ToString("htt").ToLower(), _dayViewTimeFont).Width;
|
|
g.DrawRectangle(Pens.Black, xStart, yStart, cellHourWidth, cellHourHeight);
|
|
g.DrawLine(Pens.Black, xStart + cellHourWidth, yStart + cellHourHeight,
|
|
ClientSize.Width - MarginSize * 2 - 3, yStart + cellHourHeight);
|
|
g.DrawLine(Pens.DarkGray, xStart + cellHourWidth, yStart + cellHourHeight / 2,
|
|
ClientSize.Width - MarginSize * 2 - 3, yStart + cellHourHeight / 2);
|
|
|
|
g.DrawString(dt.ToString("htt").ToLower(), _dayViewTimeFont, Brushes.Black, xStart + cellHourWidth - textWidth, yStart);
|
|
yStart += cellHourHeight;
|
|
dt = dt.AddHours(1);
|
|
}
|
|
|
|
dt = new DateTime(_calendarDate.Year, _calendarDate.Month, _calendarDate.Day, 23, 59, 0);
|
|
|
|
List<ICalendarEvent> evnts = _events.Where(e => (!e.Hidden || _showHiddenEvents) && Config.CalendarEvent.Utils.DayMatchesExactly(e, dt))
|
|
.ToList()
|
|
.OrderBy(d => d.Date)
|
|
.ToList();
|
|
|
|
xStart = cellHourWidth + 1;
|
|
yStart = 0;
|
|
|
|
g.Clip = new Region(new Rectangle(0, 0, ClientSize.Width - MarginSize * 2 - 2, cellHourHeight * 24));
|
|
_eventInstances.Clear();
|
|
for (int i = 0; i < 24; i++)
|
|
{
|
|
dt = new DateTime(_calendarDate.Year, _calendarDate.Month, _calendarDate.Day, 0, 0, 0);
|
|
dt = dt.AddHours(i);
|
|
foreach (var evnt in evnts)
|
|
{
|
|
TimeSpan ts = TimeSpan.FromHours(1);
|
|
|
|
if (evnt.Date.Ticks >= dt.Ticks && evnt.Date.Ticks < dt.Add(ts).Ticks && i >= evnt.Date.Hour)
|
|
{
|
|
int divisor = evnt.Date.Minute == 0 ? 1 : 60 / evnt.Date.Minute;
|
|
Color clr = Color.FromArgb((evnt.BackColor & 0x7FFFFFFF) | unchecked((int)0xAF000000));
|
|
g.FillRectangle(new SolidBrush(GetFinalBackColor()), xStart, yStart + cellHourHeight / divisor + 1, ClientSize.Width - MarginSize * 2 - cellHourWidth - 3, cellHourHeight * ts.Hours - 1);
|
|
g.FillRectangle(new SolidBrush(clr), xStart, yStart + cellHourHeight / divisor + 1, ClientSize.Width - MarginSize * 2 - cellHourWidth - 3, cellHourHeight * ts.Hours - 1);
|
|
g.DrawString(evnt.ToString(),
|
|
new Font("Verdana", 8, FontStyle.Bold),
|
|
new SolidBrush(Color.FromArgb(evnt.TextColor)),
|
|
xStart,
|
|
yStart + cellHourHeight / divisor);
|
|
|
|
_eventInstances.Add(new CalendarEventInstance { Event = evnt,
|
|
EventArea = new Rectangle(xStart, yStart + cellHourHeight / divisor + 1,
|
|
ClientSize.Width - MarginSize * 2 - cellHourWidth - 3,
|
|
cellHourHeight * ts.Hours),
|
|
Date = dt });
|
|
}
|
|
}
|
|
yStart += cellHourHeight;
|
|
}
|
|
|
|
g.Dispose();
|
|
return bmp;
|
|
}
|
|
|
|
private Color GetFinalBackColor()
|
|
{
|
|
Control c = this;
|
|
|
|
while (c != null)
|
|
{
|
|
if (c.BackColor != Color.Transparent)
|
|
return c.BackColor;
|
|
c = c.Parent;
|
|
}
|
|
|
|
return Color.Transparent;
|
|
}
|
|
|
|
private void ResizeScrollPanel()
|
|
{
|
|
int controlsSpacing = ((!_showTodayButton) && (!_showDateInHeader) && (!_showArrowControls)) ? 0 : 30;
|
|
|
|
_scrollPanel.Location = new Point(MarginSize, MarginSize + controlsSpacing);
|
|
_scrollPanel.Size = new Size(ClientSize.Width - MarginSize * 2 - 1, ClientSize.Height - MarginSize - 1 - controlsSpacing);
|
|
}
|
|
|
|
private void RenderDayCalendar(PaintEventArgs e)
|
|
{
|
|
Graphics g = e.Graphics;
|
|
if (_showDateInHeader)
|
|
{
|
|
SizeF dateHeaderSize = g.MeasureString(
|
|
_calendarDate.ToString("MMMM") + " " + _calendarDate.Day.ToString(CultureInfo.InvariantCulture) +
|
|
", " + _calendarDate.Year.ToString(CultureInfo.InvariantCulture), DateHeaderFont);
|
|
|
|
g.DrawString(
|
|
_calendarDate.ToString("MMMM") + " " + _calendarDate.Day.ToString(CultureInfo.InvariantCulture) +
|
|
", " + _calendarDate.Year.ToString(CultureInfo.InvariantCulture),
|
|
_dateHeaderFont, Brushes.Black, ClientSize.Width - MarginSize - dateHeaderSize.Width,
|
|
MarginSize);
|
|
}
|
|
}
|
|
|
|
private void RenderMonthCalendar(PaintEventArgs e)
|
|
{
|
|
_calendarDays.Clear();
|
|
_eventInstances.Clear();
|
|
|
|
var bmp = new Bitmap(ClientSize.Width, ClientSize.Height);
|
|
Graphics g = Graphics.FromImage(bmp);
|
|
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
|
|
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
|
|
SizeF monSize = g.MeasureString(Strings.Mon, _dayOfWeekFont);
|
|
SizeF tueSize = g.MeasureString(Strings.Tue, _dayOfWeekFont);
|
|
SizeF wedSize = g.MeasureString(Strings.Wed, _dayOfWeekFont);
|
|
SizeF thuSize = g.MeasureString(Strings.Thu, _dayOfWeekFont);
|
|
SizeF friSize = g.MeasureString(Strings.Fri, _dayOfWeekFont);
|
|
SizeF satSize = g.MeasureString(Strings.Sat, _dayOfWeekFont);
|
|
SizeF sunSize = g.MeasureString(Strings.Sun, _dayOfWeekFont);
|
|
|
|
SizeF dateHeaderSize = g.MeasureString(_calendarDate.ToString("MMMM") + " " + _calendarDate.Year.ToString(CultureInfo.InvariantCulture),
|
|
_dateHeaderFont);
|
|
int headerSpacing = Max(sunSize.Height, monSize.Height, tueSize.Height, wedSize.Height, thuSize.Height, friSize.Height, satSize.Height) + 5;
|
|
int controlsSpacing = ((!_showTodayButton) && (!_showDateInHeader) && (!_showArrowControls)) ? 0 : 30;
|
|
int cellWidth = (ClientSize.Width - MarginSize * 2) / 7;
|
|
int numWeeks = NumberOfWeeks(_calendarDate.Year, _calendarDate.Month);
|
|
int cellHeight = (ClientSize.Height - MarginSize * 2 - headerSpacing - controlsSpacing) / numWeeks;
|
|
int xStart = MarginSize;
|
|
int yStart = MarginSize;
|
|
|
|
DayOfWeek startWeekEnum = new DateTime(_calendarDate.Year, _calendarDate.Month, 1).DayOfWeek;
|
|
int startWeek;
|
|
if (CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek == DayOfWeek.Monday)
|
|
{
|
|
startWeek = startWeekEnum == DayOfWeek.Sunday ? 7 : (int)startWeekEnum;
|
|
}
|
|
else
|
|
{
|
|
startWeek = (int)startWeekEnum + 1;
|
|
}
|
|
int rogueDays = startWeek - 1;
|
|
|
|
yStart += headerSpacing + controlsSpacing;
|
|
|
|
int counter = 1;
|
|
int counter2 = 1;
|
|
|
|
bool first = false;
|
|
bool first2 = false;
|
|
|
|
_btnToday.Location = new Point(MarginSize, MarginSize);
|
|
|
|
///
|
|
/// Draw the month frame without calendar events
|
|
///
|
|
for (int y = 0; y < numWeeks; y++)
|
|
{
|
|
for (int x = 0; x < 7; x++)
|
|
{
|
|
if (rogueDays == 0 && counter <= DateTime.DaysInMonth(_calendarDate.Year, _calendarDate.Month))
|
|
{
|
|
if (!_calendarDays.ContainsKey(counter))
|
|
_calendarDays.Add(counter, new Point(xStart, (int)(yStart + 2f + g.MeasureString(counter.ToString(CultureInfo.InvariantCulture), _daysFont).Height)));
|
|
|
|
if (_calendarDate.Year == DateTime.Now.Year && _calendarDate.Month == DateTime.Now.Month
|
|
&& counter == DateTime.Now.Day && _highlightCurrentDay)
|
|
{
|
|
/// Highlight current day
|
|
g.FillRectangle(new SolidBrush(Color.FromArgb(234, 234, 234)), xStart, yStart, cellWidth, cellHeight);
|
|
}
|
|
|
|
if (first == false)
|
|
{
|
|
first = true;
|
|
if (_calendarDate.Year == DateTime.Now.Year && _calendarDate.Month == DateTime.Now.Month && counter == DateTime.Now.Day)
|
|
{
|
|
g.DrawString(_calendarDate.ToString("MMM") + " " + counter.ToString(CultureInfo.InvariantCulture),
|
|
_todayFont, Brushes.Black, xStart + 5, yStart + 2);
|
|
}
|
|
else
|
|
{
|
|
g.DrawString(_calendarDate.ToString("MMM") + " " + counter.ToString(CultureInfo.InvariantCulture),
|
|
_daysFont, Brushes.Black, xStart + 5, yStart + 2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_calendarDate.Year == DateTime.Now.Year && _calendarDate.Month == DateTime.Now.Month && counter == DateTime.Now.Day)
|
|
{
|
|
g.DrawString(counter.ToString(CultureInfo.InvariantCulture), _todayFont, Brushes.Black, xStart + 5, yStart + 2);
|
|
}
|
|
else
|
|
{
|
|
g.DrawString(counter.ToString(CultureInfo.InvariantCulture), _daysFont, Brushes.Black, xStart + 5, yStart + 2);
|
|
}
|
|
}
|
|
counter++;
|
|
}
|
|
else if (rogueDays > 0)
|
|
{
|
|
int dm =
|
|
DateTime.DaysInMonth(_calendarDate.AddMonths(-1).Year, _calendarDate.AddMonths(-1).Month) -
|
|
rogueDays + 1;
|
|
g.DrawString(dm.ToString(CultureInfo.InvariantCulture), _daysFont, new SolidBrush(Color.FromArgb(170, 170, 170)), xStart + 5, yStart + 2);
|
|
rogueDays--;
|
|
}
|
|
|
|
g.DrawRectangle(Pens.DarkGray, xStart, yStart, cellWidth, cellHeight);
|
|
if (rogueDays == 0 && counter > DateTime.DaysInMonth(_calendarDate.Year, _calendarDate.Month))
|
|
{
|
|
if (first2 == false)
|
|
first2 = true;
|
|
else
|
|
{
|
|
if (counter2 == 1)
|
|
{
|
|
g.DrawString(_calendarDate.AddMonths(1).ToString("MMM") + " " + counter2.ToString(CultureInfo.InvariantCulture), _daysFont,
|
|
new SolidBrush(Color.FromArgb(170, 170, 170)), xStart + 5, yStart + 2);
|
|
}
|
|
else
|
|
{
|
|
g.DrawString(counter2.ToString(CultureInfo.InvariantCulture), _daysFont,
|
|
new SolidBrush(Color.FromArgb(170, 170, 170)), xStart + 5, yStart + 2);
|
|
}
|
|
counter2++;
|
|
}
|
|
}
|
|
xStart += cellWidth;
|
|
}
|
|
xStart = MarginSize;
|
|
yStart += cellHeight;
|
|
}
|
|
|
|
yStart = MarginSize + controlsSpacing;
|
|
if (CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek == DayOfWeek.Monday)
|
|
{
|
|
g.DrawString(Strings.Mon, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)monSize.Width) / 2) + 0 * cellWidth, yStart);
|
|
g.DrawString(Strings.Tue, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)tueSize.Width) / 2) + 1 * cellWidth, yStart);
|
|
g.DrawString(Strings.Wed, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)wedSize.Width) / 2) + 2 * cellWidth, yStart);
|
|
g.DrawString(Strings.Thu, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)thuSize.Width) / 2) + 3 * cellWidth, yStart);
|
|
g.DrawString(Strings.Fri, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)friSize.Width) / 2) + 4 * cellWidth, yStart);
|
|
g.DrawString(Strings.Sat, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)satSize.Width) / 2) + 5 * cellWidth, yStart);
|
|
g.DrawString(Strings.Sun, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)sunSize.Width) / 2) + 6 * cellWidth, yStart);
|
|
}
|
|
else
|
|
{
|
|
g.DrawString(Strings.Sun, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)sunSize.Width) / 2) + 0 * cellWidth, yStart);
|
|
g.DrawString(Strings.Mon, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)monSize.Width) / 2) + 1 * cellWidth, yStart);
|
|
g.DrawString(Strings.Tue, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)tueSize.Width) / 2) + 2 * cellWidth, yStart);
|
|
g.DrawString(Strings.Wed, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)wedSize.Width) / 2) + 3 * cellWidth, yStart);
|
|
g.DrawString(Strings.Thu, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)thuSize.Width) / 2) + 4 * cellWidth, yStart);
|
|
g.DrawString(Strings.Fri, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)friSize.Width) / 2) + 5 * cellWidth, yStart);
|
|
g.DrawString(Strings.Sat, _dayOfWeekFont, Brushes.Black, MarginSize + ((cellWidth - (int)satSize.Width) / 2) + 6 * cellWidth, yStart);
|
|
}
|
|
|
|
if (_showDateInHeader)
|
|
{
|
|
g.DrawString(_calendarDate.ToString("MMMM") + " " + _calendarDate.Year.ToString(CultureInfo.InvariantCulture),
|
|
_dateHeaderFont, Brushes.Black, ClientSize.Width - MarginSize - dateHeaderSize.Width,
|
|
MarginSize);
|
|
}
|
|
|
|
_events.Sort(new EventComparer());
|
|
|
|
///
|
|
/// Draw calendar events
|
|
///
|
|
for (int day = 1; day <= DateTime.DaysInMonth(_calendarDate.Year, _calendarDate.Month); day++)
|
|
{
|
|
/// Top coordinate of drawing position, first event on this day starts on top
|
|
int renderOffsetY = 0;
|
|
|
|
foreach (ICalendarEvent ev in _events)
|
|
{
|
|
var dt = new DateTime(_calendarDate.Year, _calendarDate.Month, day, 23, 59, _calendarDate.Second);
|
|
|
|
if ((!ev.Hidden || _showHiddenEvents) && Config.CalendarEvent.Utils.DayMatchesExactly(ev, dt))
|
|
{
|
|
/// Determine event background color
|
|
int alpha = 255;
|
|
if (ev.Hidden && _dimDisabledEvents)
|
|
alpha = 64;
|
|
Color alphaColor = Color.FromArgb(ev.BackColor);
|
|
|
|
/// Determine event text position
|
|
int offsetY = renderOffsetY;
|
|
Region r = g.Clip;
|
|
Point point = _calendarDays[day];
|
|
SizeF sz = g.MeasureString(ev.ToString(), new Font("Calibri", 8, FontStyle.Regular));
|
|
sz.Width += 2;
|
|
sz.Height += 2;
|
|
int yy = point.Y + 1;
|
|
int xx = (sz.Width > cellWidth) ? point.X + 1 : ((cellWidth - (int)sz.Width) / 2) + point.X;
|
|
|
|
if (renderOffsetY + sz.Height > cellHeight - 10)
|
|
{
|
|
/// Skip rendering, too many events this day
|
|
continue;
|
|
}
|
|
|
|
/// Render this event
|
|
g.Clip = new Region(new Rectangle(point.X + 1, point.Y + offsetY, cellWidth - 1, (int)sz.Height));
|
|
g.FillRectangle(new SolidBrush(alphaColor), point.X + 1, point.Y + offsetY, cellWidth - 1, sz.Height);
|
|
if (ev.Hidden && _showDashedBorderOnDisabledEvents)
|
|
{
|
|
var p = new Pen(new SolidBrush(Color.FromArgb(255, 0, 0, 0))) { DashStyle = DashStyle.Dash };
|
|
g.DrawRectangle(p, point.X + 1, point.Y + offsetY, cellWidth - 2, sz.Height - 1);
|
|
}
|
|
g.DrawString(ev.ToString(), new Font("Calibri", 8, FontStyle.Regular), new SolidBrush(Color.FromArgb(ev.TextColor)), xx, yy + offsetY);
|
|
g.Clip = r;
|
|
|
|
/// Add calendar event instance to a list => support for mouse-clicks, boloons, etc.
|
|
_eventInstances.Add(new CalendarEventInstance { Event = ev,
|
|
EventArea = new Rectangle(point.X + 1, point.Y + offsetY, cellWidth - 1, (int)sz.Height),
|
|
Date = dt });
|
|
|
|
/// Move top coordinate of drawing position down
|
|
renderOffsetY += (int)sz.Height + 1;
|
|
}
|
|
}
|
|
}
|
|
_rectangles.Clear();
|
|
|
|
g.Dispose();
|
|
e.Graphics.DrawImage(bmp, 0, 0, ClientSize.Width, ClientSize.Height);
|
|
bmp.Dispose();
|
|
}
|
|
|
|
|
|
private int NumberOfWeeks(int year, int month)
|
|
{
|
|
return NumberOfWeeks(new DateTime(year, month, DateTime.DaysInMonth(year, month)));
|
|
}
|
|
|
|
private int NumberOfWeeks(DateTime date)
|
|
{
|
|
DateTime beginningOfMonth = new DateTime(date.Year, date.Month, 1);
|
|
|
|
while (date.Date.AddDays(1).DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
|
|
{
|
|
date = date.AddDays(1);
|
|
}
|
|
|
|
return (int)Math.Truncate(date.Subtract(beginningOfMonth).TotalDays / 7f) + 1;
|
|
}
|
|
|
|
private void CalendarResize(object sender, EventArgs e)
|
|
{
|
|
if (_calendarView == CalendarViews.Day)
|
|
{
|
|
ResizeScrollPanel();
|
|
}
|
|
|
|
Invalidate();
|
|
}
|
|
}
|
|
} |