Spis treści

„Hello world!” w MUI


Okno programu.

Oto okno przykładowego programu w MUI. Program jest bardzo prosty, okno zawiera tylko jeden obiekt tekstowy i żadnych gadżetów, oprócz tych na ramce. Ilość gadżetów znajdujących się po prawej stronie górnej belki okna zależy od ustawień MUI. Kod źródłowy tego programu jest również bardzo prosty i mieści się w 60 liniach, licząc również puste linie zwiększające jego przejrzystość. W artykule kod jest rozbity na części, aby tekst był łatwiejszy w czytaniu. Dostępna jest też pełna wersja kodu gotowa do skompilowania.

#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.