//----------------------------------------------------------------------------- // // 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; } }