C++程序  |  365行  |  6.66 KB

#include "SkWindow.h"
#include "SkCanvas.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)
{
	fClick = NULL;
	fWaitingOnInval = false;

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

SkWindow::~SkWindow()
{
	delete fClick;

	fMenus.deleteAll();
}

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);
		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& r)
{
	SkIRect	ir;

	r.round(&ir);
	fDirtyRgn.op(ir, SkRegion::kUnion_Op);

#ifdef SK_BUILD_FOR_WIN32
	if (!fWaitingOnInval)
	{
		fWaitingOnInval = true;
		(new SkEvent(SK_EventDelayInval))->post(this->getSinkID(), 10);
	}
#else
	this->onHandleInval(ir);
#endif
	return true;
}

#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

		SkCanvas	canvas(bm);

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

		// 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::handleMenu(uint32_t cmd)
{
	for (int i = 0; i < fMenus.count(); i++)
	{
		SkEvent* evt = fMenus[i]->createEvent(cmd);
		if (evt)
		{
			evt->post(this->getSinkID());
			return true;
		}
	}
	return false;
}

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

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 key)
{
	return false;
}

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

bool SkWindow::handleClick(int x, int y, Click::State state)
{
	bool handled = false;

	switch (state) {
	case Click::kDown_State:
		if (fClick)
			delete fClick;
		fClick = this->findClickHandler(SkIntToScalar(x), SkIntToScalar(y));
		if (fClick)
		{
			SkView::DoClickDown(fClick, x, y);
			handled = true;
		}
		break;
	case Click::kMoved_State:
		if (fClick)
		{
			SkView::DoClickMoved(fClick, x, y);
			handled = true;
		}
		break;
	case Click::kUp_State:
		if (fClick)
		{
			SkView::DoClickUp(fClick, x, y);
			delete fClick;
			fClick = NULL;
			handled = true;
		}
		break;
	}
	return handled;
}