Example #1
0
File: main.cpp Project: CCJY/coliru
 virtual ~A() {
     parent.reset();
     cout<<name<<" died"<<endl;
 }
Example #2
0
// ----------------------------------------------------------------------
// 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;
}