Imported latest changes from AqFinance.

This commit is contained in:
Martin Preuss
2022-03-24 21:58:17 +01:00
parent f72611177c
commit 0093338296
13 changed files with 886 additions and 920 deletions

View File

@@ -86,27 +86,23 @@
<headers dist="true" install="$(pkgincludedir)">
graph.h
draw.h
layout.h
setup.h
</headers>
<headers dist="true">
graph_p.h
g_draw_data.h
g_draw_xticks.h
g_draw_yticks.h
g_config.h
g_layout.h
</headers>
<sources>
$(local/typefiles)
graph.c
g_draw_data.c
g_draw_xticks.c
g_draw_yticks.c
g_config.c
g_layout.c
draw.c
layout.c
setup.c
</sources>

View File

@@ -0,0 +1,557 @@
/****************************************************************************
* This file is part of the project AqFinance.
* AqFinance (c) by 2011 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/draw.h"
#include "aqdiagram/graph/dataset_fns.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
#define MAX_TICK_LEVELS 5
#define MIN_DIST_FOR_TICKS 5
#define MIN_DIST_FOR_GRIDS 5
#define TICKDRAWFLAGS_MARKS 0x01
#define TICKDRAWFLAGS_GRIDS 0x02
#define TICKDRAWFLAGS_LABELS 0x04
static void _drawXAxis(AQDG_GRAPH *gr);
static void _drawYAxis(AQDG_GRAPH *gr);
static void _drawTitleIfSet(const AQDG_GRAPH *gr);
static void _drawSubTitleIfSet(const AQDG_GRAPH *gr);
static void _drawXTicks(AQDG_GRAPH *gr);
static void _drawYTicks(AQDG_GRAPH *gr);
static int _isPositionFree(int m1, int m2, const uint8_t *pMask, int maxLen);
static void _reservePosition(int m1, int m2, uint8_t *pMask, int maxLen);
static void _probablyDrawGridLineForXTick(const AQDG_GRAPH *gr, int x, uint8_t tickDrawFlags);
static void _probablyDrawMarkForXTick(const AQDG_GRAPH *gr, int x, int y, uint8_t tickDrawFlags, int level);
static int _getMaxTickLabelWidthForLevel(const AQDG_GRAPH *gr, const AQDG_GRAPH_TICK_LIST *tl, int level);
static int _calcDistBetweenFirstTwoTicksOfLevel(const AQDG_GRAPH *gr, const AQDG_GRAPH_TICK_LIST *tl, int level);
void AQDG_Graph_DrawFramework(AQDG_GRAPH *gr)
{
/* draw background */
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, gr->penBackground,
0, 0, gr->width, gr->height);
/* draw graph area */
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, gr->penGraphBackground,
gr->graphAreaPosX, gr->graphAreaPosY,
gr->graphAreaWidth, gr->graphAreaHeight);
_drawXAxis(gr);
_drawYAxis(gr);
_drawTitleIfSet(gr);
_drawSubTitleIfSet(gr);
}
void _drawXAxis(AQDG_GRAPH *gr)
{
const char *s;
/* ticks, axis, label */
_drawXTicks(gr);
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis,
gr->graphAreaPosX, gr->xAxisPosY,
gr->graphAreaPosX+gr->graphAreaWidth, gr->xAxisPosY);
s=AQDG_Graph_DataSet_GetLabelX(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontAxisLabel, AQDG_Direction_Horizontal,
gr->xAxisLabelPosX, gr->xAxisLabelPosY, s);
}
void _drawYAxis(AQDG_GRAPH *gr)
{
const char *s;
/* ticks, axis, label */
_drawYTicks(gr);
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis,
gr->yAxisPosX, gr->graphAreaPosY,
gr->yAxisPosX, gr->graphAreaPosY+gr->graphAreaHeight);
s=AQDG_Graph_DataSet_GetLabelY(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontAxisLabel, AQDG_Direction_Horizontal,
gr->yAxisLabelPosX, gr->yAxisLabelPosY, s);
}
void _drawTitleIfSet(const AQDG_GRAPH *gr)
{
const char *s;
s=AQDG_Graph_DataSet_GetTitle(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penTitle, gr->fontTitle, AQDG_Direction_Horizontal,
gr->titlePosX, gr->titlePosY, s);
}
void _drawSubTitleIfSet(const AQDG_GRAPH *gr)
{
const char *s;
s=AQDG_Graph_DataSet_GetSubTitle(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penSubTitle, gr->fontSubTitle, AQDG_Direction_Horizontal,
gr->subTitlePosX, gr->subTitlePosY, s);
}
void _drawXTicks(AQDG_GRAPH *gr)
{
AQDG_GRAPH_TICK_LIST *tl;
tl=AQDG_Graph_DataSet_GetXTickList(gr->dataSet);
if (tl) {
AQDG_GRAPH_TICK *t;
uint8_t *pMask;
int level;
/* reset */
pMask=(uint8_t *) malloc(gr->graphAreaWidth);
assert(pMask);
memset(pMask, 0, gr->graphAreaWidth);
/* handle each level */
for (level=1; level<MAX_TICK_LEVELS+1; level++) {
uint8_t tickDrawFlags=0;
int maxWidth=0;
int dist;
int every=1;
maxWidth=_getMaxTickLabelWidthForLevel(gr, tl, level);
/* check medium width for the current level */
dist=_calcDistBetweenFirstTwoTicksOfLevel(gr, tl, level);
if (dist==0)
dist=gr->graphAreaWidth;
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
#if 0
if (dist>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
}
else if ((dist*2)>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
every=2;
}
else if ((dist*4)>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
every=4;
}
#else
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
#endif
/* now draw according to flags */
if (tickDrawFlags) {
double minVal;
double maxVal;
int tickIntervalCnt=every;
minVal=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxVal=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double v;
tickIntervalCnt--;
v=AQDG_Graph_Tick_GetValue(t);
if (v>=minVal && v<=maxVal) {
int x, y;
x=gr->graphOriginX + (v * gr->graphFactorX);
y=gr->xAxisPosY;
_probablyDrawGridLineForXTick(gr, x, tickDrawFlags);
_probablyDrawMarkForXTick(gr, x, y, tickDrawFlags, level);
if (tickDrawFlags & TICKDRAWFLAGS_LABELS) {
const char *s;
/* draw label */
if (tickIntervalCnt<1) {
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
i=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->penAxisLabel, s);
if (i>=0) {
if ((x+(i/2) < (gr->graphAreaPosX+gr->graphAreaWidth)) &&
(x-(i/2) > gr->graphAreaPosX)) {
int m1, m2;
m1=x-(i/2)-gr->graphAreaPosX;
m2=x+(i/2)-gr->graphAreaPosX;
if (_isPositionFree(m1, m2, pMask, gr->graphAreaWidth)) {
_reservePosition(m1, m2, pMask, gr->graphAreaWidth);
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontTickLabel, AQDG_Direction_Horizontal,
x-(i/2), gr->xTickLabelPosY, s);
}
}
}
}
tickIntervalCnt=every;
}
} /* if labels to be drawn */
} /* if value within limits */
}
t=AQDG_Graph_Tick_List_Next(t);
} /* while t */
} /* if tickDrawFlags */
} /* for level */
free(pMask);
} /* if tl */
}
int _isPositionFree(int m1, int m2, const uint8_t *pMask, int maxLen)
{
int j;
for (j=m1; j<m2; j++) {
if (j<0 || j>=maxLen)
return 0;
if (pMask[j]!=0)
return 0;
}
return 1;
}
void _reservePosition(int m1, int m2, uint8_t *pMask, int maxLen)
{
int j;
m1-=SMALL_BORDER/2;
m2+=SMALL_BORDER/2;
if (m1<0)
m1=0;
if (m2>=maxLen)
m2=maxLen-1;
for (j=m1; j<m2; j++)
pMask[j]=1;
}
void _probablyDrawGridLineForXTick(const AQDG_GRAPH *gr, int x, uint8_t tickDrawFlags)
{
if (tickDrawFlags & TICKDRAWFLAGS_GRIDS) {
if (gr->flags & AQDG_GRAPH_FLAGS_WITH_GRID)
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penGrid, x, gr->graphAreaPosY, x, gr->graphAreaPosY+gr->graphAreaHeight);
}
}
void _probablyDrawMarkForXTick(const AQDG_GRAPH *gr, int x, int y, uint8_t tickDrawFlags, int level)
{
if (tickDrawFlags & TICKDRAWFLAGS_MARKS) {
int w;
switch (level) {
case 1:
w=9;
break;
case 2:
w=5;
break;
default:
case 3:
w=1;
break;
}
/* draw tick mark */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis, x, y-w, x, y+w);
}
}
int _getMaxTickLabelWidthForLevel(const AQDG_GRAPH *gr, const AQDG_GRAPH_TICK_LIST *tl, int level)
{
AQDG_GRAPH_TICK *t;
int maxWidth=0;
/* determine width of labels for this level */
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
const char *s;
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
//DBG_ERROR(0, "X-Level %d: [%s] = %f", level, s, AQDG_Graph_Tick_GetValue(t));
i=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->fontTickLabel, s);
if (i<0) {
DBG_ERROR(0, "Invalid text width (%d)", i);
}
else {
if (i>maxWidth)
maxWidth=i;
}
}
else {
DBG_ERROR(0, "X-Level %d: No tick label", level);
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
return maxWidth;
}
int _calcDistBetweenFirstTwoTicksOfLevel(const AQDG_GRAPH *gr, const AQDG_GRAPH_TICK_LIST *tl, int level)
{
const AQDG_GRAPH_TICK *t;
t=AQDG_Graph_Tick_List_First(tl);
while (t && AQDG_Graph_Tick_GetLevel(t)!=level)
t=AQDG_Graph_Tick_List_Next(t);
if (t) {
const AQDG_GRAPH_TICK *tick1=t;
t=AQDG_Graph_Tick_List_Next(t);
while (t && AQDG_Graph_Tick_GetLevel(t)!=level)
t=AQDG_Graph_Tick_List_Next(t);
if (t) {
const AQDG_GRAPH_TICK *tick2=t;
double v1, v2;
int dist;
v1=AQDG_Graph_Tick_GetValue(tick1);
v2=AQDG_Graph_Tick_GetValue(tick2);
dist=(int)((v2-v1)*gr->graphFactorX);
return dist;
}
}
return 0;
}
void _drawYTicks(AQDG_GRAPH *gr)
{
AQDG_GRAPH_TICK_LIST *tl;
tl=AQDG_Graph_DataSet_GetYTickList(gr->dataSet);
if (tl) {
AQDG_GRAPH_TICK *t;
uint8_t *pMask;
int level;
/* reset */
pMask=(uint8_t *) malloc(gr->graphAreaHeight);
assert(pMask);
memset(pMask, 0, gr->graphAreaHeight);
/* handle each level */
for (level=1; level<MAX_TICK_LEVELS+1; level++) {
uint8_t tickDrawFlags=0;
int maxHeight=0;
/* determine width of labels for this level */
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
const char *s;
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
//DBG_ERROR(0, "Y-Level %d: [%s] = %f", level, s, AQDG_Graph_Tick_GetValue(t));
i=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->fontTickLabel, s);
if (i<0) {
DBG_ERROR(0, "Invalid text width (%d)", i);
}
else {
if (i>maxHeight)
maxHeight=i;
}
}
else {
DBG_ERROR(0, "No tick label");
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
/* get 1st and 2nd entry for the current level and check width */
{
int first=1;
int hasSecond=0;
double lastValue;
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double v;
v=AQDG_Graph_Tick_GetValue(t);
if (first) {
lastValue=v;
first=0;
}
else {
int dist;
dist=(int)((v-lastValue)*gr->graphFactorY);
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxHeight+5)
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
DBG_ERROR(0, "Y-Level %d: dist=%d (flags=%02x)", level, dist, tickDrawFlags);
hasSecond=1;
break;
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
if (!first && !hasSecond) {
int dist;
dist=gr->graphAreaHeight;
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxHeight+2)
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
}
}
/* now draw according to flags */
if (tickDrawFlags) {
double minVal;
double maxVal;
minVal=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxVal=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
double v;
v=AQDG_Graph_Tick_GetValue(t);
if (AQDG_Graph_Tick_GetLevel(t)==level) {
if (v>=minVal && v<=maxVal) {
int x, y;
int w;
x=gr->yAxisPosX;
y=gr->graphOriginY - (v * gr->graphFactorY);
/* draw grid line */
if (tickDrawFlags & TICKDRAWFLAGS_GRIDS) {
if (gr->flags & AQDG_GRAPH_FLAGS_WITH_GRID)
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penGrid, gr->graphAreaPosX, y, gr->graphAreaPosX+gr->graphAreaWidth, y);
}
if (tickDrawFlags & TICKDRAWFLAGS_MARKS) {
switch (level) {
case 1:
w=9;
break;
case 2:
w=5;
break;
default:
case 3:
w=1;
break;
}
/* draw tick mark */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis, x-w, y, x+w, y);
}
if (tickDrawFlags & TICKDRAWFLAGS_LABELS) {
const char *s;
/* draw label */
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
i=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->penAxisLabel, s);
if (i>=0) {
if ((y+(i/2) < (gr->graphAreaPosY+gr->graphAreaHeight)) && (y-(i/2)>= gr->graphAreaPosY)) {
int m1, m2;
m1=y-(i/2)-gr->graphAreaPosY;
m2=y+(i/2)-gr->graphAreaPosY;
if (_isPositionFree(m1, m2, pMask, gr->graphAreaHeight)) {
_reservePosition(m1, m2, pMask, gr->graphAreaHeight);
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontTickLabel, AQDG_Direction_Horizontal,
gr->yTickLabelPosX, y-(i/2), s);
}
}
}
}
} /* if labels to be drawn */
} /* if value within limits */
}
t=AQDG_Graph_Tick_List_Next(t);
} /* while t */
} /* if tickDrawFlags */
} /* for level */
free(pMask);
} /* if tl */
}

