Added support for audacity style playback period, and added some

documentation
This commit is contained in:
Joel Holdsworth 2008-08-30 22:34:26 +01:00
parent 885704f0f8
commit 49f87b28bb
7 changed files with 278 additions and 23 deletions

View file

@ -140,16 +140,15 @@ style "timeline_ruler" = "default_base"
gtkmm__CustomObject_TimelineRuler::min_division_width = 100
gtkmm__CustomObject_TimelineRuler::mouse_chevron_size = 5
gtkmm__CustomObject_TimelineRuler::selection_chevron_size = 5
gtkmm__CustomObject_TimelineRuler::playback_arrow_colour = "#2D2D90"
gtkmm__CustomObject_TimelineRuler::playback_arrow_alpha = 0.5
gtkmm__CustomObject_TimelineRuler::playback_arrow_size = 10
gtkmm__CustomObject_TimelineRuler::playback_arrow_stem_size = 3
}
style "timeline_header_base" = "default_base"
{
# fg[NORMAL] = { 0.77, 0.77, 0.72 }
# bg[NORMAL] = { 0.18, 0.19, 0.22 }
# bg[ACTIVE] = { 0.20, 0.20, 0.20 }
# bg[PRELIGHT] = { 0.20, 0.20, 0.20 }
# bg[INSENSITIVE] = { 0.20, 0.20, 0.20 }
# bg[SELECTED] = { 0.20, 0.20, 0.20 }
}
class "gtkmm__CustomObject_TimelineBody" style:highest "timeline_body"

View file

