1599a4332a
Review URL: http://codereview.appspot.com/67139 git-svn-id: http://skia.googlecode.com/svn/trunk@200 2bbb7eff-a529-9590-31e7-b0007b416f81
896 lines
19 KiB
C++
896 lines
19 KiB
C++
#include "SkWidget.h"
|
|
#include "SkCanvas.h"
|
|
#include "SkEvent.h"
|
|
#include "SkKey.h"
|
|
#include "SkParsePaint.h"
|
|
#include "SkSystemEventTypes.h"
|
|
|
|
#if 0
|
|
|
|
SkEvent* SkListSource::getEvent(int index)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#include "SkOSFile.h"
|
|
|
|
class SkDirListSource : public SkListSource {
|
|
public:
|
|
SkDirListSource(const char path[], const char suffix[], const char target[])
|
|
: fPath(path), fSuffix(suffix), fTarget(target)
|
|
{
|
|
fCount = -1;
|
|
}
|
|
virtual int countRows()
|
|
{
|
|
if (fCount < 0)
|
|
{
|
|
fCount = 0;
|
|
fIter.reset(fPath.c_str(), fSuffix.c_str());
|
|
while (fIter.next(NULL))
|
|
fCount += 1;
|
|
fIter.reset(fPath.c_str(), fSuffix.c_str());
|
|
fIndex = 0;
|
|
}
|
|
return fCount;
|
|
}
|
|
virtual void getRow(int index, SkString* left, SkString* right)
|
|
{
|
|
(void)this->countRows();
|
|
SkASSERT((unsigned)index < (unsigned)fCount);
|
|
|
|
if (fIndex > index)
|
|
{
|
|
fIter.reset(fPath.c_str(), fSuffix.c_str());
|
|
fIndex = 0;
|
|
}
|
|
|
|
while (fIndex < index)
|
|
{
|
|
fIter.next(NULL);
|
|
fIndex += 1;
|
|
}
|
|
|
|
if (fIter.next(left))
|
|
{
|
|
if (left)
|
|
left->remove(left->size() - fSuffix.size(), fSuffix.size());
|
|
}
|
|
else
|
|
{
|
|
if (left)
|
|
left->reset();
|
|
}
|
|
if (right) // only set to ">" if we know we're on a sub-directory
|
|
right->reset();
|
|
|
|
fIndex += 1;
|
|
}
|
|
virtual SkEvent* getEvent(int index)
|
|
{
|
|
SkASSERT((unsigned)index < (unsigned)fCount);
|
|
|
|
SkEvent* evt = new SkEvent();
|
|
SkString label;
|
|
|
|
this->getRow(index, &label, NULL);
|
|
evt->setString("name", label.c_str());
|
|
|
|
int c = fPath.c_str()[fPath.size() - 1];
|
|
if (c != '/' && c != '\\')
|
|
label.prepend("/");
|
|
label.prepend(fPath);
|
|
label.append(fSuffix);
|
|
evt->setString("path", label.c_str());
|
|
evt->setS32("index", index);
|
|
evt->setS32("duration", 22);
|
|
evt->setType(fTarget);
|
|
return evt;
|
|
}
|
|
|
|
private:
|
|
SkString fPath, fSuffix;
|
|
SkString fTarget;
|
|
SkOSFile::Iter fIter;
|
|
int fCount;
|
|
int fIndex;
|
|
};
|
|
|
|
SkListSource* SkListSource::CreateFromDir(const char path[], const char suffix[], const char target[])
|
|
{
|
|
return new SkDirListSource(path, suffix, target);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
class SkDOMListSource : public SkListSource {
|
|
public:
|
|
enum Type {
|
|
kUnknown_Type,
|
|
kDir_Type,
|
|
kToggle_Type
|
|
};
|
|
struct ItemRec {
|
|
SkString fLabel;
|
|
SkString fTail, fAltTail;
|
|
SkString fTarget;
|
|
Type fType;
|
|
};
|
|
|
|
SkDOMListSource(const SkDOM& dom, const SkDOM::Node* node) : fDirTail(">")
|
|
{
|
|
const SkDOM::Node* child = dom.getFirstChild(node, "item");
|
|
int count = 0;
|
|
|
|
while (child)
|
|
{
|
|
count += 1;
|
|
child = dom.getNextSibling(child, "item");
|
|
}
|
|
|
|
fCount = count;
|
|
fList = NULL;
|
|
if (count)
|
|
{
|
|
ItemRec* rec = fList = new ItemRec[count];
|
|
|
|
child = dom.getFirstChild(node, "item");
|
|
while (child)
|
|
{
|
|
rec->fLabel.set(dom.findAttr(child, "label"));
|
|
rec->fTail.set(dom.findAttr(child, "tail"));
|
|
rec->fAltTail.set(dom.findAttr(child, "alt-tail"));
|
|
rec->fTarget.set(dom.findAttr(child, "target"));
|
|
rec->fType = kUnknown_Type;
|
|
|
|
int index = dom.findList(child, "type", "dir,toggle");
|
|
if (index >= 0)
|
|
rec->fType = (Type)(index + 1);
|
|
|
|
child = dom.getNextSibling(child, "item");
|
|
rec += 1;
|
|
}
|
|
}
|
|
}
|
|
virtual ~SkDOMListSource()
|
|
{
|
|
delete[] fList;
|
|
}
|
|
virtual int countRows()
|
|
{
|
|
return fCount;
|
|
}
|
|
virtual void getRow(int index, SkString* left, SkString* right)
|
|
{
|
|
SkASSERT((unsigned)index < (unsigned)fCount);
|
|
|
|
if (left)
|
|
*left = fList[index].fLabel;
|
|
if (right)
|
|
*right = fList[index].fType == kDir_Type ? fDirTail : fList[index].fTail;
|
|
}
|
|
virtual SkEvent* getEvent(int index)
|
|
{
|
|
SkASSERT((unsigned)index < (unsigned)fCount);
|
|
|
|
if (fList[index].fType == kDir_Type)
|
|
{
|
|
SkEvent* evt = new SkEvent();
|
|
evt->setType(fList[index].fTarget);
|
|
evt->setFast32(index);
|
|
return evt;
|
|
}
|
|
if (fList[index].fType == kToggle_Type)
|
|
fList[index].fTail.swap(fList[index].fAltTail);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
private:
|
|
int fCount;
|
|
ItemRec* fList;
|
|
SkString fDirTail;
|
|
};
|
|
|
|
SkListSource* SkListSource::CreateFromDOM(const SkDOM& dom, const SkDOM::Node* node)
|
|
{
|
|
return new SkDOMListSource(dom, node);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
SkListView::SkListView(U32 flags) : SkWidgetView(flags)
|
|
{
|
|
fSource = NULL;
|
|
fScrollIndex = 0;
|
|
fCurrIndex = -1;
|
|
fRowHeight = SkIntToScalar(16);
|
|
fVisibleRowCount = 0;
|
|
fStrCache = NULL;
|
|
|
|
fPaint[kBG_Attr].setColor(0);
|
|
fPaint[kNormalText_Attr].setTextSize(SkIntToScalar(14));
|
|
fPaint[kHiliteText_Attr].setTextSize(SkIntToScalar(14));
|
|
fPaint[kHiliteText_Attr].setColor(SK_ColorWHITE);
|
|
fPaint[kHiliteCell_Attr].setColor(SK_ColorBLUE);
|
|
}
|
|
|
|
SkListView::~SkListView()
|
|
{
|
|
delete[] fStrCache;
|
|
fSource->safeUnref();
|
|
}
|
|
|
|
void SkListView::setRowHeight(SkScalar height)
|
|
{
|
|
SkASSERT(height >= 0);
|
|
|
|
if (fRowHeight != height)
|
|
{
|
|
fRowHeight = height;
|
|
this->inval(NULL);
|
|
this->onSizeChange();
|
|
}
|
|
}
|
|
|
|
void SkListView::setSelection(int index)
|
|
{
|
|
if (fCurrIndex != index)
|
|
{
|
|
this->invalSelection();
|
|
fCurrIndex = index;
|
|
this->invalSelection();
|
|
this->ensureSelectionIsVisible();
|
|
|
|
{
|
|
SkEvent evt;
|
|
evt.setType("listview-selection");
|
|
evt.setFast32(index);
|
|
this->sendEventToParents(evt);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SkListView::moveSelectionUp()
|
|
{
|
|
if (fSource)
|
|
{
|
|
int index = fCurrIndex;
|
|
if (index < 0) // no selection
|
|
index = fSource->countRows() - 1;
|
|
else
|
|
index = SkMax32(index - 1, 0);
|
|
this->setSelection(index);
|
|
}
|
|
}
|
|
|
|
void SkListView::moveSelectionDown()
|
|
{
|
|
if (fSource)
|
|
{
|
|
int index = fCurrIndex;
|
|
if (index < 0) // no selection
|
|
index = 0;
|
|
else
|
|
index = SkMin32(index + 1, fSource->countRows() - 1);
|
|
this->setSelection(index);
|
|
}
|
|
}
|
|
|
|
void SkListView::invalSelection()
|
|
{
|
|
SkRect r;
|
|
if (this->getRowRect(fCurrIndex, &r))
|
|
this->inval(&r);
|
|
}
|
|
|
|
void SkListView::ensureSelectionIsVisible()
|
|
{
|
|
if (fSource == NULL)
|
|
return;
|
|
|
|
if ((unsigned)fCurrIndex < (unsigned)fSource->countRows())
|
|
{
|
|
int index = this->logicalToVisualIndex(fCurrIndex);
|
|
|
|
if ((unsigned)index >= (unsigned)fVisibleRowCount) // need to scroll
|
|
{
|
|
if (index < 0) // too high
|
|
fScrollIndex = fCurrIndex;
|
|
else
|
|
fScrollIndex = fCurrIndex - fVisibleRowCount + 1;
|
|
SkASSERT((unsigned)fScrollIndex < (unsigned)fSource->countRows());
|
|
|
|
this->dirtyStrCache();
|
|
this->inval(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SkListView::getRowRect(int index, SkRect* r) const
|
|
{
|
|
SkASSERT(r);
|
|
index = this->logicalToVisualIndex(index);
|
|
if (index >= 0)
|
|
{
|
|
SkScalar top = index * fRowHeight;
|
|
|
|
if (top < this->height())
|
|
{
|
|
if (r)
|
|
r->set(0, top, this->width(), top + fRowHeight);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
SkPaint& SkListView::paint(Attr attr)
|
|
{
|
|
SkASSERT((unsigned)attr < kAttrCount);
|
|
return fPaint[attr];
|
|
}
|
|
|
|
SkListSource* SkListView::setListSource(SkListSource* src)
|
|
{
|
|
if (fSource != src)
|
|
{
|
|
SkRefCnt_SafeAssign(fSource, src);
|
|
this->dirtyStrCache();
|
|
this->ensureSelectionIsVisible();
|
|
this->inval(NULL);
|
|
}
|
|
return src;
|
|
}
|
|
|
|
void SkListView::onDraw(SkCanvas* canvas)
|
|
{
|
|
this->INHERITED::onDraw(canvas);
|
|
|
|
canvas->drawPaint(fPaint[kBG_Attr]);
|
|
|
|
int visibleCount = SkMin32(fVisibleRowCount, fSource->countRows() - fScrollIndex);
|
|
if (visibleCount == 0)
|
|
return;
|
|
|
|
this->ensureStrCache(visibleCount);
|
|
int currIndex = this->logicalToVisualIndex(fCurrIndex);
|
|
|
|
if ((unsigned)currIndex < (unsigned)visibleCount)
|
|
{
|
|
SkAutoCanvasRestore restore(canvas, true);
|
|
SkRect r;
|
|
|
|
canvas->translate(0, currIndex * fRowHeight);
|
|
(void)this->getRowRect(fScrollIndex, &r);
|
|
canvas->drawRect(r, fPaint[kHiliteCell_Attr]);
|
|
}
|
|
|
|
SkPaint* p;
|
|
SkScalar y, x = SkIntToScalar(6);
|
|
SkScalar rite = this->width() - x;
|
|
|
|
{
|
|
SkScalar ascent, descent;
|
|
fPaint[kNormalText_Attr].measureText(0, NULL, &ascent, &descent);
|
|
y = SkScalarHalf(fRowHeight - descent + ascent) - ascent;
|
|
}
|
|
|
|
for (int i = 0; i < visibleCount; i++)
|
|
{
|
|
if (i == currIndex)
|
|
p = &fPaint[kHiliteText_Attr];
|
|
else
|
|
p = &fPaint[kNormalText_Attr];
|
|
|
|
p->setTextAlign(SkPaint::kLeft_Align);
|
|
canvas->drawText(fStrCache[i].c_str(), fStrCache[i].size(), x, y, *p);
|
|
p->setTextAlign(SkPaint::kRight_Align);
|
|
canvas->drawText(fStrCache[i + visibleCount].c_str(), fStrCache[i + visibleCount].size(), rite, y, *p);
|
|
canvas->translate(0, fRowHeight);
|
|
}
|
|
}
|
|
|
|
void SkListView::onSizeChange()
|
|
{
|
|
SkScalar count = SkScalarDiv(this->height(), fRowHeight);
|
|
int n = SkScalarFloor(count);
|
|
|
|
// only want to show rows that are mostly visible
|
|
if (n == 0 || count - SkIntToScalar(n) > SK_Scalar1*75/100)
|
|
n += 1;
|
|
|
|
if (fVisibleRowCount != n)
|
|
{
|
|
fVisibleRowCount = n;
|
|
this->ensureSelectionIsVisible();
|
|
this->dirtyStrCache();
|
|
}
|
|
}
|
|
|
|
void SkListView::dirtyStrCache()
|
|
{
|
|
if (fStrCache)
|
|
{
|
|
delete[] fStrCache;
|
|
fStrCache = NULL;
|
|
}
|
|
}
|
|
|
|
void SkListView::ensureStrCache(int count)
|
|
{
|
|
if (fStrCache == NULL)
|
|
{
|
|
fStrCache = new SkString[count << 1];
|
|
|
|
if (fSource)
|
|
for (int i = 0; i < count; i++)
|
|
fSource->getRow(i + fScrollIndex, &fStrCache[i], &fStrCache[i + count]);
|
|
}
|
|
}
|
|
|
|
bool SkListView::onEvent(const SkEvent& evt)
|
|
{
|
|
if (evt.isType(SK_EventType_Key))
|
|
{
|
|
switch (evt.getFast32()) {
|
|
case kUp_SkKey:
|
|
this->moveSelectionUp();
|
|
return true;
|
|
case kDown_SkKey:
|
|
this->moveSelectionDown();
|
|
return true;
|
|
case kRight_SkKey:
|
|
case kOK_SkKey:
|
|
if (fSource && fCurrIndex >= 0)
|
|
{
|
|
SkEvent* evt = fSource->getEvent(fCurrIndex);
|
|
if (evt)
|
|
{
|
|
SkView* view = this->sendEventToParents(*evt);
|
|
delete evt;
|
|
return view != NULL;
|
|
}
|
|
else // hack to make toggle work
|
|
{
|
|
this->dirtyStrCache();
|
|
this->inval(NULL);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return this->INHERITED::onEvent(evt);
|
|
}
|
|
|
|
void SkListView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
|
|
{
|
|
this->INHERITED::onInflate(dom, node);
|
|
|
|
SkScalar x;
|
|
const SkDOM::Node* child;
|
|
|
|
if (dom.findScalar(node, "row-height", &x))
|
|
this->setRowHeight(x);
|
|
|
|
if ((child = dom.getFirstChild(node, "hilite-paint")) != NULL)
|
|
SkPaint_Inflate(&this->paint(kHiliteCell_Attr), dom, child);
|
|
|
|
// look for a listsource
|
|
{
|
|
SkListSource* src = NULL;
|
|
|
|
if ((child = dom.getFirstChild(node, "file-listsource")) != NULL)
|
|
{
|
|
const char* path = dom.findAttr(child, "path");
|
|
if (path)
|
|
src = SkListSource::CreateFromDir( path,
|
|
dom.findAttr(child, "filter"),
|
|
dom.findAttr(child, "target"));
|
|
}
|
|
else if ((child = dom.getFirstChild(node, "xml-listsource")) != NULL)
|
|
{
|
|
src = SkListSource::CreateFromDOM(dom, child);
|
|
}
|
|
|
|
if (src)
|
|
{
|
|
this->setListSource(src)->unref();
|
|
this->setSelection(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "SkImageDecoder.h"
|
|
#include "SkShader.h"
|
|
|
|
class SkScrollBarView : public SkView {
|
|
public:
|
|
SkScrollBarView(const char bg[], const char fg[])
|
|
{
|
|
fBGRef = SkBitmapRef::Decode(bg, true);
|
|
fFGRef = SkBitmapRef::Decode(fg, true);
|
|
|
|
if (fBGRef)
|
|
this->setWidth(SkIntToScalar(fBGRef->bitmap().width()));
|
|
}
|
|
~SkScrollBarView()
|
|
{
|
|
delete fBGRef;
|
|
delete fFGRef;
|
|
}
|
|
protected:
|
|
virtual void onDraw(SkCanvas* canvas)
|
|
{
|
|
if (fBGRef == NULL) return;
|
|
|
|
SkPaint paint;
|
|
|
|
SkShader* shader = SkShader::CreateBitmapShader(fBGRef->bitmap(), false, SkPaint::kNo_FilterType, SkShader::kClamp_TileMode);
|
|
paint.setShader(shader)->unref();
|
|
|
|
canvas->drawPaint(paint);
|
|
}
|
|
private:
|
|
SkBitmapRef* fBGRef, *fFGRef;
|
|
};
|
|
|
|
SkGridView::SkGridView(U32 flags) : SkWidgetView(flags)
|
|
{
|
|
fSource = NULL;
|
|
fCurrIndex = -1;
|
|
fVisibleCount.set(0, 0);
|
|
|
|
fPaint[kBG_Attr].setColor(SK_ColorWHITE);
|
|
fPaint[kHiliteCell_Attr].setColor(SK_ColorYELLOW);
|
|
fPaint[kHiliteCell_Attr].setStyle(SkPaint::kStroke_Style);
|
|
fPaint[kHiliteCell_Attr].setAntiAliasOn(true);
|
|
fPaint[kHiliteCell_Attr].setStrokeWidth(SK_Scalar1*3);
|
|
|
|
fScrollBar = new SkScrollBarView("icons/scrollbarGrey.jpg", "icons/scrollbarBlue.jpg");
|
|
this->attachChildToFront(fScrollBar)->unref();
|
|
fScrollBar->setVisibleP(true);
|
|
}
|
|
|
|
SkGridView::~SkGridView()
|
|
{
|
|
fSource->safeUnref();
|
|
}
|
|
|
|
void SkGridView::getCellSize(SkPoint* size) const
|
|
{
|
|
if (size)
|
|
*size = fCellSize;
|
|
}
|
|
|
|
void SkGridView::setCellSize(SkScalar x, SkScalar y)
|
|
{
|
|
SkASSERT(x >= 0 && y >= 0);
|
|
|
|
if (!fCellSize.equals(x, y))
|
|
{
|
|
fCellSize.set(x, y);
|
|
this->inval(NULL);
|
|
}
|
|
}
|
|
|
|
void SkGridView::setSelection(int index)
|
|
{
|
|
if (fCurrIndex != index)
|
|
{
|
|
this->invalSelection();
|
|
fCurrIndex = index;
|
|
this->invalSelection();
|
|
this->ensureSelectionIsVisible();
|
|
|
|
// this generates the click
|
|
{
|
|
SkEvent evt;
|
|
evt.setType("listview-selection");
|
|
evt.setFast32(index);
|
|
this->sendEventToParents(evt);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SkGridView::moveSelectionUp()
|
|
{
|
|
if (fSource)
|
|
{
|
|
int index = fCurrIndex;
|
|
if (index < 0) // no selection
|
|
index = fSource->countRows() - 1;
|
|
else
|
|
index = SkMax32(index - 1, 0);
|
|
this->setSelection(index);
|
|
}
|
|
}
|
|
|
|
void SkGridView::moveSelectionDown()
|
|
{
|
|
if (fSource)
|
|
{
|
|
int index = fCurrIndex;
|
|
if (index < 0) // no selection
|
|
index = 0;
|
|
else
|
|
index = SkMin32(index + 1, fSource->countRows() - 1);
|
|
this->setSelection(index);
|
|
}
|
|
}
|
|
|
|
void SkGridView::invalSelection()
|
|
{
|
|
SkRect r;
|
|
if (this->getCellRect(fCurrIndex, &r))
|
|
{
|
|
SkScalar inset = 0;
|
|
if (fPaint[kHiliteCell_Attr].getStyle() != SkPaint::kFill_Style)
|
|
inset += fPaint[kHiliteCell_Attr].getStrokeWidth() / 2;
|
|
if (fPaint[kHiliteCell_Attr].isAntiAliasOn())
|
|
inset += SK_Scalar1;
|
|
r.inset(-inset, -inset);
|
|
this->inval(&r);
|
|
}
|
|
}
|
|
|
|
void SkGridView::ensureSelectionIsVisible()
|
|
{
|
|
if (fSource == NULL)
|
|
return;
|
|
#if 0
|
|
if ((unsigned)fCurrIndex < (unsigned)fSource->countRows())
|
|
{
|
|
int index = this->logicalToVisualIndex(fCurrIndex);
|
|
|
|
if ((unsigned)index >= (unsigned)fVisibleRowCount) // need to scroll
|
|
{
|
|
if (index < 0) // too high
|
|
fScrollIndex = fCurrIndex;
|
|
else
|
|
fScrollIndex = fCurrIndex - fVisibleRowCount + 1;
|
|
SkASSERT((unsigned)fScrollIndex < (unsigned)fSource->countRows());
|
|
|
|
this->dirtyStrCache();
|
|
this->inval(NULL);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool SkGridView::getCellRect(int index, SkRect* r) const
|
|
{
|
|
if (fVisibleCount.fY == 0)
|
|
return false;
|
|
|
|
index = this->logicalToVisualIndex(index);
|
|
if (index >= 0)
|
|
{
|
|
SkRect bounds;
|
|
int row = index / fVisibleCount.fY;
|
|
int col = index % fVisibleCount.fY;
|
|
|
|
bounds.set(0, 0, fCellSize.fX, fCellSize.fY);
|
|
bounds.offset(col * (fCellSize.fX + SkIntToScalar(col > 0)),
|
|
row * (fCellSize.fY + SkIntToScalar(row > 0)));
|
|
|
|
if (bounds.fTop < this->height())
|
|
{
|
|
if (r)
|
|
*r = bounds;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
SkPaint& SkGridView::paint(Attr attr)
|
|
{
|
|
SkASSERT((unsigned)attr < kAttrCount);
|
|
return fPaint[attr];
|
|
}
|
|
|
|
SkListSource* SkGridView::setListSource(SkListSource* src)
|
|
{
|
|
if (fSource != src)
|
|
{
|
|
SkRefCnt_SafeAssign(fSource, src);
|
|
// this->dirtyStrCache();
|
|
this->ensureSelectionIsVisible();
|
|
this->inval(NULL);
|
|
}
|
|
return src;
|
|
}
|
|
|
|
#include "SkShader.h"
|
|
|
|
static void copybits(SkCanvas* canvas, const SkBitmap& bm, const SkRect& dst, const SkPaint& paint)
|
|
{
|
|
SkRect src;
|
|
SkMatrix matrix;
|
|
|
|
src.set(0, 0, SkIntToScalar(bm.width()), SkIntToScalar(bm.height()));
|
|
if (matrix.setRectToRect(src, dst))
|
|
{
|
|
SkPaint p(paint);
|
|
SkShader* shader = SkShader::CreateBitmapShader(bm, false, SkPaint::kNo_FilterType, SkShader::kClamp_TileMode);
|
|
p.setShader(shader)->unref();
|
|
|
|
shader->setLocalMatrix(matrix);
|
|
canvas->drawRect(dst, p);
|
|
}
|
|
}
|
|
|
|
#include "SkImageDecoder.h"
|
|
|
|
void SkGridView::onDraw(SkCanvas* canvas)
|
|
{
|
|
this->INHERITED::onDraw(canvas);
|
|
|
|
canvas->drawPaint(fPaint[kBG_Attr]);
|
|
|
|
if (fSource == NULL)
|
|
return;
|
|
|
|
#if 0
|
|
int visibleCount = SkMin32(fVisibleRowCount, fSource->countRows() - fScrollIndex);
|
|
if (visibleCount == 0)
|
|
return;
|
|
|
|
this->ensureStrCache(visibleCount);
|
|
int currIndex = this->logicalToVisualIndex(fCurrIndex);
|
|
#endif
|
|
|
|
SkPaint p;
|
|
for (int i = 0; i < fSource->countRows(); i++)
|
|
{
|
|
bool forced = false;
|
|
SkEvent* evt = fSource->getEvent(i);
|
|
SkASSERT(evt);
|
|
SkString path(evt->findString("path"));
|
|
delete evt;
|
|
|
|
SkBitmapRef* bmr = SkBitmapRef::Decode(path.c_str(), false);
|
|
if (bmr == NULL)
|
|
{
|
|
bmr = SkBitmapRef::Decode(path.c_str(), true);
|
|
if (bmr)
|
|
forced = true;
|
|
}
|
|
|
|
if (bmr)
|
|
{
|
|
SkAutoTDelete<SkBitmapRef> autoRef(bmr);
|
|
SkRect r;
|
|
if (!this->getCellRect(i, &r))
|
|
break;
|
|
copybits(canvas, bmr->bitmap(), r, p);
|
|
}
|
|
// only draw one forced bitmap at a time
|
|
if (forced)
|
|
{
|
|
this->inval(NULL); // could inval only the remaining visible cells...
|
|
break;
|
|
}
|
|
}
|
|
|
|
// draw the hilite
|
|
{
|
|
SkRect r;
|
|
if (fCurrIndex >= 0 && this->getCellRect(fCurrIndex, &r))
|
|
canvas->drawRect(r, fPaint[kHiliteCell_Attr]);
|
|
}
|
|
}
|
|
|
|
static int check_count(int n, SkScalar s)
|
|
{
|
|
// only want to show cells that are mostly visible
|
|
if (n == 0 || s - SkIntToScalar(n) > SK_Scalar1*75/100)
|
|
n += 1;
|
|
return n;
|
|
}
|
|
|
|
void SkGridView::onSizeChange()
|
|
{
|
|
fScrollBar->setHeight(this->height());
|
|
fScrollBar->setLoc(this->locX() + this->width() - fScrollBar->width(), 0);
|
|
|
|
if (fCellSize.equals(0, 0))
|
|
{
|
|
fVisibleCount.set(0, 0);
|
|
return;
|
|
}
|
|
|
|
SkScalar rows = SkScalarDiv(this->height(), fCellSize.fY);
|
|
SkScalar cols = SkScalarDiv(this->width(), fCellSize.fX);
|
|
int y = SkScalarFloor(rows);
|
|
int x = SkScalarFloor(cols);
|
|
|
|
y = check_count(y, rows);
|
|
x = check_count(x, cols);
|
|
|
|
if (!fVisibleCount.equals(x, y))
|
|
{
|
|
fVisibleCount.set(x, y);
|
|
this->ensureSelectionIsVisible();
|
|
// this->dirtyStrCache();
|
|
}
|
|
}
|
|
|
|
bool SkGridView::onEvent(const SkEvent& evt)
|
|
{
|
|
if (evt.isType(SK_EventType_Key))
|
|
{
|
|
switch (evt.getFast32()) {
|
|
case kUp_SkKey:
|
|
this->moveSelectionUp();
|
|
return true;
|
|
case kDown_SkKey:
|
|
this->moveSelectionDown();
|
|
return true;
|
|
case kRight_SkKey:
|
|
case kOK_SkKey:
|
|
if (fSource && fCurrIndex >= 0)
|
|
{
|
|
SkEvent* evt = fSource->getEvent(fCurrIndex);
|
|
if (evt)
|
|
{
|
|
// augment the event with our local rect
|
|
(void)this->getCellRect(fCurrIndex, (SkRect*)evt->setScalars("local-rect", 4, NULL));
|
|
|
|
SkView* view = this->sendEventToParents(*evt);
|
|
delete evt;
|
|
return view != NULL;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return this->INHERITED::onEvent(evt);
|
|
}
|
|
|
|
void SkGridView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
|
|
{
|
|
this->INHERITED::onInflate(dom, node);
|
|
|
|
SkScalar x[2];
|
|
const SkDOM::Node* child;
|
|
|
|
if (dom.findScalars(node, "cell-size", x, 2))
|
|
this->setCellSize(x[0], x[1]);
|
|
|
|
if ((child = dom.getFirstChild(node, "hilite-paint")) != NULL)
|
|
SkPaint_Inflate(&this->paint(kHiliteCell_Attr), dom, child);
|
|
|
|
// look for a listsource
|
|
{
|
|
SkListSource* src = NULL;
|
|
|
|
if ((child = dom.getFirstChild(node, "file-listsource")) != NULL)
|
|
{
|
|
const char* path = dom.findAttr(child, "path");
|
|
if (path)
|
|
src = SkListSource::CreateFromDir( path,
|
|
dom.findAttr(child, "filter"),
|
|
dom.findAttr(child, "target"));
|
|
}
|
|
else if ((child = dom.getFirstChild(node, "xml-listsource")) != NULL)
|
|
{
|
|
src = SkListSource::CreateFromDOM(dom, child);
|
|
}
|
|
|
|
if (src)
|
|
{
|
|
this->setListSource(src)->unref();
|
|
this->setSelection(0);
|
|
}
|
|
}
|
|
this->onSizeChange();
|
|
}
|
|
|
|
#endif
|