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