00001
00032
00033
00034
00035 #include "linden_common.h"
00036
00037
00038 #include "llcombobox.h"
00039
00040
00041 #include "llstring.h"
00042
00043
00044 #include "llbutton.h"
00045 #include "llkeyboard.h"
00046 #include "llscrolllistctrl.h"
00047 #include "llwindow.h"
00048 #include "llfloater.h"
00049 #include "llscrollbar.h"
00050 #include "llcontrol.h"
00051 #include "llfocusmgr.h"
00052 #include "lllineeditor.h"
00053 #include "v2math.h"
00054
00055
00056 S32 LLCOMBOBOX_HEIGHT = 0;
00057 S32 LLCOMBOBOX_WIDTH = 0;
00058
00059 LLComboBox::LLComboBox( const LLString& name, const LLRect &rect, const LLString& label,
00060 void (*commit_callback)(LLUICtrl*,void*),
00061 void *callback_userdata
00062 )
00063 : LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata,
00064 FOLLOWS_LEFT | FOLLOWS_TOP),
00065 mDrawArrow(TRUE),
00066 mTextEntry(NULL),
00067 mArrowImage(NULL),
00068 mArrowImageWidth(8),
00069 mAllowTextEntry(FALSE),
00070 mMaxChars(20),
00071 mTextEntryTentative(TRUE),
00072 mListPosition(BELOW),
00073 mPrearrangeCallback( NULL ),
00074 mTextEntryCallback( NULL )
00075 {
00076
00077
00078
00079
00080
00081
00082
00083
00084 mKeyboardFocusOnClick = TRUE;
00085
00086 LLRect r;
00087 r.setOriginAndSize(0, 0, rect.getWidth(), rect.getHeight());
00088
00089
00090
00091 mButton = new LLSquareButton("comboxbox button",
00092 r, label, NULL, LLString::null,
00093 NULL, this);
00094 mButton->setMouseDownCallback(onButtonDown);
00095 mButton->setFont(LLFontGL::sSansSerifSmall);
00096 mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
00097 mButton->setHAlign( LLFontGL::LEFT );
00098
00099 const S32 ARROW_WIDTH = 16;
00100 mButton->setRightHPad( ARROW_WIDTH );
00101 addChild(mButton);
00102
00103
00104 S32 list_width = mRect.getWidth() + SCROLLBAR_SIZE;
00105 r.setOriginAndSize(0, 16, list_width, 220);
00106
00107
00108 mList = new LLScrollListCtrl(
00109 "ComboBox", r,
00110 &LLComboBox::onItemSelected, this, FALSE);
00111 mList->setVisible(FALSE);
00112 mList->setBgWriteableColor( LLColor4(1,1,1,1) );
00113 mList->setCommitOnKeyboardMovement(FALSE);
00114 mList->setFocusChangedCallback(onListFocusChanged);
00115 addChild(mList);
00116
00117 LLRect border_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
00118 mBorder = new LLViewBorder( "combo border", border_rect );
00119 addChild( mBorder );
00120 mBorder->setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP|FOLLOWS_BOTTOM);
00121
00122 LLUUID arrow_image_id( LLUI::sAssetsGroup->getString("combobox_arrow.tga") );
00123 mArrowImage = LLUI::sImageProvider->getUIImageByID(arrow_image_id);
00124 mArrowImageWidth = llmax(8,mArrowImage->getWidth(0));
00125 }
00126
00127
00128 LLComboBox::~LLComboBox()
00129 {
00130
00131 }
00132
00133
00134 LLXMLNodePtr LLComboBox::getXML(bool save_children) const
00135 {
00136 LLXMLNodePtr node = LLUICtrl::getXML();
00137
00138
00139
00140 node->createChild("allow_text_entry", TRUE)->setBoolValue(mAllowTextEntry);
00141
00142 node->createChild("max_chars", TRUE)->setIntValue(mMaxChars);
00143
00144
00145
00146 std::vector<LLScrollListItem*> data_list = mList->getAllData();
00147 std::vector<LLScrollListItem*>::iterator data_itor;
00148 for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor)
00149 {
00150 LLScrollListItem* item = *data_itor;
00151 LLScrollListCell* cell = item->getColumn(0);
00152 if (cell)
00153 {
00154 LLXMLNodePtr item_node = node->createChild("combo_item", FALSE);
00155 LLSD value = item->getValue();
00156 item_node->createChild("value", TRUE)->setStringValue(value.asString());
00157 item_node->createChild("enabled", TRUE)->setBoolValue(item->getEnabled());
00158 item_node->setStringValue(cell->getText());
00159 }
00160 }
00161
00162 return node;
00163 }
00164
00165
00166 LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00167 {
00168 LLString name("combo_box");
00169 node->getAttributeString("name", name);
00170
00171 LLString label("");
00172 node->getAttributeString("label", label);
00173
00174 LLRect rect;
00175 createRect(node, rect, parent, LLRect());
00176
00177 BOOL allow_text_entry = FALSE;
00178 node->getAttributeBOOL("allow_text_entry", allow_text_entry);
00179
00180 S32 max_chars = 20;
00181 node->getAttributeS32("max_chars", max_chars);
00182
00183 LLUICtrlCallback callback = NULL;
00184
00185 LLComboBox* combo_box = new LLComboBox(name,
00186 rect,
00187 label,
00188 callback,
00189 NULL);
00190 combo_box->setAllowTextEntry(allow_text_entry, max_chars);
00191
00192 combo_box->initFromXML(node, parent);
00193
00194 const LLString& contents = node->getValue();
00195
00196 if (contents.find_first_not_of(" \n\t") != contents.npos)
00197 {
00198 llerrs << "Legacy combo box item format used! Please convert to <combo_item> tags!" << llendl;
00199 }
00200 else
00201 {
00202 LLXMLNodePtr child;
00203 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
00204 {
00205 if (child->hasName("combo_item"))
00206 {
00207 LLString label = child->getTextContents();
00208
00209 LLString value = label;
00210 child->getAttributeString("value", value);
00211
00212 combo_box->add(label, LLSD(value) );
00213 }
00214 }
00215 }
00216
00217 combo_box->selectFirstItem();
00218
00219 return combo_box;
00220 }
00221
00222 void LLComboBox::setEnabled(BOOL enabled)
00223 {
00224 LLView::setEnabled(enabled);
00225 mButton->setEnabled(enabled);
00226 }
00227
00228 void LLComboBox::clear()
00229 {
00230 if (mTextEntry)
00231 {
00232 mTextEntry->setText(LLString::null);
00233 }
00234 mButton->setLabelSelected(LLString::null);
00235 mButton->setLabelUnselected(LLString::null);
00236 mButton->setDisabledLabel(LLString::null);
00237 mButton->setDisabledSelectedLabel(LLString::null);
00238 mList->deselectAllItems();
00239 }
00240
00241 void LLComboBox::onCommit()
00242 {
00243 if (mAllowTextEntry && getCurrentIndex() != -1)
00244 {
00245
00246
00247 mTextEntry->setValue(getSimple());
00248 mTextEntry->setTentative(FALSE);
00249 }
00250 LLUICtrl::onCommit();
00251 }
00252
00253
00254 BOOL LLComboBox::isDirty() const
00255 {
00256 BOOL grubby = FALSE;
00257 if ( mList )
00258 {
00259 grubby = mList->isDirty();
00260 }
00261 return grubby;
00262 }
00263
00264
00265 void LLComboBox::resetDirty()
00266 {
00267 if ( mList )
00268 {
00269 mList->resetDirty();
00270 }
00271 }
00272
00273
00274
00275 void LLComboBox::add(const LLString& name, EAddPosition pos, BOOL enabled)
00276 {
00277 mList->addSimpleItem(name, pos, enabled);
00278 mList->selectFirstItem();
00279 }
00280
00281
00282 void LLComboBox::add(const LLString& name, const LLUUID& id, EAddPosition pos, BOOL enabled )
00283 {
00284 mList->addSimpleItem(name, LLSD(id), pos, enabled);
00285 mList->selectFirstItem();
00286 }
00287
00288
00289 void LLComboBox::add(const LLString& name, void* userdata, EAddPosition pos, BOOL enabled )
00290 {
00291 LLScrollListItem* item = mList->addSimpleItem(name, pos, enabled);
00292 item->setUserdata( userdata );
00293 mList->selectFirstItem();
00294 }
00295
00296
00297 void LLComboBox::add(const LLString& name, LLSD value, EAddPosition pos, BOOL enabled )
00298 {
00299 mList->addSimpleItem(name, value, pos, enabled);
00300 mList->selectFirstItem();
00301 }
00302
00303
00304 void LLComboBox::sortByName()
00305 {
00306 mList->sortByColumn(0, TRUE);
00307 }
00308
00309
00310
00311
00312 BOOL LLComboBox::setSimple(const LLStringExplicit& name)
00313 {
00314 BOOL found = mList->selectSimpleItem(name, FALSE);
00315
00316 if (found)
00317 {
00318 setLabel(name);
00319 }
00320
00321 return found;
00322 }
00323
00324
00325 void LLComboBox::setValue(const LLSD& value)
00326 {
00327 BOOL found = mList->selectByValue(value);
00328 if (found)
00329 {
00330 LLScrollListItem* item = mList->getFirstSelected();
00331 if (item)
00332 {
00333 setLabel( mList->getSimpleSelectedItem() );
00334 }
00335 }
00336 }
00337
00338 const LLString& LLComboBox::getSimple() const
00339 {
00340 const LLString& res = mList->getSimpleSelectedItem();
00341 if (res.empty() && mAllowTextEntry)
00342 {
00343 return mTextEntry->getText();
00344 }
00345 else
00346 {
00347 return res;
00348 }
00349 }
00350
00351 const LLString& LLComboBox::getSimpleSelectedItem(S32 column) const
00352 {
00353 return mList->getSimpleSelectedItem(column);
00354 }
00355
00356
00357 LLSD LLComboBox::getValue() const
00358 {
00359 LLScrollListItem* item = mList->getFirstSelected();
00360 if( item )
00361 {
00362 return item->getValue();
00363 }
00364 else if (mAllowTextEntry)
00365 {
00366 return mTextEntry->getValue();
00367 }
00368 else
00369 {
00370 return LLSD();
00371 }
00372 }
00373
00374 void LLComboBox::setLabel(const LLStringExplicit& name)
00375 {
00376 if ( mAllowTextEntry )
00377 {
00378 mTextEntry->setText(name);
00379 if (mList->selectSimpleItem(name, FALSE))
00380 {
00381 mTextEntry->setTentative(FALSE);
00382 }
00383 else
00384 {
00385 mTextEntry->setTentative(mTextEntryTentative);
00386 }
00387 }
00388 else
00389 {
00390 mButton->setLabelUnselected(name);
00391 mButton->setLabelSelected(name);
00392 mButton->setDisabledLabel(name);
00393 mButton->setDisabledSelectedLabel(name);
00394 }
00395 }
00396
00397
00398 BOOL LLComboBox::remove(const LLString& name)
00399 {
00400 BOOL found = mList->selectSimpleItem(name);
00401
00402 if (found)
00403 {
00404 LLScrollListItem* item = mList->getFirstSelected();
00405 if (item)
00406 {
00407 mList->deleteSingleItem(mList->getItemIndex(item));
00408 }
00409 }
00410
00411 return found;
00412 }
00413
00414 BOOL LLComboBox::remove(S32 index)
00415 {
00416 if (index < mList->getItemCount())
00417 {
00418 mList->deleteSingleItem(index);
00419 return TRUE;
00420 }
00421 return FALSE;
00422 }
00423
00424
00425 void LLComboBox::onFocusLost()
00426 {
00427 hideList();
00428
00429 if (mAllowTextEntry && getCurrentIndex() != -1)
00430 {
00431 mTextEntry->selectAll();
00432 }
00433 LLUICtrl::onFocusLost();
00434 }
00435
00436 void LLComboBox::setButtonVisible(BOOL visible)
00437 {
00438 mButton->setVisible(visible);
00439 mDrawArrow = visible;
00440 if (mTextEntry)
00441 {
00442 LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
00443 if (visible)
00444 {
00445 text_entry_rect.mRight -= mArrowImageWidth + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
00446 }
00447
00448 mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE);
00449 }
00450 }
00451
00452 void LLComboBox::draw()
00453 {
00454 if( getVisible() )
00455 {
00456 mBorder->setKeyboardFocusHighlight(hasFocus());
00457
00458 mButton->setEnabled(mEnabled );
00459
00460
00461 LLUICtrl::draw();
00462
00463 if (mDrawArrow)
00464 {
00465
00466 if (!mArrowImage.isNull())
00467 {
00468 S32 arrow_height = llmin(mRect.getHeight(), mArrowImage->getHeight());
00469 S32 arrow_width = llround((F32)mArrowImage->getWidth() * ((F32)arrow_height / (F32)mArrowImage->getHeight()));
00470
00471 S32 left = mRect.getWidth() - mArrowImage->getWidth() - LLUI::sConfigGroup->getS32("DropShadowButton");
00472
00473 gl_draw_scaled_image( left, 0, arrow_width, arrow_height, mArrowImage, LLColor4::white);
00474 }
00475 }
00476 }
00477 }
00478
00479 BOOL LLComboBox::setCurrentByIndex( S32 index )
00480 {
00481 BOOL found = mList->selectNthItem( index );
00482 if (found)
00483 {
00484 setLabel(mList->getSimpleSelectedItem());
00485 }
00486 return found;
00487 }
00488
00489 S32 LLComboBox::getCurrentIndex() const
00490 {
00491 LLScrollListItem* item = mList->getFirstSelected();
00492 if( item )
00493 {
00494 return mList->getItemIndex( item );
00495 }
00496 return -1;
00497 }
00498
00499
00500 void* LLComboBox::getCurrentUserdata()
00501 {
00502 LLScrollListItem* item = mList->getFirstSelected();
00503 if( item )
00504 {
00505 return item->getUserdata();
00506 }
00507 return NULL;
00508 }
00509
00510
00511 void LLComboBox::showList()
00512 {
00513
00514 LLCoordWindow window_size;
00515 getWindow()->getSize(&window_size);
00516
00517 mList->arrange( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
00518
00519
00520 LLRect root_view_local;
00521 LLView* root_view = getRootView();
00522 root_view->localRectToOtherView(root_view->getLocalRect(), &root_view_local, this);
00523
00524 LLRect rect = mList->getRect();
00525
00526 S32 list_width = mRect.getWidth() + SCROLLBAR_SIZE;
00527
00528 if (mListPosition == BELOW)
00529 {
00530 if (rect.getHeight() <= -root_view_local.mBottom)
00531 {
00532
00533 rect.setLeftTopAndSize(0, 0, list_width, rect.getHeight() );
00534 }
00535 else
00536 {
00537
00538 if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight())
00539 {
00540
00541 rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight()));
00542 }
00543 else
00544 {
00545
00546 rect.setOriginAndSize(0, mRect.getHeight(), list_width, llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
00547 }
00548 }
00549 }
00550 else
00551 {
00552 if (rect.getHeight() <= root_view_local.mTop - mRect.getHeight())
00553 {
00554
00555 rect.setOriginAndSize(0, mRect.getHeight(), list_width, llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
00556 }
00557 else
00558 {
00559
00560 if (-root_view_local.mBottom > root_view_local.mTop - mRect.getHeight())
00561 {
00562
00563 rect.setLeftTopAndSize(0, 0, list_width, llmin(-root_view_local.mBottom, rect.getHeight()));
00564 }
00565 else
00566 {
00567
00568 rect.setOriginAndSize(0, mRect.getHeight(), list_width, llmin(root_view_local.mTop - mRect.getHeight(), rect.getHeight()));
00569 }
00570 }
00571
00572 }
00573 mList->setOrigin(rect.mLeft, rect.mBottom);
00574 mList->reshape(rect.getWidth(), rect.getHeight());
00575 mList->translateIntoRect(root_view_local, FALSE);
00576
00577
00578 S32 x, y;
00579 mList->localPointToScreen(0, 0, &x, &y);
00580
00581 if (y < 0)
00582 {
00583 mList->translate(0, -y);
00584 }
00585
00586
00587 if (mButton->hasMouseCapture())
00588 {
00589 gFocusMgr.setMouseCapture(mList);
00590 }
00591
00592
00593
00594
00595 if (!mList->getFirstSelected())
00596 {
00597
00598
00599 mList->selectFirstItem();
00600 }
00601 mList->setFocus(TRUE);
00602
00603
00604 mButton->setToggleState(TRUE);
00605 mList->setVisible(TRUE);
00606
00607 gFocusMgr.setTopCtrl(mList);
00608 }
00609
00610 void LLComboBox::hideList()
00611 {
00612 mButton->setToggleState(FALSE);
00613 mList->setVisible(FALSE);
00614 mList->highlightNthItem(-1);
00615
00616 if( gFocusMgr.getTopCtrl() == mList )
00617 {
00618 gFocusMgr.setTopCtrl(NULL);
00619 }
00620
00621
00622 }
00623
00624
00625
00626
00627
00628
00629
00630 void LLComboBox::onButtonDown(void *userdata)
00631 {
00632 LLComboBox *self = (LLComboBox *)userdata;
00633
00634 if (!self->mList->getVisible())
00635 {
00636 LLScrollListItem* last_selected_item = self->mList->getLastSelectedItem();
00637 if (last_selected_item)
00638 {
00639
00640 self->mList->highlightNthItem(self->mList->getItemIndex(last_selected_item));
00641 }
00642
00643 if( self->mPrearrangeCallback )
00644 {
00645 self->mPrearrangeCallback( self, self->mCallbackUserData );
00646 }
00647
00648 if (self->mList->getItemCount() != 0)
00649 {
00650 self->showList();
00651 }
00652
00653 if (self->mKeyboardFocusOnClick && !self->hasFocus())
00654 {
00655 self->setFocus( TRUE );
00656 }
00657 }
00658 else
00659 {
00660
00661 self->hideList();
00662
00663 self->onCommit();
00664 }
00665 }
00666
00667
00668
00669
00670 void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata)
00671 {
00672
00673 LLComboBox *self = (LLComboBox *) userdata;
00674
00675 const LLString& name = self->mList->getSimpleSelectedItem();
00676
00677 S32 cur_id = self->getCurrentIndex();
00678 if (cur_id != -1)
00679 {
00680 self->setLabel(name);
00681
00682 if (self->mAllowTextEntry)
00683 {
00684 gFocusMgr.setKeyboardFocus(self->mTextEntry, NULL);
00685 self->mTextEntry->selectAll();
00686 }
00687 }
00688 else
00689 {
00690
00691 self->mList->selectSimpleItem(self->mButton->getLabelSelected());
00692 }
00693 self->onCommit();
00694
00695 self->hideList();
00696 }
00697
00698
00699 void LLComboBox::onListFocusChanged(LLUICtrl* list, void* user_data)
00700 {
00701 LLComboBox *self = (LLComboBox *) list->getParent();
00702
00703 if (!self->mList->hasFocus() && !self->mButton->hasMouseCapture())
00704 {
00705
00706 LLString orig_selection = self->mAllowTextEntry ? self->mTextEntry->getText() : self->mButton->getLabelSelected();
00707
00708 self->hideList();
00709
00710
00711 self->mList->selectSimpleItem(orig_selection, FALSE);
00712 }
00713 }
00714
00715 BOOL LLComboBox::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
00716 {
00717
00718 LLString tool_tip;
00719
00720 if (LLUI::sShowXUINames)
00721 {
00722 tool_tip = getShowNamesToolTip();
00723 }
00724 else
00725 {
00726 tool_tip = mToolTipMsg;
00727 }
00728
00729 if( getVisible() && pointInView( x, y ) )
00730 {
00731 if( !tool_tip.empty() )
00732 {
00733 msg = tool_tip;
00734
00735
00736 localPointToScreen(
00737 0, 0,
00738 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
00739 localPointToScreen(
00740 mRect.getWidth(), mRect.getHeight(),
00741 &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
00742 }
00743 return TRUE;
00744 }
00745 return FALSE;
00746 }
00747
00748 BOOL LLComboBox::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
00749 {
00750 BOOL result = FALSE;
00751 if (gFocusMgr.childHasKeyboardFocus(this))
00752 {
00753
00754 LLScrollListItem* last_selected_item = mList->getLastSelectedItem();
00755 if (last_selected_item)
00756 {
00757
00758 mList->highlightNthItem(mList->getItemIndex(last_selected_item));
00759 }
00760 result = mList->handleKeyHere(key, mask, FALSE);
00761
00762 if (mList->getLastSelectedItem() != last_selected_item)
00763 {
00764 showList();
00765 }
00766 }
00767 return result;
00768 }
00769
00770 BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent)
00771 {
00772 BOOL result = FALSE;
00773 if (gFocusMgr.childHasKeyboardFocus(this))
00774 {
00775
00776 if (' ' != uni_char )
00777 {
00778 LLScrollListItem* last_selected_item = mList->getLastSelectedItem();
00779 if (last_selected_item)
00780 {
00781
00782 mList->highlightNthItem(mList->getItemIndex(last_selected_item));
00783 }
00784 result = mList->handleUnicodeCharHere(uni_char, called_from_parent);
00785 if (mList->getLastSelectedItem() != last_selected_item)
00786 {
00787 showList();
00788 }
00789 }
00790 }
00791 return result;
00792 }
00793
00794 void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative)
00795 {
00796 LLRect rect( 0, mRect.getHeight(), mRect.getWidth(), 0);
00797 if (allow && !mAllowTextEntry)
00798 {
00799 S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton");
00800 mButton->setRect(LLRect( mRect.getWidth() - mArrowImageWidth - 2 * shadow_size,
00801 rect.mTop, rect.mRight, rect.mBottom));
00802 mButton->setTabStop(FALSE);
00803
00804
00805 LLString cur_label = mButton->getLabelSelected();
00806 setLabel(LLString::null);
00807 if (!mTextEntry)
00808 {
00809 LLRect text_entry_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
00810 text_entry_rect.mRight -= mArrowImageWidth + 2 * LLUI::sConfigGroup->getS32("DropShadowButton");
00811 mTextEntry = new LLLineEditor("combo_text_entry",
00812 text_entry_rect,
00813 "",
00814 LLFontGL::sSansSerifSmall,
00815 max_chars,
00816 onTextCommit,
00817 onTextEntry,
00818 NULL,
00819 this,
00820 NULL,
00821 LLViewBorder::BEVEL_NONE,
00822 LLViewBorder::STYLE_LINE,
00823 0);
00824 mTextEntry->setSelectAllonFocusReceived(TRUE);
00825 mTextEntry->setHandleEditKeysDirectly(TRUE);
00826 mTextEntry->setCommitOnFocusLost(FALSE);
00827 mTextEntry->setText(cur_label);
00828 mTextEntry->setIgnoreTab(TRUE);
00829 mTextEntry->setFollowsAll();
00830 addChild(mTextEntry);
00831 mMaxChars = max_chars;
00832 }
00833 else
00834 {
00835 mTextEntry->setVisible(TRUE);
00836 }
00837
00838 mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
00839 }
00840 else if (!allow && mAllowTextEntry)
00841 {
00842 mButton->setRect(rect);
00843 mButton->setTabStop(TRUE);
00844
00845 if (mTextEntry)
00846 {
00847 mTextEntry->setVisible(FALSE);
00848 }
00849 mButton->setFollowsAll();
00850 }
00851 mAllowTextEntry = allow;
00852 mTextEntryTentative = set_tentative;
00853 }
00854
00855 void LLComboBox::setTextEntry(const LLStringExplicit& text)
00856 {
00857 if (mTextEntry)
00858 {
00859 mTextEntry->setText(text);
00860 updateSelection();
00861 }
00862 }
00863
00864
00865 void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
00866 {
00867 LLComboBox* self = (LLComboBox*)user_data;
00868
00869 if (self->mTextEntryCallback)
00870 {
00871 (*self->mTextEntryCallback)(line_editor, self->mCallbackUserData);
00872 }
00873
00874 KEY key = gKeyboard->currentKey();
00875 if (key == KEY_BACKSPACE ||
00876 key == KEY_DELETE)
00877 {
00878 if (self->mList->selectSimpleItem(line_editor->getText(), FALSE))
00879 {
00880 line_editor->setTentative(FALSE);
00881 }
00882 else
00883 {
00884 line_editor->setTentative(self->mTextEntryTentative);
00885 self->mList->deselectAllItems();
00886 }
00887 return;
00888 }
00889
00890 if (key == KEY_LEFT ||
00891 key == KEY_RIGHT)
00892 {
00893 return;
00894 }
00895
00896 if (key == KEY_DOWN)
00897 {
00898 self->setCurrentByIndex(llmin(self->getItemCount() - 1, self->getCurrentIndex() + 1));
00899 if (!self->mList->getVisible())
00900 {
00901 if( self->mPrearrangeCallback )
00902 {
00903 self->mPrearrangeCallback( self, self->mCallbackUserData );
00904 }
00905
00906 if (self->mList->getItemCount() != 0)
00907 {
00908 self->showList();
00909 }
00910 }
00911 line_editor->selectAll();
00912 line_editor->setTentative(FALSE);
00913 }
00914 else if (key == KEY_UP)
00915 {
00916 self->setCurrentByIndex(llmax(0, self->getCurrentIndex() - 1));
00917 if (!self->mList->getVisible())
00918 {
00919 if( self->mPrearrangeCallback )
00920 {
00921 self->mPrearrangeCallback( self, self->mCallbackUserData );
00922 }
00923
00924 if (self->mList->getItemCount() != 0)
00925 {
00926 self->showList();
00927 }
00928 }
00929 line_editor->selectAll();
00930 line_editor->setTentative(FALSE);
00931 }
00932 else
00933 {
00934
00935 self->updateSelection();
00936 }
00937 }
00938
00939 void LLComboBox::updateSelection()
00940 {
00941 LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor());
00942
00943
00944 LLWString user_wstring = mTextEntry->hasSelection() ? left_wstring : mTextEntry->getWText();
00945 LLString full_string = mTextEntry->getText();
00946
00947
00948
00949
00950 if( mTextEntry->getWText().size() == 1 )
00951 {
00952 if (mPrearrangeCallback)
00953 {
00954 mPrearrangeCallback( this, mCallbackUserData );
00955 }
00956 }
00957
00958 if (mList->selectSimpleItem(full_string, FALSE))
00959 {
00960 mTextEntry->setTentative(FALSE);
00961 }
00962 else if (!mList->selectSimpleItemByPrefix(left_wstring, FALSE))
00963 {
00964 mList->deselectAllItems();
00965 mTextEntry->setText(wstring_to_utf8str(user_wstring));
00966 mTextEntry->setTentative(mTextEntryTentative);
00967 }
00968 else
00969 {
00970 LLWString selected_item = utf8str_to_wstring(mList->getSimpleSelectedItem());
00971 LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size());
00972 mTextEntry->setText(wstring_to_utf8str(wtext));
00973 mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size());
00974 mTextEntry->endSelection();
00975 mTextEntry->setTentative(FALSE);
00976 }
00977 }
00978
00979
00980 void LLComboBox::onTextCommit(LLUICtrl* caller, void* user_data)
00981 {
00982 LLComboBox* self = (LLComboBox*)user_data;
00983 LLString text = self->mTextEntry->getText();
00984 self->setSimple(text);
00985 self->onCommit();
00986 self->mTextEntry->selectAll();
00987 }
00988
00989 void LLComboBox::setFocus(BOOL b)
00990 {
00991 LLUICtrl::setFocus(b);
00992
00993 if (b)
00994 {
00995 mList->clearSearchString();
00996 }
00997 }
00998
00999
01000
01001
01002 S32 LLComboBox::getItemCount() const
01003 {
01004 return mList->getItemCount();
01005 }
01006
01007 void LLComboBox::addColumn(const LLSD& column, EAddPosition pos)
01008 {
01009 mList->clearColumns();
01010 mList->addColumn(column, pos);
01011 }
01012
01013 void LLComboBox::clearColumns()
01014 {
01015 mList->clearColumns();
01016 }
01017
01018 void LLComboBox::setColumnLabel(const LLString& column, const LLString& label)
01019 {
01020 mList->setColumnLabel(column, label);
01021 }
01022
01023 LLScrollListItem* LLComboBox::addElement(const LLSD& value, EAddPosition pos, void* userdata)
01024 {
01025 return mList->addElement(value, pos, userdata);
01026 }
01027
01028 LLScrollListItem* LLComboBox::addSimpleElement(const LLString& value, EAddPosition pos, const LLSD& id)
01029 {
01030 return mList->addSimpleElement(value, pos, id);
01031 }
01032
01033 void LLComboBox::clearRows()
01034 {
01035 mList->clearRows();
01036 }
01037
01038 void LLComboBox::sortByColumn(LLString name, BOOL ascending)
01039 {
01040 }
01041
01042
01043
01044
01045 BOOL LLComboBox::setCurrentByID(const LLUUID& id)
01046 {
01047 BOOL found = mList->selectByID( id );
01048
01049 if (found)
01050 {
01051 setLabel(mList->getSimpleSelectedItem());
01052 }
01053
01054 return found;
01055 }
01056
01057 LLUUID LLComboBox::getCurrentID()
01058 {
01059 return mList->getStringUUIDSelectedItem();
01060 }
01061 BOOL LLComboBox::setSelectedByValue(LLSD value, BOOL selected)
01062 {
01063 BOOL found = mList->setSelectedByValue(value, selected);
01064 if (found)
01065 {
01066 setLabel(mList->getSimpleSelectedItem());
01067 }
01068 return found;
01069 }
01070
01071 LLSD LLComboBox::getSimpleSelectedValue()
01072 {
01073 return mList->getSimpleSelectedValue();
01074 }
01075
01076 BOOL LLComboBox::isSelected(LLSD value)
01077 {
01078 return mList->isSelected(value);
01079 }
01080
01081 BOOL LLComboBox::operateOnSelection(EOperation op)
01082 {
01083 if (op == OP_DELETE)
01084 {
01085 mList->deleteSelectedItems();
01086 return TRUE;
01087 }
01088 return FALSE;
01089 }
01090
01091 BOOL LLComboBox::operateOnAll(EOperation op)
01092 {
01093 if (op == OP_DELETE)
01094 {
01095 clearRows();
01096 return TRUE;
01097 }
01098 return FALSE;
01099 }