libcm is a C development framework with an emphasis on audio signal processing applications.
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.

cmGrPlot.c 31KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. #include "cmGlobal.h"
  2. #include "cmFloatTypes.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmMem.h"
  7. #include "cmMallocDebug.h"
  8. #include "cmGr.h"
  9. #include "cmGrDevCtx.h"
  10. #include "cmGrPlot.h"
  11. #include "cmVectOpsTemplateMain.h"
  12. //------------------------------------------------------------------------------------------------------------------
  13. //------------------------------------------------------------------------------------------------------------------
  14. //------------------------------------------------------------------------------------------------------------------
  15. //------------------------------------------------------------------------------------------------------------------
  16. struct cmGrPl_str;
  17. typedef struct cmGrPlotObj_str
  18. {
  19. cmGrH_t grH; // the canvas this object is drawn on
  20. cmGrObjH_t grObjH; // the grObj this object is based on
  21. cmGrPlObjTypeId_t typeId;
  22. unsigned cfgFlags;
  23. unsigned stateFlags;
  24. cmGrVExt_t vext;
  25. cmChar_t* label;
  26. unsigned labelFlags;
  27. int labelAngle;
  28. cmGrColor_t labelColor;
  29. int loffs;
  30. int toffs;
  31. int roffs;
  32. int boffs;
  33. cmGrColor_t drawColors[ kMaxPlGrId ];
  34. cmGrColor_t fillColors[ kMaxPlGrId ];
  35. unsigned fontId;
  36. unsigned fontSize;
  37. unsigned fontStyle;
  38. void* userPtr;
  39. cmGrPlotCbFunc_t cbFunc;
  40. void* cbArg;
  41. struct cmGrPl_str* p; // owning plot object manager
  42. struct cmGrPlotObj_str* parent; // containing object
  43. struct cmGrPlotObj_str* xAnchor; // x-location reference object
  44. struct cmGrPlotObj_str* yAnchor; // y-location reference object
  45. struct cmGrPlotObj_str* next;
  46. struct cmGrPlotObj_str* prev;
  47. } cmGrPlotObj_t;
  48. typedef struct cmGrPl_str
  49. {
  50. cmCtx_t* ctx; //
  51. cmErr_t err; //
  52. cmGrPlotObj_t* list; // plot object linked list
  53. cmGrPlotObj_t* fop; // focused object ptr
  54. } cmGrPl_t;
  55. cmGrPlH_t cmGrPlNullHandle = cmSTATIC_NULL_HANDLE;
  56. cmGrPlObjH_t cmGrPlObjNullHandle = cmSTATIC_NULL_HANDLE;
  57. //------------------------------------------------------------------------------------------------------------------
  58. // Plot Private Functions
  59. //------------------------------------------------------------------------------------------------------------------
  60. cmGrPl_t* _cmGrPlHandleToPtr( cmGrPlH_t h )
  61. {
  62. cmGrPl_t* p = (cmGrPl_t*)h.h;
  63. assert(p!=NULL);
  64. return p;
  65. }
  66. cmGrPlotObj_t* _cmGrPlObjHandleToPtr( cmGrPlObjH_t oh )
  67. {
  68. cmGrPlotObj_t* op = (cmGrPlotObj_t*)oh.h;
  69. assert( op!=NULL);
  70. return op;
  71. }
  72. cmGrPlRC_t _cmGrPlotObjDelete( cmGrPlotObj_t* op )
  73. {
  74. if( op==NULL || cmGrObjIsValid( op->grH, op->grObjH)==false )
  75. return kOkGrPlRC;
  76. cmGrPl_t* p = op->p;
  77. // destroy the cmGrObj - which will call _cmGrPlotObjDestroy()
  78. if( cmGrObjDestroy( op->grH, &op->grObjH ) != kOkGrRC )
  79. return cmErrMsg( &p->err, kGrFailGrPlRC, "Delete failed on the object label='%s' id=%i\n",cmStringNullGuard( op->label ), cmGrObjId(op->grObjH) );
  80. return kOkGrPlRC;
  81. }
  82. void _cmGrPlotObjUnlink( cmGrPlotObj_t* op )
  83. {
  84. cmGrPl_t* p = op->p;
  85. if( op->next != NULL )
  86. op->next->prev = op->prev;
  87. if( op->prev != NULL )
  88. op->prev->next = op->next;
  89. if( p->list == op )
  90. p->list = op->next;
  91. }
  92. void _cmGrPlotObjLink( cmGrPl_t* p, cmGrPlotObj_t* op )
  93. {
  94. if( p->list != NULL )
  95. p->list->prev = op;
  96. op->next = p->list;
  97. op->prev = NULL;
  98. p->list = op;
  99. }
  100. // Destroy all objects
  101. cmGrPlRC_t _cmGrPlotClear( cmGrPl_t* p )
  102. {
  103. cmGrPlRC_t rc = kOkGrPlRC;
  104. cmGrPlotObj_t* op = p->list;
  105. while( op!=NULL )
  106. {
  107. cmGrPlotObj_t* t = op->next;
  108. if((rc = _cmGrPlotObjDelete(op)) != kOkGrPlRC )
  109. break;
  110. op = t;
  111. }
  112. return rc;
  113. }
  114. // Destroy the plot mgr
  115. cmGrPlRC_t _cmGrPlotDestroy( cmGrPl_t* p )
  116. {
  117. cmGrPlRC_t rc;
  118. if((rc = _cmGrPlotClear(p)) != kOkGrPlRC )
  119. return rc;
  120. cmMemFree(p);
  121. return kOkGrPlRC;
  122. }
  123. bool _cmGrPlotObjIsVisible( cmGrPlotObj_t* op )
  124. { return cmIsNotFlag(op->cfgFlags,kNoDrawGrPlFl); }
  125. bool _cmGrPlotObjIsEnabled( cmGrPlotObj_t* op )
  126. {
  127. // invisible objects are never enabled
  128. if( _cmGrPlotObjIsVisible(op) == false )
  129. return false;
  130. return cmIsFlag(op->stateFlags,kEnabledGrPlFl);
  131. }
  132. bool _cmGrPlotObjIsFocused(cmGrPlotObj_t* op)
  133. { return _cmGrPlotObjIsEnabled(op) && op->p->fop==op; }
  134. bool _cmGrPlotObjIsSelected(cmGrPlotObj_t* op)
  135. { return _cmGrPlotObjIsFocused(op) || cmIsFlag(op->stateFlags,kSelectGrPlFl); }
  136. void _cmGrPlotObjSetupCbArg( cmGrPlotCbArg_t* a, cmGrPlotObj_t* op, cmGrPlCbSelId_t selId )
  137. {
  138. cmGrPlObjH_t oH;
  139. oH.h = op;
  140. memset(a,0,sizeof(a));
  141. a->ctx = op->p->ctx;
  142. a->cbArg = op->cbArg;
  143. a->selId = selId;
  144. a->objH = oH;
  145. }
  146. bool _cmGrPlotObjCb( cmGrPlotObj_t* op, cmGrPlCbSelId_t selId, unsigned deltaFlags )
  147. {
  148. if( op->cbFunc != NULL )
  149. {
  150. cmGrPlotCbArg_t a;
  151. _cmGrPlotObjSetupCbArg(&a,op,kPreEventCbSelGrPlId);
  152. a.deltaFlags = deltaFlags;
  153. return op->cbFunc(&a);
  154. }
  155. return true;
  156. }
  157. void _cmGrPlotObjSetFocus( cmGrPlotObj_t* op )
  158. {
  159. // if 'op' is not enabled then it cannot receive the focus
  160. if( _cmGrPlotObjIsEnabled(op) == false )
  161. return;
  162. // if the focus cannot be set on 'op' - then try op->parent
  163. for(; op!=NULL; op=op->parent)
  164. if( cmIsNotFlag(op->cfgFlags,kNoFocusGrPlFl) && cmIsNotFlag(op->cfgFlags,kNoDrawGrPlFl) )
  165. break;
  166. if( op != NULL )
  167. {
  168. if( op->p->fop != NULL )
  169. {
  170. // if the application callback returns false then do no release focus from the current object
  171. if(_cmGrPlotObjCb(op->p->fop, kStateChangeGrPlId, kFocusGrPlFl ) == false )
  172. return;
  173. op->p->fop = NULL;
  174. }
  175. // if the application callback returns false then do not give focus to the selected object
  176. if(_cmGrPlotObjCb(op, kStateChangeGrPlId, kFocusGrPlFl ) == false )
  177. return;
  178. op->p->fop = op;
  179. }
  180. }
  181. void _cmGrPlotObjSetSelect( cmGrPlotObj_t* op, bool clearFl )
  182. {
  183. // if the object is disabled or no selectable
  184. if( _cmGrPlotObjIsEnabled(op)==false || cmIsFlag(op->cfgFlags,kNoSelectGrPlFl | kNoDrawGrPlFl) )
  185. return;
  186. unsigned stateFlags = op->stateFlags;
  187. // if the application callback returns false then do change the select state of the object
  188. if(_cmGrPlotObjCb(op, kStateChangeGrPlId, kSelectGrPlFl ) == false )
  189. return;
  190. if( clearFl )
  191. {
  192. cmGrObjH_t parentObjH = cmGrObjParent(op->grObjH);
  193. cmGrPlotObj_t* cop = op->p->list;
  194. // clear the select flag on all objects that share op->parent
  195. for(; cop!=NULL; cop=cop->next)
  196. if( cmHandlesAreEqual(cmGrObjParent(cop->grObjH),parentObjH) )
  197. cop->stateFlags = cmClrFlag(cop->stateFlags,kSelectGrPlFl);
  198. }
  199. op->stateFlags = cmTogFlag(stateFlags,kSelectGrPlFl);
  200. }
  201. const cmGrColor_t _cmGrPlotColor( cmGrPlotObj_t* op, cmGrColor_t* array )
  202. {
  203. if( _cmGrPlotObjIsFocused(op) )
  204. return array[kFocusPlGrId];
  205. if( _cmGrPlotObjIsSelected(op) )
  206. return array[kSelectPlGrId];
  207. if( _cmGrPlotObjIsEnabled(op) )
  208. return array[kEnablePlGrId];
  209. return array[kDisablePlGrId];
  210. }
  211. unsigned _cmGrPlotObjTriShapeToFlags( unsigned typeId)
  212. {
  213. switch(typeId)
  214. {
  215. case kUTriGrPlId: return kTopGrFl;
  216. case kDTriGrPlId: return kBottomGrFl;
  217. case kLTriGrPlId: return kLeftGrFl;
  218. case kRTriGrPlId: return kRightGrFl;
  219. default:
  220. { assert(0); }
  221. }
  222. return 0;
  223. }
  224. //------------------------------------------------------------------------------------------------------------------
  225. // Plot Object Callback Functions
  226. //------------------------------------------------------------------------------------------------------------------
  227. cmGrRC_t _cmGrPlotObjCreate( cmGrObjFuncArgs_t* args )
  228. {
  229. cmGrPlotObj_t* op = args->cbArg;
  230. _cmGrPlotObjCb(op,kCreatedCbSelGrPlId,0);
  231. // return kOkGrRC to indicate that the create was successful
  232. return kOkGrRC;
  233. }
  234. void _cmGrPlotObjDestroy( cmGrObjFuncArgs_t* args )
  235. {
  236. cmGrPlotObj_t* op = args->cbArg;
  237. // TODO: is it possible to prevent destruction by returning
  238. // 'false' from the used defined callback. This feature is
  239. // slightly complicated by the fact
  240. // that in some circumstances the destroy request is not
  241. // optional - for example when the program is closing.
  242. _cmGrPlotObjCb(op,kDestroyedCbSelGrPlId,0);
  243. _cmGrPlotObjUnlink( op );
  244. cmMemFree(op->label);
  245. cmMemFree(op);
  246. }
  247. void _cmGrPlotObjGetVExt( cmGrPlotObj_t* op, cmGrVExt_t* vext )
  248. {
  249. switch( op->typeId )
  250. {
  251. case kStarGrPlId:
  252. case kCrossGrPlId:
  253. case kPlusGrPlId:
  254. case kDiamondGrPlId:
  255. case kUTriGrPlId:
  256. case kDTriGrPlId:
  257. case kLTriGrPlId:
  258. case kRTriGrPlId:
  259. case kRectGrPlId:
  260. case kLineGrPlId:
  261. case kEllipseGrPlId:
  262. {
  263. *vext = op->vext;
  264. }
  265. break;
  266. case kHLineGrPlId:
  267. case kVLineGrPlId:
  268. {
  269. cmGrVExt_t wext;
  270. cmGrObjH_t oh = cmGrObjParent(op->grObjH);
  271. cmGrObjWorldExt(oh,&wext);
  272. vext->loc.x = op->typeId==kHLineGrPlId ? wext.loc.x : op->vext.loc.x;
  273. vext->loc.y = op->typeId==kVLineGrPlId ? wext.loc.y : op->vext.loc.y;
  274. vext->sz.w = op->typeId==kHLineGrPlId ? wext.sz.w : op->vext.sz.w;
  275. vext->sz.h = op->typeId==kVLineGrPlId ? wext.sz.h : op->vext.sz.h;
  276. }
  277. break;
  278. default:
  279. { assert(0); }
  280. }
  281. // add up the anchor offsets until the first object in the container
  282. cmGrPlotObj_t* ap = op->xAnchor;
  283. for(; ap!=NULL; ap=ap->xAnchor)
  284. {
  285. vext->loc.x += ap->vext.loc.x;
  286. if( ap->xAnchor==ap->parent)
  287. break;
  288. }
  289. ap = op->yAnchor;
  290. for(; ap!=NULL; ap=ap->yAnchor)
  291. {
  292. vext->loc.y += ap->vext.loc.y;
  293. if( ap->yAnchor==ap->parent)
  294. break;
  295. }
  296. }
  297. void _cmGrPlotObjVExt( cmGrObjFuncArgs_t* args, cmGrVExt_t* vext )
  298. {
  299. cmGrPlotObj_t* op = args->cbArg;
  300. _cmGrPlotObjGetVExt(op, vext);
  301. }
  302. bool _cmGrPlotObjRender( cmGrObjFuncArgs_t* args, cmGrDcH_t dcH )
  303. {
  304. cmGrPlotObj_t* op = args->cbArg;
  305. cmGrPExt_t pext;
  306. cmGrVExt_t vext;
  307. if( !_cmGrPlotObjIsVisible(op) )
  308. return false;
  309. // get the virtual extents of this object
  310. _cmGrPlotObjVExt( args, &vext );
  311. // convert the virtual ext's to phys ext's
  312. cmGrVExt_VtoP( op->grH, op->grObjH, &vext, &pext);
  313. // expand the ext's according to the physical offsets
  314. cmGrPExtExpand(&pext,op->loffs,op->toffs,op->roffs,op->boffs);
  315. switch( op->typeId )
  316. {
  317. case kLineGrPlId:
  318. cmGrDcSetColor( dcH, _cmGrPlotColor(op,op->drawColors) );
  319. cmGrDcDrawLine( dcH, cmGrPExtL(&pext), cmGrPExtT(&pext), cmGrPExtR(&pext), cmGrPExtB(&pext) );
  320. break;
  321. case kStarGrPlId:
  322. case kCrossGrPlId:
  323. case kPlusGrPlId:
  324. case kEllipseGrPlId:
  325. case kDiamondGrPlId:
  326. case kUTriGrPlId:
  327. case kDTriGrPlId:
  328. case kLTriGrPlId:
  329. case kRTriGrPlId:
  330. case kRectGrPlId:
  331. case kHLineGrPlId:
  332. case kVLineGrPlId:
  333. {
  334. if( cmIsNotFlag(op->cfgFlags,kNoFillGrPlFl) )
  335. {
  336. // set the fill color
  337. cmGrDcSetColor( dcH, _cmGrPlotColor(op,op->fillColors) );
  338. // draw the fill
  339. switch(op->typeId)
  340. {
  341. case kEllipseGrPlId:
  342. cmGrDcFillEllipse( dcH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h);
  343. break;
  344. case kDiamondGrPlId:
  345. cmGrDcFillDiamond( dcH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h);
  346. break;
  347. case kUTriGrPlId:
  348. case kDTriGrPlId:
  349. case kLTriGrPlId:
  350. case kRTriGrPlId:
  351. cmGrDcFillTriangle( dcH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h, _cmGrPlotObjTriShapeToFlags(op->typeId));
  352. break;
  353. case kStarGrPlId:
  354. case kCrossGrPlId:
  355. case kPlusGrPlId:
  356. case kRectGrPlId:
  357. case kHLineGrPlId:
  358. case kVLineGrPlId:
  359. cmGrDcFillRect( dcH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h);
  360. break;
  361. default:
  362. { assert(0); }
  363. }
  364. }
  365. if( cmIsNotFlag(op->cfgFlags,kNoBorderGrPlFl) )
  366. {
  367. // set the border color
  368. cmGrDcSetColor( dcH, _cmGrPlotColor(op,op->drawColors) );
  369. // draw the border
  370. switch(op->typeId)
  371. {
  372. case kEllipseGrPlId:
  373. cmGrDcDrawEllipse( dcH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h);
  374. break;
  375. case kDiamondGrPlId:
  376. cmGrDcDrawDiamond( dcH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h);
  377. break;
  378. case kUTriGrPlId:
  379. case kDTriGrPlId:
  380. case kLTriGrPlId:
  381. case kRTriGrPlId:
  382. cmGrDcDrawTriangle( dcH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h, _cmGrPlotObjTriShapeToFlags(op->typeId));
  383. break;
  384. case kStarGrPlId:
  385. cmGrDcDrawLine( dcH, cmGrPExtL(&pext), cmGrPExtT(&pext), cmGrPExtR(&pext), cmGrPExtB(&pext));
  386. cmGrDcDrawLine( dcH, cmGrPExtL(&pext), cmGrPExtB(&pext), cmGrPExtR(&pext), cmGrPExtT(&pext));
  387. cmGrDcDrawLine( dcH, cmGrPExtL(&pext) + cmGrPExtW(&pext)/2, cmGrPExtT(&pext), cmGrPExtL(&pext) + cmGrPExtW(&pext)/2, cmGrPExtB(&pext));
  388. cmGrDcDrawLine( dcH, cmGrPExtL(&pext), cmGrPExtT(&pext) + cmGrPExtH(&pext)/2, cmGrPExtR(&pext), cmGrPExtT(&pext) + cmGrPExtH(&pext)/2);
  389. break;
  390. case kCrossGrPlId:
  391. cmGrDcDrawLine( dcH, cmGrPExtL(&pext), cmGrPExtT(&pext), cmGrPExtR(&pext), cmGrPExtB(&pext));
  392. cmGrDcDrawLine( dcH, cmGrPExtR(&pext), cmGrPExtT(&pext), cmGrPExtL(&pext), cmGrPExtB(&pext));
  393. break;
  394. case kPlusGrPlId:
  395. cmGrDcDrawLine( dcH, cmGrPExtL(&pext) + cmGrPExtW(&pext)/2, cmGrPExtT(&pext), cmGrPExtL(&pext) + cmGrPExtW(&pext)/2, cmGrPExtB(&pext));
  396. cmGrDcDrawLine( dcH, cmGrPExtL(&pext), cmGrPExtT(&pext) + cmGrPExtH(&pext)/2, cmGrPExtR(&pext), cmGrPExtT(&pext) + cmGrPExtH(&pext)/2);
  397. break;
  398. case kRectGrPlId:
  399. case kHLineGrPlId:
  400. case kVLineGrPlId:
  401. cmGrDcDrawRect( dcH, pext.loc.x, pext.loc.y, pext.sz.w, pext.sz.h);
  402. break;
  403. default:
  404. { assert(0); }
  405. }
  406. }
  407. if( (op->label != NULL) && cmIsNotFlag(op->cfgFlags, kNoLabelGrPlFl) )
  408. {
  409. unsigned cc = cmGrDcColor(dcH);
  410. cmGrDcSetColor(dcH,op->labelColor);
  411. cmGrDcDrawTextJustify( dcH, op->fontId, op->fontSize, op->fontStyle, op->label, &pext, op->labelFlags );
  412. cmGrDcSetColor(dcH,cc);
  413. /*
  414. cmGrPSz_t sz;
  415. cmGrPPt_t pt;
  416. cmGrDcFontSetAndMeasure( dcH, op->fontId, op->fontSize, op->fontStyle, op->label, &sz );
  417. cmGrPExtCtr( &pext, &pt );
  418. cmGrDcDrawText( dcH, op->label, pt.x - sz.w/2, pt.y + sz.h/2 );
  419. */
  420. }
  421. }
  422. break;
  423. default:
  424. { assert(0); }
  425. }
  426. return true;
  427. }
  428. int _cmGrPlotObjDistance( cmGrObjFuncArgs_t* args, int x, int y )
  429. {
  430. return 0;
  431. }
  432. bool _cmGrPlotObjEvent( cmGrObjFuncArgs_t* args, unsigned flags, unsigned key, int px, int py )
  433. {
  434. cmGrPlotObj_t* op = args->cbArg;
  435. bool fl = false;
  436. cmGrPlotCbArg_t a;
  437. if( op->cbFunc != NULL )
  438. {
  439. cmGrPlotObj_t* cb_op = op;
  440. // if this is a key up/dn event and 'op' is not the 'focused op' then callback
  441. // callback on the 'focused op' instead of this 'op'.
  442. if( (cmIsFlag(flags,kKeyDnGrFl) || cmIsFlag(flags,kKeyUpGrFl)) && op->p->fop != op )
  443. cb_op = op->p->fop;
  444. _cmGrPlotObjSetupCbArg(&a,cb_op,kPreEventCbSelGrPlId);
  445. a.eventFlags = flags;
  446. a.eventKey = key;
  447. a.eventX = px;
  448. a.eventY = py;
  449. if( op->cbFunc(&a) == false )
  450. return true;
  451. }
  452. switch( flags & kEvtMask )
  453. {
  454. case kMsDownGrFl:
  455. break;
  456. case kMsUpGrFl:
  457. _cmGrPlotObjSetFocus( op );
  458. fl = true;
  459. break;
  460. case kMsClickGrFl:
  461. _cmGrPlotObjSetSelect(op, cmIsNotFlag(flags,kCtlKeyGrFl) );
  462. fl = true;
  463. break;
  464. case kMsDragGrFl:
  465. {
  466. cmGrVExt_t vext;
  467. cmGrVExt_t wext;
  468. if( cmIsFlag(op->cfgFlags,kNoDragGrPlFl | kNoDrawGrPlFl) )
  469. return false;
  470. // get the parent world extents
  471. cmGrObjWorldExt( cmGrObjParent( args->objH ), &wext );
  472. // calc the new position of the obj
  473. cmGrV_t x = args->msVPt.x - args->msDnVOffs.w;
  474. cmGrV_t y = args->msVPt.y - args->msDnVOffs.h;
  475. cmGrVExtSet(&vext,x,y,op->vext.sz.w,op->vext.sz.h);
  476. // the obj must be remain inside the parent wext
  477. cmGrVExtContain(&wext,&vext);
  478. // calculate the obj's location as an offset from it's anchors
  479. cmGrPlotObj_t* ap = op->xAnchor;
  480. for(; ap!=NULL; ap=ap->xAnchor)
  481. vext.loc.x -= ap->vext.loc.x;
  482. ap = op->yAnchor;
  483. for(; ap!=NULL; ap=ap->yAnchor)
  484. vext.loc.y -= ap->vext.loc.y;
  485. if( !cmGrVExtIsEqual(&op->vext,&vext) )
  486. {
  487. // move the object
  488. op->vext.loc.x = vext.loc.x;
  489. op->vext.loc.y = vext.loc.y;
  490. fl = true;
  491. }
  492. }
  493. break;
  494. case kKeyDnGrFl:
  495. case kKeyUpGrFl:
  496. break;
  497. }
  498. // notify the app of the event
  499. if( op->cbFunc != NULL )
  500. {
  501. a.selId = kEventCbSelGrPlId;
  502. op->cbFunc(&a);
  503. }
  504. return fl;
  505. }
  506. bool _cmGrPlotObjIsInside( cmGrObjFuncArgs_t* args, int px, int py, cmGrV_t vx, cmGrV_t vy )
  507. {
  508. cmGrVExt_t vext;
  509. cmGrPExt_t pext;
  510. cmGrPlotObj_t* op = args->cbArg;
  511. // get the virtual extents of this object
  512. _cmGrPlotObjVExt( args, &vext );
  513. // convert the virtual ext's to phys ext's
  514. cmGrVExt_VtoP(args->grH,args->objH,&vext,&pext);
  515. // expand the ext's according to the off's
  516. cmGrPExtExpand(&pext,op->loffs,op->toffs,op->roffs,op->boffs);
  517. if( op->typeId == kLineGrPlId )
  518. if( cmVOR_PtToLineDistance(cmGrPExtL(&pext),cmGrPExtT(&pext),cmGrPExtR(&pext),cmGrPExtB(&pext),px,py) < 3 )
  519. return true;
  520. // check if the px,py is inside pext
  521. return cmGrPExtIsXyInside(&pext,px,py);
  522. }
  523. void _cmGrPlotFuncObjSetupDefault(cmGrObjFunc_t *f, void* arg )
  524. {
  525. f->createCbFunc = _cmGrPlotObjCreate;
  526. f->createCbArg = arg;
  527. f->destroyCbFunc = _cmGrPlotObjDestroy;
  528. f->destroyCbArg = arg;
  529. f->renderCbFunc = _cmGrPlotObjRender;
  530. f->renderCbArg = arg;
  531. f->distanceCbFunc = _cmGrPlotObjDistance;
  532. f->distanceCbArg = arg;
  533. f->eventCbFunc = _cmGrPlotObjEvent;
  534. f->eventCbArg = arg;
  535. f->vextCbFunc = _cmGrPlotObjVExt;
  536. f->vextCbArg = arg;
  537. f->isInsideCbFunc = _cmGrPlotObjIsInside;
  538. f->isInsideCbArg = arg;
  539. }
  540. //------------------------------------------------------------------------------------------------------------------
  541. // Plot Object Public Functions
  542. //------------------------------------------------------------------------------------------------------------------
  543. cmGrPlRC_t cmGrPlotObjCreate(
  544. cmGrPlH_t hh,
  545. cmGrH_t grH,
  546. cmGrPlObjH_t* hp,
  547. unsigned id,
  548. cmGrPlObjH_t parentPlObjH,
  549. cmGrPlObjH_t xAnchorPlObjH,
  550. cmGrPlObjH_t yAnchorPlObjH,
  551. cmGrPlObjTypeId_t typeId,
  552. unsigned cfgFlags,
  553. cmReal_t x,
  554. cmReal_t y,
  555. cmReal_t w,
  556. cmReal_t h,
  557. const cmChar_t* label,
  558. const cmGrVExt_t* wext )
  559. {
  560. cmGrPlRC_t rc;
  561. cmGrObjFunc_t funcs;
  562. if((rc = cmGrPlotObjDestroy(hp)) != kOkGrPlRC )
  563. return rc;
  564. cmGrPl_t* p = _cmGrPlHandleToPtr(hh);
  565. cmGrPlotObj_t* op = cmMemAllocZ(cmGrPlotObj_t,1);
  566. _cmGrPlotObjLink(p,op);
  567. _cmGrPlotFuncObjSetupDefault(&funcs,op);
  568. // setup the object
  569. op->grH = grH;
  570. op->typeId = typeId;
  571. op->cfgFlags = cfgFlags;
  572. op->stateFlags = kEnabledGrPlFl;
  573. op->label = label==NULL ?NULL : cmMemAllocStr(label);
  574. op->labelFlags = kHorzCtrJsGrFl | kVertCtrJsGrFl;
  575. op->labelAngle = 0;
  576. op->labelColor = kBlackGrId;
  577. op->grObjH = cmGrObjNullHandle;
  578. op->parent = cmGrPlotObjIsValid(parentPlObjH) ? _cmGrPlObjHandleToPtr(parentPlObjH) : NULL;
  579. op->xAnchor = cmGrPlotObjIsValid(xAnchorPlObjH) ? _cmGrPlObjHandleToPtr(xAnchorPlObjH) : NULL;
  580. op->yAnchor = cmGrPlotObjIsValid(yAnchorPlObjH) ? _cmGrPlObjHandleToPtr(yAnchorPlObjH) : NULL;
  581. op->p = p;
  582. op->fontId = kHelveticaFfGrId;
  583. op->fontSize = 12;
  584. op->fontStyle = kNormalFsGrFl;
  585. if( cmIsFlag(op->cfgFlags,kSymbolGrPlFl) )
  586. {
  587. int ww = w==0 ? kDefaultSymW : w;
  588. int hh = h==0 ? kDefaultSymH : h;
  589. op->loffs = ww/2;
  590. op->roffs = ww/2;
  591. op->toffs = hh/2;
  592. op->boffs = hh/2;
  593. w = 0;
  594. h = 0;
  595. }
  596. cmGrVExtSet(&op->vext,x,y,w,h);
  597. // set the default colors
  598. op->drawColors[kFocusPlGrId] = 0xcd853f;
  599. op->fillColors[kFocusPlGrId] = 0xdeb887;
  600. op->drawColors[kSelectPlGrId] = 0x483d8b;
  601. op->fillColors[kSelectPlGrId] = 0x8470ff;
  602. op->drawColors[kEnablePlGrId] = 0x000000;
  603. op->fillColors[kEnablePlGrId] = 0x009ff7;
  604. op->drawColors[kDisablePlGrId] = 0xbebebe;
  605. op->fillColors[kDisablePlGrId] = 0xd3d3de;
  606. unsigned grObjCfgFlags = 0;
  607. cmGrObjH_t parentGrH = op->parent == NULL ? cmGrObjNullHandle : op->parent->grObjH;
  608. // create the graphics system object - during this call a
  609. // call is made to funcs.create().
  610. if( cmGrObjCreate(grH, &op->grObjH, parentGrH, &funcs, id, grObjCfgFlags, wext ) != kOkGrRC )
  611. {
  612. rc = cmErrMsg(&p->err,kGrFailGrPlRC,"Graphic system object create failed for object (id=%i).",id);
  613. goto errLabel;
  614. }
  615. if( hp != NULL )
  616. hp->h = op;
  617. errLabel:
  618. if( rc != kOkGrPlRC )
  619. _cmGrPlotObjDelete(op);
  620. return rc;
  621. }
  622. cmGrPlRC_t cmGrPlotObjDestroy( cmGrPlObjH_t* hp )
  623. {
  624. cmGrPlRC_t rc = kOkGrPlRC;
  625. if( hp==NULL || cmGrPlotObjIsValid(*hp)==false )
  626. return kOkGrPlRC;
  627. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(*hp);
  628. if((rc = _cmGrPlotObjDelete(op)) != kOkGrPlRC )
  629. return rc;
  630. hp->h = NULL;
  631. return rc;
  632. }
  633. bool cmGrPlotObjIsValid( cmGrPlObjH_t h )
  634. { return h.h != NULL; }
  635. cmGrPlH_t cmGrPlotObjMgrHandle( cmGrPlObjH_t oh )
  636. {
  637. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  638. cmGrPlH_t grPlH;
  639. grPlH.h = op->p;
  640. return grPlH;
  641. }
  642. cmGrObjH_t cmGrPlotObjHandle( cmGrPlObjH_t oh )
  643. {
  644. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  645. return op->grObjH;
  646. }
  647. void cmGrPlotObjSetId( cmGrPlObjH_t oh, unsigned id )
  648. {
  649. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  650. cmGrObjSetId( op->grObjH, id );
  651. }
  652. void cmGrPlotObjSetUserPtr( cmGrPlObjH_t oh, void* userPtr )
  653. {
  654. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  655. op->userPtr = userPtr;
  656. }
  657. void* cmGrPlotObjUserPtr( cmGrPlObjH_t oh )
  658. {
  659. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  660. return op->userPtr;
  661. }
  662. unsigned cmGrPlotObjId( cmGrPlObjH_t oh )
  663. {
  664. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  665. return cmGrObjId(op->grObjH);
  666. }
  667. void cmGrPlotObjSetLabel( cmGrPlObjH_t oh, const cmChar_t* label )
  668. {
  669. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  670. if( label == op->label || (label != NULL && op->label!=NULL && strcmp(label,op->label)==0 ))
  671. return;
  672. cmMemPtrFree(&op->label);
  673. if( label != NULL )
  674. {
  675. assert( op->label == NULL );
  676. op->label = cmMemAllocStr(label);
  677. }
  678. }
  679. const cmChar_t* cmGrPlotObjLabel( cmGrPlObjH_t oh )
  680. {
  681. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  682. return op->label;
  683. }
  684. void cmGrPlotObjSetLabelAttr( cmGrPlObjH_t oh, unsigned flags, int angle, const cmGrColor_t color )
  685. {
  686. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  687. op->labelFlags = flags;
  688. op->labelAngle = angle;
  689. op->labelColor = color;
  690. }
  691. unsigned cmGrPlotObjLabelFlags( cmGrPlObjH_t oh )
  692. {
  693. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  694. return op->labelFlags;
  695. }
  696. int cmGrPlotObjLabelAngle( cmGrPlObjH_t oh )
  697. {
  698. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  699. return op->labelAngle;
  700. }
  701. const cmGrColor_t cmGrPlotObjLabelColor( cmGrPlObjH_t oh )
  702. {
  703. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  704. return op->labelColor;
  705. }
  706. void cmGrPlotObjSetStateFlags( cmGrPlObjH_t oh, unsigned flags )
  707. {
  708. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  709. if( cmIsFlag(flags,kVisibleGrPlFl) != _cmGrPlotObjIsVisible(op) )
  710. {
  711. if( _cmGrPlotObjCb(op, kStateChangeGrPlId, kVisibleGrPlFl ) == false )
  712. return;
  713. op->cfgFlags = cmTogFlag(op->cfgFlags,kNoDrawGrPlFl);
  714. }
  715. if( cmIsFlag(flags,kEnabledGrPlFl) != _cmGrPlotObjIsEnabled(op) )
  716. {
  717. if( _cmGrPlotObjCb(op, kStateChangeGrPlId, kEnabledGrPlFl ) == false )
  718. return;
  719. op->stateFlags = cmTogFlag(op->cfgFlags,kEnabledGrPlFl);
  720. }
  721. bool fl;
  722. if( cmIsFlag(flags,kSelectGrPlFl) != (fl=_cmGrPlotObjIsSelected(op)) )
  723. _cmGrPlotObjSetSelect(op, !fl );
  724. if( cmIsFlag(flags,kFocusGrPlFl) != (fl=_cmGrPlotObjIsFocused(op)) )
  725. if( fl )
  726. _cmGrPlotObjSetFocus(op);
  727. }
  728. unsigned cmGrPlotObjStateFlags( cmGrPlObjH_t oh )
  729. {
  730. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  731. return
  732. (_cmGrPlotObjIsEnabled(op) ? kEnabledGrPlFl : 0)
  733. | (_cmGrPlotObjIsVisible(op) ? kVisibleGrPlFl : 0)
  734. | (_cmGrPlotObjIsFocused(op) ? kFocusGrPlFl : 0)
  735. | (_cmGrPlotObjIsSelected(op) ? kSelectGrPlFl : 0);
  736. }
  737. void cmGrPlotObjSetCfgFlags( cmGrPlObjH_t oh, unsigned flags )
  738. {
  739. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  740. op->cfgFlags = flags;
  741. }
  742. void cmGrPlotObjClrCfgFlags( cmGrPlObjH_t oh, unsigned flags )
  743. {
  744. unsigned curFlags = cmGrPlotObjCfgFlags(oh);
  745. cmGrPlotObjSetCfgFlags(oh, cmClrFlag(curFlags,flags));
  746. }
  747. void cmGrPlotObjTogCfgFlags( cmGrPlObjH_t oh, unsigned flags )
  748. {
  749. unsigned curFlags = cmGrPlotObjCfgFlags(oh);
  750. cmGrPlotObjSetCfgFlags(oh, cmTogFlag(curFlags,flags));
  751. }
  752. unsigned cmGrPlotObjCfgFlags( cmGrPlObjH_t oh )
  753. {
  754. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  755. return op->cfgFlags;
  756. }
  757. cmGrPlRC_t cmGrPlotObjSetPhysExt( cmGrPlObjH_t oh, int loffs, int toffs, int roffs, int boffs )
  758. {
  759. cmGrPlRC_t rc = kOkGrPlRC;
  760. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  761. op->loffs = loffs;
  762. op->toffs = toffs;
  763. op->roffs = roffs;
  764. op->boffs = boffs;
  765. return rc;
  766. }
  767. void cmGrPlotObjPhysExt( cmGrPlObjH_t oh, int* loffs, int* toffs, int* roffs, int* boffs )
  768. {
  769. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  770. if( loffs != NULL )
  771. *loffs = op->loffs;
  772. if( toffs != NULL )
  773. *toffs = op->toffs;
  774. if( roffs != NULL )
  775. *roffs = op->roffs;
  776. if( boffs != NULL )
  777. *boffs = op->boffs;
  778. }
  779. void cmGrPlotObjVExt( cmGrPlObjH_t oh, cmGrVExt_t* vext )
  780. {
  781. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  782. _cmGrPlotObjGetVExt(op, vext);
  783. }
  784. void cmGrPlotObjSetFontFamily( cmGrPlObjH_t oh, unsigned id )
  785. {
  786. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  787. op->fontId = id;
  788. }
  789. unsigned cmGrPlotObjFontFamily( cmGrPlObjH_t oh )
  790. {
  791. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  792. return op->fontId;
  793. }
  794. void cmGrPlotObjSetFontStyle( cmGrPlObjH_t oh, unsigned style )
  795. {
  796. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  797. op->fontStyle = style;
  798. }
  799. unsigned cmGrPlotObjFontStyle( cmGrPlObjH_t oh )
  800. {
  801. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  802. return op->fontStyle;
  803. }
  804. void cmGrPlotObjSetFontSize( cmGrPlObjH_t oh, unsigned size )
  805. {
  806. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  807. op->fontSize = size;
  808. }
  809. unsigned cmGrPlotObjFontSize( cmGrPlObjH_t oh )
  810. {
  811. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  812. return op->fontSize;
  813. }
  814. void cmGrPlotObjSetLineColor( cmGrPlObjH_t oh, cmGrPlStateId_t id, const cmGrColor_t c )
  815. {
  816. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  817. assert( id < kMaxPlGrId );
  818. op->drawColors[ id ] = c;
  819. }
  820. const cmGrColor_t cmGrPlotObjLineColor( cmGrPlObjH_t oh, cmGrPlStateId_t id )
  821. {
  822. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  823. assert( id < kMaxPlGrId );
  824. return op->drawColors[id];
  825. }
  826. const cmGrColor_t cmGrPlotObjCurLineColor( cmGrPlObjH_t h )
  827. {
  828. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(h);
  829. return _cmGrPlotColor(op,op->drawColors);
  830. }
  831. void cmGrPlotObjSetFillColor( cmGrPlObjH_t oh, cmGrPlStateId_t id, const cmGrColor_t c )
  832. {
  833. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  834. assert( id < kMaxPlGrId );
  835. op->fillColors[ id ] = c;
  836. }
  837. const cmGrColor_t cmGrPlotObjFillColor( cmGrPlObjH_t oh, cmGrPlStateId_t id )
  838. {
  839. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(oh);
  840. assert( id < kMaxPlGrId );
  841. return op->fillColors[id];
  842. }
  843. const cmGrColor_t cmGrPlotObjCurFillColor( cmGrPlObjH_t h )
  844. {
  845. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(h);
  846. return _cmGrPlotColor(op,op->fillColors);
  847. }
  848. void cmGrPlotObjSetCb( cmGrPlObjH_t h, cmGrPlotCbFunc_t func, void* arg )
  849. {
  850. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(h);
  851. op->cbFunc = func;
  852. op->cbArg = arg;
  853. }
  854. cmGrPlotCbFunc_t cmGrPlotObjCbFunc( cmGrPlObjH_t h )
  855. {
  856. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(h);
  857. return op->cbFunc;
  858. }
  859. void* cmGrPlotObjCbArg( cmGrPlObjH_t h )
  860. {
  861. cmGrPlotObj_t* op = _cmGrPlObjHandleToPtr(h);
  862. return op->cbArg;
  863. }
  864. void cmGrPlotObjDrawAbove( cmGrPlObjH_t bH, cmGrPlObjH_t aH )
  865. {
  866. cmGrPlotObj_t* bop = _cmGrPlObjHandleToPtr(bH);
  867. cmGrPlotObj_t* aop = _cmGrPlObjHandleToPtr(aH);
  868. cmGrObjDrawAbove(bop->grObjH,aop->grObjH);
  869. }
  870. //------------------------------------------------------------------------------------------------------------------
  871. // Plot Object Manager Functions
  872. //------------------------------------------------------------------------------------------------------------------
  873. cmGrPlRC_t cmGrPlotCreate( cmCtx_t* ctx, cmGrPlH_t* hp )
  874. {
  875. cmGrPlRC_t rc;
  876. if((rc = cmGrPlotDestroy(hp)) != kOkGrPlRC )
  877. return rc;
  878. cmGrPl_t* p = cmMemAllocZ(cmGrPl_t,1);
  879. cmErrSetup(&p->err,&ctx->rpt,"cmGrPlot");
  880. p->ctx = ctx;
  881. hp->h = p;
  882. if( rc != kOkGrPlRC )
  883. _cmGrPlotDestroy(p);
  884. return rc;
  885. }
  886. cmGrPlRC_t cmGrPlotDestroy( cmGrPlH_t* hp )
  887. {
  888. cmGrPlRC_t rc;
  889. if( hp==NULL || cmGrPlotIsValid(*hp) == false )
  890. return kOkGrPlRC;
  891. cmGrPl_t* p = _cmGrPlHandleToPtr(*hp);
  892. if((rc = _cmGrPlotDestroy(p)) != kOkGrPlRC )
  893. return rc;
  894. hp->h = NULL;
  895. return rc;
  896. }
  897. bool cmGrPlotIsValid( cmGrPlH_t h )
  898. { return h.h != NULL; }
  899. cmGrPlRC_t cmGrPlotClear( cmGrPlH_t h )
  900. {
  901. cmGrPl_t* p = _cmGrPlHandleToPtr(h);
  902. return _cmGrPlotClear(p);
  903. }
  904. cmErr_t* cmGrPlotErr( cmGrPlH_t h )
  905. {
  906. cmGrPl_t* p = _cmGrPlHandleToPtr(h);
  907. return &p->err;
  908. }
  909. cmRpt_t* cmGrPlotRpt( cmGrPlH_t h )
  910. {
  911. cmGrPl_t* p = _cmGrPlHandleToPtr(h);
  912. return p->err.rpt;
  913. }
  914. cmGrPlObjH_t cmGrPlotObjectIdToHandle( cmGrPlH_t h, unsigned id )
  915. {
  916. cmGrPl_t* p = _cmGrPlHandleToPtr(h);
  917. cmGrPlObjH_t oh = cmGrPlObjNullHandle;
  918. cmGrPlotObj_t* op = p->list;
  919. for(; op!=NULL; op=op->next)
  920. if( cmGrObjId(op->grObjH) == id )
  921. {
  922. oh.h = op;
  923. break;
  924. }
  925. return oh;
  926. }
  927. unsigned cmGrPlotObjectCount( cmGrPlH_t h )
  928. {
  929. cmGrPl_t* p = _cmGrPlHandleToPtr(h);
  930. cmGrPlotObj_t* op = p->list;
  931. unsigned n = 0;
  932. for(; op!=NULL; ++n )
  933. op=op->next;
  934. return n;
  935. }
  936. cmGrPlObjH_t cmGrPlotObjectIndexToHandle( cmGrPlH_t h, unsigned index )
  937. {
  938. cmGrPl_t* p = _cmGrPlHandleToPtr(h);
  939. cmGrPlotObj_t* op = p->list;
  940. unsigned i = 0;
  941. cmGrPlObjH_t oh = cmGrPlObjNullHandle;
  942. for(; i<index && op!=NULL; ++i)
  943. op = op->next;
  944. if( op != NULL )
  945. oh.h = op;
  946. return oh;
  947. }
  948. void cmGrPlotKeyEvent( cmGrPlH_t h, cmGrH_t grH, unsigned eventFlags, cmGrKeyCodeId_t keycode )
  949. {
  950. assert( cmIsFlag(eventFlags,kKeyDnGrFl | kKeyUpGrFl));
  951. cmGrPl_t* p = _cmGrPlHandleToPtr(h);
  952. if( p->fop != NULL && cmHandlesAreEqual(p->fop->grH,grH) )
  953. {
  954. cmGrObjFuncArgs_t a;
  955. memset(&a,0,sizeof(a));
  956. a.cbArg = p->fop;
  957. a.ctx = p->ctx;
  958. a.grH = grH;
  959. a.objH = p->fop->grObjH;
  960. _cmGrPlotObjEvent(&a, eventFlags, keycode, 0, 0 );
  961. }
  962. }