View File

@@ -7,15 +7,15 @@
****************************************************************************/
#ifndef AQDG_G_DRAW_XTICKS_H
#define AQDG_G_DRAW_XTICKS_H
#ifndef AQDG_GRAPH_DRAW_H
#define AQDG_GRAPH_DRAW_H
#include <aqdiagram/graph/graph.h>
void AQDG_Graph_DrawXTicks(AQDG_GRAPH *gr);
void AQDG_Graph_DrawFramework(AQDG_GRAPH *gr);
#endif

View File

@@ -1,245 +0,0 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/g_draw_data.h"
#include "aqdiagram/graph/dataset_fns.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
void AQDG_Graph_DrawDataAsLine(AQDG_GRAPH *gr, int level, int penId)
{
AQDG_GRAPH_DATAPAIR_LIST *dpl;
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
int lastX;
int lastY;
int first=1;
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw a small star */
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y-3, x+3, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y+3, x+3, y-3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x, y-3, x, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y, x+3, y);
if (!first)
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, lastX, lastY, x, y);
else
first=0;
lastX=x;
lastY=y;
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
void AQDG_Graph_DrawDataAsBars(AQDG_GRAPH *gr, int level, int penId)
{
AQDG_GRAPH_DATAPAIR_LIST *dpl;
double dataWidth;
int barWidth;
int rv;
rv=AQDG_Graph_DataSet_GetMinValueDistX(gr->dataSet, level, &dataWidth);
if (rv<0) {
DBG_INFO(AQDG_LOGDOMAIN, "here (%d)", rv);
return;
}
else if (rv==1) {
/* use full width */
barWidth=(gr->graphAreaWidth)-10;
}
else {
barWidth=((int)(dataWidth*gr->graphFactorX))-10;
}
if (barWidth<1)
barWidth=1;
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
int leftX, bw;
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw the bar */
if ((x-(barWidth/2))<gr->graphAreaPosX) {
leftX=x;
bw=barWidth/2;
}
else {
leftX=x-(barWidth/2);
bw=barWidth;
}
if ((leftX+bw)>=(gr->graphAreaPosX+gr->graphAreaWidth)) {
bw=barWidth/2;
}
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, penId,
leftX, gr->xAxisPosY,
bw, y-gr->xAxisPosY);
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
void AQDG_Graph_DrawDataAsPoints(AQDG_GRAPH *gr, int level, int penId)
{
AQDG_GRAPH_DATAPAIR_LIST *dpl;
double dataWidth;
int barWidth;
int rv;
rv=AQDG_Graph_DataSet_GetMinValueDistX(gr->dataSet, level, &dataWidth);
if (rv<0) {
DBG_INFO(AQDG_LOGDOMAIN, "here (%d)", rv);
return;
}
else if (rv==1) {
/* use full width */
barWidth=(gr->graphAreaWidth)-10;
}
else {
barWidth=((int)(dataWidth*gr->graphFactorX))-10;
}
if (barWidth<1)
barWidth=1;
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw a small star */
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y-3, x+3, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y+3, x+3, y-3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x, y-3, x, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y, x+3, y);
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}

