lltextbox.cpp

Go to the documentation of this file.
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         // HACK: Only do this if there actually is a click callback, so that
00144         // overly large text boxes in the older UI won't start eating clicks.
00145         if (mClickedCallback)
00146         {
00147                 handled = TRUE;
00148 
00149                 // Route future Mouse messages here preemptively.  (Release on mouse up.)
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         // We only handle the click if the click both started and ended within us
00167 
00168         // HACK: Only do this if there actually is a click callback, so that
00169         // overly large text boxes in the older UI won't start eating clicks.
00170         if (mClickedCallback
00171                 && hasMouseCapture())
00172         {
00173                 handled = TRUE;
00174 
00175                 // Release the mouse
00176                 gFocusMgr.setMouseCapture( NULL );
00177 
00178                 if (getSoundFlags() & MOUSE_UP)
00179                 {
00180                         make_ui_sound("UISndClickRelease");
00181                 }
00182 
00183                 // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
00184                 // If mouseup in the widget, it's been clicked
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; // This should be set every frame during a hover.
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; // skip the new line character
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; // This is reset every frame.
00385 }
00386 
00387 void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent)
00388 {
00389         // reparse line lengths
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 // virtual
00428 LLXMLNodePtr LLTextBox::getXML(bool save_children) const
00429 {
00430         LLXMLNodePtr node = LLUICtrl::getXML();
00431 
00432         // Attributes
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         // Contents
00446         node->setStringValue(mText);
00447 
00448         return node;
00449 }
00450 
00451 // static
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 }

Generated on Fri May 16 08:32:58 2008 for SecondLife by  doxygen 1.5.5