lluictrl.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:24k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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=viewergpl$
  7.  * 
  8.  * Copyright (c) 2001-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. #include "linden_common.h"
  34. #define LLUICTRL_CPP
  35. #include "lluictrl.h"
  36. #include "llfocusmgr.h"
  37. #include "llpanel.h"
  38. #include "lluictrlfactory.h"
  39. static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");
  40. // Compiler optimization, generate extern template
  41. template class LLUICtrl* LLView::getChild<class LLUICtrl>(
  42. const std::string& name, BOOL recurse) const;
  43. LLUICtrl::CallbackParam::CallbackParam()
  44. : name("name"),
  45. function_name("function"),
  46. parameter("parameter"),
  47. control_name("control") // Shortcut to control -> "control_name" for backwards compatability
  48. {
  49. addSynonym(parameter, "userdata");
  50. }
  51. LLUICtrl::EnableControls::EnableControls()
  52. : enabled("enabled_control"),
  53. disabled("disabled_control")
  54. {}
  55. LLUICtrl::ControlVisibility::ControlVisibility()
  56. : visible("visibility_control"),
  57. invisible("invisibility_control")
  58. {
  59. addSynonym(visible, "visiblity_control");
  60. addSynonym(invisible, "invisiblity_control");
  61. }
  62. LLUICtrl::Params::Params()
  63. : tab_stop("tab_stop", true),
  64. chrome("chrome", false),
  65. label("label"),
  66. initial_value("value"),
  67. init_callback("init_callback"),
  68. commit_callback("commit_callback"),
  69. validate_callback("validate_callback"),
  70. mouseenter_callback("mouseenter_callback"),
  71. mouseleave_callback("mouseleave_callback"),
  72. control_name("control_name"),
  73. font("font", LLFontGL::getFontSansSerif()),
  74. font_halign("halign"),
  75. font_valign("valign"),
  76. length("length"),  // ignore LLXMLNode cruft
  77. type("type")    // ignore LLXMLNode cruft
  78. {
  79. addSynonym(initial_value, "initial_value");
  80. }
  81. // NOTE: the LLFocusableElement implementation has been moved from here to llfocusmgr.cpp.
  82. //static 
  83. const LLUICtrl::Params& LLUICtrl::getDefaultParams()
  84. {
  85. return LLUICtrlFactory::getDefaultParams<LLUICtrl>();
  86. }
  87. LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel) 
  88. : LLView(p),
  89. mTentative(FALSE),
  90. mIsChrome(FALSE),
  91.     mViewModel(viewmodel),
  92. mControlVariable(NULL),
  93. mEnabledControlVariable(NULL),
  94. mDisabledControlVariable(NULL),
  95. mMakeVisibleControlVariable(NULL),
  96. mMakeInvisibleControlVariable(NULL),
  97. mCommitSignal(NULL),
  98. mValidateSignal(NULL),
  99. mMouseEnterSignal(NULL),
  100. mMouseLeaveSignal(NULL),
  101. mMouseDownSignal(NULL),
  102. mMouseUpSignal(NULL),
  103. mRightMouseDownSignal(NULL),
  104. mRightMouseUpSignal(NULL),
  105. mDoubleClickSignal(NULL)
  106. {
  107. mUICtrlHandle.bind(this);
  108. }
  109. void LLUICtrl::initFromParams(const Params& p)
  110. {
  111. LLView::initFromParams(p);
  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. bool LLUICtrl::setControlValue(const LLSD& value)
  361. {
  362. if (mControlVariable)
  363. {
  364. mControlVariable->set(value);
  365. return true;
  366. }
  367. return false;
  368. }
  369. void LLUICtrl::setControlVariable(LLControlVariable* control)
  370. {
  371. if (mControlVariable)
  372. {
  373. //RN: this will happen in practice, should we try to avoid it?
  374. //llwarns << "setControlName called twice on same control!" << llendl;
  375. mControlConnection.disconnect(); // disconnect current signal
  376. mControlVariable = NULL;
  377. }
  378. if (control)
  379. {
  380. mControlVariable = control;
  381. mControlConnection = mControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("value")));
  382. setValue(mControlVariable->getValue());
  383. }
  384. }
  385. //virtual
  386. void LLUICtrl::setControlName(const std::string& control_name, LLView *context)
  387. {
  388. if (context == NULL)
  389. {
  390. context = this;
  391. }
  392. // Register new listener
  393. if (!control_name.empty())
  394. {
  395. LLControlVariable* control = context->findControl(control_name);
  396. setControlVariable(control);
  397. }
  398. }
  399. void LLUICtrl::setEnabledControlVariable(LLControlVariable* control)
  400. {
  401. if (mEnabledControlVariable)
  402. {
  403. mEnabledControlConnection.disconnect(); // disconnect current signal
  404. mEnabledControlVariable = NULL;
  405. }
  406. if (control)
  407. {
  408. mEnabledControlVariable = control;
  409. mEnabledControlConnection = mEnabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("enabled")));
  410. setEnabled(mEnabledControlVariable->getValue().asBoolean());
  411. }
  412. }
  413. void LLUICtrl::setDisabledControlVariable(LLControlVariable* control)
  414. {
  415. if (mDisabledControlVariable)
  416. {
  417. mDisabledControlConnection.disconnect(); // disconnect current signal
  418. mDisabledControlVariable = NULL;
  419. }
  420. if (control)
  421. {
  422. mDisabledControlVariable = control;
  423. mDisabledControlConnection = mDisabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("disabled")));
  424. setEnabled(!(mDisabledControlVariable->getValue().asBoolean()));
  425. }
  426. }
  427. void LLUICtrl::setMakeVisibleControlVariable(LLControlVariable* control)
  428. {
  429. if (mMakeVisibleControlVariable)
  430. {
  431. mMakeVisibleControlConnection.disconnect(); // disconnect current signal
  432. mMakeVisibleControlVariable = NULL;
  433. }
  434. if (control)
  435. {
  436. mMakeVisibleControlVariable = control;
  437. mMakeVisibleControlConnection = mMakeVisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("visible")));
  438. setVisible(mMakeVisibleControlVariable->getValue().asBoolean());
  439. }
  440. }
  441. void LLUICtrl::setMakeInvisibleControlVariable(LLControlVariable* control)
  442. {
  443. if (mMakeInvisibleControlVariable)
  444. {
  445. mMakeInvisibleControlConnection.disconnect(); // disconnect current signal
  446. mMakeInvisibleControlVariable = NULL;
  447. }
  448. if (control)
  449. {
  450. mMakeInvisibleControlVariable = control;
  451. mMakeInvisibleControlConnection = mMakeInvisibleControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getUICtrlHandle(), std::string("invisible")));
  452. setVisible(!(mMakeInvisibleControlVariable->getValue().asBoolean()));
  453. }
  454. }
  455. // static
  456. bool LLUICtrl::controlListener(const LLSD& newvalue, LLHandle<LLUICtrl> handle, std::string type)
  457. {
  458. LLUICtrl* ctrl = handle.get();
  459. if (ctrl)
  460. {
  461. if (type == "value")
  462. {
  463. ctrl->setValue(newvalue);
  464. return true;
  465. }
  466. else if (type == "enabled")
  467. {
  468. ctrl->setEnabled(newvalue.asBoolean());
  469. return true;
  470. }
  471. else if(type =="disabled")
  472. {
  473. ctrl->setEnabled(!newvalue.asBoolean());
  474. return true;
  475. }
  476. else if (type == "visible")
  477. {
  478. ctrl->setVisible(newvalue.asBoolean());
  479. return true;
  480. }
  481. else if (type == "invisible")
  482. {
  483. ctrl->setVisible(!newvalue.asBoolean());
  484. return true;
  485. }
  486. }
  487. return false;
  488. }
  489. // virtual
  490. BOOL LLUICtrl::setTextArg( const std::string& key, const LLStringExplicit& text ) 
  491. return FALSE; 
  492. }
  493. // virtual
  494. BOOL LLUICtrl::setLabelArg( const std::string& key, const LLStringExplicit& text ) 
  495. return FALSE; 
  496. }
  497. // virtual
  498. LLCtrlSelectionInterface* LLUICtrl::getSelectionInterface()
  499. return NULL; 
  500. }
  501. // virtual
  502. LLCtrlListInterface* LLUICtrl::getListInterface()
  503. return NULL; 
  504. }
  505. // virtual
  506. LLCtrlScrollInterface* LLUICtrl::getScrollInterface()
  507. return NULL; 
  508. }
  509. BOOL LLUICtrl::hasFocus() const
  510. {
  511. return (gFocusMgr.childHasKeyboardFocus(this));
  512. }
  513. void LLUICtrl::setFocus(BOOL b)
  514. {
  515. // focus NEVER goes to ui ctrls that are disabled!
  516. if (!getEnabled())
  517. {
  518. return;
  519. }
  520. if( b )
  521. {
  522. if (!hasFocus())
  523. {
  524. gFocusMgr.setKeyboardFocus( this );
  525. }
  526. }
  527. else
  528. {
  529. if( gFocusMgr.childHasKeyboardFocus(this))
  530. {
  531. gFocusMgr.setKeyboardFocus( NULL );
  532. }
  533. }
  534. }
  535. // virtual
  536. void LLUICtrl::setTabStop( BOOL b )
  537. mTabStop = b;
  538. }
  539. // virtual
  540. BOOL LLUICtrl::hasTabStop() const
  541. return mTabStop;
  542. }
  543. // virtual
  544. BOOL LLUICtrl::acceptsTextInput() const
  545. return FALSE; 
  546. }
  547. //virtual
  548. BOOL LLUICtrl::isDirty() const
  549. {
  550. return mViewModel->isDirty();
  551. };
  552. //virtual
  553. void LLUICtrl::resetDirty()
  554. {
  555.     mViewModel->resetDirty();
  556. }
  557. // virtual
  558. void LLUICtrl::onTabInto()
  559. {
  560. }
  561. // virtual
  562. void LLUICtrl::clear()
  563. {
  564. }
  565. // virtual
  566. void LLUICtrl::setIsChrome(BOOL is_chrome)
  567. {
  568. mIsChrome = is_chrome; 
  569. }
  570. // virtual
  571. BOOL LLUICtrl::getIsChrome() const
  572. LLView* parent_ctrl = getParent();
  573. while(parent_ctrl)
  574. {
  575. if(parent_ctrl->isCtrl())
  576. {
  577. break;
  578. }
  579. parent_ctrl = parent_ctrl->getParent();
  580. }
  581. if(parent_ctrl)
  582. {
  583. return mIsChrome || ((LLUICtrl*)parent_ctrl)->getIsChrome();
  584. }
  585. else
  586. {
  587. return mIsChrome ; 
  588. }
  589. }
  590. // this comparator uses the crazy disambiguating logic of LLCompareByTabOrder,
  591. // but to switch up the order so that children that have the default tab group come first
  592. // and those that are prior to the default tab group come last
  593. class CompareByDefaultTabGroup: public LLCompareByTabOrder
  594. {
  595. public:
  596. CompareByDefaultTabGroup(LLView::child_tab_order_t order, S32 default_tab_group):
  597. LLCompareByTabOrder(order),
  598. mDefaultTabGroup(default_tab_group) {}
  599. private:
  600. /*virtual*/ bool compareTabOrders(const LLView::tab_order_t & a, const LLView::tab_order_t & b) const
  601. {
  602. S32 ag = a.first; // tab group for a
  603. S32 bg = b.first; // tab group for b
  604. // these two ifs have the effect of moving elements prior to the default tab group to the end of the list 
  605. // (still sorted relative to each other, though)
  606. if(ag < mDefaultTabGroup && bg >= mDefaultTabGroup) return false;
  607. if(bg < mDefaultTabGroup && ag >= mDefaultTabGroup) return true;
  608. return a < b;  // sort correctly if they're both on the same side of the default tab group
  609. }
  610. S32 mDefaultTabGroup;
  611. };
  612. // Sorter for plugging into the query.
  613. // I'd have defined it local to the one method that uses it but that broke the VS 05 compiler. -MG
  614. class LLUICtrl::DefaultTabGroupFirstSorter : public LLQuerySorter, public LLSingleton<DefaultTabGroupFirstSorter>
  615. {
  616. public:
  617. /*virtual*/ void operator() (LLView * parent, viewList_t &children) const
  618. {
  619. children.sort(CompareByDefaultTabGroup(parent->getCtrlOrder(), parent->getDefaultTabGroup()));
  620. }
  621. };
  622. BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields, BOOL focus_flash)
  623. {
  624. // try to select default tab group child
  625. LLCtrlQuery query = getTabOrderQuery();
  626. // sort things such that the default tab group is at the front
  627. query.setSorter(DefaultTabGroupFirstSorter::getInstance());
  628. child_list_t result = query(this);
  629. if(result.size() > 0)
  630. {
  631. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front());
  632. if(!ctrl->hasFocus())
  633. {
  634. ctrl->setFocus(TRUE);
  635. ctrl->onTabInto();  
  636. if(focus_flash)
  637. {
  638. gFocusMgr.triggerFocusFlash();
  639. }
  640. }
  641. return TRUE;
  642. }
  643. // search for text field first
  644. if(prefer_text_fields)
  645. {
  646. LLCtrlQuery query = getTabOrderQuery();
  647. query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
  648. child_list_t result = query(this);
  649. if(result.size() > 0)
  650. {
  651. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front());
  652. if(!ctrl->hasFocus())
  653. {
  654. ctrl->setFocus(TRUE);
  655. ctrl->onTabInto();  
  656. gFocusMgr.triggerFocusFlash();
  657. }
  658. return TRUE;
  659. }
  660. }
  661. // no text field found, or we don't care about text fields
  662. result = getTabOrderQuery().run(this);
  663. if(result.size() > 0)
  664. {
  665. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.front());
  666. if(!ctrl->hasFocus())
  667. {
  668. ctrl->setFocus(TRUE);
  669. ctrl->onTabInto();  
  670. gFocusMgr.triggerFocusFlash();
  671. }
  672. return TRUE;
  673. }
  674. return FALSE;
  675. }
  676. BOOL LLUICtrl::focusLastItem(BOOL prefer_text_fields)
  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.back());
  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. child_list_t result = getTabOrderQuery().run(this);
  698. if(result.size() > 0)
  699. {
  700. LLUICtrl * ctrl = static_cast<LLUICtrl*>(result.back());
  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::focusNextItem(BOOL text_fields_only)
  712. {
  713. // this assumes that this method is called on the focus root.
  714. LLCtrlQuery query = getTabOrderQuery();
  715. static LLUICachedControl<bool> tab_to_text_fields_only ("TabToTextFieldsOnly", false);
  716. if(text_fields_only || tab_to_text_fields_only)
  717. {
  718. query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
  719. }
  720. child_list_t result = query(this);
  721. return focusNext(result);
  722. }
  723. BOOL LLUICtrl::focusPrevItem(BOOL text_fields_only)
  724. {
  725. // this assumes that this method is called on the focus root.
  726. LLCtrlQuery query = getTabOrderQuery();
  727. static LLUICachedControl<bool> tab_to_text_fields_only ("TabToTextFieldsOnly", false);
  728. if(text_fields_only || tab_to_text_fields_only)
  729. {
  730. query.addPreFilter(LLUICtrl::LLTextInputFilter::getInstance());
  731. }
  732. child_list_t result = query(this);
  733. return focusPrev(result);
  734. }
  735. LLUICtrl* LLUICtrl::findRootMostFocusRoot()
  736. {
  737. LLUICtrl* focus_root = NULL;
  738. LLUICtrl* next_view = this;
  739. while(next_view)
  740. {
  741. if (next_view->isFocusRoot())
  742. {
  743. focus_root = next_view;
  744. }
  745. next_view = next_view->getParentUICtrl();
  746. }
  747. return focus_root;
  748. }
  749. // Skip over any parents that are not LLUICtrl's
  750. //  Used in focus logic since only LLUICtrl elements can have focus
  751. LLUICtrl* LLUICtrl::getParentUICtrl() const
  752. {
  753. LLView* parent = getParent();
  754. while (parent)
  755. {
  756. if (parent->isCtrl())
  757. {
  758. return (LLUICtrl*)(parent);
  759. }
  760. else
  761. {
  762. parent =  parent->getParent();
  763. }
  764. }
  765. return NULL;
  766. }
  767. bool LLUICtrl::findHelpTopic(std::string& help_topic_out)
  768. {
  769. LLUICtrl* ctrl = this;
  770. // search back through the control's parents for a panel
  771. // or tab with a help_topic string defined
  772. while (ctrl)
  773. {
  774. LLPanel *panel = dynamic_cast<LLPanel *>(ctrl);
  775. if (panel)
  776. {
  777. // does the panel have a sub-panel with a help topic?
  778. LLPanel *subpanel = panel->childGetVisiblePanelWithHelp();
  779. if (subpanel)
  780. {
  781. help_topic_out = subpanel->getHelpTopic();
  782. return true; // success (subpanel)
  783. }
  784. // does the panel have an active tab with a help topic?
  785. LLPanel *tab = panel->childGetVisibleTabWithHelp();
  786. if (tab)
  787. {
  788. help_topic_out = tab->getHelpTopic();
  789. return true; // success (tab)
  790. }
  791. // otherwise, does the panel have a help topic itself?
  792. if (!panel->getHelpTopic().empty())
  793. {
  794. help_topic_out = panel->getHelpTopic();
  795. return true; // success (panel)
  796. }
  797. }
  798. ctrl = ctrl->getParentUICtrl();
  799. }
  800. return false; // no help topic found
  801. }
  802. // *TODO: Deprecate; for backwards compatability only:
  803. boost::signals2::connection LLUICtrl::setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data)
  804. {
  805. return setCommitCallback( boost::bind(cb, _1, data));
  806. }
  807. boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb )
  808. {
  809. if (!mValidateSignal) mValidateSignal = new enable_signal_t();
  810. return mValidateSignal->connect(boost::bind(cb, _2));
  811. }
  812. // virtual
  813. void LLUICtrl::setTentative(BOOL b)
  814. mTentative = b; 
  815. }
  816. // virtual
  817. BOOL LLUICtrl::getTentative() const
  818. return mTentative; 
  819. }
  820. // virtual
  821. void LLUICtrl::setColor(const LLColor4& color)
  822. { }
  823. boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb ) 
  824. if (!mCommitSignal) mCommitSignal = new commit_signal_t();
  825. return mCommitSignal->connect(cb); 
  826. }
  827. boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb ) 
  828. if (!mValidateSignal) mValidateSignal = new enable_signal_t();
  829. return mValidateSignal->connect(cb); 
  830. }
  831. boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb ) 
  832. if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t();
  833. return mMouseEnterSignal->connect(cb); 
  834. }
  835. boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb ) 
  836. if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t();
  837. return mMouseLeaveSignal->connect(cb); 
  838. }
  839. boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) 
  840. if (!mMouseDownSignal) mMouseDownSignal = new mouse_signal_t();
  841. return mMouseDownSignal->connect(cb); 
  842. }
  843. boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t::slot_type& cb ) 
  844. if (!mMouseUpSignal) mMouseUpSignal = new mouse_signal_t();
  845. return mMouseUpSignal->connect(cb); 
  846. }
  847. boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_signal_t::slot_type& cb ) 
  848. if (!mRightMouseDownSignal) mRightMouseDownSignal = new mouse_signal_t();
  849. return mRightMouseDownSignal->connect(cb); 
  850. }
  851. boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signal_t::slot_type& cb ) 
  852. if (!mRightMouseUpSignal) mRightMouseUpSignal = new mouse_signal_t();
  853. return mRightMouseUpSignal->connect(cb); 
  854. }
  855. boost::signals2::connection LLUICtrl::setDoubleClickCallback( const mouse_signal_t::slot_type& cb ) 
  856. if (!mDoubleClickSignal) mDoubleClickSignal = new mouse_signal_t();
  857. return mDoubleClickSignal->connect(cb); 
  858. }