text: /*
   * Copyright 2019 Google Inc.
   *
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  
  #include "include/core/SkCanvas.h"
  #include "include/core/SkFont.h"
  #include "include/core/SkFontMetrics.h"
  #include "include/core/SkPath.h"
  #include "samplecode/Sample.h"
  
  #include "modules/sksg/include/SkSGDraw.h"
  #include "modules/sksg/include/SkSGGroup.h"
  #include "modules/sksg/include/SkSGPaint.h"
  #include "modules/sksg/include/SkSGRect.h"
  #include "modules/sksg/include/SkSGScene.h"
  
  struct PerNodeInfo {
      // key
      sksg::Draw* fDraw;
  
      // value(s)
      sksg::GeometryNode* fGeo;
      sksg::PaintNode*    fPaint;
  };
  
  class SampleSG : public Sample {
      SkTDArray<PerNodeInfo> fSideCar;
      sk_sp<sksg::Group> fGroup;
      std::unique_ptr<sksg::Scene> fScene;
  
      PerNodeInfo* findInfo(sksg::Draw* key) {
          for (int i = 0; i < fSideCar.count(); ++i) {
              if (fSideCar[i].fDraw == key) {
                  return &fSideCar[i];
              }
          }
          return nullptr;
      }
  
      void appendNode(sk_sp<sksg::Draw> d, sk_sp<sksg::GeometryNode> g, sk_sp<sksg::PaintNode> p) {
          fGroup->addChild(d);
          auto sc = fSideCar.append();
          sc->fDraw  = d.get();
          sc->fGeo   = g.get();
          sc->fPaint = p.get();
      }
  
  public:
      SampleSG() {
          fGroup = sksg::Group::Make();
  
          fScene = sksg::Scene::Make(fGroup, sksg::AnimatorList());
  
          auto r = sksg::Rect::Make({20, 20, 400, 300});
          auto p = sksg::Color::Make(SK_ColorRED);
          auto d = sksg::Draw::Make(r, p);
          this->appendNode(d, r, p);
  
          r = sksg::Rect::Make({60, 70, 300, 400});
          p = sksg::Color::Make(SK_ColorBLUE);
          d = sksg::Draw::Make(r, p);
          this->appendNode(d, r, p);
      }
  
  protected:
      SkString name() override { return SkString("SceneGraph"); }
  
      void onDrawContent(SkCanvas* canvas) override {
          fScene->render(canvas);
      }
  
      Click* onFindClickHandler(SkScalar x, SkScalar y, ModifierKey modi) override {
          if (auto node = fScene->nodeAt({x, y})) {
              Click* click = new Click();
              click->fMeta.setPtr("node", (void*)node);
              return click;
          }
          return nullptr;
      }
  
      bool onClick(Click* click) override {
          sksg::Draw* node = nullptr;
          if (click->fMeta.findPtr("node", (void**)&node)) {
              if (auto info = this->findInfo(node)) {
                  auto geo = info->fGeo;
                  sksg::Rect* r = (sksg::Rect*)geo;
                  SkScalar dx = click->fCurr.fX - click->fPrev.fX;
                  SkScalar dy = click->fCurr.fY - click->fPrev.fY;
                  r->setL(r->getL() + dx);
                  r->setR(r->getR() + dx);
                  r->setT(r->getT() + dy);
                  r->setB(r->getB() + dy);
              }
              return true;
          }
          return false;
      }
  
  private:
  
      typedef Sample INHERITED;
  };
  
  //////////////////////////////////////////////////////////////////////////////
  
  DEF_SAMPLE( return new SampleSG(); )
  