diff --git a/icons/Makefile.am b/icons/Makefile.am
index 6693b6d1d..281901e78 100644
--- a/icons/Makefile.am
+++ b/icons/Makefile.am
@@ -33,18 +33,40 @@ iconcommand = python $(top_srcdir)/admin/render-icon.py
48x48pre = $(prerendereddir)/48x48
lumigui_DEPENDENCIES += \
- rsvg-convert \
- $(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png \
- $(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png \
- $(16x16)/panel-assets.png $(22x22)/panel-assets.png $(32x32)/panel-assets.png \
- $(16x16)/panel-timeline.png \
- $(16x16)/panel-viewer.png $(22x22)/panel-viewer.png $(32x32)/panel-viewer.png
+ rsvg-convert \
+ $(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png \
+ $(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png \
+ $(16x16)/track-disabled.png \
+ $(16x16)/track-enabled.png \
+ $(16x16)/track-locked.png \
+ $(16x16)/track-unlocked.png \
+ $(16x16)/panel-assets.png $(22x22)/panel-assets.png $(32x32)/panel-assets.png \
+ $(16x16)/panel-timeline.png \
+ $(16x16)/panel-viewer.png $(22x22)/panel-viewer.png $(32x32)/panel-viewer.png
+
+# ========== SVG Icons ==========
+
+# Timeline Tools
$(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png : $(svgdir)/tool-arrow.svg
$(iconcommand) $< $(icondir)
$(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png : $(svgdir)/tool-i-beam.svg
$(iconcommand) $< $(icondir)
+# Timeline Tracks
+$(16x16)/track-disabled.png : $(svgdir)/track-disabled.svg
+ $(iconcommand) $< $(icondir)
+$(16x16)/track-enabled.png : $(svgdir)/track-enabled.svg
+ $(iconcommand) $< $(icondir)
+$(16x16)/track-locked.png : $(svgdir)/track-locked.svg
+ $(iconcommand) $< $(icondir)
+$(16x16)/track-unlocked.png : $(svgdir)/track-unlocked.svg
+ $(iconcommand) $< $(icondir)
+
+# ========== Prerendered Icons ==========
+
+# Panels
+
$(16x16)/panel-assets.png:
cp $(16x16pre)/panel-assets.png $(16x16)
$(22x22)/panel-assets.png:
diff --git a/icons/svg/track-disabled.svg b/icons/svg/track-disabled.svg
new file mode 100644
index 000000000..04e87768e
--- /dev/null
+++ b/icons/svg/track-disabled.svg
@@ -0,0 +1,663 @@
+
+
+
diff --git a/icons/svg/track-enabled.svg b/icons/svg/track-enabled.svg
new file mode 100644
index 000000000..ab6af9f53
--- /dev/null
+++ b/icons/svg/track-enabled.svg
@@ -0,0 +1,967 @@
+
+
+
diff --git a/icons/svg/track-locked.svg b/icons/svg/track-locked.svg
new file mode 100644
index 000000000..3ff1d34a4
--- /dev/null
+++ b/icons/svg/track-locked.svg
@@ -0,0 +1,866 @@
+
+
+
diff --git a/icons/svg/track-unlocked.svg b/icons/svg/track-unlocked.svg
new file mode 100644
index 000000000..beea19846
--- /dev/null
+++ b/icons/svg/track-unlocked.svg
@@ -0,0 +1,655 @@
+
+
+
diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp
index 6c397f9f1..40d0ad09f 100644
--- a/src/gui/widgets/timeline-widget.cpp
+++ b/src/gui/widgets/timeline-widget.cpp
@@ -69,6 +69,9 @@ TimelineWidget::TimelineWidget() :
set_selection(2000000, 4000000);
tracks.push_back(&video1);
+ video1.add_child_track(&video1a);
+ video1.add_child_track(&video1b);
+ video1b.add_child_track(&video1ba);
tracks.push_back(&video2);
update_tracks();
@@ -332,7 +335,7 @@ TimelineWidget::update_tracks()
BOOST_FOREACH( Track* track, tracks )
{
ASSERT(track != NULL);
- totalHeight += track->get_height() + TrackPadding;
+ totalHeight += measure_branch_height(track);
}
}
@@ -378,6 +381,20 @@ TimelineWidget::update_scroll()
}
+int
+TimelineWidget::measure_branch_height(Track* track)
+{
+ REQUIRE(track != NULL);
+
+ int height = track->get_height();
+
+ // Recurse through all the children
+ BOOST_FOREACH( Track* child, track->get_child_tracks() )
+ height += measure_branch_height(child);
+
+ return height;
+}
+
int
TimelineWidget::get_y_scroll_offset() const
{
diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp
index 7785e7bc8..b1b3b0600 100644
--- a/src/gui/widgets/timeline-widget.hpp
+++ b/src/gui/widgets/timeline-widget.hpp
@@ -202,6 +202,8 @@ private:
void update_scroll();
+ static int measure_branch_height(timeline::Track* track);
+
int get_y_scroll_offset() const;
bool on_motion_in_body_notify_event(GdkEventMotion *event);
@@ -224,6 +226,9 @@ protected:
int totalHeight;
timeline::Track video1;
+ timeline::Track video1a;
+ timeline::Track video1b;
+ timeline::Track video1ba;
timeline::Track video2;
std::vector tracks;
@@ -239,8 +244,7 @@ protected:
// Signals
sigc::signal viewChangedSignal;
sigc::signal mouseHoverSignal;
- sigc::signal
- playbackPeriodDragReleasedSignal;
+ sigc::signal playbackPeriodDragReleasedSignal;
/* ===== Constants ===== */
public:
diff --git a/src/gui/widgets/timeline/timeline-body.cpp b/src/gui/widgets/timeline/timeline-body.cpp
index 7fa0881c5..72d56fd24 100644
--- a/src/gui/widgets/timeline/timeline-body.cpp
+++ b/src/gui/widgets/timeline/timeline-body.cpp
@@ -276,28 +276,45 @@ TimelineBody::draw_tracks(Cairo::RefPtr cr)
BOOST_FOREACH( Track* track, timelineWidget->tracks )
{
ASSERT(track != NULL);
-
- const int height = track->get_height();
- ASSERT(height >= 0);
-
- // Draw the track background
- cr->rectangle(0, 0, allocation.get_width(), height);
- gdk_cairo_set_source_color(cr->cobj(), &backgroundColour);
- cr->fill();
-
- // Render the track
- cr->save();
- track->draw_track(cr);
- cr->restore();
-
- // Shift for the next track
- cr->translate(0, height + TimelineWidget::TrackPadding);
+ draw_track_recursive(cr, track, allocation.get_width());
}
// Restore the view matrix
cr->set_matrix(view_matrix);
}
+void
+TimelineBody::draw_track_recursive(Cairo::RefPtr cr,
+ const Track *track, const int view_width) const
+{
+ REQUIRE(cr);
+ REQUIRE(track != NULL);
+
+ const int height = track->get_height();
+ ASSERT(height >= 0);
+
+ // Draw the track background
+ cr->rectangle(0, 0, view_width,
+ height - TimelineWidget::TrackPadding);
+ GdkColor colour = backgroundColour; // Needed to preserve const qualifier
+ gdk_cairo_set_source_color(cr->cobj(), &colour);
+ cr->fill();
+
+ // Render the track
+ cr->save();
+ track->draw_track(cr);
+ cr->restore();
+
+ // Shift for the next track
+ cr->translate(0, height);
+
+ BOOST_FOREACH( Track* child, track->get_child_tracks() )
+ {
+ ASSERT(track != NULL);
+ draw_track_recursive(cr, child, view_width);
+ }
+}
+
void
TimelineBody::draw_selection(Cairo::RefPtr cr)
{
diff --git a/src/gui/widgets/timeline/timeline-body.hpp b/src/gui/widgets/timeline/timeline-body.hpp
index 894cb9f09..9ce48f5e1 100644
--- a/src/gui/widgets/timeline/timeline-body.hpp
+++ b/src/gui/widgets/timeline/timeline-body.hpp
@@ -36,6 +36,8 @@ class TimelineWidget;
namespace timeline {
+class Track;
+
/**
* Implementation of the timeline body subwidget. This widget is
* displayed in the centre of the timeline widget, and displays the
@@ -111,6 +113,10 @@ private:
*/
void draw_tracks(Cairo::RefPtr cr);
+ void draw_track_recursive(Cairo::RefPtr cr,
+ const gui::widgets::timeline::Track *track,
+ const int view_width) const;
+
/**
* Draws the selected timeline period.
* @param cr The cairo context to draw into.
diff --git a/src/gui/widgets/timeline/timeline-header-container.cpp b/src/gui/widgets/timeline/timeline-header-container.cpp
index ba8323aab..3c16d912e 100644
--- a/src/gui/widgets/timeline/timeline-header-container.cpp
+++ b/src/gui/widgets/timeline/timeline-header-container.cpp
@@ -55,32 +55,15 @@ TimelineHeaderContainer::TimelineHeaderContainer(gui::widgets::TimelineWidget
// Install style properties
register_styles();
}
-
+
void
TimelineHeaderContainer::update_headers()
{
REQUIRE(timelineWidget != NULL);
-
- // Remove any pre-exisitng headers
- BOOST_FOREACH( RootHeader header, rootHeaders )
- {
- header.widget->unparent();
- }
- rootHeaders.clear();
-
// Add fresh headers
BOOST_FOREACH( Track* track, timelineWidget->tracks )
- {
- ASSERT(track != NULL);
-
- const RootHeader header = { &track->get_header_widget(), track };
- header.widget->set_parent(*this);
-
- rootHeaders.push_back(header);
- }
-
- layout_headers();
+ set_parent_recursive(track);
}
void
@@ -132,18 +115,14 @@ TimelineHeaderContainer::on_unrealize()
void
TimelineHeaderContainer::on_size_request (Requisition* requisition)
{
- // Initialize the output parameter:
- *requisition = Gtk::Requisition();
-
// We don't care about the size of all the child widgets, but if we
// don't send the size request down the tree, some widgets fail to
- // calculate their text layout correctly.
- BOOST_FOREACH( RootHeader header, rootHeaders )
- {
- if(header.widget != NULL && header.widget->is_visible())
- header.widget->size_request();
- }
-
+ // calculate their text layout correctly.
+ BOOST_FOREACH( Track* track, timelineWidget->tracks )
+ size_request_recursive(track);
+
+ // Initialize the output parameter:
+ *requisition = Gtk::Requisition();
requisition->width = TimelineWidget::HeaderWidth;
requisition->height = 0;
}
@@ -166,10 +145,12 @@ void
TimelineHeaderContainer::forall_vfunc(gboolean /* include_internals */,
GtkCallback callback, gpointer callback_data)
{
- BOOST_FOREACH( RootHeader &header, rootHeaders )
+ REQUIRE(callback != NULL);
+
+ BOOST_FOREACH( Track* track, timelineWidget->tracks )
{
- ASSERT(header.widget);
- callback(header.widget->gobj(), callback_data);
+ ASSERT(track != NULL);
+ forall_vfunc_recursive(track, callback, callback_data);
}
}
@@ -187,12 +168,12 @@ TimelineHeaderContainer::on_expose_event(GdkEventExpose *event)
read_styles();
// Paint a border underneath all the root headers
- BOOST_FOREACH( RootHeader &header, rootHeaders )
+ BOOST_FOREACH( Track* track, timelineWidget->tracks )
{
- ASSERT(header.widget);
- ASSERT(header.track != NULL);
+ ASSERT(track != NULL);
- const int height = header.track->get_height();
+ const int height = TimelineWidget::measure_branch_height(
+ track);
ASSERT(height >= 0);
style->paint_box(
@@ -237,30 +218,82 @@ TimelineHeaderContainer::layout_headers()
const int header_width = container_allocation.get_width ()
- margin * 2;
- BOOST_FOREACH( RootHeader &header, rootHeaders )
+ BOOST_FOREACH( Track* track, timelineWidget->tracks )
{
- ASSERT(header.widget);
- ASSERT(header.track != NULL);
-
- const int height = header.track->get_height();
- ASSERT(height >= 0);
-
- Gtk::Allocation header_allocation;
- header_allocation.set_x (margin);
- header_allocation.set_y (offset - y_scroll_offset + margin);
- header_allocation.set_width (header_width);
- header_allocation.set_height (height - margin * 2);
-
- if(header.widget->is_visible())
- header.widget->size_allocate (header_allocation);
-
- offset += height + TimelineWidget::TrackPadding;
+ ASSERT(track != NULL);
+ layout_headers_recursive(track, y_scroll_offset, offset,
+ header_width, 0);
}
// Repaint the background of our parenting
queue_draw ();
}
+void
+TimelineHeaderContainer::layout_headers_recursive(Track *track,
+ const int y_scroll_offset, int &offset,
+ const int header_width, int depth) const
+{
+ const int height = track->get_height();
+ ASSERT(height >= 0);
+
+ const int indent = depth * 10;
+
+ Allocation header_allocation;
+ header_allocation.set_x (margin + indent);
+ header_allocation.set_y (offset - y_scroll_offset + margin);
+ header_allocation.set_width (header_width - indent);
+ header_allocation.set_height (height - margin * 2);
+
+ Widget &widget = track->get_header_widget();
+ if(widget.is_visible())
+ widget.size_allocate (header_allocation);
+
+ offset += height + TimelineWidget::TrackPadding;
+
+ // Recurse through all the children
+ BOOST_FOREACH( Track* child, track->get_child_tracks() )
+ layout_headers_recursive(child, y_scroll_offset, offset,
+ header_width, depth + 1);
+}
+
+void
+TimelineHeaderContainer::set_parent_recursive(Track *track)
+{
+ REQUIRE(track != NULL);
+ track->get_header_widget().set_parent(*this);
+
+ // Recurse through all the children
+ BOOST_FOREACH( Track* child, track->get_child_tracks() )
+ set_parent_recursive(child);
+}
+
+void
+TimelineHeaderContainer::size_request_recursive(Track *track)
+{
+ REQUIRE(track != NULL);
+ if(track->get_header_widget().is_visible())
+ track->get_header_widget().size_request();
+
+ // Recurse through all the children
+ BOOST_FOREACH( Track* child, track->get_child_tracks() )
+ size_request_recursive(child);
+}
+
+void
+TimelineHeaderContainer::forall_vfunc_recursive(Track* track,
+ GtkCallback callback, gpointer callback_data)
+{
+ REQUIRE(track != NULL);
+ REQUIRE(callback != NULL);
+
+ callback(track->get_header_widget().gobj(), callback_data);
+
+ // Recurse through all the children
+ BOOST_FOREACH( Track* child, track->get_child_tracks() )
+ forall_vfunc_recursive(child, callback, callback_data);
+}
+
void
TimelineHeaderContainer::register_styles() const
{
diff --git a/src/gui/widgets/timeline/timeline-header-container.hpp b/src/gui/widgets/timeline/timeline-header-container.hpp
index 480ab6cde..d287f2056 100644
--- a/src/gui/widgets/timeline/timeline-header-container.hpp
+++ b/src/gui/widgets/timeline/timeline-header-container.hpp
@@ -119,6 +119,21 @@ private:
*/
void layout_headers();
+ void layout_headers_recursive(Track *track,
+ const int y_scroll_offset, int &offset,
+ const int header_width, int depth) const;
+
+ /**
+ * Recursively sets all the track header widgets to be child widgets
+ * of this widget.
+ **/
+ void set_parent_recursive(Track *track);
+
+ static void size_request_recursive(Track *track);
+
+ static void forall_vfunc_recursive(Track* track,
+ GtkCallback callback, gpointer callback_data);
+
/**
* Registers all the styles that this class will respond to.
*/
@@ -143,24 +158,6 @@ private:
* widgets are scrolled.
*/
Glib::RefPtr gdkWindow;
-
- //----- Header List -----//
-
- /**
- * A structure to represent a header widget and it's
- * associated track
- */
- struct RootHeader
- {
- Gtk::Widget *widget;
- Track *track;
- };
-
- /**
- * Contains a list of the root currently present on
- * the timeline view
- */
- std::vector< RootHeader > rootHeaders;
//----- Style Values -----//
diff --git a/src/gui/widgets/timeline/track.cpp b/src/gui/widgets/timeline/track.cpp
index f8acb35de..bac443ced 100644
--- a/src/gui/widgets/timeline/track.cpp
+++ b/src/gui/widgets/timeline/track.cpp
@@ -29,12 +29,30 @@ namespace widgets {
namespace timeline {
Track::Track() :
- label1("test1"), label2("test2"), label3("test3"), label4("test4")
+ enableButton(Gtk::StockID("track_enabled")),
+ lockButton(Gtk::StockID("track_unlocked"))
{
- headerWidget.pack_start(label1, PACK_EXPAND_WIDGET);
- headerWidget.pack_start(label2, PACK_EXPAND_WIDGET);
- headerWidget.pack_start(label3, PACK_EXPAND_WIDGET);
- headerWidget.pack_start(label4, PACK_EXPAND_WIDGET);
+ buttonBar.append(enableButton);
+ buttonBar.append(lockButton);
+
+ buttonBar.set_toolbar_style(TOOLBAR_ICONS);
+ buttonBar.set_icon_size(ICON_SIZE_MENU);
+
+ headerWidget.pack_start(titleBox, PACK_SHRINK);
+ headerWidget.pack_start(buttonBar, PACK_SHRINK);
+}
+
+void
+Track::add_child_track(timeline::Track* child)
+{
+ REQUIRE(child != NULL);
+ children.push_back(child);
+}
+
+const std::vector&
+Track::get_child_tracks() const
+{
+ return children;
}
Gtk::Widget&
@@ -43,20 +61,20 @@ Track::get_header_widget()
return headerWidget;
}
+int
+Track::get_height() const
+{
+ return 100;
+}
+
Glib::ustring
Track::get_title()
{
return "Hello";
}
-int
-Track::get_height()
-{
- return 100;
-}
-
void
-Track::draw_track(Cairo::RefPtr cairo)
+Track::draw_track(Cairo::RefPtr cairo) const
{
}
diff --git a/src/gui/widgets/timeline/track.hpp b/src/gui/widgets/timeline/track.hpp
index a1b6d48e8..9f7277dd1 100644
--- a/src/gui/widgets/timeline/track.hpp
+++ b/src/gui/widgets/timeline/track.hpp
@@ -32,25 +32,42 @@ namespace gui {
namespace widgets {
namespace timeline {
+class Clip;
+
class Track
{
public:
Track();
+ void add_child_track(timeline::Track* child);
+
+ const std::vector& get_child_tracks() const;
+
+ Gtk::Widget& get_header_widget();
+
+ int get_height() const;
+
Glib::ustring get_title();
- Gtk::Widget& get_header_widget();
+ void draw_track(Cairo::RefPtr cairo) const;
+
+private:
+
+private:
- int get_height();
+ //----- Data -----//
+ std::vector children;
+ std::vector clips;
- void draw_track(Cairo::RefPtr cairo);
-
-protected:
+ //----- Header Widgets ------//
+
Gtk::VBox headerWidget;
- Gtk::Label label1;
- Gtk::Label label2;
- Gtk::CheckButton label3;
- Gtk::Button label4;
+
+ Gtk::ToolButton enableButton;
+ Gtk::ToolButton lockButton;
+
+ Gtk::Entry titleBox;
+ Gtk::Toolbar buttonBar;
};
diff --git a/src/gui/window-manager.cpp b/src/gui/window-manager.cpp
index 4a89158d7..c7cbb3c32 100644
--- a/src/gui/window-manager.cpp
+++ b/src/gui/window-manager.cpp
@@ -92,7 +92,12 @@ WindowManager::register_stock_items()
add_stock_icon_set(factory, "panel-viewer", "panel_viewer", _("_Viewer"));
add_stock_icon_set(factory, "tool-arrow", "tool_arrow", _("_Arrow"));
- add_stock_icon_set(factory, "tool-i-beam", "tool_i_beam", _("_I-Beam"));
+ add_stock_icon_set(factory, "tool-i-beam", "tool_i_beam", _("_I-Beam"));
+
+ add_stock_icon_set(factory, "track-disabled", "track_disabled", _("Track Disabled"));
+ add_stock_icon_set(factory, "track-enabled", "track_enabled", _("Track Enabled"));
+ add_stock_icon_set(factory, "track-locked", "track_locked", _("Track Locked"));
+ add_stock_icon_set(factory, "track-unlocked", "track_unlocked", _("Track Unlocked"));
factory->add_default(); //Add factory to list of factories.
}