summaryrefslogtreecommitdiff
path: root/indra/newview/llchatmsgbox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llchatmsgbox.cpp')
-rw-r--r--indra/newview/llchatmsgbox.cpp371
1 files changed, 54 insertions, 317 deletions
diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp
index 9399e1f68d..e6398dd47a 100644
--- a/indra/newview/llchatmsgbox.cpp
+++ b/indra/newview/llchatmsgbox.cpp
@@ -1,10 +1,11 @@
/**
* @file llchatmsgbox.cpp
+ * @author Martin Reddy
* @brief chat history text box, able to show array of strings with separator
*
- * $LicenseInfo:firstyear=2004&license=viewergpl$
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-2009, Linden Research, Inc.
+ * Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -30,360 +31,96 @@
* $/LicenseInfo$
*/
-
#include "llviewerprecompiledheaders.h"
#include "llchatmsgbox.h"
#include "llwindow.h"
-#include "llfocusmgr.h"
-
-static LLDefaultChildRegistry::Register<LLChatMsgBox> r("text_chat");
-LLChatMsgBox::Params::Params()
-: text_color("text_color"),
- highlight_on_hover("hover", false),
- border_visible("border_visible", false),
- border_drop_shadow_visible("border_drop_shadow_visible", false),
- bg_visible("bg_visible", false),
- use_ellipses("use_ellipses"),
- word_wrap("word_wrap", false),
- hover_color("hover_color"),
- disabled_color("disabled_color"),
- background_color("background_color"),
- border_color("border_color"),
- line_spacing("line_spacing", 4),
- block_spacing("block_spacing",10),
- text("text"),
- font_shadow("font_shadow", LLFontGL::NO_SHADOW)
-{}
-LLChatMsgBox::LLChatMsgBox(const LLChatMsgBox::Params& p)
-: LLUICtrl(p),
- mFontGL(p.font),
- mHoverActive( p.highlight_on_hover ),
- mHasHover( FALSE ),
- mBackgroundVisible( p.bg_visible ),
- mBorderVisible( p.border_visible ),
- mShadowType( p.font_shadow ),
- mBorderDropShadowVisible( p.border_drop_shadow_visible ),
- mUseEllipses( p.use_ellipses ),
- mVAlign( LLFontGL::TOP ),
- mClickedCallback(NULL),
- mTextColor(p.text_color()),
- mDisabledColor(p.disabled_color()),
- mBackgroundColor(p.background_color()),
- mBorderColor(p.border_color()),
- mHoverColor(p.hover_color()),
- mHAlign(p.font_halign),
- mLineSpacing(p.line_spacing),
- mBlockSpasing(p.block_spacing),
- mWordWrap( p.word_wrap ),
- mFontStyle(LLFontGL::getStyleFromString(p.font.style))
-{
- setText( p.text() );
-}
+static LLDefaultChildRegistry::Register<LLChatMsgBox> r("text_chat");
-BOOL LLChatMsgBox::handleMouseDown(S32 x, S32 y, MASK mask)
+LLChatMsgBox::Params::Params() :
+ block_spacing("block_spacing", 10)
{
- 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 );
-
- if (getSoundFlags() & MOUSE_DOWN)
- {
- make_ui_sound("UISndClick");
- }
- }
-
- return handled;
+ line_spacing = 4;
}
-BOOL LLChatMsgBox::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
- && hasMouseCapture())
- {
- handled = TRUE;
-
- // Release the mouse
- gFocusMgr.setMouseCapture( NULL );
-
- if (getSoundFlags() & 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();
- }
- }
-
- return handled;
-}
+LLChatMsgBox::LLChatMsgBox(const Params& p) :
+ LLTextBox(p),
+ mBlockSpacing(p.block_spacing)
+{}
-BOOL LLChatMsgBox::handleHover(S32 x, S32 y, MASK mask)
+void LLChatMsgBox::addText( const LLStringExplicit& text )
{
- BOOL handled = LLView::handleHover(x,y,mask);
- if(mHoverActive)
+ LLWString t = mText.getWString();
+ if (! t.empty())
{
- mHasHover = TRUE; // This should be set every frame during a hover.
- getWindow()->setCursor(UI_CURSOR_ARROW);
+ t += '\n';
}
-
- return (handled || mHasHover);
-}
-
-void LLChatMsgBox::addText( const LLStringExplicit& text )
-{
- boost::shared_ptr<text_block> t(new text_block());
- t->text = wrapText(text);
- setLineLengths(*t);
- mTextStrings.push_back(t);
+ t += getWrappedText(text);
+ LLTextBox::setText(wstring_to_utf8str(t));
+ mSeparatorOffset.push_back(getLength());
}
void LLChatMsgBox::setText(const LLStringExplicit& text)
{
- mTextStrings.clear();
-
+ mSeparatorOffset.clear();
+ mText.clear();
addText(text);
-
-}
-
-void LLChatMsgBox::resetLineLengths()
-{
- for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
- it!=mTextStrings.end();++it)
- {
- boost::shared_ptr<text_block> tblock = *it;
- setLineLengths(*tblock);
- }
-}
-
-void LLChatMsgBox::setLineLengths(text_block& t)
-{
- t.lines.clear();
-
- std::string::size_type cur = 0;
- std::string::size_type len = t.text.length();
-
- while (cur < len)
- {
- std::string::size_type end = t.text.getWString().find('\n', cur);
- std::string::size_type runLen;
-
- if (end == std::string::npos)
- {
- runLen = len - cur;
- cur = len;
- }
- else
- {
- runLen = end - cur;
- cur = end + 1; // skip the new line character
- }
-
- t.lines.push_back( (S32)runLen );
- }
}
-std::string LLChatMsgBox::wrapText(const LLStringExplicit& in_text, F32 max_width)
-{
- if (max_width < 0.0f)
- {
- 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;
- // not enough room to add any more characters
- if (useLen == 0) break;
- }
-
- if (cur < len)
- {
- if (wtext[cur] == '\n')
- cur += 1;
- else
- final_wtext += '\n';
- }
- }
-
- std::string final_text = wstring_to_utf8str(final_wtext);
- return final_text;
-}
-
-S32 LLChatMsgBox::getTextLinesNum()
-{
- S32 num_lines = 0;
- for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
- it!=mTextStrings.end();++it)
- {
- boost::shared_ptr<text_block> tblock = *it;
- num_lines+=tblock->lines.size();
- }
-
- if( num_lines < 1 )
- {
- num_lines = 1;
- }
-
- return num_lines;
+void LLChatMsgBox::setValue(const LLSD& value )
+{
+ setText(value.asString());
}
S32 LLChatMsgBox::getTextPixelHeight()
{
+ S32 num_blocks = mSeparatorOffset.size();
S32 num_lines = getTextLinesNum();
- return (S32)(num_lines * mFontGL->getLineHeight() + (num_lines-1)*mLineSpacing + mBlockSpasing*(mTextStrings.size()-1) + 2*mLineSpacing);//some extra space
-}
-
-void LLChatMsgBox::setValue(const LLSD& value )
-{
- setText(value.asString());
+ return (S32)(num_lines * mDefaultFont->getLineHeight() + \
+ (num_lines-1) * mLineSpacing + \
+ (num_blocks-1) * mBlockSpacing + \
+ 2 * mLineSpacing);
}
-
-void LLChatMsgBox::draw()
+S32 LLChatMsgBox::getTextLinesNum()
{
- if (mBorderVisible)
- {
- gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
- }
-
- if( mBorderDropShadowVisible )
+ S32 num_lines = getLineCount();
+ if (num_lines < 1)
{
- static LLUICachedControl<LLColor4> color_drop_shadow ("ColorDropShadow", *(new LLColor4));
- static LLUICachedControl<S32> drop_shadow_tooltip ("DropShadowTooltip", 0);
- gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
- color_drop_shadow, drop_shadow_tooltip);
- }
-
- if (mBackgroundVisible)
- {
- LLRect r( 0, getRect().getHeight(), getRect().getWidth(), 0 );
- gl_rect_2d( r, mBackgroundColor.get() );
- }
-
- S32 text_x = 0;
- switch( mHAlign )
- {
- case LLFontGL::LEFT:
- break;
- case LLFontGL::HCENTER:
- text_x = getRect().getWidth() / 2;
- break;
- case LLFontGL::RIGHT:
- text_x = getRect().getWidth() ;
- break;
- }
-
- S32 text_y = getRect().getHeight() ;
-
- if ( getEnabled() )
- {
- if(mHasHover)
- {
- drawText( text_x, text_y, mHoverColor.get() );
- }
- else
- {
- drawText( text_x, text_y, mTextColor.get() );
- }
- }
- else
- {
- drawText( text_x, text_y, mDisabledColor.get() );
- }
-
- if (sDebugRects)
- {
- drawDebugRect();
+ num_lines = 1;
}
-
- //// *HACK: also draw debug rectangles around currently-being-edited LLView, and any elements that are being highlighted by GUI preview code (see LLFloaterUIPreview)
- //std::set<LLView*>::iterator iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this);
- //if ((sEditingUI && this == sEditingUIView) || (iter != sPreviewHighlightedElements.end() && sDrawPreviewHighlights))
- //{
- // drawDebugRect();
- //}
-
- mHasHover = FALSE; // This is reset every frame.
-}
-
-void LLChatMsgBox::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
- // reparse line lengths
- LLView::reshape(width, height, called_from_parent);
- resetLineLengths();
+
+ return num_lines;
}
-void LLChatMsgBox::drawText( S32 x, S32 y, const LLColor4& color )
+void LLChatMsgBox::drawText(S32 x, S32 y, const LLWString &text, const LLColor4 &color)
{
+ S32 start = 0;
S32 width = getRect().getWidth()-10;
-
- for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin();
- it!=mTextStrings.end();++it)
+ // iterate through each block of text that has been added
+ y -= mLineSpacing;
+ for (std::vector<S32>::iterator it = mSeparatorOffset.begin(); true ;)
{
- boost::shared_ptr<text_block> tblock = *it;
+ // display the text for this block
+ S32 num_chars = *it - start;
+ LLWString text = mDisplayText.substr(start, num_chars);
+ LLTextBox::drawText(x, y, text, color);
- S32 cur_pos = 0;
- for (std::vector<S32>::iterator iter = tblock->lines.begin();
- iter != tblock->lines.end(); ++iter)
+ // exit the loop if this is the last text block
+ start += num_chars + 1; // skip the newline
+ if (++it == mSeparatorOffset.end())
{
- S32 line_length = *iter;
- mFontGL->render(tblock->text, cur_pos, (F32)x, (F32)y, color,
- mHAlign, mVAlign,
- mFontStyle,
- mShadowType,
- line_length, getRect().getWidth(), NULL, mUseEllipses );
- cur_pos += line_length + 1;
- y -= llfloor(mFontGL->getLineHeight()) + mLineSpacing;
-
- }
- std::vector< boost::shared_ptr<text_block> >::iterator next = it;
- ++next;
- if(next == mTextStrings.end())
break;
- //separator
- gl_line_2d(5,y-mBlockSpasing/2,width,y-mBlockSpasing/2,LLColor4::grey);
- y-=mBlockSpasing;
- }
+ }
+ // output a separator line between blocks
+ S32 num_lines = std::count(text.begin(), text.end(), '\n') + 1;
+ y -= num_lines * (llfloor(mDefaultFont->getLineHeight()) + mLineSpacing);
+ S32 sep_y = y - mBlockSpacing/2 + mLineSpacing/2;
+ gl_line_2d(5, sep_y, width, sep_y, LLColor4::grey);
+ y -= mBlockSpacing;
+ }
}
-