View File

@@ -1,24 +0,0 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2022 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_G_DRAW_DATA_H
#define AQDG_G_DRAW_DATA_H
#include <aqdiagram/graph/graph.h>
void AQDG_Graph_DrawDataAsLine(AQDG_GRAPH *gr, int level, int penId);
void AQDG_Graph_DrawDataAsBars(AQDG_GRAPH *gr, int level, int penId);
void AQDG_Graph_DrawDataAsPoints(AQDG_GRAPH *gr, int level, int penId);
#endif

View File

@@ -1,232 +0,0 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/g_draw_data.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
void AQDG_Graph_DrawXTicks(AQDG_GRAPH *gr)
{
AQDG_GRAPH_TICK_LIST *tl;
tl=AQDG_Graph_DataSet_GetXTickList(gr->dataSet);
if (tl) {
AQDG_GRAPH_TICK *t;
uint8_t *pMask;
int level;
/* reset */
pMask=(uint8_t *) malloc(gr->graphAreaWidth);
assert(pMask);
memset(pMask, 0, gr->graphAreaWidth);
/* handle each level */
for (level=1; level<MAX_TICK_LEVELS+1; level++) {
uint8_t tickDrawFlags=0;
int maxWidth=0;
int every=1;
/* determine width of labels for this level */
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
const char *s;
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
//DBG_ERROR(0, "X-Level %d: [%s] = %f", level, s, AQDG_Graph_Tick_GetValue(t));
i=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->fontTickLabel, s);
if (i<0) {
DBG_ERROR(0, "Invalid text width (%d)", i);
}
else {
if (i>maxWidth)
maxWidth=i;
}
}
else {
DBG_ERROR(0, "X-Level %d: No tick label", level);
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
/* check medium width for the current level */
{
int first=1;
int hasSecond=0;
double lastValue;
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double v;
v=AQDG_Graph_Tick_GetValue(t);
if (first) {
lastValue=v;
first=0;
}
else {
int dist;
dist=(int)((v-lastValue)*gr->graphFactorX);
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
}
else if ((dist*2)>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
every=2;
}
else if ((dist*4)>maxWidth+SMALL_BORDER) {
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
every=4;
}
DBG_ERROR(0, "X-Level %d: dist=%d (flags=%02x)", level, dist, tickDrawFlags);
hasSecond=1;
break;
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
if (!first && !hasSecond) {
int dist;
dist=gr->graphAreaWidth;
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxWidth+SMALL_BORDER)
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
DBG_ERROR(0, "X-Level %d: dist=%d (flags=%02x)", level, dist, tickDrawFlags);
}
}
/* now draw according to flags */
if (tickDrawFlags) {
double minVal;
double maxVal;
int tickIntervalCnt=every;
minVal=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxVal=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double v;
tickIntervalCnt--;
v=AQDG_Graph_Tick_GetValue(t);
if (v>=minVal && v<=maxVal) {
int x, y;
int w;
x=gr->graphOriginX + (v * gr->graphFactorX);
y=gr->xAxisPosY;
/* draw grid line */
if (tickDrawFlags & TICKDRAWFLAGS_GRIDS) {
if (gr->flags & AQDG_GRAPH_FLAGS_WITH_GRID)
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penGrid, x, gr->graphAreaPosY, x, gr->graphAreaPosY+gr->graphAreaHeight);
}
if (tickDrawFlags & TICKDRAWFLAGS_MARKS) {
switch (level) {
case 1:
w=9;
break;
case 2:
w=5;
break;
default:
case 3:
w=1;
break;
}
/* draw tick mark */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis, x, y-w, x, y+w);
}
if (tickDrawFlags & TICKDRAWFLAGS_LABELS) {
const char *s;
/* draw label */
if (tickIntervalCnt<1) {
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
i=AQDG_Draw_Context_GetTextWidth(gr->drawContext, gr->penAxisLabel, s);
if (i<0) {
}
else {
if ((x+(i/2) < (gr->graphAreaPosX+gr->graphAreaWidth)) &&
(x-(i/2) > gr->graphAreaPosX)) {
int j;
int doesFit=1;
int m1, m2;
m1=SMALL_BORDER+x-(i/2)-gr->graphAreaPosX;
m2=SMALL_BORDER+x+(i/2)-gr->graphAreaPosX;
for (j=m1; j<m2; j++) {
if (pMask[j]!=0) {
doesFit=0;
break;
}
}
if (doesFit) {
m1=x-(i/2)-gr->graphAreaPosX;
m2=x+(i/2)-gr->graphAreaPosX;
for (j=m1; j<m2; j++)
pMask[j]=1;
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontTickLabel, AQDG_Direction_Horizontal,
x-(i/2), gr->xTickLabelPosY, s);
}
}
}
}
tickIntervalCnt=every;
}
} /* if labels to be drawn */
} /* if value within limits */
}
t=AQDG_Graph_Tick_List_Next(t);
} /* while t */
} /* if tickDrawFlags */
} /* for level */
free(pMask);
} /* if tl */
}

