int TimelineLayoutHelper::layout_headers_recursive (TrackTree::iterator_base parent_iterator ,const int branch_offset ,const int header_width ,const int indent_width ,const int depth ,const bool parent_expanded) { REQUIRE(depth >= 0); const bool dragging = is_dragging_track(); int child_offset = 0; TrackTree::sibling_iterator iterator; for (iterator = layoutTree.begin(parent_iterator); iterator != layoutTree.end(parent_iterator); iterator++) { Gdk::Rectangle rect; int track_height = 0; const shared_ptr<model::Track> &modelTrack = *iterator; REQUIRE(modelTrack); shared_ptr<timeline::Track> timeline_track = lookup_timeline_track(modelTrack); // Is this the root track of a dragging branch? bool being_dragged = false; if (dragging) being_dragged = (modelTrack == *draggingTrackIter); // Is the track going to be shown? if (parent_expanded) { // Calculate and store the box of the header track_height = timeline_track->get_height() + TimelineWidget::TrackPadding; const int indent = depth * indent_width; rect = Gdk::Rectangle(indent // x ,branch_offset + child_offset // y ,max( header_width - indent, 0 ) // width ,track_height); // height // Offset for the next header child_offset += track_height; // Is this header being dragged? if (being_dragged) rect.set_y(dragPoint.get_y() - dragStartOffset.get_y()); headerBoxes[timeline_track] = rect; } // Is the track animating? const bool is_track_animating = timeline_track->is_expand_animating(); animating |= is_track_animating; // Recurse to children? const bool expand_child = (animating || timeline_track->get_expanded()) && parent_expanded; int child_branch_height = layout_headers_recursive (iterator ,rect.get_y() + track_height ,header_width ,indent_width ,depth + 1 ,expand_child); // Do collapse animation as necessary if (is_track_animating) { // Calculate the height of the area which will be // shown as expanded const float a = timeline_track->get_expand_animation_state(); child_branch_height *= a * a; const int y_limit = branch_offset + child_offset + child_branch_height; // Obscureed tracks according to the animation state TrackTree::pre_order_iterator descendant_iterator(iterator); descendant_iterator++; TrackTree::sibling_iterator end(iterator); end++; for (descendant_iterator = layoutTree.begin(parent_iterator); descendant_iterator != end; descendant_iterator++) { const weak_ptr<timeline::Track> track = lookup_timeline_track(*descendant_iterator); const Gdk::Rectangle &rect = headerBoxes[track]; if (rect.get_y() + rect.get_height() > y_limit) headerBoxes.erase(track); } // Tick the track expand animation timeline_track->tick_expand_animation(); } child_offset += child_branch_height; } return child_offset; }