614 lines
16 KiB
C#
614 lines
16 KiB
C#
#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<CalendarItem> // CalendarItems list
|
|
_CalendarItems = new List<CalendarItem>();
|
|
|
|
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
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="weekDayView">WeekDayView</param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Gets and sets the panel bounding rectangle
|
|
/// </summary>
|
|
public override Rectangle Bounds
|
|
{
|
|
get { return (base.Bounds); }
|
|
|
|
set
|
|
{
|
|
base.Bounds = value;
|
|
|
|
UpdateVScrollBar();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the DayPanel Height
|
|
/// </summary>
|
|
public int PanelHeight
|
|
{
|
|
get { return (_PanelHeight); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the panel's CalendarItem list
|
|
/// </summary>
|
|
public List<CalendarItem> CalendarItems
|
|
{
|
|
get { return (_CalendarItems); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets WeekDayView
|
|
/// </summary>
|
|
public WeekDayView WeekDayView
|
|
{
|
|
get { return (_WeekDayView); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private properties
|
|
|
|
/// <summary>
|
|
/// gets the Fixed AllDayPanel height
|
|
/// </summary>
|
|
private int FixedAllDayPanelHeight
|
|
{
|
|
get { return (_WeekDayView.CalendarView.FixedAllDayPanelHeight); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// gets the Maximum AllDayPanel height
|
|
/// </summary>
|
|
private int MaximumAllDayPanelHeight
|
|
{
|
|
get { return (_WeekDayView.CalendarView.MaximumAllDayPanelHeight); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Appointment height
|
|
/// </summary>
|
|
private int AppointmentPadding
|
|
{
|
|
get { return (6); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the width of a vertical scrollbar
|
|
/// </summary>
|
|
private int VsWidth
|
|
{
|
|
get { return (SystemInformation.VerticalScrollBarWidth); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RecalcSize
|
|
|
|
/// <summary>
|
|
/// Performs panel recalc support
|
|
/// </summary>
|
|
public override void RecalcSize()
|
|
{
|
|
// Reset our panel heights
|
|
|
|
_PanelHeight = 0;
|
|
_MaximumPanelHeight = 0;
|
|
|
|
if (_CalendarItems.Count > 0)
|
|
{
|
|
// Sort the items
|
|
|
|
List<CalendarItem> 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
|
|
|
|
/// <summary>
|
|
/// Sorts the CalendarItems
|
|
/// </summary>
|
|
private List<CalendarItem> SortCalendarItems()
|
|
{
|
|
List<CalendarItem> items =
|
|
new List<CalendarItem>(_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;
|
|
|
|
/// <summary>
|
|
/// Calculates the display bounds for the AppointmentView
|
|
/// </summary>
|
|
/// <param name="item">CalendarItem</param>
|
|
/// <param name="acc">Row accumulator</param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Gets the starting day index for the given appointment
|
|
/// </summary>
|
|
/// <returns>Day of week index (0-6)</returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Updates our vertical scrollbar
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Processes Extended appointments scrollBar changes
|
|
/// </summary>
|
|
/// <param name="sender">object</param>
|
|
/// <param name="e">EventArgs</param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Resets the AllDayPanel view
|
|
/// </summary>
|
|
public void ResetView()
|
|
{
|
|
_VScrollPos = 0;
|
|
|
|
if (_VScrollBar != null)
|
|
{
|
|
_VScrollBar.ValueChanged -= _VExtScrollBar_ValueChanged;
|
|
_VScrollBar.Dispose();
|
|
_VScrollBar = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the AllDayPanel view
|
|
/// </summary>
|
|
public void UpdateView()
|
|
{
|
|
if (_WeekDayView.IsViewSelected == true)
|
|
{
|
|
if (_VScrollBar != null)
|
|
_VScrollBar.Show();
|
|
}
|
|
else
|
|
{
|
|
if (_VScrollBar != null)
|
|
_VScrollBar.Hide();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Paint processing
|
|
|
|
/// <summary>
|
|
/// Draws extended appointments
|
|
/// </summary>
|
|
/// <param name="e">ItemPaintArgs</param>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Returns copy of the item.
|
|
/// </summary>
|
|
public override BaseItem Copy()
|
|
{
|
|
AllDayPanel objCopy = new AllDayPanel(WeekDayView);
|
|
CopyToItem(objCopy);
|
|
|
|
return (objCopy);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies the AllDayPanel specific properties to new instance of the item.
|
|
/// </summary>
|
|
/// <param name="copy">New AllDayPanel instance</param>
|
|
protected override void CopyToItem(BaseItem copy)
|
|
{
|
|
AllDayPanel objCopy = copy as AllDayPanel;
|
|
base.CopyToItem(objCopy);
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|