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 "SkWidget.h"
      9 #include "SkCanvas.h"
     10 #include "SkEvent.h"
     11 #include "SkKey.h"
     12 #include "SkParsePaint.h"
     13 #include "SkSystemEventTypes.h"
     14 
     15 #if 0
     16 
     17 SkEvent* SkListSource::getEvent(int index)
     18 {
     19 	return NULL;
     20 }
     21 
     22 #include "SkOSFile.h"
     23 
     24 class SkDirListSource : public SkListSource {
     25 public:
     26 	SkDirListSource(const char path[], const char suffix[], const char target[])
     27 		: fPath(path), fSuffix(suffix), fTarget(target)
     28 	{
     29 		fCount = -1;
     30 	}
     31 	virtual int	countRows()
     32 	{
     33 		if (fCount < 0)
     34 		{
     35 			fCount = 0;
     36 			fIter.reset(fPath.c_str(), fSuffix.c_str());
     37 			while (fIter.next(NULL))
     38 				fCount += 1;
     39 			fIter.reset(fPath.c_str(), fSuffix.c_str());
     40 			fIndex = 0;
     41 		}
     42 		return fCount;
     43 	}
     44 	virtual void getRow(int index, SkString* left, SkString* right)
     45 	{
     46 		(void)this->countRows();
     47 		SkASSERT((unsigned)index < (unsigned)fCount);
     48 
     49 		if (fIndex > index)
     50 		{
     51 			fIter.reset(fPath.c_str(), fSuffix.c_str());
     52 			fIndex = 0;
     53 		}
     54 
     55 		while (fIndex < index)
     56 		{
     57 			fIter.next(NULL);
     58 			fIndex += 1;
     59 		}
     60 
     61 		if (fIter.next(left))
     62 		{
     63 			if (left)
     64 				left->remove(left->size() - fSuffix.size(), fSuffix.size());
     65 		}
     66 		else
     67 		{
     68 			if (left)
     69 				left->reset();
     70 		}
     71 		if (right)	// only set to ">" if we know we're on a sub-directory
     72 			right->reset();
     73 
     74 		fIndex += 1;
     75 	}
     76 	virtual SkEvent* getEvent(int index)
     77 	{
     78 		SkASSERT((unsigned)index < (unsigned)fCount);
     79 
     80 		SkEvent*	evt = new SkEvent();
     81 		SkString	label;
     82 
     83 		this->getRow(index, &label, NULL);
     84 		evt->setString("name", label.c_str());
     85 
     86 		int c = fPath.c_str()[fPath.size() - 1];
     87 		if (c != '/' && c != '\\')
     88 			label.prepend("/");
     89 		label.prepend(fPath);
     90 		label.append(fSuffix);
     91 		evt->setString("path", label.c_str());
     92 		evt->setS32("index", index);
     93 		evt->setS32("duration", 22);
     94 		evt->setType(fTarget);
     95 		return evt;
     96 	}
     97 
     98 private:
     99 	SkString		fPath, fSuffix;
    100 	SkString		fTarget;
    101 	SkOSFile::Iter	fIter;
    102 	int				fCount;
    103 	int				fIndex;
    104 };
    105 
    106 SkListSource* SkListSource::CreateFromDir(const char path[], const char suffix[], const char target[])
    107 {
    108 	return new SkDirListSource(path, suffix, target);
    109 }
    110 
    111 //////////////////////////////////////////////////////////////////
    112 
    113 class SkDOMListSource : public SkListSource {
    114 public:
    115 	enum Type {
    116 		kUnknown_Type,
    117 		kDir_Type,
    118 		kToggle_Type
    119 	};
    120 	struct ItemRec {
    121 		SkString	fLabel;
    122 		SkString	fTail, fAltTail;
    123 		SkString	fTarget;
    124 		Type		fType;
    125 	};
    126 
    127 	SkDOMListSource(const SkDOM& dom, const SkDOM::Node* node) : fDirTail(">")
    128 	{
    129 		const SkDOM::Node* child = dom.getFirstChild(node, "item");
    130 		int	count = 0;
    131 
    132 		while (child)
    133 		{
    134 			count += 1;
    135 			child = dom.getNextSibling(child, "item");
    136 		}
    137 
    138 		fCount = count;
    139 		fList = NULL;
    140 		if (count)
    141 		{
    142 			ItemRec* rec = fList = new ItemRec[count];
    143 
    144 			child = dom.getFirstChild(node, "item");
    145 			while (child)
    146 			{
    147 				rec->fLabel.set(dom.findAttr(child, "label"));
    148 				rec->fTail.set(dom.findAttr(child, "tail"));
    149 				rec->fAltTail.set(dom.findAttr(child, "alt-tail"));
    150 				rec->fTarget.set(dom.findAttr(child, "target"));
    151 				rec->fType = kUnknown_Type;
    152 
    153 				int	index = dom.findList(child, "type", "dir,toggle");
    154 				if (index >= 0)
    155 					rec->fType = (Type)(index + 1);
    156 
    157 				child = dom.getNextSibling(child, "item");
    158 				rec += 1;
    159 			}
    160 		}
    161 	}
    162 	virtual ~SkDOMListSource()
    163 	{
    164 		delete[] fList;
    165 	}
    166 	virtual int	countRows()
    167 	{
    168 		return fCount;
    169 	}
    170 	virtual void getRow(int index, SkString* left, SkString* right)
    171 	{
    172 		SkASSERT((unsigned)index < (unsigned)fCount);
    173 
    174 		if (left)
    175 			*left = fList[index].fLabel;
    176 		if (right)
    177 			*right = fList[index].fType == kDir_Type ? fDirTail : fList[index].fTail;
    178 	}
    179 	virtual SkEvent* getEvent(int index)
    180 	{
    181 		SkASSERT((unsigned)index < (unsigned)fCount);
    182 
    183 		if (fList[index].fType == kDir_Type)
    184 		{
    185 			SkEvent* evt = new SkEvent();
    186 			evt->setType(fList[index].fTarget);
    187 			evt->setFast32(index);
    188 			return evt;
    189 		}
    190 		if (fList[index].fType == kToggle_Type)
    191 			fList[index].fTail.swap(fList[index].fAltTail);
    192 
    193 		return NULL;
    194 	}
    195 
    196 private:
    197 	int			fCount;
    198 	ItemRec*	fList;
    199 	SkString	fDirTail;
    200 };
    201 
    202 SkListSource* SkListSource::CreateFromDOM(const SkDOM& dom, const SkDOM::Node* node)
    203 {
    204 	return new SkDOMListSource(dom, node);
    205 }
    206 
    207 //////////////////////////////////////////////////////////////////
    208 //////////////////////////////////////////////////////////////////
    209 
    210 SkListView::SkListView(U32 flags) : SkWidgetView(flags)
    211 {
    212 	fSource = NULL;
    213 	fScrollIndex = 0;
    214 	fCurrIndex = -1;
    215 	fRowHeight = SkIntToScalar(16);
    216 	fVisibleRowCount = 0;
    217 	fStrCache = NULL;
    218 
    219 	fPaint[kBG_Attr].setColor(0);
    220 	fPaint[kNormalText_Attr].setTextSize(SkIntToScalar(14));
    221 	fPaint[kHiliteText_Attr].setTextSize(SkIntToScalar(14));
    222 	fPaint[kHiliteText_Attr].setColor(SK_ColorWHITE);
    223 	fPaint[kHiliteCell_Attr].setColor(SK_ColorBLUE);
    224 }
    225 
    226 SkListView::~SkListView()
    227 {
    228 	delete[] fStrCache;
    229 	fSource->safeUnref();
    230 }
    231 
    232 void SkListView::setRowHeight(SkScalar height)
    233 {
    234 	SkASSERT(height >= 0);
    235 
    236 	if (fRowHeight != height)
    237 	{
    238 		fRowHeight = height;
    239 		this->inval(NULL);
    240 		this->onSizeChange();
    241 	}
    242 }
    243 
    244 void SkListView::setSelection(int index)
    245 {
    246 	if (fCurrIndex != index)
    247 	{
    248 		this->invalSelection();
    249 		fCurrIndex = index;
    250 		this->invalSelection();
    251 		this->ensureSelectionIsVisible();
    252 
    253 		{
    254 			SkEvent	evt;
    255 			evt.setType("listview-selection");
    256 			evt.setFast32(index);
    257 			this->sendEventToParents(evt);
    258 		}
    259 	}
    260 }
    261 
    262 void SkListView::moveSelectionUp()
    263 {
    264 	if (fSource)
    265 	{
    266 		int	index = fCurrIndex;
    267 		if (index < 0)	// no selection
    268 			index = fSource->countRows() - 1;
    269 		else
    270 			index = SkMax32(index - 1, 0);
    271 		this->setSelection(index);
    272 	}
    273 }
    274 
    275 void SkListView::moveSelectionDown()
    276 {
    277 	if (fSource)
    278 	{
    279 		int	index = fCurrIndex;
    280 		if (index < 0)	// no selection
    281 			index = 0;
    282 		else
    283 			index = SkMin32(index + 1, fSource->countRows() - 1);
    284 		this->setSelection(index);
    285 	}
    286 }
    287 
    288 void SkListView::invalSelection()
    289 {
    290 	SkRect	r;
    291 	if (this->getRowRect(fCurrIndex, &r))
    292 		this->inval(&r);
    293 }
    294 
    295 void SkListView::ensureSelectionIsVisible()
    296 {
    297 	if (fSource == NULL)
    298 		return;
    299 
    300 	if ((unsigned)fCurrIndex < (unsigned)fSource->countRows())
    301 	{
    302 		int index = this->logicalToVisualIndex(fCurrIndex);
    303 
    304 		if ((unsigned)index >= (unsigned)fVisibleRowCount)	// need to scroll
    305 		{
    306 			if (index < 0)	// too high
    307 				fScrollIndex = fCurrIndex;
    308 			else
    309 				fScrollIndex = fCurrIndex - fVisibleRowCount + 1;
    310 			SkASSERT((unsigned)fScrollIndex < (unsigned)fSource->countRows());
    311 
    312 			this->dirtyStrCache();
    313 			this->inval(NULL);
    314 		}
    315 	}
    316 }
    317 
    318 bool SkListView::getRowRect(int index, SkRect* r) const
    319 {
    320 	SkASSERT(r);
    321 	index = this->logicalToVisualIndex(index);
    322 	if (index >= 0)
    323 	{
    324 		SkScalar top = index * fRowHeight;
    325 
    326 		if (top < this->height())
    327 		{
    328 			if (r)
    329 				r->set(0, top, this->width(), top + fRowHeight);
    330 			return true;
    331 		}
    332 	}
    333 	return false;
    334 }
    335 
    336 SkPaint& SkListView::paint(Attr attr)
    337 {
    338 	SkASSERT((unsigned)attr < kAttrCount);
    339 	return fPaint[attr];
    340 }
    341 
    342 SkListSource* SkListView::setListSource(SkListSource* src)
    343 {
    344 	if (fSource != src)
    345 	{
    346 		SkRefCnt_SafeAssign(fSource, src);
    347 		this->dirtyStrCache();
    348 		this->ensureSelectionIsVisible();
    349 		this->inval(NULL);
    350 	}
    351 	return src;
    352 }
    353 
    354 void SkListView::onDraw(SkCanvas* canvas)
    355 {
    356 	this->INHERITED::onDraw(canvas);
    357 
    358 	canvas->drawPaint(fPaint[kBG_Attr]);
    359 
    360 	int	visibleCount = SkMin32(fVisibleRowCount, fSource->countRows() - fScrollIndex);
    361 	if (visibleCount == 0)
    362 		return;
    363 
    364 	this->ensureStrCache(visibleCount);
    365 	int currIndex = this->logicalToVisualIndex(fCurrIndex);
    366 
    367 	if ((unsigned)currIndex < (unsigned)visibleCount)
    368 	{
    369 		SkAutoCanvasRestore	restore(canvas, true);
    370 		SkRect	r;
    371 
    372 		canvas->translate(0, currIndex * fRowHeight);
    373 		(void)this->getRowRect(fScrollIndex, &r);
    374 		canvas->drawRect(r, fPaint[kHiliteCell_Attr]);
    375 	}
    376 
    377 	SkPaint*	p;
    378 	SkScalar	y, x = SkIntToScalar(6);
    379 	SkScalar	rite = this->width() - x;
    380 
    381 	{
    382 		SkScalar ascent, descent;
    383 		fPaint[kNormalText_Attr].measureText(0, NULL, &ascent, &descent);
    384 		y = SkScalarHalf(fRowHeight - descent + ascent) - ascent;
    385 	}
    386 
    387 	for (int i = 0; i < visibleCount; i++)
    388 	{
    389 		if (i == currIndex)
    390 			p = &fPaint[kHiliteText_Attr];
    391 		else
    392 			p = &fPaint[kNormalText_Attr];
    393 
    394 		p->setTextAlign(SkPaint::kLeft_Align);
    395 		canvas->drawText(fStrCache[i].c_str(), fStrCache[i].size(), x, y, *p);
    396 		p->setTextAlign(SkPaint::kRight_Align);
    397 		canvas->drawText(fStrCache[i + visibleCount].c_str(), fStrCache[i + visibleCount].size(), rite, y, *p);
    398 		canvas->translate(0, fRowHeight);
    399 	}
    400 }
    401 
    402 void SkListView::onSizeChange()
    403 {
    404 	SkScalar count = SkScalarDiv(this->height(), fRowHeight);
    405 	int		 n = SkScalarFloor(count);
    406 
    407 	// only want to show rows that are mostly visible
    408 	if (n == 0 || count - SkIntToScalar(n) > SK_Scalar1*75/100)
    409 		n += 1;
    410 
    411 	if (fVisibleRowCount != n)
    412 	{
    413 		fVisibleRowCount = n;
    414 		this->ensureSelectionIsVisible();
    415 		this->dirtyStrCache();
    416 	}
    417 }
    418 
    419 void SkListView::dirtyStrCache()
    420 {
    421 	if (fStrCache)
    422 	{
    423 		delete[] fStrCache;
    424 		fStrCache = NULL;
    425 	}
    426 }
    427 
    428 void SkListView::ensureStrCache(int count)
    429 {
    430 	if (fStrCache == NULL)
    431 	{
    432 		fStrCache = new SkString[count << 1];
    433 
    434 		if (fSource)
    435 			for (int i = 0; i < count; i++)
    436 				fSource->getRow(i + fScrollIndex, &fStrCache[i], &fStrCache[i + count]);
    437 	}
    438 }
    439 
    440 bool SkListView::onEvent(const SkEvent& evt)
    441 {
    442 	if (evt.isType(SK_EventType_Key))
    443 	{
    444 		switch (evt.getFast32()) {
    445 		case kUp_SkKey:
    446 			this->moveSelectionUp();
    447 			return true;
    448 		case kDown_SkKey:
    449 			this->moveSelectionDown();
    450 			return true;
    451 		case kRight_SkKey:
    452 		case kOK_SkKey:
    453 			if (fSource && fCurrIndex >= 0)
    454 			{
    455 				SkEvent* evt = fSource->getEvent(fCurrIndex);
    456 				if (evt)
    457 				{
    458 					SkView* view = this->sendEventToParents(*evt);
    459 					delete evt;
    460 					return view != NULL;
    461 				}
    462 				else	// hack to make toggle work
    463 				{
    464 					this->dirtyStrCache();
    465 					this->inval(NULL);
    466 				}
    467 			}
    468 			break;
    469 		}
    470 	}
    471 	return this->INHERITED::onEvent(evt);
    472 }
    473 
    474 void SkListView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
    475 {
    476 	this->INHERITED::onInflate(dom, node);
    477 
    478 	SkScalar			x;
    479 	const SkDOM::Node*	child;
    480 
    481 	if (dom.findScalar(node, "row-height", &x))
    482 		this->setRowHeight(x);
    483 
    484 	if ((child = dom.getFirstChild(node, "hilite-paint")) != NULL)
    485 		SkPaint_Inflate(&this->paint(kHiliteCell_Attr), dom, child);
    486 
    487 	// look for a listsource
    488 	{
    489 		SkListSource* src = NULL;
    490 
    491 		if ((child = dom.getFirstChild(node, "file-listsource")) != NULL)
    492 		{
    493 			const char* path = dom.findAttr(child, "path");
    494 			if (path)
    495 				src = SkListSource::CreateFromDir(	path,
    496 													dom.findAttr(child, "filter"),
    497 													dom.findAttr(child, "target"));
    498 		}
    499 		else if ((child = dom.getFirstChild(node, "xml-listsource")) != NULL)
    500 		{
    501 			src = SkListSource::CreateFromDOM(dom, child);
    502 		}
    503 
    504 		if (src)
    505 		{
    506 			this->setListSource(src)->unref();
    507 			this->setSelection(0);
    508 		}
    509 	}
    510 }
    511 
    512 ///////////////////////////////////////////////////////////////////////////////////////////
    513 ///////////////////////////////////////////////////////////////////////////////////////////
    514 
    515 #include "SkImageDecoder.h"
    516 #include "SkShader.h"
    517 
    518 class SkScrollBarView : public SkView {
    519 public:
    520 	SkScrollBarView(const char bg[], const char fg[])
    521 	{
    522 		fBGRef = SkBitmapRef::Decode(bg, true);
    523 		fFGRef = SkBitmapRef::Decode(fg, true);
    524 
    525 		if (fBGRef)
    526 			this->setWidth(SkIntToScalar(fBGRef->bitmap().width()));
    527 	}
    528 	~SkScrollBarView()
    529 	{
    530 		delete fBGRef;
    531 		delete fFGRef;
    532 	}
    533 protected:
    534 	virtual void onDraw(SkCanvas* canvas)
    535 	{
    536 		if (fBGRef == NULL) return;
    537 
    538 		SkPaint	paint;
    539 
    540 		SkShader* shader = SkShader::CreateBitmapShader(fBGRef->bitmap(), false, SkPaint::kNo_FilterType, SkShader::kClamp_TileMode);
    541 		paint.setShader(shader)->unref();
    542 
    543 		canvas->drawPaint(paint);
    544 	}
    545 private:
    546 	SkBitmapRef*	fBGRef, *fFGRef;
    547 };
    548 
    549 SkGridView::SkGridView(U32 flags) : SkWidgetView(flags)
    550 {
    551 	fSource = NULL;
    552 	fCurrIndex = -1;
    553 	fVisibleCount.set(0, 0);
    554 
    555 	fPaint[kBG_Attr].setColor(SK_ColorWHITE);
    556 	fPaint[kHiliteCell_Attr].setColor(SK_ColorYELLOW);
    557 	fPaint[kHiliteCell_Attr].setStyle(SkPaint::kStroke_Style);
    558 	fPaint[kHiliteCell_Attr].setAntiAliasOn(true);
    559 	fPaint[kHiliteCell_Attr].setStrokeWidth(SK_Scalar1*3);
    560 
    561 	fScrollBar = new SkScrollBarView("icons/scrollbarGrey.jpg", "icons/scrollbarBlue.jpg");
    562 	this->attachChildToFront(fScrollBar)->unref();
    563 	fScrollBar->setVisibleP(true);
    564 }
    565 
    566 SkGridView::~SkGridView()
    567 {
    568 	fSource->safeUnref();
    569 }
    570 
    571 void SkGridView::getCellSize(SkPoint* size) const
    572 {
    573 	if (size)
    574 		*size = fCellSize;
    575 }
    576 
    577 void SkGridView::setCellSize(SkScalar x, SkScalar y)
    578 {
    579 	SkASSERT(x >= 0 && y >= 0);
    580 
    581 	if (!fCellSize.equals(x, y))
    582 	{
    583 		fCellSize.set(x, y);
    584 		this->inval(NULL);
    585 	}
    586 }
    587 
    588 void SkGridView::setSelection(int index)
    589 {
    590 	if (fCurrIndex != index)
    591 	{
    592 		this->invalSelection();
    593 		fCurrIndex = index;
    594 		this->invalSelection();
    595 		this->ensureSelectionIsVisible();
    596 
    597 		// this generates the click
    598 		{
    599 			SkEvent	evt;
    600 			evt.setType("listview-selection");
    601 			evt.setFast32(index);
    602 			this->sendEventToParents(evt);
    603 		}
    604 	}
    605 }
    606 
    607 void SkGridView::moveSelectionUp()
    608 {
    609 	if (fSource)
    610 	{
    611 		int	index = fCurrIndex;
    612 		if (index < 0)	// no selection
    613 			index = fSource->countRows() - 1;
    614 		else
    615 			index = SkMax32(index - 1, 0);
    616 		this->setSelection(index);
    617 	}
    618 }
    619 
    620 void SkGridView::moveSelectionDown()
    621 {
    622 	if (fSource)
    623 	{
    624 		int	index = fCurrIndex;
    625 		if (index < 0)	// no selection
    626 			index = 0;
    627 		else
    628 			index = SkMin32(index + 1, fSource->countRows() - 1);
    629 		this->setSelection(index);
    630 	}
    631 }
    632 
    633 void SkGridView::invalSelection()
    634 {
    635 	SkRect	r;
    636 	if (this->getCellRect(fCurrIndex, &r))
    637 	{
    638 		SkScalar inset = 0;
    639 		if (fPaint[kHiliteCell_Attr].getStyle() != SkPaint::kFill_Style)
    640 			inset += fPaint[kHiliteCell_Attr].getStrokeWidth() / 2;
    641 		if (fPaint[kHiliteCell_Attr].isAntiAliasOn())
    642 			inset += SK_Scalar1;
    643 		r.inset(-inset, -inset);
    644 		this->inval(&r);
    645 	}
    646 }
    647 
    648 void SkGridView::ensureSelectionIsVisible()
    649 {
    650 	if (fSource == NULL)
    651 		return;
    652 #if 0
    653 	if ((unsigned)fCurrIndex < (unsigned)fSource->countRows())
    654 	{
    655 		int index = this->logicalToVisualIndex(fCurrIndex);
    656 
    657 		if ((unsigned)index >= (unsigned)fVisibleRowCount)	// need to scroll
    658 		{
    659 			if (index < 0)	// too high
    660 				fScrollIndex = fCurrIndex;
    661 			else
    662 				fScrollIndex = fCurrIndex - fVisibleRowCount + 1;
    663 			SkASSERT((unsigned)fScrollIndex < (unsigned)fSource->countRows());
    664 
    665 			this->dirtyStrCache();
    666 			this->inval(NULL);
    667 		}
    668 	}
    669 #endif
    670 }
    671 
    672 bool SkGridView::getCellRect(int index, SkRect* r) const
    673 {
    674 	if (fVisibleCount.fY == 0)
    675 		return false;
    676 
    677 	index = this->logicalToVisualIndex(index);
    678 	if (index >= 0)
    679 	{
    680 		SkRect	bounds;
    681 		int row = index / fVisibleCount.fY;
    682 		int col = index % fVisibleCount.fY;
    683 
    684 		bounds.set(0, 0, fCellSize.fX, fCellSize.fY);
    685 		bounds.offset(col * (fCellSize.fX + SkIntToScalar(col > 0)),
    686 					  row * (fCellSize.fY + SkIntToScalar(row > 0)));
    687 
    688 		if (bounds.fTop < this->height())
    689 		{
    690 			if (r)
    691 				*r = bounds;
    692 			return true;
    693 		}
    694 	}
    695 	return false;
    696 }
    697 
    698 SkPaint& SkGridView::paint(Attr attr)
    699 {
    700 	SkASSERT((unsigned)attr < kAttrCount);
    701 	return fPaint[attr];
    702 }
    703 
    704 SkListSource* SkGridView::setListSource(SkListSource* src)
    705 {
    706 	if (fSource != src)
    707 	{
    708 		SkRefCnt_SafeAssign(fSource, src);
    709 	//	this->dirtyStrCache();
    710 		this->ensureSelectionIsVisible();
    711 		this->inval(NULL);
    712 	}
    713 	return src;
    714 }
    715 
    716 #include "SkShader.h"
    717 
    718 static void copybits(SkCanvas* canvas, const SkBitmap& bm, const SkRect& dst, const SkPaint& paint)
    719 {
    720 	SkRect		src;
    721 	SkMatrix	matrix;
    722 
    723 	src.set(0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()));
    724 	if (matrix.setRectToRect(src, dst))
    725 	{
    726 		SkPaint	  p(paint);
    727 		SkShader* shader = SkShader::CreateBitmapShader(bm, false, SkPaint::kNo_FilterType, SkShader::kClamp_TileMode);
    728 		p.setShader(shader)->unref();
    729 
    730 		shader->setLocalMatrix(matrix);
    731 		canvas->drawRect(dst, p);
    732 	}
    733 }
    734 
    735 #include "SkImageDecoder.h"
    736 
    737 void SkGridView::onDraw(SkCanvas* canvas)
    738 {
    739 	this->INHERITED::onDraw(canvas);
    740 
    741 	canvas->drawPaint(fPaint[kBG_Attr]);
    742 
    743 	if (fSource == NULL)
    744 		return;
    745 
    746 #if 0
    747 	int	visibleCount = SkMin32(fVisibleRowCount, fSource->countRows() - fScrollIndex);
    748 	if (visibleCount == 0)
    749 		return;
    750 
    751 	this->ensureStrCache(visibleCount);
    752 	int currIndex = this->logicalToVisualIndex(fCurrIndex);
    753 #endif
    754 
    755 	SkPaint	p;
    756 	for (int i = 0; i < fSource->countRows(); i++)
    757 	{
    758 		bool	 forced = false;
    759 		SkEvent* evt = fSource->getEvent(i);
    760 		SkASSERT(evt);
    761 		SkString path(evt->findString("path"));
    762 		delete evt;
    763 
    764 		SkBitmapRef* bmr = SkBitmapRef::Decode(path.c_str(), false);
    765 		if (bmr == NULL)
    766 		{
    767 			bmr = SkBitmapRef::Decode(path.c_str(), true);
    768 			if (bmr)
    769 				forced = true;
    770 		}
    771 
    772 		if (bmr)
    773 		{
    774 			SkAutoTDelete<SkBitmapRef>	autoRef(bmr);
    775 			SkRect	r;
    776 			if (!this->getCellRect(i, &r))
    777 				break;
    778 			copybits(canvas, bmr->bitmap(), r, p);
    779 		}
    780 		// only draw one forced bitmap at a time
    781 		if (forced)
    782 		{
    783 			this->inval(NULL);	// could inval only the remaining visible cells...
    784 			break;
    785 		}
    786 	}
    787 
    788 	// draw the hilite
    789 	{
    790 		SkRect	r;
    791 		if (fCurrIndex >= 0 && this->getCellRect(fCurrIndex, &r))
    792 			canvas->drawRect(r, fPaint[kHiliteCell_Attr]);
    793 	}
    794 }
    795 
    796 static int check_count(int n, SkScalar s)
    797 {
    798 	// only want to show cells that are mostly visible
    799 	if (n == 0 || s - SkIntToScalar(n) > SK_Scalar1*75/100)
    800 		n += 1;
    801 	return n;
    802 }
    803 
    804 void SkGridView::onSizeChange()
    805 {
    806 	fScrollBar->setHeight(this->height());
    807 	fScrollBar->setLoc(this->locX() + this->width() - fScrollBar->width(), 0);
    808 
    809 	if (fCellSize.equals(0, 0))
    810 	{
    811 		fVisibleCount.set(0, 0);
    812 		return;
    813 	}
    814 
    815 	SkScalar rows = SkScalarDiv(this->height(), fCellSize.fY);
    816 	SkScalar cols = SkScalarDiv(this->width(), fCellSize.fX);
    817 	int		 y = SkScalarFloor(rows);
    818 	int		 x = SkScalarFloor(cols);
    819 
    820 	y = check_count(y, rows);
    821 	x = check_count(x, cols);
    822 
    823 	if (!fVisibleCount.equals(x, y))
    824 	{
    825 		fVisibleCount.set(x, y);
    826 		this->ensureSelectionIsVisible();
    827 	//	this->dirtyStrCache();
    828 	}
    829 }
    830 
    831 bool SkGridView::onEvent(const SkEvent& evt)
    832 {
    833 	if (evt.isType(SK_EventType_Key))
    834 	{
    835 		switch (evt.getFast32()) {
    836 		case kUp_SkKey:
    837 			this->moveSelectionUp();
    838 			return true;
    839 		case kDown_SkKey:
    840 			this->moveSelectionDown();
    841 			return true;
    842 		case kRight_SkKey:
    843 		case kOK_SkKey:
    844 			if (fSource && fCurrIndex >= 0)
    845 			{
    846 				SkEvent* evt = fSource->getEvent(fCurrIndex);
    847 				if (evt)
    848 				{
    849 					// augment the event with our local rect
    850 					(void)this->getCellRect(fCurrIndex, (SkRect*)evt->setScalars("local-rect", 4, NULL));
    851 
    852 					SkView* view = this->sendEventToParents(*evt);
    853 					delete evt;
    854 					return view != NULL;
    855 				}
    856 			}
    857 			break;
    858 		}
    859 	}
    860 	return this->INHERITED::onEvent(evt);
    861 }
    862 
    863 void SkGridView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
    864 {
    865 	this->INHERITED::onInflate(dom, node);
    866 
    867 	SkScalar			x[2];
    868 	const SkDOM::Node*	child;
    869 
    870 	if (dom.findScalars(node, "cell-size", x, 2))
    871 		this->setCellSize(x[0], x[1]);
    872 
    873 	if ((child = dom.getFirstChild(node, "hilite-paint")) != NULL)
    874 		SkPaint_Inflate(&this->paint(kHiliteCell_Attr), dom, child);
    875 
    876 	// look for a listsource
    877 	{
    878 		SkListSource* src = NULL;
    879 
    880 		if ((child = dom.getFirstChild(node, "file-listsource")) != NULL)
    881 		{
    882 			const char* path = dom.findAttr(child, "path");
    883 			if (path)
    884 				src = SkListSource::CreateFromDir(	path,
    885 													dom.findAttr(child, "filter"),
    886 													dom.findAttr(child, "target"));
    887 		}
    888 		else if ((child = dom.getFirstChild(node, "xml-listsource")) != NULL)
    889 		{
    890 			src = SkListSource::CreateFromDOM(dom, child);
    891 		}
    892 
    893 		if (src)
    894 		{
    895 			this->setListSource(src)->unref();
    896 			this->setSelection(0);
    897 		}
    898 	}
    899 	this->onSizeChange();
    900 }
    901 
    902 #endif
    903