599 lines
17 KiB
C#

#if FRAMEWORK20
using System;
using System.Collections.Generic;
using DevComponents.Schedule.Model;
using System.ComponentModel;
namespace DevComponents.DotNetBar.Schedule
{
internal class ModelMonthViewConnector : ModelViewConnector
{
#region Constants
private const int DaysInWeek = 7;
#endregion
#region Private variables
private CalendarModel _Model; // The associated CalendarModel
private MonthView _View; // The associated MonthView
private bool _IsConnected; // Connection status
private uint _RefreshCount;
#endregion
/// <summary>
/// Constructor
/// </summary>
/// <param name="model">Assoc CalendarModel</param>
/// <param name="monthView">Assoc MonthView</param>
public ModelMonthViewConnector(CalendarModel model, MonthView monthView)
{
_Model = model;
_View = monthView;
}
#region Public properties
/// <summary>
/// Gets the connection status
/// </summary>
public override bool IsConnected
{
get { return _IsConnected; }
}
#endregion
#region Connect
/// <summary>
/// Performs Model connection processing
/// </summary>
public override void Connect()
{
VerifyModel();
// Load the connection data
if (_IsConnected)
Disconnect();
LoadData();
// Get notification on Model property changes
_Model.PropertyChanged += ModelPropertyChanged;
_Model.SubPropertyChanged += ModelSubPropertyChanged;
_View.CalendarView.CustomItems.CollectionChanged += CustomItemsCollectionChanged;
_IsConnected = true;
}
#endregion
#region Disconnect
/// <summary>
/// Severs the Model/MonthView connection
/// </summary>
public override void Disconnect()
{
VerifyModel();
if (_IsConnected)
{
// Loop through each week, clearing each
// associated view connection
for (int i = 0; i < _View.MonthWeeks.Length; i++)
ClearMonthWeek(_View.MonthWeeks[i]);
_View.SubItems.Clear();
// Stop notification on Model property changes
_Model.PropertyChanged -= ModelPropertyChanged;
_Model.SubPropertyChanged -= ModelSubPropertyChanged;
_View.CalendarView.CustomItems.CollectionChanged -= CustomItemsCollectionChanged;
_IsConnected = false;
}
}
/// <summary>
/// Clears individual MonthWeek view connections
/// </summary>
/// <param name="monthWeek">MonthWeek</param>
private void ClearMonthWeek(MonthWeek monthWeek)
{
if (monthWeek.CalendarItems.Count > 0)
{
// Loop through each CalendarItem, resetting
// it's associated connection
for (int i = monthWeek.CalendarItems.Count - 1; i >= 0; i--)
{
AppointmentMonthView view =
monthWeek.CalendarItems[i] as AppointmentMonthView;
if (view != null)
{
view.IsSelectedChanged -= _View.ItemIsSelectedChanged;
view.Appointment = null;
view.IsSelected = false;
view.MonthWeek = null;
}
monthWeek.CalendarItems.RemoveAt(i);
}
}
}
#endregion
#region LoadData
/// <summary>
/// Loads Model/MonthView connection data
/// </summary>
private void LoadData()
{
MonthWeek[] wks = _View.MonthWeeks;
if (wks.Length > 0)
{
_RefreshCount++;
DateTime startDate = wks[0].FirstDayOfWeek;
DateTime endDate = DateTimeHelper.EndOfDay(wks[wks.Length - 1].LastDayOfWeek);
DateTime appStartDate = startDate.AddMonths(-1);
List<Appointment> appts = GetAppointmentList(_Model, appStartDate, endDate);
for (int i = 0; i < wks.Length; i++)
{
MonthWeek monthWeek = wks[i];
startDate = monthWeek.FirstDayOfWeek;
endDate = DateTimeHelper.EndOfDay(monthWeek.LastDayOfWeek);
UpdateWeekView(monthWeek, appts, startDate, endDate);
UpdateCustomItems(monthWeek, startDate, endDate);
}
}
}
#endregion
#region RefreshData
/// <summary>
/// Refreshes the data in a previously established
/// and loaded connection
/// </summary>
public void RefreshData()
{
LoadData();
List<CalendarItem> removedViews = null;
foreach (MonthWeek monthWeek in _View.MonthWeeks)
RemoveOutdatedViews(monthWeek, ref removedViews);
ProcessRemovedData(removedViews);
}
#region RemoveOutdatedViews
private void RemoveOutdatedViews(
MonthWeek monthWeek, ref List<CalendarItem> removedViews)
{
for (int i = monthWeek.CalendarItems.Count - 1; i >= 0; i--)
{
CalendarItem view = monthWeek.CalendarItems[i];
if (view != null)
{
if (view.RefreshCount != _RefreshCount)
{
if (removedViews == null)
removedViews = new List<CalendarItem>();
removedViews.Add(view);
_View.SubItems._Remove(view);
_View.NeedRecalcSize = true;
monthWeek.CalendarItems.RemoveAt(i);
}
}
}
}
#endregion
#region ProcessRemovedData
private void ProcessRemovedData(List<CalendarItem> removedViews)
{
if (removedViews != null && removedViews.Count > 0)
{
for (int i = 0; i < removedViews.Count; i++)
{
CalendarItem item = removedViews[i];
item.IsSelectedChanged -= _View.ItemIsSelectedChanged;
item.Dispose();
}
_View.NeedRecalcLayout = true;
}
}
#endregion
#endregion
#region UpdateWeekView
private void UpdateWeekView(MonthWeek monthWeek,
List<Appointment> apps, DateTime startDate, DateTime endDate)
{
// Loop through each appointment
// updating the assoc view accordingly
foreach (Appointment app in apps)
{
if (app.StartTime < endDate && app.EndTime > startDate)
{
if (IsAppointmentVisible(app))
{
// Get the assoc view
AppointmentMonthView view = GetViewFromWeek(monthWeek, app) ??
GetNewView(app);
// Set the view start and end times to
// match the assoc appointment
view.StartTime = app.StartTime;
view.EndTime = app.EndTime;
view.RefreshCount = _RefreshCount;
// And update the MonthWeek data
if (view.MonthWeek == null)
{
view.MonthWeek = monthWeek;
monthWeek.CalendarItems.Add(view);
_View.SubItems.Add(view);
}
view.IsSelected = app.IsSelected;
}
}
}
}
#endregion
#region UpdateCustomItems
private void UpdateCustomItems(
MonthWeek monthWeek, DateTime startDate, DateTime endDate)
{
CustomCalendarItemCollection items = _View.CalendarView.CustomItems;
if (items != null && items.Count > 0)
{
for (int i = 0; i < items.Count; i++)
{
CustomCalendarItem item = items[i];
if (IsCustomItemVisible(item) == true &&
(item.StartTime < endDate && item.EndTime > startDate))
{
item.CalendarView = _View.CalendarView;
CustomCalendarItem ci = GetItemFromWeek(monthWeek, item);
if (ci == null)
{
ci = GetNewCustomItem(item);
monthWeek.CalendarItems.Add(ci);
_View.SubItems.Insert(0, ci);
}
ci.RefreshCount = _RefreshCount;
if (ci.BaseCalendarItem != item)
{
ci.StartTime = item.StartTime;
ci.EndTime = item.EndTime;
}
}
}
}
}
#endregion
#region GetViewFrom
private List<AppointmentMonthView> GetViewsFromAll(Appointment app)
{
List<AppointmentMonthView> list = new List<AppointmentMonthView>();
for (int i = 0; i < _View.MonthWeeks.Length; i++)
{
AppointmentMonthView view =
GetViewFromWeek(_View.MonthWeeks[i], app);
if (view != null)
list.Add(view);
}
return (list);
}
private AppointmentMonthView GetViewFromWeek(MonthWeek monthWeek, Appointment appointment)
{
foreach (CalendarItem item in monthWeek.CalendarItems)
{
AppointmentMonthView view = item as AppointmentMonthView;
if (view != null && view.Appointment == appointment)
return (view);
}
return (null);
}
#endregion
#region GetItemFromWeek
private CustomCalendarItem GetItemFromWeek(MonthWeek monthWeek, CustomCalendarItem item)
{
foreach (CalendarItem citem in monthWeek.CalendarItems)
{
CustomCalendarItem view = citem as CustomCalendarItem;
if (view != null && (view == item || view.BaseCalendarItem == item))
return (view);
}
return (null);
}
#endregion
#region GetNewView
/// <summary>
/// Gets a new appointment view
/// </summary>
/// <param name="appointment">Appointment</param>
/// <returns>New view</returns>
private AppointmentMonthView GetNewView(Appointment appointment)
{
AppointmentMonthView view = new AppointmentMonthView(_View, appointment);
view.Tooltip = appointment.Tooltip;
// Set the selected state to match any current
// views that are present for this appointment
for (int i = 0; i < _View.MonthWeeks.Length; i++)
{
AppointmentMonthView viewPart =
GetViewFromWeek(_View.MonthWeeks[i], appointment);
if (viewPart != null)
{
view.IsSelected = viewPart.IsSelected;
break;
}
}
view.IsSelectedChanged += _View.ItemIsSelectedChanged;
return (view);
}
#endregion
#region GetNewCustomItem
/// <summary>
/// Gets a new CustomItem
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private CustomCalendarItem GetNewCustomItem(CustomCalendarItem item)
{
CustomCalendarItem ci = (CustomCalendarItem)item.Copy();
ci.BaseCalendarItem = item;
ci.ModelItem = item;
// Set the selected state to match any current
// views that are present for this appointment
for (int i = 0; i < _View.MonthWeeks.Length; i++)
{
CustomCalendarItem viewPart =
GetItemFromWeek(_View.MonthWeeks[i], item);
if (viewPart != null)
{
ci.IsSelected = viewPart.IsSelected;
break;
}
}
ci.IsSelectedChanged += _View.ItemIsSelectedChanged;
return (ci);
}
#endregion
#region GetView
/// <summary>
/// Returns the Month view
/// </summary>
/// <returns></returns>
public override eCalendarView GetView()
{
return (eCalendarView.Month);
}
/// <summary>
/// Verifies the Model and MonthView are valid
/// </summary>
private void VerifyModel()
{
if (_Model == null)
throw new NullReferenceException("CalendarModel must be set on connector.");
if (_View == null)
throw new NullReferenceException("MonthCalendarView must be set on connector.");
}
#endregion
#region ModelPropertyChanged
/// <summary>
/// Handles Model property change notifications
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == CalendarModel.AppointmentsPropertyName)
{
RefreshData();
_View.NeedRecalcSize = true;
_View.Refresh();
}
}
#endregion
#region ModelSubPropertyChanged
/// <summary>
/// Handles ModelSubProperty change notifications
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">SubPropertyChangedEventArgs</param>
private void ModelSubPropertyChanged(object sender, SubPropertyChangedEventArgs e)
{
if (e.Source is Owner)
{
Owner owner = (Owner)e.Source;
if (_View.OwnerKey != null && _View.OwnerKey.Equals(owner.Key))
{
if (e.PropertyChangedArgs.PropertyName == Owner.DisplayNamePropertyName)
_View.DisplayName = owner.DisplayName;
else if (e.PropertyChangedArgs.PropertyName.Equals("ColorScheme"))
_View.CalendarColor = owner.ColorScheme;
}
}
else if (e.Source is Appointment)
{
Appointment app = e.Source as Appointment;
List<AppointmentMonthView> list;
string name = e.PropertyChangedArgs.PropertyName;
if (name.Equals("Tooltip"))
{
list = GetViewsFromAll(app);
for (int i = 0; i < list.Count; i++)
list[i].Tooltip = app.Tooltip;
}
else if (name.Equals("IsSelected"))
{
list = GetViewsFromAll(app);
for (int i = 0; i < list.Count; i++)
list[i].IsSelected = app.IsSelected;
}
else if (name.Equals("CategoryColor") || name.Equals("TimeMarkedAs"))
{
list = GetViewsFromAll(app);
for (int i = 0; i < list.Count; i++)
list[i].Refresh();
}
else if (name.Equals("OwnerKey"))
{
if (_View.CalendarView.IsMultiCalendar == true)
{
if (_View.OwnerKey == app.OwnerKey)
{
RefreshData();
_View.NeedRecalcSize = true;
_View.Refresh();
}
else
{
list = GetViewsFromAll(app);
if (list.Count > 0)
{
RefreshData();
_View.NeedRecalcSize = true;
_View.Refresh();
}
}
}
}
else if (name.Equals("Visible"))
{
RefreshData();
}
}
}
#endregion
#region CustomItems_CollectionChanged
void CustomItemsCollectionChanged(object sender, EventArgs e)
{
RefreshData();
_View.NeedRecalcSize = true;
_View.Refresh();
}
#endregion
}
}
#endif