llgroupnotify.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llgroupnotify.h"
00035 
00036 #include "llfocusmgr.h"
00037 
00038 #include "llbutton.h"
00039 #include "lliconctrl.h"
00040 #include "llfloaterchat.h"      // for add_chat_history()
00041 #include "llnotify.h"
00042 #include "lltextbox.h"
00043 #include "llviewertexteditor.h"
00044 #include "lluiconstants.h"
00045 #include "llui.h"
00046 #include "llviewercontrol.h"
00047 #include "llfloatergroupinfo.h"
00048 #include "llinventoryview.h"
00049 #include "llinventory.h"
00050 
00051 #include "llglheaders.h"
00052 #include "llagent.h"
00053 // Globals
00054 //LLView* gGroupNotifyBoxView = NULL;
00055 
00056 const F32 ANIMATION_TIME = 0.333f;
00057 
00058 S32 LLGroupNotifyBox::sGroupNotifyBoxCount = 0;
00059 
00060 //---------------------------------------------------------------------------
00061 // LLGroupNotifyBox
00062 //---------------------------------------------------------------------------
00063 
00064 char* g_formatted_time(const time_t& the_time, char* buffer)
00065 {
00066         time_t t = the_time;
00067         if (!t) time(&t);
00068         LLString::copy(buffer, ctime(&t), 30);
00069         buffer[24] = '\0';
00070         return buffer;
00071 }
00072 
00073 // static
00074 LLGroupNotifyBox* LLGroupNotifyBox::show(const char* subject,
00075                                                          const char* message,
00076                                                          const char* from_name,
00077                                                          const LLUUID& group_id,
00078                                                          const U32& t,
00079                                                          const bool& has_inventory,
00080                                                          const char* inventory_name,
00081                                                          LLOfferInfo* inventory_offer)
00082 {
00083         // Get the group data
00084         LLGroupData group_data;
00085         if (!gAgent.getGroupData(group_id,group_data))
00086         {
00087                 llwarns << "Group notice for unkown group: " << group_id << llendl;
00088                 return NULL;
00089         }
00090 
00091         LLGroupNotifyBox* self;
00092         self = new LLGroupNotifyBox(subject, message, from_name, group_id, group_data.mInsigniaID, group_data.mName.c_str(),t,has_inventory,inventory_name,inventory_offer);
00093         gNotifyBoxView->addChild(self);
00094 
00095         // TODO: play a sound
00096         return self;
00097 }
00098 
00099 bool is_openable(LLAssetType::EType type)
00100 {
00101         switch(type)
00102         {
00103         case LLAssetType::AT_LANDMARK:
00104         case LLAssetType::AT_NOTECARD:
00105         case LLAssetType::AT_IMAGE_JPEG:
00106         case LLAssetType::AT_IMAGE_TGA:
00107         case LLAssetType::AT_TEXTURE:
00108         case LLAssetType::AT_TEXTURE_TGA:
00109                 return true;
00110         default:
00111                 return false;
00112         }
00113 }
00114 
00115 LLGroupNotifyBox::LLGroupNotifyBox(const char* subject,
00116                                                          const char* message,
00117                                                          const char* from_name,
00118                                                          const LLUUID& group_id,
00119                                                          const LLUUID& group_insignia,
00120                                                          const char* group_name,
00121                                                          const U32& t,
00122                                                          const bool& has_inventory,
00123                                                          const char* inventory_name,
00124                                                          LLOfferInfo* inventory_offer)
00125 :       LLPanel("groupnotify", LLGroupNotifyBox::getGroupNotifyRect(), BORDER_YES),
00126         mAnimating(TRUE),
00127         mTimer(),
00128         mGroupID(group_id),
00129         mHasInventory(has_inventory),
00130         mInventoryOffer(inventory_offer)
00131 {
00132         mIsFocusRoot = TRUE;
00133 
00134         time_t timestamp = (time_t)t;
00135 
00136         char time_buf[30];              /*Flawfinder: ignore*/  
00137         g_formatted_time(timestamp, time_buf);
00138 
00139         setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
00140         setBackgroundVisible(TRUE);
00141         setBackgroundOpaque(TRUE);
00142 
00143         // TODO: add a color for group notices
00144         setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );
00145 
00146         LLIconCtrl* icon;
00147         LLTextEditor* text;
00148 
00149         const S32 VPAD = 2;
00150         const S32 TOP = mRect.getHeight() - 32; // Get past the top menu bar
00151         const S32 BOTTOM_PAD = VPAD * 2;
00152         const S32 BTN_TOP = BOTTOM_PAD + BTN_HEIGHT + VPAD;
00153         const S32 RIGHT = mRect.getWidth() - HPAD - HPAD;
00154         const S32 LINE_HEIGHT = 16;
00155 
00156         const S32 LABEL_WIDTH = 64;
00157         const S32 ICON_WIDTH = 64;
00158 
00159         S32 y = TOP;
00160         S32 x = HPAD + HPAD;
00161 
00162 
00163         // Title
00164         LLTextBox* line;
00165 
00166         line = new LLTextBox("title",LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),"Group Notice",LLFontGL::sSansSerifHuge);
00167         line->setHAlign(LLFontGL::RIGHT);
00168         line->setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
00169         line->setBorderVisible(FALSE);
00170         line->setColor(LLColor4::white);
00171         line->setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );
00172         
00173         addChild(line);
00174 
00175         y -= llfloor(1.5f*LINE_HEIGHT);
00176 
00177         x += HPAD + HPAD + ICON_WIDTH;
00178 
00179         std::stringstream from;
00180         from << "Sent by " << from_name << ", " << group_name;
00181 
00182         line = new LLTextBox("group",LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),from.str().c_str(),LLFontGL::sSansSerif);
00183         line->setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
00184         line->setHAlign(LLFontGL::RIGHT);
00185         line->setBorderVisible(FALSE);
00186         line->setColor(LLColor4::white);
00187         line->setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );
00188         addChild(line);
00189         
00190         y -= (LINE_HEIGHT + VPAD);
00191 
00192         LLUUID icon_id(gViewerArt.getString("notify_box_icon.tga"));
00193         // TODO: change this to be the group icon.
00194         if (!group_insignia.isNull())
00195         {
00196                 icon_id = group_insignia;
00197         }
00198 
00199         x = HPAD + HPAD;
00200 
00201         icon = new LLIconCtrl("icon",
00202                                                   LLRect(x, y, x+ICON_WIDTH, y-ICON_WIDTH),
00203                                                   icon_id);
00204         icon->setMouseOpaque(FALSE);
00205         addChild(icon);
00206 
00207         x += HPAD + HPAD + ICON_WIDTH;
00208         // If we have inventory with this message, leave room for the name.
00209         S32 box_bottom = BTN_TOP + (mHasInventory ? (LINE_HEIGHT + 2*VPAD) : 0);
00210 
00211         text = new LLViewerTextEditor("box",
00212                 LLRect(x, y, RIGHT, box_bottom),
00213                 DB_GROUP_NOTICE_MSG_STR_LEN,
00214                 "",
00215                 LLFontGL::sSansSerif,
00216                 FALSE);
00217 
00218         LLStyle headerstyle(true,LLColor4::black,"SansSerifBig");
00219         LLStyle datestyle(true,LLColor4::black,"serif");
00220 
00221         text->appendStyledText(subject,false,false,&headerstyle);
00222         text->appendStyledText(time_buf,false,false,&datestyle);
00223         // Sadly, our LLTextEditor can't handle both styled and unstyled text
00224         // at the same time.  Hence this space must be styled. JC
00225         text->appendColoredText(" ",false,false,LLColor4::grey4);
00226         text->appendColoredText(message,false,false,LLColor4::grey4);
00227 
00228         LLColor4 semi_transparent(1.0f,1.0f,1.0f,0.8f);
00229         text->setCursor(0,0);
00230         text->setEnabled(FALSE);
00231         text->setWordWrap(TRUE);
00232         text->setTakesFocus(TRUE);                      // Allow focus so text can be copied.  Since it's not enabled, it will be read-only
00233         text->setTabToNextField(TRUE);
00234         text->setMouseOpaque(TRUE);
00235         text->setBorderVisible(TRUE);
00236         text->setTakesNonScrollClicks(TRUE);
00237         text->setHideScrollbarForShortDocs(TRUE);
00238         text->setReadOnlyBgColor ( semi_transparent );
00239         text->setWriteableBgColor ( semi_transparent );
00240         
00241         addChild(text);
00242 
00243         y = box_bottom - VPAD;
00244 
00245         if (mHasInventory)
00246         {
00247                         line = new LLTextBox("subjecttitle",LLRect(x,y,x + LABEL_WIDTH,y - LINE_HEIGHT),"Attached: ",LLFontGL::sSansSerif);
00248                         line->setBorderVisible(FALSE);
00249                         line->setColor(LLColor4::white);
00250                         line->setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
00251                         line->setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );
00252                         addChild(line);
00253 
00254                         LLViewerImage* item_icon = get_item_icon(mInventoryOffer->mType,
00255                                                                                                         LLInventoryType::IT_TEXTURE,
00256                                                                                                         0, FALSE);
00257 
00258 
00259                         x += LABEL_WIDTH + HPAD;
00260 
00261                         std::stringstream ss;
00262                         ss << "        " << inventory_name;
00263                         line = new LLTextBox("object_name",LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),ss.str().c_str(),LLFontGL::sSansSerif);
00264                         line->setEnabled(FALSE);
00265                         line->setBorderVisible(TRUE);
00266                         line->setDisabledColor(LLColor4::blue4);
00267                         line->setFontStyle(LLFontGL::NORMAL);
00268                         line->setBackgroundVisible(true);
00269                         line->setBackgroundColor( semi_transparent );
00270                         addChild(line);
00271 
00272                         icon = new LLIconCtrl("icon",
00273                                                                         LLRect(x, y, x+16, y-16),
00274                                                                         item_icon->getID());
00275                         icon->setMouseOpaque(FALSE);
00276                         addChild(icon);
00277         }
00278 
00279         LLButton* btn;
00280         btn = new LLButton("next",
00281                                 LLRect(mRect.getWidth()-24, BOTTOM_PAD+16, mRect.getWidth()-8, BOTTOM_PAD),
00282                                 "notify_next.tga",
00283                                 "notify_next.tga",
00284                                 "",
00285                                 onClickNext,
00286                                 this,
00287                                 LLFontGL::sSansSerif);
00288         btn->setToolTip("Next");
00289         addChild(btn);
00290         mNextBtn = btn;
00291 
00292         S32 btn_width = 80;
00293         S32 wide_btn_width = 120;
00294         LLRect btn_rect;
00295         x = 3 * HPAD;
00296 
00297         btn_rect.setOriginAndSize(x,
00298                                                                 BOTTOM_PAD,
00299                                                                 btn_width,
00300                                                                 BTN_HEIGHT);
00301 
00302         btn = new LLButton("OK", btn_rect, "", onClickOk, this);
00303         addChild(btn, -1);
00304         setDefaultBtn(btn);
00305 
00306         x += btn_width + HPAD;
00307 
00308         
00309         btn_rect.setOriginAndSize(x,
00310                                                                 BOTTOM_PAD,
00311                                                                 wide_btn_width,
00312                                                                 BTN_HEIGHT);
00313 
00314         btn = new LLButton("Group Notices", btn_rect, "", onClickGroupInfo, this);
00315         btn->setToolTip("View past notices or opt-out of receiving these messages here.");
00316         addChild(btn, -1);
00317 
00318         if (mHasInventory && mInventoryOffer)
00319         {
00320                 x += wide_btn_width + HPAD;
00321 
00322                 btn_rect.setOriginAndSize(x,
00323                                                                         BOTTOM_PAD,
00324                                                                         wide_btn_width,
00325                                                                         BTN_HEIGHT);
00326 
00327                 LLString btn_lbl("");
00328                 if(is_openable(mInventoryOffer->mType))
00329                 {
00330                         btn_lbl = "Open Attachment";
00331                 }
00332                 else
00333                 {
00334                         btn_lbl = "Save Attachment";
00335                 }
00336                 mSaveInventoryBtn = new LLButton(btn_lbl, btn_rect, "", onClickSaveInventory, this);
00337                 mSaveInventoryBtn->setVisible(mHasInventory);
00338                 addChild(mSaveInventoryBtn);
00339         }
00340 
00341         sGroupNotifyBoxCount++;
00342 
00343         // If this is the only notify box, don't show the next button
00344         if (sGroupNotifyBoxCount == 1)
00345         {
00346                 mNextBtn->setVisible(FALSE);
00347         }
00348 }
00349 
00350 
00351 // virtual
00352 LLGroupNotifyBox::~LLGroupNotifyBox()
00353 {
00354         sGroupNotifyBoxCount--;
00355 }
00356 
00357 // virtual
00358 BOOL LLGroupNotifyBox::handleRightMouseDown(S32 x, S32 y, MASK mask)
00359 {
00360         if (getVisible() && getEnabled() && pointInView(x,y))
00361         {
00362                 moveToBack();
00363                 return TRUE;
00364         }
00365 
00366         return LLPanel::handleRightMouseDown(x, y, mask);
00367 }
00368 
00369 
00370 // virtual
00371 void LLGroupNotifyBox::draw()
00372 {
00373         F32 display_time = mTimer.getElapsedTimeF32();
00374 
00375         if (mAnimating && display_time < ANIMATION_TIME)
00376         {
00377                 glMatrixMode(GL_MODELVIEW);
00378                 glPushMatrix();
00379 
00380                 S32 height = mRect.getHeight();
00381                 F32 fraction = display_time / ANIMATION_TIME;
00382                 F32 voffset = (1.f - fraction) * height;
00383 
00384                 glTranslatef(0.f, voffset, 0.f);
00385 
00386                 LLPanel::draw();
00387 
00388                 glPopMatrix();
00389         }
00390         else
00391         {
00392                 mAnimating = FALSE;
00393                 LLPanel::draw();
00394         }
00395 }
00396 
00397 
00398 void LLGroupNotifyBox::close()
00399 {
00400         // The group notice dialog may be an inventory offer.
00401         // If it has an inventory save button and that button is still enabled
00402         // Then we need to send the inventory declined message
00403         if(mHasInventory)
00404         {
00405                 inventory_offer_callback(IOR_DECLINE , mInventoryOffer); 
00406         }
00407         gNotifyBoxView->removeChild(this);
00408 
00409         die();
00410 }
00411 
00412 
00413 void LLGroupNotifyBox::moveToBack()
00414 {
00415         // Move this dialog to the back.
00416         gNotifyBoxView->removeChild(this);
00417         gNotifyBoxView->addChildAtEnd(this);
00418         mNextBtn->setVisible(FALSE);
00419 
00420         // And enable the next button on the frontmost one, if there is one
00421         if (sGroupNotifyBoxCount > 1)
00422         {
00423                 LLView* view = gNotifyBoxView->getFirstChild();
00424                 LLGroupNotifyBox* front = (LLGroupNotifyBox*)view;
00425                 front->mNextBtn->setVisible(TRUE);
00426         }
00427 }
00428 
00429 
00430 // static
00431 LLRect LLGroupNotifyBox::getGroupNotifyRect()
00432 {
00433         S32 notify_height = gSavedSettings.getS32("GroupNotifyBoxHeight");
00434         const S32 NOTIFY_WIDTH = gSavedSettings.getS32("GroupNotifyBoxWidth");
00435 
00436         const S32 TOP = gNotifyBoxView->getRect().getHeight();
00437         const S32 RIGHT = gNotifyBoxView->getRect().getWidth();
00438         const S32 LEFT = RIGHT - NOTIFY_WIDTH;
00439 
00440         return LLRect(LEFT, TOP, RIGHT, TOP-notify_height);
00441 }
00442 
00443 
00444 // static
00445 void LLGroupNotifyBox::onClickOk(void* data)
00446 {
00447         LLGroupNotifyBox* self = (LLGroupNotifyBox*)data;
00448         if (self) self->close();
00449 }
00450 
00451 void LLGroupNotifyBox::onClickGroupInfo(void* data)
00452 {
00453         LLGroupNotifyBox* self = (LLGroupNotifyBox*)data;
00454 
00455         if (self)
00456         {
00457                 LLFloaterGroupInfo::showFromUUID(self->mGroupID, "notices_tab");
00458         }
00459 
00460         //Leave notice open until explicitly closed
00461 }
00462 
00463 void LLGroupNotifyBox::onClickSaveInventory(void* data)
00464 {
00465         LLGroupNotifyBox* self = (LLGroupNotifyBox*)data;
00466 
00467         inventory_offer_callback( IOR_ACCEPT , self->mInventoryOffer); 
00468 
00469         // inventory_offer_callback will delete the offer, so make sure we aren't still pointing to it.
00470         self->mInventoryOffer = NULL;
00471         // Each item can only be received once, so disable the button.
00472         self->mSaveInventoryBtn->setEnabled(FALSE);
00473 }
00474 
00475 // static
00476 void LLGroupNotifyBox::onClickNext(void* data)
00477 {
00478         LLGroupNotifyBox* self = (LLGroupNotifyBox*)data;
00479         self->moveToBack();
00480 }

Generated on Thu Jul 1 06:08:41 2010 for Second Life Viewer by  doxygen 1.4.7