OverView.cpp revision 385fe4d4b62d7d1dd76116dd570df3290a2f487b
1/* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "OverView.h" 9#include "SampleCode.h" 10#include "SkCanvas.h" 11#include "SkView.h" 12 13static const char gIsOverview[] = "is-overview"; 14 15static int to_lower(int c) { 16 if ('A' <= c && c <= 'Z') { 17 c = c - 'A' + 'a'; 18 } 19 return c; 20} 21 22static void make_lc(SkString* str) { 23 char* ptr = str->writable_str(); 24 while (*ptr) { 25 *ptr = to_lower(*ptr); 26 ptr += 1; 27 } 28} 29 30static bool case_insensitive_find(const SkString& base, const SkString& sub) { 31 SkString lcBase(base); 32 SkString lcSub(sub); 33 make_lc(&lcBase); 34 make_lc(&lcSub); 35 return lcBase.find(lcSub.c_str()) >= 0; 36} 37 38static bool draw_this_name(const SkString& name, const SkString& filter) { 39 if (filter.isEmpty()) { 40 return true; 41 } 42 return case_insensitive_find(name, filter); 43} 44 45class OverView : public SkView { 46public: 47 OverView(int count, const SkViewFactory* factories[]); 48 virtual ~OverView(); 49 50protected: 51 bool onEvent(const SkEvent&) override; 52 bool onQuery(SkEvent* evt) override { 53 if (SampleCode::TitleQ(*evt)) { 54 SampleCode::TitleR(evt, "Overview"); 55 return true; 56 } 57 if (evt->isType(gIsOverview)) { 58 return true; 59 } 60 SkUnichar uni; 61 if (SampleCode::CharQ(*evt, &uni)) { 62 fMatchStr.appendUnichar(uni); 63 this->inval(NULL); 64 return true; 65 } 66 return this->INHERITED::onQuery(evt); 67 } 68 69 void onDraw(SkCanvas* canvas) override; 70 71 bool onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) override { 72 return false; 73 } 74 75 Click* onFindClickHandler(SkScalar cx, SkScalar cy, unsigned modi) override { 76 const SkRect crect = SkRect::MakeXYWH(cx - 0.5f, cy - 0.5f, 1, 1); 77 SkPoint loc = this->start(); 78 for (int i = 0; i < fCount; ++i) { 79 if (draw_this_name(fNames[i], fMatchStr)) { 80 if (this->bounds(loc).intersects(crect)) { 81 SkEvent evt("set-curr-index"); 82 evt.setFast32(i); 83 this->sendEventToParents(evt); 84 break; 85 } 86 this->next(&loc); 87 } 88 } 89 return NULL; 90 } 91 92private: 93 int fCount; 94 const SkViewFactory** fFactories; 95 SkString* fNames; 96 SkString fMatchStr; 97 SkPaint fNamePaint; 98 SkPaint::FontMetrics fNameMetrics; 99 SkScalar fNameW; 100 SkScalar fNameH; 101 102 SkRect bounds(const SkPoint& loc) const { 103 return SkRect::MakeXYWH(loc.x(), loc.y() + fNameMetrics.fAscent, fNameW, fNameH); 104 } 105 106 SkPoint start() const { 107 return SkPoint::Make(10, -fNameMetrics.fTop); 108 } 109 110 void next(SkPoint* loc) const { 111 loc->fY += fNameH; 112 if (loc->fY > this->height() - fNameMetrics.fBottom) { 113 loc->fY = -fNameMetrics.fTop; 114 loc->fX += fNameW; 115 } 116 } 117 118 typedef SkView INHERITED; 119}; 120 121SkView* create_overview(int count, const SkViewFactory* factories[]) { 122 return new OverView(count, factories); 123} 124 125bool is_overview(SkView* view) { 126 SkEvent isOverview(gIsOverview); 127 return view->doQuery(&isOverview); 128} 129 130OverView::OverView(int count, const SkViewFactory* factories[]) { 131 fCount = count; 132 fFactories = factories; 133 134 fNames = new SkString[count]; 135 for (int i = 0; i < count; ++i) { 136 SkView* view = (*fFactories[i])(); 137 if (view) { 138 (void)SampleCode::RequestTitle(view, &fNames[i]); 139 if (0 == fNames[i].find("GM:")) { 140 fNames[i].remove(0, 3); 141 } 142 } 143 } 144 145 fNamePaint.setAntiAlias(true); 146 fNamePaint.setTextSize(12); 147 fNameW = 160; 148 fNameH = fNamePaint.getFontMetrics(&fNameMetrics); 149} 150 151OverView::~OverView() { 152 delete[] fNames; 153} 154 155bool OverView::onEvent(const SkEvent& evt) { 156 return this->INHERITED::onEvent(evt); 157} 158 159void OverView::onDraw(SkCanvas* canvas) { 160 SkPaint paint; 161 paint.setColor(0xFFF8F8F8); 162 canvas->drawPaint(paint); 163 164 SkPoint loc = this->start(); 165 for (int i = 0; i < fCount; ++i) { 166 if (draw_this_name(fNames[i], fMatchStr)) { 167 canvas->drawRect(this->bounds(loc), paint); 168 canvas->drawText(fNames[i].c_str(), fNames[i].size(), loc.x(), loc.y(), fNamePaint); 169 this->next(&loc); 170 } 171 } 172} 173 174