add seven segment

This commit is contained in:
NishiOwO
2025-12-21 14:38:07 +09:00
parent f09960195f
commit 91d9677bf7
11 changed files with 376 additions and 43 deletions

1
.gitignore vendored
View File

@@ -11,4 +11,5 @@ examples/*/*.exe
*.lib
*.a
/Makefile
/build
compile_flags.txt

View File

@@ -0,0 +1,22 @@
#include <Mw/Milsko.h>
int main() {
MwWidget wnd, label;
int W = 480, H = 40;
MwLibraryInit();
wnd = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, W, H,
MwNtitle, "seven segment",
NULL);
label = MwVaCreateWidget(MwLabelClass, "label", wnd, 0, 0, W, H,
MwNtext, " 123456:78.90 abcdef",
MwNsevenSegment, 1,
MwNalignment, MwALIGNMENT_BEGINNING,
NULL);
MwLabelSetSevenSegment(label, 0, (1 << 0) | (1 << 3) | (1 << 6));
MwLoop(wnd);
}

View File

@@ -36,6 +36,7 @@
#define MwNfixedSize "IfixedSize"
#define MwNmargin "Imargin"
#define MwNbitmapFont "IbitmapFont"
#define MwNsevenSegment "IsevenSegment"
#define MwNtitle "Stitle"
#define MwNtext "Stext"

View File

@@ -20,6 +20,9 @@ typedef struct _MwViewport* MwViewport;
typedef struct _MwListBox* MwListBox;
typedef struct _MwComboBox* MwComboBox;
typedef struct _MwTreeView* MwTreeView;
typedef struct _MwScrollBar* MwScrollBar;
typedef struct _MwLabel* MwLabel;
typedef struct _MwLabelSegment MwLabelSegment;
typedef struct _MwListBoxEntry MwListBoxEntry;
typedef struct _MwTreeViewEntry MwTreeViewEntry;
typedef struct _MwDirectoryEntry MwDirectoryEntry;
@@ -164,6 +167,21 @@ struct _MwTreeView {
MwPoint pressed;
};
struct _MwScrollBar {
MwPoint point;
int drag;
int pos;
};
struct _MwLabel {
MwLabelSegment* segment;
};
struct _MwLabelSegment {
int key;
unsigned char value;
};
struct _MwDirectoryEntry {
char* name;
int type;

View File

@@ -17,6 +17,17 @@ extern "C" {
*/
MWDECL MwClass MwLabelClass;
/*!
* @brief Sets the custom data for seven segment
* @param handle Widget
* @param index Index
* @param data Data, `GFEDCBA` as 7-bit value
* @note See https://en.wikipedia.org/wiki/File:7_Segment_Display_with_Labeled_Segments.svg for what alphabets mean here
* */
MwInline void MwLabelSetSevenSegment(MwWidget handle, int index, int data) {
MwVaWidgetExecute(handle, "mwLabelSetSevenSegment", NULL, index, data);
}
#ifdef __cplusplus
}
#endif

View File

@@ -89,6 +89,7 @@
<integer name="fixedSize" />
<integer name="margin" />
<integer name="bitmapFont" />
<integer name="sevenSegment" />
<string name="title" />
<string name="text" />
@@ -536,7 +537,16 @@
<property name="text" />
<property name="alignment" />
<property name="bold" />
<property name="sevenSegment" />
</properties>
<functions>
<function name="SetSevenSegment">
<arguments>
<integer name="index" />
<integer name="data" />
</arguments>
</function>
</functions>
</widget>
<widget name="ListBox">
<properties>

View File

@@ -2,6 +2,6 @@ add_incdir("-I/usr/X11R7/include -I/usr/pkg/include");
add_libdir(
"-L/usr/X11R7/lib -Wl,-R/usr/X11R7/lib -L/usr/pkg/lib -Wl,-R/usr/pkg/lib");
use_backend("x11");
add_libs("pthread");
add_libs("-lpthread");
1;

View File

