|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- #pragma once
- #include <list>
- #include <memory>
-
- #include "../ext/nanovg/src/nanovg.h"
- #include "../ext/oui-blendish/blendish.h"
- #include "../ext/nanosvg/src/nanosvg.h"
-
- #include "math.hpp"
- #include "util.hpp"
- #include "events.hpp"
-
-
- #define SVG_DPI 75.0
-
-
- namespace rack {
-
-
- inline Vec in2px(Vec inches) {
- return inches.mult(SVG_DPI);
- }
-
- inline Vec mm2px(Vec millimeters) {
- return millimeters.mult(SVG_DPI / 25.4);
- }
-
-
- ////////////////////
- // resources
- ////////////////////
-
- // Constructing these directly will load from the disk each time. Use the load() functions to load from disk and cache them as long as the shared_ptr is held.
- // Implemented in gui.cpp
-
- struct Font {
- int handle;
- Font(const std::string &filename);
- ~Font();
- static std::shared_ptr<Font> load(const std::string &filename);
- };
-
- struct Image {
- int handle;
- Image(const std::string &filename);
- ~Image();
- static std::shared_ptr<Image> load(const std::string &filename);
- };
-
- struct SVG {
- NSVGimage *handle;
- SVG(const std::string &filename);
- ~SVG();
- static std::shared_ptr<SVG> load(const std::string &filename);
- };
-
-
- ////////////////////
- // Base widget
- ////////////////////
-
- /** A node in the 2D scene graph */
- struct Widget {
- /** Stores position and size */
- Rect box = Rect(Vec(), Vec(INFINITY, INFINITY));
- Widget *parent = NULL;
- std::list<Widget*> children;
- bool visible = true;
-
- virtual ~Widget();
-
- virtual Rect getChildrenBoundingBox();
- /** Returns `v` transformed into the coordinate system of `relative` */
- virtual Vec getRelativeOffset(Vec v, Widget *relative);
- /** Returns `v` transformed into world coordinates */
- Vec getAbsoluteOffset(Vec v) {
- return getRelativeOffset(v, NULL);
- }
- /** Returns a subset of the given Rect bounded by the box of this widget and all ancestors */
- virtual Rect getViewport(Rect r);
-
- template <class T>
- T *getAncestorOfType() {
- if (!parent) return NULL;
- T *p = dynamic_cast<T*>(parent);
- if (p) return p;
- return parent->getAncestorOfType<T>();
- }
-
- template <class T>
- T *getFirstDescendantOfType() {
- for (Widget *child : children) {
- T *c = dynamic_cast<T*>(child);
- if (c) return c;
- c = child->getFirstDescendantOfType<T>();
- if (c) return c;
- }
- return NULL;
- }
-
- /** Adds widget to list of children.
- Gives ownership of widget to this widget instance.
- */
- void addChild(Widget *widget);
- /** Removes widget from list of children if it exists.
- Does not delete widget but transfers ownership to caller
- Silently fails if widget is not a child
- */
- void removeChild(Widget *widget);
- void clearChildren();
- /** Recursively finalizes event start/end pairs as needed */
- void finalizeEvents();
-
- /** Advances the module by one frame */
- virtual void step();
- /** Draws to NanoVG context */
- virtual void draw(NVGcontext *vg);
-
- // Events
-
- /** Called when a mouse button is pressed over this widget
- 0 for left, 1 for right, 2 for middle.
- Return `this` to accept the event.
- Return NULL to reject the event and pass it to the widget behind this one.
- */
- virtual void onMouseDown(EventMouseDown &e);
- virtual void onMouseUp(EventMouseUp &e);
- /** Called on every frame, even if mouseRel = Vec(0, 0) */
- virtual void onMouseMove(EventMouseMove &e);
- virtual void onHoverKey(EventHoverKey &e);
- /** Called when this widget begins responding to `onMouseMove` events */
- virtual void onMouseEnter(EventMouseEnter &e) {}
- /** Called when another widget begins responding to `onMouseMove` events */
- virtual void onMouseLeave(EventMouseLeave &e) {}
- virtual void onFocus(EventFocus &e) {}
- virtual void onDefocus(EventDefocus &e) {}
- virtual void onText(EventText &e) {}
- virtual void onKey(EventKey &e) {}
- virtual void onScroll(EventScroll &e);
-
- /** Called when a widget responds to `onMouseDown` for a left button press */
- virtual void onDragStart(EventDragStart &e) {}
- /** Called when the left button is released and this widget is being dragged */
- virtual void onDragEnd(EventDragEnd &e) {}
- /** Called when a widget responds to `onMouseMove` and is being dragged */
- virtual void onDragMove(EventDragMove &e) {}
- /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
- virtual void onDragEnter(EventDragEnter &e) {}
- virtual void onDragLeave(EventDragEnter &e) {}
- virtual void onDragDrop(EventDragDrop &e) {}
- virtual void onPathDrop(EventPathDrop &e);
-
- virtual void onAction(EventAction &e) {}
- virtual void onChange(EventChange &e) {}
- virtual void onZoom(EventZoom &e);
- };
-
- struct TransformWidget : Widget {
- /** The transformation matrix */
- float transform[6];
- TransformWidget();
- Rect getChildrenBoundingBox() override;
- void identity();
- void translate(Vec delta);
- void rotate(float angle);
- void scale(Vec s);
- void draw(NVGcontext *vg) override;
- };
-
- struct ZoomWidget : Widget {
- float zoom = 1.0;
- Vec getRelativeOffset(Vec v, Widget *relative) override;
- Rect getViewport(Rect r) override;
- void setZoom(float zoom);
- void draw(NVGcontext *vg) override;
- void onMouseDown(EventMouseDown &e) override;
- void onMouseUp(EventMouseUp &e) override;
- void onMouseMove(EventMouseMove &e) override;
- void onHoverKey(EventHoverKey &e) override;
- void onScroll(EventScroll &e) override;
- void onPathDrop(EventPathDrop &e) override;
- };
-
- ////////////////////
- // Trait widgets
- ////////////////////
-
- /** Widget that does not respond to events */
- struct TransparentWidget : virtual Widget {
- void onMouseDown(EventMouseDown &e) override {}
- void onMouseUp(EventMouseUp &e) override {}
- void onMouseMove(EventMouseMove &e) override {}
- void onScroll(EventScroll &e) override {}
- };
-
- /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */
- struct OpaqueWidget : virtual Widget {
- void onMouseDown(EventMouseDown &e) override {
- Widget::onMouseDown(e);
- if (!e.target)
- e.target = this;
- e.consumed = true;
- }
- void onMouseUp(EventMouseUp &e) override {
- Widget::onMouseUp(e);
- if (!e.target)
- e.target = this;
- e.consumed = true;
- }
- void onMouseMove(EventMouseMove &e) override {
- Widget::onMouseMove(e);
- if (!e.target)
- e.target = this;
- e.consumed = true;
- }
- void onScroll(EventScroll &e) override {
- Widget::onScroll(e);
- e.consumed = true;
- }
- };
-
- struct SpriteWidget : virtual Widget {
- Vec spriteOffset;
- Vec spriteSize;
- std::shared_ptr<Image> spriteImage;
- int index = 0;
- void draw(NVGcontext *vg) override;
- };
-
- struct SVGWidget : virtual Widget {
- std::shared_ptr<SVG> svg;
- /** Sets the box size to the svg image size */
- void wrap();
- /** Sets and wraps the SVG */
- void setSVG(std::shared_ptr<SVG> svg);
- void draw(NVGcontext *vg) override;
- };
-
- /** Caches a widget's draw() result to a framebuffer so it is called less frequently
- When `dirty` is true, its children will be re-rendered on the next call to step() override.
- Events are not passed to the underlying scene.
- */
- struct FramebufferWidget : virtual Widget {
- /** Set this to true to re-render the children to the framebuffer the next time it is drawn */
- bool dirty = true;
- /** A margin in pixels around the children in the framebuffer
- This prevents cutting the rendered SVG off on the box edges.
- */
- float oversample;
- /** The root object in the framebuffer scene
- The FramebufferWidget owns the pointer
- */
- struct Internal;
- Internal *internal;
-
- FramebufferWidget();
- ~FramebufferWidget();
- void draw(NVGcontext *vg) override;
- int getImageHandle();
- void onZoom(EventZoom &e) override;
- };
-
- struct QuantityWidget : virtual Widget {
- float value = 0.0;
- float minValue = 0.0;
- float maxValue = 1.0;
- float defaultValue = 0.0;
- std::string label;
- /** Include a space character if you want a space after the number, e.g. " Hz" */
- std::string unit;
- /** The decimal place to round for displaying values.
- A precision of 2 will display as "1.00" for example.
- */
- int precision = 2;
-
- QuantityWidget();
- void setValue(float value);
- void setLimits(float minValue, float maxValue);
- void setDefaultValue(float defaultValue);
- /** Generates the display value */
- std::string getText();
- };
-
- ////////////////////
- // GUI widgets
- ////////////////////
-
- struct Label : Widget {
- std::string text;
- Label() {
- box.size.y = BND_WIDGET_HEIGHT;
- }
- void draw(NVGcontext *vg) override;
- };
-
- /** Deletes itself from parent when clicked */
- struct MenuOverlay : OpaqueWidget {
- void step() override;
- void onMouseDown(EventMouseDown &e) override;
- void onHoverKey(EventHoverKey &e) override;
- };
-
- struct MenuEntry;
-
- struct Menu : OpaqueWidget {
- Menu *parentMenu = NULL;
- Menu *childMenu = NULL;
- /** The entry which created the child menu */
- MenuEntry *activeEntry = NULL;
-
- Menu() {
- box.size = Vec(0, 0);
- }
- ~Menu();
- // Resizes menu and calls addChild()
- void pushChild(Widget *child) DEPRECATED {
- addChild(child);
- }
- void setChildMenu(Menu *menu);
- void step() override;
- void draw(NVGcontext *vg) override;
- void onScroll(EventScroll &e) override;
- };
-
- struct MenuEntry : OpaqueWidget {
- std::string text;
- MenuEntry() {
- box.size = Vec(0, BND_WIDGET_HEIGHT);
- }
- };
-
- struct MenuLabel : MenuEntry {
- void draw(NVGcontext *vg) override;
- void step() override;
- };
-
- struct MenuItem : MenuEntry {
- std::string rightText;
- void draw(NVGcontext *vg) override;
- void step() override;
- virtual Menu *createChildMenu() {return NULL;}
- void onMouseEnter(EventMouseEnter &e) override;
- void onDragDrop(EventDragDrop &e) override;
- };
-
- struct WindowOverlay : OpaqueWidget {
- };
-
- struct Window : OpaqueWidget {
- std::string title;
- void draw(NVGcontext *vg) override;
- void onDragMove(EventDragMove &e) override;
- };
-
- struct Button : OpaqueWidget {
- std::string text;
- BNDwidgetState state = BND_DEFAULT;
-
- Button() {
- box.size.y = BND_WIDGET_HEIGHT;
- }
- void draw(NVGcontext *vg) override;
- void onMouseEnter(EventMouseEnter &e) override;
- void onMouseLeave(EventMouseLeave &e) override;
- void onDragStart(EventDragStart &e) override;
- void onDragEnd(EventDragEnd &e) override;
- void onDragDrop(EventDragDrop &e) override;
- };
-
- struct ChoiceButton : Button {
- void draw(NVGcontext *vg) override;
- };
-
- struct RadioButton : OpaqueWidget, QuantityWidget {
- BNDwidgetState state = BND_DEFAULT;
-
- RadioButton() {
- box.size.y = BND_WIDGET_HEIGHT;
- }
- void draw(NVGcontext *vg) override;
- void onMouseEnter(EventMouseEnter &e) override;
- void onMouseLeave(EventMouseLeave &e) override;
- void onDragDrop(EventDragDrop &e) override;
- };
-
- struct Slider : OpaqueWidget, QuantityWidget {
- BNDwidgetState state = BND_DEFAULT;
-
- Slider() {
- box.size.y = BND_WIDGET_HEIGHT;
- }
- void draw(NVGcontext *vg) override;
- void onDragStart(EventDragStart &e) override;
- void onDragMove(EventDragMove &e) override;
- void onDragEnd(EventDragEnd &e) override;
- void onMouseDown(EventMouseDown &e) override;
- };
-
- /** Parent must be a ScrollWidget */
- struct ScrollBar : OpaqueWidget {
- enum { VERTICAL, HORIZONTAL } orientation;
- BNDwidgetState state = BND_DEFAULT;
- float offset = 0.0;
- float size = 0.0;
-
- ScrollBar() {
- box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT);
- }
- void draw(NVGcontext *vg) override;
- void onDragStart(EventDragStart &e) override;
- void onDragMove(EventDragMove &e) override;
- void onDragEnd(EventDragEnd &e) override;
- };
-
- /** Handles a container with ScrollBar */
- struct ScrollWidget : OpaqueWidget {
- Widget *container;
- ScrollBar *horizontalScrollBar;
- ScrollBar *verticalScrollBar;
- Vec offset;
-
- ScrollWidget();
- void draw(NVGcontext *vg) override;
- void step() override;
- void onMouseMove(EventMouseMove &e) override;
- void onScroll(EventScroll &e) override;
- };
-
- struct TextField : OpaqueWidget {
- std::string text;
- std::string placeholder;
- bool multiline = false;
- int begin = 0;
- int end = 0;
-
- TextField() {
- box.size.y = BND_WIDGET_HEIGHT;
- }
- void draw(NVGcontext *vg) override;
- void onMouseDown(EventMouseDown &e) override;
- void onFocus(EventFocus &e) override;
- void onText(EventText &e) override;
- void onKey(EventKey &e) override;
- void insertText(std::string newText);
- virtual void onTextChange() {}
- };
-
- struct PasswordField : TextField {
- void draw(NVGcontext *vg) override;
- };
-
- struct ProgressBar : TransparentWidget, QuantityWidget {
- ProgressBar() {
- box.size.y = BND_WIDGET_HEIGHT;
- }
- void draw(NVGcontext *vg) override;
- };
-
- struct Tooltip : Widget {
- void step() override;
- void draw(NVGcontext *vg) override;
- };
-
- struct Scene : OpaqueWidget {
- Widget *overlay = NULL;
- void setOverlay(Widget *w);
- Menu *createMenu();
- void step() override;
- };
-
-
- ////////////////////
- // globals
- ////////////////////
-
- extern Widget *gHoveredWidget;
- extern Widget *gDraggedWidget;
- extern Widget *gDragHoveredWidget;
- extern Widget *gFocusedWidget;
-
- extern Scene *gScene;
-
-
- } // namespace rack
|