Home | History | Annotate | Download | only in views
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "SkWidgetViews.h"
      9 #include "SkAnimator.h"
     10 #include "SkCanvas.h"
     11 #include "SkPaint.h"
     12 #include "SkStream.h"
     13 #include "SkSystemEventTypes.h"
     14 
     15 #ifdef SK_DEBUG
     16 	static void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
     17 	{
     18 		const char* value = dom.findAttr(node, attr);
     19 		if (value)
     20 			SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
     21 	}
     22 #else
     23 	#define assert_no_attr(dom, node, attr)
     24 #endif
     25 /*
     26 I have moved this to SkWidgetViews.h
     27 enum SkinEnum {
     28 	kButton_SkinEnum,
     29 	kProgress_SkinEnum,
     30 	kScroll_SkinEnum,
     31 	kStaticText_SkinEnum,
     32 
     33 	kSkinEnumCount
     34 };
     35 */
     36 
     37 const char* get_skin_enum_path(SkinEnum se)
     38 {
     39 	SkASSERT((unsigned)se < kSkinEnumCount);
     40 
     41 	static const char* gSkinPaths[] = {
     42             "common/default/default/skins/border3.xml",
     43             "common/default/default/skins/button.xml",
     44             "common/default/default/skins/progressBar.xml",
     45             "common/default/default/skins/scrollBar.xml",
     46             "common/default/default/skins/statictextpaint.xml"
     47 	};
     48 
     49 	return gSkinPaths[se];
     50 }
     51 
     52 void init_skin_anim(const char path[], SkAnimator* anim)
     53 {
     54 	SkASSERT(path && anim);
     55 
     56 	SkFILEStream	stream(path);
     57 
     58 	if (!stream.isValid())
     59 	{
     60 		SkDEBUGF(("init_skin_anim: loading skin failed <%s>\n", path));
     61 		sk_throw();
     62 	}
     63 
     64 	if (!anim->decodeStream(&stream))
     65 	{
     66 		SkDEBUGF(("init_skin_anim: decoding skin failed <%s>\n", path));
     67 		sk_throw();
     68 	}
     69 }
     70 
     71 void init_skin_anim(SkinEnum se, SkAnimator* anim)
     72 {
     73 	init_skin_anim(get_skin_enum_path(se), anim);
     74 }
     75 
     76 void init_skin_paint(SkinEnum se, SkPaint* paint)
     77 {
     78 	SkASSERT(paint);
     79 
     80 	SkAnimator	anim;
     81 	SkCanvas	canvas;
     82 
     83 	init_skin_anim(se, &anim);
     84 	anim.draw(&canvas, paint, 0);
     85 }
     86 
     87 void inflate_paint(const SkDOM& dom, const SkDOM::Node* node, SkPaint* paint)
     88 {
     89 	SkASSERT(paint);
     90 
     91 	SkAnimator	anim;
     92 	SkCanvas	canvas;
     93 
     94 	if (!anim.decodeDOM(dom, node))
     95 	{
     96 		SkDEBUGF(("inflate_paint: decoding dom failed\n"));
     97 		SkDEBUGCODE(dom.dump(node);)
     98 		sk_throw();
     99 	}
    100 	anim.draw(&canvas, paint, 0);
    101 }
    102 
    103 ////////////////////////////////////////////////////////////////////////////////////////
    104 
    105 SkWidgetView::SkWidgetView() : SkView(SkView::kFocusable_Mask | SkView::kEnabled_Mask)
    106 {
    107 }
    108 
    109 const char* SkWidgetView::getLabel() const
    110 {
    111 	return fLabel.c_str();
    112 }
    113 
    114 void SkWidgetView::getLabel(SkString* label) const
    115 {
    116 	if (label)
    117 		*label = fLabel;
    118 }
    119 
    120 void SkWidgetView::setLabel(const char label[])
    121 {
    122 	this->setLabel(label, label ? strlen(label) : 0);
    123 }
    124 
    125 void SkWidgetView::setLabel(const char label[], size_t len)
    126 {
    127 	if ((label == NULL && fLabel.size() != 0) || !fLabel.equals(label, len))
    128 	{
    129 		SkString	tmp(label, len);
    130 
    131 		this->onLabelChange(fLabel.c_str(), tmp.c_str());
    132 		fLabel.swap(tmp);
    133 	}
    134 }
    135 
    136 void SkWidgetView::setLabel(const SkString& label)
    137 {
    138 	if (fLabel != label)
    139 	{
    140 		this->onLabelChange(fLabel.c_str(), label.c_str());
    141 		fLabel = label;
    142 	}
    143 }
    144 
    145 bool SkWidgetView::postWidgetEvent()
    146 {
    147 	if (!fEvent.isType(""))
    148 	{
    149 		SkEvent	evt(fEvent);	// make a copy since onPrepareWidgetEvent may edit the event
    150 
    151 		if (this->onPrepareWidgetEvent(&evt))
    152 		{
    153 			SkDEBUGCODE(evt.dump("SkWidgetView::postWidgetEvent");)
    154 
    155 			this->postToListeners(evt);	// wonder if this should return true if there are > 0 listeners...
    156 			return true;
    157 		}
    158 	}
    159 	return false;
    160 }
    161 
    162 /*virtual*/ void SkWidgetView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
    163 {
    164 	this->INHERITED::onInflate(dom, node);
    165 
    166 	const char* label = dom.findAttr(node, "label");
    167 	if (label)
    168 		this->setLabel(label);
    169 
    170 	if ((node = dom.getFirstChild(node, "event")) != NULL)
    171 		fEvent.inflate(dom, node);
    172 }
    173 
    174 /*virtual*/ void SkWidgetView::onLabelChange(const char oldLabel[], const char newLabel[])
    175 {
    176 	this->inval(NULL);
    177 }
    178 
    179 static const char gWidgetEventSinkIDSlotName[] = "sk-widget-sinkid-slot";
    180 
    181 /*virtual*/ bool SkWidgetView::onPrepareWidgetEvent(SkEvent* evt)
    182 {
    183 	evt->setS32(gWidgetEventSinkIDSlotName, this->getSinkID());
    184 	return true;
    185 }
    186 
    187 SkEventSinkID SkWidgetView::GetWidgetEventSinkID(const SkEvent& evt)
    188 {
    189 	int32_t	sinkID;
    190 
    191 	return evt.findS32(gWidgetEventSinkIDSlotName, &sinkID) ? (SkEventSinkID)sinkID : 0;
    192 }
    193 
    194 ///////////////////////////////////////////////////////////////////////////////////////////////////
    195 
    196 /*virtual*/ bool SkButtonView::onEvent(const SkEvent& evt)
    197 {
    198 	if (evt.isType(SK_EventType_Key) && evt.getFast32() == kOK_SkKey)
    199 	{
    200 		this->postWidgetEvent();
    201 		return true;
    202 	}
    203 	return this->INHERITED::onEvent(evt);
    204 }
    205 
    206 ///////////////////////////////////////////////////////////////////////////////////////////////////
    207 
    208 SkCheckButtonView::SkCheckButtonView() : fCheckState(kOff_CheckState)
    209 {
    210 }
    211 
    212 void SkCheckButtonView::setCheckState(CheckState state)
    213 {
    214 	SkASSERT((unsigned)state <= kUnknown_CheckState);
    215 
    216 	if (fCheckState != state)
    217 	{
    218 		this->onCheckStateChange(this->getCheckState(), state);
    219 		fCheckState = SkToU8(state);
    220 	}
    221 }
    222 
    223 /*virtual*/ void SkCheckButtonView::onCheckStateChange(CheckState oldState, CheckState newState)
    224 {
    225 	this->inval(NULL);
    226 }
    227 
    228 /*virtual*/ void SkCheckButtonView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
    229 {
    230 	this->INHERITED::onInflate(dom, node);
    231 
    232 	int index = dom.findList(node, "check-state", "off,on,unknown");
    233 	if (index >= 0)
    234 		this->setCheckState((CheckState)index);
    235 }
    236 
    237 static const char gCheckStateSlotName[] = "sk-checkbutton-check-slot";
    238 
    239 /*virtual*/ bool SkCheckButtonView::onPrepareWidgetEvent(SkEvent* evt)
    240 {
    241 	// could check if we're "disabled", and return false...
    242 
    243 	evt->setS32(gCheckStateSlotName, this->getCheckState());
    244 	return true;
    245 }
    246 
    247 bool SkCheckButtonView::GetWidgetEventCheckState(const SkEvent& evt, CheckState* state)
    248 {
    249 	int32_t	state32;
    250 
    251 	if (evt.findS32(gCheckStateSlotName, &state32))
    252 	{
    253 		if (state)
    254 			*state = (CheckState)state32;
    255 		return true;
    256 	}
    257 	return false;
    258 }
    259 
    260 ///////////////////////////////////////////////////////////////////////////////////////////////////
    261 ///////////////////////////////////////////////////////////////////////////////////////////////////
    262 ///////////////////////////////////////////////////////////////////////////////////////////////////
    263 
    264 #include "SkTime.h"
    265 #include <stdio.h>
    266 
    267 class SkAnimButtonView : public SkButtonView {
    268 public:
    269 	SkAnimButtonView()
    270 	{
    271 		fAnim.setHostEventSink(this);
    272 		init_skin_anim(kButton_SkinEnum, &fAnim);
    273 	}
    274 
    275 protected:
    276 	virtual void onLabelChange(const char oldLabel[], const char newLabel[])
    277 	{
    278 		this->INHERITED::onLabelChange(oldLabel, newLabel);
    279 
    280 		SkEvent evt("user");
    281 		evt.setString("id", "setLabel");
    282 		evt.setString("LABEL", newLabel);
    283 		fAnim.doUserEvent(evt);
    284 	}
    285 
    286 	virtual void onFocusChange(bool gainFocus)
    287 	{
    288 		this->INHERITED::onFocusChange(gainFocus);
    289 
    290 		SkEvent evt("user");
    291 		evt.setString("id", "setFocus");
    292 		evt.setS32("FOCUS", gainFocus);
    293 		fAnim.doUserEvent(evt);
    294 	}
    295 
    296 	virtual void onSizeChange()
    297 	{
    298 		this->INHERITED::onSizeChange();
    299 
    300 		SkEvent evt("user");
    301 		evt.setString("id", "setDim");
    302 		evt.setScalar("dimX", this->width());
    303 		evt.setScalar("dimY", this->height());
    304 		fAnim.doUserEvent(evt);
    305 	}
    306 
    307 	virtual void onDraw(SkCanvas* canvas)
    308 	{
    309 		SkPaint						paint;
    310 		SkAnimator::DifferenceType	diff = fAnim.draw(canvas, &paint, SkTime::GetMSecs());
    311 
    312 		if (diff == SkAnimator::kDifferent)
    313 			this->inval(NULL);
    314 		else if (diff == SkAnimator::kPartiallyDifferent)
    315 		{
    316 			SkRect	bounds;
    317 			fAnim.getInvalBounds(&bounds);
    318 			this->inval(&bounds);
    319 		}
    320 	}
    321 
    322 	virtual bool onEvent(const SkEvent& evt)
    323 	{
    324 		if (evt.isType(SK_EventType_Inval))
    325 		{
    326 			this->inval(NULL);
    327 			return true;
    328 		}
    329 		if (evt.isType("recommendDim"))
    330 		{
    331 			SkScalar	height;
    332 
    333 			if (evt.findScalar("y", &height))
    334 				this->setHeight(height);
    335 			return true;
    336 		}
    337 		return this->INHERITED::onEvent(evt);
    338 	}
    339 
    340 	virtual bool onPrepareWidgetEvent(SkEvent* evt)
    341 	{
    342 		if (this->INHERITED::onPrepareWidgetEvent(evt))
    343 		{
    344 			SkEvent	e("user");
    345 			e.setString("id", "handlePress");
    346 			(void)fAnim.doUserEvent(e);
    347 			return true;
    348 		}
    349 		return false;
    350 	}
    351 
    352 private:
    353 	SkAnimator	fAnim;
    354 
    355 	typedef SkButtonView INHERITED;
    356 };
    357 
    358 ////////////////////////////////////////////////////////////////////////////////////////////
    359 ////////////////////////////////////////////////////////////////////////////////////////////
    360 
    361 SkView* SkWidgetFactory(const char name[])
    362 {
    363 	if (name == NULL)
    364 		return NULL;
    365 
    366 	// must be in the same order as the SkSkinWidgetEnum is declared
    367 	static const char* gNames[] = {
    368 		"sk-border",
    369 		"sk-button",
    370 		"sk-image",
    371 		"sk-list",
    372 		"sk-progress",
    373 		"sk-scroll",
    374 		"sk-text"
    375 
    376 	};
    377 
    378 	for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); i++)
    379 		if (!strcmp(gNames[i], name))
    380 			return SkWidgetFactory((SkWidgetEnum)i);
    381 
    382 	return NULL;
    383 }
    384 
    385 #include "SkImageView.h"
    386 #include "SkProgressBarView.h"
    387 #include "SkScrollBarView.h"
    388 #include "SkBorderView.h"
    389 
    390 SkView* SkWidgetFactory(SkWidgetEnum sw)
    391 {
    392 	switch (sw) {
    393 	case kBorder_WidgetEnum:
    394 		return new SkBorderView;
    395 	case kButton_WidgetEnum:
    396 		return new SkAnimButtonView;
    397 	case kImage_WidgetEnum:
    398 		return new SkImageView;
    399 	case kList_WidgetEnum:
    400 		return new SkListView;
    401 	case kProgress_WidgetEnum:
    402 		return new SkProgressBarView;
    403 	case kScroll_WidgetEnum:
    404 		return new SkScrollBarView;
    405 	case kText_WidgetEnum:
    406 		return new SkStaticTextView;
    407 	default:
    408 		SkDEBUGFAIL("unknown enum passed to SkWidgetFactory");
    409 		break;
    410 	}
    411 	return NULL;
    412 }
    413