1472 lignes
36 KiB
C
1472 lignes
36 KiB
C
#include "cmGlobal.h"
|
|
#include "cmFloatTypes.h"
|
|
#include "cmRpt.h"
|
|
#include "cmErr.h"
|
|
#include "cmCtx.h"
|
|
#include "cmErr.h"
|
|
#include "cmMem.h"
|
|
#include "cmMallocDebug.h"
|
|
#include "cmGr.h"
|
|
#include "cmGrDevCtx.h"
|
|
#include "cmGrPlot.h"
|
|
#include "cmGrPage.h"
|
|
#include "cmVectOpsTemplateMain.h"
|
|
|
|
|
|
enum
|
|
{
|
|
kHashLength = 6,
|
|
kHashCharCnt = 10,
|
|
kMaxHashCnt = 10
|
|
};
|
|
|
|
enum
|
|
{
|
|
kNotValidFl = 0x01,
|
|
kDirtyFl = 0x02, // set if the layout is dirty
|
|
kFocusFl = 0x04
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
cmGrPPt_t xy0; //
|
|
cmGrPPt_t xy1; // xy1 is on iext
|
|
} cmGrPgHash_t;
|
|
|
|
struct cmGrPgVw_str;
|
|
struct cmGrPgAxis_str;
|
|
struct cmGrPg_str;
|
|
|
|
typedef struct cmGrPgLabelFunc_str
|
|
{
|
|
unsigned id;
|
|
cmGrLabelFunc_t func;
|
|
void* arg;
|
|
cmChar_t* label;
|
|
struct cmGrPgLabelFunc_str* link;
|
|
} cmGrPgLabelFunc_t;
|
|
|
|
typedef struct cmGrPgAxis_str
|
|
{
|
|
struct cmGrPgVw_str* vp;
|
|
unsigned flags; // kHashMarkGrFl | kHashLabelGrFl
|
|
unsigned hashCnt;
|
|
unsigned hashLength;
|
|
cmChar_t* title;
|
|
|
|
cmGrPgHash_t* hash;
|
|
|
|
unsigned maxHashCnt;
|
|
|
|
cmGrPPt_t titlePt; // position of the axis title
|
|
unsigned titleFontId; // title font id
|
|
unsigned titleFontStyle; // title font style
|
|
unsigned titleFontSize; // title font size
|
|
|
|
cmGrPPt_t labelPt; // x = l/r label pos. and y=t/b label pos.
|
|
unsigned labelFontId; // label font id
|
|
unsigned labelFontStyle; // label font style
|
|
unsigned labelFontSize; // label font size
|
|
|
|
cmGrPgLabelFunc_t* func;
|
|
} cmGrPgAxis_t;
|
|
|
|
typedef struct cmGrPgVw_str
|
|
{
|
|
struct cmGrPg_str* p;
|
|
cmGrH_t grH;
|
|
unsigned ri; // row index
|
|
unsigned ci; // column index
|
|
cmGrPExt_t pext; // page around outside of view
|
|
cmGrPExt_t iext; // view physical extents
|
|
cmGrPgAxis_t axis[ kAxisGrCnt ]; //
|
|
cmGrPPt_t titlePt; // lower/center position of the view title
|
|
cmChar_t* title; // view title (upper center)
|
|
unsigned fontId; // title font id
|
|
unsigned fontStyle; // title font style
|
|
unsigned fontSize; // title font size
|
|
|
|
cmGrPgLabelFunc_t* xfunc;
|
|
cmGrPgLabelFunc_t* yfunc;
|
|
} cmGrPgVw_t;
|
|
|
|
typedef struct cmGrPg_str
|
|
{
|
|
cmCtx_t ctx;
|
|
cmErr_t err;
|
|
cmGrCbFunc_t cbFunc;
|
|
void* cbArg;
|
|
unsigned flags; // kNotValidFl
|
|
cmGrPExt_t pext; // outer border around all views
|
|
unsigned rn; // count of rows
|
|
unsigned cn; // count of columns
|
|
unsigned vn; // view count (rn*cn)
|
|
double* rpropV; // sum(rprop[rn]) == 1.0 pgaction of r.w() assigned to each row
|
|
double* cpropV; // sum(cprop[cn]) == 1.0 pgaction of r.h() assigned to each row
|
|
cmGrPgVw_t* viewV; // viewV[vn]
|
|
unsigned focusIdx; // focused view index
|
|
|
|
cmGrPPt_t titlePt; //
|
|
cmChar_t* title; // page title
|
|
unsigned fontId; // title font id
|
|
unsigned fontStyle; // title font style
|
|
unsigned fontSize; // title font size
|
|
|
|
unsigned labelFuncId; // next page label function id
|
|
cmGrPgLabelFunc_t* funcs; // linked list of value to string translation functions
|
|
|
|
} cmGrPg_t;
|
|
|
|
cmGrPgH_t cmGrPgNullHandle = cmSTATIC_NULL_HANDLE;
|
|
cmGrVwH_t cmGrVwNullHandle = cmSTATIC_NULL_HANDLE;
|
|
cmGrAxH_t cmGrAxNullHandle = cmSTATIC_NULL_HANDLE;
|
|
|
|
cmGrPg_t* _cmGrPgHandleToPtr( cmGrPgH_t h )
|
|
{
|
|
cmGrPg_t* p = (cmGrPg_t*)h.h;
|
|
assert( p!=NULL);
|
|
return p;
|
|
}
|
|
|
|
cmGrPgVw_t* _cmGrPgVwHandleToPtr( cmGrVwH_t h )
|
|
{
|
|
cmGrPgVw_t* p = (cmGrPgVw_t*)h.h;
|
|
assert( p!=NULL);
|
|
return p;
|
|
}
|
|
|
|
cmGrPgAxis_t* _cmGrPgAxisHandleToPtr( cmGrAxH_t h )
|
|
{
|
|
cmGrPgAxis_t* p = (cmGrPgAxis_t*)h.h;
|
|
assert( p!=NULL);
|
|
return p;
|
|
}
|
|
|
|
|
|
void _cmGrPgVwAxisDestroy( cmGrPgAxis_t* ap )
|
|
{
|
|
ap->func = NULL;
|
|
|
|
cmMemFree(ap->hash);
|
|
cmMemFree(ap->title);
|
|
}
|
|
|
|
void _cmGrPgVwDestroy( cmGrPgVw_t* vp )
|
|
{
|
|
unsigned i;
|
|
|
|
cmGrDestroy( &vp->grH );
|
|
|
|
cmMemFree(vp->title);
|
|
for(i=0; i<kAxisGrCnt; ++i)
|
|
_cmGrPgVwAxisDestroy(vp->axis + i );
|
|
}
|
|
|
|
void _cmGrPgFinal( cmGrPg_t* p )
|
|
{
|
|
unsigned i;
|
|
for(i=0; i<p->vn; ++i)
|
|
_cmGrPgVwDestroy( p->viewV + i );
|
|
|
|
cmGrPgLabelFunc_t* lfp = p->funcs;
|
|
while( lfp != NULL )
|
|
{
|
|
cmGrPgLabelFunc_t* np = lfp->link;
|
|
cmMemFree(lfp->label);
|
|
cmMemFree(lfp);
|
|
lfp = np;
|
|
}
|
|
|
|
p->funcs = NULL;
|
|
|
|
cmMemFree(p->viewV);
|
|
cmMemFree(p->title);
|
|
cmMemFree(p->rpropV);
|
|
cmMemFree(p->cpropV);
|
|
}
|
|
|
|
cmGrRC_t _cmGrPgDestroy( cmGrPg_t* p )
|
|
{
|
|
cmGrRC_t rc = kOkGrRC;
|
|
_cmGrPgFinal(p);
|
|
cmMemFree(p);
|
|
return rc;
|
|
}
|
|
|
|
unsigned _cmGrPgGrHandleToVwIndex( cmGrPg_t* p, cmGrH_t grH )
|
|
{
|
|
unsigned i;
|
|
for(i=0; i<p->vn; ++i)
|
|
if( cmHandlesAreEqual(p->viewV[i].grH,grH) )
|
|
return i;
|
|
|
|
return cmInvalidIdx;
|
|
}
|
|
|
|
void _cmGrPageCallback( void* arg, cmGrH_t grH, cmGrCbId_t id, unsigned eventFlags, cmGrKeyCodeId_t keycode )
|
|
{
|
|
cmGrPg_t* p = (cmGrPg_t*)arg;
|
|
|
|
switch(id)
|
|
{
|
|
case kCreateCbGrId:
|
|
case kDestroyCbGrId:
|
|
case kLocalPtCbGrId:
|
|
case kGlobalPtCbGrId:
|
|
case kPhysExtCbGrId:
|
|
case kViewExtCbGrId:
|
|
case kSelectExtCbGrId:
|
|
if( p->cbFunc != NULL )
|
|
p->cbFunc(p->cbArg,grH,id,eventFlags,keycode);
|
|
break;
|
|
|
|
case kKeyUpCbGrId:
|
|
case kKeyDnCbGrId:
|
|
{
|
|
cmGrVwH_t vwH;
|
|
cmGrPgH_t pgH;
|
|
pgH.h = p;
|
|
if(cmGrViewIsValid(vwH =cmGrPageFocusedView(pgH)))
|
|
if( p->cbFunc != NULL )
|
|
p->cbFunc(p->cbArg,cmGrViewGrHandle(vwH),id,eventFlags,keycode);
|
|
|
|
}
|
|
break;
|
|
|
|
case kFocusCbGrId:
|
|
{
|
|
unsigned i;
|
|
if((i = _cmGrPgGrHandleToVwIndex(p,grH)) != cmInvalidIdx )
|
|
{
|
|
cmGrPgH_t h;
|
|
h.h = p;
|
|
|
|
// if the focus is changing
|
|
if( i != p->focusIdx )
|
|
{
|
|
// inform the prev view that it is losing focus
|
|
if( p->focusIdx != cmInvalidIdx )
|
|
cmGrPageViewFocus(h,p->focusIdx,false);
|
|
|
|
// inform the new view that it is gaining focus
|
|
cmGrPageViewFocus(h,i,true);
|
|
|
|
if( p->cbFunc != NULL )
|
|
p->cbFunc(p->cbArg,grH,id,eventFlags,keycode);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{ assert(0); }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
cmGrRC_t cmGrPageCreate( cmCtx_t* ctx, cmGrPgH_t* hp, cmGrCbFunc_t cbFunc, void* cbArg )
|
|
{
|
|
cmGrRC_t rc;
|
|
if((rc = cmGrPageDestroy(hp)) != kOkGrRC )
|
|
return rc;
|
|
|
|
cmGrPg_t* p = cmMemAllocZ(cmGrPg_t,1);
|
|
|
|
cmErrSetup(&p->err,&ctx->rpt,"cmGrPage");
|
|
p->cbFunc = cbFunc;
|
|
p->cbArg = cbArg;
|
|
p->ctx = *ctx;
|
|
hp->h = p;
|
|
|
|
if(rc != kOkGrRC )
|
|
_cmGrPgDestroy(p);
|
|
return rc;
|
|
}
|
|
|
|
cmGrRC_t cmGrPageDestroy( cmGrPgH_t* hp )
|
|
{
|
|
cmGrRC_t rc;
|
|
if(hp==NULL || cmGrPageIsValid(*hp) == false )
|
|
return kOkGrRC;
|
|
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(*hp);
|
|
|
|
if((rc = _cmGrPgDestroy(p)) != kOkGrRC )
|
|
return rc;
|
|
|
|
hp->h = NULL;
|
|
|
|
return rc;
|
|
}
|
|
|
|
bool cmGrPageIsValid( cmGrPgH_t h )
|
|
{ return h.h != NULL; }
|
|
|
|
cmGrRC_t cmGrPageClear( cmGrPgH_t h )
|
|
{
|
|
cmGrRC_t rc = kOkGrRC;
|
|
unsigned i;
|
|
for(i=0; i<cmGrPageViewCount(h); ++i)
|
|
{
|
|
cmGrVwH_t vwH = cmGrPageViewHandle(h,i);
|
|
assert( cmGrViewIsValid(vwH) );
|
|
if((rc = cmGrViewClear(vwH)) != kOkGrRC )
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
// Calcuate the position of each view using the p->pext, and the row/col proportion vectors
|
|
// This function calculates the outer page around each view.
|
|
// It must be called whenever the size of the window holding the page changes.
|
|
bool _cmGrPgLayoutVwPosition( cmGrPg_t* p )
|
|
{
|
|
enum { kVBord=4, kHBord=4 };
|
|
|
|
// verify that the page state is sane
|
|
if( p->rn==0 || p->cn==0 || p->pext.sz.h==0 || p->pext.sz.w==0)
|
|
goto errLabel;
|
|
|
|
else
|
|
{
|
|
unsigned i,j;
|
|
int x=p->pext.loc.x;
|
|
int y=p->pext.loc.y;
|
|
|
|
// calculate the total page width/height w/o internal borders
|
|
int h = p->pext.sz.h - ((p->rn - 1) * kVBord);
|
|
int w = p->pext.sz.w - ((p->cn - 1) * kHBord);
|
|
|
|
// verify that the page area exists
|
|
if( h<=0 || w<=0 )
|
|
goto errLabel;
|
|
|
|
// force the row/col proportion vectors to sum to 1.0
|
|
cmVOD_NormalizeProbability(p->rpropV,p->rn);
|
|
cmVOD_NormalizeProbability(p->cpropV,p->cn);
|
|
|
|
// determine the row height
|
|
for(i=0; i<p->rn; ++i)
|
|
{
|
|
unsigned hh = (unsigned)floor(p->rpropV[i] * h);
|
|
|
|
if( hh == 0 )
|
|
goto errLabel;
|
|
|
|
for(j=0; j<p->vn; ++j)
|
|
if( p->viewV[j].ri == i )
|
|
{
|
|
p->viewV[j].pext.loc.y = y;
|
|
p->viewV[j].pext.sz.h = hh;
|
|
}
|
|
|
|
y += hh + kVBord;
|
|
}
|
|
|
|
// determine the column width
|
|
for(i=0; i<p->cn; ++i)
|
|
{
|
|
unsigned ww = (unsigned)floor(p->cpropV[i] * w);
|
|
|
|
if( ww == 0 )
|
|
goto errLabel;
|
|
|
|
for(j=0; j<p->vn; ++j)
|
|
if( p->viewV[j].ci == i )
|
|
{
|
|
p->viewV[j].pext.loc.x = x;
|
|
p->viewV[j].pext.sz.w = ww;
|
|
}
|
|
|
|
x += ww + kHBord;
|
|
}
|
|
|
|
p->flags = cmClrFlag(p->flags,kNotValidFl);
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
errLabel:
|
|
p->flags = cmSetFlag(p->flags,kNotValidFl);
|
|
|
|
return false;
|
|
}
|
|
|
|
// Calculate the layout for a given view.
|
|
// txW = max hash label width on x-axis
|
|
// txH = hash label height on x-axis
|
|
void _cmGrPgLayoutView( cmGrPg_t* p, cmGrPgVw_t* vp, cmGrDcH_t dcH )
|
|
{
|
|
enum { kVBord=2, kHBord=2 };
|
|
|
|
int x0 = vp->pext.loc.x + kHBord;
|
|
int y0 = vp->pext.loc.y + kVBord;
|
|
int w = vp->pext.sz.w - 2*kHBord;
|
|
int h = vp->pext.sz.h - 2*kVBord;
|
|
|
|
int y = y0;
|
|
int x = x0;
|
|
|
|
cmGrPSz_t sz;
|
|
|
|
|
|
// Create a negative string with a repeating decimal to simulate an arbitrary hash label
|
|
// Use the measurements from this string to compute the geometry of the view layouts.
|
|
char label[ kHashCharCnt + 1];
|
|
snprintf(label,kHashCharCnt,"%f",-4.0/3.0);
|
|
label[kHashCharCnt] = 0;
|
|
|
|
int mlx,mrx,mty,mby;
|
|
int i;
|
|
|
|
// add vertical space for the view title
|
|
if( vp->title != NULL )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, vp->fontId, vp->fontSize, vp->fontStyle, vp->title, &sz );
|
|
y += sz.h;
|
|
vp->titlePt.y = y;
|
|
vp->titlePt.x = vp->pext.loc.x + vp->pext.sz.w/2;
|
|
y += 2;
|
|
}
|
|
|
|
cmGrPgAxis_t* ap = vp->axis + kTopGrIdx;
|
|
|
|
// add vertical space for the top axis title
|
|
if( ap->title != NULL )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
|
|
y += sz.h;
|
|
ap->titlePt.y = y;
|
|
y += 4;
|
|
}
|
|
|
|
// add vertical space for top axis hash labels
|
|
if( cmIsFlag(ap->flags,kHashLabelGrFl ) )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
|
|
y += sz.h;
|
|
ap->labelPt.y = y;
|
|
y += 1;
|
|
}
|
|
|
|
// calc vertical space for top axis hash marks
|
|
if( cmIsFlag(ap->flags,kHashMarkGrFl ) )
|
|
{
|
|
mty = y;
|
|
y += ap->hashLength + 1;
|
|
}
|
|
|
|
// set the internal pext vertical location
|
|
vp->iext.loc.y = y;
|
|
|
|
ap = vp->axis + kBottomGrIdx;
|
|
y = y0 + h - 1 - kVBord;
|
|
|
|
// subtract vertical space for bottom axis title
|
|
if( ap->title != NULL )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
|
|
ap->titlePt.y = y;
|
|
y -= sz.h + 4;
|
|
}
|
|
|
|
// calc vertical space for bottom axis hash label
|
|
if( cmIsFlag(ap->flags,kHashLabelGrFl) )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
|
|
ap->labelPt.y = y;
|
|
y -= sz.h + 2;
|
|
}
|
|
|
|
// calc vertical space for bottom axis hash mark
|
|
if( cmIsFlag(ap->flags,kHashMarkGrFl) )
|
|
{
|
|
mby = y;
|
|
y -= ap->hashLength + 1;
|
|
}
|
|
|
|
// set the internal pext height
|
|
vp->iext.sz.h = y - vp->iext.loc.y + 1;
|
|
|
|
|
|
ap = vp->axis + kLeftGrIdx;
|
|
|
|
// add horizontal space for the left axis title
|
|
if( ap->title != NULL )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
|
|
|
|
x += sz.h; // use txH as approx of char. width for rotated title
|
|
ap->titlePt.x = x;
|
|
x += 4;
|
|
}
|
|
|
|
// add horizontal space for left axis hash labels
|
|
if( cmIsFlag(ap->flags,kHashLabelGrFl ) )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
|
|
|
|
ap->labelPt.x = x;
|
|
x += sz.w + 3;
|
|
}
|
|
|
|
// calc horizontal space for left axis hash marks
|
|
if( cmIsFlag(ap->flags,kHashMarkGrFl ) )
|
|
{
|
|
mlx = x;
|
|
x += ap->hashLength + 1;
|
|
}
|
|
|
|
// set the internal pext horz location
|
|
vp->iext.loc.x = x;
|
|
|
|
ap = vp->axis + kRightGrIdx;
|
|
x = x0 + w - 1 - kVBord;
|
|
|
|
// subtract horizontal space for right axis title
|
|
if( ap->title != NULL )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
|
|
|
|
ap->titlePt.x = x;
|
|
x -= sz.h + 2; // use txH as approx of char. width for rotated title
|
|
}
|
|
|
|
// calc horizontal space for right axis hash label
|
|
if( cmIsFlag(ap->flags,kHashLabelGrFl) )
|
|
{
|
|
cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
|
|
|
|
x -= sz.w + 1;
|
|
ap->labelPt.x = x;
|
|
x -= 3;
|
|
}
|
|
|
|
// calc horizontal space for right axis hash mark
|
|
if( cmIsFlag(ap->flags,kHashMarkGrFl) )
|
|
{
|
|
mrx = x;
|
|
x -= ap->hashLength + 1;
|
|
}
|
|
|
|
// set the internal pext width
|
|
vp->iext.sz.w = x - vp->iext.loc.x + 1;
|
|
|
|
|
|
// calc the top hash count and alloc hash array
|
|
ap = vp->axis + kTopGrIdx;
|
|
cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
|
|
ap->hashCnt = cmMin(ap->maxHashCnt,(vp->iext.sz.w + sz.w) / sz.w);
|
|
ap->hash = cmMemResizeZ( cmGrPgHash_t, ap->hash, vp->axis[ kTopGrIdx ].hashCnt );
|
|
|
|
// calc the bottom hash count and alloc hash array
|
|
ap = vp->axis + kBottomGrIdx;
|
|
cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
|
|
ap->hashCnt = cmMin(ap->maxHashCnt,(vp->iext.sz.w + sz.w) / sz.w);
|
|
ap->hash = cmMemResizeZ( cmGrPgHash_t, ap->hash, vp->axis[ kBottomGrIdx ].hashCnt );
|
|
|
|
// calc the top hash mark line beg/end
|
|
for(i=0; i< vp->axis[ kTopGrIdx ].hashCnt; ++i)
|
|
{
|
|
int x0 = round(vp->iext.loc.x - 1 + ((i * (vp->iext.sz.w + 1.0))/(vp->axis[ kTopGrIdx ].hashCnt-1)));
|
|
|
|
vp->axis[kTopGrIdx].hash[i].xy0.y = mty;
|
|
vp->axis[kTopGrIdx].hash[i].xy0.x = x0;
|
|
vp->axis[kTopGrIdx].hash[i].xy1.y = vp->iext.loc.y - 1;
|
|
vp->axis[kTopGrIdx].hash[i].xy1.x = x0;
|
|
}
|
|
|
|
// calc the bottom hash mark line beg/end
|
|
for(i=0; i< vp->axis[ kBottomGrIdx ].hashCnt; ++i)
|
|
{
|
|
int x0 = round(vp->iext.loc.x - 1 + ((i * (vp->iext.sz.w + 1.0))/(vp->axis[ kBottomGrIdx ].hashCnt-1)));
|
|
|
|
vp->axis[kBottomGrIdx].hash[i].xy0.y = mby;
|
|
vp->axis[kBottomGrIdx].hash[i].xy0.x = x0;
|
|
vp->axis[kBottomGrIdx].hash[i].xy1.y = cmGrPExtB(&vp->iext) + 1;
|
|
vp->axis[kBottomGrIdx].hash[i].xy1.x = x0;
|
|
}
|
|
|
|
// calc the left hash count and alloc hash array
|
|
ap = vp->axis + kLeftGrIdx;
|
|
cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
|
|
ap->hashCnt = cmMin(ap->maxHashCnt,(vp->iext.sz.h + sz.h) / sz.h);
|
|
ap->hash = cmMemResizeZ( cmGrPgHash_t, ap->hash, vp->axis[ kLeftGrIdx ].hashCnt );
|
|
|
|
// calc right hash count and alloc hash array
|
|
ap = vp->axis + kRightGrIdx;
|
|
cmGrDcFontSetAndMeasure(dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle, label, &sz );
|
|
ap->hashCnt = cmMin(ap->maxHashCnt,(vp->iext.sz.h + sz.h) / sz.h);
|
|
ap->hash = cmMemResizeZ( cmGrPgHash_t, ap->hash, vp->axis[ kRightGrIdx ].hashCnt );
|
|
|
|
|
|
// calc the left hash mark beg/end
|
|
for(i=0; i< vp->axis[ kLeftGrIdx ].hashCnt; ++i)
|
|
{
|
|
int y0 = round(vp->iext.loc.y - 1 + ((i * (vp->iext.sz.h + 1.0))/(vp->axis[ kLeftGrIdx ].hashCnt-1)));
|
|
|
|
vp->axis[kLeftGrIdx].hash[i].xy0.x = mlx;
|
|
vp->axis[kLeftGrIdx].hash[i].xy0.y = y0;
|
|
vp->axis[kLeftGrIdx].hash[i].xy1.x = vp->iext.loc.x - 1;
|
|
vp->axis[kLeftGrIdx].hash[i].xy1.y = y0;
|
|
}
|
|
|
|
// calc the right hash mark beg/end
|
|
for(i=0; i< vp->axis[ kRightGrIdx ].hashCnt; ++i)
|
|
{
|
|
int y0 = round(vp->iext.loc.y - 1 + ((i * (vp->iext.sz.h + 1.0))/(vp->axis[ kRightGrIdx ].hashCnt-1)));
|
|
|
|
vp->axis[kRightGrIdx].hash[i].xy0.x = mrx;
|
|
vp->axis[kRightGrIdx].hash[i].xy0.y = y0;
|
|
vp->axis[kRightGrIdx].hash[i].xy1.x = cmGrPExtR(&vp->iext) + 1;
|
|
vp->axis[kRightGrIdx].hash[i].xy1.y = y0;
|
|
}
|
|
|
|
// change the location of the view to match vp->iext
|
|
if( cmGrIsValid( vp->grH ) )
|
|
cmGrSetPhysExtentsE( vp->grH, &vp->iext );
|
|
|
|
}
|
|
|
|
bool _cmGrPageLayout( cmGrPg_t* p, cmGrDcH_t dcH )
|
|
{
|
|
unsigned i;
|
|
|
|
if( cmIsNotFlag(p->flags,kDirtyFl) )
|
|
return false;
|
|
|
|
cmGrDcSetFontFamily(dcH,kHelveticaFfGrId);
|
|
cmGrDcSetFontSize(dcH,10);
|
|
|
|
// Create a negative string with a repeating decimal to simulate an arbitrary hash label
|
|
// Use the measurements pgom this string to compute the geometry of the view layouts.
|
|
/*
|
|
char label[ kHashCharCnt + 1];
|
|
cmGrPSz_t sz;
|
|
snprintf(label,kHashCharCnt,"%f",-4.0/3.0);
|
|
label[kHashCharCnt] = 0;
|
|
cmGrDcMeasure(dcH,label,&sz);
|
|
*/
|
|
|
|
_cmGrPgLayoutVwPosition(p);
|
|
|
|
for(i=0; i<p->vn; ++i)
|
|
{
|
|
cmGrPgVw_t* vp = p->viewV + i;
|
|
|
|
_cmGrPgLayoutView(p, vp, dcH );
|
|
}
|
|
|
|
p->flags = cmClrFlag(p->flags,kDirtyFl);
|
|
|
|
return true;
|
|
}
|
|
|
|
cmGrRC_t cmGrPageInit( cmGrPgH_t h, const cmGrPExt_t* r, unsigned rn, unsigned cn, cmGrDcH_t dcH )
|
|
{
|
|
cmGrRC_t rc = kOkGrRC;
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
unsigned i;
|
|
|
|
_cmGrPgFinal(p);
|
|
|
|
if( rn*cn > 0 )
|
|
{
|
|
p->pext = *r;
|
|
p->rn = rn;
|
|
p->cn = cn;
|
|
p->vn = rn*cn;
|
|
p->rpropV = cmMemAllocZ(double, rn);
|
|
p->cpropV = cmMemAllocZ(double, cn);
|
|
p->viewV = cmMemAllocZ(cmGrPgVw_t, p->vn);
|
|
p->flags = kDirtyFl;
|
|
p->focusIdx = cmInvalidIdx;
|
|
p->fontId = kHelveticaFfGrId;
|
|
p->fontStyle = kNormalFsGrFl;
|
|
p->fontSize = 16;
|
|
|
|
// setup the view defaults
|
|
for(i=0; i<p->vn; ++i)
|
|
{
|
|
cmGrPgVw_t* vp = p->viewV + i;
|
|
|
|
vp->p = p;
|
|
vp->ri = i % p->rn;
|
|
vp->ci = i / p->rn;
|
|
vp->fontId = kHelveticaFfGrId;
|
|
vp->fontStyle = kNormalFsGrFl;
|
|
vp->fontSize = 14;
|
|
|
|
unsigned j;
|
|
for(j=0; j<kAxisGrCnt; ++j)
|
|
{
|
|
cmGrPgAxis_t* ap = vp->axis + j;
|
|
|
|
ap->vp = p->viewV + i;
|
|
ap->maxHashCnt = kMaxHashCnt;
|
|
ap->hashLength = kHashLength;
|
|
ap->flags = kHashMarkGrFl | kHashLabelGrFl;
|
|
ap->titleFontId = kHelveticaFfGrId;
|
|
ap->titleFontStyle = kNormalFsGrFl;
|
|
ap->titleFontSize = 10;
|
|
ap->labelFontId = kHelveticaFfGrId;
|
|
ap->labelFontStyle = kNormalFsGrFl;
|
|
ap->labelFontSize = 10;
|
|
}
|
|
|
|
}
|
|
|
|
// setup the default row proportions
|
|
for(i=0; i<p->rn; ++i)
|
|
p->rpropV[i] = 1.0/p->rn;
|
|
|
|
// setup the default col proportions
|
|
for(i=0; i<p->cn; ++i)
|
|
p->cpropV[i] = 1.0/p->cn;
|
|
|
|
// _cmGrPgLayoutVw() needs to be called.
|
|
p->flags = cmSetFlag(p->flags,kDirtyFl);
|
|
|
|
// layout the page
|
|
// kpl _cmGrPageLayout(p, dcH );
|
|
|
|
// notify the application that views have been created
|
|
for(i=0; i<rn*cn; ++i)
|
|
{
|
|
cmGrPgVw_t* vp = p->viewV + i;
|
|
|
|
// Set the 'id' assoc'd with this views cmGrH_t handle to 'i'.
|
|
// This will allow the grH to return the index of the plot.
|
|
if((rc = cmGrCreate(&p->ctx,&vp->grH,i,kExpandViewGrFl,_cmGrPageCallback,p,NULL)) != kOkGrRC )
|
|
break;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
cmGrRC_t cmGrPageResize( cmGrPgH_t h, const cmGrPExt_t* r, cmGrDcH_t dcH )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
p->pext = *r;
|
|
|
|
// _cmGrPgLayoutVw() needs to be called.
|
|
p->flags = cmSetFlag(p->flags,kDirtyFl);
|
|
|
|
// layout the page
|
|
// kpl _cmGrPageLayout(p, dcH );
|
|
|
|
return kOkGrRC;
|
|
}
|
|
|
|
void cmGrPageRect( cmGrPgH_t h, cmGrPExt_t* r )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
*r = p->pext;
|
|
}
|
|
|
|
unsigned cmGrPageViewCount( cmGrPgH_t h )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
return p->vn;
|
|
}
|
|
|
|
void _cmGrViewSetTitle(cmGrPgVw_t* vp, const cmChar_t* title )
|
|
{
|
|
if( title == vp->title || (title != NULL && vp->title!=NULL && strcmp(title,vp->title)==0 ))
|
|
return;
|
|
|
|
cmMemPtrFree(&vp->title);
|
|
if( title != NULL )
|
|
{
|
|
assert( vp->title == NULL );
|
|
vp->title = cmMemAllocStr(title);
|
|
}
|
|
|
|
vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
|
|
}
|
|
|
|
void _cmGrAxisSetTitle( cmGrPgAxis_t* ap, const cmChar_t* title )
|
|
{
|
|
if( title == ap->title || (title != NULL && ap->title!=NULL && strcmp(title,ap->title)==0 ))
|
|
return;
|
|
|
|
cmMemPtrFree(&ap->title);
|
|
if( title != NULL )
|
|
{
|
|
assert( ap->title == NULL );
|
|
ap->title = cmMemAllocStr(title);
|
|
}
|
|
|
|
ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
|
|
|
|
}
|
|
|
|
|
|
void _cmGrPgDrawHashMarks( cmGrPg_t* p, cmGrPgVw_t* vp, cmGrDcH_t dcH, unsigned lineColor )
|
|
{
|
|
int i,j;
|
|
cmGrDcSetColor(dcH, lineColor );
|
|
cmGrDcSetPenWidth( dcH, 1 );
|
|
|
|
for(j=0; j<kAxisGrCnt; ++j )
|
|
{
|
|
cmGrPgAxis_t* ap = vp->axis + j;
|
|
|
|
if( cmIsFlag(ap->flags, kHashMarkGrFl) )
|
|
for(i=0; i<ap->hashCnt; ++i)
|
|
{
|
|
cmGrPgHash_t* hp = ap->hash + i;
|
|
cmGrDcDrawLine(dcH, hp->xy0.x, hp->xy0.y, hp->xy1.x, hp->xy1.y);
|
|
}
|
|
}
|
|
|
|
// draw border 1 pixel outside of iext
|
|
cmGrDcDrawRect(dcH,vp->iext.loc.x-1,vp->iext.loc.y-1,vp->iext.sz.w+2,vp->iext.sz.h+2);
|
|
|
|
//printf("pgm: x:%i y:%i\n", vp->iext.loc.x, vp->iext.loc.y);
|
|
|
|
// draw the view border
|
|
//cmGrDcDrawRect(dcH,vp->pext.loc.x,vp->pext.loc.y,vp->pext.sz.w,vp->pext.sz.h);
|
|
|
|
}
|
|
|
|
void _cmGrPgHashValueToLabel( cmGrPgAxis_t* ap, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value )
|
|
{
|
|
if( ap->func == NULL )
|
|
snprintf(label,labelCharCnt,"%f",value);
|
|
else
|
|
{
|
|
ap->func->func( ap->func->arg, label, labelCharCnt, value );
|
|
}
|
|
}
|
|
|
|
void _cmGrPgDrawHashLabels( cmGrPg_t* p, cmGrPgVw_t* vp, cmGrDcH_t dcH, unsigned textColor )
|
|
{
|
|
int i;
|
|
cmGrVExt_t vext;
|
|
char s[ kHashCharCnt+1 ];
|
|
s[kHashCharCnt]=0;
|
|
|
|
cmGrViewExtents( vp->grH, &vext );
|
|
//cmGrVExtPrint("hash:",&vext);
|
|
|
|
cmGrDcSetColor(dcH, textColor );
|
|
|
|
cmGrPgAxis_t* ap = vp->axis + kLeftGrIdx;
|
|
cmGrDcSetFont( dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle );
|
|
|
|
// draw the left axis hash labels
|
|
if( cmIsFlag(ap->flags, kHashLabelGrFl ) )
|
|
{
|
|
for(i=0; i<vp->axis[ kLeftGrIdx ].hashCnt; ++i)
|
|
{
|
|
cmGrPSz_t sz;
|
|
double v = vext.loc.y + vext.sz.h - (i * vext.sz.h / (ap->hashCnt-1) );
|
|
_cmGrPgHashValueToLabel(ap,s,kHashCharCnt,v);
|
|
cmGrDcMeasure(dcH,s,&sz);
|
|
|
|
int y = ap->hash[i].xy0.y;
|
|
cmGrDcDrawText(dcH, s, ap->labelPt.x, y + (sz.h/2) );
|
|
}
|
|
}
|
|
|
|
ap = vp->axis + kRightGrIdx;
|
|
cmGrDcSetFont( dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle );
|
|
|
|
// draw the right axis hash labels
|
|
if( cmIsFlag(ap->flags, kHashLabelGrFl ))
|
|
{
|
|
for(i=0; i<ap->hashCnt; ++i)
|
|
{
|
|
cmGrPSz_t sz;
|
|
double v = vext.loc.y + vext.sz.h - (i * vext.sz.h / (ap->hashCnt-1) );
|
|
_cmGrPgHashValueToLabel(ap,s,kHashCharCnt,v);
|
|
cmGrDcMeasure(dcH,s,&sz);
|
|
|
|
int y = ap->hash[i].xy0.y;
|
|
cmGrDcDrawText(dcH, s, ap->labelPt.x, y + (sz.h/2));
|
|
}
|
|
}
|
|
|
|
|
|
// draw the top axis hash labels
|
|
ap = vp->axis + kTopGrIdx;
|
|
cmGrDcSetFont( dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle );
|
|
|
|
if( cmIsFlag(ap->flags, kHashLabelGrFl ) )
|
|
{
|
|
for(i=0; i<ap->hashCnt; ++i)
|
|
{
|
|
cmGrPSz_t sz;
|
|
double v = vext.loc.x + (i * vext.sz.w / (ap->hashCnt-1));
|
|
_cmGrPgHashValueToLabel(ap,s,kHashCharCnt,v);
|
|
cmGrDcMeasure(dcH,s,&sz);
|
|
|
|
cmGrDcDrawText(dcH, s, ap->hash[i].xy0.x - sz.w/2, ap->labelPt.y );
|
|
}
|
|
}
|
|
|
|
// draw the bottom axis hash labels
|
|
ap = vp->axis + kBottomGrIdx;
|
|
cmGrDcSetFont( dcH, ap->labelFontId, ap->labelFontSize, ap->labelFontStyle );
|
|
|
|
if( cmIsFlag(ap->flags, kHashLabelGrFl ) )
|
|
{
|
|
for(i=0; i<ap->hashCnt; ++i)
|
|
{
|
|
cmGrPSz_t sz;
|
|
double v = vext.loc.x + (i * vext.sz.w / (ap->hashCnt-1));
|
|
_cmGrPgHashValueToLabel(ap,s,kHashCharCnt,v);
|
|
cmGrDcMeasure(dcH,s,&sz);
|
|
|
|
cmGrDcDrawText(dcH, s, ap->hash[i].xy0.x - sz.w/2, ap->labelPt.y );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void _cmGrPgDrawAxisTitles( cmGrPg_t* p, cmGrPgVw_t* vp, cmGrDcH_t dcH )
|
|
{
|
|
unsigned i;
|
|
for(i=0; i<kAxisGrCnt; ++i)
|
|
{
|
|
cmGrPgAxis_t* ap = vp->axis + i;
|
|
|
|
if( ap->title != NULL )
|
|
{
|
|
cmGrPSz_t sz;
|
|
cmGrDcFontSetAndMeasure( dcH, ap->titleFontId, ap->titleFontSize, ap->titleFontStyle, ap->title, &sz );
|
|
|
|
if( i==kBottomGrIdx || i==kTopGrIdx )
|
|
{
|
|
int x = vp->iext.loc.x + (vp->iext.sz.w/2) - (sz.w/2);
|
|
cmGrDcDrawText( dcH, ap->title, x, ap->titlePt.y );
|
|
}
|
|
|
|
if( i==kLeftGrIdx || i==kRightGrIdx )
|
|
{
|
|
int y = vp->iext.loc.y + (vp->iext.sz.h/2) + (sz.w/2);
|
|
cmGrDcDrawTextRot( dcH, ap->title, ap->titlePt.x, y, 90 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmGrPageViewFocus( cmGrPgH_t h, unsigned vwIdx, bool enableFl )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
assert( vwIdx < p->vn );
|
|
if( enableFl )
|
|
p->focusIdx = vwIdx;
|
|
else
|
|
{
|
|
if( p->focusIdx == vwIdx )
|
|
p->focusIdx = cmInvalidId;
|
|
}
|
|
}
|
|
|
|
cmGrVwH_t cmGrPageFocusedView( cmGrPgH_t h )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrVwH_t vwH = cmGrVwNullHandle;
|
|
|
|
if( p->focusIdx != cmInvalidIdx )
|
|
vwH.h = p->viewV + p->focusIdx;
|
|
|
|
return vwH;
|
|
}
|
|
|
|
|
|
bool cmGrPageLayout( cmGrPgH_t h, cmGrDcH_t dcH )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrDcPushCtx(dcH);
|
|
bool fl = _cmGrPageLayout(p,dcH);
|
|
cmGrDcPopCtx(dcH);
|
|
return fl;
|
|
}
|
|
|
|
void cmGrPageDraw( cmGrPgH_t h, cmGrDcH_t dcH )
|
|
{
|
|
unsigned i;
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
|
|
cmGrDcPushCtx(dcH);
|
|
|
|
_cmGrPageLayout(p,dcH);
|
|
|
|
cmGrDcSetColor(dcH,kBlackGrId);
|
|
|
|
// for each view
|
|
for(i=0; i<p->vn; ++i)
|
|
{
|
|
cmGrPgVw_t* vp = p->viewV + i;
|
|
|
|
unsigned lineColor = p->focusIdx==i ? kRedGrId : kBlackGrId;
|
|
_cmGrPgDrawHashMarks( p, vp, dcH, lineColor );
|
|
_cmGrPgDrawHashLabels( p, vp, dcH, kBlackGrId);
|
|
_cmGrPgDrawAxisTitles( p, vp, dcH );
|
|
|
|
if( vp->title != NULL )
|
|
{
|
|
cmGrPSz_t sz;
|
|
cmGrDcFontSetAndMeasure(dcH,vp->fontId,vp->fontSize,vp->fontStyle,vp->title,&sz);
|
|
cmGrDcDrawText(dcH,vp->title, vp->titlePt.x - sz.w/2, vp->titlePt.y );
|
|
}
|
|
|
|
}
|
|
|
|
cmGrDcPopCtx(dcH);
|
|
|
|
|
|
}
|
|
|
|
cmGrPgLabelFunc_t* _cmGrPageLabelIndexToRecd( cmGrPg_t* p, unsigned idx )
|
|
{
|
|
cmGrPgLabelFunc_t* lfp = p->funcs;
|
|
unsigned i;
|
|
for(i=0; i<idx && lfp!=NULL; ++i)
|
|
lfp=lfp->link;
|
|
|
|
return lfp;
|
|
}
|
|
|
|
cmGrPgLabelFunc_t* _cmGrPageLabelIdToRecd( cmGrPg_t* p, unsigned id )
|
|
{
|
|
cmGrPgLabelFunc_t* lfp = p->funcs;
|
|
for(; lfp!=NULL; lfp=lfp->link)
|
|
if( lfp->id == id )
|
|
return lfp;
|
|
|
|
return lfp;
|
|
}
|
|
|
|
unsigned cmGrPageLabelFuncRegister( cmGrPgH_t h, cmGrLabelFunc_t func, void* arg, const cmChar_t* label )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrPgLabelFunc_t* lfp = cmMemAllocZ(cmGrPgLabelFunc_t,1);
|
|
|
|
lfp->id = p->labelFuncId++;
|
|
lfp->func = func;
|
|
lfp->arg = arg;
|
|
lfp->label = cmMemAllocStr(label);
|
|
lfp->link = p->funcs;
|
|
p->funcs = lfp;
|
|
return lfp->id;
|
|
}
|
|
|
|
unsigned cmGrPageLabelFuncCount( cmGrPgH_t h )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrPgLabelFunc_t* lfp = p->funcs;
|
|
unsigned n = 0;
|
|
|
|
for(; lfp != NULL; lfp=lfp->link )
|
|
++n;
|
|
return n;
|
|
}
|
|
|
|
unsigned cmGrPageLabelFuncIndexToId( cmGrPgH_t h, unsigned index )
|
|
{
|
|
cmGrPgLabelFunc_t* lfp;
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
|
|
if((lfp = _cmGrPageLabelIndexToRecd(p,index)) == NULL )
|
|
return cmInvalidId;
|
|
return lfp->id;
|
|
}
|
|
|
|
unsigned cmGrPageLabelFuncLabelToId( cmGrPgH_t h, const cmChar_t* label )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrPgLabelFunc_t* lfp = p->funcs;
|
|
unsigned i;
|
|
for(i=0; lfp!=NULL; lfp=lfp->link,++i)
|
|
if( lfp->label!=NULL && strcmp(label,lfp->label)==0 )
|
|
return lfp->id;
|
|
|
|
return cmInvalidId;
|
|
}
|
|
|
|
|
|
cmGrLabelFunc_t cmGrPageLabelFunc( cmGrPgH_t h, unsigned id )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrPgLabelFunc_t* lfp = _cmGrPageLabelIdToRecd(p,id);
|
|
assert( lfp != NULL );
|
|
return lfp->func;
|
|
}
|
|
|
|
const cmChar_t* cmGrPageLabelFuncLabel( cmGrPgH_t h, unsigned id )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrPgLabelFunc_t* lfp = _cmGrPageLabelIdToRecd(p,id);
|
|
assert( lfp != NULL );
|
|
return lfp->label;
|
|
}
|
|
|
|
void* cmGrPageLabelFuncArg( cmGrPgH_t h, unsigned id )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrPgLabelFunc_t* lfp = _cmGrPageLabelIdToRecd(p,id);
|
|
assert( lfp != NULL );
|
|
return lfp->arg;
|
|
}
|
|
|
|
|
|
cmGrVwH_t cmGrPageViewHandle( cmGrPgH_t h, unsigned vwIdx )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(h);
|
|
cmGrVwH_t vwH;
|
|
assert( vwIdx < p->vn );
|
|
vwH.h = p->viewV + vwIdx;
|
|
return vwH;
|
|
}
|
|
|
|
cmGrVwH_t cmGrPageGrHandleToView( cmGrPgH_t pgH, cmGrH_t grH )
|
|
{
|
|
cmGrPg_t* p = _cmGrPgHandleToPtr(pgH);
|
|
cmGrVwH_t vwH = cmGrVwNullHandle;
|
|
int i;
|
|
for(i=0; i<p->vn; ++i)
|
|
if( cmHandlesAreEqual(grH,p->viewV[i].grH) )
|
|
{
|
|
vwH.h = p->viewV + i;
|
|
break;
|
|
}
|
|
return vwH;
|
|
}
|
|
|
|
|
|
bool cmGrViewIsValid( cmGrVwH_t h )
|
|
{ return h.h != NULL; }
|
|
|
|
cmGrRC_t cmGrViewInit( cmGrVwH_t h, cmGrH_t grH, const cmChar_t* vwTitle, const cmChar_t* xLabel, const cmChar_t* yLabel )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
|
|
vp->grH = grH;
|
|
|
|
_cmGrViewSetTitle( vp, vwTitle );
|
|
_cmGrAxisSetTitle( vp->axis + kBottomGrIdx, xLabel );
|
|
_cmGrAxisSetTitle( vp->axis + kLeftGrIdx, yLabel );
|
|
|
|
vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
|
|
|
|
return kOkGrRC;
|
|
}
|
|
|
|
cmGrRC_t cmGrViewClear( cmGrVwH_t h )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
cmGrH_t grH = cmGrViewGrHandle(h);
|
|
assert( cmGrIsValid(grH) );
|
|
cmGrRC_t rc = cmGrClear( grH );
|
|
|
|
vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
|
|
|
|
return rc;
|
|
}
|
|
|
|
cmGrRC_t cmGrViewPExt( cmGrVwH_t h, cmGrPExt_t* pext )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
*pext = vp->iext;
|
|
return kOkGrRC;
|
|
}
|
|
|
|
bool cmGrViewHasFocus( cmGrVwH_t h )
|
|
{
|
|
if( cmGrViewIsValid(h) == false )
|
|
return false;
|
|
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
|
|
if( vp->p->focusIdx == cmInvalidIdx )
|
|
return false;
|
|
|
|
return cmGrId(vp->grH) == vp->p->focusIdx;
|
|
}
|
|
|
|
cmGrH_t cmGrViewGrHandle( cmGrVwH_t h )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
return vp->grH;
|
|
}
|
|
|
|
void cmGrViewSetCfg( cmGrVwH_t h, unsigned cfgFlags )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
cmGrSetCfgFlags( vp->grH, cfgFlags );
|
|
vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
|
|
}
|
|
|
|
unsigned cmGrViewCfg( cmGrVwH_t h )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
return cmGrCfgFlags( vp->grH );
|
|
}
|
|
void cmGrViewSetTitle( cmGrVwH_t h, const cmChar_t* title )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
_cmGrViewSetTitle( vp, title );
|
|
}
|
|
const cmChar_t* cmGrViewTitle( cmGrVwH_t h )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
return vp->title;
|
|
}
|
|
void cmGrViewSetFontFamily( cmGrVwH_t h, unsigned id )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
if( vp->fontId != id )
|
|
{
|
|
vp->fontId = id;
|
|
vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
|
|
}
|
|
|
|
}
|
|
unsigned cmGrViewFontFamily( cmGrVwH_t h )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
return vp->fontId;
|
|
}
|
|
void cmGrViewSetFontStyle( cmGrVwH_t h, unsigned flags )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
if( vp->fontStyle != flags )
|
|
{
|
|
vp->fontStyle = flags;
|
|
vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
|
|
}
|
|
}
|
|
unsigned cmGrViewFontStyle( cmGrVwH_t h )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
return vp->fontStyle;
|
|
}
|
|
void cmGrViewSetFontSize( cmGrVwH_t h, unsigned size )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
if( vp->fontSize != size )
|
|
{
|
|
vp->fontSize = size;
|
|
vp->p->flags = cmSetFlag(vp->p->flags, kDirtyFl);
|
|
}
|
|
}
|
|
unsigned cmGrViewFontSize( cmGrVwH_t h )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
return vp->fontSize;
|
|
}
|
|
|
|
void cmGrViewSetLabelFunc( cmGrVwH_t h, cmGrAxisIdx_t axisId, unsigned pgLabelFuncId )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
cmGrPgLabelFunc_t** lfpp = NULL;
|
|
|
|
switch( axisId )
|
|
{
|
|
case kLeftGrIdx:
|
|
case kRightGrIdx:
|
|
lfpp = &vp->yfunc;
|
|
break;
|
|
|
|
case kTopGrIdx:
|
|
case kBottomGrIdx:
|
|
lfpp = &vp->xfunc;
|
|
break;
|
|
|
|
default:
|
|
{ assert(0); }
|
|
}
|
|
|
|
assert( lfpp != NULL );
|
|
|
|
*lfpp = _cmGrPageLabelIdToRecd(vp->p, pgLabelFuncId );
|
|
}
|
|
|
|
const cmChar_t* cmGrViewValue( cmGrVwH_t h, cmGrViewValueId_t id, cmChar_t* buf, unsigned bufCharCnt )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
cmGrPgLabelFunc_t* lfp = NULL;
|
|
cmGrH_t grH = vp->grH;
|
|
cmGrV_t v;
|
|
cmGrVPt_t pt0,pt1;
|
|
|
|
switch( id )
|
|
{
|
|
case kLocalX_VwId:
|
|
v = cmGrLocalPt(grH)->x;
|
|
lfp = vp->xfunc;
|
|
break;
|
|
|
|
case kLocalY_VwId:
|
|
v = cmGrLocalPt(grH)->y;
|
|
lfp = vp->yfunc;
|
|
break;
|
|
|
|
case kGlobalX_VwId:
|
|
v = cmGrGlobalPt(grH)->x;
|
|
lfp = vp->xfunc;
|
|
break;
|
|
|
|
case kGlobalY_VwId:
|
|
v = cmGrGlobalPt(grH)->y;
|
|
lfp = vp->yfunc;
|
|
break;
|
|
|
|
case kSelX0_VwId:
|
|
cmGrSelectPoints(grH,&pt0,NULL);
|
|
v = pt0.x;
|
|
lfp = vp->xfunc;
|
|
break;
|
|
|
|
case kSelY0_VwId:
|
|
cmGrSelectPoints(grH,&pt0,NULL);
|
|
v = pt0.y;
|
|
lfp = vp->yfunc;
|
|
break;
|
|
|
|
case kSelX1_VwId:
|
|
cmGrSelectPoints(grH,NULL,&pt1);
|
|
v = pt1.x;
|
|
lfp = vp->xfunc;
|
|
break;
|
|
|
|
case kSelY1_VwId:
|
|
cmGrSelectPoints(grH,NULL,&pt1);
|
|
v = pt1.y;
|
|
lfp = vp->yfunc;
|
|
break;
|
|
|
|
case kSelW_VwId:
|
|
cmGrSelectPoints(grH,&pt0,&pt1);
|
|
v = fabs(pt1.x - pt0.x);
|
|
lfp = vp->xfunc;
|
|
break;
|
|
|
|
case kSelH_VwId:
|
|
cmGrSelectPoints(grH,&pt0,&pt1);
|
|
v = fabs(pt1.y - pt0.y);
|
|
lfp = vp->yfunc;
|
|
break;
|
|
|
|
default:
|
|
{ assert(0); }
|
|
}
|
|
|
|
if( bufCharCnt > 0 )
|
|
{
|
|
buf[0]=0;
|
|
if( lfp != NULL )
|
|
lfp->func( lfp->arg, buf, bufCharCnt, v );
|
|
else
|
|
snprintf(buf,bufCharCnt,"%f",v);
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
cmGrAxH_t cmGrViewAxisHandle( cmGrVwH_t h, cmGrAxisIdx_t axisIdx )
|
|
{
|
|
cmGrPgVw_t* vp = _cmGrPgVwHandleToPtr(h);
|
|
cmGrAxH_t axH;
|
|
assert( axisIdx < kAxisGrCnt );
|
|
axH.h = vp->axis + axisIdx;
|
|
return axH;
|
|
}
|
|
|
|
bool cmGrAxisIsValid( cmGrAxH_t h )
|
|
{ return h.h != NULL; }
|
|
|
|
void cmGrAxisSetCfg( cmGrAxH_t h, unsigned flags )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
if( ap->flags != flags )
|
|
{
|
|
ap->flags = flags;
|
|
ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
|
|
}
|
|
}
|
|
|
|
unsigned cmGrAxisCfg( cmGrAxH_t h )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
return ap->flags;
|
|
}
|
|
|
|
void cmGrAxisSetTitle( cmGrAxH_t h, const cmChar_t* title )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
_cmGrAxisSetTitle(ap,title);
|
|
}
|
|
|
|
const cmChar_t* cmGrAxisTitle( cmGrAxH_t h )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
return ap->title;
|
|
}
|
|
|
|
void cmGrAxisSetTitleFontFamily( cmGrAxH_t h, unsigned id )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
if( ap->titleFontId != id )
|
|
{
|
|
ap->titleFontId = id;
|
|
ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
|
|
}
|
|
}
|
|
|
|
unsigned cmGrAxisTitleFontFamily( cmGrAxH_t h )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
return ap->titleFontId;
|
|
}
|
|
|
|
void cmGrAxisTitleSetFontStyle( cmGrAxH_t h, unsigned flags )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
if( ap->titleFontStyle != flags )
|
|
{
|
|
ap->titleFontStyle = flags;
|
|
ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
|
|
}
|
|
}
|
|
|
|
unsigned cmGrAxisTitleFontStyle( cmGrAxH_t h )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
return ap->titleFontStyle;
|
|
}
|
|
|
|
void cmGrAxisTitleSetFontSize( cmGrAxH_t h, unsigned size )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
if( ap->titleFontSize != size )
|
|
{
|
|
ap->titleFontSize = size;
|
|
ap->vp->p->flags = cmSetFlag(ap->vp->p->flags, kDirtyFl);
|
|
}
|
|
}
|
|
|
|
unsigned cmGrAxisTitleFontSize( cmGrAxH_t h )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
return ap->titleFontSize;
|
|
}
|
|
|
|
void cmGrAxisSetLabelFunc( cmGrAxH_t h, unsigned id )
|
|
{
|
|
cmGrPgAxis_t* ap = _cmGrPgAxisHandleToPtr(h);
|
|
|
|
ap->func = _cmGrPageLabelIdToRecd( ap->vp->p, id );
|
|
}
|