diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c
index db833c6..e40994d 100644
--- a/examples/basic/periodic.c
+++ b/examples/basic/periodic.c
@@ -269,12 +269,17 @@ int main() {
wclock = child(f);
f = frame("Chart", -PaddingContent, -PaddingContent, MwChartClass,
+ MwNtype, MwCHART_3D_BAR,
+ MwNcolumnSpan, 2,
NULL);
w = child(f);
- MwChartAdd(w, -1, "A", -100, NULL);
- MwChartAdd(w, -1, "B", 100, NULL);
- MwChartAdd(w, -1, "C", 200, NULL);
- MwChartAdd(w, -1, "D", 300, NULL);
+ MwChartAdd(w, -1, "A", -400, NULL);
+ MwChartAdd(w, -1, "B", -200, NULL);
+ MwChartAdd(w, -1, "C", -100, NULL);
+ MwChartAdd(w, -1, "D", 100, NULL);
+ MwChartAdd(w, -1, "E", 200, NULL);
+ MwChartAdd(w, -1, "F", 400, NULL);
+ MwChartAdd(w, -1, "G", 800, NULL);
f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL);
w = child(f);
@@ -288,6 +293,7 @@ int main() {
f = frame("Label", -PaddingContent, -PaddingContent, MwLabelClass,
MwNtext, "Epic text\nNewline can be used too!",
+ MwNcolumnSpan, 2,
NULL);
f = frame("ListBox", -PaddingContent, -PaddingContent, MwListBoxClass,
@@ -321,9 +327,7 @@ int main() {
MwNtitle, "Sub window 2",
NULL);
- f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass,
- MwNcolumnSpan, 2,
- NULL);
+ f = frame("Tab", -PaddingContent, -PaddingContent, MwTabClass, NULL);
w = child(f);
MwSetText(MwTabAdd(w, "ABC"), MwNbackground, "#f00");
MwSetText(MwTabAdd(w, "DEF"), MwNbackground, "#0f0");
diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h
index ad29792..6df447d 100644
--- a/include/Mw/Constants.h
+++ b/include/Mw/Constants.h
@@ -114,7 +114,8 @@ enum MwCLIPBOARD {
};
enum MwCHART {
- MwCHART_BAR = 0
+ MwCHART_BAR = 0,
+ MwCHART_3D_BAR,
};
enum MwMOUSE {
diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h
index e3c6991..ad13c60 100644
--- a/include/Mw/Draw.h
+++ b/include/Mw/Draw.h
@@ -52,6 +52,13 @@ MWDECL void MWAPI MwColorTableInit(void);
*/
MWDECL MwLLColor MWAPI MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b);
+/*!
+ * @brief Fix a rectangle
+ * @param handle Widget
+ * @param rect Rectangle area
+ */
+MWDECL void MWAPI MwFixRect(MwRect* rect);
+
/*!
* @brief Draws a filled rectangle
* @param handle Widget
diff --git a/milsko.xml b/milsko.xml
index 30efce1..6bf802b 100644
--- a/milsko.xml
+++ b/milsko.xml
@@ -232,6 +232,7 @@
0
+
1
@@ -657,6 +658,8 @@
+
+
diff --git a/src/core.c b/src/core.c
index 2982c1e..481fa34 100644
--- a/src/core.c
+++ b/src/core.c
@@ -5,7 +5,7 @@
#ifdef USE_COCOA
#define PERIODIC
#endif
-#define USE_CLASSIC_THEME
+// #define USE_CLASSIC_THEME
#define RESIZE_ON_TICK
#define DRAW(handle) \
diff --git a/src/draw.c b/src/draw.c
index 5cbfd22..eb15c76 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -99,19 +99,23 @@ MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b)
return MwLLAllocColor(handle->lowlevel, cr, cg, cb);
}
+void MwFixRect(MwRect* rect) {
+ if(rect->width < 0) {
+ rect->width *= -1;
+ rect->x -= rect->width;
+ }
+
+ if(rect->height < 0) {
+ rect->height *= -1;
+ rect->y -= rect->height;
+ }
+}
+
void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) {
MwPoint p[4];
MwRect r = *rect;
- if(r.width < 0) {
- r.width *= -1;
- r.x -= r.width;
- }
-
- if(r.height < 0) {
- r.height *= -1;
- r.y -= r.height;
- }
+ MwFixRect(&r);
p[0].x = r.x;
p[0].y = r.y;
@@ -132,15 +136,7 @@ void MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color) {
MwPoint p[5];
MwRect r = *rect;
- if(r.width < 0) {
- r.width *= -1;
- r.x -= r.width;
- }
-
- if(r.height < 0) {
- r.height *= -1;
- r.y -= r.height;
- }
+ MwFixRect(&r);
p[0].x = r.x;
p[0].y = r.y;
diff --git a/src/widget/chart.c b/src/widget/chart.c
index b014513..34d8f4e 100644
--- a/src/widget/chart.c
+++ b/src/widget/chart.c
@@ -27,6 +27,8 @@ static int wcreate(MwWidget handle) {
MwSetDefault(handle);
+ MwSetInteger(handle, MwNtype, MwCHART_BAR);
+
return 0;
}
@@ -35,6 +37,35 @@ static void destroy(MwWidget handle) {
free(handle->internal);
}
+static void draw_line(MwWidget handle, const char* text, double x, double y, double width, double height, MwLLColor color) {
+ MwPoint p[2];
+ int type = MwGetInteger(handle, MwNtype);
+
+ p[0].x = x;
+ p[0].y = y;
+
+ p[1].x = x + width;
+ p[1].y = p[0].y;
+ MwDrawText(handle, NULL, p, text, MwALIGNMENT_END, color);
+
+ if(type == MwCHART_3D_BAR) {
+ MwPoint p2[2];
+
+ p2[0] = p[0];
+ p2[1] = p[0];
+
+ p2[1].x += height;
+ p2[1].y -= height;
+
+ MwLLLine(handle->lowlevel, &p2[0], color);
+
+ p[0].x += height;
+ p[0].y -= height;
+ p[1].y -= height;
+ }
+ MwLLLine(handle->lowlevel, &p[0], color);
+}
+
static void draw(MwWidget handle) {
MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground));
@@ -46,75 +77,162 @@ static void draw(MwWidget handle) {
int gap;
int width;
MwRect node;
- double min = 0xffffffff;
- double max = -0xffffffff;
+ double vmin = 0xffffffff;
+ double vmax = -0xffffffff;
int space = MwTextHeight(handle, NULL, "M");
MwPoint p[2];
+ int type = MwGetInteger(handle, MwNtype);
for(n = 0; colors[n] != NULL; n++);
for(i = 0; i < arrlen(c->entries); i++) {
- if(min > c->entries[i].value) min = c->entries[i].value;
- if(max < c->entries[i].value) max = c->entries[i].value;
+ if(vmin > c->entries[i].value) vmin = c->entries[i].value;
+ if(vmax < c->entries[i].value) vmax = c->entries[i].value;
}
+ if(MwGetInteger(handle, MwNminValue) != MwDEFAULT) vmin = MwGetInteger(handle, MwNminValue);
+ if(MwGetInteger(handle, MwNmaxValue) != MwDEFAULT) vmax = MwGetInteger(handle, MwNmaxValue);
+
r.x = 0;
r.y = 0;
r.width = MwGetInteger(handle, MwNwidth);
r.height = MwGetInteger(handle, MwNheight);
MwDrawRect(handle, &r, base);
- if(min > 0) {
- min = 0;
- } else if(min < 0) {
- min -= r.height / 10;
- }
+ if(type == MwCHART_BAR || type == MwCHART_3D_BAR) {
+ double s = 1.5;
+ double ovmin = vmin;
+ double ovmax = vmax;
+ double twidth;
+ char buf[128];
- node.x = 16;
- node.y = 0;
+ node.x = 128;
+ node.y = 0;
- width = (r.width - node.x) * 2 / (arrlen(c->entries) * 3 + 1);
- gap = width / 2;
+ width = (r.width - node.x) * s / (arrlen(c->entries) * (1 + s) + 1);
+ gap = width / s;
- p[0].x = node.x;
- p[0].y = r.height - space;
+ twidth = (width + gap) * arrlen(c->entries) + gap;
- p[1].x = node.x + (width + gap) * arrlen(c->entries) + gap;
- p[1].y = p[0].y;
- MwLLLine(handle->lowlevel, &p[0], border);
+ if(vmin > 0) {
+ vmin = 0;
+ } else if(vmin < 0) {
+ vmin -= (double)width / r.height * (vmax - vmin);
+ }
- p[0].y = r.height - space - abs(min / (max - min) * (r.height - space));
- p[1].y = p[0].y;
- MwLLLine(handle->lowlevel, &p[0], border);
- MwDrawText(handle, NULL, p, "0", MwALIGNMENT_END, border);
+ if(vmax < 0) {
+ vmax = 0;
+ } else if(vmax > 0) {
+ vmax += (double)width / r.height * (vmax - vmin);
+ }
- p[0].x = node.x;
- p[0].y = 0;
+ sprintf(buf, "%.2f", ovmax);
+ draw_line(handle, buf, node.x, (r.height - space) - (ovmax - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border);
- p[1].x = node.x;
- p[1].y = r.height - space;
- MwLLLine(handle->lowlevel, &p[0], border);
+ draw_line(handle, "0", node.x, (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border);
- node.width = width;
- for(i = 0; i < arrlen(c->entries); i++) {
- MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color);
+ sprintf(buf, "%.2f", ovmin);
+ draw_line(handle, buf, node.x, (r.height - space) - (ovmin - vmin) / (vmax - vmin) * (r.height - space), twidth, width / 2, border);
- node.x += gap;
+ p[0].x = node.x;
+ p[0].y = 0;
- node.height = c->entries[i].value / (max - min) * (r.height - space);
- node.y = r.height - space - node.height - abs(min / (max - min) * (r.height - space));
+ p[1].x = node.x;
+ p[1].y = r.height - space;
+ MwLLLine(handle->lowlevel, &p[0], border);
- MwDrawRect(handle, &node, color);
- MwDrawRectLine(handle, &node, border);
+ p[0].x = node.x;
+ p[0].y = r.height - space;
- p[0].x = node.x + node.width / 2;
- p[0].y = r.height - space / 2;
+ p[1].x = node.x + twidth;
+ p[1].y = p[0].y;
+ MwLLLine(handle->lowlevel, &p[0], border);
- MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border);
+ node.width = width;
+ for(i = 0; i < arrlen(c->entries); i++) {
+ int ColorDiff = MwGetColorDifference(handle);
+ MwLLColor color = MwParseColor(handle, c->entries[i].color == NULL ? colors[i % n] : c->entries[i].color);
+ MwLLColor colorl = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff);
+ MwLLColor colord = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff);
+ MwPoint persp_top[5];
+ MwPoint persp_right[5];
- node.x += node.width;
+ node.x += gap;
- MwLLFreeColor(color);
+ node.height = -c->entries[i].value / (vmax - vmin) * (r.height - space);
+ node.y = (r.height - space) - (0 - vmin) / (vmax - vmin) * (r.height - space);
+
+ MwDrawRect(handle, &node, color);
+
+ if(type == MwCHART_3D_BAR) {
+ MwRect node2 = node;
+
+ MwFixRect(&node2);
+
+ persp_top[0] = *(MwPoint*)&node2;
+ persp_top[1] = *(MwPoint*)&node2;
+ persp_top[1].x += node2.width;
+
+ persp_top[2] = persp_top[1];
+ persp_top[3] = persp_top[0];
+
+ persp_top[2].x += node2.width / 2;
+ persp_top[2].y -= node2.width / 2;
+
+ persp_top[3].x += node2.width / 2;
+ persp_top[3].y -= node2.width / 2;
+
+ persp_top[4] = persp_top[0];
+
+ MwLLPolygon(handle->lowlevel, persp_top, 4, colorl);
+
+ persp_right[0] = *(MwPoint*)&node2;
+ persp_right[1] = *(MwPoint*)&node2;
+ persp_right[0].x += node2.width;
+ persp_right[1].x += node2.width;
+ persp_right[1].y += node2.height;
+
+ persp_right[2] = persp_right[1];
+ persp_right[3] = persp_right[0];
+
+ persp_right[2].x += node2.width / 2;
+ persp_right[2].y -= node2.width / 2;
+
+ persp_right[3].x += node2.width / 2;
+ persp_right[3].y -= node2.width / 2;
+
+ persp_right[4] = persp_right[0];
+
+ MwLLPolygon(handle->lowlevel, persp_right, 4, colord);
+ }
+
+ if(!MwGetInteger(handle, MwNmodernLook)) {
+ MwDrawRectLine(handle, &node, border);
+
+ if(type == MwCHART_3D_BAR) {
+ MwLLLine(handle->lowlevel, &persp_top[0], border);
+ MwLLLine(handle->lowlevel, &persp_top[1], border);
+ MwLLLine(handle->lowlevel, &persp_top[2], border);
+ MwLLLine(handle->lowlevel, &persp_top[3], border);
+
+ MwLLLine(handle->lowlevel, &persp_right[0], border);
+ MwLLLine(handle->lowlevel, &persp_right[1], border);
+ MwLLLine(handle->lowlevel, &persp_right[2], border);
+ MwLLLine(handle->lowlevel, &persp_right[3], border);
+ }
+ }
+
+ p[0].x = node.x + node.width / 2;
+ p[0].y = r.height - space / 2;
+
+ MwDrawText(handle, NULL, p, c->entries[i].name, MwALIGNMENT_CENTER, border);
+
+ node.x += node.width;
+
+ MwLLFreeColor(colord);
+ MwLLFreeColor(colorl);
+ MwLLFreeColor(color);
+ }
}
MwLLFreeColor(border);