
/*
 * 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 "SkWidget.h"
#include "SkCanvas.h"
#include "SkKey.h"
#include "SkParsePaint.h"
#include "SkSystemEventTypes.h"
#include "SkTextBox.h"

#if 0

#ifdef SK_DEBUG
	static void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
	{
		const char* value = dom.findAttr(node, attr);
		if (value)
			SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
	}
#else
	#define assert_no_attr(dom, node, attr)
#endif

#include "SkAnimator.h"
#include "SkTime.h"

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

enum SkinType {
	kPushButton_SkinType,
	kStaticText_SkinType,

	kSkinTypeCount
};

struct SkinSuite {
	SkinSuite();
	~SkinSuite()
	{
		for (int i = 0; i < kSkinTypeCount; i++)
			delete fAnimators[i];
	}

	SkAnimator*	get(SkinType);

private:
	SkAnimator*	fAnimators[kSkinTypeCount];
};

SkinSuite::SkinSuite()
{
	static const char kSkinPath[] = "skins/";

	static const char* gSkinNames[] = {
		"pushbutton_skin.xml",
		"statictext_skin.xml"
	};

	for (unsigned i = 0; i < SK_ARRAY_COUNT(gSkinNames); i++)
	{
		size_t		len = strlen(gSkinNames[i]);
		SkString	path(sizeof(kSkinPath) - 1 + len);

		memcpy(path.writable_str(), kSkinPath, sizeof(kSkinPath) - 1);
		memcpy(path.writable_str() + sizeof(kSkinPath) - 1, gSkinNames[i], len);

		fAnimators[i] = new SkAnimator;
		if (!fAnimators[i]->decodeURI(path.c_str()))
		{
			delete fAnimators[i];
			fAnimators[i] = NULL;
		}
	}
}

SkAnimator* SkinSuite::get(SkinType st)
{
	SkASSERT((unsigned)st < kSkinTypeCount);
	return fAnimators[st];
}

static SkinSuite* gSkinSuite;

static SkAnimator* get_skin_animator(SkinType st)
{
#if 0
	if (gSkinSuite == NULL)
		gSkinSuite = new SkinSuite;
	return gSkinSuite->get(st);
#else
	return NULL;
#endif
}

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

void SkWidget::Init()
{
}

void SkWidget::Term()
{
	delete gSkinSuite;
}

void SkWidget::onEnabledChange()
{
	this->inval(NULL);
}

void SkWidget::postWidgetEvent()
{
	if (!fEvent.isType("") && this->hasListeners())
	{
		this->prepareWidgetEvent(&fEvent);
		this->postToListeners(fEvent);
	}
}

void SkWidget::prepareWidgetEvent(SkEvent*)
{
	// override in subclass to add any additional fields before posting
}

void SkWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
{
	this->INHERITED::onInflate(dom, node);

	if ((node = dom.getFirstChild(node, "event")) != NULL)
		fEvent.inflate(dom, node);
}

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

size_t SkHasLabelWidget::getLabel(SkString* str) const
{
	if (str)
		*str = fLabel;
	return fLabel.size();
}

size_t SkHasLabelWidget::getLabel(char buffer[]) const
{
	if (buffer)
		memcpy(buffer, fLabel.c_str(), fLabel.size());
	return fLabel.size();
}

void SkHasLabelWidget::setLabel(const SkString& str)
{
	this->setLabel(str.c_str(), str.size());
}

void SkHasLabelWidget::setLabel(const char label[])
{
	this->setLabel(label, strlen(label));
}

void SkHasLabelWidget::setLabel(const char label[], size_t len)
{
	if (!fLabel.equals(label, len))
	{
		fLabel.set(label, len);
		this->onLabelChange();
	}
}

void SkHasLabelWidget::onLabelChange()
{
	// override in subclass
}

void SkHasLabelWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
{
	this->INHERITED::onInflate(dom, node);

	const char* text = dom.findAttr(node, "label");
	if (text)
		this->setLabel(text);
}

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

void SkButtonWidget::setButtonState(State state)
{
	if (fState != state)
	{
		fState = state;
		this->onButtonStateChange();
	}
}

void SkButtonWidget::onButtonStateChange()
{
	this->inval(NULL);
}

void SkButtonWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
{
	this->INHERITED::onInflate(dom, node);

	int	index;
	if ((index = dom.findList(node, "buttonState", "off,on,unknown")) >= 0)
		this->setButtonState((State)index);
}

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

bool SkPushButtonWidget::onEvent(const SkEvent& evt)
{
	if (evt.isType(SK_EventType_Key) && evt.getFast32() == kOK_SkKey)
	{
		this->postWidgetEvent();
		return true;
	}
	return this->INHERITED::onEvent(evt);
}

static const char* computeAnimatorState(int enabled, int focused, SkButtonWidget::State state)
{
	if (!enabled)
		return "disabled";
	if (state == SkButtonWidget::kOn_State)
	{
		SkASSERT(focused);
		return "enabled-pressed";
	}
	if (focused)
		return "enabled-focused";
	return "enabled";
}

#include "SkBlurMaskFilter.h"
#include "SkEmbossMaskFilter.h"

static void create_emboss(SkPaint* paint, SkScalar radius, bool focus, bool pressed)
{
	SkEmbossMaskFilter::Light	light;

	light.fDirection[0] = SK_Scalar1/2;
	light.fDirection[1] = SK_Scalar1/2;
	light.fDirection[2] = SK_Scalar1/3;
	light.fAmbient		= 0x48;
	light.fSpecular		= 0x80;

	if (pressed)
	{
		light.fDirection[0] = -light.fDirection[0];
		light.fDirection[1] = -light.fDirection[1];
	}
	if (focus)
		light.fDirection[2] += SK_Scalar1/4;

	paint->setMaskFilter(new SkEmbossMaskFilter(light, radius))->unref();
}

void SkPushButtonWidget::onDraw(SkCanvas* canvas)
{
	this->INHERITED::onDraw(canvas);

	SkString label;
	this->getLabel(&label);

	SkAnimator* anim = get_skin_animator(kPushButton_SkinType);

	if (anim)
	{
		SkEvent	evt("user");

		evt.setString("id", "prime");
		evt.setScalar("prime-width", this->width());
		evt.setScalar("prime-height", this->height());
		evt.setString("prime-text", label);
		evt.setString("prime-state", computeAnimatorState(this->isEnabled(), this->hasFocus(), this->getButtonState()));

		(void)anim->doUserEvent(evt);
		SkPaint paint;
		anim->draw(canvas, &paint, SkTime::GetMSecs());
	}
	else
	{
		SkRect	r;
		SkPaint	p;

		r.set(0, 0, this->width(), this->height());
		p.setAntiAliasOn(true);
		p.setColor(SK_ColorBLUE);
		create_emboss(&p, SkIntToScalar(12)/5, this->hasFocus(), this->getButtonState() == kOn_State);
		canvas->drawRoundRect(r, SkScalarHalf(this->height()), SkScalarHalf(this->height()), p);
		p.setMaskFilter(NULL);

		p.setTextAlign(SkPaint::kCenter_Align);

		SkTextBox	box;
		box.setMode(SkTextBox::kOneLine_Mode);
		box.setSpacingAlign(SkTextBox::kCenter_SpacingAlign);
		box.setBox(0, 0, this->width(), this->height());

//		if (this->getButtonState() == kOn_State)
//			p.setColor(SK_ColorRED);
//		else
			p.setColor(SK_ColorWHITE);

		box.draw(canvas, label.c_str(), label.size(), p);
	}
}

SkView::Click* SkPushButtonWidget::onFindClickHandler(SkScalar x, SkScalar y)
{
	this->acceptFocus();
	return new Click(this);
}

bool SkPushButtonWidget::onClick(Click* click)
{
	SkRect	r;
	State	state = kOff_State;

	this->getLocalBounds(&r);
	if (r.contains(click->fCurr))
	{
		if (click->fState == Click::kUp_State)
			this->postWidgetEvent();
		else
			state = kOn_State;
	}
	this->setButtonState(state);
	return true;
}

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

SkStaticTextView::SkStaticTextView(U32 flags) : SkView(flags)
{
	fMargin.set(0, 0);
	fMode = kFixedSize_Mode;
	fSpacingAlign = SkTextBox::kStart_SpacingAlign;
}

SkStaticTextView::~SkStaticTextView()
{
}

void SkStaticTextView::computeSize()
{
	if (fMode == kAutoWidth_Mode)
	{
		SkScalar width = fPaint.measureText(fText.c_str(), fText.size(), NULL, NULL);
		this->setWidth(width + fMargin.fX * 2);
	}
	else if (fMode == kAutoHeight_Mode)
	{
		SkScalar width = this->width() - fMargin.fX * 2;
		int lines = width > 0 ? SkTextLineBreaker::CountLines(fText.c_str(), fText.size(), fPaint, width) : 0;

		SkScalar	before, after;
		(void)fPaint.measureText(0, NULL, &before, &after);

		this->setHeight(lines * (after - before) + fMargin.fY * 2);
	}
}

void SkStaticTextView::setMode(Mode mode)
{
	SkASSERT((unsigned)mode < kModeCount);

	if (fMode != mode)
	{
		fMode = SkToU8(mode);
		this->computeSize();
	}
}

void SkStaticTextView::setSpacingAlign(SkTextBox::SpacingAlign align)
{
	fSpacingAlign = SkToU8(align);
	this->inval(NULL);
}

void SkStaticTextView::getMargin(SkPoint* margin) const
{
	if (margin)
		*margin = fMargin;
}

void SkStaticTextView::setMargin(SkScalar dx, SkScalar dy)
{
	if (fMargin.fX != dx || fMargin.fY != dy)
	{
		fMargin.set(dx, dy);
		this->computeSize();
		this->inval(NULL);
	}
}

size_t SkStaticTextView::getText(SkString* text) const
{
	if (text)
		*text = fText;
	return fText.size();
}

size_t SkStaticTextView::getText(char text[]) const
{
	if (text)
		memcpy(text, fText.c_str(), fText.size());
	return fText.size();
}

void SkStaticTextView::setText(const SkString& text)
{
	this->setText(text.c_str(), text.size());
}

void SkStaticTextView::setText(const char text[])
{
	this->setText(text, strlen(text));
}

void SkStaticTextView::setText(const char text[], size_t len)
{
	if (!fText.equals(text, len))
	{
		fText.set(text, len);
		this->computeSize();
		this->inval(NULL);
	}
}

void SkStaticTextView::getPaint(SkPaint* paint) const
{
	if (paint)
		*paint = fPaint;
}

void SkStaticTextView::setPaint(const SkPaint& paint)
{
	if (fPaint != paint)
	{
		fPaint = paint;
		this->computeSize();
		this->inval(NULL);
	}
}

void SkStaticTextView::onDraw(SkCanvas* canvas)
{
	this->INHERITED::onDraw(canvas);

	if (fText.isEmpty())
		return;

	SkTextBox	box;

	box.setMode(fMode == kAutoWidth_Mode ? SkTextBox::kOneLine_Mode : SkTextBox::kLineBreak_Mode);
	box.setSpacingAlign(this->getSpacingAlign());
	box.setBox(fMargin.fX, fMargin.fY, this->width() - fMargin.fX, this->height() - fMargin.fY);
	box.draw(canvas, fText.c_str(), fText.size(), fPaint);
}

void SkStaticTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
{
	this->INHERITED::onInflate(dom, node);

	int	index;
	if ((index = dom.findList(node, "mode", "fixed,auto-width,auto-height")) >= 0)
		this->setMode((Mode)index);
	else
		assert_no_attr(dom, node, "mode");

	if ((index = dom.findList(node, "spacing-align", "start,center,end")) >= 0)
		this->setSpacingAlign((SkTextBox::SpacingAlign)index);
	else
		assert_no_attr(dom, node, "mode");

	SkScalar s[2];
	if (dom.findScalars(node, "margin", s, 2))
		this->setMargin(s[0], s[1]);
	else
		assert_no_attr(dom, node, "margin");

	const char* text = dom.findAttr(node, "text");
	if (text)
		this->setText(text);

	if ((node = dom.getFirstChild(node, "paint")) != NULL)
		SkPaint_Inflate(&fPaint, dom, node);
}

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

#include "SkImageDecoder.h"

SkBitmapView::SkBitmapView(U32 flags) : SkView(flags)
{
}

SkBitmapView::~SkBitmapView()
{
}

bool SkBitmapView::getBitmap(SkBitmap* bitmap) const
{
	if (bitmap)
		*bitmap = fBitmap;
	return fBitmap.getConfig() != SkBitmap::kNo_Config;
}

void SkBitmapView::setBitmap(const SkBitmap* bitmap, bool viewOwnsPixels)
{
	if (bitmap)
	{
		fBitmap = *bitmap;
		fBitmap.setOwnsPixels(viewOwnsPixels);
	}
}

bool SkBitmapView::loadBitmapFromFile(const char path[])
{
	SkBitmap	bitmap;

	if (SkImageDecoder::DecodeFile(path, &bitmap))
	{
		this->setBitmap(&bitmap, true);
		bitmap.setOwnsPixels(false);
		return true;
	}
	return false;
}

void SkBitmapView::onDraw(SkCanvas* canvas)
{
	if (fBitmap.getConfig() != SkBitmap::kNo_Config &&
		fBitmap.width() && fBitmap.height())
	{
		SkAutoCanvasRestore	restore(canvas, true);
		SkPaint				p;

		p.setFilterType(SkPaint::kBilinear_FilterType);
		canvas->scale(	this->width() / fBitmap.width(),
						this->height() / fBitmap.height(),
						0, 0);
		canvas->drawBitmap(fBitmap, 0, 0, p);
	}
}

void SkBitmapView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
{
	this->INHERITED::onInflate(dom, node);

	const char* src = dom.findAttr(node, "src");
	if (src)
		(void)this->loadBitmapFromFile(src);
}

#endif

