blob: 0cd129e573e25e1fa1035b4f60a7f6910102adf3 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
bsalomon@google.comab9e2c62012-03-08 16:20:16 +00007
tfarina@chromium.orgb1b7f7072012-09-18 01:52:20 +00008#include "OverView.h"
reed@android.com34245c72009-11-03 04:00:48 +00009#include "SampleCode.h"
10#include "SkCanvas.h"
11#include "SkView.h"
12
commit-bot@chromium.orgab131672013-09-13 12:39:55 +000013static const char gIsOverview[] = "is-overview";
bsalomon@google.comab9e2c62012-03-08 16:20:16 +000014
reedbf015c32015-02-03 15:02:24 -080015static 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
reed@android.com34245c72009-11-03 04:00:48 +000045class OverView : public SkView {
46public:
bsalomon@google.com48dd1a22011-10-31 14:18:20 +000047 OverView(int count, const SkViewFactory* factories[]);
reed@android.com34245c72009-11-03 04:00:48 +000048 virtual ~OverView();
bsalomon@google.comab9e2c62012-03-08 16:20:16 +000049
reed@android.com34245c72009-11-03 04:00:48 +000050protected:
mtklein36352bf2015-03-25 18:17:31 -070051 bool onEvent(const SkEvent&) override;
52 bool onQuery(SkEvent* evt) override {
reed@android.com34245c72009-11-03 04:00:48 +000053 if (SampleCode::TitleQ(*evt)) {
54 SampleCode::TitleR(evt, "Overview");
55 return true;
56 }
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000057 if (evt->isType(gIsOverview)) {
58 return true;
59 }
reedbf015c32015-02-03 15:02:24 -080060 SkUnichar uni;
61 if (SampleCode::CharQ(*evt, &uni)) {
brianosmanfd957892016-03-04 11:59:27 -080062 if (uni >= ' ') {
63 fMatchStr.appendUnichar(uni);
64 }
halcanary96fcdcc2015-08-27 07:41:13 -070065 this->inval(nullptr);
reedbf015c32015-02-03 15:02:24 -080066 return true;
67 }
reed@android.com34245c72009-11-03 04:00:48 +000068 return this->INHERITED::onQuery(evt);
69 }
70
mtklein36352bf2015-03-25 18:17:31 -070071 void onDraw(SkCanvas* canvas) override;
bsalomon@google.comab9e2c62012-03-08 16:20:16 +000072
mtklein36352bf2015-03-25 18:17:31 -070073 bool onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) override {
reed@android.come72fee52009-11-16 14:52:01 +000074 return false;
75 }
76
mtklein36352bf2015-03-25 18:17:31 -070077 Click* onFindClickHandler(SkScalar cx, SkScalar cy, unsigned modi) override {
reedbf015c32015-02-03 15:02:24 -080078 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 }
reed@android.com34245c72009-11-03 04:00:48 +000090 }
halcanary96fcdcc2015-08-27 07:41:13 -070091 return nullptr;
reed@android.com34245c72009-11-03 04:00:48 +000092 }
93
94private:
bsalomon@google.comab9e2c62012-03-08 16:20:16 +000095 int fCount;
96 const SkViewFactory** fFactories;
reedbf015c32015-02-03 15:02:24 -080097 SkString* fNames;
98 SkString fMatchStr;
99 SkPaint fNamePaint;
100 SkPaint::FontMetrics fNameMetrics;
101 SkScalar fNameW;
102 SkScalar fNameH;
103
104 SkRect bounds(const SkPoint& loc) const {
105 return SkRect::MakeXYWH(loc.x(), loc.y() + fNameMetrics.fAscent, fNameW, fNameH);
106 }
107
108 SkPoint start() const {
109 return SkPoint::Make(10, -fNameMetrics.fTop);
110 }
111
112 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 }
reed@android.com34245c72009-11-03 04:00:48 +0000119
120 typedef SkView INHERITED;
121};
122
bsalomon@google.com48dd1a22011-10-31 14:18:20 +0000123SkView* create_overview(int count, const SkViewFactory* factories[]) {
halcanary385fe4d2015-08-26 13:07:48 -0700124 return new OverView(count, factories);
bsalomon@google.comab9e2c62012-03-08 16:20:16 +0000125}
126
127bool is_overview(SkView* view) {
128 SkEvent isOverview(gIsOverview);
129 return view->doQuery(&isOverview);
130}
reed@android.com34245c72009-11-03 04:00:48 +0000131
bsalomon@google.com48dd1a22011-10-31 14:18:20 +0000132OverView::OverView(int count, const SkViewFactory* factories[]) {
reed@android.com34245c72009-11-03 04:00:48 +0000133 fCount = count;
134 fFactories = factories;
reedbf015c32015-02-03 15:02:24 -0800135
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);
reed@android.com34245c72009-11-03 04:00:48 +0000151}
152
153OverView::~OverView() {
reedbf015c32015-02-03 15:02:24 -0800154 delete[] fNames;
reed@android.com34245c72009-11-03 04:00:48 +0000155}
156
157bool OverView::onEvent(const SkEvent& evt) {
158 return this->INHERITED::onEvent(evt);
159}
160
reedbf015c32015-02-03 15:02:24 -0800161void OverView::onDraw(SkCanvas* canvas) {
162 SkPaint paint;
163 paint.setColor(0xFFF8F8F8);
164 canvas->drawPaint(paint);
bsalomon@google.comab9e2c62012-03-08 16:20:16 +0000165
reedbf015c32015-02-03 15:02:24 -0800166 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->drawText(fNames[i].c_str(), fNames[i].size(), loc.x(), loc.y(), fNamePaint);
171 this->next(&loc);
reed@android.com34245c72009-11-03 04:00:48 +0000172 }
173 }
174}