Added support for no-state mode to TimelineWidget
This commit is contained in:
parent
7766a223eb
commit
390354ea8a
6 changed files with 345 additions and 286 deletions
|
|
@ -245,7 +245,6 @@ TimelinePanel::update_sequence_chooser()
|
|||
|
||||
shared_ptr<timeline::TimelineState> state =
|
||||
timelineWidget->get_state();
|
||||
REQUIRE(state);
|
||||
|
||||
BOOST_FOREACH( shared_ptr< model::Sequence > sequence,
|
||||
workspace.get_project().get_sequences() )
|
||||
|
|
@ -255,10 +254,14 @@ TimelinePanel::update_sequence_chooser()
|
|||
row[sequenceChooserColumns.sequenceColumn] = sequence;
|
||||
row[sequenceChooserColumns.nameColumn] = sequence->get_name();
|
||||
|
||||
if(state->get_sequence() == sequence)
|
||||
if(state && state->get_sequence() == sequence)
|
||||
sequenceChooser.set_active(iter);
|
||||
}
|
||||
|
||||
// If there's no active sequence, then unselect
|
||||
if(!state)
|
||||
sequenceChooser.set_active(-1);
|
||||
|
||||
// Unblock the event handler
|
||||
sequenceChooserChangedConnection.unblock();
|
||||
}
|
||||
|
|
@ -287,12 +290,17 @@ TimelinePanel::update_zoom_buttons()
|
|||
{
|
||||
REQUIRE(timelineWidget);
|
||||
|
||||
timeline::TimelineViewWindow &viewWindow =
|
||||
timelineWidget->get_state()->get_view_window();
|
||||
|
||||
zoomIn.set_sensitive(viewWindow.get_time_scale() != 1);
|
||||
zoomOut.set_sensitive(viewWindow.get_time_scale()
|
||||
!= TimelineWidget::MaxScale);
|
||||
const shared_ptr<timeline::TimelineState> state =
|
||||
timelineWidget->get_state();
|
||||
if(state)
|
||||
{
|
||||
timeline::TimelineViewWindow &viewWindow =
|
||||
state->get_view_window();
|
||||
|
||||
zoomIn.set_sensitive(viewWindow.get_time_scale() != 1);
|
||||
zoomOut.set_sensitive(viewWindow.get_time_scale()
|
||||
!= TimelineWidget::MaxScale);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -51,11 +51,8 @@ TimelineWidget::TimelineWidget(
|
|||
verticalAdjustment(0, 0, 0),
|
||||
horizontalScroll(horizontalAdjustment),
|
||||
verticalScroll(verticalAdjustment),
|
||||
update_tracks_frozen(true)
|
||||
update_tracks_frozen(false)
|
||||
{
|
||||
set_state(source_state);
|
||||
thaw_update_tracks();
|
||||
|
||||
body = new TimelineBody(*this);
|
||||
ENSURE(body != NULL);
|
||||
headerContainer = new TimelineHeaderContainer(*this);
|
||||
|
|
@ -78,6 +75,8 @@ TimelineWidget::TimelineWidget(
|
|||
attach(horizontalScroll, 1, 2, 2, 3, FILL|EXPAND, SHRINK);
|
||||
attach(verticalScroll, 2, 3, 1, 2, SHRINK, FILL|EXPAND);
|
||||
|
||||
set_state(source_state);
|
||||
|
||||
set_tool(timeline::Arrow);
|
||||
}
|
||||
|
||||
|
|
@ -102,34 +101,32 @@ TimelineWidget::~TimelineWidget()
|
|||
boost::shared_ptr<timeline::TimelineState>
|
||||
TimelineWidget::get_state()
|
||||
{
|
||||
ENSURE(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
TimelineWidget::set_state(shared_ptr<timeline::TimelineState> new_state)
|
||||
{
|
||||
if(!new_state)
|
||||
return;
|
||||
|
||||
{
|
||||
state = new_state;
|
||||
REQUIRE(state);
|
||||
|
||||
// Clear the track tree
|
||||
trackMap.clear();
|
||||
|
||||
// Hook up event handlers
|
||||
state->get_view_window().changed_signal().connect( sigc::mem_fun(
|
||||
this, &TimelineWidget::on_view_window_changed) );
|
||||
state->get_sequence()->get_child_track_list().signal_changed().
|
||||
connect(sigc::mem_fun(
|
||||
this, &TimelineWidget::on_track_list_changed ) );
|
||||
|
||||
state->selection_changed_signal().connect(mem_fun(*this,
|
||||
&TimelineWidget::on_body_changed));
|
||||
state->playback_changed_signal().connect(mem_fun(*this,
|
||||
&TimelineWidget::on_body_changed));
|
||||
|
||||
if(state)
|
||||
{
|
||||
// Hook up event handlers
|
||||
state->get_view_window().changed_signal().connect( sigc::mem_fun(
|
||||
this, &TimelineWidget::on_view_window_changed) );
|
||||
state->get_sequence()->get_child_track_list().signal_changed().
|
||||
connect(sigc::mem_fun(
|
||||
this, &TimelineWidget::on_track_list_changed ) );
|
||||
|
||||
state->selection_changed_signal().connect(mem_fun(*this,
|
||||
&TimelineWidget::on_body_changed));
|
||||
state->playback_changed_signal().connect(mem_fun(*this,
|
||||
&TimelineWidget::on_body_changed));
|
||||
}
|
||||
|
||||
update_tracks();
|
||||
|
||||
// Send the state changed signal
|
||||
|
|
@ -139,10 +136,11 @@ TimelineWidget::set_state(shared_ptr<timeline::TimelineState> new_state)
|
|||
void
|
||||
TimelineWidget::zoom_view(int zoom_size)
|
||||
{
|
||||
REQUIRE(state);
|
||||
|
||||
const int view_width = body->get_allocation().get_width();
|
||||
state->get_view_window().zoom_view(view_width / 2, zoom_size);
|
||||
if(state)
|
||||
{
|
||||
const int view_width = body->get_allocation().get_width();
|
||||
state->get_view_window().zoom_view(view_width / 2, zoom_size);
|
||||
}
|
||||
}
|
||||
|
||||
ToolType
|
||||
|
|
@ -195,9 +193,9 @@ TimelineWidget::state_changed_signal() const
|
|||
void
|
||||
TimelineWidget::on_scroll()
|
||||
{
|
||||
REQUIRE(state);
|
||||
state->get_view_window().set_time_offset(
|
||||
horizontalAdjustment.get_value());
|
||||
if(state)
|
||||
state->get_view_window().set_time_offset(
|
||||
horizontalAdjustment.get_value());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -212,14 +210,16 @@ void
|
|||
TimelineWidget::on_view_window_changed()
|
||||
{
|
||||
REQUIRE(ruler != NULL);
|
||||
REQUIRE(state);
|
||||
|
||||
timeline::TimelineViewWindow &window = state->get_view_window();
|
||||
const int view_width = body->get_allocation().get_width();
|
||||
|
||||
horizontalAdjustment.set_page_size(
|
||||
window.get_time_scale() * view_width);
|
||||
horizontalAdjustment.set_value(window.get_time_offset());
|
||||
if(state)
|
||||
{
|
||||
timeline::TimelineViewWindow &window = state->get_view_window();
|
||||
const int view_width = body->get_allocation().get_width();
|
||||
|
||||
horizontalAdjustment.set_page_size(
|
||||
window.get_time_scale() * view_width);
|
||||
horizontalAdjustment.set_value(window.get_time_offset());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -235,8 +235,9 @@ void
|
|||
TimelineWidget::on_add_track_command()
|
||||
{
|
||||
// # TEST CODE
|
||||
sequence()->get_child_track_list().push_back(
|
||||
shared_ptr<model::Track>(new model::ClipTrack()));
|
||||
if(sequence())
|
||||
sequence()->get_child_track_list().push_back(
|
||||
shared_ptr<model::Track>(new model::ClipTrack()));
|
||||
}
|
||||
|
||||
/* ===== Internals ===== */
|
||||
|
|
@ -247,15 +248,20 @@ TimelineWidget::update_tracks()
|
|||
if(update_tracks_frozen)
|
||||
return;
|
||||
|
||||
// Remove any tracks which are no longer present in the model
|
||||
remove_orphaned_tracks();
|
||||
|
||||
// Create timeline tracks from all the model tracks
|
||||
create_timeline_tracks();
|
||||
|
||||
// Update the layout helper
|
||||
layoutHelper.clone_tree_from_sequence();
|
||||
layoutHelper.update_layout();
|
||||
if(state)
|
||||
{
|
||||
// Remove any tracks which are no longer present in the model
|
||||
remove_orphaned_tracks();
|
||||
|
||||
// Create timeline tracks from all the model tracks
|
||||
create_timeline_tracks();
|
||||
|
||||
// Update the layout helper
|
||||
layoutHelper.clone_tree_from_sequence();
|
||||
layoutHelper.update_layout();
|
||||
}
|
||||
else
|
||||
trackMap.clear();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -273,6 +279,8 @@ TimelineWidget::thaw_update_tracks()
|
|||
void
|
||||
TimelineWidget::create_timeline_tracks()
|
||||
{
|
||||
REQUIRE(state);
|
||||
|
||||
BOOST_FOREACH(shared_ptr<model::Track> child,
|
||||
sequence()->get_child_tracks())
|
||||
create_timeline_tracks_from_branch(child);
|
||||
|
|
@ -403,44 +411,45 @@ TimelineWidget::update_scroll()
|
|||
REQUIRE(body != NULL);
|
||||
const Allocation body_allocation = body->get_allocation();
|
||||
|
||||
REQUIRE(state);
|
||||
timeline::TimelineViewWindow &window = state->get_view_window();
|
||||
|
||||
//----- Horizontal Scroll ------//
|
||||
|
||||
// TEST CODE
|
||||
horizontalAdjustment.set_upper(1000 * GAVL_TIME_SCALE / 200);
|
||||
horizontalAdjustment.set_lower(-1000 * GAVL_TIME_SCALE / 200);
|
||||
|
||||
// Set the page size
|
||||
horizontalAdjustment.set_page_size(
|
||||
window.get_time_scale() * body_allocation.get_width());
|
||||
|
||||
//----- Vertical Scroll -----//
|
||||
|
||||
// Calculate the vertical length that can be scrolled:
|
||||
// the total height of all the tracks minus one screenful
|
||||
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
|
||||
// maximum distance
|
||||
if((int)verticalAdjustment.get_value() > y_scroll_length)
|
||||
verticalAdjustment.set_value(y_scroll_length);
|
||||
|
||||
verticalAdjustment.set_upper(y_scroll_length);
|
||||
|
||||
// Hide the scrollbar if no scrolling is possible
|
||||
if(state)
|
||||
{
|
||||
timeline::TimelineViewWindow &window = state->get_view_window();
|
||||
|
||||
//----- Horizontal Scroll ------//
|
||||
|
||||
// TEST CODE
|
||||
horizontalAdjustment.set_upper(1000 * GAVL_TIME_SCALE / 200);
|
||||
horizontalAdjustment.set_lower(-1000 * GAVL_TIME_SCALE / 200);
|
||||
|
||||
// Set the page size
|
||||
horizontalAdjustment.set_page_size(
|
||||
window.get_time_scale() * body_allocation.get_width());
|
||||
|
||||
//----- Vertical Scroll -----//
|
||||
|
||||
// Calculate the vertical length that can be scrolled:
|
||||
// the total height of all the tracks minus one screenful
|
||||
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
|
||||
// maximum distance
|
||||
if((int)verticalAdjustment.get_value() > y_scroll_length)
|
||||
verticalAdjustment.set_value(y_scroll_length);
|
||||
|
||||
verticalAdjustment.set_upper(y_scroll_length);
|
||||
|
||||
// Hide the scrollbar if no scrolling is possible
|
||||
#if 0
|
||||
// Having this code included seems to cause a layout loop as the
|
||||
// window is shrunk
|
||||
if(y_scroll_length <= 0 && verticalScroll.is_visible())
|
||||
verticalScroll.hide();
|
||||
else if(y_scroll_length > 0 && !verticalScroll.is_visible())
|
||||
verticalScroll.show();
|
||||
// Having this code included seems to cause a layout loop as the
|
||||
// window is shrunk
|
||||
if(y_scroll_length <= 0 && verticalScroll.is_visible())
|
||||
verticalScroll.hide();
|
||||
else if(y_scroll_length > 0 && !verticalScroll.is_visible())
|
||||
verticalScroll.show();
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -461,9 +470,11 @@ TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event)
|
|||
REQUIRE(event != NULL);
|
||||
ruler->set_mouse_chevron_offset(event->x);
|
||||
|
||||
REQUIRE(state);
|
||||
timeline::TimelineViewWindow &window = state->get_view_window();
|
||||
mouseHoverSignal.emit(window.x_to_time(event->x));
|
||||
if(state)
|
||||
{
|
||||
timeline::TimelineViewWindow &window = state->get_view_window();
|
||||
mouseHoverSignal.emit(window.x_to_time(event->x));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -471,8 +482,9 @@ TimelineWidget::on_motion_in_body_notify_event(GdkEventMotion *event)
|
|||
boost::shared_ptr<model::Sequence>
|
||||
TimelineWidget::sequence() const
|
||||
{
|
||||
REQUIRE(state);
|
||||
boost::shared_ptr<model::Sequence> sequence = state->get_sequence();
|
||||
if(!state)
|
||||
return shared_ptr<model::Sequence>();
|
||||
shared_ptr<model::Sequence> sequence = state->get_sequence();
|
||||
ENSURE(sequence);
|
||||
return sequence;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,16 +137,19 @@ TimelineBody::on_expose_event(GdkEventExpose* event)
|
|||
// Makes sure the widget styles have been loaded
|
||||
read_styles();
|
||||
|
||||
// Prepare to render via cairo
|
||||
const Allocation allocation = get_allocation();
|
||||
Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
|
||||
if(timelineWidget.get_state())
|
||||
{
|
||||
// Prepare to render via cairo
|
||||
const Allocation allocation = get_allocation();
|
||||
Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
|
||||
|
||||
REQUIRE(cr);
|
||||
|
||||
//----- Draw the view -----//
|
||||
draw_tracks(cr);
|
||||
draw_selection(cr);
|
||||
draw_playback_point(cr);
|
||||
REQUIRE(cr);
|
||||
|
||||
//----- Draw the view -----//
|
||||
draw_tracks(cr);
|
||||
draw_selection(cr);
|
||||
draw_playback_point(cr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -156,45 +159,48 @@ TimelineBody::on_scroll_event (GdkEventScroll* event)
|
|||
{
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
TimelineViewWindow &window = view_window();
|
||||
const Allocation allocation = get_allocation();
|
||||
|
||||
if(event->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
switch(event->direction)
|
||||
if(timelineWidget.get_state())
|
||||
{
|
||||
case GDK_SCROLL_UP:
|
||||
// User scrolled up. Zoom in
|
||||
window.zoom_view(event->x, 1);
|
||||
break;
|
||||
TimelineViewWindow &window = view_window();
|
||||
const Allocation allocation = get_allocation();
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
// User scrolled down. Zoom out
|
||||
window.zoom_view(event->x, -1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if(event->state & GDK_CONTROL_MASK)
|
||||
{
|
||||
switch(event->direction)
|
||||
{
|
||||
case GDK_SCROLL_UP:
|
||||
// User scrolled up. Zoom in
|
||||
window.zoom_view(event->x, 1);
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
// User scrolled down. Zoom out
|
||||
window.zoom_view(event->x, -1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(event->direction)
|
||||
{
|
||||
case GDK_SCROLL_UP:
|
||||
// User scrolled up. Shift 1/16th left
|
||||
window.shift_view(allocation.get_width(), -16);
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
// User scrolled down. Shift 1/16th right
|
||||
window.shift_view(allocation.get_width(), 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(event->direction)
|
||||
{
|
||||
case GDK_SCROLL_UP:
|
||||
// User scrolled up. Shift 1/16th left
|
||||
window.shift_view(allocation.get_width(), -16);
|
||||
break;
|
||||
|
||||
case GDK_SCROLL_DOWN:
|
||||
// User scrolled down. Shift 1/16th right
|
||||
window.shift_view(allocation.get_width(), 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -239,36 +245,39 @@ TimelineBody::on_motion_notify_event(GdkEventMotion *event)
|
|||
{
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
// Handle a middle-mouse drag if one is occuring
|
||||
switch(dragType)
|
||||
if(timelineWidget.get_state())
|
||||
{
|
||||
case Shift:
|
||||
{
|
||||
TimelineViewWindow &window = view_window();
|
||||
|
||||
const int64_t scale = window.get_time_scale();
|
||||
gavl_time_t offset = beginShiftTimeOffset +
|
||||
(int64_t)(mouseDownX - event->x) * scale;
|
||||
window.set_time_offset(offset);
|
||||
|
||||
set_vertical_offset((int)(mouseDownY - event->y) +
|
||||
beginShiftVerticalOffset);
|
||||
break;
|
||||
}
|
||||
// Handle a middle-mouse drag if one is occuring
|
||||
switch(dragType)
|
||||
{
|
||||
case Shift:
|
||||
{
|
||||
TimelineViewWindow &window = view_window();
|
||||
|
||||
const int64_t scale = window.get_time_scale();
|
||||
gavl_time_t offset = beginShiftTimeOffset +
|
||||
(int64_t)(mouseDownX - event->x) * scale;
|
||||
window.set_time_offset(offset);
|
||||
|
||||
set_vertical_offset((int)(mouseDownY - event->y) +
|
||||
beginShiftVerticalOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
// Forward the event to the tool
|
||||
tool->on_motion_notify_event(event);
|
||||
|
||||
// See if the track that we're hovering over has changed
|
||||
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);
|
||||
}
|
||||
|
||||
// Forward the event to the tool
|
||||
tool->on_motion_notify_event(event);
|
||||
|
||||
// See if the track that we're hovering over has changed
|
||||
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);
|
||||
|
||||
// false so that the message is passed up to the owner TimelineWidget
|
||||
return false;
|
||||
}
|
||||
|
|
@ -276,9 +285,12 @@ TimelineBody::on_motion_notify_event(GdkEventMotion *event)
|
|||
void
|
||||
TimelineBody::on_state_changed()
|
||||
{
|
||||
// Connect up some events
|
||||
view_window().changed_signal().connect(
|
||||
sigc::mem_fun(this, &TimelineBody::on_update_view) );
|
||||
if(timelineWidget.get_state())
|
||||
{
|
||||
// Connect up some events
|
||||
view_window().changed_signal().connect(
|
||||
sigc::mem_fun(this, &TimelineBody::on_update_view) );
|
||||
}
|
||||
|
||||
// Redraw
|
||||
queue_draw();
|
||||
|
|
@ -299,6 +311,9 @@ TimelineBody::draw_tracks(Cairo::RefPtr<Cairo::Context> cr)
|
|||
Cairo::Matrix view_matrix;
|
||||
cr->get_matrix(view_matrix);
|
||||
|
||||
// If the tree's empty that means there's no sequence root
|
||||
REQUIRE(!layout_tree.empty());
|
||||
|
||||
// Iterate drawing each track
|
||||
TimelineLayoutHelper::TrackTree::pre_order_iterator iterator;
|
||||
for(iterator = ++layout_tree.begin(); // ++ so we skip the sequence root
|
||||
|
|
@ -408,35 +423,39 @@ TimelineBody::draw_playback_point(Cairo::RefPtr<Cairo::Context> cr)
|
|||
// Prepare
|
||||
|
||||
shared_ptr<TimelineState> state = timelineWidget.get_state();
|
||||
REQUIRE(state);
|
||||
|
||||
const Allocation allocation = get_allocation();
|
||||
|
||||
const gavl_time_t point = state->get_playback_point();
|
||||
if(point == (gavl_time_t)GAVL_TIME_UNDEFINED)
|
||||
return;
|
||||
|
||||
const int x = view_window().time_to_x(point);
|
||||
|
||||
// Set source
|
||||
gdk_cairo_set_source_color(cr->cobj(), &playbackPointColour);
|
||||
cr->set_line_width(1);
|
||||
|
||||
// Draw
|
||||
if(x >= 0 && x < allocation.get_width())
|
||||
if(state)
|
||||
{
|
||||
cr->move_to(x + 0.5, 0);
|
||||
cr->line_to(x + 0.5, allocation.get_height());
|
||||
cr->stroke();
|
||||
const Allocation allocation = get_allocation();
|
||||
|
||||
const gavl_time_t point = state->get_playback_point();
|
||||
if(point == (gavl_time_t)GAVL_TIME_UNDEFINED)
|
||||
return;
|
||||
|
||||
const int x = view_window().time_to_x(point);
|
||||
|
||||
// Set source
|
||||
gdk_cairo_set_source_color(cr->cobj(), &playbackPointColour);
|
||||
cr->set_line_width(1);
|
||||
|
||||
// Draw
|
||||
if(x >= 0 && x < allocation.get_width())
|
||||
{
|
||||
cr->move_to(x + 0.5, 0);
|
||||
cr->line_to(x + 0.5, allocation.get_height());
|
||||
cr->stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimelineBody::begin_shift_drag()
|
||||
{
|
||||
dragType = Shift;
|
||||
beginShiftTimeOffset = view_window().get_time_offset();
|
||||
beginShiftVerticalOffset = get_vertical_offset();
|
||||
if(timelineWidget.get_state())
|
||||
{
|
||||
dragType = Shift;
|
||||
beginShiftTimeOffset = view_window().get_time_offset();
|
||||
beginShiftVerticalOffset = get_vertical_offset();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ private:
|
|||
|
||||
/**
|
||||
* A helper function to get the view window
|
||||
* @remarks This function must not be called unless the TimlineWidget
|
||||
* has a valid state.
|
||||
**/
|
||||
TimelineViewWindow& view_window() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -241,16 +241,20 @@ TimelineHeaderContainer::on_size_request (Requisition* requisition)
|
|||
|
||||
const TimelineLayoutHelper::TrackTree &layout_tree =
|
||||
timelineWidget.layoutHelper.get_layout_tree();
|
||||
|
||||
TimelineLayoutHelper::TrackTree::pre_order_iterator iterator;
|
||||
for(iterator = ++layout_tree.begin(); // ++ so that we skip the sequence root
|
||||
iterator != layout_tree.end();
|
||||
iterator++)
|
||||
|
||||
// Send a size request to all the children
|
||||
if(!layout_tree.empty())
|
||||
{
|
||||
Widget &widget =
|
||||
lookup_timeline_track(*iterator)->get_header_widget();
|
||||
if(widget.is_visible())
|
||||
widget.size_request();
|
||||
TimelineLayoutHelper::TrackTree::pre_order_iterator iterator;
|
||||
for(iterator = ++layout_tree.begin(); // ++ so that we skip the sequence root
|
||||
iterator != layout_tree.end();
|
||||
iterator++)
|
||||
{
|
||||
Widget &widget =
|
||||
lookup_timeline_track(*iterator)->get_header_widget();
|
||||
if(widget.is_visible())
|
||||
widget.size_request();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the output parameter:
|
||||
|
|
@ -348,45 +352,48 @@ TimelineHeaderContainer::layout_headers()
|
|||
timelineWidget.layoutHelper;
|
||||
const TimelineLayoutHelper::TrackTree &layout_tree =
|
||||
layout_helper.get_layout_tree();
|
||||
|
||||
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);
|
||||
|
||||
// Apply the allocation to the header
|
||||
widget.size_allocate (*header_rect);
|
||||
if(!widget.is_visible())
|
||||
{
|
||||
widget.show();
|
||||
headers_shown = true;
|
||||
}
|
||||
}
|
||||
else // No header rect, so the track must be hidden
|
||||
if(widget.is_visible())
|
||||
widget.hide();
|
||||
}
|
||||
|
||||
// If headers have been shown while we're dragging, the dragging
|
||||
// branch headers have to be brought back to the top again
|
||||
if(headers_shown && layout_helper.is_dragging_track())
|
||||
raise_recursive(layout_helper.get_dragging_track_iter());
|
||||
|
||||
// Repaint the background of our parenting
|
||||
queue_draw();
|
||||
if(!layout_tree.empty())
|
||||
{
|
||||
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);
|
||||
|
||||
// Apply the allocation to the header
|
||||
widget.size_allocate (*header_rect);
|
||||
if(!widget.is_visible())
|
||||
{
|
||||
widget.show();
|
||||
headers_shown = true;
|
||||
}
|
||||
}
|
||||
else // No header rect, so the track must be hidden
|
||||
if(widget.is_visible())
|
||||
widget.hide();
|
||||
}
|
||||
|
||||
// If headers have been shown while we're dragging, the dragging
|
||||
// branch headers have to be brought back to the top again
|
||||
if(headers_shown && layout_helper.is_dragging_track())
|
||||
raise_recursive(layout_helper.get_dragging_track_iter());
|
||||
|
||||
// Repaint the background of our parenting
|
||||
queue_draw();
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<timeline::Track>
|
||||
|
|
|
|||
|
|
@ -62,11 +62,14 @@ TimelineRuler::TimelineRuler(
|
|||
playbackPeriodArrowSize(10),
|
||||
playbackPeriodArrowStemSize(3),
|
||||
timelineWidget(timeline_widget)
|
||||
{
|
||||
// Connect event handlers
|
||||
view_window().changed_signal().connect(
|
||||
sigc::mem_fun(this, &TimelineRuler::on_update_view) );
|
||||
|
||||
{
|
||||
if(timelineWidget.get_state())
|
||||
{
|
||||
// Connect event handlers
|
||||
view_window().changed_signal().connect(
|
||||
sigc::mem_fun(this, &TimelineRuler::on_update_view) );
|
||||
}
|
||||
|
||||
// Install style properties
|
||||
register_styles();
|
||||
}
|
||||
|
|
@ -109,41 +112,44 @@ TimelineRuler::on_expose_event(GdkEventExpose* event)
|
|||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
if(!window)
|
||||
return false;
|
||||
|
||||
// Prepare to render via cairo
|
||||
const Allocation allocation = get_allocation();
|
||||
|
||||
Cairo::RefPtr<Context> cr = window->create_cairo_context();
|
||||
REQUIRE(cr);
|
||||
|
||||
// Draw the ruler
|
||||
if(!rulerImage)
|
||||
|
||||
if(timelineWidget.get_state())
|
||||
{
|
||||
// We have no cached rendering - it must be redrawn
|
||||
// but do we need ro allocate a new image?
|
||||
if(!rulerImage ||
|
||||
rulerImage->get_width() != allocation.get_width() ||
|
||||
rulerImage->get_height() != allocation.get_height())
|
||||
rulerImage = ImageSurface::create(FORMAT_RGB24,
|
||||
allocation.get_width(), allocation.get_height());
|
||||
// Prepare to render via cairo
|
||||
const Allocation allocation = get_allocation();
|
||||
|
||||
Cairo::RefPtr<Context> cr = window->create_cairo_context();
|
||||
REQUIRE(cr);
|
||||
|
||||
// Draw the ruler
|
||||
if(!rulerImage)
|
||||
{
|
||||
// We have no cached rendering - it must be redrawn
|
||||
// but do we need ro allocate a new image?
|
||||
if(!rulerImage ||
|
||||
rulerImage->get_width() != allocation.get_width() ||
|
||||
rulerImage->get_height() != allocation.get_height())
|
||||
rulerImage = ImageSurface::create(FORMAT_RGB24,
|
||||
allocation.get_width(), allocation.get_height());
|
||||
|
||||
ENSURE(rulerImage);
|
||||
|
||||
Cairo::RefPtr<Context> image_cairo = Context::create(rulerImage);
|
||||
ENSURE(image_cairo);
|
||||
|
||||
ENSURE(rulerImage);
|
||||
|
||||
Cairo::RefPtr<Context> image_cairo = Context::create(rulerImage);
|
||||
ENSURE(image_cairo);
|
||||
draw_ruler(image_cairo, allocation);
|
||||
}
|
||||
|
||||
draw_ruler(image_cairo, allocation);
|
||||
// Draw the cached ruler image
|
||||
cr->set_source(rulerImage, 0, 0);
|
||||
cr->paint();
|
||||
|
||||
// Draw the overlays
|
||||
draw_mouse_chevron(cr, allocation);
|
||||
draw_selection(cr, allocation);
|
||||
draw_playback_period(cr, allocation);
|
||||
draw_playback_point(cr, allocation);
|
||||
}
|
||||
|
||||
// Draw the cached ruler image
|
||||
cr->set_source(rulerImage, 0, 0);
|
||||
cr->paint();
|
||||
|
||||
// Draw the overlays
|
||||
draw_mouse_chevron(cr, allocation);
|
||||
draw_selection(cr, allocation);
|
||||
draw_playback_period(cr, allocation);
|
||||
draw_playback_point(cr, allocation);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -153,11 +159,14 @@ TimelineRuler::on_button_press_event(GdkEventButton* event)
|
|||
{
|
||||
REQUIRE(event != NULL);
|
||||
|
||||
if(event->button == 1)
|
||||
{
|
||||
pinnedDragTime = view_window().x_to_time(event->x);
|
||||
isDragging = true;
|
||||
}
|
||||
if(timelineWidget.get_state())
|
||||
{
|
||||
if(event->button == 1)
|
||||
{
|
||||
pinnedDragTime = view_window().x_to_time(event->x);
|
||||
isDragging = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -212,13 +221,15 @@ void
|
|||
TimelineRuler::set_leading_x(const int x)
|
||||
{
|
||||
shared_ptr<TimelineState> state = timelineWidget.get_state();
|
||||
REQUIRE(state);
|
||||
|
||||
const gavl_time_t time = view_window().x_to_time(x);
|
||||
if(time > pinnedDragTime)
|
||||
state->set_playback_period(pinnedDragTime, time);
|
||||
else
|
||||
state->set_playback_period(time, pinnedDragTime);
|
||||
if(state)
|
||||
{
|
||||
const gavl_time_t time = view_window().x_to_time(x);
|
||||
if(time > pinnedDragTime)
|
||||
state->set_playback_period(pinnedDragTime, time);
|
||||
else
|
||||
state->set_playback_period(time, pinnedDragTime);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Reference in a new issue