/***
 * Wyciąg z książki "Hello, Android!",
 * opublikowanej przez wydawnictwo Helion S.A.
 * Niniejszy kod jest chroniony prawami autorskimi. Nie może zostać wykorzystany do utworzenia 
 * materiałów treningowych, kursów, książek, artykułów, itp. Prosimy o kontakt w razie
 * pojawienia się wątpliwości.
 * Nie gwarantujemy, że niniejszy kod będzie się nadawał do jakiegokolwiek celu. 
 * Więcej informacji można znaleźć na stronie http://www.pragmaticprogrammer.com/titles/eband.
***/

package org.przyklad.dotyk;

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class Dotyk extends Activity implements OnTouchListener {
    private static final String ZNACZNIK = "Dotyk" ;
    
    // Poniższe macierze będą wykorzystywane do przewijania i powiększania obrazu
    Matrix macierz = new Matrix();
    Matrix zachowanaMacierz = new Matrix();

    // Możemy znajdować się w jednym z trzech poniższych stanów
    static final int BRAK = 0;
    static final int PRZEWIJANIE = 1;
    static final int PRZYBLIZANIE = 2;
    int tryb = BRAK;

    // Zapamiętuje pewne dane dla procesu przybliżania
    PointF start = new PointF();
    PointF srod = new PointF();
    float staryDyst = 1f;

    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ImageView widok = (ImageView) findViewById(R.id.widokObrazow);
        widok.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent zdarzenie) {
        // Zajmuje się tutaj zdarzeniami dotknięć...
        ImageView widok = (ImageView) v;

        // Wyświetla zdarzenie dotknięcia w dzienniku
        wyswietlZdarzenie(zdarzenie);

        // Przetwarza tutaj zdarzenia dotknięć. . . 
        switch (zdarzenie.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            zachowanaMacierz.set(macierz);
            start.set(zdarzenie.getX(), zdarzenie.getY());
            Log.d(ZNACZNIK, "tryb=PRZEWIJANIE" );
            tryb = PRZEWIJANIE;
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            tryb = BRAK;
            Log.d(ZNACZNIK, "tryb=BRAK" );
            break;
            
        case MotionEvent.ACTION_POINTER_DOWN:
            staryDyst = odstep(zdarzenie);
            Log.d(ZNACZNIK, "staryDyst=" + staryDyst);
            if (staryDyst > 10f) {
                zachowanaMacierz.set(macierz);
                punktSrodk(srod, zdarzenie);
                tryb = PRZYBLIZANIE;
                Log.d(ZNACZNIK, "tryb=PRZYBLIZANIE" );
            }
            break;

            
            
        case MotionEvent.ACTION_MOVE:
            if (tryb == PRZEWIJANIE) {
                macierz.set(zachowanaMacierz);
                macierz.postTranslate(zdarzenie.getX() - start.x,
                    zdarzenie.getY() - start.y);
            }
            
            else if (tryb == PRZYBLIZANIE) {
                float nowyDyst = odstep(zdarzenie);
                Log.d(ZNACZNIK, "nowyDyst=" + nowyDyst);
                if (nowyDyst > 10f) {
                    macierz.set(zachowanaMacierz);
                    float skala = nowyDyst / staryDyst;
                    macierz.postScale(skala, skala, srod.x, srod.y);
                }
            }
            
            break;
        }
        
        
        

        widok.setImageMatrix(macierz);
        return true; // wskazuje, czy zdarzenie zostało przetworzone
    


    }
    
    /** Wyświetla zdarzenie w widoku LogCat, co pomaga w procesie usuwania błędów */
    private void wyswietlZdarzenie(MotionEvent zdarzenie) {
        String nazwy[] = { "DOWN" , "UP" , "MOVE" , "CANCEL" , "OUTSIDE" ,
            "POINTER_DOWN" , "POINTER_UP" , "7?" , "8?" , "9?" };
        StringBuilder kz = new StringBuilder();
        int dzialanie = zdarzenie.getAction();
        int kodDzialania = dzialanie & MotionEvent.ACTION_MASK;
        kz.append("zdarzenie ACTION_" ).append(nazwy[kodDzialania]);
        if (kodDzialania == MotionEvent.ACTION_POINTER_DOWN
                || kodDzialania == MotionEvent.ACTION_POINTER_UP) {
            kz.append("(pid " ).append(
                    dzialanie >> MotionEvent.ACTION_POINTER_ID_SHIFT);
            kz.append(")" );
        }
        kz.append("[" );
        for (int i = 0; i < zdarzenie.getPointerCount(); i++) {
            kz.append("#" ).append(i);
            kz.append("(pid " ).append(zdarzenie.getPointerId(i));
            kz.append(")=" ).append((int) zdarzenie.getX(i));
            kz.append("," ).append((int) zdarzenie.getY(i));
            if (i + 1 < zdarzenie.getPointerCount())
                kz.append(";" );
        }
        kz.append("]" );
        Log.d(ZNACZNIK, kz.toString());
    }
    
    private float odstep(MotionEvent zdarzenie) {
        float x = zdarzenie.getX(0) - zdarzenie.getX(1);
        float y = zdarzenie.getY(0) - zdarzenie.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    private void punktSrodk(PointF punkt, MotionEvent zdarzenie) {
        float x = zdarzenie.getX(0) + zdarzenie.getX(1);
        float y = zdarzenie.getY(0) + zdarzenie.getY(1);
        punkt.set(x / 2, y / 2);
    }

    
}
