diff --git a/src/gui/lumiera_ui.rc b/src/gui/lumiera_ui.rc index 9f1f1d3b6..9d4f4d771 100644 --- a/src/gui/lumiera_ui.rc +++ b/src/gui/lumiera_ui.rc @@ -152,14 +152,13 @@ style "timeline_ruler" = "default_base" gtkmm__CustomObject_TimelineRuler::playback_period_arrow_stem_size = 3 } -style "timeline_header_base" = "default_base" +style "header_container" = "default_base" { - + gtkmm__CustomObject_HeaderContainer::heading_margin = 4 } class "gtkmm__CustomObject_TimelineBody" style:highest "timeline_body" class "gtkmm__CustomObject_TimelineRuler" style:highest "timeline_ruler" - -widget "*TimelineHeaderBaseUnselected" style:highest "timeline_header_base" +class "gtkmm__CustomObject_HeaderContainer" style:highest "header_container" diff --git a/src/gui/widgets/timeline-widget.cpp b/src/gui/widgets/timeline-widget.cpp index 2bf6285f9..a3335cfd3 100644 --- a/src/gui/widgets/timeline-widget.cpp +++ b/src/gui/widgets/timeline-widget.cpp @@ -68,17 +68,17 @@ TimelineWidget::TimelineWidget() : set_time_scale(GAVL_TIME_SCALE / 200); set_selection(2000000, 4000000); - + + tracks.push_back(&video1); + tracks.push_back(&video2); + + update_tracks(); + attach(*body, 1, 2, 1, 2, FILL|EXPAND, FILL|EXPAND); attach(*ruler, 1, 2, 0, 1, FILL|EXPAND, SHRINK); attach(*headerContainer, 0, 1, 1, 2, SHRINK, FILL|EXPAND); attach(horizontalScroll, 1, 2, 2, 3, FILL|EXPAND, SHRINK); attach(verticalScroll, 2, 3, 1, 2, SHRINK, FILL|EXPAND); - - tracks.push_back(&video1); - tracks.push_back(&video2); - - update_tracks(); set_tool(timeline::Arrow); } @@ -376,6 +376,7 @@ TimelineWidget::update_scroll() else if(y_scroll_length > 0 && !verticalScroll.is_visible()) verticalScroll.show(); #endif + } int @@ -390,6 +391,7 @@ TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event) REQUIRE(event != NULL); ruler->set_mouse_chevron_offset(event->x); mouseHoverSignal.emit(x_to_time(event->x)); + return true; } diff --git a/src/gui/widgets/timeline-widget.hpp b/src/gui/widgets/timeline-widget.hpp index 4e307bd19..7d2bfef00 100644 --- a/src/gui/widgets/timeline-widget.hpp +++ b/src/gui/widgets/timeline-widget.hpp @@ -185,6 +185,7 @@ public: /* ===== Events ===== */ protected: + void on_scroll(); void on_size_allocate(Gtk::Allocation& allocation); diff --git a/src/gui/widgets/timeline/header-container.cpp b/src/gui/widgets/timeline/header-container.cpp index dfc085fc1..6bd5a42ae 100644 --- a/src/gui/widgets/timeline/header-container.cpp +++ b/src/gui/widgets/timeline/header-container.cpp @@ -35,7 +35,9 @@ namespace widgets { namespace timeline { HeaderContainer::HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline_widget) : - timelineWidget(timeline_widget) + Glib::ObjectBase("HeaderContainer"), + timelineWidget(timeline_widget), + margin(-1) { REQUIRE(timeline_widget != NULL); @@ -48,25 +50,32 @@ HeaderContainer::HeaderContainer(lumiera::gui::widgets::TimelineWidget *timeline // so that we get notified when the view shifts timelineWidget->verticalAdjustment.signal_value_changed().connect( sigc::mem_fun(this, &HeaderContainer::on_scroll) ); + + // Install style properties + register_styles(); } void HeaderContainer::update_headers() { - ASSERT(timelineWidget != NULL); + 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); - - Glib::RefPtr headerFrame(new Gtk::Frame()); - headerFrame->add(track->get_header_widget()); - headerFrame->set_shadow_type (Gtk::SHADOW_ETCHED_OUT); - headerFrame->set_name ("TimelineHeaderBaseUnselected"); - headerFrame->set_parent(*this); - headerFrame->show(); - - const RootHeader header = { headerFrame, track }; + + const RootHeader header = { &track->get_header_widget(), track }; + header.widget->set_parent(*this); + rootHeaders.push_back(header); } @@ -78,11 +87,9 @@ HeaderContainer::on_realize() { set_flags(Gtk::NO_WINDOW); - ensure_style(); - // Call base class: - Gtk::Widget::on_realize(); - + Gtk::Container::on_realize(); + // Create the GdkWindow: GdkWindowAttr attributes; memset(&attributes, 0, sizeof(attributes)); @@ -123,9 +130,18 @@ HeaderContainer::on_unrealize() void HeaderContainer::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(); + } requisition->width = TimelineWidget::HeaderWidth; requisition->height = 0; @@ -148,13 +164,51 @@ HeaderContainer::on_size_allocate (Allocation& allocation) void HeaderContainer::forall_vfunc(gboolean /* include_internals */, GtkCallback callback, gpointer callback_data) -{ +{ BOOST_FOREACH( RootHeader &header, rootHeaders ) { ASSERT(header.widget); callback(header.widget->gobj(), callback_data); } } + +bool +HeaderContainer::on_expose_event(GdkEventExpose *event) +{ + if(gdkWindow) + { + int offset = 0; + const int y_scroll_offset = timelineWidget->get_y_scroll_offset(); + + Glib::RefPtr