• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
to_lower(int c)15 static int to_lower(int c) {
16     if ('A' <= c && c <= 'Z') {
17         c = c - 'A' + 'a';
18     }
19     return c;
20 }
21 
make_lc(SkString * str)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 
case_insensitive_find(const SkString & base,const SkString & sub)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 
draw_this_name(const SkString & name,const SkString & filter)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     ~OverView() override;
49 
50 protected:
51     bool onEvent(const SkEvent&) override;
onQuery(SkEvent * evt)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             if (uni >= ' ') {
63                 fMatchStr.appendUnichar(uni);
64             }
65             this->inval(nullptr);
66             return true;
67         }
68         return this->INHERITED::onQuery(evt);
69     }
70 
71     void onDraw(SkCanvas* canvas) override;
72 
onSendClickToChildren(SkScalar x,SkScalar y,unsigned modi)73     bool onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) override {
74         return false;
75     }
76 
onFindClickHandler(SkScalar cx,SkScalar cy,unsigned modi)77     Click* onFindClickHandler(SkScalar cx, SkScalar cy, unsigned modi) override {
78         const SkRect crect = SkRect::MakeXYWH(cx - 0.5f, cy - 0.5f, 1, 1);
79         SkPoint loc = this->start();
80         for (int i = 0; i < fCount; ++i) {
81             if (draw_this_name(fNames[i], fMatchStr)) {
82                 if (this->bounds(loc).intersects(crect)) {
83                     SkEvent evt("set-curr-index");
84                     evt.setFast32(i);
85                     this->sendEventToParents(evt);
86                     break;
87                 }
88                 this->next(&loc);
89             }
90         }
91         return nullptr;
92     }
93 
94 private:
95     int fCount;
96     const SkViewFactory** fFactories;
97     SkString* fNames;
98     SkString fMatchStr;
99     SkPaint fNamePaint;
100     SkPaint::FontMetrics fNameMetrics;
101     SkScalar fNameW;
102     SkScalar fNameH;
103 
bounds(const SkPoint & loc) const104     SkRect bounds(const SkPoint& loc) const {
105         return SkRect::MakeXYWH(loc.x(), loc.y() + fNameMetrics.fAscent, fNameW, fNameH);
106     }
107 
start() const108     SkPoint start() const {
109         return SkPoint::Make(10, -fNameMetrics.fTop);
110     }
111 
next(SkPoint * loc) const112     void next(SkPoint* loc) const {
113         loc->fY += fNameH;
114         if (loc->fY > this->height() - fNameMetrics.fBottom) {
115             loc->fY = -fNameMetrics.fTop;
116             loc->fX += fNameW;
117         }
118     }
119 
120     typedef SkView INHERITED;
121 };
122 
create_overview(int count,const SkViewFactory * factories[])123 SkView* create_overview(int count, const SkViewFactory* factories[]) {
124     return new OverView(count, factories);
125 }
126 
is_overview(SkView * view)127 bool is_overview(SkView* view) {
128     SkEvent isOverview(gIsOverview);
129     return view->doQuery(&isOverview);
130 }
131 
OverView(int count,const SkViewFactory * factories[])132 OverView::OverView(int count, const SkViewFactory* factories[]) {
133     fCount = count;
134     fFactories = factories;
135 
136     fNames = new SkString[count];
137     for (int i = 0; i < count; ++i) {
138         SkView* view = (*fFactories[i])();
139         if (view) {
140             (void)SampleCode::RequestTitle(view, &fNames[i]);
141             if (0 == fNames[i].find("GM:")) {
142                 fNames[i].remove(0, 3);
143             }
144         }
145     }
146 
147     fNamePaint.setAntiAlias(true);
148     fNamePaint.setTextSize(12);
149     fNameW = 160;
150     fNameH = fNamePaint.getFontMetrics(&fNameMetrics);
151 }
152 
~OverView()153 OverView::~OverView() {
154     delete[] fNames;
155 }
156 
onEvent(const SkEvent & evt)157 bool OverView::onEvent(const SkEvent& evt) {
158     return this->INHERITED::onEvent(evt);
159 }
160 
onDraw(SkCanvas * canvas)161 void OverView::onDraw(SkCanvas* canvas) {
162     SkPaint paint;
163     paint.setColor(0xFFF8F8F8);
164     canvas->drawPaint(paint);
165 
166     SkPoint loc = this->start();
167     for (int i = 0; i < fCount; ++i) {
168         if (draw_this_name(fNames[i], fMatchStr)) {
169             canvas->drawRect(this->bounds(loc), paint);
170             canvas->drawString(fNames[i], loc.x(), loc.y(), fNamePaint);
171             this->next(&loc);
172         }
173     }
174 }
175