libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmGrPage.c 36KB

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