WIP: Added preliminary track dragging support

This commit is contained in:
Joel Holdsworth 2009-01-10 21:25:05 +00:00
parent 27ffbd1875
commit 542af7cc80
4 changed files with 132 additions and 23 deletions

View file

@ -149,12 +149,17 @@ bool TimelineHeaderContainer::on_button_press_event (
{
case 1: // Left Click
// Did the user press the button on an expander?
if(hoveringExpander != NULL)
if(hoveringExpander)
{
// Yes? The prime for a release event
clickedExpander = hoveringExpander;
queue_draw();
}
else if(hoveringTrack) // Is the user hovering on a track
{
}
break;
case 3: // Right Click
@ -186,6 +191,8 @@ bool TimelineHeaderContainer::on_button_press_event (
bool TimelineHeaderContainer::on_button_release_event (
GdkEventButton* event)
{
TimelineLayoutHelper &layout = timelineWidget.layoutHelper;
// Did the user release the button on an expander?
if(clickedExpander != NULL)
{
@ -194,8 +201,12 @@ bool TimelineHeaderContainer::on_button_release_event (
clickedExpander->get_expanded() ? Track::Collapse : Track::Expand);
clickedExpander.reset();
timelineWidget.layoutHelper.update_layout();
layout.update_layout();
}
// Has the user been dragging?
if(layout.get_dragging_track())
layout.end_dragging_track();
return Container::on_button_release_event(event);
}
@ -204,31 +215,50 @@ bool TimelineHeaderContainer::on_motion_notify_event (
GdkEventMotion* event)
{
REQUIRE(event != NULL);
// Hit test the rectangle
shared_ptr<timeline::Track> header =
timelineWidget.layoutHelper.header_from_point(
Gdk::Point(event->x, event->y));
if(header)
{
const optional<Gdk::Rectangle> rect =
get_expander_button_rectangle(header);
const bool result = Container::on_motion_notify_event(event);
const Gdk::Point point(event->x, event->y);
TimelineLayoutHelper &layout = timelineWidget.layoutHelper;
// Are we beginning to drag a header?
if((event->state & GDK_BUTTON1_MASK) && hoveringTrack &&
!hoveringExpander && !layout.get_dragging_track())
{
layout.begin_dragging_track(hoveringTrack);
return result;
}
REQUIRE(rect);
// Are we currently dragging?
if(layout.get_dragging_track())
{
layout.drag_to_point(point);
return result;
}
// Hit test the rectangle
hoveringTrack = layout.header_from_point(point);
if(hoveringTrack)
{
const optional<Gdk::Rectangle> rect =
get_expander_button_rectangle(hoveringTrack);
REQUIRE(rect);
// Are we hovering on the expander?
if(event->x >= rect->get_x() &&
event->x < rect->get_x() + rect->get_width() &&
event->y >= rect->get_y() &&
event->y < rect->get_y() + rect->get_height())
{
hoveringExpander = header;
queue_draw();
}
}
// Are we hovering on the expander?
if(event->x >= rect->get_x() &&
event->x < rect->get_x() + rect->get_width() &&
event->y >= rect->get_y() &&
event->y < rect->get_y() + rect->get_height())
{
hoveringExpander = hoveringTrack;
queue_draw();
}
else hoveringExpander.reset();
}
return Container::on_motion_notify_event(event);
return result;
}
void

View file

@ -221,6 +221,8 @@ private:
Gtk::Menu contextMenu;
//----- User Interaction State -----//
boost::shared_ptr<timeline::Track> hoveringTrack;
boost::shared_ptr<timeline::Track> hoveringExpander;
boost::shared_ptr<timeline::Track> clickedExpander;

View file

@ -132,6 +132,71 @@ TimelineLayoutHelper::track_from_y(int y)
return shared_ptr<timeline::Track>();
}
void
TimelineLayoutHelper::begin_dragging_track(
boost::shared_ptr<timeline::Track> track)
{
REQUIRE(track);
draggingTrack = track;
g_message("begin_dragging_track");
// Find the track in the tree
const shared_ptr<model::Track> model_track = track->get_model_track();
REQUIRE(model_track);
for(draggingTrackIter = layoutTree.begin();
draggingTrackIter != layoutTree.end();
draggingTrackIter++)
{
if(*draggingTrackIter == model_track)
break;
}
}
void
TimelineLayoutHelper::end_dragging_track()
{
draggingTrack.reset();
clone_tree_from_sequence();
update_layout();
}
boost::shared_ptr<timeline::Track>
TimelineLayoutHelper::get_dragging_track() const
{
return draggingTrack;
}
void
TimelineLayoutHelper::drag_to_point(Gdk::Point point)
{
// Apply the scroll offset
point.set_y(point.get_y() + timelineWidget.get_y_scroll_offset());
// Search the headers
TrackTree::pre_order_iterator iterator;
for(iterator = ++layoutTree.begin(); // ++ so we miss out the root sequence
iterator != layoutTree.end();
iterator++)
{
// Hit test the rectangle
const weak_ptr<timeline::Track> track =
lookup_timeline_track(*iterator);
const Gdk::Rectangle &rect = headerBoxes[track];
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())
{
// Relocate the header
draggingTrackIter = layoutTree.move_after(
iterator, draggingTrackIter);
update_layout();
return;
}
}
}
int
TimelineLayoutHelper::get_total_height() const
{

View file

@ -127,6 +127,14 @@ public:
**/
boost::shared_ptr<timeline::Track> track_from_y(int y);
void begin_dragging_track(boost::shared_ptr<timeline::Track> track);
void end_dragging_track();
boost::shared_ptr<timeline::Track> get_dragging_track() const;
void drag_to_point(Gdk::Point point);
/**
* Returns the total height in pixels of the layout tree.
* @remarks This function is only on returns a valid value fter
@ -228,6 +236,10 @@ protected:
**/
int totalHeight;
TrackTree::pre_order_iterator draggingTrackIter;
boost::shared_ptr<timeline::Track> draggingTrack;
/**
* The connection to the animation timer.
* @see begin_animation()