/indra/newview/llsyswellwindow.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 870 lines · 621 code · 126 blank · 123 comment · 74 complexity · d167e1e922ba7d976e9e9faaa4aa2a07 MD5 · raw file

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