| /* | 
 |  * 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 "include/private/SkTDArray.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" | 
 | #include "tools/viewer/ClickHandlerSlide.h" | 
 |  | 
 | struct PerNodeInfo { | 
 |     // key | 
 |     sksg::Draw* fDraw; | 
 |  | 
 |     // value(s) | 
 |     sksg::GeometryNode* fGeo; | 
 |     sksg::PaintNode*    fPaint; | 
 | }; | 
 |  | 
 | class SGSlide : public ClickHandlerSlide { | 
 |     // TODO(kjlubick) use a vector instead of our private SkTDArray | 
 |     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.size(); ++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: | 
 |     SGSlide() { | 
 |         fGroup = sksg::Group::Make(); | 
 |  | 
 |         fScene = sksg::Scene::Make(fGroup); | 
 |  | 
 |         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); | 
 |         fName = "SceneGraph"; | 
 |     } | 
 |  | 
 |     void draw(SkCanvas* canvas) override { | 
 |         fScene->render(canvas); | 
 |     } | 
 |  | 
 | protected: | 
 |     Click* onFindClickHandler(SkScalar x, SkScalar y, skui::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; | 
 |     } | 
 | }; | 
 |  | 
 | ////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | DEF_SLIDE( return new SGSlide(); ) |