• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkWidget.h"
9 #include "SkCanvas.h"
10 #include "SkKey.h"
11 #include "SkParsePaint.h"
12 #include "SkSystemEventTypes.h"
13 #include "SkTextBox.h"
14 
15 #if 0
16 
17 #ifdef SK_DEBUG
18 	static void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
19 	{
20 		const char* value = dom.findAttr(node, attr);
21 		if (value)
22 			SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
23 	}
24 #else
25 	#define assert_no_attr(dom, node, attr)
26 #endif
27 
28 #include "SkAnimator.h"
29 #include "SkTime.h"
30 
31 ///////////////////////////////////////////////////////////////////////////////
32 
33 enum SkinType {
34 	kPushButton_SkinType,
35 	kStaticText_SkinType,
36 
37 	kSkinTypeCount
38 };
39 
40 struct SkinSuite {
41 	SkinSuite();
42 	~SkinSuite()
43 	{
44 		for (int i = 0; i < kSkinTypeCount; i++)
45 			delete fAnimators[i];
46 	}
47 
48 	SkAnimator*	get(SkinType);
49 
50 private:
51 	SkAnimator*	fAnimators[kSkinTypeCount];
52 };
53 
54 SkinSuite::SkinSuite()
55 {
56 	static const char kSkinPath[] = "skins/";
57 
58 	static const char* gSkinNames[] = {
59 		"pushbutton_skin.xml",
60 		"statictext_skin.xml"
61 	};
62 
63 	for (unsigned i = 0; i < SK_ARRAY_COUNT(gSkinNames); i++)
64 	{
65 		size_t		len = strlen(gSkinNames[i]);
66 		SkString	path(sizeof(kSkinPath) - 1 + len);
67 
68 		memcpy(path.writable_str(), kSkinPath, sizeof(kSkinPath) - 1);
69 		memcpy(path.writable_str() + sizeof(kSkinPath) - 1, gSkinNames[i], len);
70 
71 		fAnimators[i] = new SkAnimator;
72 		if (!fAnimators[i]->decodeURI(path.c_str()))
73 		{
74 			delete fAnimators[i];
75 			fAnimators[i] = NULL;
76 		}
77 	}
78 }
79 
80 SkAnimator* SkinSuite::get(SkinType st)
81 {
82 	SkASSERT((unsigned)st < kSkinTypeCount);
83 	return fAnimators[st];
84 }
85 
86 static SkinSuite* gSkinSuite;
87 
88 static SkAnimator* get_skin_animator(SkinType st)
89 {
90 #if 0
91 	if (gSkinSuite == NULL)
92 		gSkinSuite = new SkinSuite;
93 	return gSkinSuite->get(st);
94 #else
95 	return NULL;
96 #endif
97 }
98 
99 ///////////////////////////////////////////////////////////////////////////////
100 
101 void SkWidget::Init()
102 {
103 }
104 
105 void SkWidget::Term()
106 {
107 	delete gSkinSuite;
108 }
109 
110 void SkWidget::onEnabledChange()
111 {
112 	this->inval(NULL);
113 }
114 
115 void SkWidget::postWidgetEvent()
116 {
117 	if (!fEvent.isType("") && this->hasListeners())
118 	{
119 		this->prepareWidgetEvent(&fEvent);
120 		this->postToListeners(fEvent);
121 	}
122 }
123 
124 void SkWidget::prepareWidgetEvent(SkEvent*)
125 {
126 	// override in subclass to add any additional fields before posting
127 }
128 
129 void SkWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
130 {
131 	this->INHERITED::onInflate(dom, node);
132 
133 	if ((node = dom.getFirstChild(node, "event")) != NULL)
134 		fEvent.inflate(dom, node);
135 }
136 
137 ///////////////////////////////////////////////////////////////////////////////
138 
139 size_t SkHasLabelWidget::getLabel(SkString* str) const
140 {
141 	if (str)
142 		*str = fLabel;
143 	return fLabel.size();
144 }
145 
146 size_t SkHasLabelWidget::getLabel(char buffer[]) const
147 {
148 	if (buffer)
149 		memcpy(buffer, fLabel.c_str(), fLabel.size());
150 	return fLabel.size();
151 }
152 
153 void SkHasLabelWidget::setLabel(const SkString& str)
154 {
155 	this->setLabel(str.c_str(), str.size());
156 }
157 
158 void SkHasLabelWidget::setLabel(const char label[])
159 {
160 	this->setLabel(label, strlen(label));
161 }
162 
163 void SkHasLabelWidget::setLabel(const char label[], size_t len)
164 {
165 	if (!fLabel.equals(label, len))
166 	{
167 		fLabel.set(label, len);
168 		this->onLabelChange();
169 	}
170 }
171 
172 void SkHasLabelWidget::onLabelChange()
173 {
174 	// override in subclass
175 }
176 
177 void SkHasLabelWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
178 {
179 	this->INHERITED::onInflate(dom, node);
180 
181 	const char* text = dom.findAttr(node, "label");
182 	if (text)
183 		this->setLabel(text);
184 }
185 
186 /////////////////////////////////////////////////////////////////////////////////////
187 
188 void SkButtonWidget::setButtonState(State state)
189 {
190 	if (fState != state)
191 	{
192 		fState = state;
193 		this->onButtonStateChange();
194 	}
195 }
196 
197 void SkButtonWidget::onButtonStateChange()
198 {
199 	this->inval(NULL);
200 }
201 
202 void SkButtonWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
203 {
204 	this->INHERITED::onInflate(dom, node);
205 
206 	int	index;
207 	if ((index = dom.findList(node, "buttonState", "off,on,unknown")) >= 0)
208 		this->setButtonState((State)index);
209 }
210 
211 /////////////////////////////////////////////////////////////////////////////////////
212 
213 bool SkPushButtonWidget::onEvent(const SkEvent& evt)
214 {
215 	if (evt.isType(SK_EventType_Key) && evt.getFast32() == kOK_SkKey)
216 	{
217 		this->postWidgetEvent();
218 		return true;
219 	}
220 	return this->INHERITED::onEvent(evt);
221 }
222 
223 static const char* computeAnimatorState(int enabled, int focused, SkButtonWidget::State state)
224 {
225 	if (!enabled)
226 		return "disabled";
227 	if (state == SkButtonWidget::kOn_State)
228 	{
229 		SkASSERT(focused);
230 		return "enabled-pressed";
231 	}
232 	if (focused)
233 		return "enabled-focused";
234 	return "enabled";
235 }
236 
237 #include "SkBlurMaskFilter.h"
238 #include "SkEmbossMaskFilter.h"
239 
240 static void create_emboss(SkPaint* paint, SkScalar radius, bool focus, bool pressed)
241 {
242 	SkEmbossMaskFilter::Light	light;
243 
244 	light.fDirection[0] = SK_Scalar1/2;
245 	light.fDirection[1] = SK_Scalar1/2;
246 	light.fDirection[2] = SK_Scalar1/3;
247 	light.fAmbient		= 0x48;
248 	light.fSpecular		= 0x80;
249 
250 	if (pressed)
251 	{
252 		light.fDirection[0] = -light.fDirection[0];
253 		light.fDirection[1] = -light.fDirection[1];
254 	}
255 	if (focus)
256 		light.fDirection[2] += SK_Scalar1/4;
257 
258 	paint->setMaskFilter(new SkEmbossMaskFilter(light, radius))->unref();
259 }
260 
261 void SkPushButtonWidget::onDraw(SkCanvas* canvas)
262 {
263 	this->INHERITED::onDraw(canvas);
264 
265 	SkString label;
266 	this->getLabel(&label);
267 
268 	SkAnimator* anim = get_skin_animator(kPushButton_SkinType);
269 
270 	if (anim)
271 	{
272 		SkEvent	evt("user");
273 
274 		evt.setString("id", "prime");
275 		evt.setScalar("prime-width", this->width());
276 		evt.setScalar("prime-height", this->height());
277 		evt.setString("prime-text", label);
278 		evt.setString("prime-state", computeAnimatorState(this->isEnabled(), this->hasFocus(), this->getButtonState()));
279 
280 		(void)anim->doUserEvent(evt);
281 		SkPaint paint;
282 		anim->draw(canvas, &paint, SkTime::GetMSecs());
283 	}
284 	else
285 	{
286 		SkRect	r;
287 		SkPaint	p;
288 
289 		r.set(0, 0, this->width(), this->height());
290 		p.setAntiAliasOn(true);
291 		p.setColor(SK_ColorBLUE);
292 		create_emboss(&p, SkIntToScalar(12)/5, this->hasFocus(), this->getButtonState() == kOn_State);
293 		canvas->drawRoundRect(r, SkScalarHalf(this->height()), SkScalarHalf(this->height()), p);
294 		p.setMaskFilter(NULL);
295 
296 		p.setTextAlign(SkPaint::kCenter_Align);
297 
298 		SkTextBox	box;
299 		box.setMode(SkTextBox::kOneLine_Mode);
300 		box.setSpacingAlign(SkTextBox::kCenter_SpacingAlign);
301 		box.setBox(0, 0, this->width(), this->height());
302 
303 //		if (this->getButtonState() == kOn_State)
304 //			p.setColor(SK_ColorRED);
305 //		else
306 			p.setColor(SK_ColorWHITE);
307 
308 		box.draw(canvas, label.c_str(), label.size(), p);
309 	}
310 }
311 
312 SkView::Click* SkPushButtonWidget::onFindClickHandler(SkScalar x, SkScalar y)
313 {
314 	this->acceptFocus();
315 	return new Click(this);
316 }
317 
318 bool SkPushButtonWidget::onClick(Click* click)
319 {
320 	SkRect	r;
321 	State	state = kOff_State;
322 
323 	this->getLocalBounds(&r);
324 	if (r.contains(click->fCurr))
325 	{
326 		if (click->fState == Click::kUp_State)
327 			this->postWidgetEvent();
328 		else
329 			state = kOn_State;
330 	}
331 	this->setButtonState(state);
332 	return true;
333 }
334 
335 //////////////////////////////////////////////////////////////////////////////////////////
336 
337 SkStaticTextView::SkStaticTextView(U32 flags) : SkView(flags)
338 {
339 	fMargin.set(0, 0);
340 	fMode = kFixedSize_Mode;
341 	fSpacingAlign = SkTextBox::kStart_SpacingAlign;
342 }
343 
344 SkStaticTextView::~SkStaticTextView()
345 {
346 }
347 
348 void SkStaticTextView::computeSize()
349 {
350 	if (fMode == kAutoWidth_Mode)
351 	{
352 		SkScalar width = fPaint.measureText(fText.c_str(), fText.size(), NULL, NULL);
353 		this->setWidth(width + fMargin.fX * 2);
354 	}
355 	else if (fMode == kAutoHeight_Mode)
356 	{
357 		SkScalar width = this->width() - fMargin.fX * 2;
358 		int lines = width > 0 ? SkTextLineBreaker::CountLines(fText.c_str(), fText.size(), fPaint, width) : 0;
359 
360 		SkScalar	before, after;
361 		(void)fPaint.measureText(0, NULL, &before, &after);
362 
363 		this->setHeight(lines * (after - before) + fMargin.fY * 2);
364 	}
365 }
366 
367 void SkStaticTextView::setMode(Mode mode)
368 {
369 	SkASSERT((unsigned)mode < kModeCount);
370 
371 	if (fMode != mode)
372 	{
373 		fMode = SkToU8(mode);
374 		this->computeSize();
375 	}
376 }
377 
378 void SkStaticTextView::setSpacingAlign(SkTextBox::SpacingAlign align)
379 {
380 	fSpacingAlign = SkToU8(align);
381 	this->inval(NULL);
382 }
383 
384 void SkStaticTextView::getMargin(SkPoint* margin) const
385 {
386 	if (margin)
387 		*margin = fMargin;
388 }
389 
390 void SkStaticTextView::setMargin(SkScalar dx, SkScalar dy)
391 {
392 	if (fMargin.fX != dx || fMargin.fY != dy)
393 	{
394 		fMargin.set(dx, dy);
395 		this->computeSize();
396 		this->inval(NULL);
397 	}
398 }
399 
400 size_t SkStaticTextView::getText(SkString* text) const
401 {
402 	if (text)
403 		*text = fText;
404 	return fText.size();
405 }
406 
407 size_t SkStaticTextView::getText(char text[]) const
408 {
409 	if (text)
410 		memcpy(text, fText.c_str(), fText.size());
411 	return fText.size();
412 }
413 
414 void SkStaticTextView::setText(const SkString& text)
415 {
416 	this->setText(text.c_str(), text.size());
417 }
418 
419 void SkStaticTextView::setText(const char text[])
420 {
421 	this->setText(text, strlen(text));
422 }
423 
424 void SkStaticTextView::setText(const char text[], size_t len)
425 {
426 	if (!fText.equals(text, len))
427 	{
428 		fText.set(text, len);
429 		this->computeSize();
430 		this->inval(NULL);
431 	}
432 }
433 
434 void SkStaticTextView::getPaint(SkPaint* paint) const
435 {
436 	if (paint)
437 		*paint = fPaint;
438 }
439 
440 void SkStaticTextView::setPaint(const SkPaint& paint)
441 {
442 	if (fPaint != paint)
443 	{
444 		fPaint = paint;
445 		this->computeSize();
446 		this->inval(NULL);
447 	}
448 }
449 
450 void SkStaticTextView::onDraw(SkCanvas* canvas)
451 {
452 	this->INHERITED::onDraw(canvas);
453 
454 	if (fText.isEmpty())
455 		return;
456 
457 	SkTextBox	box;
458 
459 	box.setMode(fMode == kAutoWidth_Mode ? SkTextBox::kOneLine_Mode : SkTextBox::kLineBreak_Mode);
460 	box.setSpacingAlign(this->getSpacingAlign());
461 	box.setBox(fMargin.fX, fMargin.fY, this->width() - fMargin.fX, this->height() - fMargin.fY);
462 	box.draw(canvas, fText.c_str(), fText.size(), fPaint);
463 }
464 
465 void SkStaticTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
466 {
467 	this->INHERITED::onInflate(dom, node);
468 
469 	int	index;
470 	if ((index = dom.findList(node, "mode", "fixed,auto-width,auto-height")) >= 0)
471 		this->setMode((Mode)index);
472 	else
473 		assert_no_attr(dom, node, "mode");
474 
475 	if ((index = dom.findList(node, "spacing-align", "start,center,end")) >= 0)
476 		this->setSpacingAlign((SkTextBox::SpacingAlign)index);
477 	else
478 		assert_no_attr(dom, node, "mode");
479 
480 	SkScalar s[2];
481 	if (dom.findScalars(node, "margin", s, 2))
482 		this->setMargin(s[0], s[1]);
483 	else
484 		assert_no_attr(dom, node, "margin");
485 
486 	const char* text = dom.findAttr(node, "text");
487 	if (text)
488 		this->setText(text);
489 
490 	if ((node = dom.getFirstChild(node, "paint")) != NULL)
491 		SkPaint_Inflate(&fPaint, dom, node);
492 }
493 
494 /////////////////////////////////////////////////////////////////////////////////////////////////////
495 
496 #include "SkImageDecoder.h"
497 
498 SkBitmapView::SkBitmapView(U32 flags) : SkView(flags)
499 {
500 }
501 
502 SkBitmapView::~SkBitmapView()
503 {
504 }
505 
506 bool SkBitmapView::getBitmap(SkBitmap* bitmap) const
507 {
508 	if (bitmap)
509 		*bitmap = fBitmap;
510 	return fBitmap.getConfig() != SkBitmap::kNo_Config;
511 }
512 
513 void SkBitmapView::setBitmap(const SkBitmap* bitmap, bool viewOwnsPixels)
514 {
515 	if (bitmap)
516 	{
517 		fBitmap = *bitmap;
518 		fBitmap.setOwnsPixels(viewOwnsPixels);
519 	}
520 }
521 
522 bool SkBitmapView::loadBitmapFromFile(const char path[])
523 {
524 	SkBitmap	bitmap;
525 
526 	if (SkImageDecoder::DecodeFile(path, &bitmap))
527 	{
528 		this->setBitmap(&bitmap, true);
529 		bitmap.setOwnsPixels(false);
530 		return true;
531 	}
532 	return false;
533 }
534 
535 void SkBitmapView::onDraw(SkCanvas* canvas)
536 {
537 	if (fBitmap.getConfig() != SkBitmap::kNo_Config &&
538 		fBitmap.width() && fBitmap.height())
539 	{
540 		SkAutoCanvasRestore	restore(canvas, true);
541 		SkPaint				p;
542 
543 		p.setFilterType(SkPaint::kBilinear_FilterType);
544 		canvas->scale(	this->width() / fBitmap.width(),
545 						this->height() / fBitmap.height(),
546 						0, 0);
547 		canvas->drawBitmap(fBitmap, 0, 0, p);
548 	}
549 }
550 
551 void SkBitmapView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
552 {
553 	this->INHERITED::onInflate(dom, node);
554 
555 	const char* src = dom.findAttr(node, "src");
556 	if (src)
557 		(void)this->loadBitmapFromFile(src);
558 }
559 
560 #endif
561 
562