Allow slides/gms to extend the UI

Bug: skia:
Change-Id: Ia5971d827e6e05ab6cc30af3105b3b32ee691a34
Reviewed-on: https://skia-review.googlesource.com/128321
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/gm/gm.h b/gm/gm.h
index 0447f09..a8190bf 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -10,6 +10,7 @@
 
 #include "SkBitmap.h"
 #include "SkCanvas.h"
+#include "SkMetaData.h"
 #include "SkPaint.h"
 #include "SkSize.h"
 #include "SkString.h"
@@ -89,6 +90,9 @@
             return this->onHandleKey(uni);
         }
 
+        bool getControls(SkMetaData* controls) { return this->onGetControls(controls); }
+        void setControls(const SkMetaData& controls) { this->onSetControls(controls); }
+
         virtual void modifyGrContextOptions(GrContextOptions* options) {}
 
         /** draws a standard message that the GM is only intended to be used with the GPU.*/
@@ -103,6 +107,8 @@
 
         virtual bool onAnimate(const SkAnimTimer&) { return false; }
         virtual bool onHandleKey(SkUnichar uni) { return false; }
+        virtual bool onGetControls(SkMetaData*) { return false; }
+        virtual void onSetControls(const SkMetaData&) {}
 
     private:
         Mode     fMode;
diff --git a/tools/viewer/GMSlide.cpp b/tools/viewer/GMSlide.cpp
index 40a9c99..cfd4853 100644
--- a/tools/viewer/GMSlide.cpp
+++ b/tools/viewer/GMSlide.cpp
@@ -34,3 +34,12 @@
 bool GMSlide::onChar(SkUnichar c) {
     return fGM->handleKey(c);
 }
+
+bool GMSlide::onGetControls(SkMetaData* controls) {
+    return fGM->getControls(controls);
+}
+
+void GMSlide::onSetControls(const SkMetaData& controls) {
+    fGM->setControls(controls);
+}
+
diff --git a/tools/viewer/GMSlide.h b/tools/viewer/GMSlide.h
index 2a3faa9..c03cc8a 100644
--- a/tools/viewer/GMSlide.h
+++ b/tools/viewer/GMSlide.h
@@ -23,6 +23,9 @@
 
     bool onChar(SkUnichar c) override;
 
+    bool onGetControls(SkMetaData*) override;
+    void onSetControls(const SkMetaData&) override;
+
 private:
     skiagm::GM* fGM;
 };
diff --git a/tools/viewer/Slide.h b/tools/viewer/Slide.h
index e23a2eb..127b32d 100644
--- a/tools/viewer/Slide.h
+++ b/tools/viewer/Slide.h
@@ -15,6 +15,7 @@
 
 class SkCanvas;
 class SkAnimTimer;
+class SkMetaData;
 
 class Slide : public SkRefCnt {
 public:
@@ -33,6 +34,9 @@
     virtual bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state,
                          uint32_t modifiers) { return false; }
 
+    virtual bool onGetControls(SkMetaData*) { return false; }
+    virtual void onSetControls(const SkMetaData&) {}
+
     SkString getName() { return fName; }
 
 
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index cfb8c61..c549508 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -1646,6 +1646,31 @@
                           &SkPaint::isVerticalText, &SkPaint::setVerticalText);
             }
 
+            {
+                SkMetaData controls;
+                if (fSlides[fCurrentSlide]->onGetControls(&controls)) {
+                    if (ImGui::CollapsingHeader("Current Slide")) {
+                        SkMetaData::Iter iter(controls);
+                        const char* name;
+                        SkMetaData::Type type;
+                        int count;
+                        bool found = false;
+                        while ((name = iter.next(&type, &count)) != nullptr && found == false) {
+                            if (type == SkMetaData::kScalar_Type) {
+                                float val[3];
+                                SkASSERT(count == 3);
+                                controls.findScalars(name, &count, val);
+                                if (ImGui::SliderFloat(name, &val[0], val[1], val[2])) {
+                                    controls.setScalars(name, 3, val);
+                                    fSlides[fCurrentSlide]->onSetControls(controls);
+                                    found = paramsChanged = true;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
             if (fShowSlidePicker) {
                 ImGui::SetNextTreeNodeOpen(true);
             }