Programmable real-time audio signal processing application
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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. }