00001
00032 #include "linden_common.h"
00033 #include "lltextbox.h"
00034 #include "lluictrlfactory.h"
00035 #include "llfocusmgr.h"
00036
00037 static LLRegisterWidget<LLTextBox> r("text");
00038
00039 LLTextBox::LLTextBox(const LLString& name, const LLRect& rect, const LLString& text,
00040 const LLFontGL* font, BOOL mouse_opaque)
00041 : LLUICtrl(name, rect, mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP ),
00042 mFontGL(font ? font : LLFontGL::sSansSerifSmall),
00043 mTextColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
00044 mDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
00045 mBackgroundColor( LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" ) ),
00046 mBorderColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ),
00047 mHoverColor( LLUI::sColorsGroup->getColor( "LabelSelectedColor" ) ),
00048 mHoverActive( FALSE ),
00049 mHasHover( FALSE ),
00050 mBackgroundVisible( FALSE ),
00051 mBorderVisible( FALSE ),
00052 mFontStyle(LLFontGL::DROP_SHADOW_SOFT),
00053 mBorderDropShadowVisible( FALSE ),
00054 mUseEllipses( FALSE ),
00055 mHPad(0),
00056 mVPad(0),
00057 mHAlign( LLFontGL::LEFT ),
00058 mVAlign( LLFontGL::TOP ),
00059 mClickedCallback(NULL),
00060 mCallbackUserData(NULL)
00061 {
00062 setText( text );
00063 setTabStop(FALSE);
00064 }
00065
00066 LLTextBox::LLTextBox(const LLString& name, const LLString& text, F32 max_width,
00067 const LLFontGL* font, BOOL mouse_opaque) :
00068 LLUICtrl(name, LLRect(0, 0, 1, 1), mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
00069 mFontGL(font ? font : LLFontGL::sSansSerifSmall),
00070 mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")),
00071 mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")),
00072 mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")),
00073 mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")),
00074 mHoverColor( LLUI::sColorsGroup->getColor( "LabelSelectedColor" ) ),
00075 mHoverActive( FALSE ),
00076 mHasHover( FALSE ),
00077 mBackgroundVisible(FALSE),
00078 mBorderVisible(FALSE),
00079 mFontStyle(LLFontGL::DROP_SHADOW_SOFT),
00080 mBorderDropShadowVisible(FALSE),
00081 mUseEllipses( FALSE ),
00082 mHPad(0),
00083 mVPad(0),
00084 mHAlign(LLFontGL::LEFT),
00085 mVAlign( LLFontGL::TOP ),
00086 mClickedCallback(NULL),
00087 mCallbackUserData(NULL)
00088 {
00089 setWrappedText(text, max_width);
00090 reshapeToFitText();
00091 setTabStop(FALSE);
00092 }
00093
00094 LLTextBox::LLTextBox(const LLString& name_and_label, const LLRect& rect) :
00095 LLUICtrl(name_and_label, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
00096 mFontGL(LLFontGL::sSansSerifSmall),
00097 mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")),
00098 mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")),
00099 mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")),
00100 mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")),
00101 mBackgroundVisible(FALSE),
00102 mBorderVisible(FALSE),
00103 mFontStyle(LLFontGL::DROP_SHADOW_SOFT),
00104 mBorderDropShadowVisible(FALSE),
00105 mHPad(0),
00106 mVPad(0),
00107 mHAlign(LLFontGL::LEFT),
00108 mVAlign( LLFontGL::TOP ),
00109 mClickedCallback(NULL),
00110 mCallbackUserData(NULL)
00111 {
00112 setText( name_and_label );
00113 setTabStop(FALSE);
00114 }
00115
00116 LLTextBox::LLTextBox(const LLString& name_and_label) :
00117 LLUICtrl(name_and_label, LLRect(0, 0, 1, 1), TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
00118 mFontGL(LLFontGL::sSansSerifSmall),
00119 mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")),
00120 mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")),
00121 mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")),
00122 mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")),
00123 mBackgroundVisible(FALSE),
00124 mBorderVisible(FALSE),
00125 mFontStyle(LLFontGL::DROP_SHADOW_SOFT),
00126 mBorderDropShadowVisible(FALSE),
00127 mHPad(0),
00128 mVPad(0),
00129 mHAlign(LLFontGL::LEFT),
00130 mVAlign( LLFontGL::TOP ),
00131 mClickedCallback(NULL),
00132 mCallbackUserData(NULL)
00133 {
00134 setWrappedText(name_and_label);
00135 reshapeToFitText();
00136 setTabStop(FALSE);
00137 }
00138
00139 BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
00140 {
00141 BOOL handled = FALSE;
00142
00143
00144
00145 if (mClickedCallback)
00146 {
00147 handled = TRUE;
00148
00149
00150 gFocusMgr.setMouseCapture( this );
00151
00152 if (getSoundFlags() & MOUSE_DOWN)
00153 {
00154 make_ui_sound("UISndClick");
00155 }
00156 }
00157
00158 return handled;
00159 }
00160
00161
00162 BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
00163 {
00164 BOOL handled = FALSE;
00165
00166
00167
00168
00169
00170 if (mClickedCallback
00171 && hasMouseCapture())
00172 {
00173 handled = TRUE;
00174
00175
00176 gFocusMgr.setMouseCapture( NULL );
00177
00178 if (getSoundFlags() & MOUSE_UP)
00179 {
00180 make_ui_sound("UISndClickRelease");
00181 }
00182
00183
00184
00185 if (mClickedCallback)
00186 {
00187 (*mClickedCallback)( mCallbackUserData );
00188 }
00189 }
00190
00191 return handled;
00192 }
00193
00194 BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)
00195 {
00196 if(mHoverActive)
00197 {
00198 mHasHover = TRUE;
00199 return TRUE;
00200 }
00201 return LLView::handleHover(x,y,mask);
00202 }
00203
00204 void LLTextBox::setText(const LLStringExplicit& text)
00205 {
00206 mText.assign(text);
00207 setLineLengths();
00208 }
00209
00210 void LLTextBox::setLineLengths()
00211 {
00212 mLineLengthList.clear();
00213
00214 LLString::size_type cur = 0;
00215 LLString::size_type len = mText.getWString().size();
00216
00217 while (cur < len)
00218 {
00219 LLString::size_type end = mText.getWString().find('\n', cur);
00220 LLString::size_type runLen;
00221
00222 if (end == LLString::npos)
00223 {
00224 runLen = len - cur;
00225 cur = len;
00226 }
00227 else
00228 {
00229 runLen = end - cur;
00230 cur = end + 1;
00231 }
00232
00233 mLineLengthList.push_back( (S32)runLen );
00234 }
00235 }
00236
00237 void LLTextBox::setWrappedText(const LLStringExplicit& in_text, F32 max_width)
00238 {
00239 if (max_width < 0.0)
00240 {
00241 max_width = (F32)getRect().getWidth();
00242 }
00243
00244 LLWString wtext = utf8str_to_wstring(in_text);
00245 LLWString final_wtext;
00246
00247 LLWString::size_type cur = 0;;
00248 LLWString::size_type len = wtext.size();
00249
00250 while (cur < len)
00251 {
00252 LLWString::size_type end = wtext.find('\n', cur);
00253 if (end == LLWString::npos)
00254 {
00255 end = len;
00256 }
00257
00258 LLWString::size_type runLen = end - cur;
00259 if (runLen > 0)
00260 {
00261 LLWString run(wtext, cur, runLen);
00262 LLWString::size_type useLen =
00263 mFontGL->maxDrawableChars(run.c_str(), max_width, runLen, TRUE);
00264
00265 final_wtext.append(wtext, cur, useLen);
00266 cur += useLen;
00267 }
00268
00269 if (cur < len)
00270 {
00271 if (wtext[cur] == '\n')
00272 {
00273 cur += 1;
00274 }
00275 final_wtext += '\n';
00276 }
00277 }
00278
00279 LLString final_text = wstring_to_utf8str(final_wtext);
00280 setText(final_text);
00281 }
00282
00283 S32 LLTextBox::getTextPixelWidth()
00284 {
00285 S32 max_line_width = 0;
00286 if( mLineLengthList.size() > 0 )
00287 {
00288 S32 cur_pos = 0;
00289 for (std::vector<S32>::iterator iter = mLineLengthList.begin();
00290 iter != mLineLengthList.end(); ++iter)
00291 {
00292 S32 line_length = *iter;
00293 S32 line_width = mFontGL->getWidth( mText.getWString().c_str(), cur_pos, line_length );
00294 if( line_width > max_line_width )
00295 {
00296 max_line_width = line_width;
00297 }
00298 cur_pos += line_length+1;
00299 }
00300 }
00301 else
00302 {
00303 max_line_width = mFontGL->getWidth(mText.getWString().c_str());
00304 }
00305 return max_line_width;
00306 }
00307
00308 S32 LLTextBox::getTextPixelHeight()
00309 {
00310 S32 num_lines = mLineLengthList.size();
00311 if( num_lines < 1 )
00312 {
00313 num_lines = 1;
00314 }
00315 return (S32)(num_lines * mFontGL->getLineHeight());
00316 }
00317
00318
00319 BOOL LLTextBox::setTextArg( const LLString& key, const LLStringExplicit& text )
00320 {
00321 mText.setArg(key, text);
00322 setLineLengths();
00323 return TRUE;
00324 }
00325
00326 void LLTextBox::draw()
00327 {
00328 if (mBorderVisible)
00329 {
00330 gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
00331 }
00332
00333 if( mBorderDropShadowVisible )
00334 {
00335 static LLColor4 color_drop_shadow = LLUI::sColorsGroup->getColor("ColorDropShadow");
00336 static S32 drop_shadow_tooltip = LLUI::sConfigGroup->getS32("DropShadowTooltip");
00337 gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
00338 color_drop_shadow, drop_shadow_tooltip);
00339 }
00340
00341 if (mBackgroundVisible)
00342 {
00343 LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 );
00344 gl_rect_2d( r, mBackgroundColor );
00345 }
00346
00347 S32 text_x = 0;
00348 switch( mHAlign )
00349 {
00350 case LLFontGL::LEFT:
00351 text_x = mHPad;
00352 break;
00353 case LLFontGL::HCENTER:
00354 text_x = getRect().getWidth() / 2;
00355 break;
00356 case LLFontGL::RIGHT:
00357 text_x = getRect().getWidth() - mHPad;
00358 break;
00359 }
00360
00361 S32 text_y = getRect().getHeight() - mVPad;
00362
00363 if ( getEnabled() )
00364 {
00365 if(mHasHover)
00366 {
00367 drawText( text_x, text_y, mHoverColor );
00368 }
00369 else
00370 {
00371 drawText( text_x, text_y, mTextColor );
00372 }
00373 }
00374 else
00375 {
00376 drawText( text_x, text_y, mDisabledColor );
00377 }
00378
00379 if (sDebugRects)
00380 {
00381 drawDebugRect();
00382 }
00383
00384 mHasHover = FALSE;
00385 }
00386
00387 void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent)
00388 {
00389
00390 setLineLengths();
00391 LLView::reshape(width, height, called_from_parent);
00392 }
00393
00394 void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
00395 {
00396 if( mLineLengthList.empty() )
00397 {
00398 mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color,
00399 mHAlign, mVAlign,
00400 mFontStyle,
00401 S32_MAX, getRect().getWidth(), NULL, TRUE, mUseEllipses);
00402 }
00403 else
00404 {
00405 S32 cur_pos = 0;
00406 for (std::vector<S32>::iterator iter = mLineLengthList.begin();
00407 iter != mLineLengthList.end(); ++iter)
00408 {
00409 S32 line_length = *iter;
00410 mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color,
00411 mHAlign, mVAlign,
00412 mFontStyle,
00413 line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses );
00414 cur_pos += line_length + 1;
00415 y -= llfloor(mFontGL->getLineHeight());
00416 }
00417 }
00418 }
00419
00420 void LLTextBox::reshapeToFitText()
00421 {
00422 S32 width = getTextPixelWidth();
00423 S32 height = getTextPixelHeight();
00424 reshape( width + 2 * mHPad, height + 2 * mVPad );
00425 }
00426
00427
00428 LLXMLNodePtr LLTextBox::getXML(bool save_children) const
00429 {
00430 LLXMLNodePtr node = LLUICtrl::getXML();
00431
00432
00433 node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mFontGL));
00434 node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
00435 addColorXML(node, mTextColor, "text_color", "LabelTextColor");
00436 addColorXML(node, mDisabledColor, "disabled_color", "LabelDisabledColor");
00437 addColorXML(node, mBackgroundColor, "bg_color", "DefaultBackgroundColor");
00438 addColorXML(node, mBorderColor, "border_color", "DefaultHighlightLight");
00439 node->createChild("bg_visible", TRUE)->setBoolValue(mBackgroundVisible);
00440 node->createChild("border_visible", TRUE)->setBoolValue(mBorderVisible);
00441 node->createChild("border_drop_shadow_visible", TRUE)->setBoolValue(mBorderDropShadowVisible);
00442 node->createChild("h_pad", TRUE)->setIntValue(mHPad);
00443 node->createChild("v_pad", TRUE)->setIntValue(mVPad);
00444
00445
00446 node->setStringValue(mText);
00447
00448 return node;
00449 }
00450
00451
00452 LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00453 {
00454 LLString name("text_box");
00455 node->getAttributeString("name", name);
00456 LLFontGL* font = LLView::selectFont(node);
00457
00458 LLString text = node->getTextContents();
00459
00460 LLTextBox* text_box = new LLTextBox(name,
00461 LLRect(),
00462 text,
00463 font,
00464 FALSE);
00465
00466
00467 LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
00468 text_box->setHAlign(halign);
00469
00470 text_box->initFromXML(node, parent);
00471
00472 LLString font_style;
00473 if (node->getAttributeString("font-style", font_style))
00474 {
00475 text_box->mFontStyle = LLFontGL::getStyleFromString(font_style);
00476 }
00477
00478 BOOL mouse_opaque = text_box->getMouseOpaque();
00479 if (node->getAttributeBOOL("mouse_opaque", mouse_opaque))
00480 {
00481 text_box->setMouseOpaque(mouse_opaque);
00482 }
00483
00484 if(node->hasAttribute("text_color"))
00485 {
00486 LLColor4 color;
00487 LLUICtrlFactory::getAttributeColor(node, "text_color", color);
00488 text_box->setColor(color);
00489 }
00490
00491 if(node->hasAttribute("hover_color"))
00492 {
00493 LLColor4 color;
00494 LLUICtrlFactory::getAttributeColor(node, "hover_color", color);
00495 text_box->setHoverColor(color);
00496 text_box->setHoverActive(true);
00497 }
00498
00499 BOOL hover_active = FALSE;
00500 if(node->getAttributeBOOL("hover", hover_active))
00501 {
00502 text_box->setHoverActive(hover_active);
00503 }
00504
00505 return text_box;
00506 }