Üdvözöl az SMGUI, a státusz vezérelt grafikus felhasználói felület eszköztár kézikönyve.
A státusz-vezérelt UI alapelve az, hogy már úgyis megvannak a változóid, szóval elég csak hivatkozni azokra egy űrlapból, nem kell sem visszahívás sem azonnali kódlekezlés, csupán csak azon már meglévő változók értékei vezérlik a GUI megjelenítését.
TIPP
Ez a kézikönyv internet nélkül is használható. A jobb-klikk menüben válaszd az "Oldal mentése" menüpontot.
Ez a függvénykönyvtár mindent tartalmaz egyetlen fejlécfájlban, és használható mind fejléc, mind implementációs módban. Alapból a fejléc-mód van használatban, ami lehetővé teszi, hogy más fejlécekből is behúzásra kerüljön, és nem tartalmazza ilyenkor az implementációt. Az implementációs módhoz pontosan egyetlen egy .c/.cpp forrásban meg kell adni az UI_IMPLEMENTATION előfordító define-t pontosan ezen fejléc fájl include-ja előtt.
Az alap függvénykönyvtár platform és motor független. Bármilyen motorral és fontmeghajtóval képes működni, ehhez csak be kell húzni a megfelelő fejlécfájlt még az ui.h előtt. Például:
1
2
3
4
#include "ui_glfw.h"
#include "ui_psf2.h"
#define UI_IMPLEMENTATION
#include "ui.h"
A referencia implementáció GLFW3, SDL2/3 és X11 motorral érkezik; ami a fontokat illeti, van PC-Screen-Font (amit a Linux Console használ), illetve Scalable Screen Font (sokkal hatékonyabb, mint a TTF vagy OTF, és bármilyen font, bitmap, vektor vagy pixel font átkonvertálható SSFN-é).
Alapból - ha semmilyen másik modul nem lett előtte behúzva -, akkor az ui.h behúzza a GLFW3 motort és a PSF2 font meghajtót, valamint egy minimális, ékezetes betűk néküli ASCII font-ot is beágyaz (2080 bájt lefordítva).
Hacsak másképp nincs jelezve, minden függvény negatív hibakódot ad vissza.
Define | Leírás |
---|---|
UI_OK | Sikeres, nem volt hiba |
UI_ERR_BADINP | Hibás paraméter |
UI_ERR_BACKEND | Hiba a motor inicializálásánál |
UI_ERR_NOMEM | Memória foglalási hiba |
1
int ui_init(ui_t *ctx, int txtc, char **txtv, int w, int h, ui_image_t *icon);
Inicializálja az UI kontextust és ablakot nyit. A legelső sztringnek a txtv[] tömbben az ablak fejlécének kell lennie, a többi szabadon választható.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
txtc | Sztringek száma |
txtv | Lokalizációhoz sztringtömb |
w | Ablak szélessége |
h | Ablak magassága |
icon | Ablak ikonja kép (vagy NULL) |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
1
int ui_free(ui_t *ctx);
Bezárja az ablakot és felszabadítja a lefoglalt erőforrásokat.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
1
int ui_fullscreen(ui_t *ctx);
Váltogatja a kontextust teljesképernyős és ablakos mód között (inicializálást követően ablakos).
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
1
void *ui_getwindow(ui_t *ctx);
Amennyiben szükség lenne rá, ezzel a funkcióval lekérhető a motor által használt ablak objektum.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
Egy implementációfüggő objektumot ad vissza.
A program általános szerkezetének valami ilyesminek kell lennie:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* UI kontextus, ablakonként egy */
ui_t ctx;
/* lokalizációhoz sztringtömb */
enum { WINDOW_TITLE, HELLO_WORLD };
char *english[] = { "Window title", "Hello World!" };
/* ablak megnyitása és kontextus inicializálása */
ui_init(&ctx, 2, english, 640, 480, NULL);
/* a fő ciklus */
do {
/* tedd, amit tennél, rajzolj, amit akarsz */
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* ... */
/* események lekérése és UI réteg megjelenítése a kívánt űrlappal */
/* ha ez NULL-t ad vissza, ki kell lépni a ciklusból */
if(!(evt = ui_event(&ctx, form))) break;
/* események feldolgozása */
switch(evt->type) {
case UI_EVT_KEY: /* billentyűleütés */ break;
case UI_EVT_MOUSE: /* egérgomb esemény */ break;
case UI_EVT_GAMEPAD: /* gamepad esemény */ break;
/* ... */
}
} while(1);
/* ablak bezárása */
ui_free(&ctx);
Az SMGUI támogatja a többnyelvűséget, de ehhez a sztringeket össze kell gyűjteni egy tömbbe. Javaslom egy enum létrehozását is az indexekhez.
char *dictionary[];
Ezt a tömböt át kell adni, amikor az ablakot megnyitjuk. A legelső sztringnek a tömbben az ablak fejlécének kell lennie, a többi szabadon választható.
1
int ui_settxt(ui_t *ctx, char **txtv);
A nyelv futás közben bármikor megváltoztatható. Az új txtv[] tömbnek pontosan annyi elemének kell lennie, mint ahány elemű az inicializálásnál átadott tömb volt.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
txtv | Sztringtömb |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
Az SMGUI tetszőleges fontokat képes támogatni, és mindjárt kétféle referencia implementációval érkezik, ui_psf2.h (alapértelmezett, egyszerű bitmap font) és ui_ssfn.h (vektor, átméretezett bitmap és pixelmap fontok), de saját is egyszerűen hozzáadható.
1
int ui_fonthook(ui_t *ctx, ui_font_bbox bbox, ui_font_draw draw);
Egy bármilyen font formátum támogatásához két visszacsatolás megadására van szükség a kontextusban.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
bbox | Méretfunkció |
draw | Kirajzolófunkció |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
A visszacsatolások:
1
2
typedef int (*ui_font_bbox)(void *fnt, char *str, char *end,
int *w, int *h, int *l, int *t);
Megméri a sztringet, és a szélességét a w, a magasságát a h változóban adja vissza pixelben. Ha van baloldali átfedés, akkor az az l-be kerül. Az alapvonal felülről számítva a t-be kerül (mind az l és a t lehet NULL, ha nincs ezekre szükség). A sztring egy nullával lezárt UTF-8 sztring str-ben, de ha az end nem NULL, akkor ott véget ér.
1
2
3
typedef int (*ui_font_draw)(void *fnt, char *str, char *end,
uint8_t *dst, uint32_t color, int x, int y, int l, int t, int p,
int cx0, int cy0, int cx1, int cy1);
Kirajzolja a sztringet x, y koordinátákra (l baloldali átfedéssel és t alapvonalra) a dst pixelbufferre, aminek egy rasztersora p bájtnyi. Nagyon fontos, hogy a megadott cx0, cy0 és cx1, cy1 koordináták közötti crop régión kívül nem szabad semmit módosítania. Az implementációspecifikus fnt hivatkozik a fontra, a szöveg színe color, a nullával lezárt UTF-8 sztring str-ben, de ha az end nem NULL, akkor ott véget ér.
FIGYELEM
Ez a funkció nem inicializálja a fontot, csak letárolja a mutatót, hogy átadja a visszacsatolásoknak. A font inicializálás és felszabadítás platform-specifikus és a hívó dolga (a PSF2 meghajtónak nincs ezekre szüksége).
1
int ui_font(ui_t *ctx, void *fnt);
Beállítja a használandó fontot.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
fnt | Használandó font |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
1
int ui_swcursor(ui_t *ctx, ui_image_t *cursor);
Kikapcsolja a hardveres egérmutatót és helyette egy képet rak ki szoftveresen.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
cursor | Mutató a kurzor képre |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
1
int ui_hwcursor(ui_t *ctx);
Kikapcsolja a szoftveres egérmutatót és engedélyezi a hardverest.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
Az SMGUI többféle színtémát is támogat, amik lényegében paletták. Minden palettaelem egy UI elem színének felel meg. Ezek sorrendben a következők:
1
int ui_theme(ui_t *ctx, uint32_t *theme);
Beállít egy tetszőleges színtémát. A theme[] tömbnek annyi eleműnek kell lennie, ahány UI szín van, lásd a fenti listát.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
theme | Mutató a palettára |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
Az SMGUI bőröket is támogat, amik lényegében képek, mindegyik az UI egy-egy elemének felel meg. Ezek sorrendben a következők:
1
int ui_skin(ui_t *ctx, ui_image_t *skin);
Betölt egy tetszőleges bőrt. A skin[] tömbnek annyi eleműnek kell lennie, ahány UI elem van, lásd a fenti listát.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
skin | Mutató a bőr képek tömbre |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
Ha az stb_image.h be lett húzva az ui.h előtt, akkor a következő függvény is használható, hogy egyetlen PNG képről töltse be az összes bőrképet:
1
int ui_pngskin(ui_t *ctx, uint8_t *png, int size);
Betölt egy tetszőleges bőrt egy csomagolt PNG fájlból.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
png | Mutató a PNG képre |
size | A PNG kép mérete bájtokban |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
A csomagolt PNG-ben kell lennie egy kommentnek, x, y, w, h ASCII decimális számokkal minden sorban, amik területeket jelölnek a képen. Ilyen csomagolt PNG előállítható például az sprpack program -cdt kapcsolóival:
sprpack -cdt bőr.png egér.png felugró_balfelső.png felugró_felsőközép.png ...
Minden UI elem PNG-jét fel kell sorolni, és pontosan abban a sorrendben, ahogy fentebb látszik, máskülönben a bőr PNG nem fog működni.
1
ui_event_t *ui_event(ui_t *ctx, ui_form_t *form);
Ez az SMGUI lelke, ez a függvény lekéri az eseményeket és hozzáad a megjelenítéshez egy UI réteget a megadott elrendezés szerint.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
form | Űrlap elrendezés |
Ha ki kell lépni a fő ciklusból, NULL-al tér vissza, egyébként egy esemény objektummal.
Ha az UI-tól függetlenül megváltozott az egyik változó, amire az átadott form hivatkozik, akkor meg kell hívni az ui_refresh() függvényt az ui_event() hívása előtt, hogy kikényszerítsünk egy újrarajzolást.
A visszaadott eseményt az evt->type alapján kell értelmezni, mivel a legtöbb eseménymező típusfüggő.
Ez akkor generálódik, ha egy egérgombot lenyomnak vagy felengednek.
Paraméter | Leírás |
---|---|
evt->type | UI_EVT_MOUSE |
evt->btn | Aktuális gombstátusz |
evt->x | Aktuális egér X pozíció |
evt->y | Aktuális egér Y pozíció |
A btn mező egy bitmaszkot tartalmaz, a következő értékekkel:
Define | Leírás |
---|---|
UI_BTN_L | Bal egérgomb |
UI_BTN_M | Középső egérgomb |
UI_BTN_R | Jobb egérgomb |
UI_BTN_U | Felfelegörgetés |
UI_BTN_D | Lefelegörgetés |
UI_BTN_A | Balragörgetés |
UI_BTN_B | Jobbragörgetés |
UI_BTN_RELEASE | Ha felengedés esemény |
Ha esemény nélkül van szükség az egér pozíciójára, akkor használható az
1
int ui_getmouse(ui_t *ctx, int *x, int *y);
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
x | Mutató az X pozíció tárolásához |
y | Mutató az Y pozíció tárolásához |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
Ez akkor generálódik, ha valamelyik gamepad státusza megváltozik.
Paraméter | Leírás |
---|---|
evt->type | UI_EVT_GAMEPAD |
evt->btn | Aktuális gombstátusz |
evt->x | Bal botkar X pozíció |
evt->y | Bal botkar Y pozíció |
evt->rx | Jobb botkar X pozíció |
evt->ry | Jobb botkar Y pozíció |
evt->key[0] | Gamepad indexe ha több is lenne |
A botkarok koordinátái előjelesek, és a -32768 .. +32768 tartományba esnek. A btn mező egy bitmaszkot tartalmaz, a következő értékekkel:
Define | Leírás |
---|---|
UI_BTN_A | Az 'A'/kereszt gomb státusza |
UI_BTN_B | Az 'B'/kör gomb státusza |
UI_BTN_X | Az 'X'/négyzet gomb státusza |
UI_BTN_Y | Az 'Y'/háromszög gomb státusza |
UI_BTN_L | DPad balra státusza |
UI_BTN_R | DPad jobbra státusza |
UI_BTN_U | DPad fel státusza |
UI_BTN_D | DPad le státusza |
UI_BTN_BA | Vissza gomb státusza |
UI_BTN_ST | Start gomb státusza |
UI_BTN_GU | Útmutató gomb státusza |
UI_BTN_LT | Balhüvelyk gomb státusza |
UI_BTN_RT | Jobbhüvelyk gomb státusza |
UI_BTN_LS | Balra shoulder gomb státusza |
UI_BTN_RS | Jobbra shoulder gomb státusza |
Ez akkor generálódik, ha egy billentyűt leütnek.
Paraméter | Leírás |
---|---|
evt->type | UI_EVT_KEY |
evt->btn | Módosítók státusza |
evt->key | Leütött gomb |
A visszaadott gomb egy UTF-8 karakter, vagy (speciális gombok esetén) egy érvénytelen UTF-8 szekvencia a gomb nevével. A megkülönböztetéshez meg kell nézni, hogy key[1] üres-e, és hogy a legmagasabb bit a key[0]-ban be van-e állítva (érvényes UTF-8) vagy sem (gombnév).
TIPP
Nincs gombleképezés, hogy megtudjuk, milyen kódot gerenál egy gomb, csak ki kell iratni a evt->key tartalmát.
A btn mező egy bitmaszkot tartalmaz, a következő értékekkel:
Define | Leírás |
---|---|
UI_BTN_SHIFT | Az egyik Shift le van nyomva |
UI_BTN_CONTROL | Az egyik Control le van nyomva |
UI_BTN_ALT | Az egyik Alt le van nyomva (jobboldalit hívják AltGr-nek) |
UI_BTN_GUI | Az egyik GUI le van nyomva |
A módosító gombok (LShift, RShift, LCtrl, RCtrl, LAlt, RAlt, LGui és RGui) esetén billentyűfelengedés esemény is generálódik, ahol a UI_BTN_RELEASE be van állítva. A többi gomb nem generál ilyen eseményt.
Ez akkor keletkezik, ha a felhasználó egy fájlt húz az ablakra.
Paraméter | Leírás |
---|---|
evt->type | UI_EVT_DROP |
evt->x | Aktuális egér X pozíció |
evt->y | Aktuális egér Y pozíció |
evt->fn | A fájl elérési útja |
Ez akkor generálódik, ha az ablakot átméretezik.
Paraméter | Leírás |
---|---|
evt->type | UI_EVT_RESIZE |
evt->x | Az új ablak szélesség |
evt->y | Az új ablak magasság |
A vágólap lekéréséhez (amikor olyan billentyűzet esemény érkezett, amiben a gomb Paste), a következő függvény hívható:
1
char *ui_getclipboard(ui_t *ctx);
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
NULL-t ad vissza, ha a vágólap üres, egyébként a vágólap tartalmát egy újonnan allokált bufferben. A hívó felelőssége a buffer felszabadítása, ha már nincs rá szükség.
A vágólap beállítására (amikor olyan billentyűzet esemény érkezett, amiben a gomb Cut vagy Copy), a következő függvény való:
1
char *ui_setclipboard(ui_t *ctx, char *str);
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
str | Vágólapra helyezendő sztring |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
Az SMGUI nem tartalmaz azonnali kódlekezlést, sem visszahívásokat. Elhelyett feltételezi, hogy már úgyis megvannak a változóid, és csak egy űrlapot kér, ami ezekre a változókra hivatkozik.
Az űrlap maga egy ui_form_t elemeket tartalmazó tömb, amiben a legutolsó elem típusa MINDIG UI_END. Néhány mező általános, mások típusspecifikusak. Az általános mezők a következők:
Paraméter | Leírás |
---|---|
form->ptr | Mutató az adatra |
form->type | Űrlapelem típusa |
form->align | Űrlapelem igazítása |
form->flags | Űrlapelem jelzők (pl. láthatóság) |
form->x | Űrlapelem igényelt pozíció |
form->y | Űrlapelem igényelt pozíció |
form->w | Űrlapelem igényelt szélesség |
form->h | Űrlapelem igényelt magasság |
form->m | Űrlapelem margó |
form->p | Űrlapelem eltartás (csak tárolóknál) |
Ezek szabályozzák, hogy egy űrlapelem mező hogyan jelenik meg.
Az SMGUI nem használja a szokásos pakolt sor / oszlop / négyzetrács elrendezést, helyette HTML-szerű flexibilis folyamot alkalmaz. A koordináták megadhatók a form->x és form->y mezőkben háromféleképp: relatív, abszolút és százalékban.
Ha a form->w és form->h nincs megadva és 0, akkor a mező szélessége és magassága automatikusan számítódik. Ha az UI_ABS() makrót használjuk ezekre, akkor az a szülő tároló szélessége (vagy magassága) mínusz a megadott érték pixelben lesz a szélesség (vagy magasság).
Használható a form->align a megadott x, y koordinátákhoz való igazításhoz. Ez egy VAGY-olt bitmaszk.
Példák:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ui_form_t form[] = {
/* ezek szorosan egymás mellé kerülnek, balról jobbra,
* csak akkor új sorba, ha muszáj */
{ .type = UI_LABEL, .label = 1 },
{ .type = UI_LABEL, .label = 1 },
/* ezek szintén egymás mellé kerülnek, de eltartással */
{ .type = UI_LABEL, .x = UI_REL(10), .label = 1 },
/* ez abszolút pozícióra kerül */
{ .type = UI_LABEL, .x = UI_ABS(100), .y = UI_ABS(100), .label = 1 },
/* ez az ablak közepére kerül */
{ .type = UI_LABEL, .align = UI_CENTER | UI_MIDDLE,
.x = UI_PERCENT(50), .y = UI_PERCENT(50), .label = 1 },
/* ez ablak szélesség - 20 és ablak magasság - 20 méretű lesz */
{ .type = UI_POPUP, .x = UI_ABS(10), .y = UI_ABS(10),
.w = UI_ABS(20), .h = UI_ABS(20), .ptr = &popupform },
/* fontos, hogy zárjuk a listát */
{ .type = UI_END }
};
Mivel az űrlap csupán csak hivatkozik a változókra, ezért simán működik az, hogy az egyik szálon van megjelenítve az elrendezés és egy másik szálon történik a változók kezelése. Ugyanakkor ha magát az űrlapot szeretnénk dinamikusan változtatni egy másik szálból, akkor az a fejlesztő felelőssége, hogy ilyenkor megfelelően szemaforokkal védje az űrlapját. Például:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ui_form_t form[];
/* ez a funkció bármelyik szálról hívható */
void regenerate_form()
{
mutex_lock(&my_form_mutex);
/* itt lehet módosítani a form[] tömböt */
mutex_unlock(&my_form_mutex);
}
/* ez pedig a fő szálon a fő ciklusban */
mutex_lock(&my_form_mutex);
evt = ui_event(&ctx, form);
mutex_unlock(&my_form_mutex);
Mivel az SMGUI maga semmilyen threading függvénykönyvtárat nem használ, ezért bármelyik threading és mutex implementáció használható vele. Az SDL motor például biztosít egy SDL_Mutex típust, GLFW esetén meg használható a pthread függvénykönyvtár.
Az újrarajzolás az eseménykezelés hívásakor automatikusan megtörténik, ha szükség van rá, és ennyi. De ha valamelyik hivatkozott változó az UI látókörén kívül módosul, akkor szükséges a következő függvény hívása:
1
int ui_refresh(ui_t *ctx);
Jelzi az UI-nak, hogy szükség van az újrarajzolásra.
Paraméter | Leírás |
---|---|
ctx | Mutató az UI kontextusra |
Siker esetén 0-val tér vissza, egyébként hibakóddal.
Ha egy tárolót egy kapcsoló mező előz meg, akkor az a kapcsoló ennek a tárolónak a láthatóságát fogja kapcsolni.
Kirajzol egy felugrót.
Paraméter | Leírás |
---|---|
form->type | UI_POPUP |
form->flags | Esetleg UI_HIDDEN, UI_DRAGGABLE vagy UI_RESIZABLE |
form->ptr | Mutató egy másik ui_form_t bufferre |
form->m | Margó pixelekben |
form->p | Eltartás pixelekben |
form->label | Cím, lokalizált sztringtömb index (vagy 0) |
Ugyanaz, mint a felugró, de alapból UI_HIDDEN, azaz elrejtett és egyszerre csak egy menü lehet megjelenítve. A gyerek pipa és választó mezői ki lesznek emelve, amikor az egér föléjük kerül.
Paraméter | Leírás |
---|---|
form->type | UI_MENU |
form->flags | Esetleg UI_SCROLL |
form->ptr | Mutató egy másik ui_form_t bufferre |
form->m | Margó pixelekben |
form->p | Eltartás pixelekben |
Nem rajzol ki semmit, csak csoportosíthatóvá teszi a mezőket, hogy egyszerre lehessen őket megjeleníteni / elrejteni meg pozícionálni.
Paraméter | Leírás |
---|---|
form->type | UI_DIV |
form->flags | Esetleg UI_SCROLL |
form->ptr | Mutató egy másik ui_form_t bufferre |
form->m | Margó pixelekben |
form->p | Eltartás pixelekben |
Adatmezőket rajzol ki táblázat vagy rács formájában. Be kell húzni hozzá az ui_table.h modult.
Paraméter | Leírás |
---|---|
form->type | UI_TABLE |
form->flags | Esetleg UI_SCROLL vagy UI_NOHEADER |
form->ptr | Mutató az adatokra |
form->tblsel | A kiválasztott adatrekord indexe |
form->tblnum | Adatrekordok száma |
form->tblsiz | Egy adatrekord mérete bájtokban |
form->tblrow | Sor mérete pixelekben |
form->tblcol | Oszlop mérete pixelekben (rács esetén, egyébként 0) |
form->data | Mutató az ui_form_t fejléclistára |
form->cmps | Összehasonlító függvények rendezéshez (vagy NULL) |
form->m | Cellamargó pixelekben |
A form->ptr mutat az adatrekordokra, ami táblázat esetén valószínűleg egy struktúrákat tartalmazó tömb. A form->data listának legalább egy UI mezőt kell tartalmaznia, és MINDIG egy UI_END mezővel kell lezárni. Ez tárolja a hdr fejléceket, valamint megadja az adott oszlop megjelenítését. Táblázathoz a form->tblcol értékét 0-ára kell állítani, és ilyenkor valószínűleg a form->data több fejlécet fog tartalmazni. Rács esetén a form->tblcol nem nulla és ilyenkor egységesen minden cellához az első form->data fejléc használatos.
Paraméter | Leírás |
---|---|
hdr->type | A cella megjelenítésének típusa |
hdr->tblhdr | Fejléc cím, lokalizált sztringtömb index |
hdr->tblofs | A mező adatrekordon belüli címe (csak táblázat esetén) |
hdr->flags | UI_POINTER, ha az oszlop mezője egy mutató |
hdr->w | Oszlop szélessége, használható UI_PERCENT |
A rendezés engedélyezéséhez kétszer annyi komparátor funkciót kell megadni, mint ahány fejlécmező van. Oszloponként az első a növekvő, a második a csökkenő sorrendért felel.
1
typedef int (*ui_comp)(const void *a, const void *b);
A prototípusuk a szabványos POSIX komparátoré, a libc qsort() gyorsrendezés függvényének adódnak át paraméterül.
Kirajzol egy szöveg cimkét. Ha a form->label 0, akkor a form->ptr egy nullával lezárt UTF-8 sztringre kell mutasson.
Paraméter | Leírás |
---|---|
form->type | UI_LABEL |
form->label | Lokalizált sztringtömb indexe (vagy 0) |
form->ptr | Csak ha label 0, mutató egy sztringre |
Kirajzol egy szöveg cimkét. Ugyanaz, mint az UI_LABEL, csak form->label helyett annak a mezőnek a form->desc értékét használja, ami fölött az egér tartózkodik. Ha ez 0, akkor a form->ptr egy nullával lezárt UTF-8 sztringre kell mutasson.
Paraméter | Leírás |
---|---|
form->type | UI_STATUS |
form->ptr | Csak ha hover->desc 0, mutató egy sztringre |
hover->desc | Lokalizált sztringtömb indexe (vagy 0) |
Kirajzol egy értéket tízes számrendszerben. A szám a define végén jelzi, hogy hány biten tárolódik az érték.
Paraméter | Leírás |
---|---|
form->type | UI_DEC8 / UI_DEC16 / UI_DEC32 / UI_DEC64 |
form->ptr | Mutató az értékre |
Kirajzol egy értéket tizenhatos számrendszerben. A szám a define végén jelzi, hogy hány biten tárolódik az érték.
Paraméter | Leírás |
---|---|
form->type | UI_HEX8 / UI_HEX16 / UI_HEX32 / UI_HEX64 |
form->ptr | Mutató az értékre |
Kirajzol egy 64 bites egész számot folyamatjelzőként.
Paraméter | Leírás |
---|---|
form->type | UI_PBAR |
form->ptr | Mutató egy int64 értékre |
form->max | Teljes érték |
Kirajzol egy lebegőpontos értéket.
Paraméter | Leírás |
---|---|
form->type | UI_DEC_FLOAT |
form->ptr | Mutató az értékre |
Kirajzol egy ikont képpel. Ha a form->ptr nem NULL, akkor kattintható és úgy viselkedik, mint egy gomb.
Paraméter | Leírás |
---|---|
form->type | UI_IMAGE |
form->icon | Mutató egy ui_image_t struct-ra |
form->ptr | Mutató az int értékre (vagy NULL) |
form->value | A cimke int értéke |
Az ui_image_t képstruktúra pedig a következő:
Mező | Leírás |
---|---|
w | Szélesség pixelekben |
h | Magasság pixelekben |
p | Rasztersor bájtokban (legalább w * 4) |
buf | Pixelbuffer 32 bites RGBA színkódokkal |
Kirajzol egy szövegbeviteli mezőt. A bufferben egy nullával lezárt UTF-8 sztringnek kell lennie. Alapból bármilyen nem vezérlőkaraktert elfogad, de ez tovább szűkíthető: UI_FILTER_ID (egy UNIX azonosító), UI_FILTER_VAR (változónév, mint a UNIX azonosító, csak nem kezdődhet számmal), UI_FILTER_EXPR (kifejezés, mint a változó plusz zárójelek és operátorok), és UI_FILTER_HEX (csak a hexadecimálishoz szükséges 0-9A-F gombokat engedi). Az UI_FILTER_PASS nem a bementet, hanem a kimenetet szűri, csillagokat jelenít meg. Beillesztés is működik. Ha az ui_textosk.h modul be van húzva, akkor bevitelkor megjelenít szoftveresen egy billentyűzetet a képernyőn, egyébként az OS-specifikus OSK csak akkor jelenik meg, ha a platform támogatja azt.
Paraméter | Leírás |
---|---|
form->type | UI_TEXT |
form->ptr | Mutató a bufferre |
form->max | A buffer mérete |
form->inc | 0 bármi, vagy valamelyik UI_FILTER_x filter |
Kirajzol egy választódobozt. Ha rákattintanak, akkor az opciók egy felugróban jelennek meg.
Paraméter | Leírás |
---|---|
form->type | UI_SELECT |
form->ptr | Mutató az int értékre |
form->optc | Maximum érték plusz 1, opciók száma |
form->optv | Mutató egy sztringtömbre, opciók |
form->m | Jobb margó |
Kirajzol egy opciólistát. Pont, mint a választódoboz, csak számbekérő megjelenéssel, nincs felugró.
Paraméter | Leírás |
---|---|
form->type | UI_OPTION |
form->ptr | Mutató az int értékre |
form->optc | Maximum érték plusz 1, opciók száma |
form->optv | Mutató egy sztringtömbre, opciók |
form->m | Bal és jobb margó |
Kirajzol egy lebegőpontos számbeviteli mezőt.
Paraméter | Leírás |
---|---|
form->type | UI_FLOAT |
form->ptr | Mutató az értékre |
form->fmin | Minimum érték |
form->fmax | Maximum érték |
form->finc | Léptetési érték |
form->m | Bal és jobb margó |
Kirajzol egy egészszámbeviteli mezőt. A szám a define végén jelzi, hogy hány biten tárolódik az érték.
Paraméter | Leírás |
---|---|
form->type | UI_INT8 / UI_INT16 / UI_INT32 / UI_INT64 |
form->ptr | Mutató az értékre |
form->min | Minimum érték |
form->max | Maximum érték |
form->inc | Léptetési érték |
form->m | Bal és jobb margó |
Kirajzol egy egészszámbeviteli mezőt csúszkaként (csak 32 bit).
Paraméter | Leírás |
---|---|
form->type | UI_SLIDER |
form->ptr | Mutató az értékre |
form->min | Minimum érték |
form->max | Maximum érték |
form->inc | Léptetési érték |
Kirajzol egy függőleges szkroll mezőt (csak 32 bit). A tárolók maguktól kezelik a szkrollozást, szóval ez bármi más esetre.
Paraméter | Leírás |
---|---|
form->type | UI_VSCRBAR |
form->ptr | Mutató az int értékre |
form->max | Maximum érték |
Kirajzol egy vízszintes szkroll mezőt (csak 32 bit).
Paraméter | Leírás |
---|---|
form->type | UI_HSCRBAR |
form->ptr | Mutató az int értékre |
form->max | Maximum érték |
Kirajzol egy egészszámbeviteli mezőt színként (csak 32 bit). Ha rákattintanak, akkor egy színválasztó ugrik fel.
Paraméter | Leírás |
---|---|
form->type | UI_COLOR |
form->ptr | Mutató az int értékre |
Kirajzol egy szövegbeviteli mezőt. A bufferben egy nullával lezárt UTF-8 sztringnek kell lennie az elérési úttal. Ha a felhasználó rákattint, akkor egy elérési út választót hoz elő, amivel a sztring egyszerűen szerkeszthető. Az str paraméter leírását lásd ott. Be kell húzni hozzá az ui_file.h modult.
Paraméter | Leírás |
---|---|
form->type | UI_FILE |
form->ptr | Mutató a bufferre az elérési úttal |
form->max | A buffer mérete |
form->min | Az elérési út választó minimális magassága |
form->str | Lokalizált sztringtömb indexe (vagy 0) |
Kirajzol egy elérési út választót. Az str a lokalizált sztring tömbben egy 8 sztringből álló csoport első indexe, ezek rendre: fájl neve, mérete, módosítási dátuma, most, N perce, egy órája, N órája, tegnap. Be kell húzni hozzá az ui_file.h modult.
Paraméter | Leírás |
---|---|
form->type | UI_PATH |
form->ptr | Mutató a bufferre az elérési úttal |
form->max | A buffer mérete |
form->str | Lokalizált sztringtömb indexe (vagy 0) |
form->data | Mutató az ui_path_t kontextusra |
Az ui_path_t struktúra pedig a következő:
Mező | Leírás |
---|---|
flags | Elérési út jelzőbitek |
exts | Kiterjesztéslista (vagy NULL) |
select | Kiválasztás rendben (vagy NULL) |
A jelzőbitek:
Define | Leírás |
---|---|
UI_PATH_SEARCH | Keresőmezőt is tartalmazzon |
UI_PATH_NEWDIR | Új könyvtár létrehozása gomb is legyen |
UI_PATH_ONLYDIR | Csak könyvtárakat listázzon |
UI_PATH_HIDDEN | Listázza a rejtett fájlokat is |
A kiterjesztéslista egy nullával lezárt sztringeket tartalmazó lista, amit két nulla karakter zár, például png\0jpg\0\0. Ha meg van adva, akkor a lista csak az itt felsorolt kiterjesztésű fájlokat fogja tartalmazni.
Ha a select visszahívás NULL, akkor egyszerűen az alkönyvtárakba belép, a fájlokat meg visszaadja. Ha meg van adva
1
typedef int (*ui_form_select)(char *path, int isdir);
formában, akkor az 1-el tér vissza, ha az elérési út kiválasztható, egyébként 0-ával. Ha 0-val tért vissza, akkor az alkönyvtárakba belép, a fájlokkal pedig semmit sem csinál. A path paraméter könyvtárelválasztóra végződik, ha az egy könyvtár, és ilyenkor az isdir értéke 1. Ez arra használható, hogy további kritériát szabjunk a kiválasztandó elérési útnak, például könyvtárak esetében hogy tartalmaz-e egy bizonyos fájlt, vagy fájlok esetében hogy adott mágikus bájttal kezdődik-e vagy sem. A megadott visszahívás bármilyen plusz ellenőrzést implementálhat.
Ez egy speciális mező, amit egy tároló mezőnek kell követnie, és annak a tároló mezőnek a láthatóságát kapcsolja. Ha a következő mező mégsem tároló lenne, akkor a form->value egy index az ui_event()-nek átadott űrlap elemeire. Ha a form->label 0, akkor a form->ptr egy nullával lezárt UTF-8 sztringre kell mutasson, ami cimkeként jelenik meg. Alapból ez elé a cimke elé kerül egy jobbra vagy lefelé nyíl, hacsak nincs UI_NOBULLET megadva, ekkor ugyanis nincs nyíl, helyette a cimke más színnel jelenik meg (lásd színtéma, ez a menüelemekhez kell).
Paraméter | Leírás |
---|---|
form->type | UI_TOGGLE |
form->flags | Esetleg UI_NOBULLET |
form->label | Lokalizált sztringtömb indexe (vagy 0) |
form->ptr | Csak ha label 0, mutató egy sztringre |
form->value | Ha nem tároló követi, ui_event() űrlap indexe |
Kirajzol egy pipát cimkével. A mutatott érték jelzi, hogy be van-e pipálva. Ha rákattintanak, akkor a value int érték XOR-olódik a megadott címen lévő értékkel.
Paraméter | Leírás |
---|---|
form->type | UI_CHECK |
form->flags | Esetleg UI_NOBULLET |
form->ptr | Mutató az int értékre |
form->value | A gomb bitmaszkja |
form->label | Lokalizált sztringtömb indexe |
Kirajzol egy választót cimkével. A mutatott érték jelzi, hogy ez-e az aktív. Ha rákattintanak, akkor a value int érték kerül a megadott címre.
Paraméter | Leírás |
---|---|
form->type | UI_RADIO |
form->flags | Esetleg UI_NOBULLET |
form->ptr | Mutató az int értékre |
form->value | A gomb int értéke |
form->label | Lokalizált sztringtömb indexe |
Kirajzol egy gombot. A mutatott érték jelzi, hogy be van-e nyomva. Ha rákattintanak, akkor a value int érték kerül a megadott címre. Lehet ikonja is, cimkéje is, vagy akár mindkettő. Ha bőrrel van rajzolva, akkor ott lehet árnyék, ami függőlegesen eltolja a cimkét. Ha ez előfordulna, akkor az m margóval igazítható (lehet negatív is).
Paraméter | Leírás |
---|---|
form->type | UI_BUTTON |
form->flags | Esetleg UI_NOBORDER |
form->ptr | Mutató az int értékre |
form->value | A gomb int értéke |
form->label | Lokalizált sztringtömb indexe |
form->icon | Mutató egy ui_image_t struct-ra |
form->m | Felső margó, ha bőrözött |
Kirajzol egy gombot, ami kapcsolóként viselkedik. Ha rákattintanak, akkor a mutatott tároló mező láthatóságát kapcsolja. Ha a ptr értéke NULL, akkor a form->value egy index az ui_event()-nek átadott űrlap elemeire.
Paraméter | Leírás |
---|---|
form->type | UI_BTNTGL |
form->flags | Esetleg UI_NOBORDER |
form->ptr | Mutató egy ui_form_t tároló mezőre |
form->value | Ha a ptr NULL, ui_event() űrlap indexe |
form->label | Lokalizált sztringtömb indexe |
form->icon | Mutató egy ui_image_t struct-ra |
form->m | Felső margó, ha bőrözött |
Kirajzol egy ikont, ha be van pipálva, egyébként semmit. Ha rákattintanak, akkor a value int érték XOR-olódik a megadott címen lévő értékkel. Pontosan úgy működik, mint a pipa.
Paraméter | Leírás |
---|---|
form->type | UI_BTNICN |
form->ptr | Mutató az int értékre |
form->value | A gomb bitmaszkja |
form->icon | Mutató egy ui_image_t struct-ra |
Egy sor összefüggő vonalat húz. A form->ptr egy int16_t (short int) értékeket tartalmazó tömbre kell mutasson, több x és y párral, és a legutolsó párnak 0,0-nak kell lennie.
Paraméter | Leírás |
---|---|
form->type | UI_LINES |
form->ptr | Mutató az int16_t tömbre |
form->value | 32 bites RGBA szín |
Összeköt két pontot vízszintesen egy ívvel. A form->ptr egy pontosan 4 elemű int16_t tömbre kell mutasson, x0 és y0 a kiinduló pont, x1 és y1 pedig a végpont pár.
Paraméter | Leírás |
---|---|
form->type | UI_HCONNECT |
form->ptr | Mutató a 4 elemű int16_t tömbre |
form->value | 32 bites RGBA szín |
Összeköt két pontot függőlegesen egy ívvel. A form->ptr egy pontosan 4 elemű int16_t tömbre kell mutasson, x0 és y0 a kiinduló pont, x1 és y1 pedig a végpont pár.
Paraméter | Leírás |
---|---|
form->type | UI_VCONNECT |
form->ptr | Mutató a 4 elemű int16_t tömbre |
form->value | 32 bites RGBA szín |
Tetszőleges Bezier ív kirajzolása. A form->ptr egy pontosan 8 elemű int16_t tömbre kell mutasson, x0 és y0 a kiinduló pont, x1 és y1 a végpont, cx0 és cy0 az első kontrollpont, cx1 és cy1 pedig a második kontrollpont koordináta párja.
Paraméter | Leírás |
---|---|
form->type | UI_CURVE |
form->ptr | Mutató a 8 elemű int16_t tömbre |
form->value | 32 bites RGBA szín |
Felhasználó által kreált egyedi mezők is használhatók, ehhez mindössze típusonként 4 visszacsatolásra van szükség.
Paraméter | Leírás |
---|---|
form->type | UI_CUSTOM |
form->flags | Figyelembe kell venni a UI_HIDDEN-t és UI_DISABLED-t |
form->ptr | Mutató tetszőleges adat bufferre |
form->data | Mutató tetszőleges adat kontextusra |
form->str | Lokalizált sztringtömb indexe (vagy 0) |
form->bbox | Méretfunkció |
form->view | Kirajzolófunkció |
form->ctrl | Eseménykezelőfunkció |
form->fini | Opcionális felszabadításfunkció |
1
2
typedef int (*ui_bbox)(ui_t *ctx, int x, int y, int w, int h,
ui_form_t *form, int *dw, int *dh);
Ez a funkció a számolt területet kapja x, y, w, h változókban, ahol a mezőnek meg kell jelennie, az űrlapelemet pedig a form-ban, majd vissza kell adnia a tényleges szélességet a dw és a tényleges magasságot a dh változókban.
1
2
typedef int (*ui_view)(ui_t *ctx, int x, int y, int w, int h,
ui_form_t *form);
Ez a funkció a tényleges területet kapja x, y, w, h változókban, ahová a mezőt ki kell rajzolni, az űrlapelemet pedig a form-ban. Használhatja az alacsonyszintű _ui_line(), _ui_cbez(), _ui_rect(), _ui_blit() stb. hívásokat, vagy direktben változtathatja a pixeleket a ctx->screen képben. Nagyon fontos, hogy nem módosíthat a megadott területen hívül.
1
2
typedef int (*ui_ctrl)(ui_t *ctx, int x, int y, int w, int h,
ui_form_t *form, ui_event_t *evt);
Ez a funkció a tényleges területet kapja x, y, w, h változókban, ahol a mező található, az űrlapelemet a form-ban, az aktuális eseményt pedig az evt-ben az eseménykezeléshez. Ez csak akkor hívódik, ha a form nem UI_HIDDEN (rejtett) és nem is UI_DISABLED (inaktív), és az egér épp fölötte tartózkodik.
1
typedef int (*ui_fini)(ui_t *ctx, ui_form_t *form);
Erre az opcionális visszacsatolásra csak akkor van szükség, ha az egyedi mező memóriát allokált. Többször is meghívódhat, ezért fontos úgy megírni, hogy csak egyszer szabadítsa fel a buffer(eke)t.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#define UI_IMPLEMENTATION
#include <ui.h>
int main(int argc, char **argv)
{
/* lokalizált sztringek tömbje */
enum { WINDOW_TITLE, POPUP_TITLE, BUTTON_TITLE,
EASY_TITLE, HARD_TITLE, VOLUME_TITLE };
char *lang[] = { "Basic demo", "Show", "Button",
"easy", "hard", "Volume:" };
/* állapotok tárolására használt változók */
int button = 0, difficulty = 0, volume = 25;
/* ezekre hivatkozó űrlap, HTML-folyam szerű elrendezéssel */
ui_t ctx;
ui_form_t popup[] = {
{ .type = UI_BUTTON, .flags = UI_FORCEBR,
.ptr = &button, .value = 1,
.label = BUTTON_TITLE },
{ .type = UI_RADIO, .flags = UI_NOBR,
.ptr = &difficulty, .value = 0,
.y = 5, .label = EASY_TITLE },
{ .type = UI_RADIO, .flags = UI_FORCEBR,
.ptr = &difficulty, .value = 1,
.x = 20, .label = HARD_TITLE },
{ .type = UI_LABEL, .flags = UI_NOBR,
.y = 5, .label = VOLUME_TITLE },
{ .type = UI_SLIDER, .ptr = &volume, .max = 100 },
{ .type = UI_END }
};
ui_form_t form[] = {
{ .type = UI_POPUP, .align = UI_CENTER | UI_MIDDLE,
.ptr = &popup,
.x = UI_PERCENT(50), .y = UI_PERCENT(50),
.m = 10, .label = POPUP_TITLE },
{ .type = UI_END }
};
/* UI kontextus inicializálása */
ui_init(&ctx, sizeof(lang)/sizeof(lang[0]), lang, 640, 480, NULL);
/* várunk, amíg a felhasználó be nem zárja az ablakot */
while(ui_event(&ctx, form)) {
/* gomb lekezelése, ez akár másik szálban is lehetne */
if(button) {
printf("button clicked\n");
button = 0;
ui_refresh(&ctx);
}
}
/* ablak bezárása, erőforrások felszabadítása */
ui_free(&ctx);
return 0;
}
Az SMGUI alaprendszere hangolható néhány define-al az ui.h behúzása előtt.
FIGYELEM
Ezt mindig a modulok behúzása után szabad csak definiálni.
Akkor kell megadni, ha nemcsak a prototípusokra, de az implementációra is szükség van.
Anti-alias nélküli vonalat rajzol (kiiktatja a math.h és libm függőséget).
A várakozó események maximális száma. Ha nincs megadva, alapértelmezetten 16.
A látható felugrók maximális száma. Ha nincs megadva, alapértelmezetten 16.
Ha a kódból már meg lett hívva a glfwInit() / glfwTerminate(), SDL_Init() / SDL_Quit() stb., akkor használatos. Erre akkor van szükség, ha az SMGUI-val több ablakot is akarunk kezelni egyszerre.
Ha nem akarod, hogy az ui_event() érvényesítse a képet, hanem kódból magad hívod a glfwSwapBuffers() / SDL_RenderPresent() / stb. függvényeket. Erre akkor van szükség, ha az UI réteg fölé még rajzolni szeretnénk.
Függetlenül a GLFW3 motor is finomhangolható define-okkal, a ui_glfw.h behúzása előtt.
Alapból ez a motor OpenGL 3.3 core profile-os shaderekkel fordul, és egyaránt támogatja a glad és glew bővítménybetöltést.
A régi OpenGL API használata. Ez mindenhol működik és nem kell neki bővítménybetöltő se shader. A hátránya, hogy néhány videokártya meghajtóban bugos a visszafele kompatibilitás, emiatt nem lehet már saját shadert se használni, ha ez az opció engedélyezve lett.
Használjon shadereket, de csak OpenGL ES 2.0-t (mobil platform verzió). Csak régi mobilok támogatásához, a mai modern eszközök általában gond nélkül kezelik az OpenGL 3.3 core-t.
Akkor használatos, ha magunk akarjuk a GLFW3 visszacsatolásokat megadni. Ekkor a visszacsatolásokból meg kell hívni a motor visszacsatolásait is. Például:
1
2
3
4
5
6
7
8
9
10
11
/* visszacsatolás megadása a szokásos módon */
glfwSetMouseButtonCallback(ui_getwindow(ctx), my_glfw_mouse);
/* a visszacsatolásod */
void my_glfw_mouse(GLFWwindow *window, int button, int action, int mods)
{
/* tetszőlegesen értelmezhető */
/* ... */
/* a végén meg kell hívni az ui_glfw visszacsatolását is */
ui_glfw_mouse(window, button, action, mods);
}
A megengedő MIT licensz szerint kerül terjesztésre.
A szabad felhasználás jogát ezennel ráruházom bármely személyre aki jelen mű és dokumentációjának egy példányát (a továbbiakban “Szoftver”) megszerezte, hogy a szoftvert korlátozás nélkül - beleértve a használat, másolás, módosítás, kiadás, terjesztés, és/vagy értékesítés jogát - felhasználhassa, és a továbbadott példánnyal hasonlóan járhasson el, amennyiben a következő feltételek teljesülnek: A fenti szerzői jogot és felhasználási jogot biztosító szöveget fel kell tüntetni a Szoftver minden teljes és rész másolataiban is. A SZOFTVER “ÚGY, AHOGY VAN” KERÜL TERJESZTÉSE, MINDENNEMŰ JÓTÁLLÁS NÉLKÜL, KÖZVETVE VAGY KÖZVETETTEN, BELEÉRTVE A KERESKEDELMI JÓTÁLLÁS VAGY EGY ADOTT CÉLRA TÖRTÉNŐ FELHASZNÁLÁSRA ALKALMASSÁGOT. A SZERZŐI JOG TULAJDONOSA SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT NEM TEHETŐ FELELŐSSÉ BÁRMILYEN MÓDON, BELEÉRVE A SZOFTVER RENDELTETÉSSZERŰ HASZNÁLATA SORÁN, VAGY RENDELTETÉSSZERŰ HASZNÁLATTÓL ELTÉRŐ FELHASZNÁLÁS SORÁN A SZOFTVER ÁLTAL ESETLEGESEN OKOZOTT KÁROKÉRT.