WIP: make clips selectable in timeline

This commit is contained in:
Stefan Kangas 2011-01-02 16:57:14 +01:00 committed by Stefan Kangas
parent 5c4992310e
commit 7f615d734f
16 changed files with 246 additions and 129 deletions

View file

@ -48,6 +48,12 @@ namespace model {
return name;
}
bool
Clip::isPlayingAt(lumiera::Time position) const
{
return (begin <= position && end >= position);
}
void
Clip::setBegin(gavl_time_t begin)
{

View file

@ -26,6 +26,8 @@
#include <string>
#include "gui/gtk-lumiera.hpp"
#include "lib/lumitime.hpp"
// TODO: Remove once we get real measure of duration.
// This is here *only* for purposes of testing the GUI.
extern "C" {
@ -67,6 +69,12 @@ namespace model {
const std::string
getName() const;
/**
* Check whether or not the clip will be playing during the given time.
**/
bool
isPlayingAt(lumiera::Time position) const;
/**
* Sets the begin time of this clip.
* @param[in] begin The new begin time to set this clip to.

View file

@ -326,7 +326,7 @@ TimelineWidget::create_timeline_track_from_modelTrack(
void
TimelineWidget::remove_orphaned_tracks()
{
{
std::map<boost::shared_ptr<model::Track>,
boost::shared_ptr<timeline::Track> >
orphan_track_map(trackMap);

View file

@ -102,7 +102,8 @@ public:
*/
void set_tool(timeline::ToolType tool_type);
boost::shared_ptr<timeline::Track> get_hovering_track() const;
boost::shared_ptr<timeline::Track>
get_hovering_track() const;
public:
/* ===== Signals ===== */

View file

@ -26,41 +26,75 @@ namespace gui {
namespace widgets {
namespace timeline {
ArrowTool::ArrowTool(TimelineBody &timeline_body) :
Tool(timeline_body)
{
ArrowTool::ArrowTool(TimelineBody &timelineBody) :
Tool(timelineBody)
{
}
}
ToolType
ArrowTool::get_type() const
{
return Arrow;
}
ToolType
ArrowTool::get_type() const
{
return Arrow;
}
Gdk::Cursor
ArrowTool::get_cursor() const
{
return Gdk::Cursor(Gdk::LEFT_PTR);
}
Gdk::Cursor
ArrowTool::get_cursor() const
{
return Gdk::Cursor(Gdk::LEFT_PTR);
}
void
ArrowTool::on_button_press_event(GdkEventButton* event)
{
Tool::on_button_press_event(event);
}
void
ArrowTool::on_button_press_event(GdkEventButton* event)
{
REQUIRE (event != NULL);
Tool::on_button_press_event(event);
void
ArrowTool::on_button_release_event(GdkEventButton* event)
{
Tool::on_button_release_event(event);
}
// Convert the mouse click position to a Time
boost::shared_ptr<TimelineState> state = timelineBody.getTimelineWidget().get_state();
REQUIRE(state);
const TimelineViewWindow &window = state->get_view_window();
lumiera::Time tpoint = window.x_to_time(mousePoint.get_x());
void
ArrowTool::on_motion_notify_event(GdkEventMotion *event)
{
Tool::on_motion_notify_event(event);
}
// Get the clip, if any
boost::shared_ptr<timeline::Track> track = getHoveringTrack();
boost::shared_ptr<Clip> clip = track->getClipAt(tpoint);
// Nothing to do if there is no clip
if (clip == boost::shared_ptr<Clip>())
return;
clip->setSelected(true);
}
void
ArrowTool::on_button_release_event(GdkEventButton* event)
{
REQUIRE (event != NULL);
Tool::on_button_release_event(event);
boost::shared_ptr<timeline::Track> track =
getHoveringTrack();
}
void
ArrowTool::on_motion_notify_event(GdkEventMotion *event)
{
REQUIRE (event != NULL);
Tool::on_motion_notify_event(event);
// We do not need to do anything if we are not dragging
if (!isDragging)
return;
}
boost::shared_ptr<timeline::Track>
ArrowTool::getHoveringTrack ()
{
boost::shared_ptr<timeline::Track> track(
timelineBody.getTimelineWidget().get_hovering_track());
return track;
}
} // namespace timeline
} // namespace widgets

View file

@ -27,52 +27,63 @@
#define TIMELINE_ARROW_TOOL_HPP
#include <gtkmm.h>
#include "timeline-tool.hpp"
#include "gui/widgets/timeline-widget.hpp"
#include "timeline-body.hpp"
#include "timeline-track.hpp"
namespace gui {
namespace widgets {
namespace timeline {
/**
* A helper class to implement the timeline i-beam tool
*/
class ArrowTool : public Tool
{
public:
/**
* Constructor
* @param timeline_body The owner timeline body object
* A helper class to implement the timeline arrow tool
*/
ArrowTool(TimelineBody &timeline_body);
class ArrowTool : public Tool
{
public:
/**
* Constructor
* @param timelineBody The owner timeline body object
*/
ArrowTool(TimelineBody &timelineBody);
/**
* Gets the type of tool represented by this class
*/
ToolType get_type() const;
/**
* Gets the type of tool represented by this class
*/
ToolType get_type() const;
protected:
protected:
/**
* Gets the cursor to display for this tool at this moment.
*/
Gdk::Cursor get_cursor() const;
/**
* Gets the cursor to display for this tool at this moment.
*/
Gdk::Cursor get_cursor() const;
protected:
/**
* The event handler for button press events.
*/
void on_button_press_event(GdkEventButton* event);
/**
* The event handler for button press events.
*/
void on_button_press_event(GdkEventButton* event);
/**
* The event handler for button release events.
*/
void on_button_release_event(GdkEventButton* event);
/**
* The event handler for button release events.
*/
void on_button_release_event(GdkEventButton* event);
/**
* The event handler for mouse move events.
*/
void on_motion_notify_event(GdkEventMotion *event);
};
/**
* The event handler for mouse move events.
*/
void on_motion_notify_event(GdkEventMotion *event);
private:
boost::shared_ptr<timeline::Track>
getHoveringTrack ();
bool selectionRectangleActive;
};
} // namespace timeline
} // namespace widgets

View file

@ -69,6 +69,12 @@ TimelineBody::~TimelineBody()
WARN_IF(!tool, gui, "An invalid tool pointer is unexpected here");
}
TimelineWidget&
TimelineBody::getTimelineWidget () const
{
return timelineWidget;
}
ToolType
TimelineBody::get_tool() const
{

View file

@ -65,6 +65,9 @@ public:
*/
~TimelineBody();
TimelineWidget&
getTimelineWidget () const;
/**
* Returns the type of the currently selected timeline tool.
*/

View file

@ -76,6 +76,21 @@ namespace timeline {
}
}
boost::shared_ptr<timeline::Clip>
ClipTrack::getClipAt(lumiera::Time position) const
{
std::pair<shared_ptr<model::Clip>, shared_ptr<timeline::Clip> >
pair;
BOOST_FOREACH (pair, clipMap)
{
if (pair.first->isPlayingAt(position))
return pair.second;
}
// Nothing found
return boost::shared_ptr<timeline::Clip>();
}
//// private methods
void

View file

@ -50,10 +50,19 @@ namespace timeline {
boost::shared_ptr<model::ClipTrack> track);
/**
*
* Draw the track in the timeline.
**/
void draw_track(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;
void
draw_track(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;
/**
* Gets the clip that is occupying the given time. If there is no track, return a NULL
* pointer.
* @param the given time
**/
boost::shared_ptr<timeline::Clip>
getClipAt(lumiera::Time position) const;
private:

View file

@ -26,54 +26,60 @@ namespace gui {
namespace widgets {
namespace timeline {
Clip::Clip(boost::shared_ptr<model::Clip> clip)
: modelClip(clip),
selected(false)
{
REQUIRE(modelClip);
Clip::Clip(boost::shared_ptr<model::Clip> clip)
: modelClip(clip),
selected(false)
{
REQUIRE(modelClip);
// TODO: Connect signals
//modelClip->signalNameChanged().connect(mem_fun(this,
// &Clip::onNameChanged);
}
// TODO: Connect signals
//modelClip->signalNameChanged().connect(mem_fun(this,
// &Clip::onNameChanged);
}
void
Clip::draw_clip(Cairo::RefPtr<Cairo::Context> cr,
TimelineViewWindow* const window) const
{
REQUIRE(cr);
REQUIRE(window);
REQUIRE(modelClip);
void
Clip::draw_clip(Cairo::RefPtr<Cairo::Context> cr,
TimelineViewWindow* const window) const
{
REQUIRE(cr);
REQUIRE(window);
REQUIRE(modelClip);
int x = window->time_to_x(modelClip->getBegin());
int width = window->time_to_x(
modelClip->getEnd()) - window->time_to_x(modelClip->getBegin());
int x = window->time_to_x(modelClip->getBegin());
int width = window->time_to_x(
modelClip->getEnd()) - window->time_to_x(modelClip->getBegin());
// Draw a rectangle for the clip
cr->rectangle(x, 1, width, 100-2);
// TODO: get height from the Timeline::Track
// Draw a rectangle for the clip
cr->rectangle(x, 1, width, 100-2);
// TODO: get height from the Timeline::Track
if (selected)
cr->set_source(Cairo::SolidPattern::create_rgb (0.3, 0.3, 0.3));
else
cr->set_source(Cairo::SolidPattern::create_rgb (0.4, 0.4, 0.4));
cr->fill_preserve();
if (selected)
cr->set_source(Cairo::SolidPattern::create_rgb (0.4, 0.4, 0.8));
else
cr->set_source(Cairo::SolidPattern::create_rgb (0.4, 0.4, 0.4));
cr->fill_preserve();
cr->set_source_rgb(0.25, 0.25, 0.25);
cr->stroke();
cr->set_source_rgb(0.25, 0.25, 0.25);
cr->stroke();
// Show the clip name
cr->rectangle(x, 1, width, 100-2);
cr->clip();
// Show the clip name
cr->rectangle(x, 1, width, 100-2);
cr->clip();
cr->move_to (x + 3, 12);
cr->set_source_rgb (1.0, 1.0, 1.0);
cr->move_to (x + 3, 12);
cr->set_source_rgb (1.0, 1.0, 1.0);
cr->set_font_size (9);
cr->show_text (modelClip->getName());
cr->set_font_size (9);
cr->show_text (modelClip->getName());
// TODO: Show thumbnails for clip
}
// TODO: Show thumbnails for clip
}
void
Clip::setSelected(bool selected)
{
this->selected = selected;
}
} // namespace timeline
} // namespace widgets

View file

@ -37,27 +37,29 @@ namespace gui {
namespace widgets {
namespace timeline {
class Clip : public model::Clip
{
public:
Clip(boost::shared_ptr<model::Clip> clip);
class Clip : public model::Clip
{
public:
Clip(boost::shared_ptr<model::Clip> clip);
void draw_clip(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;
void draw_clip(Cairo::RefPtr<Cairo::Context> cairo,
TimelineViewWindow* const window) const;
void
setSelected(bool state);
/**
* Sets the selected status of the clip.
**/
void
setSelected (bool state);
private:
private:
boost::shared_ptr<model::Clip> modelClip;
boost::shared_ptr<model::Clip> modelClip;
/**
* True when this clip is selected in the GUI.
*/
bool selected;
};
/**
* True when this clip is selected in the GUI.
*/
bool selected;
};
} // namespace timeline
} // namespace widgets

View file

@ -160,7 +160,7 @@ TimelineHeaderWidget::on_expose_event(GdkEventExpose *event)
REQUIRE(style);
REQUIRE(gdkWindow);
shared_ptr<model::Track> modelTrack = track.get_modelTrack();
shared_ptr<model::Track> modelTrack = track.getModelTrack();
REQUIRE(modelTrack);
// Get the header box

View file

@ -150,7 +150,7 @@ TimelineLayoutHelper::begin_dragging_track(
dragPoint.get_y() - rect.get_y());
const shared_ptr<model::Track> modelTrack =
dragging_track->get_modelTrack();
dragging_track->getModelTrack();
draggingTrackIter = iterator_from_track(modelTrack);
dragBranchHeight = measure_branch_height(draggingTrackIter);

View file

@ -103,7 +103,7 @@ Track::get_header_widget()
}
shared_ptr<model::Track>
Track::get_modelTrack() const
Track::getModelTrack() const
{
return modelTrack;
}
@ -120,6 +120,13 @@ Track::get_expanded() const
return expanded;
}
boost::shared_ptr<timeline::Clip>
Track::getClipAt(lumiera::Time) const
{
// Default implementation returns empty pointer
return boost::shared_ptr<timeline::Clip>();
}
void
Track::expand_collapse(ExpandDirection direction)
{

View file

@ -28,6 +28,7 @@
#include "gui/widgets/menu-button.hpp"
#include "gui/widgets/mini-button.hpp"
#include "gui/widgets/button-bar.hpp"
#include "timeline-clip.hpp"
#include "timeline-header-container.hpp"
#include "timeline-header-widget.hpp"
@ -75,7 +76,7 @@ public:
Gtk::Widget& get_header_widget();
boost::shared_ptr<model::Track>
get_modelTrack() const;
getModelTrack() const;
/**
* Return the visual height of the track in pixels.
@ -109,24 +110,24 @@ public:
* @see tick_expand_animation
**/
float get_expand_animation_state() const;
/**
* Gets whether the branch is animation.
* @return Returns true if the branch is animating, false if not.
**/
bool is_expand_animating() const;
/**
* When this track is being animated, tick_expand_animation must be
* called repeatedly to cause the animation to progress.
**/
**/
void tick_expand_animation();
/**
* Calculates the expander style, given the animation state.
**/
Gtk::ExpanderStyle get_expander_style() const;
/**
*
**/
@ -139,6 +140,14 @@ public:
TimelineViewWindow* const window)
const = 0;
/**
* Gets the clip that is occupying the given time.
* The default implementation simply returns an empty pointer.
* @param the given time
**/
virtual boost::shared_ptr<timeline::Clip>
getClipAt(lumiera::Time position) const;
private:
/**