messy function arguments, removed on*Opaque()tags/v0.5.0
@@ -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; | |||
}; | |||
//////////////////// | |||
@@ -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 |
@@ -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() {} | |||
}; | |||
@@ -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; | |||
@@ -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 |
@@ -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; | |||
@@ -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(); | |||
// } | |||
// }; | |||
@@ -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) | |||
@@ -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; | |||
} | |||
@@ -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); | |||
} | |||
@@ -35,9 +35,9 @@ void SVGKnob::step() { | |||
FramebufferWidget::step(); | |||
} | |||
void SVGKnob::onChange() { | |||
void SVGKnob::onChange(EventChange &e) { | |||
dirty = true; | |||
Knob::onChange(); | |||
Knob::onChange(e); | |||
} | |||
@@ -21,9 +21,9 @@ void SVGSlider::step() { | |||
FramebufferWidget::step(); | |||
} | |||
void SVGSlider::onChange() { | |||
void SVGSlider::onChange(EventChange &e) { | |||
dirty = true; | |||
ParamWidget::onChange(); | |||
ParamWidget::onChange(e); | |||
} | |||
@@ -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); | |||
} | |||
@@ -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); | |||
} | |||
}; | |||
@@ -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; | |||
@@ -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; | |||
@@ -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) { | |||
@@ -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); | |||
} | |||
} | |||
@@ -117,7 +117,7 @@ int FramebufferWidget::getImageHandle() { | |||
return internal->fb->image; | |||
} | |||
void FramebufferWidget::onZoom() { | |||
void FramebufferWidget::onZoom(EventZoom &e) { | |||
dirty = true; | |||
} | |||
@@ -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; | |||
} | |||
@@ -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); | |||
} | |||
@@ -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,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) { | |||
@@ -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); | |||
} | |||
} | |||
@@ -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(); | |||
} | |||
@@ -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; | |||
} | |||
@@ -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; | |||
} | |||
@@ -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) { | |||
@@ -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); | |||
} | |||
} | |||
@@ -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; | |||
} | |||