
/*
 * 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 "SkWindow.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkOSMenu.h"
#include "SkSystemEventTypes.h"
#include "SkTime.h"

#define SK_EventDelayInval "\xd" "n" "\xa" "l"

#define TEST_BOUNDERx

#include "SkBounder.h"
class test_bounder : public SkBounder {
public:
    test_bounder(const SkBitmap& bm) : fCanvas(bm) {}
protected:
    virtual bool onIRect(const SkIRect& r)
    {
        SkRect    rr;

        rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop),
                SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom));

        SkPaint    p;

        p.setStyle(SkPaint::kStroke_Style);
        p.setColor(SK_ColorYELLOW);

#if 0
        rr.inset(SK_ScalarHalf, SK_ScalarHalf);
#else
        rr.inset(-SK_ScalarHalf, -SK_ScalarHalf);
#endif

        fCanvas.drawRect(rr, p);
        return true;
    }
private:
    SkCanvas    fCanvas;
};

SkWindow::SkWindow() : fFocusView(NULL)
{
    fClicks.reset();
    fWaitingOnInval = false;

#ifdef SK_BUILD_FOR_WINCE
    fConfig = SkBitmap::kRGB_565_Config;
#else
    fConfig = SkBitmap::kARGB_8888_Config;
#endif

    fMatrix.reset();
}

SkWindow::~SkWindow()
{
    fClicks.deleteAll();
    fMenus.deleteAll();
}

SkCanvas* SkWindow::createCanvas() {
    return new SkCanvas(this->getBitmap());
}

void SkWindow::setMatrix(const SkMatrix& matrix) {
    if (fMatrix != matrix) {
        fMatrix = matrix;
        this->inval(NULL);
    }
}

void SkWindow::preConcat(const SkMatrix& matrix) {
    SkMatrix m;
    m.setConcat(fMatrix, matrix);
    this->setMatrix(m);
}

void SkWindow::postConcat(const SkMatrix& matrix) {
    SkMatrix m;
    m.setConcat(matrix, fMatrix);
    this->setMatrix(m);
}

void SkWindow::setConfig(SkBitmap::Config config)
{
    this->resize(fBitmap.width(), fBitmap.height(), config);
}

void SkWindow::resize(int width, int height, SkBitmap::Config config)
{
    if (config == SkBitmap::kNo_Config)
        config = fConfig;

    if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig)
    {
        fConfig = config;
        fBitmap.setConfig(config, width, height, 0, kOpaque_SkAlphaType);
        fBitmap.allocPixels();

        this->setSize(SkIntToScalar(width), SkIntToScalar(height));
        this->inval(NULL);
    }
}

void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
{
    fBitmap.eraseARGB(a, r, g, b);
}

void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b)
{
    fBitmap.eraseRGB(r, g, b);
}

bool SkWindow::handleInval(const SkRect* localR)
{
    SkIRect    ir;

    if (localR) {
        SkRect devR;
        SkMatrix inverse;
        if (!fMatrix.invert(&inverse)) {
            return false;
        }
        fMatrix.mapRect(&devR, *localR);
        devR.round(&ir);
    } else {
        ir.set(0, 0,
               SkScalarRound(this->width()),
               SkScalarRound(this->height()));
    }
    fDirtyRgn.op(ir, SkRegion::kUnion_Op);

    this->onHandleInval(ir);
    return true;
}

void SkWindow::forceInvalAll() {
    fDirtyRgn.setRect(0, 0,
                      SkScalarCeil(this->width()),
                      SkScalarCeil(this->height()));
}

#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
    #include <windows.h>
    #include <gx.h>
    extern GXDisplayProperties gDisplayProps;
#endif

#ifdef SK_SIMULATE_FAILED_MALLOC
extern bool gEnableControlledThrow;
#endif

bool SkWindow::update(SkIRect* updateArea)
{
    if (!fDirtyRgn.isEmpty())
    {
        SkBitmap bm = this->getBitmap();

#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
        char* buffer = (char*)GXBeginDraw();
        SkASSERT(buffer);

        RECT    rect;
        GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
        buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;

        bm.setPixels(buffer);
#endif

        SkAutoTUnref<SkCanvas> canvas(this->createCanvas());

        canvas->clipRegion(fDirtyRgn);
        if (updateArea)
            *updateArea = fDirtyRgn.getBounds();

        SkAutoCanvasRestore acr(canvas, true);
        canvas->concat(fMatrix);

        // empty this now, so we can correctly record any inval calls that
        // might be made during the draw call.
        fDirtyRgn.setEmpty();

#ifdef TEST_BOUNDER
        test_bounder    b(bm);
        canvas->setBounder(&b);
#endif
#ifdef SK_SIMULATE_FAILED_MALLOC
        gEnableControlledThrow = true;
#endif
#ifdef SK_BUILD_FOR_WIN32
        //try {
            this->draw(canvas);
        //}
        //catch (...) {
        //}
#else
        this->draw(canvas);
#endif
#ifdef SK_SIMULATE_FAILED_MALLOC
        gEnableControlledThrow = false;
#endif
#ifdef TEST_BOUNDER
        canvas->setBounder(NULL);
#endif

#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
        GXEndDraw();
#endif

        return true;
    }
    return false;
}

bool SkWindow::handleChar(SkUnichar uni)
{
    if (this->onHandleChar(uni))
        return true;

    SkView* focus = this->getFocusView();
    if (focus == NULL)
        focus = this;

    SkEvent evt(SK_EventType_Unichar);
    evt.setFast32(uni);
    return focus->doEvent(evt);
}

bool SkWindow::handleKey(SkKey key)
{
    if (key == kNONE_SkKey)
        return false;

    if (this->onHandleKey(key))
        return true;

    // send an event to the focus-view
    {
        SkView* focus = this->getFocusView();
        if (focus == NULL)
            focus = this;

        SkEvent evt(SK_EventType_Key);
        evt.setFast32(key);
        if (focus->doEvent(evt))
            return true;
    }

    if (key == kUp_SkKey || key == kDown_SkKey)
    {
        if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
            this->onSetFocusView(NULL);
        return true;
    }
    return false;
}

bool SkWindow::handleKeyUp(SkKey key)
{
    if (key == kNONE_SkKey)
        return false;

    if (this->onHandleKeyUp(key))
        return true;

    //send an event to the focus-view
    {
        SkView* focus = this->getFocusView();
        if (focus == NULL)
            focus = this;

        //should this one be the same?
        SkEvent evt(SK_EventType_KeyUp);
        evt.setFast32(key);
        if (focus->doEvent(evt))
            return true;
    }
    return false;
}

void SkWindow::addMenu(SkOSMenu* menu) {
    *fMenus.append() = menu;
    this->onAddMenu(menu);
}

void SkWindow::setTitle(const char title[]) {
    if (NULL == title) {
        title = "";
    }
    fTitle.set(title);
    this->onSetTitle(title);
}

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

bool SkWindow::onEvent(const SkEvent& evt)
{
    if (evt.isType(SK_EventDelayInval))
    {
        SkRegion::Iterator    iter(fDirtyRgn);

        for (; !iter.done(); iter.next())
            this->onHandleInval(iter.rect());
        fWaitingOnInval = false;
        return true;
    }
    return this->INHERITED::onEvent(evt);
}

bool SkWindow::onGetFocusView(SkView** focus) const
{
    if (focus)
        *focus = fFocusView;
    return true;
}

bool SkWindow::onSetFocusView(SkView* focus)
{
    if (fFocusView != focus)
    {
        if (fFocusView)
            fFocusView->onFocusChange(false);
        fFocusView = focus;
        if (focus)
            focus->onFocusChange(true);
    }
    return true;
}

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

void SkWindow::onHandleInval(const SkIRect&)
{
}

bool SkWindow::onHandleChar(SkUnichar)
{
    return false;
}

bool SkWindow::onHandleKey(SkKey)
{
    return false;
}

bool SkWindow::onHandleKeyUp(SkKey)
{
    return false;
}

bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
                           unsigned modifierKeys) {
    return this->onDispatchClick(x, y, state, owner, modifierKeys);
}

bool SkWindow::onDispatchClick(int x, int y, Click::State state,
                               void* owner, unsigned modifierKeys) {
    bool handled = false;

    // First, attempt to find an existing click with this owner.
    int index = -1;
    for (int i = 0; i < fClicks.count(); i++) {
        if (owner == fClicks[i]->fOwner) {
            index = i;
            break;
        }
    }

    switch (state) {
        case Click::kDown_State: {
            if (index != -1) {
                delete fClicks[index];
                fClicks.remove(index);
            }
            Click* click = this->findClickHandler(SkIntToScalar(x),
                                                  SkIntToScalar(y), modifierKeys);

            if (click) {
                click->fOwner = owner;
                *fClicks.append() = click;
                SkView::DoClickDown(click, x, y, modifierKeys);
                handled = true;
            }
            break;
        }
        case Click::kMoved_State:
            if (index != -1) {
                SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
                handled = true;
            }
            break;
        case Click::kUp_State:
            if (index != -1) {
                SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
                delete fClicks[index];
                fClicks.remove(index);
                handled = true;
            }
            break;
        default:
            // Do nothing
            break;
    }
    return handled;
}
