Programmable real-time audio signal processing application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmUiDrvrFltk.cpp 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. //| Copyright: (C) 2019-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include <FL/Fl.H>
  4. #include <FL/Fl_Widget.H>
  5. #include <FL/Fl_Group.H>
  6. #include <FL/Fl_Tabs.H>
  7. #include <FL/Fl_Button.H>
  8. #include <FL/Fl_Check_Button.H>
  9. #include <FL/Fl_Box.H>
  10. #include <Fl/Fl_Input.H>
  11. #include <Fl/Fl_Value_Input.H>
  12. #include <Fl/Fl_Value_Slider.H>
  13. #include <Fl/Fl_Progress.H>
  14. #include <Fl/Fl_Menu_Button.H>
  15. #include <Fl/Fl_Select_Browser.H>
  16. #include <Fl/Fl_Text_Display.H>
  17. #include <FL/fl_draw.H>
  18. #include "Fl_File_Btn.h"
  19. #include "Fl_Vert_Progress.h"
  20. #include "cmGlobal.h"
  21. #include "cmRpt.h"
  22. #include "cmErr.h"
  23. #include "cmCtx.h"
  24. #include "cmMem.h"
  25. #include "cmMallocDebug.h"
  26. #include "cmRtSysMsg.h"
  27. #include "cmUiDrvr.h"
  28. #include "cmUiDrvrFltk.h"
  29. cmUiDrvrFltk::cmUiDrvrFltk(cmCtx_t* ctx, Fl_Tabs* tabs, cmUiDriverFunc_t cbFunc, void* cbArg)
  30. : _tabs(NULL),_cbFunc(NULL),_cbArgs(NULL),_panels(NULL)
  31. {
  32. cmErrSetup(&_err,&ctx->rpt,"cmUiDrvrFltk");
  33. setBaseWindow(tabs);
  34. setCallback(cbFunc,cbArg);
  35. }
  36. void cmUiDrvrFltk::setBaseWindow( Fl_Tabs* tabs )
  37. {
  38. _tabs = tabs;
  39. if( _tabs != NULL )
  40. _tabs->callback(_s_tab_cb,this);
  41. }
  42. void cmUiDrvrFltk::setCallback( cmUiDriverFunc_t cbFunc, void* cbArg )
  43. {
  44. _cbFunc = cbFunc;
  45. _cbArgs = cbArg;
  46. }
  47. cmUiDrvrFltk::~cmUiDrvrFltk()
  48. {
  49. _destroyAllPanels(false);
  50. }
  51. cmUiRC_t cmUiDrvrFltk::cmUiDriverFunc( void* cbArg, const cmUiDriverArg_t* args )
  52. {
  53. cmUiDrvrFltk* p = (cmUiDrvrFltk*)cbArg;
  54. cmUiRC_t rc = kOkUiRC;
  55. switch(args->dId)
  56. {
  57. case kInvalidDId:
  58. break;
  59. case kCreateCtlDId:
  60. rc = p->_createCtl(args);
  61. break;
  62. case kDestroyCtlDId:
  63. rc = p->_destroyCtl(args->appId,args->panelId,args->usrId,true);
  64. break;
  65. case kSetValDId:
  66. rc = p->_setValueCtl(args);
  67. break;
  68. case kEnableDId:
  69. rc = p->_enableCtl(args);
  70. break;
  71. //case kDestroyAllDId:
  72. //rc = p->_destroyAllPanels(true);
  73. //break;
  74. case kMaxDId:
  75. assert(0);
  76. break;
  77. }
  78. return rc;
  79. }
  80. void cmUiDrvrFltk::_insertNewCtl( panel_t* pp, ctl_t* ctl, Fl_Widget* wp, unsigned flags )
  81. {
  82. ctl->wdgt = wp;
  83. if( ctl->usrId != cmInvalidId )
  84. {
  85. ctl->link = pp->ctls;
  86. pp->ctls = ctl;
  87. wp->callback( _s_ctl_cb, ctl );
  88. }
  89. pp->grp->add(wp);
  90. int align_flags = 0;
  91. if( cmIsFlag(flags,kLeftUiFl)) align_flags |= FL_ALIGN_LEFT;
  92. if( cmIsFlag(flags,kTopUiFl)) align_flags |= FL_ALIGN_TOP;
  93. if( cmIsFlag(flags,kRightUiFl)) align_flags |= FL_ALIGN_RIGHT;
  94. if( cmIsFlag(flags,kBottomUiFl)) align_flags |= FL_ALIGN_BOTTOM;
  95. if( cmIsFlag(flags,kHCtrUiFl)) align_flags |= FL_ALIGN_CENTER;
  96. if( cmIsFlag(flags,kInsideUiFl)) align_flags |= FL_ALIGN_INSIDE;
  97. if( cmIsFlag(flags,kVCtrUiFl)) align_flags = cmClrFlag(align_flags,FL_ALIGN_TOP | FL_ALIGN_BOTTOM);
  98. wp->align(align_flags);
  99. int when_flags = 0;
  100. if( cmIsFlag(flags,kSendChangeFl)) when_flags |= FL_WHEN_CHANGED;
  101. if( cmIsFlag(flags,kSendEnterFl)) when_flags |= FL_WHEN_ENTER_KEY;
  102. if( cmIsFlag(flags,kSendFocusFl)) when_flags |= FL_WHEN_RELEASE;
  103. if( cmIsFlag(flags,kSendNoChangeFl)) when_flags |= FL_WHEN_NOT_CHANGED;
  104. if( when_flags != 0 )
  105. wp->when(when_flags);
  106. }
  107. bool cmUiDrvrFltk::_hasNoAlignFlags( unsigned flags ) const
  108. {
  109. return !cmIsFlag(flags, kLeftUiFl | kTopUiFl | kRightUiFl | kBottomUiFl | kVCtrUiFl | kHCtrUiFl );
  110. }
  111. cmUiRC_t cmUiDrvrFltk::_createCtl( const cmUiDriverArg_t* a )
  112. {
  113. cmUiRC_t rc;
  114. panel_t* pp;
  115. panel_t* prvPnl;
  116. // if this is a panel create request
  117. if( a->cId == kPanelUiCId )
  118. return _createPanel(a);
  119. // locate the new control's panel
  120. if((rc = _findPanel(a->appId,a->panelId,pp,prvPnl)) != kOkUiRC )
  121. return rc;
  122. // allocate the control record
  123. ctl_t* ctl ;
  124. if( a->usrId == cmInvalidId )
  125. ctl = &_dummy;
  126. else
  127. ctl = cmMemAllocZ(ctl_t,1);
  128. ctl->cId = a->cId;
  129. ctl->pnl = pp;
  130. ctl->usrId = a->usrId;
  131. ctl->flags = a->flags;
  132. int x = a->x + pp->x_offs;
  133. int y = a->y + pp->y_offs;
  134. // cache the event callback arg record so that it
  135. // does not have to be filled on every callback.
  136. cmUiDriverArgSetup(&ctl->cbArg,a->hdr.rtSubIdx,kUiDrvrSelRtId,kInvalidDId,pp->appId,a->usrId,pp->usrId,a->cId,0,0,0,NULL,x,y,a->w,a->h);
  137. //printf("%i %i %i %i\n",x,y,a->w,a->h);
  138. switch(a->cId)
  139. {
  140. case kInvalidUiCId:
  141. assert(0);
  142. break;
  143. case kPanelUiCId:
  144. break;
  145. case kBtnUiCId:
  146. ctl->u.btn = new Fl_Button(x,y,a->w,a->h,a->sval);
  147. _insertNewCtl(pp,ctl,ctl->u.btn,a->flags);
  148. ctl->cbArg.flags |= kIvalUiFl;
  149. break;
  150. case kCheckUiCId:
  151. ctl->u.chk = new Fl_Check_Button(x,y,a->w,a->h,a->sval);
  152. _insertNewCtl(pp,ctl,ctl->u.chk,a->flags);
  153. ctl->cbArg.flags |= kIvalUiFl;
  154. ctl->u.chk->value(a->ival);
  155. break;
  156. case kMenuBtnUiCId:
  157. ctl->u.mbt = new Fl_Menu_Button(x,y,a->w,a->h,a->sval!=NULL ? a->sval : NULL);
  158. _insertNewCtl(pp,ctl,ctl->u.mbt,a->flags);
  159. ctl->cbArg.flags |= kIvalUiFl;
  160. ctl->u.mbt->value(0);
  161. break;
  162. case kListUiCId:
  163. ctl->u.lst = new Fl_Select_Browser(x,y,a->w,a->h);
  164. _insertNewCtl(pp,ctl,ctl->u.lst,a->flags);
  165. ctl->cbArg.flags |= kIvalUiFl;
  166. break;
  167. case kLabelUiCId:
  168. {
  169. unsigned flags = a->flags;
  170. ctl->u.lbl = new Fl_Box(x,y,a->w,a->h);
  171. ctl->u.lbl->copy_label(a->sval);
  172. if( _hasNoAlignFlags(flags) )
  173. flags |= kHCtrUiFl | kInsideUiFl;
  174. _insertNewCtl(pp,ctl,ctl->u.lbl,flags);
  175. }
  176. break;
  177. case kStringUiCId:
  178. {
  179. unsigned flags = a->flags;
  180. ctl->u.str = new Fl_Input(x,y,a->w/2,a->h);
  181. ctl->u.str->copy_label(a->sval);
  182. if( _hasNoAlignFlags(flags) )
  183. flags |= kRightUiFl;
  184. _insertNewCtl(pp,ctl,ctl->u.str,flags);
  185. ctl->cbArg.flags |= kSvalUiFl;
  186. }
  187. break;
  188. case kConsoleUiCId:
  189. {
  190. unsigned flags = a->flags;
  191. ctl->u.con = new Fl_Text_Display(x,y,a->w,a->h);
  192. ctl->u.con->buffer(new Fl_Text_Buffer());
  193. ctl->u.con->textsize(12);
  194. ctl->u.con->textfont(FL_COURIER);
  195. ctl->u.con->copy_label(a->sval);
  196. if( _hasNoAlignFlags(flags) )
  197. flags |= kRightUiFl;
  198. _insertNewCtl(pp,ctl,ctl->u.con,flags);
  199. ctl->cbArg.flags |= kSvalUiFl;
  200. }
  201. break;
  202. case kSliderUiCId:
  203. {
  204. unsigned flags = a->flags;
  205. int w = a->w;
  206. int h = a->h;
  207. if( cmIsFlag(flags,kHorzUiFl) )
  208. {
  209. if( _hasNoAlignFlags(flags) )
  210. flags |= kRightUiFl;
  211. w /= 2;
  212. }
  213. if( cmIsFlag(flags,kVertUiFl) )
  214. {
  215. if( _hasNoAlignFlags(flags) )
  216. flags |= kTopUiFl | kHCtrUiFl;
  217. if( a->sval != NULL )
  218. {
  219. int hh,ww;
  220. fl_measure(a->sval,ww,hh);
  221. if( flags & kTopUiFl )
  222. {
  223. y += hh;
  224. h -= hh;
  225. }
  226. if( flags & kBottomUiFl)
  227. h -= hh;
  228. }
  229. }
  230. ctl->u.sld = new Fl_Value_Slider(x,y,w,h);
  231. ctl->u.sld->copy_label(a->sval);
  232. if( cmIsFlag(flags,kHorzUiFl) )
  233. ctl->u.sld->type(FL_HOR_NICE_SLIDER);
  234. if( cmIsFlag(flags,kVertUiFl) )
  235. ctl->u.sld->type(FL_VERT_NICE_SLIDER);
  236. _insertNewCtl(pp,ctl,ctl->u.sld,flags);
  237. ctl->cbArg.flags |= kFvalUiFl;
  238. }
  239. break;
  240. case kNumberUiCId:
  241. {
  242. unsigned flags = a->flags;
  243. ctl->u.num = new Fl_Value_Input(x,y,a->w/2,a->h);
  244. ctl->u.num->copy_label(a->sval);
  245. if( _hasNoAlignFlags(flags) )
  246. flags |= kRightUiFl;
  247. _insertNewCtl(pp,ctl,ctl->u.num,flags);
  248. ctl->cbArg.flags |= kFvalUiFl;
  249. ctl->u.num->when(FL_WHEN_ENTER_KEY | FL_WHEN_NOT_CHANGED );
  250. }
  251. break;
  252. case kProgressUiCId:
  253. {
  254. unsigned flags = a->flags;
  255. ctl->u.prg = new Fl_Progress(x,y,a->w/2,a->h);
  256. ctl->u.prg->copy_label(a->sval);
  257. if( _hasNoAlignFlags(flags) )
  258. flags |= kRightUiFl;
  259. _insertNewCtl(pp,ctl,ctl->u.prg,flags);
  260. ctl->u.prg->color( fl_rgb_color((unsigned char)256),fl_rgb_color((unsigned char)128));
  261. }
  262. break;
  263. case kMeterUiCId:
  264. {
  265. unsigned flags = a->flags;
  266. if( cmIsFlag(flags,kVertUiFl) )
  267. {
  268. ctl->u.mtr = new Fl_Vert_Progress(x,y,a->w/2,a->h);
  269. ctl->u.mtr->color( fl_rgb_color((unsigned char)256),fl_rgb_color((unsigned char)128));
  270. }
  271. else
  272. {
  273. ctl->u.mtr = new Fl_Progress(x,y,a->w,a->h);
  274. ctl->u.mtr->color( fl_rgb_color((unsigned char)256),fl_rgb_color((unsigned char)128));
  275. }
  276. ctl->u.mtr->copy_label(a->sval);
  277. if( _hasNoAlignFlags(flags) )
  278. flags |= kRightUiFl;
  279. _insertNewCtl(pp,ctl,ctl->u.mtr,flags);
  280. }
  281. break;
  282. case kFilenameUiCId:
  283. case kDirUiCId:
  284. {
  285. unsigned flags = a->cId==kDirUiCId ? Fl_File_Btn::kDir_Type_Id : Fl_File_Btn::kFile_Type_Id;
  286. ctl->u.fnb = new Fl_File_Btn(flags,"",x,y,a->w,a->h,a->sval);
  287. flags = a->flags;
  288. if( _hasNoAlignFlags(flags) )
  289. flags |= kRightUiFl;
  290. _insertNewCtl(pp,ctl,ctl->u.fnb,flags);
  291. ctl->cbArg.flags |= kSvalUiFl;
  292. }
  293. break;
  294. case kMaxUiCId:
  295. assert(0);
  296. break;
  297. }
  298. pp->grp->redraw();
  299. return rc;
  300. }
  301. cmUiRC_t cmUiDrvrFltk::_setValueCtl( const cmUiDriverArg_t* a )
  302. {
  303. cmUiRC_t rc;
  304. panel_t* pp = NULL;
  305. panel_t* prvPnl = NULL;
  306. ctl_t* ctl = NULL;
  307. ctl_t* prvCtl = NULL;
  308. if((rc = _findPanel(a->appId,a->panelId,pp,prvPnl)) != kOkUiRC )
  309. return rc;
  310. if((rc= _findCtl(pp, a->usrId, ctl, prvCtl )) != kOkUiRC )
  311. return rc;
  312. switch( a->cId )
  313. {
  314. case kInvalidUiCId:
  315. break;
  316. case kPanelUiCId:
  317. break;
  318. case kBtnUiCId:
  319. if( cmIsFlag(a->flags,kLblUiFl) )
  320. ctl->u.btn->copy_label(a->sval);
  321. break;
  322. case kCheckUiCId:
  323. switch( a->flags & (kLblUiFl | kValUiFl) )
  324. {
  325. case kValUiFl: ctl->u.chk->value(a->ival); break;
  326. case kLblUiFl: ctl->u.chk->copy_label(a->sval); break;
  327. }
  328. break;
  329. case kMenuBtnUiCId:
  330. switch( a->flags & (kAppendUiFl | kClearUiFl | kValUiFl) )
  331. {
  332. case kValUiFl:
  333. if( a->ival < ctl->u.mbt->size() )
  334. {
  335. ctl->u.mbt->value(a->ival);
  336. if( ctl->u.mbt->mvalue() != NULL)
  337. ctl->u.mbt->copy_label( ctl->u.mbt->mvalue()->label());
  338. }
  339. break;
  340. case kClearUiFl:
  341. ctl->u.mbt->clear();
  342. ctl->u.mbt->copy_label("");
  343. break;
  344. case kAppendUiFl:
  345. {
  346. int n;
  347. ctl->u.mbt->add( a->sval,0,ctl->u.mbt->callback(),ctl->u.mbt->user_data(),0);
  348. n = ctl->u.mbt->size();
  349. if( (n) == 2 )
  350. {
  351. ctl->u.mbt->value(0);
  352. if( ctl->u.mbt->mvalue() != NULL)
  353. {
  354. const char* s = ctl->u.mbt->mvalue()->label();
  355. ctl->u.mbt->copy_label( s);
  356. }
  357. }
  358. }
  359. break;
  360. }
  361. break;
  362. case kListUiCId:
  363. switch( a->flags & (kAppendUiFl | kClearUiFl | kValUiFl) )
  364. {
  365. case kValUiFl: ctl->u.lst->value(a->ival); break;
  366. case kAppendUiFl: ctl->u.lst->add( a->sval ); break;
  367. case kClearUiFl: ctl->u.lst->clear(); break;
  368. }
  369. break;
  370. case kLabelUiCId:
  371. ctl->u.str->value(a->sval);
  372. break;
  373. case kStringUiCId:
  374. switch( a->flags & (kLblUiFl | kValUiFl) )
  375. {
  376. case kValUiFl: ctl->u.str->value(a->sval); break;
  377. case kLblUiFl: ctl->u.str->copy_label(a->sval); break;
  378. }
  379. break;
  380. case kConsoleUiCId:
  381. switch( a->flags & (kLblUiFl | kValUiFl) )
  382. {
  383. case kValUiFl: if(a->sval!=NULL) ctl->u.con->insert(a->sval); break;
  384. case kLblUiFl: ctl->u.str->copy_label(a->sval); break;
  385. }
  386. break;
  387. case kSliderUiCId:
  388. case kNumberUiCId:
  389. {
  390. Fl_Valuator* vp = static_cast<Fl_Valuator*>(ctl->wdgt);
  391. // Correct for problem where the vertical slider values go up as the
  392. // slider knob is dragged down.
  393. bool invertFl = a->cId == kSliderUiCId && cmIsFlag(ctl->flags,kVertUiFl);
  394. switch(a->flags & (kNumMask | kLblUiFl | kMinUiFl | kMaxUiFl))
  395. {
  396. case kLblUiFl: ctl->u.num->copy_label(a->sval); break;
  397. case kValUiFl: vp->value(a->fval); break;
  398. case kIncUiFl: vp->step(a->fval); break;
  399. case kMinUiFl: invertFl ? vp->maximum(a->fval) : vp->minimum(a->fval); break;
  400. case kMaxUiFl: invertFl ? vp->minimum(a->fval) : vp->maximum(a->fval); break;
  401. }
  402. }
  403. break;
  404. case kProgressUiCId:
  405. switch( a->flags & (kLblUiFl | kValUiFl | kMinUiFl | kMaxUiFl) )
  406. {
  407. case kValUiFl: ctl->u.prg->value(a->ival); break;
  408. case kLblUiFl: ctl->u.prg->copy_label(a->sval); break;
  409. case kMinUiFl: ctl->u.prg->minimum(a->ival); break;
  410. case kMaxUiFl: ctl->u.prg->maximum(a->ival); break;
  411. }
  412. break;
  413. case kMeterUiCId:
  414. switch( a->flags & (kLblUiFl | kValUiFl | kMinUiFl | kMaxUiFl) )
  415. {
  416. case kValUiFl: ctl->u.mtr->value(a->ival); ctl->u.mtr->redraw(); break;
  417. case kLblUiFl: ctl->u.mtr->copy_label(a->sval); break;
  418. case kMinUiFl: ctl->u.prg->minimum(a->ival); break;
  419. case kMaxUiFl: ctl->u.prg->maximum(a->ival); break;
  420. }
  421. break;
  422. case kFilenameUiCId:
  423. case kDirUiCId:
  424. switch(a->flags & (kFnMask | kValUiFl | kFnPatUiFl | kFnDirUiFl) )
  425. {
  426. case kValUiFl:
  427. ctl->u.fnb->filename(a->sval);
  428. break;
  429. case kFnPatUiFl: ctl->u.fnb->pattern_string(a->sval); break;
  430. case kFnDirUiFl:
  431. ctl->u.fnb->type( ctl->u.fnb->type()==Fl_File_Btn::kFile_Type_Id ? Fl_File_Btn::kDir_Type_Id : Fl_File_Btn::kFile_Type_Id );
  432. break;
  433. }
  434. break;
  435. case kMaxUiCId:
  436. assert(0);
  437. break;
  438. }
  439. // echo the result back to the UI
  440. //if( cmIsFlag(a->flags,kValUiFl|kAppendUiFl) )
  441. // _cbFunc(_cbArgs,a);
  442. return rc;
  443. }
  444. cmUiRC_t cmUiDrvrFltk::_enableCtl( const cmUiDriverArg_t* a )
  445. {
  446. cmUiRC_t rc;
  447. panel_t* pp = NULL;
  448. panel_t* prvPnl = NULL;
  449. ctl_t* ctl = NULL;
  450. ctl_t* prvCtl = NULL;
  451. if((rc = _findPanel(a->appId,a->panelId,pp,prvPnl)) != kOkUiRC )
  452. return rc;
  453. if((rc= _findCtl(pp, a->usrId, ctl, prvCtl )) != kOkUiRC )
  454. return rc;
  455. if( a->ival )
  456. ctl->wdgt->activate();
  457. else
  458. ctl->wdgt->deactivate();
  459. _doCb(ctl,kEnableDId,0);
  460. return rc;
  461. }
  462. cmUiRC_t cmUiDrvrFltk::_destroyCtl( unsigned appId, unsigned panelId, unsigned usrId, bool deleteWindowEleFlag )
  463. {
  464. cmUiRC_t rc = kOkUiRC;
  465. panel_t* pp = NULL;
  466. panel_t* prvPnl = NULL;
  467. // locate the panel assoc'd with the ctl
  468. if((rc = _findPanel(appId,panelId,pp,prvPnl,true)) != kOkUiRC )
  469. return rc;
  470. // if the panel is the ctl to delete ...
  471. if( usrId == pp->usrId )
  472. {
  473. // ... unlink the panel
  474. if( prvPnl!=NULL)
  475. prvPnl->link = pp->link;
  476. else
  477. {
  478. assert(_panels == pp );
  479. _panels = pp->link;
  480. }
  481. }
  482. return _destroyCtl(pp,usrId,deleteWindowEleFlag);
  483. }
  484. cmUiRC_t cmUiDrvrFltk::_destroyCtl( panel_t* pp, unsigned usrId, bool deleteWindowEleFlag )
  485. {
  486. cmUiRC_t rc = kOkUiRC;
  487. ctl_t* ctl = NULL;
  488. ctl_t* prvCtl = NULL;
  489. // if the panel is the ctl to delete
  490. if( usrId == pp->usrId )
  491. {
  492. return _destroyPanel(pp,deleteWindowEleFlag);
  493. }
  494. // locate the control on the panel
  495. if((rc = _findCtl(pp,usrId,ctl,prvCtl,true)) != kOkUiRC )
  496. return rc;
  497. // unlink the control
  498. if( prvCtl!=NULL)
  499. prvCtl->link = ctl->link;
  500. else
  501. {
  502. assert( pp->ctls == ctl );
  503. pp->ctls = ctl->link;
  504. }
  505. // delete the window element
  506. if( deleteWindowEleFlag)
  507. delete ctl->wdgt;
  508. // release the control recd
  509. cmMemFree(ctl);
  510. return rc;
  511. }
  512. cmUiRC_t cmUiDrvrFltk::_createPanel( const cmUiDriverArg_t* a )
  513. {
  514. int tx,ty,tw,th;
  515. _tabs->client_area(tx,ty,tw,th);
  516. panel_t* pnl = cmMemAllocZ(panel_t,1);
  517. pnl->drvr = this;
  518. pnl->grp = new Fl_Group(tx,ty,tw,th,a->sval);
  519. pnl->grp->user_data(pnl);
  520. pnl->appId = a->appId;
  521. pnl->usrId = a->usrId;
  522. pnl->x_offs = tx + 2;
  523. pnl->y_offs = ty + 2;
  524. pnl->link = _panels;
  525. _panels = pnl;
  526. pnl->grp->end();
  527. if( cmIsFlag(a->flags,kPrependUiFl) )
  528. _tabs->insert(*pnl->grp,0);
  529. else
  530. _tabs->add(pnl->grp);
  531. // cache the event callback arg record so that it
  532. // does not have to be filled on every callback.
  533. cmUiDriverArgSetup(&pnl->cbArg,a->hdr.rtSubIdx,kUiDrvrSelRtId,kSetValDId,a->appId,a->usrId,a->usrId,kPanelUiCId,kIvalUiFl,0,0,NULL,tx,ty,tw,th);
  534. _tabs->redraw();
  535. return kOkUiRC;
  536. }
  537. cmUiRC_t cmUiDrvrFltk::_destroyAllPanels( bool deleteWindowEleFlag )
  538. {
  539. cmUiRC_t rc = kOkUiRC;
  540. while( _panels != NULL )
  541. {
  542. cmUiRC_t rc0;
  543. if((rc0 = _destroyCtl(_panels->appId,_panels->usrId,_panels->usrId,deleteWindowEleFlag)) != kOkUiRC )
  544. rc = rc0;
  545. }
  546. return rc;
  547. }
  548. cmUiRC_t cmUiDrvrFltk::_destroyPanel(panel_t* pp, bool deleteWindowEleFlag)
  549. {
  550. cmUiRC_t rc = kOkUiRC;
  551. // delete the FLTK panel itself
  552. if( deleteWindowEleFlag )
  553. {
  554. delete pp->grp;
  555. deleteWindowEleFlag = false;
  556. }
  557. while( pp->ctls != NULL )
  558. {
  559. cmUiRC_t rc0;
  560. if((rc0 = _destroyCtl(pp,pp->ctls->usrId,deleteWindowEleFlag)) != kOkUiRC )
  561. rc = rc0;
  562. }
  563. cmMemFree(pp);
  564. return rc;
  565. }
  566. cmUiRC_t cmUiDrvrFltk::_findPanel( unsigned appId, unsigned usrId, panel_t*& ppRef, panel_t*& prvPnl, bool errFl )
  567. {
  568. ppRef = NULL;
  569. prvPnl = NULL;
  570. panel_t* pp = _panels;
  571. for(; pp!=NULL; pp=pp->link)
  572. {
  573. if(pp->appId==appId && pp->usrId==usrId )
  574. {
  575. ppRef = pp;
  576. return kOkUiRC;
  577. }
  578. prvPnl = pp;
  579. }
  580. if( errFl )
  581. cmErrMsg(&_err,kPanelNotFoundUiRC,"Panel not found for id=%i.",usrId);
  582. return kPanelNotFoundUiRC;
  583. }
  584. cmUiRC_t cmUiDrvrFltk::_findCtl( panel_t* pp, unsigned usrId, ctl_t*& ctlRef, ctl_t*& prvCtlRef, bool errFl )
  585. {
  586. ctlRef = NULL;
  587. prvCtlRef = NULL;
  588. ctl_t* cp = pp->ctls;
  589. for(; cp!=NULL; cp=cp->link)
  590. {
  591. if( cp->usrId == usrId )
  592. {
  593. ctlRef = cp;
  594. return kOkUiRC;
  595. }
  596. prvCtlRef = cp;
  597. }
  598. if( errFl )
  599. cmErrMsg(&_err,kCtlNotFoundUiRC,"Control %i not found in panel %i.",usrId,pp->usrId);
  600. return kCtlNotFoundUiRC;
  601. }
  602. void cmUiDrvrFltk::_doCb( ctl_t* ctl, cmUiDId_t dId, unsigned flags )
  603. {
  604. cmUiDriverArg_t* a = &ctl->cbArg;
  605. unsigned orgFlags = a->flags;
  606. a->flags |= flags;
  607. a->dId = dId;
  608. _cbFunc(_cbArgs,&ctl->cbArg);
  609. a->flags = orgFlags;
  610. a->dId = kInvalidDId;
  611. }
  612. void cmUiDrvrFltk::_s_ctl_cb(Fl_Widget* wp, void* arg )
  613. {
  614. ctl_t* ctl = (ctl_t*)arg;
  615. cmUiDrvrFltk* p = ctl->pnl->drvr;
  616. cmUiDriverArg_t* a = &ctl->cbArg;
  617. bool callbackFl = true;
  618. unsigned flags = kValUiFl;
  619. switch( ctl->cId )
  620. {
  621. case kInvalidUiCId:
  622. assert(0);
  623. callbackFl = false;
  624. break;
  625. case kPanelUiCId:
  626. callbackFl = false;
  627. break;
  628. case kBtnUiCId:
  629. break;
  630. case kCheckUiCId:
  631. a->ival = ctl->u.chk->value();
  632. flags |= kIvalUiFl;
  633. break;
  634. case kMenuBtnUiCId:
  635. if( ctl->u.mbt->mvalue() != NULL && ctl->u.mbt->mvalue()->label() != NULL )
  636. ctl->u.mbt->copy_label(ctl->u.mbt->mvalue()->label());
  637. a->ival = ctl->u.mbt->value();
  638. flags |= kIvalUiFl;
  639. break;
  640. case kListUiCId:
  641. a->ival = ctl->u.lst->value() - 1;
  642. flags |= kIvalUiFl;
  643. break;
  644. case kLabelUiCId:
  645. callbackFl = false;
  646. break;
  647. case kStringUiCId:
  648. a->sval = ctl->u.str->value();
  649. flags |= kSvalUiFl;
  650. break;
  651. case kConsoleUiCId:
  652. callbackFl = false;
  653. break;
  654. case kSliderUiCId:
  655. a->fval = ctl->u.sld->value();
  656. flags |= kFvalUiFl;
  657. break;
  658. case kNumberUiCId:
  659. a->fval = ctl->u.num->value();
  660. flags |= kFvalUiFl;
  661. break;
  662. case kProgressUiCId:
  663. callbackFl = false;
  664. break;
  665. case kMeterUiCId:
  666. callbackFl = false;
  667. break;
  668. case kFilenameUiCId:
  669. a->sval = ctl->u.fnb->filename();
  670. flags |= kSvalUiFl;
  671. break;
  672. case kDirUiCId:
  673. a->sval = ctl->u.fnb->filename();
  674. flags |= kSvalUiFl;
  675. break;
  676. case kMaxUiCId:
  677. callbackFl = false;
  678. assert(0);
  679. break;
  680. }
  681. if( callbackFl )
  682. p->_doCb(ctl,kSetValDId,flags);
  683. }
  684. void cmUiDrvrFltk::_s_tab_cb(Fl_Widget* wp, void* arg )
  685. {
  686. cmUiDrvrFltk* p = (cmUiDrvrFltk*)arg;
  687. Fl_Widget* w = p->_tabs->value();
  688. panel_t* pp = p->_panels;
  689. for(; pp!=NULL; pp=pp->link)
  690. {
  691. // if this is the panel being selected then send a 1 otherwise send a 0.
  692. pp->cbArg.flags = cmSetFlag(pp->cbArg.flags, kIvalUiFl );
  693. pp->cbArg.dId = kSetValDId;
  694. pp->cbArg.ival = w->user_data() == pp->grp->user_data();
  695. p->_cbFunc(p->_cbArgs,&pp->cbArg);
  696. pp->cbArg.flags = cmClrFlag(pp->cbArg.flags, kIvalUiFl );
  697. pp->cbArg.dId = kInvalidDId;
  698. }
  699. }