#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 /// /// Constructor /// /// Assoc CalendarModel /// Assoc MonthView public ModelMonthViewConnector(CalendarModel model, MonthView monthView) { _Model = model; _View = monthView; } #region Public properties /// /// Gets the connection status /// public override bool IsConnected { get { return _IsConnected; } } #endregion #region Connect /// /// Performs Model connection processing /// 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 /// /// Severs the Model/MonthView connection /// 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; } } /// /// Clears individual MonthWeek view connections /// /// MonthWeek 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 /// /// Loads Model/MonthView connection data /// 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 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 /// /// Refreshes the data in a previously established /// and loaded connection /// public void RefreshData() { LoadData(); List removedViews = null; foreach (MonthWeek monthWeek in _View.MonthWeeks) RemoveOutdatedViews(monthWeek, ref removedViews); ProcessRemovedData(removedViews); } #region RemoveOutdatedViews private void RemoveOutdatedViews( MonthWeek monthWeek, ref List 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(); removedViews.Add(view); _View.SubItems._Remove(view); _View.NeedRecalcSize = true; monthWeek.CalendarItems.RemoveAt(i); } } } } #endregion #region ProcessRemovedData private void ProcessRemovedData(List 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 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 GetViewsFromAll(Appointment app) { List list = new List(); 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 /// /// Gets a new appointment view /// /// Appointment /// New view 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 /// /// Gets a new CustomItem /// /// /// 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 /// /// Returns the Month view /// /// public override eCalendarView GetView() { return (eCalendarView.Month); } /// /// Verifies the Model and MonthView are valid /// 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 /// /// Handles Model property change notifications /// /// /// private void ModelPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == CalendarModel.AppointmentsPropertyName) { RefreshData(); _View.NeedRecalcSize = true; _View.Refresh(); } } #endregion #region ModelSubPropertyChanged /// /// Handles ModelSubProperty change notifications /// /// object /// SubPropertyChangedEventArgs 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 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