00001
00033 #include "linden_common.h"
00034
00035 #include "llview.h"
00036
00037 #include <cassert>
00038 #include <boost/tokenizer.hpp>
00039
00040 #include "llevent.h"
00041 #include "llfontgl.h"
00042 #include "llfocusmgr.h"
00043 #include "llgl.h"
00044 #include "llglheaders.h"
00045 #include "llrect.h"
00046 #include "llstl.h"
00047 #include "llui.h"
00048 #include "lluictrl.h"
00049 #include "llwindow.h"
00050 #include "v3color.h"
00051
00052
00053 BOOL LLView::sDebugRects = FALSE;
00054 BOOL LLView::sDebugKeys = FALSE;
00055 S32 LLView::sDepth = 0;
00056 BOOL LLView::sDebugMouseHandling = FALSE;
00057 LLString LLView::sMouseHandlerMessage;
00058 S32 LLView::sSelectID = GL_NAME_UI_RESERVED;
00059 BOOL LLView::sEditingUI = FALSE;
00060 BOOL LLView::sForceReshape = FALSE;
00061 LLView* LLView::sEditingUIView = NULL;
00062 S32 LLView::sLastLeftXML = S32_MIN;
00063 S32 LLView::sLastBottomXML = S32_MIN;
00064 std::map<LLViewHandle,LLView*> LLView::sViewHandleMap;
00065
00066 S32 LLViewHandle::sNextID = 0;
00067 LLViewHandle LLViewHandle::sDeadHandle;
00068
00069 #if LL_DEBUG
00070 BOOL LLView::sIsDrawing = FALSE;
00071 #endif
00072
00073
00074 LLView* LLView::getViewByHandle(LLViewHandle handle)
00075 {
00076 if (handle == LLViewHandle::sDeadHandle)
00077 {
00078 return NULL;
00079 }
00080 std::map<LLViewHandle,LLView*>::iterator iter = sViewHandleMap.find(handle);
00081 if (iter != sViewHandleMap.end())
00082 {
00083 return iter->second;
00084 }
00085 else
00086 {
00087 return NULL;
00088 }
00089 }
00090
00091
00092 BOOL LLView::deleteViewByHandle(LLViewHandle handle)
00093 {
00094 std::map<LLViewHandle,LLView*>::iterator iter = sViewHandleMap.find(handle);
00095 if (iter != sViewHandleMap.end())
00096 {
00097 delete iter->second;
00098 return TRUE;
00099 }
00100 else
00101 {
00102 return FALSE;
00103 }
00104 }
00105
00106 LLView::LLView() :
00107 mParentView(NULL),
00108 mReshapeFlags(FOLLOWS_NONE),
00109 mDefaultTabGroup(0),
00110 mEnabled(TRUE),
00111 mMouseOpaque(TRUE),
00112 mSoundFlags(MOUSE_UP),
00113 mSaveToXML(TRUE),
00114 mIsFocusRoot(FALSE),
00115 mLastVisible(TRUE),
00116 mSpanChildren(FALSE),
00117 mVisible(TRUE),
00118 mHidden(FALSE),
00119 mNextInsertionOrdinal(0)
00120 {
00121 mViewHandle.init();
00122 sViewHandleMap[mViewHandle] = this;
00123 }
00124
00125 LLView::LLView(const LLString& name, BOOL mouse_opaque) :
00126 mParentView(NULL),
00127 mName(name),
00128 mReshapeFlags(FOLLOWS_NONE),
00129 mDefaultTabGroup(0),
00130 mEnabled(TRUE),
00131 mMouseOpaque(mouse_opaque),
00132 mSoundFlags(MOUSE_UP),
00133 mSaveToXML(TRUE),
00134 mIsFocusRoot(FALSE),
00135 mLastVisible(TRUE),
00136 mSpanChildren(FALSE),
00137 mVisible(TRUE),
00138 mHidden(FALSE),
00139 mNextInsertionOrdinal(0)
00140 {
00141 mViewHandle.init();
00142 sViewHandleMap[mViewHandle] = this;
00143 }
00144
00145
00146 LLView::LLView(
00147 const LLString& name, const LLRect& rect, BOOL mouse_opaque, U32 reshape) :
00148 mParentView(NULL),
00149 mName(name),
00150 mRect(rect),
00151 mReshapeFlags(reshape),
00152 mDefaultTabGroup(0),
00153 mEnabled(TRUE),
00154 mMouseOpaque(mouse_opaque),
00155 mSoundFlags(MOUSE_UP),
00156 mSaveToXML(TRUE),
00157 mIsFocusRoot(FALSE),
00158 mLastVisible(TRUE),
00159 mSpanChildren(FALSE),
00160 mVisible(TRUE),
00161 mHidden(FALSE),
00162 mNextInsertionOrdinal(0)
00163 {
00164 mViewHandle.init();
00165 sViewHandleMap[mViewHandle] = this;
00166 }
00167
00168
00169 LLView::~LLView()
00170 {
00171
00172
00173 if( gFocusMgr.getKeyboardFocus() == this )
00174 {
00175 llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl;
00176 gFocusMgr.removeKeyboardFocusWithoutCallback( this );
00177 }
00178
00179 if( hasMouseCapture() )
00180 {
00181 llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl;
00182 gFocusMgr.removeMouseCaptureWithoutCallback( this );
00183 }
00184
00185 sViewHandleMap.erase(mViewHandle);
00186
00187 deleteAllChildren();
00188
00189 if (mParentView != NULL)
00190 {
00191 mParentView->removeChild(this);
00192 }
00193
00194 dispatch_list_t::iterator itor;
00195 for (itor = mDispatchList.begin(); itor != mDispatchList.end(); ++itor)
00196 {
00197 (*itor).second->clearDispatchers();
00198 }
00199
00200 std::for_each(mFloaterControls.begin(), mFloaterControls.end(),
00201 DeletePairedPointer());
00202 }
00203
00204
00205 BOOL LLView::isView()
00206 {
00207 return TRUE;
00208 }
00209
00210
00211 BOOL LLView::isCtrl() const
00212 {
00213 return FALSE;
00214 }
00215
00216
00217 BOOL LLView::isPanel()
00218 {
00219 return FALSE;
00220 }
00221
00222 void LLView::setMouseOpaque(BOOL b)
00223 {
00224 mMouseOpaque = b;
00225 }
00226
00227 void LLView::setToolTip(const LLString& msg)
00228 {
00229 mToolTipMsg = msg;
00230 }
00231
00232
00233 void LLView::setRect(const LLRect& rect)
00234 {
00235 mRect = rect;
00236 }
00237
00238
00239 void LLView::setFollows(U32 flags)
00240 {
00241 mReshapeFlags = flags;
00242 }
00243
00244 void LLView::setFollowsNone()
00245 {
00246 mReshapeFlags = FOLLOWS_NONE;
00247 }
00248
00249 void LLView::setFollowsLeft()
00250 {
00251 mReshapeFlags |= FOLLOWS_LEFT;
00252 }
00253
00254 void LLView::setFollowsTop()
00255 {
00256 mReshapeFlags |= FOLLOWS_TOP;
00257 }
00258
00259 void LLView::setFollowsRight()
00260 {
00261 mReshapeFlags |= FOLLOWS_RIGHT;
00262 }
00263
00264 void LLView::setFollowsBottom()
00265 {
00266 mReshapeFlags |= FOLLOWS_BOTTOM;
00267 }
00268
00269 void LLView::setFollowsAll()
00270 {
00271 mReshapeFlags |= FOLLOWS_ALL;
00272 }
00273
00274 void LLView::setSoundFlags(U8 flags)
00275 {
00276 mSoundFlags = flags;
00277 }
00278
00279 void LLView::setName(LLString name)
00280 {
00281 mName = name;
00282 }
00283
00284 void LLView::setSpanChildren( BOOL span_children )
00285 {
00286 mSpanChildren = span_children; updateRect();
00287 }
00288
00289 const LLString& LLView::getToolTip()
00290 {
00291 return mToolTipMsg;
00292 }
00293
00294
00295 const LLString& LLView::getName() const
00296 {
00297 static const LLString unnamed("(no name)");
00298 return mName.empty() ? unnamed : mName;
00299 }
00300
00301 void LLView::sendChildToFront(LLView* child)
00302 {
00303 if (child->mParentView == this)
00304 {
00305 mChildList.remove( child );
00306 mChildList.push_front(child);
00307 }
00308 }
00309
00310 void LLView::sendChildToBack(LLView* child)
00311 {
00312 if (child->mParentView == this)
00313 {
00314 mChildList.remove( child );
00315 mChildList.push_back(child);
00316 }
00317 }
00318
00319 void LLView::moveChildToFrontOfTabGroup(LLUICtrl* child)
00320 {
00321 if(mCtrlOrder.find(child) != mCtrlOrder.end())
00322 {
00323 mCtrlOrder[child].second = -1 * mNextInsertionOrdinal++;
00324 }
00325 }
00326
00327 void LLView::addChild(LLView* child, S32 tab_group)
00328 {
00329 if (mParentView == child)
00330 {
00331 llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
00332 }
00333
00334 if (child->mParentView)
00335 {
00336 child->mParentView->removeChild(child);
00337 }
00338
00339
00340 mChildList.push_front(child);
00341
00342
00343 if (child->isCtrl())
00344 {
00345
00346 addCtrlAtEnd((LLUICtrl*) child, tab_group);
00347 }
00348
00349 child->mParentView = this;
00350 updateRect();
00351 }
00352
00353
00354 void LLView::addChildAtEnd(LLView* child, S32 tab_group)
00355 {
00356 if (mParentView == child)
00357 {
00358 llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
00359 }
00360
00361 if (child->mParentView)
00362 {
00363 child->mParentView->removeChild(child);
00364 }
00365
00366
00367 mChildList.push_back(child);
00368
00369
00370 if (child->isCtrl())
00371 {
00372
00373 addCtrl((LLUICtrl*) child, tab_group);
00374 }
00375
00376 child->mParentView = this;
00377 updateRect();
00378 }
00379
00380
00381 void LLView::removeChild(LLView* child, BOOL deleteIt)
00382 {
00383 if (child->mParentView == this)
00384 {
00385 mChildList.remove( child );
00386 child->mParentView = NULL;
00387 if (child->isCtrl())
00388 {
00389 removeCtrl((LLUICtrl*)child);
00390 }
00391 if (deleteIt)
00392 {
00393 delete child;
00394 }
00395 }
00396 else
00397 {
00398 llerrs << "LLView::removeChild called with non-child" << llendl;
00399 }
00400 }
00401
00402 void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group)
00403 {
00404 mCtrlOrder.insert(tab_order_pair_t(ctrl,
00405 tab_order_t(tab_group, mNextInsertionOrdinal++)));
00406 }
00407
00408 void LLView::addCtrl( LLUICtrl* ctrl, S32 tab_group)
00409 {
00410
00411 mCtrlOrder.insert(tab_order_pair_t(ctrl,
00412 tab_order_t(tab_group, -1 * mNextInsertionOrdinal++)));
00413 }
00414
00415 void LLView::removeCtrl(LLUICtrl* ctrl)
00416 {
00417 child_tab_order_t::iterator found = mCtrlOrder.find(ctrl);
00418 if(found != mCtrlOrder.end())
00419 {
00420 mCtrlOrder.erase(found);
00421 }
00422 }
00423
00424 S32 LLView::getDefaultTabGroup() const { return mDefaultTabGroup; }
00425
00426 LLView::ctrl_list_t LLView::getCtrlList() const
00427 {
00428 ctrl_list_t controls;
00429 for(child_list_const_iter_t iter = mChildList.begin();
00430 iter != mChildList.end();
00431 iter++)
00432 {
00433 if((*iter)->isCtrl())
00434 {
00435 controls.push_back(static_cast<LLUICtrl*>(*iter));
00436 }
00437 }
00438 return controls;
00439 }
00440
00441 LLView::ctrl_list_t LLView::getCtrlListSorted() const
00442 {
00443 ctrl_list_t controls = getCtrlList();
00444 std::sort(controls.begin(), controls.end(), LLCompareByTabOrder(mCtrlOrder));
00445 return controls;
00446 }
00447
00448 LLCompareByTabOrder::LLCompareByTabOrder(LLView::child_tab_order_t order): mTabOrder(order) {}
00449
00450 bool LLCompareByTabOrder::compareTabOrders(const LLView::tab_order_t & a, const LLView::tab_order_t & b) const
00451 {
00452 return a < b;
00453 }
00454
00455
00456
00457
00458 bool LLCompareByTabOrder::operator() (const LLView* const a, const LLView* const b) const
00459 {
00460 S32 a_score = 0, b_score = 0;
00461 if(a) a_score--;
00462 if(b) b_score--;
00463 if(a && a->isCtrl()) a_score--;
00464 if(b && b->isCtrl()) b_score--;
00465 if(a_score == -2 && b_score == -2)
00466 {
00467 const LLUICtrl * const a_ctrl = static_cast<const LLUICtrl*>(a);
00468 const LLUICtrl * const b_ctrl = static_cast<const LLUICtrl*>(b);
00469 LLView::child_tab_order_const_iter_t a_found = mTabOrder.find(a_ctrl), b_found = mTabOrder.find(b_ctrl);
00470 if(a_found != mTabOrder.end()) a_score--;
00471 if(b_found != mTabOrder.end()) b_score--;
00472 if(a_score == -3 && b_score == -3)
00473 {
00474
00475 return compareTabOrders(a_found->second, b_found->second);
00476 }
00477 }
00478 return (a_score == b_score) ? a < b : a_score < b_score;
00479 }
00480
00481 BOOL LLView::isInVisibleChain() const
00482 {
00483 const LLView* cur_view = this;
00484 while(cur_view)
00485 {
00486 if (!cur_view->getVisible())
00487 {
00488 return FALSE;
00489 }
00490 cur_view = cur_view->getParent();
00491 }
00492 return TRUE;
00493 }
00494
00495 BOOL LLView::isInEnabledChain() const
00496 {
00497 const LLView* cur_view = this;
00498 while(cur_view)
00499 {
00500 if (!cur_view->getEnabled())
00501 {
00502 return FALSE;
00503 }
00504 cur_view = cur_view->getParent();
00505 }
00506 return TRUE;
00507 }
00508
00509 BOOL LLView::isFocusRoot() const
00510 {
00511 return mIsFocusRoot;
00512 }
00513
00514 LLView* LLView::findRootMostFocusRoot()
00515 {
00516 LLView* focus_root = NULL;
00517 LLView* next_view = this;
00518 while(next_view)
00519 {
00520 if (next_view->isFocusRoot())
00521 {
00522 focus_root = next_view;
00523 }
00524 next_view = next_view->getParent();
00525 }
00526 return focus_root;
00527 }
00528
00529 BOOL LLView::canFocusChildren() const
00530 {
00531 return TRUE;
00532 }
00533
00534 BOOL LLView::focusNextRoot()
00535 {
00536 LLView::child_list_t result = LLView::getFocusRootsQuery().run(this);
00537 return LLView::focusNext(result);
00538 }
00539
00540 BOOL LLView::focusPrevRoot()
00541 {
00542 LLView::child_list_t result = LLView::getFocusRootsQuery().run(this);
00543 return LLView::focusPrev(result);
00544 }
00545
00546 BOOL LLView::focusNextItem(BOOL text_fields_only)
00547 {
00548
00549 LLCtrlQuery query = LLView::getTabOrderQuery();
00550 if(text_fields_only || LLUI::sConfigGroup->getBOOL("TabToTextFieldsOnly"))
00551 {
00552 query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
00553 }
00554 LLView::child_list_t result = query(this);
00555 return LLView::focusNext(result);
00556 }
00557
00558 BOOL LLView::focusPrevItem(BOOL text_fields_only)
00559 {
00560
00561 LLCtrlQuery query = LLView::getTabOrderQuery();
00562 if(text_fields_only || LLUI::sConfigGroup->getBOOL("TabToTextFieldsOnly"))
00563 {
00564 query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
00565 }
00566 LLView::child_list_t result = query(this);
00567 return LLView::focusPrev(result);
00568 }
00569
00570
00571
00572 BOOL LLView::focusNext(LLView::child_list_t & result)
00573 {
00574 LLView::child_list_iter_t focused = result.end();
00575 for(LLView::child_list_iter_t iter = result.begin();
00576 iter != result.end();
00577 ++iter)
00578 {
00579 if(gFocusMgr.childHasKeyboardFocus(*iter))
00580 {
00581 focused = iter;
00582 break;
00583 }
00584 }
00585 LLView::child_list_iter_t next = focused;
00586 next = (next == result.end()) ? result.begin() : ++next;
00587 while(next != focused)
00588 {
00589
00590 if(next == result.end())
00591 {
00592 next = result.begin();
00593 }
00594 if((*next)->isCtrl())
00595 {
00596 LLUICtrl * ctrl = static_cast<LLUICtrl*>(*next);
00597 ctrl->setFocus(TRUE);
00598 ctrl->onTabInto();
00599 gFocusMgr.triggerFocusFlash();
00600 return TRUE;
00601 }
00602 ++next;
00603 }
00604 return FALSE;
00605 }
00606
00607
00608 BOOL LLView::focusPrev(LLView::child_list_t & result)
00609 {
00610 LLView::child_list_reverse_iter_t focused = result.rend();
00611 for(LLView::child_list_reverse_iter_t iter = result.rbegin();
00612 iter != result.rend();
00613 ++iter)
00614 {
00615 if(gFocusMgr.childHasKeyboardFocus(*iter))
00616 {
00617 focused = iter;
00618 break;
00619 }
00620 }
00621 LLView::child_list_reverse_iter_t next = focused;
00622 next = (next == result.rend()) ? result.rbegin() : ++next;
00623 while(next != focused)
00624 {
00625
00626 if(next == result.rend())
00627 {
00628 next = result.rbegin();
00629 }
00630 if((*next)->isCtrl())
00631 {
00632 LLUICtrl * ctrl = static_cast<LLUICtrl*>(*next);
00633 if (!ctrl->hasFocus())
00634 {
00635 ctrl->setFocus(TRUE);
00636 ctrl->onTabInto();
00637 gFocusMgr.triggerFocusFlash();
00638 }
00639 return TRUE;
00640 }
00641 ++next;
00642 }
00643 return FALSE;
00644 }
00645
00646 BOOL LLView::focusFirstItem(BOOL prefer_text_fields)
00647 {
00648
00649 if(prefer_text_fields)
00650 {
00651 LLCtrlQuery query = LLView::getTabOrderQuery();
00652 query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
00653 LLView::child_list_t result = query(this);
00654 if(result.size() > 0)
00655 {
00656 LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front());
00657 if(!ctrl->hasFocus())
00658 {
00659 ctrl->setFocus(TRUE);
00660 ctrl->onTabInto();
00661 gFocusMgr.triggerFocusFlash();
00662 }
00663 return TRUE;
00664 }
00665 }
00666
00667 LLView::child_list_t result = LLView::getTabOrderQuery().run(this);
00668 if(result.size() > 0)
00669 {
00670 LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front());
00671 if(!ctrl->hasFocus())
00672 {
00673 ctrl->setFocus(TRUE);
00674 ctrl->onTabInto();
00675 gFocusMgr.triggerFocusFlash();
00676 }
00677 return TRUE;
00678 }
00679 return FALSE;
00680 }
00681
00682 BOOL LLView::focusLastItem(BOOL prefer_text_fields)
00683 {
00684
00685 if(prefer_text_fields)
00686 {
00687 LLCtrlQuery query = LLView::getTabOrderQuery();
00688 query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
00689 LLView::child_list_t result = query(this);
00690 if(result.size() > 0)
00691 {
00692 LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.back());
00693 if(!ctrl->hasFocus())
00694 {
00695 ctrl->setFocus(TRUE);
00696 ctrl->onTabInto();
00697 gFocusMgr.triggerFocusFlash();
00698 }
00699 return TRUE;
00700 }
00701 }
00702
00703 LLView::child_list_t result = LLView::getTabOrderQuery().run(this);
00704 if(result.size() > 0)
00705 {
00706 LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.back());
00707 if(!ctrl->hasFocus())
00708 {
00709 ctrl->setFocus(TRUE);
00710 ctrl->onTabInto();
00711 gFocusMgr.triggerFocusFlash();
00712 }
00713 return TRUE;
00714 }
00715 return FALSE;
00716 }
00717
00718
00719
00720
00721
00722
00723 void LLView::deleteAllChildren()
00724 {
00725
00726 mCtrlOrder.clear();
00727
00728 while (!mChildList.empty())
00729 {
00730 LLView* viewp = mChildList.front();
00731 delete viewp;
00732 }
00733 }
00734
00735 void LLView::setAllChildrenEnabled(BOOL b)
00736 {
00737 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
00738 {
00739 LLView* viewp = *child_it;
00740 viewp->setEnabled(b);
00741 }
00742 }
00743
00744
00745 void LLView::setTentative(BOOL b)
00746 {
00747 }
00748
00749
00750 BOOL LLView::getTentative() const
00751 {
00752 return FALSE;
00753 }
00754
00755
00756 void LLView::setEnabled(BOOL enabled)
00757 {
00758 mEnabled = enabled;
00759 }
00760
00761
00762 void LLView::setVisible(BOOL visible)
00763 {
00764 if ( mVisible != visible )
00765 {
00766 if( !visible && (gFocusMgr.getTopCtrl() == this) )
00767 {
00768 gFocusMgr.setTopCtrl( NULL );
00769 }
00770
00771 mVisible = visible;
00772
00773
00774 if (!getParent() || getParent()->isInVisibleChain())
00775 {
00776
00777 onVisibilityChange( visible );
00778 }
00779 }
00780 }
00781
00782
00783 void LLView::setHidden(BOOL hidden)
00784 {
00785 mHidden = hidden;
00786 }
00787
00788
00789 BOOL LLView::setLabelArg(const LLString& key, const LLStringExplicit& text)
00790 {
00791 return FALSE;
00792 }
00793
00794
00795 void LLView::onVisibilityChange ( BOOL new_visibility )
00796 {
00797 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
00798 {
00799 LLView* viewp = *child_it;
00800
00801 if (viewp->getVisible())
00802 {
00803 viewp->onVisibilityChange ( new_visibility );
00804 }
00805 }
00806 }
00807
00808
00809 void LLView::translate(S32 x, S32 y)
00810 {
00811 mRect.translate(x, y);
00812 }
00813
00814
00815 BOOL LLView::canSnapTo(LLView* other_view)
00816 {
00817 return other_view->getVisible();
00818 }
00819
00820
00821 void LLView::snappedTo(LLView* snap_view)
00822 {
00823 }
00824
00825 BOOL LLView::handleHover(S32 x, S32 y, MASK mask)
00826 {
00827 BOOL handled = childrenHandleHover( x, y, mask ) != NULL;
00828 if( !handled && mMouseOpaque && pointInView( x, y ) )
00829 {
00830 LLUI::sWindow->setCursor(UI_CURSOR_ARROW);
00831 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
00832 handled = TRUE;
00833 }
00834
00835 return handled;
00836 }
00837
00838 LLString LLView::getShowNamesToolTip()
00839 {
00840 LLView* view = getParent();
00841 LLString name;
00842 LLString tool_tip = mName;
00843
00844 while (view)
00845 {
00846 name = view->getName();
00847
00848 if (name == "root") break;
00849
00850 if (view->getToolTip().find(".xml") != LLString::npos)
00851 {
00852 tool_tip = view->getToolTip() + "/" + tool_tip;
00853 break;
00854 }
00855 else
00856 {
00857 tool_tip = view->getName() + "/" + tool_tip;
00858 }
00859
00860 view = view->getParent();
00861 }
00862
00863 return "/" + tool_tip;
00864 }
00865
00866
00867 BOOL LLView::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
00868 {
00869 BOOL handled = FALSE;
00870
00871 LLString tool_tip;
00872
00873 if ( getVisible() && getEnabled())
00874 {
00875 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
00876 {
00877 LLView* viewp = *child_it;
00878 S32 local_x = x - viewp->mRect.mLeft;
00879 S32 local_y = y - viewp->mRect.mBottom;
00880 if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
00881 {
00882 handled = TRUE;
00883 break;
00884 }
00885 }
00886
00887 if (LLUI::sShowXUINames && (mToolTipMsg.find(".xml", 0) == LLString::npos) &&
00888 (mName.find("Drag", 0) == LLString::npos))
00889 {
00890 tool_tip = getShowNamesToolTip();
00891 }
00892 else
00893 {
00894 tool_tip = mToolTipMsg;
00895 }
00896
00897
00898
00899 BOOL showNamesTextBox = LLUI::sShowXUINames && (getWidgetType() == WIDGET_TYPE_TEXT_BOX);
00900
00901 if( !handled && (mMouseOpaque || showNamesTextBox) && pointInView( x, y ) && !tool_tip.empty())
00902 {
00903
00904 msg = tool_tip;
00905
00906
00907 localPointToScreen(
00908 0, 0,
00909 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
00910 localPointToScreen(
00911 mRect.getWidth(), mRect.getHeight(),
00912 &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
00913
00914 handled = TRUE;
00915 }
00916 }
00917
00918 return handled;
00919 }
00920
00921 BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
00922 {
00923 BOOL handled = FALSE;
00924
00925 if( called_from_parent )
00926 {
00927
00928 if (getVisible() && mEnabled)
00929 {
00930 handled = childrenHandleKey( key, mask ) != NULL;
00931 }
00932 }
00933
00934
00935
00936 if (!handled && getVisible())
00937 {
00938 handled = handleKeyHere( key, mask, called_from_parent );
00939 if (handled && LLView::sDebugKeys)
00940 {
00941 llinfos << "Key handled by " << getName() << llendl;
00942 }
00943 }
00944
00945 if( !handled && !called_from_parent)
00946 {
00947 if (mIsFocusRoot)
00948 {
00949
00950 handled = FALSE;
00951 }
00952 else if (mParentView)
00953 {
00954
00955 handled = mParentView->handleKey( key, mask, FALSE );
00956 }
00957 }
00958 return handled;
00959 }
00960
00961
00962
00963 BOOL LLView::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
00964 {
00965 return FALSE;
00966 }
00967
00968 BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
00969 {
00970 BOOL handled = FALSE;
00971
00972 if( called_from_parent )
00973 {
00974
00975 if (getVisible() && mEnabled)
00976 {
00977 handled = childrenHandleUnicodeChar( uni_char ) != NULL;
00978 }
00979 }
00980
00981 if (!handled && getVisible())
00982 {
00983 handled = handleUnicodeCharHere(uni_char, called_from_parent);
00984 if (handled && LLView::sDebugKeys)
00985 {
00986 llinfos << "Unicode key handled by " << getName() << llendl;
00987 }
00988 }
00989
00990
00991 if (!handled && !called_from_parent)
00992 {
00993 if (mIsFocusRoot)
00994 {
00995
00996 handled = FALSE;
00997 }
00998 else if(mParentView)
00999 {
01000
01001 handled = mParentView->handleUnicodeChar(uni_char, FALSE);
01002 }
01003 }
01004
01005 return handled;
01006 }
01007
01008
01009 BOOL LLView::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent )
01010 {
01011 return FALSE;
01012 }
01013
01014
01015 BOOL LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
01016 EDragAndDropType cargo_type, void* cargo_data,
01017 EAcceptance* accept,
01018 LLString& tooltip_msg)
01019 {
01020
01021 BOOL handled = childrenHandleDragAndDrop( x, y, mask, drop,
01022 cargo_type,
01023 cargo_data,
01024 accept,
01025 tooltip_msg) != NULL;
01026 if( !handled && mMouseOpaque )
01027 {
01028 *accept = ACCEPT_NO;
01029 handled = TRUE;
01030 lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLView " << getName() << llendl;
01031 }
01032
01033 return handled;
01034 }
01035
01036 LLView* LLView::childrenHandleDragAndDrop(S32 x, S32 y, MASK mask,
01037 BOOL drop,
01038 EDragAndDropType cargo_type,
01039 void* cargo_data,
01040 EAcceptance* accept,
01041 LLString& tooltip_msg)
01042 {
01043 LLView* handled_view = FALSE;
01044
01045 if( getVisible() )
01046
01047 {
01048 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01049 {
01050 LLView* viewp = *child_it;
01051 S32 local_x = x - viewp->mRect.mLeft;
01052 S32 local_y = y - viewp->mRect.mBottom;
01053 if( viewp->pointInView(local_x, local_y) &&
01054 viewp->getVisible() &&
01055 viewp->mEnabled &&
01056 viewp->handleDragAndDrop(local_x, local_y, mask, drop,
01057 cargo_type,
01058 cargo_data,
01059 accept,
01060 tooltip_msg))
01061 {
01062 handled_view = viewp;
01063 break;
01064 }
01065 }
01066 }
01067 return handled_view;
01068 }
01069
01070 void LLView::onMouseCaptureLost()
01071 {
01072 }
01073
01074 BOOL LLView::hasMouseCapture()
01075 {
01076 return gFocusMgr.getMouseCapture() == this;
01077 }
01078
01079 BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask)
01080 {
01081 BOOL handled = childrenHandleMouseUp( x, y, mask ) != NULL;
01082 if( !handled && mMouseOpaque )
01083 {
01084 handled = TRUE;
01085 }
01086 return handled;
01087 }
01088
01089 BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask)
01090 {
01091 LLView* handled_view = childrenHandleMouseDown( x, y, mask );
01092 BOOL handled = (handled_view != NULL);
01093 if( !handled && mMouseOpaque )
01094 {
01095 handled = TRUE;
01096 handled_view = this;
01097 }
01098
01099
01100 if (sEditingUI && handled_view)
01101 {
01102
01103 EWidgetType type = handled_view->getWidgetType();
01104 if (type == WIDGET_TYPE_BUTTON
01105 || type == WIDGET_TYPE_LINE_EDITOR
01106 || type == WIDGET_TYPE_TEXT_EDITOR
01107 || type == WIDGET_TYPE_TEXT_BOX)
01108 {
01109 sEditingUIView = handled_view;
01110 }
01111 }
01112
01113 return handled;
01114 }
01115
01116 BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask)
01117 {
01118 BOOL handled = childrenHandleDoubleClick( x, y, mask ) != NULL;
01119 if( !handled && mMouseOpaque )
01120 {
01121 handleMouseDown(x, y, mask);
01122 handled = TRUE;
01123 }
01124 return handled;
01125 }
01126
01127 BOOL LLView::handleScrollWheel(S32 x, S32 y, S32 clicks)
01128 {
01129 BOOL handled = FALSE;
01130 if( getVisible() && mEnabled )
01131 {
01132 handled = childrenHandleScrollWheel( x, y, clicks ) != NULL;
01133 if( !handled && mMouseOpaque )
01134 {
01135 handled = TRUE;
01136 }
01137 }
01138 return handled;
01139 }
01140
01141 BOOL LLView::handleRightMouseDown(S32 x, S32 y, MASK mask)
01142 {
01143 BOOL handled = childrenHandleRightMouseDown( x, y, mask ) != NULL;
01144 if( !handled && mMouseOpaque )
01145 {
01146 handled = TRUE;
01147 }
01148 return handled;
01149 }
01150
01151 BOOL LLView::handleRightMouseUp(S32 x, S32 y, MASK mask)
01152 {
01153 BOOL handled = childrenHandleRightMouseUp( x, y, mask ) != NULL;
01154 if( !handled && mMouseOpaque )
01155 {
01156 handled = TRUE;
01157 }
01158 return handled;
01159 }
01160
01161 LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
01162 {
01163 LLView* handled_view = NULL;
01164 if (getVisible() && mEnabled )
01165 {
01166 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01167 {
01168 LLView* viewp = *child_it;
01169 S32 local_x = x - viewp->mRect.mLeft;
01170 S32 local_y = y - viewp->mRect.mBottom;
01171 if (viewp->pointInView(local_x, local_y) &&
01172 viewp->handleScrollWheel( local_x, local_y, clicks ))
01173 {
01174 if (sDebugMouseHandling)
01175 {
01176 sMouseHandlerMessage = LLString("->") + viewp->mName.c_str() + sMouseHandlerMessage;
01177 }
01178
01179 handled_view = viewp;
01180 break;
01181 }
01182 }
01183 }
01184 return handled_view;
01185 }
01186
01187 LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
01188 {
01189 LLView* handled_view = NULL;
01190 if (getVisible() && mEnabled )
01191 {
01192 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01193 {
01194 LLView* viewp = *child_it;
01195 S32 local_x = x - viewp->mRect.mLeft;
01196 S32 local_y = y - viewp->mRect.mBottom;
01197 if(viewp->pointInView(local_x, local_y) &&
01198 viewp->getVisible() &&
01199 viewp->getEnabled() &&
01200 viewp->handleHover(local_x, local_y, mask) )
01201 {
01202 if (sDebugMouseHandling)
01203 {
01204 sMouseHandlerMessage = LLString("->") + viewp->mName.c_str() + sMouseHandlerMessage;
01205 }
01206
01207 handled_view = viewp;
01208 break;
01209 }
01210 }
01211 }
01212 return handled_view;
01213 }
01214
01215
01216 LLView* LLView::childrenHandleKey(KEY key, MASK mask)
01217 {
01218 LLView* handled_view = NULL;
01219
01220 if ( getVisible() && mEnabled )
01221 {
01222 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01223 {
01224 LLView* viewp = *child_it;
01225 if (viewp->handleKey(key, mask, TRUE))
01226 {
01227 if (LLView::sDebugKeys)
01228 {
01229 llinfos << "Key handled by " << viewp->getName() << llendl;
01230 }
01231 handled_view = viewp;
01232 break;
01233 }
01234 }
01235 }
01236
01237 return handled_view;
01238 }
01239
01240
01241 LLView* LLView::childrenHandleUnicodeChar(llwchar uni_char)
01242 {
01243 LLView* handled_view = NULL;
01244
01245 if ( getVisible() && mEnabled )
01246 {
01247 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01248 {
01249 LLView* viewp = *child_it;
01250 if (viewp->handleUnicodeChar(uni_char, TRUE))
01251 {
01252 if (LLView::sDebugKeys)
01253 {
01254 llinfos << "Unicode character handled by " << viewp->getName() << llendl;
01255 }
01256 handled_view = viewp;
01257 break;
01258 }
01259 }
01260 }
01261
01262 return handled_view;
01263 }
01264
01265 LLView* LLView::childrenHandleMouseDown(S32 x, S32 y, MASK mask)
01266 {
01267 LLView* handled_view = NULL;
01268
01269 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01270 {
01271 LLView* viewp = *child_it;
01272 S32 local_x = x - viewp->mRect.mLeft;
01273 S32 local_y = y - viewp->mRect.mBottom;
01274
01275 if (viewp->pointInView(local_x, local_y) &&
01276 viewp->getVisible() &&
01277 viewp->mEnabled &&
01278 viewp->handleMouseDown( local_x, local_y, mask ))
01279 {
01280 if (sDebugMouseHandling)
01281 {
01282 sMouseHandlerMessage = LLString("->") + viewp->mName.c_str() + sMouseHandlerMessage;
01283 }
01284 handled_view = viewp;
01285 break;
01286 }
01287 }
01288 return handled_view;
01289 }
01290
01291 LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask)
01292 {
01293 LLView* handled_view = NULL;
01294
01295 if (getVisible() && mEnabled )
01296 {
01297 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01298 {
01299 LLView* viewp = *child_it;
01300 S32 local_x = x - viewp->mRect.mLeft;
01301 S32 local_y = y - viewp->mRect.mBottom;
01302 if (viewp->pointInView(local_x, local_y) &&
01303 viewp->getVisible() &&
01304 viewp->mEnabled &&
01305 viewp->handleRightMouseDown( local_x, local_y, mask ))
01306 {
01307 if (sDebugMouseHandling)
01308 {
01309 sMouseHandlerMessage = LLString("->") + viewp->mName.c_str() + sMouseHandlerMessage;
01310 }
01311 handled_view = viewp;
01312 break;
01313 }
01314 }
01315 }
01316 return handled_view;
01317 }
01318
01319 LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)
01320 {
01321 LLView* handled_view = NULL;
01322
01323 if (getVisible() && mEnabled )
01324 {
01325 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01326 {
01327 LLView* viewp = *child_it;
01328 S32 local_x = x - viewp->mRect.mLeft;
01329 S32 local_y = y - viewp->mRect.mBottom;
01330 if (viewp->pointInView(local_x, local_y) &&
01331 viewp->getVisible() &&
01332 viewp->mEnabled &&
01333 viewp->handleDoubleClick( local_x, local_y, mask ))
01334 {
01335 if (sDebugMouseHandling)
01336 {
01337 sMouseHandlerMessage = LLString("->") + viewp->mName.c_str() + sMouseHandlerMessage;
01338 }
01339 handled_view = viewp;
01340 break;
01341 }
01342 }
01343 }
01344 return handled_view;
01345 }
01346
01347 LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)
01348 {
01349 LLView* handled_view = NULL;
01350 if( getVisible() && mEnabled )
01351 {
01352 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01353 {
01354 LLView* viewp = *child_it;
01355 S32 local_x = x - viewp->mRect.mLeft;
01356 S32 local_y = y - viewp->mRect.mBottom;
01357 if (!viewp->pointInView(local_x, local_y))
01358 continue;
01359 if (!viewp->getVisible())
01360 continue;
01361 if (!viewp->mEnabled)
01362 continue;
01363 if (viewp->handleMouseUp( local_x, local_y, mask ))
01364 {
01365 if (sDebugMouseHandling)
01366 {
01367 sMouseHandlerMessage = LLString("->") + viewp->mName.c_str() + sMouseHandlerMessage;
01368 }
01369 handled_view = viewp;
01370 break;
01371 }
01372 }
01373 }
01374 return handled_view;
01375 }
01376
01377 LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
01378 {
01379 LLView* handled_view = NULL;
01380 if( getVisible() && mEnabled )
01381 {
01382 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01383 {
01384 LLView* viewp = *child_it;
01385 S32 local_x = x - viewp->mRect.mLeft;
01386 S32 local_y = y - viewp->mRect.mBottom;
01387 if (viewp->pointInView(local_x, local_y) &&
01388 viewp->getVisible() &&
01389 viewp->mEnabled &&
01390 viewp->handleRightMouseUp( local_x, local_y, mask ))
01391 {
01392 if (sDebugMouseHandling)
01393 {
01394 sMouseHandlerMessage = LLString("->") + viewp->mName.c_str() + sMouseHandlerMessage;
01395 }
01396 handled_view = viewp;
01397 break;
01398 }
01399 }
01400 }
01401 return handled_view;
01402 }
01403
01404
01405 void LLView::draw()
01406 {
01407 if (sDebugRects)
01408 {
01409 drawDebugRect();
01410
01411
01412 if (mRect.mRight <= mRect.mLeft
01413 || mRect.mTop <= mRect.mBottom)
01414 {
01415 llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
01416 }
01417 }
01418
01419 LLRect rootRect = getRootView()->getRect();
01420 LLRect screenRect;
01421
01422
01423 LLView* focus_view = gFocusMgr.getKeyboardFocus();
01424 if (focus_view && focus_view->getParent() != this)
01425 {
01426 focus_view = NULL;
01427 }
01428
01429 for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
01430 {
01431 LLView *viewp = *child_iter;
01432 ++sDepth;
01433
01434 if (viewp->getVisible() && viewp != focus_view)
01435 {
01436
01437 localRectToScreen(viewp->getRect(),&screenRect);
01438 if ( rootRect.rectInRect(&screenRect) )
01439 {
01440 glMatrixMode(GL_MODELVIEW);
01441 LLUI::pushMatrix();
01442 {
01443 LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
01444 viewp->draw();
01445 }
01446 LLUI::popMatrix();
01447 }
01448 }
01449
01450 --sDepth;
01451 }
01452
01453 if (focus_view && focus_view->getVisible())
01454 {
01455 drawChild(focus_view);
01456 }
01457
01458
01459 if (sEditingUI && this == sEditingUIView)
01460 {
01461 drawDebugRect();
01462 }
01463 }
01464
01465
01466 void LLView::drawDebugRect()
01467 {
01468
01469 LLGLSNoTexture no_texture;
01470
01471
01472 LLColor4 border_color(0.f, 0.f, 0.f, 1.f);
01473 if (sEditingUI)
01474 {
01475 border_color.mV[0] = 1.f;
01476 }
01477 else
01478 {
01479 border_color.mV[sDepth%3] = 1.f;
01480 }
01481
01482 glColor4fv( border_color.mV );
01483
01484 glBegin(GL_LINES);
01485 glVertex2i(0, mRect.getHeight() - 1);
01486 glVertex2i(0, 0);
01487
01488 glVertex2i(0, 0);
01489 glVertex2i(mRect.getWidth() - 1, 0);
01490
01491 glVertex2i(mRect.getWidth() - 1, 0);
01492 glVertex2i(mRect.getWidth() - 1, mRect.getHeight() - 1);
01493
01494 glVertex2i(mRect.getWidth() - 1, mRect.getHeight() - 1);
01495 glVertex2i(0, mRect.getHeight() - 1);
01496 glEnd();
01497
01498
01499 if (mChildList.size() && !sEditingUI)
01500 {
01501
01502 S32 x, y;
01503 glColor4fv( border_color.mV );
01504 x = mRect.getWidth()/2;
01505 y = mRect.getHeight()/2;
01506 LLString debug_text = llformat("%s (%d x %d)", getName().c_str(),
01507 mRect.getWidth(), mRect.getHeight());
01508 LLFontGL::sSansSerifSmall->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color,
01509 LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL,
01510 S32_MAX, S32_MAX, NULL, FALSE);
01511 }
01512 }
01513
01514 void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_draw)
01515 {
01516 if (childp && childp->getParent() == this)
01517 {
01518 ++sDepth;
01519
01520 if (childp->getVisible() || force_draw)
01521 {
01522 glMatrixMode(GL_MODELVIEW);
01523 LLUI::pushMatrix();
01524 {
01525 LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset, 0.f);
01526 childp->draw();
01527 }
01528 LLUI::popMatrix();
01529 }
01530
01531 --sDepth;
01532 }
01533 }
01534
01535
01536 void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
01537 {
01538
01539 updateRect();
01540
01541
01542 S32 delta_width = width - mRect.getWidth();
01543 S32 delta_height = height - mRect.getHeight();
01544
01545 if (delta_width || delta_height || sForceReshape)
01546 {
01547
01548 mRect.mRight = mRect.mLeft + width;
01549 mRect.mTop = mRect.mBottom + height;
01550
01551
01552 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01553 {
01554 LLView* viewp = *child_it;
01555 LLRect child_rect( viewp->mRect );
01556
01557 if (viewp->followsRight() && viewp->followsLeft())
01558 {
01559 child_rect.mRight += delta_width;
01560 }
01561 else if (viewp->followsRight())
01562 {
01563 child_rect.mLeft += delta_width;
01564 child_rect.mRight += delta_width;
01565 }
01566 else if (viewp->followsLeft())
01567 {
01568
01569 }
01570 else
01571 {
01572
01573
01574 }
01575
01576 if (viewp->followsTop() && viewp->followsBottom())
01577 {
01578 child_rect.mTop += delta_height;
01579 }
01580 else if (viewp->followsTop())
01581 {
01582 child_rect.mTop += delta_height;
01583 child_rect.mBottom += delta_height;
01584 }
01585 else if (viewp->followsBottom())
01586 {
01587
01588 }
01589 else
01590 {
01591
01592
01593 }
01594
01595 S32 delta_x = child_rect.mLeft - viewp->mRect.mLeft;
01596 S32 delta_y = child_rect.mBottom - viewp->mRect.mBottom;
01597 viewp->translate( delta_x, delta_y );
01598 viewp->reshape(child_rect.getWidth(), child_rect.getHeight());
01599 }
01600 }
01601
01602 if (!called_from_parent)
01603 {
01604 if (mParentView)
01605 {
01606 mParentView->reshape(mParentView->getRect().getWidth(), mParentView->getRect().getHeight(), FALSE);
01607 }
01608 }
01609 }
01610
01611 LLRect LLView::getRequiredRect()
01612 {
01613 return mRect;
01614 }
01615
01616 const LLRect LLView::getScreenRect() const
01617 {
01618
01619 LLRect screen_rect;
01620 localPointToScreen(0, 0, &screen_rect.mLeft, &screen_rect.mBottom);
01621 localPointToScreen(mRect.getWidth(), mRect.getHeight(), &screen_rect.mRight, &screen_rect.mTop);
01622 return screen_rect;
01623 }
01624
01625 const LLRect LLView::getLocalRect() const
01626 {
01627 LLRect local_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
01628 return local_rect;
01629 }
01630
01631 const LLRect LLView::getLocalSnapRect() const
01632 {
01633 LLRect local_snap_rect = getSnapRect();
01634 local_snap_rect.translate(-mRect.mLeft, -mRect.mBottom);
01635 return local_snap_rect;
01636 }
01637
01638 void LLView::updateRect()
01639 {
01640 if (mSpanChildren && mChildList.size())
01641 {
01642 LLView* first_child = (*mChildList.begin());
01643 LLRect child_spanning_rect = first_child->mRect;
01644
01645 for ( child_list_iter_t child_it = ++mChildList.begin(); child_it != mChildList.end(); ++child_it)
01646 {
01647 LLView* viewp = *child_it;
01648 if (viewp->getVisible())
01649 {
01650 child_spanning_rect.unionWith(viewp->mRect);
01651 }
01652 }
01653
01654 S32 translate_x = llmin(0, child_spanning_rect.mLeft);
01655 S32 translate_y = llmin(0, child_spanning_rect.mBottom);
01656 S32 new_width = llmax(mRect.getWidth() + translate_x, child_spanning_rect.getWidth());
01657 S32 new_height = llmax(mRect.getHeight() + translate_y, child_spanning_rect.getHeight());
01658
01659 mRect.setOriginAndSize(mRect.mLeft + translate_x, mRect.mBottom + translate_y, new_width, new_height);
01660
01661 for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01662 {
01663 LLView* viewp = *child_it;
01664 viewp->mRect.translate(-translate_x, -translate_y);
01665 }
01666 }
01667 }
01668
01669 BOOL LLView::hasAncestor(LLView* parentp)
01670 {
01671 if (!parentp)
01672 {
01673 return FALSE;
01674 }
01675
01676 LLView* viewp = getParent();
01677 while(viewp)
01678 {
01679 if (viewp == parentp)
01680 {
01681 return TRUE;
01682 }
01683 viewp = viewp->getParent();
01684 }
01685
01686 return FALSE;
01687 }
01688
01689
01690
01691 BOOL LLView::childHasKeyboardFocus( const LLString& childname ) const
01692 {
01693 LLView *child = getChildByName(childname);
01694 if (child)
01695 {
01696 return gFocusMgr.childHasKeyboardFocus(child);
01697 }
01698 else
01699 {
01700 return FALSE;
01701 }
01702 }
01703
01704
01705
01706 BOOL LLView::hasChild(const LLString& childname, BOOL recurse) const
01707 {
01708 return getChildByName(childname, recurse) ? TRUE : FALSE;
01709 }
01710
01711
01712
01713
01714 LLView* LLView::getChildByName(const LLString& name, BOOL recurse) const
01715 {
01716 if(name.empty())
01717 return NULL;
01718 child_list_const_iter_t child_it;
01719
01720 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01721 {
01722 LLView* childp = *child_it;
01723 if (childp->getName() == name)
01724 {
01725 return childp;
01726 }
01727 }
01728 if (recurse)
01729 {
01730
01731 for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
01732 {
01733 LLView* childp = *child_it;
01734 LLView* viewp = childp->getChildByName(name, recurse);
01735 if ( viewp )
01736 {
01737 return viewp;
01738 }
01739 }
01740 }
01741 return NULL;
01742 }
01743
01744
01745 void LLView::onFocusLost()
01746 {
01747 }
01748
01749
01750 void LLView::onFocusReceived()
01751 {
01752 }
01753
01754
01755 void LLView::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const
01756 {
01757 *local_x = screen_x - mRect.mLeft;
01758 *local_y = screen_y - mRect.mBottom;
01759
01760 const LLView* cur = this;
01761 while( cur->mParentView )
01762 {
01763 cur = cur->mParentView;
01764 *local_x -= cur->mRect.mLeft;
01765 *local_y -= cur->mRect.mBottom;
01766 }
01767 }
01768
01769 void LLView::localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const
01770 {
01771 *screen_x = local_x + mRect.mLeft;
01772 *screen_y = local_y + mRect.mBottom;
01773
01774 const LLView* cur = this;
01775 while( cur->mParentView )
01776 {
01777 cur = cur->mParentView;
01778 *screen_x += cur->mRect.mLeft;
01779 *screen_y += cur->mRect.mBottom;
01780 }
01781 }
01782
01783 void LLView::screenRectToLocal(const LLRect& screen, LLRect* local) const
01784 {
01785 *local = screen;
01786 local->translate( -mRect.mLeft, -mRect.mBottom );
01787
01788 const LLView* cur = this;
01789 while( cur->mParentView )
01790 {
01791 cur = cur->mParentView;
01792 local->translate( -cur->mRect.mLeft, -cur->mRect.mBottom );
01793 }
01794 }
01795
01796 void LLView::localRectToScreen(const LLRect& local, LLRect* screen) const
01797 {
01798 *screen = local;
01799 screen->translate( mRect.mLeft, mRect.mBottom );
01800
01801 const LLView* cur = this;
01802 while( cur->mParentView )
01803 {
01804 cur = cur->mParentView;
01805 screen->translate( cur->mRect.mLeft, cur->mRect.mBottom );
01806 }
01807 }
01808
01809 LLView* LLView::getRootView()
01810 {
01811 LLView* view = this;
01812 while( view->mParentView )
01813 {
01814 view = view->mParentView;
01815 }
01816 return view;
01817 }
01818
01819
01820 LLWindow* LLView::getWindow(void)
01821 {
01822 return LLUI::sWindow;
01823 }
01824
01825
01826
01827
01828 BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside )
01829 {
01830 S32 delta_x = 0;
01831 S32 delta_y = 0;
01832
01833 if (allow_partial_outside)
01834 {
01835 const S32 KEEP_ONSCREEN_PIXELS = 16;
01836
01837 if( mRect.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft )
01838 {
01839 delta_x = constraint.mLeft - (mRect.mRight - KEEP_ONSCREEN_PIXELS);
01840 }
01841 else
01842 if( mRect.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
01843 {
01844 delta_x = constraint.mRight - (mRect.mLeft + KEEP_ONSCREEN_PIXELS);
01845 delta_x += llmax( 0, mRect.getWidth() - constraint.getWidth() );
01846 }
01847
01848 if( mRect.mTop > constraint.mTop )
01849 {
01850 delta_y = constraint.mTop - mRect.mTop;
01851 }
01852 else
01853 if( mRect.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
01854 {
01855 delta_y = constraint.mBottom - (mRect.mTop - KEEP_ONSCREEN_PIXELS);
01856 delta_y -= llmax( 0, mRect.getHeight() - constraint.getHeight() );
01857 }
01858 }
01859 else
01860 {
01861 if( mRect.mLeft < constraint.mLeft )
01862 {
01863 delta_x = constraint.mLeft - mRect.mLeft;
01864 }
01865 else
01866 if( mRect.mRight > constraint.mRight )
01867 {
01868 delta_x = constraint.mRight - mRect.mRight;
01869 delta_x += llmax( 0, mRect.getWidth() - constraint.getWidth() );
01870 }
01871
01872 if( mRect.mTop > constraint.mTop )
01873 {
01874 delta_y = constraint.mTop - mRect.mTop;
01875 }
01876 else
01877 if( mRect.mBottom < constraint.mBottom )
01878 {
01879 delta_y = constraint.mBottom - mRect.mBottom;
01880 delta_y -= llmax( 0, mRect.getHeight() - constraint.getHeight() );
01881 }
01882 }
01883
01884 if (delta_x != 0 || delta_y != 0)
01885 {
01886 translate(delta_x, delta_y);
01887 return TRUE;
01888 }
01889 return FALSE;
01890 }
01891
01892 BOOL LLView::localPointToOtherView( S32 x, S32 y, S32 *other_x, S32 *other_y, LLView* other_view)
01893 {
01894 LLView* cur_view = this;
01895 LLView* root_view = NULL;
01896
01897 while (cur_view)
01898 {
01899 if (cur_view == other_view)
01900 {
01901 *other_x = x;
01902 *other_y = y;
01903 return TRUE;
01904 }
01905
01906 x += cur_view->getRect().mLeft;
01907 y += cur_view->getRect().mBottom;
01908
01909 cur_view = cur_view->getParent();
01910 root_view = cur_view;
01911 }
01912
01913
01914 cur_view = other_view;
01915 while (cur_view)
01916 {
01917 x -= cur_view->getRect().mLeft;
01918 y -= cur_view->getRect().mBottom;
01919
01920 cur_view = cur_view->getParent();
01921
01922 if (cur_view == root_view)
01923 {
01924 *other_x = x;
01925 *other_y = y;
01926 return TRUE;
01927 }
01928 }
01929
01930 *other_x = x;
01931 *other_y = y;
01932 return FALSE;
01933 }
01934
01935 BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, LLView* other_view ) const
01936 {
01937 LLRect cur_rect = local;
01938 const LLView* cur_view = this;
01939 const LLView* root_view = NULL;
01940
01941 while (cur_view)
01942 {
01943 if (cur_view == other_view)
01944 {
01945 *other = cur_rect;
01946 return TRUE;
01947 }
01948
01949 cur_rect.translate(cur_view->getRect().mLeft, cur_view->getRect().mBottom);
01950
01951 cur_view = cur_view->getParent();
01952 root_view = cur_view;
01953 }
01954
01955
01956 cur_view = other_view;
01957 while (cur_view)
01958 {
01959 cur_rect.translate(-cur_view->getRect().mLeft, -cur_view->getRect().mBottom);
01960
01961 cur_view = cur_view->getParent();
01962
01963 if (cur_view == root_view)
01964 {
01965 *other = cur_rect;
01966 return TRUE;
01967 }
01968 }
01969
01970 *other = cur_rect;
01971 return FALSE;
01972 }
01973
01974
01975 LLXMLNodePtr LLView::getXML(bool save_children) const
01976 {
01977 const LLString& type_name = getWidgetTag();
01978
01979 LLXMLNodePtr node = new LLXMLNode(type_name, FALSE);
01980
01981 node->createChild("name", TRUE)->setStringValue(getName());
01982 node->createChild("width", TRUE)->setIntValue(getRect().getWidth());
01983 node->createChild("height", TRUE)->setIntValue(getRect().getHeight());
01984
01985 LLView* parent = getParent();
01986 S32 left = mRect.mLeft;
01987 S32 bottom = mRect.mBottom;
01988 if (parent) bottom -= parent->getRect().getHeight();
01989
01990 node->createChild("left", TRUE)->setIntValue(left);
01991 node->createChild("bottom", TRUE)->setIntValue(bottom);
01992
01993 U32 follows_flags = getFollows();
01994 if (follows_flags)
01995 {
01996 std::stringstream buffer;
01997 bool pipe = false;
01998 if (followsLeft())
01999 {
02000 buffer << "left";
02001 pipe = true;
02002 }
02003 if (followsTop())
02004 {
02005 if (pipe) buffer << "|";
02006 buffer << "top";
02007 pipe = true;
02008 }
02009 if (followsRight())
02010 {
02011 if (pipe) buffer << "|";
02012 buffer << "right";
02013 pipe = true;
02014 }
02015 if (followsBottom())
02016 {
02017 if (pipe) buffer << "|";
02018 buffer << "bottom";
02019 }
02020 node->createChild("follows", TRUE)->setStringValue(buffer.str());
02021 }
02022
02023 node->createChild("hidden", TRUE)->setBoolValue(mHidden);
02024 node->createChild("mouse_opaque", TRUE)->setBoolValue(mMouseOpaque );
02025 if (!mToolTipMsg.empty())
02026 {
02027 node->createChild("tool_tip", TRUE)->setStringValue(mToolTipMsg);
02028 }
02029 if (mSoundFlags != MOUSE_UP)
02030 {
02031 node->createChild("sound_flags", TRUE)->setIntValue((S32)mSoundFlags);
02032 }
02033
02034 node->createChild("enabled", TRUE)->setBoolValue(mEnabled);
02035
02036 if (!mControlName.empty())
02037 {
02038 node->createChild("control_name", TRUE)->setStringValue(mControlName);
02039 }
02040 return node;
02041 }
02042
02043
02044 void LLView::addColorXML(LLXMLNodePtr node, const LLColor4& color,
02045 const LLString& xml_name, const LLString& control_name)
02046 {
02047 if (color != LLUI::sColorsGroup->getColor(control_name))
02048 {
02049 node->createChild(xml_name, TRUE)->setFloatValue(4, color.mV);
02050 }
02051 }
02052
02053
02054 void LLView::saveColorToXML(std::ostream& out, const LLColor4& color,
02055 const LLString& xml_name, const LLString& control_name,
02056 const LLString& indent)
02057 {
02058 if (color != LLUI::sColorsGroup->getColor(control_name))
02059 {
02060 out << indent << xml_name << "=\""
02061 << color.mV[VRED] << ", "
02062 << color.mV[VGREEN] << ", "
02063 << color.mV[VBLUE] << ", "
02064 << color.mV[VALPHA] << "\"\n";
02065 }
02066 }
02067
02068
02069 LLString LLView::escapeXML(const LLString& xml, LLString& indent)
02070 {
02071 LLString ret = indent + "\"" + LLXMLNode::escapeXML(xml);
02072
02073
02074 size_t index = ret.size()-1;
02075 size_t fnd;
02076
02077 while ((fnd = ret.rfind("\n", index)) != std::string::npos)
02078 {
02079 ret.replace(fnd, 1, "\"\n" + indent + "\"");
02080 index = fnd-1;
02081 }
02082
02083
02084 ret.append("\"");
02085
02086 return ret;
02087 }
02088
02089
02090 LLWString LLView::escapeXML(const LLWString& xml)
02091 {
02092 LLWString out;
02093 for (LLWString::size_type i = 0; i < xml.size(); ++i)
02094 {
02095 llwchar c = xml[i];
02096 switch(c)
02097 {
02098 case '"': out.append(utf8string_to_wstring(""")); break;
02099 case '\'': out.append(utf8string_to_wstring("'")); break;
02100 case '&': out.append(utf8string_to_wstring("&")); break;
02101 case '<': out.append(utf8string_to_wstring("<")); break;
02102 case '>': out.append(utf8string_to_wstring(">")); break;
02103 default: out.push_back(c); break;
02104 }
02105 }
02106 return out;
02107 }
02108
02109
02110 const LLCtrlQuery & LLView::getTabOrderQuery()
02111 {
02112 static LLCtrlQuery query;
02113 if(query.getPreFilters().size() == 0) {
02114 query.addPreFilter(LLVisibleFilter::getInstance());
02115 query.addPreFilter(LLEnabledFilter::getInstance());
02116 query.addPreFilter(LLTabStopFilter::getInstance());
02117 query.addPostFilter(LLUICtrl::LLTabStopPostFilter::getInstance());
02118 }
02119 return query;
02120 }
02121
02122
02123 const LLCtrlQuery & LLView::getFocusRootsQuery()
02124 {
02125 static LLCtrlQuery query;
02126 if(query.getPreFilters().size() == 0) {
02127 query.addPreFilter(LLVisibleFilter::getInstance());
02128 query.addPreFilter(LLEnabledFilter::getInstance());
02129 query.addPreFilter(LLView::LLFocusRootsFilter::getInstance());
02130 }
02131 return query;
02132 }
02133
02134
02135 void LLView::userSetShape(const LLRect& new_rect)
02136 {
02137 reshape(new_rect.getWidth(), new_rect.getHeight());
02138 translate(new_rect.mLeft - mRect.mLeft, new_rect.mBottom - mRect.mBottom);
02139 }
02140
02141 LLView* LLView::findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir,
02142 LLView::ESnapType snap_type, S32 threshold, S32 padding)
02143 {
02144 LLView* snap_view = NULL;
02145
02146 if (!mParentView)
02147 {
02148 new_rect = mRect;
02149 return snap_view;
02150 }
02151
02152
02153
02154 LLRect test_rect = getSnapRect();
02155 LLRect view_rect = getSnapRect();
02156 test_rect.stretch(padding);
02157 view_rect.stretch(padding);
02158
02159 BOOL snapped_x = FALSE;
02160 BOOL snapped_y = FALSE;
02161
02162 LLRect parent_local_snap_rect = mParentView->getLocalSnapRect();
02163
02164 if (snap_type == SNAP_PARENT || snap_type == SNAP_PARENT_AND_SIBLINGS)
02165 {
02166 if (llabs(parent_local_snap_rect.mRight - test_rect.mRight) <= threshold && (parent_local_snap_rect.mRight - test_rect.mRight) * mouse_dir.mX >= 0)
02167 {
02168 view_rect.translate(parent_local_snap_rect.mRight - view_rect.mRight, 0);
02169 snap_view = mParentView;
02170 snapped_x = TRUE;
02171 }
02172
02173 if (llabs(test_rect.mLeft - parent_local_snap_rect.mLeft) <= threshold && test_rect.mLeft * mouse_dir.mX <= 0)
02174 {
02175 view_rect.translate(parent_local_snap_rect.mLeft - view_rect.mLeft, 0);
02176 snap_view = mParentView;
02177 snapped_x = TRUE;
02178 }
02179
02180 if (llabs(test_rect.mBottom - parent_local_snap_rect.mBottom) <= threshold && test_rect.mBottom * mouse_dir.mY <= 0)
02181 {
02182 view_rect.translate(0, parent_local_snap_rect.mBottom - view_rect.mBottom);
02183 snap_view = mParentView;
02184 snapped_y = TRUE;
02185 }
02186
02187 if (llabs(parent_local_snap_rect.mTop - test_rect.mTop) <= threshold && (parent_local_snap_rect.mTop - test_rect.mTop) * mouse_dir.mY >= 0)
02188 {
02189 view_rect.translate(0, parent_local_snap_rect.mTop - view_rect.mTop);
02190 snap_view = mParentView;
02191 snapped_y = TRUE;
02192 }
02193 }
02194 if (snap_type == SNAP_SIBLINGS || snap_type == SNAP_PARENT_AND_SIBLINGS)
02195 {
02196 for ( child_list_const_iter_t child_it = mParentView->getChildList()->begin();
02197 child_it != mParentView->getChildList()->end(); ++child_it)
02198 {
02199 LLView* siblingp = *child_it;
02200
02201 if (siblingp == this || !siblingp->getVisible() || !canSnapTo(siblingp))
02202 {
02203 continue;
02204 }
02205
02206 LLRect sibling_rect = siblingp->getSnapRect();
02207
02208 if (!snapped_x && llabs(test_rect.mRight - sibling_rect.mLeft) <= threshold && (test_rect.mRight - sibling_rect.mLeft) * mouse_dir.mX <= 0)
02209 {
02210 view_rect.translate(sibling_rect.mLeft - view_rect.mRight, 0);
02211 if (!snapped_y)
02212 {
02213 if (llabs(test_rect.mTop - sibling_rect.mTop) <= threshold && (test_rect.mTop - sibling_rect.mTop) * mouse_dir.mY <= 0)
02214 {
02215 view_rect.translate(0, sibling_rect.mTop - test_rect.mTop);
02216 snapped_y = TRUE;
02217 }
02218 else if (llabs(test_rect.mBottom - sibling_rect.mBottom) <= threshold && (test_rect.mBottom - sibling_rect.mBottom) * mouse_dir.mY <= 0)
02219 {
02220 view_rect.translate(0, sibling_rect.mBottom - test_rect.mBottom);
02221 snapped_y = TRUE;
02222 }
02223 }
02224 snap_view = siblingp;
02225 snapped_x = TRUE;
02226 }
02227
02228 if (!snapped_x && llabs(test_rect.mLeft - sibling_rect.mRight) <= threshold && (test_rect.mLeft - sibling_rect.mRight) * mouse_dir.mX <= 0)
02229 {
02230 view_rect.translate(sibling_rect.mRight - view_rect.mLeft, 0);
02231 if (!snapped_y)
02232 {
02233 if (llabs(test_rect.mTop - sibling_rect.mTop) <= threshold && (test_rect.mTop - sibling_rect.mTop) * mouse_dir.mY <= 0)
02234 {
02235 view_rect.translate(0, sibling_rect.mTop - test_rect.mTop);
02236 snapped_y = TRUE;
02237 }
02238 else if (llabs(test_rect.mBottom - sibling_rect.mBottom) <= threshold && (test_rect.mBottom - sibling_rect.mBottom) * mouse_dir.mY <= 0)
02239 {
02240 view_rect.translate(0, sibling_rect.mBottom - test_rect.mBottom);
02241 snapped_y = TRUE;
02242 }
02243 }
02244 snap_view = siblingp;
02245 snapped_x = TRUE;
02246 }
02247
02248 if (!snapped_y && llabs(test_rect.mBottom - sibling_rect.mTop) <= threshold && (test_rect.mBottom - sibling_rect.mTop) * mouse_dir.mY <= 0)
02249 {
02250 view_rect.translate(0, sibling_rect.mTop - view_rect.mBottom);
02251 if (!snapped_x)
02252 {
02253 if (llabs(test_rect.mLeft - sibling_rect.mLeft) <= threshold && (test_rect.mLeft - sibling_rect.mLeft) * mouse_dir.mX <= 0)
02254 {
02255 view_rect.translate(sibling_rect.mLeft - test_rect.mLeft, 0);
02256 snapped_x = TRUE;
02257 }
02258 else if (llabs(test_rect.mRight - sibling_rect.mRight) <= threshold && (test_rect.mRight - sibling_rect.mRight) * mouse_dir.mX <= 0)
02259 {
02260 view_rect.translate(sibling_rect.mRight - test_rect.mRight, 0);
02261 snapped_x = TRUE;
02262 }
02263 }
02264 snap_view = siblingp;
02265 snapped_y = TRUE;
02266 }
02267
02268 if (!snapped_y && llabs(test_rect.mTop - sibling_rect.mBottom) <= threshold && (test_rect.mTop - sibling_rect.mBottom) * mouse_dir.mY <= 0)
02269 {
02270 view_rect.translate(0, sibling_rect.mBottom - view_rect.mTop);
02271 if (!snapped_x)
02272 {
02273 if (llabs(test_rect.mLeft - sibling_rect.mLeft) <= threshold && (test_rect.mLeft - sibling_rect.mLeft) * mouse_dir.mX <= 0)
02274 {
02275 view_rect.translate(sibling_rect.mLeft - test_rect.mLeft, 0);
02276 snapped_x = TRUE;
02277 }
02278 else if (llabs(test_rect.mRight - sibling_rect.mRight) <= threshold && (test_rect.mRight - sibling_rect.mRight) * mouse_dir.mX <= 0)
02279 {
02280 view_rect.translate(sibling_rect.mRight - test_rect.mRight, 0);
02281 snapped_x = TRUE;
02282 }
02283 }
02284 snap_view = siblingp;
02285 snapped_y = TRUE;
02286 }
02287
02288 if (snapped_x && snapped_y)
02289 {
02290 break;
02291 }
02292 }
02293 }
02294
02295
02296 view_rect.stretch(-padding);
02297 new_rect = view_rect;
02298 return snap_view;
02299 }
02300
02301 LLView* LLView::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding)
02302 {
02303 LLRect snap_rect = getSnapRect();
02304 S32 snap_pos = 0;
02305 switch(snap_edge)
02306 {
02307 case SNAP_LEFT:
02308 snap_pos = snap_rect.mLeft;
02309 break;
02310 case SNAP_RIGHT:
02311 snap_pos = snap_rect.mRight;
02312 break;
02313 case SNAP_TOP:
02314 snap_pos = snap_rect.mTop;
02315 break;
02316 case SNAP_BOTTOM:
02317 snap_pos = snap_rect.mBottom;
02318 break;
02319 }
02320
02321 if (!mParentView)
02322 {
02323 new_edge_val = snap_pos;
02324 return NULL;
02325 }
02326
02327 LLView* snap_view = NULL;
02328
02329
02330
02331 LLRect test_rect = snap_rect;
02332 test_rect.stretch(padding);
02333
02334 BOOL snapped_x = FALSE;
02335 BOOL snapped_y = FALSE;
02336
02337 LLRect parent_local_snap_rect = mParentView->getLocalSnapRect();
02338
02339 if (snap_type == SNAP_PARENT || snap_type == SNAP_PARENT_AND_SIBLINGS)
02340 {
02341 switch(snap_edge)
02342 {
02343 case SNAP_RIGHT:
02344 if (llabs(parent_local_snap_rect.mRight - test_rect.mRight) <= threshold && (parent_local_snap_rect.mRight - test_rect.mRight) * mouse_dir.mX >= 0)
02345 {
02346 snap_pos = parent_local_snap_rect.mRight - padding;
02347 snap_view = mParentView;
02348 snapped_x = TRUE;
02349 }
02350 break;
02351 case SNAP_LEFT:
02352 if (llabs(test_rect.mLeft - parent_local_snap_rect.mLeft) <= threshold && test_rect.mLeft * mouse_dir.mX <= 0)
02353 {
02354 snap_pos = parent_local_snap_rect.mLeft + padding;
02355 snap_view = mParentView;
02356 snapped_x = TRUE;
02357 }
02358 break;
02359 case SNAP_BOTTOM:
02360 if (llabs(test_rect.mBottom - parent_local_snap_rect.mBottom) <= threshold && test_rect.mBottom * mouse_dir.mY <= 0)
02361 {
02362 snap_pos = parent_local_snap_rect.mBottom + padding;
02363 snap_view = mParentView;
02364 snapped_y = TRUE;
02365 }
02366 break;
02367 case SNAP_TOP:
02368 if (llabs(parent_local_snap_rect.mTop - test_rect.mTop) <= threshold && (parent_local_snap_rect.mTop - test_rect.mTop) * mouse_dir.mY >= 0)
02369 {
02370 snap_pos = parent_local_snap_rect.mTop - padding;
02371 snap_view = mParentView;
02372 snapped_y = TRUE;
02373 }
02374 break;
02375 default:
02376 llerrs << "Invalid snap edge" << llendl;
02377 }
02378 }
02379
02380 if (snap_type == SNAP_SIBLINGS || snap_type == SNAP_PARENT_AND_SIBLINGS)
02381 {
02382 for ( child_list_const_iter_t child_it = mParentView->getChildList()->begin();
02383 child_it != mParentView->getChildList()->end(); ++child_it)
02384 {
02385 LLView* siblingp = *child_it;
02386
02387 if (siblingp == this || !siblingp->getVisible() || !canSnapTo(siblingp))
02388 {
02389 continue;
02390 }
02391
02392 LLRect sibling_rect = siblingp->getSnapRect();
02393
02394 switch(snap_edge)
02395 {
02396 case SNAP_RIGHT:
02397 if (!snapped_x)
02398 {
02399 if (llabs(test_rect.mRight - sibling_rect.mLeft) <= threshold && (test_rect.mRight - sibling_rect.mLeft) * mouse_dir.mX <= 0)
02400 {
02401 snap_pos = sibling_rect.mLeft - padding;
02402 snap_view = siblingp;
02403 snapped_x = TRUE;
02404 }
02405
02406 else if (llabs(sibling_rect.mTop - (test_rect.mBottom - padding)) <= threshold ||
02407 llabs(sibling_rect.mBottom - (test_rect.mTop + padding)) <= threshold)
02408 {
02409 if (llabs(test_rect.mRight - sibling_rect.mRight) <= threshold && (test_rect.mRight - sibling_rect.mRight) * mouse_dir.mX <= 0)
02410 {
02411 snap_pos = sibling_rect.mRight;
02412 snap_view = siblingp;
02413 snapped_x = TRUE;
02414 }
02415 }
02416 }
02417 break;
02418 case SNAP_LEFT:
02419 if (!snapped_x)
02420 {
02421 if (llabs(test_rect.mLeft - sibling_rect.mRight) <= threshold && (test_rect.mLeft - sibling_rect.mRight) * mouse_dir.mX <= 0)
02422 {
02423 snap_pos = sibling_rect.mRight + padding;
02424 snap_view = siblingp;
02425 snapped_x = TRUE;
02426 }
02427
02428 else if (llabs(sibling_rect.mTop - (test_rect.mBottom - padding)) <= threshold ||
02429 llabs(sibling_rect.mBottom - (test_rect.mTop + padding)) <= threshold)
02430 {
02431 if (llabs(test_rect.mLeft - sibling_rect.mLeft) <= threshold && (test_rect.mLeft - sibling_rect.mLeft) * mouse_dir.mX <= 0)
02432 {
02433 snap_pos = sibling_rect.mLeft;
02434 snap_view = siblingp;
02435 snapped_x = TRUE;
02436 }
02437 }
02438 }
02439 break;
02440 case SNAP_BOTTOM:
02441 if (!snapped_y)
02442 {
02443 if (llabs(test_rect.mBottom - sibling_rect.mTop) <= threshold && (test_rect.mBottom - sibling_rect.mTop) * mouse_dir.mY <= 0)
02444 {
02445 snap_pos = sibling_rect.mTop + padding;
02446 snap_view = siblingp;
02447 snapped_y = TRUE;
02448 }
02449
02450 else if (llabs(sibling_rect.mRight - (test_rect.mLeft - padding)) <= threshold ||
02451 llabs(sibling_rect.mLeft - (test_rect.mRight + padding)) <= threshold)
02452 {
02453 if (llabs(test_rect.mBottom - sibling_rect.mBottom) <= threshold && (test_rect.mBottom - sibling_rect.mBottom) * mouse_dir.mY <= 0)
02454 {
02455 snap_pos = sibling_rect.mBottom;
02456 snap_view = siblingp;
02457 snapped_y = TRUE;
02458 }
02459 }
02460 }
02461 break;
02462 case SNAP_TOP:
02463 if (!snapped_y)
02464 {
02465 if (llabs(test_rect.mTop - sibling_rect.mBottom) <= threshold && (test_rect.mTop - sibling_rect.mBottom) * mouse_dir.mY <= 0)
02466 {
02467 snap_pos = sibling_rect.mBottom - padding;
02468 snap_view = siblingp;
02469 snapped_y = TRUE;
02470 }
02471
02472 else if (llabs(sibling_rect.mRight - (test_rect.mLeft - padding)) <= threshold ||
02473 llabs(sibling_rect.mLeft - (test_rect.mRight + padding)) <= threshold)
02474 {
02475 if (llabs(test_rect.mTop - sibling_rect.mTop) <= threshold && (test_rect.mTop - sibling_rect.mTop) * mouse_dir.mY <= 0)
02476 {
02477 snap_pos = sibling_rect.mTop;
02478 snap_view = siblingp;
02479 snapped_y = TRUE;
02480 }
02481 }
02482 }
02483 break;
02484 default:
02485 llerrs << "Invalid snap edge" << llendl;
02486 }
02487 if (snapped_x && snapped_y)
02488 {
02489 break;
02490 }
02491 }
02492 }
02493
02494 new_edge_val = snap_pos;
02495 return snap_view;
02496 }
02497
02498 bool operator==(const LLViewHandle& lhs, const LLViewHandle& rhs)
02499 {
02500 return lhs.mID == rhs.mID;
02501 }
02502
02503 bool operator!=(const LLViewHandle& lhs, const LLViewHandle& rhs)
02504 {
02505 return lhs.mID != rhs.mID;
02506 }
02507
02508 bool operator<(const LLViewHandle &lhs, const LLViewHandle &rhs)
02509 {
02510 return lhs.mID < rhs.mID;
02511 }
02512
02513
02514
02515
02516
02517 void LLView::registerEventListener(LLString name, LLSimpleListener* function)
02518 {
02519 mDispatchList.insert(std::pair<LLString, LLSimpleListener*>(name, function));
02520 }
02521
02522 void LLView::deregisterEventListener(LLString name)
02523 {
02524 dispatch_list_t::iterator itor = mDispatchList.find(name);
02525 if (itor != mDispatchList.end())
02526 {
02527 mDispatchList.erase(itor);
02528 }
02529 }
02530
02531 LLString LLView::findEventListener(LLSimpleListener *listener) const
02532 {
02533 dispatch_list_t::const_iterator itor;
02534 for (itor = mDispatchList.begin(); itor != mDispatchList.end(); ++itor)
02535 {
02536 if (itor->second == listener)
02537 {
02538 return itor->first;
02539 }
02540 }
02541 if (mParentView)
02542 {
02543 return mParentView->findEventListener(listener);
02544 }
02545 return LLString::null;
02546 }
02547
02548 LLSimpleListener* LLView::getListenerByName(const LLString& callback_name)
02549 {
02550 LLSimpleListener* callback = NULL;
02551 dispatch_list_t::iterator itor = mDispatchList.find(callback_name);
02552 if (itor != mDispatchList.end())
02553 {
02554 callback = itor->second;
02555 }
02556 else if (mParentView)
02557 {
02558 callback = mParentView->getListenerByName(callback_name);
02559 }
02560 return callback;
02561 }
02562
02563 void LLView::addListenerToControl(LLEventDispatcher *dispatcher, const LLString& name, LLSD filter, LLSD userdata)
02564 {
02565 LLSimpleListener* listener = getListenerByName(name);
02566 if (listener)
02567 {
02568 dispatcher->addListener(listener, filter, userdata);
02569 }
02570 }
02571
02572 LLControlBase *LLView::findControl(LLString name)
02573 {
02574 control_map_t::iterator itor = mFloaterControls.find(name);
02575 if (itor != mFloaterControls.end())
02576 {
02577 return itor->second;
02578 }
02579 if (mParentView)
02580 {
02581 return mParentView->findControl(name);
02582 }
02583 return LLUI::sConfigGroup->getControl(name);
02584 }
02585
02586 const S32 FLOATER_H_MARGIN = 15;
02587 const S32 MIN_WIDGET_HEIGHT = 10;
02588 const S32 VPAD = 4;
02589
02590
02591 U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect)
02592 {
02593 U32 follows = 0;
02594 S32 x = FLOATER_H_MARGIN;
02595 S32 y = 0;
02596 S32 w = 0;
02597 S32 h = 0;
02598
02599 U32 last_x = 0;
02600 U32 last_y = 0;
02601 if (parent_view)
02602 {
02603 last_y = parent_view->getRect().getHeight();
02604 child_list_t::const_iterator itor = parent_view->getChildList()->begin();
02605 if (itor != parent_view->getChildList()->end())
02606 {
02607 LLView *last_view = (*itor);
02608 if (last_view->getSaveToXML())
02609 {
02610 last_x = last_view->getRect().mLeft;
02611 last_y = last_view->getRect().mBottom;
02612 }
02613 }
02614 }
02615
02616 LLString rect_control;
02617 node->getAttributeString("rect_control", rect_control);
02618 if (! rect_control.empty())
02619 {
02620 LLRect rect = LLUI::sConfigGroup->getRect(rect_control);
02621 x = rect.mLeft;
02622 y = rect.mBottom;
02623 w = rect.getWidth();
02624 h = rect.getHeight();
02625 }
02626
02627 if (node->hasAttribute("left"))
02628 {
02629 node->getAttributeS32("left", x);
02630 }
02631 if (node->hasAttribute("bottom"))
02632 {
02633 node->getAttributeS32("bottom", y);
02634 }
02635
02636
02637
02638 if (parent_view)
02639 {
02640 w = llmax(required_rect.getWidth(), parent_view->getRect().getWidth() - (FLOATER_H_MARGIN) - x);
02641 h = llmax(MIN_WIDGET_HEIGHT, required_rect.getHeight());
02642 }
02643
02644 if (node->hasAttribute("width"))
02645 {
02646 node->getAttributeS32("width", w);
02647 }
02648 if (node->hasAttribute("height"))
02649 {
02650 node->getAttributeS32("height", h);
02651 }
02652
02653 if (parent_view)
02654 {
02655 if (node->hasAttribute("left_delta"))
02656 {
02657 S32 left_delta = 0;
02658 node->getAttributeS32("left_delta", left_delta);
02659 x = last_x + left_delta;
02660 }
02661 else if (node->hasAttribute("left") && node->hasAttribute("right"))
02662 {
02663
02664 S32 right = 0;
02665 node->getAttributeS32("right", right);
02666 if (right < 0)
02667 {
02668 right = parent_view->getRect().getWidth() + right;
02669 }
02670 w = right - x;
02671 }
02672 else if (node->hasAttribute("left"))
02673 {
02674 if (x < 0)
02675 {
02676 x = parent_view->getRect().getWidth() + x;
02677 follows |= FOLLOWS_RIGHT;
02678 }
02679 else
02680 {
02681 follows |= FOLLOWS_LEFT;
02682 }
02683 }
02684 else if (node->hasAttribute("width") && node->hasAttribute("right"))
02685 {
02686 S32 right = 0;
02687 node->getAttributeS32("right", right);
02688 if (right < 0)
02689 {
02690 right = parent_view->getRect().getWidth() + right;
02691 }
02692 x = right - w;
02693 }
02694 else
02695 {
02696
02697 x = last_x;
02698 }
02699
02700 if (node->hasAttribute("bottom_delta"))
02701 {
02702 S32 bottom_delta = 0;
02703 node->getAttributeS32("bottom_delta", bottom_delta);
02704 y = last_y + bottom_delta;
02705 }
02706 else if (node->hasAttribute("top"))
02707 {
02708
02709 S32 top = 0;
02710 node->getAttributeS32("top", top);
02711 if (top < 0)
02712 {
02713 top = parent_view->getRect().getHeight() + top;
02714 }
02715 h = top - y;
02716 }
02717 else if (node->hasAttribute("bottom"))
02718 {
02719 if (y < 0)
02720 {
02721 y = parent_view->getRect().getHeight() + y;
02722 follows |= FOLLOWS_TOP;
02723 }
02724 else
02725 {
02726 follows |= FOLLOWS_BOTTOM;
02727 }
02728 }
02729 else
02730 {
02731
02732 if (last_y == 0)
02733 {
02734
02735 y = parent_view->getRect().getHeight() - (h + VPAD);
02736 follows |= FOLLOWS_TOP;
02737 }
02738 else
02739 {
02740
02741 y = last_y - (h + VPAD);
02742 }
02743 }
02744 }
02745 else
02746 {
02747 x = llmax(x, 0);
02748 y = llmax(y, 0);
02749 follows = FOLLOWS_LEFT | FOLLOWS_TOP;
02750 }
02751 rect.setOriginAndSize(x, y, w, h);
02752
02753 return follows;
02754 }
02755
02756 void LLView::initFromXML(LLXMLNodePtr node, LLView* parent)
02757 {
02758
02759 LLRect view_rect;
02760 U32 follows_flags = createRect(node, view_rect, parent, getRequiredRect());
02761
02762 reshape(view_rect.getWidth(), view_rect.getHeight());
02763 setRect(view_rect);
02764 setFollows(follows_flags);
02765
02766 if (node->hasAttribute("follows"))
02767 {
02768 setFollowsNone();
02769
02770 LLString follows;
02771 node->getAttributeString("follows", follows);
02772
02773 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
02774 boost::char_separator<char> sep("|");
02775 tokenizer tokens(follows, sep);
02776 tokenizer::iterator token_iter = tokens.begin();
02777
02778 while(token_iter != tokens.end())
02779 {
02780 const std::string& token_str = *token_iter;
02781 if (token_str == "left")
02782 {
02783 setFollowsLeft();
02784 }
02785 else if (token_str == "right")
02786 {
02787 setFollowsRight();
02788 }
02789 else if (token_str == "top")
02790 {
02791 setFollowsTop();
02792 }
02793 else if (token_str == "bottom")
02794 {
02795 setFollowsBottom();
02796 }
02797 else if (token_str == "all")
02798 {
02799 setFollowsAll();
02800 }
02801 ++token_iter;
02802 }
02803 }
02804
02805 if (node->hasAttribute("control_name"))
02806 {
02807 LLString control_name;
02808 node->getAttributeString("control_name", control_name);
02809 setControlName(control_name, NULL);
02810 }
02811
02812 if (node->hasAttribute("tool_tip"))
02813 {
02814 LLString tool_tip_msg("");
02815 node->getAttributeString("tool_tip", tool_tip_msg);
02816 setToolTip(tool_tip_msg);
02817 }
02818
02819 if (node->hasAttribute("enabled"))
02820 {
02821 BOOL enabled;
02822 node->getAttributeBOOL("enabled", enabled);
02823 setEnabled(enabled);
02824 }
02825
02826 if (node->hasAttribute("visible"))
02827 {
02828 BOOL visible;
02829 node->getAttributeBOOL("visible", visible);
02830 setVisible(visible);
02831 }
02832
02833 if (node->hasAttribute("hidden"))
02834 {
02835 BOOL hidden;
02836 node->getAttributeBOOL("hidden", hidden);
02837 setHidden(hidden);
02838 }
02839
02840 node->getAttributeS32("default_tab_group", mDefaultTabGroup);
02841
02842 reshape(view_rect.getWidth(), view_rect.getHeight());
02843 }
02844
02845
02846 LLFontGL* LLView::selectFont(LLXMLNodePtr node)
02847 {
02848 LLFontGL* gl_font = NULL;
02849
02850 if (node->hasAttribute("font"))
02851 {
02852 LLString font_name;
02853 node->getAttributeString("font", font_name);
02854
02855 gl_font = LLFontGL::fontFromName(font_name.c_str());
02856 }
02857 return gl_font;
02858 }
02859
02860
02861 LLFontGL::HAlign LLView::selectFontHAlign(LLXMLNodePtr node)
02862 {
02863 LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT;
02864
02865 if (node->hasAttribute("halign"))
02866 {
02867 LLString horizontal_align_name;
02868 node->getAttributeString("halign", horizontal_align_name);
02869 gl_hfont_align = LLFontGL::hAlignFromName(horizontal_align_name);
02870 }
02871 return gl_hfont_align;
02872 }
02873
02874
02875 LLFontGL::VAlign LLView::selectFontVAlign(LLXMLNodePtr node)
02876 {
02877 LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE;
02878
02879 if (node->hasAttribute("valign"))
02880 {
02881 LLString vert_align_name;
02882 node->getAttributeString("valign", vert_align_name);
02883 gl_vfont_align = LLFontGL::vAlignFromName(vert_align_name);
02884 }
02885 return gl_vfont_align;
02886 }
02887
02888
02889 LLFontGL::StyleFlags LLView::selectFontStyle(LLXMLNodePtr node)
02890 {
02891 LLFontGL::StyleFlags gl_font_style = LLFontGL::NORMAL;
02892
02893 if (node->hasAttribute("style"))
02894 {
02895 LLString style_flags_name;
02896 node->getAttributeString("style", style_flags_name);
02897
02898 if (style_flags_name == "normal")
02899 {
02900 gl_font_style = LLFontGL::NORMAL;
02901 }
02902 else if (style_flags_name == "bold")
02903 {
02904 gl_font_style = LLFontGL::BOLD;
02905 }
02906 else if (style_flags_name == "italic")
02907 {
02908 gl_font_style = LLFontGL::ITALIC;
02909 }
02910 else if (style_flags_name == "underline")
02911 {
02912 gl_font_style = LLFontGL::UNDERLINE;
02913 }
02914
02915 }
02916 return gl_font_style;
02917 }
02918
02919 void LLView::setControlValue(const LLSD& value)
02920 {
02921 LLUI::sConfigGroup->setValue(getControlName(), value);
02922 }
02923
02924
02925 LLString LLView::getControlName() const
02926 {
02927 return mControlName;
02928 }
02929
02930
02931 void LLView::setControlName(const LLString& control_name, LLView *context)
02932 {
02933 if (context == NULL)
02934 {
02935 context = this;
02936 }
02937
02938
02939 if (!mControlName.empty())
02940 {
02941 clearDispatchers();
02942 }
02943
02944
02945 if (!control_name.empty())
02946 {
02947 LLControlBase *control = context->findControl(control_name);
02948 if (control)
02949 {
02950 mControlName = control_name;
02951 LLSD state = control->registerListener(this, "DEFAULT");
02952 setValue(state);
02953 }
02954 }
02955 }
02956
02957
02958 bool LLView::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
02959 {
02960 if (userdata.asString() == "DEFAULT" && event->desc() == "value_changed")
02961 {
02962 LLSD state = event->getValue();
02963 setValue(state);
02964 return TRUE;
02965 }
02966 return FALSE;
02967 }
02968
02969 void LLView::setValue(const LLSD& value)
02970 {
02971 }
02972
02973
02974 void LLView::addBoolControl(LLString name, bool initial_value)
02975 {
02976 mFloaterControls[name] = new LLControl(name, TYPE_BOOLEAN, initial_value, "Internal floater control");
02977 }
02978
02979 LLControlBase *LLView::getControl(LLString name)
02980 {
02981 control_map_t::iterator itor = mFloaterControls.find(name);
02982 if (itor != mFloaterControls.end())
02983 {
02984 return itor->second;
02985 }
02986 return NULL;
02987 }