#if FRAMEWORK20 using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Globalization; using System.Windows.Forms; namespace DevComponents.DotNetBar.Schedule { public class MonthView : BaseView { #region Constants private const int MaxNumberOfWeeks = 52; #endregion #region Events public event EventHandler IsSideBarVisibleChanged; #endregion #region Private variables private int _NumberOfWeeks; // Number of week in display private MonthWeek[] _MonthWeeks; // Array of weeks private CalendarMonthColor _ViewColor = // View display color table new CalendarMonthColor(eCalendarColor.Automatic); private int _DaysOffset; // Moving day offset private bool _IsSideBarVisible = true; // Flag denoting SideBar visibility private Size _MoreImageSize = new Size(16, 16); private Bitmap _MoreImage; private Bitmap _MoreImageHot; private ItemRect _MoreRect; #endregion /// /// Constructor /// /// Parent CalendarView public MonthView(CalendarView calendarView) : base(calendarView, eCalendarView.Month) { // Set our non-client drawing info and our CalendarColor NClientData = new NonClientData( eTabOrientation.Horizontal, (int)eCalendarMonthPart.OwnerTabBorder, (int)eCalendarMonthPart.OwnerTabForeground, (int)eCalendarMonthPart.OwnerTabBackground, (int)eCalendarMonthPart.OwnerTabContentBackground, (int)eCalendarMonthPart.OwnerTabSelectedForeground, (int)eCalendarMonthPart.OwnerTabSelectedBackground); CalendarColorTable = _ViewColor; // Hook onto needed event HookEvents(true); } #region Public properties #region MonthWeek public MonthWeek[] MonthWeeks { get { return (_MonthWeeks); } } #endregion #region IsSideBarVisible /// /// Gets and sets the SideBar visibility /// public bool IsSideBarVisible { get { return (_IsSideBarVisible); } set { if (_IsSideBarVisible != value) { bool oldValue = _IsSideBarVisible; _IsSideBarVisible = value; OnIsSideBarVisibleChanged(oldValue, value); InvalidateRect(true); } } } /// /// OnIsSideBarVisibleChanged event propagation /// protected virtual void OnIsSideBarVisibleChanged(bool oldVal, bool newVal) { if (IsSideBarVisibleChanged != null) IsSideBarVisibleChanged(this, new IsSideBarVisibleChangedEventArgs(oldVal, newVal)); } #endregion #endregion #region Private properties /// /// Gets the sidebar width /// private int SideBarWidth { get { return (_IsSideBarVisible ? Font.Height + 6 : 0); } } /// /// Gets the DayHeader height /// private int DayHeaderHeight { get { return (Font.Height + 4); } } #endregion #region HookEvents /// /// Hooks (or unhooks) needed events /// /// True to hook, false to unhook private void HookEvents(bool hook) { if (hook == true) { CalendarView.SelectedViewChanged += SelectedViewChanged; CalendarView.MonthViewStartDateChanged += MonthViewStartDateChanged; CalendarView.MonthViewEndDateChanged += MonthViewEndDateChanged; CalendarView.IsMonthSideBarVisibleChanged += IsMonthSideBarVisibleChanged; } else { CalendarView.SelectedViewChanged -= SelectedViewChanged; CalendarView.MonthViewStartDateChanged -= MonthViewStartDateChanged; CalendarView.MonthViewEndDateChanged -= MonthViewEndDateChanged; CalendarView.IsMonthSideBarVisibleChanged -= IsMonthSideBarVisibleChanged; } } #endregion #region Event handling #region SelectedViewChanged /// /// Processes CalendarView SelectedViewChanged events /// /// CalendarView /// SelectedViewEventArgs void SelectedViewChanged(object sender, SelectedViewEventArgs e) { IsViewSelected = (e.NewValue == eCalendarView.Month); if (IsViewSelected == true) { AutoSyncViewDate(e.OldValue); UpdateDateSelection(); } else { ResetView(); } } #endregion #region MonthViewStartDateChanged /// /// Processes StartDate changes /// /// /// void MonthViewStartDateChanged(object sender, DateChangeEventArgs e) { StartDate = e.NewValue; } #endregion #region MonthViewEndDateChanged /// /// Processes EndDate changes /// /// /// void MonthViewEndDateChanged(object sender, DateChangeEventArgs e) { EndDate = e.NewValue; } #endregion #region IsMonthSideBarVisibleChanged /// /// Processes CalendarView IsMonthSideBarVisibleChanged events /// /// CalendarView /// SelectedViewEventArgs void IsMonthSideBarVisibleChanged( object sender, IsMonthSideBarVisibleChangedEventArgs e) { IsSideBarVisible = e.NewValue; } #endregion #endregion #region GetViewAreaFromPoint /// /// Gets the view area under the given mouse /// point (tab, header, content, etc) /// /// Point /// eViewArea public override eViewArea GetViewAreaFromPoint(Point pt) { if (Bounds.Contains(pt) == true) { if (ClientRect.Contains(pt)) { if (pt.X < Bounds.X + SideBarWidth) return (eViewArea.InSideBarPanel); if (pt.Y < ClientRect.Y + DayOfWeekHeaderHeight) return (eViewArea.InDayOfWeekHeader); if (pt.X >= _MonthWeeks[0].Bounds.X) { for (int i = 0; i < _NumberOfWeeks; i++) { if (pt.Y < _MonthWeeks[i].Bounds.Y + DayHeaderHeight) return (eViewArea.InWeekHeader); if (pt.Y < _MonthWeeks[i].Bounds.Bottom) return (eViewArea.InContent); } } return (eViewArea.NotInView); } return (base.GetViewAreaFromPoint(pt)); } return (eViewArea.NotInView); } #endregion #region GetDateSelectionFromPoint /// /// Gets the date selection from the given point. The startDate /// and endDate will vary based upon the view type (WeekDay / Month) /// /// Point in question /// out start date /// out end date /// True if a valid selection exists /// at the given point public override bool GetDateSelectionFromPoint( Point pt, out DateTime startDate, out DateTime endDate) { base.GetDateSelectionFromPoint(pt, out startDate, out endDate); int week, day; if (GetPointItem(pt, out week, out day)) { startDate = _MonthWeeks[week].FirstDayOfWeek.AddDays(day); endDate = startDate.AddDays(1); return (true); } return (false); } #endregion #region GetItemWeek public MonthWeek GetItemWeek(CalendarItem item) { for (int i = 0; i < _NumberOfWeeks; i++) { if (_MonthWeeks[i].CalendarItems.Contains(item)) return (_MonthWeeks[i]); } return (null); } #endregion #region SetSelectedItem /// /// Handles selected item changes /// /// CalendarItem /// EventArgs public void ItemIsSelectedChanged(object sender, EventArgs e) { CalendarItem ci = sender as CalendarItem; if (ci != null && IsSelecting == false) { try { IsSelecting = true; if (ci.IsSelected == true) { SelectedItem = SetSelectedItem(SelectedItem, ci); } else { if (ci == SelectedItem) SelectedItem = null; } } finally { IsSelecting = false; } } } /// /// Sets the current selected item /// /// Previous CalendarItem /// New CalendarItem to select /// Base selected CalendarItem protected override CalendarItem SetSelectedItem(CalendarItem pci, CalendarItem nci) { CalendarItem selItem = null; for (int i = 0; i < _NumberOfWeeks; i++) { List items = _MonthWeeks[i].CalendarItems; for (int j = 0; j < items.Count; j++) { CalendarItem item = items[j]; item.IsSelected = (nci != null ? (item.ModelItem == nci.ModelItem) : false); if (item.IsSelected == true && selItem == null) { selItem = item; SelectedItem = item; } } } return (selItem); } #endregion #region UpdateDateSelection /// /// Updates each monthWeeks DayRects to reflect /// the date selection start and end values /// protected override void UpdateDateSelection() { if (IsViewSelected == true) { // Loop through each week for (int i = 0; i < _NumberOfWeeks; i++) { DateTime date = _MonthWeeks[i].FirstDayOfWeek; // loop through each day of the week, setting // the selection status according to the date // selection range for (int j = 0; j < DaysInWeek; j++) { bool selected = (DateSelectionStart.HasValue && DateSelectionEnd.HasValue && date >= DateSelectionStart && date < DateSelectionEnd); _MonthWeeks[i].DayRects[j].IsSelected = selected; date = date.AddDays(1); } } } } #endregion #region RecalcSize routines /// /// Performs NeedRecalcSize requests /// public override void RecalcSize() { base.RecalcSize(); if (IsViewSelected == true) { // Normalize our start and end dates DateTime startDate; DateTime endDate; NormalizeDates(out startDate, out endDate); // Calculate each weeks display info CalcMonthWeeks(startDate, endDate); // Update our Model connection and views UpdateView(); UpdateDateSelection(); if (DaysOfTheWeek != null) DaysOfTheWeek.NeedsMeasured = true; NeedRecalcLayout = false; } } #region NormalizeDates /// /// Normalizes the user specified start and end dates /// /// [out] Normalized start date /// [out] Normalized end date private void NormalizeDates(out DateTime startDate, out DateTime endDate) { startDate = this.StartDate; endDate = this.EndDate; // If both values are unset, then set them to // today's date / + 1 month if (startDate == DateTime.MinValue && endDate == DateTime.MinValue) { startDate = DateTime.Today.Date; endDate = startDate.AddMonths(1); } endDate = DateHelper.GetEndOfWeek(endDate, DateHelper.GetLastDayOfWeek()); startDate = DateHelper.GetDateForDayOfWeek(startDate, DateHelper.GetFirstDayOfWeek()); DaysOfTheWeek = new DaysOfTheWeek(); } #endregion #region Update View /// /// Updates our connection model view /// private void UpdateView() { // If we have had a date range change, just // reset our entire view if (DateRangeChanged == true) ResetView(); // If we have no Model connection, attempt // to reconnect if this view is selected if (Connector == null) { if (CalendarModel != null) Connector = new ModelMonthViewConnector(CalendarModel, this); } // We have a connection, so update our CalendarItems if (Connector != null) { UpdateCalendarItems(); CalendarView.DoViewLoadComplete(this); } } #region UpdateCalendarItems /// /// Updates our CalendarItems list /// private void UpdateCalendarItems() { // Get a working list of our CalendarItems List[] items = SortCalendarItems(); // Go through our CalendarItems on a per week basis bool moreItems = false; int days = _NumberOfWeeks * DaysInWeek; ulong[] acc = new ulong[days]; for (int i = 0; i < _NumberOfWeeks; i++) { // Calculate the display bounds for each item for (int j = 0; j < items[i].Count; j++) CalcAppointmentBounds(items[i][j], i, acc); moreItems |= UpdateMoreItems(_MonthWeeks[i], acc, i); } // If we have no need of our previously allocated "More" // images then dispose of them and reset our handles if (moreItems == false) { if (_MoreImage != null) { _MoreImage.Dispose(); _MoreImage = null; } if (_MoreImageHot != null) { _MoreImageHot.Dispose(); _MoreImageHot = null; } } // Update our current day selection UpdateDateSelection(); } #region SortCalendarItems /// /// Sorts the provided CalendarItems /// /// Sorted CalendarItems private List[] SortCalendarItems() { List[] items = new List[_NumberOfWeeks]; for (int i = 0; i < _NumberOfWeeks; i++) { items[i] = new List(_MonthWeeks[i].CalendarItems.Count); if (_MonthWeeks[i].CalendarItems.Count > 0) { items[i].AddRange(_MonthWeeks[i].CalendarItems); items[i].Sort( delegate(CalendarItem c1, CalendarItem c2) { int n = c1.StartTime.TimeOfDay.CompareTo(c2.StartTime.TimeOfDay); if (n != 0) return (n); n = c1.StartTime.CompareTo(c2.StartTime); if (n != 0) return (n); n = c1.EndTime.CompareTo(c2.EndTime); if (n != 0) return (n); int result = 0; CalendarView.DoDetailSortEvent(this, c1, c2, ref result); return (result); } ); } } return (items); } #endregion #region CalcAppointmentBounds /// /// Calculates the display bounds for the AppointmentView /// /// CalendarItem /// Week associated with the view /// Row accumulator private void CalcAppointmentBounds( CalendarItem item, int week, ulong[] acc) { // Determine the starting day index for // the given appointment int ns = GetDayIndex(week, item); // Calculate the top and height for the item Rectangle r = _MonthWeeks[week].DayRects[ns].Bounds; r.Y += DayHeaderHeight + 1; r.Height = AppointmentHeight; r.Width = 0; // Determine the ending day index DateTime st = _MonthWeeks[week].FirstDayOfWeek.AddDays(ns); int ne = ns + (item.EndTime - st).Days; if (item.EndTime.Hour > 0 || item.EndTime.Minute > 0 || item.EndTime.Second > 0) ne++; if (ne > DaysInWeek) ne = DaysInWeek; int weekOffset = week * DaysInWeek; int freeAcc = GetFreeAcc(weekOffset + ns, weekOffset + ne, acc); if (freeAcc >= 0) { ulong u = (1ul << freeAcc); for (int i = ns; i < ne; i++) { r.Width += _MonthWeeks[week].DayRects[i].Bounds.Width; acc[weekOffset + i] |= u; } r.Y += (freeAcc * AppointmentHeight); } else { r.Y = _MonthWeeks[week].Bounds.Bottom; } DateTime start = _MonthWeeks[week].FirstDayOfWeek; DateTime end = start.AddDays(DaysInWeek); // Check to see if we can only display // a partial representation for the view if (item.EndTime >= start && item.StartTime < end) { int hpad = CalendarView.MonthViewHorizontalPadding; if (item.StartTime >= start) { r.X += hpad; r.Width -= hpad; } if (item.EndTime <= end) r.Width -= hpad; } // Now that we have calculated the items height and // width, invoke a Recalc on the item item.WidthInternal = r.Width - 1; item.HeightInternal = r.Height - 1; item.RecalcSize(); // Set our bounds for the item r.Width = item.WidthInternal; r.Height = item.HeightInternal; item.Bounds = r; // Set it's display state if (CalendarView.IsMonthMoreItemsIndicatorVisible == true) item.Displayed = (r.Bottom < _MonthWeeks[week].Bounds.Bottom - _MoreImageSize.Height); else item.Displayed = (r.Top < _MonthWeeks[week].Bounds.Bottom - 2); } #region GetFreeAcc private int GetFreeAcc(int ns, int ne, ulong[] acc) { for (int i = 0; i < sizeof(ulong) * 8; i++) { if (CheckFreeAcc(ns, ne, acc, i) == true) return (i); } return (-1); } #region CheckFreeAcc private bool CheckFreeAcc(int ns, int ne, ulong[] acc, int n) { for (int i = ns; i < ne; i++) { ulong u = acc[i]; if ((u & (1ul << n)) != 0) return (false); } return (true); } #endregion #endregion #region GetDayIndex /// /// Gets the starting day index for the given appointment /// /// Week index /// CalendarItem /// Day of week index (0-6) private int GetDayIndex(int week, CalendarItem item) { DateTime date = _MonthWeeks[week].FirstDayOfWeek; for (int i = 0; i < DaysInWeek; i++) { date = date.AddDays(1); if (date > item.StartTime) return (i); } return (0); } #endregion #endregion #region UpdateMoreItems /// /// UpdateMoreItems /// /// /// /// private bool UpdateMoreItems(MonthWeek monthWeek, ulong[] acc, int week) { bool moreItems = false; int weekOffset = week * DaysInWeek; int rowHeight = monthWeek.DayRects[0].Bounds.Height - DayHeaderHeight - _MoreImageSize.Height - 1; for (int j = 0; j < DaysInWeek; j++) { int height = GetMoreHeight(acc[weekOffset + j]); if (CalendarView.IsMonthMoreItemsIndicatorVisible == false || height <= rowHeight) { monthWeek.MoreItems[j].Bounds = Rectangle.Empty; } else { moreItems = true; Rectangle r = monthWeek.DayRects[j].Bounds; r.X = r.Right - _MoreImageSize.Width; r.Y = r.Bottom - _MoreImageSize.Height; r.Size = _MoreImageSize; monthWeek.MoreItems[j].Bounds = r; } } return (moreItems); } #region GetMoreHeight private int GetMoreHeight(ulong u) { int height = 0; while (u != 0) { height += AppointmentHeight; u = u >> 1; } return (height); } #endregion #endregion #endregion #region CalcMonthWeeks /// /// Calculates display info for the MonthWeek data /// /// Start date /// End date private void CalcMonthWeeks(DateTime startDate, DateTime endDate) { // Get the number of weeks for the date range _NumberOfWeeks = DateHelper.GetNumberOfWeeks(startDate, endDate); _NumberOfWeeks = Math.Max(1, _NumberOfWeeks); _NumberOfWeeks = Math.Min(_NumberOfWeeks, MaxNumberOfWeeks); // Allocate our MonthWeeks array to // hold our weeks info if (_MonthWeeks == null || _MonthWeeks.Length != _NumberOfWeeks) _MonthWeeks = new MonthWeek[_NumberOfWeeks]; // Update display info on each week float dy = 0; float weekHeight = ((float)ClientRect.Height - DayOfWeekHeaderHeight) / _NumberOfWeeks; int sx = ClientRect.X + SideBarWidth; int sy = ClientRect.Y + DayOfWeekHeaderHeight; int y2 = sy; // Loop through each week for (int i = 0; i < _NumberOfWeeks; i++) { if (_MonthWeeks[i] == null) _MonthWeeks[i] = new MonthWeek(this); // Set the weeks first day of the week _MonthWeeks[i].FirstDayOfWeek = startDate.AddDays(i * DaysInWeek); // Calculate the bounding rect limits dy += weekHeight; int y1 = y2; y2 = sy + (int)dy; if (i + 1 == _NumberOfWeeks) y2 = ClientRect.Y + ClientRect.Height - 1; // Set the bounding rect _MonthWeeks[i].Bounds = new Rectangle(sx, y1, ClientRect.Width - SideBarWidth - 1, y2 - y1); } } #endregion #endregion #endregion #region Paint processing #region Root paint code /// /// Paint processing /// /// ItemPaintArgs public override void Paint(ItemPaintArgs e) { // Set our current color table _ViewColor.SetColorTable(); // Only draw something if we have something to draw if (_NumberOfWeeks > 0) { // Calculate our drawing ranges int dayStart, dayEnd, dayCount; int weekStart, weekEnd, weekCount; if (e.ClipRectangle.Contains(ClientRect)) { // The clipping rect encompasses our entire calendar // so set our start and end values accordingly dayStart = 0; dayEnd = DaysInWeek - 1; dayCount = DaysInWeek; weekStart = 0; weekEnd = _NumberOfWeeks - 1; weekCount = _NumberOfWeeks; } else { // We only need to draw part of our calendar, so // calculate our day and week count and range dayCount = GetDayRange(e, out dayStart, out dayEnd); weekCount = GetWeekRange(e, out weekStart, out weekEnd); } // Draw our calendar parts if (dayCount > 0) { DrawDayOfTheWeekHeader(e, dayStart, dayEnd); if (weekCount > 0) { DrawDays(e, weekStart, weekEnd, dayStart, dayEnd); if (Connector != null && Connector.IsConnected) DrawWeekAppointments(e, weekStart, weekEnd); } } if (_IsSideBarVisible == true && weekCount > 0) DrawSideBarHeader(e, weekStart, weekEnd); } // Let the base painting take place base.Paint(e); } #region Clip range routines /// /// Calculates the range of days needed to be drawn /// to satisfy the specified paint request /// /// ItemPaintArgs /// [out] Day start index /// [out] Day end index /// Day range count (end - start) private int GetDayRange(ItemPaintArgs e, out int dayStart, out int dayEnd) { // Calc our starting index int start = 0; while (start < DaysInWeek) { Rectangle dr1 = _MonthWeeks[0].DayRects[start].Bounds; if (dr1.Right >= e.ClipRectangle.X) break; start++; } // Calc our ending index int end = start; while (end < DaysInWeek) { Rectangle dr2 = _MonthWeeks[0].DayRects[end].Bounds; if (dr2.X >= e.ClipRectangle.Right) break; end++; } // Set the user supplied 'out' values, and // return the range count to the caller if (end - start == 0) { dayStart = 0; dayEnd = 0; return (0); } dayStart = start; dayEnd = end - 1; return (end - start); } /// /// Calculates the range of weeks needed to be drawn /// to satisfy the specified paint request /// /// ItemPaintArgs /// [out] Week start index /// [out] Week end index /// Week range count (end - start) private int GetWeekRange(ItemPaintArgs e, out int weekStart, out int weekEnd) { // Calc our starting index int start = 0; while (start < _NumberOfWeeks) { if (_MonthWeeks[start].Bounds.Bottom > e.ClipRectangle.Y) break; start++; } // Calc our ending index int end = start; while (end < _NumberOfWeeks) { if (_MonthWeeks[end].Bounds.Y >= e.ClipRectangle.Bottom) break; end++; } // Set the user supplied 'out' values, and // return the range count to the caller if (end - start == 0) { weekStart = 0; weekEnd = 0; return (0); } weekStart = start; weekEnd = end - 1; return (end - start); } #endregion #endregion #region DayOfTheWeek header drawing #region DrawDayOfTheWeekHeader /// /// Draws the top Day of the week header /// /// ItemPaintArgs /// Start day index /// End day index private void DrawDayOfTheWeekHeader(ItemPaintArgs e, int dayStart, int dayEnd) { Graphics g = e.Graphics; Rectangle r = new Rectangle(ClientRect.X - 1, ClientRect.Y - 1, SideBarWidth + 1, DayOfWeekHeaderHeight + 1); using (Brush br = _ViewColor.BrushPart((int)eCalendarMonthPart.OwnerTabContentBackground, r)) { g.FillRectangle(br, r); } // Calculate our contiguous header rect // area so we can fill it all at once r = new Rectangle( _MonthWeeks[0].DayRects[dayStart].Bounds.X, ClientRect.Y, _MonthWeeks[0].DayRects[dayEnd].Bounds.Right - _MonthWeeks[0].DayRects[dayStart].Bounds.X, DayOfWeekHeaderHeight); if (r.Width > 0 && r.Height > 0) { using (Brush lbr = _ViewColor.BrushPart((int)eCalendarMonthPart.DayOfTheWeekHeaderBackground, r)) { g.FillRectangle(lbr, r); } // Establish our Days Of The Week text type DaysOfTheWeek.eDayType type = GetDaysOfTheWeekType(g); // Loop through each day, drawing the // day of the week text in the header area eTextFormat tf = eTextFormat.VerticalCenter | eTextFormat.NoPadding; using (Pen pen = new Pen( _ViewColor.GetColor((int)eCalendarMonthPart.DayOfTheWeekHeaderBorder))) { for (int i = dayStart; i <= dayEnd; i++) { r.X = _MonthWeeks[0].DayRects[i].Bounds.X; r.Width = _MonthWeeks[0].DayRects[i].Bounds.Width; if (CalendarView.DoPreRenderMonthHeader(g, this, i, r) == false) { // Center the header text until the text // will no longer fit, then left justify it if (DaysOfTheWeek.DaySize[(int) type][i].Width < r.Width) tf |= eTextFormat.HorizontalCenter; // Draw the text and header border TextDrawing.DrawString(g, DaysOfTheWeek.DayText[(int) type][i], Font, _ViewColor.GetColor((int) eCalendarMonthPart.DayOfTheWeekHeaderForeground), r, tf); CalendarView.DoPostRenderMonthHeader(g, this, i, r); } g.DrawRectangle(pen, r); } } } } #endregion #region GetDaysOfTheWeekType private DaysOfTheWeek.eDayType GetDaysOfTheWeekType(Graphics g) { // Determine if the current DayRect bounds // are constrained by the text threshold DaysOfTheWeek.MeasureText(g, Font); for (int i = 0; i < DaysInWeek; i++) { if (_MonthWeeks[0].DayRects[i].Bounds.Width < DaysOfTheWeek.DaySize[(int)DaysOfTheWeek.eDayType.Long][i].Width) { return (DaysOfTheWeek.eDayType.Short); } } return (DaysOfTheWeek.eDayType.Long); } #endregion #endregion #region Day drawing #region DrawDays /// /// Draws day header and content /// /// ItemPaintArgs /// Week start index /// Week end index /// Day start index /// Day end index private void DrawDays(ItemPaintArgs e, int weekStart, int weekEnd, int dayStart, int dayEnd) { Graphics g = e.Graphics; Rectangle r = new Rectangle( _MonthWeeks[0].DayRects[dayStart].Bounds.X, 0, _MonthWeeks[0].DayRects[dayEnd].Bounds.Right - _MonthWeeks[0].DayRects[dayStart].Bounds.X, DayHeaderHeight); if (r.Width > 0 && r.Height > 0) { // Loop through each day in each week, displaying // the associated day content and header int nowHeaderWeek = -1; int nowHeaderDay = -1; DateTime now = DateTime.Now; using (Pen pen1 = new Pen( _ViewColor.GetColor((int) eCalendarMonthPart.DayContentBorder))) { using (Pen pen2 = new Pen( _ViewColor.GetColor((int) eCalendarMonthPart.DayHeaderBorder))) { for (int i = weekStart; i <= weekEnd; i++) { for (int j = dayStart; j <= dayEnd; j++) { if (CalendarView.HighlightCurrentDay == true) { DateTime date = _MonthWeeks[i].FirstDayOfWeek.AddDays(j); if (now.Date.Equals(date.Date) == true) { nowHeaderDay = i; nowHeaderWeek = j; continue; } } DrawDayBackground(g, i, j, eCalendarMonthPart.DayHeaderBackground); DrawDayContent(g, i, j, pen1); DrawDayHeader(g, i, j, pen2); } } } } // Draw "Now" day header and border if (nowHeaderDay >= 0) { using (Pen pen1 = new Pen( _ViewColor.GetColor((int) eCalendarMonthPart.NowDayHeaderBorder))) { using (Pen pen2 = new Pen( _ViewColor.GetColor((int) eCalendarMonthPart.NowDayHeaderBorder))) { DrawDayBackground(g, nowHeaderDay, nowHeaderWeek, eCalendarMonthPart.NowDayHeaderBackground); DrawDayContent(g, nowHeaderDay, nowHeaderWeek, pen1); DrawDayHeader(g, nowHeaderDay, nowHeaderWeek, pen2); } } } } } #region DrawDayBackground /// /// DrawDayBackground /// /// /// /// /// private void DrawDayBackground(Graphics g, int week, int day, eCalendarMonthPart part) { Rectangle r = _MonthWeeks[week].DayRects[day].Bounds; r.Height = DayHeaderHeight; using (Brush br = _ViewColor.BrushPart((int)part, r)) g.FillRectangle(br, r); } #endregion #endregion #region DrawDayContent /// /// Draws the day content /// /// /// Week index /// Day index /// Pen private void DrawDayContent(Graphics g, int iweek, int iday, Pen pen) { Rectangle r = _MonthWeeks[iweek].DayRects[iday].Bounds; r.Y += DayHeaderHeight; r.Height -= DayHeaderHeight; DrawBackground(g, iweek, iday, r); DrawMoreImage(g, iweek, iday, r); DrawBorder(g, pen, iweek, r); } #region DrawBackground private void DrawBackground(Graphics g, int iweek, int iday, Rectangle r) { DateTime date = _MonthWeeks[iweek].FirstDayOfWeek.AddDays(iday); int dayMonth = date.Month; DateTime startTime = date; DateTime endTime = date.AddDays(1).AddMinutes(-1); eSlotDisplayState state = GetSlotState(iweek, iday, dayMonth); if (CalendarView.DoMonthViewPreRenderSlotBackground( g, this, startTime, endTime, r, ref state) == false) { eCalendarMonthPart part = GetContentPart(state); using (Brush br = _ViewColor.BrushPart((int)part, r)) g.FillRectangle(br, r); CalendarView.DoMonthViewPostRenderSlotBackground( g, this, startTime, endTime, r, state); } } #region GetSlotState /// /// GetSlotState /// /// private eSlotDisplayState GetSlotState(int iweek, int iday, int dayMonth) { eSlotDisplayState state = eSlotDisplayState.None; if (DisplayedOwnerKeyIndex == CalendarView.SelectedOwnerIndex) { if (_MonthWeeks[iweek].DayRects[iday].IsSelected) state |= eSlotDisplayState.Selected; } if (dayMonth == StartDate.Month) state |= eSlotDisplayState.Work; return (state); } #endregion #region GetContentPart /// /// Gets the content calendar part for the given /// week and dayMonth /// /// private eCalendarMonthPart GetContentPart(eSlotDisplayState state) { if ((state & eSlotDisplayState.Selected) == eSlotDisplayState.Selected) return (eCalendarMonthPart.DayContentSelectionBackground); if ((state & eSlotDisplayState.Work) == eSlotDisplayState.Work) return (eCalendarMonthPart.DayContentActiveBackground); return (eCalendarMonthPart.DayContactInactiveBackground); } #endregion #endregion #region DrawMoreImage private void DrawMoreImage(Graphics g, int iweek, int iday, Rectangle r) { ItemRect moreRect = _MonthWeeks[iweek].MoreItems[iday]; if (moreRect.Bounds.IsEmpty == false) { Bitmap bm = moreRect.IsSelected ? GetMoreImageHot(g) : GetMoreImage(g); if (bm != null) { Region regSave = g.Clip; g.SetClip(r, CombineMode.Intersect); g.DrawImageUnscaledAndClipped(bm, moreRect.Bounds); g.Clip = regSave; } } } #endregion #region DrawBorder private void DrawBorder( Graphics g, Pen pen, int iweek, Rectangle r) { if (iweek < _NumberOfWeeks - 1) r.Height--; g.DrawRectangle(pen, r); } #endregion #endregion #region DrawDayHeader /// /// Draws day header /// /// /// Week index /// Day index /// Text pen private void DrawDayHeader(Graphics g, int iweek, int iday, Pen pen) { // Calculate the display rect and draw the text Rectangle r = _MonthWeeks[iweek].DayRects[iday].Bounds; r.Height = Math.Min(DayHeaderHeight, r.Height); if (r.Height > 0) { // Draw the border area g.DrawRectangle(pen, r); // Get the associated day and text DateTime day = _MonthWeeks[iweek].FirstDayOfWeek.AddDays(iday); string s = GetDayHeaderText(day); r.Inflate(-2, 0); TextDrawing.DrawString(g, s, BoldFont, _ViewColor.GetColor((int)eCalendarMonthPart.DayHeaderForeground), r, eTextFormat.VerticalCenter | eTextFormat.Left | eTextFormat.NoPadding); } } #region GetDayHeaderText /// /// GetDayHeaderText /// /// /// private string GetDayHeaderText(DateTime date) { if (date.Day == 1) { DateTimeFormatInfo dtfi = ScheduleSettings.GetActiveCulture().DateTimeFormat; string s = dtfi.MonthDayPattern.Replace("dd", "d"); return (date.ToString(s)); } return (String.Format("{0}", date.Day)); } #endregion #endregion #endregion #region DrawWeekAppointments /// /// Initiates the drawing of weekly appointments /// /// ItemPaintArgs /// Week start index /// Week end index private void DrawWeekAppointments(ItemPaintArgs e, int weekStart, int weekEnd) { Graphics g = e.Graphics; // Loop through each subItem - on a weekly basis - so that // we can set an appropriate clipping region for the week for (int i = weekStart; i <= weekEnd; i++) { List items = _MonthWeeks[i].CalendarItems; if (items.Count > 0) { // Set our week-based clipping region Rectangle r = _MonthWeeks[i].Bounds; r.Height -= 1; Region regSave = g.Clip; g.SetClip(r, CombineMode.Intersect); // Loop through each CalendarItem in the week for (int j = 0; j < items.Count; j++) { // If we can display the item, then initiate the paint if (items[j].Displayed == true) { if (e.ClipRectangle.IsEmpty || e.ClipRectangle.IntersectsWith(items[j].DisplayRectangle)) { items[j].Paint(e); } } } // Restore the original clip region g.Clip = regSave; regSave.Dispose(); } } } #endregion #region GetMoreImage private Bitmap GetMoreImage(Graphics g) { if (_MoreImage == null) _MoreImage = GetMoreBitmap(g, Color.LightGray); return (_MoreImage); } #endregion #region GetMoreImageHot private Bitmap GetMoreImageHot(Graphics g) { if (_MoreImageHot == null) _MoreImageHot = GetMoreBitmap(g, _ViewColor.GetColor((int)eCalendarMonthPart.NowDayHeaderBorder)); return (_MoreImageHot); } #endregion #region GetMoreBitmap private Bitmap GetMoreBitmap(Graphics g, Color color) { Bitmap bmp = new Bitmap(_MoreImageSize.Width, _MoreImageSize.Height, g); using (Graphics gBmp = Graphics.FromImage(bmp)) { gBmp.CompositingQuality = CompositingQuality.HighQuality; gBmp.SmoothingMode = SmoothingMode.AntiAlias; using (GraphicsPath path = GetMoreImagePath()) { using (Brush br = new SolidBrush(color)) gBmp.FillPath(br, path); gBmp.DrawPath(Pens.White, path); } } return (bmp); } #endregion #region GetMoreImagePath /// /// Gets the More image path /// /// private GraphicsPath GetMoreImagePath() { GraphicsPath path = new GraphicsPath(); path.AddLines(new Point[] { new Point(2, 3), new Point(7, 11), new Point(12, 3) }); path.CloseAllFigures(); return (path); } #endregion #region SideBar header drawing /// /// Draws the SideBar header /// /// ItemPaintArgs /// Week start index /// Week end index private void DrawSideBarHeader(ItemPaintArgs e, int weekStart, int weekEnd) { // Calc the contiguous SideBar background rect Rectangle r = new Rectangle(ClientRect.X, _MonthWeeks[weekStart].Bounds.Y, SideBarWidth, _MonthWeeks[weekEnd].Bounds.Bottom - _MonthWeeks[weekStart].Bounds.Y); // Make sure we have something to draw if (r.Height > 0 && r.Width > 0 && e.ClipRectangle.IntersectsWith(r)) { Graphics g = e.Graphics; // Fill the bar with our color gradient using (Brush lbr = _ViewColor.BrushPart((int)eCalendarMonthPart.SideBarBackground, r)) { g.FillRectangle(lbr, r); } // Set uo our output to have both // vertically and horizontally centered text using (StringFormat sf = new StringFormat()) { sf.FormatFlags = StringFormatFlags.NoWrap; sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; // Calc our rect origin and prepare to // output the SideBar text PointF ptf = new PointF(ClientRect.X, 0); Rectangle rf = new Rectangle(0, 0, 0, SideBarWidth); using (Brush br = _ViewColor.BrushPart((int)eCalendarMonthPart.SideBarForeground, rf)) { using (Pen pen = new Pen( _ViewColor.GetColor((int)eCalendarMonthPart.SideBarBorder))) { // Loop through each individual week, displaying // the rotated header text appropriately for (int i = weekStart; i <= weekEnd; i++) { rf.Width = _MonthWeeks[i].Bounds.Height; if (rf.Width > 0) { ptf.Y = _MonthWeeks[i].Bounds.Y + rf.Width; g.TranslateTransform(ptf.X, ptf.Y); g.RotateTransform(-90); g.DrawString(_MonthWeeks[i].WeekRange, Font, br, rf, sf); g.DrawRectangle(pen, rf.X, rf.Y, rf.Width, rf.Height); g.ResetTransform(); } } } } } } } #endregion #endregion #region Mouse routines #region MouseDown processing /// /// MouseDown event processing /// /// public override void InternalMouseDown(MouseEventArgs objArg) { // Forward on the event base.InternalMouseDown(objArg); if (objArg.Button == MouseButtons.Left) { if (IsTabMoving == false) { // Locate where the event took place int week, day; if (GetPointItem(objArg.Location, out week, out day)) { MyCursor = GetCursor(); if (ProcessCilButtonDown(week, day) == false) { if (ProcessMoreButtonDown(week, day) == false) ProcessMvlButtonDown(week, day); } } IsCopyDrag = false; } } } #region CalendarItem MouseDown processing /// /// CalendarItem left mouseDown processing /// /// Week index /// Day index private bool ProcessCilButtonDown(int week, int day) { CalendarItem item = m_HotSubItem as CalendarItem; if (item != null) { if (item.HitArea != CalendarItem.eHitArea.None) { // Give the user a chance to cancel the // operation before it starts if (CalendarView.DoBeforeAppointmentViewChange(this, item, ((item.HitArea == CalendarItem.eHitArea.Move) ? eViewOperation.AppointmentMove : eViewOperation.AppointmentResize)) == false) { if (IsResizing == false && IsMoving == false) { OldStartTime = item.StartTime; OldEndTime = item.EndTime; OldOwnerKey = OwnerKey; } // Flag appropriate action if (item.HitArea == CalendarItem.eHitArea.LeftResize) IsStartResizing = true; else if (item.HitArea == CalendarItem.eHitArea.RightResize) IsEndResizing = true; else if (item.HitArea == CalendarItem.eHitArea.Move) { TimeSpan ts = _MonthWeeks[week].FirstDayOfWeek.AddDays(day) - item.StartTime; _DaysOffset = (int)(Math.Ceiling(ts.TotalDays)); IsMoving = true; } } } return (true); } return (false); } #endregion #region MonthView MouseDown processing /// /// Handles MonthView left MouseDown events /// /// Week index /// Day index private void ProcessMvlButtonDown(int week, int day) { DateTime startDate = _MonthWeeks[week].FirstDayOfWeek.AddDays(day); DateTime endDate = startDate.AddDays(1); ExtendSelection(ref startDate, ref endDate); CalendarView.DateSelectionStart = startDate; CalendarView.DateSelectionEnd = endDate; SelectedItem = null; } #endregion #region MoreItems MouseDown processing /// /// ProcessMoreButtonDown /// /// /// /// private bool ProcessMoreButtonDown(int week, int day) { if (CalendarView.IsMonthMoreItemsIndicatorVisible == true) { ItemRect moreRect = _MonthWeeks[week].MoreItems[day]; if (moreRect.IsSelected == true) { eCalendarView calendarView = eCalendarView.Day; DateTime startDate = _MonthWeeks[week].FirstDayOfWeek.AddDays(day); if (CalendarView.DoMonthMoreItemsIndicatorClick( this, ref calendarView, ref startDate) == false) { moreRect.IsSelected = false; DateSelectionAnchor = null; CalendarView.DateSelectionStart = null; CalendarView.DateSelectionEnd = null; CalendarView.SelectedView = calendarView; CalendarView.EnsureVisible(startDate, startDate); } return (true); } } return (false); } #endregion #endregion #region MouseMove processing /// /// MouseMove event processing /// /// MouseEventArgs public override void InternalMouseMove(MouseEventArgs objArg) { // Forward on the event, but only if we are not in // the middle of moving or resizing a CalendarItem if (Control.MouseButtons == MouseButtons.None) ClearMouseStates(); if (!IsMoving && !IsStartResizing && !IsEndResizing) base.InternalMouseMove(objArg); if (IsTabMoving == false) { // Set the cursor MyCursor = GetCursor(); int week, day; bool inItem = GetPointItem(objArg.Location, out week, out day); switch (objArg.Button) { case MouseButtons.Left: if (DragDropAppointment(objArg) == false) { // Locate where the event took place // and process it accordingly if (inItem == true) { if (DateSelectionAnchor != null) { ProcessMvMouseMove(week, day); } else if (SelectedItem != null) { if (IsMoving == true) ProcessItemMove(week, day); else if (IsStartResizing == true) ProcessItemLeftResize(week, day); else if (IsEndResizing == true) ProcessItemRightResize(week, day); } } } break; case MouseButtons.None: if (inItem == true) ProcessMoreMouseMove(week, day, objArg); break; } } } #region GetCursor /// /// Gets the cursor /// /// Cursor private Cursor GetCursor() { CalendarItem item = m_HotSubItem as CalendarItem; if (item != null) { switch (item.HitArea) { case CalendarItem.eHitArea.LeftResize: case CalendarItem.eHitArea.RightResize: return (Cursors.SizeWE); case CalendarItem.eHitArea.Move: return (IsMoving ? Cursors.SizeAll : DefaultCursor); } } return (DefaultCursor); } #endregion #region DragDropAppointment /// /// Initiates a user "DragDrop" operation - if enabled /// /// /// True if operation started private bool DragDropAppointment(MouseEventArgs objArgs) { if (IsMoving == true && CanDrag == true) { Point pt = objArgs.Location; BaseView bv = CalendarView.GetViewFromPoint(pt); MonthView mv = bv as MonthView; if (mv != null && mv != this) { eViewArea area = mv.GetViewAreaFromPoint(pt); if (area == eViewArea.InContent) { bool isNewCopyDrag = IsNewCopyDrag; if (CalendarView.DoAppointmentViewChanging(SelectedItem, mv.OwnerKey, SelectedItem.StartTime, SelectedItem.EndTime, eViewOperation.AppointmentMove, isNewCopyDrag) == false) { DragCopy(); ClearMouseStates(); if (PosWin != null) PosWin.Hide(); AppointmentView av = SelectedItem as AppointmentView; if (av != null) return (mv.DragAppointment(this, av, pt, isNewCopyDrag)); CustomCalendarItem ci = SelectedItem as CustomCalendarItem; if (ci != null) return (mv.DragCustomItem(this, ci, pt, isNewCopyDrag)); } } } } return (false); } #region DragCustomItem private bool DragCustomItem( MonthView pv, CustomCalendarItem ci, Point pt, bool isNewCopyDrag) { // Set the new owner and selected view, and // recalc the new layout ci.OwnerKey = OwnerKey; DateTime sd = ci.StartTime; TimeSpan ts = ci.EndTime.Subtract(ci.StartTime); int week = GetPointWeek(pt); int day = GetPointDay(pt, week); MonthWeek mw = _MonthWeeks[week]; DateTime date = mw.FirstDayOfWeek.AddDays(day - pv._DaysOffset); ci.StartTime = new DateTime(date.Year, date.Month, date.Day, sd.Hour, sd.Minute, 0); ci.EndTime = ci.StartTime.Add(ts); NeedRecalcLayout = true; RecalcSize(); CalendarView.SelectedOwnerIndex = this.DisplayedOwnerKeyIndex; // Get the new view CustomCalendarItem view = GetCustomCalendarItem(ci); if (view != null) SetNewDragItem(pv, view, isNewCopyDrag); return (true); } #endregion #region DragAppointment /// /// Drags the given appointment from one view to another /// /// Previous view /// AppointmentView /// Point private bool DragAppointment( MonthView pv, AppointmentView av, Point pt, bool isNewCopyDrag) { // Set the new owner and selected view, and // recalc the new layout av.Appointment.OwnerKey = OwnerKey; DateTime sd = av.Appointment.StartTime; int week = GetPointWeek(pt); if (week >= 0) { int day = GetPointDay(pt, week); MonthWeek mw = _MonthWeeks[week]; DateTime date = mw.FirstDayOfWeek.AddDays(day - pv._DaysOffset); av.Appointment.MoveTo( new DateTime(date.Year, date.Month, date.Day, sd.Hour, sd.Minute, 0)); NeedRecalcLayout = true; RecalcSize(); CalendarView.SelectedOwnerIndex = this.DisplayedOwnerKeyIndex; // Get the new appointment view AppointmentView view = GetAppointmentView(av.Appointment); if (view != null) SetNewDragItem(pv, view, isNewCopyDrag); } return (true); } #endregion #region SetNewDragItem private void SetNewDragItem(MonthView pv, CalendarItem view, bool isNewCopyDrag) { CalendarView.CalendarPanel.InternalMouseMove(new MouseEventArgs(MouseButtons.None, 0, view.Bounds.X + 5, view.Bounds.Y, 0)); MouseEventArgs args = new MouseEventArgs(MouseButtons.Left, 1, view.Bounds.X + 5, view.Bounds.Y, 0); IsMoving = true; InternalMouseMove(args); CalendarView.CalendarPanel.InternalMouseDown(args); _DaysOffset = pv._DaysOffset; SelectedItem = view; IsCopyDrag = true; IsNewCopyDrag = isNewCopyDrag; } #endregion #endregion #region MonthView mouseMove processing /// /// Processes MonthView mouseMove events /// /// /// private void ProcessMvMouseMove(int week, int day) { DateTime date = _MonthWeeks[week].FirstDayOfWeek.AddDays(day); // Let the user select forwards or backwards if (date >= DateSelectionAnchor) { CalendarView.DateSelectionStart = DateSelectionAnchor.Value; CalendarView.DateSelectionEnd = date.AddDays(1); } else { CalendarView.DateSelectionStart = date; CalendarView.DateSelectionEnd = DateSelectionAnchor.Value.AddDays(1); } } #endregion #region MoreItems MouseMove processing /// /// ProcessMoreMouseMove /// /// /// /// private void ProcessMoreMouseMove(int week, int day, MouseEventArgs objArg) { ItemRect moreRect = _MonthWeeks[week].MoreItems[day]; if (moreRect.Bounds.Contains(objArg.Location) == true) { if (_MoreRect != moreRect) { if (_MoreRect != null) _MoreRect.IsSelected = false; _MoreRect = moreRect; _MoreRect.IsSelected = true; } } else { if (_MoreRect != null) { _MoreRect.IsSelected = false; _MoreRect = null; } } } #endregion #region CalendarItem mouseMove processing /// /// Processes CalendarItem mouseMove events /// /// Week index /// Day index private void ProcessItemMove(int week, int day) { day -= _DaysOffset; DateTime date = _MonthWeeks[week].FirstDayOfWeek.AddDays(day); DateTime newDate = new DateTime(date.Year, date.Month, date.Day, SelectedItem.StartTime.Hour, SelectedItem.StartTime.Minute, SelectedItem.StartTime.Second); TimeSpan ts = SelectedItem.EndTime - SelectedItem.StartTime; int startWeek1, endWeek1; int day1 = GetCalendarItemWeekRange(SelectedItem, out startWeek1, out endWeek1); if (startWeek1 != week || day1 != day) { if (DragCopy() == false) { try { if (SelectedItem is CustomCalendarItem) CalendarView.CustomItems.BeginUpdate(); else CalendarModel.BeginUpdate(); // Let the user cancel the operation if desired if (CalendarView.DoAppointmentViewChanging(SelectedItem, null, newDate, newDate + ts, eViewOperation.AppointmentMove, IsNewCopyDrag) == false) { SelectedItem.StartTime = newDate; SelectedItem.EndTime = newDate + ts; int startWeek2, endWeek2; GetCalendarItemWeekRange(SelectedItem, out startWeek2, out endWeek2); startWeek1 = Math.Min(startWeek1, startWeek2); endWeek1 = Math.Max(endWeek1, endWeek2); for (int i = startWeek1; i <= endWeek1; i++) InvalidateRect(_MonthWeeks[i].Bounds, true); } } finally { if (SelectedItem is CustomCalendarItem) CalendarView.CustomItems.EndUpdate(); else CalendarModel.EndUpdate(); } } } } /// /// Gets the CalendarItems current week/day range /// /// CalendarItem /// [out] Start week index /// [out] End week index /// Day index private int GetCalendarItemWeekRange( CalendarItem item, out int startWeek, out int endWeek) { startWeek = -1; endWeek = -1; int day = 0; for (int i = 0; i < _NumberOfWeeks; i++) { DateTime startTime = _MonthWeeks[i].FirstDayOfWeek; DateTime endTime = startTime.AddDays(DaysInWeek); if (item.StartTime < endTime && item.EndTime > startTime) { if (startWeek < 0) { startWeek = i; day = item.StartTime.Day - startTime.Day; } endWeek = i; } } if (startWeek == -1) { startWeek = 0; endWeek = _NumberOfWeeks - 1; day = 0; } return (day); } #endregion #region CalendarItem mouseResize processing /// /// Processes CalendarItem left resizing /// /// Week index /// Day index private void ProcessItemLeftResize(int week, int day) { DateTime date = _MonthWeeks[week].FirstDayOfWeek.AddDays(day); DateTime newStartTime = new DateTime(date.Year, date.Month, date.Day, SelectedItem.StartTime.Hour, SelectedItem.StartTime.Minute, SelectedItem.StartTime.Second); if (newStartTime < SelectedItem.EndTime && SelectedItem.StartTime != newStartTime) { // Let the user cancel the operation if desired if (CalendarView.DoAppointmentViewChanging(SelectedItem, null, newStartTime, SelectedItem.EndTime, eViewOperation.AppointmentResize, IsNewCopyDrag) == false) { SelectedItem.StartTime = newStartTime; InvalidateRect(true); } } } /// /// Processes CalendarItem right resizing /// /// Week index /// Day index private void ProcessItemRightResize(int week, int day) { DateTime date = _MonthWeeks[week].FirstDayOfWeek.AddDays(day); DateTime newEndTime = new DateTime(date.Year, date.Month, date.Day, SelectedItem.EndTime.Hour, SelectedItem.EndTime.Minute, SelectedItem.EndTime.Second); if (newEndTime.Hour == 0 && newEndTime.Minute == 0 && newEndTime.Second == 0) newEndTime = newEndTime.AddDays(1); if (newEndTime > SelectedItem.StartTime && SelectedItem.EndTime != newEndTime) { // Let the user cancel the operation if desired if (CalendarView.DoAppointmentViewChanging(SelectedItem, null, SelectedItem.StartTime, newEndTime, eViewOperation.AppointmentResize, IsNewCopyDrag) == false) { SelectedItem.EndTime = newEndTime; InvalidateRect(true); } } } #endregion #endregion #region Mouse support routines /// /// Gets the week and day index item for /// the given point /// /// Point /// [out] Week index /// [out] Day index /// Success or failure private bool GetPointItem(Point pt, out int week, out int day) { day = -1; if ((week = GetPointWeek(pt)) >= 0) { if ((day = GetPointDay(pt, week)) >= 0) return (true); } return (false); } /// /// Gets the week index for the given point /// /// Point /// Week index private int GetPointWeek(Point pt) { for (int i = 0; i < _NumberOfWeeks; i++) { Rectangle r = _MonthWeeks[i].Bounds; if (pt.X >= r.X && pt.X <= r.Right && pt.Y > r.Y && pt.Y < r.Bottom) return (i); } return (-1); } /// /// Gets the day index for the given point /// /// Point /// Week index /// Day index private int GetPointDay(Point pt, int week) { ItemRects rs = _MonthWeeks[week].DayRects; for (int i = 0; i < DaysInWeek; i++) { Rectangle r = rs[i].Bounds; if (pt.X >= r.X && pt.X <= r.Right && pt.Y > r.Y && pt.Y < r.Bottom) return (i); } return (-1); } #endregion #endregion #region InternalKeyDown #region InternalKeyDown /// /// Processes KeyDown events /// /// public override void InternalKeyDown(KeyEventArgs objArg) { switch (objArg.KeyData) { case Keys.Up: case Keys.Up | Keys.Shift: case Keys.Up | Keys.Control: case Keys.Up | Keys.Control | Keys.Shift: ProcessUpDownKey(objArg, -7); break; case Keys.Down: case Keys.Down | Keys.Shift: case Keys.Down | Keys.Control: case Keys.Down | Keys.Control | Keys.Shift: ProcessUpDownKey(objArg, 7); break; case Keys.Left: case Keys.Left | Keys.Shift: case Keys.Left | Keys.Control: case Keys.Left | Keys.Control | Keys.Shift: ProcessLeftRightKey(objArg, -1); break; case Keys.Right: case Keys.Right | Keys.Shift: case Keys.Right | Keys.Control: case Keys.Right | Keys.Control | Keys.Shift: ProcessLeftRightKey(objArg, 1); break; case Keys.Home: case Keys.Home | Keys.Shift: case Keys.Home | Keys.Control: case Keys.Home | Keys.Control | Keys.Shift: ProcessHomeKey(objArg); break; case Keys.End: case Keys.End | Keys.Shift: case Keys.End | Keys.Control: case Keys.End | Keys.Control | Keys.Shift: ProcessEndKey(objArg); break; case Keys.PageUp: case Keys.PageUp | Keys.Shift: case Keys.PageUp | Keys.Control: case Keys.PageUp | Keys.Control | Keys.Shift: ProcessUpDownKey(objArg, -7); break; case Keys.PageDown: case Keys.PageDown | Keys.Shift: case Keys.PageDown | Keys.Control: case Keys.PageDown | Keys.Control | Keys.Shift: ProcessUpDownKey(objArg, 7); break; } } #endregion #region ProcessUpDownKey /// /// Processes Up and Down Key events /// /// /// protected virtual void ProcessUpDownKey(KeyEventArgs objArg, int dy) { if (ValidDateSelection()) { DateTime startDate = CalendarView.DateSelectionStart.Value; DateTime endDate = CalendarView.DateSelectionEnd.Value; if (startDate.Equals(DateSelectionAnchor.Value) == true) startDate = endDate.AddDays(-1); startDate = startDate.AddDays(dy); endDate = startDate.AddDays(1); int week = GetWeekFromDate(startDate); if (week >= 0) { ExtendSelection(ref startDate, ref endDate); CalendarView.DateSelectionStart = startDate; CalendarView.DateSelectionEnd = endDate; } } objArg.Handled = true; } #endregion #region ProcessLeftRightKey /// /// Processes Left and Right key events /// /// /// protected virtual void ProcessLeftRightKey(KeyEventArgs objArg, int dx) { if (ValidDateSelection()) { DateTime startDate = CalendarView.DateSelectionStart.Value; DateTime endDate = CalendarView.DateSelectionEnd.Value; if (startDate.Equals(DateSelectionAnchor.Value) == true) startDate = endDate.AddDays(-1); startDate = startDate.AddDays(dx); endDate = startDate.AddDays(1); DateTime viewStart = _MonthWeeks[0].FirstDayOfWeek; DateTime viewEnd = _MonthWeeks[_MonthWeeks.Length - 1].FirstDayOfWeek.AddDays(7); bool cancelled = false; if (startDate < viewStart || endDate > viewEnd) { cancelled = CalendarView.DoViewDateChanging(this, StartDate, EndDate, ref startDate, ref endDate); if (cancelled == false) CalendarView.EnsureVisible(startDate, startDate.AddDays(1)); } if (cancelled == false) { ExtendSelection(ref startDate, ref endDate); CalendarView.DateSelectionStart = startDate; CalendarView.DateSelectionEnd = endDate; } } objArg.Handled = true; } #endregion #region ProcessHomeKey /// /// Processes Hoe key events /// /// protected virtual void ProcessHomeKey(KeyEventArgs objArg) { int week = ((objArg.Modifiers & Keys.Control) != Keys.Control) ? GetHomeEndWeek() : 0; if (week >= 0) { DateTime startDate = _MonthWeeks[week].FirstDayOfWeek; DateTime endDate = startDate.AddDays(1); ExtendSelection(ref startDate, ref endDate); CalendarView.DateSelectionStart = startDate; CalendarView.DateSelectionEnd = endDate; SelectedItem = null; } objArg.Handled = true; } #endregion #region ProcessEndKey /// /// Processes End key events /// /// protected virtual void ProcessEndKey(KeyEventArgs objArg) { int week = ((objArg.Modifiers & Keys.Control) != Keys.Control) ? GetHomeEndWeek() : _NumberOfWeeks - 1; if (week >= 0) { DateTime startDate = _MonthWeeks[week].FirstDayOfWeek.AddDays(6); DateTime endDate = startDate.AddDays(1); ExtendSelection(ref startDate, ref endDate); CalendarView.DateSelectionStart = startDate; CalendarView.DateSelectionEnd = endDate; SelectedItem = null; } objArg.Handled = true; } #endregion #region GetWeekFromDate /// /// Gets the week containing the given date /// /// /// Week or -1 private int GetWeekFromDate(DateTime date) { for (int i = 0; i < _NumberOfWeeks; i++) { DateTime dc = _MonthWeeks[i].FirstDayOfWeek; if (dc <= date && dc.AddDays(7) > date) return (i); } return (-1); } #endregion #region GetHomeEndWeek /// /// Gets the Home and End week from the /// current selection range /// /// private int GetHomeEndWeek() { if (ValidDateSelection() == true) { if (CalendarView.DateSelectionStart.Equals(DateSelectionAnchor.Value) == true) return (GetWeekFromDate(DateSelectionEnd.Value.AddDays(-1))); return (GetWeekFromDate(DateSelectionStart.Value)); } return (-1); } #endregion #endregion #region IDisposable Members protected override void Dispose(bool disposing) { if (disposing == true && IsDisposed == false) { ResetView(); HookEvents(false); } base.Dispose(disposing); } #endregion #region Copy object /// /// Returns copy of the item. /// public override BaseItem Copy() { MonthView objCopy = new MonthView(this.CalendarView); CopyToItem(objCopy); return (objCopy); } /// /// Copies the MonthView specific properties to new instance of the item. /// /// New MonthView instance protected override void CopyToItem(BaseItem copy) { MonthView objCopy = copy as MonthView; if (objCopy != null) { base.CopyToItem(objCopy); objCopy._IsSideBarVisible = this._IsSideBarVisible; } } #endregion } #region EventArgs #region IsSideBarVisibleChangedEventArgs /// /// IsSideBarVisibleChangedEventArgs /// public class IsSideBarVisibleChangedEventArgs : ValueChangedEventArgs { public IsSideBarVisibleChangedEventArgs(bool oldValue, bool newValue) : base(oldValue, newValue) { } } #endregion #endregion } #endif