virtual ~A() { parent.reset(); cout<<name<<" died"<<endl; }
// ---------------------------------------------------------------------- // static method - called once for all widgets by the // WidgetEventResponder, which self- // registers to all events upon creation of the first widget. // bool ofxWidget::mouseEvent(ofMouseEventArgs& args_) { // If we register a mouse down event, we do a hit test over // all visible widgets, and re-order if necessary. // Then, and in all other cases, we do a hit-test on the // frontmost widget and, if positive, forward the event to this // widget. updateVisibleWidgetsList(); if (sVisibleWidgets.empty()) return false; // ---------| invariant: there are some widgets flying around. bool eventAttended = false; float mx = args_.x; float my = args_.y; // if we have a mouse down on a widget, we need to check which // widget was hit and potentially re-order widgets. // find the first widget that is under the mouse, that is also visible // if it is not yet up front, bring it to the front. // hit-test only visible widgets - this makes sure to only evaluate // the widgets which are visible, and whose parents are visible, too. auto itUnderMouse = std::find_if(sVisibleWidgets.begin(), sVisibleWidgets.end(), [&mx, &my](std::weak_ptr<ofxWidget>& w) ->bool { auto p = w.lock(); if (p && p->mVisible && p->mRect.inside(mx, my)) { return true; } else { return false; } }); // if we have a click, we want to make sure the widget gets to be the topmost widget. if (args_.type == ofMouseEventArgs::Pressed) { // --- now iterate over sAllWidgets instead of just the visible widgets. // we need to do this, because otherwise the reorder check won't be safe // as the number of children in sVisibleWidgets is potentially incorrect, // as the number of children there refers to all children of a widget, // and not just the visible children of the widget. auto itPressedWidget = (itUnderMouse == sVisibleWidgets.end() ? sAllWidgets.end() : findIt(*itUnderMouse, sAllWidgets.begin(), sAllWidgets.end())); if (itPressedWidget != sAllWidgets.end()) { if (!isSame(*itPressedWidget, sFocusedWidget)) { // change in focus detected. // first, let the first element know that it is losing focus if (auto previousElementInFocus = sFocusedWidget.lock()) if (previousElementInFocus->onFocusLeave) previousElementInFocus->onFocusLeave(); sFocusedWidget = *itPressedWidget; // now that the new wiget is at the front, send an activate callback. if (auto nextFocusedWidget = sFocusedWidget.lock()) if (nextFocusedWidget->onFocusEnter) nextFocusedWidget->onFocusEnter(); } bringToFront(itPressedWidget); // reorder widgets } else { // hit test was not successful, no wigets found. if (auto previousElementInFocus = sFocusedWidget.lock()) if (previousElementInFocus->onFocusLeave) previousElementInFocus->onFocusLeave(); sFocusedWidget.reset(); // no widget gets the focus, then. } } // end if (args_.type == ofMouseEventArgs::Pressed) // now, we will attempt to send the mouse event to the widget that // is in focus. if (itUnderMouse != sVisibleWidgets.end()) { // a widget is under the mouse. // is it the same as the current widget under the mouse? if (!isSame(*itUnderMouse, sWidgetUnderMouse)) { if (auto nU = itUnderMouse->lock()) { // there is a new widget under the mouse if (auto w = sWidgetUnderMouse.lock()) { // there was an old widget under the mouse if (w->onMouseLeave) w->onMouseLeave(); w->mHover = false; } if (nU->onMouseEnter) nU->onMouseEnter(); nU->mHover = true; sWidgetUnderMouse = *itUnderMouse; } } } else { if (auto w = sWidgetUnderMouse.lock()) { // there was a widget under mouse, // but now there is none. if (w->onMouseLeave) w->onMouseLeave(); w->mHover = false; sWidgetUnderMouse.reset(); } } if (auto w = sFocusedWidget.lock()) { if (w->onMouse) { w->onMouse(args_); eventAttended = true; } } // store last mouse position last thing, so that // we are able to calculate a difference. sLastMousePos.set(mx, my); return eventAttended; }