llsyswellwindow.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:27k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llsyswellwindow.cpp
  3.  * @brief                                    // TODO
  4.  * $LicenseInfo:firstyear=2000&license=viewergpl$
  5.  * 
  6.  * Copyright (c) 2000-2010, Linden Research, Inc.
  7.  * 
  8.  * Second Life Viewer Source Code
  9.  * The source code in this file ("Source Code") is provided by Linden Lab
  10.  * to you under the terms of the GNU General Public License, version 2.0
  11.  * ("GPL"), unless you have obtained a separate licensing agreement
  12.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  13.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15.  * 
  16.  * There are special exceptions to the terms and conditions of the GPL as
  17.  * it is applied to this Source Code. View the full text of the exception
  18.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  19.  * online at
  20.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21.  * 
  22.  * By copying, modifying or distributing this software, you acknowledge
  23.  * that you have read and understood your obligations described above,
  24.  * and agree to abide by those obligations.
  25.  * 
  26.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28.  * COMPLETENESS OR PERFORMANCE.
  29.  * $/LicenseInfo$
  30.  */
  31. #include "llviewerprecompiledheaders.h" // must be first include
  32. #include "llagent.h"
  33. #include "llflatlistview.h"
  34. #include "llfloaterreg.h"
  35. #include "llnotifications.h"
  36. #include "llsyswellwindow.h"
  37. #include "llbottomtray.h"
  38. #include "llscriptfloater.h"
  39. #include "llviewercontrol.h"
  40. #include "llviewerwindow.h"
  41. #include "llchiclet.h"
  42. #include "lltoastpanel.h"
  43. #include "llnotificationmanager.h"
  44. #include "llnotificationsutil.h"
  45. #include "llspeakers.h"
  46. //---------------------------------------------------------------------------------
  47. LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLTransientDockableFloater(NULL, true,  key),
  48. mChannel(NULL),
  49. mMessageList(NULL),
  50. mSysWellChiclet(NULL),
  51. mSeparator(NULL),
  52. NOTIFICATION_WELL_ANCHOR_NAME("notification_well_panel"),
  53. IM_WELL_ANCHOR_NAME("im_well_panel")
  54. {
  55. mTypedItemsCount[IT_NOTIFICATION] = 0;
  56. mTypedItemsCount[IT_INSTANT_MESSAGE] = 0;
  57. setOverlapsScreenChannel(true);
  58. }
  59. //---------------------------------------------------------------------------------
  60. BOOL LLSysWellWindow::postBuild()
  61. {
  62. mMessageList = getChild<LLFlatListView>("notification_list");
  63. // get a corresponding channel
  64. initChannel();
  65. LLPanel::Params params;
  66. mSeparator = LLUICtrlFactory::create<LLPanel>(params);
  67. LLUICtrlFactory::instance().buildPanel(mSeparator, "panel_separator.xml");
  68. LLRect rc = mSeparator->getRect();
  69. rc.setOriginAndSize(0, 0, mMessageList->getItemsRect().getWidth(), rc.getHeight());
  70. mSeparator->setRect(rc);
  71. mSeparator->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP);
  72. mSeparator->setVisible(FALSE);
  73. mMessageList->addItem(mSeparator);
  74. // click on SysWell Window should clear "new message" state (and 'Lit' status). EXT-3147.
  75. // mouse up callback is not called in this case.
  76. setMouseDownCallback(boost::bind(&LLSysWellWindow::releaseNewMessagesState, this));
  77. return LLTransientDockableFloater::postBuild();
  78. }
  79. //---------------------------------------------------------------------------------
  80. void LLSysWellWindow::setMinimized(BOOL minimize)
  81. {
  82. LLTransientDockableFloater::setMinimized(minimize);
  83. }
  84. //---------------------------------------------------------------------------------
  85. void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask)
  86. {
  87. // just set floater visible. Screen channels will be cleared.
  88. setVisible(TRUE);
  89. }
  90. void LLSysWellWindow::setSysWellChiclet(LLSysWellChiclet* chiclet) 
  91. mSysWellChiclet = chiclet;
  92. if(mSysWellChiclet)
  93. mSysWellChiclet->updateWidget(isWindowEmpty()); 
  94. }
  95. //---------------------------------------------------------------------------------
  96. LLSysWellWindow::~LLSysWellWindow()
  97. {
  98. }
  99. //---------------------------------------------------------------------------------
  100. void LLSysWellWindow::removeItemByID(const LLUUID& id)
  101. {
  102. if(mMessageList->removeItemByValue(id))
  103. {
  104. handleItemRemoved(IT_NOTIFICATION);
  105. reshapeWindow();
  106. }
  107. else
  108. {
  109. llwarns << "Unable to remove notification from the list, ID: " << id
  110. << llendl;
  111. }
  112. // hide chiclet window if there are no items left
  113. if(isWindowEmpty())
  114. {
  115. setVisible(FALSE);
  116. }
  117. }
  118. //---------------------------------------------------------------------------------
  119. //---------------------------------------------------------------------------------
  120. void LLSysWellWindow::initChannel() 
  121. {
  122. LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(
  123. LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
  124. mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel);
  125. if(NULL == mChannel)
  126. {
  127. llwarns << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << llendl;
  128. }
  129. }
  130. //---------------------------------------------------------------------------------
  131. void LLSysWellWindow::getAllowedRect(LLRect& rect)
  132. {
  133. rect = gViewerWindow->getWorldViewRectScaled();
  134. }
  135. //---------------------------------------------------------------------------------
  136. //---------------------------------------------------------------------------------
  137. void LLSysWellWindow::setVisible(BOOL visible)
  138. {
  139. if (visible)
  140. {
  141. if (NULL == getDockControl() && getDockTongue().notNull())
  142. {
  143. setDockControl(new LLDockControl(
  144. LLBottomTray::getInstance()->getChild<LLView>(getAnchorViewName()), this,
  145. getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1)));
  146. }
  147. }
  148. // do not show empty window
  149. if (NULL == mMessageList || isWindowEmpty()) visible = FALSE;
  150. LLTransientDockableFloater::setVisible(visible);
  151. // update notification channel state
  152. if(mChannel)
  153. {
  154. mChannel->updateShowToastsState();
  155. mChannel->redrawToasts();
  156. }
  157. if (visible)
  158. {
  159. releaseNewMessagesState();
  160. }
  161. }
  162. //---------------------------------------------------------------------------------
  163. void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock)
  164. {
  165. LLTransientDockableFloater::setDocked(docked, pop_on_undock);
  166. // update notification channel state
  167. if(mChannel)
  168. {
  169. mChannel->updateShowToastsState();
  170. mChannel->redrawToasts();
  171. }
  172. }
  173. //---------------------------------------------------------------------------------
  174. void LLSysWellWindow::reshapeWindow()
  175. {
  176. // save difference between floater height and the list height to take it into account while calculating new window height
  177. // it includes height from floater top to list top and from floater bottom and list bottom
  178. static S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight();
  179. S32 notif_list_height = mMessageList->getItemsRect().getHeight() + 2 * mMessageList->getBorderWidth();
  180. LLRect curRect = getRect();
  181. S32 new_window_height = notif_list_height + parent_list_delta_height;
  182. if (new_window_height > MAX_WINDOW_HEIGHT)
  183. {
  184. new_window_height = MAX_WINDOW_HEIGHT;
  185. }
  186. S32 newY = curRect.mTop + new_window_height - curRect.getHeight();
  187. S32 newWidth = curRect.getWidth() < MIN_WINDOW_WIDTH ? MIN_WINDOW_WIDTH
  188. : curRect.getWidth();
  189. curRect.setLeftTopAndSize(curRect.mLeft, newY, newWidth, new_window_height);
  190. reshape(curRect.getWidth(), curRect.getHeight(), TRUE);
  191. setRect(curRect);
  192. // update notification channel state
  193. // update on a window reshape is important only when a window is visible and docked
  194. if(mChannel && getVisible() && isDocked())
  195. {
  196. mChannel->updateShowToastsState();
  197. }
  198. }
  199. void LLSysWellWindow::releaseNewMessagesState()
  200. {
  201. if (NULL != mSysWellChiclet)
  202. {
  203. mSysWellChiclet->setNewMessagesState(false);
  204. }
  205. }
  206. //---------------------------------------------------------------------------------
  207. bool LLSysWellWindow::isWindowEmpty()
  208. {
  209. // keep in mind, mSeparator is always in the list
  210. return mMessageList->size() == 1;
  211. }
  212. // *TODO: mantipov: probably is deprecated
  213. void LLSysWellWindow::handleItemAdded(EItemType added_item_type)
  214. {
  215. bool should_be_shown = ++mTypedItemsCount[added_item_type] == 1 && anotherTypeExists(added_item_type);
  216. if (should_be_shown && !mSeparator->getVisible())
  217. {
  218. mSeparator->setVisible(TRUE);
  219. // refresh list to recalculate mSeparator position
  220. mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight());
  221. }
  222. //fix for EXT-3254
  223. //set limits for min_height. 
  224. S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight();
  225. std::vector<LLPanel*> items;
  226. mMessageList->getItems(items);
  227. if(items.size()>1)//first item is separator
  228. {
  229. S32 min_height;
  230. S32 min_width;
  231. getResizeLimits(&min_width,&min_height);
  232. min_height = items[1]->getRect().getHeight() + 2 * mMessageList->getBorderWidth() + parent_list_delta_height;
  233. setResizeLimits(min_width,min_height);
  234. }
  235. mSysWellChiclet->updateWidget(isWindowEmpty());
  236. }
  237. void LLSysWellWindow::handleItemRemoved(EItemType removed_item_type)
  238. {
  239. bool should_be_hidden = --mTypedItemsCount[removed_item_type] == 0;
  240. if (should_be_hidden && mSeparator->getVisible())
  241. {
  242. mSeparator->setVisible(FALSE);
  243. // refresh list to recalculate mSeparator position
  244. mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight());
  245. }
  246. mSysWellChiclet->updateWidget(isWindowEmpty());
  247. }
  248. bool LLSysWellWindow::anotherTypeExists(EItemType item_type)
  249. {
  250. bool exists = false;
  251. switch(item_type)
  252. {
  253. case IT_INSTANT_MESSAGE:
  254. if (mTypedItemsCount[IT_NOTIFICATION] > 0)
  255. {
  256. exists = true;
  257. }
  258. break;
  259. case IT_NOTIFICATION:
  260. if (mTypedItemsCount[IT_INSTANT_MESSAGE] > 0)
  261. {
  262. exists = true;
  263. }
  264. break;
  265. }
  266. return exists;
  267. }
  268. /************************************************************************/
  269. /*         RowPanel implementation                                      */
  270. /************************************************************************/
  271. //---------------------------------------------------------------------------------
  272. LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId,
  273. S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) :
  274. LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent)
  275. {
  276. LLUICtrlFactory::getInstance()->buildPanel(this, "panel_activeim_row.xml", NULL);
  277. // Choose which of the pre-created chiclets (IM/group) to use.
  278. // The other one gets hidden.
  279. LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId);
  280. switch (im_chiclet_type)
  281. {
  282. case LLIMChiclet::TYPE_GROUP:
  283. mChiclet = getChild<LLIMGroupChiclet>("group_chiclet");
  284. break;
  285. case LLIMChiclet::TYPE_AD_HOC:
  286. mChiclet = getChild<LLAdHocChiclet>("adhoc_chiclet");
  287. break;
  288. case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway
  289. case LLIMChiclet::TYPE_IM:
  290. mChiclet = getChild<LLIMP2PChiclet>("p2p_chiclet");
  291. break;
  292. }
  293. // Initialize chiclet.
  294. mChiclet->setChicletSizeChangedCallback(boost::bind(&LLIMWellWindow::RowPanel::onChicletSizeChanged, this, mChiclet, _2));
  295. mChiclet->enableCounterControl(true);
  296. mChiclet->setCounter(chicletCounter);
  297. mChiclet->setSessionId(sessionId);
  298. mChiclet->setIMSessionName(name);
  299. mChiclet->setOtherParticipantId(otherParticipantId);
  300. mChiclet->setVisible(true);
  301. LLTextBox* contactName = getChild<LLTextBox>("contact_name");
  302. contactName->setValue(name);
  303. mCloseBtn = getChild<LLButton>("hide_btn");
  304. mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::RowPanel::onClosePanel, this));
  305. }
  306. //---------------------------------------------------------------------------------
  307. void LLIMWellWindow::RowPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
  308. {
  309. LLTextBox* text = getChild<LLTextBox>("contact_name");
  310. S32 new_text_left = mChiclet->getRect().mRight + CHICLET_HPAD;
  311. LLRect text_rect = text->getRect(); 
  312. text_rect.mLeft = new_text_left;
  313. text->setRect(text_rect);
  314. }
  315. //---------------------------------------------------------------------------------
  316. LLIMWellWindow::RowPanel::~RowPanel()
  317. {
  318. }
  319. //---------------------------------------------------------------------------------
  320. void LLIMWellWindow::RowPanel::onClosePanel()
  321. {
  322. gIMMgr->leaveSession(mChiclet->getSessionId());
  323. // This row panel will be removed from the list in LLSysWellWindow::sessionRemoved().
  324. }
  325. //---------------------------------------------------------------------------------
  326. void LLIMWellWindow::RowPanel::onMouseEnter(S32 x, S32 y, MASK mask)
  327. {
  328. setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected"));
  329. }
  330. //---------------------------------------------------------------------------------
  331. void LLIMWellWindow::RowPanel::onMouseLeave(S32 x, S32 y, MASK mask)
  332. {
  333. setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected"));
  334. }
  335. //---------------------------------------------------------------------------------
  336. // virtual
  337. BOOL LLIMWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask)
  338. {
  339. // Pass the mouse down event to the chiclet (EXT-596).
  340. if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown()
  341. {
  342. mChiclet->onMouseDown();
  343. return TRUE;
  344. }
  345. return LLPanel::handleMouseDown(x, y, mask);
  346. }
  347. // virtual
  348. BOOL LLIMWellWindow::RowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)
  349. {
  350. return mChiclet->handleRightMouseDown(x, y, mask);
  351. }
  352. /************************************************************************/
  353. /*         ObjectRowPanel implementation                                */
  354. /************************************************************************/
  355. LLIMWellWindow::ObjectRowPanel::ObjectRowPanel(const LLUUID& notification_id, bool new_message/* = false*/)
  356.  : LLPanel()
  357.  , mChiclet(NULL)
  358. {
  359. LLUICtrlFactory::getInstance()->buildPanel(this, "panel_active_object_row.xml", NULL);
  360. initChiclet(notification_id);
  361. LLTextBox* obj_name = getChild<LLTextBox>("object_name");
  362. obj_name->setValue(LLScriptFloaterManager::getObjectName(notification_id));
  363. mCloseBtn = getChild<LLButton>("hide_btn");
  364. mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::ObjectRowPanel::onClosePanel, this));
  365. }
  366. //---------------------------------------------------------------------------------
  367. LLIMWellWindow::ObjectRowPanel::~ObjectRowPanel()
  368. {
  369. }
  370. //---------------------------------------------------------------------------------
  371. void LLIMWellWindow::ObjectRowPanel::onClosePanel()
  372. {
  373. LLScriptFloaterManager::getInstance()->onRemoveNotification(mChiclet->getSessionId());
  374. }
  375. void LLIMWellWindow::ObjectRowPanel::initChiclet(const LLUUID& notification_id, bool new_message/* = false*/)
  376. {
  377. // Choose which of the pre-created chiclets to use.
  378. switch(LLScriptFloaterManager::getObjectType(notification_id))
  379. {
  380. case LLScriptFloaterManager::OBJ_GIVE_INVENTORY:
  381. mChiclet = getChild<LLInvOfferChiclet>("inv_offer_chiclet");
  382. break;
  383. default:
  384. mChiclet = getChild<LLScriptChiclet>("object_chiclet");
  385. break;
  386. }
  387. mChiclet->setVisible(true);
  388. mChiclet->setSessionId(notification_id);
  389. }
  390. //---------------------------------------------------------------------------------
  391. void LLIMWellWindow::ObjectRowPanel::onMouseEnter(S32 x, S32 y, MASK mask)
  392. {
  393. setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemSelected"));
  394. }
  395. //---------------------------------------------------------------------------------
  396. void LLIMWellWindow::ObjectRowPanel::onMouseLeave(S32 x, S32 y, MASK mask)
  397. {
  398. setTransparentColor(LLUIColorTable::instance().getColor("SysWellItemUnselected"));
  399. }
  400. //---------------------------------------------------------------------------------
  401. // virtual
  402. BOOL LLIMWellWindow::ObjectRowPanel::handleMouseDown(S32 x, S32 y, MASK mask)
  403. {
  404. // Pass the mouse down event to the chiclet (EXT-596).
  405. if (!mChiclet->pointInView(x, y) && !mCloseBtn->getRect().pointInRect(x, y)) // prevent double call of LLIMChiclet::onMouseDown()
  406. {
  407. mChiclet->onMouseDown();
  408. return TRUE;
  409. }
  410. return LLPanel::handleMouseDown(x, y, mask);
  411. }
  412. // virtual
  413. BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)
  414. {
  415. return mChiclet->handleRightMouseDown(x, y, mask);
  416. }
  417. /************************************************************************/
  418. /*         LLNotificationWellWindow implementation                      */
  419. /************************************************************************/
  420. //////////////////////////////////////////////////////////////////////////
  421. // PUBLIC METHODS
  422. LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key)
  423. : LLSysWellWindow(key)
  424. {
  425. // init connections to the list's update events
  426. connectListUpdaterToSignal("notify");
  427. connectListUpdaterToSignal("groupnotify");
  428. connectListUpdaterToSignal("offer");
  429. }
  430. // static
  431. LLNotificationWellWindow* LLNotificationWellWindow::getInstance(const LLSD& key /*= LLSD()*/)
  432. {
  433. return LLFloaterReg::getTypedInstance<LLNotificationWellWindow>("notification_well_window", key);
  434. }
  435. // virtual
  436. BOOL LLNotificationWellWindow::postBuild()
  437. {
  438. BOOL rv = LLSysWellWindow::postBuild();
  439. setTitle(getString("title_notification_well_window"));
  440. return rv;
  441. }
  442. // virtual
  443. void LLNotificationWellWindow::setVisible(BOOL visible)
  444. {
  445. if (visible)
  446. {
  447. // when Notification channel is cleared, storable toasts will be added into the list.
  448. clearScreenChannels();
  449. }
  450. LLSysWellWindow::setVisible(visible);
  451. }
  452. //---------------------------------------------------------------------------------
  453. void LLNotificationWellWindow::addItem(LLSysWellItem::Params p)
  454. {
  455. LLSD value = p.notification_id;
  456. // do not add clones
  457. if( mMessageList->getItemByValue(value))
  458. return;
  459. LLSysWellItem* new_item = new LLSysWellItem(p);
  460. if (mMessageList->addItem(new_item, value, ADD_TOP))
  461. {
  462. handleItemAdded(IT_NOTIFICATION);
  463. reshapeWindow();
  464. new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1));
  465. new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1));
  466. }
  467. else
  468. {
  469. llwarns << "Unable to add Notification into the list, notification ID: " << p.notification_id
  470. << ", title: " << p.title
  471. << llendl;
  472. new_item->die();
  473. }
  474. }
  475. void LLNotificationWellWindow::closeAll()
  476. {
  477. // Need to clear notification channel, to add storable toasts into the list.
  478. clearScreenChannels();
  479. std::vector<LLPanel*> items;
  480. mMessageList->getItems(items);
  481. for (std::vector<LLPanel*>::iterator
  482.  iter = items.begin(),
  483.  iter_end = items.end();
  484.  iter != iter_end; ++iter)
  485. {
  486. LLSysWellItem* sys_well_item = dynamic_cast<LLSysWellItem*>(*iter);
  487. if (sys_well_item)
  488. onItemClose(sys_well_item);
  489. }
  490. }
  491. //////////////////////////////////////////////////////////////////////////
  492. // PRIVATE METHODS
  493. void LLNotificationWellWindow::initChannel() 
  494. {
  495. LLSysWellWindow::initChannel();
  496. if(mChannel)
  497. {
  498. mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2));
  499. }
  500. }
  501. void LLNotificationWellWindow::clearScreenChannels()
  502. {
  503. // 1 - remove StartUp toast and channel if present
  504. if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown())
  505. {
  506. LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose();
  507. }
  508. // 2 - remove toasts in Notification channel
  509. if(mChannel)
  510. {
  511. mChannel->removeAndStoreAllStorableToasts();
  512. }
  513. }
  514. void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id)
  515. {
  516. LLSysWellItem::Params p;
  517. p.notification_id = id;
  518. p.title = static_cast<LLToastPanel*>(info_panel)->getTitle();
  519. addItem(p);
  520. }
  521. void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type)
  522. {
  523. LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance();
  524. LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type);
  525. if(n_handler)
  526. {
  527. n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1));
  528. }
  529. else
  530. {
  531. llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl;
  532. }
  533. }
  534. void LLNotificationWellWindow::onItemClick(LLSysWellItem* item)
  535. {
  536. LLUUID id = item->getID();
  537. LLFloaterReg::showInstance("inspect_toast", id);
  538. }
  539. void LLNotificationWellWindow::onItemClose(LLSysWellItem* item)
  540. {
  541. LLUUID id = item->getID();
  542. removeItemByID(id);
  543. if(mChannel)
  544. mChannel->killToastByNotificationID(id);
  545. }
  546. /************************************************************************/
  547. /*         LLIMWellWindow  implementation                               */
  548. /************************************************************************/
  549. //////////////////////////////////////////////////////////////////////////
  550. // PUBLIC METHODS
  551. LLIMWellWindow::LLIMWellWindow(const LLSD& key)
  552. : LLSysWellWindow(key)
  553. {
  554. LLIMMgr::getInstance()->addSessionObserver(this);
  555. LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findIMChiclet, this, _1));
  556. LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLIMWellWindow::findObjectChiclet, this, _1));
  557. }
  558. LLIMWellWindow::~LLIMWellWindow()
  559. {
  560. LLIMMgr::getInstance()->removeSessionObserver(this);
  561. }
  562. // static
  563. LLIMWellWindow* LLIMWellWindow::getInstance(const LLSD& key /*= LLSD()*/)
  564. {
  565. return LLFloaterReg::getTypedInstance<LLIMWellWindow>("im_well_window", key);
  566. }
  567. BOOL LLIMWellWindow::postBuild()
  568. {
  569. BOOL rv = LLSysWellWindow::postBuild();
  570. setTitle(getString("title_im_well_window"));
  571. return rv;
  572. }
  573. //virtual
  574. void LLIMWellWindow::sessionAdded(const LLUUID& session_id,
  575.    const std::string& name, const LLUUID& other_participant_id)
  576. {
  577. LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
  578. if (!session) return;
  579. // no need to spawn chiclets for participants in P2P calls called through Avaline
  580. if (session->isP2P() && session->isOtherParticipantAvaline()) return;
  581. if (mMessageList->getItemByValue(session_id)) return;
  582. addIMRow(session_id, 0, name, other_participant_id);
  583. reshapeWindow();
  584. }
  585. //virtual
  586. void LLIMWellWindow::sessionRemoved(const LLUUID& sessionId)
  587. {
  588. delIMRow(sessionId);
  589. reshapeWindow();
  590. }
  591. //virtual
  592. void LLIMWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
  593. {
  594. //for outgoing ad-hoc and group im sessions only
  595. LLChiclet* chiclet = findIMChiclet(old_session_id);
  596. if (chiclet)
  597. {
  598. chiclet->setSessionId(new_session_id);
  599. mMessageList->updateValue(old_session_id, new_session_id);
  600. }
  601. }
  602. LLChiclet* LLIMWellWindow::findObjectChiclet(const LLUUID& notification_id)
  603. {
  604. LLChiclet* res = NULL;
  605. ObjectRowPanel* panel = mMessageList->getTypedItemByValue<ObjectRowPanel>(notification_id);
  606. if (panel != NULL)
  607. {
  608. res = panel->mChiclet;
  609. }
  610. return res;
  611. }
  612. //////////////////////////////////////////////////////////////////////////
  613. // PRIVATE METHODS
  614. LLChiclet* LLIMWellWindow::findIMChiclet(const LLUUID& sessionId)
  615. {
  616. LLChiclet* res = NULL;
  617. RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId);
  618. if (panel != NULL)
  619. {
  620. res = panel->mChiclet;
  621. }
  622. return res;
  623. }
  624. //---------------------------------------------------------------------------------
  625. void LLIMWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,
  626.    const std::string& name, const LLUUID& otherParticipantId)
  627. {
  628. RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId);
  629. if (mMessageList->insertItemAfter(mSeparator, item, sessionId))
  630. {
  631. handleItemAdded(IT_INSTANT_MESSAGE);
  632. }
  633. else
  634. {
  635. llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId
  636. << ", name: " << name
  637. << ", other participant ID: " << otherParticipantId
  638. << llendl;
  639. item->die();
  640. }
  641. }
  642. //---------------------------------------------------------------------------------
  643. void LLIMWellWindow::delIMRow(const LLUUID& sessionId)
  644. {
  645. //fix for EXT-3252
  646. //without this line LLIMWellWindow receive onFocusLost
  647. //and hide itself. It was becaue somehow LLIMChicklet was in focus group for
  648. //LLIMWellWindow...
  649. //But I didn't find why this happen..
  650. gFocusMgr.clearLastFocusForGroup(this);
  651. if (mMessageList->removeItemByValue(sessionId))
  652. {
  653. handleItemRemoved(IT_INSTANT_MESSAGE);
  654. }
  655. else
  656. {
  657. llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId
  658. << llendl;
  659. }
  660. // remove all toasts that belong to this session from a screen
  661. if(mChannel)
  662. mChannel->removeToastsBySessionID(sessionId);
  663. // hide chiclet window if there are no items left
  664. if(isWindowEmpty())
  665. {
  666. setVisible(FALSE);
  667. }
  668. else
  669. {
  670. setFocus(true);
  671. }
  672. }
  673. void LLIMWellWindow::addObjectRow(const LLUUID& notification_id, bool new_message/* = false*/)
  674. {
  675. if (mMessageList->getItemByValue(notification_id) == NULL)
  676. {
  677. ObjectRowPanel* item = new ObjectRowPanel(notification_id, new_message);
  678. if (mMessageList->insertItemAfter(mSeparator, item, notification_id))
  679. {
  680. handleItemAdded(IT_INSTANT_MESSAGE);
  681. }
  682. else
  683. {
  684. llwarns << "Unable to add Object Row into the list, notificationID: " << notification_id << llendl;
  685. item->die();
  686. }
  687. reshapeWindow();
  688. }
  689. }
  690. void LLIMWellWindow::removeObjectRow(const LLUUID& notification_id)
  691. {
  692. if (mMessageList->removeItemByValue(notification_id))
  693. {
  694. handleItemRemoved(IT_INSTANT_MESSAGE);
  695. }
  696. else
  697. {
  698. llwarns << "Unable to remove Object Row from the list, notificationID: " << notification_id << llendl;
  699. }
  700. reshapeWindow();
  701. // hide chiclet window if there are no items left
  702. if(isWindowEmpty())
  703. {
  704. setVisible(FALSE);
  705. }
  706. }
  707. void LLIMWellWindow::addIMRow(const LLUUID& session_id)
  708. {
  709. if (hasIMRow(session_id)) return;
  710. LLIMModel* im_model = LLIMModel::getInstance();
  711. addIMRow(session_id, 0, im_model->getName(session_id), im_model->getOtherParticipantID(session_id));
  712. reshapeWindow();
  713. }
  714. bool LLIMWellWindow::hasIMRow(const LLUUID& session_id)
  715. {
  716. return mMessageList->getItemByValue(session_id);
  717. }
  718. void LLIMWellWindow::closeAll()
  719. {
  720. // Generate an ignorable alert dialog if there is an active voice IM sesion
  721. bool need_confirmation = false;
  722. const LLIMModel& im_model = LLIMModel::instance();
  723. std::vector<LLSD> values;
  724. mMessageList->getValues(values);
  725. for (std::vector<LLSD>::iterator
  726.  iter = values.begin(),
  727.  iter_end = values.end();
  728.  iter != iter_end; ++iter)
  729. {
  730. LLIMSpeakerMgr* speaker_mgr =  im_model.getSpeakerManager(*iter);
  731. if (speaker_mgr && speaker_mgr->isVoiceActive())
  732. {
  733. need_confirmation = true;
  734. break;
  735. }
  736. }
  737. if ( need_confirmation )
  738. {
  739. //Bring up a confirmation dialog
  740. LLNotificationsUtil::add
  741. ("ConfirmCloseAll", LLSD(), LLSD(),
  742.  boost::bind(&LLIMWellWindow::confirmCloseAll, this, _1, _2));
  743. }
  744. else
  745. {
  746. closeAllImpl();
  747. }
  748. }
  749. void LLIMWellWindow::closeAllImpl()
  750. {
  751. std::vector<LLSD> values;
  752. mMessageList->getValues(values);
  753. for (std::vector<LLSD>::iterator
  754.  iter = values.begin(),
  755.  iter_end = values.end();
  756.  iter != iter_end; ++iter)
  757. {
  758. LLPanel* panel = mMessageList->getItemByValue(*iter);
  759. RowPanel* im_panel = dynamic_cast <RowPanel*> (panel);
  760. if (im_panel)
  761. {
  762. gIMMgr->leaveSession(*iter);
  763. continue;
  764. }
  765. ObjectRowPanel* obj_panel = dynamic_cast <ObjectRowPanel*> (panel);
  766. if (obj_panel)
  767. {
  768. LLScriptFloaterManager::instance().onRemoveNotification(*iter);
  769. }
  770. }
  771. }
  772. bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& response)
  773. {
  774. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  775. switch(option)
  776. {
  777. case 0:
  778. {
  779. closeAllImpl();
  780. return  true;
  781. }
  782. default:
  783. break;
  784. }
  785. return false;
  786. }
  787. // EOF