summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/lldate.h2
-rw-r--r--indra/llui/CMakeLists.txt2
-rw-r--r--indra/llui/llbadge.cpp263
-rw-r--r--indra/llui/llbadge.h152
-rw-r--r--indra/llui/llbutton.cpp94
-rw-r--r--indra/llui/llbutton.h12
-rw-r--r--indra/llxuixml/llinitparam.h2
-rw-r--r--indra/newview/skins/default/colors.xml6
-rw-r--r--indra/newview/skins/default/textures/textures.xml2
-rw-r--r--indra/newview/skins/default/textures/widgets/Badge.pngbin0 -> 1716 bytes
-rw-r--r--indra/newview/skins/default/xui/en/widgets/badge.xml14
11 files changed, 543 insertions, 6 deletions
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 7ff8b550ad..f2bf2366ac 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -34,6 +34,8 @@
#include "stdtypes.h"
+#include "llpreprocessor.h"
+
/**
* @class LLDate
* @brief This class represents a particular point in time in UTC.
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 33ab2e93b5..fb585e062c 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -28,6 +28,7 @@ include_directories(
set(llui_SOURCE_FILES
llaccordionctrl.cpp
llaccordionctrltab.cpp
+ llbadge.cpp
llbutton.cpp
llcheckboxctrl.cpp
llclipboard.cpp
@@ -119,6 +120,7 @@ set(llui_HEADER_FILES
llaccordionctrl.h
llaccordionctrltab.h
+ llbadge.h
llbutton.h
llcallbackmap.h
llcheckboxctrl.h
diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp
new file mode 100644
index 0000000000..ea934aa93b
--- /dev/null
+++ b/indra/llui/llbadge.cpp
@@ -0,0 +1,263 @@
+/**
+ * @file llbadge.cpp
+ * @brief Implementation for badges
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#define LLBADGE_CPP
+#include "llbadge.h"
+
+#include "lluictrlfactory.h"
+
+
+static LLDefaultChildRegistry::Register<LLBadge> r("badge");
+
+// Compiler optimization, generate extern template
+template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
+
+
+LLBadge::Params::Params()
+ : image("image")
+ , image_color("image_color")
+ , label("label")
+ , label_color("label_color")
+ , location("location", LLRelPos::TOP_LEFT)
+ , location_percent_hcenter("location_percent_hcenter")
+ , location_percent_vcenter("location_percent_vcenter")
+ , padding_horiz("padding_horiz")
+ , padding_vert("padding_vert")
+{
+ // We set a name here so the name isn't necessary in any xml files that use badges
+ name = "badge";
+}
+
+bool LLBadge::Params::equals(const Params& a) const
+{
+ bool comp = true;
+
+ // skip owner in comparison on purpose
+
+ comp &= (image() == a.image());
+ comp &= (image_color() == a.image_color());
+ comp &= (label() == a.label());
+ comp &= (label_color() == a.label_color());
+ comp &= (location() == a.location());
+ comp &= (location_percent_hcenter() == a.location_percent_hcenter());
+ comp &= (location_percent_vcenter() == a.location_percent_vcenter());
+ comp &= (padding_horiz() == a.padding_horiz());
+ comp &= (padding_vert() == a.padding_vert());
+
+ return comp;
+}
+
+LLBadge::LLBadge(const LLBadge::Params& p)
+ : LLUICtrl(p)
+ , mOwner(p.owner)
+ , mGLFont(p.font)
+ , mImage(p.image)
+ , mImageColor(p.image_color)
+ , mLabel(p.label)
+ , mLabelColor(p.label_color)
+ , mLocation(p.location)
+ , mLocationPercentHCenter(0.5f)
+ , mLocationPercentVCenter(0.5f)
+ , mPaddingHoriz(p.padding_horiz)
+ , mPaddingVert(p.padding_vert)
+{
+ if (mImage.isNull())
+ {
+ llwarns << "Badge: " << getName() << " with no image!" << llendl;
+ }
+
+ //
+ // The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter
+ // based on the Location enum and our horizontal and vertical location percentages. The
+ // draw code then uses this on the owner rectangle to compute the screen location for
+ // the badge.
+ //
+
+ if (!LLRelPos::IsCenter(mLocation))
+ {
+ F32 h_center = p.location_percent_hcenter * 0.01f;
+ F32 v_center = p.location_percent_vcenter * 0.01f;
+
+ if (LLRelPos::IsRight(mLocation))
+ {
+ mLocationPercentHCenter = 0.5f * (1.0f + h_center);
+ }
+ else if (LLRelPos::IsLeft(mLocation))
+ {
+ mLocationPercentHCenter = 0.5f * (1.0f - h_center);
+ }
+
+ if (LLRelPos::IsTop(mLocation))
+ {
+ mLocationPercentVCenter = 0.5f * (1.0f + v_center);
+ }
+ else if (LLRelPos::IsBottom(mLocation))
+ {
+ mLocationPercentVCenter = 0.5f * (1.0f - v_center);
+ }
+ }
+}
+
+LLBadge::~LLBadge()
+{
+}
+
+void LLBadge::setLabel(const LLStringExplicit& label)
+{
+ mLabel = label;
+}
+
+//
+// This is a fallback function to render a rectangle for badges without a valid image
+//
+void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, const LLColor4U &color)
+{
+ gGL.pushUIMatrix();
+ gGL.loadUIIdentity();
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.color4ubv(color.mV);
+ gGL.texCoord2i(0, 0);
+
+ F32 x = LLFontGL::sCurOrigin.mX + centerX - width * 0.5f;
+ F32 y = LLFontGL::sCurOrigin.mY + centerY - height * 0.5f;
+
+ LLRectf screen_rect(llround(x),
+ llround(y),
+ llround(x) + width,
+ llround(y) + height);
+
+ LLVector3 vertices[4];
+ vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f);
+ vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f);
+ vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
+ vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
+
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, 4);
+ }
+ gGL.end();
+
+ gGL.popUIMatrix();
+}
+
+
+// virtual
+void LLBadge::draw()
+{
+ if (!mLabel.empty())
+ {
+ LLUICtrl* owner_ctrl = mOwner.get();
+
+ if (owner_ctrl)
+ {
+ //
+ // Calculate badge position based on owner
+ //
+
+ LLRect owner_rect;
+ owner_ctrl->localRectToOtherView(owner_ctrl->getLocalRect(), & owner_rect, this);
+
+ F32 badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter;
+ F32 badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter;
+
+ //
+ // Calculate badge size based on label text
+ //
+
+ LLWString badge_label_wstring = mLabel;
+
+ S32 badge_label_begin_offset = 0;
+ S32 badge_char_length = S32_MAX;
+ S32 badge_pixel_length = S32_MAX;
+ F32 *right_position_out = NULL;
+ BOOL do_not_use_ellipses = false;
+
+ F32 badge_width = (2.0f * mPaddingHoriz) +
+ mGLFont->getWidthF32(badge_label_wstring.c_str(), badge_label_begin_offset, badge_char_length);
+
+ F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight();
+
+ //
+ // Draw button image, if available.
+ // Otherwise draw basic rectangular button.
+ //
+
+ F32 alpha = getDrawContext().mAlpha;
+
+ if (!mImage.isNull())
+ {
+ F32 badge_x = badge_center_x - badge_width * 0.5f;
+ F32 badge_y = badge_center_y - badge_height * 0.5f;
+
+ mImage->drawSolid(badge_x, badge_y, badge_width, badge_height, mImageColor % alpha);
+ }
+ else
+ {
+ lldebugs << "No image for badge " << getName() << " on owner " << owner_ctrl->getName() << llendl;
+
+ renderBadgeBackground(badge_center_x, badge_center_y,
+ badge_width, badge_height,
+ mImageColor % alpha);
+ }
+
+ //
+ // Draw the label
+ //
+
+ mGLFont->render(badge_label_wstring, badge_label_begin_offset,
+ badge_center_x, badge_center_y,
+ mLabelColor % alpha,
+ LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position
+ LLFontGL::NORMAL, // normal text (not bold, italics, etc.)
+ LLFontGL::DROP_SHADOW_SOFT,
+ badge_char_length, badge_pixel_length,
+ right_position_out, do_not_use_ellipses);
+ }
+ }
+}
+
+
+namespace LLInitParam
+{
+ void TypeValues<LLRelPos::Location>::declareValues()
+ {
+ declare("bottom", LLRelPos::BOTTOM);
+ declare("bottom_left", LLRelPos::BOTTOM_LEFT);
+ declare("bottom_right", LLRelPos::BOTTOM_RIGHT);
+ declare("center", LLRelPos::CENTER);
+ declare("left", LLRelPos::LEFT);
+ declare("right", LLRelPos::RIGHT);
+ declare("top", LLRelPos::TOP);
+ declare("top_left", LLRelPos::TOP_LEFT);
+ declare("top_right", LLRelPos::TOP_RIGHT);
+ }
+}
+
+
+// eof
diff --git a/indra/llui/llbadge.h b/indra/llui/llbadge.h
new file mode 100644
index 0000000000..c2e0a763b2
--- /dev/null
+++ b/indra/llui/llbadge.h
@@ -0,0 +1,152 @@
+/**
+ * @file llbadge.h
+ * @brief Header for badges
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLBADGE_H
+#define LL_LLBADGE_H
+
+#include <string>
+
+#include "lluicolor.h"
+#include "lluictrl.h"
+#include "llstring.h"
+#include "lluiimage.h"
+
+//
+// Declarations
+//
+
+class LLUICtrlFactory;
+class LLFontGL;
+
+//
+// Relative Position Alignment
+//
+
+namespace LLRelPos
+{
+ enum Location
+ {
+ CENTER = 0,
+
+ LEFT = (1 << 0),
+ RIGHT = (1 << 1),
+
+ TOP = (1 << 2),
+ BOTTOM = (1 << 3),
+
+ BOTTOM_LEFT = (BOTTOM | LEFT),
+ BOTTOM_RIGHT = (BOTTOM | RIGHT),
+
+ TOP_LEFT = (TOP | LEFT),
+ TOP_RIGHT = (TOP | RIGHT),
+ };
+
+ inline bool IsBottom(Location relPos) { return (relPos & BOTTOM) == BOTTOM; }
+ inline bool IsCenter(Location relPos) { return (relPos == CENTER); }
+ inline bool IsLeft(Location relPos) { return (relPos & LEFT) == LEFT; }
+ inline bool IsRight(Location relPos) { return (relPos & RIGHT) == RIGHT; }
+ inline bool IsTop(Location relPos) { return (relPos & TOP) == TOP; }
+}
+
+// NOTE: This needs to occur before Optional<LLRelPos::Location> declaration for proper compilation.
+namespace LLInitParam
+{
+ template<>
+ struct TypeValues<LLRelPos::Location> : public TypeValuesHelper<LLRelPos::Location>
+ {
+ static void declareValues();
+ };
+}
+
+//
+// Classes
+//
+
+class LLBadge
+: public LLUICtrl
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional< LLHandle<LLUICtrl> > owner; // Mandatory in code but not in xml
+
+ Optional< LLUIImage* > image;
+ Optional< LLUIColor > image_color;
+
+ Optional< std::string > label;
+ Optional< LLUIColor > label_color;
+
+ Optional< LLRelPos::Location > location;
+ Optional< U32 > location_percent_hcenter;
+ Optional< U32 > location_percent_vcenter;
+
+ Optional< F32 > padding_horiz;
+ Optional< F32 > padding_vert;
+
+ Params();
+
+ bool equals(const Params&) const;
+ };
+
+protected:
+ friend class LLUICtrlFactory;
+ LLBadge(const Params& p);
+
+public:
+
+ ~LLBadge();
+
+ virtual void draw();
+
+ const std::string getLabel() const { return wstring_to_utf8str(mLabel); }
+ void setLabel( const LLStringExplicit& label);
+
+private:
+ const LLFontGL* mGLFont;
+
+ LLPointer< LLUIImage > mImage;
+ LLUIColor mImageColor;
+
+ LLUIString mLabel;
+ LLUIColor mLabelColor;
+
+ LLRelPos::Location mLocation;
+ F32 mLocationPercentHCenter;
+ F32 mLocationPercentVCenter;
+
+ LLHandle< LLUICtrl > mOwner;
+
+ F32 mPaddingHoriz;
+ F32 mPaddingVert;
+};
+
+// Build time optimization, generate once in .cpp file
+#ifndef LLBADGE_CPP
+extern template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
+#endif
+
+#endif // LL_LLBADGE_H
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 45ceaff696..a63281b3c1 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -56,6 +56,9 @@ static LLDefaultChildRegistry::Register<LLButton> r("button");
template class LLButton* LLView::getChild<class LLButton>(
const std::string& name, BOOL recurse) const;
+
+
+
// globals loaded from settings.xml
S32 LLBUTTON_H_PAD = 0;
S32 BTN_HEIGHT_SMALL= 0;
@@ -99,7 +102,8 @@ LLButton::Params::Params()
scale_image("scale_image", true),
hover_glow_amount("hover_glow_amount"),
commit_on_return("commit_on_return", true),
- use_draw_context_alpha("use_draw_context_alpha", true)
+ use_draw_context_alpha("use_draw_context_alpha", true),
+ badge("badge")
{
addSynonym(is_toggle, "toggle");
held_down_delay.seconds = 0.5f;
@@ -160,8 +164,8 @@ LLButton::LLButton(const LLButton::Params& p)
mMouseDownSignal(NULL),
mMouseUpSignal(NULL),
mHeldDownSignal(NULL),
- mUseDrawContextAlpha(p.use_draw_context_alpha)
-
+ mUseDrawContextAlpha(p.use_draw_context_alpha),
+ mBadge(NULL)
{
static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>());
@@ -244,6 +248,17 @@ LLButton::LLButton(const LLButton::Params& p)
{
setHeldDownCallback(initCommitCallback(p.mouse_held_callback));
}
+
+ // Only create a badge here if a non-default one was provided.
+ if (p.badge.isProvided())
+ {
+ if (!p.badge().equals(LLUICtrlFactory::getDefaultParams<LLBadge>()))
+ {
+ LLBadge::Params badge_params(p.badge());
+ badge_params.owner = getUICtrlHandle();
+ mBadge = LLUICtrlFactory::create<LLBadge>(badge_params);
+ }
+ }
}
LLButton::~LLButton()
@@ -327,6 +342,13 @@ boost::signals2::connection LLButton::setHeldDownCallback( button_callback_t cb,
BOOL LLButton::postBuild()
{
autoResize();
+
+ // Attach the badge to the appropriate parent panel
+ if (mBadge)
+ {
+ addBadgeToParentPanel();
+ }
+
return TRUE;
}
BOOL LLButton::handleUnicodeCharHere(llwchar uni_char)
@@ -867,7 +889,7 @@ void LLButton::draw()
S32_MAX, text_width,
NULL, mUseEllipses);
}
-
+
LLUICtrl::draw();
}
@@ -1063,6 +1085,70 @@ void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignmen
}
}
+void LLButton::addBadgeToParentPanel()
+{
+ if (mBadge)
+ {
+ // Find the appropriate parent panel for the badge
+
+ LLPanel * parentPanel = NULL;
+ LLUICtrl * parent = getParentUICtrl();
+
+ while (parent)
+ {
+ parentPanel = dynamic_cast<LLPanel*>(parent);
+
+ if (parentPanel != NULL)
+ {
+ break;
+ }
+
+ parent = parent->getParentUICtrl();
+ }
+
+ if (parentPanel)
+ {
+ parentPanel->addChild(mBadge);
+ }
+ else
+ {
+ llwarns << "Unable to find parent panel for badge " << mBadge->getName() << " on button " << getName() << llendl;
+ }
+ }
+ else
+ {
+ llwarns << "Unable to add NULL badge to button " << getName() << llendl;
+ }
+}
+
+void LLButton::setBadgeLabel(const LLStringExplicit& label)
+{
+ if (mBadge == NULL)
+ {
+ LLBadge::Params badge_params(LLUICtrlFactory::getDefaultParams<LLBadge>());
+ badge_params.owner = getUICtrlHandle();
+ mBadge = LLUICtrlFactory::create<LLBadge>(badge_params);
+
+ addBadgeToParentPanel();
+ }
+
+ if (mBadge)
+ {
+ mBadge->setLabel(label);
+
+ //
+ // Push the badge to the front so it renders last
+ //
+
+ LLUICtrl * parent = mBadge->getParentUICtrl();
+
+ if (parent)
+ {
+ parent->sendChildToFront(mBadge);
+ }
+ }
+}
+
void LLButton::onMouseCaptureLost()
{
resetMouseDownTimer();
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 0cfc393e05..232ab81e0d 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -27,6 +27,8 @@
#ifndef LL_LLBUTTON_H
#define LL_LLBUTTON_H
+#include "lluuid.h"
+#include "llbadge.h"
#include "llcontrol.h"
#include "lluictrl.h"
#include "v4color.h"
@@ -52,8 +54,6 @@ S32 round_up(S32 grid, S32 value);
class LLUICtrlFactory;
-class LLUIImage;
-class LLUUID;
//
// Classes
@@ -126,6 +126,8 @@ public:
Optional<TimeIntervalParam> held_down_delay;
Optional<bool> use_draw_context_alpha;
+
+ Optional<LLBadge::Params> badge;
Params();
};
@@ -249,6 +251,8 @@ public:
void setImageDisabledSelected(LLPointer<LLUIImage> image);
void setImageFlash(LLPointer<LLUIImage> image);
void setImagePressed(LLPointer<LLUIImage> image);
+
+ void setBadgeLabel(const LLStringExplicit& label);
void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
BOOL getCommitOnReturn() const { return mCommitOnReturn; }
@@ -267,6 +271,8 @@ protected:
LLPointer<LLUIImage> getImageUnselected() const { return mImageUnselected; }
LLPointer<LLUIImage> getImageSelected() const { return mImageSelected; }
+ void addBadgeToParentPanel();
+
LLFrameTimer mMouseDownTimer;
private:
@@ -357,6 +363,8 @@ private:
bool mForcePressedState;
LLFrameTimer mFlashingTimer;
+
+ LLBadge* mBadge;
};
// Build time optimization, generate once in .cpp file
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index a853999e94..ce7cb5b3e0 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -34,6 +34,8 @@
#include <boost/unordered_map.hpp>
#include <boost/shared_ptr.hpp>
+#include "llerror.h"
+
namespace LLInitParam
{
template<typename T> const T& defaultValue() { static T value; return value; }
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index a19eccf748..0795e38366 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -133,6 +133,12 @@
name="AvatarListItemIconVoiceLeftColor"
reference="AvatarListItemIconOfflineColor" />
<color
+ name="BadgeImageColor"
+ value="0.25 0.85 0.25 1.0" />
+ <color
+ name="BadgeLabelColor"
+ reference="White" />
+ <color
name="ButtonBorderColor"
reference="Unused?" />
<color
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 4f19dd9a6d..2a78337f65 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -72,6 +72,8 @@ with the same filename but different name
<texture name="BackButton_Over" file_name="icons/back_arrow_over.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
<texture name="BackButton_Press" file_name="icons/back_arrow_press.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
+ <texture name="Badge" file_name="widgets/Badge.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+
<texture name="Blank" file_name="Blank.png" preload="false" />
diff --git a/indra/newview/skins/default/textures/widgets/Badge.png b/indra/newview/skins/default/textures/widgets/Badge.png
new file mode 100644
index 0000000000..afda6b66b9
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Badge.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/widgets/badge.xml b/indra/newview/skins/default/xui/en/widgets/badge.xml
new file mode 100644
index 0000000000..4eb633ac0c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/badge.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Additional attributes:
+ -->
+<badge font="SansSerifSmall"
+ image="Badge"
+ image_color="BadgeImageColor"
+ label_color="BadgeLabelColor"
+ location="top_left"
+ location_percent_hcenter="85"
+ location_percent_vcenter="85"
+ padding_horiz="7"
+ padding_vert="4"
+ >
+</badge>