aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/lltextbox.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llui/lltextbox.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llui/lltextbox.cpp')
-rw-r--r--linden/indra/llui/lltextbox.cpp457
1 files changed, 457 insertions, 0 deletions
diff --git a/linden/indra/llui/lltextbox.cpp b/linden/indra/llui/lltextbox.cpp
new file mode 100644
index 0000000..d70f223
--- /dev/null
+++ b/linden/indra/llui/lltextbox.cpp
@@ -0,0 +1,457 @@
1/**
2 * @file lltextbox.cpp
3 * @brief A text display widget
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "linden_common.h"
29
30#include "lltextbox.h"
31
32#include "llerror.h"
33#include "llgl.h"
34#include "llui.h"
35#include "lluictrlfactory.h"
36#include "llcontrol.h"
37#include "llfocusmgr.h"
38#include "llstl.h"
39#include <boost/tokenizer.hpp>
40
41LLTextBox::LLTextBox(const LLString& name, const LLRect& rect, const LLString& text,
42 const LLFontGL* font, BOOL mouse_opaque)
43: LLUICtrl(name, rect, mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP ),
44 mTextColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
45 mDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
46 mBackgroundColor( LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" ) ),
47 mBorderColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ),
48 mBackgroundVisible( FALSE ),
49 mBorderVisible( FALSE ),
50 mDropshadowVisible( TRUE ),
51 mBorderDropShadowVisible( FALSE ),
52 mHPad(0),
53 mVPad(0),
54 mHAlign( LLFontGL::LEFT ),
55 mVAlign( LLFontGL::TOP ),
56 mClickedCallback(NULL),
57 mCallbackUserData(NULL)
58{
59 // TomY TODO Nuke this eventually
60 setText( !text.empty() ? text : name );
61 mFontGL = font ? font : LLFontGL::sSansSerifSmall;
62 setTabStop(FALSE);
63}
64
65LLTextBox::LLTextBox(const LLString& name, const LLString& text, F32 max_width,
66 const LLFontGL* font, BOOL mouse_opaque) :
67 LLUICtrl(name, LLRect(0, 0, 1, 1), mouse_opaque, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
68 mFontGL(font ? font : LLFontGL::sSansSerifSmall),
69 mTextColor(LLUI::sColorsGroup->getColor("LabelTextColor")),
70 mDisabledColor(LLUI::sColorsGroup->getColor("LabelDisabledColor")),
71 mBackgroundColor(LLUI::sColorsGroup->getColor("DefaultBackgroundColor")),
72 mBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight")),
73 mBackgroundVisible(FALSE),
74 mBorderVisible(FALSE),
75 mDropshadowVisible(TRUE),
76 mBorderDropShadowVisible(FALSE),
77 mHPad(0),
78 mVPad(0),
79 mHAlign(LLFontGL::LEFT),
80 mVAlign( LLFontGL::TOP ),
81 mClickedCallback(NULL),
82 mCallbackUserData(NULL)
83{
84 setWrappedText(!text.empty() ? text : name, max_width);
85 reshapeToFitText();
86 setTabStop(FALSE);
87}
88
89LLTextBox::~LLTextBox()
90{
91}
92
93// virtual
94EWidgetType LLTextBox::getWidgetType() const
95{
96 return WIDGET_TYPE_TEXT_BOX;
97}
98
99// virtual
100LLString LLTextBox::getWidgetTag() const
101{
102 return LL_TEXT_BOX_TAG;
103}
104
105BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
106{
107 BOOL handled = FALSE;
108
109 // HACK: Only do this if there actually is a click callback, so that
110 // overly large text boxes in the older UI won't start eating clicks.
111 if (mClickedCallback)
112 {
113 handled = TRUE;
114
115 // Route future Mouse messages here preemptively. (Release on mouse up.)
116 gFocusMgr.setMouseCapture( this, NULL );
117
118 if (mSoundFlags & MOUSE_DOWN)
119 {
120 make_ui_sound("UISndClick");
121 }
122 }
123
124 return handled;
125}
126
127
128BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
129{
130 BOOL handled = FALSE;
131
132 // We only handle the click if the click both started and ended within us
133
134 // HACK: Only do this if there actually is a click callback, so that
135 // overly large text boxes in the older UI won't start eating clicks.
136 if (mClickedCallback
137 && this == gFocusMgr.getMouseCapture())
138 {
139 handled = TRUE;
140
141 // Release the mouse
142 gFocusMgr.setMouseCapture( NULL, NULL );
143
144 if (mSoundFlags & MOUSE_UP)
145 {
146 make_ui_sound("UISndClickRelease");
147 }
148
149 // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
150 // If mouseup in the widget, it's been clicked
151 if (mClickedCallback)
152 {
153 (*mClickedCallback)( mCallbackUserData );
154 }
155 }
156
157 return handled;
158}
159
160void LLTextBox::setText(const LLString& text)
161{
162 mText.assign(text);
163 setLineLengths();
164}
165
166void LLTextBox::setLineLengths()
167{
168 mLineLengthList.clear();
169
170 LLString::size_type cur = 0;
171 LLString::size_type len = mText.getWString().size();
172
173 while (cur < len)
174 {
175 LLString::size_type end = mText.getWString().find('\n', cur);
176 LLString::size_type runLen;
177
178 if (end == LLString::npos)
179 {
180 runLen = len - cur;
181 cur = len;
182 }
183 else
184 {
185 runLen = end - cur;
186 cur = end + 1; // skip the new line character
187 }
188
189 mLineLengthList.push_back( (S32)runLen );
190 }
191}
192
193void LLTextBox::setWrappedText(const LLString& in_text, F32 max_width)
194{
195 if (max_width < 0.0)
196 {
197 max_width = (F32)getRect().getWidth();
198 }
199
200 LLWString wtext = utf8str_to_wstring(in_text);
201 LLWString final_wtext;
202
203 LLWString::size_type cur = 0;;
204 LLWString::size_type len = wtext.size();
205
206 while (cur < len)
207 {
208 LLWString::size_type end = wtext.find('\n', cur);
209 if (end == LLWString::npos)
210 {
211 end = len;
212 }
213
214 LLWString::size_type runLen = end - cur;
215 if (runLen > 0)
216 {
217 LLWString run(wtext, cur, runLen);
218 LLWString::size_type useLen =
219 mFontGL->maxDrawableChars(run.c_str(), max_width, runLen, TRUE);
220
221 final_wtext.append(wtext, cur, useLen);
222 cur += useLen;
223 }
224
225 if (cur < len)
226 {
227 if (wtext[cur] == '\n')
228 {
229 cur += 1;
230 }
231 final_wtext += '\n';
232 }
233 }
234
235 LLString final_text = wstring_to_utf8str(final_wtext);
236 setText(final_text);
237}
238
239S32 LLTextBox::getTextPixelWidth()
240{
241 S32 max_line_width = 0;
242 if( mLineLengthList.size() > 0 )
243 {
244 S32 cur_pos = 0;
245 for (std::vector<S32>::iterator iter = mLineLengthList.begin();
246 iter != mLineLengthList.end(); ++iter)
247 {
248 S32 line_length = *iter;
249 S32 line_width = mFontGL->getWidth( mText.getWString().c_str(), cur_pos, line_length );
250 if( line_width > max_line_width )
251 {
252 max_line_width = line_width;
253 }
254 cur_pos += line_length+1;
255 }
256 }
257 else
258 {
259 max_line_width = mFontGL->getWidth(mText.getWString().c_str());
260 }
261 return max_line_width;
262}
263
264S32 LLTextBox::getTextPixelHeight()
265{
266 S32 num_lines = mLineLengthList.size();
267 if( num_lines < 1 )
268 {
269 num_lines = 1;
270 }
271 return (S32)(num_lines * mFontGL->getLineHeight());
272}
273
274
275void LLTextBox::setValue(const LLSD& value )
276{
277 setText(value.asString());
278}
279
280LLSD LLTextBox::getValue() const
281{
282 return LLSD(getText());
283}
284
285BOOL LLTextBox::setTextArg( const LLString& key, const LLString& text )
286{
287 mText.setArg(key, text);
288 setLineLengths();
289 return TRUE;
290}
291
292void LLTextBox::draw()
293{
294 if( getVisible() )
295 {
296 if (mBorderVisible)
297 {
298 gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
299 }
300
301 if( mBorderDropShadowVisible )
302 {
303 static LLColor4 color_drop_shadow = LLUI::sColorsGroup->getColor("ColorDropShadow");
304 static S32 drop_shadow_tooltip = LLUI::sConfigGroup->getS32("DropShadowTooltip");
305 gl_drop_shadow(0, mRect.getHeight(), mRect.getWidth(), 0,
306 color_drop_shadow, drop_shadow_tooltip);
307 }
308
309 if (mBackgroundVisible)
310 {
311 LLRect r( 0, mRect.getHeight(), mRect.getWidth(), 0 );
312 gl_rect_2d( r, mBackgroundColor );
313 }
314
315 S32 text_x = 0;
316 switch( mHAlign )
317 {
318 case LLFontGL::LEFT:
319 text_x = mHPad;
320 break;
321 case LLFontGL::HCENTER:
322 text_x = mRect.getWidth() / 2;
323 break;
324 case LLFontGL::RIGHT:
325 text_x = mRect.getWidth() - mHPad;
326 break;
327 }
328
329 S32 text_y = mRect.getHeight() - mVPad;
330
331 if ( getEnabled() )
332 {
333 drawText( text_x, text_y, mTextColor );
334 }
335 else
336 {
337 drawText( text_x, text_y, mDisabledColor );
338 }
339
340 if (sDebugRects)
341 {
342 drawDebugRect();
343 }
344 }
345}
346
347void LLTextBox::reshape(S32 width, S32 height, BOOL called_from_parent)
348{
349 // reparse line lengths
350 setText(mText);
351 LLView::reshape(width, height, called_from_parent);
352}
353
354void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )
355{
356 if( !mLineLengthList.empty() )
357 {
358 S32 cur_pos = 0;
359 for (std::vector<S32>::iterator iter = mLineLengthList.begin();
360 iter != mLineLengthList.end(); ++iter)
361 {
362 S32 line_length = *iter;
363 mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color,
364 mHAlign, mVAlign,
365 mDropshadowVisible ? LLFontGL::DROP_SHADOW : LLFontGL::NORMAL,
366 line_length, mRect.getWidth(), NULL, TRUE );
367 cur_pos += line_length + 1;
368 y -= llfloor(mFontGL->getLineHeight());
369 }
370 }
371 else
372 {
373 mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color,
374 mHAlign, mVAlign,
375 mDropshadowVisible ? LLFontGL::DROP_SHADOW : LLFontGL::NORMAL,
376 S32_MAX, mRect.getWidth(), NULL, TRUE);
377 }
378}
379
380
381void LLTextBox::reshapeToFitText()
382{
383 S32 width = getTextPixelWidth();
384 S32 height = getTextPixelHeight();
385 reshape( width + 2 * mHPad, height + 2 * mVPad );
386}
387
388// virtual
389LLXMLNodePtr LLTextBox::getXML(bool save_children) const
390{
391 LLXMLNodePtr node = LLUICtrl::getXML();
392
393 // Attributes
394
395 node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mFontGL));
396
397 node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
398
399 addColorXML(node, mTextColor, "text_color", "LabelTextColor");
400 addColorXML(node, mDisabledColor, "disabled_color", "LabelDisabledColor");
401 addColorXML(node, mBackgroundColor, "bg_color", "DefaultBackgroundColor");
402 addColorXML(node, mBorderColor, "border_color", "DefaultHighlightLight");
403
404 node->createChild("bg_visible", TRUE)->setBoolValue(mBackgroundVisible);
405
406 node->createChild("border_visible", TRUE)->setBoolValue(mBorderVisible);
407
408 node->createChild("drop_shadow_visible", TRUE)->setBoolValue(mDropshadowVisible);
409
410 node->createChild("border_drop_shadow_visible", TRUE)->setBoolValue(mBorderDropShadowVisible);
411
412 node->createChild("h_pad", TRUE)->setIntValue(mHPad);
413
414 node->createChild("v_pad", TRUE)->setIntValue(mVPad);
415
416 // Contents
417
418 node->setStringValue(mText);
419
420 return node;
421}
422
423// static
424LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
425{
426 LLString name("text_box");
427 node->getAttributeString("name", name);
428 LLFontGL* font = LLView::selectFont(node);
429
430 LLString text = node->getTextContents();
431
432 // TomY Yes I know this is a hack, but insert a space to make a blank text field
433 if (text == "")
434 {
435 text = " ";
436 }
437
438 LLTextBox* text_box = new LLTextBox(name,
439 LLRect(),
440 text,
441 font,
442 FALSE);
443
444 LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
445 text_box->setHAlign(halign);
446
447 text_box->initFromXML(node, parent);
448
449 if(node->hasAttribute("text_color"))
450 {
451 LLColor4 color;
452 LLUICtrlFactory::getAttributeColor(node, "text_color", color);
453 text_box->setColor(color);
454 }
455
456 return text_box;
457}