WIP: make clips selectable in timeline
This commit is contained in:
parent
5c4992310e
commit
7f615d734f
16 changed files with 246 additions and 129 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ===== */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ public:
|
|||
*/
|
||||
~TimelineBody();
|
||||
|
||||
TimelineWidget&
|
||||
getTimelineWidget () const;
|
||||
|
||||
/**
|
||||
* Returns the type of the currently selected timeline tool.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue