PageRenderTime 68ms CodeModel.GetById 15ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llui/llbadge.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 381 lines | 264 code | 62 blank | 55 comment | 52 complexity | d811e1e3ce81126ceb23462a2537dbab MD5 | raw file
  1/** 
  2 * @file llbadge.cpp
  3 * @brief Implementation for badges
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#define LLBADGE_CPP
 28#include "llbadge.h"
 29
 30#include "llscrollcontainer.h"
 31#include "lluictrlfactory.h"
 32
 33
 34static LLDefaultChildRegistry::Register<LLBadge> r("badge");
 35
 36static const S32 BADGE_OFFSET_NOT_SPECIFIED = 0x7FFFFFFF;
 37
 38// Compiler optimization, generate extern template
 39template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
 40
 41
 42LLBadge::Params::Params()
 43	: image("image")
 44	, border_image("border_image")
 45	, border_color("border_color")
 46	, image_color("image_color")
 47	, label("label")
 48	, label_color("label_color")
 49	, label_offset_horiz("label_offset_horiz")
 50	, label_offset_vert("label_offset_vert")
 51	, location("location", LLRelPos::TOP_LEFT)
 52	, location_offset_hcenter("location_offset_hcenter")
 53	, location_offset_vcenter("location_offset_vcenter")
 54	, location_percent_hcenter("location_percent_hcenter")
 55	, location_percent_vcenter("location_percent_vcenter")
 56	, padding_horiz("padding_horiz")
 57	, padding_vert("padding_vert")
 58{}
 59
 60bool LLBadge::Params::equals(const Params& a) const
 61{
 62	bool comp = true;
 63	
 64	// skip owner in comparison on purpose
 65	
 66	comp &= (border_image() == a.border_image());
 67	comp &= (border_color() == a.border_color());
 68	comp &= (image() == a.image());
 69	comp &= (image_color() == a.image_color());
 70	comp &= (label() == a.label());
 71	comp &= (label_color() == a.label_color());
 72	comp &= (label_offset_horiz() == a.label_offset_horiz());
 73	comp &= (label_offset_vert() == a.label_offset_vert());
 74	comp &= (location() == a.location());
 75	comp &= (location_offset_hcenter() == a.location_offset_hcenter());
 76	comp &= (location_offset_vcenter() == a.location_offset_vcenter());
 77	comp &= (location_percent_hcenter() == a.location_percent_hcenter());
 78	comp &= (location_percent_vcenter() == a.location_percent_vcenter());
 79	comp &= (padding_horiz() == a.padding_horiz());
 80	comp &= (padding_vert() == a.padding_vert());
 81	
 82	return comp;
 83}
 84
 85LLBadge::LLBadge(const LLBadge::Params& p)
 86	: LLUICtrl(p)
 87	, mOwner(p.owner)
 88	, mBorderImage(p.border_image)
 89	, mBorderColor(p.border_color)
 90	, mGLFont(p.font)
 91	, mImage(p.image)
 92	, mImageColor(p.image_color)
 93	, mLabel(p.label)
 94	, mLabelColor(p.label_color)
 95	, mLabelOffsetHoriz(p.label_offset_horiz)
 96	, mLabelOffsetVert(p.label_offset_vert)
 97	, mLocation(p.location)
 98	, mLocationOffsetHCenter(BADGE_OFFSET_NOT_SPECIFIED)
 99	, mLocationOffsetVCenter(BADGE_OFFSET_NOT_SPECIFIED)
100	, mLocationPercentHCenter(0.5f)
101	, mLocationPercentVCenter(0.5f)
102	, mPaddingHoriz(p.padding_horiz)
103	, mPaddingVert(p.padding_vert)
104	, mParentScroller(NULL)
105{
106	if (mImage.isNull())
107	{
108		llwarns << "Badge: " << getName() << " with no image!" << llendl;
109	}
110
111	if (p.location_offset_hcenter.isProvided())
112	{
113		mLocationOffsetHCenter = p.location_offset_hcenter();
114	}
115
116	if (p.location_offset_vcenter.isProvided())
117	{
118		mLocationOffsetVCenter = p.location_offset_vcenter();
119	}
120
121	//
122	// The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter
123	// based on the Location enum and our horizontal and vertical location percentages.  The
124	// draw code then uses this on the owner rectangle to compute the screen location for
125	// the badge.
126	//
127
128	if (!LLRelPos::IsCenter(mLocation))
129	{
130		F32 h_center = p.location_percent_hcenter * 0.01f;
131		F32 v_center = p.location_percent_vcenter * 0.01f;
132
133		if (LLRelPos::IsRight(mLocation))
134		{
135			mLocationPercentHCenter = 0.5f * (1.0f + h_center);
136		}
137		else if (LLRelPos::IsLeft(mLocation))
138		{
139			mLocationPercentHCenter = 0.5f * (1.0f - h_center);
140		}
141			
142		if (LLRelPos::IsTop(mLocation))
143		{
144			mLocationPercentVCenter = 0.5f * (1.0f + v_center);
145		}
146		else if (LLRelPos::IsBottom(mLocation))
147		{
148			mLocationPercentVCenter = 0.5f * (1.0f - v_center);
149		}
150	}
151}
152
153LLBadge::~LLBadge()
154{
155}
156
157bool LLBadge::addToView(LLView * view)
158{
159	bool child_added = view->addChild(this);
160
161	if (child_added)
162	{
163		setShape(view->getLocalRect());
164
165		// Find a parent scroll container, if there is one in case we need it for positioning
166
167		LLView * parent = mOwner.get();
168
169		while ((parent != NULL) && ((mParentScroller = dynamic_cast<LLScrollContainer *>(parent)) == NULL))
170		{
171			parent = parent->getParent();
172		}
173	}
174
175	return child_added;
176}
177
178void LLBadge::setLabel(const LLStringExplicit& label)
179{
180	mLabel = label;
181}
182
183//
184// This is a fallback function to render a rectangle for badges without a valid image
185//
186void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, const LLColor4U &color)
187{
188	gGL.pushUIMatrix();
189	gGL.loadUIIdentity();
190	gGL.setSceneBlendType(LLRender::BT_REPLACE);
191	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
192	
193	gGL.color4ubv(color.mV);
194	gGL.texCoord2i(0, 0);
195	
196	F32 x = LLFontGL::sCurOrigin.mX + centerX - width * 0.5f;
197	F32 y = LLFontGL::sCurOrigin.mY + centerY - height * 0.5f;
198	
199	LLRectf screen_rect(llround(x),
200						llround(y),
201						llround(x) + width,
202						llround(y) + height);
203	
204	LLVector3 vertices[4];
205	vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop,    1.0f);
206	vertices[1] = LLVector3(screen_rect.mLeft,  screen_rect.mTop,    1.0f);
207	vertices[2] = LLVector3(screen_rect.mLeft,  screen_rect.mBottom, 1.0f);
208	vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
209	
210	gGL.begin(LLRender::QUADS);
211	{
212		gGL.vertexBatchPreTransformed(vertices, 4);
213	}
214	gGL.end();
215	
216	gGL.popUIMatrix();
217}
218
219
220// virtual
221void LLBadge::draw()
222{
223	if (!mLabel.empty())
224	{
225		LLView* owner_view = mOwner.get();
226
227		if (owner_view)
228		{
229			//
230			// Calculate badge size based on label text
231			//
232
233			LLWString badge_label_wstring = mLabel;
234
235			S32 badge_label_begin_offset = 0;
236			S32 badge_char_length = S32_MAX;
237			S32 badge_pixel_length = S32_MAX;
238			F32 *right_position_out = NULL;
239			BOOL do_not_use_ellipses = false;
240
241			F32 badge_width = (2.0f * mPaddingHoriz) +
242				mGLFont->getWidthF32(badge_label_wstring.c_str(), badge_label_begin_offset, badge_char_length);
243
244			F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight();
245
246			//
247			// Calculate badge position based on owner
248			//
249			
250			LLRect owner_rect;
251			owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this);
252
253			S32 location_offset_horiz = mLocationOffsetHCenter;
254			S32 location_offset_vert = mLocationOffsetVCenter;
255
256			// If we're in a scroll container, do some math to keep us in the same place on screen if applicable
257			if (mParentScroller != NULL)
258			{
259				LLRect visibleRect = mParentScroller->getVisibleContentRect();
260
261				if (mLocationOffsetHCenter != BADGE_OFFSET_NOT_SPECIFIED)
262				{
263					if (LLRelPos::IsRight(mLocation))
264					{
265						location_offset_horiz += visibleRect.mRight;
266					}
267					else if (LLRelPos::IsLeft(mLocation))
268					{
269						location_offset_horiz += visibleRect.mLeft;
270					}
271					else // center
272					{
273						location_offset_horiz += (visibleRect.mLeft + visibleRect.mRight) / 2;
274					}
275				}
276
277				if (mLocationOffsetVCenter != BADGE_OFFSET_NOT_SPECIFIED)
278				{
279					if (LLRelPos::IsTop(mLocation))
280					{
281						location_offset_vert += visibleRect.mTop;
282					}
283					else if (LLRelPos::IsBottom(mLocation))
284					{
285						location_offset_vert += visibleRect.mBottom;
286					}
287					else // center
288					{
289						location_offset_vert += (visibleRect.mBottom + visibleRect.mTop) / 2;
290					}
291				}
292			}
293			
294			F32 badge_center_x;
295			F32 badge_center_y;
296
297			// Compute x position
298			if (mLocationOffsetHCenter == BADGE_OFFSET_NOT_SPECIFIED)
299			{
300				badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter;
301			}
302			else
303			{
304				badge_center_x = location_offset_horiz;
305			}
306
307			// Compute y position
308			if (mLocationOffsetVCenter == BADGE_OFFSET_NOT_SPECIFIED)
309			{
310				badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter;
311			}
312			else
313			{
314				badge_center_y = location_offset_vert;
315			}
316
317			//
318			// Draw button image, if available.
319			// Otherwise draw basic rectangular button.
320			//
321
322			F32 alpha = getDrawContext().mAlpha;
323
324			if (!mImage.isNull())
325			{
326				F32 badge_x = badge_center_x - badge_width * 0.5f;
327				F32 badge_y = badge_center_y - badge_height * 0.5f;
328			
329				mImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mImageColor % alpha);
330
331				if (!mBorderImage.isNull())
332				{
333					mBorderImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mBorderColor % alpha);
334				}
335			}
336			else
337			{
338				lldebugs << "No image for badge " << getName() << " on owner " << owner_view->getName() << llendl;
339				
340				renderBadgeBackground(badge_center_x, badge_center_y,
341									  badge_width, badge_height,
342									  mImageColor % alpha);
343			}
344
345			//
346			// Draw the label
347			//
348
349			mGLFont->render(badge_label_wstring,
350							badge_label_begin_offset,
351							badge_center_x + mLabelOffsetHoriz,
352							badge_center_y + mLabelOffsetVert,
353							mLabelColor % alpha,
354							LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position
355							LLFontGL::NORMAL, // normal text (not bold, italics, etc.)
356							LLFontGL::DROP_SHADOW_SOFT,
357							badge_char_length, badge_pixel_length,
358							right_position_out, do_not_use_ellipses);
359		}
360	}
361}
362
363
364namespace LLInitParam
365{
366	void TypeValues<LLRelPos::Location>::declareValues()
367	{
368		declare("bottom",		LLRelPos::BOTTOM);
369		declare("bottom_left",	LLRelPos::BOTTOM_LEFT);
370		declare("bottom_right", LLRelPos::BOTTOM_RIGHT);
371		declare("center",		LLRelPos::CENTER);
372		declare("left",			LLRelPos::LEFT);
373		declare("right",		LLRelPos::RIGHT);
374		declare("top",			LLRelPos::TOP);
375		declare("top_left",		LLRelPos::TOP_LEFT);
376		declare("top_right",	LLRelPos::TOP_RIGHT);
377	}
378}
379
380
381// eof