Files
SingularityViewer/indra/newview/llgroupnotify.cpp
Inusaito Sayori 9723a45e72 Modernize LLIconCtrl
Adds min_height and min_width attributes
Adds mPriority for controlling priority with which to call LLUI::getUIImage*
Moves specialized setImage()s into setValue
Removes mImageName and mImageID, value is stored in base as LLSD now
2013-12-01 15:58:24 -05:00

475 lines
13 KiB
C++

/**
* @file llgroupnotify.cpp
* @brief Non-blocking notification that doesn't take keyboard focus.
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llgroupnotify.h"
#include "llfocusmgr.h"
#include "llbutton.h"
#include "lliconctrl.h"
#include "llfloaterchat.h" // for add_chat_history()
#include "llgroupactions.h"
#include "llnotify.h"
#include "lltextbox.h"
#include "llviewertexteditor.h"
#include "lluiconstants.h"
#include "llui.h"
#include "llviewercontrol.h"
#include "llinventoryicon.h"
#include "llinventory.h"
#include "lltrans.h"
#include "llglheaders.h"
#include "llagent.h"
// Globals
//LLView* gGroupNotifyBoxView = NULL;
const F32 ANIMATION_TIME = 0.333f;
S32 LLGroupNotifyBox::sGroupNotifyBoxCount = 0;
//---------------------------------------------------------------------------
// LLGroupNotifyBox
//---------------------------------------------------------------------------
bool is_openable(LLAssetType::EType type)
{
switch(type)
{
case LLAssetType::AT_LANDMARK:
case LLAssetType::AT_NOTECARD:
case LLAssetType::AT_IMAGE_JPEG:
case LLAssetType::AT_IMAGE_TGA:
case LLAssetType::AT_TEXTURE:
case LLAssetType::AT_TEXTURE_TGA:
return true;
default:
return false;
}
}
LLGroupNotifyBox::LLGroupNotifyBox(const std::string& subject,
const std::string& message,
const std::string& from_name,
const LLUUID& group_id,
const LLUUID& group_insignia,
const std::string& group_name,
const LLDate& time_stamp,
const bool& has_inventory,
const std::string& inventory_name,
const LLSD& inventory_offer)
: LLPanel("groupnotify", LLGroupNotifyBox::getGroupNotifyRect(), BORDER_YES),
mAnimating(TRUE),
mTimer(),
mGroupID(group_id),
mHasInventory(has_inventory),
mInventoryOffer(NULL)
{
const S32 VPAD = 2;
const S32 TOP = getRect().getHeight() - 32; // Get past the top menu bar
const S32 BOTTOM_PAD = VPAD * 2;
const S32 BTN_TOP = BOTTOM_PAD + BTN_HEIGHT + VPAD;
const S32 RIGHT = getRect().getWidth() - HPAD - HPAD;
const S32 LINE_HEIGHT = 16;
const S32 LABEL_WIDTH = 64;
const S32 ICON_WIDTH = 64;
time_t timestamp = (time_t)time_stamp.secondsSinceEpoch();
if (!timestamp) time(&timestamp);
std::string time_buf;
timeToFormattedString(timestamp, gSavedSettings.getString("TimestampFormat"), time_buf);
if (mHasInventory)
{
mInventoryOffer = new LLOfferInfo(inventory_offer);
}
setFocusRoot(TRUE);
setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
setBackgroundVisible(TRUE);
setBackgroundOpaque(TRUE);
setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );
LLIconCtrl* icon;
LLTextEditor* text;
S32 y = TOP;
S32 x = HPAD + HPAD;
class NoticeText : public LLTextBox
{
public:
NoticeText(const std::string& name, const LLRect& rect, const std::string& text = LLStringUtil::null, const LLFontGL* font = NULL)
: LLTextBox(name, rect, text, font)
{
setHAlign(LLFontGL::RIGHT);
setFontShadow(LLFontGL::DROP_SHADOW_SOFT);
setBorderVisible(FALSE);
setColor( gColors.getColor("GroupNotifyTextColor") );
setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );
}
};
// Title
addChild(new NoticeText(std::string("title"),LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),LLTrans::getString("GroupNotifyGroupNotice"),LLFontGL::getFontSansSerifHuge()));
y -= llfloor(1.5f*LINE_HEIGHT);
x += HPAD + HPAD + ICON_WIDTH;
std::stringstream from;
from << LLTrans::getString("GroupNotifySentBy") << " " + from_name << LLTrans::getString(",") + " " << group_name;
addChild(new NoticeText(std::string("group"),LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),from.str(),LLFontGL::getFontSansSerif()));
y -= (LINE_HEIGHT + VPAD);
x = HPAD + HPAD;
// TODO: change this to be the group icon.
if (!group_insignia.isNull())
{
icon = new LLIconCtrl(std::string("icon"),
LLRect(x, y, x+ICON_WIDTH, y-ICON_WIDTH),
group_insignia.asString());
}
else
{
icon = new LLIconCtrl(std::string("icon"),
LLRect(x, y, x+ICON_WIDTH, y-ICON_WIDTH),
std::string("notify_box_icon.tga"));
}
icon->setMouseOpaque(FALSE);
addChild(icon);
x += HPAD + HPAD + ICON_WIDTH;
// If we have inventory with this message, leave room for the name.
S32 box_bottom = BTN_TOP + (mHasInventory ? (LINE_HEIGHT + 2*VPAD) : 0);
text = new LLViewerTextEditor(std::string("box"),
LLRect(x, y, RIGHT, box_bottom),
DB_GROUP_NOTICE_MSG_STR_LEN,
LLStringUtil::null,
LLFontGL::getFontSansSerif(),
FALSE);
static const LLStyleSP headerstyle(new LLStyle(true,LLColor4::black,"SansSerifBig"));
static const LLStyleSP datestyle(new LLStyle(true,LLColor4::black,"serif"));
text->appendStyledText(subject + "\n",false,false,headerstyle);
text->appendStyledText(time_buf,false,false,datestyle);
// Sadly, our LLTextEditor can't handle both styled and unstyled text
// at the same time. Hence this space must be styled. JC
text->appendColoredText(std::string(" "),false,false,LLColor4::grey4);
text->setParseHTML(TRUE);
text->appendColoredText(std::string("\n\n") + message,false,false,LLColor4::grey4);
LLColor4 semi_transparent(1.0f,1.0f,1.0f,0.8f);
text->setCursor(0,0);
text->setEnabled(FALSE);
text->setWordWrap(TRUE);
//text->setTabStop(FALSE); // was interfering with copy-and-paste
text->setTabsToNextField(TRUE);
text->setMouseOpaque(TRUE);
text->setBorderVisible(TRUE);
text->setTakesNonScrollClicks(TRUE);
text->setHideScrollbarForShortDocs(TRUE);
text->setReadOnlyBgColor ( semi_transparent );
text->setWriteableBgColor ( semi_transparent );
addChild(text);
y = box_bottom - VPAD;
if (mHasInventory)
{
addChild(new NoticeText(std::string("subjecttitle"),LLRect(x,y,x + LABEL_WIDTH,y - LINE_HEIGHT),LLTrans::getString("GroupNotifyAttached"),LLFontGL::getFontSansSerif()));
LLUIImagePtr item_icon = LLInventoryIcon::getIcon(mInventoryOffer->mType,
LLInventoryType::IT_TEXTURE,
0, FALSE);
x += LABEL_WIDTH + HPAD;
std::stringstream ss;
ss << " " << inventory_name;
LLTextBox *line = new LLTextBox(std::string("object_name"),LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),ss.str(),LLFontGL::getFontSansSerif());
line->setEnabled(FALSE);
line->setBorderVisible(TRUE);
line->setDisabledColor(LLColor4::blue4);
line->setFontStyle(LLFontGL::NORMAL);
line->setBackgroundVisible(true);
line->setBackgroundColor( semi_transparent );
addChild(line);
icon = new LLIconCtrl(std::string("icon"),
LLRect(x, y, x+16, y-16),
item_icon->getName());
icon->setMouseOpaque(FALSE);
addChild(icon);
}
LLButton* btn;
btn = new LLButton(LLTrans::getString("next"),
LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD),
std::string("notify_next.png"),
std::string("notify_next.png"),
LLStringUtil::null,
boost::bind(&LLGroupNotifyBox::onClickNext, this),
LLFontGL::getFontSansSerif());
btn->setToolTip(LLTrans::getString("next"));
btn->setScaleImage(TRUE);
addChild(btn);
mNextBtn = btn;
S32 btn_width = 80;
S32 wide_btn_width = 120;
LLRect btn_rect;
x = 3 * HPAD;
btn_rect.setOriginAndSize(x,
BOTTOM_PAD,
btn_width,
BTN_HEIGHT);
btn = new LLButton(LLTrans::getString("ok"), btn_rect, LLStringUtil::null, boost::bind(&LLGroupNotifyBox::onClickOk,this));
addChild(btn, -1);
setDefaultBtn(btn);
x += btn_width + HPAD;
btn_rect.setOriginAndSize(x,
BOTTOM_PAD,
wide_btn_width,
BTN_HEIGHT);
btn = new LLButton(LLTrans::getString("GroupNotifyGroupNotices"), btn_rect, LLStringUtil::null, boost::bind(LLGroupActions::showTab, mGroupID, "notices_tab"));
btn->setToolTip(LLTrans::getString("GroupNotifyViewPastNotices"));
addChild(btn, -1);
if (mHasInventory)
{
x += wide_btn_width + HPAD;
btn_rect.setOriginAndSize(x,
BOTTOM_PAD,
wide_btn_width,
BTN_HEIGHT);
std::string btn_lbl("");
if(is_openable(mInventoryOffer->mType))
{
btn_lbl = LLTrans::getString("GroupNotifyOpenAttachment");
}
else
{
btn_lbl = LLTrans::getString("GroupNotifySaveAttachment");
}
mSaveInventoryBtn = new LLButton(btn_lbl, btn_rect, LLStringUtil::null, boost::bind(&LLGroupNotifyBox::onClickSaveInventory,this));
mSaveInventoryBtn->setVisible(mHasInventory);
addChild(mSaveInventoryBtn);
}
sGroupNotifyBoxCount++;
// If this is the only notify box, don't show the next button
if (sGroupNotifyBoxCount == 1)
{
mNextBtn->setVisible(FALSE);
}
}
// virtual
LLGroupNotifyBox::~LLGroupNotifyBox()
{
sGroupNotifyBoxCount--;
}
// virtual
BOOL LLGroupNotifyBox::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
moveToBack();
return TRUE;
}
// virtual
void LLGroupNotifyBox::draw()
{
F32 display_time = mTimer.getElapsedTimeF32();
if (mAnimating && display_time < ANIMATION_TIME)
{
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
S32 height = getRect().getHeight();
F32 fraction = display_time / ANIMATION_TIME;
F32 voffset = (1.f - fraction) * height;
gGL.translatef(0.f, voffset, 0.f);
LLPanel::draw();
gGL.popMatrix();
}
else
{
mAnimating = FALSE;
LLPanel::draw();
}
}
void LLGroupNotifyBox::close()
{
// The group notice dialog may be an inventory offer.
// If it has an inventory save button and that button is still enabled
// Then we need to send the inventory declined message
if(mHasInventory)
{
mInventoryOffer->forceResponse(IOR_DECLINE);
mInventoryOffer = NULL;
mHasInventory = FALSE;
}
gNotifyBoxView->removeChild(this);
die();
}
//static
void LLGroupNotifyBox::initClass()
{
LLNotificationChannel::buildChannel("Group Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "groupnotify"));
LLNotifications::instance().getChannel("Group Notifications")->connectChanged(&LLGroupNotifyBox::onNewNotification);
}
//static
bool LLGroupNotifyBox::onNewNotification(const LLSD& notify)
{
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
if (notification)
{
const LLSD& payload = notification->getPayload();
// Get the group data
LLGroupData group_data;
if (!gAgent.getGroupData(payload["group_id"].asUUID(),group_data))
{
llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl;
return false;
}
LLGroupNotifyBox* self;
self = new LLGroupNotifyBox(payload["subject"].asString(),
payload["message"].asString(),
payload["sender_name"].asString(),
payload["group_id"].asUUID(),
group_data.mInsigniaID,
group_data.mName,
notification->getDate(),
payload["inventory_offer"].isDefined(),
payload["inventory_name"].asString(),
payload["inventory_offer"]);
gNotifyBoxView->addChild(self);
}
return false;
}
void LLGroupNotifyBox::moveToBack()
{
// Move this dialog to the back.
gNotifyBoxView->removeChild(this);
gNotifyBoxView->addChildInBack(this);
mNextBtn->setVisible(FALSE);
// And enable the next button on the frontmost one, if there is one
if (sGroupNotifyBoxCount > 1)
{
LLView* view = gNotifyBoxView->getFirstChild();
if(view && "groupnotify" == view->getName())
{
LLGroupNotifyBox* front = (LLGroupNotifyBox*)view;
if(front->mNextBtn)
{
front->mNextBtn->setVisible(TRUE);
}
}
}
}
// static
LLRect LLGroupNotifyBox::getGroupNotifyRect()
{
S32 notify_height = gSavedSettings.getS32("GroupNotifyBoxHeight");
const S32 NOTIFY_WIDTH = gSavedSettings.getS32("GroupNotifyBoxWidth");
const S32 TOP = gNotifyBoxView->getRect().getHeight();
const S32 RIGHT = gNotifyBoxView->getRect().getWidth();
const S32 LEFT = RIGHT - NOTIFY_WIDTH;
return LLRect(LEFT, TOP, RIGHT, TOP-notify_height);
}
void LLGroupNotifyBox::onClickOk()
{
close();
}
void LLGroupNotifyBox::onClickSaveInventory()
{
mInventoryOffer->forceResponse(IOR_ACCEPT);
mInventoryOffer = NULL;
mHasInventory = FALSE;
// Each item can only be received once, so disable the button.
mSaveInventoryBtn->setEnabled(FALSE);
}
void LLGroupNotifyBox::onClickNext()
{
moveToBack();
}