PageRenderTime 88ms CodeModel.GetById 0ms RepoModel.GetById 0ms 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
Possible License(s): LGPL-2.1
  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. #define LLBADGE_CPP
  27. #include "llbadge.h"
  28. #include "llscrollcontainer.h"
  29. #include "lluictrlfactory.h"
  30. static LLDefaultChildRegistry::Register<LLBadge> r("badge");
  31. static const S32 BADGE_OFFSET_NOT_SPECIFIED = 0x7FFFFFFF;
  32. // Compiler optimization, generate extern template
  33. template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
  34. LLBadge::Params::Params()
  35. : image("image")
  36. , border_image("border_image")
  37. , border_color("border_color")
  38. , image_color("image_color")
  39. , label("label")
  40. , label_color("label_color")
  41. , label_offset_horiz("label_offset_horiz")
  42. , label_offset_vert("label_offset_vert")
  43. , location("location", LLRelPos::TOP_LEFT)
  44. , location_offset_hcenter("location_offset_hcenter")
  45. , location_offset_vcenter("location_offset_vcenter")
  46. , location_percent_hcenter("location_percent_hcenter")
  47. , location_percent_vcenter("location_percent_vcenter")
  48. , padding_horiz("padding_horiz")
  49. , padding_vert("padding_vert")
  50. {}
  51. bool LLBadge::Params::equals(const Params& a) const
  52. {
  53. bool comp = true;
  54. // skip owner in comparison on purpose
  55. comp &= (border_image() == a.border_image());
  56. comp &= (border_color() == a.border_color());
  57. comp &= (image() == a.image());
  58. comp &= (image_color() == a.image_color());
  59. comp &= (label() == a.label());
  60. comp &= (label_color() == a.label_color());
  61. comp &= (label_offset_horiz() == a.label_offset_horiz());
  62. comp &= (label_offset_vert() == a.label_offset_vert());
  63. comp &= (location() == a.location());
  64. comp &= (location_offset_hcenter() == a.location_offset_hcenter());
  65. comp &= (location_offset_vcenter() == a.location_offset_vcenter());
  66. comp &= (location_percent_hcenter() == a.location_percent_hcenter());
  67. comp &= (location_percent_vcenter() == a.location_percent_vcenter());
  68. comp &= (padding_horiz() == a.padding_horiz());
  69. comp &= (padding_vert() == a.padding_vert());
  70. return comp;
  71. }
  72. LLBadge::LLBadge(const LLBadge::Params& p)
  73. : LLUICtrl(p)
  74. , mOwner(p.owner)
  75. , mBorderImage(p.border_image)
  76. , mBorderColor(p.border_color)
  77. , mGLFont(p.font)
  78. , mImage(p.image)
  79. , mImageColor(p.image_color)
  80. , mLabel(p.label)
  81. , mLabelColor(p.label_color)
  82. , mLabelOffsetHoriz(p.label_offset_horiz)
  83. , mLabelOffsetVert(p.label_offset_vert)
  84. , mLocation(p.location)
  85. , mLocationOffsetHCenter(BADGE_OFFSET_NOT_SPECIFIED)
  86. , mLocationOffsetVCenter(BADGE_OFFSET_NOT_SPECIFIED)
  87. , mLocationPercentHCenter(0.5f)
  88. , mLocationPercentVCenter(0.5f)
  89. , mPaddingHoriz(p.padding_horiz)
  90. , mPaddingVert(p.padding_vert)
  91. , mParentScroller(NULL)
  92. {
  93. if (mImage.isNull())
  94. {
  95. llwarns << "Badge: " << getName() << " with no image!" << llendl;
  96. }
  97. if (p.location_offset_hcenter.isProvided())
  98. {
  99. mLocationOffsetHCenter = p.location_offset_hcenter();
  100. }
  101. if (p.location_offset_vcenter.isProvided())
  102. {
  103. mLocationOffsetVCenter = p.location_offset_vcenter();
  104. }
  105. //
  106. // The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter
  107. // based on the Location enum and our horizontal and vertical location percentages. The
  108. // draw code then uses this on the owner rectangle to compute the screen location for
  109. // the badge.
  110. //
  111. if (!LLRelPos::IsCenter(mLocation))
  112. {
  113. F32 h_center = p.location_percent_hcenter * 0.01f;
  114. F32 v_center = p.location_percent_vcenter * 0.01f;
  115. if (LLRelPos::IsRight(mLocation))
  116. {
  117. mLocationPercentHCenter = 0.5f * (1.0f + h_center);
  118. }
  119. else if (LLRelPos::IsLeft(mLocation))
  120. {
  121. mLocationPercentHCenter = 0.5f * (1.0f - h_center);
  122. }
  123. if (LLRelPos::IsTop(mLocation))
  124. {
  125. mLocationPercentVCenter = 0.5f * (1.0f + v_center);
  126. }
  127. else if (LLRelPos::IsBottom(mLocation))
  128. {
  129. mLocationPercentVCenter = 0.5f * (1.0f - v_center);
  130. }
  131. }
  132. }
  133. LLBadge::~LLBadge()
  134. {
  135. }
  136. bool LLBadge::addToView(LLView * view)
  137. {
  138. bool child_added = view->addChild(this);
  139. if (child_added)
  140. {
  141. setShape(view->getLocalRect());
  142. // Find a parent scroll container, if there is one in case we need it for positioning
  143. LLView * parent = mOwner.get();
  144. while ((parent != NULL) && ((mParentScroller = dynamic_cast<LLScrollContainer *>(parent)) == NULL))
  145. {
  146. parent = parent->getParent();
  147. }
  148. }
  149. return child_added;
  150. }
  151. void LLBadge::setLabel(const LLStringExplicit& label)
  152. {
  153. mLabel = label;
  154. }
  155. //
  156. // This is a fallback function to render a rectangle for badges without a valid image
  157. //
  158. void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, const LLColor4U &color)
  159. {
  160. gGL.pushUIMatrix();
  161. gGL.loadUIIdentity();
  162. gGL.setSceneBlendType(LLRender::BT_REPLACE);
  163. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  164. gGL.color4ubv(color.mV);
  165. gGL.texCoord2i(0, 0);
  166. F32 x = LLFontGL::sCurOrigin.mX + centerX - width * 0.5f;
  167. F32 y = LLFontGL::sCurOrigin.mY + centerY - height * 0.5f;
  168. LLRectf screen_rect(llround(x),
  169. llround(y),
  170. llround(x) + width,
  171. llround(y) + height);
  172. LLVector3 vertices[4];
  173. vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f);
  174. vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f);
  175. vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
  176. vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
  177. gGL.begin(LLRender::QUADS);
  178. {
  179. gGL.vertexBatchPreTransformed(vertices, 4);
  180. }
  181. gGL.end();
  182. gGL.popUIMatrix();
  183. }
  184. // virtual
  185. void LLBadge::draw()
  186. {
  187. if (!mLabel.empty())
  188. {
  189. LLView* owner_view = mOwner.get();
  190. if (owner_view)
  191. {
  192. //
  193. // Calculate badge size based on label text
  194. //
  195. LLWString badge_label_wstring = mLabel;
  196. S32 badge_label_begin_offset = 0;
  197. S32 badge_char_length = S32_MAX;
  198. S32 badge_pixel_length = S32_MAX;
  199. F32 *right_position_out = NULL;
  200. BOOL do_not_use_ellipses = false;
  201. F32 badge_width = (2.0f * mPaddingHoriz) +
  202. mGLFont->getWidthF32(badge_label_wstring.c_str(), badge_label_begin_offset, badge_char_length);
  203. F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight();
  204. //
  205. // Calculate badge position based on owner
  206. //
  207. LLRect owner_rect;
  208. owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this);
  209. S32 location_offset_horiz = mLocationOffsetHCenter;
  210. S32 location_offset_vert = mLocationOffsetVCenter;
  211. // If we're in a scroll container, do some math to keep us in the same place on screen if applicable
  212. if (mParentScroller != NULL)
  213. {
  214. LLRect visibleRect = mParentScroller->getVisibleContentRect();
  215. if (mLocationOffsetHCenter != BADGE_OFFSET_NOT_SPECIFIED)
  216. {
  217. if (LLRelPos::IsRight(mLocation))
  218. {
  219. location_offset_horiz += visibleRect.mRight;
  220. }
  221. else if (LLRelPos::IsLeft(mLocation))
  222. {
  223. location_offset_horiz += visibleRect.mLeft;
  224. }
  225. else // center
  226. {
  227. location_offset_horiz += (visibleRect.mLeft + visibleRect.mRight) / 2;
  228. }
  229. }
  230. if (mLocationOffsetVCenter != BADGE_OFFSET_NOT_SPECIFIED)
  231. {
  232. if (LLRelPos::IsTop(mLocation))
  233. {
  234. location_offset_vert += visibleRect.mTop;
  235. }
  236. else if (LLRelPos::IsBottom(mLocation))
  237. {
  238. location_offset_vert += visibleRect.mBottom;
  239. }
  240. else // center
  241. {
  242. location_offset_vert += (visibleRect.mBottom + visibleRect.mTop) / 2;
  243. }
  244. }
  245. }
  246. F32 badge_center_x;
  247. F32 badge_center_y;
  248. // Compute x position
  249. if (mLocationOffsetHCenter == BADGE_OFFSET_NOT_SPECIFIED)
  250. {
  251. badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter;
  252. }
  253. else
  254. {
  255. badge_center_x = location_offset_horiz;
  256. }
  257. // Compute y position
  258. if (mLocationOffsetVCenter == BADGE_OFFSET_NOT_SPECIFIED)
  259. {
  260. badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter;
  261. }
  262. else
  263. {
  264. badge_center_y = location_offset_vert;
  265. }
  266. //
  267. // Draw button image, if available.
  268. // Otherwise draw basic rectangular button.
  269. //
  270. F32 alpha = getDrawContext().mAlpha;
  271. if (!mImage.isNull())
  272. {
  273. F32 badge_x = badge_center_x - badge_width * 0.5f;
  274. F32 badge_y = badge_center_y - badge_height * 0.5f;
  275. mImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mImageColor % alpha);
  276. if (!mBorderImage.isNull())
  277. {
  278. mBorderImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mBorderColor % alpha);
  279. }
  280. }
  281. else
  282. {
  283. lldebugs << "No image for badge " << getName() << " on owner " << owner_view->getName() << llendl;
  284. renderBadgeBackground(badge_center_x, badge_center_y,
  285. badge_width, badge_height,
  286. mImageColor % alpha);
  287. }
  288. //
  289. // Draw the label
  290. //
  291. mGLFont->render(badge_label_wstring,
  292. badge_label_begin_offset,
  293. badge_center_x + mLabelOffsetHoriz,
  294. badge_center_y + mLabelOffsetVert,
  295. mLabelColor % alpha,
  296. LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position
  297. LLFontGL::NORMAL, // normal text (not bold, italics, etc.)
  298. LLFontGL::DROP_SHADOW_SOFT,
  299. badge_char_length, badge_pixel_length,
  300. right_position_out, do_not_use_ellipses);
  301. }
  302. }
  303. }
  304. namespace LLInitParam
  305. {
  306. void TypeValues<LLRelPos::Location>::declareValues()
  307. {
  308. declare("bottom", LLRelPos::BOTTOM);
  309. declare("bottom_left", LLRelPos::BOTTOM_LEFT);
  310. declare("bottom_right", LLRelPos::BOTTOM_RIGHT);
  311. declare("center", LLRelPos::CENTER);
  312. declare("left", LLRelPos::LEFT);
  313. declare("right", LLRelPos::RIGHT);
  314. declare("top", LLRelPos::TOP);
  315. declare("top_left", LLRelPos::TOP_LEFT);
  316. declare("top_right", LLRelPos::TOP_RIGHT);
  317. }
  318. }
  319. // eof