// obsluga myszy w ekg
// (c) 2006 adam wysocki <gophi@ekg.chmurka.net>

1. wstep
2. aktualne bindingi
3. terminologia
4. struktury i typy danych
5. rozpoznawane zdarzenia przyciskow
6. interfejs
7. przyklad uzycia
8. do zrobienia

1. wstep

obsluga myszy w ekg jest na razie wstepnym, eksperymentalnym frameworkiem 
do dalszego obudowania, dzialajacym tylko w interfejsie ncurses. ten plik 
zawiera opis aktualnych bindingow (czyli obszarow, w ktore mozna kliknac 
lub na ktorych mozna wykonac gesty) oraz developerski opis, przydatny 
podczas dodawania obslugi myszy do kolejnych elementow ekg. gdyby cos 
z niego bylo nie do konca jasne albo dwuznaczne, nalezy napisac na 
ekg-users (adres znajduje sie na stronie ekg). poprawki mile widziane.

jesli nie jestes zainteresowany rozwijaniem obslugi myszy w ekg, a jedynie 
jej uzywaniem, to rozdzial "aktualne bindingi" jest jedynym, ktory powinienes 
przeczytac.

2. aktualne bindingi

aktualne przyporzadkowania zdarzen myszy. gest to przesuniecie myszy 
podczas trzymania ktoregos przycisku. jesli nie zostalo okreslone 
inaczej, gest mozna wykonac trzymajac lewy lub prawy przycisk. lpm 
to lewy przycisk myszy, ppm - prawy.

obszar			| zdarzenie		| polecenie lub opis
------------------------+-----------------------+-------------------
header			| klikniecie		| /list <osoba>
header			| podwojne klikniecie	| /find <osoba>
statusbar: zegar	| klikniecie		| /exec ^date
statusbar: uin, nick	| klikniecie		| /status
statusbar: uin, nick	| prawe klikniecie	| /find <uin>
statusbar: query	| klikniecie		| /list $
statusbar: query	| prawe klikniecie	| /find $
statusbar: more		| klikniecie		| Page Down
statusbar: win/numer	| klikniecie		| /window list $
statusbar: act/numer	| klikniecie		| /window list <numer_okna>
statusbar: act/numer	| podwojne klikniecie	| /window switch <numer_okna>
rozmowa			| gest w lewo		| /window prev
rozmowa			| gest w prawo		| /window next
rozmowa			| gest w gore		| /window last
rozmowa			| gest w dol z lpm	| /window oldest
rozmowa			| gest w dol z ppm	| /window active

3. terminologia

- zdarzenie myszy (mouse_event): zmiana wartosci zmiennej mouse, zdarzenie 
  przycisku myszy lub prosba o zwolnienie pamieci ze strukturami. NIE jest 
  tozsame ze zdarzeniem myszy w man mouse z ncurses. wszystkie zdarzenia 
  myszy sa obslugiwane w funkcji mouse_event().

- zdarzenie przycisku myszy (bevent): klikniecie, podwojne klikniecie, 
  potrojne klikniecie, wcisniecie lub puszczenie przycisku. zdarzenia 
  przyciskow myszy sa obslugiwane przez odpowiednio dodane handlery.