View File

@@ -1,214 +0,0 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "aqdiagram/graph/g_draw_data.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
void AQDG_Graph_DrawYTicks(AQDG_GRAPH *gr)
{
AQDG_GRAPH_TICK_LIST *tl;
tl=AQDG_Graph_DataSet_GetYTickList(gr->dataSet);
if (tl) {
AQDG_GRAPH_TICK *t;
uint8_t *pMask;
int level;
/* reset */
pMask=(uint8_t *) malloc(gr->graphAreaHeight);
assert(pMask);
memset(pMask, 0, gr->graphAreaHeight);
/* handle each level */
for (level=1; level<MAX_TICK_LEVELS+1; level++) {
uint8_t tickDrawFlags=0;
int maxHeight=0;
/* determine width of labels for this level */
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
const char *s;
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
//DBG_ERROR(0, "Y-Level %d: [%s] = %f", level, s, AQDG_Graph_Tick_GetValue(t));
i=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->fontTickLabel, s);
if (i<0) {
DBG_ERROR(0, "Invalid text width (%d)", i);
}
else {
if (i>maxHeight)
maxHeight=i;
}
}
else {
DBG_ERROR(0, "No tick label");
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
/* get 1st and 2nd entry for the current level and check width */
{
int first=1;
int hasSecond=0;
double lastValue;
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
if (AQDG_Graph_Tick_GetLevel(t)==level) {
double v;
v=AQDG_Graph_Tick_GetValue(t);
if (first) {
lastValue=v;
first=0;
}
else {
int dist;
dist=(int)((v-lastValue)*gr->graphFactorY);
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxHeight+5)
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
DBG_ERROR(0, "Y-Level %d: dist=%d (flags=%02x)", level, dist, tickDrawFlags);
hasSecond=1;
break;
}
}
t=AQDG_Graph_Tick_List_Next(t);
}
if (!first && !hasSecond) {
int dist;
dist=gr->graphAreaHeight;
if (dist>MIN_DIST_FOR_TICKS)
tickDrawFlags|=TICKDRAWFLAGS_MARKS;
if (dist>MIN_DIST_FOR_GRIDS)
tickDrawFlags|=TICKDRAWFLAGS_GRIDS;
if (dist>maxHeight+2)
tickDrawFlags|=TICKDRAWFLAGS_LABELS;
}
}
/* now draw according to flags */
if (tickDrawFlags) {
double minVal;
double maxVal;
minVal=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxVal=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
t=AQDG_Graph_Tick_List_First(tl);
while (t) {
double v;
v=AQDG_Graph_Tick_GetValue(t);
if (AQDG_Graph_Tick_GetLevel(t)==level) {
if (v>=minVal && v<=maxVal) {
int x, y;
int w;
x=gr->yAxisPosX;
y=gr->graphOriginY - (v * gr->graphFactorY);
/* draw grid line */
if (tickDrawFlags & TICKDRAWFLAGS_GRIDS) {
if (gr->flags & AQDG_GRAPH_FLAGS_WITH_GRID)
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penGrid, gr->graphAreaPosX, y, gr->graphAreaPosX+gr->graphAreaWidth, y);
}
if (tickDrawFlags & TICKDRAWFLAGS_MARKS) {
switch (level) {
case 1:
w=9;
break;
case 2:
w=5;
break;
default:
case 3:
w=1;
break;
}
/* draw tick mark */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis, x-w, y, x+w, y);
}
if (tickDrawFlags & TICKDRAWFLAGS_LABELS) {
const char *s;
/* draw label */
s=AQDG_Graph_Tick_GetLabel(t);
if (s && *s) {
int i;
i=AQDG_Draw_Context_GetTextHeight(gr->drawContext, gr->penAxisLabel, s);
if (i<0) {
}
else {
if ((y+(i/2) < (gr->graphAreaPosY+gr->graphAreaHeight)) &&
(y-(i/2)>= gr->graphAreaPosY)) {
int j;
int doesFit=1;
int m1, m2;
m1=SMALL_BORDER+y-(i/2)-gr->graphAreaPosY;
m2=SMALL_BORDER+y+(i/2)-gr->graphAreaPosY;
for (j=m1; j<m2; j++) {
if (pMask[j]!=0) {
doesFit=0;
break;
}
}
if (doesFit) {
m1=y-(i/2)-gr->graphAreaPosY;
m2=y+(i/2)-gr->graphAreaPosY;
for (j=m1; j<m2; j++)
pMask[j]=1;
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontTickLabel, AQDG_Direction_Horizontal,
gr->yTickLabelPosX, y-(i/2), s);
}
}
}
}
} /* if labels to be drawn */
} /* if value within limits */
}
t=AQDG_Graph_Tick_List_Next(t);
} /* while t */
} /* if tickDrawFlags */
} /* for level */
free(pMask);
} /* if tl */
}

