Merge branch 'newlayout' into gui
This commit is contained in:
commit
eb6f364084
14 changed files with 3326 additions and 311 deletions
|
|
@ -144,6 +144,8 @@ libgui_la_SOURCES = \
|
|||
$(lumigui_srcdir)/widgets/timeline/timeline-group-track.hpp \
|
||||
$(lumigui_srcdir)/widgets/timeline/timeline-clip.cpp \
|
||||
$(lumigui_srcdir)/widgets/timeline/timeline-clip.hpp \
|
||||
$(lumigui_srcdir)/widgets/timeline/timeline-layout-helper.cpp \
|
||||
$(lumigui_srcdir)/widgets/timeline/timeline-layout-helper.hpp \
|
||||
$(lumigui_srcdir)/model/project.cpp \
|
||||
$(lumigui_srcdir)/model/project.hpp \
|
||||
$(lumigui_srcdir)/model/track.cpp \
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <nobug.h>
|
||||
#include <vector>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include "lib/util.hpp"
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace widgets {
|
|||
|
||||
const int TimelineWidget::TrackPadding = 1;
|
||||
const int TimelineWidget::HeaderWidth = 150;
|
||||
const int TimelineWidget::HeaderIndentWidth = 10;
|
||||
const double TimelineWidget::ZoomIncrement = 1.25;
|
||||
const int64_t TimelineWidget::MaxScale = 30000000;
|
||||
|
||||
|
|
@ -43,13 +44,13 @@ TimelineWidget::TimelineWidget(
|
|||
shared_ptr<model::Sequence> source_sequence) :
|
||||
Table(2, 2),
|
||||
sequence(source_sequence),
|
||||
layoutHelper(*this),
|
||||
viewWindow(this, 0, 1),
|
||||
selectionStart(0),
|
||||
selectionEnd(0),
|
||||
playbackPeriodStart(0),
|
||||
playbackPeriodEnd(0),
|
||||
playbackPoint(GAVL_TIME_UNDEFINED),
|
||||
totalHeight(0),
|
||||
horizontalAdjustment(0, 0, 0),
|
||||
verticalAdjustment(0, 0, 0),
|
||||
horizontalScroll(horizontalAdjustment),
|
||||
|
|
@ -300,17 +301,9 @@ TimelineWidget::update_tracks()
|
|||
headerContainer->show_all_children();
|
||||
headerContainer->update_headers();
|
||||
|
||||
// Update the body
|
||||
body->queue_draw();
|
||||
|
||||
// Recalculate the total height of the timeline scrolled area
|
||||
totalHeight = 0;
|
||||
BOOST_FOREACH(shared_ptr<model::Track> track,
|
||||
sequence->get_child_tracks())
|
||||
{
|
||||
REQUIRE(track);
|
||||
totalHeight += measure_branch_height(track);
|
||||
}
|
||||
// Update the layout helper
|
||||
layoutHelper.clone_tree_from_sequence();
|
||||
layoutHelper.update_layout();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -338,9 +331,6 @@ TimelineWidget::create_timeline_tracks_from_branch(
|
|||
// We will need to create one
|
||||
trackMap[model_track] =
|
||||
create_timeline_track_from_model_track(model_track);
|
||||
|
||||
// Hook up
|
||||
|
||||
}
|
||||
|
||||
// Recurse to child tracks
|
||||
|
|
@ -418,6 +408,9 @@ TimelineWidget::lookup_timeline_track(
|
|||
shared_ptr<model::Track> model_track) const
|
||||
{
|
||||
REQUIRE(sequence);
|
||||
REQUIRE(model_track);
|
||||
REQUIRE(model_track != sequence); // The sequence isn't really a track
|
||||
|
||||
std::map<shared_ptr<model::Track>, shared_ptr<timeline::Track> >::
|
||||
const_iterator iterator = trackMap.find(model_track);
|
||||
if(iterator == trackMap.end())
|
||||
|
|
@ -433,30 +426,15 @@ TimelineWidget::lookup_timeline_track(
|
|||
return iterator->second;
|
||||
}
|
||||
|
||||
boost::shared_ptr<model::Track>
|
||||
TimelineWidget::lookup_model_track(
|
||||
const timeline::Track *timeline_track) const
|
||||
void
|
||||
TimelineWidget::on_layout_changed()
|
||||
{
|
||||
REQUIRE(sequence);
|
||||
REQUIRE(headerContainer != NULL);
|
||||
REQUIRE(body != NULL);
|
||||
|
||||
std::pair<shared_ptr<model::Track>, shared_ptr<timeline::Track> >
|
||||
pair;
|
||||
BOOST_FOREACH( pair, trackMap )
|
||||
{
|
||||
if(pair.second.get() == timeline_track)
|
||||
{
|
||||
ENSURE(pair.first);
|
||||
return pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
// The track is not present in the map
|
||||
// We are in an error condition if the timeline track is not found
|
||||
// - the timeline tracks must always be synchronous with the model
|
||||
// tracks.
|
||||
ENSURE(0);
|
||||
return shared_ptr<model::Track>();
|
||||
}
|
||||
headerContainer->layout_headers();
|
||||
body->queue_draw();
|
||||
}
|
||||
|
||||
void
|
||||
TimelineWidget::update_scroll()
|
||||
|
|
@ -478,7 +456,8 @@ TimelineWidget::update_scroll()
|
|||
|
||||
// Calculate the vertical length that can be scrolled:
|
||||
// the total height of all the tracks minus one screenful
|
||||
int y_scroll_length = totalHeight - body_allocation.get_height();
|
||||
int y_scroll_length = layoutHelper.get_total_height() -
|
||||
body_allocation.get_height();
|
||||
if(y_scroll_length < 0) y_scroll_length = 0;
|
||||
|
||||
// If by resizing we're now over-scrolled, scroll back to
|
||||
|
|
@ -500,29 +479,6 @@ TimelineWidget::update_scroll()
|
|||
|
||||
}
|
||||
|
||||
int
|
||||
TimelineWidget::measure_branch_height(
|
||||
shared_ptr<model::Track> model_track)
|
||||
{
|
||||
REQUIRE(model_track);
|
||||
|
||||
const shared_ptr<timeline::Track> timeline_track =
|
||||
lookup_timeline_track(model_track);
|
||||
ENSURE(timeline_track);
|
||||
|
||||
int height = timeline_track->get_height() + TrackPadding;
|
||||
|
||||
// Recurse through all the children
|
||||
BOOST_FOREACH( shared_ptr<model::Track> child,
|
||||
model_track->get_child_tracks() )
|
||||
{
|
||||
REQUIRE(child);
|
||||
height += measure_branch_height(child);
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
int
|
||||
TimelineWidget::get_y_scroll_offset() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "timeline/timeline-ibeam-tool.hpp"
|
||||
#include "timeline/timeline-group-track.hpp"
|
||||
#include "timeline/timeline-clip-track.hpp"
|
||||
#include "timeline/timeline-layout-helper.hpp"
|
||||
|
||||
#include "../model/sequence.hpp"
|
||||
|
||||
|
|
@ -216,24 +217,12 @@ private:
|
|||
**/
|
||||
boost::shared_ptr<timeline::Track> lookup_timeline_track(
|
||||
boost::shared_ptr<model::Track> model_track) const;
|
||||
|
||||
/**
|
||||
* Looks up a model track in trackMap that corresponds to a
|
||||
* given timeline track.
|
||||
* @param timeline_track The timeline UI track to look up.
|
||||
* @returns The model track found, or an empty shared_ptr if
|
||||
* timeline_track has no corresponding timeline UI track (this is an
|
||||
* error condition).
|
||||
**/
|
||||
boost::shared_ptr<model::Track> lookup_model_track(
|
||||
const timeline::Track *timeline_track) const;
|
||||
|
||||
// ----- Layout Functions ----- //
|
||||
|
||||
void update_scroll();
|
||||
void on_layout_changed();
|
||||
|
||||
int measure_branch_height(
|
||||
boost::shared_ptr<model::Track> model_track);
|
||||
void update_scroll();
|
||||
|
||||
int get_y_scroll_offset() const;
|
||||
|
||||
|
|
@ -276,6 +265,9 @@ protected:
|
|||
std::map<boost::shared_ptr<model::Track>,
|
||||
boost::shared_ptr<timeline::Track> >
|
||||
trackMap;
|
||||
|
||||
// Helper Classes
|
||||
timeline::TimelineLayoutHelper layoutHelper;
|
||||
|
||||
// View State
|
||||
timeline::TimelineViewWindow viewWindow;
|
||||
|
|
@ -289,8 +281,6 @@ protected:
|
|||
|
||||
boost::shared_ptr<timeline::Track> hoveringTrack;
|
||||
|
||||
int totalHeight;
|
||||
|
||||
// Child Widgets
|
||||
timeline::TimelineHeaderContainer *headerContainer;
|
||||
timeline::TimelineBody *body;
|
||||
|
|
@ -318,11 +308,13 @@ public:
|
|||
protected:
|
||||
static const int TrackPadding;
|
||||
static const int HeaderWidth;
|
||||
static const int HeaderIndentWidth;
|
||||
static const double ZoomIncrement;
|
||||
|
||||
friend class timeline::TimelineViewWindow;
|
||||
friend class timeline::TimelineBody;
|
||||
friend class timeline::TimelineHeaderContainer;
|
||||
friend class timeline::TimelineLayoutHelper;
|
||||
friend class timeline::TimelineRuler;
|
||||
friend class timeline::Tool;
|
||||
friend class timeline::ArrowTool;
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ bool
|
|||
TimelineBody::on_motion_notify_event(GdkEventMotion *event)
|
||||
{
|
||||
REQUIRE(event != NULL);
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
// Handle a middle-mouse drag if one is occuring
|
||||
switch(dragType)
|
||||
|
|
@ -270,8 +271,8 @@ TimelineBody::on_motion_notify_event(GdkEventMotion *event)
|
|||
tool->on_motion_notify_event(event);
|
||||
|
||||
// See if the track that we're hovering over has changed
|
||||
shared_ptr<timeline::Track> new_hovering_track =
|
||||
track_from_point(event->y);
|
||||
shared_ptr<timeline::Track> new_hovering_track(
|
||||
timelineWidget->layoutHelper.track_from_y(event->y));
|
||||
if(timelineWidget->get_hovering_track() != new_hovering_track)
|
||||
timelineWidget->set_hovering_track(new_hovering_track);
|
||||
|
||||
|
|
@ -287,35 +288,53 @@ TimelineBody::draw_tracks(Cairo::RefPtr<Cairo::Context> cr)
|
|||
REQUIRE(timelineWidget->sequence);
|
||||
|
||||
// Prepare
|
||||
TimelineLayoutHelper &layout_helper = timelineWidget->layoutHelper;
|
||||
const TimelineLayoutHelper::TrackTree &layout_tree =
|
||||
layout_helper.get_layout_tree();
|
||||
const Allocation allocation = get_allocation();
|
||||
|
||||
// Save the view matrix
|
||||
Cairo::Matrix view_matrix;
|
||||
cr->get_matrix(view_matrix);
|
||||
|
||||
// Translate the view by the scroll distance
|
||||
cr->translate(0, -get_vertical_offset());
|
||||
|
||||
// Interate drawing each track
|
||||
BOOST_FOREACH( shared_ptr<model::Track> model_track,
|
||||
timelineWidget->sequence->get_child_tracks() )
|
||||
draw_track_recursive(cr, model_track, allocation.get_width());
|
||||
// Iterate drawing each track
|
||||
TimelineLayoutHelper::TrackTree::pre_order_iterator iterator;
|
||||
for(iterator = ++layout_tree.begin(); // ++ so we skip the sequence root
|
||||
iterator != layout_tree.end();
|
||||
iterator++)
|
||||
{
|
||||
const shared_ptr<model::Track> model_track(*iterator);
|
||||
const shared_ptr<timeline::Track> timeline_track =
|
||||
timelineWidget->lookup_timeline_track(*iterator);
|
||||
|
||||
optional<Gdk::Rectangle> rect =
|
||||
layout_helper.get_track_header_rect(timeline_track);
|
||||
|
||||
// Is this track visible?
|
||||
if(rect)
|
||||
{
|
||||
// Translate to the top of the track
|
||||
cr->set_matrix(view_matrix);
|
||||
cr->translate(0, rect->get_y());
|
||||
|
||||
// Draw the track
|
||||
draw_track(cr, timeline_track, allocation.get_width());
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the view matrix
|
||||
cr->set_matrix(view_matrix);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineBody::draw_track_recursive(Cairo::RefPtr<Cairo::Context> cr,
|
||||
shared_ptr<model::Track> model_track, const int view_width) const
|
||||
TimelineBody::draw_track(Cairo::RefPtr<Cairo::Context> cr,
|
||||
shared_ptr<timeline::Track> timeline_track,
|
||||
const int view_width) const
|
||||
{
|
||||
REQUIRE(cr);
|
||||
REQUIRE(model_track != NULL);
|
||||
REQUIRE(timeline_track != NULL);
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
shared_ptr<timeline::Track> timeline_track = timelineWidget->
|
||||
lookup_timeline_track(model_track);
|
||||
|
||||
|
||||
const int height = timeline_track->get_height();
|
||||
REQUIRE(height >= 0);
|
||||
|
||||
|
|
@ -329,14 +348,6 @@ TimelineBody::draw_track_recursive(Cairo::RefPtr<Cairo::Context> cr,
|
|||
cr->save();
|
||||
timeline_track->draw_track(cr, &timelineWidget->get_view_window());
|
||||
cr->restore();
|
||||
|
||||
// Shift for the next track
|
||||
cr->translate(0, height + TimelineWidget::TrackPadding);
|
||||
|
||||
// Recurse drawing into children
|
||||
BOOST_FOREACH( shared_ptr<model::Track> child,
|
||||
model_track->get_child_tracks() )
|
||||
draw_track_recursive(cr, child, view_width);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -436,60 +447,6 @@ TimelineBody::set_vertical_offset(int offset)
|
|||
timelineWidget->verticalAdjustment.set_value(offset);
|
||||
}
|
||||
|
||||
shared_ptr<timeline::Track>
|
||||
TimelineBody::track_from_point(const int y) const
|
||||
{
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
REQUIRE(timelineWidget->sequence);
|
||||
|
||||
int offset = -get_vertical_offset();
|
||||
|
||||
BOOST_FOREACH( shared_ptr<model::Track> model_track,
|
||||
timelineWidget->sequence->get_child_tracks() )
|
||||
{
|
||||
shared_ptr<timeline::Track> result = track_from_branch(
|
||||
model_track, y, offset);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
// No track has been found with this point in it
|
||||
return boost::shared_ptr<timeline::Track>();
|
||||
}
|
||||
|
||||
shared_ptr<timeline::Track> TimelineBody::track_from_branch(
|
||||
shared_ptr<model::Track> model_track,
|
||||
const int y, int &offset) const
|
||||
{
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
|
||||
shared_ptr<timeline::Track> timeline_track = timelineWidget->
|
||||
lookup_timeline_track(model_track);
|
||||
|
||||
const int height = timeline_track->get_height();
|
||||
REQUIRE(height >= 0);
|
||||
|
||||
// Does the point fall in this track?
|
||||
if(offset <= y && y < offset + height)
|
||||
return timeline_track;
|
||||
|
||||
// Add the height of this track to the accumulation
|
||||
offset += height;
|
||||
|
||||
// Recurse drawing into children
|
||||
BOOST_FOREACH( shared_ptr<model::Track> child,
|
||||
model_track->get_child_tracks() )
|
||||
{
|
||||
shared_ptr<timeline::Track> result =
|
||||
track_from_branch(child, y, offset);
|
||||
if(result != NULL)
|
||||
return result;
|
||||
}
|
||||
|
||||
// No track has been found in this branch
|
||||
return shared_ptr<timeline::Track>();
|
||||
}
|
||||
|
||||
void
|
||||
TimelineBody::register_styles() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -118,8 +118,9 @@ private:
|
|||
*/
|
||||
void draw_tracks(Cairo::RefPtr<Cairo::Context> cr);
|
||||
|
||||
void draw_track_recursive(Cairo::RefPtr<Cairo::Context> cr,
|
||||
boost::shared_ptr<model::Track> track, const int view_width) const;
|
||||
void draw_track(Cairo::RefPtr<Cairo::Context> cr,
|
||||
boost::shared_ptr<timeline::Track> timeline_track,
|
||||
const int view_width) const;
|
||||
|
||||
/**
|
||||
* Draws the selected timeline period.
|
||||
|
|
@ -138,14 +139,7 @@ private:
|
|||
int get_vertical_offset() const;
|
||||
|
||||
void set_vertical_offset(int offset);
|
||||
|
||||
boost::shared_ptr<timeline::Track> track_from_point(const int y)
|
||||
const;
|
||||
|
||||
boost::shared_ptr<timeline::Track> track_from_branch(
|
||||
boost::shared_ptr<model::Track> model_track,
|
||||
const int y, int &offset) const;
|
||||
|
||||
|
||||
/**
|
||||
* Registers all the styles that this class will respond to.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ TimelineHeaderContainer::TimelineHeaderContainer(
|
|||
|
||||
// Install style properties
|
||||
register_styles();
|
||||
|
||||
// Load the styles up
|
||||
read_styles();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -135,6 +138,7 @@ TimelineHeaderContainer::on_unrealize()
|
|||
bool TimelineHeaderContainer::on_button_press_event (
|
||||
GdkEventButton* event)
|
||||
{
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
switch(event->button)
|
||||
|
|
@ -152,8 +156,9 @@ bool TimelineHeaderContainer::on_button_press_event (
|
|||
case 3: // Right Click
|
||||
{
|
||||
// Popup the context menu
|
||||
shared_ptr<Track> header = header_from_point(
|
||||
Gdk::Point(event->x, event->y));
|
||||
shared_ptr<Track> header(
|
||||
timelineWidget->layoutHelper.header_from_point(
|
||||
Gdk::Point(event->x, event->y)));
|
||||
|
||||
// Are we hovering on a header?
|
||||
if(header)
|
||||
|
|
@ -183,7 +188,8 @@ bool TimelineHeaderContainer::on_button_release_event (
|
|||
// Yes? The toggle the expanding
|
||||
clickedExpander->set_expanded(!clickedExpander->get_expanded());
|
||||
clickedExpander.reset();
|
||||
layout_headers();
|
||||
|
||||
timelineWidget->layoutHelper.update_layout();
|
||||
}
|
||||
|
||||
return Container::on_button_release_event(event);
|
||||
|
|
@ -265,8 +271,6 @@ TimelineHeaderContainer::on_expose_event(GdkEventExpose *event)
|
|||
if(gdkWindow)
|
||||
{
|
||||
const Allocation container_allocation = get_allocation();
|
||||
|
||||
read_styles();
|
||||
|
||||
// Paint a border underneath all the root headers
|
||||
BOOST_FOREACH( shared_ptr<model::Track> model_track,
|
||||
|
|
@ -304,88 +308,59 @@ TimelineHeaderContainer::on_hovering_track_changed(
|
|||
|
||||
void
|
||||
TimelineHeaderContainer::layout_headers()
|
||||
{
|
||||
{
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
REQUIRE(margin >= 0); // read_styles must have been called before now
|
||||
|
||||
// We can't layout before the widget has been set up
|
||||
if(!gdkWindow)
|
||||
return;
|
||||
|
||||
// Make sure the style are loaded
|
||||
read_styles();
|
||||
|
||||
// Clear previously cached layout
|
||||
headerBoxes.clear();
|
||||
|
||||
// Start at minus-the-scroll offset
|
||||
int offset = -timelineWidget->get_y_scroll_offset();
|
||||
|
||||
const Allocation container_allocation = get_allocation();
|
||||
const int header_width = container_allocation.get_width();
|
||||
TimelineLayoutHelper &layout_helper =
|
||||
timelineWidget->layoutHelper;
|
||||
const TimelineLayoutHelper::TrackTree &layout_tree =
|
||||
layout_helper.get_layout_tree();
|
||||
|
||||
BOOST_FOREACH( shared_ptr<model::Track> model_track, get_tracks() )
|
||||
layout_headers_recursive(
|
||||
model_track, offset, header_width, 0, true);
|
||||
TimelineLayoutHelper::TrackTree::pre_order_iterator iterator;
|
||||
for(iterator = ++layout_tree.begin(); // ++ so that we skip the sequence root
|
||||
iterator != layout_tree.end();
|
||||
iterator++)
|
||||
{
|
||||
const shared_ptr<timeline::Track> timeline_track =
|
||||
lookup_timeline_track(*iterator);
|
||||
|
||||
Widget &widget = timeline_track->get_header_widget();
|
||||
|
||||
optional<Gdk::Rectangle> header_rect =
|
||||
layout_helper.get_track_header_rect(timeline_track);
|
||||
|
||||
if(header_rect)
|
||||
{
|
||||
REQUIRE(header_rect->get_width() >= 0);
|
||||
REQUIRE(header_rect->get_height() >= 0);
|
||||
|
||||
// Calculate the allocation of the header widget
|
||||
Allocation header_allocation(
|
||||
header_rect->get_x() + margin + expand_button_size, // x
|
||||
header_rect->get_y() + margin, // y
|
||||
max( header_rect->get_width() - expand_button_size -
|
||||
margin * 2, 0 ), // width
|
||||
header_rect->get_height() - margin * 2); // height
|
||||
|
||||
// Apply the allocation to the header
|
||||
widget.size_allocate (header_allocation);
|
||||
if(!widget.is_visible())
|
||||
widget.show();
|
||||
}
|
||||
else // No header rect, so the track must be hidden
|
||||
if(widget.is_visible())
|
||||
widget.hide();
|
||||
}
|
||||
|
||||
// Repaint the background of our parenting
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void
|
||||
TimelineHeaderContainer::layout_headers_recursive(
|
||||
shared_ptr<model::Track> model_track, int &offset,
|
||||
const int header_width, const int depth, bool parent_expanded)
|
||||
{
|
||||
REQUIRE(depth >= 0);
|
||||
REQUIRE(model_track != NULL);
|
||||
|
||||
shared_ptr<timeline::Track> timeline_track =
|
||||
lookup_timeline_track(model_track);
|
||||
|
||||
const int indent = depth * 10;
|
||||
Widget &widget = timeline_track->get_header_widget();
|
||||
|
||||
if(parent_expanded)
|
||||
{
|
||||
const int track_height = timeline_track->get_height();
|
||||
|
||||
// Calculate the box of the header
|
||||
Gdk::Rectangle header_box(
|
||||
indent, // x
|
||||
offset, // y
|
||||
max( header_width - indent, 0 ), // width
|
||||
track_height); // height
|
||||
REQUIRE(header_box.get_height() >= 0);
|
||||
|
||||
// Cache the bounding box
|
||||
headerBoxes[timeline_track] = header_box;
|
||||
|
||||
// Calculate the allocation of the header widget
|
||||
Allocation header_allocation(
|
||||
header_box.get_x() + margin + expand_button_size, // x
|
||||
header_box.get_y() + margin, // y
|
||||
max( header_box.get_width() - expand_button_size -
|
||||
margin * 2, 0 ), // width
|
||||
header_box.get_height() - margin * 2); // height
|
||||
|
||||
// Apply the allocation to the header
|
||||
widget.size_allocate (header_allocation);
|
||||
if(!widget.is_visible())
|
||||
widget.show();
|
||||
|
||||
// Offset for the next header
|
||||
offset += track_height + TimelineWidget::TrackPadding;
|
||||
}
|
||||
else
|
||||
if(widget.is_visible())
|
||||
widget.hide();
|
||||
|
||||
// Recurse through all the children
|
||||
BOOST_FOREACH( boost::shared_ptr<model::Track> child,
|
||||
model_track->get_child_tracks() )
|
||||
layout_headers_recursive(
|
||||
child, offset, header_width, depth + 1,
|
||||
timeline_track->get_expanded() && parent_expanded);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineHeaderContainer::set_parent_recursive(
|
||||
boost::shared_ptr<model::Track> model_track)
|
||||
|
|
@ -442,6 +417,7 @@ TimelineHeaderContainer::draw_header_decoration(
|
|||
shared_ptr<model::Track> model_track,
|
||||
const Gdk::Rectangle &clip_rect)
|
||||
{
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
REQUIRE(model_track != NULL);
|
||||
REQUIRE(clip_rect.get_width() > 0);
|
||||
REQUIRE(clip_rect.get_height() > 0);
|
||||
|
|
@ -452,10 +428,11 @@ TimelineHeaderContainer::draw_header_decoration(
|
|||
shared_ptr<timeline::Track> timeline_track =
|
||||
lookup_timeline_track(model_track);
|
||||
|
||||
// Get the cached header box
|
||||
weak_ptr<timeline::Track> ptr(timeline_track);
|
||||
REQUIRE(contains(headerBoxes, ptr));
|
||||
const Gdk::Rectangle &box = headerBoxes[timeline_track];
|
||||
// Get the header box
|
||||
const optional<Gdk::Rectangle> &optional_box =
|
||||
timelineWidget->layoutHelper.get_track_header_rect(timeline_track);
|
||||
REQUIRE(optional_box);
|
||||
const Gdk::Rectangle box = *optional_box;
|
||||
|
||||
// Paint the box, if it will be visible
|
||||
if(box.get_x() < clip_rect.get_width() &&
|
||||
|
|
@ -498,58 +475,55 @@ TimelineHeaderContainer::draw_header_decoration(
|
|||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<timeline::Track>
|
||||
TimelineHeaderContainer::header_from_point(const Gdk::Point &point)
|
||||
{
|
||||
std::pair<shared_ptr<timeline::Track>, Gdk::Rectangle> pair;
|
||||
BOOST_FOREACH( pair, headerBoxes )
|
||||
{
|
||||
// Hit test the rectangle
|
||||
const Gdk::Rectangle &rect = pair.second;
|
||||
|
||||
if(point.get_x() >= rect.get_x() &&
|
||||
point.get_x() < rect.get_x() + rect.get_width() &&
|
||||
point.get_y() >= rect.get_y() &&
|
||||
point.get_y() < rect.get_y() + rect.get_height())
|
||||
return pair.first;
|
||||
}
|
||||
|
||||
return shared_ptr<timeline::Track>();
|
||||
}
|
||||
|
||||
shared_ptr<timeline::Track>
|
||||
TimelineHeaderContainer::expander_button_from_point(
|
||||
const Gdk::Point &point)
|
||||
{
|
||||
std::pair<shared_ptr<timeline::Track>, Gdk::Rectangle> pair;
|
||||
BOOST_FOREACH( pair, headerBoxes )
|
||||
{
|
||||
const TimelineLayoutHelper::TrackTree &layout_tree =
|
||||
timelineWidget->layoutHelper.get_layout_tree();
|
||||
|
||||
TimelineLayoutHelper::TrackTree::pre_order_iterator iterator;
|
||||
for(iterator = ++layout_tree.begin(); // ++ so we skip the sequence root
|
||||
iterator != layout_tree.end();
|
||||
iterator++)
|
||||
{
|
||||
// Hit test the rectangle
|
||||
const Gdk::Rectangle rect =
|
||||
get_expander_button_rectangle(pair.first);
|
||||
const shared_ptr<timeline::Track> timeline_track =
|
||||
lookup_timeline_track(*iterator);
|
||||
|
||||
if(point.get_x() >= rect.get_x() &&
|
||||
point.get_x() < rect.get_x() + rect.get_width() &&
|
||||
point.get_y() >= rect.get_y() &&
|
||||
point.get_y() < rect.get_y() + rect.get_height())
|
||||
return pair.first;
|
||||
// Hit test the rectangle
|
||||
const optional<Gdk::Rectangle> rect =
|
||||
get_expander_button_rectangle(timeline_track);
|
||||
|
||||
if(rect)
|
||||
{
|
||||
if(point.get_x() >= rect->get_x() &&
|
||||
point.get_x() < rect->get_x() + rect->get_width() &&
|
||||
point.get_y() >= rect->get_y() &&
|
||||
point.get_y() < rect->get_y() + rect->get_height())
|
||||
return timeline_track;
|
||||
}
|
||||
}
|
||||
|
||||
return shared_ptr<timeline::Track>();
|
||||
}
|
||||
|
||||
const Gdk::Rectangle
|
||||
const optional<Gdk::Rectangle>
|
||||
TimelineHeaderContainer::get_expander_button_rectangle(
|
||||
shared_ptr<Track> track)
|
||||
{
|
||||
REQUIRE(timelineWidget != NULL);
|
||||
REQUIRE(track != NULL);
|
||||
weak_ptr<timeline::Track> ptr(track);
|
||||
REQUIRE(contains(headerBoxes, ptr));
|
||||
|
||||
const Gdk::Rectangle &box = headerBoxes[track];
|
||||
return Gdk::Rectangle(
|
||||
margin + box.get_x(), margin + box.get_y(),
|
||||
expand_button_size, box.get_height() - margin * 2);
|
||||
optional<Gdk::Rectangle> box =
|
||||
timelineWidget->layoutHelper.get_track_header_rect(track);
|
||||
if(box)
|
||||
{
|
||||
return optional<Gdk::Rectangle>(Gdk::Rectangle(
|
||||
margin + box->get_x(), margin + box->get_y(),
|
||||
expand_button_size, box->get_height() - margin * 2));
|
||||
}
|
||||
|
||||
return optional<Gdk::Rectangle>();
|
||||
}
|
||||
|
||||
shared_ptr<timeline::Track>
|
||||
|
|
@ -594,7 +568,13 @@ void
|
|||
TimelineHeaderContainer::read_styles()
|
||||
{
|
||||
if(margin <= 0)
|
||||
get_style_property("heading_margin", margin);
|
||||
{
|
||||
get_style_property("heading_margin", margin);
|
||||
margin = max(margin, 0);
|
||||
}
|
||||
else
|
||||
WARN(gui, "TimelineHeaderContainer::read_styles()"
|
||||
" should only be called once");
|
||||
}
|
||||
|
||||
} // namespace timeline
|
||||
|
|
|
|||
|
|
@ -149,19 +149,7 @@ private:
|
|||
* stacking etc.
|
||||
*/
|
||||
void layout_headers();
|
||||
|
||||
/**
|
||||
* Recursively lays out all the controls in the header widget.
|
||||
* @param track The parent track object which will be recursed into.
|
||||
* @param offset A shared value used to accumulate the y-offset of
|
||||
* header widgets.
|
||||
* @param header_width The width of this widget in pixels.
|
||||
* @param depth The depth within the tree of track.
|
||||
**/
|
||||
void layout_headers_recursive(boost::shared_ptr<model::Track> track,
|
||||
int &offset, const int header_width, const int depth,
|
||||
bool parent_expanded);
|
||||
|
||||
|
||||
/**
|
||||
* Recursively sets all the track header widgets to be child widgets
|
||||
* of this widget.
|
||||
|
|
@ -199,9 +187,6 @@ private:
|
|||
void draw_header_decoration(
|
||||
boost::shared_ptr<model::Track> model_track,
|
||||
const Gdk::Rectangle &clip_rect);
|
||||
|
||||
boost::shared_ptr<timeline::Track> header_from_point(
|
||||
const Gdk::Point &point);
|
||||
|
||||
/**
|
||||
* Given a point, expander_button_from_point finds the track of the
|
||||
|
|
@ -219,7 +204,7 @@ private:
|
|||
* @param track The track to get the expander button rectangle of.
|
||||
* @return Returns the rectangle of the expander button of track.
|
||||
**/
|
||||
const Gdk::Rectangle get_expander_button_rectangle(
|
||||
const boost::optional<Gdk::Rectangle> get_expander_button_rectangle(
|
||||
boost::shared_ptr<timeline::Track> track);
|
||||
|
||||
/**
|
||||
|
|
@ -278,16 +263,7 @@ private:
|
|||
* click is not processed by track headers.
|
||||
**/
|
||||
Gtk::Menu contextMenu;
|
||||
|
||||
/**
|
||||
* A map of tracks to the rectangles of their headers.
|
||||
* @remarks This map is used as a cache, so that the rectangles don't
|
||||
* need to be perpetually recalculated. This cache is regenerated by
|
||||
* the layout_headers method.
|
||||
**/
|
||||
std::map<boost::weak_ptr<timeline::Track>, Gdk::Rectangle>
|
||||
headerBoxes;
|
||||
|
||||
|
||||
//----- User Interaction State -----//
|
||||
boost::shared_ptr<timeline::Track> hoveringExpander;
|
||||
|
||||
|
|
@ -307,6 +283,7 @@ private:
|
|||
**/
|
||||
int expand_button_size;
|
||||
|
||||
friend class gui::widgets::TimelineWidget;
|
||||
friend class timeline::Track;
|
||||
};
|
||||
|
||||
|
|
|
|||
216
src/gui/widgets/timeline/timeline-layout-helper.cpp
Normal file
216
src/gui/widgets/timeline/timeline-layout-helper.cpp
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
timeline-layout-helper.cpp - Implementation of the timeline
|
||||
layout helper class
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "timeline-layout-helper.hpp"
|
||||
#include "../timeline-widget.hpp"
|
||||
#include "../../model/sequence.hpp"
|
||||
|
||||
using namespace Gtk;
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
using namespace lumiera;
|
||||
using namespace util;
|
||||
|
||||
namespace gui {
|
||||
namespace widgets {
|
||||
namespace timeline {
|
||||
|
||||
TimelineLayoutHelper::TimelineLayoutHelper(TimelineWidget &owner) :
|
||||
timelineWidget(owner),
|
||||
totalHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TimelineLayoutHelper::clone_tree_from_sequence()
|
||||
{
|
||||
const shared_ptr<model::Sequence> &sequence = timelineWidget.sequence;
|
||||
REQUIRE(sequence);
|
||||
|
||||
layoutTree.clear();
|
||||
TrackTree::iterator_base iterator = layoutTree.set_head(sequence);
|
||||
add_branch(iterator, sequence);
|
||||
}
|
||||
|
||||
TimelineLayoutHelper::TrackTree&
|
||||
TimelineLayoutHelper::get_layout_tree()
|
||||
{
|
||||
return layoutTree;
|
||||
}
|
||||
|
||||
void
|
||||
TimelineLayoutHelper::add_branch(
|
||||
TrackTree::iterator_base parent_iterator,
|
||||
shared_ptr<model::Track> parent)
|
||||
{
|
||||
BOOST_FOREACH(shared_ptr<model::Track> child,
|
||||
parent->get_child_tracks())
|
||||
{
|
||||
TrackTree::iterator_base child_iterator =
|
||||
layoutTree.append_child(parent_iterator, child);
|
||||
add_branch(child_iterator, child);
|
||||
}
|
||||
}
|
||||
|
||||
optional<Gdk::Rectangle>
|
||||
TimelineLayoutHelper::get_track_header_rect(
|
||||
boost::weak_ptr<timeline::Track> track)
|
||||
{
|
||||
if(contains(headerBoxes, track))
|
||||
{
|
||||
Gdk::Rectangle rect(headerBoxes[track]);
|
||||
rect.set_y(rect.get_y() - timelineWidget.get_y_scroll_offset());
|
||||
return optional<Gdk::Rectangle>(rect);
|
||||
}
|
||||
return optional<Gdk::Rectangle>();
|
||||
}
|
||||
|
||||
shared_ptr<timeline::Track>
|
||||
TimelineLayoutHelper::header_from_point(Gdk::Point point)
|
||||
{
|
||||
// Apply the scroll offset
|
||||
point.set_y(point.get_y() + timelineWidget.get_y_scroll_offset());
|
||||
|
||||
// Search the headers
|
||||
std::pair<weak_ptr<timeline::Track>, Gdk::Rectangle> pair;
|
||||
BOOST_FOREACH( pair, headerBoxes )
|
||||
{
|
||||
// Hit test the rectangle
|
||||
const Gdk::Rectangle &rect = pair.second;
|
||||
|
||||
if(point.get_x() >= rect.get_x() &&
|
||||
point.get_x() < rect.get_x() + rect.get_width() &&
|
||||
point.get_y() >= rect.get_y() &&
|
||||
point.get_y() < rect.get_y() + rect.get_height())
|
||||
return shared_ptr<timeline::Track>(pair.first);
|
||||
}
|
||||
|
||||
// No track was found - return an empty pointer
|
||||
return shared_ptr<timeline::Track>();
|
||||
}
|
||||
|
||||
boost::shared_ptr<timeline::Track>
|
||||
TimelineLayoutHelper::track_from_y(int y)
|
||||
{
|
||||
// Apply the scroll offset
|
||||
y += timelineWidget.get_y_scroll_offset();
|
||||
|
||||
// Search the tracks
|
||||
std::pair<weak_ptr<timeline::Track>, Gdk::Rectangle> pair;
|
||||
BOOST_FOREACH( pair, headerBoxes )
|
||||
{
|
||||
// Hit test the rectangle
|
||||
const Gdk::Rectangle &rect = pair.second;
|
||||
if(y >= rect.get_y() && y < rect.get_y() + rect.get_height())
|
||||
return shared_ptr<timeline::Track>(pair.first);
|
||||
}
|
||||
|
||||
// No track was found - return an empty pointer
|
||||
return shared_ptr<timeline::Track>();
|
||||
}
|
||||
|
||||
int
|
||||
TimelineLayoutHelper::get_total_height() const
|
||||
{
|
||||
ENSURE(totalHeight >= 0);
|
||||
return totalHeight;
|
||||
}
|
||||
|
||||
void
|
||||
TimelineLayoutHelper::update_layout()
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
// Clear previously cached layout
|
||||
headerBoxes.clear();
|
||||
|
||||
// Do the layout
|
||||
const int header_width = TimelineWidget::HeaderWidth;
|
||||
const int indent_width = TimelineWidget::HeaderIndentWidth;
|
||||
layout_headers_recursive(layoutTree.begin(),
|
||||
offset, header_width, indent_width, 0, true);
|
||||
|
||||
totalHeight = offset;
|
||||
|
||||
// Signal that the layout has changed
|
||||
timelineWidget.on_layout_changed();
|
||||
}
|
||||
|
||||
void
|
||||
TimelineLayoutHelper::layout_headers_recursive(
|
||||
TrackTree::iterator_base parent_iterator,
|
||||
int &offset, const int header_width, const int indent_width,
|
||||
const int depth, const bool parent_expanded)
|
||||
{
|
||||
REQUIRE(depth >= 0);
|
||||
|
||||
TrackTree::sibling_iterator iterator;
|
||||
for(iterator = layoutTree.begin(parent_iterator);
|
||||
iterator != layoutTree.end(parent_iterator);
|
||||
iterator++)
|
||||
{
|
||||
const shared_ptr<model::Track> &model_track = *iterator;
|
||||
REQUIRE(model_track);
|
||||
|
||||
shared_ptr<timeline::Track> timeline_track =
|
||||
lookup_timeline_track(model_track);
|
||||
|
||||
if(parent_expanded)
|
||||
{
|
||||
// Calculate and store the box of the header
|
||||
const int track_height = timeline_track->get_height();
|
||||
const int indent = depth * indent_width;
|
||||
|
||||
headerBoxes[timeline_track] = Gdk::Rectangle(
|
||||
indent, // x
|
||||
offset, // y
|
||||
max( header_width - indent, 0 ), // width
|
||||
track_height); // height
|
||||
|
||||
// Offset for the next header
|
||||
offset += track_height + TimelineWidget::TrackPadding;
|
||||
}
|
||||
|
||||
layout_headers_recursive(iterator, offset, header_width,
|
||||
indent_width, depth + 1,
|
||||
timeline_track->get_expanded() && parent_expanded);
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<timeline::Track>
|
||||
TimelineLayoutHelper::lookup_timeline_track(
|
||||
shared_ptr<model::Track> model_track)
|
||||
{
|
||||
REQUIRE(model_track != NULL);
|
||||
shared_ptr<timeline::Track> timeline_track =
|
||||
timelineWidget.lookup_timeline_track(model_track);
|
||||
ENSURE(timeline_track);
|
||||
|
||||
return timeline_track;
|
||||
}
|
||||
|
||||
} // namespace timeline
|
||||
} // namespace widgets
|
||||
} // namespace gui
|
||||
222
src/gui/widgets/timeline/timeline-layout-helper.hpp
Normal file
222
src/gui/widgets/timeline/timeline-layout-helper.hpp
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
timeline-layout-helper.hpp - Declaration of the timeline
|
||||
layout helper class
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
/** @file timeline-layout-helper.cpp
|
||||
** This file contains the definition of the layout helpeer class
|
||||
*/
|
||||
|
||||
#ifndef TIMELINE_LAYOUT_HELPER_HPP
|
||||
#define TIMELINE_LAYOUT_HELPER_HPP
|
||||
|
||||
#include "../../gtk-lumiera.hpp"
|
||||
#include "../../../lib/tree.hpp"
|
||||
|
||||
namespace gui {
|
||||
|
||||
namespace model {
|
||||
class Track;
|
||||
}
|
||||
|
||||
namespace widgets {
|
||||
|
||||
class TimelineWidget;
|
||||
|
||||
namespace timeline {
|
||||
|
||||
class Track;
|
||||
|
||||
/**
|
||||
* A helper class for the TimelineWidget. TimelineLayoutHelper
|
||||
* is a class which calculates the layout of tracks in the timeline
|
||||
* track tree.
|
||||
* @see gui::widgets::TimelineWidget
|
||||
*/
|
||||
class TimelineLayoutHelper : public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Definition of the layout track tree type.
|
||||
**/
|
||||
typedef lumiera::tree< boost::shared_ptr<model::Track> > TrackTree;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param owner The timeline widget which is the owner of this helper
|
||||
* class.
|
||||
**/
|
||||
TimelineLayoutHelper(TimelineWidget &owner);
|
||||
|
||||
/**
|
||||
* Clones the timelineWidget sequence's track tree to create a layout
|
||||
* tree which will be identitcal to it.
|
||||
* @remarks The current layout tree will be deleted and replaced with
|
||||
* the clone.
|
||||
* @see add_branch
|
||||
**/
|
||||
void clone_tree_from_sequence();
|
||||
|
||||
/**
|
||||
* Gets a reference to the helper's layout tree.
|
||||
* @return Returns a reference to the helper's layout tree.
|
||||
**/
|
||||
TrackTree& get_layout_tree();
|
||||
|
||||
/**
|
||||
* Recalculates the track layout from layoutTree.
|
||||
* @see layout_headers_recursive
|
||||
**/
|
||||
void update_layout();
|
||||
|
||||
/**
|
||||
* Get's the header rectangle of a given timeline track.
|
||||
* @param[in] track The track which will be looked up.
|
||||
* @return Returns the rectangle of the header offset by the y-scroll
|
||||
* offset, or if the track is hidden, or not present in the layout
|
||||
* tree, an empty optional will be returned.
|
||||
* @remarks This function is only usable after update_layout() has
|
||||
* been called on a valid tree of tracks.
|
||||
* @see update_layout()
|
||||
**/
|
||||
boost::optional<Gdk::Rectangle> get_track_header_rect(
|
||||
boost::weak_ptr<timeline::Track> track);
|
||||
|
||||
/**
|
||||
* Searches for a header which has the specified point inside of it.
|
||||
* @param[in] point The point to search with.
|
||||
* @return Returns the header which has been found, or if no header is
|
||||
* found, an empty shared pointer is returned.
|
||||
* @remarks The point specified is relative to the scroll offset, so
|
||||
* y = 0 is the top edge of the scroll view. This function is only
|
||||
* usable after update_layout() has been called on a valid tree of
|
||||
* tracks.
|
||||
* @see update_layout()
|
||||
**/
|
||||
boost::shared_ptr<timeline::Track> header_from_point(
|
||||
Gdk::Point point);
|
||||
|
||||
/**
|
||||
* Searches for a tack which has the specified y-offset inside of it.
|
||||
* @param[in] y The y-coordinate to search with.
|
||||
* @return Returns the track which has been found, or if no track is
|
||||
* found, an empty shared pointer is returned.
|
||||
* @remarks The point specified is relative to the scroll offset, so
|
||||
* y = 0 is the top edge of the scroll view. This function is only
|
||||
* usable after update_layout() has been called on a valid tree of
|
||||
* tracks.
|
||||
* @see update_layout()
|
||||
**/
|
||||
boost::shared_ptr<timeline::Track> track_from_y(int y);
|
||||
|
||||
/**
|
||||
* Returns the total height in pixels of the layout tree.
|
||||
* @remarks This function is only on returns a valid value fter
|
||||
* update_layout() has been called on a valid tree of tracks.
|
||||
* @see update_layout()
|
||||
**/
|
||||
int get_total_height() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* A helper function for clone_tree_from_sequence(). This function
|
||||
* clones a branch within the model tree into the specified point in
|
||||
* that layout tree.
|
||||
* @param[in] parent_iterator The iterator of the node in the tree
|
||||
* which will become the parent of any tracks added.
|
||||
* @param[in] parent A pointer to the model track whose children
|
||||
* will be added to the layout tree branch.
|
||||
* @see clone_tree_from_sequence()
|
||||
**/
|
||||
void add_branch(TrackTree::iterator_base parent_iterator,
|
||||
boost::shared_ptr<model::Track> parent);
|
||||
|
||||
/**
|
||||
* Recursively calculates the boxes for a given branch in the timeline
|
||||
* tree.
|
||||
* @param[in] parent_iterator The iterator of the parent of the branch
|
||||
* whose boxes will be laid out.
|
||||
* @param[in,out] offset The accumulating y-offset value in pixels.
|
||||
* This value should be set to 0 on the first call, and will
|
||||
* susequently accumulate the offset of each box.
|
||||
* @param[in] header_width The width of the header container widget in
|
||||
* pixels
|
||||
* @param[in] depth The depth within the tree of tracks. depth = 0 for
|
||||
* root tracks.
|
||||
* @param[in] parent_expanded This value is set to true if all of the
|
||||
* ancestors of this track, up to the root are expanded and visible,
|
||||
* false if any of them are collapsed.
|
||||
* @see update_layout()
|
||||
**/
|
||||
void layout_headers_recursive(
|
||||
TrackTree::iterator_base parent_iterator,
|
||||
int &offset, const int header_width, const int indent_width,
|
||||
const int depth, const bool parent_expanded);
|
||||
|
||||
/**
|
||||
* A helper function which calls lookup_timeline_track within the
|
||||
* parent timeline widget, but also applies lots of data consistency
|
||||
* checks in the process.
|
||||
* @param model_track The model track to look up in the parent widget.
|
||||
* @return Returns the track found, or returns NULL if no matching
|
||||
* track was found.
|
||||
* @remarks If the return value is going to be NULL, an ENSURE will
|
||||
* fail.
|
||||
**/
|
||||
boost::shared_ptr<timeline::Track> lookup_timeline_track(
|
||||
boost::shared_ptr<model::Track> model_track);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* The owner timeline widget as provided to the constructor.
|
||||
**/
|
||||
TimelineWidget &timelineWidget;
|
||||
|
||||
/**
|
||||
* The layout tree.
|
||||
**/
|
||||
TrackTree layoutTree;
|
||||
|
||||
/**
|
||||
* A map of tracks to the rectangles of their headers.
|
||||
* @remarks This map is used as a cache, so that the rectangles don't
|
||||
* need to be perpetually recalculated. This cache is regenerated by
|
||||
* the update_layout method.
|
||||
* @see update_layout()
|
||||
**/
|
||||
std::map<boost::weak_ptr<timeline::Track>, Gdk::Rectangle>
|
||||
headerBoxes;
|
||||
|
||||
/**
|
||||
* The total height of the track tree layout in pixels. This value
|
||||
* is only valid after layout_headers has been called.
|
||||
* @see update_layout()
|
||||
**/
|
||||
int totalHeight;
|
||||
};
|
||||
|
||||
} // namespace timeline
|
||||
} // namespace widgets
|
||||
} // namespace gui
|
||||
|
||||
#endif // TIMELINE_LAYOUT_HELPER_HPP
|
||||
|
|
@ -90,6 +90,12 @@ Track::get_header_widget()
|
|||
return headerWidget;
|
||||
}
|
||||
|
||||
shared_ptr<model::Track>
|
||||
Track::get_model_track() const
|
||||
{
|
||||
return model_track;
|
||||
}
|
||||
|
||||
int
|
||||
Track::get_height() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ public:
|
|||
|
||||
Gtk::Widget& get_header_widget();
|
||||
|
||||
boost::shared_ptr<model::Track> get_model_track() const;
|
||||
|
||||
int get_height() const;
|
||||
|
||||
bool get_expanded() const;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ noinst_HEADERS += \
|
|||
$(liblumiera_la_srcdir)/observable-list.hpp \
|
||||
$(liblumiera_la_srcdir)/sync.hpp \
|
||||
$(liblumiera_la_srcdir)/sync-classlock.hpp \
|
||||
$(liblumiera_la_srcdir)/tree.hpp \
|
||||
$(liblumiera_la_srcdir)/test/mockinjector.hpp \
|
||||
$(liblumiera_la_srcdir)/test/suite.hpp \
|
||||
$(liblumiera_la_srcdir)/test/testoption.hpp \
|
||||
|
|
|
|||
2709
src/lib/tree.hpp
Normal file
2709
src/lib/tree.hpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue