@@ -12,6 +12,7 @@ namespace app { | |||
struct PortWidget : widget::OpaqueWidget { | |||
engine::Module *module = NULL; | |||
int portId; | |||
bool hovered = false; | |||
enum Type { | |||
OUTPUT, | |||
@@ -27,6 +28,8 @@ struct PortWidget : widget::OpaqueWidget { | |||
void draw(const widget::DrawContext &ctx) override; | |||
void onButton(const event::Button &e) override; | |||
void onEnter(const event::Enter &e) override; | |||
void onLeave(const event::Leave &e) override; | |||
void onDragStart(const event::DragStart &e) override; | |||
void onDragEnd(const event::DragEnd &e) override; | |||
void onDragDrop(const event::DragDrop &e) override; | |||
@@ -110,6 +110,7 @@ struct HoverScroll : Event, Position { | |||
/** Occurs when a Widget begins consuming the Hover event. | |||
Must consume to set the widget as hovered. | |||
*/ | |||
struct Enter : Event { | |||
}; | |||
@@ -122,6 +123,7 @@ struct Leave : Event { | |||
/** Occurs when a Widget begins consuming the Button press event. | |||
Must consume to set the widget as selected. | |||
*/ | |||
struct Select : Event { | |||
}; | |||
@@ -141,12 +143,14 @@ struct SelectKey : Event, Key { | |||
/** Occurs when text is typed while a Widget is selected. | |||
If consumed, a HoverText event will not be triggered. | |||
*/ | |||
struct SelectText : Event, Text { | |||
}; | |||
/** Occurs when a Widget begins being dragged. | |||
Must consume to set the widget as dragged. | |||
*/ | |||
struct DragStart : Event { | |||
}; | |||
@@ -177,6 +181,7 @@ struct DragHover : Event, Position { | |||
}; | |||
/** Occurs when the mouse enters a Widget while dragging. | |||
Must consume to set the widget as drag-hovered. | |||
*/ | |||
struct DragEnter : Event { | |||
/** The dragged widget */ | |||
@@ -21,6 +21,7 @@ struct MenuItem : MenuEntry { | |||
void draw(const widget::DrawContext &ctx) override; | |||
void step() override; | |||
void onEnter(const event::Enter &e) override; | |||
void onDragStart(const event::DragStart &e) override; | |||
void onDragDrop(const event::DragDrop &e) override; | |||
void doAction(); | |||
virtual Menu *createChildMenu() {return NULL;} | |||
@@ -25,6 +25,7 @@ struct TextField : widget::OpaqueWidget { | |||
void onButton(const event::Button &e) override; | |||
void onHover(const event::Hover &e) override; | |||
void onEnter(const event::Enter &e) override; | |||
void onSelect(const event::Select &e) override; | |||
void onSelectText(const event::SelectText &e) override; | |||
void onSelectKey(const event::SelectKey &e) override; | |||
@@ -30,19 +30,24 @@ struct ModuleResizeHandle : Widget { | |||
bool right = false; | |||
float dragX; | |||
Rect originalBox; | |||
ModuleResizeHandle() { | |||
box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT); | |||
} | |||
void onButton(const event::Button &e) override { | |||
if (e.button == GLFW_MOUSE_BUTTON_LEFT) { | |||
e.consume(this); | |||
} | |||
} | |||
void onDragStart(const event::DragStart &e) override { | |||
dragX = APP->scene->rackWidget->mousePos.x; | |||
ModuleWidget *m = getAncestorOfType<ModuleWidget>(); | |||
originalBox = m->box; | |||
e.consume(this); | |||
} | |||
void onDragMove(const event::DragMove &e) override { | |||
ModuleWidget *m = getAncestorOfType<ModuleWidget>(); | |||
@@ -64,6 +69,7 @@ struct ModuleResizeHandle : Widget { | |||
} | |||
APP->scene->rackWidget->requestModuleBox(m, newBox); | |||
} | |||
void draw(const DrawContext &ctx) override { | |||
for (float x = 5.0; x <= 10.0; x += 5.0) { | |||
nvgBeginPath(ctx.vg); | |||
@@ -88,10 +88,8 @@ struct CcChoice : LedDisplayChoice { | |||
} | |||
void step() override { | |||
if (!module) { | |||
text = ""; | |||
if (!module) | |||
return; | |||
} | |||
if (module->learningId == id) { | |||
if (0 <= focusCc) | |||
text = string::f("%d", focusCc); | |||
@@ -103,25 +101,27 @@ struct CcChoice : LedDisplayChoice { | |||
text = string::f("%d", module->learnedCcs[id]); | |||
color.a = 1.0; | |||
if (APP->event->selectedWidget == this) | |||
APP->event->selectedWidget = NULL; | |||
APP->event->setSelected(NULL); | |||
} | |||
} | |||
void onSelect(const event::Select &e) override { | |||
e.consume(this); | |||
if (!module) | |||
return; | |||
module->learningId = id; | |||
focusCc = -1; | |||
e.consume(this); | |||
} | |||
void onDeselect(const event::Deselect &e) override { | |||
if (!module) | |||
return; | |||
if (0 <= focusCc && focusCc < 128) { | |||
module->learnedCcs[id] = focusCc; | |||
if (module->learningId == id) { | |||
if (0 <= focusCc && focusCc < 128) { | |||
module->learnedCcs[id] = focusCc; | |||
} | |||
module->learningId = -1; | |||
} | |||
module->learningId = -1; | |||
} | |||
void onSelectText(const event::SelectText &e) override { | |||
@@ -180,20 +180,22 @@ struct NoteChoice : LedDisplayChoice { | |||
color.a = 1.0; | |||
if (APP->event->selectedWidget == this) | |||
APP->event->selectedWidget = NULL; | |||
APP->event->setSelected(NULL); | |||
} | |||
} | |||
void onSelect(const event::Select &e) override { | |||
e.consume(this); | |||
if (!module) | |||
return; | |||
module->learningId = id; | |||
e.consume(this); | |||
} | |||
void onDeselect(const event::Deselect &e) override { | |||
if (!module) | |||
return; | |||
module->learningId = -1; | |||
if (module->learningId == id) { | |||
module->learningId = -1; | |||
} | |||
} | |||
}; |
@@ -216,8 +216,7 @@ void CableWidget::draw(const widget::DrawContext &ctx) { | |||
} | |||
else { | |||
// Draw opaque if mouse is hovering over a connected port | |||
PortWidget *hoveredPort = dynamic_cast<PortWidget*>(APP->event->hoveredWidget); | |||
if (hoveredPort && (hoveredPort == outputPort || hoveredPort == inputPort)) | |||
if (outputPort->hovered || inputPort->hovered) | |||
opacity = 1.0; | |||
} | |||
@@ -36,6 +36,7 @@ void Knob::onDragStart(const event::DragStart &e) { | |||
} | |||
APP->window->cursorLock(); | |||
e.consume(this); | |||
} | |||
void Knob::onDragEnd(const event::DragEnd &e) { | |||
@@ -62,6 +62,7 @@ struct ModuleBox : widget::OpaqueWidget { | |||
widget::Widget *previewWidget = NULL; | |||
/** Number of frames since draw() has been called */ | |||
int visibleFrames = 0; | |||
bool selected = false; | |||
void setModel(plugin::Model *model) { | |||
this->model = model; | |||
@@ -125,7 +126,7 @@ struct ModuleBox : widget::OpaqueWidget { | |||
} | |||
widget::OpaqueWidget::draw(ctx); | |||
if (APP->event->hoveredWidget == this) { | |||
if (selected) { | |||
nvgBeginPath(ctx.vg); | |||
nvgRect(ctx.vg, 0.0, 0.0, box.size.x, box.size.y); | |||
nvgFillColor(ctx.vg, nvgRGBAf(1, 1, 1, 0.25)); | |||
@@ -134,6 +135,15 @@ struct ModuleBox : widget::OpaqueWidget { | |||
} | |||
void onButton(const event::Button &e) override; | |||
void onEnter(const event::Enter &e) override { | |||
e.consume(this); | |||
selected = true; | |||
} | |||
void onLeave(const event::Leave &e) override { | |||
selected = false; | |||
} | |||
}; | |||
@@ -193,13 +193,15 @@ void ModuleWidget::drawShadow(const widget::DrawContext &ctx) { | |||
void ModuleWidget::onHover(const event::Hover &e) { | |||
widget::OpaqueWidget::onHover(e); | |||
// 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(APP->window->win, GLFW_KEY_DELETE) == GLFW_PRESS | |||
|| glfwGetKey(APP->window->win, GLFW_KEY_BACKSPACE) == GLFW_PRESS) | |||
&& (APP->window->getMods() & WINDOW_MOD_MASK) == 0) { | |||
removeAction(); | |||
e.consume(NULL); | |||
return; | |||
if (!APP->event->selectedWidget) { | |||
// 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(APP->window->win, GLFW_KEY_DELETE) == GLFW_PRESS | |||
|| glfwGetKey(APP->window->win, GLFW_KEY_BACKSPACE) == GLFW_PRESS) | |||
&& (APP->window->getMods() & WINDOW_MOD_MASK) == 0) { | |||
removeAction(); | |||
e.consume(NULL); | |||
return; | |||
} | |||
} | |||
} | |||
@@ -268,6 +270,7 @@ void ModuleWidget::onHoverKey(const event::HoverKey &e) { | |||
void ModuleWidget::onDragStart(const event::DragStart &e) { | |||
oldPos = box.pos; | |||
dragPos = APP->scene->rackWidget->mousePos.minus(box.pos); | |||
e.consume(this); | |||
} | |||
void ModuleWidget::onDragEnd(const event::DragEnd &e) { | |||
@@ -167,6 +167,7 @@ void ParamWidget::onEnter(const event::Enter &e) { | |||
paramTooltip->paramWidget = this; | |||
APP->scene->addChild(paramTooltip); | |||
tooltip = paramTooltip; | |||
e.consume(this); | |||
} | |||
} | |||
@@ -78,6 +78,15 @@ void PortWidget::onButton(const event::Button &e) { | |||
e.consume(this); | |||
} | |||
void PortWidget::onEnter(const event::Enter &e) { | |||
hovered = true; | |||
e.consume(this); | |||
} | |||
void PortWidget::onLeave(const event::Leave &e) { | |||
hovered = false; | |||
} | |||
void PortWidget::onDragStart(const event::DragStart &e) { | |||
CableWidget *cw = NULL; | |||
if (type == OUTPUT && (APP->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) { | |||
@@ -110,6 +119,7 @@ void PortWidget::onDragStart(const event::DragStart &e) { | |||
cw->setInput(this); | |||
} | |||
APP->scene->rackWidget->setIncompleteCable(cw); | |||
e.consume(this); | |||
} | |||
void PortWidget::onDragEnd(const event::DragEnd &e) { | |||
@@ -158,6 +168,7 @@ void PortWidget::onDragEnter(const event::DragEnter &e) { | |||
else | |||
cw->hoveredInputPort = this; | |||
} | |||
e.consume(this); | |||
} | |||
void PortWidget::onDragLeave(const event::DragLeave &e) { | |||
@@ -28,6 +28,7 @@ void SVGButton::onDragStart(const event::DragStart &e) { | |||
sw->setSVG(frames[1]); | |||
fb->dirty = true; | |||
} | |||
e.consume(this); | |||
} | |||
void SVGButton::onDragEnd(const event::DragEnd &e) { | |||
@@ -55,6 +55,7 @@ void Switch::onDragStart(const event::DragStart &e) { | |||
} | |||
} | |||
} | |||
e.consume(this); | |||
} | |||
void Switch::onDragEnd(const event::DragEnd &e) { | |||
@@ -415,9 +415,10 @@ struct AccountEmailField : ui::TextField { | |||
if (e.action == GLFW_PRESS && e.key == GLFW_KEY_TAB) { | |||
APP->event->selectedWidget = passwordField; | |||
e.consume(this); | |||
return; | |||
} | |||
ui::TextField::onSelectKey(e); | |||
if (!e.getConsumed()) | |||
ui::TextField::onSelectKey(e); | |||
} | |||
}; | |||
@@ -431,9 +432,10 @@ struct AccountPasswordField : ui::PasswordField { | |||
if (e.action == GLFW_PRESS && (e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER)) { | |||
logInItem->doAction(); | |||
e.consume(this); | |||
return; | |||
} | |||
ui::PasswordField::onSelectKey(e); | |||
if (!e.getConsumed()) | |||
ui::PasswordField::onSelectKey(e); | |||
} | |||
}; | |||
@@ -14,14 +14,16 @@ void State::setHovered(widget::Widget *w) { | |||
// event::Leave | |||
event::Leave eLeave; | |||
hoveredWidget->onLeave(eLeave); | |||
hoveredWidget = NULL; | |||
} | |||
hoveredWidget = w; | |||
if (hoveredWidget) { | |||
if (w) { | |||
// event::Enter | |||
event::Context eEnterContext; | |||
event::Enter eEnter; | |||
hoveredWidget->onEnter(eEnter); | |||
eEnter.context = &eEnterContext; | |||
w->onEnter(eEnter); | |||
hoveredWidget = eEnterContext.consumed; | |||
} | |||
} | |||
@@ -33,14 +35,16 @@ void State::setDragged(widget::Widget *w) { | |||
// event::DragEnd | |||
event::DragEnd eDragEnd; | |||
draggedWidget->onDragEnd(eDragEnd); | |||
draggedWidget = NULL; | |||
} | |||
draggedWidget = w; | |||
if (draggedWidget) { | |||
if (w) { | |||
// event::DragStart | |||
event::Context eDragStartContext; | |||
event::DragStart eDragStart; | |||
draggedWidget->onDragStart(eDragStart); | |||
eDragStart.context = &eDragStartContext; | |||
w->onDragStart(eDragStart); | |||
draggedWidget = eDragStartContext.consumed; | |||
} | |||
} | |||
@@ -53,15 +57,17 @@ void State::setDragHovered(widget::Widget *w) { | |||
event::DragLeave eDragLeave; | |||
eDragLeave.origin = draggedWidget; | |||
dragHoveredWidget->onDragLeave(eDragLeave); | |||
dragHoveredWidget = NULL; | |||
} | |||
dragHoveredWidget = w; | |||
if (dragHoveredWidget) { | |||
if (w) { | |||
// event::DragEnter | |||
event::Context eDragEnterContext; | |||
event::DragEnter eDragEnter; | |||
eDragEnter.context = &eDragEnterContext; | |||
eDragEnter.origin = draggedWidget; | |||
dragHoveredWidget->onDragEnter(eDragEnter); | |||
w->onDragEnter(eDragEnter); | |||
dragHoveredWidget = eDragEnterContext.consumed; | |||
} | |||
} | |||
@@ -73,14 +79,16 @@ void State::setSelected(widget::Widget *w) { | |||
// event::Deselect | |||
event::Deselect eDeselect; | |||
selectedWidget->onDeselect(eDeselect); | |||
selectedWidget = NULL; | |||
} | |||
selectedWidget = w; | |||
if (selectedWidget) { | |||
if (w) { | |||
// event::Select | |||
event::Context eSelectContext; | |||
event::Select eSelect; | |||
selectedWidget->onSelect(eSelect); | |||
eSelect.context = &eSelectContext; | |||
w->onSelect(eSelect); | |||
selectedWidget = eSelectContext.consumed; | |||
} | |||
} | |||
@@ -20,6 +20,7 @@ void Button::draw(const widget::DrawContext &ctx) { | |||
void Button::onEnter(const event::Enter &e) { | |||
state = BND_HOVER; | |||
e.consume(this); | |||
} | |||
void Button::onLeave(const event::Leave &e) { | |||
@@ -30,6 +31,7 @@ void Button::onDragStart(const event::DragStart &e) { | |||
state = BND_ACTIVE; | |||
if (quantity) | |||
quantity->setMax(); | |||
e.consume(this); | |||
} | |||
void Button::onDragEnd(const event::DragEnd &e) { | |||
@@ -38,6 +38,7 @@ void MenuItem::step() { | |||
} | |||
void MenuItem::onEnter(const event::Enter &e) { | |||
e.consume(this); | |||
Menu *parentMenu = dynamic_cast<Menu*>(parent); | |||
if (!parentMenu) | |||
return; | |||
@@ -53,6 +54,10 @@ void MenuItem::onEnter(const event::Enter &e) { | |||
parentMenu->setChildMenu(childMenu); | |||
} | |||
void MenuItem::onDragStart(const event::DragStart &e) { | |||
e.consume(this); | |||
} | |||
void MenuItem::onDragDrop(const event::DragDrop &e) { | |||
if (e.origin != this) | |||
return; | |||
@@ -24,6 +24,7 @@ void RadioButton::draw(const widget::DrawContext &ctx) { | |||
void RadioButton::onEnter(const event::Enter &e) { | |||
if (state != BND_ACTIVE) | |||
state = BND_HOVER; | |||
e.consume(this); | |||
} | |||
void RadioButton::onLeave(const event::Leave &e) { | |||
@@ -22,6 +22,7 @@ void ScrollBar::draw(const widget::DrawContext &ctx) { | |||
void ScrollBar::onDragStart(const event::DragStart &e) { | |||
state = BND_ACTIVE; | |||
APP->window->cursorLock(); | |||
e.consume(this); | |||
} | |||
void ScrollBar::onDragMove(const event::DragMove &e) { | |||
@@ -26,6 +26,7 @@ void Slider::draw(const widget::DrawContext &ctx) { | |||
void Slider::onDragStart(const event::DragStart &e) { | |||
state = BND_ACTIVE; | |||
APP->window->cursorLock(); | |||
e.consume(this); | |||
} | |||
void Slider::onDragMove(const event::DragMove &e) { | |||
@@ -51,6 +51,10 @@ void TextField::onEnter(const event::Enter &e) { | |||
e.consume(this); | |||
} | |||
void TextField::onSelect(const event::Select &e) { | |||
e.consume(this); | |||
} | |||
void TextField::onSelectText(const event::SelectText &e) { | |||
if (e.codepoint < 128) { | |||
std::string newText(1, (char) e.codepoint); | |||
@@ -120,14 +120,6 @@ void Widget::draw(const DrawContext &ctx) { | |||
child->draw(childCtx); | |||
// Draw red hitboxes | |||
// if (APP->event->hoveredWidget == child) { | |||
// nvgBeginPath(ctx.vg); | |||
// nvgRect(ctx.vg, 0, 0, child->box.size.x, child->box.size.y); | |||
// nvgFillColor(ctx.vg, nvgRGBAf(1, 0, 0, 0.5)); | |||
// nvgFill(ctx.vg); | |||
// } | |||
nvgRestore(ctx.vg); | |||
} | |||
} | |||