Added remove track feature

This commit is contained in:
Joel Holdsworth 2008-12-20 14:31:11 +00:00
parent bc2fdc40e9
commit 992cd4d77b
10 changed files with 204 additions and 17 deletions

View file

@ -289,13 +289,20 @@ TimelineWidget::update_tracks()
{
REQUIRE(sequence);
// 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 header container
ASSERT(headerContainer != NULL);
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,
@ -316,9 +323,6 @@ TimelineWidget::create_timeline_tracks()
BOOST_FOREACH(shared_ptr<model::Track> child,
sequence->get_child_tracks())
create_timeline_tracks_from_branch(child);
headerContainer->show_all_children();
body->queue_draw();
}
void
@ -351,14 +355,59 @@ TimelineWidget::create_timeline_track_from_model_track(
// Choose a corresponding timeline track class from the model track's
// class
if(typeid(*model_track) == typeid(model::ClipTrack))
return shared_ptr<timeline::Track>(new timeline::ClipTrack());
return shared_ptr<timeline::Track>(new timeline::ClipTrack(*this));
else if(typeid(*model_track) == typeid(model::GroupTrack))
return shared_ptr<timeline::Track>(new timeline::GroupTrack());
return shared_ptr<timeline::Track>(new timeline::GroupTrack(*this));
ASSERT(NULL); // Unknown track type;
return shared_ptr<timeline::Track>();
}
void
TimelineWidget::remove_orphaned_tracks()
{
REQUIRE(sequence);
REQUIRE(headerContainer != NULL);
REQUIRE(body != NULL);
std::map<boost::shared_ptr<model::Track>,
boost::shared_ptr<timeline::Track> >
orphan_track_map(trackMap);
// Remove all tracks which are still present in the sequence
BOOST_FOREACH(shared_ptr<model::Track> child,
sequence->get_child_tracks())
search_orphaned_tracks_in_branch(child, orphan_track_map);
// orphan_track_map now contains all the orphaned tracks
// Remove them
std::pair<shared_ptr<model::Track>, shared_ptr<timeline::Track> >
pair;
BOOST_FOREACH( pair, orphan_track_map )
{
ENSURE(pair.first)
trackMap.erase(pair.first);
}
}
void
TimelineWidget::search_orphaned_tracks_in_branch(
boost::shared_ptr<model::Track> model_track,
std::map<boost::shared_ptr<model::Track>,
boost::shared_ptr<timeline::Track> > &orphan_track_map)
{
REQUIRE(model_track);
// Is the timeline UI still present?
if(contains(orphan_track_map, model_track))
orphan_track_map.erase(model_track);
// Recurse to child tracks
BOOST_FOREACH(shared_ptr<model::Track> child,
model_track->get_child_tracks())
search_orphaned_tracks_in_branch(child, orphan_track_map);
}
shared_ptr<timeline::Track>
TimelineWidget::lookup_timeline_track(
shared_ptr<model::Track> model_track) const
@ -378,7 +427,32 @@ TimelineWidget::lookup_timeline_track(
ENSURE(iterator->second != NULL);
return iterator->second;
}
boost::shared_ptr<model::Track>
TimelineWidget::lookup_model_track(
const timeline::Track *timeline_track) const
{
REQUIRE(sequence);
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>();
}
void
TimelineWidget::update_scroll()
{

View file

@ -191,10 +191,21 @@ private:
* @return The timeline track created, or an empty shared_ptr if
* model_track has an unreckognised type (this is an error condition).
**/
static boost::shared_ptr<timeline::Track>
boost::shared_ptr<timeline::Track>
create_timeline_track_from_model_track(
boost::shared_ptr<model::Track> model_track);
/**
* Removes any UI tracks which no longer have corresponding model
* tracks present in the sequence.
**/
void remove_orphaned_tracks();
void search_orphaned_tracks_in_branch(
boost::shared_ptr<model::Track> model_track,
std::map<boost::shared_ptr<model::Track>,
boost::shared_ptr<timeline::Track> > &orphan_track_map);
/**
* Looks up a timeline UI track in trackMap that corresponds to a
* given model_track.
@ -205,6 +216,17 @@ 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 ----- //
@ -305,6 +327,7 @@ protected:
friend class timeline::Tool;
friend class timeline::ArrowTool;
friend class timeline::IBeamTool;
friend class timeline::Track;
};
} // namespace widgets

View file

@ -29,7 +29,8 @@ namespace gui {
namespace widgets {
namespace timeline {
ClipTrack::ClipTrack()
ClipTrack::ClipTrack(TimelineWidget &timeline_widget) :
Track(timeline_widget)
{
}

View file

@ -41,7 +41,7 @@ class TimelineViewWindow;
class ClipTrack : public timeline::Track
{
public:
ClipTrack();
ClipTrack(TimelineWidget &timeline_widget);
void draw_track(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;

View file

@ -28,7 +28,8 @@ namespace gui {
namespace widgets {
namespace timeline {
GroupTrack::GroupTrack()
GroupTrack::GroupTrack(TimelineWidget &timeline_widget) :
Track(timeline_widget)
{
}

View file

@ -36,7 +36,7 @@ namespace timeline {
class GroupTrack : public timeline::Track
{
public:
GroupTrack();
GroupTrack(TimelineWidget &timeline_widget);
void draw_track(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* constwindow)

View file

@ -150,11 +150,25 @@ bool TimelineHeaderContainer::on_button_press_event (
break;
case 3: // Right Click
// Popup the context menu
contextMenu.popup(event->button, event->time);
break;
{
// Popup the context menu
shared_ptr<Track> header = header_from_point(
Gdk::Point(event->x, event->y));
// Are we hovering on a header?
if(header)
{
// Yes - show the header's context menu
header->show_header_context_menu(
event->button, event->time);
}
else
{
// No - show the default context menu
contextMenu.popup(event->button, event->time);
}
break;
}
}
return true;
@ -239,6 +253,12 @@ TimelineHeaderContainer::forall_vfunc(gboolean /* include_internals */,
}
}
void
TimelineHeaderContainer::on_remove(Widget* widget)
{
// Do nothing - this is just to keep Gtk::Container happy
}
bool
TimelineHeaderContainer::on_expose_event(GdkEventExpose *event)
{
@ -477,6 +497,25 @@ TimelineHeaderContainer::draw_header_decoration(
draw_header_decoration(child, clip_rect);
}
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)

