PageRenderTime 170ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llui/llpanel.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1050 lines | 821 code | 138 blank | 91 comment | 128 complexity | 6c14c17f8ae69d0fc369d72dfb0de0f0 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llpanel.cpp
  3. * @brief LLPanel base class
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. // Opaque view with a background and a border. Can contain LLUICtrls.
  27. #include "linden_common.h"
  28. #define LLPANEL_CPP
  29. #include "llpanel.h"
  30. #include "llfocusmgr.h"
  31. #include "llfontgl.h"
  32. #include "llrect.h"
  33. #include "llerror.h"
  34. #include "lldir.h"
  35. #include "lltimer.h"
  36. #include "llaccordionctrltab.h"
  37. #include "llbutton.h"
  38. #include "llmenugl.h"
  39. //#include "llstatusbar.h"
  40. #include "llui.h"
  41. #include "llkeyboard.h"
  42. #include "lllineeditor.h"
  43. #include "llcontrol.h"
  44. #include "lltextbox.h"
  45. #include "lluictrl.h"
  46. #include "lluictrlfactory.h"
  47. #include "llviewborder.h"
  48. #include "lltabcontainer.h"
  49. static LLDefaultChildRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML);
  50. LLPanel::factory_stack_t LLPanel::sFactoryStack;
  51. // Compiler optimization, generate extern template
  52. template class LLPanel* LLView::getChild<class LLPanel>(
  53. const std::string& name, BOOL recurse) const;
  54. LLPanel::LocalizedString::LocalizedString()
  55. : name("name"),
  56. value("value")
  57. {}
  58. const LLPanel::Params& LLPanel::getDefaultParams()
  59. {
  60. return LLUICtrlFactory::getDefaultParams<LLPanel>();
  61. }
  62. LLPanel::Params::Params()
  63. : has_border("border", false),
  64. border(""),
  65. background_visible("background_visible", false),
  66. background_opaque("background_opaque", false),
  67. bg_opaque_color("bg_opaque_color"),
  68. bg_alpha_color("bg_alpha_color"),
  69. bg_opaque_image_overlay("bg_opaque_image_overlay"),
  70. bg_alpha_image_overlay("bg_alpha_image_overlay"),
  71. bg_opaque_image("bg_opaque_image"),
  72. bg_alpha_image("bg_alpha_image"),
  73. min_width("min_width", 100),
  74. min_height("min_height", 100),
  75. strings("string"),
  76. filename("filename"),
  77. class_name("class"),
  78. help_topic("help_topic"),
  79. visible_callback("visible_callback"),
  80. accepts_badge("accepts_badge")
  81. {
  82. addSynonym(background_visible, "bg_visible");
  83. addSynonym(has_border, "border_visible");
  84. addSynonym(label, "title");
  85. }
  86. LLPanel::LLPanel(const LLPanel::Params& p)
  87. : LLUICtrl(p),
  88. LLBadgeHolder(p.accepts_badge),
  89. mBgVisible(p.background_visible),
  90. mBgOpaque(p.background_opaque),
  91. mBgOpaqueColor(p.bg_opaque_color()),
  92. mBgAlphaColor(p.bg_alpha_color()),
  93. mBgOpaqueImageOverlay(p.bg_opaque_image_overlay),
  94. mBgAlphaImageOverlay(p.bg_alpha_image_overlay),
  95. mBgOpaqueImage(p.bg_opaque_image()),
  96. mBgAlphaImage(p.bg_alpha_image()),
  97. mDefaultBtn(NULL),
  98. mBorder(NULL),
  99. mLabel(p.label),
  100. mHelpTopic(p.help_topic),
  101. mCommitCallbackRegistrar(false),
  102. mEnableCallbackRegistrar(false),
  103. mXMLFilename(p.filename),
  104. mVisibleSignal(NULL)
  105. // *NOTE: Be sure to also change LLPanel::initFromParams(). We have too
  106. // many classes derived from LLPanel to retrofit them all to pass in params.
  107. {
  108. if (p.has_border)
  109. {
  110. addBorder(p.border);
  111. }
  112. }
  113. LLPanel::~LLPanel()
  114. {
  115. delete mVisibleSignal;
  116. }
  117. // virtual
  118. BOOL LLPanel::isPanel() const
  119. {
  120. return TRUE;
  121. }
  122. void LLPanel::addBorder(LLViewBorder::Params p)
  123. {
  124. removeBorder();
  125. p.rect = getLocalRect();
  126. mBorder = LLUICtrlFactory::create<LLViewBorder>(p);
  127. addChild( mBorder );
  128. }
  129. void LLPanel::addBorder()
  130. {
  131. LLViewBorder::Params p;
  132. p.border_thickness(LLPANEL_BORDER_WIDTH);
  133. addBorder(p);
  134. }
  135. void LLPanel::removeBorder()
  136. {
  137. if (mBorder)
  138. {
  139. removeChild(mBorder);
  140. delete mBorder;
  141. mBorder = NULL;
  142. }
  143. }
  144. // virtual
  145. void LLPanel::clearCtrls()
  146. {
  147. LLView::ctrl_list_t ctrls = getCtrlList();
  148. for (LLView::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
  149. {
  150. LLUICtrl* ctrl = *ctrl_it;
  151. ctrl->setFocus( FALSE );
  152. ctrl->setEnabled( FALSE );
  153. ctrl->clear();
  154. }
  155. }
  156. void LLPanel::setCtrlsEnabled( BOOL b )
  157. {
  158. LLView::ctrl_list_t ctrls = getCtrlList();
  159. for (LLView::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
  160. {
  161. LLUICtrl* ctrl = *ctrl_it;
  162. ctrl->setEnabled( b );
  163. }
  164. }
  165. void LLPanel::draw()
  166. {
  167. F32 alpha = getDrawContext().mAlpha;
  168. // draw background
  169. if( mBgVisible )
  170. {
  171. alpha = getCurrentTransparency();
  172. LLRect local_rect = getLocalRect();
  173. if (mBgOpaque )
  174. {
  175. // opaque, in-front look
  176. if (mBgOpaqueImage.notNull())
  177. {
  178. mBgOpaqueImage->draw( local_rect, mBgOpaqueImageOverlay % alpha );
  179. }
  180. else
  181. {
  182. // fallback to flat colors when there are no images
  183. gl_rect_2d( local_rect, mBgOpaqueColor.get() % alpha);
  184. }
  185. }
  186. else
  187. {
  188. // transparent, in-back look
  189. if (mBgAlphaImage.notNull())
  190. {
  191. mBgAlphaImage->draw( local_rect, mBgAlphaImageOverlay % alpha );
  192. }
  193. else
  194. {
  195. gl_rect_2d( local_rect, mBgAlphaColor.get() % alpha );
  196. }
  197. }
  198. }
  199. updateDefaultBtn();
  200. LLView::draw();
  201. }
  202. void LLPanel::updateDefaultBtn()
  203. {
  204. if( mDefaultBtn)
  205. {
  206. if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
  207. {
  208. LLButton* buttonp = dynamic_cast<LLButton*>(gFocusMgr.getKeyboardFocus());
  209. BOOL focus_is_child_button = buttonp && buttonp->getCommitOnReturn();
  210. // only enable default button when current focus is not a return-capturing button
  211. mDefaultBtn->setBorderEnabled(!focus_is_child_button);
  212. }
  213. else
  214. {
  215. mDefaultBtn->setBorderEnabled(FALSE);
  216. }
  217. }
  218. }
  219. void LLPanel::refresh()
  220. {
  221. // do nothing by default
  222. // but is automatically called in setFocus(TRUE)
  223. }
  224. void LLPanel::setDefaultBtn(LLButton* btn)
  225. {
  226. if (mDefaultBtn && mDefaultBtn->getEnabled())
  227. {
  228. mDefaultBtn->setBorderEnabled(FALSE);
  229. }
  230. mDefaultBtn = btn;
  231. if (mDefaultBtn)
  232. {
  233. mDefaultBtn->setBorderEnabled(TRUE);
  234. }
  235. }
  236. void LLPanel::setDefaultBtn(const std::string& id)
  237. {
  238. LLButton *button = getChild<LLButton>(id);
  239. if (button)
  240. {
  241. setDefaultBtn(button);
  242. }
  243. else
  244. {
  245. setDefaultBtn(NULL);
  246. }
  247. }
  248. BOOL LLPanel::handleKeyHere( KEY key, MASK mask )
  249. {
  250. BOOL handled = FALSE;
  251. LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
  252. // handle user hitting ESC to defocus
  253. if (key == KEY_ESCAPE)
  254. {
  255. setFocus(FALSE);
  256. return TRUE;
  257. }
  258. else if( (mask == MASK_SHIFT) && (KEY_TAB == key))
  259. {
  260. //SHIFT-TAB
  261. if (cur_focus)
  262. {
  263. LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
  264. if (focus_root)
  265. {
  266. handled = focus_root->focusPrevItem(FALSE);
  267. }
  268. }
  269. }
  270. else if( (mask == MASK_NONE ) && (KEY_TAB == key))
  271. {
  272. //TAB
  273. if (cur_focus)
  274. {
  275. LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
  276. if (focus_root)
  277. {
  278. handled = focus_root->focusNextItem(FALSE);
  279. }
  280. }
  281. }
  282. // If RETURN was pressed and something has focus, call onCommit()
  283. if (!handled && cur_focus && key == KEY_RETURN && mask == MASK_NONE)
  284. {
  285. LLButton* focused_button = dynamic_cast<LLButton*>(cur_focus);
  286. if (focused_button && focused_button->getCommitOnReturn())
  287. {
  288. // current focus is a return-capturing button,
  289. // let *that* button handle the return key
  290. handled = FALSE;
  291. }
  292. else if (mDefaultBtn && mDefaultBtn->getVisible() && mDefaultBtn->getEnabled())
  293. {
  294. // If we have a default button, click it when return is pressed
  295. mDefaultBtn->onCommit();
  296. handled = TRUE;
  297. }
  298. else if (cur_focus->acceptsTextInput())
  299. {
  300. // call onCommit for text input handling control
  301. cur_focus->onCommit();
  302. handled = TRUE;
  303. }
  304. }
  305. return handled;
  306. }
  307. void LLPanel::handleVisibilityChange ( BOOL new_visibility )
  308. {
  309. LLUICtrl::handleVisibilityChange ( new_visibility );
  310. if (mVisibleSignal)
  311. (*mVisibleSignal)(this, LLSD(new_visibility) ); // Pass BOOL as LLSD
  312. }
  313. void LLPanel::setFocus(BOOL b)
  314. {
  315. if( b && !hasFocus())
  316. {
  317. // give ourselves focus preemptively, to avoid infinite loop
  318. LLUICtrl::setFocus(TRUE);
  319. // then try to pass to first valid child
  320. focusFirstItem();
  321. }
  322. else
  323. {
  324. LLUICtrl::setFocus(b);
  325. }
  326. }
  327. void LLPanel::setBorderVisible(BOOL b)
  328. {
  329. if (mBorder)
  330. {
  331. mBorder->setVisible( b );
  332. }
  333. }
  334. LLFastTimer::DeclareTimer FTM_PANEL_CONSTRUCTION("Panel Construction");
  335. LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_node)
  336. {
  337. std::string name("panel");
  338. node->getAttributeString("name", name);
  339. std::string class_attr;
  340. node->getAttributeString("class", class_attr);
  341. LLPanel* panelp = NULL;
  342. { LLFastTimer _(FTM_PANEL_CONSTRUCTION);
  343. if(!class_attr.empty())
  344. {
  345. panelp = LLRegisterPanelClass::instance().createPanelClass(class_attr);
  346. if (!panelp)
  347. {
  348. llwarns << "Panel class \"" << class_attr << "\" not registered." << llendl;
  349. }
  350. }
  351. if (!panelp)
  352. {
  353. panelp = createFactoryPanel(name);
  354. llassert(panelp);
  355. if (!panelp)
  356. {
  357. return NULL; // :(
  358. }
  359. }
  360. }
  361. // factory panels may have registered their own factory maps
  362. if (!panelp->getFactoryMap().empty())
  363. {
  364. sFactoryStack.push_back(&panelp->getFactoryMap());
  365. }
  366. // for local registry callbacks; define in constructor, referenced in XUI or postBuild
  367. panelp->mCommitCallbackRegistrar.pushScope();
  368. panelp->mEnableCallbackRegistrar.pushScope();
  369. panelp->initPanelXML(node, parent, output_node, LLUICtrlFactory::getDefaultParams<LLPanel>());
  370. panelp->mCommitCallbackRegistrar.popScope();
  371. panelp->mEnableCallbackRegistrar.popScope();
  372. if (!panelp->getFactoryMap().empty())
  373. {
  374. sFactoryStack.pop_back();
  375. }
  376. return panelp;
  377. }
  378. void LLPanel::initFromParams(const LLPanel::Params& p)
  379. {
  380. //setting these here since panel constructor not called with params
  381. //and LLView::initFromParams will use them to set visible and enabled
  382. setVisible(p.visible);
  383. setEnabled(p.enabled);
  384. setFocusRoot(p.focus_root);
  385. setSoundFlags(p.sound_flags);
  386. // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
  387. LLUICtrl::initFromParams(p);
  388. // visible callback
  389. if (p.visible_callback.isProvided())
  390. {
  391. setVisibleCallback(initCommitCallback(p.visible_callback));
  392. }
  393. for (LLInitParam::ParamIterator<LocalizedString>::const_iterator it = p.strings.begin();
  394. it != p.strings.end();
  395. ++it)
  396. {
  397. mUIStrings[it->name] = it->value;
  398. }
  399. setLabel(p.label());
  400. setHelpTopic(p.help_topic);
  401. setShape(p.rect);
  402. parseFollowsFlags(p);
  403. setToolTip(p.tool_tip());
  404. setFromXUI(p.from_xui);
  405. mHoverCursor = getCursorFromString(p.hover_cursor);
  406. if (p.has_border)
  407. {
  408. addBorder(p.border);
  409. }
  410. // let constructors set this value if not provided
  411. if (p.use_bounding_rect.isProvided())
  412. {
  413. setUseBoundingRect(p.use_bounding_rect);
  414. }
  415. setDefaultTabGroup(p.default_tab_group);
  416. setMouseOpaque(p.mouse_opaque);
  417. setBackgroundVisible(p.background_visible);
  418. setBackgroundOpaque(p.background_opaque);
  419. setBackgroundColor(p.bg_opaque_color().get());
  420. setTransparentColor(p.bg_alpha_color().get());
  421. mBgOpaqueImage = p.bg_opaque_image();
  422. mBgAlphaImage = p.bg_alpha_image();
  423. mBgOpaqueImageOverlay = p.bg_opaque_image_overlay;
  424. mBgAlphaImageOverlay = p.bg_alpha_image_overlay;
  425. setAcceptsBadge(p.accepts_badge);
  426. }
  427. static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
  428. static LLFastTimer::DeclareTimer FTM_EXTERNAL_PANEL_LOAD("Load Extern Panel Reference");
  429. static LLFastTimer::DeclareTimer FTM_PANEL_POSTBUILD("Panel PostBuild");
  430. BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node, const LLPanel::Params& default_params)
  431. {
  432. Params params(default_params);
  433. {
  434. LLFastTimer timer(FTM_PANEL_SETUP);
  435. LLXMLNodePtr referenced_xml;
  436. std::string xml_filename = mXMLFilename;
  437. // if the panel didn't provide a filename, check the node
  438. if (xml_filename.empty())
  439. {
  440. node->getAttributeString("filename", xml_filename);
  441. setXMLFilename(xml_filename);
  442. }
  443. LLXUIParser parser;
  444. if (!xml_filename.empty())
  445. {
  446. if (output_node)
  447. {
  448. //if we are exporting, we want to export the current xml
  449. //not the referenced xml
  450. parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
  451. Params output_params(params);
  452. setupParamsForExport(output_params, parent);
  453. output_node->setName(node->getName()->mString);
  454. parser.writeXUI(output_node, output_params, &default_params);
  455. return TRUE;
  456. }
  457. LLUICtrlFactory::instance().pushFileName(xml_filename);
  458. LLFastTimer timer(FTM_EXTERNAL_PANEL_LOAD);
  459. if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml))
  460. {
  461. llwarns << "Couldn't parse panel from: " << xml_filename << llendl;
  462. return FALSE;
  463. }
  464. parser.readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName());
  465. // add children using dimensions from referenced xml for consistent layout
  466. setShape(params.rect);
  467. LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance());
  468. LLUICtrlFactory::instance().popFileName();
  469. }
  470. // ask LLUICtrlFactory for filename, since xml_filename might be empty
  471. parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
  472. if (output_node)
  473. {
  474. Params output_params(params);
  475. setupParamsForExport(output_params, parent);
  476. output_node->setName(node->getName()->mString);
  477. parser.writeXUI(output_node, output_params, &default_params);
  478. }
  479. params.from_xui = true;
  480. applyXUILayout(params, parent);
  481. {
  482. LLFastTimer timer(FTM_PANEL_CONSTRUCTION);
  483. initFromParams(params);
  484. }
  485. // add children
  486. LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node);
  487. // Connect to parent after children are built, because tab containers
  488. // do a reshape() on their child panels, which requires that the children
  489. // be built/added. JC
  490. if (parent)
  491. {
  492. S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup();
  493. parent->addChild(this, tab_group);
  494. }
  495. {
  496. LLFastTimer timer(FTM_PANEL_POSTBUILD);
  497. postBuild();
  498. }
  499. }
  500. return TRUE;
  501. }
  502. bool LLPanel::hasString(const std::string& name)
  503. {
  504. return mUIStrings.find(name) != mUIStrings.end();
  505. }
  506. std::string LLPanel::getString(const std::string& name, const LLStringUtil::format_map_t& args) const
  507. {
  508. ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
  509. if (found_it != mUIStrings.end())
  510. {
  511. // make a copy as format works in place
  512. LLUIString formatted_string = LLUIString(found_it->second);
  513. formatted_string.setArgList(args);
  514. return formatted_string.getString();
  515. }
  516. std::string err_str("Failed to find string " + name + " in panel " + getName()); //*TODO: Translate
  517. if(LLUI::sSettingGroups["config"]->getBOOL("QAMode"))
  518. {
  519. llerrs << err_str << llendl;
  520. }
  521. else
  522. {
  523. llwarns << err_str << llendl;
  524. }
  525. return LLStringUtil::null;
  526. }
  527. std::string LLPanel::getString(const std::string& name) const
  528. {
  529. ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
  530. if (found_it != mUIStrings.end())
  531. {
  532. return found_it->second;
  533. }
  534. std::string err_str("Failed to find string " + name + " in panel " + getName()); //*TODO: Translate
  535. if(LLUI::sSettingGroups["config"]->getBOOL("QAMode"))
  536. {
  537. llerrs << err_str << llendl;
  538. }
  539. else
  540. {
  541. llwarns << err_str << llendl;
  542. }
  543. return LLStringUtil::null;
  544. }
  545. void LLPanel::childSetVisible(const std::string& id, bool visible)
  546. {
  547. LLView* child = findChild<LLView>(id);
  548. if (child)
  549. {
  550. child->setVisible(visible);
  551. }
  552. }
  553. bool LLPanel::childIsVisible(const std::string& id) const
  554. {
  555. LLView* child = findChild<LLView>(id);
  556. if (child)
  557. {
  558. return (bool)child->getVisible();
  559. }
  560. return false;
  561. }
  562. void LLPanel::childSetEnabled(const std::string& id, bool enabled)
  563. {
  564. LLView* child = findChild<LLView>(id);
  565. if (child)
  566. {
  567. child->setEnabled(enabled);
  568. }
  569. }
  570. void LLPanel::childSetTentative(const std::string& id, bool tentative)
  571. {
  572. LLUICtrl* child = findChild<LLUICtrl>(id);
  573. if (child)
  574. {
  575. child->setTentative(tentative);
  576. }
  577. }
  578. bool LLPanel::childIsEnabled(const std::string& id) const
  579. {
  580. LLView* child = findChild<LLView>(id);
  581. if (child)
  582. {
  583. return (bool)child->getEnabled();
  584. }
  585. return false;
  586. }
  587. void LLPanel::childSetToolTip(const std::string& id, const std::string& msg)
  588. {
  589. LLView* child = findChild<LLView>(id);
  590. if (child)
  591. {
  592. child->setToolTip(msg);
  593. }
  594. }
  595. void LLPanel::childSetRect(const std::string& id, const LLRect& rect)
  596. {
  597. LLView* child = findChild<LLView>(id);
  598. if (child)
  599. {
  600. child->setRect(rect);
  601. }
  602. }
  603. bool LLPanel::childGetRect(const std::string& id, LLRect& rect) const
  604. {
  605. LLView* child = findChild<LLView>(id);
  606. if (child)
  607. {
  608. rect = child->getRect();
  609. return true;
  610. }
  611. return false;
  612. }
  613. void LLPanel::childSetFocus(const std::string& id, BOOL focus)
  614. {
  615. LLUICtrl* child = findChild<LLUICtrl>(id);
  616. if (child)
  617. {
  618. child->setFocus(focus);
  619. }
  620. }
  621. BOOL LLPanel::childHasFocus(const std::string& id)
  622. {
  623. LLUICtrl* child = findChild<LLUICtrl>(id);
  624. if (child)
  625. {
  626. return child->hasFocus();
  627. }
  628. else
  629. {
  630. return FALSE;
  631. }
  632. }
  633. // *TODO: Deprecate; for backwards compatability only:
  634. // Prefer getChild<LLUICtrl>("foo")->setCommitCallback(boost:bind(...)),
  635. // which takes a generic slot. Or use mCommitCallbackRegistrar.add() with
  636. // a named callback and reference it in XML.
  637. void LLPanel::childSetCommitCallback(const std::string& id, boost::function<void (LLUICtrl*,void*)> cb, void* data)
  638. {
  639. LLUICtrl* child = findChild<LLUICtrl>(id);
  640. if (child)
  641. {
  642. child->setCommitCallback(boost::bind(cb, child, data));
  643. }
  644. }
  645. void LLPanel::childSetValidate(const std::string& id, boost::function<bool (const LLSD& data)> cb)
  646. {
  647. LLUICtrl* child = findChild<LLUICtrl>(id);
  648. if (child)
  649. {
  650. child->setValidateBeforeCommit(cb);
  651. }
  652. }
  653. void LLPanel::childSetColor(const std::string& id, const LLColor4& color)
  654. {
  655. LLUICtrl* child = findChild<LLUICtrl>(id);
  656. if (child)
  657. {
  658. child->setColor(color);
  659. }
  660. }
  661. LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const
  662. {
  663. LLUICtrl* child = findChild<LLUICtrl>(id);
  664. if (child)
  665. {
  666. return child->getSelectionInterface();
  667. }
  668. return NULL;
  669. }
  670. LLCtrlListInterface* LLPanel::childGetListInterface(const std::string& id) const
  671. {
  672. LLUICtrl* child = findChild<LLUICtrl>(id);
  673. if (child)
  674. {
  675. return child->getListInterface();
  676. }
  677. return NULL;
  678. }
  679. LLCtrlScrollInterface* LLPanel::childGetScrollInterface(const std::string& id) const
  680. {
  681. LLUICtrl* child = findChild<LLUICtrl>(id);
  682. if (child)
  683. {
  684. return child->getScrollInterface();
  685. }
  686. return NULL;
  687. }
  688. void LLPanel::childSetValue(const std::string& id, LLSD value)
  689. {
  690. LLUICtrl* child = findChild<LLUICtrl>(id);
  691. if (child)
  692. {
  693. child->setValue(value);
  694. }
  695. }
  696. LLSD LLPanel::childGetValue(const std::string& id) const
  697. {
  698. LLUICtrl* child = findChild<LLUICtrl>(id);
  699. if (child)
  700. {
  701. return child->getValue();
  702. }
  703. // Not found => return undefined
  704. return LLSD();
  705. }
  706. BOOL LLPanel::childSetTextArg(const std::string& id, const std::string& key, const LLStringExplicit& text)
  707. {
  708. LLUICtrl* child = findChild<LLUICtrl>(id);
  709. if (child)
  710. {
  711. return child->setTextArg(key, text);
  712. }
  713. return FALSE;
  714. }
  715. BOOL LLPanel::childSetLabelArg(const std::string& id, const std::string& key, const LLStringExplicit& text)
  716. {
  717. LLView* child = findChild<LLView>(id);
  718. if (child)
  719. {
  720. return child->setLabelArg(key, text);
  721. }
  722. return FALSE;
  723. }
  724. BOOL LLPanel::childSetToolTipArg(const std::string& id, const std::string& key, const LLStringExplicit& text)
  725. {
  726. LLView* child = findChild<LLView>(id);
  727. if (child)
  728. {
  729. return child->setToolTipArg(key, text);
  730. }
  731. return FALSE;
  732. }
  733. void LLPanel::childShowTab(const std::string& id, const std::string& tabname, bool visible)
  734. {
  735. LLTabContainer* child = findChild<LLTabContainer>(id);
  736. if (child)
  737. {
  738. child->selectTabByName(tabname);
  739. }
  740. }
  741. LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
  742. {
  743. LLTabContainer* child = findChild<LLTabContainer>(id);
  744. if (child)
  745. {
  746. return child->getCurrentPanel();
  747. }
  748. return NULL;
  749. }
  750. LLPanel* LLPanel::childGetVisibleTabWithHelp()
  751. {
  752. LLView *child;
  753. bfs_tree_iterator_t it = beginTreeBFS();
  754. // skip ourselves
  755. ++it;
  756. for (; it != endTreeBFS(); ++it)
  757. {
  758. child = *it;
  759. LLPanel *curTabPanel = NULL;
  760. // do we have a tab container?
  761. LLTabContainer *tab = dynamic_cast<LLTabContainer *>(child);
  762. if (tab && tab->getVisible())
  763. {
  764. curTabPanel = tab->getCurrentPanel();
  765. }
  766. // do we have an accordion tab?
  767. LLAccordionCtrlTab* accordion = dynamic_cast<LLAccordionCtrlTab *>(child);
  768. if (accordion && accordion->getDisplayChildren())
  769. {
  770. curTabPanel = dynamic_cast<LLPanel *>(accordion->getAccordionView());
  771. }
  772. // if we found a valid tab, does it have a help topic?
  773. if (curTabPanel && !curTabPanel->getHelpTopic().empty())
  774. {
  775. return curTabPanel;
  776. }
  777. }
  778. // couldn't find any active tabs with a help topic string
  779. return NULL;
  780. }
  781. LLPanel *LLPanel::childGetVisiblePanelWithHelp()
  782. {
  783. LLView *child;
  784. bfs_tree_iterator_t it = beginTreeBFS();
  785. // skip ourselves
  786. ++it;
  787. for (; it != endTreeBFS(); ++it)
  788. {
  789. child = *it;
  790. // do we have a panel with a help topic?
  791. LLPanel *panel = dynamic_cast<LLPanel *>(child);
  792. if (panel && panel->isInVisibleChain() && !panel->getHelpTopic().empty())
  793. {
  794. return panel;
  795. }
  796. }
  797. // couldn't find any active panels with a help topic string
  798. return NULL;
  799. }
  800. void LLPanel::childSetAction(const std::string& id, const commit_signal_t::slot_type& function)
  801. {
  802. LLButton* button = findChild<LLButton>(id);
  803. if (button)
  804. {
  805. button->setClickedCallback(function);
  806. }
  807. }
  808. void LLPanel::childSetAction(const std::string& id, boost::function<void(void*)> function, void* value)
  809. {
  810. LLButton* button = findChild<LLButton>(id);
  811. if (button)
  812. {
  813. button->setClickedCallback(boost::bind(function, value));
  814. }
  815. }
  816. void LLPanel::childSetActionTextbox(const std::string& id, boost::function<void(void*)> function, void* value)
  817. {
  818. LLTextBox* textbox = findChild<LLTextBox>(id);
  819. if (textbox)
  820. {
  821. textbox->setClickedCallback(boost::bind(function, value));
  822. }
  823. }
  824. void LLPanel::childSetControlName(const std::string& id, const std::string& control_name)
  825. {
  826. LLUICtrl* view = findChild<LLUICtrl>(id);
  827. if (view)
  828. {
  829. view->setControlName(control_name, NULL);
  830. }
  831. }
  832. boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t::slot_type& cb )
  833. {
  834. if (!mVisibleSignal)
  835. {
  836. mVisibleSignal = new commit_signal_t();
  837. }
  838. return mVisibleSignal->connect(cb);
  839. }
  840. static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels");
  841. //-----------------------------------------------------------------------------
  842. // buildPanel()
  843. //-----------------------------------------------------------------------------
  844. BOOL LLPanel::buildFromFile(const std::string& filename, LLXMLNodePtr output_node, const LLPanel::Params& default_params)
  845. {
  846. LLFastTimer timer(FTM_BUILD_PANELS);
  847. BOOL didPost = FALSE;
  848. LLXMLNodePtr root;
  849. //if exporting, only load the language being exported,
  850. //instead of layering localized version on top of english
  851. if (output_node)
  852. {
  853. if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
  854. {
  855. llwarns << "Couldn't parse panel from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
  856. return didPost;
  857. }
  858. }
  859. else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
  860. {
  861. llwarns << "Couldn't parse panel from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
  862. return didPost;
  863. }
  864. // root must be called panel
  865. if( !root->hasName("panel" ) )
  866. {
  867. llwarns << "Root node should be named panel in : " << filename << llendl;
  868. return didPost;
  869. }
  870. lldebugs << "Building panel " << filename << llendl;
  871. LLUICtrlFactory::instance().pushFileName(filename);
  872. {
  873. if (!getFactoryMap().empty())
  874. {
  875. sFactoryStack.push_back(&getFactoryMap());
  876. }
  877. // for local registry callbacks; define in constructor, referenced in XUI or postBuild
  878. getCommitCallbackRegistrar().pushScope();
  879. getEnableCallbackRegistrar().pushScope();
  880. didPost = initPanelXML(root, NULL, output_node, default_params);
  881. getCommitCallbackRegistrar().popScope();
  882. getEnableCallbackRegistrar().popScope();
  883. setXMLFilename(filename);
  884. if (!getFactoryMap().empty())
  885. {
  886. sFactoryStack.pop_back();
  887. }
  888. }
  889. LLUICtrlFactory::instance().popFileName();
  890. return didPost;
  891. }
  892. //-----------------------------------------------------------------------------
  893. // createFactoryPanel()
  894. //-----------------------------------------------------------------------------
  895. LLPanel* LLPanel::createFactoryPanel(const std::string& name)
  896. {
  897. std::deque<const LLCallbackMap::map_t*>::iterator itor;
  898. for (itor = sFactoryStack.begin(); itor != sFactoryStack.end(); ++itor)
  899. {
  900. const LLCallbackMap::map_t* factory_map = *itor;
  901. // Look up this panel's name in the map.
  902. LLCallbackMap::map_const_iter_t iter = factory_map->find( name );
  903. if (iter != factory_map->end())
  904. {
  905. // Use the factory to create the panel, instead of using a default LLPanel.
  906. LLPanel *ret = (LLPanel*) iter->second.mCallback( iter->second.mData );
  907. return ret;
  908. }
  909. }
  910. LLPanel::Params panel_p;
  911. return LLUICtrlFactory::create<LLPanel>(panel_p);
  912. }