"Hello world!" w MUI
From MorphOS Library
Grzegorz Kraszewski
Ten artykuł w innych językach: angielski
#include <proto/muimaster.h> #include <proto/intuition.h>
Zaczynamy od dołączenia plików nagłówkowych bibliotek muimaster.library i intuition.library. Warto zauważyć, że biblioteki te będą otwarte i zamknięte automatycznie.
Object *App, *Win;
Tutaj mamy globalne wskaźniki na obiekt aplikacji i obiekt okna. Trzymanie wskaźników do wielu obiektów MUI w zmiennych globalnych nie jest zbyt eleganckim stylem programowania, ale kilka to jeszcze nie tragedia, zwłaszcza w tak prostym programie.
Object* build_gui(void) { App = MUI_NewObject(MUIC_Application, MUIA_Application_Author, (ULONG)"Grzegorz Kraszewski", MUIA_Application_Base, (ULONG)"HELLOWORLD", MUIA_Application_Copyright, (ULONG)"© 2010 Grzegorz Kraszewski", MUIA_Application_Description, (ULONG)"Hello World in MUI.", MUIA_Application_Title, (ULONG)"Hello World", MUIA_Application_Version, (ULONG)"$VER: HelloWorld 1.0 (16.11.2010)", MUIA_Application_Window, (ULONG)(Win = MUI_NewObject(MUIC_Window, MUIA_Window_Title, (ULONG)"Hello World", MUIA_Window_RootObject, MUI_NewObject(MUIC_Group, MUIA_Group_Child, MUI_NewObject(MUIC_Text, MUIA_Text_Contents, (ULONG)"Hello world!", TAG_END), TAG_END), TAG_END)), TAG_END); }
Powyższa funkcja tworzy kompletne drzewo obiektów dla naszego programu. Główny obiekt jest klasy Application. Posiada obiekt podrzędny klasy Window. Okno z kolei posiada obiekt główny (ang. root object), który zawsze jest instancją klasy Group. Wreszcie grupa główna zawiera w sobie obiekt klasy Text. Przy tworzeniu obiektu aplikacji podano 6 atrybutów pełniących rolę opisową. Wartości tych artrybutów są wykorzystywane przez system w różnych miejscach. Znaczenie tych atrybutów wyjaśnione jest w dokumentacji klasy Application znajdującej się w pakiecie SDK. Znaczenie pozostałych atrybutów w sposób raczej oczywisty wynika z ich nazw, szczegóły są omówione w dokumentacji odpowiednich klas.
Sposób stworzenia interfejsu graficznego w tym programie jest typowy dla MUI. Kompletne drzewo obiektów jest tworzone w jdnym dużym wywołaniu funkcji MUI_NewObject() zawierającym w sobie zagnieżdżone podwywołania. Kolejność wywoływania funkcji jest odwrotna od kolejności czytania kodu. Na początku tworzone są najgłębiej zagnieżdżone obiekty, a otrzymane wskaźniki są podawane do konstruktorów obiektów nadrzędnych. Ostatnim tworzonym obiektem jest obiekt aplikacji. Ten sposób tworzenia drzewa obiektów zapewnia automatyczną obsługę błędów. Jeżeli którykolwiek konstruktor nie będzie w stanie stworzyć obiektu, jego wynikiem będzie wskaźnik zerowy (NULL). Wskaźnik ten zostanie przekazany do konstruktora obiektu nadrzędnego, co automatycznie spowoduje błąd konstrukcji i również zwrócenie NULL-a, oraz zniszczenie tych obiektów podrzędnych, które udało się stworzyć do momentu błędu. Ostatecznie wskaźnik zerowy dotrze do konstruktora obiektu aplikacji, również powodując jego błąd i zwrócenie NULL-a przez główne wywołanie MUI_NewObject(). W efekcie drzewo obiektów aplikacji może mieć po konstrukcji tylko dwa stany: albo jest w pełni zbudowane, albo nie jest w ogóle zbudowane, a wszystkie obiekty zostały prawidłowo zniszczone. To w zasadniczy sposób upraszcza obsługę błędów.
void notifications(void) { DoMethod(Win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit); }
Następny krok to ustawienie notyfikacji. Ten prosty przykład zawiera tylko jedną notyfikację, kończącą program po kliknięciu gadżetu zamknięcia okna. MUI mapuje kliknięcie lewym przyciskiem myszy w gadżet zamknięcia okna na zmianę wartości atrybutu MUIA_Window_CloseRequest. Celem notyfikacji jest obiekt aplikacji, metoda MUIM_Application_ReturnID() przekazuje podany identyfikator do głównej pętli programu.
void main_loop(void) { ULONG signals = 0; set(Win, MUIA_Window_Open, TRUE); while (DoMethod(App, MUIM_Application_NewInput, &signals) != MUIV_Application_ReturnID_Quit) { signals = Wait(signals | SIGBREAKF_CTRL_C); if (signals & SIGBREAKF_CTRL_C) break; } set(Win, MUIA_Window_Open, FALSE); }
Typowa pętla główna została omówiona w poprzednim rozdziale. Jedyną nowością jest otwarcie okna przed wejściem w pętlę i zamknięcie po wyjściu z niej.
int main(void) { App = build_gui(); if (App) { notifications(); main_loop(); MUI_DisposeObject(App); } return 0; }
Na koniec główna funkcja programu. Na początku tworzone jest drzewo obiektów, po czym następuje sprawdzenie czy tworzenie drzewa zakończyło się sukcesem. W przypadku błędu program natychmiast kończy swoje działanie. Jeżeli interfejs graficzny został stworzony poprawnie, ustawiane są notyfikacje, a następnie program wchodzi do głównej pętli. Po zakończeniu tejże obiekt aplikacji jest niszczony, co automatycznie powoduje zniszczenie również wszystkich obiektów podrzędnych.