View file

@ -118,6 +118,12 @@ private:
**/
void forall_vfunc(gboolean include_internals, GtkCallback callback,
gpointer callback_data);
/**
* An event handler that is called when a widget is removed from the
* container.
**/
void on_remove(Widget* widget);
/* ===== Events ===== */
private:
@ -193,6 +199,9 @@ 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
@ -297,6 +306,8 @@ private:
* in pixels.
**/
int expand_button_size;
friend class timeline::Track;
};
} // namespace timeline

View file

@ -24,15 +24,18 @@
#include <gtk/gtktoolbar.h>
#include "timeline-track.hpp"
#include "../timeline-widget.hpp"
#include "../../window-manager.hpp"
using namespace boost;
using namespace Gtk;
namespace gui {
namespace widgets {
namespace timeline {
Track::Track() :
Track::Track(TimelineWidget &timeline_widget) :
timelineWidget(timeline_widget),
expanded(true),
enableButton(Gtk::StockID("track_enabled")),
lockButton(Gtk::StockID("track_unlocked"))
@ -54,6 +57,14 @@ Track::Track() :
headerWidget.pack_start(titleBox, PACK_SHRINK);
headerWidget.pack_start(buttonBar, PACK_SHRINK);
// Setup the context menu
Menu::MenuList& menu_list = contextMenu.items();
menu_list.push_back( Menu_Helpers::MenuElem(_("_Add Track"),
sigc::mem_fun(timelineWidget,
&TimelineWidget::on_add_track_command) ) );
menu_list.push_back( Menu_Helpers::MenuElem(_("_Remove Track"),
sigc::mem_fun(this, &Track::on_remove_track) ) );
}
Gtk::Widget&
@ -80,6 +91,23 @@ Track::set_expanded(bool expanded)
this->expanded = expanded;
}
void
Track::show_header_context_menu(guint button, guint32 time)
{
contextMenu.popup(button, time);
}
void
Track::on_remove_track()
{
shared_ptr<model::Track> model_track =
timelineWidget.lookup_model_track(this);
ASSERT(model_track);
ASSERT(timelineWidget.sequence);
timelineWidget.sequence->get_child_track_list().remove(model_track);
}
} // namespace timeline
} // namespace widgets
} // namespace gui

View file

@ -25,6 +25,7 @@
#include "../../gtk-lumiera.hpp"
#include "../../model/track.hpp"
#include "timeline-header-container.hpp"
#ifndef TIMELINE_TRACK_HPP
#define TIMELINE_TRACK_HPP
@ -38,7 +39,7 @@ class TimelineViewWindow;
class Track
{
public:
Track();
Track(TimelineWidget &timeline_widget);
Gtk::Widget& get_header_widget();
@ -47,12 +48,19 @@ public:
bool get_expanded() const;
void set_expanded(bool expanded);
void show_header_context_menu(guint button, guint32 time);
virtual void draw_track(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window)
const = 0;
private:
void on_remove_track();
private:
TimelineWidget &timelineWidget;
bool expanded;
@ -65,6 +73,8 @@ private:
Gtk::Entry titleBox;
Gtk::Toolbar buttonBar;
Gtk::Menu contextMenu;
};