00001
00032
00033
00034
00035
00036 #include "linden_common.h"
00037
00038 #include "llboost.h"
00039
00040 #include "llradiogroup.h"
00041 #include "indra_constants.h"
00042
00043 #include "llviewborder.h"
00044 #include "llcontrol.h"
00045 #include "llui.h"
00046 #include "llfocusmgr.h"
00047
00048 LLRadioGroup::LLRadioGroup(const LLString& name, const LLRect& rect,
00049 const LLString& control_name,
00050 LLUICtrlCallback callback,
00051 void* userdata,
00052 BOOL border)
00053 : LLUICtrl(name, rect, TRUE, callback, userdata, FOLLOWS_LEFT | FOLLOWS_TOP),
00054 mSelectedIndex(0)
00055 {
00056 setControlName(control_name, NULL);
00057 init(border);
00058 }
00059
00060 LLRadioGroup::LLRadioGroup(const LLString& name, const LLRect& rect,
00061 S32 initial_index,
00062 LLUICtrlCallback callback,
00063 void* userdata,
00064 BOOL border) :
00065 LLUICtrl(name, rect, TRUE, callback, userdata, FOLLOWS_LEFT | FOLLOWS_TOP),
00066 mSelectedIndex(initial_index)
00067 {
00068 init(border);
00069 }
00070
00071 void LLRadioGroup::init(BOOL border)
00072 {
00073 if (border)
00074 {
00075 addChild( new LLViewBorder( "radio group border",
00076 LLRect(0, mRect.getHeight(), mRect.getWidth(), 0),
00077 LLViewBorder::BEVEL_NONE,
00078 LLViewBorder::STYLE_LINE,
00079 1 ) );
00080 }
00081 mHasBorder = border;
00082 }
00083
00084
00085
00086
00087 LLRadioGroup::~LLRadioGroup()
00088 {
00089 }
00090
00091
00092
00093 void LLRadioGroup::setEnabled(BOOL enabled)
00094 {
00095 for (child_list_const_iter_t child_iter = getChildList()->begin();
00096 child_iter != getChildList()->end(); ++child_iter)
00097 {
00098 LLView *child = *child_iter;
00099 child->setEnabled(enabled);
00100 }
00101 LLView::setEnabled(enabled);
00102 }
00103
00104 void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled)
00105 {
00106 S32 count = 0;
00107 for (button_list_t::iterator iter = mRadioButtons.begin();
00108 iter != mRadioButtons.end(); ++iter)
00109 {
00110 LLRadioCtrl* child = *iter;
00111 if (count == index)
00112 {
00113 child->setEnabled(enabled);
00114 if (index == mSelectedIndex && enabled == FALSE)
00115 {
00116 setSelectedIndex(-1);
00117 }
00118 break;
00119 }
00120 count++;
00121 }
00122 count = 0;
00123 if (mSelectedIndex < 0)
00124 {
00125
00126
00127
00128 for (button_list_t::iterator iter = mRadioButtons.begin();
00129 iter != mRadioButtons.end(); ++iter)
00130 {
00131 LLRadioCtrl* child = *iter;
00132 if (count >= index && mSelectedIndex >= 0)
00133 {
00134 break;
00135 }
00136 if (child->getEnabled())
00137 {
00138 setSelectedIndex(count);
00139 }
00140 count++;
00141 }
00142 if (mSelectedIndex < 0)
00143 {
00144 setSelectedIndex(0);
00145 }
00146 }
00147 }
00148
00149 S32 LLRadioGroup::getSelectedIndex() const
00150 {
00151 return mSelectedIndex;
00152 }
00153
00154 BOOL LLRadioGroup::setSelectedIndex(S32 index, BOOL from_event)
00155 {
00156 if (index < 0 || index >= (S32)mRadioButtons.size())
00157 {
00158 return FALSE;
00159 }
00160
00161 mSelectedIndex = index;
00162
00163 if (!from_event)
00164 {
00165 setControlValue(getSelectedIndex());
00166 }
00167
00168 return TRUE;
00169 }
00170
00171 BOOL LLRadioGroup::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
00172 {
00173 BOOL handled = FALSE;
00174
00175 if (getEnabled() && !called_from_parent && mask == MASK_NONE)
00176 {
00177 switch(key)
00178 {
00179 case KEY_DOWN:
00180 if (!setSelectedIndex((getSelectedIndex() + 1)))
00181 {
00182 make_ui_sound("UISndInvalidOp");
00183 }
00184 else
00185 {
00186 onCommit();
00187 }
00188 handled = TRUE;
00189 break;
00190 case KEY_UP:
00191 if (!setSelectedIndex((getSelectedIndex() - 1)))
00192 {
00193 make_ui_sound("UISndInvalidOp");
00194 }
00195 else
00196 {
00197 onCommit();
00198 }
00199 handled = TRUE;
00200 break;
00201 case KEY_LEFT:
00202 if (!setSelectedIndex((getSelectedIndex() - 1)))
00203 {
00204 make_ui_sound("UISndInvalidOp");
00205 }
00206 else
00207 {
00208 onCommit();
00209 }
00210 handled = TRUE;
00211 break;
00212 case KEY_RIGHT:
00213 if (!setSelectedIndex((getSelectedIndex() + 1)))
00214 {
00215 make_ui_sound("UISndInvalidOp");
00216 }
00217 else
00218 {
00219 onCommit();
00220 }
00221 handled = TRUE;
00222 break;
00223 default:
00224 break;
00225 }
00226 }
00227 return handled;
00228 }
00229
00230 void LLRadioGroup::draw()
00231 {
00232 S32 current_button = 0;
00233
00234 BOOL take_focus = FALSE;
00235 if (gFocusMgr.childHasKeyboardFocus(this))
00236 {
00237 take_focus = TRUE;
00238 }
00239
00240 for (button_list_t::iterator iter = mRadioButtons.begin();
00241 iter != mRadioButtons.end(); ++iter)
00242 {
00243 LLRadioCtrl* radio = *iter;
00244 BOOL selected = (current_button == mSelectedIndex);
00245 radio->setValue( selected );
00246 if (take_focus && selected && !gFocusMgr.childHasKeyboardFocus(radio))
00247 {
00248 radio->focusFirstItem();
00249 }
00250 current_button++;
00251 }
00252
00253 LLView::draw();
00254 }
00255
00256
00257
00258
00259 LLRadioCtrl* LLRadioGroup::addRadioButton(const LLString& name, const LLString& label, const LLRect& rect, const LLFontGL* font )
00260 {
00261
00262 LLRadioCtrl* radio = new LLRadioCtrl(name, rect, label, font,
00263 onClickButton, this);
00264 addChild(radio);
00265 mRadioButtons.push_back(radio);
00266 return radio;
00267 }
00268
00269
00270
00271
00272
00273 void LLRadioGroup::onClickButton(LLUICtrl* ui_ctrl, void* userdata)
00274 {
00275
00276
00277 LLRadioCtrl* clickedRadio = (LLRadioCtrl*) ui_ctrl;
00278 LLRadioGroup* self = (LLRadioGroup*) userdata;
00279
00280 S32 counter = 0;
00281 for (button_list_t::iterator iter = self->mRadioButtons.begin();
00282 iter != self->mRadioButtons.end(); ++iter)
00283 {
00284 LLRadioCtrl* radio = *iter;
00285 if (radio == clickedRadio)
00286 {
00287
00288 self->setSelectedIndex(counter);
00289 self->setControlValue(counter);
00290
00291
00292 self->onCommit();
00293
00294 return;
00295 }
00296
00297 counter++;
00298 }
00299
00300 llwarns << "LLRadioGroup::onClickButton - clicked button that isn't a child" << llendl;
00301 }
00302
00303 void LLRadioGroup::setValue( const LLSD& value )
00304 {
00305 LLString value_name = value.asString();
00306 int idx = 0;
00307 for (button_list_t::const_iterator iter = mRadioButtons.begin();
00308 iter != mRadioButtons.end(); ++iter)
00309 {
00310 LLRadioCtrl* radio = *iter;
00311 if (radio->getName() == value_name)
00312 {
00313 setSelectedIndex(idx);
00314 idx = -1;
00315 break;
00316 }
00317 ++idx;
00318 }
00319 if (idx != -1)
00320 {
00321
00322 if (value.isInteger())
00323 {
00324 setSelectedIndex((S32) value.asInteger(), TRUE);
00325 }
00326 else
00327 {
00328 llwarns << "LLRadioGroup::setValue: value not found: " << value_name << llendl;
00329 }
00330 }
00331 }
00332
00333 LLSD LLRadioGroup::getValue() const
00334 {
00335 int index = getSelectedIndex();
00336 int idx = 0;
00337 for (button_list_t::const_iterator iter = mRadioButtons.begin();
00338 iter != mRadioButtons.end(); ++iter)
00339 {
00340 if (idx == index) return LLSD((*iter)->getName());
00341 ++idx;
00342 }
00343 return LLSD();
00344 }
00345
00346
00347 LLXMLNodePtr LLRadioGroup::getXML(bool save_children) const
00348 {
00349 LLXMLNodePtr node = LLUICtrl::getXML();
00350
00351
00352
00353 node->createChild("draw_border", TRUE)->setBoolValue(mHasBorder);
00354
00355
00356
00357 for (button_list_t::const_iterator iter = mRadioButtons.begin();
00358 iter != mRadioButtons.end(); ++iter)
00359 {
00360 LLRadioCtrl* radio = *iter;
00361
00362 LLXMLNodePtr child_node = radio->LLView::getXML();
00363 child_node->setStringValue(radio->getLabel());
00364 child_node->setName("radio_item");
00365
00366 node->addChild(child_node);
00367 }
00368
00369 return node;
00370 }
00371
00372
00373 LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00374 {
00375 LLString name("radio_group");
00376 node->getAttributeString("name", name);
00377
00378 U32 initial_value = 0;
00379 node->getAttributeU32("initial_value", initial_value);
00380
00381 BOOL draw_border = TRUE;
00382 node->getAttributeBOOL("draw_border", draw_border);
00383
00384 LLRect rect;
00385 createRect(node, rect, parent, LLRect());
00386
00387 LLRadioGroup* radio_group = new LLRadioGroup(name,
00388 rect,
00389 initial_value,
00390 NULL,
00391 NULL,
00392 draw_border);
00393
00394 const LLString& contents = node->getValue();
00395
00396 LLRect group_rect = radio_group->getRect();
00397
00398 LLFontGL *font = LLView::selectFont(node);
00399
00400 if (contents.find_first_not_of(" \n\t") != contents.npos)
00401 {
00402
00403 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00404 boost::char_separator<char> sep("\t\n");
00405 tokenizer tokens(contents, sep);
00406 tokenizer::iterator token_iter = tokens.begin();
00407
00408 const S32 HPAD = 4, VPAD = 4;
00409 S32 cur_y = group_rect.getHeight() - VPAD;
00410
00411 while(token_iter != tokens.end())
00412 {
00413 const char* line = token_iter->c_str();
00414 LLRect rect(HPAD, cur_y, group_rect.getWidth() - (2 * HPAD), cur_y - 15);
00415 cur_y -= VPAD + 15;
00416 radio_group->addRadioButton("radio", line, rect, font);
00417 ++token_iter;
00418 }
00419 llwarns << "Legacy radio group format used! Please convert to use <radio_item> tags!" << llendl;
00420 }
00421 else
00422 {
00423
00424 LLXMLNodePtr child;
00425 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
00426 {
00427 if (child->hasName("radio_item"))
00428 {
00429 LLRect item_rect;
00430 createRect(child, item_rect, radio_group, rect);
00431
00432 LLString radioname("radio");
00433 child->getAttributeString("name", radioname);
00434 LLString item_label = child->getTextContents();
00435
00436
00437
00438 if ( item_label == "" )
00439 {
00440 item_label = " ";
00441 }
00442
00443 LLRadioCtrl* radio = radio_group->addRadioButton(radioname, item_label.c_str(), item_rect, font);
00444
00445 radio->initFromXML(child, radio_group);
00446 }
00447 }
00448 }
00449
00450 radio_group->initFromXML(node, parent);
00451
00452 return radio_group;
00453 }
00454
00455
00456 BOOL LLRadioGroup::setCurrentByID( const LLUUID& id )
00457 {
00458 return FALSE;
00459 }
00460
00461 LLUUID LLRadioGroup::getCurrentID()
00462 {
00463 return LLUUID::null;
00464 }
00465
00466 BOOL LLRadioGroup::setSelectedByValue(LLSD value, BOOL selected)
00467 {
00468 S32 idx = 0;
00469 std::string value_string = value.asString();
00470 for (button_list_t::const_iterator iter = mRadioButtons.begin();
00471 iter != mRadioButtons.end(); ++iter)
00472 {
00473 if((*iter)->getName() == value_string)
00474 {
00475 setSelectedIndex(idx);
00476 return TRUE;
00477 }
00478 idx++;
00479 }
00480
00481 return FALSE;
00482 }
00483
00484 LLSD LLRadioGroup::getSimpleSelectedValue()
00485 {
00486 return getValue();
00487 }
00488
00489 BOOL LLRadioGroup::isSelected(LLSD value)
00490 {
00491 S32 idx = 0;
00492 std::string value_string = value.asString();
00493 for (button_list_t::const_iterator iter = mRadioButtons.begin();
00494 iter != mRadioButtons.end(); ++iter)
00495 {
00496 if((*iter)->getName() == value_string)
00497 {
00498 if (idx == mSelectedIndex)
00499 {
00500 return TRUE;
00501 }
00502 }
00503 idx++;
00504 }
00505 return FALSE;
00506 }
00507
00508 BOOL LLRadioGroup::operateOnSelection(EOperation op)
00509 {
00510 return FALSE;
00511 }
00512
00513 BOOL LLRadioGroup::operateOnAll(EOperation op)
00514 {
00515 return FALSE;
00516 }
00517
00518
00519 LLRadioCtrl::LLRadioCtrl(const LLString& name, const LLRect& rect, const LLString& label,
00520 const LLFontGL* font, void (*commit_callback)(LLUICtrl*, void*), void* callback_userdata) :
00521 LLCheckBoxCtrl(name, rect, label, font, commit_callback, callback_userdata, FALSE, RADIO_STYLE)
00522 {
00523 setTabStop(FALSE);
00524 }
00525
00526 LLRadioCtrl::~LLRadioCtrl()
00527 {
00528 }
00529
00530 void LLRadioCtrl::setValue(const LLSD& value)
00531 {
00532 LLCheckBoxCtrl::setValue(value);
00533 mButton->setTabStop(value.asBoolean());
00534 }
00535