PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llui/lluictrl.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1062 lines | 845 code | 121 blank | 96 comment | 123 complexity | f16a4a490656e264caf104206161c97a MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lluictrl.cpp
  3. * @author James Cook, Richard Nelson, Tom Yedwab
  4. * @brief Abstract base class for UI controls
  5. *
  6. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include "linden_common.h"
  28. #define LLUICTRL_CPP
  29. #include "lluictrl.h"
  30. #include "llfocusmgr.h"
  31. #include "llpanel.h"
  32. #include "lluictrlfactory.h"
  33. static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");
  34. F32 LLUICtrl::sActiveControlTransparency = 1.0f;
  35. F32 LLUICtrl::sInactiveControlTransparency = 1.0f;
  36. // Compiler optimization, generate extern template
  37. template class LLUICtrl* LLView::getChild<class LLUICtrl>(
  38. const std::string& name, BOOL recurse) const;
  39. LLUICtrl::CallbackParam::CallbackParam()
  40. : name("name"),
  41. function_name("function"),
  42. parameter("parameter"),
  43. control_name("control") // Shortcut to control -> "control_name" for backwards compatability
  44. {
  45. addSynonym(parameter, "userdata");
  46. }
  47. LLUICtrl::EnableControls::EnableControls()
  48. : enabled("enabled_control"),
  49. disabled("disabled_control")
  50. {}
  51. LLUICtrl::ControlVisibility::ControlVisibility()
  52. : visible("visibility_control"),
  53. invisible("invisibility_control")
  54. {
  55. addSynonym(visible, "visiblity_control");
  56. addSynonym(invisible, "invisiblity_control");
  57. }
  58. LLUICtrl::Params::Params()
  59. : tab_stop("tab_stop", true),
  60. chrome("chrome", false),
  61. requests_front("requests_front", false),
  62. label("label"),
  63. initial_value("value"),
  64. init_callback("init_callback"),
  65. commit_callback("commit_callback"),
  66. validate_callback("validate_callback"),
  67. mouseenter_callback("mouseenter_callback"),
  68. mouseleave_callback("mouseleave_callback"),
  69. control_name("control_name"),
  70. font("font", LLFontGL::getFontSansSerif()),
  71. font_halign("halign"),
  72. font_valign("valign"),
  73. length("length"), // ignore LLXMLNode cruft
  74. type("type") // ignore LLXMLNode cruft
  75. {
  76. addSynonym(initial_value, "initial_value");
  77. }
  78. // NOTE: the LLFocusableElement implementation has been moved from here to llfocusmgr.cpp.
  79. //static
  80. const LLUICtrl::Params& LLUICtrl::getDefaultParams()
  81. {
  82. return LLUICtrlFactory::getDefaultParams<LLUICtrl>();
  83. }
  84. LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)
  85. : LLView(p),
  86. mIsChrome(FALSE),
  87. mRequestsFront(p.requests_front),
  88. mTabStop(FALSE),
  89. mTentative(FALSE),
  90. mViewModel(viewmodel),
  91. mControlVariable(NULL),
  92. mEnabledControlVariable(NULL),
  93. mDisabledControlVariable(NULL),
  94. mMakeVisibleControlVariable(NULL),
  95. mMakeInvisibleControlVariable(NULL),
  96. mCommitSignal(NULL),
  97. mValidateSignal(NULL),
  98. mMouseEnterSignal(NULL),
  99. mMouseLeaveSignal(NULL),
  100. mMouseDownSignal(NULL),
  101. mMouseUpSignal(NULL),
  102. mRightMouseDownSignal(NULL),
  103. mRightMouseUpSignal(NULL),
  104. mDoubleClickSignal(NULL),
  105. mTransparencyType(TT_DEFAULT)
  106. {
  107. }
  108. void LLUICtrl::initFromParams(const Params& p)
  109. {
  110. LLView::initFromParams(p);
  111. mRequestsFront = p.requests_front;
  112. setIsChrome(p.chrome);
  113. setControlName(p.control_name);
  114. if(p.enabled_controls.isProvided())
  115. {
  116. if (p.enabled_controls.enabled.isChosen())
  117. {
  118. LLControlVariable* control = findControl(p.enabled_controls.enabled);
  119. if (control)
  120. setEnabledControlVariable(control);
  121. }
  122. else if(p.enabled_controls.disabled.isChosen())
  123. {
  124. LLControlVariable* control = findControl(p.enabled_controls.disabled);
  125. if (control)
  126. setDisabledControlVariable(control);
  127. }
  128. }
  129. if(p.controls_visibility.isProvided())
  130. {
  131. if (p.controls_visibility.visible.isChosen())
  132. {
  133. LLControlVariable* control = findControl(p.controls_visibility.visible);
  134. if (control)
  135. setMakeVisibleControlVariable(control);
  136. }
  137. else if (p.controls_visibility.invisible.isChosen())
  138. {
  139. LLControlVariable* control = findControl(p.controls_visibility.invisible);
  140. if (control)
  141. setMakeInvisibleControlVariable(control);
  142. }
  143. }
  144. setTabStop(p.tab_stop);
  145. if (p.initial_value.isProvided()
  146. && !p.control_name.isProvided())
  147. {
  148. setValue(p.initial_value);
  149. }
  150. if (p.commit_callback.isProvided())
  151. {
  152. setCommitCallback(initCommitCallback(p.commit_callback));
  153. }
  154. if (p.validate_callback.isProvided())
  155. {
  156. setValidateCallback(initEnableCallback(p.validate_callback));
  157. }
  158. if (p.init_callback.isProvided())
  159. {
  160. if (p.init_callback.function.isProvided())
  161. {
  162. p.init_callback.function()(this, p.init_callback.parameter);
  163. }
  164. else
  165. {
  166. commit_callback_t* initfunc = (CommitCallbackRegistry::getValue(p.init_callback.function_name));
  167. if (initfunc)
  168. {
  169. (*initfunc)(this, p.init_callback.parameter);
  170. }
  171. }
  172. }
  173. if(p.mouseenter_callback.isProvided())
  174. {
  175. setMouseEnterCallback(initCommitCallback(p.mouseenter_callback));
  176. }
  177. if(p.mouseleave_callback.isProvided())
  178. {
  179. setMouseLeaveCallback(initCommitCallback(p.mouseleave_callback));
  180. }
  181. }
  182. LLUICtrl::~LLUICtrl()
  183. {
  184. gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
  185. if( gFocusMgr.getTopCtrl() == this )
  186. {
  187. llwarns << "UI Control holding top ctrl deleted: " << getName() << ". Top view removed." << llendl;
  188. gFocusMgr.removeTopCtrlWithoutCallback( this );
  189. }
  190. delete mCommitSignal;
  191. delete mValidateSignal;
  192. delete mMouseEnterSignal;
  193. delete mMouseLeaveSignal;
  194. delete mMouseDownSignal;
  195. delete mMouseUpSignal;
  196. delete mRightMouseDownSignal;
  197. delete mRightMouseUpSignal;
  198. delete mDoubleClickSignal;
  199. }
  200. void default_commit_handler(LLUICtrl* ctrl, const LLSD& param)
  201. {}
  202. bool default_enable_handler(LLUICtrl* ctrl, const LLSD& param)
  203. {
  204. return true;
  205. }
  206. LLUICtrl::commit_signal_t::slot_type LLUICtrl::initCommitCallback(const CommitCallbackParam& cb)
  207. {
  208. if (cb.function.isProvided())
  209. {
  210. if (cb.parameter.isProvided())
  211. return boost::bind(cb.function(), _1, cb.parameter);
  212. else
  213. return cb.function();
  214. }
  215. else
  216. {
  217. std::string function_name = cb.function_name;
  218. commit_callback_t* func = (CommitCallbackRegistry::getValue(function_name));
  219. if (func)
  220. {
  221. if (cb.parameter.isProvided())
  222. return boost::bind((*func), _1, cb.parameter);
  223. else
  224. return commit_signal_t::slot_type(*func);
  225. }
  226. else if (!function_name.empty())
  227. {
  228. llwarns << "No callback found for: '" << function_name << "' in control: " << getName() << llendl;
  229. }
  230. }
  231. return default_commit_handler;
  232. }
  233. LLUICtrl::enable_signal_t::slot_type LLUICtrl::initEnableCallback(const EnableCallbackParam& cb)
  234. {
  235. // Set the callback function
  236. if (cb.function.isProvided())
  237. {
  238. if (cb.parameter.isProvided())
  239. return boost::bind(cb.function(), this, cb.parameter);
  240. else
  241. return cb.function();
  242. }
  243. else
  244. {
  245. enable_callback_t* func = (EnableCallbackRegistry::getValue(cb.function_name));
  246. if (func)
  247. {
  248. if (cb.parameter.isProvided())
  249. return boost::bind((*func), this, cb.parameter);
  250. else
  251. return enable_signal_t::slot_type(*func);
  252. }
  253. }
  254. return default_enable_handler;
  255. }
  256. // virtual
  257. void LLUICtrl::onMouseEnter(S32 x, S32 y, MASK mask)
  258. {
  259. if (mMouseEnterSignal)
  260. {
  261. (*mMouseEnterSignal)(this, getValue());
  262. }
  263. }
  264. // virtual
  265. void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask)
  266. {
  267. if(mMouseLeaveSignal)
  268. {
  269. (*mMouseLeaveSignal)(this, getValue());
  270. }
  271. }
  272. //virtual
  273. BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask)
  274. {
  275. BOOL handled = LLView::handleMouseDown(x,y,mask);
  276. if (mMouseDownSignal)
  277. {
  278. (*mMouseDownSignal)(this,x,y,mask);
  279. }
  280. return handled;
  281. }
  282. //virtual
  283. BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask)
  284. {
  285. BOOL handled = LLView::handleMouseUp(x,y,mask);
  286. if (mMouseUpSignal)
  287. {
  288. (*mMouseUpSignal)(this,x,y,mask);
  289. }
  290. return handled;
  291. }
  292. //virtual
  293. BOOL LLUICtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
  294. {
  295. BOOL handled = LLView::handleRightMouseDown(x,y,mask);
  296. if (mRightMouseDownSignal)
  297. {
  298. (*mRightMouseDownSignal)(this,x,y,mask);
  299. }
  300. return handled;
  301. }
  302. //virtual
  303. BOOL LLUICtrl::handleRightMouseUp(S32 x, S32 y, MASK mask)
  304. {
  305. BOOL handled = LLView::handleRightMouseUp(x,y,mask);
  306. if(mRightMouseUpSignal)
  307. {
  308. (*mRightMouseUpSignal)(this,x,y,mask);
  309. }
  310. return handled;
  311. }
  312. BOOL LLUICtrl::handleDoubleClick(S32 x, S32 y, MASK mask)
  313. {
  314. BOOL handled = LLView::handleDoubleClick(x, y, mask);
  315. if (mDoubleClickSignal)
  316. {
  317. (*mDoubleClickSignal)(this, x, y, mask);
  318. }
  319. return handled;
  320. }
  321. // can't tab to children of a non-tab-stop widget
  322. BOOL LLUICtrl::canFocusChildren() const
  323. {
  324. return hasTabStop();
  325. }
  326. void LLUICtrl::onCommit()
  327. {
  328. if (mCommitSignal)
  329. (*mCommitSignal)(this, getValue());
  330. }
  331. //virtual
  332. BOOL LLUICtrl::isCtrl() const
  333. {
  334. return TRUE;
  335. }
  336. //virtual
  337. void LLUICtrl::setValue(const LLSD& value)
  338. {
  339. mViewModel->setValue(value);
  340. }
  341. //virtual
  342. LLSD LLUICtrl::getValue() const
  343. {
  344. return mViewModel->getValue();
  345. }
  346. /// When two widgets are displaying the same data (e.g. during a skin
  347. /// change), share their ViewModel.
  348. void LLUICtrl::shareViewModelFrom(const LLUICtrl& other)
  349. {
  350. // Because mViewModel is an LLViewModelPtr, this assignment will quietly
  351. // dispose of the previous LLViewModel -- unless it's already shared by
  352. // somebody else.
  353. mViewModel = other.mViewModel;
  354. }
  355. //virtual
  356. LLViewModel* LLUICtrl::getViewModel() const
  357. {
  358. return mViewModel;
  359. }
  360. //virtual
  361. BOOL LLUICtrl::postBuild()
  362. {
  363. //
  364. // Find all of the children that want to be in front and move them to the front
  365. //
  366. if (getChildCount() > 0)
  367. {
  368. std::vector<LLUICtrl*> childrenToMoveToFront;
  369. for (LLView::child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it)
  370. {
  371. LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(*child_it);
  372. if (uictrl && uictrl->mRequestsFront)
  373. {
  374. childrenToMoveToFront.push_back(uictrl);
  375. }
  376. }
  377. for (std::vector<LLUICtrl*>::iterator it = childrenToMoveToFront.begin(); it != childrenToMoveToFront.end(); ++it)
  378. {
  379. sendChildToFront(*it);
  380. }
  381. }
  382. return LLView::postBuild();
  383. }
  384. bool LLUICtrl::setControlValue(const LLSD& value)
  385. {
  386. if (mControlVariable)
  387. {
  388. mControlVariable->set(value);
  389. return true;
  390. }
  391. return false;
  392. }
  393. void LLUICtrl::setControlVariable(LLControlVariable* control)
  394. {
  395. if (mControlVariable)
  396. {
  397. //RN: this will happen in practice, should we try to avoid it?
  398. //llwarns << "setControlName called twice on same control!" << llendl;
  399. mControlConnection.disconnect(); // disconnect current signal
  400. mControlVariable = NULL;
  401. }
  402. if (control)
  403. {
  404. mControlVariable = control;
  405. mControlConnection = mControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("value")));
  406. setValue(mControlVariable->getValue());
  407. }
  408. }
  409. //virtual
  410. void LLUICtrl::setControlName(const std::string& control_name, LLView *context)
  411. {
  412. if (context == NULL)
  413. {
  414. context = this;
  415. }
  416. // Register new listener
  417. if (!control_name.empty())
  418. {
  419. LLControlVariable* control = context->findControl(control_name);
  420. setControlVariable(control);
  421. }
  422. }
  423. void LLUICtrl::setEnabledControlVariable(LLControlVariable* control)
  424. {
  425. if (mEnabledControlVariable)
  426. {
  427. mEnabledControlConnection.disconnect(); // disconnect current signal
  428. mEnabledControlVariable = NULL;
  429. }
  430. if (control)
  431. {
  432. mEnabledControlVariable = control;
  433. mEnabledControlConnection = mEnabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("enabled")));
  434. setEnabled(mEnabledControlVariable->getValue().asBoolean());
  435. }
  436. }
  437. void LLUICtrl::setDisabledControlVariable(LLControlVariable* control)
  438. {
  439. if (mDisabledControlVariable)
  440. {
  441. mDisabledControlConnection.disconnect(); // disconnect current signal
  442. mDisabledControlVariable = NULL;
  443. }
  444. if (control)
  445. {
  446. mDisabledControlVariable = control;
  447. mDisabledControlConnection = mDisabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("disabled")));
  448. setEnabled(!(mDisabledControlVariable->getValue().asBoolean()));
  449. }
  450. }
  451. void LLUICtrl::setMakeVisibleControlVariable(LLControlVariable* control)
  452. {
  453. if (mMakeVisibleControlVariable)
  454. {
  455. mMakeVisibleControlConnection.disconnect(); // disconnect current signal
  456. mMakeVisibleControlVariable = NULL;
  457. }
  458. if (control)
  459. {
  460. mMakeVisibleControlVariable = control;
  461. mMakeVisibleControlConnection = mMakeVisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("visible")));
  462. setVisible(mMakeVisibleControlVariable->getValue().asBoolean());
  463. }
  464. }
  465. void LLUICtrl::setMakeInvisibleControlVariable(LLControlVariable* control)
  466. {
  467. if (mMakeInvisibleControlVariable)
  468. {
  469. mMakeInvisibleControlConnection.disconnect(); // disconnect current signal
  470. mMakeInvisibleControlVariable = NULL;
  471. }
  472. if (control)
  473. {
  474. mMakeInvisibleControlVariable = control;
  475. mMakeInvisibleControlConnection = mMakeInvisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("invisible")));
  476. setVisible(!(mMakeInvisibleControlVariable->getValue().asBoolean()));
  477. }
  478. }
  479. // static
  480. bool LLUICtrl::controlListener(const LLSD& newvalue, LLHandle<LLUICtrl> handle, std::string type)
  481. {
  482. LLUICtrl* ctrl = handle.get();
  483. if (ctrl)
  484. {
  485. if (type == "value")
  486. {
  487. ctrl->setValue(newvalue);
  488. return true;
  489. }
  490. else if (type == "enabled")
  491. {
  492. ctrl->setEnabled(newvalue.asBoolean());
  493. return true;
  494. }
  495. else if(type =="disabled")
  496. {
  497. ctrl->setEnabled(!newvalue.asBoolean());
  498. return true;
  499. }
  500. else if (type == "visible")
  501. {
  502. ctrl->setVisible(newvalue.asBoolean());
  503. return true;
  504. }
  505. else if (type == "invisible")
  506. {
  507. ctrl->setVisible(!newvalue.asBoolean());
  508. return true;
  509. }
  510. }
  511. return false;
  512. }
  513. // virtual
  514. BOOL LLUICtrl::setTextArg( const std::string& key, const LLStringExplicit& text )
  515. {
  516. return FALSE;
  517. }
  518. // virtual
  519. BOOL LLUICtrl::setLabelArg( const std::string& key, const LLStringExplicit& text )
  520. {
  521. return FALSE;
  522. }
  523. // virtual
  524. LLCtrlSelectionInterface* LLUICtrl::getSelectionInterface()
  525. {
  526. return NULL;
  527. }
  528. // virtual
  529. LLCtrlListInterface* LLUICtrl::getListInterface()
  530. {
  531. return NULL;
  532. }
  533. // virtual
  534. LLCtrlScrollInterface* LLUICtrl::getScrollInterface()
  535. {
  536. return NULL;
  537. }
  538. BOOL LLUICtrl::hasFocus() const
  539. {
  540. return (gFocusMgr.childHasKeyboardFocus(this));
  541. }
  542. void LLUICtrl::setFocus(BOOL b)
  543. {
  544. // focus NEVER goes to ui ctrls that are disabled!
  545. if (!getEnabled())
  546. {
  547. return;
  548. }
  549. if( b )
  550. {
  551. if (!hasFocus())
  552. {
  553. gFocusMgr.setKeyboardFocus( this );
  554. }
  555. }
  556. else
  557. {
  558. if( gFocusMgr.childHasKeyboardFocus(this))
  559. {
  560. gFocusMgr.setKeyboardFocus( NULL );
  561. }
  562. }
  563. }
  564. // virtual
  565. void LLUICtrl::setTabStop( BOOL b )
  566. {
  567. mTabStop = b;
  568. }
  569. // virtual
  570. BOOL LLUICtrl::hasTabStop() const
  571. {
  572. return mTabStop;
  573. }
  574. // virtual
  575. BOOL LLUICtrl::acceptsTextInput() const
  576. {
  577. return FALSE;
  578. }
  579. //virtual
  580. BOOL LLUICtrl::isDirty() const
  581. {
  582. return mViewModel->isDirty();
  583. };
  584. //virtual
  585. void LLUICtrl::resetDirty()
  586. {
  587. mViewModel->resetDirty();
  588. }
  589. // virtual
  590. void LLUICtrl::onTabInto()
  591. {
  592. }
  593. // virtual
  594. void LLUICtrl::clear()
  595. {
  596. }
  597. // virtual
  598. void LLUICtrl::setIsChrome(BOOL is_chrome)
  599. {
  600. mIsChrome = is_chrome;
  601. }
  602. // virtual
  603. BOOL LLUICtrl::getIsChrome() const
  604. {
  605. LLView* parent_ctrl = getParent();
  606. while(parent_ctrl)
  607. {
  608. if(parent_ctrl->isCtrl())
  609. {
  610. break;
  611. }
  612. parent_ctrl = parent_ctrl->getParent();
  613. }
  614. if(parent_ctrl)
  615. {
  616. return mIsChrome || ((LLUICtrl*)parent_ctrl)->getIsChrome();
  617. }
  618. else
  619. {
  620. return mIsChrome ;
  621. }
  622. }
  623. // this comparator uses the crazy disambiguating logic of LLCompareByTabOrder,
  624. // but to switch up the order so that children that have the default tab group come first
  625. // and those that are prior to the default tab group come last
  626. class CompareByDefaultTabGroup: public LLCompareByTabOrder
  627. {
  628. public:
  629. CompareByDefaultTabGroup(const LLView::child_tab_order_t& order, S32 default_tab_group):
  630. LLCompareByTabOrder(order),
  631. mDefaultTabGroup(default_tab_group) {}
  632. private:
  633. /*virtual*/ bool compareTabOrders(const LLView::tab_order_t & a, const LLView::tab_order_t & b) const
  634. {
  635. S32 ag = a.first; // tab group for a
  636. S32 bg = b.first; // tab group for b
  637. // these two ifs have the effect of moving elements prior to the default tab group to the end of the list
  638. // (still sorted relative to each other, though)
  639. if(ag < mDefaultTabGroup && bg >= mDefaultTabGroup) return false;
  640. if(bg < mDefaultTabGroup && ag >= mDefaultTabGroup) return true;
  641. return a < b; // sort correctly if they're both on the same side of the default tab group
  642. }
  643. S32 mDefaultTabGroup;
  644. };
  645. // Sorter for plugging into the query.
  646. // I'd have defined it local to the one method that uses it but that broke the VS 05 compiler. -MG
  647. class LLUICtrl::DefaultTabGroupFirstSorter : public LLQuerySorter, public LLSingleton<DefaultTabGroupFirstSorter>
  648. {
  649. public:
  650. /*virtual*/ void operator() (LLView * parent, viewList_t &children) const
  651. {
  652. children.sort(CompareByDefaultTabGroup(parent->getCtrlOrder(), parent->getDefaultTabGroup()));
  653. }
  654. };
  655. LLFastTimer::DeclareTimer FTM_FOCUS_FIRST_ITEM("Focus First Item");
  656. BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields, BOOL focus_flash)
  657. {
  658. LLFastTimer _(FTM_FOCUS_FIRST_ITEM);
  659. // try to select default tab group child
  660. LLCtrlQuery query = getTabOrderQuery();
  661. // sort things such that the default tab group is at the front
  662. query.setSorter(DefaultTabGroupFirstSorter::getInstance());
  663. child_list_t result = query(this);
  664. if(result.size() > 0)
  665. {
  666. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front());
  667. if(!ctrl->hasFocus())
  668. {
  669. ctrl->setFocus(TRUE);
  670. ctrl->onTabInto();
  671. if(focus_flash)
  672. {
  673. gFocusMgr.triggerFocusFlash();
  674. }
  675. }
  676. return TRUE;
  677. }
  678. // search for text field first
  679. if(prefer_text_fields)
  680. {
  681. LLCtrlQuery query = getTabOrderQuery();
  682. query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
  683. child_list_t result = query(this);
  684. if(result.size() > 0)
  685. {
  686. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front());
  687. if(!ctrl->hasFocus())
  688. {
  689. ctrl->setFocus(TRUE);
  690. ctrl->onTabInto();
  691. gFocusMgr.triggerFocusFlash();
  692. }
  693. return TRUE;
  694. }
  695. }
  696. // no text field found, or we don't care about text fields
  697. result = getTabOrderQuery().run(this);
  698. if(result.size() > 0)
  699. {
  700. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front());
  701. if(!ctrl->hasFocus())
  702. {
  703. ctrl->setFocus(TRUE);
  704. ctrl->onTabInto();
  705. gFocusMgr.triggerFocusFlash();
  706. }
  707. return TRUE;
  708. }
  709. return FALSE;
  710. }
  711. BOOL LLUICtrl::focusLastItem(BOOL prefer_text_fields)
  712. {
  713. // search for text field first
  714. if(prefer_text_fields)
  715. {
  716. LLCtrlQuery query = getTabOrderQuery();
  717. query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
  718. child_list_t result = query(this);
  719. if(result.size() > 0)
  720. {
  721. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.back());
  722. if(!ctrl->hasFocus())
  723. {
  724. ctrl->setFocus(TRUE);
  725. ctrl->onTabInto();
  726. gFocusMgr.triggerFocusFlash();
  727. }
  728. return TRUE;
  729. }
  730. }
  731. // no text field found, or we don't care about text fields
  732. child_list_t result = getTabOrderQuery().run(this);
  733. if(result.size() > 0)
  734. {
  735. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.back());
  736. if(!ctrl->hasFocus())
  737. {
  738. ctrl->setFocus(TRUE);
  739. ctrl->onTabInto();
  740. gFocusMgr.triggerFocusFlash();
  741. }
  742. return TRUE;
  743. }
  744. return FALSE;
  745. }
  746. BOOL LLUICtrl::focusNextItem(BOOL text_fields_only)
  747. {
  748. // this assumes that this method is called on the focus root.
  749. LLCtrlQuery query = getTabOrderQuery();
  750. static LLUICachedControl<bool> tab_to_text_fields_only ("TabToTextFieldsOnly", false);
  751. if(text_fields_only || tab_to_text_fields_only)
  752. {
  753. query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
  754. }
  755. child_list_t result = query(this);
  756. return focusNext(result);
  757. }
  758. BOOL LLUICtrl::focusPrevItem(BOOL text_fields_only)
  759. {
  760. // this assumes that this method is called on the focus root.
  761. LLCtrlQuery query = getTabOrderQuery();
  762. static LLUICachedControl<bool> tab_to_text_fields_only ("TabToTextFieldsOnly", false);
  763. if(text_fields_only || tab_to_text_fields_only)
  764. {
  765. query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
  766. }
  767. child_list_t result = query(this);
  768. return focusPrev(result);
  769. }
  770. LLUICtrl* LLUICtrl::findRootMostFocusRoot()
  771. {
  772. LLUICtrl* focus_root = NULL;
  773. LLUICtrl* next_view = this;
  774. while(next_view && next_view->hasTabStop())
  775. {
  776. if (next_view->isFocusRoot())
  777. {
  778. focus_root = next_view;
  779. }
  780. next_view = next_view->getParentUICtrl();
  781. }
  782. return focus_root;
  783. }
  784. // Skip over any parents that are not LLUICtrl's
  785. // Used in focus logic since only LLUICtrl elements can have focus
  786. LLUICtrl* LLUICtrl::getParentUICtrl() const
  787. {
  788. LLView* parent = getParent();
  789. while (parent)
  790. {
  791. if (parent->isCtrl())
  792. {
  793. return (LLUICtrl*)(parent);
  794. }
  795. else
  796. {
  797. parent = parent->getParent();
  798. }
  799. }
  800. return NULL;
  801. }
  802. bool LLUICtrl::findHelpTopic(std::string& help_topic_out)
  803. {
  804. LLUICtrl* ctrl = this;
  805. // search back through the control's parents for a panel
  806. // or tab with a help_topic string defined
  807. while (ctrl)
  808. {
  809. LLPanel *panel = dynamic_cast<LLPanel *>(ctrl);
  810. if (panel)
  811. {
  812. // does the panel have a sub-panel with a help topic?
  813. LLPanel *subpanel = panel->childGetVisiblePanelWithHelp();
  814. if (subpanel)
  815. {
  816. help_topic_out = subpanel->getHelpTopic();
  817. return true; // success (subpanel)
  818. }
  819. // does the panel have an active tab with a help topic?
  820. LLPanel *tab = panel->childGetVisibleTabWithHelp();
  821. if (tab)
  822. {
  823. help_topic_out = tab->getHelpTopic();
  824. return true; // success (tab)
  825. }
  826. // otherwise, does the panel have a help topic itself?
  827. if (!panel->getHelpTopic().empty())
  828. {
  829. help_topic_out = panel->getHelpTopic();
  830. return true; // success (panel)
  831. }
  832. }
  833. ctrl = ctrl->getParentUICtrl();
  834. }
  835. return false; // no help topic found
  836. }
  837. // *TODO: Deprecate; for backwards compatability only:
  838. boost::signals2::connection LLUICtrl::setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data)
  839. {
  840. return setCommitCallback( boost::bind(cb, _1, data));
  841. }
  842. boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb )
  843. {
  844. if (!mValidateSignal) mValidateSignal = new enable_signal_t();
  845. return mValidateSignal->connect(boost::bind(cb, _2));
  846. }
  847. // virtual
  848. void LLUICtrl::setTentative(BOOL b)
  849. {
  850. mTentative = b;
  851. }
  852. // virtual
  853. BOOL LLUICtrl::getTentative() const
  854. {
  855. return mTentative;
  856. }
  857. // virtual
  858. void LLUICtrl::setColor(const LLColor4& color)
  859. { }
  860. F32 LLUICtrl::getCurrentTransparency()
  861. {
  862. F32 alpha = 0;
  863. switch(mTransparencyType)
  864. {
  865. case TT_DEFAULT:
  866. alpha = getDrawContext().mAlpha;
  867. break;
  868. case TT_ACTIVE:
  869. alpha = sActiveControlTransparency;
  870. break;
  871. case TT_INACTIVE:
  872. alpha = sInactiveControlTransparency;
  873. break;
  874. case TT_FADING:
  875. alpha = sInactiveControlTransparency / 2;
  876. break;
  877. }
  878. return alpha;
  879. }
  880. void LLUICtrl::setTransparencyType(ETypeTransparency type)
  881. {
  882. mTransparencyType = type;
  883. }
  884. boost::signals2::connection LLUICtrl::setCommitCallback(const CommitCallbackParam& cb)
  885. {
  886. return setCommitCallback(initCommitCallback(cb));
  887. }
  888. boost::signals2::connection LLUICtrl::setValidateCallback(const EnableCallbackParam& cb)
  889. {
  890. return setValidateCallback(initEnableCallback(cb));
  891. }
  892. boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb )
  893. {
  894. if (!mCommitSignal) mCommitSignal = new commit_signal_t();
  895. return mCommitSignal->connect(cb);
  896. }
  897. boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb )
  898. {
  899. if (!mValidateSignal) mValidateSignal = new enable_signal_t();
  900. return mValidateSignal->connect(cb);
  901. }
  902. boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb )
  903. {
  904. if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t();
  905. return mMouseEnterSignal->connect(cb);
  906. }
  907. boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb )
  908. {
  909. if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t();
  910. return mMouseLeaveSignal->connect(cb);
  911. }
  912. boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
  913. {
  914. if (!mMouseDownSignal) mMouseDownSignal = new mouse_signal_t();
  915. return mMouseDownSignal->connect(cb);
  916. }
  917. boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t::slot_type& cb )
  918. {
  919. if (!mMouseUpSignal) mMouseUpSignal = new mouse_signal_t();
  920. return mMouseUpSignal->connect(cb);
  921. }
  922. boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_signal_t::slot_type& cb )
  923. {
  924. if (!mRightMouseDownSignal) mRightMouseDownSignal = new mouse_signal_t();
  925. return mRightMouseDownSignal->connect(cb);
  926. }
  927. boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signal_t::slot_type& cb )
  928. {
  929. if (!mRightMouseUpSignal) mRightMouseUpSignal = new mouse_signal_t();
  930. return mRightMouseUpSignal->connect(cb);
  931. }
  932. boost::signals2::connection LLUICtrl::setDoubleClickCallback( const mouse_signal_t::slot_type& cb )
  933. {
  934. if (!mDoubleClickSignal) mDoubleClickSignal = new mouse_signal_t();
  935. return mDoubleClickSignal->connect(cb);
  936. }
  937. void LLUICtrl::addInfo(LLSD & info)
  938. {
  939. LLView::addInfo(info);
  940. info["value"] = getValue();
  941. }