Browse Source

Refactor event framework. Everything uses Event* structs instead of

messy function arguments, removed on*Opaque()
tags/v0.5.0
Andrew Belt 7 years ago
parent
commit
8e251c0ddb
30 changed files with 570 additions and 397 deletions
  1. +29
    -29
      include/app.hpp
  2. +107
    -0
      include/events.hpp
  3. +77
    -87
      include/widgets.hpp
  4. +7
    -6
      src/app/Knob.cpp
  5. +36
    -24
      src/app/ModuleWidget.cpp
  6. +5
    -3
      src/app/ParamWidget.cpp
  7. +6
    -6
      src/app/PluginManagerWidget.cpp
  8. +16
    -13
      src/app/Port.cpp
  9. +17
    -13
      src/app/RackScene.cpp
  10. +16
    -10
      src/app/RackWidget.cpp
  11. +2
    -2
      src/app/SVGKnob.cpp
  12. +2
    -2
      src/app/SVGSlider.cpp
  13. +2
    -2
      src/app/SVGSwitch.cpp
  14. +11
    -11
      src/app/Toolbar.cpp
  15. +6
    -6
      src/core/AudioInterface.cpp
  16. +8
    -7
      src/core/Blank.cpp
  17. +82
    -25
      src/gui.cpp
  18. +8
    -7
      src/widgets/Button.cpp
  19. +1
    -1
      src/widgets/FramebufferWidget.cpp
  20. +4
    -4
      src/widgets/Menu.cpp
  21. +5
    -4
      src/widgets/MenuItem.cpp
  22. +11
    -7
      src/widgets/MenuOverlay.cpp
  23. +4
    -2
      src/widgets/QuantityWidget.cpp
  24. +6
    -5
      src/widgets/RadioButton.cpp
  25. +5
    -5
      src/widgets/ScrollBar.cpp
  26. +3
    -3
      src/widgets/ScrollWidget.cpp
  27. +12
    -8
      src/widgets/Slider.cpp
  28. +16
    -17
      src/widgets/TextField.cpp
  29. +37
    -76
      src/widgets/Widget.cpp
  30. +29
    -12
      src/widgets/ZoomWidget.cpp

+ 29
- 29
include/app.hpp View File

@@ -67,12 +67,12 @@ struct ModuleWidget : OpaqueWidget {
void draw(NVGcontext *vg) override;

Vec dragPos;
Widget *onMouseMove(Vec pos, Vec mouseRel) override;
Widget *onHoverKey(Vec pos, int key) override;
void onDragStart() override;
void onDragMove(Vec mouseRel) override;
void onDragEnd() override;
void onMouseDownOpaque(int button) override;
void onMouseDown(EventMouseDown &e) override;
void onMouseMove(EventMouseMove &e) override;
void onHoverKey(EventHoverKey &e) override;
void onDragStart(EventDragStart &e) override;
void onDragEnd(EventDragEnd &e) override;
void onDragMove(EventDragMove &e) override;
};

struct ValueLight;
@@ -144,9 +144,9 @@ struct RackWidget : OpaqueWidget {
void step() override;
void draw(NVGcontext *vg) override;

Widget *onMouseMove(Vec pos, Vec mouseRel) override;
void onMouseDownOpaque(int button) override;
void onZoom() override;
void onMouseMove(EventMouseMove &e) override;
void onMouseDown(EventMouseDown &e) override;
void onZoom(EventZoom &e) override;
};

