Updated LLView:

-Removed a few extra unneeded virtuals
 -Pulled tabgroups out of llpanel and into LLView
 -removeChild doesn't support delete. Delete manually.
 -addChildAtEnd renamed to addChildInBack
 -getScreenRect renamed to calcScreenRect
 -added calcScreenBoundingRect and calcBoundingRect(which updateBoundingRect calls
 -General cleanup. Someone at LL figured out that dynamic_cast actually exists.
Fixed PieMenu not reliably centering on cursor.
Fixed context menu crash in line and text editors.
Classes with LLEditMenuHandler as a base do not need to set gEditMenuHandler to NULL, since LLEditMenuHandler's dtor does that already!
This commit is contained in:
Shyotl
2012-02-21 21:59:22 -06:00
parent e2e65c39bf
commit bdeead6f8e
29 changed files with 404 additions and 396 deletions

View File

@@ -81,7 +81,9 @@ S32 LLView::sLastBottomXML = S32_MIN;
BOOL LLView::sIsDrawing = FALSE;
#endif
LLView::LLView() :
LLView::LLView()
: mVisible(TRUE),
mInDraw(false),
mParentView(NULL),
mReshapeFlags(FOLLOWS_NONE),
mDefaultTabGroup(0),
@@ -92,18 +94,20 @@ LLView::LLView() :
mIsFocusRoot(FALSE),
mLastVisible(TRUE),
mUseBoundingRect(FALSE),
mVisible(TRUE),
mNextInsertionOrdinal(0),
mHoverCursor(UI_CURSOR_ARROW),
mLastTabGroup(0),
// <edit>
mDelayedDelete(FALSE)
// </edit>
{
}
LLView::LLView(const std::string& name, BOOL mouse_opaque) :
mParentView(NULL),
LLView::LLView(const std::string& name, BOOL mouse_opaque)
: mVisible(TRUE),
mInDraw(false),
mName(name),
mParentView(NULL),
mReshapeFlags(FOLLOWS_NONE),
mDefaultTabGroup(0),
mEnabled(TRUE),
@@ -113,9 +117,9 @@ LLView::LLView(const std::string& name, BOOL mouse_opaque) :
mIsFocusRoot(FALSE),
mLastVisible(TRUE),
mUseBoundingRect(FALSE),
mVisible(TRUE),
mNextInsertionOrdinal(0),
mHoverCursor(UI_CURSOR_ARROW),
mLastTabGroup(0),
// <edit>
mDelayedDelete(FALSE)
// </edit>
@@ -124,9 +128,11 @@ LLView::LLView(const std::string& name, BOOL mouse_opaque) :
LLView::LLView(
const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 reshape) :
mParentView(NULL),
const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 reshape)
: mVisible(TRUE),
mInDraw(false),
mName(name),
mParentView(NULL),
mRect(rect),
mBoundingRect(rect),
mReshapeFlags(reshape),
@@ -138,9 +144,9 @@ LLView::LLView(
mIsFocusRoot(FALSE),
mLastVisible(TRUE),
mUseBoundingRect(FALSE),
mVisible(TRUE),
mNextInsertionOrdinal(0),
mHoverCursor(UI_CURSOR_ARROW),
mLastTabGroup(0),
// <edit>
mDelayedDelete(FALSE)
// </edit>
@@ -234,7 +240,7 @@ void LLView::setUseBoundingRect( BOOL use_bounding_rect )
}
}
BOOL LLView::getUseBoundingRect()
BOOL LLView::getUseBoundingRect() const
{
return mUseBoundingRect;
}
@@ -263,6 +269,7 @@ void LLView::sendChildToFront(LLView* child)
void LLView::sendChildToBack(LLView* child)
{
// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs
if (child && child->getParent() == this)
{
// minor optimization, but more importantly,
@@ -291,16 +298,18 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child)
}
}
void LLView::addChild(LLView* child, S32 tab_group)
// virtual
bool LLView::addChild(LLView* child, S32 tab_group)
{
if (!child)
{
return;
return false;
}
if (mParentView == child)
{
llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
}
// remove from current parent
if (child->mParentView)
{
@@ -313,86 +322,57 @@ void LLView::addChild(LLView* child, S32 tab_group)
// add to ctrl list if is LLUICtrl
if (child->isCtrl())
{
// controls are stored in reverse order from render order
addCtrlAtEnd((LLUICtrl*) child, tab_group);
LLUICtrl* ctrl = static_cast<LLUICtrl*>(child);
mCtrlOrder.insert(tab_order_pair_t(ctrl,
tab_order_t(tab_group, mNextInsertionOrdinal)));
mNextInsertionOrdinal++;
}
child->mParentView = this;
updateBoundingRect();
mLastTabGroup = tab_group;
return true;
}
void LLView::addChildAtEnd(LLView* child, S32 tab_group)
bool LLView::addChildInBack(LLView* child, S32 tab_group)
{
if (mParentView == child)
if(addChild(child, tab_group))
{
llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
}
// remove from current parent
if (child->mParentView)
{
child->mParentView->removeChild(child);
sendChildToBack(child);
return true;
}
// add to back of child list
mChildList.push_back(child);
// add to ctrl list if is LLUICtrl
if (child->isCtrl())
{
// controls are stored in reverse order from render order
addCtrl((LLUICtrl*) child, tab_group);
}
child->mParentView = this;
updateBoundingRect();
return false;
}
// remove the specified child from the view, and set it's parent to NULL.
void LLView::removeChild(LLView* child, BOOL deleteIt)
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())
{
removeCtrl((LLUICtrl*)child);
}
if (deleteIt)
{
delete child;
child_tab_order_t::iterator found = mCtrlOrder.find(static_cast<LLUICtrl*>(child));
if(found != mCtrlOrder.end())
{
mCtrlOrder.erase(found);
}
}
}
else
{
llerrs << "LLView::removeChild called with non-child" << llendl;
llwarns << child->getName() << "is not a child of " << getName() << llendl;
}
updateBoundingRect();
}
void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group)
{
mCtrlOrder.insert(tab_order_pair_t(ctrl,
tab_order_t(tab_group, mNextInsertionOrdinal++)));
}
void LLView::addCtrl( LLUICtrl* ctrl, S32 tab_group)
{
// add to front of list by using negative ordinal, which monotonically increases
mCtrlOrder.insert(tab_order_pair_t(ctrl,
tab_order_t(tab_group, -1 * mNextInsertionOrdinal++)));
}
void LLView::removeCtrl(LLUICtrl* ctrl)
{
child_tab_order_t::iterator found = mCtrlOrder.find(ctrl);
if(found != mCtrlOrder.end())
{
mCtrlOrder.erase(found);
}
}
LLView::ctrl_list_t LLView::getCtrlList() const
{
ctrl_list_t controls;
@@ -1325,56 +1305,72 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask)
void LLView::draw()
{
if (sDebugRects)
{
drawDebugRect();
drawChildren();
}
// Check for bogus rectangle
if (getRect().mRight <= getRect().mLeft
|| getRect().mTop <= getRect().mBottom)
{
llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
}
}
LLRect rootRect = getRootView()->getRect();
LLRect screenRect;
void LLView::drawChildren()
{
// draw focused control on top of everything else
LLUICtrl* focus_view = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
/*LLUICtrl* focus_view = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
if (focus_view && focus_view->getParent() != this)
{
focus_view = NULL;
}
++sDepth;
for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
}*/
if (!mChildList.empty())
{
LLView *viewp = *child_iter;
LLView* rootp = getRootView();
++sDepth;
if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid())
for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();) // ++child_iter)
{
// Only draw views that are within the root view
localRectToScreen(viewp->getRect(),&screenRect);
if ( rootRect.overlaps(screenRect) )
{
gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
child_list_reverse_iter_t child = child_iter++;
LLView *viewp = *child;
if (viewp == NULL)
{
LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
viewp->draw();
continue;
}
if (viewp->getVisible() && /*viewp != focus_view && */viewp->getRect().isValid())
{
// Only draw views that are within the root view
LLRect screen_rect = viewp->calcScreenRect();
if ( rootp->getLocalRect().overlaps(screen_rect) )
{
//gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
{
LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
// 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)
{
viewp->drawDebugRect();
// Check for bogus rectangle
if (!getRect().isValid())
{
llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
}
}
}
LLUI::popMatrix();
}
LLUI::popMatrix();
}
}
--sDepth;
}
--sDepth;
if (focus_view && focus_view->getVisible())
/*if (focus_view && focus_view->getVisible())
{
drawChild(focus_view);
}
}*/
// HACK
if (sEditingUI && this == sEditingUIView)
@@ -1391,12 +1387,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);
}
LLRect debug_rect = mUseBoundingRect ? mBoundingRect : mRect;
LLRect debug_rect = getUseBoundingRect() ? mBoundingRect : mRect;
// draw red rectangle for the border
LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
@@ -1539,43 +1535,51 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
updateBoundingRect();
}
void LLView::updateBoundingRect()
LLRect LLView::calcBoundingRect()
{
if (isDead()) return;
if (mUseBoundingRect)
{
LLRect local_bounding_rect = LLRect::null;
LLRect local_bounding_rect = LLRect::null;
BOOST_FOREACH(LLView* childp, mChildList)
{
// ignore invisible and "top" children when calculating bounding rect
// such as combobox popups
if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
{
continue;
}
LLRect child_bounding_rect = childp->getBoundingRect();
if (local_bounding_rect.isEmpty())
{
// start out with bounding rect equal to first visible child's bounding rect
local_bounding_rect = child_bounding_rect;
}
else
{
// accumulate non-null children rectangles
if (child_bounding_rect.notEmpty())
{
local_bounding_rect.unionWith(child_bounding_rect);
}
}
// such as combobox popups
if (!childp->getVisible() || childp == gFocusMgr.getTopCtrl())
{
continue;
}
mBoundingRect = local_bounding_rect;
// translate into parent-relative coordinates
mBoundingRect.translate(mRect.mLeft, mRect.mBottom);
LLRect child_bounding_rect = childp->getBoundingRect();
if (local_bounding_rect.isEmpty())
{
// start out with bounding rect equal to first visible child's bounding rect
local_bounding_rect = child_bounding_rect;
}
else
{
// accumulate non-null children rectangles
if (!child_bounding_rect.isEmpty())
{
local_bounding_rect.unionWith(child_bounding_rect);
}
}
}
// convert to parent-relative coordinates
local_bounding_rect.translate(mRect.mLeft, mRect.mBottom);
return local_bounding_rect;
}
void LLView::updateBoundingRect()
{
if (isDead()) return;
LLRect cur_rect = mBoundingRect;
if (getUseBoundingRect())
{
mBoundingRect = calcBoundingRect();
}
else
{
@@ -1583,21 +1587,40 @@ 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();
}
/*if (mBoundingRect != cur_rect)
{
dirtyRect();
}*/
}
LLRect LLView::getScreenRect() const
LLRect LLView::calcScreenRect() const
{
// *FIX: check for one-off error
LLRect screen_rect;
localPointToScreen(0, 0, &screen_rect.mLeft, &screen_rect.mBottom);
localPointToScreen(getRect().getWidth(), getRect().getHeight(), &screen_rect.mRight, &screen_rect.mTop);
return screen_rect;
}
LLRect LLView::calcScreenBoundingRect() const
{
LLRect screen_rect;
// get bounding rect, if used
LLRect bounding_rect = getUseBoundingRect() ? mBoundingRect : mRect;
// convert to local coordinates, as defined by mRect
bounding_rect.translate(-mRect.mLeft, -mRect.mBottom);
localPointToScreen(bounding_rect.mLeft, bounding_rect.mBottom, &screen_rect.mLeft, &screen_rect.mBottom);
localPointToScreen(bounding_rect.mRight, bounding_rect.mTop, &screen_rect.mRight, &screen_rect.mTop);
return screen_rect;
}
LLRect LLView::getLocalBoundingRect() const
{
LLRect local_bounding_rect = getBoundingRect();
@@ -1644,15 +1667,19 @@ BOOL LLView::hasAncestor(const LLView* parentp) const
BOOL LLView::childHasKeyboardFocus( const std::string& childname ) const
{
LLView *child = getChildView(childname, TRUE, FALSE);
if (child)
LLView *focus = dynamic_cast<LLView *>(gFocusMgr.getKeyboardFocus());
while (focus != NULL)
{
return gFocusMgr.childHasKeyboardFocus(child);
}
else
{
return FALSE;
if (focus->getName() == childname)
{
return TRUE;
}
focus = focus->getParent();
}
return FALSE;
}
//-----------------------------------------------------------------------------