#if FRAMEWORK20 using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace DevComponents.DotNetBar.Schedule { public class AllDayPanel : BaseItem { #region Private variables private WeekDayView _WeekDayView; // Assoc WeekDayView private List // CalendarItems list _CalendarItems = new List(); private VScrollBarAdv _VScrollBar; // Vertical scroll bar private int _VScrollPos; // Vertical scrollbar pos private int _PanelHeight; // Panel height (current) private int _MaximumPanelHeight; // Panel height (max) #endregion /// /// Constructor /// /// WeekDayView public AllDayPanel(WeekDayView weekDayView) { // Save the provided weekDayView and // tell the system we are a container _WeekDayView = weekDayView; SetIsContainer(true); SubItems.AllowParentRemove = false; } #region Public properties /// /// Gets and sets the panel bounding rectangle /// public override Rectangle Bounds { get { return (base.Bounds); } set { base.Bounds = value; UpdateVScrollBar(); } } /// /// Gets the DayPanel Height /// public int PanelHeight { get { return (_PanelHeight); } } /// /// Gets the panel's CalendarItem list /// public List CalendarItems { get { return (_CalendarItems); } } /// /// Gets WeekDayView /// public WeekDayView WeekDayView { get { return (_WeekDayView); } } #endregion #region Private properties /// /// gets the Fixed AllDayPanel height /// private int FixedAllDayPanelHeight { get { return (_WeekDayView.CalendarView.FixedAllDayPanelHeight); } } /// /// gets the Maximum AllDayPanel height /// private int MaximumAllDayPanelHeight { get { return (_WeekDayView.CalendarView.MaximumAllDayPanelHeight); } } /// /// Gets the Appointment height /// private int AppointmentPadding { get { return (6); } } /// /// Gets the width of a vertical scrollbar /// private int VsWidth { get { return (SystemInformation.VerticalScrollBarWidth); } } #endregion #region RecalcSize /// /// Performs panel recalc support /// public override void RecalcSize() { // Reset our panel heights _PanelHeight = 0; _MaximumPanelHeight = 0; if (_CalendarItems.Count > 0) { // Sort the items List items = SortCalendarItems(); // Go through our CalendarItems on a per column basis // accumulating extended appointment data ulong[] acc = new ulong[DaysInWeek]; int maxAcc = -1; for (int i = 0; i < items.Count; i++) { int freeAcc = CalcAppointmentBounds(items[i], acc); if (freeAcc > maxAcc) maxAcc = freeAcc; } // Determine our current panel height from our processed data if (_WeekDayView.CalendarView.IsMultiCalendar == false) { _MaximumPanelHeight = (maxAcc + 1) * _WeekDayView.AppointmentHeight; // Set out current and maximum panel heights _MaximumPanelHeight += AppointmentPadding; _PanelHeight = _MaximumPanelHeight; if (_PanelHeight > MaximumAllDayPanelHeight) _PanelHeight = MaximumAllDayPanelHeight; } } // Take into account the FixedAllDayPanelHeight setting if (_WeekDayView.CalendarView.IsMultiCalendar == true) { _PanelHeight = (FixedAllDayPanelHeight >= 0) ? FixedAllDayPanelHeight : 50; _MaximumPanelHeight = _PanelHeight; } else if (FixedAllDayPanelHeight >= 0) { _PanelHeight = FixedAllDayPanelHeight; } HeightInternal = _PanelHeight; base.RecalcSize(); } #region SortCalendarItems /// /// Sorts the CalendarItems /// private List SortCalendarItems() { List items = new List(_CalendarItems.Count); items.AddRange(_CalendarItems); items.Sort( delegate(CalendarItem c1, CalendarItem c2) { if (c1.StartTime > c2.StartTime) return (1); if (c1.StartTime < c2.StartTime) return (-1); if (c1.EndTime > c2.EndTime) return (-1); if (c1.EndTime < c2.EndTime) return (1); return (0); } ); return (items); } #endregion #region CalcAppointmentBounds const int DaysInWeek = 7; /// /// Calculates the display bounds for the AppointmentView /// /// CalendarItem /// Row accumulator private int CalcAppointmentBounds(CalendarItem item, ulong[] acc) { // Determine the starting day index for // the given appointment int ns = GetDayIndex(item); // Calculate the top and height for the item Rectangle r = _WeekDayView.DayColumns[ns].Bounds; r.Width = 0; r.Y = _WeekDayView.ClientRect.Y + _WeekDayView.DayOfWeekHeaderHeight + _VScrollPos + 2; r.Height = _WeekDayView.AppointmentHeight; int maxAcc = -1; // Determine the ending day index DateTime st = _WeekDayView.DayColumns[ns].Date; int ne = ns + (item.EndTime - st).Days; if (item.EndTime.Hour > 0 || item.EndTime.Minute > 0 || item.EndTime.Second > 0) ne++; if (ne > DaysInWeek) ne = DaysInWeek; int freeAcc = GetFreeAcc(ns, ne, acc); if (freeAcc >= 0) { ulong u = (1ul << freeAcc); for (int i = ns; i < ne; i++) { if (i < _WeekDayView.NumberOfColumns) r.Width += _WeekDayView.DayColumns[i].Bounds.Width; acc[i] |= u; } r.Y += (freeAcc * _WeekDayView.AppointmentHeight); if (freeAcc > maxAcc) maxAcc = freeAcc; } else { r.Y = _WeekDayView.DayColumns[0].Bounds.Bottom; } DateTime start = _WeekDayView.DayColumns[0].Date; DateTime end = _WeekDayView.DayColumns[_WeekDayView.DayColumns.Length - 1].Date; // Check to see if we can only display // a partial representation for the view if (item.EndTime >= start && item.StartTime < end) { int hpad = 4; if (item.StartTime >= start) { r.X += hpad; r.Width -= hpad; } if (item.EndTime <= end) r.Width -= hpad; } // Now that we have calculated the items height and // width, invoke a Recalc on the item item.WidthInternal = r.Width; item.HeightInternal = r.Height - 1; item.RecalcSize(); // Set our bounds for the item r.Width = item.WidthInternal; r.Height = item.HeightInternal; item.Bounds = r; // Set it's display state item.Displayed = true; return (maxAcc); } #region GetFreeAcc private int GetFreeAcc(int ns, int ne, ulong[] acc) { for (int i = 0; i < sizeof(ulong) * 8; i++) { if (CheckFreeAcc(ns, ne, acc, i) == true) return (i); } return (-1); } #region CheckFreeAcc private bool CheckFreeAcc(int ns, int ne, ulong[] acc, int n) { for (int i = ns; i < ne; i++) { ulong u = acc[i]; if ((u & (1ul << n)) != 0) return (false); } return (true); } #endregion #endregion #region GetDayIndex /// /// Gets the starting day index for the given appointment /// /// Day of week index (0-6) private int GetDayIndex(CalendarItem item) { DateTime date = _WeekDayView.DayColumns[0].Date; for (int i = 0; i < _WeekDayView.DayColumns.Length; i++) { date = date.AddDays(1); if (date > item.StartTime) return (i); } return (0); } #endregion #endregion #endregion #region Scrollbar routines #region UpdateVScrollBar /// /// Updates our vertical scrollbar /// private void UpdateVScrollBar() { if (_PanelHeight > 0 && _PanelHeight < _MaximumPanelHeight) { // If we don't have one already, allocate it if (_VScrollBar == null) { _VScrollBar = new VScrollBarAdv(); _VScrollBar.Width = VsWidth; Control c = (Control)this.GetContainerControl(true); if (c != null) c.Controls.Add(_VScrollBar); _VScrollBar.ValueChanged += _VExtScrollBar_ValueChanged; } // Initialize the scrollbar _VScrollBar.Location = new Point(Bounds.Right + 1, Bounds.Y); _VScrollBar.Height = _PanelHeight; _VScrollBar.SmallChange = _PanelHeight / 2; _VScrollBar.LargeChange = _WeekDayView.AppointmentHeight * 2; _VScrollBar.Maximum = _MaximumPanelHeight - _VScrollBar.Height + _VScrollBar.LargeChange; if (_VScrollBar.Visible == false) { _VScrollPos = 0; _VScrollBar.Value = 0; _VScrollBar.Show(); _VScrollBar.BringToFront(); } else { if (_VScrollBar.Value > _VScrollBar.Maximum - _VScrollBar.LargeChange) _VScrollBar.Value = _VScrollBar.Maximum - _VScrollBar.LargeChange; } _VScrollBar.Refresh(); } else if (_VScrollBar != null) { _VScrollPos = 0; _VScrollBar.ValueChanged -= _VExtScrollBar_ValueChanged; _VScrollBar.Dispose(); _VScrollBar = null; } } #endregion #region _VExtScrollBar_ValueChanged /// /// Processes Extended appointments scrollBar changes /// /// object /// EventArgs void _VExtScrollBar_ValueChanged(object sender, EventArgs e) { int vdelta = -_VScrollBar.Value - _VScrollPos; if (vdelta != 0) { _VScrollPos = -_VScrollBar.Value; // Now that we have calculated the items height and // width, invoke a Recalc on the item for (int i = 0; i < _CalendarItems.Count; i++) { CalendarItem item = _CalendarItems[i]; Rectangle r = item.Bounds; r.Y += vdelta; item.Bounds = r; } Refresh(); } } #endregion #endregion #region Reset / update view /// /// Resets the AllDayPanel view /// public void ResetView() { _VScrollPos = 0; if (_VScrollBar != null) { _VScrollBar.ValueChanged -= _VExtScrollBar_ValueChanged; _VScrollBar.Dispose(); _VScrollBar = null; } } /// /// Updates the AllDayPanel view /// public void UpdateView() { if (_WeekDayView.IsViewSelected == true) { if (_VScrollBar != null) _VScrollBar.Show(); } else { if (_VScrollBar != null) _VScrollBar.Hide(); } } #endregion #region Paint processing /// /// Draws extended appointments /// /// ItemPaintArgs public override void Paint(ItemPaintArgs e) { Graphics g = e.Graphics; if (e.ClipRectangle.IntersectsWith(Bounds)) { Region regSave = g.Clip; g.SetClip(Bounds, CombineMode.Intersect); using (Brush br = _WeekDayView.WeekDayColor.BrushPart( (int) eCalendarWeekDayPart.DayAllDayEventBackground, Bounds)) { g.FillRectangle(br, Bounds); } using (Pen pen = new Pen( _WeekDayView.WeekDayColor.GetColor((int) eCalendarWeekDayPart.DayViewBorder))) { g.DrawLine(pen, Bounds.X, Bounds.Y, Bounds.X, Bounds.Bottom); g.DrawLine(pen, Bounds.Right - 1, Bounds.Y, Bounds.Right - 1, Bounds.Bottom); } // Loop through each day in each week, displaying // the associated day content int selItem = -1; for (int i = 0; i < _CalendarItems.Count; i++) { // Initiate the paint if (_CalendarItems[i].Displayed == true) { if (_CalendarItems[i].IsSelected == true) selItem = i; else _CalendarItems[i].Paint(e); } } if (selItem >= 0) _CalendarItems[selItem].Paint(e); // Restore the original clip region g.Clip = regSave; } } #endregion #region Copy implementation /// /// Returns copy of the item. /// public override BaseItem Copy() { AllDayPanel objCopy = new AllDayPanel(WeekDayView); CopyToItem(objCopy); return (objCopy); } /// /// Copies the AllDayPanel specific properties to new instance of the item. /// /// New AllDayPanel instance protected override void CopyToItem(BaseItem copy) { AllDayPanel objCopy = copy as AllDayPanel; base.CopyToItem(objCopy); } #endregion } } #endif