Czas chyba zostawić dekoracje (co prawda potraktowane nieco po macoszemu) i zająć się czymś ciekawym. Dzisiaj na tapecie: Menu.
Właśnie otworzyłem sobie w Vimie manual fvwm żeby niczego nie przeoczyć... BTW, zastanawiam się nad podpięciem vima jako pierwszoplanowej przeglądarki manuali. Jest duużo fajniejszy od pinfo, czytanie manuali przez plugin man.so jest naprawdę przyjemne...
ale wracam do tematu. Menu. Najpierw lista poleceń związanych z obsługą menu w tym WM:
AddToMenu
Polecenie AddToMenu tworzy nowe menu, albo dodaje kolejne pozycje do menu już istniejącego. Prosty przykład:
AddToMenu MojeMenu + "Mój terminal" Exec exec xterm + "Mój edytor" Exec exec gvim
Taka konstrukcja zdefiniuje proste menu o nazwie "MojeMenu". Zawierać będzie 2 pozycje nazwane "Mój terminal" i "Mój edytor". Składnia jest, myślę, bardzo prosta. Tutaj po raz kolejny widać sławne fvwm-owskie "+ " służące do zestawiania list instrukcji. Przy okazji dekoracji o tym nie powiedziałem, więc powiem to teraz - instrukcje "+ " nie muszą występować w nieprzerwanym ciągu. Mógłbym np. wpisać coś takiego:
AddToMenu MojeMenu + "Mój terminal" Exec exec xterm Exec mozilla + "Mój edytor" Exec exec gvim
A zdefiniowane menu by było takie same, jak w pierwszym przypadku (2 pozycje). "+ " po prostu pamięta konstrukcję, do której ostatnio miał przynależeć.
Mamy teraz menu. Wyświetlić je można poleceniem "Menu" lub "Popup". Jedyna ważna różnica między nimi to to, że polecenie "Popup" nadaje się do wywołania z innego menu. No dobra, "Menu" też się nada. Tyle że "Menu" nie wygeneruje menu "wyskakującego", i przy otworzeniu zniszczy poprzednie menu. Jeśli to brzmi zamotanie, to po prostu wypróbujcie obydwie kombinacje. Hmm... właśnie "odkryłem", że można wygenerować rekursywne menu :)
Obsługa menu jest bardzo rozbudowana. Składnia Menu/Popup wygląda w sumie tak:
Menu/Popup nazwa_menu [pozycja] [funkcja_specjalna]
Opcjonalne argumenty: "pozycja" to po prostu określenie pozycji menu, też zresztą jeszcze bardziej rozbudowana, bo trzeba najpierw podać kontekst (Button/Window/RootWindow/This/Icon/Mouse/(...)), potem offset lewego górnego narożnika menu od tego kontekstu, przy czym offset można też definiować jako zależny od obiektu, no i dodatkowo można tutaj przeforsować kilka opcji definiowanych w innych miejscach... powiedzmy po prostu, że jest to bardzo, bardzo złożone i elastyczne. Domyślne zachowanie to menu pojawiające się pod myszą.
Funkcja specjalna to funkcja, która ma się wykonać jeśli menu zostało wywołane przez podwójne kliknięcie lub podwójne naciśnięcie klawisza.
Ok, a teraz może żeby sobie ułatwić pokazywanie testowego menu:
Key F1 A A Menu MojeMenu
I może jakieś bardziej skomplikowane zrobimy:
DestroyMenu MojeMenu AddToMenu MojeMenu + Title MojeMenu + XTerm%xterm.png% Exec exec xterm -rv + "" nop + %xterm.png%rxvt Exec exec rxvt + Rekursja Popup MojeMenu + Mo–zilla Exec mozilla -splash + "\"Zniknij\" menu" nop + Titile "Dolny Tytuł"
No, ładnie :) To krótki przykład, ale pokazuje od razu kilka rzeczy: Po pierwsze, najpierw niszczymy stare menu. To dobry nawyk. Wszędzie tam, gdzie określamy jakąś nową dekorację, funkcję, menu czy cokolwiek innego warto jest użyć najpierw funkcji DestroyDecor, DestroyFunction czy DestroyMenu aby być pewnym, że pracujemy z absolutnie czystą strukturą. Zwłasza w przypadku funkcji może to nam oszczędzić kłopotów, bo wtedy często nie widać od razu że w ciele funkcji mamy jakiegoś pasażera na gapę. A, skoro jestem przy DestroyMenu. Istnieje tego drugi wariant - "DestroyMenu recreate MojeMenu" - usuwa on tylko zawartość menu, ale samo menu pozostaje. Używa się tego przede wszystkim w menu, które niszczy i redefiniuje samo siebie, dzięki temu po zniszczeniu tak naprawdę nie znika.
Potem mamy "+ Title MojeMenu" - to polecenie dodaje tytuł do menu. Dodaje go zawsze na aktywnej pozycji, dzięki czemu możliwe jest stworzenie menu w którym tytuły będą się przeplatały z "normalnymi" pozycjami. A, jeszcze coś - istnieje sposób by jednak kazać upchnąć tytuł na szczytowej pozycji, obojętnie jak długie by nasze menu już nie było - do definicji tytułu trzeba dokleić słówko "top", np.
+ Titile "Dolny Tytuł" Top
by zamazało górny tytuł.
Następna linijka: "+ XTerm%xterm.png% Exec exec xterm -rv". Tutaj występuje notacja %foobar%. Tak określa się ikonkę dla pozycji menu. Wystarczy umieścić taki zapis w etykiecie pozycji, a fvwm doda do niej odpowiedni obrazek. Wolno pominąć tekst etykiety, wtedy pozostanie jedynie ikonka. Wolno też użyć dwóch ikonek dla jednej etykiety - zostaną wtedy rozmieszczone po lewej i prawej stronie. Jeśli zamiast "%" użyje się "*", to obrazek zostanie umieszczony ponad pozycją, a nie obok niej. Aby użyć w etykiecie znaku "%" czy "*", należy go zdublować, czyli użyć "**" lub "%%"
Następna linijka:
+ "" nop
To, po prostu, separator. Tak się go definiuje. Pusta etykietka i wywołanie funkcji "nop", która nic nie robi. Następnie wywołanie rxvt, a potem stworzenie sub-menu pod nazwą "Rekursja".
Następna linijka (+ Mo–zilla Exec mozilla -splash) pokazuje jak definiować "akceleratory", czyli po prostu klawisze skrótu. Wystarczy literkę "skrótu" poprzedzić znaczkiem "–". Tutaj mała uwaga - absolutnie dopuszczalne jest występowanie kilku identycznych skrótów w obrębie jednego menu, np.
+ –xterm Exec exec xterm + r–xvt Exec exec rxvt
w takim wypadku naciskanie "x" będzie jedynie przełączało focus pomiędzy tymi pozycjami, ale nie wybierze automatycznie pierwszej pasującej. Więc nie trzeba się obawiać konfliktów skrótów.
Następna pozycja (+ "\"Zniknij\" menu" nop) pokazuje jak ważne jest używanie pustej etykiety przy definiowaniu separatorów. Bo tutaj mimo użycia nop nie powstanie gustowny separator, ale klikalna pozycja. Tyle że wywołująca pustą funkcję (czy też "masło" lub "mydło", jeśli obracamy się w klimatach kultu domino ;) Pozycję tę nazwałem tak, a nie inaczej, gdyż może służyć właśnie do "znikania" menu.
A na koniec wstawiłem już wspomniany dodatkowy tytuł.
A więc, jak widać, jest to bardzo proste. Za pomocą AddToMenu definiuje się skład menu, określa tytuły, etykiety, ikonki, i funkcje do wykonania. Funkcje mogą być oczywiście dowolne, tutaj używałem tylko "Exec", ale można podłożyć tam cokolwiek co fvwm jest w stanie zinterpretować. A, byłbym zapomniał - można do menu dodać coś zwanego "side pixmap", na screenshotach z "FVWM trailer" widać to w moim menu. Taką piksmapę definiuje się za pomocą @foobar@ w nazwie menu. Czyli np.
AddToMenu MyMenu@my_side_pixmap.xpm@
Dobrze... więc o czym już powiedziałem? Tworzenie menu było, niszczenie było, ikonki były, skróty klawiaturowe też... w sumie z podstaw było już wszystko... no to przejdźmy teraz do "kustomizacji" wyglądu i zachowania menu.
MenuStyle
Polecenie MenuStyle dla menu tym, czym AddToDecor dla okien. Definiuje szablony ich wyglądu. Szablon można zniszczyć poleceniem DestroyMenuStyle.
Składnia to: MenuStyle nazwa_stylu opcje_stylu
Nazwa stylu jest wybierana w pełni dowolnie. Jeśli jako nazwy użyje się "*", to zmieniany będzie styl domyślny, czyli styl tych wszystkich menu którym nie pookreślaliśmy wyraźnie żadnego stylu. Acha, i stylu "*" nie można zniszczyć za pomocą DestroyMenuStyle.
Lista opcji:
- Fvwm/Mwm/Win
- Coś jak makro, które ustawia predefiniowany zestaw opcji aby zaemulować zachowanie fvwm/mwm/windows
- BorderWidth
- Grubość ramki dookoła menu
- Foreground/Background
- Kolor fontu/kolor tła
- Greyed
- Kolor fontu dla pozycji, która jest "niedozwolona". Np. jakaś aplikacja może, za pomocą MWMHints zażądać, by nie robiono na niej "minimize", i jeśli menu operacji na oknie będzie zawierało taką funkcję to pojawi się ona "wygaszona" kolorem tutaj zdefiniowanym.
- HilightBack/HilightBackOff
- Kolor podświetlenia tła dla aktywnej pozycji. Albo wyłączenie podświetlania.
- ActiveFore/ActiveForeOff
- Podobnie jak powyższe, tyle że odnosi się do koloru fontu.
- MenuColorset
- Jak foreground/background, tyle że używa kolorsetu.
- ActiveColorset
- Jak ActiveFore, tyle że kolorset.
- GreyedColorset
- j.w.
- Hilight3DThick/Hilight3DThin/Hilight3DOff
- Grubość obramowania 3D wybranej pozycji menu, 2 stopnie lub wyłączona.
- Hilight3DThickness
- To samo, tyle że definiowane w pikselach. Można użyć argumentu ujemnego, wtedy obramowanie jest rysowane wypukłe.
- Animation/AnimationOff
- Kiedy menu wyłazi poza ekran, może w sposób animowany zostać przesunięte. Polecam to, bo menu które przesuwa się bez animacji może być bardzo mylące.
- Font
- Wiadomo, font.
- MenuFace
- Piksmapa dla tła w menu. Staroć, odkąd kolorsety to umieją stała się ta opcja jakby zbyteczną.
- PopupDelay
- Wiadomo, ile milisekund fvwm ma czekać z automatycznym pokazaniem submenu. Jeśli ustawi się na zero, to trzeba będzie kliknąć.
- PopupOffset
- Offset dla rozwijanych submenu. Domyślnie nakładają się częściowo na menu macierzyste, ale można to zmienić (vide screenshot z "FVWM trailer")
- TitleWarp/TitleWarpOff
- Czy przy otwieraniu menu mysz ma być przenoszona do tytułu? (Warto brać poprawkę na to, że przy obsłudze z klawiatury fvwm i tak potrafi "wrócić" kursor na miejsce, z którego go zabrał, więc ta opcja niekoniecznie jest upierdliwa. Choć i tak IMO jest bez sensu i przeszkadza)
- TitleUnderlines0/TitleUnderlines1/TitleUnderlines2
- Ile linii ma być rysowanych pod tytułem w menu.
- SeparatorsLong/SeparatorsShort
- Czy separatory w menu mają być krótkie czy długie?
- TrianglesSolid/TrianglesRelief
- Rodzaj trójkącików w pozycjach rozwijanych. Albo "wypełnione", albo puste.
- PopupImmediately/PopupDelayed
- "Main switch" dla PopupDelayed. Kiedy ustawi się PopupImmediately to PopupDelay nie jest w ogóle brane pod uwagę.
- PopdownImmediately/PopdownDelayed
- Opóźnienie w znikaniu submenu jeśli kursor z niego wyskoczy. Wygodne w przenoszeniu myszy do submenu po skosie, kiedy to w niektórych systemach submenu radośnie znika. Miałem gdzieś namiary na stronę jakiegoś mac-fana który walnął referat na siedem stron A4, z obrazkami, dokumentujący dlaczego MacOS X jest cool, a Windows lame, biorąc pod uwagę właśnie tylko tę opcję. To zachowanie ma nawet jakąś specjalną nazwę w języku speców od UI... nieważne, fvwm to ma. A, i zachowanie jest zawsze w pewnym stopniu dopasowywane do tego, czy akurat nawigujesz po menu myszą czy klawiaturą.
- PopupActiveArea
- Automatyczne rozwijanie submenu w zależności od tego, jak blisko "trójkącika" znajduje się kursor myszy. Przyjmuje wartości od 51 do 100, i oznaczają one procentową szerokość menu. Właśnie opcje takie jak ta upewniają mnie w przekonaniu, że fvwm jest tworzone przez Obcych.
- DoubleClickTime
- No, wiadomo.
- SidePic
- To samo, co @foobar@ w nazwie menu.
- SideColor
- Ustawia kolor do użycia w kolumnie z SidePic. Vide screenshot z trailera, ten żółty pasek to właśnie to.
- PopupAsRootMenu/PopupAsSubmenu
- Skomplikowane dosyć w opisie. W pierwszej linii decyduje o tym, czy po kliknięciu na pozycji submenu owo submenu otworzy się jako menu-dziecko, połączone z menu-matką, czy też ubije menu-matkę i otworzy się samodzielne.
- RemoveSubmenus/HoldSubmenus
- Czy usuwać submenu gdy kursor wrócił do menu nadrzędnego.
- SubmenusRight/SubmenusLeft
- Łatwo się domyślić.
- SelectOnRelease
- Jeśli ten klawisz zostanie *puszczony*, to zostanie wybrana aktywna pozycja z menu. Wymyślone na potrzeby alt+tab.
- VerticalItemSpacing
- Przyjmuje dwa parametry liczbowe, które decydują o liczbie linii odstępu (w pikselach) ponad i pod pozycją w menu. Używanie ujemnych wartości może "ścieśnić" menu albo w ogóle rozwalić jego layout (gdy opcje zaczną się na siebie nakładać)
- VerticalTitleSpacing
- To samo, tyle że dotyczy tytułów.
- AutomaticHotkeys/AutomaticHotkeysOff.
- Jeśli włączone, fvwm automatycznie dodaje "skrót" do każdej pozycji w menu. Wybiera do tego celu zawsze pierwszą literę etykiety. Oczywiście można to przeforsować własnoręcznie wpychając znaczki "–" tam, gdzie trzeba.
- ItemFormat
- Noo... tego się najbardziej bałem. To po prostu "format string" dla pozycji menu. Nie będę opisywał, bo to trochę jak opisywanie printf(). Z tym że ItemFormat przyjmuje nieco mniej parametrów. Można tym ustalić położenie ikonek, tekstu, obszar podświetlany przy aktywacji, odstępy między tymi obiektami z dokładnością do 1 piksela, itp. Opcja dla stukniętych fvwm-świrów ("Ta cholerna ikonka jest o piksel za dalego od etykiety! Zaraz oszaleję jeśli tego nie poprawię!") albo Ludzi z Tajnym Planem Działania.
Uff... definiowanie wyglądu menu uznaję za odwalone. Zainteresowani będą siedzieć w manach i FvwmConsole przez kilka godzin żeby to sprawdzić w praktyce :)
A ja lecę z resztą koksu:
ChangeMenuStyle menustyle menu menu2 menu3 ...
To polecenie pozwala przypisać jakiś styl utworzony przez MenuStyle konkretnemu menu, czy też od razu większej ich ilości.
CopyMenuStyle oryginalny-menustyle replika-menustyle
A to powoduje zreplikowanie jakiegoś stylu, żeby np. dodać do niego jakiś boczny obrazek czy zmienić nieco jego format, bez potrzeby zbędnego wklepywania jeszcze raz już zdefiniowanych w innym stylu opcji.
DestroyMenuStyle menustyle
Wiadomo, posyła wystrój menu do /dev/null.
Mogę z radością zakomunikować, że więcej poleceń operujących bezpośrednio na menu *nie* ma. Hurrej! Teraz zostaje już tylko strona praktyczna - każdy może sobie stworzyć własne menu. Moja prywatna konfiguracja menu to:
MenuStyle * Font xft:Arial-13, HilightBackOff, ActiveFore white,\ Hilight3dOff, Animation, PopupOffset 0 100, TitleWarpOff,\ TitleUnderlines2, SeparatorsShort, SideColor yellow, AutomaticHotkeys,\ Background #b1bdc9
Na co warto zwrócić uwagę? Po pierwsze, na samą specyfikę menu - gdy jest za długie, to pojawia się pozycja "More... >" i można rozwinąć obok dalszą część menu (można to zrobić od razu klawiszem "Insert"). To, że menu zawsze starają się mieścić na ekranie, to, że wielkość ikonek których można użyć w menu jest nieograniczona. To, że każde menu/submenu ma własną nazwę, a co za tym idzie można mu przypisać inny styl - inne tło, inny font, inny "format string".
Do tego warto zwrócić uwagę na bardzo fajną obsługę z klawiatury - jest bardzo intuicyjna, klawisze home/end/pgup/pgdn, esc, insert, C-g. Acha, klawiszem <backspace> menu zamienia się w pełnoprawne okienko, z ramką etc. Coś jak oderwanie menu w gtk czy też "utrwalanie" okienka w blackbox/E/WindowMaker. Zamiast backspace można też po prostu kliknąć środkowym przyciskiem myszy na tytule menu.
I, na koniec, to co najlepsze - definiowanie menu przez zewnętrzne programy i redefiniujące się menu. Np. menu do wyboru tapety zawierające w przeciwieństwie do WindowMakera także miniaturki tapet, albo aktualizujące się przy każdym otwieraniu menu ze spisem dokumentów OpenOffice, posortowanych według daty ostatniej zmiany i podzielonych w submenu "Writer", "Calc" etc. Albo jeszcze co innego. Ale to temat na osobną bajkę.
Kto ma Pytania? Co trzeba dokładniej omówić?
(W następnym odcinku będzie chyba o układaniu ikonek na pulpicie, trochę kombinacji z myszą i pewnie o poleceniu "Style")