Titanium Desktop – problemy z menu na OS X

Titanium to bardzo przyjemne narzędzie, kiedy osoba taka jak ja – przyzwyczajona na codzień do budowania interfejsów w HTML5 i wytrenowana w JavaScripcie musi szybko postawić aplikację na desktop, czy mobile. Niestety, nie jest to rozwiązanie pozbawione wad – nie mamy bezpośredniego dostępu do systemowego API, możemy jedynie polegać na developerach z Appcelerator i liczyć na to, że nie zapomnieli o dodaniu funkcjonalności, której właśnie potrzebujemy. Niestety, nie zawsze tak jest.

Ostatnio, miałem za zadanie przygotować prosty widget na pulpit, wyświetlający użytkownikowi codziennie losową poradę. Projekt na tyle banalny, że nie wart przesiadania się na Visual Studio i C# aby przygotować wersję na Windows, a następnie zabawy w Cocoa i praktycznie przepisywanie całości od zera. Mam delikatne uczulenie na Adobe AIR – po co zmuszać użytkowników do instalacji całego środowiska uruchomieniowego tylko po to, aby na ich pulpitach raz dziennie wyskakiwał radosny stworek z poradą? Dlatego zapadła decyzja – działamy pod Titanium. To był dobry wybór – po jednym dniu roboczym aplikacja była gotowa. Prawie.

Titanium a menu w Mac OS X

Temat ogarnięcia menu aplikacji zostawiłem sobie na sam koniec – w sumie, widget nie wymagał żadnego menu, poza pozycją „Zamknij”. Domyślnie, aplikacja wypuszczona z Titanium pod OS X ma menu składające się z „File”, „Window”, „Help” – których nie potrzebowałem. Dlatego postanowiłem je usunąć. Szybki rzut okiem na dokumentację:

1
var menu = Titanium.UI.getMenu();

powinno załatwić sprawę. A więc, zgodnie z dokumentacją robię:

1
menu.clear();

…i nic. O co chodzi? Gdzie jest menu?

1
console.log(menu.getLength());

Rzut okiem w logger – o zgrozo, zwraca 0. Szybkie googlanie, jest wątek na bugtrackerze. Szajse. Temat nie ruszony od pół roku. Do domyślnego menu pod OS X nie ma dostępu. Możemy dodać swoje pozycje do menu, ale nie możemy go wyczyścić.

Rozwiązanie

Całe szczęście, pakiety .app można otworzyć pod makiem. Rozwiązaniem problemu jest podmiana pliku MainMenu.nib w pakiecie. Aby się do niego dostać, należy kliknąć prawym przyciskiem myszy na pliku YOUR_APP.app w katalogu /dist/osx/ projektu i wybrać „Pokaż zawartość pakietu”. Następnie, udajemy się do Contents/Resources/English.lproj/.

Pliki te tworzone edytować można przez Interface Buildera z pakietu XCode. Aby pozbyć się niechcianego menu, podmieniamy MainMenu.nib na nasz.

Ok, tylko że podmiana MainMenu.nib w pakiecie po każdej kompilacji może doprowadzić człowieka do rozpaczy. Na szczęście, wystarczy dodać go do katalogu Resources projektu :) Przy kompilacji Titanium pakuje do pakietu nasz śliczny, pusty plik menu, OS X sobie z tym pięknie radzi.

BONUS: polskie znaczki w nazwie projektu

Wszystko działa pięknie, niestety projekt który realizowałem miał „ż” w tytule. Spróbowałem w tiapp.xml ustawić piękny, polskojęzyczny tytuł. Kompilacja – i bum, błąd. Kompilator nie radzi sobie z łyknięciem czegokolwiek innego niż czyste ASCII. Zostawiłem więc „z” zamiast „ż” w tiapp.xml, natomiast coś trzeba było zrobić z tytułem, który trafia do menu. Pod Windows nie ma problemu, wystarczy z poziomu kodu dobrać się do okienka:

1
2
var w = Titanium.UI.getCurrentWindow();
w.setTitle("Bździągwa");

i viola!

Natomiast, pod makiem trzeba znów pohakować. W pakiecie .app znajduje się plik Info.plist, a w nim pozycja „CFBundleName”. Musimy ją edytować – tu możemy korzystać z polskich znaków do woli, UTF8 jest obsługiwany. Niestety, plik ten nie znajduje się w katalogu Resources, więc trik z automatyczną podmianą przy kompilacji nie zadziała. Trzeba go podmieniać ręcznie przed wypuszczeniem aplikacji do klientów. I tu uwaga, nie zadziała też automatyczne utworzenie pakietu dmg. Musimy go przygotować samemu. Osobiście, przygotowałem sobie zmieniony plik Info.plist i dodałem do katalogu z projektem, szybkie

1
cp Resources/Info.plist dist/osx/APPLICATION_NAME.app/Contents/Info.plist

załatwia sprawę.

Powodzenia!