HOWTO
for F in $(find src -type f \( -name '*.cpp' -or -name '*.hpp' \) -exec egrep -q '§§§' {} \; -print);
do D=$(basename $F);
sed -r -e"s/§§§/$D/" $F ;
done
268 lines
6.9 KiB
C++
268 lines
6.9 KiB
C++
/*
|
|
TimelineIBeamTool - Selection marking tool
|
|
|
|
Copyright (C) Lumiera.org
|
|
2008, Joel Holdsworth <joel@airwebreathe.org.uk>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
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.
|
|
|
|
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.
|
|
|
|
* *****************************************************/
|
|
|
|
|
|
/** @file timeline-ibeam-tool.cpp
|
|
** TODO timeline-ibeam-tool.cpp
|
|
*/
|
|
|
|
|
|
#include "gui/widget/timeline/timeline-ibeam-tool.hpp"
|
|
#include "gui/widget/timeline-widget.hpp"
|
|
#include "lib/time/mutation.hpp"
|
|
|
|
using namespace gui::widget;
|
|
|
|
using lib::time::Mutation;
|
|
using std::shared_ptr;
|
|
|
|
|
|
namespace gui {
|
|
namespace widget {
|
|
namespace timeline {
|
|
|
|
/* ===== Constants ===== */
|
|
|
|
const int IBeamTool::DragZoneWidth = 5;
|
|
const int IBeamTool::ScrollSlideRateDivisor = 16;
|
|
const int IBeamTool::ScrollSlideEventInterval = 40;
|
|
|
|
|
|
|
|
/* ===== Implementation ===== */
|
|
|
|
IBeamTool::IBeamTool (TimelineBody& timeline_body)
|
|
: Tool(timeline_body)
|
|
, selectionControl()
|
|
, dragType(None)
|
|
, pinnedDragTime()
|
|
, scrollSlideRate(0)
|
|
{
|
|
// Connect the timlinebody selection to the selectionControl
|
|
get_state()->setSelectionControl (selectionControl);
|
|
}
|
|
|
|
|
|
IBeamTool::~IBeamTool()
|
|
{
|
|
selectionControl.disconnect();
|
|
end_scroll_slide();
|
|
}
|
|
|
|
|
|
ToolType
|
|
IBeamTool::get_type() const
|
|
{
|
|
return IBeam;
|
|
}
|
|
|
|
|
|
Glib::RefPtr<Gdk::Cursor>
|
|
IBeamTool::get_cursor() const
|
|
{
|
|
// Are we dragging?
|
|
// Make the cursor indicate that type of drag
|
|
switch(dragType)
|
|
{
|
|
case Selection:
|
|
return Gdk::Cursor::create(Gdk::XTERM);
|
|
case GrabStart:
|
|
return Gdk::Cursor::create(Gdk::LEFT_SIDE);
|
|
case GrabEnd:
|
|
return Gdk::Cursor::create(Gdk::RIGHT_SIDE);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Are we hovering over the ends of the selection?
|
|
// Make the cursor indicate that the user can resize the selection.
|
|
if(is_mouse_in_start_drag_zone())
|
|
return Gdk::Cursor::create(Gdk::LEFT_SIDE);
|
|
if(is_mouse_in_end_drag_zone())
|
|
return Gdk::Cursor::create(Gdk::RIGHT_SIDE);
|
|
|
|
// By default return an I-beam cursor
|
|
return Gdk::Cursor::create(Gdk::XTERM);
|
|
}
|
|
|
|
|
|
void
|
|
IBeamTool::on_button_press_event (GdkEventButton* event)
|
|
{
|
|
Tool::on_button_press_event(event);
|
|
shared_ptr<TimelineState> state = get_state();
|
|
|
|
if (event->button == 1)
|
|
{
|
|
const Time time = state->getViewWindow().x_to_time(event->x);
|
|
|
|
if (is_mouse_in_start_drag_zone())
|
|
{
|
|
// User began to drag the start of the selection
|
|
dragType = GrabStart;
|
|
pinnedDragTime = state->getSelectionEnd();
|
|
}
|
|
else
|
|
if (is_mouse_in_end_drag_zone())
|
|
{
|
|
// User began to drag the end of the selection
|
|
dragType = GrabEnd;
|
|
pinnedDragTime = state->getSelectionStart();
|
|
}
|
|
else
|
|
{
|
|
// User began the drag in clear space, begin a Select drag
|
|
dragType = Selection;
|
|
pinnedDragTime = time;
|
|
selectionControl (TimeSpan(time, Duration::NIL));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
IBeamTool::on_button_release_event (GdkEventButton* event)
|
|
{
|
|
// Ensure that we can't get a mixed up state
|
|
ENSURE(isDragging == (dragType != None));
|
|
ENSURE(isDragging == (event->button == 1));
|
|
|
|
if (event->button == 1)
|
|
{
|
|
set_leading_x(event->x);
|
|
|
|
// Terminate the drag now the button is released
|
|
dragType = None;
|
|
|
|
// If there was a scroll slide, terminate it
|
|
end_scroll_slide();
|
|
|
|
// Apply the cursor - there are some corner cases where it can
|
|
// change by the end of the drag
|
|
apply_cursor();
|
|
}
|
|
|
|
Tool::on_button_release_event(event);
|
|
}
|
|
|
|
|
|
void
|
|
IBeamTool::on_motion_notify_event (GdkEventMotion *event)
|
|
{
|
|
Tool::on_motion_notify_event(event);
|
|
|
|
// Ensure that we can't get a mixed up state
|
|
ENSURE(isDragging == (dragType != None));
|
|
|
|
if (isDragging)
|
|
{
|
|
set_leading_x(event->x);
|
|
|
|
// Is the mouse out of bounds? if so we must begin scrolling
|
|
const Gdk::Rectangle body_rect(get_body_rectangle());
|
|
if (event->x < 0)
|
|
begin_scroll_slide(
|
|
event->x / ScrollSlideRateDivisor);
|
|
else
|
|
if (event->x > body_rect.get_width())
|
|
begin_scroll_slide(
|
|
(event->x - body_rect.get_width()) / ScrollSlideRateDivisor);
|
|
else end_scroll_slide();
|
|
}
|
|
|
|
apply_cursor();
|
|
}
|
|
|
|
|
|
bool
|
|
IBeamTool::on_scroll_slide_timer()
|
|
{
|
|
const Gdk::Rectangle body_rect (get_body_rectangle());
|
|
view_window().shift_view (body_rect.get_width(), scrollSlideRate);
|
|
|
|
// Return true to keep the timer going
|
|
return true;
|
|
}
|
|
|
|
|
|
void
|
|
IBeamTool::set_leading_x (const int x)
|
|
{
|
|
shared_ptr<TimelineState> state = get_state();
|
|
|
|
// The line below needs handled differently now; ////////////TODO GTK-3
|
|
//
|
|
//const bool set_playback_period = dragType == Selection;
|
|
|
|
TimeVar newStartPoint (state->getViewWindow().x_to_time(x));
|
|
Offset selectionLength (pinnedDragTime, newStartPoint);
|
|
|
|
if (newStartPoint > pinnedDragTime)
|
|
newStartPoint=pinnedDragTime; // use the smaller one as selection start
|
|
|
|
selectionControl (TimeSpan (newStartPoint, Duration(selectionLength)));
|
|
}
|
|
|
|
|
|
void
|
|
IBeamTool::begin_scroll_slide (int scroll_slide_rate)
|
|
{
|
|
scrollSlideRate = scroll_slide_rate;
|
|
if (!scrollSlideEvent.connected())
|
|
scrollSlideEvent = Glib::signal_timeout().connect(
|
|
sigc::mem_fun(this, &IBeamTool::on_scroll_slide_timer),
|
|
ScrollSlideEventInterval);
|
|
}
|
|
|
|
|
|
void
|
|
IBeamTool::end_scroll_slide()
|
|
{
|
|
scrollSlideRate = 0;
|
|
if (scrollSlideEvent.connected())
|
|
scrollSlideEvent.disconnect();
|
|
}
|
|
|
|
|
|
bool
|
|
IBeamTool::is_mouse_in_start_drag_zone() const
|
|
{
|
|
const int start_x = view_window().time_to_x(
|
|
get_state()->getSelectionStart());
|
|
|
|
return (mousePoint.get_x() <= start_x &&
|
|
mousePoint.get_x() > start_x - DragZoneWidth);
|
|
}
|
|
|
|
|
|
bool
|
|
IBeamTool::is_mouse_in_end_drag_zone() const
|
|
{
|
|
const int end_x = view_window().time_to_x(
|
|
get_state()->getSelectionEnd());
|
|
|
|
return (mousePoint.get_x() >= end_x &&
|
|
mousePoint.get_x() < end_x + DragZoneWidth);
|
|
}
|
|
|
|
|
|
}}}// namespace gui::widget::timeline
|