123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- #include <FL/Fl.H>
- #include <FL/Fl_Widget.H>
- #include <FL/Fl_Double_Window.H>
- #include <FL/Fl_Text_Buffer.H>
- #include <FL/Fl_Text_Display.H>
- #include <FL/Fl_Tabs.H>
- #include <FL/Fl_Menu_Item.H>
- #include <FL/Fl_Menu_Bar.H>
- #include <FL/Fl_Button.H>
- #include <FL/Fl_Check_Button.H>
- #include <FL/Fl_Menu_Button.H>
- #include <FL/Fl_Value_Input.H>
- #include <FL/Fl_Value_Slider.H>
- #include <FL/Fl_Input.H>
- #include <FL/Fl_Box.H>
- #include <FL/Fl_File_Chooser.H>
- #include <FL/fl_draw.H>
-
- #include "Fl_Splitter.h"
-
- #include "cmPrefix.h"
- #include "cmGlobal.h"
- #include "cmRpt.h"
- #include "cmErr.h"
- #include "cmCtx.h"
- #include "cmMem.h"
- #include "cmMallocDebug.h"
- #include "cmFileSys.h"
- #include "cmThread.h"
-
- #include "appErr.h"
- #include "app.h"
-
- class drawWnd : public Fl_Widget
- {
- public:
- drawWnd(app* ap, int x, int y, int w, int h, const char* label = NULL );
- virtual ~drawWnd();
-
- virtual int handle(int event);
- virtual void resize(int x, int y, int w, int h );
-
- protected:
- virtual void draw();
-
- private:
- app* _app;
- };
-
- drawWnd::drawWnd(app* ap, int x, int y, int w, int h, const char* label )
- : Fl_Widget(x,y,w,h,label),
- _app(ap)
- {}
-
- drawWnd::~drawWnd()
- {}
-
- int drawWnd::handle(int event)
- {
- switch(event)
- {
- case FL_PUSH:
- {
- const char* label;
- switch( Fl::event_button() )
- {
- case FL_LEFT_MOUSE: label = "left"; break;
- case FL_RIGHT_MOUSE: label = "right"; break;
- case FL_MIDDLE_MOUSE: label = "middle"; break;
- default:
- label = "none";
- }
-
- _app->print("%i %i %s\n",Fl::event_x(),Fl::event_y(),label);
- }
- break;
-
- default:
- return Fl_Widget::handle(event);
- }
-
- return 1;
- }
-
- void drawWnd::resize(int x, int y, int w, int h )
- {
- // must call base to make size change
- Fl_Widget::resize(x,y,w,h);
- }
-
- void drawWnd::draw()
- {
- int offs = 10;
- //fl_draw_box(FL_DOWN_BOX,x()+10,y()+10,w()-20,h()-20,FL_RED);
- //fl_frame("XXXX",x()+offs,y()+offs,w()-2*offs,h()-2*offs);
- fl_line_style(FL_SOLID,1,NULL);
- fl_color(FL_RED);
- fl_line(x()+offs,y()+offs,x()+w()-offs,y()+h()-offs);
-
-
- int x = w()/2;
- int y = h()/2;
-
- fl_color(FL_BLACK);
- fl_draw(90,"string",x,y);
-
- // XXXXXXX
- // X00000X
- // X00000X
- // X00X00X
- // X00000X
- // X00000X
- // XXXXXXX
-
- fl_rect(x-3,y-3,7,7);
- fl_point(x,y);
- }
-
- //----------------------------------------------------------------------------------------------------
- //----------------------------------------------------------------------------------------------------
- //----------------------------------------------------------------------------------------------------
-
- app::app(cmCtx_t* ctx, cmTsMp1cH_t printqH, int w, int h, const char* label, int argc, char* argv[])
- : Fl_Double_Window(w,h,label), _timerPeriodSecs(0),
- _ctx(ctx), _splt(NULL),_buf(NULL),_con(NULL),_tabs(NULL),_menu(NULL),
- _printqH(printqH),_printFl(0)
- {
-
- // install a callback to cleanup when the app window closes
- // (the btn and menu callbacks also rely on a pointer to 'this' being found in app.user_data()
- // see _getApp())
- callback(_s_callback,this);
-
- // the main window is divided between the menu bar on top
- // and a horizontal splitter on the bottom
- begin();
- createMenu(w,kMenuH);
- _splt = new Fl_HSplitter(0, kMenuH, w, h-kStatusH, h-kStatusH-100);
- end();
-
- // Create a text display object for console output and
- // add it to the lower splitter area
- _buf = new Fl_Text_Buffer();
- _con = new Fl_Text_Display(_splt->container2->x(),_splt->container2->y(),_splt->container2->w(),_splt->container2->h());
- _con->buffer(_buf);
- _splt->container2->add(_con);
-
- // create tabbed windows
- const char* titles[] = { "Title 1", "Title 2" };
- _create_tabs(2,titles);
-
- // make the splitter the resizable group element (thereby making the menu non-resizable).
- // see:http://fltk.org/articles.php?L415+I0+T+M1000+P1
- resizable(_splt);
- show(argc, argv);
-
- // The application is now visible.
- // direct all output to the console window
- cmRptSetup(&_ctx->rpt,_s_print,_s_print, this);
- cmTsMp1cSetCbFunc(_printqH, _s_print_queue_cb, this );
-
-
- // install a timer
- _timerPeriodSecs = 0.1;
- Fl::add_timeout(_timerPeriodSecs,app::_s_timer_cb,this);
-
- // install an idle callback
- //Fl::add_idle(_s_idle_cb,this);
-
- print("Started!\n");
- }
-
- app::~app()
- {}
-
- void app::createControls(Fl_Group* grp)
- {
- const int vBord = 3;
- const int ctl_width = 100;
- int xx = grp->x() + 5;
- int yy = grp->y() + vBord;
-
- Fl_Check_Button* cbt = new Fl_Check_Button(xx,yy,ctl_width,kCtlH,"Check");
- cbt->callback( _s_btn_cb, kBtn1MId );
- yy += cbt->h() + vBord;
-
- Fl_Button* btn = new Fl_Button(xx,yy,ctl_width,kCtlH,"Button");
- btn->callback( _s_btn_cb, kBtn2MId );
- yy += btn->h() + vBord;
-
- // menu buttons callback through menuCallback() not btnCallback()
- Fl_Menu_Button* mbt = new Fl_Menu_Button(xx,yy,ctl_width,kCtlH,"Menu");
-
- mbt->add("Item 1",0,_s_menu_btn_cb, (void*)kMenuBtn1MId, 0);
- mbt->add("Item 2",0,_s_menu_btn_cb, (void*)kMenuBtn2MId, 0);
- yy += mbt->h() + vBord;
-
- Fl_Value_Input* vip = new Fl_Value_Input(xx,yy,ctl_width/2,kCtlH,"Value In");
- vip->callback(_s_value_cb, kValue1MId );
- vip->align(FL_ALIGN_RIGHT); // place label to the right of the input ctl
- // Only make the callback when the enter key is struck or the ctl loses focus and the value has changed.
- // Removing this line causes the callback whenever the input changes.
- vip->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE );
- vip->bounds(-10.0,10.0);
- vip->step(0.1);
- yy += vip->h() + vBord;
-
- Fl_Value_Slider* sdp = new Fl_Value_Slider(xx,yy,ctl_width,kCtlH,"Slider");
- sdp->callback(_s_value_cb, kValue2MId );
- sdp->align(FL_ALIGN_RIGHT);
- sdp->type(FL_HOR_NICE_SLIDER);
- sdp->bounds(-10.0,10.0);
- sdp->step(0.1);
- yy += sdp->h() + vBord;
-
- Fl_Input* inp = new Fl_Input(xx,yy,ctl_width/2,kCtlH,"Text");
- inp->callback(_s_input_cb,kInput1MId);
- inp->align(FL_ALIGN_RIGHT);
- yy += inp->h() + vBord;
-
-
- }
-
-
- void app::initializeTab(int tabIndex, int x, int y, int w, int h, const char* label)
- {
- switch(tabIndex)
- {
- case 0:
- {
- Fl_Group* grp = new Fl_Group(x,y,w,h,label);
- grp->begin();
- createControls(grp);
- grp->end();
- }
- break;
-
- case 1:
- {
- Fl_Group* grp = new Fl_Group(x,y,w,h,label);
- grp->begin();
- _draw = new drawWnd(this,x,y,w,h,NULL);
- grp->end();
- }
- break;
- }
-
- }
-
- void app::createMenu(int w, int h)
- {
- Fl_Menu_Item items[] =
- {
- { "&File", 0, 0, 0, FL_SUBMENU },
- { "&New File", FL_COMMAND + 'n', (Fl_Callback*)_s_menu_cb, (void*)kFileNewMId },
- { "&Open File", FL_COMMAND + 'o', (Fl_Callback*)_s_menu_cb, (void*)kFileOpenMId },
- { 0 },
- { "&Edit", 0, 0, 0, FL_SUBMENU },
- { "&Copy", FL_COMMAND + 'c', (Fl_Callback*)_s_menu_cb, (void*)kEditCopyMId },
- { "&Paste", FL_COMMAND + 'v', (Fl_Callback*)_s_menu_cb, (void*)kEditPasteMId },
- { 0 },
- { 0 }
- };
-
- _menu = new Fl_Menu_Bar(0,0,w,h);
- _menu->copy(items);
- }
-
- void app::menuCallback(const Fl_Menu_Item* mip, long int id)
- {
- switch(id)
- {
- case kFileOpenMId:
- {
- // file chooser demo
-
- const char* pathStr = cmFsUserDir(); // make the default dir the user's home dir
- const char patStr[] = "Text Files (*.txt)\tAudio Files (*.{wav,aif,aiff})"; // All Files (*.*) is append to this automatically
- const char titleStr[] = "Select files";
-
- Fl_File_Chooser fc = Fl_File_Chooser(pathStr,patStr,Fl_File_Chooser::MULTI,titleStr);
-
- fc.preview(0); // default the previous option to 'off'.
- fc.show(); // show the chooser
-
- // make the chooser modal
- while( fc.shown() )
- Fl::wait();
-
- // print the selected files
- int i;
- for(i=1; i<=fc.count(); ++i)
- print("%i %s\n",i,cmStringNullGuard(fc.value(i)));
-
- }
- break;
- }
-
- print("%i %s\n",id,mip->label());
- }
-
- void app::btnCallback(const Fl_Button* bp, int id )
- {
- print("%i %s %i\n",id,bp->label(),bp->value());
- }
-
- void app::valueCallback(const Fl_Valuator* vp, int id )
- {
- print("%i %s %f\n",id,vp->label(),vp->value());
- }
-
- void app::inputCallback(const Fl_Input* ip, int id )
- {
- print("%i %s %s\n",id,ip->label(),ip->value());
- }
-
- void app::appCallback(Fl_Widget* wp)
- {
- switch( Fl::event() )
- {
- case FL_CLOSE:
- {
-
- /*
- int cc = _closeCnt;
-
- // attempt to shut down the pgm
- _closeCnt += finalizePgm() == false;
-
- // the first time the pgm fails to shut down
- // do not allow the pgm to close the main window
- // this will give a chance for the error messages
- // to be diplayed in the console - all successive
- // times the return value from finalizePgm() is
-
- // ignored and the program is terminated.
- if( _closeCnt == 1 && cc==0)
- {
- // send a strong hint that a problem occurred on shutdown
- // and prevent the app from receiving events that might cause it to
- // crash
- deactivate();
- return;
- }
- */
-
- // When all windows are windows are closed then the app.
- // will close - so hiding the application window
- // causes the program to close.
- //
- // Note that simply returning from this callback will
- // prevent the application from closing. Because the existence
- // of the callback alone is enough to disable default
- // event handling.
- hide();
- }
- break;
- }
-
- }
- bool app::idleCallback()
- { return true; }
-
-
- bool app::timerCallback()
- {
- _checkPrintQueue();
- return true;
- }
-
- void app::error( const char* fmt, ... )
- {
- va_list vl;
- va_start(vl,fmt);
-
- int bufCharCnt = 511;
- char buf[bufCharCnt+1];
-
- int n = vsnprintf(buf,bufCharCnt,fmt,vl);
-
- if( n > 0 )
- print("%s Error: %s\n",label(),buf);
-
- va_end(vl);
- }
-
- void app::vprint(const char* fmt, va_list vl )
- {
- int bufCharCnt = 511;
- char buf[bufCharCnt+1];
-
- int n = vsnprintf(buf,bufCharCnt,fmt,vl);
-
- if( n > 0 )
- {
- // if the print queue exists (it might not during startup or shutdown) ...
- if( cmTsMp1cIsValid(_printqH) )
- {
- cmThRC_t thRC;
-
- // ... enqueue the text to print
- if((thRC = cmTsMp1cEnqueueMsg(_printqH,buf,n+1)) != kOkThRC && _printFl==0 )
- {
- // Print queue error msg's directly to stdout rather than throught
- // the error mechanism - this prevents generating a stack overflow
- // when the print queue runs out of space and attempts to print a
- // 'queue out of memory' error msg.
- // The queue itself does will not print errors because it does
- // not have a valid cmRpt_t pointer. See cmMp1cCreate() above.
- ++_printFl;
- cmErrMsg(&_ctx->err,kQueueFailAppRC,"Print enqueue failed.");
- --_printFl;
- }
- }
- else
- _print(buf); // ... otherwise just send the text directly to the output console
- }
-
- }
-
- void app::print( const char* fmt, ... )
- {
- va_list vl;
- va_start(vl,fmt);
- vprint(fmt,vl);
- va_end(vl);
- }
-
- void app::_s_menu_cb(Fl_Widget* wp, void* data)
- {
- const Fl_Menu_Item* mip;
- app* ap;
-
- if((ap=_getApp(wp)) != NULL )
- if((mip = ap->_menu->mvalue()) != NULL )
- ap->menuCallback(mip,(long int)mip->user_data());
- }
-
- void app::_s_menu_btn_cb(Fl_Widget* wp, void* data)
- {
- const Fl_Menu_Button* bp;
- const Fl_Menu_Item* mip;
- app* ap;
-
- if((ap=_getApp(wp)) != NULL )
- if((bp = static_cast<Fl_Menu_Button*>(wp)) != NULL )
- if((mip = bp->mvalue()) != NULL)
- ap->menuCallback(mip,(long int)data);
- }
-
- void app::_s_btn_cb(Fl_Widget* wp, long data )
- {
- app* ap;
-
- if((ap = _getApp(wp)) != NULL )
- if( wp != NULL )
- ap->btnCallback( static_cast<const Fl_Button*>(wp),data);
- }
-
- void app::_s_value_cb( Fl_Widget* wp, long data)
- {
- app* ap;
- Fl_Valuator* vp;
-
- if((ap = _getApp(wp)) != NULL )
- if((vp = static_cast<Fl_Valuator*>(wp)) != NULL)
- ap->valueCallback(vp,data);
- }
-
- void app::_s_input_cb( Fl_Widget* wp, long data)
- {
- app* ap;
- Fl_Input* inp;
-
- if((ap = _getApp(wp)) != NULL)
- if((inp = static_cast<Fl_Input*>(wp)) != NULL )
- ap->inputCallback(inp,data);
- }
-
- void app::_s_callback(Fl_Widget* wp, void* data)
- { ((app*)data)->appCallback(wp); }
-
- void app::_s_idle_cb(void *data)
- {
- app* thisPtr = (app*)data;
-
- if( thisPtr->idleCallback() == false )
- Fl::remove_idle(_s_idle_cb,data);
- }
-
- void app::_s_timer_cb(void* userPtr)
- {
- app* thisPtr = (app*)userPtr;
-
- if( thisPtr->timerCallback() )
- Fl::repeat_timeout(thisPtr->_timerPeriodSecs,_s_timer_cb,userPtr);
- }
-
- void app::_s_print( void* userPtr, const char* text )
- { ((app*)userPtr)->print(text); }
-
-
- void app::_create_tabs(int titleCnt, const char* titleArray[])
- {
- // Create a tab view and added it to the upper splitter area
- _tabs = new Fl_Tabs(_splt->container1->x(),_splt->container1->y(),_splt->container1->w(),_splt->container1->h());
- _splt->container1->add(_tabs);
-
- int tx,ty,th,tw,i;
- _tabs->client_area(tx,ty,tw,th);
-
- for(i=0; i<titleCnt; ++i)
- {
- _tabs->begin();
- initializeTab(i,tx,ty,tw,th,titleArray[i]);
- _tabs->end();
- }
-
- // Create an empty tab group and make it resizable
- // to prevent the other tab groups from being resizable.
- _tabs->begin();
- _tabs->resizable(new Fl_Group(tx,ty+30,1,1));
- _tabs->end();
- }
-
- app* app::_getApp( Fl_Widget* w )
- {
- // walk up the widget tree until the top widget is found
- Fl_Group* gp = w->parent();
- while( gp->parent() != NULL )
- gp=gp->parent();
-
- // the user data for the top widget is a pointer app - as set in: callback(_s_callback,this);
- return (app*)gp->user_data();
- }
-
- cmRC_t app::_s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
- {
- app* ap = (app*)userCbPtr;
- ap->_print((const char*)msgDataPtr);
- return cmOkRC;
- }
-
- void app::_checkPrintQueue()
- {
- while( cmTsMp1cMsgWaiting(_printqH) )
- if( cmTsMp1cDequeueMsg(_printqH, NULL, 0) != kOkThRC )
- error("Print dequeue failed.");
- }
-
- void app::_print( const char* text )
- {
- if( _con != NULL )
- _con->insert(text);
- }
|