summaryrefslogtreecommitdiff
path: root/indra/llui/lltextbox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/lltextbox.cpp')
-rw-r--r--indra/llui/lltextbox.cpp438
1 files changed, 438 insertions, 0 deletions
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
new file mode 100644
index 0000000000..0cd2e98514
--- /dev/null
+++ b/indra/llui/lltextbox.cpp
@@ -0,0 +1,438 @@
+/**
+ * @file lltextbox.cpp
+ * @brief A text display widget
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "lltextbox.h"
+
+#include "llerror.h"
+#include "llgl.h"
+#include "llui.h"
+#include "lluictrlfactory.h"
+#include "llcontrol.h"
+#include "llfocusmgr.h"
+#include "llstl.h"
+#include <boost/tokenizer.hpp>
+
+LLTextBox::LLTextBox(const LLString& name, const LLRect& rect, const LLString& text,
+ const LLFontGL* font, BOOL mouse_opaque)
+: LLUICtrl(name, rect, mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP ),
+ mTextColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
+ mDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
+ mBackgroundColor( LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" ) ),
+ mBorderColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ),
+ mBackgroundVisible( FALSE ),
+ mBorderVisible( FALSE ),
+ mDropshadowVisible( TRUE ),
+ mBorderDropShadowVisible( FALSE ),
+ mHPad(0),
+ mVPad(0),
+ mHAlign( LLFontGL::LEFT ),
+ mVAlign( LLFontGL::TOP ),
+ mClickedCallback(NULL),
+ mCallbackUserData(NULL)
+{
+ // TomY TODO Nuke this eventually
+ setText( !text.empty() ? text : name );
+ mFontGL = font ? font : LLFontGL::sSansSerifSmall;
+ setTabStop(FALSE);
+}
+
+LLTextBox::LLTextBox(const LLString& name, const LLString& text, F32 max_width,
+ const LLFontGL* font, BOOL mouse_opaque) :
+ LLUICtrl(name, LLRect(0, 0, 1, 1), mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
+ mFontGL(font ? font : LLFontGL::sSansSerifSmall),
+ mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")),
+ mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")),
+ mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")),
+ mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")),
+ mBackgroundVisible(FALSE),
+ mBorderVisible(FALSE),
+ mDropshadowVisible(TRUE),
+ mBorderDropShadowVisible(FALSE),
+ mHPad(0),
+ mVPad(0),
+ mHAlign(LLFontGL::LEFT),
+ mVAlign( LLFontGL::TOP ),
+ mClickedCallback(NULL),
+ mCallbackUserData(NULL)
+{
+ setWrappedText(!text.empty() ? text : name, max_width);
+ reshapeToFitText();
+ setTabStop(FALSE);
+}
+
+LLTextBox::~LLTextBox()
+{
+}
+
+// virtual
+EWidgetType LLTextBox::getWidgetType() const
+{
+ return WIDGET_TYPE_TEXT_BOX;
+}
+
+// virtual
+LLString LLTextBox::getWidgetTag() const
+{
+ return LL_TEXT_BOX_TAG;
+}
+
+BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
+
+ // HACK: Only do this if there actually is a click callback, so that
+ // overly large text boxes in the older UI won't start eating clicks.
+ if (mClickedCallback)
+ {
+ handled = TRUE;
+
+ // Route future Mouse messages here preemptively. (Release on mouse up.)
+ gFocusMgr.setMouseCapture( this, NULL );
+
+ if (mSoundFlags & MOUSE_DOWN)
+ {
+ make_ui_sound("UISndClick");
+ }
+ }
+
+ return handled;
+}
+
+
+BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
+
+ // We only handle the click if the click both started and ended within us
+
+ // HACK: Only do this if there actually is a click callback, so that
+ // overly large text boxes in the older UI won't start eating clicks.
+ if (mClickedCallback
+ && this == gFocusMgr.getMouseCapture())
+ {
+ handled = TRUE;
+
+ // Release the mouse
+ gFocusMgr.setMouseCapture( NULL, NULL );
+
+ if (mSoundFlags & MOUSE_UP)
+ {
+ make_ui_sound("UISndClickRelease");
+ }
+
+ // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
+ // If mouseup in the widget, it's been clicked
+ if (mClickedCallback)
+ {
+ (*mClickedCallback)( mCallbackUserData );
+ }
+ }
+
+ return handled;
+}
+
+void LLTextBox::setText(const LLString& text)
+{
+ mText.assign(text);
+ setLineLengths();
+}
+
+void LLTextBox::setLineLengths()
+{
+ mLineLengthList.clear();
+
+ LLString::size_type cur = 0;
+ LLString::size_type len = mText.getWString().size();
+
+ while (cur < len)
+ {
+ LLString::size_type end = mText.getWString().find('\n', cur);
+ LLString::size_type runLen;
+
+ if (end == LLString::npos)
+ {
+ runLen = len - cur;
+ cur = len;
+ }
+ else
+ {
+ runLen = end - cur;
+ cur = end + 1; // skip the new line character
+ }
+
+ mLineLengthList.push_back( (S32)runLen );
+ }
+}
+
+void LLTextBox::setWrappedText(const LLString& in_text, F32 max_width)
+{
+ if (max_width < 0.0)
+ {
+ max_width = (F32)getRect().getWidth();
+ }
+
+ LLWString wtext = utf8str_to_wstring(in_text);
+ LLWString final_wtext;
+
+ LLWString::size_type cur = 0;;
+ LLWString::size_type len = wtext.size();
+
+ while (cur < len)
+ {
+ LLWString::size_type end = wtext.find('\n', cur);
+ if (end == LLWString::npos)
+ {
+ end = len;
+ }
+
+ LLWString::size_type runLen = end - cur;
+ if (runLen > 0)
+ {
+ LLWString run(wtext, cur, runLen);
+ LLWString::size_type useLen =
+ mFontGL->maxDrawableChars(run.c_str(), max_width, runLen, TRUE);
+
+ final_wtext.append(wtext, cur, useLen);
+ cur += useLen;
+ }
+
+ if (cur < len)
+ {
+ if (wtext[cur] == '\n')
+ {
+ cur += 1;
+ }
+ final_wtext += '\n';
+ }
+ }
+
+ LLString final_text = wstring_to_utf8str(final_wtext);
+ setText(final_text);
+}
+
+S32 LLTextBox::getTextPixelWidth()
+{
+ S32 max_line_width = 0;
+ if( mLineLengthList.size() > 0 )
+ {
+ S32 cur_pos = 0;
+ for (std::vector<S32>::iterator iter = mLineLengthList.begin();
+ iter != mLineLengthList.end(); ++iter)
+ {
+ S32 line_length = *iter;
+ S32 line_width = mFontGL->getWidth( mText.getWString().c_str(), cur_pos, line_length );
+ if( line_width > max_line_width )
+ {
+ max_line_width = line_width;
+ }
+ cur_pos += line_length+1;
+ }
+ }
+ else
+ {
+ max_line_width = mFontGL->getWidth(mText.getWString().c_str());
+ }
+ return max_line_width;
+}
+
+S32 LLTextBox::getTextPixelHeight()
+{
+ S32 num_lines = mLineLengthList.size();
+ if( num_lines < 1 )
+ {
+ num_lines = 1;
+ }
+ return (S32)(num_lines * mFontGL->getLineHeight());
+}
+
+
+void LLTextBox::setValue(const LLSD& value )
+{
+ setText(value.asString());
+}
+
+LLSD LLTextBox::getValue() const
+{
+ return LLSD(getText());
+}
+
+BOOL LLTextBox::setTextArg( const LLString& key, const LLString& text )
+{
+ mText.setArg(key, text);
+ setLineLengths();
+ return TRUE;
+}
+
+void LLTextBox::draw()
+{
+ if( getVisible() )
+ {
+ if (mBorderVisible)
+ {
+ gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
+ }
+
+ if( mBorderDropShadowVisible )
+ {
+ static LLColor4 color_drop_shadow = LLUI::sColorsGroup->getColor("ColorDropShadow");
+ static S32 drop_shadow_tooltip = LLUI::sConfigGroup->getS32("DropShadowTooltip");
+ gl_drop_shadow(0, mRect.getHeight(), mRect.getWidth(), 0,
+ color_drop_shadow, drop_shadow_tooltip);
+ }
+
+ if (mBackgroundVisible)
+ {
+ LLRect r( 0, mRect.getHeight(), mRect.getWidth(), 0 );
+ gl_rect_2d( r, mBackgroundColor );
+ }
+
+ S32 text_x = 0;
+ switch( mHAlign )
+ {
+ case LLFontGL::LEFT:
+ text_x = mHPad;
+ break;
+ case LLFontGL::HCENTER:
+ text_x = mRect.getWidth() / 2;
+ break;
+ case LLFontGL::RIGHT:
+ text_x = mRect.getWidth() - mHPad;
+ break;
+ }
+
+ S32 text_y = mRect.getHeight() - mVPad;
+
+ if ( getEnabled() )
+ {
+ drawText( text_x, text_y, mTextColor );
+ }
+ else
+ {
+ drawText( text_x, text_y, mDisabledColor );
+ }
+
+ if (sDebugRects)
+ {
+ drawDebugRect();
+ }
+ }
+}
+
+void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ // reparse line lengths
+ setText(mText);
+ LLView::reshape(width, height, called_from_parent);
+}
+
+void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
+{
+ if( !mLineLengthList.empty() )
+ {
+ S32 cur_pos = 0;
+ for (std::vector<S32>::iterator iter = mLineLengthList.begin();
+ iter != mLineLengthList.end(); ++iter)
+ {
+ S32 line_length = *iter;
+ mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color,
+ mHAlign, mVAlign,
+ mDropshadowVisible ? LLFontGL::DROP_SHADOW : LLFontGL::NORMAL,
+ line_length, mRect.getWidth(), NULL, TRUE );
+ cur_pos += line_length + 1;
+ y -= llfloor(mFontGL->getLineHeight());
+ }
+ }
+ else
+ {
+ mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color,
+ mHAlign, mVAlign,
+ mDropshadowVisible ? LLFontGL::DROP_SHADOW : LLFontGL::NORMAL,
+ S32_MAX, mRect.getWidth(), NULL, TRUE);
+ }
+}
+
+
+void LLTextBox::reshapeToFitText()
+{
+ S32 width = getTextPixelWidth();
+ S32 height = getTextPixelHeight();
+ reshape( width + 2 * mHPad, height + 2 * mVPad );
+}
+
+// virtual
+LLXMLNodePtr LLTextBox::getXML(bool save_children) const
+{
+ LLXMLNodePtr node = LLUICtrl::getXML();
+
+ // Attributes
+
+ node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mFontGL));
+
+ node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
+
+ addColorXML(node, mTextColor, "text_color", "LabelTextColor");
+ addColorXML(node, mDisabledColor, "disabled_color", "LabelDisabledColor");
+ addColorXML(node, mBackgroundColor, "bg_color", "DefaultBackgroundColor");
+ addColorXML(node, mBorderColor, "border_color", "DefaultHighlightLight");
+
+ node->createChild("bg_visible", TRUE)->setBoolValue(mBackgroundVisible);
+
+ node->createChild("border_visible", TRUE)->setBoolValue(mBorderVisible);
+
+ node->createChild("drop_shadow_visible", TRUE)->setBoolValue(mDropshadowVisible);
+
+ node->createChild("border_drop_shadow_visible", TRUE)->setBoolValue(mBorderDropShadowVisible);
+
+ node->createChild("h_pad", TRUE)->setIntValue(mHPad);
+
+ node->createChild("v_pad", TRUE)->setIntValue(mVPad);
+
+ // Contents
+
+ node->setStringValue(mText);
+
+ return node;
+}
+
+// static
+LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+{
+ LLString name("text_box");
+ node->getAttributeString("name", name);
+ LLFontGL* font = LLView::selectFont(node);
+
+ LLString text = node->getTextContents();
+
+ // TomY Yes I know this is a hack, but insert a space to make a blank text field
+ if (text == "")
+ {
+ text = " ";
+ }
+
+ LLTextBox* text_box = new LLTextBox(name,
+ LLRect(),
+ text,
+ font,
+ FALSE);
+
+ LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
+ text_box->setHAlign(halign);
+
+ text_box->initFromXML(node, parent);
+
+ if(node->hasAttribute("text_color"))
+ {
+ LLColor4 color;
+ LLUICtrlFactory::getAttributeColor(node, "text_color", color);
+ text_box->setColor(color);
+ }
+
+ return text_box;
+}