| @@ -346,10 +346,10 @@ struct Change : Base { | |||
| }; | |||
| /** Occurs after the zoom level of a Widget is changed. | |||
| /** Occurs when the pixel buffer of this module must be refreshed. | |||
| Recurses. | |||
| */ | |||
| struct Zoom : Base { | |||
| struct Dirty : Base { | |||
| }; | |||
| @@ -436,7 +436,7 @@ struct State { | |||
| bool handleText(math::Vec pos, int codepoint); | |||
| bool handleKey(math::Vec pos, int key, int scancode, int action, int mods); | |||
| bool handleDrop(math::Vec pos, const std::vector<std::string>& paths); | |||
| bool handleZoom(); | |||
| bool handleDirty(); | |||
| }; | |||
| @@ -33,6 +33,7 @@ struct FramebufferWidget : Widget { | |||
| FramebufferWidget(); | |||
| ~FramebufferWidget(); | |||
| void onDirty(const event::Dirty& e) override; | |||
| void step() override; | |||
| void draw(const DrawArgs& args) override; | |||
| virtual void drawFramebuffer(); | |||
| @@ -34,9 +34,18 @@ struct Widget { | |||
| virtual ~Widget(); | |||
| void setPosition(math::Vec pos); | |||
| math::Vec getPosition() { | |||
| return box.pos; | |||
| } | |||
| void setSize(math::Vec size); | |||
| math::Vec getSize() { | |||
| return box.size; | |||
| } | |||
| void show(); | |||
| void hide(); | |||
| bool isVisible() { | |||
| return visible; | |||
| } | |||
| void requestDelete(); | |||
| virtual math::Rect getChildrenBoundingBox(); | |||
| @@ -180,8 +189,8 @@ struct Widget { | |||
| } | |||
| virtual void onAction(const event::Action& e) {} | |||
| virtual void onChange(const event::Change& e) {} | |||
| virtual void onZoom(const event::Zoom& e) { | |||
| recurseEvent(&Widget::onZoom, e); | |||
| virtual void onDirty(const event::Dirty& e) { | |||
| recurseEvent(&Widget::onDirty, e); | |||
| } | |||
| virtual void onReposition(const event::Reposition& e) {} | |||
| virtual void onResize(const event::Resize& e) {} | |||
| @@ -13,6 +13,9 @@ struct ZoomWidget : Widget { | |||
| math::Vec getRelativeOffset(math::Vec v, Widget* relative) override; | |||
| math::Rect getViewport(math::Rect r) override; | |||
| void setZoom(float zoom); | |||
| float getZoom() { | |||
| return zoom; | |||
| } | |||
| void draw(const DrawArgs& args) override; | |||
| void onHover(const event::Hover& e) override { | |||
| @@ -402,13 +402,12 @@ bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) { | |||
| if (!w2->visible) | |||
| continue; | |||
| // Check intersection | |||
| if (mwBox.isIntersecting(w2->box)) { | |||
| if (mwBox.isIntersecting(w2->box)) | |||
| return false; | |||
| } | |||
| } | |||
| // Accept requested position | |||
| mw->box = mwBox; | |||
| mw->setPosition(mwBox.pos); | |||
| RackWidget_updateAdjacent(this); | |||
| return true; | |||
| } | |||
| @@ -459,11 +458,11 @@ void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { | |||
| } | |||
| // We failed to find a box. This shouldn't happen on an infinite rack. | |||
| assert(0); | |||
| assert(false); | |||
| } | |||
| void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) { | |||
| mw->box.pos = pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE); | |||
| mw->setPosition(pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE)); | |||
| // Comparison of center X coordinates | |||
| auto cmp = [&](const widget::Widget * a, const widget::Widget * b) { | |||
| @@ -489,24 +488,26 @@ void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) { | |||
| float xLimit = mw->box.pos.x; | |||
| for (auto it = leftModules.rbegin(); it != leftModules.rend(); it++) { | |||
| widget::Widget* w = *it; | |||
| float x = xLimit - w->box.size.x; | |||
| x = std::round(x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; | |||
| if (w->box.pos.x < x) | |||
| math::Vec newPos = w->box.pos; | |||
| newPos.x = xLimit - w->box.size.x; | |||
| newPos.x = std::round(newPos.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; | |||
| if (w->box.pos.x < newPos.x) | |||
| break; | |||
| w->box.pos.x = x; | |||
| xLimit = x; | |||
| w->setPosition(newPos); | |||
| xLimit = newPos.x; | |||
| } | |||
| // Shove right modules | |||
| xLimit = mw->box.pos.x + mw->box.size.x; | |||
| for (auto it = rightModules.begin(); it != rightModules.end(); it++) { | |||
| widget::Widget* w = *it; | |||
| float x = xLimit; | |||
| x = std::round(x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; | |||
| if (w->box.pos.x > x) | |||
| math::Vec newPos = w->box.pos; | |||
| newPos.x = xLimit; | |||
| newPos.x = std::round(newPos.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; | |||
| if (w->box.pos.x > newPos.x) | |||
| break; | |||
| w->box.pos.x = x; | |||
| xLimit = x + w->box.size.x; | |||
| w->setPosition(newPos); | |||
| xLimit = newPos.x + w->box.size.x; | |||
| } | |||
| RackWidget_updateAdjacent(this); | |||
| @@ -13,14 +13,14 @@ void State::setHovered(widget::Widget* w) { | |||
| return; | |||
| if (hoveredWidget) { | |||
| // Leave | |||
| // Trigger Leave event | |||
| Leave eLeave; | |||
| hoveredWidget->onLeave(eLeave); | |||
| hoveredWidget = NULL; | |||
| } | |||
| if (w) { | |||
| // Enter | |||
| // Trigger Enter event | |||
| Context cEnter; | |||
| cEnter.target = w; | |||
| Enter eEnter; | |||
| @@ -35,7 +35,7 @@ void State::setDragged(widget::Widget* w, int button) { | |||
| return; | |||
| if (draggedWidget) { | |||
| // DragEnd | |||
| // Trigger DragEnd event | |||
| DragEnd eDragEnd; | |||
| eDragEnd.button = dragButton; | |||
| draggedWidget->onDragEnd(eDragEnd); | |||
| @@ -45,7 +45,7 @@ void State::setDragged(widget::Widget* w, int button) { | |||
| dragButton = button; | |||
| if (w) { | |||
| // DragStart | |||
| // Trigger DragStart event | |||
| Context cDragStart; | |||
| cDragStart.target = w; | |||
| DragStart eDragStart; | |||
| @@ -61,7 +61,7 @@ void State::setDragHovered(widget::Widget* w) { | |||
| return; | |||
| if (dragHoveredWidget) { | |||
| // DragLeave | |||
| // Trigger DragLeave event | |||
| DragLeave eDragLeave; | |||
| eDragLeave.button = dragButton; | |||
| eDragLeave.origin = draggedWidget; | |||
| @@ -70,7 +70,7 @@ void State::setDragHovered(widget::Widget* w) { | |||
| } | |||
| if (w) { | |||
| // DragEnter | |||
| // Trigger DragEnter event | |||
| Context cDragEnter; | |||
| cDragEnter.target = w; | |||
| DragEnter eDragEnter; | |||
| @@ -87,14 +87,14 @@ void State::setSelected(widget::Widget* w) { | |||
| return; | |||
| if (selectedWidget) { | |||
| // Deselect | |||
| // Trigger Deselect event | |||
| Deselect eDeselect; | |||
| selectedWidget->onDeselect(eDeselect); | |||
| selectedWidget = NULL; | |||
| } | |||
| if (w) { | |||
| // Select | |||
| // Trigger Select event | |||
| Context cSelect; | |||
| cSelect.target = w; | |||
| Select eSelect; | |||
| @@ -122,7 +122,7 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| widget::Widget* clickedWidget = NULL; | |||
| if (!cursorLocked) { | |||
| // Button | |||
| // Trigger Button event | |||
| Context cButton; | |||
| Button eButton; | |||
| eButton.context = &cButton; | |||
| @@ -142,7 +142,7 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| setDragHovered(NULL); | |||
| if (clickedWidget && draggedWidget) { | |||
| // DragDrop | |||
| // Trigger DragDrop event | |||
| DragDrop eDragDrop; | |||
| eDragDrop.button = dragButton; | |||
| eDragDrop.origin = draggedWidget; | |||
| @@ -163,7 +163,7 @@ bool State::handleButton(math::Vec pos, int button, int action, int mods) { | |||
| if (clickedWidget | |||
| && clickTime - lastClickTime <= doubleClickDuration | |||
| && lastClickedWidget == clickedWidget) { | |||
| // DoubleClick | |||
| // Trigger DoubleClick event | |||
| DoubleClick eDoubleClick; | |||
| clickedWidget->onDoubleClick(eDoubleClick); | |||
| // Reset double click | |||
| @@ -193,14 +193,14 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| } | |||
| if (draggedWidget) { | |||
| // DragMove | |||
| // Trigger DragMove event | |||
| DragMove eDragMove; | |||
| eDragMove.button = dragButton; | |||
| eDragMove.mouseDelta = mouseDelta; | |||
| draggedWidget->onDragMove(eDragMove); | |||
| if (!cursorLocked) { | |||
| // DragHover | |||
| // Trigger DragHover event | |||
| Context cDragHover; | |||
| DragHover eDragHover; | |||
| eDragHover.context = &cDragHover; | |||
| @@ -217,7 +217,7 @@ bool State::handleHover(math::Vec pos, math::Vec mouseDelta) { | |||
| } | |||
| if (!cursorLocked) { | |||
| // Hover | |||
| // Trigger Hover event | |||
| Context cHover; | |||
| Hover eHover; | |||
| eHover.context = &cHover; | |||
| @@ -240,7 +240,7 @@ bool State::handleLeave() { | |||
| } | |||
| bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||
| // HoverScroll | |||
| // Trigger HoverScroll event | |||
| Context cHoverScroll; | |||
| HoverScroll eHoverScroll; | |||
| eHoverScroll.context = &cHoverScroll; | |||
| @@ -252,7 +252,7 @@ bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) { | |||
| } | |||
| bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||
| // PathDrop | |||
| // Trigger PathDrop event | |||
| Context cPathDrop; | |||
| PathDrop ePathDrop(paths); | |||
| ePathDrop.context = &cPathDrop; | |||
| @@ -264,7 +264,7 @@ bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) { | |||
| bool State::handleText(math::Vec pos, int codepoint) { | |||
| if (selectedWidget) { | |||
| // SelectText | |||
| // Trigger SelectText event | |||
| Context cSelectText; | |||
| SelectText eSelectText; | |||
| eSelectText.context = &cSelectText; | |||
| @@ -274,7 +274,7 @@ bool State::handleText(math::Vec pos, int codepoint) { | |||
| return true; | |||
| } | |||
| // HoverText | |||
| // Trigger HoverText event | |||
| Context cHoverText; | |||
| HoverText eHoverText; | |||
| eHoverText.context = &cHoverText; | |||
| @@ -297,7 +297,7 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||
| } | |||
| if (selectedWidget) { | |||
| // SelectKey | |||
| // Trigger SelectKey event | |||
| Context cSelectKey; | |||
| SelectKey eSelectKey; | |||
| eSelectKey.context = &cSelectKey; | |||
| @@ -313,7 +313,7 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||
| return true; | |||
| } | |||
| // HoverKey | |||
| // Trigger HoverKey event | |||
| Context cHoverKey; | |||
| HoverKey eHoverKey; | |||
| eHoverKey.context = &cHoverKey; | |||
| @@ -329,12 +329,12 @@ bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods | |||
| return !!cHoverKey.target; | |||
| } | |||
| bool State::handleZoom() { | |||
| // Zoom | |||
| Context cZoom; | |||
| Zoom eZoom; | |||
| eZoom.context = &cZoom; | |||
| rootWidget->onZoom(eZoom); | |||
| bool State::handleDirty() { | |||
| // Trigger Dirty event | |||
| Context cDirty; | |||
| Dirty eDirty; | |||
| eDirty.context = &cDirty; | |||
| rootWidget->onDirty(eDirty); | |||
| return true; | |||
| } | |||
| @@ -15,6 +15,11 @@ FramebufferWidget::~FramebufferWidget() { | |||
| nvgluDeleteFramebuffer(fb); | |||
| } | |||
| void FramebufferWidget::onDirty(const event::Dirty& e) { | |||
| dirty = true; | |||
| Widget::onDirty(e); | |||
| } | |||
| void FramebufferWidget::step() { | |||
| Widget::step(); | |||
| @@ -15,6 +15,8 @@ Widget::~Widget() { | |||
| } | |||
| void Widget::setPosition(math::Vec pos) { | |||
| if (pos.isEqual(box.pos)) | |||
| return; | |||
| box.pos = pos; | |||
| // event::Reposition | |||
| event::Reposition eReposition; | |||
| @@ -22,6 +24,8 @@ void Widget::setPosition(math::Vec pos) { | |||
| } | |||
| void Widget::setSize(math::Vec size) { | |||
| if (size.isEqual(box.size)) | |||
| return; | |||
| box.size = size; | |||
| // event::Resize | |||
| event::Resize eResize; | |||
| @@ -23,10 +23,11 @@ void ZoomWidget::setZoom(float zoom) { | |||
| return; | |||
| this->zoom = zoom; | |||
| event::Context cZoom; | |||
| event::Zoom eZoom; | |||
| eZoom.context = &cZoom; | |||
| Widget::onZoom(eZoom); | |||
| // Trigger Dirty event | |||
| event::Context cDirty; | |||
| event::Dirty eDirty; | |||
| eDirty.context = &cDirty; | |||
| Widget::onDirty(eDirty); | |||
| } | |||
| void ZoomWidget::draw(const DrawArgs& args) { | |||
| @@ -384,7 +384,7 @@ void Window::run() { | |||
| glfwGetWindowContentScale(win, &newPixelRatio, NULL); | |||
| newPixelRatio = std::floor(newPixelRatio + 0.5); | |||
| if (newPixelRatio != pixelRatio) { | |||
| APP->event->handleZoom(); | |||
| APP->event->handleDirty(); | |||
| pixelRatio = newPixelRatio; | |||
| } | |||