View File

@@ -1,22 +0,0 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2022 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
****************************************************************************/
#ifndef AQDG_G_DRAW_YTICKS_H
#define AQDG_G_DRAW_YTICKS_H
#include <aqdiagram/graph/graph.h>
void AQDG_Graph_DrawYTicks(AQDG_GRAPH *gr);
#endif

View File

@@ -11,11 +11,9 @@
#endif
#include "graph_p.h"
#include "aqdiagram/graph/g_draw_data.h"
#include "aqdiagram/graph/g_draw_xticks.h"
#include "aqdiagram/graph/g_draw_yticks.h"
#include "aqdiagram/graph/g_layout.h"
#include "aqdiagram/graph/g_config.h"
#include "aqdiagram/graph/draw.h"
#include "aqdiagram/graph/layout.h"
#include "aqdiagram/graph/setup.h"
#include <gwenhywfar/debug.h>
@@ -25,6 +23,10 @@ GWEN_LIST2_FUNCTIONS(AQDG_GRAPH, AQDG_Graph)
void AQDG_Graph_DrawDataAsBars(AQDG_GRAPH *gr, int level, int penId);
void AQDG_Graph_DrawDataAsLine(AQDG_GRAPH *gr, int level, int penId);
AQDG_GRAPH *AQDG_Graph_new(AQDG_GRAPH_DATASET *ds, AQDG_DRAW_CONTEXT *drawContext, int width, int height)
{
@@ -48,77 +50,232 @@ void AQDG_Graph_free(AQDG_GRAPH *gr)
if (gr) {
GWEN_LIST_FINI(AQDG_GRAPH, gr)
AQDG_Draw_Context_free(gr->drawContext);
AQDG_Graph_DataSet_free(gr->dataSet);
GWEN_FREE_OBJECT(gr);
}
}
void AQDG_Graph_DrawFramework(AQDG_GRAPH *gr)
void AQDG_Graph_DrawDataAsLine(AQDG_GRAPH *gr, int level, int penId)
{
const char *s;
AQDG_GRAPH_DATAPAIR_LIST *dpl;
/* draw background */
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, gr->penBackground,
0, 0, gr->width, gr->height);
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
int lastX;
int lastY;
int first=1;
/* draw graph area */
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, gr->penGraphBackground,
gr->graphAreaPosX, gr->graphAreaPosY,
gr->graphAreaWidth, gr->graphAreaHeight);
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
AQDG_Graph_DrawXTicks(gr);
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
/* draw x-axis */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis,
gr->graphAreaPosX, gr->xAxisPosY,
gr->graphAreaPosX+gr->graphAreaWidth, gr->xAxisPosY);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
/* x-axis label */
s=AQDG_Graph_DataSet_GetLabelX(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontAxisLabel, AQDG_Direction_Horizontal,
gr->xAxisLabelPosX, gr->xAxisLabelPosY, s);
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw a small star */
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y-3, x+3, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y+3, x+3, y-3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x, y-3, x, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y, x+3, y);
if (!first)
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, lastX, lastY, x, y);
else
first=0;
/* draw y ticks */
AQDG_Graph_DrawYTicks(gr);
lastX=x;
lastY=y;
}
/* draw y-axis */
AQDG_Draw_Context_DrawLine(gr->drawContext, gr->penAxis,
gr->yAxisPosX, gr->graphAreaPosY,
gr->yAxisPosX, gr->graphAreaPosY+gr->graphAreaHeight);
dp=AQDG_Graph_DataPair_List_Next(dp);
}
/* y-axis label */
s=AQDG_Graph_DataSet_GetLabelY(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penAxisLabel, gr->fontAxisLabel, AQDG_Direction_Horizontal,
gr->yAxisLabelPosX, gr->yAxisLabelPosY, s);
/* title */
s=AQDG_Graph_DataSet_GetTitle(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penTitle, gr->fontTitle, AQDG_Direction_Horizontal,
gr->titlePosX, gr->titlePosY, s);
/* subtitle */
s=AQDG_Graph_DataSet_GetSubTitle(gr->dataSet);
if (s && *s)
AQDG_Draw_Context_DrawText(gr->drawContext, gr->penSubTitle, gr->fontSubTitle, AQDG_Direction_Horizontal,
gr->subTitlePosX, gr->subTitlePosY, s);
}
}
void AQDG_Graph_DrawDataAsBars(AQDG_GRAPH *gr, int level, int penId)
{
AQDG_GRAPH_DATAPAIR_LIST *dpl;
double dataWidth;
int barWidth;
int rv;
rv=AQDG_Graph_DataSet_GetMinValueDistX(gr->dataSet, level, &dataWidth);
if (rv<0) {
DBG_INFO(AQDG_LOGDOMAIN, "here (%d)", rv);
return;
}
else if (rv==1) {
/* use full width */
barWidth=(gr->graphAreaWidth)-10;
}
else {
barWidth=((int)(dataWidth*gr->graphFactorX))-10;
}
if (barWidth<1)
barWidth=1;
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
int leftX, bw;
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw the bar */
if ((x-(barWidth/2))<gr->graphAreaPosX) {
leftX=x;
bw=barWidth/2;
}
else {
leftX=x-(barWidth/2);
bw=barWidth;
}
if ((leftX+bw)>=(gr->graphAreaPosX+gr->graphAreaWidth)) {
bw=barWidth/2;
}
AQDG_Draw_Context_DrawFilledRect(gr->drawContext, penId,
leftX, gr->xAxisPosY,
bw, y-gr->xAxisPosY);
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
void AQDG_Graph_DrawDataAsPoints(AQDG_GRAPH *gr, int level, int penId)
{
AQDG_GRAPH_DATAPAIR_LIST *dpl;
double dataWidth;
int barWidth;
int rv;
rv=AQDG_Graph_DataSet_GetMinValueDistX(gr->dataSet, level, &dataWidth);
if (rv<0) {
DBG_INFO(AQDG_LOGDOMAIN, "here (%d)", rv);
return;
}
else if (rv==1) {
/* use full width */
barWidth=(gr->graphAreaWidth)-10;
}
else {
barWidth=((int)(dataWidth*gr->graphFactorX))-10;
}
if (barWidth<1)
barWidth=1;
dpl=AQDG_Graph_DataSet_GetDataPairList(gr->dataSet);
if (dpl) {
AQDG_GRAPH_DATAPAIR *dp;
double minValX;
double maxValX;
double minValY;
double maxValY;
minValX=AQDG_Graph_DataSet_GetMinValueX(gr->dataSet);
maxValX=AQDG_Graph_DataSet_GetMaxValueX(gr->dataSet);
minValY=AQDG_Graph_DataSet_GetMinValueY(gr->dataSet);
maxValY=AQDG_Graph_DataSet_GetMaxValueY(gr->dataSet);
dp=AQDG_Graph_DataPair_List_First(dpl);
while (dp) {
if (AQDG_Graph_DataPair_GetLevel(dp)==level) {
double vX;
double vY;
int x, y;
vX=AQDG_Graph_DataPair_GetValueX(dp);
vY=AQDG_Graph_DataPair_GetValueY(dp);
if (vX<minValX)
vX=minValX;
else if (vX>maxValX)
vX=maxValX;
if (vY<minValY)
vY=minValY;
else if (vY>maxValY)
vY=maxValY;
x=gr->graphOriginX + (vX * gr->graphFactorX);
y=gr->graphOriginY - (vY * gr->graphFactorY);
/* draw a small star */
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y-3, x+3, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y+3, x+3, y-3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x, y-3, x, y+3);
AQDG_Draw_Context_DrawLine(gr->drawContext, penId, x-3, y, x+3, y);
}
dp=AQDG_Graph_DataPair_List_Next(dp);
}
}
}
@@ -158,10 +315,3 @@ int AQDG_Graph_Draw(AQDG_GRAPH *gr)
return 0;
}

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
* This file is part of the project AqFinance.
* AqFinance (c) by 2011 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -10,21 +10,21 @@
# include <config.h>
#endif
#include "aqdiagram/graph/g_layout.h"
#include "aqdiagram/graph/tick_fns.h"
#include "aqdiagram/graph/layout.h"
//#include "aqdiagram/graph/dataset_fns.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
static void _getTickLabelMaxSizes(AQDG_GRAPH *gr, AQDG_GRAPH_TICK_LIST *tl, int *pMaxWidth, int *pMaxHeight);
static void _calcTickLabelMaxSizes(AQDG_GRAPH *gr, AQDG_GRAPH_TICK_LIST *tl, int *pMaxWidth, int *pMaxHeight);
static void _sampleSizes(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds);
static void _layout(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds);
static void _calcGraphArea(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds);
void AQDG_Graph_PrepareGraph(AQDG_GRAPH *gr)
{
AQDG_GRAPH_TICK_LIST *tl;
@@ -44,8 +44,7 @@ void AQDG_Graph_PrepareGraph(AQDG_GRAPH *gr)
void _getTickLabelMaxSizes(AQDG_GRAPH *gr, AQDG_GRAPH_TICK_LIST *tl, int *pMaxWidth, int *pMaxHeight)
void _calcTickLabelMaxSizes(AQDG_GRAPH *gr, AQDG_GRAPH_TICK_LIST *tl, int *pMaxWidth, int *pMaxHeight)
{
if (tl) {
AQDG_GRAPH_TICK *t;
@@ -102,14 +101,14 @@ void _sampleSizes(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds)
gr->xTickLabelPosY=-1;
tl=AQDG_Graph_DataSet_GetXTickList(ds);
if (tl)
_getTickLabelMaxSizes(gr, tl, &(gr->xTickLabelMaxWidth), &(gr->xTickLabelMaxHeight));
_calcTickLabelMaxSizes(gr, tl, &(gr->xTickLabelMaxWidth), &(gr->xTickLabelMaxHeight));
gr->yTickLabelMaxWidth=-1;
gr->yTickLabelMaxHeight=-1;
gr->yTickLabelPosX=-1;
tl=AQDG_Graph_DataSet_GetYTickList(ds);
if (tl)
_getTickLabelMaxSizes(gr, tl, &(gr->yTickLabelMaxWidth), &(gr->yTickLabelMaxHeight));
_calcTickLabelMaxSizes(gr, tl, &(gr->yTickLabelMaxWidth), &(gr->yTickLabelMaxHeight));
/* title */
gr->titleWidth=-1;
@@ -293,7 +292,7 @@ void _calcGraphArea(AQDG_GRAPH *gr, AQDG_GRAPH_DATASET *ds)
gr->xAxisPosY=gr->graphAreaPosY;
}
else if (gr->graphOriginY>=gr->graphAreaHeight) {
/* x-axis on lower border */
/* y-axis on lower border */
gr->xAxisPosY=gr->graphAreaPosY+gr->graphAreaHeight-1;
}
else {

View File

@@ -7,15 +7,15 @@
****************************************************************************/
#ifndef AQDG_G_LAYOUT_H
#define AQDG_G_LAYOUT_H
#ifndef AQDG_GRAPH_LAYOUT_H
#define AQDG_GRAPH_LAYOUT_H
#include <aqdiagram/graph/graph.h>
void AQDG_Graph_PrepareGraph(AQDG_GRAPH *gr);
void AQDG_Graph_PrepareGraph(AQDG_GRAPH *gr);
#endif

View File

@@ -1,6 +1,6 @@
/****************************************************************************
* This file is part of the project AqDiagram.
* AqDiagram (c) by 2020 Martin Preuss, all rights reserved.
* This file is part of the project AqFinance.
* AqFinance (c) by 2011 Martin Preuss, all rights reserved.
*
* The license for this file can be found in the file COPYING which you
* should have received along with this file.
@@ -10,21 +10,23 @@
# include <config.h>
#endif
#include "aqdiagram/graph/g_config.h"
#include "aqdiagram/graph/setup.h"
#include "aqdiagram/graph/tick_fns.h"
#include "graph_p.h"
#include <gwenhywfar/debug.h>
static int _createPenFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name);
static int _createFontFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name, int defaultFontSize);
static int _createPenFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name);
static int _createFontFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name, int defaultFontSize);
static int _createPensAndFontsFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig);
static int _createPenFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS_PEN *sp);
static int _createFontFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS_FONT *sf);
static int _createPensAndFontsFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS *settings);
static void _releasePensAndFonts(AQDG_GRAPH *gr);
static void _releasePensAndFonts(AQDG_GRAPH *gr);
@@ -83,69 +85,7 @@ int AQDG_Graph_Fini(AQDG_GRAPH *gr)
void _releasePensAndFonts(AQDG_GRAPH *gr)
{
if (gr->penTitle>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penTitle);
gr->penTitle=-1;
}
if (gr->penSubTitle>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penSubTitle);
gr->penSubTitle=-1;
}
if (gr->penAxisLabel>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penAxisLabel);
gr->penAxisLabel=-1;
}
if (gr->penAxis>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penAxis);
gr->penAxis=-1;
}
if (gr->penGraph>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGraph);
gr->penGraph=-1;
}
if (gr->penGraphBackground>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGraphBackground);
gr->penGraphBackground=-1;
}
if (gr->penGrid>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGrid);
gr->penGrid=-1;
}
if (gr->fontTitle>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontTitle);
gr->fontTitle=-1;
}
if (gr->fontSubTitle>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontSubTitle);
gr->fontSubTitle=-1;
}
if (gr->fontAxisLabel>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontAxisLabel);
gr->fontAxisLabel=-1;
}
if (gr->fontTickLabel>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontTickLabel);
gr->fontTickLabel=-1;
}
}
int _createPenFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name)
int _createPenFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name)
{
GWEN_DB_NODE *db;
uint32_t frontColour;
@@ -170,7 +110,7 @@ int _createPenFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *nam
int _createFontFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name, int defaultFontSize)
int _createFontFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *name, int defaultFontSize)
{
GWEN_DB_NODE *db;
const char *fontName;
@@ -182,6 +122,7 @@ int _createFontFromConfig(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig, const char *na
db=GWEN_DB_GetGroup(dbConfig, 0, name);
assert(db);
fontName=GWEN_DB_GetCharValue(db, "fontName", 0, "");
fontSize=GWEN_DB_GetIntValue(db, "fontSize", 0, defaultFontSize);
fontSlant=AQDG_Slant_fromString(GWEN_DB_GetCharValue(db, "fontSlant", 0, "none"));
@@ -204,56 +145,56 @@ int _createPensAndFontsFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig)
int rv;
AQDG_GRAPH_SUBGRAPH_LIST *sgList;
rv=_createPenFromConfig(gr, dbConfig, "penTitle");
rv=_createPenFromDb(gr, dbConfig, "penTitle");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penTitle=rv;
rv=_createPenFromConfig(gr, dbConfig, "penSubTitle");
rv=_createPenFromDb(gr, dbConfig, "penSubTitle");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penSubTitle=rv;
rv=_createPenFromConfig(gr, dbConfig, "penAxisLabel");
rv=_createPenFromDb(gr, dbConfig, "penAxisLabel");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penAxisLabel=rv;
rv=_createPenFromConfig(gr, dbConfig, "penAxis");
rv=_createPenFromDb(gr, dbConfig, "penAxis");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penAxis=rv;
rv=_createPenFromConfig(gr, dbConfig, "penGraph");
rv=_createPenFromDb(gr, dbConfig, "penGraph");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGraph=rv;
rv=_createPenFromConfig(gr, dbConfig, "penGraphBackground");
rv=_createPenFromDb(gr, dbConfig, "penGraphBackground");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGraphBackground=rv;
rv=_createPenFromConfig(gr, dbConfig, "penGrid");
rv=_createPenFromDb(gr, dbConfig, "penGrid");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->penGrid=rv;
rv=_createPenFromConfig(gr, dbConfig, "penBackground");
rv=_createPenFromDb(gr, dbConfig, "penBackground");
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
@@ -262,28 +203,28 @@ int _createPensAndFontsFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig)
rv=_createFontFromConfig(gr, dbConfig, "fontTitle", 16);
rv=_createFontFromDb(gr, dbConfig, "fontTitle", 16);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontTitle=rv;
rv=_createFontFromConfig(gr, dbConfig, "fontSubTitle", 14);
rv=_createFontFromDb(gr, dbConfig, "fontSubTitle", 14);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontSubTitle=rv;
rv=_createFontFromConfig(gr, dbConfig, "fontAxisLabel", 12);
rv=_createFontFromDb(gr, dbConfig, "fontAxisLabel", 12);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
}
gr->fontAxisLabel=rv;
rv=_createFontFromConfig(gr, dbConfig, "fontTickLabel", 10);
rv=_createFontFromDb(gr, dbConfig, "fontTickLabel", 10);
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
@@ -299,9 +240,9 @@ int _createPensAndFontsFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig)
while (sg) {
rv=AQDG_Draw_Context_PenCreate(gr->drawContext,
AQDG_Graph_SubGraph_GetColour(sg),
AQDG_Graph_SubGraph_GetLineWidth(sg),
AQDG_Graph_SubGraph_GetDashType(sg));
AQDG_Graph_SubGraph_GetColour(sg),
AQDG_Graph_SubGraph_GetLineWidth(sg),
AQDG_Graph_SubGraph_GetDashType(sg));
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
@@ -318,17 +259,14 @@ int _createPensAndFontsFromDb(AQDG_GRAPH *gr, GWEN_DB_NODE *dbConfig)
int _createPenFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS_PEN *sp)
{
int rv;
rv=AQDG_Draw_Context_PenCreate(gr->drawContext,
AQDG_Graph_SettingsPen_GetFrontColour(sp),
AQDG_Graph_SettingsPen_GetLineWidth(sp),
AQDG_Graph_SettingsPen_GetDashType(sp));
AQDG_Graph_SettingsPen_GetFrontColour(sp),
AQDG_Graph_SettingsPen_GetLineWidth(sp),
AQDG_Graph_SettingsPen_GetDashType(sp));
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
@@ -344,9 +282,9 @@ int _createFontFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS_FONT *sf)
int rv;
rv=AQDG_Draw_Context_FontCreate(gr->drawContext, "",
AQDG_Graph_SettingsFont_GetFontSize(sf),
AQDG_Graph_SettingsFont_GetFontSlant(sf),
AQDG_Graph_SettingsFont_GetFontWeight(sf));
AQDG_Graph_SettingsFont_GetFontSize(sf),
AQDG_Graph_SettingsFont_GetFontSlant(sf),
AQDG_Graph_SettingsFont_GetFontWeight(sf));
if (rv<0) {
DBG_INFO(0, "here (%d)", rv);
return rv;
@@ -515,3 +453,64 @@ int _createPensAndFontsFromSettings(AQDG_GRAPH *gr, const AQDG_GRAPH_SETTINGS *s
void _releasePensAndFonts(AQDG_GRAPH *gr)
{
if (gr->penTitle>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penTitle);
gr->penTitle=-1;
}
if (gr->penSubTitle>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penSubTitle);
gr->penSubTitle=-1;
}
if (gr->penAxisLabel>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penAxisLabel);
gr->penAxisLabel=-1;
}
if (gr->penAxis>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penAxis);
gr->penAxis=-1;
}
if (gr->penGraph>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGraph);
gr->penGraph=-1;
}
if (gr->penGraphBackground>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGraphBackground);
gr->penGraphBackground=-1;
}
if (gr->penGrid>=0) {
AQDG_Draw_Context_PenRelease(gr->drawContext, gr->penGrid);
gr->penGrid=-1;
}
if (gr->fontTitle>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontTitle);
gr->fontTitle=-1;
}
if (gr->fontSubTitle>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontSubTitle);
gr->fontSubTitle=-1;
}
if (gr->fontAxisLabel>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontAxisLabel);
gr->fontAxisLabel=-1;
}
if (gr->fontTickLabel>=0) {
AQDG_Draw_Context_FontRelease(gr->drawContext, gr->fontTickLabel);
gr->fontTickLabel=-1;
}
}

View File

@@ -7,12 +7,14 @@
****************************************************************************/
#ifndef AQDG_G_CONFIG_H
#define AQDG_G_CONFIG_H
#ifndef AQDG_GRAPH_SETUP_H
#define AQDG_GRAPH_SETUP_H
#include <aqdiagram/graph/graph.h>
#endif