// documentTop is in timeline coordinates private void LayoutSubTimeline( TimelinePath path, ITimeline timeline, ref float documentTop, bool expandedTimeline, Context c, TimelineLayout result) { //if (c.TestRecursion(timeline)) // return; RectangleF bounds; SizeF pixelSize = c.PixelSize; float margin = pixelSize.Height * m_margin; float groupTop = documentTop; float documentBottom = groupTop; foreach (IGroup group in timeline.Groups) { bool expanded = expandedTimeline && group.Expanded; float groupBottom = groupTop; float trackTop = groupTop; foreach (ITrack track in group.Tracks) { float eventTop = trackTop + margin; float trackBottom = eventTop; foreach (IInterval interval in track.Intervals) { bounds = GetBounds(interval, eventTop, c); trackBottom = Math.Max(trackBottom, bounds.Bottom); bounds = GdiUtil.Transform(c.Transform, bounds); // add it, even if 'expandedTimeline' is false, to get the shadow effect result.Add(path + interval, bounds); } foreach (IKey key in track.Keys) { bounds = GetBounds(key, eventTop, c); trackBottom = Math.Max(trackBottom, bounds.Bottom); bounds = GdiUtil.Transform(c.Transform, bounds); // add it, even if 'expandedTimeline' is false, to get the shadow effect result.Add(path + key, bounds); } trackBottom += margin; trackBottom = Math.Max(trackBottom, trackTop + MinimumTrackSize); // need height for track, even if it's empty bounds = new RectangleF(c.Bounds.X, trackTop, c.Bounds.Width, trackBottom - trackTop); bounds = GdiUtil.Transform(c.Transform, bounds); bounds.X = c.ClientRectangle.X; // add it, even if 'expandedTimeline' is false, to get the shadow effect result.Add(path + track, bounds); if (expanded) trackTop = trackBottom; groupBottom = Math.Max(groupBottom, trackBottom); } // need height for group, even if it's empty groupBottom = Math.Max(groupBottom, groupTop + Math.Max(margin*2, MinimumTrackSize)); float groupHeight = groupBottom - groupTop; bounds = new RectangleF(0, groupTop, c.Bounds.Width, groupHeight); bounds = GdiUtil.Transform(c.Transform, bounds); bounds.X = c.ClientRectangle.X; // add it, even if 'expandedTimeline' is false, to get the shadow effect result.Add(path + group, bounds); if (expandedTimeline) groupTop = groupBottom; documentBottom = Math.Max(documentBottom, groupBottom); } if (expandedTimeline) { // Draw Markers, but limit them to be within the owning timeline. RectangleF originalBounds = c.Bounds; c.Bounds.Height = documentBottom - c.Bounds.Y; foreach (IMarker marker in timeline.Markers) { bounds = GetBounds(marker, c); bounds = GdiUtil.Transform(c.Transform, bounds); result.Add(path + marker, bounds); } c.Bounds = originalBounds; } documentTop = documentBottom; }
// documentTop is in timeline coordinates private void LayoutSubTimeline( TimelinePath path, ref float documentTop, Context c, TimelineLayout result) { SizeF pixelSize = c.PixelSize; float margin = pixelSize.Height * m_margin; // Limit Markers, etc., to being drawn within the owning timeline. RectangleF originalBounds = c.Bounds; c.Bounds.Y = documentTop; // Add a large bounding box for the whole TimelineReference row. float docRowHeight = Math.Max(margin * 2, MinimumTrackSize); RectangleF refBounds = new RectangleF(c.Bounds.X, documentTop, c.Bounds.Width, docRowHeight); documentTop += docRowHeight; // The whole timeline, with all groups and tracks laid out, and offset by the reference.Start. ITimelineReference reference = (ITimelineReference)path.Last; TimelineReferenceOptions options = reference.Options; IHierarchicalTimeline resolved = reference.Target; if (resolved != null) { Matrix localToWorld = D2dTimelineControl.CalculateLocalToWorld(path); c.PushTransform(localToWorld, MatrixOrder.Prepend); LayoutSubTimeline(path, resolved, ref documentTop, options.Expanded, c, result); c.PopTransform(); } // Now that we know the height of the tallest group, we can update the collapsed rectangle. if (!options.Expanded) { docRowHeight = Math.Max(docRowHeight, documentTop - refBounds.Y); refBounds.Height = docRowHeight; } refBounds = GdiUtil.Transform(c.Transform, refBounds); result.Add(path, refBounds); // Restore the bounds so that the horizontal scale (tick marks & numbers) is correct. c.Bounds = originalBounds; }