# data file for the Fltk User Interface Designer (fluid) version 1.0300 header_name {.H} code_name {.C} comment {// // 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; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // } {in_source in_header } decl {\#include } {public local } decl {\#include } {private local } decl {class Fl_Scalepack;} {public local } decl {class Fl_Sometimes_Input;} {public local } decl {\#include } {public global } decl {\#include } {public local } decl {\#include } {private local } decl {\#include } {public global } decl {\#include } {private local } decl {\#include } {private local } decl {\#include } {private local } decl {\#include } {private local } decl {\#include } {private local } decl {\#include "event_edit.H"} {private local } decl {\#include "../jack.H"} {private local } decl {\#include "../NSM.H"} {private local } decl {extern NSM_Client *nsm;} {private local } decl {\#include "../transport.H"} {private local } decl {extern UI *ui;} {private local } decl {class O_Canvas;} {private local } decl {class Triggers;} {public local } decl {class Instrument_Editor;} {private local } decl {Fl_Color canvas_background_color;} {public local } decl {Fl_Color velocity_colors[128];} {public local } Function {init_colors()} {open private C return_type {static void} } { code {unsigned int i; /* velocity colors */ Fl_Color c[] = { FL_BLUE, FL_GREEN, FL_RED }; int b[] = {0, 64, 127 }; int nbreaks = 3; for ( int i = 0; i < nbreaks - 1; i++ ) { int k = 0; for ( int j = b[i]; j <= b[i+1]; j++, k++ ) velocity_colors[ j ] = fl_color_average( c[i+1], c[i], ( k ) / (float)(b[i+1] - b[i] )); } } {} } widget_class Visual_Metronome {open xywh {978 1028 100 100} type Double visible } { Fl_Slider progress { private xywh {139 115 1149 23} type Horizontal box FLAT_BOX color 7 selection_color 54 code0 {o->resize( x(), (y() + h()) - (h() / 3), w(), h() / 3 );} code1 {o->slider_size( 0.25 );} code2 {o->slider( FL_FLAT_BOX );} } Function {draw(void)} {open protected return_type void } { code {if ( damage() & ~FL_DAMAGE_CHILD ) { if ( ! _bpb ) return; int bw = w() / _bpb; int b = _bpb; if ( b ) { for ( int i = 0; i < b; ++i ) { if ( i == _beat ) fl_color( velocity_colors[ i * 127 / _bpb ] ); else fl_color( FL_GRAY ); int X = x() + ( i * bw ); int Y = y(); int W = bw; int H = h() - 14; fl_rectf(X,Y,W,H); fl_color( fl_darker( fl_color() ) ); fl_rect( X,Y,W,H); char pat[4]; snprintf( pat, sizeof(pat), "%d", i + 1 ); fl_font( FL_HELVETICA_BOLD, 24 ); fl_draw( pat, X,Y,W,H, FL_ALIGN_CENTER ); } } } progress->resize( x(), y() + h() - 14, w(), 14 ); if ( damage() & FL_DAMAGE_CHILD ) update_child( *progress ); else draw_child( *progress ); // _flip = ! _flip;} {} } decl {int _bpb} {private local } decl {int _tpb} {private local } decl {int _beat} {private local } decl {bool _flip} {private local } decl {int _tick} {private local } Function {bpb( int b )} {open private return_type void } { code {if ( b != _bpb ) { _bpb = b; redraw(); }} {} } Function {tpb( int ticks )} {open private return_type void } { code {_tpb = ticks; progress->minimum( 0 ); progress->maximum( ticks );} {} } Function {beat( int b )} {open private return_type void } { code {if ( b == _beat || b >= _bpb ) return; _flip = ! _flip; _beat = b; redraw();} {} } Function {tick( int tick )} {open private return_type void } { code {if ( tick == _tick ) return; if ( _beat < 0 ) return; if ( _flip ) { progress->value( _tpb - tick ); } else { progress->value( tick ); } _tick = tick;} {} } Function {update( void )} {open return_type void } { code {if ( transport.beats_per_bar ) { bpb( transport.beats_per_bar ); tpb( transport.ticks_per_beat ); beat( transport.beat - 1 ); tick( transport.tick - 1 );}} {} } code {_bpb = 0; _tpb = 0; _beat = 0; _tick = 0; _flip = 0;} {} } class Overlay_Callback_Window {: {public Fl_Overlay_Window} } { decl {void (*_draw_overlay_callback)(void*);} {private local } decl {void *_draw_overlay_userdata;} {private local } Function {Overlay_Callback_Window(int X, int Y, int W, int H, const char *L=0) : Fl_Overlay_Window(X,Y,W,H,L)} {open } { code {_draw_overlay_callback = 0; _draw_overlay_userdata = 0;} {} } Function {Overlay_Callback_Window(int W, int H, const char *L=0) : Fl_Overlay_Window(W,H,L)} {open } { code {_draw_overlay_callback = 0; _draw_overlay_userdata = 0;} {} } Function {draw_overlay()} {open return_type {virtual void} } { code {if ( _draw_overlay_callback ) _draw_overlay_callback( _draw_overlay_userdata );} {} } Function {draw_overlay_callback( void(*cb)(void*), void *v)} {open return_type void } { code {_draw_overlay_callback = cb; _draw_overlay_userdata = v;} {} } } Function {update_transport( void * )} {open return_type void } { code {// transport_poll(); handle_midi_input(); ui->progress_group->do_callback(); ui->vmetro_widget->update(); ui->triggers_widget->update(); Fl::repeat_timeout( TRANSPORT_POLL_INTERVAL, update_transport ); static int oldstate = -1; if ( transport.rolling != oldstate ) { ui->play_button->label( transport.rolling ? "@square" : "@>" ); oldstate = transport.rolling; if ( transport.rolling ) { ui->menu_new->deactivate(); ui->menu_open->deactivate(); } else { ui->menu_new->activate(); ui->menu_open->activate(); } } if ( nsm && nsm->is_active() ) { if ( ui->menu_new->active() ) { ui->menu_new->deactivate(); ui->menu_open->deactivate(); ui->menu_save_as->deactivate(); } } // JUST A TEST if ( transport.rolling ) { if ( ui->tabs->value() == ui->pattern_tab ) ui->pattern_canvas_widget->redraw_playhead(); else if ( ui->tabs->value() == ui->phrase_tab ) ui->phrase_canvas_widget->redraw_playhead(); } ui->transport_state->do_callback();} {} } class UI {open } { decl {Fl_Text_Buffer *sequence_notes_buffer;} {private local } decl {Fl_Text_Buffer *pattern_notes_buffer;} {private local } decl {Fl_Text_Buffer *phrase_notes_buffer} {private local } Function {UI()} {open } { code {fl_register_images(); canvas_background_color = FL_GREEN; playback_mode_menu = NULL; main_window = make_main_window(); seq_window = make_seq_window(); init_colors(); // make_instrument_edit_dialog(); // use old focus behavior Fl::visible_focus( 0 ); // try to fill the screen, but only when the screen is tiny and our window is huge. { int sx, sy, sw, sh; Fl::screen_xywh( sx, sy, sw, sh ); if ( sw < main_window->w() || sh < main_window->h() ) main_window->resize( sx, sy, sw, sh ); } Fl::add_timeout( TRANSPORT_POLL_INTERVAL, update_transport ); playlist->signal_new_song.connect( sigc::mem_fun( this, &UI::update_sequence_widgets ) ); pattern_canvas_widget->signal_settings_change.connect( sigc::mem_fun( this, &UI::update_pattern_widgets ) ); phrase_canvas_widget->signal_settings_change.connect( sigc::mem_fun( this, &UI::update_phrase_widgets ) );} {} } Function {~UI()} {open } { code {delete seq_window; delete main_window;} {} } Function {run()} {open } { code {Fl::run();} {} } Function {load_settings()} {open return_type void } { code {char *path; asprintf( &path, "%s/%s", config.user_config_dir, "view" ); ((Fl_Menu_Settings*)menu_bar)->load( menu_bar->find_item( "&View" ), path ); free( path );} {} } Function {save_settings()} {open return_type void } { code {char *path; asprintf( &path, "%s/%s", config.user_config_dir, "view" ); ((Fl_Menu_Settings*)menu_bar)->dump( menu_bar->find_item( "&View" ), path ); free( path );} {} } Function {draw_overlay( void *v )} {open protected return_type {static void} } { code {((UI*)v)->draw_overlay();} {} } Function {draw_overlay()} {open protected return_type void } { code {Canvas *c = current_canvas(); if ( c ) c->draw_overlay();} {} } Function {make_main_window()} {open } { Fl_Window main_window { label {Non Sequencer} callback {// Ignore escape if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape ) return; if ( maybe_save_song() ) quit();} open xywh {213 323 865 805} type Double color 47 resizable code0 {o->color( FL_BACKGROUND_COLOR );} code1 {o->draw_overlay_callback( &UI::draw_overlay, this );} code2 {o->xclass( APP_NAME );} class Overlay_Callback_Window size_range {700 509 0 0} visible } { Fl_Group {} {open xywh {0 25 865 70} box FLAT_BOX } { Fl_Group {} {open xywh {552 26 312 69} code0 {o->resizable(0);} } { Fl_Value_Input {} { label BPM callback {transport.set_beats_per_minute( o->value() );} xywh {825 39 35 19} labelsize 9 align 1 when 8 textsize 10 code1 {transport.signal_tempo_change.connect( sigc::mem_fun( o, static_cast(&Fl_Valuator::value) ) );} code2 {o->value( transport.beats_per_minute );} } Fl_Group {} { label {Time Sig.} open xywh {756 38 64 21} labelsize 9 } { Fl_Value_Input {} { callback {transport.set_beats_per_bar( o->value() );} xywh {756 39 24 19} textsize 10 code0 {transport.signal_bpb_change.connect( sigc::mem_fun( o, static_cast(&Fl_Valuator::value) ) );} code1 {o->value( transport.beats_per_bar );} } Fl_Box {} { label {/} xywh {780 38 14 21} } Fl_Value_Input {} { callback {transport.set_beat_type( o->value() );} xywh {795 39 24 19} textsize 10 code0 {transport.signal_beat_change.connect( sigc::mem_fun( o, static_cast(&Fl_Valuator::value) ) );} code1 {o->value( transport.beat_type );} } } Fl_Choice record_mode_menu { label {Record Mode} callback {if ( ! transport.recording ) config.record_mode = (record_mode_e)o->value(); else o->value( config.record_mode );} xywh {555 39 105 19} box DOWN_BOX down_box BORDER_BOX color 37 labelsize 9 align 1 textsize 9 } { MenuItem {} { label Merge xywh {15 15 40 25} labelfont 3 labelsize 10 } MenuItem {} { label Overwrite xywh {25 25 40 25} labelfont 3 labelsize 10 } MenuItem {} { label Layer xywh {35 35 40 25} labelfont 3 labelsize 10 } MenuItem {} { label New xywh {45 45 40 25} labelfont 3 labelsize 10 } } Fl_Choice playback_mode_menu { label {Playback &Mode} xywh {665 39 85 19} box DOWN_BOX down_box BORDER_BOX color 37 labelsize 9 align 1 } { MenuItem {} { label Pattern callback {song.play_mode = PATTERN;} xywh {5 5 40 25} labelfont 3 labelsize 10 } MenuItem {} { label Sequence callback {song.play_mode = SEQUENCE;} xywh {15 15 40 25} labelfont 3 labelsize 10 } MenuItem {} { label Trigger callback {song.play_mode = TRIGGER;} xywh {25 25 40 25} labelfont 3 labelsize 10 } MenuItem {} { label Queue callback {song.play_mode = QUEUE;} xywh {0 0 40 24} labelfont 3 labelsize 10 } } Fl_Pack {} {open xywh {555 60 305 30} type HORIZONTAL class Fl_Scalepack } { Fl_Button {} { label Sequence callback {tabs->value( sequence_tab ); edit_menu->deactivate(); menu_bar->redraw();} xywh {565 70 68 15} type Radio shortcut 0x80031 selection_color 69 } Fl_Button {} { label Phrase callback {tabs->value( phrase_tab ); edit_menu->activate(); menu_bar->redraw();} xywh {575 80 68 5} type Radio shortcut 0x80032 selection_color 69 } Fl_Button {} { label Pattern callback {tabs->value( pattern_tab ); edit_menu->activate(); menu_bar->redraw();} xywh {585 90 68 0} type Radio shortcut 0x80033 value 1 selection_color 69 } } } Fl_Pack vmetro_widget { label Metronome xywh {160 27 390 61} type HORIZONTAL box UP_BOX color 40 selection_color 48 labelsize 33 align 0 resizable code0 {o->box( FL_FLAT_BOX );} class Visual_Metronome } {} Fl_Pack transport_controls_group {open xywh {4 27 151 60} type HORIZONTAL code0 {o->spacing( 2 );} class Fl_Scalepack } { Fl_Button play_button { label {@>} callback {transport.toggle();} xywh {10 29 43 38} shortcut 0x20 labeltype ENGRAVED_LABEL } Fl_Button rec_button { label {@circle} callback {transport.recording = o->value(); if ( o->value() ) { if ( config.record_mode == NEW ) { pattern *p = new pattern; p->length( -1 ); pattern_canvas_widget->grid( p ); } ((pattern*)pattern_canvas_widget->grid())->record( 0 ); o->labelcolor( FL_RED ); } else { pattern::recording()->record_stop(); o->labelcolor( FL_WHITE ); }} xywh {60 29 43 38} type Toggle shortcut 0x80072 selection_color 47 labeltype ENGRAVED_LABEL when 1 } Fl_Button home_button { label {@|<} callback {transport.locate( 0 );} xywh {110 29 43 38} shortcut 0xff50 labeltype ENGRAVED_LABEL } } } Fl_Tabs tabs { callback {((Fl_Group*)o->value())->child( 0 )->take_focus();} open xywh {-1 91 868 694} box FLAT_BOX color 47 labeltype SHADOW_LABEL labelsize 19 when 1 resizable code0 {canvas_background_color = fl_rgb_color( 18, 18, 18 );} } { Fl_Group sequence_tab {open xywh {0 91 865 692} box FLAT_BOX color 37 labeltype NO_LABEL labelsize 12 hide resizable code0 {update_sequence_widgets();} } { Fl_Group {} {open xywh {5 118 240 502} labelsize 12 } { Fl_Browser playlist_browser { label Playlist xywh {5 155 240 398} type Hold box EMBOSSED_BOX color 39 selection_color 30 labelsize 12 labelcolor 55 align 1 when 4 textsize 18 textcolor 95 resizable code0 {static int widths[] = { 40, 30, 0 };} code1 {o->column_widths( widths ); o->column_char( '\\t' );} code2 {o->value( 1 );} } Fl_Button sequence_phrase_delete_button { label Delete callback {int val = playlist_browser->value(); if ( val > 1 ) { // playlist_browser->value( playlist_browser->value() + 1 ); playlist->remove( val - 2 ); update_sequence_widgets(); if ( ! playlist_browser->value() ) playlist_browser->value( playlist_browser->size() ); }} xywh {6 559 64 25} shortcut 0xffff color 88 labelcolor 23 } Fl_Button sequence_phrase_up_button { label Up callback {if ( playlist_browser->value() > 2 ) { playlist->move( playlist_browser->value() - 2, UP ); playlist_browser->value( playlist_browser->value() - 1 ); update_sequence_widgets(); }} xywh {135 559 45 25} shortcut 0xffbf } Fl_Button sequence_phrase_down_button { label Down callback {if ( playlist_browser->value() > 1 ) { playlist->move( playlist_browser->value() - 2, DOWN ); playlist_browser->value( playlist_browser->value() + 1 ); update_sequence_widgets(); }} xywh {185 559 58 25} shortcut 0xffc0 } Fl_Menu_Button sequence_phrase_choice { label {Insert Phrase} callback {playlist->insert( playlist_browser->value() - 1, o->value() + 1 ); update_sequence_widgets(); int val = playlist_browser->value(); if ( val ) playlist_browser->value( playlist_browser->value() + 1 ); else playlist_browser->value( playlist_browser->size() );} open xywh {5 590 235 30} color 63 } {} } Fl_Input sequence_name_field { label Name callback {playlist->name( o->value() );} xywh {10 109 235 27} color 48 labelsize 12 align 1 when 1 } Fl_Light_Button detach_button { label Detach callback {if ( o->value() ) { Fl_Group *g = seq_detached_group; seq_window->show(); g->add( sequence_tab ); sequence_tab->resize( g->x(), g->y(), g->w(), g->h() ); tabs->do_callback(); main_window->redraw(); } else { seq_window->hide(); tabs->insert( (Fl_Widget&)*sequence_tab, 0 ); sequence_tab->resize( pattern_tab->x(), pattern_tab->y(), pattern_tab->w(), pattern_tab->h() ); tabs->do_callback(); }} xywh {7 749 78 26} } Fl_Text_Editor sequence_notes_edit { label {Notes:} callback {playlist->notes( o->buffer()->text() );} xywh {254 732 606 48} selection_color 48 labelsize 12 align 5 textcolor 94 code0 {o->buffer( sequence_notes_buffer = new Fl_Text_Buffer );} } Fl_Box triggers_widget { label Patterns xywh {253 118 607 598} box FLAT_BOX color 48 labelsize 12 align 1 resizable code0 {o->color( FL_BACKGROUND_COLOR );} code1 {o->rows( 32 );} class Triggers } Fl_Group progress_group { callback {if ( ! o->visible_r() ) return; phrase *p = phrase::phrase_by_number( playlist->playing() ); if ( p ) phrase_progress->value( p->index() / (double)p->length() ); if ( playlist->length() ) sequence_progress->value( playlist->index() / (double)playlist->length() );} open xywh {10 649 233 66} } { Fl_Slider phrase_progress { label Phrase xywh {10 649 233 24} type Horizontal labelsize 12 align 1 } Fl_Slider sequence_progress { label Sequence callback {transport.locate( (tick_t)((double)playlist->length() * o->value()) );} xywh {10 691 233 24} type Horizontal labelsize 12 align 1 } } } Fl_Group phrase_tab { xywh {0 91 865 693} box FLAT_BOX color 47 labeltype NO_LABEL hide code0 {update_phrase_widgets();} } { Fl_Box phrase_canvas_widget { label Phrase xywh {0 91 865 637} box FLAT_BOX color 37 labelsize 100 align 16 resizable class Canvas } Fl_Group phrase_settings_group {open xywh {0 728 865 55} box FLAT_BOX color 47 } { Fl_Input phrase_name_field { label {name:} callback {phrase_canvas_widget->grid()->name( strdup( o->value() ) ); // if the name changed.. update_sequence_widgets();} xywh {5 734 185 21} box ROUNDED_BOX color 49 labelfont 2 labelsize 12 labelcolor 55 align 20 textfont 2 textsize 12 code0 {o->up_box( FL_ROUNDED_BOX );} class Fl_Sometimes_Input } Fl_Light_Button phrase_mute_button { label Mute xywh {0 751 93 23} color 37 hide } Fl_Light_Button phrase_solo_button { label Solo xywh {106 751 87 23} color 37 hide } Fl_Text_Editor phrase_notes_edit { label {Notes:} callback {phrase_canvas_widget->grid()->notes( o->buffer()->text() );} xywh {200 742 660 36} selection_color 48 labelsize 12 textcolor 94 resizable code0 {o->buffer( phrase_notes_buffer = new Fl_Text_Buffer );} } Fl_Value_Slider phrase_number_spinner { label {Phrase:} callback {phrase *p = ((phrase *)phrase_canvas_widget->grid())->by_number( o->value() ); if ( p ) phrase_canvas_widget->grid( p ); o->maximum( phrase::phrases() );} xywh {45 760 140 18} type Horizontal labelsize 10 align 4 minimum 1 maximum 128 step 1 value 1 textsize 14 } } } Fl_Group pattern_tab {open xywh {0 91 867 694} box FLAT_BOX color 47 labeltype NO_LABEL code0 {update_pattern_widgets();} } { Fl_Box pattern_canvas_widget { label Pattern xywh {0 91 865 637} box FLAT_BOX color 37 labelsize 100 align 16 resizable class Canvas } Fl_Group pattern_settings_group {open xywh {0 730 867 55} box FLAT_BOX color 47 } { Fl_Group {} {open xywh {5 733 420 44} code0 {o->resizable(0);} } { Fl_Input pattern_name_field { label {name:} callback {pattern_canvas_widget->grid()->name( strdup( o->value() ) );} xywh {5 734 185 21} box BORDER_BOX color 49 labelsize 12 align 20 when 8 textsize 12 textcolor 55 code0 {o->up_box( FL_BORDER_BOX );} class Fl_Sometimes_Input } Fl_Light_Button pattern_mute_button { label Mute callback {Grid *g = pattern_canvas_widget->grid(); g->mode( g->mode() == MUTE ? PLAY : MUTE ); o->value( g->mode() == MUTE ); pattern_solo_button->value( 0 );} xywh {195 734 58 19} type Normal shortcut 0x6d color 37 labelsize 12 } Fl_Light_Button pattern_solo_button { label Solo callback {Grid *g = pattern_canvas_widget->grid(); g->mode( g->mode() == SOLO ? PLAY : SOLO ); o->value( g->mode() == SOLO ); pattern_mute_button->value( 0 );} xywh {195 758 58 19} type Normal shortcut 0x73 color 37 labelsize 12 } Fl_Value_Slider pattern_number_spinner { label Pattern callback {pattern *p = ((pattern *)pattern_canvas_widget->grid())->by_number( o->value() ); if ( p ) pattern_canvas_widget->grid( p ); o->maximum( pattern::patterns() );} xywh {45 759 140 18} type Horizontal labelsize 10 align 4 minimum 1 maximum 128 step 1 value 1 } Fl_Button pattern_selection_mode { label Select callback {pattern_canvas_widget->selection_mode( o->value() );} tooltip {Enable selection mode (you can also just hold down shift and drag the mouse)} xywh {260 733 45 44} type Toggle selection_color 5 labelsize 10 } Fl_Value_Slider velocity_slider { label Velocity callback {pattern_canvas_widget->selected_velocity( o->value() );} selected xywh {310 742 110 18} type {Horz Fill} labelsize 10 align 1 maximum 127 value 64 textsize 9 } } Fl_Group {} {open xywh {455 731 409 54} } { Fl_Output mapping_text { label Mapping xywh {535 761 105 19} labelsize 10 align 20 textsize 11 } Fl_Menu_Button mapping_menu { label {@>} callback {mapping_text->value( o->text() ); char picked[80]; mapping_menu->item_pathname(picked, sizeof(picked)-1 ); const char *text = o->text(); if ( ! strcmp( text, picked ) ) // nothing picked... return; if ( 0 == strncmp( picked, "Instrument", strlen( "Instrument" ) ) ) { ((pattern*)pattern_canvas_widget->grid())->mapping.open( Mapping::INSTRUMENT, o->text() ); pattern_canvas_widget->changed_mapping(); pattern_key_combo->deactivate(); } else if ( 0 == strncmp( picked, "Scale", strlen( "Scale" ) ) ) { ((pattern*)pattern_canvas_widget->grid())->mapping.open( Mapping::SCALE, o->text() ); pattern_canvas_widget->changed_mapping(); pattern_key_combo->activate(); }} open xywh {640 761 30 19} labeltype NO_LABEL labelsize 10 textsize 12 code0 {update_mapping_menu();} } { Submenu mapping_scale_menu { label Scale open xywh {25 25 74 25} } {} Submenu mapping_instrument_menu { label Instrument open xywh {10 10 74 25} } {} } Fl_Choice pattern_key_combo { label {&Key} callback {((pattern*)pattern_canvas_widget->grid())->mapping.key( o->value() ); pattern_canvas_widget->changed_mapping();} xywh {700 761 75 19} down_box BORDER_BOX labelsize 10 when 1 textsize 11 } { MenuItem {} { label C xywh {30 30 40 25} labelsize 11 } MenuItem {} { label {C\#/Db} xywh {40 40 40 25} labelsize 11 } MenuItem {} { label D xywh {50 50 40 25} labelsize 11 } MenuItem {} { label {D\#/Eb} xywh {60 60 40 25} labelsize 11 } MenuItem {} { label E xywh {70 70 40 25} labelsize 11 } MenuItem {} { label F xywh {80 80 40 25} labelsize 11 } MenuItem {} { label {F\#/Gb} xywh {90 90 40 25} labelsize 11 } MenuItem {} { label G xywh {100 100 40 25} labelsize 11 } MenuItem {} { label {G\#} xywh {110 110 40 25} labelsize 11 } MenuItem {} { label A xywh {0 0 40 25} labelsize 11 } MenuItem {} { label {A\#/Bb} xywh {10 10 40 25} labelsize 11 } MenuItem {} { label B xywh {20 20 40 25} labelsize 11 } } Fl_Choice pattern_note_combo { label {&Note 1/} callback {((pattern*)pattern_canvas_widget->grid())->note( atoi( o->menu()[ o->value() ].text ));} xywh {715 736 45 19} down_box BORDER_BOX labelsize 10 when 1 textsize 12 } { MenuItem {} { label 1 xywh {0 0 40 25} labelsize 11 } MenuItem {} { label 2 xywh {10 10 40 25} labelsize 11 } MenuItem {} { label 4 xywh {20 20 40 25} labelsize 11 } MenuItem {} { label 8 xywh {30 30 40 25} labelsize 11 } MenuItem {} { label 16 xywh {40 40 40 25} labelsize 11 } MenuItem {} { label 32 xywh {50 50 40 25} labelsize 11 } MenuItem {} { label 64 xywh {60 60 40 25} labelsize 11 divider } MenuItem {} { label 3 xywh {60 60 40 25} labelsize 11 } MenuItem {} { label 6 xywh {70 70 40 25} labelsize 11 } MenuItem {} { label 12 xywh {80 80 40 25} labelsize 11 } MenuItem {} { label 24 xywh {90 90 40 25} labelsize 11 } } Fl_Choice pattern_res_combo { label {&Resolution 1/} callback {pattern_canvas_widget->grid()->resolution( atoi( o->menu()[ o->value() ].text ));} xywh {615 736 55 19} down_box BORDER_BOX labelsize 10 when 1 textsize 12 } { MenuItem {} { label 1 xywh {40 40 40 25} labelsize 11 } MenuItem {} { label 2 xywh {50 50 40 25} labelsize 11 } MenuItem {} { label 4 xywh {30 30 40 25} labelsize 11 } MenuItem {} { label 8 xywh {40 40 40 25} labelsize 11 } MenuItem {} { label 16 xywh {50 50 40 25} labelsize 11 } MenuItem {} { label 32 xywh {60 60 40 25} labelsize 11 } MenuItem {} { label 64 xywh {80 80 40 25} labelsize 11 } MenuItem {} { label 128 xywh {90 90 40 25} labelsize 11 divider } MenuItem {} { label 3 xywh {70 70 40 25} labelsize 11 } MenuItem {} { label 6 xywh {80 80 40 25} labelsize 11 } MenuItem {} { label 12 xywh {90 90 40 25} labelsize 11 } MenuItem {} { label 24 xywh {100 100 40 25} labelsize 11 } } Fl_Choice pattern_channel_choice { label {Channel:} callback {((pattern *)pattern_canvas_widget->grid())->channel( o->value() );} open xywh {810 735 47 19} down_box BORDER_BOX labelsize 10 textsize 12 code0 {char pat[3]; for ( int i = 1; i <= 16; i++ ) { snprintf( pat, 3, "%i", i ); o->add( pat ); }} } {} Fl_Choice pattern_port_choice { label {Port:} callback {((pattern *)pattern_canvas_widget->grid())->port( o->value() );} open xywh {810 760 47 19} down_box BORDER_BOX labelsize 10 textsize 12 code0 {char pat[3]; for ( int i = 1; i <= 16; i++ ) { snprintf( pat, 3, "%i", i ); o->add( pat ); }} } {} Fl_Input_Choice pattern_bars_choice { label {Bars:} callback {((pattern *)pattern_canvas_widget->grid())->bars( atoi( o->value() ) );} open xywh {486 736 55 19} labelsize 10 textsize 12 code0 {char pat[4]; for ( int i = 1; i <= 16; i++ ) { snprintf( pat, 3, "%i", i ); o->add( pat ); }} code1 {for ( int i = 32; i <= 256; i <<= 1 ) { snprintf( pat, sizeof(pat), "%i", i ); o->add( pat ); }} } {} Fl_Box {} { xywh {455 735 0 46} labelsize 8 align 1 resizable } } } } } Fl_Group {} {open xywh {0 784 865 23} } { Fl_Box status { label status xywh {1 784 782 23} box UP_BOX align 84 code0 {o->label( NULL );} } Fl_Box transport_state { label state callback {const char *s = "INVALID"; if ( transport.master ) s = "Master"; else if ( transport.valid ) s = "Slave"; if ( s != o->label() ) { o->label( s ); if ( ! strcmp( s, "INVALID" ) ) o->color( fl_darker( FL_RED ) ); else o->color( FL_BACKGROUND_COLOR ); }} xywh {783 784 82 23} box THIN_UP_BOX align 64 } } Fl_Group {} {open xywh {0 0 865 24} } { Fl_Menu_Bar menu_bar {open xywh {0 0 865 24} color 47 resizable } { Submenu {} { label {&File} open xywh {0 0 100 20} color 37 } { MenuItem menu_new { label {&New} callback {if ( maybe_save_song() ) { init_song(); // Sync the GUI. update_pattern_widgets(); update_sequence_widgets(); update_phrase_widgets(); gui_status( "New song." ); }} xywh {0 0 40 25} } MenuItem menu_open { label {&Open} callback {char *name = fl_file_chooser( "Open File", "Non Files (*.non)", NULL, 0 ); if ( name ) { if ( ! load_song( name ) ) fl_alert( "Could not load song!" ); else gui_status( "Song opened." ); update_sequence_widgets(); update_pattern_widgets(); update_phrase_widgets(); playback_mode_menu->value( song.play_mode ); playback_mode_menu->redraw(); }} xywh {0 0 40 25} shortcut 0x4006f color 37 } MenuItem menu_save { label {&Save} callback {save_dialog( song.filename );} xywh {0 0 40 25} shortcut 0x40073 color 37 deactivate code0 {song.signal_dirty.connect( sigc::mem_fun( o, &Fl_Menu_Item::activate ) );} code1 {song.signal_clean.connect( sigc::mem_fun( o, &Fl_Menu_Item::deactivate ) );} } MenuItem menu_save_as { label {Save &As} callback {save_dialog( NULL );} xywh {0 0 40 25} } MenuItem {} { label {&Import} callback {char *name = fl_file_chooser( "MIDI Import", "MIDI Files (*.mid)", NULL, 0 ); if ( ! name ) return; smf f; if ( ! f.open( name, smf::READ ) ) { fl_message( "could not open file" ); return; } f.read_header(); switch ( f.format() ) { case 0: if ( ! pattern::import( &f, 0 ) ) fl_message( "Error importing MIDI" ); break; case 1: case 2: { char **sa = f.track_listing(); if ( sa && *sa ) { List_Chooser tc( "Select tracks to import:", "Import" ); char *s; for ( int i = 0; (s = sa[i]); ++i ) { tc.add( s ); free( s ); } free( sa ); tc.show(); while( tc.shown() ) Fl::wait(); int n = 0; for ( int i = 1; i <= tc.browser->size(); ++i ) { if ( tc.browser->selected( i ) ) { if ( pattern::import( &f , i - 1 ) ) ++n; else WARNING( "error importing track %d", i - 1 ); } } // fl_message( "%d patterns imported.", n ); gui_status( "Imported %d tracks as patterns", n ); } break; } }} xywh {0 0 40 25} code0 {\#include "../smf.H"} } MenuItem {} { label {&Export} callback {// Fl_File_Chooser::custom_filter_label = "*.mid"; Fl_File_Chooser *fc = new Fl_File_Chooser( ".", "MIDI Files (*.mid)", Fl_File_Chooser::CREATE, "MIDI Export" ); fc->show(); // wait for user to make a choice while( fc->shown() ) Fl::wait(); if ( ! fc->value() ) return; if ( tabs->value() == pattern_tab ) ((pattern*)pattern_canvas_widget->grid())->save( fc->value() );} xywh {0 0 40 25} code0 {\#include } } MenuItem {} { label {&Quit} callback {main_window->do_callback();} xywh {0 0 40 25} shortcut 0x40071 color 37 } } Submenu {} { label {&View} open xywh {10 10 74 25} color 37 } { MenuItem {} { label {&Metronome} callback {int val = o->menu()[ o->value() ].value(); if ( val ) vmetro_widget->show(); else vmetro_widget->hide();} xywh {0 0 40 25} type Toggle value 1 } MenuItem {} { label {&Compacted} callback {int val = o->menu()[ o->value() ].value(); pattern_canvas_widget->row_compact( val ? Canvas::ON : Canvas::OFF ); pattern_canvas_widget->redraw();} xywh {10 10 40 25} type Toggle value 1 } MenuItem {} { label {&Follow Playhead} callback {int val = o->menu()[ o->value() ].value(); config.follow_playhead = val ? true : false;} xywh {10 10 40 25} type Toggle value 1 } MenuItem {} { label {&Theme} callback {fl_theme_chooser();} xywh {0 0 40 24} } } Submenu {} { label {&Help} open xywh {100 0 74 25} color 37 } { MenuItem {} { label {&Manual} callback {show_help_dialog( "MANUAL" );} xywh {10 10 40 25} divider } MenuItem {} { label {&About} callback {About_Dialog ab( PIXMAP_PATH "/non-sequencer/icon-256x256.png" ); ab.logo_box->label( VERSION ); ab.title->label( "Non Sequencer" ); ab.copyright->label( "Copyright (C) 2007-2013 Jonathan Moore Liles" ); ab.credits->label( "Non Sequencer was written from scratch by\\nJonathan Moore Liles for his own use\\n(see the manual).\\n\\nNobody planned. Nobody helped.\\nYou can help now by donating time, money,\\nand/or replacing the rest of Linux Audio\\nwith fast, light, reliable alternatives.\\n" ); ab.website_url->label( "http://non.tuxfamily.org" ); ab.run();} xywh {0 0 40 25} color 37 code0 {\#include "../non.H"} } } Submenu edit_menu { label {&Edit} open xywh {0 0 68 18} } { MenuItem {} { label {Add New} callback {Grid *g = current_canvas()->grid()->create(); current_canvas()->grid( g ); update_pattern_widgets(); update_sequence_widgets(); update_phrase_widgets();} xywh {0 0 34 18} shortcut 0x61 } MenuItem {} { label Previous callback {if ( tabs->value() == pattern_tab ) { pattern_number_spinner->value( max( 0, (int)pattern_number_spinner->value() - 1 ) ); pattern_number_spinner->do_callback(); } else { phrase_number_spinner->value( max( 0, (int)phrase_number_spinner->value() - 1 ) ); phrase_number_spinner->do_callback(); }} xywh {10 10 34 18} shortcut 0x5b } MenuItem {} { label Next callback {if ( tabs->value() == pattern_tab ) { pattern_number_spinner->value( min( 127, (int)pattern_number_spinner->value() + 1 )); pattern_number_spinner->do_callback(); } else { phrase_number_spinner->value( min( 127, (int)phrase_number_spinner->value() + 1 )); phrase_number_spinner->do_callback(); }} xywh {20 20 34 18} shortcut 0x5d } MenuItem {} { label Duplicate callback {Canvas *w = current_canvas(); w->grid( w->grid()->clone() ); // number of phrases may have changed. ui->update_sequence_widgets();} xywh {30 30 34 18} shortcut 0x64 } MenuItem {} { label {Delete Selected} callback {Canvas *w = current_canvas(); w->grid()->delete_selected();} xywh {50 50 34 18} shortcut 0xffff } MenuItem {} { label Clear callback {Canvas *w = current_canvas(); w->grid()->clear();} xywh {60 60 34 18} shortcut 0x1ffff } MenuItem {} { label {Edit Events} callback {event_editor( pattern_canvas_widget->grid() );} xywh {10 10 40 25} } MenuItem {} { label {Select All} callback {Canvas *w = current_canvas(); w->grid()->select_all();} xywh {70 70 34 18} shortcut 0x40061 } MenuItem {} { label {Select None} callback {Canvas *w = current_canvas(); w->grid()->select_none();} xywh {80 80 34 18} shortcut 0x50061 } MenuItem {} { label {Invert Selection} callback {Canvas *w = current_canvas(); w->grid()->invert_selection();} xywh {90 90 34 18} shortcut 0x50069 } MenuItem {} { label Cut callback {Canvas *w = current_canvas(); w->cut();} xywh {110 110 34 18} shortcut 0x40078 } MenuItem {} { label Copy callback {Canvas *w = current_canvas(); w->copy();} xywh {100 100 34 18} shortcut 0x40063 } MenuItem {} { label Paste callback {Canvas *w = current_canvas(); w->paste();} xywh {120 120 34 18} shortcut 0x40076 } MenuItem {} { label Undo callback {Canvas *w = current_canvas(); w->grid()->undo();} xywh {110 110 34 18} shortcut 0x4007a } } } Fl_Button sm_indicator { label SM xywh {825 5 35 15} box ROUNDED_BOX down_box ROUNDED_BOX color 46 selection_color 93 labelfont 3 labelcolor 39 deactivate } } } } Function {make_seq_window()} {} { Fl_Window seq_window { label {Non Sequencer - Sequence} callback {sequence_tab->activate(); o->hide(); detach_button->value( 0 );} xywh {681 189 876 675} type Double hide resizable } { Fl_Group seq_detached_group {open xywh {0 0 876 675} resizable } {} } } Function {update_pattern_widgets()} {} { code {if ( ! pattern_settings_group ) return; if ( !pattern_canvas_widget) return; pattern *g = (pattern *)pattern_canvas_widget->grid(); if ( !g ) return; pattern_number_spinner->value( g->number() ); pattern_name_field->value( g->name() ); pattern_channel_choice->value( g->channel() ); pattern_port_choice->value( g->port() ); pattern_solo_button->value( g->mode() == SOLO ); pattern_mute_button->value( g->mode() == MUTE ); pattern_selection_mode->value( pattern_canvas_widget->selection_mode() ); { char pat[5]; snprintf( pat, sizeof(pat), "%i", g->bars() ); pattern_bars_choice->value( pat ); } if ( g->mapping.key() == -1 ) pattern_key_combo->deactivate(); else { pattern_key_combo->activate(); pattern_key_combo->value( g->mapping.key() ); } mapping_text->value( g->mapping.name() ); pattern_note_combo->value( find_numeric_menu_item( menu_pattern_note_combo, g->note() )); pattern_res_combo->value( find_numeric_menu_item( menu_pattern_res_combo, g->resolution() )); /* if ( g->notes() ) pattern_notes_buffer->text( g->notes() ); else pattern_notes_buffer->text( strdup( "" ) ); */ pattern_settings_group->redraw();} {} } Function {update_phrase_widgets()} {} { code {if ( ! phrase_canvas_widget ) return; phrase *g = (phrase *)phrase_canvas_widget->grid(); if ( ! g ) return; g->viewport.y = 0; g->viewport.h = pattern::patterns(); phrase_canvas_widget->resize_grid(); phrase_canvas_widget->changed_mapping(); phrase_number_spinner->value( g->number() ); phrase_name_field->value( g->name() ); phrase_solo_button->value( g->mode() == SOLO ); phrase_mute_button->value( g->mode() == MUTE ); if ( g->notes() ) phrase_notes_buffer->text( g->notes() ); else phrase_notes_buffer->text( strdup( "" ) ); phrase_settings_group->redraw();} {} } Function {update_sequence_widgets()} {} { code {if ( playlist->notes() ) sequence_notes_buffer->text( playlist->notes() ); else sequence_notes_buffer->text( strdup( "" ) ); sequence_name_field->value( playlist->name() ); sequence_phrase_choice->clear(); for ( int i = 1; i <= phrase::phrases(); i++ ) { phrase *p = phrase::phrase_by_number( i ); if ( p ) sequence_phrase_choice->add( p->name() ); } Fl_Browser *o = playlist_browser; int val = o->value(); o->clear(); char *s = playlist->dump(); char *l = strtok( s, "\\n" ); o->add( "@b@C2Bar\\t@b@C2\#\\t@b@C2Name" ); if ( ! l ) return; o->add( l ); while ( ( l = strtok( NULL, "\\n" ) ) ) { o->add( l ); } o->value( val ); free( s ); if ( playback_mode_menu ) playback_mode_menu->value( song.play_mode );} {} } Function {update_mapping_menu()} {} { code {char **sa = Instrument::listing(); if ( sa ) { for ( int i = 0; sa[i]; i++ ) { char pat[512]; snprintf( pat, 512, "Instrument/%s", sa[i] ); mapping_menu->add( pat, 0, 0, 0, 0 ); free( sa[i] ); } free( sa ); } sa = Scale::listing(); for ( int i = 0; sa[i]; i++ ) { char pat[512]; snprintf( pat, 512, "Scale/%s", sa[i] ); mapping_menu->add( pat, 0, 0, 0, 0 ); free( sa[i] ); } free( sa );} {} } Function {update_canvas_widgets()} {return_type {static void} } { code {if ( ui->pattern_canvas_widget->grid() ) ui->update_pattern_widgets(); if ( ui->phrase_canvas_widget->grid() ) ui->update_phrase_widgets();} {} } Function {find_numeric_menu_item( const Fl_Menu_Item *menu, int n )} {return_type {static int} } { code {for ( unsigned int i = 0; menu[i].text; i++ ) { if ( atoi( menu[i].text ) == n ) return i; } return 0;} {} } Function {save_dialog( const char *name )} {return_type void } { code {if ( ! name ) { Fl_File_Chooser *fc = new Fl_File_Chooser( ".", "Non Sequences (*.non)", Fl_File_Chooser::CREATE, "Save sequence" ); fc->show(); // wait for user to make a choice while( fc->shown() ) Fl::wait(); if ( ! fc->value() ) return; name = fc->value(); } if ( ! save_song( name ) ) fl_alert( "Could not save song" ); else gui_status( "Saved." );} {} } Function {show_help_dialog( const char *file )} {return_type void } { code {char pat[256]; snprintf( pat, 256, "file://%s/non-sequencer/%s.html", DOCUMENT_PATH, file ); open_url( pat );} {} } Function {maybe_save_song()} {return_type bool } { code {if ( song.dirty() ) { int c = fl_choice( "Song has been modified since last save. What shall I do?", "&Cancel", "&Save", "&Discard" ); switch ( c ) { case 0: return false; case 1: /* SAVE */ save_dialog( song.filename ); break; case 2: break; } } return true;} {} } Function {switch_to_pattern( int n )} {return_type void } { code {pattern *p = pattern::pattern_by_number( n ); if ( p ) { tabs->value( pattern_tab ); pattern_canvas_widget->take_focus(); pattern_canvas_widget->grid( p ); // update_pattern_widgets(); }} {} } Function {edit_instrument_row( Instrument *i, int n )} {return_type void } { code {Instrument_Editor ie; ie.set( i, n ); ie.run();} {} } Function {current_canvas()} {open return_type {Canvas*} } { code {if ( tabs->value() == pattern_tab ) return pattern_canvas_widget; else if ( tabs->value() == phrase_tab ) return phrase_canvas_widget; else return NULL;} {} } } class Instrument_Editor {} { Function {Instrument_Editor()} {open return_type void } { code {make_window();} {} } decl {Instrument *_inst;} {private local } decl {int _note;} {private local } Function {make_window()} {open } { Fl_Window window { label {Instrument Editor} callback {done->do_callback();} open xywh {670 458 335 190} type Double hide } { Fl_Box {} { label {Instrument Row} xywh {8 15 321 28} box ROUNDED_BOX color 94 labelsize 22 labelcolor 39 } Fl_Input name_field { label Name callback {_inst->note_name( _note, strdup( o->value() ) );} xywh {10 70 321 25} selection_color 48 align 1 when 1 textcolor 32 } Fl_Value_Slider volume_slider { label {Volume %} callback {_inst->velocity( _note, o->value() );} xywh {10 112 321 27} type Horizontal align 1 maximum 100 step 1 textsize 14 } Fl_Value_Output note_field { label {Note:} xywh {52 158 43 24} } Fl_Return_Button done { label Done callback {if ( _inst ) _inst->save(); window->hide();} xywh {255 157 76 25} } } } Function {set( Instrument *i, int n )} {open return_type void } { code {_inst = i; _note = n; volume_slider->value( i->velocity( n ) ); name_field->value( i->note_name( n ) ); note_field->value( n );} {} } Function {run()} {open return_type void } { code {window->show(); while ( window->shown() ) Fl::wait();} {} } } class Trigger {: {public Fl_Progress} } { Function {Trigger( int X, int Y, int W, int H, const char *L =0) : Fl_Progress( X, Y, W, H, L )} {open } { code {minimum( 0 ); maximum( 1 ); //angles( 0, 360 ); // type( Fl_Dial::ARC_DIAL ); // type(FL_VERTICAL);} {} } Function {handle( int m )} {open return_type int } { code {int r = 0; switch ( m ) { case FL_PUSH: { switch ( Fl::event_button() ) { case 1: { pattern *p = pattern::pattern_by_number( atoi( label() ) ); if ( p ) { if ( TRIGGER == song.play_mode ) { if ( p->playing() ) p->stop(); else p->trigger(); } else { if ( p->mode() == PLAY ) p->mode( MUTE ); else p->mode( PLAY ); } } break; } case 2: { pattern *p = pattern::pattern_by_number( atoi( label() ) ); if ( p ) { if ( p->mode() != SOLO ) p->mode( SOLO ); else p->mode( PLAY ); } break; } case 3: { ui->switch_to_pattern( atoi( label() ) ); } break; } r = 1; break; } case FL_RELEASE: do_callback(); r = 1; break; case FL_DRAG: r = 1; break; default: r = Fl_Widget::handle( m ); break; } return r;} {} } } widget_class Triggers { xywh {390 620 335 390} type Double hide code0 {\#include } code1 {populate();} class Fl_Group } { Function {populate( void )} {open private return_type void } { code {_timer = 0; for ( int i = 0; i < 128; i++ ) { Trigger *b = new Trigger( 1,1,1,1 ); char pat[4]; sprintf( pat, "%d",i +1); b->label( strdup( pat ) ); b->labelsize( 8 ); b->color2( FL_GRAY ); b->box( FL_FLAT_BOX ); // b->down_box( FL_ROUNDED_BOX ); b->selection_color( FL_GREEN ); b->color( FL_BLACK ); b->color2( FL_GREEN ); b->align( FL_ALIGN_CENTER ); add( b ); }} {} } Function {update( void )} {open return_type void } { code {++_timer; if ( !visible_r() ) return; if ( ! takesevents() ) return; Fl_Color mode_color[3]; mode_color[PLAY] = fl_color_average( FL_GRAY, FL_GREEN, 0.5 ); // mode_color[PLAY] = fl_color; mode_color[MUTE] = FL_LIGHT2; mode_color[SOLO] = fl_color_average( FL_GRAY, FL_RED, 0.5 ); if ( ! _rows ) return; for ( int i = 0; i < MAX_PATTERN; i++ ) { Trigger *b = (Trigger*)child( i ); if ( i >= pattern::patterns() ) { b->color( FL_BLACK ); b->value( 0 ); continue; } pattern *p = pattern::pattern_by_number( i + 1 ); if ( p->playing() ) { b->color( FL_GRAY ); b->selection_color( mode_color[ p->mode() ] ); if ( p->queue() >= 0 ) { if ( _timer % 16 < 8 ) { b->color( mode_color[ p->queue() ] ); } } b->value( (double)p->index() / p->length() ); } else { b->value( 0 ); } }} {} } decl {unsigned long _timer;} {private local } decl {int _rows;} {private local } Function {rows(int v)} {open return_type void } { code {_rows = v; redraw();} {} } Function {draw()} {open return_type void } { code {int _cols = 128 / _rows; int bw = w() / _cols; int bh = h() / _rows; int t = 0; for ( int i = 0; i < _rows; i++ ) for ( int j = 0; j < _cols ; j++, t++ ) child( t )->resize( x() + (bw * j), y() + (bh * i), bw, bh ); Fl_Group::draw();} {} } decl {\#include } {private local } } class List_Chooser {} { Function {List_Chooser( const char *name, const char *action )} {} { Fl_Window window {open xywh {525 313 310 545} type Single hide resizable non_modal size_range {310 524 0 0} } { Fl_Browser browser { label name xywh {5 26 300 480} type Multi box THIN_DOWN_BOX color 32 selection_color 0 align 1 textcolor 55 resizable code0 {o->label( name );} } Fl_Group {} {open xywh {5 505 300 39} } { Fl_Button {} { label Cancel callback {browser->clear(); window->hide();} xywh {5 513 75 27} } Fl_Return_Button button { label action callback {window->hide();} xywh {115 513 190 27} code0 {o->label( action );} } } } } Function {show()} {open } { code {window->show();} {} } Function {shown()} {open return_type bool } { code {return window->shown();} {} } Function {add( const char *item )} {open } { code {browser->add( item );} {} } } decl {float status_intensity;} {private local } Function {fade_status(void*)} {private return_type {static void} } { code {ui->status->labelcolor( fl_color_average( FL_FOREGROUND_COLOR, FL_BACKGROUND_COLOR, status_intensity ) ); status_intensity -= 0.01f; ui->status->redraw(); if ( status_intensity >= 0.01f ) Fl::repeat_timeout( 1 / 15.0f, fade_status );} {} } Function {gui_status( const char *fmt, ... )} {C return_type void } { code {va_list args; static char pat[256]; if ( fmt ) { va_start( args, fmt ); vsnprintf( pat, 256, fmt, args ); va_end( args ); } ui->status->label( pat ); ui->status->redraw(); status_intensity = 1.0f; Fl::remove_timeout( fade_status ); Fl::add_timeout( 1 / 15.0f, fade_status );} {} }