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