• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkWidgetViews.h"
2 #include "SkAnimator.h"
3 #include "SkCanvas.h"
4 #include "SkPaint.h"
5 #include "SkStream.h"
6 #include "SkSystemEventTypes.h"
7 
8 #ifdef SK_DEBUG
assert_no_attr(const SkDOM & dom,const SkDOM::Node * node,const char attr[])9 	static void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
10 	{
11 		const char* value = dom.findAttr(node, attr);
12 		if (value)
13 			SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
14 	}
15 #else
16 	#define assert_no_attr(dom, node, attr)
17 #endif
18 /*
19 I have moved this to SkWidgetViews.h
20 enum SkinEnum {
21 	kButton_SkinEnum,
22 	kProgress_SkinEnum,
23 	kScroll_SkinEnum,
24 	kStaticText_SkinEnum,
25 
26 	kSkinEnumCount
27 };
28 */
29 
get_skin_enum_path(SkinEnum se)30 const char* get_skin_enum_path(SkinEnum se)
31 {
32 	SkASSERT((unsigned)se < kSkinEnumCount);
33 
34 	static const char* gSkinPaths[] = {
35             "common/default/default/skins/border3.xml",
36             "common/default/default/skins/button.xml",
37             "common/default/default/skins/progressBar.xml",
38             "common/default/default/skins/scrollBar.xml",
39             "common/default/default/skins/statictextpaint.xml"
40 	};
41 
42 	return gSkinPaths[se];
43 }
44 
init_skin_anim(const char path[],SkAnimator * anim)45 void init_skin_anim(const char path[], SkAnimator* anim)
46 {
47 	SkASSERT(path && anim);
48 
49 	SkFILEStream	stream(path);
50 
51 	if (!stream.isValid())
52 	{
53 		SkDEBUGF(("init_skin_anim: loading skin failed <%s>\n", path));
54 		sk_throw();
55 	}
56 
57 	if (!anim->decodeStream(&stream))
58 	{
59 		SkDEBUGF(("init_skin_anim: decoding skin failed <%s>\n", path));
60 		sk_throw();
61 	}
62 }
63 
init_skin_anim(SkinEnum se,SkAnimator * anim)64 void init_skin_anim(SkinEnum se, SkAnimator* anim)
65 {
66 	init_skin_anim(get_skin_enum_path(se), anim);
67 }
68 
init_skin_paint(SkinEnum se,SkPaint * paint)69 void init_skin_paint(SkinEnum se, SkPaint* paint)
70 {
71 	SkASSERT(paint);
72 
73 	SkAnimator	anim;
74 	SkCanvas	canvas;
75 
76 	init_skin_anim(se, &anim);
77 	anim.draw(&canvas, paint, 0);
78 }
79 
inflate_paint(const SkDOM & dom,const SkDOM::Node * node,SkPaint * paint)80 void inflate_paint(const SkDOM& dom, const SkDOM::Node* node, SkPaint* paint)
81 {
82 	SkASSERT(paint);
83 
84 	SkAnimator	anim;
85 	SkCanvas	canvas;
86 
87 	if (!anim.decodeDOM(dom, node))
88 	{
89 		SkDEBUGF(("inflate_paint: decoding dom failed\n"));
90 		SkDEBUGCODE(dom.dump(node);)
91 		sk_throw();
92 	}
93 	anim.draw(&canvas, paint, 0);
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////////////
97 
SkWidgetView()98 SkWidgetView::SkWidgetView() : SkView(SkView::kFocusable_Mask | SkView::kEnabled_Mask)
99 {
100 }
101 
getLabel() const102 const char* SkWidgetView::getLabel() const
103 {
104 	return fLabel.c_str();
105 }
106 
getLabel(SkString * label) const107 void SkWidgetView::getLabel(SkString* label) const
108 {
109 	if (label)
110 		*label = fLabel;
111 }
112 
setLabel(const char label[])113 void SkWidgetView::setLabel(const char label[])
114 {
115 	this->setLabel(label, label ? strlen(label) : 0);
116 }
117 
setLabel(const char label[],size_t len)118 void SkWidgetView::setLabel(const char label[], size_t len)
119 {
120 	if (label == NULL && fLabel.size() != 0 || !fLabel.equals(label, len))
121 	{
122 		SkString	tmp(label, len);
123 
124 		this->onLabelChange(fLabel.c_str(), tmp.c_str());
125 		fLabel.swap(tmp);
126 	}
127 }
128 
setLabel(const SkString & label)129 void SkWidgetView::setLabel(const SkString& label)
130 {
131 	if (fLabel != label)
132 	{
133 		this->onLabelChange(fLabel.c_str(), label.c_str());
134 		fLabel = label;
135 	}
136 }
137 
postWidgetEvent()138 bool SkWidgetView::postWidgetEvent()
139 {
140 	if (!fEvent.isType(""))
141 	{
142 		SkEvent	evt(fEvent);	// make a copy since onPrepareWidgetEvent may edit the event
143 
144 		if (this->onPrepareWidgetEvent(&evt))
145 		{
146 			SkDEBUGCODE(evt.dump("SkWidgetView::postWidgetEvent");)
147 
148 			this->postToListeners(evt);	// wonder if this should return true if there are > 0 listeners...
149 			return true;
150 		}
151 	}
152 	return false;
153 }
154 
onInflate(const SkDOM & dom,const SkDOM::Node * node)155 /*virtual*/ void SkWidgetView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
156 {
157 	this->INHERITED::onInflate(dom, node);
158 
159 	const char* label = dom.findAttr(node, "label");
160 	if (label)
161 		this->setLabel(label);
162 
163 	if ((node = dom.getFirstChild(node, "event")) != NULL)
164 		fEvent.inflate(dom, node);
165 }
166 
onLabelChange(const char oldLabel[],const char newLabel[])167 /*virtual*/ void SkWidgetView::onLabelChange(const char oldLabel[], const char newLabel[])
168 {
169 	this->inval(NULL);
170 }
171 
172 static const char gWidgetEventSinkIDSlotName[] = "sk-widget-sinkid-slot";
173 
onPrepareWidgetEvent(SkEvent * evt)174 /*virtual*/ bool SkWidgetView::onPrepareWidgetEvent(SkEvent* evt)
175 {
176 	evt->setS32(gWidgetEventSinkIDSlotName, this->getSinkID());
177 	return true;
178 }
179 
GetWidgetEventSinkID(const SkEvent & evt)180 SkEventSinkID SkWidgetView::GetWidgetEventSinkID(const SkEvent& evt)
181 {
182 	int32_t	sinkID;
183 
184 	return evt.findS32(gWidgetEventSinkIDSlotName, &sinkID) ? (SkEventSinkID)sinkID : 0;
185 }
186 
187 ///////////////////////////////////////////////////////////////////////////////////////////////////
188 
onEvent(const SkEvent & evt)189 /*virtual*/ bool SkButtonView::onEvent(const SkEvent& evt)
190 {
191 	if (evt.isType(SK_EventType_Key) && evt.getFast32() == kOK_SkKey)
192 	{
193 		this->postWidgetEvent();
194 		return true;
195 	}
196 	return this->INHERITED::onEvent(evt);
197 }
198 
199 ///////////////////////////////////////////////////////////////////////////////////////////////////
200 
SkCheckButtonView()201 SkCheckButtonView::SkCheckButtonView() : fCheckState(kOff_CheckState)
202 {
203 }
204 
setCheckState(CheckState state)205 void SkCheckButtonView::setCheckState(CheckState state)
206 {
207 	SkASSERT((unsigned)state <= kUnknown_CheckState);
208 
209 	if (fCheckState != state)
210 	{
211 		this->onCheckStateChange(this->getCheckState(), state);
212 		fCheckState = SkToU8(state);
213 	}
214 }
215 
onCheckStateChange(CheckState oldState,CheckState newState)216 /*virtual*/ void SkCheckButtonView::onCheckStateChange(CheckState oldState, CheckState newState)
217 {
218 	this->inval(NULL);
219 }
220 
onInflate(const SkDOM & dom,const SkDOM::Node * node)221 /*virtual*/ void SkCheckButtonView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
222 {
223 	this->INHERITED::onInflate(dom, node);
224 
225 	int index = dom.findList(node, "check-state", "off,on,unknown");
226 	if (index >= 0)
227 		this->setCheckState((CheckState)index);
228 }
229 
230 static const char gCheckStateSlotName[] = "sk-checkbutton-check-slot";
231 
onPrepareWidgetEvent(SkEvent * evt)232 /*virtual*/ bool SkCheckButtonView::onPrepareWidgetEvent(SkEvent* evt)
233 {
234 	// could check if we're "disabled", and return false...
235 
236 	evt->setS32(gCheckStateSlotName, this->getCheckState());
237 	return true;
238 }
239 
GetWidgetEventCheckState(const SkEvent & evt,CheckState * state)240 bool SkCheckButtonView::GetWidgetEventCheckState(const SkEvent& evt, CheckState* state)
241 {
242 	int32_t	state32;
243 
244 	if (evt.findS32(gCheckStateSlotName, &state32))
245 	{
246 		if (state)
247 			*state = (CheckState)state32;
248 		return true;
249 	}
250 	return false;
251 }
252 
253 ///////////////////////////////////////////////////////////////////////////////////////////////////
254 ///////////////////////////////////////////////////////////////////////////////////////////////////
255 ///////////////////////////////////////////////////////////////////////////////////////////////////
256 
257 #include "SkTime.h"
258 #include <stdio.h>
259 
260 class SkAnimButtonView : public SkButtonView {
261 public:
SkAnimButtonView()262 	SkAnimButtonView()
263 	{
264 		fAnim.setHostEventSink(this);
265 		init_skin_anim(kButton_SkinEnum, &fAnim);
266 	}
267 
268 protected:
onLabelChange(const char oldLabel[],const char newLabel[])269 	virtual void onLabelChange(const char oldLabel[], const char newLabel[])
270 	{
271 		this->INHERITED::onLabelChange(oldLabel, newLabel);
272 
273 		SkEvent evt("user");
274 		evt.setString("id", "setLabel");
275 		evt.setString("LABEL", newLabel);
276 		fAnim.doUserEvent(evt);
277 	}
278 
onFocusChange(bool gainFocus)279 	virtual void onFocusChange(bool gainFocus)
280 	{
281 		this->INHERITED::onFocusChange(gainFocus);
282 
283 		SkEvent evt("user");
284 		evt.setString("id", "setFocus");
285 		evt.setS32("FOCUS", gainFocus);
286 		fAnim.doUserEvent(evt);
287 	}
288 
onSizeChange()289 	virtual void onSizeChange()
290 	{
291 		this->INHERITED::onSizeChange();
292 
293 		SkEvent evt("user");
294 		evt.setString("id", "setDim");
295 		evt.setScalar("dimX", this->width());
296 		evt.setScalar("dimY", this->height());
297 		fAnim.doUserEvent(evt);
298 	}
299 
onDraw(SkCanvas * canvas)300 	virtual void onDraw(SkCanvas* canvas)
301 	{
302 		SkPaint						paint;
303 		SkAnimator::DifferenceType	diff = fAnim.draw(canvas, &paint, SkTime::GetMSecs());
304 
305 		if (diff == SkAnimator::kDifferent)
306 			this->inval(NULL);
307 		else if (diff == SkAnimator::kPartiallyDifferent)
308 		{
309 			SkRect	bounds;
310 			fAnim.getInvalBounds(&bounds);
311 			this->inval(&bounds);
312 		}
313 	}
314 
onEvent(const SkEvent & evt)315 	virtual bool onEvent(const SkEvent& evt)
316 	{
317 		if (evt.isType(SK_EventType_Inval))
318 		{
319 			this->inval(NULL);
320 			return true;
321 		}
322 		if (evt.isType("recommendDim"))
323 		{
324 			SkScalar	height;
325 
326 			if (evt.findScalar("y", &height))
327 				this->setHeight(height);
328 			return true;
329 		}
330 		return this->INHERITED::onEvent(evt);
331 	}
332 
onPrepareWidgetEvent(SkEvent * evt)333 	virtual bool onPrepareWidgetEvent(SkEvent* evt)
334 	{
335 		if (this->INHERITED::onPrepareWidgetEvent(evt))
336 		{
337 			SkEvent	e("user");
338 			e.setString("id", "handlePress");
339 			(void)fAnim.doUserEvent(e);
340 			return true;
341 		}
342 		return false;
343 	}
344 
345 private:
346 	SkAnimator	fAnim;
347 
348 	typedef SkButtonView INHERITED;
349 };
350 
351 ////////////////////////////////////////////////////////////////////////////////////////////
352 
353 #include "SkTextBox.h"
354 
SkStaticTextView()355 SkStaticTextView::SkStaticTextView()
356 {
357 	fMargin.set(0, 0);
358 	fMode = kFixedSize_Mode;
359 	fSpacingAlign = SkTextBox::kStart_SpacingAlign;
360 
361 	init_skin_paint(kStaticText_SkinEnum, &fPaint);
362 }
363 
~SkStaticTextView()364 SkStaticTextView::~SkStaticTextView()
365 {
366 }
367 
computeSize()368 void SkStaticTextView::computeSize()
369 {
370 	if (fMode == kAutoWidth_Mode)
371 	{
372 		SkScalar width = fPaint.measureText(fText.c_str(), fText.size());
373 		this->setWidth(width + fMargin.fX * 2);
374 	}
375 	else if (fMode == kAutoHeight_Mode)
376 	{
377 		SkScalar width = this->width() - fMargin.fX * 2;
378 		int lines = width > 0 ? SkTextLineBreaker::CountLines(fText.c_str(), fText.size(), fPaint, width) : 0;
379 
380 		this->setHeight(lines * fPaint.getFontSpacing() + fMargin.fY * 2);
381 	}
382 }
383 
setMode(Mode mode)384 void SkStaticTextView::setMode(Mode mode)
385 {
386 	SkASSERT((unsigned)mode < kModeCount);
387 
388 	if (fMode != mode)
389 	{
390 		fMode = SkToU8(mode);
391 		this->computeSize();
392 	}
393 }
394 
setSpacingAlign(SkTextBox::SpacingAlign align)395 void SkStaticTextView::setSpacingAlign(SkTextBox::SpacingAlign align)
396 {
397 	fSpacingAlign = SkToU8(align);
398 	this->inval(NULL);
399 }
400 
getMargin(SkPoint * margin) const401 void SkStaticTextView::getMargin(SkPoint* margin) const
402 {
403 	if (margin)
404 		*margin = fMargin;
405 }
406 
setMargin(SkScalar dx,SkScalar dy)407 void SkStaticTextView::setMargin(SkScalar dx, SkScalar dy)
408 {
409 	if (fMargin.fX != dx || fMargin.fY != dy)
410 	{
411 		fMargin.set(dx, dy);
412 		this->computeSize();
413 		this->inval(NULL);
414 	}
415 }
416 
getText(SkString * text) const417 size_t SkStaticTextView::getText(SkString* text) const
418 {
419 	if (text)
420 		*text = fText;
421 	return fText.size();
422 }
423 
getText(char text[]) const424 size_t SkStaticTextView::getText(char text[]) const
425 {
426 	if (text)
427 		memcpy(text, fText.c_str(), fText.size());
428 	return fText.size();
429 }
430 
setText(const SkString & text)431 void SkStaticTextView::setText(const SkString& text)
432 {
433 	this->setText(text.c_str(), text.size());
434 }
435 
setText(const char text[])436 void SkStaticTextView::setText(const char text[])
437 {
438 	if (text == NULL)
439 		text = "";
440 	this->setText(text, strlen(text));
441 }
442 
setText(const char text[],size_t len)443 void SkStaticTextView::setText(const char text[], size_t len)
444 {
445 	if (!fText.equals(text, len))
446 	{
447 		fText.set(text, len);
448 		this->computeSize();
449 		this->inval(NULL);
450 	}
451 }
452 
getPaint(SkPaint * paint) const453 void SkStaticTextView::getPaint(SkPaint* paint) const
454 {
455 	if (paint)
456 		*paint = fPaint;
457 }
458 
setPaint(const SkPaint & paint)459 void SkStaticTextView::setPaint(const SkPaint& paint)
460 {
461 	if (fPaint != paint)
462 	{
463 		fPaint = paint;
464 		this->computeSize();
465 		this->inval(NULL);
466 	}
467 }
468 
onDraw(SkCanvas * canvas)469 void SkStaticTextView::onDraw(SkCanvas* canvas)
470 {
471 	this->INHERITED::onDraw(canvas);
472 
473 	if (fText.isEmpty())
474 		return;
475 
476 	SkTextBox	box;
477 
478 	box.setMode(fMode == kAutoWidth_Mode ? SkTextBox::kOneLine_Mode : SkTextBox::kLineBreak_Mode);
479 	box.setSpacingAlign(this->getSpacingAlign());
480 	box.setBox(fMargin.fX, fMargin.fY, this->width() - fMargin.fX, this->height() - fMargin.fY);
481 	box.draw(canvas, fText.c_str(), fText.size(), fPaint);
482 }
483 
onInflate(const SkDOM & dom,const SkDOM::Node * node)484 void SkStaticTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
485 {
486 	this->INHERITED::onInflate(dom, node);
487 
488 	int	index;
489 	if ((index = dom.findList(node, "mode", "fixed,auto-width,auto-height")) >= 0)
490 		this->setMode((Mode)index);
491 	else
492 		assert_no_attr(dom, node, "mode");
493 
494 	if ((index = dom.findList(node, "spacing-align", "start,center,end")) >= 0)
495 		this->setSpacingAlign((SkTextBox::SpacingAlign)index);
496 	else
497 		assert_no_attr(dom, node, "spacing-align");
498 
499 	SkScalar s[2];
500 	if (dom.findScalars(node, "margin", s, 2))
501 		this->setMargin(s[0], s[1]);
502 	else
503 		assert_no_attr(dom, node, "margin");
504 
505 	const char* text = dom.findAttr(node, "text");
506 	if (text)
507 		this->setText(text);
508 
509 	if ((node = dom.getFirstChild(node, "paint")) != NULL &&
510 		(node = dom.getFirstChild(node, "screenplay")) != NULL)
511 	{
512 		inflate_paint(dom, node, &fPaint);
513 	}
514 }
515 
516 ////////////////////////////////////////////////////////////////////////////////////////////
517 ////////////////////////////////////////////////////////////////////////////////////////////
518 
SkWidgetFactory(const char name[])519 SkView* SkWidgetFactory(const char name[])
520 {
521 	if (name == NULL)
522 		return NULL;
523 
524 	// must be in the same order as the SkSkinWidgetEnum is declared
525 	static const char* gNames[] = {
526 		"sk-border",
527 		"sk-button",
528 		"sk-image",
529 		"sk-list",
530 		"sk-progress",
531 		"sk-scroll",
532 		"sk-text"
533 
534 	};
535 
536 	for (int i = 0; i < SK_ARRAY_COUNT(gNames); i++)
537 		if (!strcmp(gNames[i], name))
538 			return SkWidgetFactory((SkWidgetEnum)i);
539 
540 	return NULL;
541 }
542 
543 #include "SkImageView.h"
544 #include "SkProgressBarView.h"
545 #include "SkScrollBarView.h"
546 #include "SkBorderView.h"
547 
SkWidgetFactory(SkWidgetEnum sw)548 SkView* SkWidgetFactory(SkWidgetEnum sw)
549 {
550 	switch (sw) {
551 	case kBorder_WidgetEnum:
552 		return new SkBorderView;
553 	case kButton_WidgetEnum:
554 		return new SkAnimButtonView;
555 	case kImage_WidgetEnum:
556 		return new SkImageView;
557 	case kList_WidgetEnum:
558 		return new SkListView;
559 	case kProgress_WidgetEnum:
560 		return new SkProgressBarView;
561 	case kScroll_WidgetEnum:
562 		return new SkScrollBarView;
563 	case kText_WidgetEnum:
564 		return new SkStaticTextView;
565 	default:
566 		SkASSERT(!"unknown enum passed to SkWidgetFactory");
567 		break;
568 	}
569 	return NULL;
570 }
571