struct RackRail : TransparentWidget {
@@ -184,8 +184,8 @@ struct ParamWidget : OpaqueWidget, QuantityWidget {
json_t *toJson();
void fromJson(json_t *rootJ);
virtual void randomize();
void onMouseDownOpaque(int button) override;
void onChange() override;
void onMouseDown(EventMouseDown &e) override;
void onChange(EventChange &e) override;
};

/** Implements vertical dragging behavior for ParamWidgets */
@@ -193,11 +193,11 @@ struct Knob : ParamWidget {
/** Snap to nearest integer while dragging */
bool snap = false;
float dragValue;
void onDragStart() override;
void onDragMove(Vec mouseRel) override;
void onDragEnd() override;
void onDragStart(EventDragStart &e) override;
void onDragMove(EventDragMove &e) override;
void onDragEnd(EventDragEnd &e) override;
/** Tell engine to smoothly vary this parameter */
void onChange() override;
void onChange(EventChange &e) override;
};

struct SpriteKnob : virtual Knob, SpriteWidget {
@@ -216,7 +216,7 @@ struct SVGKnob : virtual Knob, FramebufferWidget {
SVGKnob();
void setSVG(std::shared_ptr<SVG> svg);
void step() override;
void onChange() override;
void onChange(EventChange &e) override;
};

struct SVGSlider : Knob, FramebufferWidget {
@@ -228,7 +228,7 @@ struct SVGSlider : Knob, FramebufferWidget {

SVGSlider();
void step() override;
void onChange() override;
void onChange(EventChange &e) override;
};

struct Switch : ParamWidget {
@@ -243,12 +243,12 @@ struct SVGSwitch : virtual Switch, FramebufferWidget {
/** Adds an SVG file to represent the next switch position */
void addFrame(std::shared_ptr<SVG> svg);
void step() override;
void onChange() override;
void onChange(EventChange &e) override;
};

/** A switch that cycles through each mechanical position */
struct ToggleSwitch : virtual Switch {
void onDragStart() override {
void onDragStart(EventDragStart &e) override {
// Cycle through values
// e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3.
if (value >= maxValue)
@@ -262,10 +262,10 @@ struct ToggleSwitch : virtual Switch {
struct MomentarySwitch : virtual Switch {
/** Don't randomize state */
void randomize() override {}
void onDragStart() override {
void onDragStart(EventDragStart &e) override {
setValue(maxValue);
}
void onDragEnd() override {
void onDragEnd(EventDragEnd &e) override {
setValue(minValue);
}
};
@@ -286,12 +286,12 @@ struct Port : OpaqueWidget {

~Port();
void draw(NVGcontext *vg) override;
void onMouseDownOpaque(int button) override;
void onDragEnd() override;
void onDragStart() override;
void onDragDrop(Widget *origin) override;
void onDragEnter(Widget *origin) override;
void onDragLeave(Widget *origin) override;
void onMouseDown(EventMouseDown &e) override;
void onDragStart(EventDragStart &e) override;
void onDragEnd(EventDragEnd &e) override;
void onDragDrop(EventDragDrop &e) override;
void onDragEnter(EventDragEnter &e) override;
void onDragLeave(EventDragEnter &e) override;
};

struct SVGPort : Port, FramebufferWidget {
@@ -365,8 +365,8 @@ struct RackScene : Scene {
RackScene();
void step() override;
void draw(NVGcontext *vg) override;
Widget *onHoverKey(Vec pos, int key) override;
bool onPathDrop(Vec pos, const std::list<std::string>& paths) override;
void onHoverKey(EventHoverKey &e) override;
void onPathDrop(EventPathDrop &e) override;
};

////////////////////


+ 107
- 0
include/events.hpp View File

@@ -0,0 +1,107 @@
#pragma once
#include <list>

#include "math.hpp"


namespace rack {


struct Widget;


struct Event {
/** Set this to true to signal that no other widgets should receive the event */
bool consumed = false;
};

struct EventPosition : Event {
Vec pos;
};

///////////

struct EventMouseDown : EventPosition {
int button;
/** The widget which responded to the click. Set it to `this` if consumed. */
Widget *target = NULL;
};

struct EventMouseUp : EventPosition {
int button;
Widget *target = NULL;
};

struct EventMouseMove : EventPosition {
Vec mouseRel;
Widget *target = NULL;
};

struct EventHoverKey : EventPosition {
int key;
Widget *target = NULL;
};

struct EventMouseEnter : Event {
};

struct EventMouseLeave : Event {
};

struct EventFocus : Event {
};

struct EventDefocus : Event {
};

struct EventText : Event {
int codepoint;
};

struct EventKey : Event {
int key;
};

struct EventScroll : EventPosition {
Vec scrollRel;
};

/////////////

struct EventDragStart : Event {
};

struct EventDragEnd : Event {
};

struct EventDragMove : Event {
Vec mouseRel;
};

struct EventDragEnter : Event {
Widget *origin = NULL;
};

struct EventDragLeave : Event {
Widget *origin = NULL;
};

struct EventDragDrop : Event {
Widget *origin = NULL;
};

struct EventPathDrop : EventPosition {
std::list<std::string> paths;
};

struct EventAction : Event {
};

struct EventChange : Event {
};

struct EventZoom : Event {
};


} // namespace rack

+ 77
- 87
include/widgets.hpp View File

@@ -8,6 +8,7 @@

#include "math.hpp"
#include "util.hpp"
#include "events.hpp"


#define SVG_DPI 75.0
@@ -122,36 +123,36 @@ struct Widget {
Return `this` to accept the event.
Return NULL to reject the event and pass it to the widget behind this one.
*/
virtual Widget *onMouseDown(Vec pos, int button);
virtual Widget *onMouseUp(Vec pos, int button);
virtual void onMouseDown(EventMouseDown &e);
virtual void onMouseUp(EventMouseUp &e);
/** Called on every frame, even if mouseRel = Vec(0, 0) */
virtual Widget *onMouseMove(Vec pos, Vec mouseRel);
virtual Widget *onHoverKey(Vec pos, int key);
virtual void onMouseMove(EventMouseMove &e);
virtual void onHoverKey(EventHoverKey &e);
/** Called when this widget begins responding to `onMouseMove` events */
virtual void onMouseEnter() {}
virtual void onMouseEnter(EventMouseEnter &e) {}
/** Called when another widget begins responding to `onMouseMove` events */
virtual void onMouseLeave() {}
virtual bool onFocus() {return false;}
virtual void onDefocus() {}
virtual bool onFocusText(int codepoint) {return false;}
virtual bool onFocusKey(int key) {return false;}
virtual Widget *onScroll(Vec pos, Vec scrollRel);
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() {}
virtual void onDragStart(EventDragStart &e) {}
/** Called when the left button is released and this widget is being dragged */
virtual void onDragEnd() {}
virtual void onDragEnd(EventDragEnd &e) {}
/** Called when a widget responds to `onMouseMove` and is being dragged */
virtual void onDragMove(Vec mouseRel) {}
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(Widget *origin) {}
virtual void onDragLeave(Widget *origin) {}
virtual void onDragDrop(Widget *origin) {}
virtual bool onPathDrop(Vec pos, const std::list<std::string>& paths);
virtual void onAction() {}
virtual void onChange() {}
virtual void onZoom();
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 {
@@ -171,11 +172,11 @@ struct ZoomWidget : Widget {
Rect getViewport(Rect r) override;
void setZoom(float zoom);
void draw(NVGcontext *vg) override;
Widget *onMouseDown(Vec pos, int button) override;
Widget *onMouseUp(Vec pos, int button) override;
Widget *onMouseMove(Vec pos, Vec mouseRel) override;
Widget *onHoverKey(Vec pos, int key) override;
Widget *onScroll(Vec pos, Vec scrollRel) 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;
};

////////////////////
@@ -184,47 +185,36 @@ struct ZoomWidget : Widget {

/** Widget that does not respond to events */
struct TransparentWidget : virtual Widget {
Widget *onMouseDown(Vec pos, int button) override {return NULL;}
Widget *onMouseUp(Vec pos, int button) override {return NULL;}
Widget *onMouseMove(Vec pos, Vec mouseRel) override {return NULL;}
Widget *onScroll(Vec pos, Vec scrollRel) override {return NULL;}
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 {
Widget *onMouseDown(Vec pos, int button) override {
Widget *w = Widget::onMouseDown(pos, button);
if (w) return w;
onMouseDownOpaque(button);
return this;
void onMouseDown(EventMouseDown &e) override {
Widget::onMouseDown(e);
if (!e.target)
e.target = this;
e.consumed = true;
}
Widget *onMouseUp(Vec pos, int button) override {
Widget *w = Widget::onMouseUp(pos, button);
if (w) return w;
onMouseUpOpaque(button);
return this;
void onMouseUp(EventMouseUp &e) override {
Widget::onMouseUp(e);
if (!e.target)
e.target = this;
e.consumed = true;
}
Widget *onMouseMove(Vec pos, Vec mouseRel) override {
Widget *w = Widget::onMouseMove(pos, mouseRel);
if (w) return w;
onMouseMoveOpaque(mouseRel);
return this;
void onMouseMove(EventMouseMove &e) override {
Widget::onMouseMove(e);
if (!e.target)
e.target = this;
e.consumed = true;
}
Widget *onScroll(Vec pos, Vec scrollRel) override {
Widget *w = Widget::onScroll(pos, scrollRel);
if (w) return w;
if (onScrollOpaque(scrollRel))
return this;
return NULL;
void onScroll(EventScroll &e) override {
Widget::onScroll(e);
e.consumed = true;
}

/** "High level" events called by the above lower level events.
Use these if you don't care about the clicked position.
*/
virtual void onMouseDownOpaque(int button) {}
virtual void onMouseUpOpaque(int button) {}
virtual void onMouseMoveOpaque(Vec mouseRel) {}
virtual bool onScrollOpaque(Vec scrollRel) {return false;}
};

struct SpriteWidget : virtual Widget {
@@ -265,7 +255,7 @@ struct FramebufferWidget : virtual Widget {
~FramebufferWidget();
void draw(NVGcontext *vg) override;
int getImageHandle();
void onZoom() override;
void onZoom(EventZoom &e) override;
};

struct QuantityWidget : virtual Widget {
@@ -303,9 +293,9 @@ struct Label : Widget {

// Deletes itself from parent when clicked
struct MenuOverlay : OpaqueWidget {
void onDragDrop(Widget *origin) override;
bool onScrollOpaque(Vec scrollRel) override {return true;}
Widget *onHoverKey(Vec pos, int key) override;
void onDragDrop(EventDragDrop &e) override;
void onScroll(EventScroll &e) override;
void onHoverKey(EventHoverKey &e) override;
};

struct MenuEntry;
@@ -325,7 +315,7 @@ struct Menu : OpaqueWidget {
void setChildMenu(Menu *menu);
void step() override;
void draw(NVGcontext *vg) override;
bool onScrollOpaque(Vec scrollRel) override;
void onScroll(EventScroll &e) override;
};

struct MenuEntry : OpaqueWidget {
@@ -344,8 +334,8 @@ struct MenuLabel : MenuEntry {
struct MenuItem : MenuEntry {
void draw(NVGcontext *vg) override;
virtual Menu *createChildMenu() {return NULL;}
void onMouseEnter() override;
void onDragDrop(Widget *origin) override;
void onMouseEnter(EventMouseEnter &e) override;
void onDragDrop(EventDragDrop &e) override;
};

struct Button : OpaqueWidget {
@@ -356,11 +346,11 @@ struct Button : OpaqueWidget {
box.size.y = BND_WIDGET_HEIGHT;
}
void draw(NVGcontext *vg) override;
void onMouseEnter() override;
void onMouseLeave() override;
void onDragStart() override;
void onDragEnd() override;
void onDragDrop(Widget *origin) 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 {
@@ -374,9 +364,9 @@ struct RadioButton : OpaqueWidget, QuantityWidget {
box.size.y = BND_WIDGET_HEIGHT;
}
void draw(NVGcontext *vg) override;
void onMouseEnter() override;
void onMouseLeave() override;
void onDragDrop(Widget *origin) override;
void onMouseEnter(EventMouseEnter &e) override;
void onMouseLeave(EventMouseLeave &e) override;
void onDragDrop(EventDragDrop &e) override;
};

struct Slider : OpaqueWidget, QuantityWidget {
@@ -386,10 +376,10 @@ struct Slider : OpaqueWidget, QuantityWidget {
box.size.y = BND_WIDGET_HEIGHT;
}
void draw(NVGcontext *vg) override;
void onDragStart() override;
void onDragMove(Vec mouseRel) override;
void onDragEnd() override;
void onMouseDownOpaque(int button) 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 */
@@ -401,9 +391,9 @@ struct ScrollBar : OpaqueWidget {
box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT);
}
void draw(NVGcontext *vg) override;
void onDragStart() override;
void onDragMove(Vec mouseRel) override;
void onDragEnd() override;
void onDragStart(EventDragStart &e) override;
void onDragMove(EventDragMove &e) override;
void onDragEnd(EventDragEnd &e) override;
};

/** Handles a container with ScrollBar */
@@ -415,7 +405,7 @@ struct ScrollWidget : OpaqueWidget {

ScrollWidget();
void step() override;
bool onScrollOpaque(Vec scrollRel) override;
void onScroll(EventScroll &e) override;
};

struct TextField : OpaqueWidget {
@@ -429,10 +419,10 @@ struct TextField : OpaqueWidget {
box.size.y = BND_WIDGET_HEIGHT;
}
void draw(NVGcontext *vg) override;
Widget *onMouseDown(Vec pos, int button) override;
bool onFocusText(int codepoint) override;
bool onFocusKey(int key) override;
bool onFocus() 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() {}
};


+ 7
- 6
src/app/Knob.cpp View File

@@ -10,29 +10,30 @@ namespace rack {
#define KNOB_SENSITIVITY 0.0015


void Knob::onDragStart() {
void Knob::onDragStart(EventDragStart &e) {
guiCursorLock();
dragValue = value;
randomizable = false;
}

void Knob::onDragMove(Vec mouseRel) {
void Knob::onDragMove(EventDragMove &e) {
// Drag slower if Mod
float delta = KNOB_SENSITIVITY * (maxValue - minValue) * -e.mouseRel.y;
if (guiIsModPressed())
mouseRel = mouseRel.mult(1/16.0);
dragValue += KNOB_SENSITIVITY * (maxValue - minValue) * -mouseRel.y;
delta /= 16.0;
dragValue += delta;
if (snap)
setValue(roundf(dragValue));
else
setValue(dragValue);
}

void Knob::onDragEnd() {
void Knob::onDragEnd(EventDragEnd &e) {
guiCursorUnlock();
randomizable = true;
}

void Knob::onChange() {
void Knob::onChange(EventChange &e) {
if (!module)
return;



+ 36
- 24
src/app/ModuleWidget.cpp View File

@@ -165,7 +165,22 @@ void ModuleWidget::draw(NVGcontext *vg) {
nvgResetScissor(vg);
}

Widget *ModuleWidget::onMouseMove(Vec pos, Vec mouseRel) {
void ModuleWidget::onMouseDown(EventMouseDown &e) {
Widget::onMouseDown(e);
if (e.consumed)
return;

if (e.button == 1) {
createContextMenu();
}
e.consumed = true;
e.target = this;
}

void ModuleWidget::onMouseMove(EventMouseMove &e) {
OpaqueWidget::onMouseMove(e);

// Don't delete the ModuleWidget if a TextField is focused
if (!gFocusedWidget) {
// Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget.
if (glfwGetKey(gWindow, GLFW_KEY_DELETE) == GLFW_PRESS || glfwGetKey(gWindow, GLFW_KEY_BACKSPACE) == GLFW_PRESS) {
@@ -174,82 +189,85 @@ Widget *ModuleWidget::onMouseMove(Vec pos, Vec mouseRel) {
this->finalizeEvents();
delete this;
// Kinda sketchy because events will be passed further down the tree
return NULL;
return;
}
}
}
return OpaqueWidget::onMouseMove(pos, mouseRel);
}

Widget *ModuleWidget::onHoverKey(Vec pos, int key) {
switch (key) {
void ModuleWidget::onHoverKey(EventHoverKey &e) {
switch (e.key) {
case GLFW_KEY_I:
if (guiIsModPressed() && !guiIsShiftPressed()) {
reset();
return this;
e.consumed = true;
return;
}
break;
case GLFW_KEY_R:
if (guiIsModPressed() && !guiIsShiftPressed()) {
randomize();
return this;
e.consumed = true;
return;
}
break;
case GLFW_KEY_D:
if (guiIsModPressed() && !guiIsShiftPressed()) {
gRackWidget->cloneModule(this);
return this;
e.consumed = true;
return;
}
break;
}

return Widget::onHoverKey(pos, key);
Widget::onHoverKey(e);
}

void ModuleWidget::onDragStart() {
void ModuleWidget::onDragStart(EventDragStart &e) {
dragPos = gRackWidget->lastMousePos.minus(box.pos);
}

void ModuleWidget::onDragMove(Vec mouseRel) {
void ModuleWidget::onDragEnd(EventDragEnd &e) {
}

void ModuleWidget::onDragMove(EventDragMove &e) {
Rect newBox = box;
newBox.pos = gRackWidget->lastMousePos.minus(dragPos);
gRackWidget->requestModuleBoxNearest(this, newBox);
}

void ModuleWidget::onDragEnd() {
}

struct DisconnectMenuItem : MenuItem {
ModuleWidget *moduleWidget;
void onAction() override {
void onAction(EventAction &e) override {
moduleWidget->disconnect();
}
};

struct ResetMenuItem : MenuItem {
ModuleWidget *moduleWidget;
void onAction() override {
void onAction(EventAction &e) override {
moduleWidget->reset();
}
};

struct RandomizeMenuItem : MenuItem {
ModuleWidget *moduleWidget;
void onAction() override {
void onAction(EventAction &e) override {
moduleWidget->randomize();
}
};

struct CloneMenuItem : MenuItem {
ModuleWidget *moduleWidget;
void onAction() override {
void onAction(EventAction &e) override {
gRackWidget->cloneModule(moduleWidget);
}
};

struct DeleteMenuItem : MenuItem {
ModuleWidget *moduleWidget;
void onAction() override {
void onAction(EventAction &e) override {
gRackWidget->deleteModule(moduleWidget);
moduleWidget->finalizeEvents();
delete moduleWidget;
@@ -295,11 +313,5 @@ Menu *ModuleWidget::createContextMenu() {
return menu;
}

void ModuleWidget::onMouseDownOpaque(int button) {
if (button == 1) {
createContextMenu();
}
}


} // namespace rack

+ 5
- 3
src/app/ParamWidget.cpp View File

@@ -19,13 +19,15 @@ void ParamWidget::randomize() {
setValue(rescalef(randomf(), 0.0, 1.0, minValue, maxValue));
}

void ParamWidget::onMouseDownOpaque(int button) {
if (button == 1) {
void ParamWidget::onMouseDown(EventMouseDown &e) {
if (e.button == 1) {
setValue(defaultValue);
}
e.consumed = true;
e.target = this;
}

void ParamWidget::onChange() {
void ParamWidget::onChange(EventChange &e) {
if (!module)
return;



+ 6
- 6
src/app/PluginManagerWidget.cpp View File

@@ -15,7 +15,7 @@ PluginManagerWidget::PluginManagerWidget() {
Vec pos = Vec(0, 0);

struct RegisterButton : Button {
void onAction() override {
void onAction(EventAction &e) override {
std::thread t(openBrowser, "https://vcvrack.com/");
t.detach();
}
@@ -46,7 +46,7 @@ PluginManagerWidget::PluginManagerWidget() {
struct LogInButton : Button {
TextField *emailField;
TextField *passwordField;
void onAction() override {
void onAction(EventAction &e) override {
std::thread t(pluginLogIn, emailField->text, passwordField->text);
t.detach();
passwordField->text = "";
@@ -79,7 +79,7 @@ PluginManagerWidget::PluginManagerWidget() {
Vec pos = Vec(0, 0);

struct ManageButton : Button {
void onAction() override {
void onAction(EventAction &e) override {
std::thread t(openBrowser, "https://vcvrack.com/");
t.detach();
}
@@ -92,7 +92,7 @@ PluginManagerWidget::PluginManagerWidget() {
pos.x += manageButton->box.size.x;

struct RefreshButton : Button {
void onAction() override {
void onAction(EventAction &e) override {
std::thread t(pluginRefresh);
t.detach();
}
@@ -106,7 +106,7 @@ PluginManagerWidget::PluginManagerWidget() {
pos.x += refreshButton->box.size.x;

struct LogOutButton : Button {
void onAction() override {
void onAction(EventAction &e) override {
pluginLogOut();
}
};
@@ -142,7 +142,7 @@ PluginManagerWidget::PluginManagerWidget() {
pos.x += downloadProgress->box.size.x;

// struct CancelButton : Button {
// void onAction() override {
// void onAction(EventAction &e) override {
// pluginCancelDownload();
// }
// };


+ 16
- 13
src/app/Port.cpp View File

@@ -17,23 +17,20 @@ void Port::draw(NVGcontext *vg) {
}
}

void Port::onMouseDownOpaque(int button) {
if (button == 1) {
void Port::onMouseDown(EventMouseDown &e) {
if (e.button == 1) {
gRackWidget->wireContainer->removeTopWire(this);

// HACK
// Update hovered*Port of active wire if applicable
onDragEnter(NULL);
EventDragEnter e;
onDragEnter(e);
}
e.consumed = true;
e.target = this;
}

void Port::onDragEnd() {
// FIXME
// If the source Port is deleted, this will be called, removing the cable
gRackWidget->wireContainer->commitActiveWire();
}

void Port::onDragStart() {
void Port::onDragStart(EventDragStart &e) {
// Try to grab wire on top of stack
WireWidget *wire = gRackWidget->wireContainer->getTopWire(this);
if (guiIsModPressed()) {
@@ -62,10 +59,16 @@ void Port::onDragStart() {
gRackWidget->wireContainer->setActiveWire(wire);
}

void Port::onDragDrop(Widget *origin) {
void Port::onDragEnd(EventDragEnd &e) {
// FIXME
// If the source Port is deleted, this will be called, removing the cable
gRackWidget->wireContainer->commitActiveWire();
}

void Port::onDragDrop(EventDragDrop &e) {
}

void Port::onDragEnter(Widget *origin) {
void Port::onDragEnter(EventDragEnter &e) {
// Reject ports if this is an input port and something is already plugged into it
if (type == INPUT) {
WireWidget *topWire = gRackWidget->wireContainer->getTopWire(this);
@@ -82,7 +85,7 @@ void Port::onDragEnter(Widget *origin) {
}
}

void Port::onDragLeave(Widget *origin) {
void Port::onDragLeave(EventDragEnter &e) {
WireWidget *activeWire = gRackWidget->wireContainer->activeWire;
if (activeWire) {
if (type == INPUT)


+ 17
- 13
src/app/RackScene.cpp View File

@@ -82,51 +82,55 @@ void RackScene::draw(NVGcontext *vg) {
Scene::draw(vg);
}

Widget *RackScene::onHoverKey(Vec pos, int key) {
switch (key) {
void RackScene::onHoverKey(EventHoverKey &e) {
switch (e.key) {
case GLFW_KEY_N:
if (guiIsModPressed() && !guiIsShiftPressed()) {
gRackWidget->reset();
return this;
e.consumed = true;
return;
}
break;
case GLFW_KEY_Q:
if (guiIsModPressed() && !guiIsShiftPressed()) {
guiClose();
return this;
e.consumed = true;
return;
}
break;
case GLFW_KEY_O:
if (guiIsModPressed() && !guiIsShiftPressed()) {
gRackWidget->openDialog();
return this;
e.consumed = true;
return;
}
break;
case GLFW_KEY_S:
if (guiIsModPressed() && !guiIsShiftPressed()) {
gRackWidget->saveDialog();
return this;
e.consumed = true;
return;
}
if (guiIsModPressed() && guiIsShiftPressed()) {
gRackWidget->saveAsDialog();
return this;
e.consumed = true;
return;
}
break;
}

return Widget::onHoverKey(pos, key);
Widget::onHoverKey(e);
}


bool RackScene::onPathDrop(Vec pos, const std::list<std::string>& paths) {
if (paths.size() >= 1) {
const std::string& firstPath = paths.front();
void RackScene::onPathDrop(EventPathDrop &e) {
if (e.paths.size() >= 1) {
const std::string& firstPath = e.paths.front();
if (extractExtension(firstPath) == "vcv") {
gRackWidget->loadPatch(firstPath);
return true;
e.consumed = true;
}
}
return false;
}




+ 16
- 10
src/app/RackWidget.cpp View File

@@ -375,7 +375,7 @@ void RackWidget::draw(NVGcontext *vg) {
struct AddModuleMenuItem : MenuItem {
Model *model;
Vec modulePos;
void onAction() override {
void onAction(EventAction &e) override {
ModuleWidget *moduleWidget = model->createModuleWidget();
gRackWidget->moduleContainer->addChild(moduleWidget);
// Move module nearest to the mouse position
@@ -388,7 +388,7 @@ struct AddModuleMenuItem : MenuItem {

struct UrlItem : MenuItem {
std::string url;
void onAction() override {
void onAction(EventAction &e) override {
std::thread t(openBrowser, url);
t.detach();
}
@@ -487,13 +487,17 @@ struct SearchModuleField : TextField {
}
};

Widget *RackWidget::onMouseMove(Vec pos, Vec mouseRel) {
lastMousePos = pos;
return OpaqueWidget::onMouseMove(pos, mouseRel);
void RackWidget::onMouseMove(EventMouseMove &e) {
OpaqueWidget::onMouseMove(e);
lastMousePos = e.pos;
}

void RackWidget::onMouseDownOpaque(int button) {
if (button == 1) {
void RackWidget::onMouseDown(EventMouseDown &e) {
Widget::onMouseDown(e);
if (e.consumed)
return;

if (e.button == 1) {
Menu *menu = gScene->createMenu();

menu->pushChild(construct<MenuLabel>(&MenuLabel::text, "Add module"));
@@ -519,15 +523,17 @@ void RackWidget::onMouseDownOpaque(int button) {
AddManufacturerMenuItem *item = new AddManufacturerMenuItem();
item->text = manufacturerName;
item->manufacturerName = manufacturerName;
item->modulePos = lastMousePos;
item->modulePos = e.pos;
menu->pushChild(item);
}
}
e.consumed = true;
e.target = this;
}

void RackWidget::onZoom() {
void RackWidget::onZoom(EventZoom &e) {
rails->box.size = Vec();
Widget::onZoom();
Widget::onZoom(e);
}




+ 2
- 2
src/app/SVGKnob.cpp View File

@@ -35,9 +35,9 @@ void SVGKnob::step() {
FramebufferWidget::step();
}

void SVGKnob::onChange() {
void SVGKnob::onChange(EventChange &e) {
dirty = true;
Knob::onChange();
Knob::onChange(e);
}




+ 2
- 2
src/app/SVGSlider.cpp View File

@@ -21,9 +21,9 @@ void SVGSlider::step() {
FramebufferWidget::step();
}

void SVGSlider::onChange() {
void SVGSlider::onChange(EventChange &e) {
dirty = true;
ParamWidget::onChange();
ParamWidget::onChange(e);
}




+ 2
- 2
src/app/SVGSwitch.cpp View File

@@ -22,12 +22,12 @@ void SVGSwitch::step() {
FramebufferWidget::step();
}

void SVGSwitch::onChange() {
void SVGSwitch::onChange(EventChange &e) {
assert(frames.size() > 0);
int index = clampi((int) roundf(value), 0, frames.size() - 1);
sw->setSVG(frames[index]);
dirty = true;
Switch::onChange();
Switch::onChange(e);
}




+ 11
- 11
src/app/Toolbar.cpp View File

@@ -7,37 +7,37 @@ namespace rack {


struct NewItem : MenuItem {
void onAction() override {
void onAction(EventAction &e) override {
gRackWidget->reset();
}
};

struct OpenItem : MenuItem {
void onAction() override {
void onAction(EventAction &e) override {
gRackWidget->openDialog();
}
};

struct SaveItem : MenuItem {
void onAction() override {
void onAction(EventAction &e) override {
gRackWidget->saveDialog();
}
};

struct SaveAsItem : MenuItem {
void onAction() override {
void onAction(EventAction &e) override {
gRackWidget->saveAsDialog();
}
};

struct QuitItem : MenuItem {
void onAction() override {
void onAction(EventAction &e) override {
guiClose();
}
};

struct FileChoice : ChoiceButton {
void onAction() override {
void onAction(EventAction &e) override {
Menu *menu = gScene->createMenu();
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y));
menu->box.size.x = box.size.x;
@@ -54,21 +54,21 @@ struct FileChoice : ChoiceButton {


struct PauseItem : MenuItem {
void onAction() override {
void onAction(EventAction &e) override {
gPaused = !gPaused;
}
};

struct SampleRateItem : MenuItem {
float sampleRate;
void onAction() override {
void onAction(EventAction &e) override {
engineSetSampleRate(sampleRate);
gPaused = false;
}
};

struct SampleRateChoice : ChoiceButton {
void onAction() override {
void onAction(EventAction &e) override {
Menu *menu = gScene->createMenu();
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y));
menu->box.size.x = box.size.x;
@@ -149,8 +149,8 @@ Toolbar::Toolbar() {
xPos += margin;
{
struct ZoomSlider : Slider {
void onAction() override {
Slider::onAction();
void onAction(EventAction &e) override {
Slider::onAction(e);
gRackScene->zoomWidget->setZoom(value / 100.0);
}
};


+ 6
- 6
src/core/AudioInterface.cpp View File

@@ -326,14 +326,14 @@ void AudioInterface::closeDevice() {
struct AudioItem : MenuItem {
AudioInterface *audioInterface;
int deviceId;
void onAction() override {
void onAction(EventAction &e) override {
audioInterface->setDeviceId(deviceId);
}
};

struct AudioChoice : ChoiceButton {
AudioInterface *audioInterface;
void onAction() override {
void onAction(EventAction &e) override {
Menu *menu = gScene->createMenu();
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x;
@@ -364,14 +364,14 @@ struct AudioChoice : ChoiceButton {
struct SampleRateItem : MenuItem {
AudioInterface *audioInterface;
float sampleRate;
void onAction() override {
void onAction(EventAction &e) override {
audioInterface->setSampleRate(sampleRate);
}
};

struct SampleRateChoice : ChoiceButton {
AudioInterface *audioInterface;
void onAction() override {
void onAction(EventAction &e) override {
Menu *menu = gScene->createMenu();
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x;
@@ -395,14 +395,14 @@ struct SampleRateChoice : ChoiceButton {
struct BlockSizeItem : MenuItem {
AudioInterface *audioInterface;
int blockSize;
void onAction() override {
void onAction(EventAction &e) override {
audioInterface->setBlockSize(blockSize);
}
};

struct BlockSizeChoice : ChoiceButton {
AudioInterface *audioInterface;
void onAction() override {
void onAction(EventAction &e) override {
Menu *menu = gScene->createMenu();
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x;


+ 8
- 7
src/core/Blank.cpp View File

@@ -10,20 +10,21 @@ struct ModuleResizeHandle : Widget {
ModuleResizeHandle() {
box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT);
}
Widget *onMouseDown(Vec pos, int button) override {
if (button == 0)
return this;
return NULL;
void onMouseDown(EventMouseDown &e) override {
if (e.button == 0) {
e.consumed = true;
e.target = this;
}
}
void onDragStart() override {
void onDragStart(EventDragStart &e) override {
assert(parent);
originalWidth = parent->box.size.x;
totalX = 0.0;
}
void onDragMove(Vec mouseRel) override {
void onDragMove(EventDragMove &e) override {
ModuleWidget *m = dynamic_cast<ModuleWidget*>(parent);
assert(m);
totalX += mouseRel.x;
totalX += e.mouseRel.x;
float targetWidth = originalWidth;
if (right)
targetWidth += totalX;


+ 82
- 25
src/gui.cpp View File

@@ -54,25 +54,36 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) {
#endif

if (action == GLFW_PRESS) {
Widget *w = NULL;
// onMouseDown
Widget *w = gScene->onMouseDown(gMousePos, button);
{
EventMouseDown e;
e.pos = gMousePos;
e.button = button;
gScene->onMouseDown(e);
w = e.target;
}

if (button == GLFW_MOUSE_BUTTON_LEFT) {
if (w) {
// onDragStart
w->onDragStart();
EventDragStart e;
w->onDragStart(e);
}
gDraggedWidget = w;

if (w != gFocusedWidget) {
if (gFocusedWidget) {
// onDefocus
w->onDefocus();
EventDefocus e;
w->onDefocus(e);
}
gFocusedWidget = NULL;
if (w) {
// onFocus
if (w->onFocus()) {
EventFocus e;
w->onFocus(e);
if (e.consumed) {
gFocusedWidget = w;
}
}
@@ -81,17 +92,27 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) {
}
else if (action == GLFW_RELEASE) {
// onMouseUp
Widget *w = gScene->onMouseUp(gMousePos, button);
Widget *w = NULL;
{
EventMouseUp e;
e.pos = gMousePos;
e.button = button;
gScene->onMouseUp(e);
w = e.target;
}

if (button == GLFW_MOUSE_BUTTON_LEFT) {
if (gDraggedWidget) {
// onDragDrop
w->onDragDrop(gDraggedWidget);
EventDragDrop e;
e.origin = gDraggedWidget;
w->onDragDrop(e);
}
// gDraggedWidget might have been set to null in the last event, recheck here
if (gDraggedWidget) {
// onDragEnd
gDraggedWidget->onDragEnd();
EventDragEnd e;
gDraggedWidget->onDragEnd(e);
}
gDraggedWidget = NULL;
gDragHoveredWidget = NULL;
@@ -141,19 +162,32 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) {

gMousePos = mousePos;

Widget *hovered = NULL;
// onMouseMove
Widget *hovered = gScene->onMouseMove(gMousePos, mouseRel);
{
EventMouseMove e;
e.pos = mousePos;
e.mouseRel = mouseRel;
gScene->onMouseMove(e);
hovered = e.target;
}

if (gDraggedWidget) {
// onDragMove
gDraggedWidget->onDragMove(mouseRel);
EventDragMove e;
e.mouseRel = mouseRel;
gDraggedWidget->onDragMove(e);

if (hovered != gDragHoveredWidget) {
if (gDragHoveredWidget) {
gDragHoveredWidget->onDragLeave(gDraggedWidget);
EventDragEnter e;
e.origin = gDraggedWidget;
gDragHoveredWidget->onDragLeave(e);
}
if (hovered) {
hovered->onDragEnter(gDraggedWidget);
EventDragEnter e;
e.origin = gDraggedWidget;
hovered->onDragEnter(e);
}
gDragHoveredWidget = hovered;
}
@@ -162,11 +196,13 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) {
if (hovered != gHoveredWidget) {
if (gHoveredWidget) {
// onMouseLeave
gHoveredWidget->onMouseLeave();
EventMouseLeave e;
gHoveredWidget->onMouseLeave(e);
}
if (hovered) {
// onMouseEnter
hovered->onMouseEnter();
// onMouseEnter
EventMouseEnter e;
hovered->onMouseEnter(e);
}
gHoveredWidget = hovered;
}
@@ -174,14 +210,19 @@ void cursorPosCallback(GLFWwindow* window, double xpos, double ypos) {
if (glfwGetMouseButton(gWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS) {
// TODO
// Define a new global called gScrollWidget, which remembers the widget where middle-click was first pressed
gScene->onScroll(mousePos, mouseRel);
EventScroll e;
e.pos = mousePos;
e.scrollRel = mouseRel;
gScene->onScroll(e);
}
}

void cursorEnterCallback(GLFWwindow* window, int entered) {
if (!entered) {
if (gHoveredWidget) {
gHoveredWidget->onMouseLeave();
// onMouseLeave
EventMouseLeave e;
gHoveredWidget->onMouseLeave(e);
}
gHoveredWidget = NULL;
}
@@ -194,31 +235,47 @@ void scrollCallback(GLFWwindow *window, double x, double y) {
scrollRel = Vec(y, x);
#endif
// onScroll
gScene->onScroll(gMousePos, scrollRel.mult(50.0));
EventScroll e;
e.pos = gMousePos;
e.scrollRel = scrollRel.mult(50.0);
gScene->onScroll(e);
}

void charCallback(GLFWwindow *window, unsigned int codepoint) {
if (gFocusedWidget) {
gFocusedWidget->onFocusText(codepoint);
// onText
EventText e;
e.codepoint = codepoint;
gFocusedWidget->onText(e);
}
}

void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
// onFocusKey
if (gFocusedWidget && gFocusedWidget->onFocusKey(key))
return;
if (gFocusedWidget) {
// onKey
EventKey e;
e.key = key;
gFocusedWidget->onKey(e);
if (e.consumed)
return;
}
// onHoverKey
gScene->onHoverKey(gMousePos, key);
EventHoverKey e;
e.pos = gMousePos;
e.key = key;
gScene->onHoverKey(e);
}
}

void dropCallback(GLFWwindow *window, int count, const char **paths) {
std::list<std::string> pathsList;
// onPathDrop
EventPathDrop e;
e.pos = gMousePos;
for (int i = 0; i < count; i++) {
pathsList.push_back(paths[i]);
e.paths.push_back(paths[i]);
}
gScene->onPathDrop(gMousePos, pathsList);
gScene->onPathDrop(e);
}

void errorCallback(int error, const char *description) {


+ 8
- 7
src/widgets/Button.cpp View File

@@ -7,25 +7,26 @@ void Button::draw(NVGcontext *vg) {
bndToolButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str());
}

void Button::onMouseEnter() {
void Button::onMouseEnter(EventMouseEnter &e) {
state = BND_HOVER;
}

void Button::onMouseLeave() {
void Button::onMouseLeave(EventMouseLeave &e) {
state = BND_DEFAULT;
}

void Button::onDragStart() {
void Button::onDragStart(EventDragStart &e) {
state = BND_ACTIVE;
}

void Button::onDragEnd() {
void Button::onDragEnd(EventDragEnd &e) {
state = BND_HOVER;
}

void Button::onDragDrop(Widget *origin) {
if (origin == this) {
onAction();
void Button::onDragDrop(EventDragDrop &e) {
if (e.origin == this) {
EventAction eAction;
onAction(eAction);
}
}



+ 1
- 1
src/widgets/FramebufferWidget.cpp View File

@@ -117,7 +117,7 @@ int FramebufferWidget::getImageHandle() {
return internal->fb->image;
}

void FramebufferWidget::onZoom() {
void FramebufferWidget::onZoom(EventZoom &e) {
dirty = true;
}



+ 4
- 4
src/widgets/Menu.cpp View File

@@ -52,12 +52,12 @@ void Menu::draw(NVGcontext *vg) {
}


bool Menu::onScrollOpaque(Vec scrollRel) {
void Menu::onScroll(EventScroll &e) {
if (!parent)
return true;
return;
if (!parent->box.contains(box))
box.pos = box.pos.plus(scrollRel);
return true;
box.pos = box.pos.plus(e.scrollRel);
e.consumed = true;
}




+ 5
- 4
src/widgets/MenuItem.cpp View File

@@ -22,7 +22,7 @@ void MenuItem::draw(NVGcontext *vg) {
bndIconLabelValue(vg, x, 0.0, box.size.x, box.size.y, -1, rightColor, BND_LEFT, BND_LABEL_FONT_SIZE, rightText.c_str(), NULL);
}

void MenuItem::onMouseEnter() {
void MenuItem::onMouseEnter(EventMouseEnter &e) {
Menu *parentMenu = dynamic_cast<Menu*>(parent);
if (!parentMenu)
return;
@@ -38,11 +38,12 @@ void MenuItem::onMouseEnter() {
parentMenu->setChildMenu(childMenu);
}

void MenuItem::onDragDrop(Widget *origin) {
if (origin != this)
void MenuItem::onDragDrop(EventDragDrop &e) {
if (e.origin != this)
return;

onAction();
EventAction eAction;
onAction(eAction);
// deletes `this`
gScene->setOverlay(NULL);
}


+ 11
- 7
src/widgets/MenuOverlay.cpp View File

@@ -3,18 +3,22 @@

namespace rack {

void MenuOverlay::onDragDrop(Widget *origin) {
if (origin == this) {
void MenuOverlay::onDragDrop(EventDragDrop &e) {
if (e.origin == this) {
// deletes `this`
gScene->setOverlay(NULL);
}
}

Widget *MenuOverlay::onHoverKey(Vec pos, int key) {
Widget *w = Widget::onHoverKey(pos, key);
if (w) return w;
// Steal all keys
return this;
void MenuOverlay::onScroll(EventScroll &e) {
// Don't recurse children, consume the event
e.consumed = true;
}

void MenuOverlay::onHoverKey(EventHoverKey &e) {
// Recurse children but consume the event
Widget::onHoverKey(e);
e.consumed = true;
}




+ 4
- 2
src/widgets/QuantityWidget.cpp View File

@@ -4,12 +4,14 @@
namespace rack {

QuantityWidget::QuantityWidget() {
onChange();
EventChange e;
onChange(e);
}

void QuantityWidget::setValue(float value) {
this->value = clampf(value, fminf(minValue, maxValue), fmaxf(minValue, maxValue));
onChange();
EventChange e;
onChange(e);
}

void QuantityWidget::setLimits(float minValue, float maxValue) {


+ 6
- 5
src/widgets/RadioButton.cpp View File

@@ -7,22 +7,23 @@ void RadioButton::draw(NVGcontext *vg) {
bndRadioButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, value == 0.0 ? state : BND_ACTIVE, -1, label.c_str());
}

void RadioButton::onMouseEnter() {
void RadioButton::onMouseEnter(EventMouseEnter &e) {
state = BND_HOVER;
}

void RadioButton::onMouseLeave() {
void RadioButton::onMouseLeave(EventMouseLeave &e) {
state = BND_DEFAULT;
}

void RadioButton::onDragDrop(Widget *origin) {
if (origin == this) {
void RadioButton::onDragDrop(EventDragDrop &e) {
if (e.origin == this) {
if (value == 0.0)
value = 1.0;
else
value = 0.0;

onAction();
EventAction eAction;
onAction(eAction);
}
}



+ 5
- 5
src/widgets/ScrollBar.cpp View File

@@ -19,21 +19,21 @@ void ScrollBar::draw(NVGcontext *vg) {
bndScrollBar(vg, 0.0, 0.0, box.size.x, box.size.y, state, offset, size);
}

void ScrollBar::onDragStart() {
void ScrollBar::onDragStart(EventDragStart &e) {
state = BND_ACTIVE;
guiCursorLock();
}

void ScrollBar::onDragMove(Vec mouseRel) {
void ScrollBar::onDragMove(EventDragMove &e) {
ScrollWidget *scrollWidget = dynamic_cast<ScrollWidget*>(parent);
assert(scrollWidget);
if (orientation == HORIZONTAL)
scrollWidget->offset.x += mouseRel.x;
scrollWidget->offset.x += e.mouseRel.x;
else
scrollWidget->offset.y += mouseRel.y;
scrollWidget->offset.y += e.mouseRel.y;
}

void ScrollBar::onDragEnd() {
void ScrollBar::onDragEnd(EventDragEnd &e) {
state = BND_DEFAULT;
guiCursorUnlock();
}


+ 3
- 3
src/widgets/ScrollWidget.cpp View File

@@ -58,9 +58,9 @@ void ScrollWidget::step() {
Widget::step();
}

bool ScrollWidget::onScrollOpaque(Vec scrollRel) {
offset = offset.minus(scrollRel);
return true;
void ScrollWidget::onScroll(EventScroll &e) {
offset = offset.minus(e.scrollRel);
e.consumed = true;
}




+ 12
- 8
src/widgets/Slider.cpp View File

@@ -11,26 +11,30 @@ void Slider::draw(NVGcontext *vg) {
bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, progress, getText().c_str(), NULL);
}

void Slider::onDragStart() {
void Slider::onDragStart(EventDragStart &e) {
state = BND_ACTIVE;
guiCursorLock();
}

void Slider::onDragMove(Vec mouseRel) {
setValue(value + SLIDER_SENSITIVITY * (maxValue - minValue) * mouseRel.x);
void Slider::onDragMove(EventDragMove &e) {
setValue(value + SLIDER_SENSITIVITY * (maxValue - minValue) * e.mouseRel.x);
}

void Slider::onDragEnd() {
void Slider::onDragEnd(EventDragEnd &e) {
state = BND_DEFAULT;
guiCursorUnlock();
onAction();
EventAction eAction;
onAction(eAction);
}

void Slider::onMouseDownOpaque(int button) {
if (button == 1) {
void Slider::onMouseDown(EventMouseDown &e) {
if (e.button == 1) {
setValue(defaultValue);
onAction();
EventAction eAction;
onAction(eAction);
}
e.consumed = true;
e.target = this;
}




+ 16
- 17
src/widgets/TextField.cpp View File

@@ -24,21 +24,25 @@ void TextField::draw(NVGcontext *vg) {
}
}

Widget *TextField::onMouseDown(Vec pos, int button) {
end = begin = bndTextFieldTextPosition(gVg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), pos.x, pos.y);
return OpaqueWidget::onMouseDown(pos, button);
void TextField::onMouseDown(EventMouseDown &e) {
end = begin = bndTextFieldTextPosition(gVg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), e.pos.x, e.pos.y);
OpaqueWidget::onMouseDown(e);
}

void TextField::onFocus(EventFocus &e) {
begin = 0;
end = text.size();
e.consumed = true;
}

bool TextField::onFocusText(int codepoint) {
char c = codepoint;
std::string newText(1, c);
void TextField::onText(EventText &e) {
std::string newText(1, (char) e.codepoint);
insertText(newText);
return true;
e.consumed = true;
}

bool TextField::onFocusKey(int key) {
switch (key) {
void TextField::onKey(EventKey &e) {
switch (e.key) {
case GLFW_KEY_BACKSPACE:
if (begin < end) {
text.erase(begin, end - begin);
@@ -107,20 +111,15 @@ bool TextField::onFocusKey(int key) {
insertText("\n");
}
else {
onAction();
EventAction e;
onAction(e);
}
break;
}

begin = mini(maxi(begin, 0), text.size());
end = mini(maxi(end, 0), text.size());
return true;
}

bool TextField::onFocus() {
begin = 0;
end = text.size();
return true;
e.consumed = true;
}

void TextField::insertText(std::string newText) {


+ 37
- 76
src/widgets/Widget.cpp View File

@@ -78,18 +78,21 @@ void Widget::clearChildren() {
void Widget::finalizeEvents() {
// Stop dragging and hovering this widget
if (gHoveredWidget == this) {
gHoveredWidget->onMouseLeave();
EventMouseLeave e;
gHoveredWidget->onMouseLeave(e);
gHoveredWidget = NULL;
}
if (gDraggedWidget == this) {
gDraggedWidget->onDragEnd();
EventDragEnd e;
gDraggedWidget->onDragEnd(e);
gDraggedWidget = NULL;
}
if (gDragHoveredWidget == this) {
gDragHoveredWidget = NULL;
}
if (gFocusedWidget == this) {
gFocusedWidget->onDefocus();
EventDefocus e;
gFocusedWidget->onDefocus(e);
gFocusedWidget = NULL;
}
for (Widget *child : children) {
@@ -114,93 +117,51 @@ void Widget::draw(NVGcontext *vg) {
}
}

Widget *Widget::onMouseDown(Vec pos, int button) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
Widget *child = *it;
if (!child->visible)
continue;
if (child->box.contains(pos)) {
Widget *w = child->onMouseDown(pos.minus(child->box.pos), button);
if (w)
return w;
}
}
return NULL;
#define RECURSE_EVENT_POSITION(_method) { \
Vec pos = e.pos; \
for (auto it = children.rbegin(); it != children.rend(); it++) { \
Widget *child = *it; \
if (!child->visible) \
continue; \
if (child->box.contains(pos)) { \
e.pos = pos.minus(child->box.pos); \
child->_method(e); \
if (e.consumed) \
break; \
} \
} \
e.pos = pos; \
}

Widget *Widget::onMouseUp(Vec pos, int button) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
Widget *child = *it;
if (!child->visible)
continue;
if (child->box.contains(pos)) {
Widget *w = child->onMouseUp(pos.minus(child->box.pos), button);
if (w)
return w;
}
}
return NULL;

void Widget::onMouseDown(EventMouseDown &e) {
RECURSE_EVENT_POSITION(onMouseDown);
}

Widget *Widget::onMouseMove(Vec pos, Vec mouseRel) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
Widget *child = *it;
if (!child->visible)
continue;
if (child->box.contains(pos)) {
Widget *w = child->onMouseMove(pos.minus(child->box.pos), mouseRel);
if (w)
return w;
}
}
return NULL;
void Widget::onMouseUp(EventMouseUp &e) {
RECURSE_EVENT_POSITION(onMouseUp);
}

Widget *Widget::onHoverKey(Vec pos, int key) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
Widget *child = *it;
if (!child->visible)
continue;
if (child->box.contains(pos)) {
Widget *w = child->onHoverKey(pos.minus(child->box.pos), key);
if (w)
return w;
}
}
return NULL;
void Widget::onMouseMove(EventMouseMove &e) {
RECURSE_EVENT_POSITION(onMouseMove);
}

Widget *Widget::onScroll(Vec pos, Vec scrollRel) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
Widget *child = *it;
if (!child->visible)
continue;
if (child->box.contains(pos)) {
Widget *w = child->onScroll(pos.minus(child->box.pos), scrollRel);
if (w)
return w;
}
}
return NULL;
void Widget::onHoverKey(EventHoverKey &e) {
RECURSE_EVENT_POSITION(onHoverKey);
}

bool Widget::onPathDrop(Vec pos, const std::list<std::string>& paths) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
Widget *child = *it;
if (!child->visible)
continue;
if (child->box.contains(pos)) {
if (child->onPathDrop(pos.minus(child->box.pos), paths));
return true;
}
}
return false;
void Widget::onScroll(EventScroll &e) {
RECURSE_EVENT_POSITION(onScroll);
}

void Widget::onPathDrop(EventPathDrop &e) {
RECURSE_EVENT_POSITION(onPathDrop);
}

void Widget::onZoom() {
void Widget::onZoom(EventZoom &e) {
for (auto it = children.rbegin(); it != children.rend(); it++) {
Widget *child = *it;
child->onZoom();
child->onZoom(e);
}
}



+ 29
- 12
src/widgets/ZoomWidget.cpp View File

@@ -18,8 +18,10 @@ Rect ZoomWidget::getViewport(Rect r) {
}

void ZoomWidget::setZoom(float zoom) {
if (zoom != this->zoom)
onZoom();
if (zoom != this->zoom) {
EventZoom e;
onZoom(e);
}
this->zoom = zoom;
}

@@ -28,24 +30,39 @@ void ZoomWidget::draw(NVGcontext *vg) {
Widget::draw(vg);
}

Widget *ZoomWidget::onMouseDown(Vec pos, int button) {
return Widget::onMouseDown(pos.div(zoom), button);
void ZoomWidget::onMouseDown(EventMouseDown &e) {
Vec pos = e.pos;
e.pos = e.pos.div(zoom);
Widget::onMouseDown(e);
e.pos = pos;
}

Widget *ZoomWidget::onMouseUp(Vec pos, int button) {
return Widget::onMouseUp(pos.div(zoom), button);
void ZoomWidget::onMouseUp(EventMouseUp &e) {
Vec pos = e.pos;
e.pos = e.pos.div(zoom);
Widget::onMouseUp(e);
e.pos = pos;
}

Widget *ZoomWidget::onMouseMove(Vec pos, Vec mouseRel) {
return Widget::onMouseMove(pos.div(zoom), mouseRel);
void ZoomWidget::onMouseMove(EventMouseMove &e) {
Vec pos = e.pos;
e.pos = e.pos.div(zoom);
Widget::onMouseMove(e);
e.pos = pos;
}

Widget *ZoomWidget::onHoverKey(Vec pos, int key) {
return Widget::onHoverKey(pos.div(zoom), key);
void ZoomWidget::onHoverKey(EventHoverKey &e) {
Vec pos = e.pos;
e.pos = e.pos.div(zoom);
Widget::onHoverKey(e);
e.pos = pos;
}

Widget *ZoomWidget::onScroll(Vec pos, Vec scrollRel) {
return Widget::onScroll(pos.div(zoom), scrollRel);
void ZoomWidget::onScroll(EventScroll &e) {
Vec pos = e.pos;
e.pos = e.pos.div(zoom);
Widget::onScroll(e);
e.pos = pos;
}




Loading…
Cancel
Save