lltextbox.cpp

Go to the documentation of this file.
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         // TomY TODO Nuke this eventually
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 // virtual
00098 EWidgetType LLTextBox::getWidgetType() const
00099 {
00100         return WIDGET_TYPE_TEXT_BOX;
00101 }
00102 
00103 // virtual
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         // HACK: Only do this if there actually is a click callback, so that
00114         // overly large text boxes in the older UI won't start eating clicks.
00115         if (mClickedCallback)
00116         {
00117                 handled = TRUE;
00118 
00119                 // Route future Mouse messages here preemptively.  (Release on mouse up.)
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         // We only handle the click if the click both started and ended within us
00137 
00138         // HACK: Only do this if there actually is a click callback, so that
00139         // overly large text boxes in the older UI won't start eating clicks.
00140         if (mClickedCallback
00141                 && hasMouseCapture())
00142         {
00143                 handled = TRUE;
00144 
00145                 // Release the mouse
00146                 gFocusMgr.setMouseCapture( NULL );
00147 
00148                 if (mSoundFlags & MOUSE_UP)
00149                 {
00150                         make_ui_sound("UISndClickRelease");
00151                 }
00152 
00153                 // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
00154                 // If mouseup in the widget, it's been clicked
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; // skip the new line character
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         // reparse line lengths
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 // virtual
00393 LLXMLNodePtr LLTextBox::getXML(bool save_children) const
00394 {
00395         LLXMLNodePtr node = LLUICtrl::getXML();
00396 
00397         // Attributes
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         // Contents
00419 
00420         node->setStringValue(mText);
00421 
00422         return node;
00423 }
00424 
00425 // static
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         // TomY Yes I know this is a hack, but insert a space to make a blank text field
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 }

Generated on Thu Jul 1 06:09:17 2010 for Second Life Viewer by  doxygen 1.4.7