wip line chart

This commit is contained in:
Nishi 2026-09-14 07:58:11 +09:00
commit b54721a323
4 changed files with 112 additions and 46 deletions

View file

@ -294,6 +294,19 @@ int main() {
MwChartAdd(w, -1, "G", 10, NULL); MwChartAdd(w, -1, "G", 10, NULL);
MwChartAdd(w, -1, "H", 20, NULL); MwChartAdd(w, -1, "H", 20, NULL);
f = frame("Line Chart", -PaddingContent, -PaddingContent, MwChartClass,
MwNtype, MwCHART_LINE,
NULL);
w = child(f);
MwChartAdd(w, -1, "A", -800, NULL);
MwChartAdd(w, -1, "B", -400, NULL);
MwChartAdd(w, -1, "C", -200, NULL);
MwChartAdd(w, -1, "D", -100, NULL);
MwChartAdd(w, -1, "E", 100, NULL);
MwChartAdd(w, -1, "F", 200, NULL);
MwChartAdd(w, -1, "G", 400, NULL);
MwChartAdd(w, -1, "H", 800, NULL);
f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL); f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL);
w = child(f); w = child(f);
MwComboBoxAdd(w, -1, "Hello!"); MwComboBoxAdd(w, -1, "Hello!");
@ -306,7 +319,6 @@ int main() {
f = frame("Label", -PaddingContent, -PaddingContent, MwLabelClass, f = frame("Label", -PaddingContent, -PaddingContent, MwLabelClass,
MwNtext, "Epic text\nNewline can be used too!", MwNtext, "Epic text\nNewline can be used too!",
MwNcolumnSpan, 2,
NULL); NULL);
f = frame("ListBox", -PaddingContent, -PaddingContent, MwListBoxClass, f = frame("ListBox", -PaddingContent, -PaddingContent, MwListBoxClass,

View file

@ -117,7 +117,8 @@ enum MwCHART {
MwCHART_BAR = 0, MwCHART_BAR = 0,
MwCHART_3D_BAR, MwCHART_3D_BAR,
MwCHART_PIE, MwCHART_PIE,
MwCHART_3D_PIE MwCHART_3D_PIE,
MwCHART_LINE
}; };
enum MwMOUSE { enum MwMOUSE {

View file

@ -214,8 +214,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {}
static MwBool lmao = MwFALSE; static MwBool lmao = MwFALSE;
static int MwLLPendingImpl(MwLL handle) { static int MwLLPendingImpl(MwLL handle) {
lmao = !lmao; lmao = !lmao;
return lmao; return lmao;
} }
static void MwLLNextEventImpl(MwLL handle) { static void MwLLNextEventImpl(MwLL handle) {
MwLLDispatch(handle, draw, NULL); MwLLDispatch(handle, draw, NULL);
@ -259,10 +259,10 @@ static void MwLLRaiseImpl(MwLL handle) {}
static void MwLLClipImpl(MwLL handle, MwRect* rect) {} static void MwLLClipImpl(MwLL handle, MwRect* rect) {}
static void MwLLSetupDragAndDropImpl(MwLL handle) {} static void MwLLSetupDragAndDropImpl(MwLL handle) {}
static int MwLLCairoCallInitImpl(void) { static int MwLLCairoCallInitImpl(void) {
if(cairo_load_funcs() != 0) { if(cairo_load_funcs() != 0) {
return 1; return 1;
} }
return 0; return 0;
} }
#include "call.c" #include "call.c"
CALL(Cairo); CALL(Cairo);

View file

@ -62,6 +62,19 @@ static void draw_line(MwWidget handle, const char* text, double x, double y, dou
MwLLLine(handle->lowlevel, &p[0], color); MwLLLine(handle->lowlevel, &p[0], color);
} }
#define CALC_VMIN_VMAX \
if(vmin > 0) { \
vmin = 0; \
} else if(vmin < 0) { \
vmin -= (double)width / r.height * (vmax - vmin); \
} \
\
if(vmax < 0) { \
vmax = 0; \
} else if(vmax > 0) { \
vmax += (double)width / r.height * (vmax - vmin); \
}
static void draw(MwWidget handle) { static void draw(MwWidget handle) {
int ColorDiff = MwGetColorDifference(handle); int ColorDiff = MwGetColorDifference(handle);
MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
@ -73,13 +86,14 @@ static void draw(MwWidget handle) {
int n; int n;
int gap; int gap;
int width; int width;
MwRect node;
double vmin = 0xffffffff; double vmin = 0xffffffff;
double vmax = -0xffffffff; double vmax = -0xffffffff;
int space = MwTextHeight(handle, NULL, "M"); int space = MwTextHeight(handle, NULL, "M");
MwPoint p[2]; MwPoint p[2];
int type = MwGetInteger(handle, MwNtype); int type = MwGetInteger(handle, MwNtype);
int modern = MwGetInteger(handle, MwNmodernLook); int modern = MwGetInteger(handle, MwNmodernLook);
double ovmin;
double ovmax;
for(n = 0; colors[n] != NULL; n++); for(n = 0; colors[n] != NULL; n++);
@ -91,6 +105,9 @@ static void draw(MwWidget handle) {
if(MwGetInteger(handle, MwNminValue) != MwDEFAULT) vmin = MwGetInteger(handle, MwNminValue); if(MwGetInteger(handle, MwNminValue) != MwDEFAULT) vmin = MwGetInteger(handle, MwNminValue);
if(MwGetInteger(handle, MwNmaxValue) != MwDEFAULT) vmax = MwGetInteger(handle, MwNmaxValue); if(MwGetInteger(handle, MwNmaxValue) != MwDEFAULT) vmax = MwGetInteger(handle, MwNmaxValue);
ovmin = vmin;
ovmax = vmax;
r.x = 0; r.x = 0;
r.y = 0; r.y = 0;
r.width = MwGetInteger(handle, MwNwidth); r.width = MwGetInteger(handle, MwNwidth);
@ -98,11 +115,10 @@ static void draw(MwWidget handle) {
MwDrawRect(handle, &r, base); MwDrawRect(handle, &r, base);
if(type == MwCHART_BAR || type == MwCHART_3D_BAR) { if(type == MwCHART_BAR || type == MwCHART_3D_BAR) {
double s = 1.5; double s = 1.5;
double ovmin = vmin;
double ovmax = vmax;
double twidth; double twidth;
char buf[128]; char buf[128];
MwRect node;
node.x = 0; node.x = 0;
@ -121,20 +137,10 @@ static void draw(MwWidget handle) {
width = (r.width - node.x) * s / (arrlen(c->entries) * (1 + s) + 1); width = (r.width - node.x) * s / (arrlen(c->entries) * (1 + s) + 1);
gap = width / s; gap = width / s;
CALC_VMIN_VMAX;
twidth = (width + gap) * arrlen(c->entries) + gap; twidth = (width + gap) * arrlen(c->entries) + gap;
if(vmin > 0) {
vmin = 0;
} else if(vmin < 0) {
vmin -= (double)width / r.height * (vmax - vmin);
}
if(vmax < 0) {
vmax = 0;
} else if(vmax > 0) {
vmax += (double)width / r.height * (vmax - vmin);
}
sprintf(buf, NUMFMT, ovmax); sprintf(buf, NUMFMT, ovmax);
draw_line(handle, buf, node.x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border); draw_line(handle, buf, node.x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border);
@ -247,7 +253,7 @@ static void draw(MwWidget handle) {
double cangle = 0; double cangle = 0;
int k; int k;
double vsquish = type == MwCHART_3D_PIE ? 2 : 1; double vsquish = type == MwCHART_3D_PIE ? 2 : 1;
MwPoint p[360 + 1 + 1]; MwPoint p2[360 + 1 + 1];
for(i = 0; i < arrlen(c->entries); i++) { for(i = 0; i < arrlen(c->entries); i++) {
if(c->entries[i].value > 0) sum += c->entries[i].value; if(c->entries[i].value > 0) sum += c->entries[i].value;
@ -268,62 +274,62 @@ static void draw(MwWidget handle) {
color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color); color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color);
colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff);
p[0].x = r.width / 2; p2[0].x = r.width / 2;
p[0].y = r.height / 2; p2[0].y = r.height / 2;
for(j = 0; j <= div; j++) { for(j = 0; j <= div; j++) {
double a = angle / div * j; double a = angle / div * j;
p[div - j + 1].x = p[0].x + cos((cangle + a - 90) / 180 * M_PI) * radius / 2; p2[div - j + 1].x = p2[0].x + cos((cangle + a - 90) / 180 * M_PI) * radius / 2;
p[div - j + 1].y = p[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2 / vsquish; p2[div - j + 1].y = p2[0].y + sin((cangle + a - 90) / 180 * M_PI) * radius / 2 / vsquish;
} }
count = j + 1; count = j + 1;
if((k == 0 || k == 1) && type == MwCHART_3D_PIE) { if((k == 0 || k == 1) && type == MwCHART_3D_PIE) {
int j; int j;
MwPoint p2[360 + 1 + 1]; MwPoint p3[360 + 1 + 1];
int d = 0; int d = 0;
for(d = 1; d <= 2; d++) { for(d = 1; d <= 2; d++) {
for(j = 0; j < count - 1; j++) { for(j = 0; j < count - 1; j++) {
p2[3 + j] = p[1 + j]; p3[3 + j] = p2[1 + j];
p2[3 + j].y += radius / 8 / d; p3[3 + j].y += radius / 8 / d;
} }
p2[0] = p[count - 1]; p3[0] = p2[count - 1];
p2[1] = p[0]; p3[1] = p2[0];
p2[2] = p[1]; p3[2] = p2[1];
if(k == 0) { if(k == 0) {
MwLLPolygon(handle->lowlevel, p2, count + 2, color); MwLLPolygon(handle->lowlevel, p3, count + 2, color);
} else if(d == 1 && k == 1) { } else if(d == 1 && k == 1) {
for(j = 3; j < count + 1; j++) { for(j = 3; j < count + 1; j++) {
if(!modern) MwLLLine(handle->lowlevel, &p2[j], border); if(!modern) MwLLLine(handle->lowlevel, &p3[j], border);
} }
p[0] = p[1]; p2[0] = p2[1];
p[0].y += radius / 8; p2[0].y += radius / 8;
if(!modern) MwLLLine(handle->lowlevel, p, border); if(!modern) MwLLLine(handle->lowlevel, p2, border);
} }
} }
} }
if(k == 2) { if(k == 2) {
MwLLPolygon(handle->lowlevel, p, count, type == MwCHART_3D_PIE ? colorl : color); MwLLPolygon(handle->lowlevel, p2, count, type == MwCHART_3D_PIE ? colorl : color);
} else if(k == 3) { } else if(k == 3) {
int j; int j;
p[count] = p[0]; p[count] = p2[0];
for(j = 0; j < count; j++) { for(j = 0; j < count; j++) {
if(!modern) MwLLLine(handle->lowlevel, &p[j], border); if(!modern) MwLLLine(handle->lowlevel, &p2[j], border);
} }
p[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4; p2[0].x += cos((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4;
p[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish; p2[0].y += sin((cangle + angle / 2 - 90) / 180 * M_PI) * radius / 4 / vsquish;
handle->bgcolor = type == MwCHART_3D_PIE ? colorl : color; handle->bgcolor = type == MwCHART_3D_PIE ? colorl : color;
MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border); MwDrawText(handle, NULL, p2, c->entries[i].name, MwALIGNMENT_CENTER, border);
} }
cangle += angle; cangle += angle;
@ -341,6 +347,53 @@ static void draw(MwWidget handle) {
MwLLLine(handle->lowlevel, p, border); MwLLLine(handle->lowlevel, p, border);
p[0].x = p[1].x = r.width / 2 + radius / 2; p[0].x = p[1].x = r.width / 2 + radius / 2;
MwLLLine(handle->lowlevel, p, border);
}
} else if(type == MwCHART_LINE) {
char buf[128];
MwRect node;
double twidth;
double x = 0;
for(i = 0; i < arrlen(c->entries); i++) {
int w;
sprintf(buf, NUMFMT, c->entries[i].value);
w = MwTextWidth(handle, NULL, buf);
if(x < w) x = w;
}
width = 16;
twidth = r.width - x;
CALC_VMIN_VMAX;
sprintf(buf, NUMFMT, ovmax);
draw_line(handle, buf, x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border);
draw_line(handle, "0", x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border);
sprintf(buf, NUMFMT, ovmin);
draw_line(handle, buf, x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border);
draw_line(handle, "", x, (r.height - space) - (vmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border);
p[0].x = x;
p[0].y = 0;
p[1] = p[0];
p[1].y = r.height - space;
MwLLLine(handle->lowlevel, p, border);
for(i = 1; i < arrlen(c->entries); i++) {
p[0].x = x + (r.width - x) / (arrlen(c->entries) + 1) * i;
p[0].y = (r.height - space) - (c->entries[i - 1].value - vmin) / (vmax - vmin) * (r.height - space);
p[1].x = x + (r.width - x) / (arrlen(c->entries) + 1) * (i + 1);
p[1].y = (r.height - space) - (c->entries[i].value - vmin) / (vmax - vmin) * (r.height - space);
MwLLLine(handle->lowlevel, p, border); MwLLLine(handle->lowlevel, p, border);
} }
} }