Home | History | Annotate | Download | only in samplecode
      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     ~OverView() override;
     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             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 
     73     bool onSendClickToChildren(SkScalar x, SkScalar y, unsigned modi) override {
     74         return false;
     75     }
     76 
     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 
    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     }
    119 
    120     typedef SkView INHERITED;
    121 };
    122 
    123 SkView* create_overview(int count, const SkViewFactory* factories[]) {
    124     return new OverView(count, factories);
    125 }
    126 
    127 bool is_overview(SkView* view) {
    128     SkEvent isOverview(gIsOverview);
    129     return view->doQuery(&isOverview);
    130 }
    131 
    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 
    153 OverView::~OverView() {
    154     delete[] fNames;
    155 }
    156 
    157 bool OverView::onEvent(const SkEvent& evt) {
    158     return this->INHERITED::onEvent(evt);
    159 }
    160 
    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