GEM jest małą biblioteką obsługi podstawowych elementów graficznego interfejsu użytkownika jak przyciski, okna dialogowe, pola edycyjne, selektor plików. Nazwa jest skrótem od Graphics Entry Manager i nawiązuje do systemu operacyjnego GEM firmy Digital Research stosowanego m.in. w komputerach Atari ST.

Podstawowymi elementami GEM są przyciski i pola edycji, które z poziomu programisty są tymi samymi obiektami, opisanymi w zmiennej strukturalnej typu GEMBOX. GEM nie tworzy oddzielnych okien, "okna" wiadomości, czy wybierania pliku wyświetlane są w podstawowym oknie SDLWindow. Selektor plików tworzony jest w obrazie GEMScreen typu SDL_Texture, który następnie jest wyświetlany. Przy korzystaniu z GEM zalecane jest używanie GEMScreen jako targetu.

Definicje w BasicGEM.h wraz z wartościami domyślnymi:

  • FILES_MAX 1000 - maksymalna ilość plików w katalogu wyświetlana w selektorze plików
  • ALERTW 320, ALERTH 200 - szerokość i wysokość okna komunikatów
  • GEMMOUSEBUTTONUP 0 - czy GEMMenu obsługuje zdarzenia puszczenia przycisków myszy: 0 - nie, 1 - tak
  • CFACE 0xafcfaf - kolor powierzchni (tła) obiektów GEM
  • CUPPER 0xcfffcf - kolor jasny/górnej krawędzi
  • CLOWER 0x7faf7f - kolor ciemny/dolnej krawędzi
  • CTEXT 0x000000 - kolor tekstu
  • CTEXTBG 0xafffaf - kolor tła tekstu
  • CCURSOR 0xff0000 - kolor kursora tekstowego
  • CDIS 0x8fbf8f - kolor tekstu nieaktywnego przycisku
  • tablica GEMColor typu union BASSDLColor zawierająca wartości 16 kolorów, domyślnie odpowiadają one podstawowym kolorom Atari ST, a wartość alfa wynosi 127 (pół-przeźroczyste).
  • obraz GEMScreen typu SDL_Texture* będący wirtualnym ekranem stosowanym w GEM
  • struktura GEMBOX opisująca obiekty GEM


Tworzenie menu GEM polega na zadeklarowaniu obiektów typu GEMBOX, podanie ich współrzędnych, typów i właściwości, następnie sprawdzaniu i obsługiwaniu zdarzeń z nimi związanych. Można w tym celu napisać własną procedurę lub używać komendy GEMMenu. Do BasicC dołączony jest przykładowy program graficzny NIKIFOR wykorzystujący GEM.

Struktura GEMBOX zawiera następujące pola:

  • Text - tekst wyświetlany w danym obiekcie, typ char*
  • State - liczba typu Uint8, zawierająca informacje o stanie i właściwościach obiektu, ustawienie kolejnych bitów na 1 oznacza:
0 (odpowiada wartości 1): obiekt aktywny, obsługiwany przez GEM
1 (2): widoczny, brak widoczności oznacza również brak aktywności (pomijanie przez funkcje GEM)
2 (4): wybrany
3 (8): odznaczany (bit 2 ustawiany na 0) przy kolejnym wywołaniu GEMMenu
4 (16): radiowy - może być wybrany tylko jeden z tej grupy
5 (32): XOR - kliknięcie w obiekt powoduje wybranie/odznaczenie
  • Type - liczba Uint8 oznaczająca typ obiektu: 0 - pusty blok, 1 - przycisk tekstowy, 2 - przycisk obrazkowy, 10 - puste pole tekstowe, 11 - linia tekstu, 12 - pole z tekstem wieloliniowym, 13 - lista tekstowa
  • x,y,w,h - współrzędne i wymiary obiektu, typ int
  • n,s - liczby typu int, znaczenie zależne od typu obiektu lub do innego wykorzystania
  • P - wskaźnik na obraz typu SDL_Texture*, który może być wyświetlany w obiekcie


Obiekty typu GEMBOX deklarujemy poprzez: struct GEMBOX nazwa;
można zadeklarować tablicę obiektów: struct GEMBOX nazwa_tablicy[ilość];

Przykład Informatyczne Pianino z przycisków GEM:

#include "BasicGEM.h"
MAIN
	int w,o;
	struct GEMBOX b[48];
	STRING txt[21]={" "};
	SDLOpen(0)
	For(w,0,20)
		GEMBox(b[w],1,txt[w],5+w*30,10,30,200) b[w].State+=16;b[w].n=RGBA(222,222,222,255);
		GEMBox(b[w+21],0,0,25+w*30,10,20,100) b[w+21].State+=16;b[w+21].n=RGBA(66,66,66,155);
		txt[w][0]=((w+2) MOD 7)+65;
	Next
	b[23].State=0;b[27].State=0;b[30].State=0;b[34].State=0;b[37].State=0;b[41].State=0;
	GEMBox(b[42],1,"SIN",5,300,99,20) b[42].State+=8;
	GEMBox(b[43],1,"ROUND",100,300,99,20) b[43].State+=8;
	GEMBox(b[44],1,"TOOTH",200,300,99,20) b[44].State+=8;
	GEMBox(b[45],1,"TRIANG",300,300,99,20) b[45].State+=8;
	GEMBox(b[46],1,"SQUARE",400,300,99,20) b[46].State+=8;
	GEMBox(b[47],1,"NOISE",500,300,99,20) b[47].State+=8;
	Do
		Target(GEMScreen)
		Color(CFACE)
		Cls
		GEMBoxesDraw(b,sizeof b/sizeof b[0])
		GEMShow
		GEMMenu(b,sizeof b/sizeof b[0],0,w)
		Print$ "Wcisnieto przycisk nr" _ w );
		if(w==42)Wave(0,sin,0.1,.5)
		if(w==43)Wave(0,WavRound,0.1,1)
		if(w==44)Wave(0,WavTooth,.5,1)
		if(w==45)Wave(0,WavTriang,.5,.5)
		if(w==46)Wave(0,WavSqr,0.2,0.2)
		if(w==47)Wave(0,WavNoise,0.1,1)
		o=1<<w/7;
		w=w MOD 7;
		Print$ "Segment:" _ o $ "Dzwiek:" _ w NL
		If(o<5)
			if(w<3)Sound(0,(128+w*16)*o,1,1)
			else Sound(0,(168+(w-3)*24)*o,1,1)
		Else
			o>>=3;
			if(w<3)Sound(0,(136+w*16)*o,1,1)
			else Sound(0,(180+(w-3)*24)*o,1,1)
		EndIf
	Loop
	SDLQuit
ENDMAIN