Wiele interfejsów dla jednej aplikacji, podobne interfejsy dla wielu aplikacji
17.09.2014 | aktual.: 18.09.2014 12:52
Wprowadzenie
UWAGA: Przedstawiana biblioteka jest w fazie pre‑alfa. Korzystasz na własne ryzykoLibgreattao do biblioteka szablonów UI mojego autorstwa. Można ją uważać za połączenie wxWidgets, XUL i XSLT. Jednak w niej, to nie twórca aplikacji definiuje interfejs, a zamiast niego robią to twórcy systemu i użytkownicy. Programista jedynie publikuje zestaw dostępnych funkcjonalności i określa klasę okien. Po określeniu funkcjonalności biblioteka z użyciem szablonów dla danej klasy okna tworzy interfejs. To w szablonie są zdefiniowane widżety.
Libgreattao może korzystać z wielu backendów, lecz obecnie wspierany jest tylko dla GTK+2. W przyszłości zamierzam stworzyć dla Qt5 i ncurses.
Biblioteka nie jest jeszcze bezpieczna dla wątków. Przeznaczona jest jak narazie tylko dla 64 bitowych systemów.
Instalacja
Najpierw trzeba ściągnąć bibliotekę ze strony: http://slawek.lach.art.pl/Projekty/libgreattao.xhtml. Następnie trzeba ją skompilować.
Wchodzimy do katalogu z biblioteką, a następnie wydajemy polecenia.
make make -C Modules/common make -C Modules/GTK+ sudo make install make -C Demos
Użytkowanie
W katalogu Demos są proste aplikacje napisane przy użyciu libgreattao. Jak narazie funkcjonalne są tylo dwa: edytor.o i główny.o . Dla przykładu uruchomimy główny.o .
Demos/główny.o
Aplikacja wyświetla dialog zapytania, co zrobić. Akcje są podejmowane po kliknięciu przycisku, np. Exit powoduje wyjście z aplikacji.
A teraz magia.
Demos/główny.o --tao-design modern
Teraz nasze okno ma zupełnie inny interfejs. Mamy pole wyboru i przycisk ok. Akcja jest podejmowana po kliknięciu w przycisk ok na podstawie wybranego elementu z listy wyboru.
A oto kod naszej aplikacji:
#include "../main.h" #include "../tao_domain.h" int integer=1; int count = 0; void* Window; void callback(void *mesh, void *data) { if (data == (void *) 0) { tao_release_window(Window); exit(0); } else if (data == (void *) 1) { if (!fork()) { execlp("Demos/przyciski.o","Demos/przyciski.o",NULL); exit(1); } } else if (data == (void *) 2) { if (!fork()) { puts("2"); execlp("Demos/przyciski2.o","Demos/przyciski2.o",NULL); exit(1); } } else if (data == (void *) 3) { if (!fork()) { execlp("Demos/edytor.o","Demos/list.o",NULL); } } } int main(int argc, char *argv[]) { tao_initialize("tao demo", "Super", &argc, argv); Window=tao_new_window("/desktop/dialogs/question_dialog"); tao_add_handler(Window,"/message",&callback,3); tao_add_handler(Window,"/actions/exit",&callback,0); tao_add_handler(Window,"/actions/Button1",&callback,1); tao_add_handler(Window,"/actions/Button2",&callback,2); tao_add_handler(Window,"/actions/Button3",&callback,3); tao_set_hint(Window,"/message", HINT_DESCRIPTION, "Który program chcesz uruchomić??"); tao_set_hint(Window,"/actions/exit", HINT_NAME, "Exit"); tao_set_hint(Window,NULL, HINT_NAME, "Demonstrations"); tao_add_handler(Window,"/:abort",&callback,0); tao_handle_events(); };
Prawda, że mało tego kodu? Jak na aplikację oferującą dwa interfejsy jest to bardzo mało kodu. W dodatku nie ma tam żadnych widżetów.
Definiowanie własnego interfejsu użytkownika
Libgreattao szuka zestawu szablonów określonego przełącznikiem -‑tao-design (domyślnie mWidgets) w $HOME/.tao/common/design . Jeżeli go nie znajdzie, to szuka w /usr/tao-design . W przypadku braku możliwości załadowania plików z szablonami dla naszej klasy okna szuka go w /usr/tao-design/mWidgets.
Teraz dodamy przycisk exit dla okien zapytań w zestawie szablonów modern, ale tylko dla aplikacji dostarczających akcję exit.
- Tworzymy katalogi $HOME/.tao/common/design/modern
- Kopiujemy zawartość katalogu /usr/tao-design/modern do $HOME/.tao/common/design/modern
- Otwieramy plik $HOME/.tao/common/design/modern/desktop/dialogs/question_dialog Plik powinien mieć zawartość, jak poniżej, po czym zapisujemy go
<root> <label dir-for="label" path="/message" /> <label dir-for="description" path="/message" /> <custom:select> <template path="/actions/*"> <custom:select-item> <attr-connect name="label" function="last-dir" /> <handler> <var name="path" action="change" function="path" /> </handler> </custom:select-item> </template> </custom:select> <hbox> <button label="ok"> <handler> <call var="path" /> </handler> </button> <template path="/actions/exit"> <button label="cancel" dir-for="label,event" /> </template> </hbox> </root>
W pliku mamy cztery szablony. Dwa dla funkcji /message, które pozwalają wyświetlić nazwę /message i jej opis. Jeden jest dla akcji(/actions/*) i powoduje on, że akcje będą wyświetlane w menu rozwijalnym. Jeżeli spojrzeć na definicję tej klasy okna w zestawie szablonów mWidgets, zauważymy, że były tam definiowane przyciski. W dodatku w klasie dla mWidgets przyciski były połączone z domyślnym zdarzeniem dla przycisków. Tutaj mamy dwa handlery. Jeden zapisuje nam do zmiennej ostatnio wybraną akcję, a drugi(dla przycisku ok) wywołuje ostatnio wybraną akcję na podstawie tej zmiennej. Ostatnim szablonem jest szablon dla przycisku. Przycisk ten będzie wywoływał domyśne zdarzenie dla /actions/exit po kliknięciu. Domyślnie będzie mieć labelkę cancel, lecz to programista będzie mógł zmienić, gdyż w atrybucie dir‑for jest wartość label.
Interaktywna powłoka
Libgreattao pozwala na korzystanie z programów w trybie interaktywnej powłoki. Powłoka jak na razie jest bardzo prosta. Prawdę pisząc nie pozwala ona na tworzenie zmiennych.
Aby uruchomić program w trybie interaktywnej powłoki, używamy przełącznika -‑tao-shell-interactive.
Teraz uruchomimy nasz główny w trybie interaktywnej powłoki i wywołamy na pierwszym oknie klasy /desktop/dialogs/question_dialog akcję /actions/exit .
run /desktop/dialogs/question_dialog[1] /actions/exit
To już wszystko na dzisiaj.