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     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(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 
     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 SkNEW_ARGS(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