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