layout.md 6.5 KB

Elrendezés

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)

Mező jelzők

Ezek szabályozzák, hogy egy űrlapelem mező hogyan jelenik meg.

  • UI_HIDDEN nem látszik, nem befolyásolja a normál folyamot
  • UI_NOBULLET csak [kapcsoló], [pipa] és [választó], csak a címkét jelenítsék meg
  • UI_NOHEADER csak [táblázat] és rács, ne rajzolja ki a fejlécet
  • UI_NOBR a következő mezőt ugyanebbe a sorba kényszeríti, nincs sortörés
  • UI_FORCEBR ellenkező, a következő mező mindenképp új sorba kerül
  • UI_ALTSKIN olyan mezők esetén, amik több bőrt is támogatnak (pl. tab menü helyett)
  • UI_NOBORDER tárolóknál, ne jelenjen meg a keret
  • UI_NOSHADOW felugróknál, ne legyen árnyékuk
  • UI_HSCROLL tárolóknál, jelenljen meg vízszintes szkrollozó
  • UI_VSCROLL tárolóknál, jelenljen meg függőleges szkrollozó
  • UI_SCROLL ugyanaz, mint az UI_HSCROLL + UI_VSCROLL
  • UI_DRAGGABLE felugróknál, engedélyezi, hogy a felhasználó átmozgassa
  • UI_RESIZABLE felugróknál, engedélyezi, hogy a felhasználó átméretezze
  • UI_SELECTED a beviteli mezőt kiválasztottként jeleníti meg
  • UI_DISABLED inaktívvá teszi a mezőt, más a megjelenése és nem kattintható

Pozícionálás

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.

  • Relatív pozícionálás az alapértelmezett, de használható az UI_REL() makró is. Az így pozícionált mezők befolyásolják a folyamot.
  • Abszolút pozícionáláshoz az UI_ABS() makrót kell használni. Megváltoztatható a gravitáció is, UI_ABS_RIGHT() (jobbról) vagy UI_ABS_BOTTOM() (alulról) a szülő tároló jobb oldalától vagy aljától számítódik. A normál folyamon kívüli.
  • Százalékhoz az UI_PERCENT() makró használatos. Ez a szülő tároló méretéhez képest határozza meg a pozíciót. A normál folyamon kívüli.
  • Százalék plusz valamennyi pixelhez az UI_PERPLUS() makrót kell használni.

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.

  • UI_LEFT a mezőt úgy helyezi, hogy a form->x balra van (alapértelmezett)
  • UI_RIGHT a mezőt úgy helyezi, hogy a form->x jobbra van
  • UI_CENTER a mezőt úgy helyezi, hogy a form->x középre kerül
  • UI_TOP a mezőt úgy helyezi, hogy a form->y felülre kerül (alapértelmezett)
  • UI_BOTTOM a mezőt úgy helyezi, hogy a form->y alulra kerül
  • UI_MIDDLE a mezőt úgy helyezi, hogy a form->y középre kerül

Példák:

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 }
};

Többszálúság

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:

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.

Újrarajzolás

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:

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.