#if FRAMEWORK20
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DevComponents.Schedule.Model;
namespace DevComponents.DotNetBar.Schedule
{
public class WeekDayView : BaseView
{
#region Constants
private const int HoursPerDay = 24;
private const int MinutesPerHour = 60;
private const int MaxNumberOfColumns = 3 * 31;
#endregion
#region Private variables
private AllDayPanel _AllDayPanel; // AllDay items panel
private DayColumn[] _DayColumns; // Array of DayColumns
private int _NumberOfColumns; // Number of DayColumns
private Size[] _DayColumnSize; // Array of day text sizes
private CalendarWeekDayColor _ViewColor = // View display color table
new CalendarWeekDayColor(eCalendarColor.Automatic);
private int _LastCol; // Last processed column
private Point _LastMovePoint; // Last mouse move Point
private Point _LastPointOffset; // Last Point offset
private Rectangle _LastBounds; // MouseDown item bounds
int _LastMoveCol;
int _LastDm;
private bool _IsPanelResizing; // Flag denoting panel resizing
private bool _WasAllDayItem;
private int _SelectedSliceStart; // Absolute slice start
private int _SelectedSliceEnd; // Absolute slice end (e.g. 450 - 1440)
private Timer _ScrollViewTimer; // Timer used to implement auto view scrolling
private int _VScrollPos; // Vertical scroll bar pos
private Color _BusyColor; // Cached brush colors
private Color _WorkColor;
private Color _OffWorkColor;
private Color _SelectedColor;
private Brush _BusyBrush; // Cached brushes
private Brush _WorkBrush;
private Brush _OffWorkBrush;
private Brush _SelectedBrush;
private Brush _AllDayBrush;
private Color _AllDayColor;
private int _LocalStartSlice;
private int _LocalNumberOfSlices;
#endregion
///
/// Constructor
///
/// CalendarView
///
public WeekDayView(CalendarView calendarView, eCalendarView eCalendarView)
: base(calendarView, eCalendarView)
{
// Allocate our AllDayPanel
_AllDayPanel = new AllDayPanel(this);
_AllDayPanel.Displayed = true;
// Set our non-client drawing info and CalendarColor
NClientData = new NonClientData(
eTabOrientation.Horizontal,
(int)eCalendarWeekDayPart.OwnerTabBorder,
(int)eCalendarWeekDayPart.OwnerTabForeground,
(int)eCalendarWeekDayPart.OwnerTabBackground,
(int)eCalendarWeekDayPart.OwnerTabContentBackground,
(int)eCalendarWeekDayPart.OwnerTabSelectedForeground,
(int)eCalendarWeekDayPart.OwnerTabSelectedBackground);
CalendarColorTable = _ViewColor;
// Hook onto our events
HookEvents(true);
}
#region Public properties
#region DayColumns
///
/// Gets the view DayColumns
///
public DayColumn[] DayColumns
{
get { return (_DayColumns); }
}
#endregion
#region NumberOfColumns
///
/// Gets the view's number of DayColumns
///
public int NumberOfColumns
{
get { return (_NumberOfColumns); }
}
#endregion
#region VScrollBar
///
/// Gets the WeekDay vertical scrollbar
///
public VScrollBarAdv VScrollBar
{
get { return (CalendarView.WeekDayVScrollBar ); }
}
#endregion
#endregion
#region Internal properties
#region Base calendar properties
///
/// Gets the Sub-Day view rectangle
///
internal Rectangle ViewRect
{
get
{
Rectangle r = ClientRect;
int n = DayOfWeekHeaderHeight + _AllDayPanel.PanelHeight;
r.Y += n;
r.Height -= (n + 1);
return (r);
}
}
///
/// Gets the CalendarColor
///
internal CalendarWeekDayColor WeekDayColor
{
get { return (_ViewColor); }
}
#endregion
#region DayColumn properties
///
/// Gets the local StartSlice
///
internal int LocalStartSlice
{
get { return (_LocalStartSlice); }
}
///
/// Gets the local NumberOfSlices
///
internal int LocalNumberOfSlices
{
get { return (_LocalNumberOfSlices); }
}
#endregion
#region AllDayPanel properties
///
/// Gets the view's AllDayPanel
///
internal AllDayPanel AllDayPanel
{
get { return (_AllDayPanel); }
}
#endregion
#endregion
#region Private properties
#region DayColumnWidth
///
/// Gets the DayColumnWidth
///
private float DayColumnWidth
{
get { return (((float)ClientRect.Width - 1) / _NumberOfColumns); }
}
#endregion
#region AllDay Panel properties
///
/// Gets the maximum AllDayPanel height
///
private int MaximumAllDayPanelHeight
{
get { return (CalendarView.MaximumAllDayPanelHeight); }
}
#endregion
#region Time Slice properties
///
/// Gets the TimeSlotDuration
///
private int TimeSlotDuration
{
get { return (CalendarView.TimeSlotDuration); }
}
///
/// Gets the default Time Slice height
///
private float TimeSliceHeight
{
get { return (CalendarView.TimeSliceHeight); }
set { CalendarView.TimeSliceHeight = value; }
}
///
/// Gets the SlotsPerHour
///
private int SlotsPerHour
{
get { return (CalendarView.SlotsPerHour); }
}
///
/// Gets the NumberOfSlices
///
private int NumberOfSlices
{
get { return (CalendarView.NumberOfSlices); }
set { CalendarView.NumberOfSlices = value; }
}
///
/// Gets the NumberOfActiveSlices
///
private int NumberOfActiveSlices
{
get { return (CalendarView.NumberOfActiveSlices); }
}
///
/// Gets the StartSlice
///
private int StartSlice
{
get { return (CalendarView.StartSlice); }
set { CalendarView.StartSlice = value; }
}
#endregion
#region BusyBrush
///
/// Gets and sets the Busy time brush
///
private Brush BusyBrush
{
get
{
Color color = _ViewColor.GetColor(
(int)eCalendarWeekDayPart.DayAllDayEventBackground);
if (_BusyColor != color)
{
_BusyColor = color;
BusyBrush = new SolidBrush(color);
}
return (_BusyBrush);
}
set
{
if (_BusyBrush != value)
{
if (_BusyBrush != null)
_BusyBrush.Dispose();
_BusyBrush = value;
}
}
}
#endregion
#region WorkBrush
///
/// Gets and sets the Work time brush
///
private Brush WorkBrush
{
get
{
Color color = _ViewColor.GetColor(
(int)eCalendarWeekDayPart.DayWorkHoursBackground);
if (_WorkColor != color)
{
_WorkColor = color;
WorkBrush = new SolidBrush(color);
}
return (_WorkBrush);
}
set
{
if (_WorkBrush != value)
{
if (_WorkBrush != null)
_WorkBrush.Dispose();
_WorkBrush = value;
}
}
}
#endregion
#region OffWorkBrush
///
/// Gets and sets the Off-hours work time brush
///
private Brush OffWorkBrush
{
get
{
Color color = _ViewColor.GetColor(
(int)eCalendarWeekDayPart.DayOffWorkHoursBackground);
if (_OffWorkColor != color)
{
_OffWorkColor = color;
OffWorkBrush = new SolidBrush(color);
}
return (_OffWorkBrush);
}
set
{
if (_OffWorkBrush != value)
{
if (_OffWorkBrush != null)
_OffWorkBrush.Dispose();
_OffWorkBrush = value;
}
}
}
#endregion
#region AllDayBrush
///
/// Gets and sets the Off-hours work time brush
///
private Brush AllDayBrush
{
get
{
Color color = _ViewColor.GetColor(
(int)eCalendarWeekDayPart.DayAllDayEventBackground);
if (_AllDayColor != color)
{
_AllDayColor = color;
AllDayBrush = new SolidBrush(color);
}
return (_AllDayBrush);
}
set
{
if (_AllDayBrush != value)
{
if (_AllDayBrush != null)
_AllDayBrush.Dispose();
_AllDayBrush = value;
}
}
}
#endregion
#region SelectedBrush
///
/// Gets and sets the selected brush
///
private Brush SelectedBrush
{
get
{
Color color = _ViewColor.GetColor(
(int)eCalendarWeekDayPart.SelectionBackground);
if (_SelectedColor != color)
{
_SelectedColor = color;
SelectedBrush = new SolidBrush(color);
}
return (_SelectedBrush);
}
set
{
if (_SelectedBrush != value)
{
if (_SelectedBrush != null)
_SelectedBrush.Dispose();
_SelectedBrush = value;
}
}
}
#endregion
#region FirstOnScreenSlice
private int FirstOnScreenSlice
{
get { return ((int)(-_VScrollPos / TimeSliceHeight)); }
}
#endregion
#region LastOnScreenSlice
private int LastOnScreenSlice
{
get { return (FirstOnScreenSlice + OnScreenSlices - 1); }
}
#endregion
#region OnScreenSlices
private int OnScreenSlices
{
get { return ((int)Math.Ceiling(VsPanel.ScrollBar.Height / TimeSliceHeight)); }
}
#endregion
#region VsPanel
///
/// Gets the WeekDay vertical scroll panel
///
private VScrollPanel VsPanel
{
get { return (CalendarView.WeekDayVScrollPanel); }
}
#endregion
#endregion
#region Hook / Unhook Events
///
/// Routine hooks all necessary events for this control
///
/// True to hook, false to unhook
private void HookEvents(bool hook)
{
if (hook == true)
{
CalendarView.SelectedViewChanged += SelectedViewChanged;
CalendarView.TimeSlotDurationChanged += TimeSlotDurationChanged;
CalendarView.FixedAllDayPanelHeightChanged += FixedAllDayPanelHeightChanged;
CalendarView.MaximumAllDayPanelHeightChanged += MaximumAllDayPanelHeightChanged;
CalendarView.WeekDayVScrollPanel.ScrollBarChanged += VScrollPanelScrollBarChanged;
if (this.ECalendarView == eCalendarView.Day)
{
CalendarView.DayViewDateChanged += DayViewDateChanged;
}
else
{
CalendarView.WeekViewStartDateChanged += WeekViewStartDateChanged;
CalendarView.WeekViewEndDateChanged += WeekViewEndDateChanged;
}
}
else
{
CalendarView.SelectedViewChanged -= SelectedViewChanged;
CalendarView.TimeSlotDurationChanged -= TimeSlotDurationChanged;
CalendarView.FixedAllDayPanelHeightChanged -= FixedAllDayPanelHeightChanged;
CalendarView.MaximumAllDayPanelHeightChanged -= MaximumAllDayPanelHeightChanged;
CalendarView.WeekDayVScrollPanel.ScrollBarChanged -= VScrollPanelScrollBarChanged;
if (this.ECalendarView == eCalendarView.Day)
{
CalendarView.DayViewDateChanged -= DayViewDateChanged;
}
else
{
CalendarView.WeekViewStartDateChanged -= WeekViewStartDateChanged;
CalendarView.WeekViewEndDateChanged -= WeekViewEndDateChanged;
}
}
}
#endregion
#region Event handling routines
#region SelectedViewChanged
///
/// Processes view changes
///
/// object
/// SelectedViewEventArgs
void SelectedViewChanged(object sender, SelectedViewEventArgs e)
{
// Update our IsViewSelected state
IsViewSelected = (e.NewValue == this.ECalendarView);
if (IsViewSelected == true)
{
AutoSyncViewDate(e.OldValue);
UpdateDateSelection();
}
else
{
ResetView();
}
// Update our AllDayPanel view
_AllDayPanel.UpdateView();
}
#endregion
#region DayViewDateChanged
///
/// Processes DayViewDate changes
///
///
///
void DayViewDateChanged(object sender, DateChangeEventArgs e)
{
StartDate = e.NewValue;
EndDate = e.NewValue;
}
#endregion
#region WeekViewStartDateChanged
///
/// Processes StartDate changes
///
///
///
void WeekViewStartDateChanged(object sender, DateChangeEventArgs e)
{
StartDate = e.NewValue;
}
#endregion
#region WeekViewEndDateChanged
///
/// Processes EndDate changes
///
///
///
void WeekViewEndDateChanged(object sender, DateChangeEventArgs e)
{
EndDate = e.NewValue;
}
#endregion
#region TimeSlotDurationChanged
///
/// Handles TimeSlotDurationChanged events
///
/// object
/// TimeSlotDurationChangedEventArgs
void TimeSlotDurationChanged(
object sender, TimeSlotDurationChangedEventArgs e)
{
// Reset our slice selection range and
// invalidate our control
_SelectedSliceStart = 0;
_SelectedSliceEnd = 0;
NeedRecalcLayout = true;
RecalcSize();
}
#endregion
#region FixedAllDayPanelHeightChanged
///
/// Handles FixedAllDayPanelHeightChanged events
///
///
///
void FixedAllDayPanelHeightChanged(
object sender, FixedAllDayPanelHeightChangedEventArgs e)
{
NeedRecalcLayout = true;
}
#endregion
#region MaximumAllDayPanelHeightChanged
///
/// Handles MaximumAllDayPanelHeightChanged events
///
///
///
void MaximumAllDayPanelHeightChanged(
object sender, MaximumAllDayPanelHeightChangedEventArgs e)
{
NeedRecalcLayout = true;
}
#endregion
#region VScrollPanel_ScrollBarChanged
///
/// Handles ScrollBarChanged events
///
///
///
void VScrollPanelScrollBarChanged(object sender, EventArgs e)
{
int vdelta = -VsPanel.ScrollBar.Value - _VScrollPos;
if (vdelta != 0)
{
_VScrollPos = -VsPanel.ScrollBar.Value;
// Offset our DayColumn accordingly
for (int i = 0; i < _NumberOfColumns; i++)
{
DayColumn dayColumn = _DayColumns[i];
Rectangle r = dayColumn.Bounds;
r.Y += vdelta;
dayColumn.Bounds = r;
for (int j = 0; j < dayColumn.CalendarItems.Count; j++)
{
dayColumn.CalendarItems[j].Displayed =
dayColumn.CalendarItems[j].Bounds.IntersectsWith(ClientRect);
}
}
// Redraw our view
InvalidateRect(ViewRect);
}
}
#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 (pt.Y >= ClientRect.Y)
{
if (AllDayPanel.Bounds.Contains(pt))
return (eViewArea.InAllDayPanel);
if (pt.Y < ClientRect.Y + DayOfWeekHeaderHeight)
return (eViewArea.InDayOfWeekHeader);
return (eViewArea.InContent);
}
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 col, slice;
if (GetPointItem(pt, out col, out slice, true) == true)
{
startDate = GetTime(_DayColumns[col].Date, slice, 0);
endDate = startDate.AddMinutes(TimeSlotDuration);
return (true);
}
return (false);
}
#endregion
#region GetDateBounds
///
/// Gets the bounding display rectangle for the given date/time.
///
/// The date/time
/// Bounding display rectangle
public Rectangle GetDateBounds(DateTime date)
{
int col = GetColumnFromDate(date);
if (col >= 0)
{
int slice = GetDateSlice(date);
if (slice >= 0)
return (GetSliceRect(col, slice));
}
return (Rectangle.Empty);
}
///
/// Gets the bounding display rectangle for the given
/// starting and ending date/time range.
///
/// Start date
/// End date
/// Bounding display rectangle
public Rectangle GetDateBounds(DateTime startDate, DateTime endDate)
{
Rectangle r1 = GetDateBounds(startDate);
Rectangle r2 = GetDateBounds(endDate);
return (Rectangle.Union(r1, r2));
}
#endregion
#region IsAllDayItem
internal bool IsAllDayItem(CalendarItem item)
{
if (item.Equals(SelectedItem) &&
(IsEndResizing || IsStartResizing || IsMoving))
{
return (false);
}
return (IsAllDayItem(item.StartTime, item.EndTime));
}
internal bool IsAllDayItem(Appointment item)
{
if (SelectedItem != null && item.Equals(SelectedItem.ModelItem) &&
(IsEndResizing || IsStartResizing || IsMoving))
{
return (false);
}
return (IsAllDayItem(item.StartTime, item.EndTime));
}
private bool IsAllDayItem(DateTime startTime, DateTime endTime)
{
//if (NumberOfColumns > 1 ||
if ( CalendarView.AllDayDisplayMode != eAllDayDisplayMode.None)
{
if ((endTime - startTime).TotalDays >= 1)
return (true);
}
//if (NumberOfColumns > 1 ||
if ( CalendarView.AllDayDisplayMode == eAllDayDisplayMode.ByDayBoundary)
{
return (startTime.Day != endTime.Day ||
(endTime - startTime).TotalDays > 1);
}
return (false);
}
#endregion
#region SetSelectedItem
///
/// Handles selected item changes
///
/// CalendarItem
/// EventArgs
internal void ItemIsSelectedChanged(object sender, EventArgs e)
{
CalendarItem ci = sender as CalendarItem;
if (ci != null)
{
if (ci.IsSelected == true)
{
SelectedItem = SetSelectedItem(SelectedItem, ci);
}
else
{
if (ci == SelectedItem)
SelectedItem = null;
}
}
}
#region SetSelectedItem
protected override CalendarItem SetSelectedItem(CalendarItem pci, CalendarItem nci)
{
CalendarItem selItem = null;
for (int i = 0; i < DayColumns.Length; i++)
selItem = SetSelectedCalendarItem(nci, DayColumns[i].CalendarItems, selItem);
selItem = SetSelectedCalendarItem(nci, AllDayPanel.CalendarItems, selItem);
return (selItem);
}
#region SetSelectedCalendarItem
private CalendarItem SetSelectedCalendarItem(
CalendarItem nci, List items, CalendarItem selItem)
{
for (int i = 0; i < items.Count; i++)
{
CalendarItem item = items[i];
item.IsSelected = (nci != null ? (item.ModelItem == nci.ModelItem) : false);
if (item.IsSelected == true && selItem == null)
{
selItem = item;
SelectedItem = item;
}
}
return (selItem);
}
#endregion
#endregion
#endregion
#region UpdateDateSelection
#region UpdateDateSelection
///
/// Updates our slice selection range to reflect
/// the given date selection start and end values
///
protected override void UpdateDateSelection()
{
if (IsViewSelected == true)
{
// Get the new absolute slice selection range
int sliceStart = 0;
int sliceEnd = 0;
if (DateSelectionStart.HasValue && DateSelectionEnd.HasValue)
{
sliceStart = GetDateSlice(DateSelectionStart);
sliceEnd = GetDateSlice(DateSelectionEnd);
if (sliceStart < 0 && sliceEnd < 0)
{
sliceStart = 0;
sliceEnd = 0;
}
if (sliceStart < 0)
sliceStart = 0;
if (sliceEnd < 0)
sliceEnd = _NumberOfColumns * NumberOfActiveSlices;
}
// Limit our range to only those slices
// that are visible on the screen
int s1 = (int)(-_VScrollPos / TimeSliceHeight);
int s2 = (int)(s1 + ViewRect.Height / TimeSliceHeight + 2);
if (s2 > s1)
{
ProcessSelRange(sliceStart, sliceEnd, s1, s2);
// Save our new selection range
_SelectedSliceStart = sliceStart;
_SelectedSliceEnd = sliceEnd;
}
}
}
#endregion
#region GetDateSlice
///
/// Gets the absolute slice value for the given date
///
/// Selection date
/// Absolute slice
private int GetDateSlice(DateTime? selDate)
{
if (selDate.HasValue)
return (GetDateSlice(selDate.Value));
return (-1);
}
private int GetDateSlice(DateTime selDate)
{
// Loop through each column
for (int i = 0; i < _NumberOfColumns; i++)
{
DateTime date = _DayColumns[i].Date;
// If we have found our containing column, then
// calculate the absolute slice value and return it
if (selDate >= date && selDate < date.AddDays(1))
{
int slice = ((selDate.Hour * MinutesPerHour) + selDate.Minute) / TimeSlotDuration;
return (i * NumberOfActiveSlices + slice - StartSlice);
}
}
return (-1);
}
#endregion
#region ProcessSelRange
///
/// Processes the selection time slice range
///
/// Slice range start
/// Slice range end
/// Slice start limit
/// Slice end limit
private void ProcessSelRange(int sliceStart, int sliceEnd, int s1, int s2)
{
// Calculate our starting and ending column range
int fcol = Math.Min(_SelectedSliceStart / NumberOfActiveSlices, sliceStart / NumberOfActiveSlices);
int lcol = Math.Max(_SelectedSliceEnd / NumberOfActiveSlices, sliceEnd / NumberOfActiveSlices);
lcol = Math.Min(_NumberOfColumns - 1, lcol);
// Loop through each column
for (int i = fcol; i <= lcol; i++)
{
// Get the selection status for the given range
bool[] oldSelected = SelectedSlices(s1, s2, i, _SelectedSliceStart, _SelectedSliceEnd);
bool[] newSelected = SelectedSlices(s1, s2, i, sliceStart, sliceEnd);
// Invalidate those slices whose
// selection status changed
Rectangle vRect = ViewRect;
for (int j = 0; j < s2 - s1; j++)
{
if (oldSelected[j] != newSelected[j])
{
Rectangle r = GetSliceRect(i, s1 + j);
r.Intersect(vRect);
if (r.Width > 0 && r.Height > 0)
InvalidateRect(r);
}
}
}
}
#endregion
#region SelectedSlices
///
/// Gets an array of slice selection values
/// over the given range of column slices
///
/// Slice start limit
/// Slice end limit
/// Column
/// Slice range start
/// Slice range end
/// Array of selection values
private bool[] SelectedSlices(int s1, int s2, int col, int sliceStart, int sliceEnd)
{
// Calculate our number of entries and
// allocate our IsSelected array accordingly
int n = s2 - s1;
bool[] sel = new bool[n + 1];
// Loop through the range of entries determining if
// the specific slice is within the selection range
int slice = col * NumberOfActiveSlices + s1;
for (int i = 0; i < n; i++)
{
sel[i] = (slice >= sliceStart && slice < sliceEnd);
slice++;
}
// Return the array to the caller
return (sel);
}
#endregion
#endregion
#region RecalcSize routines
#region RecalcSize
///
/// 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);
if (NeedRecalcLayout == true)
_DayColumnSize = null;
// Allocate our DayColumns
AllocateDayColumns(startDate, endDate);
// Update our Model connection view,
// AllDayPanel, CalendarItems, and DateSelection
UpdateView();
UpdateAllDayPanelItems();
UpdateDayColumns(startDate, endDate);
UpdateCalendarItems();
UpdateDateSelection();
// Set our display view rectangle
Rectangle r = ClientRect;
r.Y += DayOfWeekHeaderHeight;
r.Height -= DayOfWeekHeaderHeight;
SetViewRectangle(r);
// Final Recalc cleanup
if (DaysOfTheWeek != null)
DaysOfTheWeek.NeedsMeasured = true;
NeedRecalcLayout = false;
CalendarView.DoViewLoadComplete(this);
}
}
#endregion
#region NormalizeDates
///
/// Normalizes the user specified start and end dates
///
/// [out] Normalized start date
/// [out] Normalized end date
protected virtual void NormalizeDates(out DateTime startDate, out DateTime endDate)
{
startDate = this.StartDate;
endDate = this.EndDate;
}
#endregion
#region AllocateDayColumns
///
/// Allocates out DayColumns
///
///
///
private void AllocateDayColumns(DateTime startDate, DateTime endDate)
{
// Allocate our DayColumns array to
// hold our info
_NumberOfColumns = (endDate - startDate).Days + 1;
_NumberOfColumns = Math.Max(_NumberOfColumns, 1);
_NumberOfColumns = Math.Min(_NumberOfColumns, MaxNumberOfColumns);
if (_DayColumns == null || _DayColumns.Length != _NumberOfColumns)
_DayColumns = new DayColumn[_NumberOfColumns];
// Prepare to update display info on each time slot
Rectangle r = ViewRect;
r.Y += _VScrollPos;
// Loop through each day column
float dcWidth = DayColumnWidth;
float x1 = r.X;
// Update each DayColumn
for (int i = 0; i < _NumberOfColumns; i++)
{
if (_DayColumns[i] == null)
_DayColumns[i] = new DayColumn(0);
_DayColumns[i].Date = startDate.AddDays(i);
float x2 = (i == _NumberOfColumns - 1) ? r.Right - 1 : x1 + dcWidth;
if (IsLayoutNeeded(i) == true)
_DayColumns[i].Bounds = new Rectangle((int) x1, r.Y, (int) x2 - (int) x1, r.Height);
x1 = x2;
}
}
#endregion
#region UpdateView
///
/// 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 ModelWeekDayViewConnector(CalendarModel, this);
SubItems.Insert(0, _AllDayPanel);
}
}
}
#endregion
#region ResetView
///
/// Disconnects and resets the Model connection
///
internal override void ResetView()
{
_AllDayPanel.ResetView();
base.ResetView();
}
#endregion
#region UpdateAllDayPanelItems
///
/// Updates our AllDayPanel items
///
private void UpdateAllDayPanelItems()
{
if (NeedRecalcLayout == true)
{
// Initiate a RecalcSize for the panel
_AllDayPanel.WidthInternal = ClientRect.Width;
_AllDayPanel.HeightInternal = MaximumAllDayPanelHeight;
_AllDayPanel.RecalcSize();
// Set the panel's bounding rect accordingly
Rectangle r = ClientRect;
r.Width = _AllDayPanel.WidthInternal;
r.Y += DayOfWeekHeaderHeight;
r.Height = _AllDayPanel.HeightInternal;
_AllDayPanel.Bounds = r;
}
}
private bool IsLayoutNeeded(int col)
{
return (NeedRecalcLayout == true ||
_DayColumns[col].NeedRecalcLayout == true);
}
#endregion
#region UpdateDayColumns
///
/// Calculates and updates DayColumn bounds
///
/// Start date
/// End date
protected void UpdateDayColumns(DateTime startDate, DateTime endDate)
{
// Establish our current TimeSlice range
GetTimeSliceData();
// Updating display info on each column
Rectangle r = ViewRect;
r.Y += _VScrollPos;
r.Height = (int) (TimeSliceHeight * NumberOfSlices);
for (int i = 0; i < _NumberOfColumns; i++)
{
_DayColumns[i].TimeSliceHeight = TimeSliceHeight;
if (IsLayoutNeeded(i) == true)
{
_DayColumns[i].Bounds = new
Rectangle(_DayColumns[i].Bounds.X, r.Y, _DayColumns[i].Bounds.Width, r.Height);
InvalidateRect(_DayColumns[i].Bounds);
}
}
}
#region GetTimeSliceData
private void GetTimeSliceData()
{
_LocalStartSlice = 0;
_LocalNumberOfSlices = (HoursPerDay * MinutesPerHour) / TimeSlotDuration + 1;
if (CalendarView.ShowOnlyWorkDayHours == true)
{
WorkTime startTime = new WorkTime(23, 59);
WorkTime endTime = new WorkTime(0, 0);
for (int i = 0; i < NumberOfColumns; i++)
{
DayColumn dc = _DayColumns[i];
if (dc.WorkStartTime.IsEmpty == false || dc.WorkEndTime.IsEmpty == false)
{
if (dc.WorkStartTime <= dc.WorkEndTime)
{
if (dc.WorkStartTime < startTime)
startTime = dc.WorkStartTime;
if (dc.WorkEndTime > endTime)
endTime = dc.WorkEndTime;
}
else
{
startTime = new WorkTime(0, 0);
endTime = new WorkTime(23, 59);
break;
}
}
}
if (endTime > startTime)
{
int startMinutes = (startTime.Hour * MinutesPerHour) + startTime.Minute;
int endMinutes = (endTime.Hour * MinutesPerHour) + endTime.Minute;
_LocalStartSlice = startMinutes / TimeSlotDuration;
_LocalNumberOfSlices = (endMinutes - startMinutes) / TimeSlotDuration + 1;
}
if (StartSlice >= 0)
{
int endSlice = _LocalStartSlice + _LocalNumberOfSlices - 1;
if (_LocalStartSlice > StartSlice)
_LocalStartSlice = StartSlice;
if (StartSlice + NumberOfSlices > endSlice)
endSlice = StartSlice + NumberOfSlices - 1;
_LocalNumberOfSlices = endSlice - _LocalStartSlice + 1;
}
}
StartSlice = _LocalStartSlice;
NumberOfSlices = _LocalNumberOfSlices;
TimeSliceHeight = (float)ViewRect.Height / NumberOfActiveSlices;
}
#endregion
#endregion
#region UpdateCalendarItems
///
/// Updates our CalendarItems list
///
private void UpdateCalendarItems()
{
List list = new List();
for (int i = 0; i < _NumberOfColumns; i++)
{
if (IsLayoutNeeded(i) == true)
{
if (_DayColumns[i].CalendarItems.Count > 0)
{
List items = SortCalendarItems(i);
list.Clear();
for (int j = 0; j < items.Count; j++)
{
ColumnList colList = GetColList(list, items[j]);
colList.AddColumnSlot(items[j], 0);
}
foreach (ColumnList colList in list)
colList.CountColumns();
CalcAppointmentBounds(i, list);
}
_DayColumns[i].NeedRecalcLayout = false;
}
}
}
#region GetColList
private ColumnList GetColList(List list, CalendarItem item)
{
int id = CalendarView.DoGetAppointmentGroupId(item, -1);
int index;
if (GetColListIndex(list, id, out index) == true)
return (list[index]);
ColumnList clist = new ColumnList(id);
if (index < list.Count)
list.Insert(index, clist);
else
list.Add(clist);
return (clist);
}
#region GetColListIndex
private bool GetColListIndex(List list, int id, out int index)
{
for (index=0; index < list.Count; index++)
{
ColumnList colList = list[index];
if (colList.Id == id)
return (true);
if (colList.Id > id)
break;
}
return (false);
}
#endregion
#endregion
#region SortCalendarItems
///
/// Sorts the DayColumn CalendarItem list
///
/// DayColumn index
private List SortCalendarItems(int col)
{
List items = new List();
items.AddRange(_DayColumns[col].CalendarItems);
if (items.Count > 0)
{
items.Sort(
delegate(CalendarItem c1, CalendarItem c2)
{
if (c1.StartTime > c2.StartTime)
return (1);
if (c1.StartTime < c2.StartTime)
return (-1);
if (c1.EndTime - c1.StartTime > c2.EndTime - c2.StartTime)
return (1);
if (c1.EndTime - c1.StartTime < c2.EndTime - c2.StartTime)
return (-1);
int result = 0;
CalendarView.DoDetailSortEvent(this, c1, c2, ref result);
return (result);
}
);
}
return (items);
}
#endregion
#region CalcAppointmentBounds
///
/// Calculates normal appointment bounds
///
/// DayColumn column
/// Accumulated ColumnList
private void CalcAppointmentBounds(int col, List list)
{
Rectangle r = _DayColumns[col].Bounds;
r.X++;
r.Width -= 8;
for (int k = 0; k < list.Count; k++)
{
ColumnList colList = list[k];
Rectangle r3 = r;
float dx3 = (float)r3.Width / list.Count;
r3.X += (int)(dx3 * k);
r3.Width = (int)dx3;
for (int i = 0; i < colList.SList.Count; i++)
{
for (int j = 0; j < colList.SList[i].Count; j++)
{
Rectangle r2 = r3;
SlotItem si = colList.SList[i][j];
CalendarItem item = si.CItem;
float dx = (float)r2.Width / si.Count;
r2.X += (int)(dx * i);
if (si.SList != null && si.SList.Count == 1)
r2.Width = (int)(dx * (si.SList[0].Column - si.Column));
else if (si.SList == null)
r2.Width = r3.Width - (r2.X - r3.X);
else
r2.Width = (int)dx;
DateTime startTime = item.StartTime;
if (startTime.Date < _DayColumns[col].Date)
startTime = _DayColumns[col].Date;
DateTime endTime = item.EndTime;
if (endTime > _DayColumns[col].Date.AddDays(1))
endTime = _DayColumns[col].Date.AddDays(1);
DateTime date = startTime.Date;
TimeSpan ts1 = startTime.AddMinutes(-StartSlice * TimeSlotDuration) - date;
TimeSpan ts2 = endTime - startTime;
int pos = (int)(ts1.TotalMinutes / TimeSlotDuration * TimeSliceHeight);
int height = (int)Math.Round(ts2.TotalMinutes / TimeSlotDuration * TimeSliceHeight);
AppointmentView view = item as AppointmentView;
if (view != null)
{
Font font = view.Font ?? CalendarView.Font;
if (font != null)
height = Math.Max(font.Height + 6, height);
}
r2.Y = r.Y + (int)pos;
r2.Height = height;
// Now that we have calculated the items height and
// width, invoke a Recalc on the item
item.WidthInternal = r2.Width;
item.HeightInternal = r2.Height - 1;
item.RecalcSize();
// Set our bounds for the item
r2.Width = item.WidthInternal;
r2.Height = item.HeightInternal;
if (item.Bounds != r2)
{
InvalidateRect(item.Bounds);
InvalidateRect(r2);
}
item.Bounds = r2;
// Set it's display state
item.Displayed = r2.IntersectsWith(ClientRect);
}
}
}
}
#endregion
#endregion
#endregion
#region Paint processing
#region Root paint code
///
/// Paint processing
///
/// ItemPaintArgs
public override void Paint(ItemPaintArgs e)
{
Graphics g = e.Graphics;
// Set our current color table
_ViewColor.SetColorTable();
// Only draw something if we have something to draw
if (_DayColumns != null)
{
// Calculate our drawing ranges
int dayStart, dayEnd;
int sliceStart, sliceEnd;
int dayCount = GetDayRange(e, out dayStart, out dayEnd);
int sliceCount = GetSliceRange(e, out sliceStart, out sliceEnd);
// Draw our calendar parts
if (dayCount > 0)
DrawDayOfTheWeekHeader(e, dayStart, dayEnd);
if (sliceCount > 0 && dayCount > 0)
{
// Set our clipping region
Rectangle r = ViewRect;
r.X = ClientRect.X;
r.Width = ClientRect.Width;
Region regSave = g.Clip;
g.SetClip(r, CombineMode.Intersect);
// Draw our slices and appointments
DrawSlices(e, sliceStart, sliceEnd, dayStart, dayEnd);
DrawTimeIndicators(g, sliceStart, sliceEnd, eTimeIndicatorLevel.Bottom);
if (Connector != null && Connector.IsConnected)
DrawWeekAppointments(e, dayStart, dayEnd);
DrawTimeIndicators(g, sliceStart, sliceEnd, eTimeIndicatorLevel.Top);
// Restore our original clip region
g.Clip = regSave;
}
// Initiate the painting of our AllDay Panel
_AllDayPanel.Paint(e);
// Update our Alt-Key window
UpdatePosWin(ViewRect);
}
// 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 < _NumberOfColumns)
{
if (_DayColumns[start].Bounds.Right > e.ClipRectangle.X)
break;
start++;
}
// Calc our ending index
int end = start;
while (end < _NumberOfColumns)
{
if (_DayColumns[end].Bounds.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 slices needed to be drawn
/// to satisfy the specified paint request
///
/// ItemPaintArgs
/// [out] Slice start index
/// [out] Slice end index
/// Slice range count (end - start)
internal int GetSliceRange(ItemPaintArgs e, out int sliceStart, out int sliceEnd)
{
// Calc our starting index
int start = 0;
Rectangle v = ViewRect;
while (start < NumberOfSlices)
{
Rectangle r = GetSliceRect(0, start);
if (r.Bottom > v.Top)
{
if (r.Bottom > e.ClipRectangle.Y)
break;
}
start++;
}
// Calc our ending index
int end = start;
while (end < NumberOfSlices)
{
Rectangle r = GetSliceRect(0, end);
if (r.Y >= e.ClipRectangle.Bottom)
break;
end++;
}
// Set the user supplied 'out' values, and
// return the range count to the caller
if (end - start == 0)
{
sliceStart = 0;
sliceEnd = 0;
return (0);
}
sliceStart = start;
sliceEnd = end - 1;
return (end - start);
}
private bool SliceIsSelected(int col, int slice)
{
int nslice = col * NumberOfActiveSlices + slice;
return (nslice >= _SelectedSliceStart && nslice < _SelectedSliceEnd);
}
#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(
_DayColumns[dayStart].Bounds.X, ClientRect.Y,
_DayColumns[dayEnd].Bounds.Right -
_DayColumns[dayStart].Bounds.X, DayOfWeekHeaderHeight);
if (r.Width > 0 && r.Height > 0)
{
// 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
int nowHeader = -1;
using (Brush br =
_ViewColor.BrushPart((int) eCalendarWeekDayPart.DayHeaderBackground, r))
{
using (Pen pen = new Pen(
_ViewColor.GetColor((int) eCalendarWeekDayPart.DayHeaderBorder)))
{
for (int i = dayStart; i <= dayEnd; i++)
{
if (CalendarView.HighlightCurrentDay == true &&
_DayColumns[i].Date.Date.Equals(DateTime.Now.Date))
{
nowHeader = i;
continue;
}
DrawColumnHeader(g, i, type, r, br, pen, eCalendarWeekDayPart.DayHeaderForeground);
}
}
}
// Draw the current "Now" header
if (nowHeader >= 0)
{
using (Brush br =
_ViewColor.BrushPart((int) eCalendarWeekDayPart.NowDayHeaderBackground, r))
{
using (Pen pen = new Pen(
_ViewColor.GetColor((int) eCalendarWeekDayPart.NowDayHeaderBorder)))
{
DrawColumnHeader(g, nowHeader, type, r, br, pen, eCalendarWeekDayPart.NowDayHeaderForeground);
}
}
}
}
}
#region DrawColumnHeader
///
/// DrawColumnHeader
///
///
///
///
///
///
///
///
private void DrawColumnHeader(Graphics g, int i,
DaysOfTheWeek.eDayType type, Rectangle r, Brush br, Pen pen, eCalendarWeekDayPart part)
{
r.X = _DayColumns[i].Bounds.X;
r.Width = _DayColumns[i].Bounds.Width;
g.FillRectangle(br, r);
g.DrawRectangle(pen, r);
Rectangle t = r;
if (CalendarView.DoPreRenderWeekDayHeader(g, this, i, t) == false)
{
// Draw the header text
int n = i % DaysInWeek;
eTextFormat tf = eTextFormat.VerticalCenter | eTextFormat.NoPadding;
r.Inflate(-2, 0);
r.X += 1;
TextDrawing.DrawString(g,
_DayColumns[i].Date.Day.ToString(), BoldFont, Color.Black, r, tf);
r.X += _DayColumnSize[n].Width;
r.Width -= _DayColumnSize[n].Width;
if (type != DaysOfTheWeek.eDayType.None)
{
tf |= eTextFormat.HorizontalCenter;
TextDrawing.DrawString(g, DaysOfTheWeek.DayText[(int) type][n],
Font, _ViewColor.GetColor((int) part), r, tf);
}
CalendarView.DoPostRenderWeekDayHeader(g, this, i, t);
}
}
#endregion
#endregion
#region GetDaysOfTheWeekType
///
/// Get the index for our day of the week text
///
/// Graphics handle
/// Index to header text
private DaysOfTheWeek.eDayType GetDaysOfTheWeekType(Graphics g)
{
// Resize our DayColumn day text if it
// hasn't been resized previously
if (_DayColumnSize == null)
{
_DayColumnSize = new Size[_NumberOfColumns];
for (int i = 0; i < _NumberOfColumns; i++)
{
_DayColumnSize[i] = TextDrawing.MeasureString(g,
_DayColumns[i].Date.Day.ToString(), BoldFont, 0, eTextFormat.NoPadding);
}
}
// Determine if the current DayRect bounds
// are constrained by the text threshold
DaysOfTheWeek.MeasureText(g, Font);
for (int i = 0; i < _NumberOfColumns; i++)
{
if (_DayColumns[i].Bounds.Width <
_DayColumnSize[i].Width + DaysOfTheWeek.DaySize[(int)DaysOfTheWeek.eDayType.Short][i % 7].Width)
{
return (DaysOfTheWeek.eDayType.None);
}
}
for (int i = 0; i < _NumberOfColumns; i++)
{
if (_DayColumns[i].Bounds.Width <
_DayColumnSize[i].Width + DaysOfTheWeek.DaySize[(int)DaysOfTheWeek.eDayType.Long][i % 7].Width)
{
return (DaysOfTheWeek.eDayType.Short);
}
}
return (DaysOfTheWeek.eDayType.Long);
}
#endregion
#endregion
#region DrawSlices
#region DrawSlices
///
/// Draws Normal Appointment time slices
///
/// ItemPaintArgs
/// Start slice
/// End slice
/// Day start
/// Day end
private void DrawSlices(ItemPaintArgs e,
int sliceStart, int sliceEnd, int dayStart, int dayEnd)
{
Graphics g = e.Graphics;
DaySlot[,] daySlots = GetDaySlots(sliceStart, sliceEnd, dayStart, dayEnd);
DrawContent(g, sliceStart, sliceEnd, dayStart, dayEnd, daySlots);
DrawDaySlot(g, sliceStart, sliceEnd, dayStart, dayEnd, daySlots, false);
DrawBorders(g, sliceStart, sliceEnd, dayStart, dayEnd, daySlots);
DrawDaySlot(g, sliceStart, sliceEnd, dayStart, dayEnd, daySlots, true);
}
#endregion
#region GetDaySlots
///
/// Gets the array of DaySlot information
///
///
///
///
///
/// array of DaySlots
private DaySlot[,] GetDaySlots(int sliceStart, int sliceEnd, int dayStart, int dayEnd)
{
DaySlot[,] daySlots = new DaySlot[dayEnd - dayStart + 1, sliceEnd - sliceStart + 1];
for (int i = dayStart; i <= dayEnd; i++)
{
for (int j = sliceStart; j <= sliceEnd; j++)
{
DaySlot daySlot = new DaySlot();
daySlots[i - dayStart, j - sliceStart] = daySlot;
daySlot.Bounds = GetSliceRect(i, j);
daySlot.Selected = SliceIsSelected(i, j);
if (j <= sliceEnd &&
CalendarView.HasViewDisplayCustomizations == true)
{
int start = ((StartSlice + j) * TimeSlotDuration) % 1440;
int end = Math.Min(start + TimeSlotDuration, 1439);
WorkTime wkStart = new WorkTime(start / MinutesPerHour, start % MinutesPerHour);
WorkTime wkEnd = new WorkTime(end / MinutesPerHour, end % MinutesPerHour);
daySlot.Appearance = CalendarView.ViewDisplayCustomizations.GetDaySlotAppearance(
OwnerKey, _DayColumns[i].Date, wkStart, wkEnd);
}
}
}
return (daySlots);
}
#endregion
#region DrawContent
///
/// Time slice content drawing
///
/// Graphics
/// Start slice
/// End slice
/// Day start
/// Day end
///
private void DrawContent(Graphics g,
int sliceStart, int sliceEnd, int dayStart, int dayEnd, DaySlot[,] daySlots)
{
// Loop through each day in each week, displaying
// the associated day content
for (int i = dayStart; i <= dayEnd; i++)
{
for (int j = sliceStart; j <= sliceEnd; j++)
{
DaySlot daySlot = daySlots[i - dayStart, j - sliceStart];
DaySlotAppearance dsa = daySlot.Appearance;
if (CalendarView.DoPreRenderWeekDaySlotBackground(g, this, i, j, daySlot.Bounds) == false)
{
if (dsa != null && daySlot.Selected == false)
{
using (Brush br = new SolidBrush(dsa.BackColor))
g.FillRectangle(br, daySlot.Bounds);
continue;
}
g.FillRectangle(GetContentBrush(daySlot, i, j), daySlot.Bounds);
}
CalendarView.DoPostRenderWeekDaySlotBackground(g, this, i, j, daySlot.Bounds);
}
}
}
#region GetContentBrush
///
/// Gets the background content brush
/// for the given time slice
///
///
/// Column index
/// Time slice
/// Background brush
private Brush GetContentBrush(DaySlot daySlot, int col, int slice)
{
int start = (StartSlice + slice) * TimeSlotDuration;
if (slice < NumberOfActiveSlices)
{
if (daySlot.Selected == true)
return (SelectedBrush);
WorkTime wkStart = new
WorkTime(start / MinutesPerHour, start % MinutesPerHour);
if (_DayColumns[col].IsWorkTime(wkStart) == true)
return (WorkBrush);
if (_DayColumns[col].IsBusyTime(wkStart) == true)
return (BusyBrush);
}
else
{
return (AllDayBrush);
}
return (OffWorkBrush);
}
#endregion
#endregion
#region DrawDaySlot
///
/// Initiates DaySlot drawing
///
///
///
///
///
///
///
/// On top of borders
private void DrawDaySlot(Graphics g, int sliceStart,
int sliceEnd, int dayStart, int dayEnd, DaySlot[,] daySlots, bool onTop)
{
List dsaList = null;
Rectangle dRect = Rectangle.Empty;
for (int i = dayStart; i <= dayEnd; i++)
{
DaySlot lastDaySlot = null;
for (int j = sliceStart; j <= sliceEnd; j++)
{
DaySlot daySlot = daySlots[i - dayStart, j - sliceStart];
Rectangle r = daySlot.Bounds;
DaySlotAppearance dsa = daySlot.Appearance;
if (lastDaySlot != null &&
(lastDaySlot.Appearance != dsa || lastDaySlot.Selected != daySlot.Selected))
{
FlushDaySlotText(g, i, dsaList, ref dRect, lastDaySlot.Selected);
}
lastDaySlot = daySlot;
if (dsa != null)
{
if (dsa.OnTop == onTop)
{
if (daySlot.Selected == true)
{
if (dsa.ShowTextWhenSelected == true)
dRect = dRect.IsEmpty ? r : Rectangle.Union(dRect, r);
}
else
{
dRect = dRect.IsEmpty ? r : Rectangle.Union(dRect, r);
}
if (dsaList == null)
dsaList = new List();
if (dsaList.Contains(dsa) == false)
dsaList.Add(dsa);
}
continue;
}
}
if (lastDaySlot != null)
FlushDaySlotText(g, i, dsaList, ref dRect, lastDaySlot.Selected);
}
}
#region FlushDaySlotText
///
/// Flushes out pending DaySlot drawing
///
///
///
///
/// Display rect
///
private void FlushDaySlotText(Graphics g,
int dayCol, List dsaList, ref Rectangle dRect, bool selected)
{
if (dsaList != null && dsaList.Count > 0)
{
if (dRect.IsEmpty == false)
DrawDaySlotText(g, dayCol, dsaList, dRect, selected);
dsaList.Clear();
dRect = Rectangle.Empty;
}
}
#endregion
#region DrawDaySlotText
///
/// Draws the DaySlot Text
///
///
///
///
///
///
private void DrawDaySlotText(Graphics g,
int dayCol, IEnumerable dsaList, Rectangle cRect, bool selected)
{
foreach (DaySlotAppearance dsa in dsaList)
{
DateTime startTime = GetSlotTime(dayCol, dsa.StartTime);
DateTime endTime = GetSlotTime(dayCol, dsa.EndTime);
DateTime e = endTime.AddMinutes(-1);
WorkTime wkEnd = new WorkTime(e.Hour, e.Minute);
int start = GetWorkTimeSlice(dsa.StartTime);
int end = GetWorkTimeSlice(wkEnd);
Rectangle r = GetSliceRect(dayCol, start);
r = Rectangle.Union(r, GetSliceRect(dayCol, end));
Region rgnSave = g.Clip;
g.SetClip(cRect, CombineMode.Intersect);
string text = dsa.Text;
if (CalendarView.DoRenderDaySlotAppearanceText(g,
r, dsa, startTime, endTime, selected, ref text) == false)
{
if (String.IsNullOrEmpty(dsa.Text) == false)
{
eTextFormat tf = GetTextFormat(dsa.TextAlignment);
Font font = dsa.Font ?? Font;
Color color = (selected == true)
? (dsa.SelectedTextColor.IsEmpty ? Color.Black : dsa.SelectedTextColor)
: (dsa.TextColor.IsEmpty ? Color.Black : dsa.TextColor);
TextDrawing.DrawString(g, text, font, color, r, tf);
}
}
g.Clip = rgnSave;
}
}
#region GetSlotTime
private DateTime GetSlotTime(int dayCol, WorkTime wkTime)
{
DateTime time = _DayColumns[dayCol].Date;
time = time.AddHours(wkTime.Hour);
time = time.AddMinutes(wkTime.Minute);
return (time);
}
#endregion
#region GetWorkTimeSlice
private int GetWorkTimeSlice(WorkTime wkTime)
{
int slice = ((wkTime.Hour * MinutesPerHour) +
wkTime.Minute) / TimeSlotDuration;
return (slice - StartSlice);
}
#region GetTextFormat
private eTextFormat GetTextFormat(ContentAlignment alignment)
{
eTextFormat tf = eTextFormat.WordBreak;
switch (alignment)
{
case ContentAlignment.TopLeft:
tf |= eTextFormat.Top | eTextFormat.Left;
break;
case ContentAlignment.TopCenter:
tf |= eTextFormat.Top | eTextFormat.HorizontalCenter;
break;
case ContentAlignment.TopRight:
tf |= eTextFormat.Top | eTextFormat.Right;
break;
case ContentAlignment.MiddleLeft:
tf |= eTextFormat.VerticalCenter | eTextFormat.Left;
break;
case ContentAlignment.MiddleCenter:
tf |= eTextFormat.VerticalCenter | eTextFormat.HorizontalCenter;
break;
case ContentAlignment.MiddleRight:
tf |= eTextFormat.VerticalCenter | eTextFormat.Right;
break;
case ContentAlignment.BottomLeft:
tf |= eTextFormat.Bottom | eTextFormat.Left;
break;
case ContentAlignment.BottomCenter:
tf |= eTextFormat.Bottom | eTextFormat.HorizontalCenter;
break;
case ContentAlignment.BottomRight:
tf |= eTextFormat.Bottom | eTextFormat.Right;
break;
}
return (tf);
}
#endregion
#endregion
#endregion
#endregion
#region DrawTimeIndicators
#region DrawTimeIndicators
///
/// Draw view TimeIndicators
///
///
///
///
private void DrawTimeIndicators(Graphics g,
int sliceStart, int sliceEnd, eTimeIndicatorLevel level)
{
DateTime start = _DayColumns[0].Date;
DateTime end = _DayColumns[_NumberOfColumns - 1].Date.AddDays(1);
Rectangle r = Rectangle.Union(GetSliceRect(0, sliceStart), GetSliceRect(0, sliceEnd));
for (int i = 0; i < CalendarView.TimeIndicators.Count; i++)
{
TimeIndicator ti = CalendarView.TimeIndicators[i];
if (ti.IndicatorLevel == level)
{
if (ti.IndicatorArea == eTimeIndicatorArea.All ||
ti.IndicatorArea == eTimeIndicatorArea.Content)
{
if (ti.IsVisible(CalendarView, this))
{
DateTime time = ti.IndicatorDisplayTime;
if (time >= start && time < end)
DrawTimeIndicator(g, r, ti);
}
}
}
}
}
#endregion
#region DrawTimeIndicator
#region DrawTimeIndicator
///
/// Draws individual view TimeIndicator
///
///
///
///
private void DrawTimeIndicator(Graphics g, Rectangle sRect, TimeIndicator ti)
{
Rectangle r = GetIndicatorRect(ti);
if (r.IntersectsWith(sRect) == true)
{
if (r.Height > 0)
{
ColorDef cdef = GetIndicatorColor(ti);
if (cdef != null)
{
using (Brush br = _ViewColor.BrushPart(cdef, r))
{
if (br is LinearGradientBrush)
((LinearGradientBrush) br).WrapMode = WrapMode.TileFlipX;
g.FillRectangle(br, r);
}
}
}
Color color = GetIndicatorBorder(ti);
if (color.IsEmpty == false)
{
using (Pen pen = new Pen(color))
g.DrawLine(pen, r.X + 1, r.Bottom, r.Right - 1, r.Bottom);
}
}
}
#endregion
#region GetIndicatorRect
///
/// Gets the TimeIndicator rectangle
///
///
///
internal override Rectangle GetIndicatorRect(TimeIndicator ti)
{
return (GetIndicatorRect(ti, ti.IndicatorDisplayTime));
}
///
/// Gets the TimeIndicator rectangle for the
/// given DataTime
///
///
///
///
internal override Rectangle GetIndicatorRect(TimeIndicator ti, DateTime time)
{
DateTime startTime = GetTime(_DayColumns[0].Date, 0, 0);
DateTime endTime = GetTime(_DayColumns[NumberOfColumns - 1].Date, NumberOfActiveSlices, 0);
if (time >= startTime && time < endTime)
{
int offset = (int) (time.Hour * SlotsPerHour * TimeSliceHeight +
(TimeSliceHeight * time.Minute) / TimeSlotDuration);
offset -= (int) (StartSlice * TimeSliceHeight);
Rectangle r = ViewRect;
r.Width -= 1;
r.Y = _DayColumns[0].Bounds.Y + offset - ti.Thickness;
r.Height = ti.Thickness;
return (r);
}
return (Rectangle.Empty);
}
#endregion
#region GetIndicatorColor
///
/// Gets the Indicator Back color
///
///
///
private ColorDef GetIndicatorColor(TimeIndicator ti)
{
ColorDef cdef = ti.IndicatorColor;
if (cdef == null || cdef.IsEmpty == true)
cdef = _ViewColor.GetColorDef((int)eCalendarWeekDayPart.TimeIndicator);
return (cdef);
}
#endregion
#region GetIndicatorBorder
///
/// Gets the Indicator Border color
///
///
///
private Color GetIndicatorBorder(TimeIndicator ti)
{
return (ti.BorderColor.IsEmpty == false ? ti.BorderColor :
_ViewColor.GetColor((int)eCalendarWeekDayPart.TimeIndicatorBorder));
}
#endregion
#endregion
#endregion
#region DrawBorders
#region DrawBorders
///
/// Draws time slice borders
///
/// Graphics
/// Start slice
/// End slice
/// Day start
/// Day end
///
private void DrawBorders(Graphics g,
int sliceStart, int sliceEnd, int dayStart, int dayEnd, DaySlot[,] daySlots)
{
// Draw the horizontal and vertical borders, and
// the current "Now" border
DrawHorizontalBorders(g, sliceStart, sliceEnd, dayStart, dayEnd, daySlots);
DrawVerticalBorders(g, sliceStart, sliceEnd, dayStart, dayEnd);
if (CalendarView.HighlightCurrentDay == true)
DrawNowBorder(g, dayStart, dayEnd);
}
#endregion
#region DrawHorizontalBorders
///
/// Draws horizontal borders
///
///
///
///
///
///
///
private void DrawHorizontalBorders(Graphics g,
int sliceStart, int sliceEnd, int dayStart, int dayEnd, DaySlot[,] daySlots)
{
if (CalendarView.HasViewDisplayCustomizations == true)
{
int n = MinutesPerHour / TimeSlotDuration;
Color hourBorderColor = _ViewColor.GetColor((int)eCalendarWeekDayPart.DayHourBorder);
Color halfHourBorderColor = _ViewColor.GetColor((int)eCalendarWeekDayPart.DayHalfHourBorder);
for (int i = dayStart; i <= dayEnd; i++)
{
for (int j = sliceStart; j <= sliceEnd; j++)
{
DaySlot daySlot = daySlots[i - dayStart, j - sliceStart];
Rectangle r = daySlot.Bounds;
DaySlotAppearance dsa = daySlot.Appearance;
Point pt1 = r.Location;
Point pt2 = new Point(r.Right - 1, r.Y);
if (dsa != null && daySlot.Selected == false)
{
using (Pen pen = new Pen(j % n == 0 ? dsa.HourBorderColor : dsa.HalfHourBorderColor))
g.DrawLine(pen, pt1, pt2);
continue;
}
using (Pen pen = new Pen(j % n == 0 ? hourBorderColor : halfHourBorderColor))
g.DrawLine(pen, pt1, pt2);
}
}
}
else
{
using (Pen pen1 = new Pen(
_ViewColor.GetColor((int) eCalendarWeekDayPart.DayHourBorder)))
{
using (Pen pen2 = new Pen(
_ViewColor.GetColor((int) eCalendarWeekDayPart.DayHalfHourBorder)))
{
Point pt1 = new Point(_DayColumns[dayStart].Bounds.X, 0);
Point pt2 = new Point(_DayColumns[dayEnd].Bounds.Right - 1, 0);
int n = MinutesPerHour/TimeSlotDuration;
for (int i = sliceStart; i <= sliceEnd; i++)
{
Rectangle r = GetSliceRect(0, i);
pt1.Y = pt2.Y = r.Y;
g.DrawLine((i%n) == 0 ? pen1 : pen2, pt1, pt2);
}
}
}
}
}
#endregion
#region DrawVerticalBorders
///
/// Draws the vertical borders
///
///
///
///
///
///
private void DrawVerticalBorders(Graphics g,
int sliceStart, int sliceEnd, int dayStart, int dayEnd)
{
Rectangle r1 = GetSliceRect(0, sliceStart);
Rectangle r2 = GetSliceRect(0, sliceEnd);
using (Pen pen1 = new Pen(
_ViewColor.GetColor((int)eCalendarWeekDayPart.DayViewBorder)))
{
Point pt1 = new Point(0, r1.Y);
Point pt2 = new Point(0, r2.Bottom);
for (int i = dayStart; i <= dayEnd; i++)
{
pt1.X = pt2.X = _DayColumns[i].Bounds.X;
g.DrawLine(pen1, pt1, pt2);
}
pt1.X = pt2.X = _DayColumns[dayEnd].Bounds.Right;
g.DrawLine(pen1, pt1, pt2);
}
}
#endregion
#region DrawNowBorder
///
/// Draws the Current-Day Now border
///
///
///
///
private void DrawNowBorder(Graphics g, int dayStart, int dayEnd)
{
// Draw the "Current" day border
for (int i = dayStart; i <= dayEnd; i++)
{
if (_DayColumns[i].Date.Date.Equals(DateTime.Now.Date))
{
Rectangle r = _DayColumns[i].Bounds;
using (Pen pen = new Pen(
_ViewColor.GetColor((int)eCalendarWeekDayPart.NowDayHeaderBorder)))
{
g.DrawRectangle(pen, r);
}
break;
}
}
}
#endregion
#endregion
#endregion
#region DrawWeekAppointments
///
/// Initiates the drawing of weekly appointments
///
/// ItemPaintArgs
/// Day start index
/// Day end index
private void DrawWeekAppointments(ItemPaintArgs e, int dayStart, int dayEnd)
{
if (e.ClipRectangle.IntersectsWith(ViewRect) == true)
{
// Loop through each day in each week, displaying
// the associated day content
List selItems = null;
for (int i = 0; i <= dayEnd; i++)
{
List items = _DayColumns[i].CalendarItems;
if (items != null && items.Count > 0)
{
int right = _DayColumns[i].Bounds.Right - 1;
for (int j = 0; j < items.Count; j++)
{
CalendarItem item = items[j];
if ((item.Displayed == true) &&
(i >= dayStart || item.Bounds.Right > right))
{
if (item.IsSelected == false)
{
item.Paint(e);
}
else
{
if (selItems == null)
selItems = new List();
selItems.Add(item);
}
}
}
}
}
if (selItems != null)
{
foreach (CalendarItem item in selItems)
item.Paint(e);
}
}
}
#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 (SelectedItem != null)
_WasAllDayItem = IsAllDayItem(SelectedItem);
if (objArg.Button == MouseButtons.Left)
{
if (IsTabMoving == false)
{
// Locate where the event took place
if (InPanelResize(objArg.Location) == true)
{
MyCursor = Cursors.HSplit;
_IsPanelResizing = true;
}
else if (ViewRect.Contains(objArg.Location) == true)
{
int col, slice;
if (GetPointItem(objArg.Location, out col, out slice, true))
{
MyCursor = GetContentCursor();
if (ProcessCilButtonDown(col, objArg) == false)
ProcessDvlButtonDown(col, slice);
IsMouseDown = true;
}
IsCopyDrag = false;
}
}
}
}
#region CalendarItem MouseDown processing
///
/// CalendarItem left mouseDown processing
///
/// DayColumn col index
/// MouseEventArgs
private bool ProcessCilButtonDown(int col, MouseEventArgs objArg)
{
CalendarItem item = m_HotSubItem as CalendarItem;
if (item != null)
{
_WasAllDayItem = IsAllDayItem(item);
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)
{
_LastCol = col;
_LastBounds = item.Bounds;
_LastPointOffset = objArg.Location;
_LastMovePoint = objArg.Location;
_LastMoveCol = -1;
_LastDm = int.MinValue;
if (IsResizing == false && IsMoving == false)
{
OldStartTime = item.StartTime;
OldEndTime = item.EndTime;
OldOwnerKey = OwnerKey;
}
// Flag appropriate action
if (item.HitArea == CalendarItem.eHitArea.TopResize)
IsStartResizing = true;
else if (item.HitArea == CalendarItem.eHitArea.BottomResize)
IsEndResizing = true;
else if (item.HitArea == CalendarItem.eHitArea.Move)
IsMoving = true;
// Update our initial PosWin display
UpdatePosWin(ViewRect);
}
}
return (true);
}
return (false);
}
#endregion
#region DayView MouseDown processing
///
/// Handles DayView left MouseDown events
///
/// DayColumn col index
/// Time slice
private void ProcessDvlButtonDown(int col, int slice)
{
DateTime startDate = GetTime(_DayColumns[col].Date, slice, 0);
DateTime endDate = startDate.AddMinutes(TimeSlotDuration);
ExtendSelection(ref startDate, ref endDate);
CalendarView.DateSelectionStart = startDate;
CalendarView.DateSelectionEnd = endDate;
SelectedItem = null;
}
#endregion
#endregion
#region MouseUp processing
///
/// MouseUp event processing
///
/// MouseEventArgs
public override void InternalMouseUp(MouseEventArgs objArg)
{
base.InternalMouseUp(objArg);
CancelScrollTimer();
// Reset our panel resizing flag
_IsPanelResizing = false;
if (SelectedItem != null &&
(IsAllDayItem(SelectedItem) != _WasAllDayItem))
{
ReloadView();
}
}
#endregion
#region MouseMove processing
#region InternalMouseMove
///
/// 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)
{
if (_IsPanelResizing == true)
{
MyCursor = Cursors.HSplit;
ProcessPanelMove(objArg);
}
else
{
if (InPanelResize(objArg.Location) == true)
{
MyCursor = Cursors.HSplit;
}
else
{
MyCursor = GetContentCursor();
if (objArg.Button == MouseButtons.Left)
ProcessContentMove(objArg);
}
}
}
}
#endregion
#region InPanelResize
///
/// Determines if the mouse is in the
/// panel resize area
///
/// Mouse location
/// true if in the resize area
private bool InPanelResize(Point pt)
{
if (CalendarView.IsMultiCalendar == true)
{
Rectangle r = ViewRect;
if (pt.X > r.Left && pt.X < r.Right &&
pt.Y > r.Y - 3 && pt.Y < r.Y + 3)
{
return (true);
}
}
return (false);
}
#endregion
#region ProcessPanelMove
///
/// Processes the actual panel resizing
///
/// MouseEventArgs
private void ProcessPanelMove(MouseEventArgs objArg)
{
if (_IsPanelResizing == true)
{
Point pt = objArg.Location;
if (pt.Y < ClientRect.Y + DayOfWeekHeaderHeight)
pt.Y = ClientRect.Y + DayOfWeekHeaderHeight;
else if (pt.Y > ClientRect.Bottom - 50)
pt.Y = ClientRect.Bottom - 50;
int n = pt.Y - (ClientRect.Y + DayOfWeekHeaderHeight);
CalendarView.FixedAllDayPanelHeight = n;
}
}
#endregion
#region ProcessContentMove
///
/// Processes content mouse moves
///
/// MouseEventArgs
private void ProcessContentMove(MouseEventArgs objArg)
{
// Locate where the event took place
// and process it accordingly
int col, slice;
if (GetPointItem(objArg.Location, out col, out slice, false))
{
// The slice is visible, so no need to
// enable scrolling - just process the event
EnableViewScrolling(false);
ProcessMouseMove(col, slice, objArg);
}
else if (IsMouseDown == true)
{
if (DragDropAppointment(objArg) == false)
{
// The selected slice is not visible,
// so we need to enable scrolling
EnableViewScrolling(true);
// Only process the event if the user is selecting
// time slice cells (auto moving apps is intrusive looking)
if (DateSelectionAnchor != null)
{
if (col >= 0)
{
if (slice < 0)
slice = 0;
ProcessDvMouseMove(col, slice);
}
}
}
}
}
#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);
WeekDayView wv = bv as WeekDayView;
if (wv != null && wv != this)
{
eViewArea area = bv.GetViewAreaFromPoint(pt);
if (area == eViewArea.InContent)
{
if (CalendarView.DoAppointmentViewChanging(SelectedItem, wv.OwnerKey, SelectedItem.StartTime,
SelectedItem.EndTime, eViewOperation.AppointmentMove, IsNewCopyDrag) == false)
{
DragCopy();
ClearMouseStates();
CancelScrollTimer();
if (PosWin != null)
PosWin.Hide();
AppointmentView av = SelectedItem as AppointmentView;
if (av != null)
return (wv.DragAppointment(this, av, objArgs.Location));
CustomCalendarItem ci = SelectedItem as CustomCalendarItem;
if (ci != null)
return (wv.DragCustomItem(this, ci, objArgs.Location));
}
}
}
}
return (false);
}
#region DragCustomItem
private bool DragCustomItem(WeekDayView pv, CustomCalendarItem ci, Point pt)
{
// Set the new owner and selected view, and
// recalc the new layout
if (ci.BaseCalendarItem != null)
ci = ci.BaseCalendarItem;
ci.OwnerKey = OwnerKey;
_LastMoveCol = 0;
_LastDm = int.MinValue;
if (NumberOfColumns > 1)
{
DateTime sd = ci.StartTime;
TimeSpan ts = ci.EndTime.Subtract(ci.StartTime);
if (Bounds.X > pv.Bounds.X)
{
ci.StartTime = new DateTime(_DayColumns[0].Date.Year,
_DayColumns[0].Date.Month, _DayColumns[0].Date.Day, sd.Hour, sd.Minute, 0);
}
else
{
_LastMoveCol = NumberOfColumns - 1;
ci.StartTime = new DateTime(_DayColumns[NumberOfColumns - 1].Date.Year,
_DayColumns[NumberOfColumns - 1].Date.Month,
_DayColumns[NumberOfColumns - 1].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, pt);
return (true);
}
#endregion
#region DragAppointment
///
/// Drags the given appointment from one view to another
///
/// Previous view
/// Item to move
private bool DragAppointment(WeekDayView pv, AppointmentView av, Point pt)
{
// Set the new owner and selected view, and
// recalc the new layout
av.Appointment.OwnerKey = OwnerKey;
_LastMoveCol = 0;
_LastDm = int.MinValue;
if (NumberOfColumns > 1)
{
DateTime sd = av.Appointment.StartTime;
if (Bounds.X > pv.Bounds.X)
{
av.Appointment.MoveTo(
new DateTime(_DayColumns[0].Date.Year, _DayColumns[0].Date.Month,
_DayColumns[0].Date.Day, sd.Hour, sd.Minute, 0));
}
else
{
_LastMoveCol = NumberOfColumns - 1;
av.Appointment.MoveTo(
new DateTime(_DayColumns[NumberOfColumns - 1].Date.Year,
_DayColumns[NumberOfColumns - 1].Date.Month,
_DayColumns[NumberOfColumns - 1].Date.Day, sd.Hour, sd.Minute, 0));
}
}
NeedRecalcLayout = true;
RecalcSize();
CalendarView.SelectedOwnerIndex = this.DisplayedOwnerKeyIndex;
// Get the new view
AppointmentView view = GetAppointmentView(av.Appointment);
if (view != null)
SetNewDragItem(pv, view, pt);
return (true);
}
#endregion
#region SetNewDragItem
private void SetNewDragItem(WeekDayView pv, CalendarItem view, Point pt)
{
_LastBounds = pv._LastBounds;
_LastMovePoint = pv._LastMovePoint;
_LastPointOffset = pv._LastPointOffset;
int dy = _LastPointOffset.Y - _LastBounds.Y;
CalendarView.CalendarPanel.InternalMouseMove(new
MouseEventArgs(MouseButtons.None, 0, view.Bounds.X, view.Bounds.Y - dy, 0));
MouseEventArgs args = new
MouseEventArgs(MouseButtons.Left, 1, view.Bounds.X, view.Bounds.Y + dy, 0);
IsMoving = true;
InternalMouseMove(args);
CalendarView.CalendarPanel.InternalMouseDown(args);
SelectedItem = view;
IsNewCopyDrag = true;
}
#endregion
#endregion
#endregion
#region GetContentCursor
///
/// Gets the cursor
///
/// Cursor
private Cursor GetContentCursor()
{
CalendarItem item = m_HotSubItem as CalendarItem;
if (item != null)
{
switch (item.HitArea)
{
case CalendarItem.eHitArea.TopResize:
case CalendarItem.eHitArea.BottomResize:
return (Cursors.SizeNS);
case CalendarItem.eHitArea.Move:
return (IsMoving ? Cursors.SizeAll : DefaultCursor);
}
}
return (DefaultCursor);
}
#endregion
#region ProcessMouseMove
///
/// Processes user MouseMove
///
/// DayColumn
/// Slice
///
private void ProcessMouseMove(int col, int slice, MouseEventArgs objArg)
{
if (DateSelectionAnchor != null)
{
ProcessDvMouseMove(col, slice);
}
else if (SelectedItem != null)
{
if (objArg.Location.Equals(_LastMovePoint) == false)
{
if (IsMoving == true)
ProcessItemMove(col, slice, objArg);
else if (IsStartResizing == true)
ProcessItemTopResize(col, slice, objArg);
else if (IsEndResizing == true)
ProcessItemBottomResize(col, slice, objArg);
_LastMovePoint = objArg.Location;
}
}
}
#endregion
#region DayView mouseMove processing
///
/// Processes DayView mouseMove events
///
/// DayColumn col index
/// Time slice
private void ProcessDvMouseMove(int col, int slice)
{
DateTime date = GetTime(_DayColumns[col].Date, slice, 0);
// Let the user select forwards or backwards
if (date >= DateSelectionAnchor)
{
CalendarView.DateSelectionStart = DateSelectionAnchor.Value;
CalendarView.DateSelectionEnd = date.AddMinutes(TimeSlotDuration);
}
else
{
CalendarView.DateSelectionStart = date;
CalendarView.DateSelectionEnd = DateSelectionAnchor.Value.AddMinutes(TimeSlotDuration);
}
}
#endregion
#region CalendarItem MouseMove processing
#region ProcessItemMove
///
/// Processes CalendarItem mouseMove events
///
/// DayColumn col index
/// Time slice
///
private void ProcessItemMove(int col, int slice, MouseEventArgs objArg)
{
// Calculate our new item date
int dm = GetDeltaMinutes(slice, true, objArg);
if (_LastDm == int.MinValue)
_LastDm = dm;
int ddm = dm - _LastDm;
if (_LastMoveCol == -1)
_LastMoveCol = col;
if (col != _LastMoveCol)
ddm += ((col - _LastMoveCol) * HoursPerDay * MinutesPerHour);
_LastDm = dm;
_LastMoveCol = col;
DateTime newDate = SelectedItem.StartTime.AddMinutes(ddm);
TimeSpan ts = SelectedItem.EndTime - SelectedItem.StartTime;
if (newDate != SelectedItem.StartTime)
{
if (CalendarView.AllDayDisplayMode != eAllDayDisplayMode.None)
{
// Make sure we don't cross day boundaries
DateTime start = GetTime(_DayColumns[col].Date, 0, 0);
DateTime end = start.AddMinutes(NumberOfActiveSlices * TimeSlotDuration);
if (newDate < start)
newDate = start;
if (newDate + ts > end)
newDate -= (newDate + ts) - end;
}
// If we have a new date, set our item to it
if (newDate != SelectedItem.StartTime)
{
if (DragCopy() == false)
{
try
{
if (SelectedItem is CustomCalendarItem)
CalendarView.CustomItems.BeginUpdate();
else
CalendarModel.BeginUpdate();
// Make the move
if (CalendarView.DoAppointmentViewChanging(SelectedItem, null, newDate,
newDate + ts, eViewOperation.AppointmentMove,
IsCopyDrag) == false)
{
SelectedItem.StartTime = newDate;
SelectedItem.EndTime = newDate + ts;
InvalidateItems(col);
}
}
finally
{
if (SelectedItem is CustomCalendarItem)
CalendarView.CustomItems.EndUpdate();
else
CalendarModel.EndUpdate();
}
}
else
{
_LastMoveCol = _LastCol;
}
}
}
}
#endregion
#endregion
#region CalendarItem MouseResize processing
#region ProcessItemTopResize
///
/// Processes CalendarItem left resizing
///
/// Time slice
///
private void ProcessItemTopResize(int col, int slice, MouseEventArgs objArg)
{
int dm = GetDeltaMinutes(slice, true, objArg);
DateTime newStartTime;
if (CalendarView.AllDayDisplayMode != eAllDayDisplayMode.None)
{
newStartTime = new DateTime(
SelectedItem.StartTime.Year, SelectedItem.StartTime.Month, SelectedItem.StartTime.Day);
newStartTime = GetTime(newStartTime, 0, dm);
}
else
{
newStartTime = GetTime(_DayColumns[col].Date.Date, 0, dm);
if (newStartTime < _DayColumns[0].Date)
newStartTime = _DayColumns[0].Date;
}
if (newStartTime != SelectedItem.StartTime && newStartTime < SelectedItem.EndTime)
{
if ((SelectedItem.EndTime - newStartTime).TotalMinutes < 0)
newStartTime = SelectedItem.EndTime.AddMinutes(-1);
ResizeItem(_LastCol, newStartTime, SelectedItem.EndTime);
}
}
#endregion
#region ProcessItemBottomResize
///
/// Processes CalendarItem right resizing
///
/// Time slice
///
private void ProcessItemBottomResize(int col, int slice, MouseEventArgs objArg)
{
int dm = GetDeltaMinutes(slice, false, objArg);
DateTime newEndTime;
DateTime end;
if (CalendarView.AllDayDisplayMode != eAllDayDisplayMode.None)
{
newEndTime = new DateTime(
SelectedItem.StartTime.Year, SelectedItem.StartTime.Month, SelectedItem.StartTime.Day);
if (newEndTime < _DayColumns[0].Date)
newEndTime = _DayColumns[0].Date;
newEndTime = GetTime(newEndTime, 0, dm);
end = GetTime(_DayColumns[_LastCol].Date, NumberOfActiveSlices, 0);
}
else
{
newEndTime = GetTime(_DayColumns[col].Date.Date, 0, dm);
if (newEndTime < _DayColumns[0].Date)
newEndTime = _DayColumns[0].Date;
end = GetTime(_DayColumns[_DayColumns.Length - 1].Date, NumberOfActiveSlices, 0);
}
if (newEndTime > end)
newEndTime = end;
if (newEndTime != SelectedItem.EndTime && newEndTime > SelectedItem.StartTime)
{
if ((newEndTime - SelectedItem.StartTime).TotalMinutes < 0)
newEndTime = SelectedItem.StartTime.AddMinutes(1);
ResizeItem(_LastCol, SelectedItem.StartTime, newEndTime);
}
}
#endregion
#region ResizeItem
///
/// Initiates the resize of the selected item
///
///
///
///
private void ResizeItem(int col, DateTime startTime, DateTime endTime)
{
// Let the user cancel the operation if desired
if (CalendarView.DoAppointmentViewChanging(SelectedItem, null, startTime,
endTime, eViewOperation.AppointmentResize, IsNewCopyDrag) == false)
{
InvalidateItems(col);
SelectedItem.StartTime = startTime;
SelectedItem.EndTime = endTime;
}
}
#endregion
#endregion
#region GetDeltaMinutes
///
/// Gets the changes in minutes
/// from the last mouse operation (move or resize)
///
/// Current slice
/// Flag denoting top or bottom delta
/// MouseEventArgs
/// Delta minutes
private int GetDeltaMinutes(int slice, bool ftop, MouseEventArgs objArg)
{
// Calculate our delta minutes
Rectangle t = GetSliceRect(0, slice);
int dm = (objArg.Location.Y - _LastPointOffset.Y);
dm += ftop ? _LastBounds.Top - t.Top
: _LastBounds.Bottom - t.Bottom;
dm = (int)(TimeSlotDuration * dm / TimeSliceHeight);
// If the Alt key is not pressed, then round
// our value off to the nearest slice
if ((Control.ModifierKeys & Keys.Alt) != Keys.Alt)
{
slice += (dm / TimeSlotDuration);
dm = 0;
}
dm += (slice * TimeSlotDuration);
// Make sure we don't cross our day boundaries
if (CalendarView.AllDayDisplayMode != eAllDayDisplayMode.None)
{
if (ftop == true)
{
if (dm < 0)
dm = 0;
}
else
{
dm += TimeSlotDuration;
if (dm >= MinutesPerHour * HoursPerDay)
dm = MinutesPerHour * HoursPerDay - 1;
}
}
return (dm);
}
#endregion
#region InvalidateItems
///
/// Invalidates altered DayColumns
///
/// Current column
internal void InvalidateItems(int col)
{
if (SelectedItem.IsRecurring == false)
{
_DayColumns[_LastCol].NeedRecalcLayout = true;
_DayColumns[col].NeedRecalcLayout = true;
InvalidateRect(_DayColumns[col].Bounds, true);
if (_LastCol != col)
InvalidateRect(_DayColumns[_LastCol].Bounds);
}
else
{
NeedRecalcLayout = true;
}
_LastCol = col;
}
#endregion
#region View Scrolling support
#region EnableViewScrolling
///
/// Routine to enable or disable view scrolling
///
/// true to enable
private void EnableViewScrolling(bool enable)
{
if (enable == true)
{
if (VsPanel.ScrollBar.Maximum > VsPanel.ScrollBar.LargeChange)
{
if (_ScrollViewTimer == null)
{
_ScrollViewTimer = new Timer();
_ScrollViewTimer.Interval = 10;
_ScrollViewTimer.Tick += ScrollViewTimerTick;
_ScrollViewTimer.Start();
}
}
}
else
{
CancelScrollTimer();
}
}
#endregion
#region CancelScrollTimer
///
/// Cancels the view scroll timer
///
private void CancelScrollTimer()
{
// Dispose of our scroll timer
if (_ScrollViewTimer != null)
{
_ScrollViewTimer.Stop();
_ScrollViewTimer.Tick -= ScrollViewTimerTick;
_ScrollViewTimer = null;
}
}
#endregion
#region ScrollAmount
///
/// Determines the amount to scroll (which is
/// based loosely upon the delta magnitude)
///
/// Point delta
/// Scroll amount
private int ScrollAmount(int delta)
{
int dy = Math.Abs(delta);
int amt = (dy < 16 ? 2 : dy < 32 ? 8 : 32);
return (delta < 0 ? -amt : amt);
}
#endregion
#region ScrollViewTimer_Tick
///
/// Handles view scroll timer ticks
///
/// object
/// EventArgs
private void ScrollViewTimerTick(object sender, EventArgs e)
{
Control c = (Control)this.GetContainerControl(true);
if (c != null)
{
// Calculate our delta
Point pt = c.PointToClient(Cursor.Position);
Rectangle r = ViewRect;
int dy = (pt.Y < r.Top) ? ScrollAmount(pt.Y - r.Top) :
(pt.Y >= r.Bottom) ? ScrollAmount(pt.Y - r.Bottom) : 0;
// Scroll if necessary
if (dy != 0)
{
int value = VsPanel.ScrollBar.Value + dy;
value = Math.Max(value, 0);
value = Math.Min(value, VsPanel.ScrollBar.Maximum);
if (VsPanel.ScrollBar.Value != value)
{
VsPanel.ScrollBar.Value = value;
if (PosWin != null)
PosWin.Hide();
InternalMouseMove(new
MouseEventArgs(MouseButtons.Left, 0, pt.X, pt.Y, 0));
}
}
}
}
#endregion
#endregion
#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, -CalendarView.TimeSlotDuration);
break;
case Keys.Down:
case Keys.Down | Keys.Shift:
case Keys.Down | Keys.Control:
case Keys.Down | Keys.Control | Keys.Shift:
ProcessUpDownKey(objArg, CalendarView.TimeSlotDuration);
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:
ProcessPageUpDownKey(objArg, -1);
break;
case Keys.PageDown:
case Keys.PageDown | Keys.Shift:
case Keys.PageDown | Keys.Control:
case Keys.PageDown | Keys.Control | Keys.Shift:
ProcessPageUpDownKey(objArg, 1);
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.AddMinutes(-TimeSlotDuration);
startDate = startDate.AddMinutes(dy);
DateTime viewStart = GetTime(DayColumns[0].Date, 0, 0);
DateTime viewEnd = viewStart.AddMinutes(NumberOfActiveSlices * TimeSlotDuration);
endDate = startDate.AddMinutes(TimeSlotDuration);
if (startDate >= viewStart && endDate <= viewEnd)
{
ExtendSelection(ref startDate, ref endDate);
CalendarView.DateSelectionStart = startDate;
CalendarView.DateSelectionEnd = endDate;
EnsureSelectionVisible();
}
}
objArg.Handled = true;
}
#endregion
#region ProcessLeftRightKey
///
/// Processes Left and Right key events
///
///
///
protected virtual void ProcessLeftRightKey(KeyEventArgs objArg, int dx)
{
if (CalendarView.WeekDayCanExtendRange == true)
{
DateTime oldDate = CalendarView.DayViewDate;
DateTime newDate = CalendarView.DayViewDate.AddDays(dx);
if (CalendarView.DoViewDateChanging(this,
oldDate, oldDate, ref newDate, ref newDate) == false)
{
if (ValidDateSelection())
{
dx = (newDate - oldDate).Days;
DateTime startDate = CalendarView.DateSelectionStart.Value;
DateTime endDate = CalendarView.DateSelectionEnd.Value;
startDate = startDate.AddDays(dx);
endDate = endDate.AddDays(dx);
CalendarView.DateSelectionStart = startDate;
CalendarView.DateSelectionEnd = endDate;
DateSelectionAnchor = DateSelectionAnchor.Value.AddDays(dx);
}
CalendarView.DayViewDate = CalendarView.DayViewDate.AddDays(dx);
}
}
objArg.Handled = true;
}
#endregion
#region ProcessHomeKey
///
/// Processes Home key events
///
///
protected virtual void ProcessHomeKey(KeyEventArgs objArg)
{
int col = GetHomeEndCol();
if (col >= 0)
{
DateTime startDate = GetTime(DayColumns[col].Date, 0, 0);
if ((objArg.Modifiers & Keys.Control) != Keys.Control)
{
WorkTime wt = DayColumns[col].WorkStartTime;
if (wt.IsEmpty == false)
startDate = DayColumns[col].Date.AddMinutes(wt.Hour * 60 + wt.Minute);
}
DateTime endDate = startDate.AddMinutes(TimeSlotDuration);
ExtendSelection(ref startDate, ref endDate);
CalendarView.DateSelectionStart = startDate;
CalendarView.DateSelectionEnd = endDate;
EnsureSelectionVisible();
}
objArg.Handled = true;
}
#endregion
#region ProcessEndKey
///
/// Processes End Key events
///
///
protected virtual void ProcessEndKey(KeyEventArgs objArg)
{
int col = GetHomeEndCol();
if (col >= 0)
{
DateTime startDate = GetTime(DayColumns[col].Date, NumberOfActiveSlices, 0);
if ((objArg.Modifiers & Keys.Control) != Keys.Control)
{
WorkTime wt = DayColumns[col].WorkEndTime;
if (wt.IsEmpty == false)
startDate = DayColumns[col].Date.AddMinutes(wt.Hour * 60 + wt.Minute);
}
DateTime endDate = startDate;
startDate = startDate.AddMinutes(-TimeSlotDuration);
ExtendSelection(ref startDate, ref endDate);
CalendarView.DateSelectionStart = startDate;
CalendarView.DateSelectionEnd = endDate;
EnsureSelectionVisible();
}
objArg.Handled = true;
}
#endregion
#region ProcessPageUpDownKey
///
/// Processes Page Up and Down key events
///
///
/// Paging direction (-1, 1)
protected virtual void ProcessPageUpDownKey(KeyEventArgs objArg, int dy)
{
if (ValidDateSelection())
{
DateTime startDate = CalendarView.DateSelectionStart.Value;
DateTime endDate = CalendarView.DateSelectionEnd.Value;
int col = GetColumnFromDate(startDate);
if ((uint)col < DayColumns.Length)
{
DateTime viewStart = GetTime(DayColumns[col].Date, 0, 0);
DateTime viewEnd = viewStart.AddMinutes(NumberOfActiveSlices * TimeSlotDuration);
if (startDate.Equals(DateSelectionAnchor.Value) == true)
startDate = endDate.AddMinutes(-TimeSlotDuration);
startDate = (dy < 0)
? GetPageUpStartDate(viewStart, startDate)
: GetPageDownStartDate(viewStart, viewEnd, startDate);
endDate = startDate.AddMinutes(TimeSlotDuration);
if (startDate >= viewStart && endDate <= viewEnd)
{
ExtendSelection(ref startDate, ref endDate);
CalendarView.DateSelectionStart = startDate;
CalendarView.DateSelectionEnd = endDate;
EnsureSelectionVisible();
}
}
}
objArg.Handled = true;
}
private DateTime GetPageUpStartDate(
DateTime viewStart, DateTime startDate)
{
DateTime fosDate = viewStart.AddMinutes(TimeSlotDuration*FirstOnScreenSlice);
if (startDate.Equals(fosDate) == false)
return (fosDate);
startDate = startDate.AddMinutes(-TimeSlotDuration * OnScreenSlices);
if (startDate < viewStart)
startDate = viewStart;
return (startDate);
}
private DateTime GetPageDownStartDate(
DateTime viewStart, DateTime viewEnd, DateTime startDate)
{
DateTime eosDate = viewStart.AddMinutes(TimeSlotDuration * LastOnScreenSlice);
if (startDate.Equals(eosDate) == false)
return (eosDate);
startDate = eosDate.AddMinutes(TimeSlotDuration * OnScreenSlices);
if (startDate > viewEnd)
startDate = viewEnd;
return (startDate);
}
#endregion
#region GetHomeEndCol
///
/// Gets the Home and End column from the current
/// selection range
///
///
private int GetHomeEndCol()
{
if (ValidDateSelection() == true)
{
if (CalendarView.DateSelectionStart.Equals(DateSelectionAnchor.Value) == true)
return (GetColumnFromDate(DateSelectionEnd.Value.AddMinutes(-TimeSlotDuration)));
return (GetColumnFromDate(DateSelectionStart.Value));
}
return ((NumberOfColumns == 1) ? 0 : -1);
}
#endregion
#region GetColumnFromDate
///
/// Gets the view column from the given date
///
///
/// The DayColumns index, or -1 if invalid.
public int GetColumnFromDate(DateTime date)
{
for (int i = 0; i < DayColumns.Length; i++)
{
DateTime dc = DayColumns[i].Date.Date;
if (dc <= date && dc.AddDays(1) > date)
return (i);
}
return (-1);
}
#endregion
#region EnsureSelectionVisible
///
/// Ensures the given selection is visible
///
protected virtual void EnsureSelectionVisible()
{
DateTime start = CalendarView.DateSelectionStart.Value;
DateTime end = CalendarView.DateSelectionEnd.Value;
bool refreshed = start.Equals(DateSelectionAnchor) ?
EnsureDateVisible(end.AddMinutes(-CalendarView.TimeSlotDuration)) :
EnsureDateVisible(start);
if (refreshed == false)
Refresh();
}
#endregion
#region EnsureDateVisible
///
/// Ensures the given date is visible
///
///
///
protected virtual bool EnsureDateVisible(DateTime date)
{
if (CalendarView.WeekDayVScrollPanel.ScrollBar.Maximum >
CalendarView.WeekDayVScrollPanel.ScrollBar.LargeChange)
{
Rectangle r = ViewRect;
int offset = (int)(date.Hour * CalendarView.SlotsPerHour * CalendarView.TimeSliceHeight +
(CalendarView.TimeSliceHeight * date.Minute) / CalendarView.TimeSlotDuration);
offset -= (int)(CalendarView.StartSlice * CalendarView.TimeSliceHeight);
int top = CalendarView.WeekDayVScrollPanel.ScrollBar.Value;
int bottom = top + r.Height;
if (offset < top || offset + CalendarView.TimeSliceHeight > bottom)
{
if (offset + CalendarView.TimeSliceHeight > bottom)
offset -= (int)(r.Height - CalendarView.TimeSliceHeight);
offset = Math.Min(offset, CalendarView.WeekDayVScrollPanel.ScrollBar.Maximum);
offset = Math.Max(offset, 0);
CalendarView.WeekDayVScrollPanel.ScrollBar.Value = offset;
return (true);
}
return (false);
}
return (true);
}
#endregion
#endregion
#region TimeSlice support routines
#region GetPointItem
///
/// Gets the column and slice index item for
/// the given point
///
/// Point
/// [out] DayColumn column
/// [out] Time slice
///
/// Item visible state
private bool GetPointItem(Point pt, out int col, out int slice, bool partial)
{
slice = -1;
if ((col = GetPointCol(pt)) >= 0)
{
slice = GetPointSlice(pt, col);
if (slice >= 0 && slice < NumberOfActiveSlices)
return (IsSliceVisible(col, slice, partial));
}
return (false);
}
#endregion
#region IsSliceVisible
///
/// Determines if a given slice is visible
///
/// DayColumn
/// Slice in question
/// Partially visible is ok
/// Slice visibility
private bool IsSliceVisible(int col, int slice, bool partial)
{
Rectangle r = GetSliceRect(col, slice);
Rectangle t = ViewRect;
if (partial == true)
{
if (r.Bottom < t.Top)
return (false);
if (r.Top > t.Bottom)
return (false);
}
else
{
if (r.Top < t.Top)
return (false);
if (r.Bottom > t.Bottom)
return (false);
}
return (true);
}
#endregion
#region GetSliceRect
///
/// Gets the given slice rectangle
///
/// Column
/// Slice
/// Bounding rectangle
private Rectangle GetSliceRect(int col, int slice)
{
if ((uint)col < _DayColumns.Length)
{
Rectangle r = _DayColumns[col].Bounds;
float n = slice * TimeSliceHeight;
r.Y += (int)(n);
r.Height = (int)(n + TimeSliceHeight) - (int)n;
return (r);
}
return (Rectangle.Empty);
}
#endregion
#region GetPointCol
///
/// Gets the col index for the given point
///
/// Point
/// Column
private int GetPointCol(Point pt)
{
for (int i = 0; i < _NumberOfColumns; i++)
{
if (pt.X >= _DayColumns[i].Bounds.X &&
pt.X < _DayColumns[i].Bounds.Right)
{
return (i);
}
}
return (-1);
}
#endregion
#region GetPointSlice
///
/// Gets the slice index for the given point
///
/// Point
///
/// Slice index
private int GetPointSlice(Point pt, int col)
{
int s1 = (int)(-_VScrollPos / TimeSliceHeight);
Rectangle r = GetSliceRect(col, s1);
if (pt.Y < r.Top)
return (s1 - 1);
for (int i = s1; i < NumberOfActiveSlices; i++)
{
r = GetSliceRect(col, i);
if (pt.Y >= r.Top && pt.Y < r.Bottom)
return (i);
}
return (NumberOfActiveSlices - 1);
}
#endregion
#region GetTime
///
/// Gets the DateTime adjusted by the given
/// slice and minutes delta
///
///
///
///
///
private DateTime GetTime(DateTime date, int slice, int minutes)
{
return (date.AddMinutes((StartSlice + slice) * TimeSlotDuration + minutes));
}
#endregion
#endregion
#region IDisposable Members
protected override void Dispose(bool disposing)
{
if (disposing == true && IsDisposed == false)
{
ResetView();
BusyBrush = null;
WorkBrush = null;
OffWorkBrush = null;
SelectedBrush = null;
HookEvents(false);
}
base.Dispose(disposing);
}
#endregion
#region Copy object support
///
/// Returns copy of the item.
///
public override BaseItem Copy()
{
WeekDayView objCopy = new WeekDayView(this.CalendarView, this.ECalendarView);
CopyToItem(objCopy);
return (objCopy);
}
///
/// Copies the WeekDayView specific properties to new instance of the item.
///
/// New WeekDayView instance
protected override void CopyToItem(BaseItem copy)
{
WeekDayView objCopy = copy as WeekDayView;
base.CopyToItem(objCopy);
}
#endregion
#region DaySlot class def
private class DaySlot
{
public Rectangle Bounds;
public bool Selected;
public DaySlotAppearance Appearance;
}
#endregion
}
}
#endif