summaryrefslogtreecommitdiff
path: root/indra/llui/llview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/llview.cpp')
-rwxr-xr-x[-rw-r--r--]indra/llui/llview.cpp1460
1 files changed, 649 insertions, 811 deletions
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 781c111474..a8beb9cfc9 100644..100755
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -3,31 +3,25 @@
* @author James Cook
* @brief Container for other views, anything that draws.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 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.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 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.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * 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
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,8 +30,10 @@
#define LLVIEW_CPP
#include "llview.h"
-#include <cassert>
+#include <sstream>
#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
#include "llrender.h"
#include "llevent.h"
@@ -50,13 +46,18 @@
#include "v3color.h"
#include "lluictrlfactory.h"
#include "lltooltip.h"
-
+#include "llsdutil.h"
+#include "llsdserialize.h"
+#include "llviewereventrecorder.h"
+#include "llkeyboard.h"
// for ui edit hack
#include "llbutton.h"
#include "lllineeditor.h"
#include "lltexteditor.h"
#include "lltextbox.h"
+static const S32 LINE_HEIGHT = 15;
+
S32 LLView::sDepth = 0;
bool LLView::sDebugRects = false;
bool LLView::sDebugRectsShowNames = true;
@@ -72,6 +73,8 @@ S32 LLView::sLastLeftXML = S32_MIN;
S32 LLView::sLastBottomXML = S32_MIN;
std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack;
+LLView::DrilldownFunc LLView::sDrilldown =
+ boost::bind(&LLView::pointInView, _1, _2, _3, HIT_TEST_USE_BOUNDING_RECT);
//#if LL_DEBUG
BOOL LLView::sIsDrawing = FALSE;
@@ -83,6 +86,16 @@ template class LLView* LLView::getChild<class LLView>(
static LLDefaultChildRegistry::Register<LLView> r("view");
+namespace LLInitParam
+{
+ void TypeValues<LLView::EOrientation>::declareValues()
+ {
+ declare("horizontal", LLView::HORIZONTAL);
+ declare("vertical", LLView::VERTICAL);
+ }
+}
+
+
LLView::Follows::Follows()
: string(""),
flags("flags", FOLLOWS_LEFT | FOLLOWS_TOP)
@@ -107,11 +120,8 @@ LLView::Params::Params()
top_delta("top_delta", S32_MAX),
left_pad("left_pad"),
left_delta("left_delta", S32_MAX),
- center_horiz("center_horiz", false),
- center_vert("center_vert", false),
from_xui("from_xui", false),
- user_resize("user_resize"),
- auto_resize("auto_resize"),
+ focus_root("focus_root", false),
needs_translate("translate"),
xmlns("xmlns"),
xmlns_xsi("xmlns:xsi"),
@@ -123,16 +133,17 @@ LLView::Params::Params()
}
LLView::LLView(const LLView::Params& p)
-: mName(p.name),
+: LLTrace::MemTrackable<LLView>("LLView"),
+ mVisible(p.visible),
+ mInDraw(false),
+ mName(p.name),
mParentView(NULL),
mReshapeFlags(FOLLOWS_NONE),
mFromXUI(p.from_xui),
- mIsFocusRoot(FALSE),
+ mIsFocusRoot(p.focus_root),
mLastVisible(FALSE),
- mNextInsertionOrdinal(0),
mHoverCursor(getCursorFromString(p.hover_cursor)),
mEnabled(p.enabled),
- mVisible(p.visible),
mMouseOpaque(p.mouse_opaque),
mSoundFlags(p.sound_flags),
mUseBoundingRect(p.use_bounding_rect),
@@ -149,10 +160,10 @@ LLView::LLView(const LLView::Params& p)
LLView::~LLView()
{
dirtyRect();
- //llinfos << "Deleting view " << mName << ":" << (void*) this << llendl;
+ //LL_INFOS() << "Deleting view " << mName << ":" << (void*) this << LL_ENDL;
if (LLView::sIsDrawing)
{
- lldebugs << "Deleting view " << mName << " during UI draw() phase" << llendl;
+ LL_DEBUGS() << "Deleting view " << mName << " during UI draw() phase" << LL_ENDL;
}
// llassert(LLView::sIsDrawing == FALSE);
@@ -160,7 +171,7 @@ LLView::~LLView()
if( hasMouseCapture() )
{
- //llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl;
+ //LL_WARNS() << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << LL_ENDL;
gFocusMgr.removeMouseCaptureWithoutCallback( this );
}
@@ -173,8 +184,6 @@ LLView::~LLView()
if (mDefaultWidgets)
{
- std::for_each(mDefaultWidgets->begin(), mDefaultWidgets->end(),
- DeletePairedPointer());
delete mDefaultWidgets;
mDefaultWidgets = NULL;
}
@@ -224,15 +233,17 @@ void LLView::setUseBoundingRect( BOOL use_bounding_rect )
}
}
-BOOL LLView::getUseBoundingRect()
+BOOL LLView::getUseBoundingRect() const
{
return mUseBoundingRect;
}
// virtual
-std::string LLView::getName() const
+const std::string& LLView::getName() const
{
- return mName.empty() ? std::string("(no name)") : mName;
+ static std::string no_name("(no name)");
+
+ return mName.empty() ? no_name : mName;
}
void LLView::sendChildToFront(LLView* child)
@@ -265,22 +276,6 @@ void LLView::sendChildToBack(LLView* child)
}
}
-void LLView::moveChildToFrontOfTabGroup(LLUICtrl* child)
-{
- if(mCtrlOrder.find(child) != mCtrlOrder.end())
- {
- mCtrlOrder[child].second = -1 * mNextInsertionOrdinal++;
- }
-}
-
-void LLView::moveChildToBackOfTabGroup(LLUICtrl* child)
-{
- if(mCtrlOrder.find(child) != mCtrlOrder.end())
- {
- mCtrlOrder[child].second = mNextInsertionOrdinal++;
- }
-}
-
// virtual
bool LLView::addChild(LLView* child, S32 tab_group)
{
@@ -288,9 +283,10 @@ bool LLView::addChild(LLView* child, S32 tab_group)
{
return false;
}
- if (mParentView == child)
+
+ if (this == child)
{
- llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
+ LL_ERRS() << "Adding view " << child->getName() << " as child of itself" << LL_ENDL;
}
// remove from current parent
@@ -302,14 +298,10 @@ bool LLView::addChild(LLView* child, S32 tab_group)
// add to front of child list, as normal
mChildList.push_front(child);
- // add to ctrl list if is LLUICtrl
- if (child->isCtrl())
+ // add to tab order list
+ if (tab_group != 0)
{
- LLUICtrl* ctrl = static_cast<LLUICtrl*>(child);
- mCtrlOrder.insert(tab_order_pair_t(ctrl,
- tab_order_t(tab_group, mNextInsertionOrdinal)));
-
- mNextInsertionOrdinal++;
+ mTabOrder.insert(tab_order_pair_t(child, tab_group));
}
child->mParentView = this;
@@ -336,95 +328,87 @@ void LLView::removeChild(LLView* child)
//llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs
if (child->mParentView == this)
{
+ // if we are removing an item we are currently iterating over, that would be bad
+ llassert(child->mInDraw == false);
mChildList.remove( child );
child->mParentView = NULL;
- if (child->isCtrl())
+ child_tab_order_t::iterator found = mTabOrder.find(child);
+ if(found != mTabOrder.end())
{
- child_tab_order_t::iterator found = mCtrlOrder.find(static_cast<LLUICtrl*>(child));
- if(found != mCtrlOrder.end())
- {
- mCtrlOrder.erase(found);
- }
+ mTabOrder.erase(found);
}
}
else
{
- llerrs << "LLView::removeChild called with non-child" << llendl;
+ LL_WARNS() << "\"" << child->getName() << "\" is not a child of " << getName() << LL_ENDL;
}
updateBoundingRect();
}
-LLView::ctrl_list_t LLView::getCtrlList() const
+BOOL LLView::isInVisibleChain() const
{
- ctrl_list_t controls;
- for(child_list_const_iter_t iter = mChildList.begin();
- iter != mChildList.end();
- iter++)
+ BOOL visible = TRUE;
+
+ const LLView* viewp = this;
+ while(viewp)
{
- if((*iter)->isCtrl())
+ if (!viewp->getVisible())
{
- controls.push_back(static_cast<LLUICtrl*>(*iter));
+ visible = FALSE;
+ break;
}
+ viewp = viewp->getParent();
}
- return controls;
+
+ return visible;
}
-LLView::ctrl_list_t LLView::getCtrlListSorted() const
+BOOL LLView::isInEnabledChain() const
{
- ctrl_list_t controls = getCtrlList();
- std::sort(controls.begin(), controls.end(), LLCompareByTabOrder(mCtrlOrder));
- return controls;
-}
-
+ BOOL enabled = TRUE;
-// This method compares two LLViews by the tab order specified in the comparator object. The
-// code for this is a little convoluted because each argument can have four states:
-// 1) not a control, 2) a control but not in the tab order, 3) a control in the tab order, 4) null
-bool LLCompareByTabOrder::operator() (const LLView* const a, const LLView* const b) const
-{
- S32 a_score = 0, b_score = 0;
- if(a) a_score--;
- if(b) b_score--;
- if(a && a->isCtrl()) a_score--;
- if(b && b->isCtrl()) b_score--;
- if(a_score == -2 && b_score == -2)
+ const LLView* viewp = this;
+ while(viewp)
{
- const LLUICtrl * const a_ctrl = static_cast<const LLUICtrl*>(a);
- const LLUICtrl * const b_ctrl = static_cast<const LLUICtrl*>(b);
- LLView::child_tab_order_const_iter_t a_found = mTabOrder.find(a_ctrl), b_found = mTabOrder.find(b_ctrl);
- if(a_found != mTabOrder.end()) a_score--;
- if(b_found != mTabOrder.end()) b_score--;
- if(a_score == -3 && b_score == -3)
+ if (!viewp->getEnabled())
{
- // whew! Once we're in here, they're both in the tab order, and we can compare based on that
- return compareTabOrders(a_found->second, b_found->second);
+ enabled = FALSE;
+ break;
}
+ viewp = viewp->getParent();
}
- return (a_score == b_score) ? a < b : a_score < b_score;
+
+ return enabled;
}
-bool LLView::trueToRoot(const boost::function<bool (const LLView*)>& predicate) const
+static void buildPathname(std::ostream& out, const LLView* view)
{
- const LLView* cur_view = this;
- while(cur_view)
+ if (! (view && view->getParent()))
{
- if(!predicate(cur_view))
- {
- return false;
- }
- cur_view = cur_view->getParent();
+ return; // Don't include root in the path.
}
- return true;
+
+ buildPathname(out, view->getParent());
+
+ // Build pathname into ostream on the way back from recursion.
+ out << '/' << view->getName();
}
-BOOL LLView::isInVisibleChain() const
+std::string LLView::getPathname() const
{
- return trueToRoot(&LLView::getVisible);
+ std::ostringstream out;
+ buildPathname(out, this);
+ return out.str();
}
-BOOL LLView::isInEnabledChain() const
+//static
+std::string LLView::getPathname(const LLView* view)
{
- return trueToRoot(&LLView::getEnabled);
+ if (! view)
+ {
+ return "NULL";
+ }
+ return view->getPathname();
}
// virtual
@@ -434,17 +418,6 @@ BOOL LLView::canFocusChildren() const
}
//virtual
-void LLView::setTentative(BOOL b)
-{
-}
-
-//virtual
-BOOL LLView::getTentative() const
-{
- return FALSE;
-}
-
-//virtual
void LLView::setEnabled(BOOL enabled)
{
mEnabled = enabled;
@@ -495,9 +468,9 @@ BOOL LLView::focusPrevRoot()
// static
BOOL LLView::focusNext(LLView::child_list_t & result)
{
- LLView::child_list_iter_t focused = result.end();
- for(LLView::child_list_iter_t iter = result.begin();
- iter != result.end();
+ LLView::child_list_reverse_iter_t focused = result.rend();
+ for(LLView::child_list_reverse_iter_t iter = result.rbegin();
+ iter != result.rend();
++iter)
{
if(gFocusMgr.childHasKeyboardFocus(*iter))
@@ -506,14 +479,14 @@ BOOL LLView::focusNext(LLView::child_list_t & result)
break;
}
}
- LLView::child_list_iter_t next = focused;
- next = (next == result.end()) ? result.begin() : ++next;
+ LLView::child_list_reverse_iter_t next = focused;
+ next = (next == result.rend()) ? result.rbegin() : ++next;
while(next != focused)
{
// wrap around to beginning if necessary
- if(next == result.end())
+ if(next == result.rend())
{
- next = result.begin();
+ next = result.rbegin();
}
if((*next)->isCtrl())
{
@@ -531,9 +504,9 @@ BOOL LLView::focusNext(LLView::child_list_t & result)
// static
BOOL LLView::focusPrev(LLView::child_list_t & result)
{
- LLView::child_list_reverse_iter_t focused = result.rend();
- for(LLView::child_list_reverse_iter_t iter = result.rbegin();
- iter != result.rend();
+ LLView::child_list_iter_t focused = result.end();
+ for(LLView::child_list_iter_t iter = result.begin();
+ iter != result.end();
++iter)
{
if(gFocusMgr.childHasKeyboardFocus(*iter))
@@ -542,14 +515,14 @@ BOOL LLView::focusPrev(LLView::child_list_t & result)
break;
}
}
- LLView::child_list_reverse_iter_t next = focused;
- next = (next == result.rend()) ? result.rbegin() : ++next;
+ LLView::child_list_iter_t next = focused;
+ next = (next == result.end()) ? result.begin() : ++next;
while(next != focused)
{
// wrap around to beginning if necessary
- if(next == result.rend())
+ if(next == result.end())
{
- next = result.rbegin();
+ next = result.begin();
}
if((*next)->isCtrl())
{
@@ -573,7 +546,7 @@ BOOL LLView::focusPrev(LLView::child_list_t & result)
void LLView::deleteAllChildren()
{
// clear out the control ordering
- mCtrlOrder.clear();
+ mTabOrder.clear();
while (!mChildList.empty())
{
@@ -584,9 +557,8 @@ void LLView::deleteAllChildren()
void LLView::setAllChildrenEnabled(BOOL b)
{
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ BOOST_FOREACH(LLView* viewp, mChildList)
{
- LLView* viewp = *child_it;
viewp->setEnabled(b);
}
}
@@ -603,22 +575,42 @@ void LLView::setVisible(BOOL visible)
{
// tell all children of this view that the visibility may have changed
dirtyRect();
- handleVisibilityChange( visible );
+ onVisibilityChange( visible );
}
updateBoundingRect();
}
}
// virtual
-void LLView::handleVisibilityChange ( BOOL new_visibility )
+void LLView::onVisibilityChange ( BOOL new_visibility )
{
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ BOOL old_visibility;
+ BOOL log_visibility_change = LLViewerEventRecorder::instance().getLoggingStatus();
+ BOOST_FOREACH(LLView* viewp, mChildList)
{
- LLView* viewp = *child_it;
// only views that are themselves visible will have their overall visibility affected by their ancestors
- if (viewp->getVisible())
+ old_visibility=viewp->getVisible();
+
+ if(log_visibility_change)
+ {
+ if (old_visibility!=new_visibility)
{
- viewp->handleVisibilityChange ( new_visibility );
+ LLViewerEventRecorder::instance().logVisibilityChange( viewp->getPathname(), viewp->getName(), new_visibility,"widget");
+ }
+ }
+
+ if (old_visibility)
+ {
+ viewp->onVisibilityChange ( new_visibility );
+ }
+
+ if(log_visibility_change)
+ {
+ // Consider changing returns to confirm success and know which widget grabbed it
+ // For now assume success and log at highest xui possible
+ // NOTE we log actual state - which may differ if it somehow failed to set visibility
+ LL_DEBUGS() << "LLView::handleVisibilityChange - now: " << getVisible() << " xui: " << viewp->getPathname() << " name: " << viewp->getName() << LL_ENDL;
+
}
}
}
@@ -648,64 +640,196 @@ BOOL LLView::handleHover(S32 x, S32 y, MASK mask)
void LLView::onMouseEnter(S32 x, S32 y, MASK mask)
{
- //llinfos << "Mouse entered " << getName() << llendl;
+ //LL_INFOS() << "Mouse entered " << getName() << LL_ENDL;
}
void LLView::onMouseLeave(S32 x, S32 y, MASK mask)
{
- //llinfos << "Mouse left " << getName() << llendl;
+ //LL_INFOS() << "Mouse left " << getName() << LL_ENDL;
+}
+
+bool LLView::visibleAndContains(S32 local_x, S32 local_y)
+{
+ return sDrilldown(this, local_x, local_y)
+ && getVisible();
}
+bool LLView::visibleEnabledAndContains(S32 local_x, S32 local_y)
+{
+ return visibleAndContains(local_x, local_y)
+ && getEnabled();
+}
+
+// This is NOT event recording related
+void LLView::logMouseEvent()
+{
+ if (sDebugMouseHandling)
+ {
+ sMouseHandlerMessage = std::string("/") + mName + sMouseHandlerMessage;
+ }
+}
+
+template <typename METHOD, typename CHARTYPE>
+LLView* LLView::childrenHandleCharEvent(const std::string& desc, const METHOD& method,
+ CHARTYPE c, MASK mask)
+{
+ if ( getVisible() && getEnabled() )
+ {
+ BOOST_FOREACH(LLView* viewp, mChildList)
+ {
+ if ((viewp->*method)(c, mask, TRUE))
+ {
+ if (LLView::sDebugKeys)
+ {
+ LL_INFOS() << desc << " handled by " << viewp->getName() << LL_ENDL;
+ }
+ return viewp;
+ }
+ }
+ }
+ return NULL;
+}
+
+// XDATA might be MASK, or S32 clicks
+template <typename METHOD, typename XDATA>
+LLView* LLView::childrenHandleMouseEvent(const METHOD& method, S32 x, S32 y, XDATA extra, bool allow_mouse_block)
+{
+ BOOST_FOREACH(LLView* viewp, mChildList)
+ {
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+
+ if (!viewp->visibleEnabledAndContains(local_x, local_y))
+ {
+ continue;
+ }
+
+ if ((viewp->*method)( local_x, local_y, extra )
+ || (allow_mouse_block && viewp->blockMouseEvent( local_x, local_y )))
+ {
+ LL_DEBUGS() << "LLView::childrenHandleMouseEvent calling updatemouseeventinfo - local_x|global x "<< local_x << " " << x << "local/global y " << local_y << " " << y << LL_ENDL;
+ LL_DEBUGS() << "LLView::childrenHandleMouseEvent getPathname for viewp result: " << viewp->getPathname() << "for this view: " << getPathname() << LL_ENDL;
+
+ LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname());
+
+ // This is NOT event recording related
+ viewp->logMouseEvent();
+
+ return viewp;
+ }
+ }
+ return NULL;
+}
LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = NULL;
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ BOOST_FOREACH(LLView* viewp, mChildList)
{
- LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if(!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible())
+ // Differs from childrenHandleMouseEvent() in that we want to offer
+ // tooltips even for disabled widgets.
+ if(!viewp->visibleAndContains(local_x, local_y))
{
continue;
}
- if (viewp->handleToolTip(local_x, local_y, mask) )
+ if (viewp->handleToolTip(local_x, local_y, mask)
+ || viewp->blockMouseEvent(local_x, local_y))
{
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
+ // This is NOT event recording related
+ viewp->logMouseEvent();
+ return viewp;
+ }
+ }
+ return NULL;
+}
- handled_view = viewp;
- break;
+LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ // default to not accepting drag and drop, will be overridden by handler
+ *accept = ACCEPT_NO;
+
+ BOOST_FOREACH(LLView* viewp, mChildList)
+ {
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if( !viewp->visibleEnabledAndContains(local_x, local_y))
+ {
+ continue;
}
- if (viewp->blockMouseEvent(local_x, local_y))
+ // Differs from childrenHandleMouseEvent() simply in that this virtual
+ // method call diverges pretty radically from the usual (x, y, int).
+ if (viewp->handleDragAndDrop(local_x, local_y, mask, drop,
+ cargo_type,
+ cargo_data,
+ accept,
+ tooltip_msg)
+ || viewp->blockMouseEvent(local_x, local_y))
{
- handled_view = viewp;
- break;
+ return viewp;
}
}
- return handled_view;
+ return NULL;
}
+LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
+{
+ BOOST_FOREACH(LLView* viewp, mChildList)
+ {
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if(!viewp->visibleEnabledAndContains(local_x, local_y))
+ {
+ continue;
+ }
+
+ // This call differentiates this method from childrenHandleMouseEvent().
+ LLUI::sWindow->setCursor(viewp->getHoverCursor());
-LLView* LLView::childFromPoint(S32 x, S32 y)
+ if (viewp->handleHover(local_x, local_y, mask)
+ || viewp->blockMouseEvent(local_x, local_y))
+ {
+ // This is NOT event recording related
+ viewp->logMouseEvent();
+ return viewp;
+ }
+ }
+ return NULL;
+}
+
+LLView* LLView::childFromPoint(S32 x, S32 y, bool recur)
{
- if (!getVisible() )
+ if (!getVisible())
return false;
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+
+ BOOST_FOREACH(LLView* viewp, mChildList)
{
- LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible() )
+ if (!viewp->visibleAndContains(local_x, local_y))
{
continue;
}
+ // Here we've found the first (frontmost) visible child at this level
+ // containing the specified point. Is the caller asking us to drill
+ // down and return the innermost leaf child at this point, or just the
+ // top-level child?
+ if (recur)
+ {
+ LLView* leaf(viewp->childFromPoint(local_x, local_y, recur));
+ // Maybe viewp is already a leaf LLView, or maybe it has children
+ // but this particular (x, y) point falls between them. If the
+ // recursive call returns non-NULL, great, use that; else just use
+ // viewp.
+ return leaf? leaf : viewp;
+ }
return viewp;
}
@@ -718,18 +842,18 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
// parents provide tooltips first, which are optionally
// overridden by children, in case child is mouse_opaque
- if (!mToolTipMsg.empty())
+ std::string tooltip = getToolTip();
+ if (!tooltip.empty())
{
// allow "scrubbing" over ui by showing next tooltip immediately
// if previous one was still visible
F32 timeout = LLToolTipMgr::instance().toolTipVisible()
- ? 0.f
- : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" );
+ ? LLUI::sSettingGroups["config"]->getF32( "ToolTipFastDelay" )
+ : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" );
LLToolTipMgr::instance().show(LLToolTip::Params()
- .message(mToolTipMsg)
- .sticky_rect(calcScreenRect())
- .delay_time(timeout));
-
+ .message(tooltip)
+ .sticky_rect(calcScreenRect())
+ .delay_time(timeout));
handled = TRUE;
}
@@ -756,10 +880,12 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
if (!handled)
{
+ // For event logging we don't care which widget handles it
+ // So we capture the key at the end of this function once we know if it was handled
handled = handleKeyHere( key, mask );
- if (handled && LLView::sDebugKeys)
+ if (handled)
{
- llinfos << "Key handled by " << getName() << llendl;
+ LL_DEBUGS() << "Key handled by " << getName() << LL_ENDL;
}
}
}
@@ -796,7 +922,7 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
handled = handleUnicodeCharHere(uni_char);
if (handled && LLView::sDebugKeys)
{
- llinfos << "Unicode key handled by " << getName() << llendl;
+ LL_INFOS() << "Unicode key handled by " << getName() << LL_ENDL;
}
}
}
@@ -807,6 +933,11 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
handled = mParentView->handleUnicodeChar(uni_char, FALSE);
}
+ if (handled)
+ {
+ LLViewerEventRecorder::instance().logKeyUnicodeEvent(uni_char);
+ }
+
return handled;
}
@@ -825,45 +956,6 @@ BOOL LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
return childrenHandleDragAndDrop( x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL;
}
-LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
- BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
-{
- LLView* handled_view = NULL;
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if( !viewp->pointInView(local_x, local_y) ||
- !viewp->getVisible() ||
- !viewp->getEnabled())
- {
- continue;
- }
- if (viewp->handleDragAndDrop(local_x, local_y, mask, drop,
- cargo_type,
- cargo_data,
- accept,
- tooltip_msg))
- {
- handled_view = viewp;
- break;
- }
-
- if (viewp->blockMouseEvent(x, y))
- {
- *accept = ACCEPT_NO;
- handled_view = viewp;
- break;
- }
- }
- return handled_view;
-}
-
void LLView::onMouseCaptureLost()
{
}
@@ -875,12 +967,16 @@ BOOL LLView::hasMouseCapture()
BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)
{
- return childrenHandleMouseUp( x, y, mask ) != NULL;
+ LLView* r = childrenHandleMouseUp( x, y, mask );
+
+ return (r!=NULL);
}
BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
{
- return childrenHandleMouseDown( x, y, mask ) != NULL;
+ LLView* r= childrenHandleMouseDown(x, y, mask );
+
+ return (r!=NULL);
}
BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask)
@@ -913,391 +1009,57 @@ BOOL LLView::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
return childrenHandleMiddleMouseUp( x, y, mask ) != NULL;
}
-
LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
{
- LLView* handled_view = NULL;
- if (getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled())
- {
- continue;
- }
-
- if (viewp->handleScrollWheel( local_x, local_y, clicks ))
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
-
- handled_view = viewp;
- break;
- }
- }
- }
- return handled_view;
-}
-
-LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
-{
- LLView* handled_view = NULL;
- if (getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if(!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled())
- {
- continue;
- }
-
- if (viewp->handleHover(local_x, local_y, mask) )
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
-
- handled_view = viewp;
- break;
- }
-
- if (viewp->blockMouseEvent(local_x, local_y))
- {
- LLUI::sWindow->setCursor(viewp->getHoverCursor());
-
- handled_view = viewp;
- break;
- }
- }
- }
- return handled_view;
+ return childrenHandleMouseEvent(&LLView::handleScrollWheel, x, y, clicks, false);
}
// Called during downward traversal
LLView* LLView::childrenHandleKey(KEY key, MASK mask)
{
- LLView* handled_view = NULL;
-
- if ( getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- if (viewp->handleKey(key, mask, TRUE))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Key handled by " << viewp->getName() << llendl;
- }
- handled_view = viewp;
- break;
- }
- }
- }
-
- return handled_view;
+ return childrenHandleCharEvent("Key", &LLView::handleKey, key, mask);
}
// Called during downward traversal
LLView* LLView::childrenHandleUnicodeChar(llwchar uni_char)
{
- LLView* handled_view = NULL;
-
- if ( getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- if (viewp->handleUnicodeChar(uni_char, TRUE))
- {
- if (LLView::sDebugKeys)
- {
- llinfos << "Unicode character handled by " << viewp->getName() << llendl;
- }
- handled_view = viewp;
- break;
- }
- }
- }
-
- return handled_view;
+ return childrenHandleCharEvent("Unicode character", &LLView::handleUnicodeCharWithDummyMask,
+ uni_char, MASK_NONE);
}
LLView* LLView::childrenHandleMouseDown(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = NULL;
-
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
-
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled())
- {
- continue;
- }
-
- if(viewp->handleMouseDown( local_x, local_y, mask ))
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
- handled_view = viewp;
- break;
- }
-
- if(viewp->blockMouseEvent(local_x, local_y))
- {
- handled_view = viewp;
- break;
- }
- }
- return handled_view;
+ return childrenHandleMouseEvent(&LLView::handleMouseDown, x, y, mask);
}
LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = NULL;
-
- if (getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
-
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled())
- {
- continue;
- }
-
- if (viewp->handleRightMouseDown( local_x, local_y, mask ))
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
-
- handled_view = viewp;
- break;
- }
-
- if (viewp->blockMouseEvent(local_x, local_y))
- {
- handled_view = viewp;
- break;
- }
- }
- }
- return handled_view;
+ return childrenHandleMouseEvent(&LLView::handleRightMouseDown, x, y, mask);
}
LLView* LLView::childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = NULL;
-
- if (getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled())
- {
- continue;
- }
-
- if(viewp->handleMiddleMouseDown( local_x, local_y, mask ))
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
- handled_view = viewp;
- break;
- }
-
- if (viewp->blockMouseEvent(local_x, local_y))
- {
- handled_view = viewp;
- break;
- }
- }
- }
- return handled_view;
+ return childrenHandleMouseEvent(&LLView::handleMiddleMouseDown, x, y, mask);
}
LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = NULL;
-
- if (getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
-
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled())
- {
- continue;
- }
-
- if (viewp->handleDoubleClick( local_x, local_y, mask ))
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
- handled_view = viewp;
- break;
- }
-
- if (viewp->blockMouseEvent(local_x, local_y))
- {
- handled_view = viewp;
- break;
- }
- }
- }
- return handled_view;
+ return childrenHandleMouseEvent(&LLView::handleDoubleClick, x, y, mask);
}
LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = NULL;
- if( getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled())
- {
- continue;
- }
-
- if (viewp->handleMouseUp( local_x, local_y, mask ))
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
- handled_view = viewp;
- break;
- }
-
- if (viewp->blockMouseEvent(local_x, local_y))
- {
- handled_view = viewp;
- break;
- }
- }
- }
- return handled_view;
+ return childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask);
}
LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = NULL;
- if( getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled() )
- {
- continue;
- }
-
- if(viewp->handleRightMouseUp( local_x, local_y, mask ))
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
- handled_view = viewp;
- break;
- }
-
- if(viewp->blockMouseEvent(local_x, local_y))
- {
- handled_view = viewp;
- break;
- }
- }
- }
- return handled_view;
+ return childrenHandleMouseEvent(&LLView::handleRightMouseUp, x, y, mask);
}
LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask)
{
- LLView* handled_view = NULL;
- if( getVisible() && getEnabled() )
- {
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
- {
- LLView* viewp = *child_it;
- S32 local_x = x - viewp->getRect().mLeft;
- S32 local_y = y - viewp->getRect().mBottom;
- if (!viewp->pointInView(local_x, local_y)
- || !viewp->getVisible()
- || !viewp->getEnabled())
- {
- continue;
- }
-
- if(viewp->handleMiddleMouseUp( local_x, local_y, mask ))
- {
- if (sDebugMouseHandling)
- {
- sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
- }
- handled_view = viewp;
- break;
- }
-
- if (viewp->blockMouseEvent(local_x, local_y))
- {
- handled_view = viewp;
- break;
- }
- }
- }
- return handled_view;
+ return childrenHandleMouseEvent(&LLView::handleMiddleMouseUp, x, y, mask);
}
void LLView::draw()
@@ -1309,26 +1071,31 @@ void LLView::drawChildren()
{
if (!mChildList.empty())
{
- LLRect rootRect = getRootView()->getRect();
- LLRect screenRect;
-
+ LLView* rootp = LLUI::getRootView();
++sDepth;
for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();) // ++child_iter)
{
child_list_reverse_iter_t child = child_iter++;
LLView *viewp = *child;
+
+ if (viewp == NULL)
+ {
+ continue;
+ }
if (viewp->getVisible() && viewp->getRect().isValid())
{
- // Only draw views that are within the root view
- localRectToScreen(viewp->getRect(),&screenRect);
- if ( rootRect.overlaps(screenRect) && LLUI::sDirtyRect.overlaps(screenRect))
+ LLRect screen_rect = viewp->calcScreenRect();
+ if ( rootp->getLocalRect().overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect))
{
LLUI::pushMatrix();
{
- LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
+ LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom);
+ // flag the fact we are in draw here, in case overridden draw() method attempts to remove this widget
+ viewp->mInDraw = true;
viewp->draw();
+ viewp->mInDraw = false;
if (sDebugRects)
{
@@ -1337,7 +1104,7 @@ void LLView::drawChildren()
// Check for bogus rectangle
if (!getRect().isValid())
{
- llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
+ LL_WARNS() << "Bogus rectangle for " << getName() << " with " << mRect << LL_ENDL;
}
}
}
@@ -1375,12 +1142,12 @@ void LLView::drawDebugRect()
// drawing solids requires texturing be disabled
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- if (mUseBoundingRect)
+ if (getUseBoundingRect())
{
- LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom, 0.f);
+ LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom);
}
- LLRect debug_rect = mUseBoundingRect ? mBoundingRect : mRect;
+ LLRect debug_rect = getUseBoundingRect() ? mBoundingRect : mRect;
// draw red rectangle for the border
LLColor4 border_color(0.25f, 0.25f, 0.25f, 1.f);
@@ -1422,11 +1189,24 @@ void LLView::drawDebugRect()
&& preview_iter == sPreviewHighlightedElements.end()
&& sDebugRectsShowNames)
{
- //char temp[256];
S32 x, y;
gGL.color4fv( border_color.mV );
- x = debug_rect.getWidth()/2;
- y = debug_rect.getHeight()/2;
+
+ x = debug_rect.getWidth() / 2;
+
+ S32 rect_height = debug_rect.getHeight();
+ S32 lines = rect_height / LINE_HEIGHT + 1;
+
+ S32 depth = 0;
+ LLView * viewp = this;
+ while (NULL != viewp)
+ {
+ viewp = viewp->getParent();
+ depth++;
+ }
+
+ y = rect_height - LINE_HEIGHT * (depth % lines + 1);
+
std::string debug_text = llformat("%s (%d x %d)", getName().c_str(),
debug_rect.getWidth(), debug_rect.getHeight());
LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
@@ -1446,10 +1226,10 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr
if ((childp->getVisible() && childp->getRect().isValid())
|| force_draw)
{
- glMatrixMode(GL_MODELVIEW);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
{
- LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset, 0.f);
+ LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset);
childp->draw();
}
LLUI::popMatrix();
@@ -1473,9 +1253,10 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
mRect.mTop = getRect().mBottom + height;
// move child views according to reshape flags
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ BOOST_FOREACH(LLView* viewp, mChildList)
{
- LLView* viewp = *child_it;
+ if (viewp != NULL)
+ {
LLRect child_rect( viewp->mRect );
if (viewp->followsRight() && viewp->followsLeft())
@@ -1519,9 +1300,13 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
S32 delta_x = child_rect.mLeft - viewp->getRect().mLeft;
S32 delta_y = child_rect.mBottom - viewp->getRect().mBottom;
viewp->translate( delta_x, delta_y );
- viewp->reshape(child_rect.getWidth(), child_rect.getHeight());
+ if (child_rect.getWidth() != viewp->getRect().getWidth() || child_rect.getHeight() != viewp->getRect().getHeight())
+ {
+ viewp->reshape(child_rect.getWidth(), child_rect.getHeight());
+ }
}
}
+ }
if (!called_from_parent)
{
@@ -1538,10 +1323,8 @@ LLRect LLView::calcBoundingRect()
{
LLRect local_bounding_rect = LLRect::null;
- child_list_const_iter_t child_it;
- for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ BOOST_FOREACH(LLView* childp, mChildList)
{
- LLView* childp = *child_it;
// ignore invisible and "top" children when calculating bounding rect
// such as combobox popups
if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
@@ -1578,7 +1361,7 @@ void LLView::updateBoundingRect()
LLRect cur_rect = mBoundingRect;
- if (mUseBoundingRect)
+ if (getUseBoundingRect())
{
mBoundingRect = calcBoundingRect();
}
@@ -1588,7 +1371,7 @@ void LLView::updateBoundingRect()
}
// give parent view a chance to resize, in case we just moved, for example
- if (getParent() && getParent()->mUseBoundingRect)
+ if (getParent() && getParent()->getUseBoundingRect())
{
getParent()->updateBoundingRect();
}
@@ -1612,7 +1395,7 @@ LLRect LLView::calcScreenBoundingRect() const
{
LLRect screen_rect;
// get bounding rect, if used
- LLRect bounding_rect = mUseBoundingRect ? mBoundingRect : mRect;
+ LLRect bounding_rect = getUseBoundingRect() ? mBoundingRect : mRect;
// convert to local coordinates, as defined by mRect
bounding_rect.translate(-mRect.mLeft, -mRect.mBottom);
@@ -1668,15 +1451,19 @@ BOOL LLView::hasAncestor(const LLView* parentp) const
BOOL LLView::childHasKeyboardFocus( const std::string& childname ) const
{
- LLView *child = findChildView(childname, TRUE);
- if (child)
- {
- return gFocusMgr.childHasKeyboardFocus(child);
- }
- else
+ LLView *focus = dynamic_cast<LLView *>(gFocusMgr.getKeyboardFocus());
+
+ while (focus != NULL)
{
- return FALSE;
+ if (focus->getName() == childname)
+ {
+ return TRUE;
+ }
+
+ focus = focus->getParent();
}
+
+ return FALSE;
}
//-----------------------------------------------------------------------------
@@ -1691,31 +1478,20 @@ BOOL LLView::hasChild(const std::string& childname, BOOL recurse) const
//-----------------------------------------------------------------------------
LLView* LLView::getChildView(const std::string& name, BOOL recurse) const
{
- LLView* child = findChildView(name, recurse);
- if (!child)
- {
- child = getDefaultWidget<LLView>(name);
- if (!child)
- {
- child = LLUICtrlFactory::createDefaultWidget<LLView>(name);
- }
- }
- return child;
+ return getChild<LLView>(name, recurse);
}
-static LLFastTimer::DeclareTimer FTM_FIND_VIEWS("Find Widgets");
+static LLTrace::BlockTimerStatHandle FTM_FIND_VIEWS("Find Widgets");
LLView* LLView::findChildView(const std::string& name, BOOL recurse) const
{
- LLFastTimer ft(FTM_FIND_VIEWS);
+ LL_RECORD_BLOCK_TIME(FTM_FIND_VIEWS);
//richard: should we allow empty names?
//if(name.empty())
// return NULL;
- child_list_const_iter_t child_it;
// Look for direct children *first*
- for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ BOOST_FOREACH(LLView* childp, mChildList)
{
- LLView* childp = *child_it;
llassert(childp);
if (childp->getName() == name)
{
@@ -1725,9 +1501,8 @@ LLView* LLView::findChildView(const std::string& name, BOOL recurse) const
if (recurse)
{
// Look inside each child as well.
- for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ BOOST_FOREACH(LLView* childp, mChildList)
{
- LLView* childp = *child_it;
llassert(childp);
LLView* viewp = childp->findChildView(name, recurse);
if ( viewp )
@@ -1741,14 +1516,14 @@ LLView* LLView::findChildView(const std::string& name, BOOL recurse) const
BOOL LLView::parentPointInView(S32 x, S32 y, EHitTestType type) const
{
- return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT)
+ return (getUseBoundingRect() && type == HIT_TEST_USE_BOUNDING_RECT)
? mBoundingRect.pointInRect( x, y )
: mRect.pointInRect( x, y );
}
BOOL LLView::pointInView(S32 x, S32 y, EHitTestType type) const
{
- return (mUseBoundingRect && type == HIT_TEST_USE_BOUNDING_RECT)
+ return (getUseBoundingRect() && type == HIT_TEST_USE_BOUNDING_RECT)
? mBoundingRect.pointInRect( x + mRect.mLeft, y + mRect.mBottom )
: mRect.localPointInRect( x, y );
}
@@ -1775,16 +1550,18 @@ void LLView::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* l
void LLView::localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const
{
- *screen_x = local_x + getRect().mLeft;
- *screen_y = local_y + getRect().mBottom;
+ *screen_x = local_x;
+ *screen_y = local_y;
const LLView* cur = this;
- while( cur->mParentView )
+ do
{
+ LLRect cur_rect = cur->getRect();
+ *screen_x += cur_rect.mLeft;
+ *screen_y += cur_rect.mBottom;
cur = cur->mParentView;
- *screen_x += cur->getRect().mLeft;
- *screen_y += cur->getRect().mBottom;
}
+ while( cur );
}
void LLView::screenRectToLocal(const LLRect& screen, LLRect* local) const
@@ -1844,67 +1621,31 @@ LLView* LLView::findNextSibling(LLView* child)
return (next_it != mChildList.end()) ? *next_it : NULL;
}
-void LLView::deleteViewByHandle(LLHandle<LLView> handle)
-{
- LLView* viewp = handle.get();
-
- delete viewp;
-}
-
-LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside)
+LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, S32 min_overlap_pixels)
{
LLCoordGL delta;
- if (allow_partial_outside)
- {
- const S32 KEEP_ONSCREEN_PIXELS = 16;
+ const S32 KEEP_ONSCREEN_PIXELS_WIDTH = llmin(min_overlap_pixels, input.getWidth());
+ const S32 KEEP_ONSCREEN_PIXELS_HEIGHT = llmin(min_overlap_pixels, input.getHeight());
- if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft )
- {
- delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS);
- }
- else
- if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
- {
- delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS);
- }
+ if( input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH < constraint.mLeft )
+ {
+ delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH);
+ }
+ else if( input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH > constraint.mRight )
+ {
+ delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH);
+ }
- if( input.mTop > constraint.mTop )
- {
- delta.mY = constraint.mTop - input.mTop;
- }
- else
- if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
- {
- delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS);
- }
+ if( input.mTop > constraint.mTop )
+ {
+ delta.mY = constraint.mTop - input.mTop;
}
else
+ if( input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT < constraint.mBottom )
{
- if( input.mLeft < constraint.mLeft )
- {
- delta.mX = constraint.mLeft - input.mLeft;
- }
- else
- if( input.mRight > constraint.mRight )
- {
- delta.mX = constraint.mRight - input.mRight;
- // compensate for left edge possible going off screen
- delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() );
- }
-
- if( input.mTop > constraint.mTop )
- {
- delta.mY = constraint.mTop - input.mTop;
- }
- else
- if( input.mBottom < constraint.mBottom )
- {
- delta.mY = constraint.mBottom - input.mBottom;
- // compensate for top edge possible going off screen
- delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() );
- }
+ delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT);
}
return delta;
@@ -1913,9 +1654,9 @@ LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BO
// Moves the view so that it is entirely inside of constraint.
// If the view will not fit because it's too big, aligns with the top and left.
// (Why top and left? That's where the drag bars are for floaters.)
-BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside )
+BOOL LLView::translateIntoRect(const LLRect& constraint, S32 min_overlap_pixels)
{
- LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside);
+ LLCoordGL translation = getNeededTranslation(getRect(), constraint, min_overlap_pixels);
if (translation.mX != 0 || translation.mY != 0)
{
@@ -1927,9 +1668,9 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs
// move this view into "inside" but not onto "exclude"
// NOTE: if this view is already contained in "inside", we ignore the "exclude" rect
-BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside )
+BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels)
{
- LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside);
+ LLCoordGL translation = getNeededTranslation(getRect(), inside, min_overlap_pixels);
if (translation.mX != 0 || translation.mY != 0)
{
@@ -1977,7 +1718,7 @@ void LLView::centerWithin(const LLRect& bounds)
translate( left - getRect().mLeft, bottom - getRect().mBottom );
}
-BOOL LLView::localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LLView* other_view) const
+BOOL LLView::localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, const LLView* other_view) const
{
const LLView* cur_view = this;
const LLView* root_view = NULL;
@@ -2020,7 +1761,7 @@ BOOL LLView::localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LL
return FALSE;
}
-BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, LLView* other_view ) const
+BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, const LLView* other_view ) const
{
LLRect cur_rect = local;
const LLView* cur_view = this;
@@ -2059,15 +1800,63 @@ BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, LLView* o
return FALSE;
}
+
+class CompareByTabOrder
+{
+public:
+ CompareByTabOrder(const LLView::child_tab_order_t& order, S32 default_tab_group = 0)
+ : mTabOrder(order),
+ mDefaultTabGroup(default_tab_group)
+ {}
+ virtual ~CompareByTabOrder() {}
+
+ // This method compares two LLViews by the tab order specified in the comparator object. The
+ // code for this is a little convoluted because each argument can have four states:
+ // 1) not a control, 2) a control but not in the tab order, 3) a control in the tab order, 4) null
+ bool operator() (const LLView* const a, const LLView* const b) const
+ {
+ S32 a_group = 0, b_group = 0;
+ if(!a) return false;
+ if(!b) return true;
+
+ LLView::child_tab_order_const_iter_t a_found = mTabOrder.find(a), b_found = mTabOrder.find(b);
+ if(a_found != mTabOrder.end())
+ {
+ a_group = a_found->second;
+ }
+ if(b_found != mTabOrder.end())
+ {
+ b_group = b_found->second;
+ }
+
+ if(a_group < mDefaultTabGroup && b_group >= mDefaultTabGroup) return true;
+ if(b_group < mDefaultTabGroup && a_group >= mDefaultTabGroup) return false;
+ return a_group > b_group; // sort correctly if they're both on the same side of the default tab groupreturn a > b;
+ }
+private:
+ // ok to store a reference, as this should only be allocated on stack during view query operations
+ const LLView::child_tab_order_t& mTabOrder;
+ const S32 mDefaultTabGroup;
+};
+
+class SortByTabOrder : public LLQuerySorter, public LLSingleton<SortByTabOrder>
+{
+ /*virtual*/ void sort(LLView * parent, LLView::child_list_t &children) const
+ {
+ children.sort(CompareByTabOrder(parent->getTabOrder(), parent->getDefaultTabGroup()));
+ }
+};
+
// static
-const LLCtrlQuery & LLView::getTabOrderQuery()
+const LLViewQuery & LLView::getTabOrderQuery()
{
- static LLCtrlQuery query;
+ static LLViewQuery query;
if(query.getPreFilters().size() == 0) {
query.addPreFilter(LLVisibleFilter::getInstance());
query.addPreFilter(LLEnabledFilter::getInstance());
query.addPreFilter(LLTabStopFilter::getInstance());
query.addPostFilter(LLLeavesFilter::getInstance());
+ query.setSorter(SortByTabOrder::getInstance());
}
return query;
}
@@ -2082,9 +1871,9 @@ class LLFocusRootsFilter : public LLQueryFilter, public LLSingleton<LLFocusRoots
};
// static
-const LLCtrlQuery & LLView::getFocusRootsQuery()
+const LLViewQuery & LLView::getFocusRootsQuery()
{
- static LLCtrlQuery query;
+ static LLViewQuery query;
if(query.getPreFilters().size() == 0) {
query.addPreFilter(LLVisibleFilter::getInstance());
query.addPreFilter(LLEnabledFilter::getInstance());
@@ -2097,7 +1886,10 @@ const LLCtrlQuery & LLView::getFocusRootsQuery()
void LLView::setShape(const LLRect& new_rect, bool by_user)
{
- handleReshape(new_rect, by_user);
+ if (new_rect != getRect())
+ {
+ handleReshape(new_rect, by_user);
+ }
}
void LLView::handleReshape(const LLRect& new_rect, bool by_user)
@@ -2233,7 +2025,7 @@ LLView* LLView::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESna
}
break;
default:
- llerrs << "Invalid snap edge" << llendl;
+ LL_ERRS() << "Invalid snap edge" << LL_ENDL;
}
}
@@ -2335,7 +2127,7 @@ LLView* LLView::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESna
}
break;
default:
- llerrs << "Invalid snap edge" << llendl;
+ LL_ERRS() << "Invalid snap edge" << LL_ENDL;
}
}
}
@@ -2372,10 +2164,6 @@ LLControlVariable *LLView::findControl(const std::string& name)
return control_group.getControl(name);
}
-const S32 FLOATER_H_MARGIN = 15;
-const S32 MIN_WIDGET_HEIGHT = 10;
-const S32 VPAD = 4;
-
void LLView::initFromParams(const LLView::Params& params)
{
LLRect required_rect = getRequiredRect();
@@ -2487,150 +2275,163 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect)
}
//static
-void LLView::applyXUILayout(LLView::Params& p, LLView* parent)
+void LLView::applyXUILayout(LLView::Params& p, LLView* parent, LLRect layout_rect)
{
+ if (!parent) return;
+
const S32 VPAD = 4;
const S32 MIN_WIDGET_HEIGHT = 10;
// *NOTE: This will confuse export of floater/panel coordinates unless
// the default is also "topleft". JC
- if (p.layout().empty() && parent)
+ if (p.layout().empty())
{
p.layout = parent->getLayout();
}
-
- if (parent)
+ if (layout_rect.isEmpty())
{
- LLRect parent_rect = parent->getLocalRect();
- // overwrite uninitialized rect params, using context
- LLRect last_rect = parent->getLocalRect();
+ layout_rect = parent->getLocalRect();
+ }
+
+ // overwrite uninitialized rect params, using context
+ LLRect default_rect = parent->getLocalRect();
+
+ bool layout_topleft = (p.layout() == "topleft");
- bool layout_topleft = (p.layout() == "topleft");
+ // convert negative or centered coordinates to parent relative values
+ // Note: some of this logic matches the logic in TypedParam<LLRect>::setValueFromBlock()
+ if (p.rect.left.isProvided())
+ {
+ p.rect.left = p.rect.left + ((p.rect.left >= 0) ? layout_rect.mLeft : layout_rect.mRight);
+ }
+ if (p.rect.right.isProvided())
+ {
+ p.rect.right = p.rect.right + ((p.rect.right >= 0) ? layout_rect.mLeft : layout_rect.mRight);
+ }
+ if (p.rect.bottom.isProvided())
+ {
+ p.rect.bottom = p.rect.bottom + ((p.rect.bottom >= 0) ? layout_rect.mBottom : layout_rect.mTop);
if (layout_topleft)
{
//invert top to bottom
- if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top;
- if (p.rect.bottom.isProvided()) p.rect.bottom = parent_rect.getHeight() - p.rect.bottom;
+ p.rect.bottom = layout_rect.mBottom + layout_rect.mTop - p.rect.bottom;
}
+ }
+ if (p.rect.top.isProvided())
+ {
+ p.rect.top = p.rect.top + ((p.rect.top >= 0) ? layout_rect.mBottom : layout_rect.mTop);
+ if (layout_topleft)
+ {
+ //invert top to bottom
+ p.rect.top = layout_rect.mBottom + layout_rect.mTop - p.rect.top;
+ }
+ }
- // convert negative or centered coordinates to parent relative values
- // Note: some of this logic matches the logic in TypedParam<LLRect>::setValueFromBlock()
+ // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels
+ if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0)
+ {
+ p.rect.height = MIN_WIDGET_HEIGHT;
+ }
+
+ default_rect.translate(0, default_rect.getHeight());
- if (p.center_horiz)
+ // If there was a recently constructed child, use its rectangle
+ get_last_child_rect(parent, &default_rect);
+
+ if (layout_topleft)
+ {
+ // Invert the sense of bottom_delta for topleft layout
+ if (p.bottom_delta.isProvided())
{
- if (p.rect.left.isProvided() && p.rect.right.isProvided())
- {
- S32 width = p.rect.right - p.rect.left;
- width = llmax(width, 0);
- S32 offset = parent_rect.getWidth()/2 - width/2;
- p.rect.left = p.rect.left + offset;
- p.rect.right = p.rect.right + offset;
- }
- else
- {
- p.rect.left = p.rect.left + parent_rect.getWidth()/2 - p.rect.width/2;
- p.rect.right.setProvided(false); // recalculate the right
- }
+ p.bottom_delta = -p.bottom_delta;
}
- else
+ else if (p.top_pad.isProvided())
{
- if (p.rect.left.isProvided() && p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth();
- if (p.rect.right.isProvided() && p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth();
+ p.bottom_delta = -(p.rect.height + p.top_pad);
}
- if (p.center_vert)
+ else if (p.top_delta.isProvided())
{
- if (p.rect.bottom.isProvided() && p.rect.top.isProvided())
- {
- S32 height = p.rect.top - p.rect.bottom;
- height = llmax(height, 0);
- S32 offset = parent_rect.getHeight()/2 - height/2;
- p.rect.bottom = p.rect.bottom + offset;
- p.rect.top = p.rect.top + offset;
- }
- else
- {
- p.rect.bottom = p.rect.bottom + parent_rect.getHeight()/2 - p.rect.height/2;
- p.rect.top.setProvided(false); // recalculate the top
- }
+ p.bottom_delta =
+ -(p.top_delta + p.rect.height - default_rect.getHeight());
+ }
+ else if (!p.left_delta.isProvided()
+ && !p.left_pad.isProvided())
+ {
+ // set default position is just below last rect
+ p.bottom_delta.set(-(p.rect.height + VPAD), false);
}
else
{
- if (p.rect.bottom.isProvided() && p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight();
- if (p.rect.top.isProvided() && p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight();
+ p.bottom_delta.set(0, false);
}
-
-
- // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels
- if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0)
+
+ // default to same left edge
+ if (!p.left_delta.isProvided())
{
- p.rect.height = MIN_WIDGET_HEIGHT;
+ p.left_delta.set(0, false);
}
-
- last_rect.translate(0, last_rect.getHeight());
-
- // If there was a recently constructed child, use its rectangle
- get_last_child_rect(parent, &last_rect);
-
- if (layout_topleft)
+ if (p.left_pad.isProvided())
{
- p.bottom_delta.setIfNotProvided(0, false);
-
- // Invert the sense of bottom_delta for topleft layout
- if (p.bottom_delta.isProvided())
- {
- p.bottom_delta = -p.bottom_delta;
- }
- else if (p.top_pad.isProvided())
- {
- p.bottom_delta = -(p.rect.height + p.top_pad);
- }
- else if (p.top_delta.isProvided())
- {
- p.bottom_delta =
- -(p.top_delta + p.rect.height - last_rect.getHeight());
- }
- else if (!p.bottom_delta.isProvided()
- && !p.left_delta.isProvided()
- && !p.top_pad.isProvided()
- && !p.left_pad.isProvided())
- {
- // set default position is just below last rect
- p.bottom_delta.set(-(p.rect.height + VPAD), false);
- }
-
- // default to same left edge
- p.left_delta.setIfNotProvided(0, false);
- if (p.left_pad.isProvided())
- {
- // left_pad is based on prior widget's right edge
- p.left_delta.set(p.left_pad + last_rect.getWidth(), false);
- }
+ // left_pad is based on prior widget's right edge
+ p.left_delta.set(p.left_pad + default_rect.getWidth(), false);
+ }
- last_rect.translate(p.left_delta, p.bottom_delta);
+ default_rect.translate(p.left_delta, p.bottom_delta);
+ }
+ else
+ {
+ // set default position is just below last rect
+ if (!p.bottom_delta.isProvided())
+ {
+ p.bottom_delta.set(-(p.rect.height + VPAD), false);
}
- else
- {
- // set default position is just below last rect
- p.bottom_delta.setIfNotProvided(-(p.rect.height + VPAD), false);
- p.left_delta.setIfNotProvided(0, false);
- last_rect.translate(p.left_delta, p.bottom_delta);
+ if (!p.left_delta.isProvided())
+ {
+ p.left_delta.set(0, false);
}
+ default_rect.translate(p.left_delta, p.bottom_delta);
+ }
- // this handles case where *both* x and x_delta are provided
- // ignore x in favor of default x + x_delta
- if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false);
- if (p.left_delta.isProvided()) p.rect.left.set(0, false);
+ // this handles case where *both* x and x_delta are provided
+ // ignore x in favor of default x + x_delta
+ if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false);
+ if (p.left_delta.isProvided()) p.rect.left.set(0, false);
- // selectively apply rectangle defaults, making sure that
- // params are not flagged as having been "provided"
- // as rect params are overconstrained and rely on provided flags
- p.rect.left.setIfNotProvided(last_rect.mLeft, false);
- p.rect.bottom.setIfNotProvided(last_rect.mBottom, false);
- p.rect.top.setIfNotProvided(last_rect.mTop, false);
- p.rect.right.setIfNotProvided(last_rect.mRight, false);
- p.rect.width.setIfNotProvided(last_rect.getWidth(), false);
- p.rect.height.setIfNotProvided(last_rect.getHeight(), false);
+ // selectively apply rectangle defaults, making sure that
+ // params are not flagged as having been "provided"
+ // as rect params are overconstrained and rely on provided flags
+ if (!p.rect.left.isProvided())
+ {
+ p.rect.left.set(default_rect.mLeft, false);
+ //HACK: get around the fact that setting a rect param component value won't invalidate the existing rect object value
+ p.rect.paramChanged(p.rect.left, true);
+ }
+ if (!p.rect.bottom.isProvided())
+ {
+ p.rect.bottom.set(default_rect.mBottom, false);
+ p.rect.paramChanged(p.rect.bottom, true);
+ }
+ if (!p.rect.top.isProvided())
+ {
+ p.rect.top.set(default_rect.mTop, false);
+ p.rect.paramChanged(p.rect.top, true);
+ }
+ if (!p.rect.right.isProvided())
+ {
+ p.rect.right.set(default_rect.mRight, false);
+ p.rect.paramChanged(p.rect.right, true);
+
+ }
+ if (!p.rect.width.isProvided())
+ {
+ p.rect.width.set(default_rect.getWidth(), false);
+ p.rect.paramChanged(p.rect.width, true);
+ }
+ if (!p.rect.height.isProvided())
+ {
+ p.rect.height.set(default_rect.getHeight(), false);
+ p.rect.paramChanged(p.rect.height, true);
}
}
@@ -2649,7 +2450,7 @@ static S32 invert_vertical(S32 y, LLView* parent)
}
else
{
- llwarns << "Attempting to convert layout to top-left with no parent" << llendl;
+ LL_WARNS() << "Attempting to convert layout to top-left with no parent" << LL_ENDL;
return y;
}
}
@@ -2824,6 +2625,19 @@ LLView::tree_post_iterator_t LLView::endTreeDFSPost()
return tree_post_iterator_t();
}
+LLView::bfs_tree_iterator_t LLView::beginTreeBFS()
+{
+ return bfs_tree_iterator_t(this,
+ boost::bind(boost::mem_fn(&LLView::beginChild), _1),
+ boost::bind(boost::mem_fn(&LLView::endChild), _1));
+}
+
+LLView::bfs_tree_iterator_t LLView::endTreeBFS()
+{
+ // an empty iterator is an "end" iterator
+ return bfs_tree_iterator_t();
+}
+
LLView::root_to_view_iterator_t LLView::beginRootToView()
{
@@ -2838,11 +2652,14 @@ LLView::root_to_view_iterator_t LLView::endRootToView()
// only create maps on demand, as they incur heap allocation/deallocation cost
// when a view is constructed/deconstructed
-LLView::default_widget_map_t& LLView::getDefaultWidgetMap() const
+LLView& LLView::getDefaultWidgetContainer() const
{
if (!mDefaultWidgets)
{
- mDefaultWidgets = new default_widget_map_t();
+ LLView::Params p;
+ p.name = "default widget container";
+ p.visible = false; // ensures default widgets can't steal focus, etc.
+ mDefaultWidgets = new LLView(p);
}
return *mDefaultWidgets;
}
@@ -2857,9 +2674,9 @@ S32 LLView::notifyParent(const LLSD& info)
bool LLView::notifyChildren(const LLSD& info)
{
bool ret = false;
- for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ BOOST_FOREACH(LLView* childp, mChildList)
{
- ret |= (*child_it)->notifyChildren(info);
+ ret = ret || childp->notifyChildren(info);
}
return ret;
}
@@ -2879,3 +2696,24 @@ const LLViewDrawContext& LLViewDrawContext::getCurrentContext()
return *sDrawContextStack.back();
}
+
+LLSD LLView::getInfo(void)
+{
+ LLSD info;
+ addInfo(info);
+ return info;
+}
+
+void LLView::addInfo(LLSD & info)
+{
+ info["path"] = getPathname();
+ info["class"] = typeid(*this).name();
+ info["visible"] = getVisible();
+ info["visible_chain"] = isInVisibleChain();
+ info["enabled"] = getEnabled();
+ info["enabled_chain"] = isInEnabledChain();
+ info["available"] = isAvailable();
+ LLRect rect(calcScreenRect());
+ info["rect"] = LLSDMap("left", rect.mLeft)("top", rect.mTop)
+ ("right", rect.mRight)("bottom", rect.mBottom);
+}