diff --git a/examples/basic/periodic.c b/examples/basic/periodic.c
index 5b6526566..db833c67c 100644
--- a/examples/basic/periodic.c
+++ b/examples/basic/periodic.c
@@ -270,6 +270,11 @@ int main() {
f = frame("Chart", -PaddingContent, -PaddingContent, MwChartClass,
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);
f = frame("ComboBox", -PaddingContent, 24, MwComboBoxClass, NULL);
w = child(f);
diff --git a/include/Mw/Constants.h b/include/Mw/Constants.h
index 15853ff7b..ad29792ef 100644
--- a/include/Mw/Constants.h
+++ b/include/Mw/Constants.h
@@ -113,6 +113,10 @@ enum MwCLIPBOARD {
MwCLIPBOARD_PRIMARY,
};
+enum MwCHART {
+ MwCHART_BAR = 0
+};
+
enum MwMOUSE {
MwMOUSE_LEFT = 1,
MwMOUSE_MIDDLE,
diff --git a/include/Mw/Draw.h b/include/Mw/Draw.h
index 542aac57e..e3c6991f1 100644
--- a/include/Mw/Draw.h
+++ b/include/Mw/Draw.h
@@ -60,6 +60,14 @@ MWDECL MwLLColor MWAPI MwLightenColor(MwWidget handle, MwLLColor color, int r, i
*/
MWDECL void MWAPI MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color);
+/*!
+ * @brief Draws a rectangle
+ * @param handle Widget
+ * @param rect Rectangle area
+ * @param color Color
+ */
+MWDECL void MWAPI MwDrawRectLine(MwWidget handle, MwRect* rect, MwLLColor color);
+
/*!
* @brief Draws a filled rectangle that fades to a darker color
* @param handle Widget
diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h
index 39730db7d..d820ea470 100644
--- a/include/Mw/StringDefs.h
+++ b/include/Mw/StringDefs.h
@@ -57,6 +57,7 @@
#define MwNhour "Ihour"
#define MwNminute "Iminute"
#define MwNsecond "Isecond"
+#define MwNtype "Itype"
#define MwNtitle "Stitle"
#define MwNtext "Stext"
diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h
index a9bc3cf90..0be60e855 100644
--- a/include/Mw/TypeDefs.h
+++ b/include/Mw/TypeDefs.h
@@ -30,6 +30,8 @@ typedef struct _MwBox* MwBox;
typedef struct _MwSubWindow* MwSubWindow;
typedef struct _MwTab* MwTab;
typedef struct _MwTable* MwTable;
+typedef struct _MwChartEntry MwChartEntry;
+typedef struct _MwChart* MwChart;
typedef struct _MwMouse MwMouse;
typedef struct _MwTTFInfo* MwTTFInfo;
#ifdef _MILSKO
@@ -247,6 +249,16 @@ struct _MwTab {
char** names;
};
+struct _MwChartEntry {
+ char* name;
+ char* color;
+ double value;
+};
+
+struct _MwChart {
+ MwChartEntry* entries;
+};
+
struct _MwMouse {
MwPoint point;
int button;
diff --git a/include/Mw/Widget/Chart.h b/include/Mw/Widget/Chart.h
index 6ab404b2a..d0957a2b2 100644
--- a/include/Mw/Widget/Chart.h
+++ b/include/Mw/Widget/Chart.h
@@ -17,6 +17,39 @@ extern "C" {
*/
MWDECL MwClass MwChartClass;
+/*!
+ * @brief Adds the entry to the chart
+ * @param handle Widget
+ * @param index Index
+ * @param text Text
+ * @param value Value
+ * @return Index
+ */
+MwInline int MwChartAdd(MwWidget handle, int index, const char* text, double value, const char* color) {
+ int out;
+
+ MwVaWidgetExecute(handle, "mwChartAdd", (void*)&out, index, text, value, color);
+
+ return out;
+}
+
+/*!
+ * @brief Deletes item from the chart
+ * @param handle Widget
+ * @param index Index
+ */
+MwInline void MwChartDelete(MwWidget handle, int index) {
+ MwVaWidgetExecute(handle, "mwChartDelete", NULL, index);
+}
+
+/*!
+ * @brief Resets the chart
+ * @param handle Widget
+ */
+MwInline void MwChartReset(MwWidget handle) {
+ MwVaWidgetExecute(handle, "mwChartReset", NULL);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/include/Mw/Widget/ComboBox.h b/include/Mw/Widget/ComboBox.h
index 7b2dc2fca..fd5c3430d 100644
--- a/include/Mw/Widget/ComboBox.h
+++ b/include/Mw/Widget/ComboBox.h
@@ -41,6 +41,23 @@ MwInline const char* MwComboBoxGet(MwWidget handle, int index) {
return text;
}
+/*!
+ * @brief Deletes the entry from combobox
+ * @param handle Widget
+ * @param index Index
+ */
+MwInline void MwComboBoxDelete(MwWidget handle, int index) {
+ MwVaWidgetExecute(handle, "mwComboBoxDelete", NULL, index);
+}
+
+/*!
+ * @brief Resets the combobox
+ * @param handle Widget
+ */
+MwInline void MwComboBoxReset(MwWidget handle) {
+ MwVaWidgetExecute(handle, "mwComboBoxReset", NULL);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/milsko.xml b/milsko.xml
index 573b84d2d..30efce111 100644
--- a/milsko.xml
+++ b/milsko.xml
@@ -1,10 +1,11 @@
@@ -228,6 +230,9 @@
0
+
+ 0
+
1
@@ -649,6 +654,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -879,9 +907,26 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/core.c b/src/core.c
index 481fa340f..2982c1ed9 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 bbd02642b..5cbfd22b0 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -101,22 +101,67 @@ MwLLColor MwLightenColor(MwWidget handle, MwLLColor color, int r, int g, int b)
void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) {
MwPoint p[4];
+ MwRect r = *rect;
- p[0].x = rect->x;
- p[0].y = rect->y;
+ if(r.width < 0) {
+ r.width *= -1;
+ r.x -= r.width;
+ }
- p[1].x = rect->x + rect->width;
- p[1].y = rect->y;
+ if(r.height < 0) {
+ r.height *= -1;
+ r.y -= r.height;
+ }
- p[2].x = rect->x + rect->width;
- p[2].y = rect->y + rect->height;
+ p[0].x = r.x;
+ p[0].y = r.y;
- p[3].x = rect->x;
- p[3].y = rect->y + rect->height;
+ p[1].x = r.x + r.width;
+ p[1].y = r.y;
+
+ p[2].x = r.x + r.width;
+ p[2].y = r.y + r.height;
+
+ p[3].x = r.x;
+ p[3].y = r.y + r.height;
MwLLPolygon(handle->lowlevel, p, 4, color);
}
+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;
+ }
+
+ p[0].x = r.x;
+ p[0].y = r.y;
+
+ p[1].x = r.x + r.width;
+ p[1].y = r.y;
+
+ p[2].x = r.x + r.width;
+ p[2].y = r.y + r.height;
+
+ p[3].x = r.x;
+ p[3].y = r.y + r.height;
+
+ p[4] = p[0];
+
+ MwLLLine(handle->lowlevel, &p[0], color);
+ MwLLLine(handle->lowlevel, &p[1], color);
+ MwLLLine(handle->lowlevel, &p[2], color);
+ MwLLLine(handle->lowlevel, &p[3], color);
+}
+
void MwDrawRectFading(MwWidget handle, MwRect* rect, MwLLColor color) {
MwLLPixmap pixmap;
int y;
diff --git a/src/widget/chart.c b/src/widget/chart.c
index 46f248ef7..b01451383 100644
--- a/src/widget/chart.c
+++ b/src/widget/chart.c
@@ -1,12 +1,62 @@
#include
+#include "../../external/stb_ds.h"
+
+static const char* palette0[] = {
+ "#800",
+ "#080",
+ "#880",
+ "#008",
+ "#808",
+ "#088",
+ "#888",
+ "#f00",
+ "#0f0",
+ "#ff0",
+ "#00f",
+ "#f0f",
+ "#0ff",
+ "#fff",
+ NULL};
+
static int wcreate(MwWidget handle) {
+ MwChart c = malloc(sizeof(*c));
+ memset(c, 0, sizeof(*c));
+
+ handle->internal = c;
+
+ MwSetDefault(handle);
+
return 0;
}
+static void destroy(MwWidget handle) {
+ MwChartReset(handle);
+ free(handle->internal);
+}
+
static void draw(MwWidget handle) {
- MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
- MwRect r;
+ MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
+ MwLLColor border = MwParseColor(handle, MwGetText(handle, MwNforeground));
+ MwRect r;
+ MwChart c = handle->internal;
+ int i;
+ const char** colors = palette0;
+ int n;
+ int gap;
+ int width;
+ MwRect node;
+ double min = 0xffffffff;
+ double max = -0xffffffff;
+ int space = MwTextHeight(handle, NULL, "M");
+ MwPoint p[2];
+
+ 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;
+ }
r.x = 0;
r.y = 0;
@@ -14,31 +64,144 @@ static void draw(MwWidget handle) {
r.height = MwGetInteger(handle, MwNheight);
MwDrawRect(handle, &r, base);
+ if(min > 0) {
+ min = 0;
+ } else if(min < 0) {
+ min -= r.height / 10;
+ }
+
+ node.x = 16;
+ node.y = 0;
+
+ width = (r.width - node.x) * 2 / (arrlen(c->entries) * 3 + 1);
+ gap = width / 2;
+
+ p[0].x = node.x;
+ p[0].y = r.height - space;
+
+ p[1].x = node.x + (width + gap) * arrlen(c->entries) + gap;
+ p[1].y = p[0].y;
+ MwLLLine(handle->lowlevel, &p[0], border);
+
+ 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);
+
+ p[0].x = node.x;
+ p[0].y = 0;
+
+ p[1].x = node.x;
+ p[1].y = r.height - space;
+ MwLLLine(handle->lowlevel, &p[0], 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);
+
+ node.x += gap;
+
+ 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));
+
+ MwDrawRect(handle, &node, color);
+ MwDrawRectLine(handle, &node, 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(color);
+ }
+
+ MwLLFreeColor(border);
MwLLFreeColor(base);
}
static void prop_change(MwWidget handle, const char* key) {
- if(strcmp(key, MwNhour) == 0 || strcmp(key, MwNminute) == 0 || strcmp(key, MwNsecond) == 0) MwForceRender(handle);
+ if(strcmp(key, MwNtype) == 0) MwForceRender(handle);
+}
+
+static int mwChartAddImpl(MwWidget handle, int index, const char* text, double value, const char* color) {
+ MwChart c = handle->internal;
+ MwChartEntry e;
+
+ if(index == -1) index = arrlen(c->entries);
+
+ e.name = MwStringDuplicate(text);
+ e.color = color == NULL ? NULL : MwStringDuplicate(color);
+ e.value = value;
+
+ arrins(c->entries, index, e);
+
+ MwForceRender(handle);
+
+ return index;
+}
+
+static void mwChartDeleteImpl(MwWidget handle, int index) {
+ MwChart c = handle->internal;
+
+ if(index == -1) index = arrlen(c->entries) - 1;
+
+ free(c->entries[index].name);
+ if(c->entries[index].color != NULL) free(c->entries[index].color);
+ arrdel(c->entries, index);
+
+ MwForceRender(handle);
+}
+
+static void mwChartResetImpl(MwWidget handle) {
+ MwChart c = handle->internal;
+ int i;
+
+ for(i = 0; i < arrlen(c->entries); i++) {
+ free(c->entries[i].name);
+ if(c->entries[i].color != NULL) free(c->entries[i].color);
+ }
+ arrfree(c->entries);
+
+ MwForceRender(handle);
+}
+
+static void func_handler(MwWidget handle, const char* name, void* out, va_list va) {
+ if(strcmp(name, "mwChartAdd") == 0) {
+ int index = va_arg(va, int);
+ const char* text = va_arg(va, const char*);
+ double value = va_arg(va, double);
+ const char* color = va_arg(va, const char*);
+ *(int*)out = mwChartAddImpl(handle, index, text, value, color);
+ }
+ if(strcmp(name, "mwChartDelete") == 0) {
+ int index = va_arg(va, int);
+ mwChartDeleteImpl(handle, index);
+ }
+ if(strcmp(name, "mwChartReset") == 0) {
+ mwChartResetImpl(handle);
+ }
}
MwClassRec MwChartClassRec = {
- wcreate, /* create */
- NULL, /* destroy */
- draw, /* draw */
- NULL, /* click */
- NULL, /* parent_resize */
- prop_change, /* prop_change */
- NULL, /* mouse_move */
- NULL, /* mouse_up */
- NULL, /* mouse_down */
- NULL, /* key */
- NULL, /* execute */
- NULL, /* tick */
- NULL, /* resize */
- NULL, /* children_update */
- NULL, /* children_prop_change */
- NULL, /* clipboard */
- NULL, /* props_change */
+ wcreate, /* create */
+ destroy, /* destroy */
+ draw, /* draw */
+ NULL, /* click */
+ NULL, /* parent_resize */
+ prop_change, /* prop_change */
+ NULL, /* mouse_move */
+ NULL, /* mouse_up */
+ NULL, /* mouse_down */
+ NULL, /* key */
+ func_handler, /* execute */
+ NULL, /* tick */
+ MwForceRender, /* resize */
+ NULL, /* children_update */
+ NULL, /* children_prop_change */
+ NULL, /* clipboard */
+ NULL, /* props_change */
NULL,
NULL,
NULL};
diff --git a/src/widget/combobox.c b/src/widget/combobox.c
index e53647dde..5502a0702 100644
--- a/src/widget/combobox.c
+++ b/src/widget/combobox.c
@@ -20,12 +20,8 @@ static int wcreate(MwWidget handle) {
static void destroy(MwWidget handle) {
MwComboBox cb = handle->internal;
- int i;
- for(i = 0; i < arrlen(cb->list); i++) {
- free(cb->list[i]);
- }
- arrfree(cb->list);
+ MwComboBoxReset(handle);
free(handle->internal);
}
@@ -145,6 +141,13 @@ static void prop_change(MwWidget handle, const char* prop) {
}
}
+static void parent_resize(MwWidget handle) {
+ MwComboBox cb = handle->internal;
+ if(cb->opened) {
+ click(handle);
+ }
+}
+
static void mwComboBoxAddImpl(MwWidget handle, int index, const char* text) {
MwComboBox cb = handle->internal;
char* t = MwStringDuplicate(text);
@@ -153,7 +156,7 @@ static void mwComboBoxAddImpl(MwWidget handle, int index, const char* text) {
arrins(cb->list, index, t);
- if(index <= MwGetInteger(handle, MwNvalue)) MwForceRender(handle);
+ MwForceRender(handle);
}
static const char* mwComboBoxGetImpl(MwWidget handle, int index) {
@@ -162,6 +165,29 @@ static const char* mwComboBoxGetImpl(MwWidget handle, int index) {
return cb->list[index];
}
+static void mwComboBoxDeleteImpl(MwWidget handle, int index) {
+ MwComboBox cb = handle->internal;
+ int n = MwGetInteger(handle, MwNvalue);
+
+ free(cb->list[index]);
+ arrdel(cb->list, index);
+
+ if(index < n && n > 0) {
+ MwSetInteger(handle, MwNvalue, n - 1);
+ }
+
+ MwForceRender(handle);
+}
+
+static void mwComboBoxResetImpl(MwWidget handle) {
+ MwComboBox cb = handle->internal;
+
+ arrfree(cb->list);
+ MwSetInteger(handle, MwNvalue, 0);
+
+ MwForceRender(handle);
+}
+
static void func_handler(MwWidget handle, const char* name, void* out, va_list va) {
if(strcmp(name, "mwComboBoxAdd") == 0) {
int index = va_arg(va, int);
@@ -172,12 +198,12 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v
int index = va_arg(va, int);
*(const char**)out = mwComboBoxGetImpl(handle, index);
}
-}
-
-static void parent_resize(MwWidget handle) {
- MwComboBox cb = handle->internal;
- if(cb->opened) {
- click(handle);
+ if(strcmp(name, "mwComboBoxDelete") == 0) {
+ int index = va_arg(va, int);
+ mwComboBoxDeleteImpl(handle, index);
+ }
+ if(strcmp(name, "mwComboBoxReset") == 0) {
+ mwComboBoxResetImpl(handle);
}
}
diff --git a/src/widget/treeview.c b/src/widget/treeview.c
index 3fba309e5..d07d355e5 100644
--- a/src/widget/treeview.c
+++ b/src/widget/treeview.c
@@ -317,6 +317,7 @@ static int wcreate(MwWidget handle) {
}
static void destroy(MwWidget handle) {
+ MwTreeViewReset(handle);
free(handle->internal);
}
diff --git a/src/widget/window.c b/src/widget/window.c
index 3d0afe254..9ea16a304 100644
--- a/src/widget/window.c
+++ b/src/widget/window.c
@@ -51,6 +51,7 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v
mwWindowShouldCloseImpl(handle, out);
}
}
+
MwClassRec MwWindowClassRec = {
wcreate, /* create */
NULL, /* destroy */