- gest myszy: jest rozpoznawany, gdy przesuniemy mysz trzymajac ktorys 
  przycisk. gesty stworzone zostaly na podstawie obslugi myszy w irssi 
  (http://wouter.coekaerts.be/site/irssi/mouse) z ta roznica, ze kierunek 
  jest obliczany nastepujaco:
  - odleglosc_x > 2 * odleglosc_y: kierunek poziomy
  - odleglosc_y > 2 * odleglosc_x: kierunek pionowy
  - pozostale: gest nierozpoznany

4. struktury i typy danych

- mouse_area_t - opisuje jeden konkretny obszar na ekranie. obszar jest 
  prostokatem zdefiniowanym przez polozenie lewego gornego rogu oraz 
  szerokosc i wysokosc. struktura zawiera takze polozenie prawego dolnego 
  rogu, ustawiane przez funkcje obslugi myszy. obszar moze, ale nie musi, 
  miec taki sam rozmiar jak ktores okno (np. header albo statusbar). oprocz 
  tego kazdy obszar ma swoja nazwe - przydatne do lepszej identyfikacji 
  w oknie debugowania i podczas zmiany rozmiaru okna.

- mouse_coords_t - struktura opisujaca koordynaty punktu na ekranie lub 
  w obszarze. zawiera zmienne x (numer kolumny) i y (numer wiersza). lewy 
  gorny rog ma koordynaty 0,0.

- mouse_bevent_t - struktura na liscie w mouse_area_t. opisuje zdarzenie 
  przycisku dla obszaru, do ktorego nalezy (wartosc zdarzenia okreslajaca, 
  ze np. zostal podwojnie klikniety ktorys przycisk i wskaznik do handlera 
  mouse_handler_t, ktory obsluzy to zdarzenie).

- mouse_handler_t - wywolywane do obslugi zdarzenia. dostaje maske przycisku 
  (mmask_t) i wskaznik do opisu koordynatow (mouse_coords_t). maska przycisku 
  moze sie przydac, gdyby ktos chcial podpiac kilka zdarzen przycisku do 
  jednego handlera (podobnie jak signo w sighandlerach). koordynaty mierzone 
  sa wzgledem poczatku obszaru (a nie ekranu lub okna). handler niczego nie 
  zwraca.

5. rozpoznawane zdarzenia przyciskow

jak w man 3ncurses mouse:

- BUTTONx_PRESSED: przycisk zostal wcisniety i jest trzymany
- BUTTONx_RELEASED: przycisk zostal puszczony
- BUTTONx_CLICKED: przycisk zostal klikniety
- BUTTONx_DOUBLE_CLICKED: przycisk zostal podwojnie klikniety
- BUTTONx_TRIPLE_CLICKED: przycisk zostal potrojnie klikniety

x moze przyjmowac wartosci od 1 do 5 (dla NCURSES_MOUSE_VERSION == 1 tylko 4). 
dla normalnych myszek 1 to lewy, 2 srodkowy a 3 prawy przycisk. oprocz tego, 
jesli numer zdarzenia jest zORowany z BUTTON_CTRL, BUTTON_SHIFT lub BUTTON_ALT, 
oznacza to zdarzenie przy wcisnietym ktoryms z tych klawiszy.

dodajac button eventy powinno sie pamietac, ze:

- niektore terminale maja jakies alternatywne funkcje dla klikniec z ktoryms 
  z klawiszy ctrl, shift lub alt i nie przekazuja takiego klikniecia do 
  programu.

- nie kazdy posiada srodkowy przycisk myszki lub emulacje przez wcisniecie 
  obu przyciskow.

6. interfejs

- mouse_event() - obsluguje zdarzenia myszy
- mouse_bevent_add() - dodaje button event do obszaru
- mouse_area_add() - dodaje obszar do listy
- mouse_area_find() - znajduje obszar po nazwie
- mouse_area_del() - usuwa obszar z listy
- mouse_area_move() - przesuwa obszar
- mouse_area_resize() - ustawia nowy rozmiar obszaru
- mouse_in_area() - sprawdza czy punkt nalezy do obszaru

wskazniki, ktore dostaja te funkcje, nie musza byc alokowane - moga 
wskazywac na obiekty lokalne dla wywolujacej funkcji.

mouse_bevent_add() powinno byc wywolywane na lokalnej strukturze, 
a dopiero po wszystkich mouse_bevent_add() powinno zostac wywolane 
mouse_area_add().

mouse_area_resize() jest przydatne podczas zmiany rozmiaru okna, np. 
po dostaniu przez leb sigwinchem albo zmianie wartosci ktorejs zmiennej.

7. przyklad uzycia

gdyby ktos chcial bardziej czytelnie, niz w zrodlach ekg, dla 
hipotetycznego obszaru "test":

static void mouse_bevent_test (struct mouse_coords_t *coords, mmask_t bstate)
{
	if (bstate == BUTTON1_CLICKED) {
		// ...
	}  else if (bstate == BUTTON1_DOUBLE_CLICKED) {
		// ...
	}
}

...()
{
	struct mouse_area_t a;

	a.name = "test";
	a.start.x = a.start.y = 0;
	a.size.x = a.size.y = 10;
	a.bevents = NULL;
	mouse_bevent_add(&a, BUTTON1_CLICKED, mouse_bevent_test);
	mouse_bevent_add(&a, BUTTON1_DOUBLE_CLICKED, mouse_bevent_test);
	mouse_area_add(&a);
}

nie trzeba sie troszczyc o zwalnianie niczego, mouse_event("destroy") zrobi 
to sama, jednak trzeba pamietac zeby przed pierwszym mouse_bevent_add() pole 
bevents bylo rowne NULL. pole name nie musi byc zaalokowane - zostanie 
zaalokowane przez mouse_area_add().

8. do zrobienia

- mozliwosc oskryptowania myszy w pythonie
- mozliwosc bindowania beventow przez uzytkownika (/mouse_bind?)
  - -a: przypisanie akcji do pary obszar,zdarzenie
  - -d: usuniecie akcji dla podanej pary obszar,zdarzenie
  - [-l]: wylistowanie przypisanych akcji
  - -L: wylistowanie przypisanych oraz domyslnych akcji
  - konkurs na nazwe dla pary obszar,zdarzenie :)
  - definicje:
    - obszar (w nawiasie znaczenie parametru)
      - current (konkurs na lepsza nazwe dla obszaru current_window :))
      - contacts ($1: nick)
      - header (naglowek jako calosc)
        - header:query_ip ($1: ip)
        - header:query_descr ($1: opis)
      - status (pasek stanu jako calosc)
        - status:time
        - status:uin
        - status:nick
        - status:more
        - status:query
        - status:window
        - status:act ($1: numer okna)
        - status:query_ip ($1: ip)
        - status:query_descr ($1: opis)
    - zdarzenie (przycisk-czynnosc)
      - przycisk
        - left
        - middle
        - right
      - czynnosc
        - click
        - double_click
        - triple_click
        - gesture_up
        - gesture_down
        - gesture_left
        - gesture_right
        - roll_up (przycisk ignorowany)
        - roll_down (przycisk ignorowany)
    - akcja
      - wszystkie akcje z /bind
      - komendy do wykonania (przyjmuja parametry)
- moze obsluga masek, a nie tylko wartosci, w mouse_bevent_add()?
- beventy dla listy kontaktow i paska stanu (jesli nie zaznaczono inaczej, 
  to klikniecia):
  - lista: /list <osoba>
  - lista: podwojne: /query <osoba>
  - rolka: scrollowanie listy (moe oglnie te dla okna rozmowy?)
  - pasek: query_ip: /exec ^host <ip>
  - pasek: query_descr i inne odnosnie opisu: /list <osoba>
- pamietac o sigwinch i innych mozliwosciach (zmiany wartosci zmiennych, 
  zdarzenia itd.) zmiany obecnosci, polozenia i rozmiaru obszarow. podczas 
  dodawania obszaru do okna warto grepnac zrodla pod katem wystepowania 
  odpowiednich funkcji z ncurses dla tego okna. jesli pozycja w oknie ma 
  znaczenie to trzeba tez pilnowac, zeby opis pozycji poszczegolnych 
  elementow byl aktualizowany

// $Id$
