//-----------------------------------------------------------------------------
//
// Copyright (c) 2009 Nesterovsky Bros. All rights reserved.
//
//
// Sample scheduler.
//
//-----------------------------------------------------------------------------
namespace NesterovskyBros.Collections
{
using System;
///
/// A schedule bookmark.
///
public class ScheduleBookmark: ScheduleNode
{
///
/// Creates a container bookmark.
///
public ScheduleBookmark():
base(DateTime.MinValue, null)
{
}
///
/// Creates a schedule bookmark.
///
/// A bookmark date.
/// A bookmark description.
public ScheduleBookmark(DateTime date, string description):
base(date, description)
{
}
}
///
/// A schedule node.
///
public class ScheduleNode: IndexedNode
where Node: ScheduleNode
{
///
/// Creates a schedule node.
///
/// A node date.
/// A node description.
public ScheduleNode(DateTime date, string description)
{
this.offset = date - DateTime.MinValue;
this.description = description;
}
///
/// A bookmark date.
///
public DateTime Date
{
get
{
TimeSpan result = TimeSpan.Zero;
ScheduleNode bookmark = this;
do
{
result += bookmark.offset;
bookmark = bookmark.Parent;
}
while(bookmark != null);
return DateTime.MinValue + result;
}
}
///
/// Text row.
///
public string Description
{
get { return description; }
}
///
/// Inserts a schedule node into a tree.
///
/// a reference node.
/// a node to insert.
public static void Insert(Node reference, Node value)
{
DateTime date = value.Date;
DateTime otherDate;
Node other = Find(reference, date, out otherDate);
if (otherDate > date)
{
InsertBefore(other, value);
}
else
{
InsertAfter(other, value);
}
}
///
/// Finds node near or coinciding with a date.
///
/// a reference node.
/// a date to look for.
/// a date of found node.
/// a node near or coinciding with a date.
public static Node Find(
Node reference,
DateTime date,
out DateTime nodeDate)
{
nodeDate = reference.Date;
Node node = reference;
while(true)
{
Node parent = node;
if (date > nodeDate)
{
node = node.Right;
}
else if (date < nodeDate)
{
node = node.Left;
}
else
{
return node;
}
if (node == null)
{
return parent;
}
nodeDate += node.offset;
}
}
///
/// Adjusts schedule upon indreasing or decreasing interval
/// before or after this node.
///
/// a reference node.
/// change offset.
///
/// true when interval increased or decreased before this node, and
/// false when after it.
///
public static void OnScheduleChanged(
Node reference,
TimeSpan offset,
bool before)
{
Node node = reference;
bool left;
if (before)
{
left = node.Left == null;
if (!left)
{
node = Predecessor(node);
}
}
else
{
left = node.Right != null;
if (left)
{
node = Successor(node);
}
}
while(!node.IsContainer)
{
Node parent = node.Parent;
bool leftNode = parent.Right != node;
if (left != leftNode)
{
if (leftNode)
{
node.offset -= offset;
}
else
{
node.offset += offset;
}
}
node = parent;
left = leftNode;
}
}
///
/// Informational string representation of the schedule node.
///
/// string value.
public override string ToString()
{
return "Index: " + Index +
", Date: " + Date +
", description: " + Description;
}
///
/// Rebinds node's parent.
/// RebindParent is called before parent is changed.
///
/// parent a new parent node.
protected override void RebindParent(Node parent)
{
base.RebindParent(parent);
if (parent != null)
{
offset = Date - parent.Date;
}
else
{
offset = Date - DateTime.MinValue;
}
}
///
/// Bookmark offset.
///
private TimeSpan offset;
///
/// Node description.
///
private string description;
}
}