
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkPaint.h"
#include "SkUnitMappers.h"
#include "SkCubicInterval.h"

#include "SkWidgetViews.h"

static SkStaticTextView* make_textview(SkView* parent,
                                       const SkRect& bounds,
                                       const SkPaint& paint) {
    SkStaticTextView* view = new SkStaticTextView;
    view->setMode(SkStaticTextView::kFixedSize_Mode);
    view->setPaint(paint);
    view->setVisibleP(true);
    view->setSize(bounds.width(), bounds.height());
    view->setLoc(bounds.fLeft, bounds.fTop);
    parent->attachChildToFront(view)->unref();
    return view;
}

static void set_scalar(SkStaticTextView* view, SkScalar value) {
    SkString str;
    str.appendScalar(value);
    view->setText(str);
}

class UnitMapperView : public SampleView {
    SkPoint fPts[4];
    SkMatrix fMatrix;
    SkStaticTextView* fViews[4];

    void setViews() {
        set_scalar(fViews[0], fPts[1].fX);
        set_scalar(fViews[1], fPts[1].fY);
        set_scalar(fViews[2], fPts[2].fX);
        set_scalar(fViews[3], fPts[2].fY);
    }

public:
    UnitMapperView() {
        fPts[0].set(0, 0);
        fPts[1].set(SK_Scalar1 / 3, SK_Scalar1 / 3);
        fPts[2].set(SK_Scalar1 * 2 / 3, SK_Scalar1 * 2 / 3);
        fPts[3].set(SK_Scalar1, SK_Scalar1);

        fMatrix.setScale(SK_Scalar1 * 200, -SK_Scalar1 * 200);
        fMatrix.postTranslate(SkIntToScalar(100), SkIntToScalar(300));

        SkRect r = {
            SkIntToScalar(350), SkIntToScalar(100),
            SkIntToScalar(500), SkIntToScalar(130)
        };
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setTextSize(SkIntToScalar(25));
        for (int i = 0; i < 4; i++) {
            fViews[i] = make_textview(this, r, paint);
            r.offset(0, r.height());
        }
        this->setViews();
    }
    
protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "UnitMapper");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }
    
    virtual void onDrawContent(SkCanvas* canvas) {
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setColor(0xFF8888FF);

        SkRect r = { 0, 0, SK_Scalar1, SK_Scalar1 };
        
        canvas->concat(fMatrix);
        canvas->drawRect(r, paint);

        paint.setColor(SK_ColorBLACK);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(0);
        paint.setStrokeCap(SkPaint::kRound_Cap);
        
        SkPath path;
        path.moveTo(fPts[0]);
        path.cubicTo(fPts[1], fPts[2], fPts[3]);
        canvas->drawPath(path, paint);

        paint.setColor(SK_ColorRED);
        paint.setStrokeWidth(0);
        canvas->drawLine(0, 0, SK_Scalar1, SK_Scalar1, paint);

        paint.setColor(SK_ColorBLUE);
        paint.setStrokeWidth(SK_Scalar1 / 60);
        for (int i = 0; i < 50; i++) {
            SkScalar x = i * SK_Scalar1 / 49;
            canvas->drawPoint(x, SkEvalCubicInterval(&fPts[1], x), paint);
        }

        paint.setStrokeWidth(SK_Scalar1 / 20);
        paint.setColor(SK_ColorGREEN);
        canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, &fPts[1], paint);
    }

    SkPoint invertPt(SkScalar x, SkScalar y) {
        SkPoint pt;
        SkMatrix m;
        fMatrix.invert(&m);
        m.mapXY(x, y, &pt);
        return pt;
    }

    int hittest(SkScalar x, SkScalar y) {
        SkPoint target = { x, y };
        SkPoint pts[2] = { fPts[1], fPts[2] };
        fMatrix.mapPoints(pts, 2);
        for (int i = 0; i < 2; i++) {
            if (SkPoint::Distance(pts[i], target) < SkIntToScalar(4)) {
                return i + 1;
            }
        }
        return -1;
    }

    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
        fDragIndex = hittest(x, y);
        return fDragIndex >= 0 ? new Click(this) : NULL;
    }
    
    virtual bool onClick(Click* click) {
        if (fDragIndex >= 0) {
            fPts[fDragIndex] = invertPt(click->fCurr.fX, click->fCurr.fY);
            this->setViews();
            this->inval(NULL);
            return true;
        }
        return false;
    }
    
private:
    int fDragIndex;

    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new UnitMapperView; }
static SkViewRegister reg(MyFactory);

