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