/** * @file llpopupview.cpp * @brief Holds transient popups * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llpopupview.h" static LLPanelInjector r("popup_holder"); bool view_visible_and_enabled(LLView* viewp) { return viewp->getVisible() && viewp->getEnabled(); } bool view_visible(LLView* viewp) { return viewp->getVisible(); } LLPopupView::LLPopupView(const LLPopupView::Params& p) : LLPanel(p) { // register ourself as handler of UI popups LLUI::getInstance()->setPopupFuncs(boost::bind(&LLPopupView::addPopup, this, _1), boost::bind(&LLPopupView::removePopup, this, _1), boost::bind(&LLPopupView::clearPopups, this)); } LLPopupView::~LLPopupView() { // set empty callback function so we can't handle popups anymore LLUI::getInstance()->setPopupFuncs(LLUI::add_popup_t(), LLUI::remove_popup_t(), LLUI::clear_popups_t()); } void LLPopupView::draw() { S32 screen_x, screen_y; // remove dead popups for (popup_list_t::iterator popup_it = mPopups.begin(); popup_it != mPopups.end();) { if (!popup_it->get()) { mPopups.erase(popup_it++); } else { popup_it++; } } // draw in reverse order (most recent is on top) for (popup_list_t::reverse_iterator popup_it = mPopups.rbegin(); popup_it != mPopups.rend();) { LLView* popup = popup_it->get(); if (popup->getVisible()) { popup->localPointToScreen(0, 0, &screen_x, &screen_y); LLUI::pushMatrix(); { LLUI::translate( (F32) screen_x, (F32) screen_y); popup->draw(); } LLUI::popMatrix(); } ++popup_it; } LLPanel::draw(); } bool LLPopupView::handleMouseEvent(boost::function func, boost::function predicate, S32 x, S32 y, bool close_popups) { bool handled = false; // make a copy of list of popups, in case list is modified during mouse event handling popup_list_t popups(mPopups); for (popup_list_t::iterator popup_it = popups.begin(), popup_end = popups.end(); popup_it != popup_end; ++popup_it) { LLView* popup = popup_it->get(); if (!popup || !predicate(popup)) { continue; } S32 popup_x, popup_y; if (localPointToOtherView(x, y, &popup_x, &popup_y, popup) && popup->pointInView(popup_x, popup_y)) { if (func(popup, popup_x, popup_y)) { handled = true; break; } } if (close_popups) { mPopups.remove(*popup_it); popup->onTopLost(); } } return handled; } bool LLPopupView::handleMouseDown(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true); if (!handled) { handled = LLPanel::handleMouseDown(x, y, mask); } return handled; } bool LLPopupView::handleMouseUp(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false); if (!handled) { handled = LLPanel::handleMouseUp(x, y, mask); } return handled; } bool LLPopupView::handleMiddleMouseDown(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleMiddleMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true); if (!handled) { handled = LLPanel::handleMiddleMouseDown(x, y, mask); } return handled; } bool LLPopupView::handleMiddleMouseUp(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleMiddleMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false); if (!handled) { handled = LLPanel::handleMiddleMouseUp(x, y, mask); } return handled; } bool LLPopupView::handleRightMouseDown(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleRightMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true); if (!handled) { handled = LLPanel::handleRightMouseDown(x, y, mask); } return handled; } bool LLPopupView::handleRightMouseUp(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleRightMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false); if (!handled) { handled = LLPanel::handleRightMouseUp(x, y, mask); } return handled; } bool LLPopupView::handleDoubleClick(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleDoubleClick, _1, _2, _3, mask), view_visible_and_enabled, x, y, false); if (!handled) { handled = LLPanel::handleDoubleClick(x, y, mask); } return handled; } bool LLPopupView::handleHover(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleHover, _1, _2, _3, mask), view_visible_and_enabled, x, y, false); if (!handled) { handled = LLPanel::handleHover(x, y, mask); } return handled; } bool LLPopupView::handleScrollWheel(S32 x, S32 y, S32 clicks) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleScrollWheel, _1, _2, _3, clicks), view_visible_and_enabled, x, y, false); if (!handled) { handled = LLPanel::handleScrollWheel(x, y, clicks); } return handled; } bool LLPopupView::handleToolTip(S32 x, S32 y, MASK mask) { bool handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleToolTip, _1, _2, _3, mask), view_visible, x, y, false); if (!handled) { handled = LLPanel::handleToolTip(x, y, mask); } return handled; } void LLPopupView::addPopup(LLView* popup) { if (popup) { mPopups.remove(popup->getHandle()); mPopups.push_front(popup->getHandle()); } } void LLPopupView::removePopup(LLView* popup) { if (popup) { mPopups.remove(popup->getHandle()); popup->onTopLost(); } } void LLPopupView::clearPopups() { while (!mPopups.empty()) { popup_list_t::iterator popup_it = mPopups.begin(); LLView* popup = popup_it->get(); // Remove before notifying in case it will cause removePopup mPopups.erase(popup_it); if (popup) { popup->onTopLost(); } } }