diff --git a/timeline/src/Timeline.C b/timeline/src/Timeline.C index 0f826c1..c4779b4 100644 --- a/timeline/src/Timeline.C +++ b/timeline/src/Timeline.C @@ -1482,6 +1482,8 @@ Timeline::add_track ( Track *track ) tracks->add( track ); +// update_track_order(); + engine->unlock(); unlock(); @@ -1491,6 +1493,91 @@ Timeline::add_track ( Track *track ) } +void +Timeline::insert_track ( Track *track, int n ) +{ + if ( n > tracks->children() || n < 0 ) + return; + + wrlock(); + + engine->lock(); + + tracks->insert( *track, n ); + + update_track_order(); + + tracks->redraw(); + + engine->unlock(); + + unlock(); + + /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ +// redraw(); +} + +static +bool +compare_tracks ( Track *a, Track *b ) +{ + return *a < *b; +} + +void +Timeline::apply_track_order ( void ) +{ + wrlock(); + + engine->lock(); + + std::list tl; + + for ( int i = 0; i < tracks->children(); i++ ) + tl.push_back( (Track*)tracks->child( i ) ); + + tl.sort(compare_tracks); + + Fl_Widget **a = const_cast(tracks->array()); + + int j = 0; + for ( std::list::const_iterator i = tl.begin(); + i != tl.end(); + i++, j++ ) + a[j] = *i; + + update_track_order(); + + engine->unlock(); + + unlock(); +} + +void +Timeline::update_track_order ( void ) +{ + for ( int i = 0; i < tracks->children(); i++ ) + ((Track*)tracks->child( i ))->row( i ); +} + +int +Timeline::find_track ( const Track *track ) const +{ + return tracks->find( *track ); +} + +void +Timeline::move_track_up ( Track *track ) +{ + insert_track( track, find_track( track ) - 1 ); +} + +void +Timeline::move_track_down ( Track *track ) +{ + insert_track( track, find_track( track ) + 2 ); +} + /** remove /track/ from the timeline */ void Timeline::remove_track ( Track *track ) @@ -1504,10 +1591,13 @@ Timeline::remove_track ( Track *track ) /* FIXME: what to do about track contents? */ tracks->remove( track ); + update_track_order(); + engine->unlock(); unlock(); + /* FIXME: why is this necessary? doesn't the above add do DAMAGE_CHILD? */ redraw(); } @@ -1545,6 +1635,8 @@ Timeline::command_load ( const char *name, const char *display_name ) Project::set_name ( display_name ? display_name : name ); + apply_track_order(); + return true; } diff --git a/timeline/src/Timeline.H b/timeline/src/Timeline.H index 48de0d2..6c50256 100644 --- a/timeline/src/Timeline.H +++ b/timeline/src/Timeline.H @@ -127,6 +127,10 @@ class Timeline : public Fl_Single_Window, public RWLock static void handle_peer_scan_complete ( void * v ); + void update_track_order ( void ); + void apply_track_order ( void ); + void insert_track ( Track *track, int n ); + public: OSC::Endpoint *osc; @@ -222,6 +226,11 @@ public: void add_track ( Track *track ); void remove_track ( Track *track ); + void move_track_up ( Track *track ); + void move_track_down ( Track *track ); + + int find_track ( const Track * track ) const; + int ntracks ( void ) const; void zoom ( float secs ); diff --git a/timeline/src/Track.C b/timeline/src/Track.C index 92d4d34..e18144a 100644 --- a/timeline/src/Track.C +++ b/timeline/src/Track.C @@ -109,6 +109,7 @@ Track::~Track ( ) void Track::init ( void ) { + _row = 0; _sequence = NULL; _name = NULL; _selected = false; @@ -294,7 +295,8 @@ Track::set ( Log_Entry &e ) } } - + else if ( ! strcmp( s, ":row" ) ) + row( atoi( v ) ); } } @@ -317,6 +319,19 @@ Track::get_unjournaled ( Log_Entry &e ) const e.add( ":armed", armed() ); e.add( ":mute", mute() ); e.add( ":solo", solo() ); + e.add( ":row", timeline->find_track( this ) ); +} + +int +Track::row ( void ) const +{ + return _row; +} + +void +Track::row ( int n ) +{ + _row = n; } void @@ -780,6 +795,14 @@ Track::menu_cb ( const Fl_Menu_ *m ) { ((Fl_Sometimes_Input*)name_field)->take_focus(); } + else if ( ! strcmp( picked, "/Move Up" ) ) + { + timeline->move_track_up( this ); + } + else if ( ! strcmp( picked, "/Move Down" ) ) + { + timeline->move_track_down( this ); + } } #include "FL/menu_popup.H" @@ -816,6 +839,8 @@ Track::menu ( void ) const { "Mute", FL_CTRL + 'm', 0, 0, FL_MENU_TOGGLE | ( mute() ? FL_MENU_VALUE : 0 ) }, { "Solo", FL_CTRL + 's', 0, 0, FL_MENU_TOGGLE | ( solo() ? FL_MENU_VALUE : 0 ) }, { 0 }, + { "Move Up", FL_SHIFT + '1', 0, 0 }, + { "Move Down", FL_SHIFT + '2', 0, 0 }, { "Remove", 0, 0, 0 }, // transport->rolling ? FL_MENU_INACTIVE : 0 }, { 0 }, }; diff --git a/timeline/src/Track.H b/timeline/src/Track.H index cb4db1c..cbd960b 100644 --- a/timeline/src/Track.H +++ b/timeline/src/Track.H @@ -85,6 +85,11 @@ public: Fl_Color color ( void ) const { return child(0)->color(); } void color ( Fl_Color c ) { child(0)->color( c ); } + bool operator< ( const Track &rhs ) const + { + return _row < rhs._row; + } + private: static int _soloing; @@ -97,6 +102,8 @@ private: int _size; + int _row; + enum { AUDIO } _type; Audio_Sequence *_sequence; @@ -198,6 +205,8 @@ public: bool selected ( void ) const { return _selected; } + int row ( void ) const; + void row ( int ); static void cb_input_field ( Fl_Widget *w, void *v ); void cb_input_field ( void );