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 13 static const char gIsOverview[] = "is-overview"; 14 15 static int to_lower(int c) { 16 if ('A' <= c && c <= 'Z') { 17 c = c - 'A' + 'a'; 18 } 19 return c; 20 } 21 22 static 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 30 static 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 38 static 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 45 class OverView : public SkView { 46 public: 47 OverView(int count, const SkViewFactory* factories[]); 48 virtual ~OverView(); 49 50 protected: 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(nullptr); 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 nullptr; 90 } 91 92 private: 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 121 SkView* create_overview(int count, const SkViewFactory* factories[]) { 122 return new OverView(count, factories); 123 } 124 125 bool is_overview(SkView* view) { 126 SkEvent isOverview(gIsOverview); 127 return view->doQuery(&isOverview); 128 } 129 130 OverView::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 151 OverView::~OverView() { 152 delete[] fNames; 153 } 154 155 bool OverView::onEvent(const SkEvent& evt) { 156 return this->INHERITED::onEvent(evt); 157 } 158 159 void 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