@@ -115,6 +115,7 @@ new_example("examples/basic/combobox");
new_example("examples/basic/treeview");
new_example("examples/basic/box");
new_example("examples/basic/clipboard");
new_example("examples/basic/sevensegment");
if (param_get("opengl")) {
new_example("examples/gldemos/boing", $gl_libs);

View File

@@ -1,5 +1,7 @@
#include <Mw/Milsko.h>
#include "../../external/stb_ds.h"
static int create(MwWidget handle) {
MwSetDefault(handle);

View File

@@ -1,13 +1,119 @@
#include <Mw/Milsko.h>
#include "../../external/stb_ds.h"
#define ShortOne 5
#define LongOne 10
#define Spacing 2
static int create(MwWidget handle) {
MwLabel lab = malloc(sizeof(*lab));
lab->segment = NULL;
handle->internal = lab;
MwSetDefault(handle);
MwSetInteger(handle, MwNalignment, MwALIGNMENT_CENTER);
MwSetInteger(handle, MwNbold, 0);
MwSetInteger(handle, MwNsevenSegment, 0);
return 0;
}
static void destroy(MwWidget handle) {
MwLabel lab = handle->internal;
hmfree(lab->segment);
free(handle->internal);
}
static void draw_v(unsigned char* raw, int x, int y, int stride, MwLLColor text) {
int cy, cx, b;
for(cy = y; cy < y + LongOne; cy++) {
for(cx = x; cx < x + ShortOne; cx++) {
unsigned char* px = &raw[(cy * stride + cx) * 4];
px[0] = text->common.red;
px[1] = text->common.green;
px[2] = text->common.blue;
px[3] = 255;
}
}
b = y - (ShortOne - 1) / 2;
for(cy = b; cy < b + (ShortOne - 1) / 2; cy++) {
int w = (cy - b) * 2 + 1;
int b2 = x + (ShortOne - w) / 2;
for(cx = b2; cx < b2 + w; cx++) {
unsigned char* px;
px = &raw[(cy * stride + cx) * 4];
px[0] = text->common.red;
px[1] = text->common.green;
px[2] = text->common.blue;
px[3] = 255;
}
}
b = y + LongOne;
for(cy = b; cy < b + (ShortOne - 1) / 2; cy++) {
int w = ((ShortOne - 1) / 2 - 1 - (cy - b)) * 2 + 1;
int b2 = x + (ShortOne - w) / 2;
for(cx = b2; cx < b2 + w; cx++) {
unsigned char* px;
px = &raw[(cy * stride + cx) * 4];
px[0] = text->common.red;
px[1] = text->common.green;
px[2] = text->common.blue;
px[3] = 255;
}
}
}
static void draw_h(unsigned char* raw, int x, int y, int stride, MwLLColor text) {
int cy, cx, b;
for(cx = x; cx < x + LongOne; cx++) {
for(cy = y; cy < y + ShortOne; cy++) {
unsigned char* px = &raw[(cy * stride + cx) * 4];
px[0] = text->common.red;
px[1] = text->common.green;
px[2] = text->common.blue;
px[3] = 255;
}
}
b = x - (ShortOne - 1) / 2;
for(cx = b; cx < b + (ShortOne - 1) / 2; cx++) {
int w = (cx - b) * 2 + 1;
int b2 = y + (ShortOne - w) / 2;
for(cy = b2; cy < b2 + w; cy++) {
unsigned char* px;
px = &raw[(cy * stride + cx) * 4];
px[0] = text->common.red;
px[1] = text->common.green;
px[2] = text->common.blue;
px[3] = 255;
}
}
b = x + LongOne;
for(cx = b; cx < b + (ShortOne - 1) / 2; cx++) {
int w = ((ShortOne - 1) / 2 - 1 - (cx - b)) * 2 + 1;
int b2 = y + (ShortOne - w) / 2;
for(cy = b2; cy < b2 + w; cy++) {
unsigned char* px;
px = &raw[(cy * stride + cx) * 4];
px[0] = text->common.red;
px[1] = text->common.green;
px[2] = text->common.blue;
px[3] = 255;
}
}
}
static void draw(MwWidget handle) {
MwRect r;
MwPoint p;
@@ -16,6 +122,7 @@ static void draw(MwWidget handle) {
int align;
const char* str = MwGetText(handle, MwNtext);
MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap);
MwLabel lab = handle->internal;
if(str == NULL) str = "";
@@ -28,40 +135,206 @@ static void draw(MwWidget handle) {
if(bgpx != NULL) MwLLDrawPixmap(handle->lowlevel, &r, bgpx);
align = MwGetInteger(handle, MwNalignment);
if(align == MwALIGNMENT_CENTER) {
p.x = r.width / 2;
} else if(align == MwALIGNMENT_BEGINNING) {
p.x = MwTextWidth(handle, str) / 2;
} else if(align == MwALIGNMENT_END) {
p.x = r.width - MwTextWidth(handle, str) / 2;
if(MwGetInteger(handle, MwNsevenSegment)) {
MwLLPixmap px;
unsigned char* raw;
int w = 0, h = ShortOne * 3 + LongOne * 2, i;
int x = 0;
/* so - this mode cannot do unicode.
* but you wouldn't show unicode on 7 segment anyways
*/
/* L
* S <--->
*
* S
* ^
* |
* L |
* |
* v
*/
for(i = 0; (hmgeti(lab->segment, i) != -1) || str[i] != 0; i++) {
if(i > 0 && ((hmgeti(lab->segment, i) != -1) || str[i] != '.')) w += Spacing;
if(hmgeti(lab->segment, i) != -1 || ('0' <= str[i] && str[i] <= '9') || ('A' <= str[i] && str[i] <= 'F') || ('a' <= str[i] && str[i] <= 'f')) {
w += LongOne + ShortOne * 2;
} else if(str[i] == ':' || str[i] == ' ') {
w += ShortOne;
}
}
raw = malloc(w * h * 4);
memset(raw, 0, w * h * 4);
for(i = 0; (hmgeti(lab->segment, i) != -1) || str[i] != 0; i++) {
if((hmgeti(lab->segment, i) != -1) || ('0' <= str[i] && str[i] <= '9') || ('A' <= str[i] && str[i] <= 'F') || ('a' <= str[i] && str[i] <= 'f')) {
int la = 0, lb = 0, lc = 0, ld = 0, le = 0, lf = 0, lg = 0;
/* https://en.wikipedia.org/wiki/File:7_Segment_Display_with_Labeled_Segments.svg */
if(hmgeti(lab->segment, i) != -1) {
unsigned char c = hmget(lab->segment, i);
if(c & (1 << 0)) la = 1;
if(c & (1 << 1)) lb = 1;
if(c & (1 << 2)) lc = 1;
if(c & (1 << 3)) ld = 1;
if(c & (1 << 4)) le = 1;
if(c & (1 << 5)) lf = 1;
if(c & (1 << 6)) lg = 1;
} else {
if(str[i] == '0') {
la = lb = lc = ld = le = lf = 1;
} else if(str[i] == '1') {
lb = lc = 1;
} else if(str[i] == '2') {
la = lb = ld = le = lg = 1;
} else if(str[i] == '3') {
la = lb = lc = ld = lg = 1;
} else if(str[i] == '4') {
lb = lc = lf = lg = 1;
} else if(str[i] == '5') {
la = lc = ld = lf = lg = 1;
} else if(str[i] == '6') {
la = lc = ld = le = lf = lg = 1;
} else if(str[i] == '7') {
la = lb = lc = 1;
} else if(str[i] == '8') {
la = lb = lc = ld = le = lf = lg = 1;
} else if(str[i] == '9') {
la = lb = lc = ld = lf = lg = 1;
} else if(str[i] == 'A' || str[i] == 'a') {
la = lb = lc = le = lf = lg = 1;
} else if(str[i] == 'B' || str[i] == 'b') {
lc = ld = le = lf = lg = 1;
} else if(str[i] == 'C' || str[i] == 'c') {
ld = le = lg = 1;
} else if(str[i] == 'D' || str[i] == 'd') {
lb = lc = ld = le = lg = 1;
} else if(str[i] == 'E' || str[i] == 'e') {
la = ld = le = lf = lg = 1;
} else if(str[i] == 'F' || str[i] == 'f') {
la = le = lf = lg = 1;
}
}
if(la) draw_h(raw, x + ShortOne, 0, w, text);
if(lb) draw_v(raw, x + ShortOne + LongOne, ShortOne, w, text);
if(lc) draw_v(raw, x + ShortOne + LongOne, ShortOne * 2 + LongOne, w, text);
if(ld) draw_h(raw, x + ShortOne, ShortOne * 2 + LongOne * 2, w, text);
if(le) draw_v(raw, x, ShortOne * 2 + LongOne, w, text);
if(lf) draw_v(raw, x, ShortOne, w, text);
if(lg) draw_h(raw, x + ShortOne, ShortOne + LongOne, w, text);
x += LongOne + ShortOne * 2;
} else if(str[i] == ':') {
int cy, cx;
for(cy = 1; cy < h - 1; cy++) {
int c = (LongOne - ShortOne) / 2 + ShortOne;
int c1 = (c <= cy && cy <= (c + ShortOne)) ? 1 : 0;
int c2 = ((ShortOne + LongOne + c) <= cy && cy <= (ShortOne + LongOne + c + ShortOne)) ? 1 : 0;
if(c1 || c2) {
for(cx = x; cx < x + ShortOne; cx++) {
unsigned char* px = &raw[(cy * w + cx) * 4];
px[0] = text->common.red;
px[1] = text->common.green;
px[2] = text->common.blue;
px[3] = 255;
}
}
}
x += ShortOne;
} else if(str[i] == ' ') {
x += ShortOne;
} else if(str[i] == '.') {
int cy, cx;
for(cy = h - (ShortOne - 1) / 2 - 1; cy < h; cy++) {
for(cx = x - Spacing - (ShortOne - 1) / 2 - 1; cx < (x - Spacing); cx++) {
unsigned char* px = &raw[(cy * w + cx) * 4];
px[0] = text->common.red;
px[1] = text->common.green;
px[2] = text->common.blue;
px[3] = 255;
}
}
continue;
}
x += Spacing;
}
px = MwLoadRaw(handle, raw, w, h);
r.y = 0;
r.height = h;
if(align == MwALIGNMENT_CENTER) {
r.x = (r.width - w) / 2;
} else if(align == MwALIGNMENT_BEGINNING) {
r.x = 0;
} else if(align == MwALIGNMENT_END) {
r.x = r.width - w;
}
r.width = w;
MwLLDrawPixmap(handle->lowlevel, &r, px);
MwLLDestroyPixmap(px);
} else {
if(align == MwALIGNMENT_CENTER) {
p.x = r.width / 2;
} else if(align == MwALIGNMENT_BEGINNING) {
p.x = MwTextWidth(handle, str) / 2;
} else if(align == MwALIGNMENT_END) {
p.x = r.width - MwTextWidth(handle, str) / 2;
}
p.y = r.height / 2;
MwDrawText(handle, &p, str, MwGetInteger(handle, MwNbold), MwALIGNMENT_CENTER, text);
}
p.y = r.height / 2;
MwDrawText(handle, &p, str, MwGetInteger(handle, MwNbold), MwALIGNMENT_CENTER, text);
MwLLFreeColor(text);
MwLLFreeColor(base);
}
static void prop_change(MwWidget handle, const char* key) {
if(strcmp(key, MwNtext) == 0 || strcmp(key, MwNalignment) == 0) MwForceRender(handle);
if(strcmp(key, MwNtext) == 0 || strcmp(key, MwNalignment) == 0 || strcmp(key, MwNsevenSegment) == 0) MwForceRender(handle);
}
static void mwLabelSetSevenSegmentImpl(MwWidget handle, int index, unsigned char data) {
MwLabel lab = handle->internal;
hmput(lab->segment, index, data);
}
static void func_handler(MwWidget handle, const char* name, void* out, va_list va) {
(void)out;
if(strcmp(name, "mwLabelSetSevenSegment") == 0) {
int index = va_arg(va, int);
int data = va_arg(va, int);
mwLabelSetSevenSegmentImpl(handle, index, data);
}
}
MwClassRec MwLabelClassRec = {
create, /* 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 */
create, /* 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 */
NULL, /* resize */
NULL, /* children_update */
NULL, /* children_prop_change */
NULL,
NULL,
NULL,

View File

@@ -1,13 +1,7 @@
#include <Mw/Milsko.h>
typedef struct scrollbar {
MwPoint point;
int drag;
int pos;
} scrollbar_t;
static int create(MwWidget handle) {
scrollbar_t* scr = malloc(sizeof(*scr));
MwScrollBar scr = malloc(sizeof(*scr));
handle->internal = scr;
@@ -60,10 +54,10 @@ static void add_value(MwWidget handle, int mul) {
}
static void draw(MwWidget handle) {
MwRect r, rt, rbar;
MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
MwLLColor dark = MwLightenColor(handle, base, -64, -64, -64);
scrollbar_t* scr = handle->internal;
MwRect r, rt, rbar;
MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
MwLLColor dark = MwLightenColor(handle, base, -64, -64, -64);
MwScrollBar scr = handle->internal;
int or ;
int uy, dy, ux, dx;
MwLLPixmap bgpx = MwGetVoid(handle, MwNbackgroundPixmap);
@@ -144,8 +138,8 @@ static void draw(MwWidget handle) {
}
static void mouse_move(MwWidget handle) {
int or = MwGetInteger(handle, MwNorientation);
scrollbar_t* scr = handle->internal;
int or = MwGetInteger(handle, MwNorientation);
MwScrollBar scr = handle->internal;
if(!handle->pressed) return;
@@ -172,11 +166,11 @@ static void mouse_move(MwWidget handle) {
}
static void mouse_down(MwWidget handle, void* ptr) {
int ww = MwGetInteger(handle, MwNwidth);
int wh = MwGetInteger(handle, MwNheight);
int or = MwGetInteger(handle, MwNorientation);
scrollbar_t* scr = handle->internal;
MwLLMouse* m = ptr;
int ww = MwGetInteger(handle, MwNwidth);
int wh = MwGetInteger(handle, MwNheight);
int or = MwGetInteger(handle, MwNorientation);
MwScrollBar scr = handle->internal;
MwLLMouse* m = ptr;
if(m->button == MwLLMouseWheelUp) {
int min = MwGetInteger(handle, MwNminValue);