@ -46,6 +46,8 @@ TimelineWidget::TimelineWidget() :
verticalAdjustment(0, 0, 0),
selectionStart(0),
selectionEnd(0),
playbackPeriodStart(0),
playbackPeriodEnd(0),
horizontalScroll(horizontalAdjustment),
verticalScroll(verticalAdjustment)
{
@ -183,8 +185,12 @@ TimelineWidget::get_selection_end() const
}
void
TimelineWidget::set_selection(gavl_time_t start, gavl_time_t end)
TimelineWidget::set_selection(gavl_time_t start, gavl_time_t end,
bool reset_playback_period)
{
REQUIRE(ruler != NULL);
REQUIRE(body != NULL);
if(start < end)
{
selectionStart = start;
@ -196,6 +202,46 @@ TimelineWidget::set_selection(gavl_time_t start, gavl_time_t end)
selectionStart = end;
selectionEnd = start;
}
if(reset_playback_period)
{
playbackPeriodStart = selectionStart;
playbackPeriodEnd = selectionEnd;
}
ruler->queue_draw();
body->queue_draw();
}
gavl_time_t
TimelineWidget::get_playback_period_start() const
{
return playbackPeriodStart;
}
gavl_time_t
TimelineWidget::get_playback_period_end() const
{
return playbackPeriodEnd;
}
void
TimelineWidget::set_playback_period(gavl_time_t start, gavl_time_t end)
{
REQUIRE(ruler != NULL);
REQUIRE(body != NULL);
if(start < end)
{
playbackPeriodStart = start;
playbackPeriodEnd = end;
}
else
{
// The period is back-to-front, flip it round
playbackPeriodStart = end;
playbackPeriodEnd = start;
}
ruler->queue_draw();
body->queue_draw();

View file

@ -120,8 +120,30 @@ public:
/**
* Sets the period of the selection.
* @param start The start time.
* @param end The end time.
* @param reset_playback_period Specifies whether to set the playback
* period to the same as this new selection.
*/
void set_selection(gavl_time_t start, gavl_time_t end);
void set_selection(gavl_time_t start, gavl_time_t end,
bool reset_playback_period = true);
/**
* Gets the time at which the playback period begins.
*/
gavl_time_t get_playback_period_start() const;
/**
* Gets the time at which the playback period ends.
*/
gavl_time_t get_playback_period_end() const;
/**
* Sets the playback period.
* @param start The start time.
* @param end The end time.
*/
void set_playback_period(gavl_time_t start, gavl_time_t end);
/**
* Gets the type of the tool currently active.
@ -169,6 +191,8 @@ protected:
// Selection State
gavl_time_t selectionStart;
gavl_time_t selectionEnd;
gavl_time_t playbackPeriodStart;
gavl_time_t playbackPeriodEnd;
int totalHeight;

View file

@ -349,23 +349,18 @@ TimelineBody::register_styles() const
{
GtkWidgetClass *klass = GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj()));
gtk_widget_class_install_style_property(
GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj())),
g_param_spec_boxed("background",
"Track Background",
gtk_widget_class_install_style_property(klass,
g_param_spec_boxed("background", "Track Background",
"The background colour of timeline tracks",
GDK_TYPE_COLOR, G_PARAM_READABLE));
gtk_widget_class_install_style_property(
GTK_WIDGET_CLASS(G_OBJECT_GET_CLASS(gobj())),
g_param_spec_boxed("selection",
"End lines of a selection",
gtk_widget_class_install_style_property(klass,
g_param_spec_boxed("selection", "End lines of a selection",
"The colour of selection limit lines",
GDK_TYPE_COLOR, G_PARAM_READABLE));
gtk_widget_class_install_style_property(klass,
g_param_spec_float("selection_alpha",
"Selection Alpha",
g_param_spec_float("selection_alpha", "Selection Alpha",
"The transparency of the selection marque.",
0, 1.0, 0.5, G_PARAM_READABLE));
}

View file

@ -90,6 +90,7 @@ IBeamTool::on_button_press_event(GdkEventButton* event)
Tool::on_button_press_event(event);
TimelineWidget *timeline_widget = get_timeline_widget();
REQUIRE(timeline_widget != NULL);
if(event->button == 1)
{
@ -181,12 +182,16 @@ void
IBeamTool::set_leading_x(const int x)
{
TimelineWidget *timeline_widget = get_timeline_widget();
REQUIRE(timeline_widget != NULL);
const bool set_playback_period = dragType == Selection;
const gavl_time_t time = timeline_widget->x_to_time(x);
if(time > pinnedDragTime)
timeline_widget->set_selection(pinnedDragTime, time);
timeline_widget->set_selection(
pinnedDragTime, time, set_playback_period);
else
timeline_widget->set_selection(time, pinnedDragTime);
timeline_widget->set_selection(
time, pinnedDragTime, set_playback_period);
}
void

View file

@ -45,6 +45,8 @@ namespace timeline {
TimelineRuler::TimelineRuler(
lumiera::gui::widgets::TimelineWidget *timeline_widget) :
Glib::ObjectBase("TimelineRuler"),
isDragging(false),
pinnedDragTime(0),
mouseChevronOffset(0),
annotationHorzMargin(0),
annotationVertMargin(0),
@ -54,6 +56,9 @@ TimelineRuler::TimelineRuler(
minDivisionWidth(100),
mouseChevronSize(5),
selectionChevronSize(5),
playbackArrowAlpha(0.5f),
playbackArrowSize(10),
playbackArrowStemSize(3),
timelineWidget(timeline_widget)
{
REQUIRE(timelineWidget != NULL);
@ -82,7 +87,10 @@ TimelineRuler::on_realize()
Widget::on_realize();
// Set event notifications
add_events(Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK);
add_events(Gdk::POINTER_MOTION_MASK |
Gdk::SCROLL_MASK |
Gdk::BUTTON_PRESS_MASK |
Gdk::BUTTON_RELEASE_MASK);
// Load styles
read_styles();
@ -130,16 +138,47 @@ TimelineRuler::on_expose_event(GdkEventExpose* event)
// Draw the overlays
draw_mouse_chevron(cr, allocation);
draw_selection(cr, allocation);
draw_playback_period(cr, allocation);
return true;
}
bool
TimelineRuler::on_button_press_event(GdkEventButton* event)
{
REQUIRE(event != NULL);
if(event->button == 1)
{
pinnedDragTime = timelineWidget->x_to_time(event->x);
isDragging = true;
}
return true;
}
bool
TimelineRuler::on_button_release_event(GdkEventButton* event)
{
REQUIRE(event != NULL);
if(event->button == 1)
isDragging = false;
return true;
}
bool
TimelineRuler::on_motion_notify_event(GdkEventMotion *event)
{
REQUIRE(event != NULL);
set_mouse_chevron_offset(event->x);
if(isDragging)
set_leading_x(event->x);
return true;
}
@ -162,6 +201,18 @@ TimelineRuler::on_size_allocate(Gtk::Allocation& allocation)
rulerImage.clear(); // The widget has changed size - redraw
}
void
TimelineRuler::set_leading_x(const int x)
{
REQUIRE(timelineWidget != NULL);
const gavl_time_t time = timelineWidget->x_to_time(x);
if(time > pinnedDragTime)
timelineWidget->set_playback_period(pinnedDragTime, time);
else
timelineWidget->set_playback_period(time, pinnedDragTime);
}
void
TimelineRuler::draw_ruler(Cairo::RefPtr<Cairo::Context> cr,
const Gdk::Rectangle ruler_rect)
@ -299,6 +350,74 @@ TimelineRuler::draw_selection(Cairo::RefPtr<Cairo::Context> cr,
}
}
void
TimelineRuler::draw_playback_period(Cairo::RefPtr<Cairo::Context> cr,
const Gdk::Rectangle ruler_rect)
{
REQUIRE(cr);
REQUIRE(ruler_rect.get_width() > 0);
REQUIRE(ruler_rect.get_height() > 0);
REQUIRE(timelineWidget != NULL);
// Calculate coordinates
const float halfSize = playbackArrowSize / 2;
const float a = timelineWidget->time_to_x(
timelineWidget->playbackPeriodStart) + 1 + 0.5f;
const float b = a + halfSize;
const float d = timelineWidget->time_to_x(
timelineWidget->playbackPeriodEnd) + 0.5f;
const float c = d - halfSize;
const float e = ruler_rect.get_height() - playbackArrowSize - 0.5f;
const float f = e + (playbackArrowSize - playbackArrowStemSize) / 2;
const float g = ruler_rect.get_height() - playbackArrowSize / 2
- 0.5f;
const float i = ruler_rect.get_height() - 0.5f;
const float h = i - (playbackArrowSize - playbackArrowStemSize) / 2;
// Contruct the path
if(d - a >= playbackArrowSize)
{
// Draw an arrow: <===>
cr->move_to(a, g);
cr->line_to(b, e);
cr->line_to(b, f);
cr->line_to(c, f);
cr->line_to(c, e);
cr->line_to(d, g);
cr->line_to(c, i);
cr->line_to(c, h);
cr->line_to(b, h);
cr->line_to(b, i);
cr->line_to(a, g);
}
else
{
// The space is too narrow for an arrow, so draw calipers: > <
cr->move_to(a, g);
cr->rel_line_to(-halfSize, -halfSize);
cr->rel_line_to(0, playbackArrowSize);
cr->move_to(d, g);
cr->rel_line_to(halfSize, -halfSize);
cr->rel_line_to(0, playbackArrowSize);
}
// Fill
cr->set_source_rgba(
(float)playbackArrowColour.red / 0xFFFF,
(float)playbackArrowColour.green / 0xFFFF,
(float)playbackArrowColour.blue / 0xFFFF,
playbackArrowAlpha);
cr->fill_preserve();
// Stroke
gdk_cairo_set_source_color(cr->cobj(), &playbackArrowColour);
cr->set_line_width(1);
cr->stroke();
}
gavl_time_t
TimelineRuler::calculate_major_spacing() const
{
@ -402,6 +521,29 @@ TimelineRuler::register_styles() const
"Selection Chevron Size",
"The height of the selection chevrons in pixels.",
0, G_MAXINT, 5, G_PARAM_READABLE));
gtk_widget_class_install_style_property(klass,
g_param_spec_boxed("playback_arrow_colour",
"End lines of a selection",
"The colour of selection limit lines",
GDK_TYPE_COLOR, G_PARAM_READABLE));
gtk_widget_class_install_style_property(klass,
g_param_spec_float("playback_arrow_alpha", "Playback Arrow Alpha",
"The transparency of the playback period arrow.",
0, 1.0, 0.5, G_PARAM_READABLE));
gtk_widget_class_install_style_property(klass,
g_param_spec_int("playback_arrow_size",
"Playback Arrow Head Size",
"The height of the playback arrow head in pixels.",
0, G_MAXINT, 10, G_PARAM_READABLE));
gtk_widget_class_install_style_property(klass,
g_param_spec_int("playback_arrow_stem_size",
"Playback Arrow Stem Size",
"The height of the playback arrow head in pixels.",
0, G_MAXINT, 3, G_PARAM_READABLE));
}
void
@ -415,6 +557,13 @@ TimelineRuler::read_styles()
get_style_property("min_division_width", minDivisionWidth);
get_style_property("mouse_chevron_size", mouseChevronSize);
get_style_property("selection_chevron_size", selectionChevronSize);
playbackArrowColour = WindowManager::read_style_colour_property(
*this, "playback_arrow_colour", 0, 0, 0);
get_style_property("playback_arrow_alpha", playbackArrowAlpha);
get_style_property("playback_arrow_size", playbackArrowSize);
get_style_property("playback_arrow_stem_size",
playbackArrowStemSize);
}
} // namespace timeline

View file

@ -59,14 +59,34 @@ protected:
bool on_expose_event(GdkEventExpose *event);
/**
* The event handler for button press events.
*/
bool on_button_press_event(GdkEventButton* event);
/**
* The event handler for button release events.
*/
bool on_button_release_event(GdkEventButton* event);
/**
* The event handler for mouse move events.
*/
bool on_motion_notify_event(GdkEventMotion *event);
void on_size_request(Gtk::Requisition *requisition);
void on_size_allocate(Gtk::Allocation& allocation);
/* ===== Internals ===== */
private:
/* ===== Internal Methods ===== */
/**
* As the user drags, this function is called to update the position
* of the moving end of the playback period.
*/
void set_leading_x(const int x);
void draw_ruler(Cairo::RefPtr<Cairo::Context> cairo,
const Gdk::Rectangle ruler_rect);
@ -75,6 +95,9 @@ private:
void draw_selection(Cairo::RefPtr<Cairo::Context> cr,
const Gdk::Rectangle ruler_rect);
void draw_playback_period(Cairo::RefPtr<Cairo::Context> cr,
const Gdk::Rectangle ruler_rect);
gavl_time_t calculate_major_spacing() const;
@ -83,6 +106,16 @@ private:
void read_styles();
private:
// State values
bool isDragging;
/**
* During a selection drag, one end of the selection is moving with
* the mouse, the other is pinned. pinnedDragTime specifies the time
* of that point.
*/
gavl_time_t pinnedDragTime;
// Indicated values
int mouseChevronOffset;
@ -96,7 +129,11 @@ private:
int minDivisionWidth;
int mouseChevronSize;
int selectionChevronSize;
GdkColor playbackArrowColour;
float playbackArrowAlpha;
int playbackArrowSize;
int playbackArrowStemSize;
// Owner
lumiera::gui::widgets::TimelineWidget *timelineWidget;