/// <summary> /// Handles the appoinment overlaps badly. /// </summary> /// <param name="day">The day.</param> private static void handleOverlaps(DayWithHourRegion day) { //TODO: work out overlaps through a better process if (day.Appointments.Count > 0) { for (int j = 0; j < day.Appointments.Count; j++) { AppointmentWithHourRegion app = day.Appointments[j] as AppointmentWithHourRegion; //if we have overlaps, things get nasty if (app.HasOverlaps) { foreach (AppointmentWithHourRegion overlapApp in app.OverlappingAppointments) { //if another appointment overlaps if (!overlapApp.Bounds.IsEmpty && overlapApp.Bounds.IntersectsWith(new Rectangle(app.Bounds.X, app.Bounds.Y, app.Bounds.Width, app.Bounds.Height)) ) { //if the app width is bigger, trim it if (app.Bounds.Width >= overlapApp.Bounds.Width) { //if current app x starts after the other app x if (app.Bounds.X >= overlapApp.Bounds.X) { app.Bounds = new Rectangle( app.Bounds.X + app.Bounds.Width / 4, app.Bounds.Y, app.Bounds.Width - app.Bounds.Width / 4, app.Bounds.Height); } else { app.Bounds = new Rectangle( app.Bounds.X, app.Bounds.Y, app.Bounds.Width - app.Bounds.Width / 4, app.Bounds.Height); } } } if (app.Bounds.X + app.Bounds.Width > day.Bounds.X + day.Bounds.Width) { Rectangle rect = app.Bounds; rect.Width = day.Bounds.X + day.Bounds.Width - app.Bounds.X; app.Bounds = rect; } } } } } }
/// <summary> /// Raises the <see cref="E:Paint"/> event. /// </summary> /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs"/> instance containing the event data.</param> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); //paint hour headers foreach (HeaderRegion header in hourHeaders) { RendererCache.Current.Header.DrawBox(e.Graphics, Font, header.Bounds, header.Name, true, BorderInfo.Default, TextAlignment.Right); } for (int j = 0; j < DayRegions.Count; j++) { DayWithHourRegion day = DayRegions[j] as DayWithHourRegion; if (day != null) { //paint header RendererCache.Current.Header.DrawBox(e.Graphics, Font, day.TitleBounds, day.Name); foreach (HourRegion hour in day.Hours) { if (hour.IsWorkingHour) { RendererCache.Current.Item.DrawBox(e.Graphics, Font, hour.Bounds); RendererCache.Current.ItemLight.DrawLine(e.Graphics, hour.Bounds30.X + 1, hour.Bounds30.Y, hour.Bounds30.X + hour.Bounds30.Width - 2, hour.Bounds30.Y); } else { //non working hours are dark RendererCache.Current.Control.DrawBox(e.Graphics, Font, hour.Bounds); } } foreach (HourRegion hour in day.Hours) { AppointmentRegion paintSelected = null; // int yPosition = hour.Bounds.Y; foreach (AppointmentWithHourRegion app in hour.Appointments) { if (app.Appointment == SelectedAppointment) { paintSelected = app; } else { RendererCache.Current.Appointment.DrawBox(e.Graphics, Font, app.BodyBounds, app.FormattedSubject); if (app.ColourBlockBounds != Rectangle.Empty) { RendererCache.Current.Appointment.DrawBox(e.Graphics, Font, app.ColourBlockBounds, app.Appointment.ColorBlockBrush); } } } // repaint just the selected appointment - to get the border onto it even with overlap if (paintSelected != null) { RendererCache.Current.AppointmentSelected.DrawBox(e.Graphics, Font, paintSelected.BodyBounds, paintSelected.FormattedSubject); if (paintSelected.ColourBlockBounds != Rectangle.Empty) { RendererCache.Current.AppointmentSelected.DrawBox(e.Graphics, Font, paintSelected.ColourBlockBounds, paintSelected.Appointment.ColorBlockBrush); //draw top and bottom blocks RendererCache.Current.AppointmentSelected.DrawBox(e.Graphics, Font, paintSelected.SelectTopBounds, paintSelected.Appointment.ColorBlockBrush); RendererCache.Current.AppointmentSelected.DrawBox(e.Graphics, Font, paintSelected.SelectBottomBounds, paintSelected.Appointment.ColorBlockBrush); } } } } } }
/// <summary> /// Calculate the time slot bounds. This works out the size and /// shape that days will take up on the screen. This method /// is called from OnPaint only when the property BoundsValidTimeSlot /// is set to false (this property is set to false in cases such as /// when the control has been resized or the date shown has /// changed). /// </summary> protected override void CalculateTimeSlotBounds(Graphics g) { if (Width == 0 || Height == 0) { return; } DayRegions.Clear(); hourHeaders.Clear(); int numberOfDays = 1; //set up the start day if (!SingleDay) { //five days numberOfDays = 5; if (Date.DayOfWeek != DayOfWeek.Monday) { //handle sunday being set - go forwards in that case if (Date.DayOfWeek == DayOfWeek.Sunday) { Date = Date.AddDays(1); } else if (Date.DayOfWeek == DayOfWeek.Saturday) { Date = Date.AddDays(2); } else { DateTime temp = Date; while (temp.DayOfWeek != DayOfWeek.Monday) { temp = temp.AddDays(-1); } Date = temp; } } } //set up days for (int i = 0; i < numberOfDays; i++) { DayWithHourRegion day = new DayWithHourRegion(); day.Date = Date.AddDays(i); day.IsInCurrentMonth = true; this.DayRegions.Add(day); } int hourCount = 0; //set up hours for (int j = 0; j < DayRegions.Count; j++) { DayWithHourRegion day = DayRegions[j] as DayWithHourRegion; if (day != null) { for (int i = 0; i < 24; i++) { if (RenderWorkingHoursOnly) { if (i >= (WorkStartHour - 1) && i < (WorkEndHour + 1)) { HourRegion hour = new HourRegion(); hour.IsWorkingHour = (i >= WorkStartHour && i < WorkEndHour); hour.Hour = i; day.Hours.Add(hour); } } else { HourRegion hour = new HourRegion(); hour.IsWorkingHour = (i >= WorkStartHour && i < WorkEndHour); hour.Hour = i; day.Hours.Add(hour); } } if (j == 0) { hourCount = day.Hours.Count; } } } int timeMarkerWidth = 0; if (this.Width > 120) { timeMarkerWidth = 80; } int dayHeaderHeight = (int)(RendererCache.Current.Header.GetTextInfo(g, this.Font).Height * 1.2); int hourHeight = ((Height - 1 - dayHeaderHeight) / hourCount); int xCurrent = timeMarkerWidth; int hourWidth = (Width - timeMarkerWidth - 1) / numberOfDays; int bounds15height = (hourHeight) / 4; //set up day and hour bounds for (int j = 0; j < DayRegions.Count; j++) { DayWithHourRegion day = DayRegions[j] as DayWithHourRegion; if (day != null) { int yCurrent = dayHeaderHeight; //set up day bounds day.Bounds = new Rectangle(xCurrent, 0, hourWidth, hourHeight * day.Hours.Count); day.Name = day.Date.DayOfWeek.ToString(); day.TitleBounds = new Rectangle(xCurrent, 0, hourWidth, dayHeaderHeight); day.BodyBounds = new Rectangle(day.Bounds.X, day.Bounds.Y, day.Bounds.Width, day.Bounds.Height); foreach (HourRegion hour in day.Hours) { //work out the hour bounds hour.Bounds = new Rectangle(xCurrent, yCurrent, hourWidth, hourHeight); //work out the 15 minute divisions hour.Bounds00 = new Rectangle(xCurrent, yCurrent, hourWidth, bounds15height); hour.Bounds15 = new Rectangle(xCurrent, yCurrent + hour.Bounds00.Height, hourWidth, bounds15height); hour.Bounds30 = new Rectangle(xCurrent, yCurrent + hour.Bounds00.Height + hour.Bounds15.Height, hourWidth, bounds15height); hour.Bounds45 = new Rectangle(xCurrent, yCurrent + hour.Bounds00.Height + hour.Bounds15.Height + hour.Bounds30.Height, hourWidth, bounds15height); if (j == 0) { HeaderRegion header = new HeaderRegion(); header.Bounds = new Rectangle(0, yCurrent, timeMarkerWidth, hourHeight); header.Name = string.Format("{0}:00", hour.Hour); hourHeaders.Add(header); } yCurrent += hourHeight; } } xCurrent += hourWidth; } BoundsValidTimeSlot = true; }