lumiera_/src/gui/panels/timeline-panel.cpp

417 lines
10 KiB
C++
Raw Normal View History

/*
2008-04-19 21:31:27 +02:00
timeline-panel.cpp - Implementation of the timeline panel
2010-12-17 23:28:49 +01:00
Copyright (C) Lumiera.org
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
2010-12-17 23:28:49 +01:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
2010-12-17 23:28:49 +01:00
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.
2010-12-17 23:28:49 +01:00
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.
2010-12-17 23:28:49 +01:00
* *****************************************************/
#include "gui/gtk-lumiera.hpp"
#include "gui/panels/timeline-panel.hpp"
#include "gui/widgets/timeline/timeline-zoom-scale.hpp"
#include "gui/workspace/workspace-window.hpp"
#include "gui/model/project.hpp"
#include "gui/controller/controller.hpp"
#include "lib/util.hpp"
#include <boost/foreach.hpp>
2008-08-16 23:06:46 +02:00
2008-05-22 20:19:04 +02:00
using namespace Gtk;
using namespace sigc;
using namespace gui::widgets;
using namespace gui::widgets::timeline;
using namespace gui::model;
2008-05-22 20:19:04 +02:00
using std::tr1::shared_ptr;
using std::tr1::weak_ptr;
using util::contains;
namespace gui {
namespace panels {
const int TimelinePanel::ZoomToolSteps = 2; // 2 seems comfortable
TimelinePanel::TimelinePanel (workspace::PanelManager &panel_manager,
GdlDockItem *dock_item)
: Panel(panel_manager, dock_item, get_title(), get_stock_id())
, timeCode("sequence_clock", "timecode_widget", true)
, previousButton(Stock::MEDIA_PREVIOUS)
, rewindButton(Stock::MEDIA_REWIND)
, playPauseButton(Stock::MEDIA_PLAY)
, stopButton(Stock::MEDIA_STOP)
, forwardButton(Stock::MEDIA_FORWARD)
, nextButton(Stock::MEDIA_NEXT)
, arrowTool(Gtk::StockID("tool_arrow"))
, iBeamTool(Gtk::StockID("tool_i_beam"))
, zoomIn(Stock::ZOOM_IN)
, zoomOut(Stock::ZOOM_OUT)
2011-10-06 19:38:10 +02:00
, zoomScale()
, updatingToolbar(false)
, currentTool(timeline::Arrow)
2009-03-27 15:26:08 +01:00
{
2008-11-22 20:08:12 +01:00
// Hook up notifications
2009-04-13 17:11:50 +02:00
get_project().get_sequences().signal_changed().connect(mem_fun(this,
&TimelinePanel::on_sequence_list_changed));
2008-11-22 20:08:12 +01:00
2009-03-27 15:26:08 +01:00
// Setup the sequence chooser
sequenceChooserModel = Gtk::ListStore::create(sequenceChooserColumns);
ENSURE(sequenceChooserModel);
2009-03-21 17:57:56 +01:00
2009-03-27 15:26:08 +01:00
sequenceChooser.set_model(sequenceChooserModel);
sequenceChooser.pack_start(sequenceChooserColumns.nameColumn);
2009-03-21 17:57:56 +01:00
sequenceChooser.show_all();
2009-03-27 15:26:08 +01:00
sequenceChooserChangedConnection = sequenceChooser.signal_changed().
connect( sigc::mem_fun(*this, &TimelinePanel::on_sequence_chosen) );
panelBar.pack_start(sequenceChooser, PACK_SHRINK);
// Setup the toolbar
toolbar.append(timeCode);
2008-10-07 22:17:29 +02:00
2008-09-12 21:55:54 +02:00
toolbar.append(previousButton);
toolbar.append(rewindButton);
2008-10-07 22:17:29 +02:00
toolbar.append(playPauseButton,
mem_fun(this, &TimelinePanel::on_play_pause));
toolbar.append(stopButton,
mem_fun(this, &TimelinePanel::on_stop));
2008-09-12 21:55:54 +02:00
toolbar.append(forwardButton);
toolbar.append(nextButton);
2008-08-30 15:00:47 +02:00
2010-12-24 23:17:28 +01:00
toolbar.append(separator1);
2008-08-30 15:00:47 +02:00
2008-10-07 22:17:29 +02:00
toolbar.append(arrowTool,
mem_fun(this, &TimelinePanel::on_arrow_tool));
toolbar.append(iBeamTool,
mem_fun(this, &TimelinePanel::on_ibeam_tool));
2008-09-12 21:55:54 +02:00
2010-12-24 23:17:28 +01:00
toolbar.append(separator2);
2008-09-12 21:55:54 +02:00
2011-10-06 19:38:10 +02:00
toolbar.append(zoomScale);
zoomScale.signal_zoom().
connect(mem_fun(this,&TimelinePanel::on_zoom));
2009-03-09 21:45:50 +01:00
toolbar.show_all();
2009-03-21 17:57:56 +01:00
panelBar.pack_start(toolbar, PACK_SHRINK);
2010-07-07 04:07:15 +02:00
// Setup tooltips
sequenceChooser .set_tooltip_text(_("Change sequence"));
2010-07-07 04:07:15 +02:00
previousButton .set_tooltip_text(_("To beginning"));
rewindButton .set_tooltip_text(_("Rewind"));
playPauseButton .set_tooltip_text(_("Start playback"));
stopButton .set_tooltip_text(_("Stop playback"));
forwardButton .set_tooltip_text(_("Forward"));
nextButton .set_tooltip_text(_("To end"));
arrowTool .set_tooltip_text(_("Selection tool"));
iBeamTool .set_tooltip_text(_("Marker tool"));
zoomIn .set_tooltip_text(_("Zoom in"));
zoomOut .set_tooltip_text(_("Zoom out"));
zoomScale .set_tooltip_text(_("Adjust timeline zoom scale"));
2010-07-07 04:07:15 +02:00
2009-03-27 15:26:08 +01:00
// Setup the timeline widget
shared_ptr<Sequence> sequence ///////////////////////////////TICKET #796 : should use std::tr1::shared_ptr instead of boost
2009-04-13 17:11:50 +02:00
= *get_project().get_sequences().begin();
2009-03-27 15:26:08 +01:00
timelineWidget.reset(new TimelineWidget(load_state(sequence)));
pack_start(*timelineWidget, PACK_EXPAND_WIDGET);
// since TimelineWidget is now initialised,
// wire the zoom slider to react on timeline state changes
zoomScale.wireTimelineState (timelineWidget->get_state(),
timelineWidget->state_changed_signal());
2008-08-30 15:00:47 +02:00
// Set the initial UI state
2009-03-21 17:57:56 +01:00
update_sequence_chooser();
update_tool_buttons();
update_zoom_buttons();
show_time (Time::ZERO);
}
const char*
TimelinePanel::get_title()
{
return _("Timeline");
}
2009-04-04 19:53:09 +02:00
const gchar*
TimelinePanel::get_stock_id()
{
return "panel_timeline";
}
2008-10-07 22:17:29 +02:00
void
TimelinePanel::on_play_pause()
2009-01-17 17:12:11 +01:00
{
2008-10-07 22:17:29 +02:00
if(!is_playing())
{
play();
}
else
{
pause();
2008-10-07 22:17:29 +02:00
}
update_playback_buttons();
}
void
TimelinePanel::on_stop()
{
2009-04-13 17:11:50 +02:00
get_controller().get_playback_controller().stop();
update_playback_buttons();
2008-10-07 22:17:29 +02:00
}
void
TimelinePanel::on_arrow_tool()
{
set_tool(timeline::Arrow);
}
void
TimelinePanel::on_ibeam_tool()
{
set_tool(timeline::IBeam);
}
2011-10-06 19:38:10 +02:00
void
TimelinePanel::on_zoom(double time_scale_ratio)
2011-10-06 19:38:10 +02:00
{
REQUIRE(timelineWidget);
timelineWidget->zoom_view(time_scale_ratio);
2011-10-06 19:38:10 +02:00
}
void
TimelinePanel::on_zoom_in()
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
timelineWidget->zoom_view(ZoomToolSteps);
update_zoom_buttons();
}
void
TimelinePanel::on_zoom_out()
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
timelineWidget->zoom_view(-ZoomToolSteps);
update_zoom_buttons();
}
2008-08-16 23:06:46 +02:00
void
TimelinePanel::on_mouse_hover(Time)
2008-08-16 23:06:46 +02:00
{
/* do nothing */
2008-10-07 22:17:29 +02:00
}
void
TimelinePanel::on_playback_period_drag_released()
{
//----- TEST CODE - this needs to set the playback point via the
// real backend
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
timelineWidget->get_state()->setPlaybackPoint(
timelineWidget->get_state()->getPlaybackPeriodStart());
2008-10-07 22:17:29 +02:00
//----- END TEST CODE
play();
}
2008-11-22 20:08:12 +01:00
void
TimelinePanel::on_sequence_list_changed()
{
2009-03-21 17:57:56 +01:00
update_sequence_chooser();
}
void
2009-03-27 15:26:08 +01:00
TimelinePanel::on_sequence_chosen()
2009-03-21 17:57:56 +01:00
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
2009-03-21 17:57:56 +01:00
2009-03-27 15:26:08 +01:00
Gtk::TreeIter iter = sequenceChooser.get_active();
if(iter)
2009-03-21 17:57:56 +01:00
{
2009-03-27 15:26:08 +01:00
weak_ptr<Sequence> sequence_ptr =
(*iter)[sequenceChooserColumns.sequenceColumn];
2009-03-27 15:26:08 +01:00
shared_ptr<Sequence> sequence(sequence_ptr.lock());
2009-03-27 15:26:08 +01:00
if(sequence)
{
shared_ptr<timeline::TimelineState> old_state(
timelineWidget->get_state());
REQUIRE(old_state);
if(sequence != old_state->get_sequence())
timelineWidget->set_state(load_state(sequence));
}
2009-03-21 17:57:56 +01:00
}
2009-03-27 15:26:08 +01:00
update_zoom_buttons();
2008-11-22 20:08:12 +01:00
}
void
2009-03-27 15:26:08 +01:00
TimelinePanel::update_sequence_chooser()
{
2009-03-27 15:26:08 +01:00
REQUIRE(sequenceChooserModel);
// Block the event handler
sequenceChooserChangedConnection.block();
2009-03-27 15:26:08 +01:00
// Repopulate the sequence chooser
sequenceChooserModel->clear();
shared_ptr<timeline::TimelineState> state =
timelineWidget->get_state();
BOOST_FOREACH( shared_ptr< model::Sequence > sequence,
2009-04-13 17:11:50 +02:00
get_project().get_sequences() )
{
2009-03-27 15:26:08 +01:00
Gtk::TreeIter iter = sequenceChooserModel->append();
Gtk::TreeModel::Row row = *iter;
row[sequenceChooserColumns.sequenceColumn] = sequence;
row[sequenceChooserColumns.nameColumn] = sequence->get_name();
if(state && state->get_sequence() == sequence)
2009-03-27 15:26:08 +01:00
sequenceChooser.set_active(iter);
}
2008-11-22 20:08:12 +01:00
// If there's no active sequence, then unselect
if(!state)
sequenceChooser.set_active(-1);
2009-03-27 15:26:08 +01:00
// Unblock the event handler
sequenceChooserChangedConnection.unblock();
}
2008-10-07 22:17:29 +02:00
void
TimelinePanel::update_playback_buttons()
{
2010-07-07 04:07:15 +02:00
if (is_playing())
{
playPauseButton.set_stock_id(Stock::MEDIA_PAUSE);
playPauseButton.set_tooltip_text("Pause playback");
}
else
{
playPauseButton.set_stock_id(Stock::MEDIA_PLAY);
playPauseButton.set_tooltip_text("Start playback");
}
2008-08-16 23:06:46 +02:00
}
void
TimelinePanel::update_tool_buttons()
{
if(!updatingToolbar)
2008-12-06 20:12:18 +01:00
{
updatingToolbar = true;
arrowTool.set_active(currentTool == timeline::Arrow);
iBeamTool.set_active(currentTool == timeline::IBeam);
updatingToolbar = false;
}
}
void
TimelinePanel::update_zoom_buttons()
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
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);
}
}
2008-10-07 22:17:29 +02:00
void
TimelinePanel::play()
{
2009-04-13 17:11:50 +02:00
get_controller().get_playback_controller().play();
}
void
TimelinePanel::pause()
2008-10-07 22:17:29 +02:00
{
2009-04-13 17:11:50 +02:00
get_controller().get_playback_controller().pause();
2008-10-07 22:17:29 +02:00
}
bool
2009-04-13 17:11:50 +02:00
TimelinePanel::is_playing()
2008-10-07 22:17:29 +02:00
{
2009-04-13 17:11:50 +02:00
return get_controller().get_playback_controller().is_playing();
2008-10-07 22:17:29 +02:00
}
void
TimelinePanel::set_tool(timeline::ToolType tool)
{
2009-03-27 15:26:08 +01:00
REQUIRE(timelineWidget);
if(updatingToolbar) return;
2009-03-27 15:26:08 +01:00
currentTool = tool;
timelineWidget->set_tool(tool);
update_tool_buttons();
}
2008-08-30 15:00:47 +02:00
void
TimelinePanel::show_time(Time time)
2008-08-30 15:00:47 +02:00
{
////////////TODO integrate the Timecode Widget
// timeIndicator.set_text(string(time));
2008-08-30 15:00:47 +02:00
}
2008-10-07 22:17:29 +02:00
bool
TimelinePanel::on_frame()
{
/////////TODO what happens here??
2008-10-07 22:17:29 +02:00
return true;
}
2009-03-27 15:26:08 +01:00
shared_ptr<timeline::TimelineState>
TimelinePanel::load_state(weak_ptr<Sequence> sequence)
{
/* state exists */
2009-03-27 15:26:08 +01:00
if(contains(timelineStates, sequence))
return timelineStates[sequence];
2009-03-27 15:26:08 +01:00
shared_ptr<Sequence> shared_sequence = sequence.lock();
if(shared_sequence)
{
shared_ptr<timeline::TimelineState> new_state(
new timeline::TimelineState(shared_sequence));
timelineStates[sequence] = new_state;
return new_state;
}
2009-03-27 15:26:08 +01:00
return shared_ptr< timeline::TimelineState >();
}
}} // namespace gui::panels