123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- /**
- * @file llradiogroup.cpp
- * @brief LLRadioGroup base class
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "llradiogroup.h"
- #include "indra_constants.h"
- #include "llcontrol.h"
- #include "llviewborder.h"
- static const std::string LL_RADIO_GROUP_TAG = "radio_group";
- static const std::string LL_RADIO_ITEM_TAG = "radio_item";
- static LLRegisterWidget<LLRadioGroup> r17(LL_RADIO_GROUP_TAG);
- ///////////////////////////////////////////////////////////////////////////////
- // LLRadioCtrl class
- ///////////////////////////////////////////////////////////////////////////////
- //virtual
- const std::string& LLRadioCtrl::getTag() const
- {
- return LL_RADIO_ITEM_TAG;
- }
- void LLRadioCtrl::setValue(const LLSD& value)
- {
- LLCheckBoxCtrl::setValue(value);
- mButton->setTabStop(value.asBoolean());
- }
- //virtual
- LLXMLNodePtr LLRadioCtrl::getXML(bool save_children) const
- {
- LLXMLNodePtr nodep = LLCheckBoxCtrl::getXML();
- nodep->setName(LL_RADIO_ITEM_TAG);
- nodep->setStringValue(getLabel());
- return nodep;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // LLRadioGroup class
- ///////////////////////////////////////////////////////////////////////////////
- LLRadioGroup::LLRadioGroup(const std::string& name, const LLRect& rect,
- const char* control_name,
- LLUICtrlCallback callback, void* userdata,
- bool border)
- : LLUICtrl(name, rect, true, callback, userdata, FOLLOWS_LEFT | FOLLOWS_TOP),
- mSelectedIndex(0)
- {
- setControlName(control_name, NULL);
- init(border);
- }
- LLRadioGroup::LLRadioGroup(const std::string& name, const LLRect& rect,
- S32 initial_index, LLUICtrlCallback callback,
- void* userdata, bool border)
- : LLUICtrl(name, rect, true, callback, userdata, FOLLOWS_LEFT | FOLLOWS_TOP),
- mSelectedIndex(initial_index)
- {
- init(border);
- }
- void LLRadioGroup::init(bool border)
- {
- if (border)
- {
- addChild(new LLViewBorder("radio group border",
- LLRect(0, getRect().getHeight(),
- getRect().getWidth(), 0),
- LLViewBorder::BEVEL_NONE,
- LLViewBorder::STYLE_LINE, 1));
- }
- mHasBorder = border;
- }
- //virtual
- void LLRadioGroup::setEnabled(bool enabled)
- {
- for (child_list_const_iter_t it = getChildList()->begin(),
- end = getChildList()->end();
- it != end; ++it)
- {
- (*it)->setEnabled(enabled);
- }
- LLView::setEnabled(enabled);
- }
- void LLRadioGroup::setIndexEnabled(S32 index, bool enabled)
- {
- button_list_t::iterator begin = mRadioButtons.begin();
- button_list_t::iterator end = mRadioButtons.end();
- S32 count = 0;
- for (button_list_t::iterator iter = begin; iter != end; ++iter)
- {
- LLRadioCtrl* childp = *iter;
- if (count == index)
- {
- childp->setEnabled(enabled);
- if (index == mSelectedIndex && !enabled)
- {
- setSelectedIndex(-1);
- }
- break;
- }
- ++count;
- }
- count = 0;
- if (mSelectedIndex < 0)
- {
- // Set to highest enabled value < index, or lowest value above index if
- // none lower are enabled, or 0 if none are enabled
- for (button_list_t::iterator iter = begin; iter != end; ++iter)
- {
- if (count >= index && mSelectedIndex >= 0)
- {
- break;
- }
- LLRadioCtrl* childp = *iter;
- if (childp->getEnabled())
- {
- setSelectedIndex(count);
- }
- ++count;
- }
- if (mSelectedIndex < 0)
- {
- setSelectedIndex(0);
- }
- }
- }
- bool LLRadioGroup::setSelectedIndex(S32 index, bool from_event)
- {
- if (index < 0 || index >= (S32)mRadioButtons.size())
- {
- return false;
- }
- mSelectedIndex = index;
- if (!from_event)
- {
- setControlValue(getSelectedIndex());
- }
- return true;
- }
- bool LLRadioGroup::handleKeyHere(KEY key, MASK mask)
- {
- bool handled = false;
- // do any of the tab buttons have keyboard focus ?
- if (mask == MASK_NONE)
- {
- handled = true;
- switch (key)
- {
- case KEY_DOWN:
- if (!setSelectedIndex(getSelectedIndex() + 1))
- {
- make_ui_sound("UISndInvalidOp");
- }
- else
- {
- onCommit();
- }
- break;
- case KEY_UP:
- if (!setSelectedIndex(getSelectedIndex() - 1))
- {
- make_ui_sound("UISndInvalidOp");
- }
- else
- {
- onCommit();
- }
- break;
- case KEY_LEFT:
- if (!setSelectedIndex(getSelectedIndex() - 1))
- {
- make_ui_sound("UISndInvalidOp");
- }
- else
- {
- onCommit();
- }
- break;
- case KEY_RIGHT:
- if (!setSelectedIndex(getSelectedIndex() + 1))
- {
- make_ui_sound("UISndInvalidOp");
- }
- else
- {
- onCommit();
- }
- break;
- default:
- handled = false;
- }
- }
- return handled;
- }
- void LLRadioGroup::draw()
- {
- S32 current_button = 0;
- bool take_focus = false;
- if (gFocusMgr.childHasKeyboardFocus(this))
- {
- take_focus = true;
- }
- for (button_list_t::iterator iter = mRadioButtons.begin(),
- end = mRadioButtons.end();
- iter != end; ++iter)
- {
- LLRadioCtrl* radiop = *iter;
- bool selected = current_button == mSelectedIndex;
- radiop->setValue(selected);
- if (take_focus && selected && !gFocusMgr.childHasKeyboardFocus(radiop))
- {
- // Do not flash keyboard focus when navigating via keyboard
- bool dont_flash = false;
- radiop->focusFirstItem(false, dont_flash);
- }
- ++current_button;
- }
- LLView::draw();
- }
- // When adding a button, we need to ensure that the radio group gets a message
- // when the button is clicked.
- LLRadioCtrl* LLRadioGroup::addRadioButton(const std::string& name,
- const std::string& label,
- const LLRect& rect,
- const LLFontGL* fontp)
- {
- // Highlight will get fixed in draw method above
- LLRadioCtrl* radiop = new LLRadioCtrl(name, rect, label, fontp,
- onClickButton, this);
- addChild(radiop);
- mRadioButtons.push_back(radiop);
- return radiop;
- }
- // Handle one button being clicked. All child buttons must have this method as
- // their callback.
- //static
- void LLRadioGroup::onClickButton(LLUICtrl* ctrlp, void* userdata)
- {
- LLRadioCtrl* clicked_radiop = (LLRadioCtrl*)ctrlp;
- LLRadioGroup* self = (LLRadioGroup*)userdata;
- S32 counter = 0;
- for (button_list_t::iterator iter = self->mRadioButtons.begin(),
- end = self->mRadioButtons.end();
- iter != end; ++iter)
- {
- LLRadioCtrl* radiop = *iter;
- if (radiop == clicked_radiop)
- {
- #if 1 // Note: original code did not have this check and unconditionnaly
- // called onCommit(), which was commented as a bug; this fix should
- // not have any bad consequence... HB
- if (self->mSelectedIndex != counter)
- #endif
- {
- self->setSelectedIndex(counter);
- self->setControlValue(counter);
- self->onCommit();
- }
- return;
- }
- ++counter;
- }
- // This should never happen.
- llerrs << "Passed LLUICtrl pointer is not a child button of radio group: "
- << self->getName() << llendl;
- }
- void LLRadioGroup::setValue(const LLSD& value)
- {
- std::string value_name = value.asString();
- S32 idx = 0;
- for (button_list_t::const_iterator iter = mRadioButtons.begin(),
- end = mRadioButtons.end();
- iter != end; ++iter)
- {
- LLRadioCtrl* radiop = *iter;
- if (radiop->getName() == value_name)
- {
- setSelectedIndex(idx);
- idx = -1;
- break;
- }
- ++idx;
- }
- if (idx != -1)
- {
- // String not found, try integer
- if (value.isInteger())
- {
- setSelectedIndex(value.asInteger(), true);
- }
- else
- {
- llwarns << "Value not found: " << value_name << llendl;
- }
- }
- }
- LLSD LLRadioGroup::getValue() const
- {
- S32 index = getSelectedIndex();
- S32 idx = 0;
- for (button_list_t::const_iterator iter = mRadioButtons.begin(),
- end = mRadioButtons.end();
- iter != end; ++iter)
- {
- if (idx == index)
- {
- return LLSD((*iter)->getName());
- }
- ++idx;
- }
- return LLSD();
- }
- //virtual
- const std::string& LLRadioGroup::getTag() const
- {
- return LL_RADIO_GROUP_TAG;
- }
- //virtual
- LLXMLNodePtr LLRadioGroup::getXML(bool save_children) const
- {
- LLXMLNodePtr nodep = LLUICtrl::getXML();
- nodep->setName(LL_RADIO_GROUP_TAG);
- // Attributes
- nodep->createChild("draw_border", true)->setBoolValue(mHasBorder);
- // Contents
- for (button_list_t::const_iterator iter = mRadioButtons.begin(),
- end = mRadioButtons.end();
- iter != end; ++iter)
- {
- LLXMLNodePtr child_nodep = (*iter)->getXML();
- nodep->addChild(child_nodep);
- }
- return nodep;
- }
- // static
- LLView* LLRadioGroup::fromXML(LLXMLNodePtr nodep, LLView* parentp,
- LLUICtrlFactory*)
- {
- std::string name = LL_RADIO_GROUP_TAG;
- nodep->getAttributeString("name", name);
- U32 initial_value = 0;
- nodep->getAttributeU32("initial_value", initial_value);
- bool draw_border = true;
- nodep->getAttributeBool("draw_border", draw_border);
- LLRect rect;
- createRect(nodep, rect, parentp, LLRect());
- LLRadioGroup* groupp = new LLRadioGroup(name, rect, initial_value, NULL,
- NULL, draw_border);
- LLFontGL* fontp = LLView::selectFont(nodep);
- LLXMLNodePtr childp;
- for (LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();
- childp = childp->getNextSibling())
- {
- if (childp->hasName("radio_item"))
- {
- LLRect item_rect;
- createRect(childp, item_rect, groupp, rect);
- std::string radioname("radio");
- childp->getAttributeString("name", radioname);
- std::string item_label = childp->getTextContents();
- LLRadioCtrl* radiop = groupp->addRadioButton(radioname, item_label,
- item_rect, fontp);
- radiop->initFromXML(childp, groupp);
- }
- }
- groupp->initFromXML(nodep, parentp);
- return groupp;
- }
- bool LLRadioGroup::setSelectedByValue(const LLSD& value, bool selected)
- {
- S32 idx = 0;
- std::string value_string = value.asString();
- for (button_list_t::const_iterator iter = mRadioButtons.begin(),
- end = mRadioButtons.end();
- iter != end; ++iter)
- {
- if ((*iter)->getName() == value_string)
- {
- setSelectedIndex(idx);
- return true;
- }
- ++idx;
- }
- return false;
- }
- bool LLRadioGroup::isSelected(const LLSD& value) const
- {
- S32 idx = 0;
- std::string value_string = value.asString();
- for (button_list_t::const_iterator iter = mRadioButtons.begin(),
- end = mRadioButtons.end();
- iter != end; ++iter)
- {
- if ((*iter)->getName() == value_string)
- {
- if (idx == mSelectedIndex)
- {
- return true;
- }
- }
- ++idx;
- }
- return false;
- }
|