private void Initialize(SchedulesOnDay schedules, MyObservableList <BaseViewItemHomeworkExamGrade> events, MyObservableList <ViewItemHoliday> holidays) { List <ScheduleItem> schedulesCopied; if (schedules == null) { // Different semester case, so no schedules schedulesCopied = new List <ScheduleItem>(); } else { schedulesCopied = schedules.Where(i => i.EndTime.TimeOfDay > i.StartTime.TimeOfDay).Select(i => new ScheduleItem(this, i)).ToList(); } List <EventItem> eventsCopied = new List <EventItem>(); List <BaseViewItemHomeworkExam> allDayEvents = new List <ViewItems.BaseViewItems.BaseViewItemHomeworkExam>(); foreach (var e in events.OfType <BaseViewItemHomeworkExam>()) { if (e.IsDuringDay()) { eventsCopied.Add(new EventItem(this, e)); } else { allDayEvents.Add(e); } } AllDayItems = allDayEvents; Holidays = holidays.ToList(); HasHolidays = Holidays.Any(); _cachedHolidayAndAllDayItems = null; var schedulesFinal = schedulesCopied.ToArray(); var eventsFinal = eventsCopied.ToList(); ScheduleItems = schedulesFinal; // Handle schedule collisions while (schedulesCopied.Count > 0) { var collidingSchedules = new List <ScheduleItem>() { schedulesCopied[0] }; schedulesCopied.RemoveAt(0); AddColliding(schedulesCopied, collidingSchedules); if (collidingSchedules.Count > 1) { for (int i = 0; i < collidingSchedules.Count; i++) { collidingSchedules[i].Column = i; collidingSchedules[i].NumOfColumns = collidingSchedules.Count; } } } // Handle event collisions while (eventsCopied.Count > 0) { var collidingEvents = new List <EventItem>() { eventsCopied[0] }; eventsCopied.RemoveAt(0); AddColliding(eventsCopied, collidingEvents); List <ScheduleItem> scheduleCollisionsWithEvent = new List <ScheduleItem>(); // If there's a colliding schedule, we collapse bool doesCollideWithSchedule = false; foreach (var e in collidingEvents) { foreach (var s in schedulesFinal) { if (s.CollidesWith(e)) { doesCollideWithSchedule = true; scheduleCollisionsWithEvent.Add(s); } } } if (doesCollideWithSchedule) { var firstEvent = collidingEvents[0]; firstEvent.IsCollapsedMode = true; foreach (var e in collidingEvents.Skip(1)) { firstEvent.AddAdditionalItem(e); eventsFinal.Remove(e); } foreach (var s in scheduleCollisionsWithEvent) { if (firstEvent.AdditionalItems != null) { s.LeftOffset = _spacingWithAdditionalItems; } else { // LeftOffset might have been previously assigned, so make sure we're assigning higher value if (_spacingWhenNoAdditionalItems > s.LeftOffset) { s.LeftOffset = _spacingWhenNoAdditionalItems; } } } } else if (collidingEvents.Count == 1) { // Nothing } else if (collidingEvents.Count == 2) { // Exactly two items collidingEvents[0].NumOfColumns = 2; collidingEvents[1].NumOfColumns = 2; collidingEvents[1].Column = 1; } else { // More than two items EventItem prev = null; bool isLeftSide = true; while (collidingEvents.Count > 0) { var curr = collidingEvents[0]; curr.NumOfColumns = 2; collidingEvents.RemoveAt(0); if (prev != null) { if (!isLeftSide) { curr.Column = 1; } // Find out if any items collide with the prev item, and therefore need to become mini-items with the curr item while (collidingEvents.Count > 0) { var next = collidingEvents[0]; if (prev.CollidesWith(next)) { collidingEvents.RemoveAt(0); curr.AddAdditionalItem(next); eventsFinal.Remove(next); } else { break; } } } // Prev becomes curr prev = curr; // And we switch the side isLeftSide = !isLeftSide; } } } EventItems = eventsFinal.ToArray(); if (ScheduleItems.Any() || EventItems.Any()) { var min = ScheduleItems.OfType <BaseScheduleItem>().Concat(EventItems.OfType <BaseScheduleItem>()).Min(i => i.StartTime); if (min.Minutes == 59 && min.Hours != 23) { // So that a task that's due before class (1 min before) doesn't cause an entire hour to be rendered, we adjust 0:59 to the next hour // Note that we exclude incrementing 23:59 since that would make it the next day min = min.Add(TimeSpan.FromMinutes(1)); } StartTime = new TimeSpan(min.Hours, 0, 0); EndTime = new TimeSpan(ScheduleItems.OfType <BaseScheduleItem>().Concat(EventItems.OfType <BaseScheduleItem>()).Max(i => i.EndTime).Hours, 0, 0); if (EndTime < StartTime) { EndTime = StartTime.Add(TimeSpan.FromHours(1)); } } CalculateOffsets(); }