libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmGrPage.c 36KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471
  1. #include "cmGlobal.h"
  2. #include "cmFloatTypes.h"
  3. #include "cmRpt.h"
  4. #include "cmErr.h"
  5. #include "cmCtx.h"
  6. #include "cmErr.h"
  7. #include "cmMem.h"
  8. #include "cmMallocDebug.h"
  9. #include "cmGr.h"
  10. #include "cmGrDevCtx.h"
  11. #include "cmGrPlot.h"
  12. #include "cmGrPage.h"
  13. #include "cmVectOpsTemplateMain.h"
  14. enum
  15. {
  16. kHashLength = 6,
  17. kHashCharCnt = 10,
  18. kMaxHashCnt = 10
  19. };
  20. enum
  21. {
  22. kNotValidFl = 0x01,
  23. kDirtyFl = 0x02, // set if the layout is dirty
  24. kFocusFl = 0x04
  25. };
  26. typedef struct
  27. {
  28. cmGrPPt_t xy0; //
  29. cmGrPPt_t xy1; // xy1 is on iext
  30. } cmGrPgHash_t;
  31. struct cmGrPgVw_str;
  32. struct cmGrPgAxis_str;
  33. struct cmGrPg_str;
  34. typedef struct cmGrPgLabelFunc_str
  35. {
  36. unsigned id;
  37. cmGrLabelFunc_t func;
  38. void* arg;
  39. cmChar_t* label;
  40. struct cmGrPgLabelFunc_str* link;
  41. } cmGrPgLabelFunc_t;
  42. typedef struct cmGrPgAxis_str
  43. {
  44. struct cmGrPgVw_str* vp;
  45. unsigned flags; // kHashMarkGrFl | kHashLabelGrFl
  46. unsigned hashCnt;
  47. unsigned hashLength;
  48. cmChar_t* title;
  49. cmGrPgHash_t* hash;
  50. unsigned maxHashCnt;
  51. cmGrPPt_t titlePt; // position of the axis title
  52. unsigned titleFontId; // title font id
  53. unsigned titleFontStyle; // title font style
  54. unsigned titleFontSize; // title font size
  55. cmGrPPt_t labelPt; // x = l/r label pos. and y=t/b label pos.
  56. unsigned labelFontId; // label font id
  57. unsigned labelFontStyle; // label font style
  58. unsigned labelFontSize; // label font size
  59. cmGrPgLabelFunc_t* func;
  60. } cmGrPgAxis_t;
  61. typedef struct cmGrPgVw_str
  62. {
  63. struct cmGrPg_str* p;
  64. cmGrH_t grH;
  65. unsigned ri; // row index
  66. unsigned ci; // column index
  67. cmGrPExt_t pext; // page around outside of view
  68. cmGrPExt_t iext; // view physical extents
  69. cmGrPgAxis_t axis[ kAxisGrCnt ]; //
  70. cmGrPPt_t titlePt; // lower/center position of the view title
  71. cmChar_t* title; // view title (upper center)
  72. unsigned fontId; // title font id
  73. unsigned fontStyle; // title font style
  74. unsigned fontSize; // title font size
  75. cmGrPgLabelFunc_t* xfunc;
  76. cmGrPgLabelFunc_t* yfunc;
  77. } cmGrPgVw_t;
  78. typedef struct cmGrPg_str
  79. {
  80. cmCtx_t ctx;
  81. cmErr_t err;
  82. cmGrCbFunc_t cbFunc;
  83. void* cbArg;
  84. unsigned flags; // kNotValidFl
  85. cmGrPExt_t pext; // outer border around all views
  86. unsigned rn; // count of rows
  87. unsigned cn; // count of columns
  88. unsigned vn; // view count (rn*cn)
  89. double* rpropV; // sum(rprop[rn]) == 1.0 pgaction of r.w() assigned to each row
  90. double* cpropV; // sum(cprop[cn]) == 1.0 pgaction of r.h() assigned to each row
  91. cmGrPgVw_t* viewV; // viewV[vn]
  92. unsigned focusIdx; // focused view index
  93. cmGrPPt_t titlePt; //
  94. cmChar_t* title; // page title
  95. unsigned fontId; // title font id
  96. unsigned fontStyle; // title font style
  97. unsigned fontSize; // title font size
  98. unsigned labelFuncId; // next page label function id
  99. cmGrPgLabelFunc_t* funcs; // linked list of value to string translation functions
  100. } cmGrPg_t;
  101. cmGrPgH_t cmGrPgNullHandle = cmSTATIC_NULL_HANDLE;
  102. cmGrVwH_t cmGrVwNullHandle = cmSTATIC_NULL_HANDLE;
  103. cmGrAxH_t cmGrAxNullHandle = cmSTATIC_NULL_HANDLE;
  104. cmGrPg_t* _cmGrPgHandleToPtr( cmGrPgH_t h )
  105. {
  106. cmGrPg_t* p = (cmGrPg_t*)h.h;
  107. assert( p!=NULL);
  108. return p;
  109. }
  110. cmGrPgVw_t* _cmGrPgVwHandleToPtr( cmGrVwH_t h )
  111. {
  112. cmGrPgVw_t* p = (cmGrPgVw_t*)h.h;
  113. assert( p!=NULL);
  114. return p;
  115. }
  116. cmGrPgAxis_t* _cmGrPgAxisHandleToPtr( cmGrAxH_t h )
  117. {
  118. cmGrPgAxis_t* p = (cmGrPgAxis_t*)h.h;
  119. assert( p!=NULL);
  120. return p;
  121. }
  122. void _cmGrPgVwAxisDestroy( cmGrPgAxis_t* ap )
  123. {
  124. ap->func = NULL;
  125. cmMemFree(ap->hash);
  126. cmMemFree(ap->title);
  127. }
  128. void _cmGrPgVwDestroy( cmGrPgVw_t* vp )
  129. {
  130. unsigned i;
  131. cmGrDestroy( &vp->grH );
  132. cmMemFree(vp->title);
  133. for(i=0; i<kAxisGrCnt; ++i)
  134. _cmGrPgVwAxisDestroy(vp->axis + i );
  135. }
  136. void _cmGrPgFinal( cmGrPg_t* p )
  137. {
  138. unsigned i;
  139. for(i=0; i<p->vn; ++i)
  140. _cmGrPgVwDestroy( p->viewV + i );
  141. cmGrPgLabelFunc_t* lfp = p->funcs;
  142. while( lfp != NULL )
  143. {
  144. cmGrPgLabelFunc_t* np = lfp->link;
  145. cmMemFree(lfp->label);
  146. cmMemFree(lfp);
  147. lfp = np;
  148. }
  149. p->funcs = NULL;
  150. cmMemFree(p->viewV);
  151. cmMemFree(p->title);
  152. cmMemFree(p->rpropV);
  153. cmMemFree(p->cpropV);
  154. }
  155. cmGrRC_t _cmGrPgDestroy( cmGrPg_t* p )
  156. {
  157. cmGrRC_t rc = kOkGrRC;
  158. _cmGrPgFinal(p);
  159. cmMemFree(p);
  160. return rc;
  161. }
  162. unsigned _cmGrPgGrHandleToVwIndex( cmGrPg_t* p, cmGrH_t grH )
  163. {
  164. unsigned i;
  165. for(i=0; i<p->vn; ++i)
  166. if( cmHandlesAreEqual(p->viewV[i].grH,grH) )
  167. return i;
  168. return cmInvalidIdx;
  169. }
  170. void _cmGrPageCallback( void* arg, cmGrH_t grH, cmGrCbId_t id, unsigned eventFlags, cmGrKeyCodeId_t keycode )
  171. {
  172. cmGrPg_t* p = (cmGrPg_t*)arg;
  173. switch(id)
  174. {
  175. case kCreateCbGrId:
  176. case kDestroyCbGrId:
  177. case kLocalPtCbGrId:
  178. case kGlobalPtCbGrId:
  179. case kPhysExtCbGrId:
  180. case kViewExtCbGrId:
  181. case kSelectExtCbGrId:
  182. if( p->cbFunc != NULL )
  183. p->cbFunc(p->cbArg,grH,id,eventFlags,keycode);
  184. break;
  185. case kKeyUpCbGrId:
  186. case kKeyDnCbGrId:
  187. {
  188. cmGrVwH_t vwH;
  189. cmGrPgH_t pgH;
  190. pgH.h = p;
  191. if(cmGrViewIsValid(vwH =cmGrPageFocusedView(pgH)))
  192. if( p->cbFunc != NULL )
  193. p->cbFunc(p->cbArg,cmGrViewGrHandle(vwH),id,eventFlags,keycode);
  194. }
  195. break;
  196. case kFocusCbGrId:
  197. {
  198. unsigned i;
  199. if((i = _cmGrPgGrHandleToVwIndex(p,grH)) != cmInvalidIdx )
  200. {
  201. cmGrPgH_t h;
  202. h.h = p;
  203. // if the focus is changing
  204. if( i != p->focusIdx )
  205. {
  206. // inform the prev view that it is losing focus
  207. if( p->focusIdx != cmInvalidIdx )
  208. cmGrPageViewFocus(h,p->focusIdx,false);
  209. // inform the new view that it is gaining focus
  210. cmGrPageViewFocus(h,i,true);
  211. if( p->cbFunc != NULL )
  212. p->cbFunc(p->cbArg,grH,id,eventFlags,keycode);
  213. }
  214. }
  215. }
  216. break;
  217. default:
  218. { assert(0); }
  219. }
  220. }
  221. cmGrRC_t cmGrPageCreate( cmCtx_t* ctx, cmGrPgH_t* hp, cmGrCbFunc_t cbFunc, void* cbArg )
  222. {
  223. cmGrRC_t rc;
  224. if((rc = cmGrPageDestroy(hp)) != kOkGrRC )
  225. return rc;
  226. cmGrPg_t* p = cmMemAllocZ(cmGrPg_t,1);
  227. cmErrSetup(&p->err,&ctx->rpt,"cmGrPage");
  228. p->cbFunc = cbFunc;
  229. p->cbArg = cbArg;
  230. p->ctx = *ctx;
  231. hp->h = p;
  232. if(rc != kOkGrRC )
  233. _cmGrPgDestroy(p);
  234. return rc;
  235. }
  236. cmGrRC_t cmGrPageDestroy( cmGrPgH_t* hp )
  237. {
  238. cmGrRC_t rc;
  239. if(hp==NULL || cmGrPageIsValid(*hp) == false )
  240. return kOkGrRC;
  241. cmGrPg_t* p = _cmGrPgHandleToPtr(*hp);
  242. if((rc = _cmGrPgDestroy(p)) != kOkGrRC )
  243. return rc;
  244. hp->h = NULL;
  245. return rc;
  246. }
  247. bool cmGrPageIsValid( cmGrPgH_t h )
  248. { return h.h != NULL; }
  249. cmGrRC_t cmGrPageClear( cmGrPgH_t h )
  250. {
  251. cmGrRC_t rc = kOkGrRC;
  252. unsigned i;
  253. for(i=0; i<cmGrPageViewCount(h); ++i)
  254. {
  255. cmGrVwH_t vwH = cmGrPageViewHandle(h,i);
  256. assert( cmGrViewIsValid(vwH) );
  257. if((rc = cmGrViewClear(vwH)) != kOkGrRC )
  258. break;
  259. }
  260. return rc;
  261. }
  262. // Calcuate the position of each view using the p->pext, and the row/col proportion vectors
  263. // This function calculates the outer page around each view.
  264. // It must be called whenever the size of the window holding the page changes.
  265. bool _cmGrPgLayoutVwPosition( cmGrPg_t* p )
  266. {
  267. enum { kVBord=4, kHBord=4 };
  268. // verify that the page state is sane
  269. if( p->rn==0 || p->cn==0 || p->pext.sz.h==0 || p->pext.sz.w==0)
  270. goto errLabel;
  271. else
  272. {
  273. unsigned i,j;
  274. int x=p->pext.loc.x;
  275. int y=p->pext.loc.y;
  276. // calculate the total page width/height w/o internal borders
  277. int h = p->pext.sz.h - ((p->rn - 1) * kVBord);
  278. int w = p->pext.sz.w - ((p->cn - 1) * kHBord);
  279. // verify that the page area exists
  280. if( h<=0 || w<=0 )
  281. goto errLabel;
  282. // force the row/col proportion vectors to sum to 1.0
  283. cmVOD_NormalizeProbability(p->rpropV,p->rn);
  284. cmVOD_NormalizeProbability(p->cpropV,p->cn);
  285. // determine the row height
  286. for(i=0; i<p->rn; ++i)
  287. {
  288. unsigned hh = (unsigned)floor(p->rpropV[i] * h);
  289. if( hh == 0 )
  290. goto errLabel;
  291. for(j=0; j<p->vn; ++j)
  292. if( p->viewV[j].ri == i )
  293. {
  294. p->viewV[j].pext.loc.y = y;
  295. p->viewV[j].pext.sz.h = hh;
  296. }
  297. y += hh + kVBord;
  298. }
  299. // determine the column width
  300. for(i=0; i<p->cn; ++i)
  301. {
  302. unsigned ww = (unsigned)floor(p->cpropV[i] * w);
  303. if( ww == 0 )
  304. goto errLabel;
  305. for(j=0; j<p->vn; ++j)
  306. if( p->viewV[j].ci == i )
  307. {
  308. p->viewV[j].pext.loc.x = x;
  309. p->viewV[j].pext.sz.w = ww;
  310. }
  311. x += ww + kHBord;
  312. }
  313. p->flags = cmClrFlag(p->flags,kNotValidFl);
  314. return true;
  315. }
  316. errLabel:
  317. p->flags = cmSetFlag(p->flags,kNotValidFl);
  318. return false;
  319. }
  320. // Calculate the layout for a given view.
  321. // txW = max hash label width on x-axis
  322. // txH = hash label height on x-axis
  323. void _cmGrPgLayoutView( cmGrPg_t* p, cmGrPgVw_t* vp, cmGrDcH_t dcH )
  324. {
  325. enum { kVBord=2, kHBord=2 };
  326. int x0 = vp->pext.loc.x + kHBord;
  327. int y0 = vp->pext.loc.y + kVBord;
  328. int w = vp->pext.sz.w - 2*kHBord;
  329. int h = vp->pext.sz.h - 2*kVBord;
  330. int y = y0;
  331. int x = x0;
  332. cmGrPSz_t sz;
  333. // Create a negative string with a repeating decimal to simulate an arbitrary hash label
  334. // Use the measurements pgom this string to compute the geometry of the view layouts.
  335. char label[ kHashCharCnt + 1];
  336. snprintf(label,kHashCharCnt,"%f",-4.0/3.0);
  337. label[kHashCharCnt] = 0;
  338. int mlx,mrx,mty,mby;
  339. int i;
  340. // add vertical space for the view title
  341. if( vp->title != NULL )
  342. {
  343. cmGrDcFontSetAndMeasure(dcH, vp->fontId, vp->fontSize, vp->fontStyle, vp->title, &sz );
  344. y += sz.h;
  345. vp->titlePt.y = y;
  346. vp->titlePt.x = vp->pext.loc.x + vp->pext.sz.w/2;
  347. y += 2;
  348. }
  349. cmGrPgAxis_t* ap = vp->axis + kTopGrIdx;
  350. // add vertical space for the top axis title
  351. if( ap->title != NULL )
  352. {
  353. cmGrDcFontSetAndMeasure(dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
  354. y += sz.h;
  355. ap->titlePt.y = y;
  356. y += 4;
  357. }
  358. // add vertical space for top axis hash labels
  359. if( cmIsFlag(ap->flags,kHashLabelGrFl ) )
  360. {
  361. cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
  362. y += sz.h;
  363. ap->labelPt.y = y;
  364. y += 1;
  365. }
  366. // calc vertical space for top axis hash marks
  367. if( cmIsFlag(ap->flags,kHashMarkGrFl ) )
  368. {
  369. mty = y;
  370. y += ap->hashLength + 1;
  371. }
  372. // set the internal pext vertical location
  373. vp->iext.loc.y = y;
  374. ap = vp->axis + kBottomGrIdx;
  375. y = y0 + h - 1 - kVBord;
  376. // subtract vertical space for bottom axis title
  377. if( ap->title != NULL )
  378. {
  379. cmGrDcFontSetAndMeasure(dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
  380. ap->titlePt.y = y;
  381. y -= sz.h + 4;
  382. }
  383. // calc vertical space for bottom axis hash label
  384. if( cmIsFlag(ap->flags,kHashLabelGrFl) )
  385. {
  386. cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
  387. ap->labelPt.y = y;
  388. y -= sz.h + 2;
  389. }
  390. // calc vertical space for bottom axis hash mark
  391. if( cmIsFlag(ap->flags,kHashMarkGrFl) )
  392. {
  393. mby = y;
  394. y -= ap->hashLength + 1;
  395. }
  396. // set the internal pext height
  397. vp->iext.sz.h = y - vp->iext.loc.y + 1;
  398. ap = vp->axis + kLeftGrIdx;
  399. // add horizontal space for the left axis title
  400. if( ap->title != NULL )
  401. {
  402. cmGrDcFontSetAndMeasure(dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
  403. x += sz.h; // use txH as approx of char. width for rotated title
  404. ap->titlePt.x = x;
  405. x += 4;
  406. }
  407. // add horizontal space for left axis hash labels
  408. if( cmIsFlag(ap->flags,kHashLabelGrFl ) )
  409. {
  410. cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
  411. ap->labelPt.x = x;
  412. x += sz.w + 3;
  413. }
  414. // calc horizontal space for left axis hash marks
  415. if( cmIsFlag(ap->flags,kHashMarkGrFl ) )
  416. {
  417. mlx = x;
  418. x += ap->hashLength + 1;
  419. }
  420. // set the internal pext horz location
  421. vp->iext.loc.x = x;
  422. ap = vp->axis + kRightGrIdx;
  423. x = x0 + w - 1 - kVBord;
  424. // subtract horizontal space for right axis title
  425. if( ap->title != NULL )
  426. {
  427. cmGrDcFontSetAndMeasure(dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
  428. ap->titlePt.x = x;
  429. x -= sz.h + 2; // use txH as approx of char. width for rotated title
  430. }
  431. // calc horizontal space for right axis hash label
  432. if( cmIsFlag(ap->flags,kHashLabelGrFl) )
  433. {
  434. cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
  435. x -= sz.w + 1;
  436. ap->labelPt.x = x;
  437. x -= 3;
  438. }
  439. // calc horizontal space for right axis hash mark
  440. if( cmIsFlag(ap->flags,kHashMarkGrFl) )
  441. {
  442. mrx = x;
  443. x -= ap->hashLength + 1;
  444. }
  445. // set the internal pext width
  446. vp->iext.sz.w = x - vp->iext.loc.x + 1;
  447. // calc the top hash count and alloc hash array
  448. ap = vp->axis + kTopGrIdx;
  449. cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
  450. ap->hashCnt = cmMin(ap->maxHashCnt,(vp->iext.sz.w + sz.w) / sz.w);
  451. ap->hash = cmMemResizeZ( cmGrPgHash_t, ap->hash, vp->axis[ kTopGrIdx ].hashCnt );
  452. // calc the bottom hash count and alloc hash array
  453. ap = vp->axis + kBottomGrIdx;
  454. cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
  455. ap->hashCnt = cmMin(ap->maxHashCnt,(vp->iext.sz.w + sz.w) / sz.w);
  456. ap->hash = cmMemResizeZ( cmGrPgHash_t, ap->hash, vp->axis[ kBottomGrIdx ].hashCnt );
  457. // calc the top hash mark line beg/end
  458. for(i=0; i< vp->axis[ kTopGrIdx ].hashCnt; ++i)
  459. {
  460. int x0 = round(vp->iext.loc.x - 1 + ((i * (vp->iext.sz.w + 1.0))/(vp->axis[ kTopGrIdx ].hashCnt-1)));
  461. vp->axis[kTopGrIdx].hash[i].xy0.y = mty;
  462. vp->axis[kTopGrIdx].hash[i].xy0.x = x0;
  463. vp->axis[kTopGrIdx].hash[i].xy1.y = vp->iext.loc.y - 1;
  464. vp->axis[kTopGrIdx].hash[i].xy1.x = x0;
  465. }
  466. // calc the bottom hash mark line beg/end
  467. for(i=0; i< vp->axis[ kBottomGrIdx ].hashCnt; ++i)
  468. {
  469. int x0 = round(vp->iext.loc.x - 1 + ((i * (vp->iext.sz.w + 1.0))/(vp->axis[ kBottomGrIdx ].hashCnt-1)));
  470. vp->axis[kBottomGrIdx].hash[i].xy0.y = mby;
  471. vp->axis[kBottomGrIdx].hash[i].xy0.x = x0;
  472. vp->axis[kBottomGrIdx].hash[i].xy1.y = cmGrPExtB(&vp->iext) + 1;
  473. vp->axis[kBottomGrIdx].hash[i].xy1.x = x0;
  474. }
  475. // calc the left hash count and alloc hash array
  476. ap = vp->axis + kLeftGrIdx;
  477. cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
  478. ap->hashCnt = cmMin(ap->maxHashCnt,(vp->iext.sz.h + sz.h) / sz.h);
  479. ap->hash = cmMemResizeZ( cmGrPgHash_t, ap->hash, vp->axis[ kLeftGrIdx ].hashCnt );
  480. // calc right hash count and alloc hash array
  481. ap = vp->axis + kRightGrIdx;
  482. cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
  483. ap->hashCnt = cmMin(ap->maxHashCnt,(vp->iext.sz.h + sz.h) / sz.h);
  484. ap->hash = cmMemResizeZ( cmGrPgHash_t, ap->hash, vp->axis[ kRightGrIdx ].hashCnt );
  485. // calc the left hash mark beg/end
  486. for(i=0; i< vp->axis[ kLeftGrIdx ].hashCnt; ++i)
  487. {
  488. int y0 = round(vp->iext.loc.y - 1 + ((i * (vp->iext.sz.h + 1.0))/(vp->axis[ kLeftGrIdx ].hashCnt-1)));
  489. vp->axis[kLeftGrIdx].hash[i].xy0.x = mlx;
  490. vp->axis[kLeftGrIdx].hash[i].xy0.y = y0;
  491. vp->axis[kLeftGrIdx].hash[i].xy1.x = vp->iext.loc.x - 1;
  492. vp->axis[kLeftGrIdx].hash[i].xy1.y = y0;
  493. }
  494. // calc the right hash mark beg/end
  495. for(i=0; i< vp->axis[ kRightGrIdx ].hashCnt; ++i)
  496. {
  497. int y0 = round(vp->iext.loc.y - 1 + ((i * (vp->iext.sz.h + 1.0))/(vp->axis[ kRightGrIdx ].hashCnt-1)));
  498. vp->axis[kRightGrIdx].hash[i].xy0.x = mrx;
  499. vp->axis[kRightGrIdx].hash[i].xy0.y = y0;
  500. vp->axis[kRightGrIdx].hash[i].xy1.x = cmGrPExtR(&vp->iext) + 1;
  501. vp->axis[kRightGrIdx].hash[i].xy1.y = y0;
  502. }
  503. // change the location of the view to match vp->iext
  504. if( cmGrIsValid( vp->grH ) )
  505. cmGrSetPhysExtentsE( vp->grH, &vp->iext );
  506. }
  507. void _cmGrPageLayout( cmGrPg_t* p, cmGrDcH_t dcH )
  508. {
  509. unsigned i;
  510. if( cmIsNotFlag(p->flags,kDirtyFl) )
  511. return;
  512. cmGrDcSetFontFamily(dcH,kHelveticaFfGrId);
  513. cmGrDcSetFontSize(dcH,10);
  514. // Create a negative string with a repeating decimal to simulate an arbitrary hash label
  515. // Use the measurements pgom this string to compute the geometry of the view layouts.
  516. char label[ kHashCharCnt + 1];
  517. cmGrPSz_t sz;
  518. snprintf(label,kHashCharCnt,"%f",-4.0/3.0);
  519. label[kHashCharCnt] = 0;
  520. cmGrDcMeasure(dcH,label,&sz);
  521. _cmGrPgLayoutVwPosition(p);
  522. for(i=0; i<p->vn; ++i)
  523. {
  524. cmGrPgVw_t* vp = p->viewV + i;
  525. _cmGrPgLayoutView(p, vp, dcH );
  526. }
  527. p->flags = cmClrFlag(p->flags,kDirtyFl);
  528. }
  529. cmGrRC_t cmGrPageInit( cmGrPgH_t h, const cmGrPExt_t* r, unsigned rn, unsigned cn, cmGrDcH_t dcH )
  530. {
  531. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  532. unsigned i;
  533. _cmGrPgFinal(p);
  534. if( rn*cn > 0 )
  535. {
  536. p->pext = *r;
  537. p->rn = rn;
  538. p->cn = cn;
  539. p->vn = rn*cn;
  540. p->rpropV = cmMemAllocZ(double, rn);
  541. p->cpropV = cmMemAllocZ(double, cn);
  542. p->viewV = cmMemAllocZ(cmGrPgVw_t, p->vn);
  543. p->flags = kDirtyFl;
  544. p->focusIdx = cmInvalidIdx;
  545. p->fontId = kHelveticaFfGrId;
  546. p->fontStyle = kNormalFsGrFl;
  547. p->fontSize = 16;
  548. // setup the view defaults
  549. for(i=0; i<p->vn; ++i)
  550. {
  551. cmGrPgVw_t* vp = p->viewV + i;
  552. vp->p = p;
  553. vp->ri = i % p->rn;
  554. vp->ci = i / p->rn;
  555. vp->fontId = kHelveticaFfGrId;
  556. vp->fontStyle = kNormalFsGrFl;
  557. vp->fontSize = 14;
  558. unsigned j;
  559. for(j=0; j<kAxisGrCnt; ++j)
  560. {
  561. cmGrPgAxis_t* ap = vp->axis + j;
  562. ap->vp = p->viewV + i;
  563. ap->maxHashCnt = kMaxHashCnt;
  564. ap->hashLength = kHashLength;
  565. ap->flags = kHashMarkGrFl | kHashLabelGrFl;
  566. ap->titleFontId = kHelveticaFfGrId;
  567. ap->titleFontStyle = kNormalFsGrFl;
  568. ap->titleFontSize = 10;
  569. ap->labelFontId = kHelveticaFfGrId;
  570. ap->labelFontStyle = kNormalFsGrFl;
  571. ap->labelFontSize = 10;
  572. }
  573. }
  574. // setup the default row proportions
  575. for(i=0; i<p->rn; ++i)
  576. p->rpropV[i] = 1.0/p->rn;
  577. // setup the default col proportions
  578. for(i=0; i<p->cn; ++i)
  579. p->cpropV[i] = 1.0/p->cn;
  580. // _cmGrPgLayoutVw() needs to be called.
  581. p->flags = cmSetFlag(p->flags,kDirtyFl);
  582. // layout the page
  583. _cmGrPageLayout(p, dcH );
  584. // notify the application that views have been created
  585. for(i=0; i<rn*cn; ++i)
  586. {
  587. cmGrPgVw_t* vp = p->viewV + i;
  588. // Set the 'id' assoc'd with this views cmGrH_t handle to 'i'.
  589. // This will allow the grH to return the index of the plot.
  590. if( cmGrCreate(&p->ctx,&vp->grH,i,kExpandViewGrFl,_cmGrPageCallback,p,NULL) == kOkGrRC )
  591. {
  592. //if( p->rspdr != NULL )
  593. // p->rspdr->on_view_create( p->rspdrArg, i );
  594. }
  595. }
  596. }
  597. return kOkGrRC;
  598. }
  599. cmGrRC_t cmGrPageResize( cmGrPgH_t h, const cmGrPExt_t* r, cmGrDcH_t dcH )
  600. {
  601. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  602. p->pext = *r;
  603. // _cmGrPgLayoutVw() needs to be called.
  604. p->flags = cmSetFlag(p->flags,kDirtyFl);
  605. // layout the page
  606. _cmGrPageLayout(p, dcH );
  607. return kOkGrRC;
  608. }
  609. void cmGrPageRect( cmGrPgH_t h, cmGrPExt_t* r )
  610. {
  611. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  612. *r = p->pext;
  613. }
  614. unsigned cmGrPageViewCount( cmGrPgH_t h )
  615. {
  616. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  617. return p->vn;
  618. }
  619. void _cmGrViewSetTitle(cmGrPgVw_t* vp, const cmChar_t* title )
  620. {
  621. if( title == vp->title || (title != NULL && vp->title!=NULL && strcmp(title,vp->title)==0 ))
  622. return;
  623. cmMemPtrFree(&vp->title);
  624. if( title != NULL )
  625. {
  626. assert( vp->title == NULL );
  627. vp->title = cmMemAllocStr(title);
  628. }
  629. vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
  630. }
  631. void _cmGrAxisSetTitle( cmGrPgAxis_t* ap, const cmChar_t* title )
  632. {
  633. if( title == ap->title || (title != NULL && ap->title!=NULL && strcmp(title,ap->title)==0 ))
  634. return;
  635. cmMemPtrFree(&ap->title);
  636. if( title != NULL )
  637. {
  638. assert( ap->title == NULL );
  639. ap->title = cmMemAllocStr(title);
  640. }
  641. ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
  642. }
  643. void _cmGrPgDrawHashMarks( cmGrPg_t* p, cmGrPgVw_t* vp, cmGrDcH_t dcH, unsigned lineColor )
  644. {
  645. int i,j;
  646. cmGrDcSetColor(dcH, lineColor );
  647. cmGrDcSetPenWidth( dcH, 1 );
  648. for(j=0; j<kAxisGrCnt; ++j )
  649. {
  650. cmGrPgAxis_t* ap = vp->axis + j;
  651. if( cmIsFlag(ap->flags, kHashMarkGrFl) )
  652. for(i=0; i<ap->hashCnt; ++i)
  653. {
  654. cmGrPgHash_t* hp = ap->hash + i;
  655. cmGrDcDrawLine(dcH, hp->xy0.x, hp->xy0.y, hp->xy1.x, hp->xy1.y);
  656. }
  657. }
  658. // draw border 1 pixel outside of iext
  659. cmGrDcDrawRect(dcH,vp->iext.loc.x-1,vp->iext.loc.y-1,vp->iext.sz.w+2,vp->iext.sz.h+2);
  660. //printf("pgm: x:%i y:%i\n", vp->iext.loc.x, vp->iext.loc.y);
  661. // draw the view border
  662. //cmGrDcDrawRect(dcH,vp->pext.loc.x,vp->pext.loc.y,vp->pext.sz.w,vp->pext.sz.h);
  663. }
  664. void _cmGrPgHashValueToLabel( cmGrPgAxis_t* ap, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value )
  665. {
  666. if( ap->func == NULL )
  667. snprintf(label,labelCharCnt,"%f",value);
  668. else
  669. {
  670. ap->func->func( ap->func->arg, label, labelCharCnt, value );
  671. }
  672. }
  673. void _cmGrPgDrawHashLabels( cmGrPg_t* p, cmGrPgVw_t* vp, cmGrDcH_t dcH, unsigned textColor )
  674. {
  675. int i;
  676. cmGrVExt_t vext;
  677. char s[ kHashCharCnt+1 ];
  678. s[kHashCharCnt]=0;
  679. cmGrViewExtents( vp->grH, &vext );
  680. //cmGrVExtPrint("hash:",&vext);
  681. cmGrDcSetColor(dcH, textColor );
  682. cmGrPgAxis_t* ap = vp->axis + kLeftGrIdx;
  683. cmGrDcSetFont( dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle );
  684. // draw the left axis hash labels
  685. if( cmIsFlag(ap->flags, kHashLabelGrFl ) )
  686. {
  687. for(i=0; i<vp->axis[ kLeftGrIdx ].hashCnt; ++i)
  688. {
  689. cmGrPSz_t sz;
  690. double v = vext.loc.y + vext.sz.h - (i * vext.sz.h / (ap->hashCnt-1) );
  691. _cmGrPgHashValueToLabel(ap,s,kHashCharCnt,v);
  692. cmGrDcMeasure(dcH,s,&sz);
  693. int y = ap->hash[i].xy0.y;
  694. cmGrDcDrawText(dcH, s, ap->labelPt.x, y + (sz.h/2) );
  695. }
  696. }
  697. ap = vp->axis + kRightGrIdx;
  698. cmGrDcSetFont( dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle );
  699. // draw the right axis hash labels
  700. if( cmIsFlag(ap->flags, kHashLabelGrFl ))
  701. {
  702. for(i=0; i<ap->hashCnt; ++i)
  703. {
  704. cmGrPSz_t sz;
  705. double v = vext.loc.y + vext.sz.h - (i * vext.sz.h / (ap->hashCnt-1) );
  706. _cmGrPgHashValueToLabel(ap,s,kHashCharCnt,v);
  707. cmGrDcMeasure(dcH,s,&sz);
  708. int y = ap->hash[i].xy0.y;
  709. cmGrDcDrawText(dcH, s, ap->labelPt.x, y + (sz.h/2));
  710. }
  711. }
  712. // draw the top axis hash labels
  713. ap = vp->axis + kTopGrIdx;
  714. cmGrDcSetFont( dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle );
  715. if( cmIsFlag(ap->flags, kHashLabelGrFl ) )
  716. {
  717. for(i=0; i<ap->hashCnt; ++i)
  718. {
  719. cmGrPSz_t sz;
  720. double v = vext.loc.x + (i * vext.sz.w / (ap->hashCnt-1));
  721. _cmGrPgHashValueToLabel(ap,s,kHashCharCnt,v);
  722. cmGrDcMeasure(dcH,s,&sz);
  723. cmGrDcDrawText(dcH, s, ap->hash[i].xy0.x - sz.w/2, ap->labelPt.y );
  724. }
  725. }
  726. // draw the bottom axis hash labels
  727. ap = vp->axis + kBottomGrIdx;
  728. cmGrDcSetFont( dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle );
  729. if( cmIsFlag(ap->flags, kHashLabelGrFl ) )
  730. {
  731. for(i=0; i<ap->hashCnt; ++i)
  732. {
  733. cmGrPSz_t sz;
  734. double v = vext.loc.x + (i * vext.sz.w / (ap->hashCnt-1));
  735. _cmGrPgHashValueToLabel(ap,s,kHashCharCnt,v);
  736. cmGrDcMeasure(dcH,s,&sz);
  737. cmGrDcDrawText(dcH, s, ap->hash[i].xy0.x - sz.w/2, ap->labelPt.y );
  738. }
  739. }
  740. }
  741. void _cmGrPgDrawAxisTitles( cmGrPg_t* p, cmGrPgVw_t* vp, cmGrDcH_t dcH )
  742. {
  743. unsigned i;
  744. for(i=0; i<kAxisGrCnt; ++i)
  745. {
  746. cmGrPgAxis_t* ap = vp->axis + i;
  747. if( ap->title != NULL )
  748. {
  749. cmGrPSz_t sz;
  750. cmGrDcFontSetAndMeasure( dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
  751. if( i==kBottomGrIdx || i==kTopGrIdx )
  752. {
  753. int x = vp->iext.loc.x + (vp->iext.sz.w/2) - (sz.w/2);
  754. cmGrDcDrawText( dcH, ap->title, x, ap->titlePt.y );
  755. }
  756. if( i==kLeftGrIdx || i==kRightGrIdx )
  757. {
  758. int y = vp->iext.loc.y + (vp->iext.sz.h/2) + (sz.w/2);
  759. cmGrDcDrawTextRot( dcH, ap->title, ap->titlePt.x, y, 90 );
  760. }
  761. }
  762. }
  763. }
  764. void cmGrPageViewFocus( cmGrPgH_t h, unsigned vwIdx, bool enableFl )
  765. {
  766. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  767. assert( vwIdx < p->vn );
  768. if( enableFl )
  769. p->focusIdx = vwIdx;
  770. else
  771. {
  772. if( p->focusIdx == vwIdx )
  773. p->focusIdx = cmInvalidId;
  774. }
  775. }
  776. cmGrVwH_t cmGrPageFocusedView( cmGrPgH_t h )
  777. {
  778. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  779. cmGrVwH_t vwH = cmGrVwNullHandle;
  780. if( p->focusIdx != cmInvalidIdx )
  781. vwH.h = p->viewV + p->focusIdx;
  782. return vwH;
  783. }
  784. void cmGrPageLayout( cmGrPgH_t h, cmGrDcH_t dcH )
  785. {
  786. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  787. cmGrDcPushCtx(dcH);
  788. _cmGrPageLayout(p,dcH);
  789. cmGrDcPopCtx(dcH);
  790. }
  791. void cmGrPageDraw( cmGrPgH_t h, cmGrDcH_t dcH )
  792. {
  793. unsigned i;
  794. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  795. cmGrDcPushCtx(dcH);
  796. _cmGrPageLayout(p,dcH);
  797. cmGrDcSetColor(dcH,kBlackGrId);
  798. // for each view
  799. for(i=0; i<p->vn; ++i)
  800. {
  801. cmGrPgVw_t* vp = p->viewV + i;
  802. unsigned lineColor = p->focusIdx==i ? kRedGrId : kBlackGrId;
  803. _cmGrPgDrawHashMarks( p, vp, dcH, lineColor );
  804. _cmGrPgDrawHashLabels( p, vp, dcH, kBlackGrId);
  805. _cmGrPgDrawAxisTitles( p, vp, dcH );
  806. if( vp->title != NULL )
  807. {
  808. cmGrPSz_t sz;
  809. cmGrDcFontSetAndMeasure(dcH,vp->fontId,vp->fontSize,vp->fontStyle,vp->title,&sz);
  810. cmGrDcDrawText(dcH,vp->title, vp->titlePt.x - sz.w/2, vp->titlePt.y );
  811. }
  812. }
  813. cmGrDcPopCtx(dcH);
  814. }
  815. cmGrPgLabelFunc_t* _cmGrPageLabelIndexToRecd( cmGrPg_t* p, unsigned idx )
  816. {
  817. cmGrPgLabelFunc_t* lfp = p->funcs;
  818. unsigned i;
  819. for(i=0; i<idx && lfp!=NULL; ++i)
  820. lfp=lfp->link;
  821. return lfp;
  822. }
  823. cmGrPgLabelFunc_t* _cmGrPageLabelIdToRecd( cmGrPg_t* p, unsigned id )
  824. {
  825. cmGrPgLabelFunc_t* lfp = p->funcs;
  826. for(; lfp!=NULL; lfp=lfp->link)
  827. if( lfp->id == id )
  828. return lfp;
  829. return lfp;
  830. }
  831. unsigned cmGrPageLabelFuncRegister( cmGrPgH_t h, cmGrLabelFunc_t func, void* arg, const cmChar_t* label )
  832. {
  833. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  834. cmGrPgLabelFunc_t* lfp = cmMemAllocZ(cmGrPgLabelFunc_t,1);
  835. lfp->id = p->labelFuncId++;
  836. lfp->func = func;
  837. lfp->arg = arg;
  838. lfp->label = cmMemAllocStr(label);
  839. lfp->link = p->funcs;
  840. p->funcs = lfp;
  841. return lfp->id;
  842. }
  843. unsigned cmGrPageLabelFuncCount( cmGrPgH_t h )
  844. {
  845. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  846. cmGrPgLabelFunc_t* lfp = p->funcs;
  847. unsigned n = 0;
  848. for(; lfp != NULL; lfp=lfp->link )
  849. ++n;
  850. return n;
  851. }
  852. unsigned cmGrPageLabelFuncIndexToId( cmGrPgH_t h, unsigned index )
  853. {
  854. cmGrPgLabelFunc_t* lfp;
  855. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  856. if((lfp = _cmGrPageLabelIndexToRecd(p,index)) == NULL )
  857. return cmInvalidId;
  858. return lfp->id;
  859. }
  860. unsigned cmGrPageLabelFuncLabelToId( cmGrPgH_t h, const cmChar_t* label )
  861. {
  862. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  863. cmGrPgLabelFunc_t* lfp = p->funcs;
  864. unsigned i;
  865. for(i=0; lfp!=NULL; lfp=lfp->link,++i)
  866. if( lfp->label!=NULL && strcmp(label,lfp->label)==0 )
  867. return lfp->id;
  868. return cmInvalidId;
  869. }
  870. cmGrLabelFunc_t cmGrPageLabelFunc( cmGrPgH_t h, unsigned id )
  871. {
  872. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  873. cmGrPgLabelFunc_t* lfp = _cmGrPageLabelIdToRecd(p,id);
  874. assert( lfp != NULL );
  875. return lfp->func;
  876. }
  877. const cmChar_t* cmGrPageLabelFuncLabel( cmGrPgH_t h, unsigned id )
  878. {
  879. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  880. cmGrPgLabelFunc_t* lfp = _cmGrPageLabelIdToRecd(p,id);
  881. assert( lfp != NULL );
  882. return lfp->label;
  883. }
  884. void* cmGrPageLabelFuncArg( cmGrPgH_t h, unsigned id )
  885. {
  886. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  887. cmGrPgLabelFunc_t* lfp = _cmGrPageLabelIdToRecd(p,id);
  888. assert( lfp != NULL );
  889. return lfp->arg;
  890. }
  891. cmGrVwH_t cmGrPageViewHandle( cmGrPgH_t h, unsigned vwIdx )
  892. {
  893. cmGrPg_t* p = _cmGrPgHandleToPtr(h);
  894. cmGrVwH_t vwH;
  895. assert( vwIdx < p->vn );
  896. vwH.h = p->viewV + vwIdx;
  897. return vwH;
  898. }
  899. cmGrVwH_t cmGrPageGrHandleToView( cmGrPgH_t pgH, cmGrH_t grH )
  900. {
  901. cmGrPg_t* p = _cmGrPgHandleToPtr(pgH);
  902. cmGrVwH_t vwH = cmGrVwNullHandle;
  903. int i;
  904. for(i=0; i<p->vn; ++i)
  905. if( cmHandlesAreEqual(grH,p->viewV[i].grH) )
  906. {
  907. vwH.h = p->viewV + i;
  908. break;
  909. }
  910. return vwH;
  911. }
  912. bool cmGrViewIsValid( cmGrVwH_t h )
  913. { return h.h != NULL; }
  914. cmGrRC_t cmGrViewInit( cmGrVwH_t h, cmGrH_t grH, const cmChar_t* vwTitle, const cmChar_t* xLabel, const cmChar_t* yLabel )
  915. {
  916. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  917. vp->grH = grH;
  918. _cmGrViewSetTitle( vp, vwTitle );
  919. _cmGrAxisSetTitle( vp->axis + kBottomGrIdx, xLabel );
  920. _cmGrAxisSetTitle( vp->axis + kLeftGrIdx, yLabel );
  921. vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
  922. return kOkGrRC;
  923. }
  924. cmGrRC_t cmGrViewClear( cmGrVwH_t h )
  925. {
  926. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  927. cmGrH_t grH = cmGrViewGrHandle(h);
  928. assert( cmGrIsValid(grH) );
  929. cmGrRC_t rc = cmGrClear( grH );
  930. vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
  931. return rc;
  932. }
  933. cmGrRC_t cmGrViewPExt( cmGrVwH_t h, cmGrPExt_t* pext )
  934. {
  935. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  936. *pext = vp->iext;
  937. return kOkGrRC;
  938. }
  939. bool cmGrViewHasFocus( cmGrVwH_t h )
  940. {
  941. if( cmGrViewIsValid(h) == false )
  942. return false;
  943. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  944. if( vp->p->focusIdx == cmInvalidIdx )
  945. return false;
  946. return cmGrId(vp->grH) == vp->p->focusIdx;
  947. }
  948. cmGrH_t cmGrViewGrHandle( cmGrVwH_t h )
  949. {
  950. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  951. return vp->grH;
  952. }
  953. void cmGrViewSetCfg( cmGrVwH_t h, unsigned cfgFlags )
  954. {
  955. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  956. cmGrSetCfgFlags( vp->grH, cfgFlags );
  957. vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
  958. }
  959. unsigned cmGrViewCfg( cmGrVwH_t h )
  960. {
  961. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  962. return cmGrCfgFlags( vp->grH );
  963. }
  964. void cmGrViewSetTitle( cmGrVwH_t h, const cmChar_t* title )
  965. {
  966. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  967. _cmGrViewSetTitle( vp, title );
  968. }
  969. const cmChar_t* cmGrViewTitle( cmGrVwH_t h )
  970. {
  971. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  972. return vp->title;
  973. }
  974. void cmGrViewSetFontFamily( cmGrVwH_t h, unsigned id )
  975. {
  976. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  977. if( vp->fontId != id )
  978. {
  979. vp->fontId = id;
  980. vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
  981. }
  982. }
  983. unsigned cmGrViewFontFamily( cmGrVwH_t h )
  984. {
  985. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  986. return vp->fontId;
  987. }
  988. void cmGrViewSetFontStyle( cmGrVwH_t h, unsigned flags )
  989. {
  990. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  991. if( vp->fontStyle != flags )
  992. {
  993. vp->fontStyle = flags;
  994. vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
  995. }
  996. }
  997. unsigned cmGrViewFontStyle( cmGrVwH_t h )
  998. {
  999. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  1000. return vp->fontStyle;
  1001. }
  1002. void cmGrViewSetFontSize( cmGrVwH_t h, unsigned size )
  1003. {
  1004. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  1005. if( vp->fontSize != size )
  1006. {
  1007. vp->fontSize = size;
  1008. vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
  1009. }
  1010. }
  1011. unsigned cmGrViewFontSize( cmGrVwH_t h )
  1012. {
  1013. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  1014. return vp->fontSize;
  1015. }
  1016. void cmGrViewSetLabelFunc( cmGrVwH_t h, cmGrAxisIdx_t axisId, unsigned pgLabelFuncId )
  1017. {
  1018. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  1019. cmGrPgLabelFunc_t** lfpp = NULL;
  1020. switch( axisId )
  1021. {
  1022. case kLeftGrIdx:
  1023. case kRightGrIdx:
  1024. lfpp = &vp->yfunc;
  1025. break;
  1026. case kTopGrIdx:
  1027. case kBottomGrIdx:
  1028. lfpp = &vp->xfunc;
  1029. break;
  1030. default:
  1031. { assert(0); }
  1032. }
  1033. assert( lfpp != NULL );
  1034. *lfpp = _cmGrPageLabelIdToRecd(vp->p, pgLabelFuncId );
  1035. }
  1036. const cmChar_t* cmGrViewValue( cmGrVwH_t h, cmGrViewValueId_t id, cmChar_t* buf, unsigned bufCharCnt )
  1037. {
  1038. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  1039. cmGrPgLabelFunc_t* lfp = NULL;
  1040. cmGrH_t grH = vp->grH;
  1041. cmGrV_t v;
  1042. cmGrVPt_t pt0,pt1;
  1043. switch( id )
  1044. {
  1045. case kLocalX_VwId:
  1046. v = cmGrLocalPt(grH)->x;
  1047. lfp = vp->xfunc;
  1048. break;
  1049. case kLocalY_VwId:
  1050. v = cmGrLocalPt(grH)->y;
  1051. lfp = vp->yfunc;
  1052. break;
  1053. case kGlobalX_VwId:
  1054. v = cmGrGlobalPt(grH)->x;
  1055. lfp = vp->xfunc;
  1056. break;
  1057. case kGlobalY_VwId:
  1058. v = cmGrGlobalPt(grH)->y;
  1059. lfp = vp->yfunc;
  1060. break;
  1061. case kSelX0_VwId:
  1062. cmGrSelectPoints(grH,&pt0,NULL);
  1063. v = pt0.x;
  1064. lfp = vp->xfunc;
  1065. break;
  1066. case kSelY0_VwId:
  1067. cmGrSelectPoints(grH,&pt0,NULL);
  1068. v = pt0.y;
  1069. lfp = vp->yfunc;
  1070. break;
  1071. case kSelX1_VwId:
  1072. cmGrSelectPoints(grH,NULL,&pt1);
  1073. v = pt1.x;
  1074. lfp = vp->xfunc;
  1075. break;
  1076. case kSelY1_VwId:
  1077. cmGrSelectPoints(grH,NULL,&pt1);
  1078. v = pt1.y;
  1079. lfp = vp->yfunc;
  1080. break;
  1081. case kSelW_VwId:
  1082. cmGrSelectPoints(grH,&pt0,&pt1);
  1083. v = fabs(pt1.x - pt0.x);
  1084. lfp = vp->xfunc;
  1085. break;
  1086. case kSelH_VwId:
  1087. cmGrSelectPoints(grH,&pt0,&pt1);
  1088. v = fabs(pt1.y - pt0.y);
  1089. lfp = vp->yfunc;
  1090. break;
  1091. default:
  1092. { assert(0); }
  1093. }
  1094. if( bufCharCnt > 0 )
  1095. {
  1096. buf[0]=0;
  1097. if( lfp != NULL )
  1098. lfp->func( lfp->arg, buf, bufCharCnt, v );
  1099. else
  1100. snprintf(buf,bufCharCnt,"%f",v);
  1101. }
  1102. return buf;
  1103. }
  1104. cmGrAxH_t cmGrViewAxisHandle( cmGrVwH_t h, cmGrAxisIdx_t axisIdx )
  1105. {
  1106. cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
  1107. cmGrAxH_t axH;
  1108. assert( axisIdx < kAxisGrCnt );
  1109. axH.h = vp->axis + axisIdx;
  1110. return axH;
  1111. }
  1112. bool cmGrAxisIsValid( cmGrAxH_t h )
  1113. { return h.h != NULL; }
  1114. void cmGrAxisSetCfg( cmGrAxH_t h, unsigned flags )
  1115. {
  1116. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1117. if( ap->flags != flags )
  1118. {
  1119. ap->flags = flags;
  1120. ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
  1121. }
  1122. }
  1123. unsigned cmGrAxisCfg( cmGrAxH_t h )
  1124. {
  1125. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1126. return ap->flags;
  1127. }
  1128. void cmGrAxisSetTitle( cmGrAxH_t h, const cmChar_t* title )
  1129. {
  1130. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1131. _cmGrAxisSetTitle(ap,title);
  1132. }
  1133. const cmChar_t* cmGrAxisTitle( cmGrAxH_t h )
  1134. {
  1135. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1136. return ap->title;
  1137. }
  1138. void cmGrAxisSetTitleFontFamily( cmGrAxH_t h, unsigned id )
  1139. {
  1140. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1141. if( ap->titleFontId != id )
  1142. {
  1143. ap->titleFontId = id;
  1144. ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
  1145. }
  1146. }
  1147. unsigned cmGrAxisTitleFontFamily( cmGrAxH_t h )
  1148. {
  1149. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1150. return ap->titleFontId;
  1151. }
  1152. void cmGrAxisTitleSetFontStyle( cmGrAxH_t h, unsigned flags )
  1153. {
  1154. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1155. if( ap->titleFontStyle != flags )
  1156. {
  1157. ap->titleFontStyle = flags;
  1158. ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
  1159. }
  1160. }
  1161. unsigned cmGrAxisTitleFontStyle( cmGrAxH_t h )
  1162. {
  1163. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1164. return ap->titleFontStyle;
  1165. }
  1166. void cmGrAxisTitleSetFontSize( cmGrAxH_t h, unsigned size )
  1167. {
  1168. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1169. if( ap->titleFontSize != size )
  1170. {
  1171. ap->titleFontSize = size;
  1172. ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
  1173. }
  1174. }
  1175. unsigned cmGrAxisTitleFontSize( cmGrAxH_t h )
  1176. {
  1177. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1178. return ap->titleFontSize;
  1179. }
  1180. void cmGrAxisSetLabelFunc( cmGrAxH_t h, unsigned id )
  1181. {
  1182. cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
  1183. ap->func = _cmGrPageLabelIdToRecd( ap->vp->p, id );
  1184. }