From 4e634beff58459936ed136f9cf8c966881ece48f Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Wed, 27 Jan 2010 19:58:01 -0600 Subject: [PATCH] Mixer: Add context menu to mixer strips. --- FL/menu_popup.C | 11 ++- FL/menu_popup.H | 1 + Mixer/Mixer.C | 2 + Mixer/Mixer_Strip.C | 186 +++++++++++++++++++++++++++++++++++++++++--- Mixer/Mixer_Strip.H | 19 +++++ Mixer/main.C | 2 +- 6 files changed, 207 insertions(+), 14 deletions(-) diff --git a/FL/menu_popup.C b/FL/menu_popup.C index 7e3dd05..435593c 100644 --- a/FL/menu_popup.C +++ b/FL/menu_popup.C @@ -23,9 +23,9 @@ /** popup menu and execute callback */ bool -menu_popup ( Fl_Menu_ *m ) +menu_popup ( Fl_Menu_ *m, int X, int Y ) { - const Fl_Menu_Item *r = m->menu()->popup( Fl::event_x(), Fl::event_y(), m->label() ); + const Fl_Menu_Item *r = m->menu()->popup( X, Y, m->label() ); if ( r ) { @@ -38,6 +38,13 @@ menu_popup ( Fl_Menu_ *m ) return false; } +/** popup menu and execute callback */ +bool +menu_popup ( Fl_Menu_ *m ) +{ + return menu_popup( m, Fl::event_x(), Fl::event_y() ); +} + /** set a single callback for all items in menu. */ void menu_set_callback( Fl_Menu_Item *menu, void (*callback)( Fl_Widget *, void * ), void *user_data ) diff --git a/FL/menu_popup.H b/FL/menu_popup.H index 6d6bf99..55f6257 100644 --- a/FL/menu_popup.H +++ b/FL/menu_popup.H @@ -21,5 +21,6 @@ class Fl_Menu_; class Fl_Menu_Item; class Fl_Widget; +bool menu_popup ( Fl_Menu_ *m, int X, int Y ); bool menu_popup ( Fl_Menu_ *m ); void menu_set_callback ( Fl_Menu_Item *menu, void (*callback)( Fl_Widget *, void * ), void *user_data ); diff --git a/Mixer/Mixer.C b/Mixer/Mixer.C index 75252c4..3e563e7 100644 --- a/Mixer/Mixer.C +++ b/Mixer/Mixer.C @@ -298,6 +298,8 @@ void Mixer::add ( Mixer_Strip *ms ) mixer_strips->add( ms ); + ms->take_focus(); + rows( _rows ); scroll->redraw(); diff --git a/Mixer/Mixer_Strip.C b/Mixer/Mixer_Strip.C index 110da27..0ef9aa2 100644 --- a/Mixer/Mixer_Strip.C +++ b/Mixer/Mixer_Strip.C @@ -51,6 +51,10 @@ #include "Meter_Indicator_Module.H" #include "util/debug.h" +#include +#include "FL/test_press.H" +#include "FL/menu_popup.H" + extern Mixer *mixer; @@ -206,20 +210,13 @@ void Mixer_Strip::cb_handle(Fl_Widget* o) { } else if ( o == left_button ) - { - mixer->move_left( this ); - } + command_move_left(); else if ( o == right_button ) - { - mixer->move_right( this ); - } + command_move_right(); else if ( o == close_button ) { if ( Fl::event_shift() || 1 == fl_choice( "Are you sure you want to remove this strip?\n\n(this action cannot be undone)", "Cancel", "Remove", NULL ) ) - { - ((Mixer*)parent())->remove( this ); - Fl::delete_widget( this ); - } + command_close(); } else if ( o == name_field ) name( name_field->value() ); @@ -240,6 +237,7 @@ void Mixer_Strip::cb_handle(Fl_Widget* o, void* v) { } + void Mixer_Strip::name ( const char *name ) { char *s = strdup( name ); @@ -296,6 +294,8 @@ Mixer_Strip::update ( void ) void Mixer_Strip::init ( ) { + selection_color( FL_FOREGROUND_COLOR ); + _chain = 0; // box(FL_THIN_UP_BOX); @@ -449,6 +449,94 @@ Mixer_Strip::init ( ) // _chain->configure_ports(); } +void +Mixer_Strip::draw ( void ) +{ + if ( !fl_not_clipped( x(), y(), w(), h() ) ) + return; + + /* don't bother drawing anything else, all we're doing is drawing the focus. */ + if ( damage() != FL_DAMAGE_USER1 ) + Fl_Group::draw(); + + Fl_Group::draw_box( FL_ROUNDED_FRAME, x(), y(), w(), h(), _focused ? Fl_Group::selection_color() : Fl_Group::color() ); +} + + + +void +Mixer_Strip::menu_cb ( const Fl_Menu_ *m ) +{ + char picked[256]; + + m->item_pathname( picked, sizeof( picked ) ); + + Logger log( this ); + + if ( ! strcmp( picked, "Width/Narrow" ) ) + command_width( false ); + else if ( ! strcmp( picked, "Width/Wide" ) ) + command_width( true ); + else if ( ! strcmp( picked, "View/Fader" ) ) + command_view( false ); + else if ( ! strcmp( picked, "View/Signal" ) ) + command_view( true ); + else if ( ! strcmp( picked, "/Move Left" ) ) + command_move_left(); + else if ( ! strcmp( picked, "/Move Right" ) ) + command_move_right(); + else if ( ! strcmp( picked, "/Rename" ) ) + name_field->take_focus(); + else if ( ! strcmp( picked, "/Remove" ) ) + { + if ( Fl::event_shift() || 1 == fl_choice( "Are you sure you want to remove this strip?\n\n(this action cannot be undone)", "Cancel", "Remove", NULL ) ) + command_close(); + } +} + +void +Mixer_Strip::menu_cb ( Fl_Widget *w, void *v ) +{ + ((Mixer_Strip*)v)->menu_cb( (Fl_Menu_*) w ); +} + + +/** build the context menu */ +Fl_Menu_Button & +Mixer_Strip::menu ( void ) const +{ + static Fl_Menu_Button m( 0, 0, 0, 0, "Strip" ); + static char label[256]; + + snprintf( label, sizeof(label), "Strip/%s", name() ); + m.label( label ); + +// int c = output.size(); + + Fl_Menu_Item menu[] = + { + { "Width", 0, 0, 0, FL_SUBMENU }, + { "Narrow", 'n', 0, 0, FL_MENU_RADIO | ( ! width_button->value() ? FL_MENU_VALUE : 0 ) }, + { "Wide", 'w', 0, 0, FL_MENU_RADIO | ( width_button->value() ? FL_MENU_VALUE : 0 ) }, + { 0 }, + { "View", 0, 0, 0, FL_SUBMENU }, + { "Fader", 'f', 0, 0, FL_MENU_RADIO | ( 0 == tab_button->value() ? FL_MENU_VALUE : 0 ) }, + { "Signal", 's', 0, 0, FL_MENU_RADIO | ( 1 == tab_button->value() ? FL_MENU_VALUE : 0 ) }, + { 0 }, + { "Move Left", '[', 0, 0 }, + { "Move Right", ']', 0, 0 }, + { "Color", 0, 0, 0 }, + { "Rename", FL_CTRL + 'n', 0, 0 }, + { "Remove", FL_Delete, 0, 0 }, + { 0 }, + }; + + menu_set_callback( menu, &Mixer_Strip::menu_cb, (void*)this ); + + m.copy( menu, (void*)this ); + + return m; +} int Mixer_Strip::handle ( int m ) @@ -457,6 +545,38 @@ Mixer_Strip::handle ( int m ) switch ( m ) { + case FL_KEYBOARD: + if ( test_press( FL_Menu ) ) + { + menu_popup( &menu(), x(), y() ); + return 1; + } + else + return menu().test_shortcut() || Fl_Group::handle( m ); + case FL_PUSH: + { + int r; + if ( test_press( FL_BUTTON3 ) ) + { + menu_popup( &menu() ); + r = 1; + } + else + r = Fl_Group::handle( m ); + + if ( r ) + take_focus(); + + return r; + } + case FL_FOCUS: + _focused = true; + damage( FL_DAMAGE_USER1 ); + return 1; + case FL_UNFOCUS: + _focused = false; + damage( FL_DAMAGE_USER1 ); + return 1; /* case FL_ENTER: */ /* name_field->color( FL_BLACK ); */ /* name_field->redraw(); */ @@ -472,5 +592,49 @@ Mixer_Strip::handle ( int m ) } - return 0; + return Fl_Group::handle( m ); +} + + +/************/ +/* Commands */ +/************/ + +void +Mixer_Strip::command_move_left ( void ) +{ + mixer->move_left( this ); +} + +void +Mixer_Strip::command_move_right ( void ) +{ + mixer->move_right( this ); +} + +void +Mixer_Strip::command_close ( void ) +{ + mixer->remove( this ); + Fl::delete_widget( this ); +} + +void +Mixer_Strip::command_rename ( const char * s ) +{ + name( s ); +} + +void +Mixer_Strip::command_width ( bool b ) +{ + width_button->value( b ); + width_button->do_callback(); +} + +void +Mixer_Strip::command_view ( bool b ) +{ + tab_button->value( b ); + tab_button->do_callback(); } diff --git a/Mixer/Mixer_Strip.H b/Mixer/Mixer_Strip.H index 1f0c5a9..56347e2 100644 --- a/Mixer/Mixer_Strip.H +++ b/Mixer/Mixer_Strip.H @@ -47,6 +47,8 @@ class Meter_Indicator_Module; class Module; class Fl_Flip_Button; class Fl_Input; +class Fl_Menu_; +class Fl_Menu_Button; class Mixer_Strip : public Fl_Group, public Loggable { @@ -107,14 +109,31 @@ private: void cb_handle(Fl_Widget*); static void cb_handle(Fl_Widget*, void*); + bool _focused; + void set_tab ( void ); void update_port_names ( void ); + void menu_cb ( const Fl_Menu_ *m ); + static void menu_cb ( Fl_Widget *w, void *v ); + Fl_Menu_Button & menu ( void ) const; + protected: void get ( Log_Entry &e ) const; void set ( Log_Entry &e ); virtual int handle ( int m ); + virtual void draw ( void ); + +public: + + void command_move_left ( void ); + void command_move_right ( void ); + void command_close ( void ); + void command_rename ( const char * s ); + void command_width ( bool b ); + void command_view ( bool b ); + }; diff --git a/Mixer/main.C b/Mixer/main.C index d3a5f5e..fc65e6b 100644 --- a/Mixer/main.C +++ b/Mixer/main.C @@ -92,7 +92,7 @@ main ( int argc, char **argv ) Fl_Tooltip::size( 14 ); Fl_Tooltip::hoverdelay( 0.1f ); -// Fl::visible_focus( 0 ); + Fl::visible_focus( 0 ); LOG_REGISTER_CREATE( Mixer_Strip ); LOG_REGISTER_CREATE( Chain );