Timeline: Replace the scrollbars with a new Pan/zoom widget.

This commit is contained in:
Jonathan Moore Liles 2012-11-01 03:35:04 -07:00
parent 455fb7e1b9
commit b50766b7da
7 changed files with 142 additions and 219 deletions

@ -1 +1 @@
Subproject commit f24b36393548f176a197a8a4aa05a79620b77ada Subproject commit ff7f8bdc4dfcbf6c34f5165a97f9a4368f69f6c8

View File

@ -430,6 +430,12 @@ Audio_Region::draw_fade ( const Fade &fade, Fade::fade_dir_e dir, bool line, int
fl_end_polygon(); fl_end_polygon();
} }
Fl_Color
Audio_Region::actual_box_color ( void ) const
{
return Audio_Region::inherit_track_color ? sequence()->track()->color() : _box_color;
}
void void
Audio_Region::draw_box( void ) Audio_Region::draw_box( void )
{ {
@ -437,7 +443,7 @@ Audio_Region::draw_box( void )
Fl_Color selection_color = _selection_color; Fl_Color selection_color = _selection_color;
Fl_Color color = Audio_Region::inherit_track_color ? sequence()->track()->color() : _box_color; Fl_Color color = actual_box_color();
color = fl_color_average( color, sequence()->color(), 0.75f ); color = fl_color_average( color, sequence()->color(), 0.75f );

View File

@ -164,6 +164,7 @@ public:
void split ( nframes_t where ); void split ( nframes_t where );
bool recording ( void ) const; bool recording ( void ) const;
virtual Fl_Color actual_box_color ( void ) const;
/* Engine */ /* Engine */
nframes_t read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) const; nframes_t read ( sample_t *buf, nframes_t pos, nframes_t nframes, int channel ) const;
nframes_t write ( nframes_t nframes ); nframes_t write ( nframes_t nframes );

View File

@ -1,107 +0,0 @@
/*******************************************************************************/
/* Copyright (C) 2008 Jonathan Moore Liles */
/* */
/* 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; see the file COPYING. If not,write to the Free Software */
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/
#pragma once
#include <FL/Fl.H>
#include <FL/Fl_Scrollbar.H>
#include <FL/Fl_Slider.H>
#include <stdio.h>
class Scalebar : public Fl_Scrollbar
{
int _zoom;
bool _zoom_changed;
int _zoom_min;
int _zoom_max;
void constrain ( void )
{
if ( _zoom > _zoom_max )
_zoom = _zoom_max;
else
if ( _zoom < _zoom_min )
_zoom = _zoom_min;
}
void maybe_do_callback ( int z )
{
if ( z != _zoom )
{
_zoom_changed = true;
do_callback();
_zoom_changed = false;
slider_size( w() / maximum() );
}
}
public:
Scalebar ( int X, int Y, int W, int H ) : Fl_Scrollbar ( X, Y, W, H )
{
_zoom = 1;
_zoom_min = 0;
_zoom_max = 4;
_zoom_changed = false;
step( 1 );
}
bool zoom_changed ( void ) const { return _zoom_changed; }
double zoom ( void ) const { return _zoom; }
void zoom ( int v ) { int z = _zoom ; _zoom = v; constrain(); maybe_do_callback( z ); }
// double value ( void ) const { return Fl_Slider::value(); }
void zoom_range ( int zmin, int zmax ) { _zoom_min = zmin; _zoom_max = zmax; }
void zoom_out ( void ) { int z = _zoom; ++_zoom; constrain(); maybe_do_callback( z ); }
void zoom_in ( void ) {int z = _zoom; --_zoom; constrain(); maybe_do_callback( z ); }
int
handle ( int m )
{
switch ( m )
{
case FL_MOUSEWHEEL:
{
if ( ! Fl::event_ctrl() )
return 0;
int d = Fl::event_dy();
double z = _zoom;
_zoom += d;
constrain();
maybe_do_callback( z );
return 1;
}
default:
return Fl_Scrollbar::handle( m );
}
}
};

View File

@ -160,6 +160,7 @@ protected:
public: public:
virtual ~Sequence_Widget ( ); virtual ~Sequence_Widget ( );
virtual Sequence_Widget *clone ( void ) const = 0; virtual Sequence_Widget *clone ( void ) const = 0;
@ -235,6 +236,7 @@ public:
virtual void box_color ( Fl_Color v ) { _box_color = v; } virtual void box_color ( Fl_Color v ) { _box_color = v; }
virtual Fl_Color selection_color ( void ) const { return _selection_color; } virtual Fl_Color selection_color ( void ) const { return _selection_color; }
virtual void selection_color ( Fl_Color v ) { _selection_color = v; } virtual void selection_color ( Fl_Color v ) { _selection_color = v; }
virtual Fl_Color actual_box_color ( void ) const { return box_color(); }
Sequence * sequence ( void ) const { return _sequence; } Sequence * sequence ( void ) const { return _sequence; }
void sequence ( Sequence *t ) { _sequence = t; } void sequence ( Sequence *t ) { _sequence = t; }

View File

@ -28,6 +28,7 @@
#include <FL/Fl_Widget.H> #include <FL/Fl_Widget.H>
#include <FL/fl_draw.H> #include <FL/fl_draw.H>
#include <FL/Fl_Menu_Button.H> #include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Panzoomer.H>
#include "Timeline.H" #include "Timeline.H"
#include "Tempo_Sequence.H" #include "Tempo_Sequence.H"
@ -35,12 +36,10 @@
#include "Cursor_Sequence.H" #include "Cursor_Sequence.H"
#include "Audio_Sequence.H" #include "Audio_Sequence.H"
#include "Control_Sequence.H" #include "Control_Sequence.H"
#include "Scalebar.H"
#include "Sequence.H" #include "Sequence.H"
#include "Annotation_Sequence.H" #include "Annotation_Sequence.H"
#include "Track.H" #include "Track.H"
#include "Transport.H" #include "Transport.H"
#include "Engine/Engine.H" // for lock() #include "Engine/Engine.H" // for lock()
#include "FL/menu_popup.H" #include "FL/menu_popup.H"
@ -227,18 +226,13 @@ Timeline::snapshot ( void )
} }
} }
/** recalculate the size of vertical scrolling area and inform scrollbar */
void
Timeline::adjust_vscroll ( void )
{
vscroll->value( _yposition, h() - rulers->h() - hscroll->h(), 0, pack_visible_height( tracks ) );
}
/** recalculate the size of horizontal scrolling area and inform scrollbar */ /** recalculate the size of horizontal scrolling area and inform scrollbar */
void void
Timeline::adjust_hscroll ( void ) Timeline::adjust_hscroll ( void )
{ {
hscroll->value( ts_to_x( xoffset ), tracks->w() - Track::width(), 0, ts_to_x( length() ) ); hscroll->y_value( hscroll->y_value(), h() - rulers->h() - hscroll->h(), 0, pack_visible_height( tracks ));
hscroll->x_value( ts_to_x( xoffset ), tracks->w() - Track::width(), 0, ts_to_x( length() ) );
} }
void void
@ -250,33 +244,31 @@ Timeline::cb_scroll ( Fl_Widget *w, void *v )
void void
Timeline::cb_scroll ( Fl_Widget *w ) Timeline::cb_scroll ( Fl_Widget *w )
{ {
if ( w == vscroll ) //adjust_hscroll();
{
tracks->position( tracks->x(), (rulers->y() + rulers->h()) - vscroll->value() );
yposition( vscroll->value() );
adjust_vscroll();
}
else
{
if ( hscroll->zoom_changed() ) if ( hscroll->zoom_changed() )
{ {
nframes_t under_mouse = x_to_offset( Fl::event_x() ); nframes_t under_mouse = x_to_offset( Fl::event_x() );
_fpp = hscroll->zoom(); _fpp = hscroll->zoom();
const int tw = tracks->w() - Track::width(); const int tw = tracks->w() - Track::width();
// hscroll->value( ts_to_x( xoffset ), tw, 0, ts_to_x( length() ) );
hscroll->value( max( 0, ts_to_x( under_mouse ) - ( Fl::event_x() - tracks->x() - Track::width() ) ), hscroll->x_value( ts_to_x( under_mouse ) );
tw, 0, ts_to_x( length() ) );
redraw(); redraw();
} }
xposition( hscroll->value() ); if ( _old_yposition != hscroll->y_value() )
{
tracks->position( tracks->x(), (rulers->y() + rulers->h()) - hscroll->y_value() );
damage( FL_DAMAGE_SCROLL );
}
if ( _old_xposition != x_to_ts( hscroll->x_value() ))
{
damage( FL_DAMAGE_SCROLL );
xposition( hscroll->x_value() );
} }
} }
@ -550,7 +542,6 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
box( FL_FLAT_BOX ); box( FL_FLAT_BOX );
xoffset = 0; xoffset = 0;
_yposition = 0;
_old_yposition = 0; _old_yposition = 0;
_old_xposition = 0; _old_xposition = 0;
@ -585,31 +576,26 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
menu_set_callback( const_cast<Fl_Menu_Item*>(menu->menu()), &Timeline::menu_cb, (void*)this ); menu_set_callback( const_cast<Fl_Menu_Item*>(menu->menu()), &Timeline::menu_cb, (void*)this );
{ {
Scalebar *o = new Scalebar( X, Y + H - 18, W - 18, 18 ); Fl_Panzoomer *o = new Fl_Panzoomer( X, Y + H - 100, W, 100 );
o->range( 0, 48000 * 300 ); // o->range( 0, 48000 * 300 );
// o->zoom_range( 1, 16384 ); // o->zoom_range( 1, 16384 );
// o->zoom_range( 1, 65536 << 4 ); // o->zoom_range( 1, 65536 << 4 );
o->zoom_range( 1, 20 ); o->zoom_range( 1, 20 );
o->zoom( 8 ); o->zoom( 8 );
o->box( FL_FLAT_BOX );
o->color( FL_BACKGROUND_COLOR );
o->type( FL_HORIZONTAL ); o->type( FL_HORIZONTAL );
o->callback( cb_scroll, this ); o->callback( cb_scroll, this );
o->draw_thumbnail_view_callback( &Timeline::draw_thumbnail_view, this );
hscroll = o; hscroll = o;
} }
{ {
Fl_Scrollbar *o = new Fl_Scrollbar( X + W - 18, Y, 18, H - 18 ); Fl_Pack *o = new Fl_Pack( X + Track::width(), Y, (W - Track::width()), H - hscroll->h(), "rulers" );
o->type( FL_VERTICAL );
o->callback( cb_scroll, this );
vscroll = o;
}
{
Fl_Pack *o = new Fl_Pack( X + Track::width(), Y, (W - Track::width()) - vscroll->w(), H - hscroll->h(), "rulers" );
o->type( Fl_Pack::VERTICAL ); o->type( Fl_Pack::VERTICAL );
{ {
@ -701,7 +687,7 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
// length() = x_to_ts( W ); // length() = x_to_ts( W );
{ {
Fl_Pack *o = new Fl_Pack( X, rulers->y() + rulers->h(), W - vscroll->w(), 1 ); Fl_Pack *o = new Fl_Pack( X, rulers->y() + rulers->h(), W, 1 );
o->type( Fl_Pack::VERTICAL ); o->type( Fl_Pack::VERTICAL );
o->spacing( 1 ); o->spacing( 1 );
@ -715,10 +701,9 @@ Timeline::Timeline ( int X, int Y, int W, int H, const char* L ) : BASE( X, Y, W
add( rulers ); add( rulers );
/* make sure scrollbars are on top */ /* make sure scrollbars are on top */
add( vscroll );
add( hscroll ); add( hscroll );
vscroll->range( 0, tracks->h() ); // vscroll->range( 0, tracks->h() );
redraw(); redraw();
@ -1082,13 +1067,12 @@ Timeline::resize ( int X, int Y, int W, int H )
BASE::resize( X, Y, W, H ); BASE::resize( X, Y, W, H );
/* why is this necessary? */ /* why is this necessary? */
rulers->resize( BX + Track::width(), BY, W - Track::width() - vscroll->w(), rulers->h() ); rulers->resize( BX + Track::width(), BY, W - Track::width(), rulers->h() );
/* why is THIS necessary? */ /* why is THIS necessary? */
hscroll->resize( BX, BY + H - 18, hscroll->w(), 18 ); hscroll->resize( BX, BY + H - 100, hscroll->w(), 100 );
vscroll->size( vscroll->w(), H - 18 );
tracks->resize( BX, BY + rulers->h(), W - vscroll->w(), H - vscroll->h() ); tracks->resize( BX, BY + rulers->h(), W, H - hscroll->h() );
} }
@ -1122,6 +1106,55 @@ Timeline::add_cursor ( Cursor_Point *o )
punch_cursor_track->add( o ); punch_cursor_track->add( o );
} }
void
Timeline::draw_thumbnail_view ( int X, int Y, int W, int H, void *v )
{
((Timeline*)v)->draw_thumbnail_view( X,Y,W,H );
}
void
Timeline::draw_thumbnail_view ( int X, int Y, int W, int H ) const
{
nframes_t sf = 0;
nframes_t ef = timeline->length();
double ty = Y;
for ( int i = 0; i < timeline->tracks->children(); i++ )
{
Track *t = (Track*)timeline->tracks->child( i );
Sequence *s = t->sequence();
if ( !s )
continue;
fl_color( FL_BLACK );
const double scale = (double)H / ( pack_visible_height( tracks ) );
// double th = (double)H / timeline->tracks->children();
const double th = t->h() * scale;
fl_line( X, ty,
X + W, ty );
for ( list <Sequence_Widget *>::const_iterator r = s->_widgets.begin();
r != s->_widgets.end(); ++r )
{
fl_rectf(
X + ( W * ( (double)(*r)->start() / ef ) ),
ty,
W * ( (double)(*r)->length() / ef ),
th,
(*r)->actual_box_color());
}
ty += th;
}
}
void void
Timeline::draw_cursors ( Cursor_Sequence *o ) const Timeline::draw_cursors ( Cursor_Sequence *o ) const
{ {
@ -1165,9 +1198,6 @@ Timeline::draw_cursors ( void ) const
void void
Timeline::draw ( void ) Timeline::draw ( void )
{ {
// resize_rulers();
int X, Y, W, H; int X, Y, W, H;
int bdx = 0; int bdx = 0;
@ -1178,13 +1208,40 @@ Timeline::draw ( void )
W = tracks->w() - bdw - 1; W = tracks->w() - bdw - 1;
H = tracks->h(); H = tracks->h();
adjust_vscroll(); adjust_hscroll();
hscroll->redraw();
#ifndef USE_UNOPTIMIZED_DRAWING int dx = ts_to_x( _old_xposition ) - ts_to_x( xoffset );
if ( ( damage() & FL_DAMAGE_ALL ) ) int dy = _old_yposition - hscroll->y_value();
#else
#warning Optimized drawing of timeline disabled. This will waste your CPU. int c = damage();
#endif
if ( c & FL_DAMAGE_SCROLL )
{
/* if ( dx && dy ) */
/* { */
/* /\* FIXME: scrolling both at once is... problematic *\/ */
/* c |= FL_DAMAGE_ALL; */
/* } */
/* else */
{
/* draw_child( *rulers ); */
Y = rulers->y() + rulers->h();
H = h() - rulers->h() - hscroll->h();
if ( dy )
fl_scroll( X, Y, Track::width(), H, 0, dy, draw_clip, this );
if ( dx )
fl_scroll( rulers->x(), rulers->y(), rulers->w(), rulers->h(), dx, 0, draw_clip, this );
fl_scroll( X + Track::width(), Y, W - Track::width(), H, dx, dy, draw_clip, this );
}
}
if ( c & FL_DAMAGE_ALL )
{ {
DMESSAGE( "complete redraw" ); DMESSAGE( "complete redraw" );
@ -1202,59 +1259,38 @@ Timeline::draw ( void )
fl_pop_clip(); fl_pop_clip();
draw_child( *hscroll ); draw_child( *hscroll );
draw_child( *vscroll );
redraw_overlay(); redraw_overlay();
goto done; goto done;
} }
if ( damage() & FL_DAMAGE_SCROLL ) if ( c & FL_DAMAGE_CHILD )
{
int dx = ts_to_x( _old_xposition ) - ts_to_x( xoffset );
int dy = _old_yposition - _yposition;
/* draw_child( *rulers ); */
if ( ! dy )
fl_scroll( rulers->x(), rulers->y(), rulers->w(), rulers->h(), dx, 0, draw_clip, this );
Y = rulers->y() + rulers->h();
H = h() - rulers->h() - hscroll->h();
if ( dy == 0 )
fl_scroll( X + Track::width(), Y, W - Track::width(), H, dx, dy, draw_clip, this );
else
fl_scroll( X, Y, W, H, dx, dy, draw_clip, this );
}
if ( damage() & FL_DAMAGE_CHILD )
{ {
fl_push_clip( rulers->x(), rulers->y(), rulers->w(), rulers->h() ); fl_push_clip( rulers->x(), rulers->y(), rulers->w(), rulers->h() );
update_child( *rulers ); update_child( *rulers );
fl_pop_clip(); fl_pop_clip();
if ( ! ( damage() & FL_DAMAGE_SCROLL ) ) /* if ( ! ( damage() & FL_DAMAGE_SCROLL ) ) */
{ /* { */
fl_push_clip( tracks->x(), rulers->y() + rulers->h(), tracks->w(), h() - rulers->h() - hscroll->h() ); fl_push_clip( tracks->x(), rulers->y() + rulers->h(), tracks->w(), h() - rulers->h() - hscroll->h() );
update_child( *tracks ); update_child( *tracks );
draw_cursors(); draw_cursors();
fl_pop_clip(); fl_pop_clip();
} /* } */
update_child( *hscroll ); update_child( *hscroll );
update_child( *vscroll );
} }
done: done:
/* hscroll->redraw(); */
/* update_child( *hscroll ); */
_old_xposition = xoffset; _old_xposition = xoffset;
_old_yposition = _yposition; _old_yposition = hscroll->y_value();
} }
/** draw a single cursor line at /frame/ with color /color/ using symbol routine /symbol/ for the cap */ /** draw a single cursor line at /frame/ with color /color/ using symbol routine /symbol/ for the cap */
@ -1377,6 +1413,7 @@ Timeline::redraw_playhead ( void )
xposition( max( 0, playhead_x - ( ( tracks->w() - Track::width() ) >> 1 ) ) ); xposition( max( 0, playhead_x - ( ( tracks->w() - Track::width() ) >> 1 ) ) );
else if ( playhead_x > ts_to_x( xoffset ) + ( tracks->w() - Track::width() ) ) else if ( playhead_x > ts_to_x( xoffset ) + ( tracks->w() - Track::width() ) )
xposition( playhead_x ); xposition( playhead_x );
adjust_hscroll();
} }
} }
} }
@ -1481,7 +1518,7 @@ Timeline::handle_scroll ( int m )
if ( m == FL_KEYBOARD && if ( m == FL_KEYBOARD &&
Fl::event_key() != FL_Home && Fl::event_key() != FL_Home &&
Fl::event_key() != FL_End ) Fl::event_key() != FL_End )
return menu->test_shortcut() || hscroll->handle( m ) || vscroll->handle( m ); return menu->test_shortcut() || hscroll->handle( m );
else else
return 0; return 0;
} }
@ -1707,18 +1744,6 @@ Timeline::xposition ( int X )
damage( FL_DAMAGE_SCROLL ); damage( FL_DAMAGE_SCROLL );
} }
/** set vertical scroll position to absolute pixel coordinate /Y/ */
void
Timeline::yposition ( int Y )
{
_yposition = Y;
int dy = _old_yposition - _yposition;
if ( dy )
damage( FL_DAMAGE_SCROLL );
}
/** zoom in by one zoom step */ /** zoom in by one zoom step */
void void
Timeline::zoom_in ( void ) Timeline::zoom_in ( void )

