diff options
Diffstat (limited to 'indra/llui/llpanel.cpp')
-rw-r--r-- | indra/llui/llpanel.cpp | 1750 |
1 files changed, 875 insertions, 875 deletions
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index d580566b13..f6758133f3 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -1,875 +1,875 @@ -/** - * @file llpanel.cpp - * @brief LLPanel base class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -// Opaque view with a background and a border. Can contain LLUICtrls. - -#include "linden_common.h" - -#define LLPANEL_CPP -#include "llpanel.h" - -#include "llfocusmgr.h" -#include "llfontgl.h" -#include "llrect.h" -#include "llerror.h" -#include "lldir.h" -#include "lltimer.h" - -#include "llbutton.h" -#include "llmenugl.h" -#include "llui.h" -#include "llkeyboard.h" -#include "lllineeditor.h" -#include "llcontrol.h" -#include "lltextbox.h" -#include "lluictrl.h" -#include "lluictrlfactory.h" -#include "llviewborder.h" - -static LLDefaultChildRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML); -LLPanel::factory_stack_t LLPanel::sFactoryStack; - - -// Compiler optimization, generate extern template -template class LLPanel* LLView::getChild<class LLPanel>( - const std::string& name, BOOL recurse) const; - -LLPanel::LocalizedString::LocalizedString() -: name("name"), - value("value") -{} - -const LLPanel::Params& LLPanel::getDefaultParams() -{ - return LLUICtrlFactory::getDefaultParams<LLPanel>(); -} - -LLPanel::Params::Params() -: has_border("border", false), - border(""), - background_visible("background_visible", false), - background_opaque("background_opaque", false), - bg_opaque_color("bg_opaque_color"), - bg_alpha_color("bg_alpha_color"), - bg_opaque_image_overlay("bg_opaque_image_overlay"), - bg_alpha_image_overlay("bg_alpha_image_overlay"), - bg_opaque_image("bg_opaque_image"), - bg_alpha_image("bg_alpha_image"), - min_width("min_width", 100), - min_height("min_height", 100), - strings("string"), - filename("filename"), - class_name("class"), - help_topic("help_topic"), - visible_callback("visible_callback"), - accepts_badge("accepts_badge") -{ - addSynonym(background_visible, "bg_visible"); - addSynonym(has_border, "border_visible"); - addSynonym(label, "title"); -} - - -LLPanel::LLPanel(const LLPanel::Params& p) -: LLUICtrl(p), - LLBadgeHolder(p.accepts_badge), - mBgVisible(p.background_visible), - mBgOpaque(p.background_opaque), - mBgOpaqueColor(p.bg_opaque_color()), - mBgAlphaColor(p.bg_alpha_color()), - mBgOpaqueImageOverlay(p.bg_opaque_image_overlay), - mBgAlphaImageOverlay(p.bg_alpha_image_overlay), - mBgOpaqueImage(p.bg_opaque_image()), - mBgAlphaImage(p.bg_alpha_image()), - mDefaultBtn(NULL), - mBorder(NULL), - mLabel(p.label), - mHelpTopic(p.help_topic), - mCommitCallbackRegistrar(false), - mEnableCallbackRegistrar(false), - mXMLFilename(p.filename), - mVisibleSignal(NULL) - // *NOTE: Be sure to also change LLPanel::initFromParams(). We have too - // many classes derived from LLPanel to retrofit them all to pass in params. -{ - if (p.has_border) - { - addBorder(p.border); - } -} - -LLPanel::~LLPanel() -{ - delete mVisibleSignal; -} - -// virtual -BOOL LLPanel::isPanel() const -{ - return TRUE; -} - -void LLPanel::addBorder(LLViewBorder::Params p) -{ - removeBorder(); - p.rect = getLocalRect(); - - mBorder = LLUICtrlFactory::create<LLViewBorder>(p); - addChild( mBorder ); -} - -void LLPanel::addBorder() -{ - LLViewBorder::Params p; - p.border_thickness(LLPANEL_BORDER_WIDTH); - addBorder(p); -} - - -void LLPanel::removeBorder() -{ - if (mBorder) - { - removeChild(mBorder); - delete mBorder; - mBorder = NULL; - } -} - - -// virtual -void LLPanel::clearCtrls() -{ - LLPanel::ctrl_list_t ctrls = getCtrlList(); - for (LLPanel::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it) - { - LLUICtrl* ctrl = *ctrl_it; - ctrl->setFocus( FALSE ); - ctrl->setEnabled( FALSE ); - ctrl->clear(); - } -} - -void LLPanel::setCtrlsEnabled( BOOL b ) -{ - LLPanel::ctrl_list_t ctrls = getCtrlList(); - for (LLPanel::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it) - { - LLUICtrl* ctrl = *ctrl_it; - ctrl->setEnabled( b ); - } -} - -LLPanel::ctrl_list_t LLPanel::getCtrlList() const -{ - ctrl_list_t controls; - for(child_list_t::const_iterator it = getChildList()->begin(), end_it = getChildList()->end(); it != end_it; ++it) - { - LLView* viewp = *it; - if(viewp->isCtrl()) - { - controls.push_back(static_cast<LLUICtrl*>(viewp)); - } - } - return controls; -} - - -void LLPanel::draw() -{ - F32 alpha = getDrawContext().mAlpha; - - // draw background - if( mBgVisible ) - { - alpha = getCurrentTransparency(); - - LLRect local_rect = getLocalRect(); - if (mBgOpaque ) - { - // opaque, in-front look - if (mBgOpaqueImage.notNull()) - { - mBgOpaqueImage->draw( local_rect, mBgOpaqueImageOverlay % alpha ); - } - else - { - // fallback to flat colors when there are no images - gl_rect_2d( local_rect, mBgOpaqueColor.get() % alpha); - } - } - else - { - // transparent, in-back look - if (mBgAlphaImage.notNull()) - { - mBgAlphaImage->draw( local_rect, mBgAlphaImageOverlay % alpha ); - } - else - { - gl_rect_2d( local_rect, mBgAlphaColor.get() % alpha ); - } - } - } - - updateDefaultBtn(); - - LLView::draw(); -} - -void LLPanel::updateDefaultBtn() -{ - if( mDefaultBtn) - { - if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled()) - { - LLButton* buttonp = dynamic_cast<LLButton*>(gFocusMgr.getKeyboardFocus()); - BOOL focus_is_child_button = buttonp && buttonp->getCommitOnReturn(); - // only enable default button when current focus is not a return-capturing button - mDefaultBtn->setBorderEnabled(!focus_is_child_button); - } - else - { - mDefaultBtn->setBorderEnabled(FALSE); - } - } -} - -void LLPanel::refresh() -{ - // do nothing by default - // but is automatically called in setFocus(TRUE) -} - -void LLPanel::setDefaultBtn(LLButton* btn) -{ - if (mDefaultBtn && mDefaultBtn->getEnabled()) - { - mDefaultBtn->setBorderEnabled(FALSE); - } - mDefaultBtn = btn; - if (mDefaultBtn) - { - mDefaultBtn->setBorderEnabled(TRUE); - } -} - -void LLPanel::setDefaultBtn(const std::string& id) -{ - LLButton *button = getChild<LLButton>(id); - if (button) - { - setDefaultBtn(button); - } - else - { - setDefaultBtn(NULL); - } -} - -BOOL LLPanel::handleKeyHere( KEY key, MASK mask ) -{ - BOOL handled = FALSE; - - LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); - - // handle user hitting ESC to defocus - if (key == KEY_ESCAPE) - { - setFocus(FALSE); - return TRUE; - } - else if( (mask == MASK_SHIFT) && (KEY_TAB == key)) - { - //SHIFT-TAB - if (cur_focus) - { - LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot(); - if (focus_root) - { - handled = focus_root->focusPrevItem(FALSE); - } - } - } - else if( (mask == MASK_NONE ) && (KEY_TAB == key)) - { - //TAB - if (cur_focus) - { - LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot(); - if (focus_root) - { - handled = focus_root->focusNextItem(FALSE); - } - } - } - - // If RETURN was pressed and something has focus, call onCommit() - if (!handled && cur_focus && key == KEY_RETURN && mask == MASK_NONE) - { - LLButton* focused_button = dynamic_cast<LLButton*>(cur_focus); - if (focused_button && focused_button->getCommitOnReturn()) - { - // current focus is a return-capturing button, - // let *that* button handle the return key - handled = FALSE; - } - else if (mDefaultBtn && mDefaultBtn->getVisible() && mDefaultBtn->getEnabled()) - { - // If we have a default button, click it when return is pressed - mDefaultBtn->onCommit(); - handled = TRUE; - } - else if (cur_focus->acceptsTextInput()) - { - // call onCommit for text input handling control - cur_focus->onCommit(); - handled = TRUE; - } - } - - return handled; -} - -void LLPanel::onVisibilityChange ( BOOL new_visibility ) -{ - LLUICtrl::onVisibilityChange ( new_visibility ); - if (mVisibleSignal) - (*mVisibleSignal)(this, LLSD(new_visibility) ); // Pass BOOL as LLSD -} - -void LLPanel::setFocus(BOOL b) -{ - if( b && !hasFocus()) - { - // give ourselves focus preemptively, to avoid infinite loop - LLUICtrl::setFocus(TRUE); - // then try to pass to first valid child - focusFirstItem(); - } - else - { - LLUICtrl::setFocus(b); - } -} - -void LLPanel::setBorderVisible(BOOL b) -{ - if (mBorder) - { - mBorder->setVisible( b ); - } -} - -LLTrace::BlockTimerStatHandle FTM_PANEL_CONSTRUCTION("Panel Construction"); - -LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_node) -{ - std::string name("panel"); - node->getAttributeString("name", name); - - std::string class_attr; - node->getAttributeString("class", class_attr); - - LLPanel* panelp = NULL; - - { LL_RECORD_BLOCK_TIME(FTM_PANEL_CONSTRUCTION); - - if(!class_attr.empty()) - { - panelp = LLRegisterPanelClass::instance().createPanelClass(class_attr); - if (!panelp) - { - LL_WARNS() << "Panel class \"" << class_attr << "\" not registered." << LL_ENDL; - } - } - - if (!panelp) - { - panelp = createFactoryPanel(name); - llassert(panelp); - - if (!panelp) - { - return NULL; // :( - } - } - - } - // factory panels may have registered their own factory maps - if (!panelp->getFactoryMap().empty()) - { - sFactoryStack.push_back(&panelp->getFactoryMap()); - } - // for local registry callbacks; define in constructor, referenced in XUI or postBuild - panelp->mCommitCallbackRegistrar.pushScope(); - panelp->mEnableCallbackRegistrar.pushScope(); - - panelp->initPanelXML(node, parent, output_node, LLUICtrlFactory::getDefaultParams<LLPanel>()); - - panelp->mCommitCallbackRegistrar.popScope(); - panelp->mEnableCallbackRegistrar.popScope(); - - if (!panelp->getFactoryMap().empty()) - { - sFactoryStack.pop_back(); - } - - return panelp; -} - -void LLPanel::initFromParams(const LLPanel::Params& p) -{ - //setting these here since panel constructor not called with params - //and LLView::initFromParams will use them to set visible and enabled - setVisible(p.visible); - setEnabled(p.enabled); - setFocusRoot(p.focus_root); - setSoundFlags(p.sound_flags); - - // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible - LLUICtrl::initFromParams(p); - - // visible callback - if (p.visible_callback.isProvided()) - { - setVisibleCallback(initCommitCallback(p.visible_callback)); - } - - for (LLInitParam::ParamIterator<LocalizedString>::const_iterator it = p.strings.begin(); - it != p.strings.end(); - ++it) - { - mUIStrings[it->name] = it->value; - } - - setLabel(p.label()); - setHelpTopic(p.help_topic); - setShape(p.rect); - parseFollowsFlags(p); - - setToolTip(p.tool_tip()); - setFromXUI(p.from_xui); - - mHoverCursor = getCursorFromString(p.hover_cursor); - - if (p.has_border) - { - addBorder(p.border); - } - // let constructors set this value if not provided - if (p.use_bounding_rect.isProvided()) - { - setUseBoundingRect(p.use_bounding_rect); - } - setDefaultTabGroup(p.default_tab_group); - setMouseOpaque(p.mouse_opaque); - - setBackgroundVisible(p.background_visible); - setBackgroundOpaque(p.background_opaque); - setBackgroundColor(p.bg_opaque_color().get()); - setTransparentColor(p.bg_alpha_color().get()); - mBgOpaqueImage = p.bg_opaque_image(); - mBgAlphaImage = p.bg_alpha_image(); - mBgOpaqueImageOverlay = p.bg_opaque_image_overlay; - mBgAlphaImageOverlay = p.bg_alpha_image_overlay; - - setAcceptsBadge(p.accepts_badge); -} - -static LLTrace::BlockTimerStatHandle FTM_PANEL_SETUP("Panel Setup"); -static LLTrace::BlockTimerStatHandle FTM_EXTERNAL_PANEL_LOAD("Load Extern Panel Reference"); -static LLTrace::BlockTimerStatHandle FTM_PANEL_POSTBUILD("Panel PostBuild"); - -BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node, const LLPanel::Params& default_params) -{ - Params params(default_params); - { - LL_RECORD_BLOCK_TIME(FTM_PANEL_SETUP); - - LLXMLNodePtr referenced_xml; - std::string xml_filename = mXMLFilename; - - // if the panel didn't provide a filename, check the node - if (xml_filename.empty()) - { - node->getAttributeString("filename", xml_filename); - setXMLFilename(xml_filename); - } - - LLXUIParser parser; - - if (!xml_filename.empty()) - { - if (output_node) - { - //if we are exporting, we want to export the current xml - //not the referenced xml - parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName()); - Params output_params(params); - setupParamsForExport(output_params, parent); - output_node->setName(node->getName()->mString); - parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); - return TRUE; - } - - LLUICtrlFactory::instance().pushFileName(xml_filename); - - LL_RECORD_BLOCK_TIME(FTM_EXTERNAL_PANEL_LOAD); - if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml)) - { - LL_WARNS() << "Couldn't parse panel from: " << xml_filename << LL_ENDL; - - return FALSE; - } - - parser.readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName()); - - // add children using dimensions from referenced xml for consistent layout - setShape(params.rect); - LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance()); - - LLUICtrlFactory::instance().popFileName(); - } - - // ask LLUICtrlFactory for filename, since xml_filename might be empty - parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName()); - - if (output_node) - { - Params output_params(params); - setupParamsForExport(output_params, parent); - output_node->setName(node->getName()->mString); - parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); - } - - params.from_xui = true; - applyXUILayout(params, parent); - { - LL_RECORD_BLOCK_TIME(FTM_PANEL_CONSTRUCTION); - initFromParams(params); - } - - // add children - LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node); - - // Connect to parent after children are built, because tab containers - // do a reshape() on their child panels, which requires that the children - // be built/added. JC - if (parent) - { - S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup(); - parent->addChild(this, tab_group); - } - - { - LL_RECORD_BLOCK_TIME(FTM_PANEL_POSTBUILD); - postBuild(); - } - } - return TRUE; -} - -bool LLPanel::hasString(const std::string& name) -{ - return mUIStrings.find(name) != mUIStrings.end(); -} - -std::string LLPanel::getString(const std::string& name, const LLStringUtil::format_map_t& args) const -{ - ui_string_map_t::const_iterator found_it = mUIStrings.find(name); - if (found_it != mUIStrings.end()) - { - // make a copy as format works in place - LLUIString formatted_string = LLUIString(found_it->second); - formatted_string.setArgList(args); - return formatted_string.getString(); - } - std::string err_str("Failed to find string " + name + " in panel " + getName()); //*TODO: Translate - if(LLUI::getInstance()->mSettingGroups["config"]->getBOOL("QAMode")) - { - LL_ERRS() << err_str << LL_ENDL; - } - else - { - LL_WARNS() << err_str << LL_ENDL; - } - return LLStringUtil::null; -} - -std::string LLPanel::getString(const std::string& name) const -{ - ui_string_map_t::const_iterator found_it = mUIStrings.find(name); - if (found_it != mUIStrings.end()) - { - return found_it->second; - } - std::string err_str("Failed to find string " + name + " in panel " + getName()); //*TODO: Translate - if(LLUI::getInstance()->mSettingGroups["config"]->getBOOL("QAMode")) - { - LL_ERRS() << err_str << LL_ENDL; - } - else - { - LL_WARNS() << err_str << LL_ENDL; - } - return LLStringUtil::null; -} - - -void LLPanel::childSetVisible(const std::string& id, bool visible) -{ - LLView* child = findChild<LLView>(id); - if (child) - { - child->setVisible(visible); - } -} - -void LLPanel::childSetEnabled(const std::string& id, bool enabled) -{ - LLView* child = findChild<LLView>(id); - if (child) - { - child->setEnabled(enabled); - } -} - -void LLPanel::childSetFocus(const std::string& id, BOOL focus) -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - child->setFocus(focus); - } -} - -BOOL LLPanel::childHasFocus(const std::string& id) -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - return child->hasFocus(); - } - else - { - return FALSE; - } -} - -// *TODO: Deprecate; for backwards compatability only: -// Prefer getChild<LLUICtrl>("foo")->setCommitCallback(boost:bind(...)), -// which takes a generic slot. Or use mCommitCallbackRegistrar.add() with -// a named callback and reference it in XML. -void LLPanel::childSetCommitCallback(const std::string& id, boost::function<void (LLUICtrl*,void*)> cb, void* data) -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - child->setCommitCallback(boost::bind(cb, child, data)); - } -} - -void LLPanel::childSetColor(const std::string& id, const LLColor4& color) -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - child->setColor(color); - } -} - -LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - return child->getSelectionInterface(); - } - return NULL; -} - -LLCtrlListInterface* LLPanel::childGetListInterface(const std::string& id) const -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - return child->getListInterface(); - } - return NULL; -} - -LLCtrlScrollInterface* LLPanel::childGetScrollInterface(const std::string& id) const -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - return child->getScrollInterface(); - } - return NULL; -} - -void LLPanel::childSetValue(const std::string& id, LLSD value) -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - child->setValue(value); - } -} - -LLSD LLPanel::childGetValue(const std::string& id) const -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - return child->getValue(); - } - // Not found => return undefined - return LLSD(); -} - -BOOL LLPanel::childSetTextArg(const std::string& id, const std::string& key, const LLStringExplicit& text) -{ - LLUICtrl* child = findChild<LLUICtrl>(id); - if (child) - { - return child->setTextArg(key, text); - } - return FALSE; -} - -BOOL LLPanel::childSetLabelArg(const std::string& id, const std::string& key, const LLStringExplicit& text) -{ - LLView* child = findChild<LLView>(id); - if (child) - { - return child->setLabelArg(key, text); - } - return FALSE; -} - -void LLPanel::childSetAction(const std::string& id, const commit_signal_t::slot_type& function) -{ - LLButton* button = findChild<LLButton>(id); - if (button) - { - button->setClickedCallback(function); - } -} - -void LLPanel::childSetAction(const std::string& id, boost::function<void(void*)> function, void* value) -{ - LLButton* button = findChild<LLButton>(id); - if (button) - { - button->setClickedCallback(boost::bind(function, value)); - } -} - -boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t::slot_type& cb ) -{ - if (!mVisibleSignal) - { - mVisibleSignal = new commit_signal_t(); - } - - return mVisibleSignal->connect(cb); -} - -//----------------------------------------------------------------------------- -// buildPanel() -//----------------------------------------------------------------------------- -BOOL LLPanel::buildFromFile(const std::string& filename, const LLPanel::Params& default_params) -{ - LL_PROFILE_ZONE_SCOPED; - BOOL didPost = FALSE; - LLXMLNodePtr root; - - if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) - { - LL_WARNS() << "Couldn't parse panel from: " << filename << LL_ENDL; - return didPost; - } - - // root must be called panel - if( !root->hasName("panel" ) ) - { - LL_WARNS() << "Root node should be named panel in : " << filename << LL_ENDL; - return didPost; - } - - LL_DEBUGS() << "Building panel " << filename << LL_ENDL; - - LLUICtrlFactory::instance().pushFileName(filename); - { - if (!getFactoryMap().empty()) - { - sFactoryStack.push_back(&getFactoryMap()); - } - - // for local registry callbacks; define in constructor, referenced in XUI or postBuild - getCommitCallbackRegistrar().pushScope(); - getEnableCallbackRegistrar().pushScope(); - - didPost = initPanelXML(root, NULL, NULL, default_params); - - getCommitCallbackRegistrar().popScope(); - getEnableCallbackRegistrar().popScope(); - - setXMLFilename(filename); - - if (!getFactoryMap().empty()) - { - sFactoryStack.pop_back(); - } - } - LLUICtrlFactory::instance().popFileName(); - return didPost; -} - -//----------------------------------------------------------------------------- -// createFactoryPanel() -//----------------------------------------------------------------------------- -LLPanel* LLPanel::createFactoryPanel(const std::string& name) -{ - std::deque<const LLCallbackMap::map_t*>::iterator itor; - for (itor = sFactoryStack.begin(); itor != sFactoryStack.end(); ++itor) - { - const LLCallbackMap::map_t* factory_map = *itor; - - // Look up this panel's name in the map. - LLCallbackMap::map_const_iter_t iter = factory_map->find( name ); - if (iter != factory_map->end()) - { - // Use the factory to create the panel, instead of using a default LLPanel. - LLPanel *ret = (LLPanel*) iter->second.mCallback( iter->second.mData ); - return ret; - } - } - LLPanel::Params panel_p; - return LLUICtrlFactory::create<LLPanel>(panel_p); -} +/**
+ * @file llpanel.cpp
+ * @brief LLPanel base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+// Opaque view with a background and a border. Can contain LLUICtrls.
+
+#include "linden_common.h"
+
+#define LLPANEL_CPP
+#include "llpanel.h"
+
+#include "llfocusmgr.h"
+#include "llfontgl.h"
+#include "llrect.h"
+#include "llerror.h"
+#include "lldir.h"
+#include "lltimer.h"
+
+#include "llbutton.h"
+#include "llmenugl.h"
+#include "llui.h"
+#include "llkeyboard.h"
+#include "lllineeditor.h"
+#include "llcontrol.h"
+#include "lltextbox.h"
+#include "lluictrl.h"
+#include "lluictrlfactory.h"
+#include "llviewborder.h"
+
+static LLDefaultChildRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML);
+LLPanel::factory_stack_t LLPanel::sFactoryStack;
+
+
+// Compiler optimization, generate extern template
+template class LLPanel* LLView::getChild<class LLPanel>(
+ const std::string& name, bool recurse) const;
+
+LLPanel::LocalizedString::LocalizedString()
+: name("name"),
+ value("value")
+{}
+
+const LLPanel::Params& LLPanel::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLPanel>();
+}
+
+LLPanel::Params::Params()
+: has_border("border", false),
+ border(""),
+ background_visible("background_visible", false),
+ background_opaque("background_opaque", false),
+ bg_opaque_color("bg_opaque_color"),
+ bg_alpha_color("bg_alpha_color"),
+ bg_opaque_image_overlay("bg_opaque_image_overlay"),
+ bg_alpha_image_overlay("bg_alpha_image_overlay"),
+ bg_opaque_image("bg_opaque_image"),
+ bg_alpha_image("bg_alpha_image"),
+ min_width("min_width", 100),
+ min_height("min_height", 100),
+ strings("string"),
+ filename("filename"),
+ class_name("class"),
+ help_topic("help_topic"),
+ visible_callback("visible_callback"),
+ accepts_badge("accepts_badge")
+{
+ addSynonym(background_visible, "bg_visible");
+ addSynonym(has_border, "border_visible");
+ addSynonym(label, "title");
+}
+
+
+LLPanel::LLPanel(const LLPanel::Params& p)
+: LLUICtrl(p),
+ LLBadgeHolder(p.accepts_badge),
+ mBgVisible(p.background_visible),
+ mBgOpaque(p.background_opaque),
+ mBgOpaqueColor(p.bg_opaque_color()),
+ mBgAlphaColor(p.bg_alpha_color()),
+ mBgOpaqueImageOverlay(p.bg_opaque_image_overlay),
+ mBgAlphaImageOverlay(p.bg_alpha_image_overlay),
+ mBgOpaqueImage(p.bg_opaque_image()),
+ mBgAlphaImage(p.bg_alpha_image()),
+ mDefaultBtn(NULL),
+ mBorder(NULL),
+ mLabel(p.label),
+ mHelpTopic(p.help_topic),
+ mCommitCallbackRegistrar(false),
+ mEnableCallbackRegistrar(false),
+ mXMLFilename(p.filename),
+ mVisibleSignal(NULL)
+ // *NOTE: Be sure to also change LLPanel::initFromParams(). We have too
+ // many classes derived from LLPanel to retrofit them all to pass in params.
+{
+ if (p.has_border)
+ {
+ addBorder(p.border);
+ }
+}
+
+LLPanel::~LLPanel()
+{
+ delete mVisibleSignal;
+}
+
+// virtual
+bool LLPanel::isPanel() const
+{
+ return true;
+}
+
+void LLPanel::addBorder(LLViewBorder::Params p)
+{
+ removeBorder();
+ p.rect = getLocalRect();
+
+ mBorder = LLUICtrlFactory::create<LLViewBorder>(p);
+ addChild( mBorder );
+}
+
+void LLPanel::addBorder()
+{
+ LLViewBorder::Params p;
+ p.border_thickness(LLPANEL_BORDER_WIDTH);
+ addBorder(p);
+}
+
+
+void LLPanel::removeBorder()
+{
+ if (mBorder)
+ {
+ removeChild(mBorder);
+ delete mBorder;
+ mBorder = NULL;
+ }
+}
+
+
+// virtual
+void LLPanel::clearCtrls()
+{
+ LLPanel::ctrl_list_t ctrls = getCtrlList();
+ for (LLPanel::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
+ {
+ LLUICtrl* ctrl = *ctrl_it;
+ ctrl->setFocus( false );
+ ctrl->setEnabled( false );
+ ctrl->clear();
+ }
+}
+
+void LLPanel::setCtrlsEnabled( bool b )
+{
+ LLPanel::ctrl_list_t ctrls = getCtrlList();
+ for (LLPanel::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
+ {
+ LLUICtrl* ctrl = *ctrl_it;
+ ctrl->setEnabled( b );
+ }
+}
+
+LLPanel::ctrl_list_t LLPanel::getCtrlList() const
+{
+ ctrl_list_t controls;
+ for(child_list_t::const_iterator it = getChildList()->begin(), end_it = getChildList()->end(); it != end_it; ++it)
+ {
+ LLView* viewp = *it;
+ if(viewp->isCtrl())
+ {
+ controls.push_back(static_cast<LLUICtrl*>(viewp));
+ }
+ }
+ return controls;
+}
+
+
+void LLPanel::draw()
+{
+ F32 alpha = getDrawContext().mAlpha;
+
+ // draw background
+ if( mBgVisible )
+ {
+ alpha = getCurrentTransparency();
+
+ LLRect local_rect = getLocalRect();
+ if (mBgOpaque )
+ {
+ // opaque, in-front look
+ if (mBgOpaqueImage.notNull())
+ {
+ mBgOpaqueImage->draw( local_rect, mBgOpaqueImageOverlay % alpha );
+ }
+ else
+ {
+ // fallback to flat colors when there are no images
+ gl_rect_2d( local_rect, mBgOpaqueColor.get() % alpha);
+ }
+ }
+ else
+ {
+ // transparent, in-back look
+ if (mBgAlphaImage.notNull())
+ {
+ mBgAlphaImage->draw( local_rect, mBgAlphaImageOverlay % alpha );
+ }
+ else
+ {
+ gl_rect_2d( local_rect, mBgAlphaColor.get() % alpha );
+ }
+ }
+ }
+
+ updateDefaultBtn();
+
+ LLView::draw();
+}
+
+void LLPanel::updateDefaultBtn()
+{
+ if( mDefaultBtn)
+ {
+ if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
+ {
+ LLButton* buttonp = dynamic_cast<LLButton*>(gFocusMgr.getKeyboardFocus());
+ bool focus_is_child_button = buttonp && buttonp->getCommitOnReturn();
+ // only enable default button when current focus is not a return-capturing button
+ mDefaultBtn->setBorderEnabled(!focus_is_child_button);
+ }
+ else
+ {
+ mDefaultBtn->setBorderEnabled(false);
+ }
+ }
+}
+
+void LLPanel::refresh()
+{
+ // do nothing by default
+ // but is automatically called in setFocus(true)
+}
+
+void LLPanel::setDefaultBtn(LLButton* btn)
+{
+ if (mDefaultBtn && mDefaultBtn->getEnabled())
+ {
+ mDefaultBtn->setBorderEnabled(false);
+ }
+ mDefaultBtn = btn;
+ if (mDefaultBtn)
+ {
+ mDefaultBtn->setBorderEnabled(true);
+ }
+}
+
+void LLPanel::setDefaultBtn(const std::string& id)
+{
+ LLButton *button = getChild<LLButton>(id);
+ if (button)
+ {
+ setDefaultBtn(button);
+ }
+ else
+ {
+ setDefaultBtn(NULL);
+ }
+}
+
+bool LLPanel::handleKeyHere( KEY key, MASK mask )
+{
+ bool handled = false;
+
+ LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+
+ // handle user hitting ESC to defocus
+ if (key == KEY_ESCAPE)
+ {
+ setFocus(false);
+ return true;
+ }
+ else if( (mask == MASK_SHIFT) && (KEY_TAB == key))
+ {
+ //SHIFT-TAB
+ if (cur_focus)
+ {
+ LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
+ if (focus_root)
+ {
+ handled = focus_root->focusPrevItem(false);
+ }
+ }
+ }
+ else if( (mask == MASK_NONE ) && (KEY_TAB == key))
+ {
+ //TAB
+ if (cur_focus)
+ {
+ LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
+ if (focus_root)
+ {
+ handled = focus_root->focusNextItem(false);
+ }
+ }
+ }
+
+ // If RETURN was pressed and something has focus, call onCommit()
+ if (!handled && cur_focus && key == KEY_RETURN && mask == MASK_NONE)
+ {
+ LLButton* focused_button = dynamic_cast<LLButton*>(cur_focus);
+ if (focused_button && focused_button->getCommitOnReturn())
+ {
+ // current focus is a return-capturing button,
+ // let *that* button handle the return key
+ handled = false;
+ }
+ else if (mDefaultBtn && mDefaultBtn->getVisible() && mDefaultBtn->getEnabled())
+ {
+ // If we have a default button, click it when return is pressed
+ mDefaultBtn->onCommit();
+ handled = true;
+ }
+ else if (cur_focus->acceptsTextInput())
+ {
+ // call onCommit for text input handling control
+ cur_focus->onCommit();
+ handled = true;
+ }
+ }
+
+ return handled;
+}
+
+void LLPanel::onVisibilityChange ( bool new_visibility )
+{
+ LLUICtrl::onVisibilityChange ( new_visibility );
+ if (mVisibleSignal)
+ (*mVisibleSignal)(this, LLSD(new_visibility) ); // Pass bool as LLSD
+}
+
+void LLPanel::setFocus(bool b)
+{
+ if( b && !hasFocus())
+ {
+ // give ourselves focus preemptively, to avoid infinite loop
+ LLUICtrl::setFocus(true);
+ // then try to pass to first valid child
+ focusFirstItem();
+ }
+ else
+ {
+ LLUICtrl::setFocus(b);
+ }
+}
+
+void LLPanel::setBorderVisible(bool b)
+{
+ if (mBorder)
+ {
+ mBorder->setVisible( b );
+ }
+}
+
+LLTrace::BlockTimerStatHandle FTM_PANEL_CONSTRUCTION("Panel Construction");
+
+LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_node)
+{
+ std::string name("panel");
+ node->getAttributeString("name", name);
+
+ std::string class_attr;
+ node->getAttributeString("class", class_attr);
+
+ LLPanel* panelp = NULL;
+
+ { LL_RECORD_BLOCK_TIME(FTM_PANEL_CONSTRUCTION);
+
+ if(!class_attr.empty())
+ {
+ panelp = LLRegisterPanelClass::instance().createPanelClass(class_attr);
+ if (!panelp)
+ {
+ LL_WARNS() << "Panel class \"" << class_attr << "\" not registered." << LL_ENDL;
+ }
+ }
+
+ if (!panelp)
+ {
+ panelp = createFactoryPanel(name);
+ llassert(panelp);
+
+ if (!panelp)
+ {
+ return NULL; // :(
+ }
+ }
+
+ }
+ // factory panels may have registered their own factory maps
+ if (!panelp->getFactoryMap().empty())
+ {
+ sFactoryStack.push_back(&panelp->getFactoryMap());
+ }
+ // for local registry callbacks; define in constructor, referenced in XUI or postBuild
+ panelp->mCommitCallbackRegistrar.pushScope();
+ panelp->mEnableCallbackRegistrar.pushScope();
+
+ panelp->initPanelXML(node, parent, output_node, LLUICtrlFactory::getDefaultParams<LLPanel>());
+
+ panelp->mCommitCallbackRegistrar.popScope();
+ panelp->mEnableCallbackRegistrar.popScope();
+
+ if (!panelp->getFactoryMap().empty())
+ {
+ sFactoryStack.pop_back();
+ }
+
+ return panelp;
+}
+
+void LLPanel::initFromParams(const LLPanel::Params& p)
+{
+ //setting these here since panel constructor not called with params
+ //and LLView::initFromParams will use them to set visible and enabled
+ setVisible(p.visible);
+ setEnabled(p.enabled);
+ setFocusRoot(p.focus_root);
+ setSoundFlags(p.sound_flags);
+
+ // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
+ LLUICtrl::initFromParams(p);
+
+ // visible callback
+ if (p.visible_callback.isProvided())
+ {
+ setVisibleCallback(initCommitCallback(p.visible_callback));
+ }
+
+ for (LLInitParam::ParamIterator<LocalizedString>::const_iterator it = p.strings.begin();
+ it != p.strings.end();
+ ++it)
+ {
+ mUIStrings[it->name] = it->value;
+ }
+
+ setLabel(p.label());
+ setHelpTopic(p.help_topic);
+ setShape(p.rect);
+ parseFollowsFlags(p);
+
+ setToolTip(p.tool_tip());
+ setFromXUI(p.from_xui);
+
+ mHoverCursor = getCursorFromString(p.hover_cursor);
+
+ if (p.has_border)
+ {
+ addBorder(p.border);
+ }
+ // let constructors set this value if not provided
+ if (p.use_bounding_rect.isProvided())
+ {
+ setUseBoundingRect(p.use_bounding_rect);
+ }
+ setDefaultTabGroup(p.default_tab_group);
+ setMouseOpaque(p.mouse_opaque);
+
+ setBackgroundVisible(p.background_visible);
+ setBackgroundOpaque(p.background_opaque);
+ setBackgroundColor(p.bg_opaque_color().get());
+ setTransparentColor(p.bg_alpha_color().get());
+ mBgOpaqueImage = p.bg_opaque_image();
+ mBgAlphaImage = p.bg_alpha_image();
+ mBgOpaqueImageOverlay = p.bg_opaque_image_overlay;
+ mBgAlphaImageOverlay = p.bg_alpha_image_overlay;
+
+ setAcceptsBadge(p.accepts_badge);
+}
+
+static LLTrace::BlockTimerStatHandle FTM_PANEL_SETUP("Panel Setup");
+static LLTrace::BlockTimerStatHandle FTM_EXTERNAL_PANEL_LOAD("Load Extern Panel Reference");
+static LLTrace::BlockTimerStatHandle FTM_PANEL_POSTBUILD("Panel PostBuild");
+
+bool LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node, const LLPanel::Params& default_params)
+{
+ Params params(default_params);
+ {
+ LL_RECORD_BLOCK_TIME(FTM_PANEL_SETUP);
+
+ LLXMLNodePtr referenced_xml;
+ std::string xml_filename = mXMLFilename;
+
+ // if the panel didn't provide a filename, check the node
+ if (xml_filename.empty())
+ {
+ node->getAttributeString("filename", xml_filename);
+ setXMLFilename(xml_filename);
+ }
+
+ LLXUIParser parser;
+
+ if (!xml_filename.empty())
+ {
+ if (output_node)
+ {
+ //if we are exporting, we want to export the current xml
+ //not the referenced xml
+ parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+ Params output_params(params);
+ setupParamsForExport(output_params, parent);
+ output_node->setName(node->getName()->mString);
+ parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
+ return true;
+ }
+
+ LLUICtrlFactory::instance().pushFileName(xml_filename);
+
+ LL_RECORD_BLOCK_TIME(FTM_EXTERNAL_PANEL_LOAD);
+ if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml))
+ {
+ LL_WARNS() << "Couldn't parse panel from: " << xml_filename << LL_ENDL;
+
+ return false;
+ }
+
+ parser.readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName());
+
+ // add children using dimensions from referenced xml for consistent layout
+ setShape(params.rect);
+ LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance());
+
+ LLUICtrlFactory::instance().popFileName();
+ }
+
+ // ask LLUICtrlFactory for filename, since xml_filename might be empty
+ parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+
+ if (output_node)
+ {
+ Params output_params(params);
+ setupParamsForExport(output_params, parent);
+ output_node->setName(node->getName()->mString);
+ parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
+ }
+
+ params.from_xui = true;
+ applyXUILayout(params, parent);
+ {
+ LL_RECORD_BLOCK_TIME(FTM_PANEL_CONSTRUCTION);
+ initFromParams(params);
+ }
+
+ // add children
+ LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node);
+
+ // Connect to parent after children are built, because tab containers
+ // do a reshape() on their child panels, which requires that the children
+ // be built/added. JC
+ if (parent)
+ {
+ S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup();
+ parent->addChild(this, tab_group);
+ }
+
+ {
+ LL_RECORD_BLOCK_TIME(FTM_PANEL_POSTBUILD);
+ postBuild();
+ }
+ }
+ return true;
+}
+
+bool LLPanel::hasString(const std::string& name)
+{
+ return mUIStrings.find(name) != mUIStrings.end();
+}
+
+std::string LLPanel::getString(const std::string& name, const LLStringUtil::format_map_t& args) const
+{
+ ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
+ if (found_it != mUIStrings.end())
+ {
+ // make a copy as format works in place
+ LLUIString formatted_string = LLUIString(found_it->second);
+ formatted_string.setArgList(args);
+ return formatted_string.getString();
+ }
+ std::string err_str("Failed to find string " + name + " in panel " + getName()); //*TODO: Translate
+ if(LLUI::getInstance()->mSettingGroups["config"]->getBOOL("QAMode"))
+ {
+ LL_ERRS() << err_str << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << err_str << LL_ENDL;
+ }
+ return LLStringUtil::null;
+}
+
+std::string LLPanel::getString(const std::string& name) const
+{
+ ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
+ if (found_it != mUIStrings.end())
+ {
+ return found_it->second;
+ }
+ std::string err_str("Failed to find string " + name + " in panel " + getName()); //*TODO: Translate
+ if(LLUI::getInstance()->mSettingGroups["config"]->getBOOL("QAMode"))
+ {
+ LL_ERRS() << err_str << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << err_str << LL_ENDL;
+ }
+ return LLStringUtil::null;
+}
+
+
+void LLPanel::childSetVisible(const std::string& id, bool visible)
+{
+ LLView* child = findChild<LLView>(id);
+ if (child)
+ {
+ child->setVisible(visible);
+ }
+}
+
+void LLPanel::childSetEnabled(const std::string& id, bool enabled)
+{
+ LLView* child = findChild<LLView>(id);
+ if (child)
+ {
+ child->setEnabled(enabled);
+ }
+}
+
+void LLPanel::childSetFocus(const std::string& id, bool focus)
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ child->setFocus(focus);
+ }
+}
+
+bool LLPanel::childHasFocus(const std::string& id)
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ return child->hasFocus();
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// *TODO: Deprecate; for backwards compatability only:
+// Prefer getChild<LLUICtrl>("foo")->setCommitCallback(boost:bind(...)),
+// which takes a generic slot. Or use mCommitCallbackRegistrar.add() with
+// a named callback and reference it in XML.
+void LLPanel::childSetCommitCallback(const std::string& id, boost::function<void (LLUICtrl*,void*)> cb, void* data)
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ child->setCommitCallback(boost::bind(cb, child, data));
+ }
+}
+
+void LLPanel::childSetColor(const std::string& id, const LLColor4& color)
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ child->setColor(color);
+ }
+}
+
+LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ return child->getSelectionInterface();
+ }
+ return NULL;
+}
+
+LLCtrlListInterface* LLPanel::childGetListInterface(const std::string& id) const
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ return child->getListInterface();
+ }
+ return NULL;
+}
+
+LLCtrlScrollInterface* LLPanel::childGetScrollInterface(const std::string& id) const
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ return child->getScrollInterface();
+ }
+ return NULL;
+}
+
+void LLPanel::childSetValue(const std::string& id, LLSD value)
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ child->setValue(value);
+ }
+}
+
+LLSD LLPanel::childGetValue(const std::string& id) const
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ return child->getValue();
+ }
+ // Not found => return undefined
+ return LLSD();
+}
+
+bool LLPanel::childSetTextArg(const std::string& id, const std::string& key, const LLStringExplicit& text)
+{
+ LLUICtrl* child = findChild<LLUICtrl>(id);
+ if (child)
+ {
+ return child->setTextArg(key, text);
+ }
+ return false;
+}
+
+bool LLPanel::childSetLabelArg(const std::string& id, const std::string& key, const LLStringExplicit& text)
+{
+ LLView* child = findChild<LLView>(id);
+ if (child)
+ {
+ return child->setLabelArg(key, text);
+ }
+ return false;
+}
+
+void LLPanel::childSetAction(const std::string& id, const commit_signal_t::slot_type& function)
+{
+ LLButton* button = findChild<LLButton>(id);
+ if (button)
+ {
+ button->setClickedCallback(function);
+ }
+}
+
+void LLPanel::childSetAction(const std::string& id, boost::function<void(void*)> function, void* value)
+{
+ LLButton* button = findChild<LLButton>(id);
+ if (button)
+ {
+ button->setClickedCallback(boost::bind(function, value));
+ }
+}
+
+boost::signals2::connection LLPanel::setVisibleCallback( const commit_signal_t::slot_type& cb )
+{
+ if (!mVisibleSignal)
+ {
+ mVisibleSignal = new commit_signal_t();
+ }
+
+ return mVisibleSignal->connect(cb);
+}
+
+//-----------------------------------------------------------------------------
+// buildPanel()
+//-----------------------------------------------------------------------------
+bool LLPanel::buildFromFile(const std::string& filename, const LLPanel::Params& default_params)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ bool didPost = false;
+ LLXMLNodePtr root;
+
+ if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
+ {
+ LL_WARNS() << "Couldn't parse panel from: " << filename << LL_ENDL;
+ return didPost;
+ }
+
+ // root must be called panel
+ if( !root->hasName("panel" ) )
+ {
+ LL_WARNS() << "Root node should be named panel in : " << filename << LL_ENDL;
+ return didPost;
+ }
+
+ LL_DEBUGS() << "Building panel " << filename << LL_ENDL;
+
+ LLUICtrlFactory::instance().pushFileName(filename);
+ {
+ if (!getFactoryMap().empty())
+ {
+ sFactoryStack.push_back(&getFactoryMap());
+ }
+
+ // for local registry callbacks; define in constructor, referenced in XUI or postBuild
+ getCommitCallbackRegistrar().pushScope();
+ getEnableCallbackRegistrar().pushScope();
+
+ didPost = initPanelXML(root, NULL, NULL, default_params);
+
+ getCommitCallbackRegistrar().popScope();
+ getEnableCallbackRegistrar().popScope();
+
+ setXMLFilename(filename);
+
+ if (!getFactoryMap().empty())
+ {
+ sFactoryStack.pop_back();
+ }
+ }
+ LLUICtrlFactory::instance().popFileName();
+ return didPost;
+}
+
+//-----------------------------------------------------------------------------
+// createFactoryPanel()
+//-----------------------------------------------------------------------------
+LLPanel* LLPanel::createFactoryPanel(const std::string& name)
+{
+ std::deque<const LLCallbackMap::map_t*>::iterator itor;
+ for (itor = sFactoryStack.begin(); itor != sFactoryStack.end(); ++itor)
+ {
+ const LLCallbackMap::map_t* factory_map = *itor;
+
+ // Look up this panel's name in the map.
+ LLCallbackMap::map_const_iter_t iter = factory_map->find( name );
+ if (iter != factory_map->end())
+ {
+ // Use the factory to create the panel, instead of using a default LLPanel.
+ LLPanel *ret = (LLPanel*) iter->second.mCallback( iter->second.mData );
+ return ret;
+ }
+ }
+ LLPanel::Params panel_p;
+ return LLUICtrlFactory::create<LLPanel>(panel_p);
+}
|