View File

@ -50,11 +50,11 @@ class Time_Sequence;
class Annotation_Sequence; class Annotation_Sequence;
class Cursor_Sequence; class Cursor_Sequence;
class Track; class Track;
class Scalebar;
class Sequence; class Sequence;
class Sequence_Widget; class Sequence_Widget;
class Cursor_Region; class Cursor_Region;
class Cursor_Point; class Cursor_Point;
class Fl_Panzoomer;
namespace OSC { class Endpoint; } namespace OSC { class Endpoint; }
@ -96,7 +96,8 @@ class Timeline : public Fl_Single_Window, public RWLock
{ {
static void draw_clip ( void * v, int X, int Y, int W, int H ); static void draw_clip ( void * v, int X, int Y, int W, int H );
static void draw_thumbnail_view( int X, int Y,int W, int H, void *v);
void draw_thumbnail_view( int X, int Y,int W, int H) const;
int _old_xposition; int _old_xposition;
int _old_yposition; int _old_yposition;
@ -106,10 +107,8 @@ class Timeline : public Fl_Single_Window, public RWLock
Fl_Scroll *scroll; Fl_Scroll *scroll;
Fl_Pack *tracks; Fl_Pack *tracks;
Fl_Pack *rulers; Fl_Pack *rulers;
Scalebar *hscroll; Fl_Panzoomer *hscroll;
Fl_Scrollbar *vscroll;
void adjust_vscroll ( void );
void adjust_hscroll ( void ); void adjust_hscroll ( void );
static void cb_scroll ( Fl_Widget *w, void *v ); static void cb_scroll ( Fl_Widget *w, void *v );
void cb_scroll ( Fl_Widget *w ); void cb_scroll ( Fl_Widget *w );
@ -180,8 +179,6 @@ public:
nframes_t xoffset; nframes_t xoffset;
int _yposition;
nframes_t _sample_rate; nframes_t _sample_rate;
Timeline ( int X, int Y, int W, int H, const char *L=0 ); Timeline ( int X, int Y, int W, int H, const char *L=0 );
@ -228,7 +225,6 @@ public:
position_info render_tempomap ( nframes_t start, nframes_t length, measure_line_callback *cb, void *arg ) const; position_info render_tempomap ( nframes_t start, nframes_t length, measure_line_callback *cb, void *arg ) const;
void xposition ( int X ); void xposition ( int X );
void yposition ( int Y );
void draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const; void draw_cursor ( nframes_t frame, Fl_Color color, void (*symbol)(Fl_Color) ) const;
void draw_cursors ( Cursor_Sequence *o ) const; void draw_cursors ( Cursor_Sequence *o ) const;
void draw_cursors ( void ) const; void draw_cursors ( void ) const;