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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llchiclet.cpp
  3.  * @brief LLChiclet class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h" // must be first include
  33. #include "llchiclet.h"
  34. #include "llagent.h"
  35. #include "llavataractions.h"
  36. #include "llbottomtray.h"
  37. #include "lleventtimer.h"
  38. #include "llgroupactions.h"
  39. #include "lliconctrl.h"
  40. #include "llimfloater.h"
  41. #include "llimview.h"
  42. #include "llfloaterreg.h"
  43. #include "lllocalcliprect.h"
  44. #include "llmenugl.h"
  45. #include "llnotifications.h"
  46. #include "llnotificationsutil.h"
  47. #include "lloutputmonitorctrl.h"
  48. #include "llscriptfloater.h"
  49. #include "llspeakers.h"
  50. #include "lltextbox.h"
  51. #include "llvoiceclient.h"
  52. #include "llgroupmgr.h"
  53. #include "llnotificationmanager.h"
  54. #include "lltransientfloatermgr.h"
  55. #include "llsyswellwindow.h"
  56. static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
  57. static LLDefaultChildRegistry::Register<LLIMWellChiclet> t2_0("chiclet_im_well");
  58. static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");
  59. static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p");
  60. static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group");
  61. static LLDefaultChildRegistry::Register<LLAdHocChiclet> t5("chiclet_im_adhoc");
  62. static LLDefaultChildRegistry::Register<LLScriptChiclet> t6("chiclet_script");
  63. static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer");
  64. boost::signals2::signal<LLChiclet* (const LLUUID&),
  65. LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > >
  66. LLIMChiclet::sFindChicletsSignal;
  67. //////////////////////////////////////////////////////////////////////////
  68. //////////////////////////////////////////////////////////////////////////
  69. //////////////////////////////////////////////////////////////////////////
  70. /**
  71.  * Updates the Well's 'Lit' state to flash it when "new messages" are come.
  72.  *
  73.  * It gets callback which will be called 2*N times with passed period. See EXT-3147
  74.  */
  75. class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer
  76. {
  77. public:
  78. typedef boost::function<void()> callback_t;
  79. /**
  80.  * Constructor.
  81.  *
  82.  * @param count - how many times callback should be called (twice to not change original state)
  83.  * @param period - how frequently callback should be called
  84.  * @param cb - callback to be called each tick
  85.  */
  86. FlashToLitTimer(S32 count, F32 period, callback_t cb)
  87. : LLEventTimer(period)
  88. , mCallback(cb)
  89. , mFlashCount(2 * count)
  90. , mCurrentFlashCount(0)
  91. {
  92. mEventTimer.stop();
  93. }
  94. BOOL tick()
  95. {
  96. mCallback();
  97. if (++mCurrentFlashCount == mFlashCount) mEventTimer.stop();
  98. return FALSE;
  99. }
  100. void flash()
  101. {
  102. mCurrentFlashCount = 0;
  103. mEventTimer.start();
  104. }
  105. void stopFlashing()
  106. {
  107. mEventTimer.stop();
  108. }
  109. private:
  110. callback_t mCallback;
  111. /**
  112.  * How many times Well will blink.
  113.  */
  114. S32 mFlashCount;
  115. S32 mCurrentFlashCount;
  116. };
  117. LLSysWellChiclet::Params::Params()
  118. : button("button")
  119. , unread_notifications("unread_notifications")
  120. , max_displayed_count("max_displayed_count", 99)
  121. , flash_to_lit_count("flash_to_lit_count", 3)
  122. , flash_period("flash_period", 0.5F)
  123. {
  124. button.name("button");
  125. button.tab_stop(FALSE);
  126. button.label(LLStringUtil::null);
  127. }
  128. LLSysWellChiclet::LLSysWellChiclet(const Params& p)
  129. : LLChiclet(p)
  130. , mButton(NULL)
  131. , mCounter(0)
  132. , mMaxDisplayedCount(p.max_displayed_count)
  133. , mIsNewMessagesState(false)
  134. , mFlashToLitTimer(NULL)
  135. , mContextMenu(NULL)
  136. {
  137. LLButton::Params button_params = p.button;
  138. mButton = LLUICtrlFactory::create<LLButton>(button_params);
  139. addChild(mButton);
  140. mFlashToLitTimer = new FlashToLitTimer(p.flash_to_lit_count, p.flash_period, boost::bind(&LLSysWellChiclet::changeLitState, this));
  141. }
  142. LLSysWellChiclet::~LLSysWellChiclet()
  143. {
  144. delete mFlashToLitTimer;
  145. }
  146. void LLSysWellChiclet::setCounter(S32 counter)
  147. {
  148. // do nothing if the same counter is coming. EXT-3678.
  149. if (counter == mCounter) return;
  150. // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter)
  151. std::string s_count;
  152. if(counter != 0)
  153. {
  154. static std::string more_messages_exist("+");
  155. std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : "");
  156. s_count = llformat("%d%s"
  157. , llmin(counter, mMaxDisplayedCount)
  158. , more_messages.c_str()
  159. );
  160. }
  161. mButton->setLabel(s_count);
  162. setNewMessagesState(counter > mCounter);
  163. // we have to flash to 'Lit' state each time new unread message is coming.
  164. if (counter > mCounter)
  165. {
  166. mFlashToLitTimer->flash();
  167. }
  168. else if (counter == 0)
  169. {
  170. // if notification is resolved while well is flashing it can leave in the 'Lit' state
  171. // when flashing finishes itself. Let break flashing here.
  172. mFlashToLitTimer->stopFlashing();
  173. }
  174. mCounter = counter;
  175. }
  176. boost::signals2::connection LLSysWellChiclet::setClickCallback(
  177. const commit_callback_t& cb)
  178. {
  179. return mButton->setClickedCallback(cb);
  180. }
  181. void LLSysWellChiclet::setToggleState(BOOL toggled) {
  182. mButton->setToggleState(toggled);
  183. }
  184. void LLSysWellChiclet::changeLitState()
  185. {
  186. setNewMessagesState(!mIsNewMessagesState);
  187. }
  188. void LLSysWellChiclet::setNewMessagesState(bool new_messages)
  189. {
  190. /*
  191. Emulate 4 states of button by background images, see detains in EXT-3147
  192. xml attribute           Description
  193. image_unselected        "Unlit" - there are no new messages
  194. image_selected          "Unlit" + "Selected" - there are no new messages and the Well is open
  195. image_pressed           "Lit" - there are new messages
  196. image_pressed_selected  "Lit" + "Selected" - there are new messages and the Well is open
  197. */
  198. mButton->setForcePressedState(new_messages);
  199. mIsNewMessagesState = new_messages;
  200. }
  201. void LLSysWellChiclet::updateWidget(bool is_window_empty)
  202. {
  203. mButton->setEnabled(!is_window_empty);
  204. }
  205. // virtual
  206. BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
  207. {
  208. if(!mContextMenu)
  209. {
  210. createMenu();
  211. }
  212. if (mContextMenu)
  213. {
  214. mContextMenu->show(x, y);
  215. LLMenuGL::showPopup(this, mContextMenu, x, y);
  216. }
  217. return TRUE;
  218. }
  219. /************************************************************************/
  220. /*               LLIMWellChiclet implementation                         */
  221. /************************************************************************/
  222. LLIMWellChiclet::LLIMWellChiclet(const Params& p)
  223. : LLSysWellChiclet(p)
  224. {
  225. LLIMModel::instance().addNewMsgCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1));
  226. LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(&LLIMWellChiclet::messageCountChanged, this, _1));
  227. LLIMMgr::getInstance()->addSessionObserver(this);
  228. LLIMWellWindow::getInstance()->setSysWellChiclet(this);
  229. }
  230. LLIMWellChiclet::~LLIMWellChiclet()
  231. {
  232. LLIMMgr::getInstance()->removeSessionObserver(this);
  233. }
  234. void LLIMWellChiclet::onMenuItemClicked(const LLSD& user_data)
  235. {
  236. std::string action = user_data.asString();
  237. if("close all" == action)
  238. {
  239. LLIMWellWindow::getInstance()->closeAll();
  240. }
  241. }
  242. bool LLIMWellChiclet::enableMenuItem(const LLSD& user_data)
  243. {
  244. std::string item = user_data.asString();
  245. if (item == "can close all")
  246. {
  247. return !LLIMWellWindow::getInstance()->isWindowEmpty();
  248. }
  249. return true;
  250. }
  251. void LLIMWellChiclet::createMenu()
  252. {
  253. if(mContextMenu)
  254. {
  255. llwarns << "Menu already exists" << llendl;
  256. return;
  257. }
  258. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  259. registrar.add("IMWellChicletMenu.Action",
  260. boost::bind(&LLIMWellChiclet::onMenuItemClicked, this, _2));
  261. LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
  262. enable_registrar.add("IMWellChicletMenu.EnableItem",
  263. boost::bind(&LLIMWellChiclet::enableMenuItem, this, _2));
  264. mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
  265. ("menu_im_well_button.xml",
  266.  LLMenuGL::sMenuContainer,
  267.  LLViewerMenuHolderGL::child_registry_t::instance());
  268. }
  269. void LLIMWellChiclet::messageCountChanged(const LLSD& session_data)
  270. {
  271. setCounter(LLBottomTray::getInstance()->getTotalUnreadIMCount());
  272. }
  273. /************************************************************************/
  274. /*               LLNotificationChiclet implementation                   */
  275. /************************************************************************/
  276. LLNotificationChiclet::LLNotificationChiclet(const Params& p)
  277. : LLSysWellChiclet(p)
  278. , mUreadSystemNotifications(0)
  279. {
  280. // connect counter handlers to the signals
  281. connectCounterUpdatersToSignal("notify");
  282. connectCounterUpdatersToSignal("groupnotify");
  283. connectCounterUpdatersToSignal("offer");
  284. // ensure that notification well window exists, to synchronously
  285. // handle toast add/delete events.
  286. LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);
  287. }
  288. void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type)
  289. {
  290. LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance();
  291. LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type);
  292. if(n_handler)
  293. {
  294. n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this));
  295. n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this));
  296. }
  297. }
  298. void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
  299. {
  300. std::string action = user_data.asString();
  301. if("close all" == action)
  302. {
  303. LLNotificationWellWindow::getInstance()->closeAll();
  304. }
  305. }
  306. bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data)
  307. {
  308. std::string item = user_data.asString();
  309. if (item == "can close all")
  310. {
  311. return mUreadSystemNotifications != 0;
  312. }
  313. return true;
  314. }
  315. void LLNotificationChiclet::createMenu()
  316. {
  317. if(mContextMenu)
  318. {
  319. llwarns << "Menu already exists" << llendl;
  320. return;
  321. }
  322. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  323. registrar.add("NotificationWellChicletMenu.Action",
  324. boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2));
  325. LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
  326. enable_registrar.add("NotificationWellChicletMenu.EnableItem",
  327. boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
  328. mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
  329. ("menu_notification_well_button.xml",
  330.  LLMenuGL::sMenuContainer,
  331.  LLViewerMenuHolderGL::child_registry_t::instance());
  332. }
  333. /*virtual*/
  334. void LLNotificationChiclet::setCounter(S32 counter)
  335. {
  336. LLSysWellChiclet::setCounter(counter);
  337. updateWidget(getCounter() == 0);
  338. }
  339. //////////////////////////////////////////////////////////////////////////
  340. //////////////////////////////////////////////////////////////////////////
  341. //////////////////////////////////////////////////////////////////////////
  342. LLChiclet::Params::Params()
  343.  : show_counter("show_counter", true)
  344.  , enable_counter("enable_counter", false)
  345. {
  346. }
  347. LLChiclet::LLChiclet(const Params& p)
  348. : LLUICtrl(p)
  349. , mSessionId(LLUUID::null)
  350. , mShowCounter(p.show_counter)
  351. {
  352. }
  353. LLChiclet::~LLChiclet()
  354. {
  355. }
  356. boost::signals2::connection LLChiclet::setLeftButtonClickCallback(
  357. const commit_callback_t& cb)
  358. {
  359. return setCommitCallback(cb);
  360. }
  361. BOOL LLChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
  362. {
  363. onCommit();
  364. childrenHandleMouseDown(x,y,mask);
  365. return TRUE;
  366. }
  367. boost::signals2::connection LLChiclet::setChicletSizeChangedCallback(
  368. const chiclet_size_changed_callback_t& cb)
  369. {
  370. return mChicletSizeChangedSignal.connect(cb);
  371. }
  372. void LLChiclet::onChicletSizeChanged()
  373. {
  374. mChicletSizeChangedSignal(this, getValue());
  375. }
  376. LLSD LLChiclet::getValue() const
  377. {
  378. return LLSD(getSessionId());
  379. }
  380. void LLChiclet::setValue(const LLSD& value)
  381. {
  382. if(value.isUUID())
  383. setSessionId(value.asUUID());
  384. }
  385. //////////////////////////////////////////////////////////////////////////
  386. //////////////////////////////////////////////////////////////////////////
  387. //////////////////////////////////////////////////////////////////////////
  388. LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)
  389. : LLChiclet(p)
  390. , mShowSpeaker(false)
  391. , mDefaultWidth(p.rect().getWidth())
  392. , mNewMessagesIcon(NULL)
  393. , mSpeakerCtrl(NULL)
  394. , mCounterCtrl(NULL)
  395. , mChicletButton(NULL)
  396. {
  397. enableCounterControl(p.enable_counter);
  398. }
  399. /* virtual*/
  400. BOOL LLIMChiclet::postBuild()
  401. {
  402. mChicletButton = getChild<LLButton>("chiclet_button");
  403. mChicletButton->setCommitCallback(boost::bind(&LLIMChiclet::onMouseDown, this));
  404. mChicletButton->setDoubleClickCallback(boost::bind(&LLIMChiclet::onMouseDown, this));
  405. return TRUE;
  406. }
  407. void LLIMChiclet::setShowSpeaker(bool show)
  408. {
  409. bool needs_resize = getShowSpeaker() != show;
  410. if(needs_resize)
  411. {
  412. mShowSpeaker = show;
  413. toggleSpeakerControl();
  414. }
  415. }
  416. void LLIMChiclet::enableCounterControl(bool enable) 
  417. {
  418. mCounterEnabled = enable;
  419. if(!enable)
  420. {
  421. LLChiclet::setShowCounter(false);
  422. }
  423. }
  424. void LLIMChiclet::setShowCounter(bool show)
  425. {
  426. if(!mCounterEnabled)
  427. {
  428. return;
  429. }
  430. bool needs_resize = getShowCounter() != show;
  431. if(needs_resize)
  432. {
  433. LLChiclet::setShowCounter(show);
  434. toggleCounterControl();
  435. }
  436. }
  437. void LLIMChiclet::initSpeakerControl()
  438. {
  439. // virtual
  440. }
  441. void LLIMChiclet::setRequiredWidth()
  442. {
  443. bool show_speaker = getShowSpeaker();
  444. bool show_counter = getShowCounter();
  445. S32 required_width = mDefaultWidth;
  446. if (show_counter)
  447. {
  448. required_width += mCounterCtrl->getRect().getWidth();
  449. }
  450. if (show_speaker)
  451. {
  452. required_width += mSpeakerCtrl->getRect().getWidth();
  453. reshape(required_width, getRect().getHeight());
  454. onChicletSizeChanged();
  455. }
  456. void LLIMChiclet::toggleSpeakerControl()
  457. {
  458. if(getShowSpeaker())
  459. {
  460. // move speaker to the right of chiclet icon
  461. LLRect speaker_rc = mSpeakerCtrl->getRect();
  462. speaker_rc.setLeftTopAndSize(mDefaultWidth, speaker_rc.mTop, speaker_rc.getWidth(), speaker_rc.getHeight());
  463. mSpeakerCtrl->setRect(speaker_rc);
  464. if(getShowCounter())
  465. {
  466. // move speaker to the right of counter
  467. mSpeakerCtrl->translate(mCounterCtrl->getRect().getWidth(), 0);
  468. }
  469. initSpeakerControl();
  470. }
  471. setRequiredWidth();
  472. mSpeakerCtrl->setSpeakerId(LLUUID::null);
  473. mSpeakerCtrl->setVisible(getShowSpeaker());
  474. }
  475. void LLIMChiclet::setCounter(S32 counter)
  476. {
  477. if (mCounterCtrl->getCounter() == counter)
  478. {
  479. return;
  480. }
  481. mCounterCtrl->setCounter(counter);
  482. setShowCounter(counter);
  483. setShowNewMessagesIcon(counter);
  484. }
  485. void LLIMChiclet::toggleCounterControl()
  486. {
  487. setRequiredWidth();
  488. mCounterCtrl->setVisible(getShowCounter());
  489. }
  490. void LLIMChiclet::setShowNewMessagesIcon(bool show)
  491. {
  492. if(mNewMessagesIcon)
  493. {
  494. mNewMessagesIcon->setVisible(show);
  495. }
  496. setRequiredWidth();
  497. }
  498. bool LLIMChiclet::getShowNewMessagesIcon()
  499. {
  500. return mNewMessagesIcon->getVisible();
  501. }
  502. void LLIMChiclet::onMouseDown()
  503. {
  504. LLIMFloater::toggle(getSessionId());
  505. setCounter(0);
  506. }
  507. void LLIMChiclet::setToggleState(bool toggle)
  508. {
  509. mChicletButton->setToggleState(toggle);
  510. }
  511. void LLIMChiclet::draw()
  512. {
  513. LLUICtrl::draw();
  514. }
  515. // static
  516. LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id)
  517. {
  518. EType type = TYPE_UNKNOWN;
  519. if(session_id.isNull())
  520. return type;
  521. EInstantMessage im_type = LLIMModel::getInstance()->getType(session_id);
  522. if (IM_COUNT == im_type)
  523. {
  524. llassert_always(0 && "IM session not found"); // should never happen
  525. return type;
  526. }
  527. switch(im_type)
  528. {
  529. case IM_NOTHING_SPECIAL:
  530. case IM_SESSION_P2P_INVITE:
  531. type = TYPE_IM;
  532. break;
  533. case IM_SESSION_GROUP_START:
  534. case IM_SESSION_INVITE:
  535. if (gAgent.isInGroup(session_id))
  536. {
  537. type = TYPE_GROUP;
  538. }
  539. else
  540. {
  541. type = TYPE_AD_HOC;
  542. }
  543. break;
  544. case IM_SESSION_CONFERENCE_START:
  545. type = TYPE_AD_HOC;
  546. default:
  547. break;
  548. }
  549. return type;
  550. }
  551. //////////////////////////////////////////////////////////////////////////
  552. //////////////////////////////////////////////////////////////////////////
  553. //////////////////////////////////////////////////////////////////////////
  554. LLIMP2PChiclet::Params::Params()
  555. : avatar_icon("avatar_icon")
  556. , chiclet_button("chiclet_button")
  557. , unread_notifications("unread_notifications")
  558. , speaker("speaker")
  559. , new_message_icon("new_message_icon")
  560. , show_speaker("show_speaker")
  561. {
  562. }
  563. LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
  564. : LLIMChiclet(p)
  565. , mChicletIconCtrl(NULL)
  566. , mPopupMenu(NULL)
  567. {
  568. LLButton::Params button_params = p.chiclet_button;
  569. mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
  570. addChild(mChicletButton);
  571. LLIconCtrl::Params new_msg_params = p.new_message_icon;
  572. mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
  573. addChild(mNewMessagesIcon);
  574. LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
  575. mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
  576. addChild(mChicletIconCtrl);
  577. LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
  578. mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
  579. addChild(mCounterCtrl);
  580. setCounter(getCounter());
  581. setShowCounter(getShowCounter());
  582. LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
  583. mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
  584. addChild(mSpeakerCtrl);
  585. sendChildToFront(mNewMessagesIcon);
  586. setShowSpeaker(p.show_speaker);
  587. }
  588. void LLIMP2PChiclet::initSpeakerControl()
  589. {
  590. mSpeakerCtrl->setSpeakerId(getOtherParticipantId());
  591. }
  592. void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id)
  593. {
  594. LLIMChiclet::setOtherParticipantId(other_participant_id);
  595. mChicletIconCtrl->setValue(getOtherParticipantId());
  596. }
  597. void LLIMP2PChiclet::updateMenuItems()
  598. {
  599. if(!mPopupMenu)
  600. return;
  601. if(getSessionId().isNull())
  602. return;
  603. LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId());
  604. bool open_window_exists = open_im_floater && open_im_floater->getVisible();
  605. mPopupMenu->getChild<LLUICtrl>("Send IM")->setEnabled(!open_window_exists);
  606. bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId());
  607. mPopupMenu->getChild<LLUICtrl>("Add Friend")->setEnabled(!is_friend);
  608. }
  609. BOOL LLIMP2PChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
  610. {
  611. if(!mPopupMenu)
  612. {
  613. createPopupMenu();
  614. }
  615. if (mPopupMenu)
  616. {
  617. updateMenuItems();
  618. mPopupMenu->arrangeAndClear();
  619. LLMenuGL::showPopup(this, mPopupMenu, x, y);
  620. }
  621. return TRUE;
  622. }
  623. void LLIMP2PChiclet::createPopupMenu()
  624. {
  625. if(mPopupMenu)
  626. {
  627. llwarns << "Menu already exists" << llendl;
  628. return;
  629. }
  630. if(getSessionId().isNull())
  631. {
  632. return;
  633. }
  634. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  635. registrar.add("IMChicletMenu.Action", boost::bind(&LLIMP2PChiclet::onMenuItemClicked, this, _2));
  636. mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
  637. ("menu_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  638. }
  639. void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data)
  640. {
  641. std::string level = user_data.asString();
  642. LLUUID other_participant_id = getOtherParticipantId();
  643. if("profile" == level)
  644. {
  645. LLAvatarActions::showProfile(other_participant_id);
  646. }
  647. else if("im" == level)
  648. {
  649. LLAvatarActions::startIM(other_participant_id);
  650. }
  651. else if("add" == level)
  652. {
  653. LLAvatarActions::requestFriendshipDialog(other_participant_id);
  654. }
  655. else if("end" == level)
  656. {
  657. LLAvatarActions::endIM(other_participant_id);
  658. }
  659. }
  660. //////////////////////////////////////////////////////////////////////////
  661. //////////////////////////////////////////////////////////////////////////
  662. //////////////////////////////////////////////////////////////////////////
  663. LLAdHocChiclet::Params::Params()
  664. : avatar_icon("avatar_icon")
  665. , chiclet_button("chiclet_button")
  666. , unread_notifications("unread_notifications")
  667. , speaker("speaker")
  668. , new_message_icon("new_message_icon")
  669. , show_speaker("show_speaker")
  670. , avatar_icon_color("avatar_icon_color", LLColor4::green)
  671. {
  672. }
  673. LLAdHocChiclet::LLAdHocChiclet(const Params& p)
  674. : LLIMChiclet(p)
  675. , mChicletIconCtrl(NULL)
  676. , mPopupMenu(NULL)
  677. {
  678. LLButton::Params button_params = p.chiclet_button;
  679. mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
  680. addChild(mChicletButton);
  681. LLIconCtrl::Params new_msg_params = p.new_message_icon;
  682. mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
  683. addChild(mNewMessagesIcon);
  684. LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
  685. mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
  686. //Make the avatar modified
  687. mChicletIconCtrl->setColor(p.avatar_icon_color);
  688. addChild(mChicletIconCtrl);
  689. LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
  690. mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
  691. addChild(mCounterCtrl);
  692. setCounter(getCounter());
  693. setShowCounter(getShowCounter());
  694. LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
  695. mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
  696. addChild(mSpeakerCtrl);
  697. sendChildToFront(mNewMessagesIcon);
  698. setShowSpeaker(p.show_speaker);
  699. }
  700. void LLAdHocChiclet::setSessionId(const LLUUID& session_id)
  701. {
  702. LLChiclet::setSessionId(session_id);
  703. LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
  704. mChicletIconCtrl->setValue(im_session->mOtherParticipantID);
  705. }
  706. void LLAdHocChiclet::draw()
  707. {
  708. switchToCurrentSpeaker();
  709. LLIMChiclet::draw();
  710. }
  711. void LLAdHocChiclet::initSpeakerControl()
  712. {
  713. switchToCurrentSpeaker();
  714. }
  715. void LLAdHocChiclet::switchToCurrentSpeaker()
  716. {
  717. LLUUID speaker_id;
  718. LLSpeakerMgr::speaker_list_t speaker_list;
  719. LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE);
  720. for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i)
  721. {
  722. LLPointer<LLSpeaker> s = *i;
  723. if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING)
  724. {
  725. speaker_id = s->mID;
  726. break;
  727. }
  728. }
  729. mSpeakerCtrl->setSpeakerId(speaker_id);
  730. }
  731. void LLAdHocChiclet::createPopupMenu()
  732. {
  733. if(mPopupMenu)
  734. {
  735. llwarns << "Menu already exists" << llendl;
  736. return;
  737. }
  738. if(getSessionId().isNull())
  739. {
  740. return;
  741. }
  742. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  743. registrar.add("IMChicletMenu.Action", boost::bind(&LLAdHocChiclet::onMenuItemClicked, this, _2));
  744. mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
  745. ("menu_imchiclet_adhoc.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  746. }
  747. void LLAdHocChiclet::onMenuItemClicked(const LLSD& user_data)
  748. {
  749. std::string level = user_data.asString();
  750. LLUUID group_id = getSessionId();
  751. if("end" == level)
  752. {
  753. LLGroupActions::endIM(group_id);
  754. }
  755. }
  756. BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
  757. {
  758. if(!mPopupMenu)
  759. {
  760. createPopupMenu();
  761. }
  762. if (mPopupMenu)
  763. {
  764. mPopupMenu->arrangeAndClear();
  765. LLMenuGL::showPopup(this, mPopupMenu, x, y);
  766. }
  767. return TRUE;
  768. }
  769. //////////////////////////////////////////////////////////////////////////
  770. //////////////////////////////////////////////////////////////////////////
  771. //////////////////////////////////////////////////////////////////////////
  772. LLIMGroupChiclet::Params::Params()
  773. : group_icon("group_icon")
  774. , chiclet_button("chiclet_button")
  775. , unread_notifications("unread_notifications")
  776. , speaker("speaker")
  777. , new_message_icon("new_message_icon")
  778. , show_speaker("show_speaker")
  779. {
  780. }
  781. LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)
  782. : LLIMChiclet(p)
  783. , LLGroupMgrObserver(LLUUID::null)
  784. , mChicletIconCtrl(NULL)
  785. , mPopupMenu(NULL)
  786. {
  787. LLButton::Params button_params = p.chiclet_button;
  788. mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
  789. addChild(mChicletButton);
  790. LLIconCtrl::Params new_msg_params = p.new_message_icon;
  791. mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
  792. addChild(mNewMessagesIcon);
  793. LLChicletGroupIconCtrl::Params avatar_params = p.group_icon;
  794. mChicletIconCtrl = LLUICtrlFactory::create<LLChicletGroupIconCtrl>(avatar_params);
  795. addChild(mChicletIconCtrl);
  796. LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
  797. mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
  798. addChild(mCounterCtrl);
  799. setCounter(getCounter());
  800. setShowCounter(getShowCounter());
  801. LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
  802. mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
  803. addChild(mSpeakerCtrl);
  804. sendChildToFront(mNewMessagesIcon);
  805. setShowSpeaker(p.show_speaker);
  806. }
  807. LLIMGroupChiclet::~LLIMGroupChiclet()
  808. {
  809. LLGroupMgr::getInstance()->removeObserver(this);
  810. }
  811. void LLIMGroupChiclet::draw()
  812. {
  813. if(getShowSpeaker())
  814. {
  815. switchToCurrentSpeaker();
  816. }
  817. LLIMChiclet::draw();
  818. }
  819. void LLIMGroupChiclet::initSpeakerControl()
  820. {
  821. switchToCurrentSpeaker();
  822. }
  823. void LLIMGroupChiclet::switchToCurrentSpeaker()
  824. {
  825. LLUUID speaker_id;
  826. LLSpeakerMgr::speaker_list_t speaker_list;
  827. LLIMModel::getInstance()->findIMSession(getSessionId())->mSpeakers->getSpeakerList(&speaker_list, FALSE);
  828. for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i)
  829. {
  830. LLPointer<LLSpeaker> s = *i;
  831. if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING)
  832. {
  833. speaker_id = s->mID;
  834. break;
  835. }
  836. }
  837. mSpeakerCtrl->setSpeakerId(speaker_id);
  838. }
  839. void LLIMGroupChiclet::setSessionId(const LLUUID& session_id)
  840. {
  841. LLChiclet::setSessionId(session_id);
  842. LLGroupMgr* grp_mgr = LLGroupMgr::getInstance();
  843. LLGroupMgrGroupData* group_data = grp_mgr->getGroupData(session_id);
  844. if (group_data && group_data->mInsigniaID.notNull())
  845. {
  846. mChicletIconCtrl->setValue(group_data->mInsigniaID);
  847. }
  848. else
  849. {
  850. if(getSessionId() != mID)
  851. {
  852. grp_mgr->removeObserver(this);
  853. mID = getSessionId();
  854. grp_mgr->addObserver(this);
  855. }
  856. grp_mgr->sendGroupPropertiesRequest(session_id);
  857. }
  858. }
  859. void LLIMGroupChiclet::changed(LLGroupChange gc)
  860. {
  861. if (GC_PROPERTIES == gc)
  862. {
  863. LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(getSessionId());
  864. if (group_data)
  865. {
  866. mChicletIconCtrl->setValue(group_data->mInsigniaID);
  867. }
  868. }
  869. }
  870. void LLIMGroupChiclet::updateMenuItems()
  871. {
  872. if(!mPopupMenu)
  873. return;
  874. if(getSessionId().isNull())
  875. return;
  876. LLIMFloater* open_im_floater = LLIMFloater::findInstance(getSessionId());
  877. bool open_window_exists = open_im_floater && open_im_floater->getVisible();
  878. mPopupMenu->getChild<LLUICtrl>("Chat")->setEnabled(!open_window_exists);
  879. }
  880. BOOL LLIMGroupChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
  881. {
  882. if(!mPopupMenu)
  883. {
  884. createPopupMenu();
  885. }
  886. if (mPopupMenu)
  887. {
  888. updateMenuItems();
  889. mPopupMenu->arrangeAndClear();
  890. LLMenuGL::showPopup(this, mPopupMenu, x, y);
  891. }
  892. return TRUE;
  893. }
  894. void LLIMGroupChiclet::createPopupMenu()
  895. {
  896. if(mPopupMenu)
  897. {
  898. llwarns << "Menu already exists" << llendl;
  899. return;
  900. }
  901. if(getSessionId().isNull())
  902. {
  903. return;
  904. }
  905. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  906. registrar.add("IMChicletMenu.Action", boost::bind(&LLIMGroupChiclet::onMenuItemClicked, this, _2));
  907. mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>
  908. ("menu_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  909. }
  910. void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data)
  911. {
  912. std::string level = user_data.asString();
  913. LLUUID group_id = getSessionId();
  914. if("group chat" == level)
  915. {
  916. LLGroupActions::startIM(group_id);
  917. }
  918. else if("info" == level)
  919. {
  920. LLGroupActions::show(group_id);
  921. }
  922. else if("end" == level)
  923. {
  924. LLGroupActions::endIM(group_id);
  925. }
  926. }
  927. //////////////////////////////////////////////////////////////////////////
  928. //////////////////////////////////////////////////////////////////////////
  929. //////////////////////////////////////////////////////////////////////////
  930. LLChicletPanel::Params::Params()
  931. : chiclet_padding("chiclet_padding")
  932. , scrolling_offset("scrolling_offset")
  933. , scroll_button_hpad("scroll_button_hpad")
  934. , scroll_ratio("scroll_ratio")
  935. , min_width("min_width")
  936. {
  937. };
  938. LLChicletPanel::LLChicletPanel(const Params&p)
  939. : LLPanel(p)
  940. , mScrollArea(NULL)
  941. , mLeftScrollButton(NULL)
  942. , mRightScrollButton(NULL)
  943. , mChicletPadding(p.chiclet_padding)
  944. , mScrollingOffset(p.scrolling_offset)
  945. , mScrollButtonHPad(p.scroll_button_hpad)
  946. , mScrollRatio(p.scroll_ratio)
  947. , mMinWidth(p.min_width)
  948. , mShowControls(true)
  949. {
  950. LLPanel::Params panel_params;
  951. panel_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT);
  952. mScrollArea = LLUICtrlFactory::create<LLPanel>(panel_params,this);
  953. // important for Show/Hide Camera and Move controls menu in bottom tray to work properly
  954. mScrollArea->setMouseOpaque(false);
  955. addChild(mScrollArea);
  956. }
  957. LLChicletPanel::~LLChicletPanel()
  958. {
  959. LLTransientFloaterMgr::getInstance()->removeControlView(mLeftScrollButton);
  960. LLTransientFloaterMgr::getInstance()->removeControlView(mRightScrollButton);
  961. }
  962. void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
  963. LLUUID session_id = data["session_id"].asUUID();
  964. S32 unread = data["participant_unread"].asInteger();
  965. LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
  966. if (im_floater && im_floater->getVisible())
  967. {
  968. unread = 0;
  969. }
  970. std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(session_id);
  971. std::list<LLChiclet *>::iterator iter;
  972. for (iter = chiclets.begin(); iter != chiclets.end(); iter++) {
  973. LLChiclet* chiclet = *iter;
  974. if (chiclet != NULL)
  975. {
  976. chiclet->setCounter(unread);
  977. }
  978.     else
  979.     {
  980.      llwarns << "Unable to set counter for chiclet " << session_id << llendl;
  981.     }
  982. }
  983. }
  984. void object_chiclet_callback(const LLSD& data)
  985. {
  986. LLUUID notification_id = data["notification_id"];
  987. bool new_message = data["new_message"];
  988. std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(notification_id);
  989. std::list<LLChiclet *>::iterator iter;
  990. for (iter = chiclets.begin(); iter != chiclets.end(); iter++)
  991. {
  992. LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*iter);
  993. if (chiclet != NULL)
  994. {
  995. if(data.has("unread"))
  996. {
  997. chiclet->setCounter(data["unread"]);
  998. }
  999. chiclet->setShowNewMessagesIcon(new_message);
  1000. }
  1001. }
  1002. }
  1003. BOOL LLChicletPanel::postBuild()
  1004. {
  1005. LLPanel::postBuild();
  1006. LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1));
  1007. LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1));
  1008. LLScriptFloaterManager::getInstance()->addNewObjectCallback(boost::bind(object_chiclet_callback, _1));
  1009. LLScriptFloaterManager::getInstance()->addToggleObjectFloaterCallback(boost::bind(object_chiclet_callback, _1));
  1010. LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1));
  1011. LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLChicletPanel::onCurrentVoiceChannelChanged, this, _1));
  1012. mLeftScrollButton=getChild<LLButton>("chicklet_left_scroll_button");
  1013. LLTransientFloaterMgr::getInstance()->addControlView(mLeftScrollButton);
  1014. mLeftScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this));
  1015. mLeftScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onLeftScrollHeldDown,this));
  1016. mLeftScrollButton->setEnabled(false);
  1017. mRightScrollButton=getChild<LLButton>("chicklet_right_scroll_button");
  1018. LLTransientFloaterMgr::getInstance()->addControlView(mRightScrollButton);
  1019. mRightScrollButton->setMouseDownCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this));
  1020. mRightScrollButton->setHeldDownCallback(boost::bind(&LLChicletPanel::onRightScrollHeldDown,this));
  1021. mRightScrollButton->setEnabled(false);
  1022. return TRUE;
  1023. }
  1024. void LLChicletPanel::onCurrentVoiceChannelChanged(const LLUUID& session_id)
  1025. {
  1026. static LLUUID s_previous_active_voice_session_id;
  1027. std::list<LLChiclet*> chiclets = LLIMChiclet::sFindChicletsSignal(session_id);
  1028. for(std::list<LLChiclet *>::iterator it = chiclets.begin(); it != chiclets.end(); ++it)
  1029. {
  1030. LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
  1031. if(chiclet)
  1032. {
  1033. chiclet->setShowSpeaker(true);
  1034. }
  1035. }
  1036. if(!s_previous_active_voice_session_id.isNull() && s_previous_active_voice_session_id != session_id)
  1037. {
  1038. chiclets = LLIMChiclet::sFindChicletsSignal(s_previous_active_voice_session_id);
  1039. for(std::list<LLChiclet *>::iterator it = chiclets.begin(); it != chiclets.end(); ++it)
  1040. {
  1041. LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
  1042. if(chiclet)
  1043. {
  1044. chiclet->setShowSpeaker(false);
  1045. }
  1046. }
  1047. }
  1048. s_previous_active_voice_session_id = session_id;
  1049. }
  1050. bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
  1051. {
  1052. if(mScrollArea->addChild(chiclet))
  1053. {
  1054. // chiclets should be aligned to right edge of scroll panel
  1055. S32 left_shift = 0;
  1056. if (!canScrollLeft())
  1057. {
  1058. // init left shift for the first chiclet in the list...
  1059. if (mChicletList.empty())
  1060. {
  1061. // ...start from the right border of the scroll area for the first added chiclet 
  1062. left_shift = mScrollArea->getRect().getWidth();
  1063. }
  1064. else
  1065. {
  1066. // ... start from the left border of the first chiclet minus padding
  1067. left_shift = getChiclet(0)->getRect().mLeft - getChicletPadding();
  1068. }
  1069. // take into account width of the being added chiclet
  1070. left_shift -= chiclet->getRequiredRect().getWidth();
  1071. // if we overflow the scroll area we do not need to shift chiclets
  1072. if (left_shift < 0)
  1073. {
  1074. left_shift = 0;
  1075. }
  1076. }
  1077. mChicletList.insert(mChicletList.begin() + index, chiclet);
  1078. // shift first chiclet to place it in correct position. 
  1079. // rest ones will be placed in arrange()
  1080. if (!canScrollLeft())
  1081. {
  1082. getChiclet(0)->translate(left_shift - getChiclet(0)->getRect().mLeft, 0);
  1083. }
  1084. chiclet->setLeftButtonClickCallback(boost::bind(&LLChicletPanel::onChicletClick, this, _1, _2));
  1085. chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
  1086. arrange();
  1087. LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet);
  1088. return true;
  1089. }
  1090. return false;
  1091. }
  1092. void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
  1093. {
  1094. arrange();
  1095. }
  1096. void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD&param)
  1097. {
  1098. if (mCommitSignal)
  1099. {
  1100. (*mCommitSignal)(ctrl,param);
  1101. }
  1102. }
  1103. void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
  1104. {
  1105. LLChiclet* chiclet = *it;
  1106. mScrollArea->removeChild(chiclet);
  1107. mChicletList.erase(it);
  1108. arrange();
  1109. LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet);
  1110. chiclet->die();
  1111. }
  1112. void LLChicletPanel::removeChiclet(S32 index)
  1113. {
  1114. if(index >= 0 && index < getChicletCount())
  1115. {
  1116. removeChiclet(mChicletList.begin() + index);
  1117. }
  1118. }
  1119. S32 LLChicletPanel::getChicletIndex(const LLChiclet* chiclet)
  1120. {
  1121. if(mChicletList.empty())
  1122. return -1;
  1123. S32 size = getChicletCount();
  1124. for(int n = 0; n < size; ++n)
  1125. {
  1126. if(chiclet == mChicletList[n])
  1127. return n;
  1128. }
  1129. return -1;
  1130. }
  1131. void LLChicletPanel::removeChiclet(LLChiclet*chiclet)
  1132. {
  1133. chiclet_list_t::iterator it = mChicletList.begin();
  1134. for( ; mChicletList.end() != it; ++it)
  1135. {
  1136. LLChiclet* temp = *it;
  1137. if(temp == chiclet)
  1138. {
  1139. removeChiclet(it);
  1140. return;
  1141. }
  1142. }
  1143. }
  1144. void LLChicletPanel::removeChiclet(const LLUUID& im_session_id)
  1145. {
  1146. chiclet_list_t::iterator it = mChicletList.begin();
  1147. for( ; mChicletList.end() != it; ++it)
  1148. {
  1149. LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
  1150. if(chiclet->getSessionId() == im_session_id)
  1151. {
  1152. removeChiclet(it);
  1153. return;
  1154. }
  1155. }
  1156. }
  1157. void LLChicletPanel::removeAll()
  1158. {
  1159. S32 size = getChicletCount();
  1160. for(S32 n = 0; n < size; ++n)
  1161. {
  1162. mScrollArea->removeChild(mChicletList[n]);
  1163. }
  1164. mChicletList.erase(mChicletList.begin(), mChicletList.end());
  1165. showScrollButtonsIfNeeded();
  1166. }
  1167. void LLChicletPanel::scrollToChiclet(const LLChiclet* chiclet)
  1168. {
  1169. const LLRect& rect = chiclet->getRect();
  1170. if (rect.mLeft < 0)
  1171. {
  1172. scroll(llabs(rect.mLeft));
  1173. showScrollButtonsIfNeeded();
  1174. }
  1175. else
  1176. {
  1177. S32 scrollWidth = mScrollArea->getRect().getWidth();
  1178. if (rect.mRight > scrollWidth)
  1179. {
  1180. scroll(-llabs(rect.mRight - scrollWidth));
  1181. showScrollButtonsIfNeeded();
  1182. }
  1183. }
  1184. }
  1185. void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )
  1186. {
  1187. LLPanel::reshape(width,height,called_from_parent);
  1188. //Needed once- to avoid error at first call of reshape() before postBuild()
  1189. if(!mLeftScrollButton||!mRightScrollButton)
  1190. return;
  1191. LLRect scroll_button_rect = mLeftScrollButton->getRect();
  1192. mLeftScrollButton->setRect(LLRect(0,scroll_button_rect.mTop,scroll_button_rect.getWidth(),
  1193. scroll_button_rect.mBottom));
  1194. scroll_button_rect = mRightScrollButton->getRect();
  1195. mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop,
  1196. width, scroll_button_rect.mBottom));
  1197. bool need_show_scroll = needShowScroll();
  1198. if(need_show_scroll)
  1199. {
  1200. mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad,
  1201. height, width - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));
  1202. }
  1203. else
  1204. {
  1205. mScrollArea->setRect(LLRect(0,height, width, 0));
  1206. }
  1207. mShowControls = width >= mMinWidth;
  1208. mScrollArea->setVisible(mShowControls);
  1209. trimChiclets();
  1210. showScrollButtonsIfNeeded();
  1211. }
  1212. S32 LLChicletPanel::notifyParent(const LLSD& info)
  1213. {
  1214. if(info.has("notification"))
  1215. {
  1216. std::string str_notification = info["notification"];
  1217. if(str_notification == "size_changes")
  1218. {
  1219. arrange();
  1220. return 1;
  1221. }
  1222. }
  1223. return LLPanel::notifyParent(info);
  1224. }
  1225. void LLChicletPanel::setChicletToggleState(const LLUUID& session_id, bool toggle)
  1226. {
  1227. if(session_id.isNull())
  1228. {
  1229. llwarns << "Null Session ID" << llendl;
  1230. }
  1231. // toggle off all chiclets, except specified
  1232. S32 size = getChicletCount();
  1233. for(int n = 0; n < size; ++n)
  1234. {
  1235. LLIMChiclet* chiclet = getChiclet<LLIMChiclet>(n);
  1236. if(chiclet && chiclet->getSessionId() != session_id)
  1237. {
  1238. chiclet->setToggleState(false);
  1239. }
  1240. }
  1241. // toggle specified chiclet
  1242. LLIMChiclet* chiclet = findChiclet<LLIMChiclet>(session_id);
  1243. if(chiclet)
  1244. {
  1245. chiclet->setToggleState(toggle);
  1246. }
  1247. }
  1248. void LLChicletPanel::arrange()
  1249. {
  1250. if(mChicletList.empty())
  1251. return;
  1252. //initial arrange of chicklets positions
  1253. S32 chiclet_left = getChiclet(0)->getRect().mLeft;
  1254. S32 size = getChicletCount();
  1255. for( int n = 0; n < size; ++n)
  1256. {
  1257. LLChiclet* chiclet = getChiclet(n);
  1258. S32 chiclet_width = chiclet->getRequiredRect().getWidth();
  1259. LLRect rect = chiclet->getRect();
  1260. rect.set(chiclet_left, rect.mTop, chiclet_left + chiclet_width, rect.mBottom);
  1261. chiclet->setRect(rect);
  1262. chiclet_left += chiclet_width + getChicletPadding();
  1263. }
  1264. //reset size and pos on mScrollArea
  1265. LLRect rect = getRect();
  1266. LLRect scroll_button_rect = mLeftScrollButton->getRect();
  1267. bool need_show_scroll = needShowScroll();
  1268. if(need_show_scroll)
  1269. {
  1270. mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + mScrollButtonHPad,
  1271. rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - mScrollButtonHPad, 0));
  1272. }
  1273. else
  1274. {
  1275. mScrollArea->setRect(LLRect(0,rect.getHeight(), rect.getWidth(), 0));
  1276. }
  1277. trimChiclets();
  1278. showScrollButtonsIfNeeded();
  1279. }
  1280. void LLChicletPanel::trimChiclets()
  1281. {
  1282. // trim right
  1283. if(!mChicletList.empty())
  1284. {
  1285. S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
  1286. S32 first_chiclet_left = getChiclet(0)->getRect().mLeft;
  1287. S32 scroll_width = mScrollArea->getRect().getWidth();
  1288. if(last_chiclet_right < scroll_width || first_chiclet_left > 0)
  1289. {
  1290. shiftChiclets(scroll_width - last_chiclet_right);
  1291. }
  1292. }
  1293. }
  1294. bool LLChicletPanel::needShowScroll()
  1295. {
  1296. if(mChicletList.empty())
  1297. return false;
  1298. S32 chicklet_width  = (*mChicletList.rbegin())->getRect().mRight - (*mChicletList.begin())->getRect().mLeft;
  1299. return chicklet_width>getRect().getWidth();
  1300. }
  1301. void LLChicletPanel::showScrollButtonsIfNeeded()
  1302. {
  1303. bool can_scroll_left = canScrollLeft();
  1304. bool can_scroll_right = canScrollRight();
  1305. mLeftScrollButton->setEnabled(can_scroll_left);
  1306. mRightScrollButton->setEnabled(can_scroll_right);
  1307. bool show_scroll_buttons = (can_scroll_left || can_scroll_right) && mShowControls;
  1308. mLeftScrollButton->setVisible(show_scroll_buttons);
  1309. mRightScrollButton->setVisible(show_scroll_buttons);
  1310. }
  1311. void LLChicletPanel::draw()
  1312. {
  1313. child_list_const_iter_t it = getChildList()->begin();
  1314. for( ; getChildList()->end() != it; ++it)
  1315. {
  1316. LLView* child = *it;
  1317. if(child == dynamic_cast<LLView*>(mScrollArea))
  1318. {
  1319. LLLocalClipRect clip(mScrollArea->getRect());
  1320. drawChild(mScrollArea);
  1321. }
  1322. else
  1323. {
  1324. drawChild(child);
  1325. }
  1326. }
  1327. }
  1328. bool LLChicletPanel::canScrollRight()
  1329. {
  1330. if(mChicletList.empty())
  1331. return false;
  1332. S32 scroll_width = mScrollArea->getRect().getWidth();
  1333. S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
  1334. if(last_chiclet_right > scroll_width)
  1335. return true;
  1336. return false;
  1337. }
  1338. bool LLChicletPanel::canScrollLeft()
  1339. {
  1340. if(mChicletList.empty())
  1341. return false;
  1342. return getChiclet(0)->getRect().mLeft < 0;
  1343. }
  1344. void LLChicletPanel::scroll(S32 offset)
  1345. {
  1346. shiftChiclets(offset);
  1347. }
  1348. void LLChicletPanel::shiftChiclets(S32 offset, S32 start_index /* = 0 */)
  1349. {
  1350. if(start_index < 0 || start_index >= getChicletCount())
  1351. {
  1352. return;
  1353. }
  1354. chiclet_list_t::const_iterator it = mChicletList.begin() + start_index;
  1355. for(;mChicletList.end() != it; ++it)
  1356. {
  1357. LLChiclet* chiclet = *it;
  1358. chiclet->translate(offset,0);
  1359. }
  1360. }
  1361. void LLChicletPanel::scrollLeft()
  1362. {
  1363. if(canScrollLeft())
  1364. {
  1365. S32 offset = getScrollingOffset();
  1366. LLRect first_chiclet_rect = getChiclet(0)->getRect();
  1367. // shift chiclets in case first chiclet is partially visible
  1368. if(first_chiclet_rect.mLeft < 0 && first_chiclet_rect.mRight > 0)
  1369. {
  1370. offset = llabs(first_chiclet_rect.mLeft);
  1371. }
  1372. scroll(offset);
  1373. showScrollButtonsIfNeeded();
  1374. }
  1375. }
  1376. void LLChicletPanel::scrollRight()
  1377. {
  1378. if(canScrollRight())
  1379. {
  1380. S32 offset = - getScrollingOffset();
  1381. S32 last_chiclet_right = (*mChicletList.rbegin())->getRect().mRight;
  1382. S32 scroll_rect_width = mScrollArea->getRect().getWidth();
  1383. // if after scrolling, the last chiclet will not be aligned to 
  1384. // scroll area right side - align it.
  1385. if( last_chiclet_right + offset < scroll_rect_width )
  1386. {
  1387. offset = scroll_rect_width - last_chiclet_right;
  1388. }
  1389. scroll(offset);
  1390. showScrollButtonsIfNeeded();
  1391. }
  1392. }
  1393. void LLChicletPanel::onLeftScrollClick()
  1394. {
  1395. scrollLeft();
  1396. }
  1397. void LLChicletPanel::onRightScrollClick()
  1398. {
  1399. scrollRight();
  1400. }
  1401. void LLChicletPanel::onLeftScrollHeldDown()
  1402. {
  1403. S32 offset = mScrollingOffset;
  1404. mScrollingOffset = mScrollingOffset / mScrollRatio;
  1405. scrollLeft();
  1406. mScrollingOffset = offset;
  1407. }
  1408. void LLChicletPanel::onRightScrollHeldDown()
  1409. {
  1410. S32 offset = mScrollingOffset;
  1411. mScrollingOffset = mScrollingOffset / mScrollRatio;
  1412. scrollRight();
  1413. mScrollingOffset = offset;
  1414. }
  1415. boost::signals2::connection LLChicletPanel::setChicletClickedCallback(
  1416. const commit_callback_t& cb)
  1417. {
  1418. return setCommitCallback(cb);
  1419. }
  1420. BOOL LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks)
  1421. {
  1422. if(clicks > 0)
  1423. {
  1424. scrollRight();
  1425. }
  1426. else
  1427. {
  1428. scrollLeft();
  1429. }
  1430. return TRUE;
  1431. }
  1432. bool LLChicletPanel::isAnyIMFloaterDoked()
  1433. {
  1434. bool res = false;
  1435. for (chiclet_list_t::iterator it = mChicletList.begin(); it
  1436. != mChicletList.end(); it++)
  1437. {
  1438. LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>(
  1439. "impanel", (*it)->getSessionId());
  1440. if (im_floater != NULL && im_floater->getVisible()
  1441. && !im_floater->isMinimized() && im_floater->isDocked())
  1442. {
  1443. res = true;
  1444. break;
  1445. }
  1446. }
  1447. return res;
  1448. }
  1449. S32 LLChicletPanel::getTotalUnreadIMCount()
  1450. {
  1451. S32 count = 0;
  1452. chiclet_list_t::const_iterator it = mChicletList.begin();
  1453. for( ; mChicletList.end() != it; ++it)
  1454. {
  1455. LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(*it);
  1456. if(chiclet)
  1457. {
  1458. count += chiclet->getCounter();
  1459. }
  1460. }
  1461. return count;
  1462. }
  1463. //////////////////////////////////////////////////////////////////////////
  1464. //////////////////////////////////////////////////////////////////////////
  1465. //////////////////////////////////////////////////////////////////////////
  1466. LLChicletNotificationCounterCtrl::Params::Params()
  1467. : max_displayed_count("max_displayed_count", 99)
  1468. {
  1469. }
  1470. LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p)
  1471.  : LLTextBox(p)
  1472.  , mCounter(0)
  1473.  , mInitialWidth(0)
  1474.  , mMaxDisplayedCount(p.max_displayed_count)
  1475. {
  1476. mInitialWidth = getRect().getWidth();
  1477. }
  1478. void LLChicletNotificationCounterCtrl::setCounter(S32 counter)
  1479. {
  1480. mCounter = counter;
  1481. // note same code in LLSysWellChiclet::setCounter(S32 counter)
  1482. std::string s_count;
  1483. if(counter != 0)
  1484. {
  1485. static std::string more_messages_exist("+");
  1486. std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : "");
  1487. s_count = llformat("%d%s"
  1488. , llmin(counter, mMaxDisplayedCount)
  1489. , more_messages.c_str()
  1490. );
  1491. }
  1492. if(mCounter != 0)
  1493. {
  1494. setText(s_count);
  1495. }
  1496. else
  1497. {
  1498. setText(std::string(""));
  1499. }
  1500. }
  1501. LLRect LLChicletNotificationCounterCtrl::getRequiredRect()
  1502. {
  1503. LLRect rc;
  1504. S32 text_width = getTextPixelWidth();
  1505. rc.mRight = rc.mLeft + llmax(text_width, mInitialWidth);
  1506. return rc;
  1507. }
  1508. void LLChicletNotificationCounterCtrl::setValue(const LLSD& value)
  1509. {
  1510. if(value.isInteger())
  1511. setCounter(value.asInteger());
  1512. }
  1513. LLSD LLChicletNotificationCounterCtrl::getValue() const
  1514. {
  1515. return LLSD(getCounter());
  1516. }
  1517. //////////////////////////////////////////////////////////////////////////
  1518. //////////////////////////////////////////////////////////////////////////
  1519. //////////////////////////////////////////////////////////////////////////
  1520. LLChicletAvatarIconCtrl::LLChicletAvatarIconCtrl(const Params& p)
  1521.  : LLAvatarIconCtrl(p)
  1522. {
  1523. }
  1524. //////////////////////////////////////////////////////////////////////////
  1525. //////////////////////////////////////////////////////////////////////////
  1526. //////////////////////////////////////////////////////////////////////////
  1527. LLChicletGroupIconCtrl::LLChicletGroupIconCtrl(const Params& p)
  1528. : LLIconCtrl(p)
  1529. , mDefaultIcon(p.default_icon)
  1530. {
  1531. setValue(LLUUID::null);
  1532. }
  1533. void LLChicletGroupIconCtrl::setValue(const LLSD& value )
  1534. {
  1535. if(value.asUUID().isNull())
  1536. {
  1537. LLIconCtrl::setValue(mDefaultIcon);
  1538. }
  1539. else
  1540. {
  1541. LLIconCtrl::setValue(value);
  1542. }
  1543. }
  1544. //////////////////////////////////////////////////////////////////////////
  1545. //////////////////////////////////////////////////////////////////////////
  1546. //////////////////////////////////////////////////////////////////////////
  1547. LLChicletInvOfferIconCtrl::LLChicletInvOfferIconCtrl(const Params& p)
  1548. : LLChicletAvatarIconCtrl(p)
  1549.  , mDefaultIcon(p.default_icon)
  1550. {
  1551. }
  1552. void LLChicletInvOfferIconCtrl::setValue(const LLSD& value )
  1553. {
  1554. if(value.asUUID().isNull())
  1555. {
  1556. LLIconCtrl::setValue(mDefaultIcon);
  1557. }
  1558. else
  1559. {
  1560. LLChicletAvatarIconCtrl::setValue(value);
  1561. }
  1562. }
  1563. //////////////////////////////////////////////////////////////////////////
  1564. //////////////////////////////////////////////////////////////////////////
  1565. //////////////////////////////////////////////////////////////////////////
  1566. LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p)
  1567.  : LLOutputMonitorCtrl(p)
  1568. {
  1569. }
  1570. //////////////////////////////////////////////////////////////////////////
  1571. //////////////////////////////////////////////////////////////////////////
  1572. //////////////////////////////////////////////////////////////////////////
  1573. LLScriptChiclet::Params::Params()
  1574.  : icon("icon")
  1575.  , chiclet_button("chiclet_button")
  1576.  , new_message_icon("new_message_icon")
  1577. {
  1578. }
  1579. LLScriptChiclet::LLScriptChiclet(const Params&p)
  1580.  : LLIMChiclet(p)
  1581.  , mChicletIconCtrl(NULL)
  1582. {
  1583. LLButton::Params button_params = p.chiclet_button;
  1584. mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
  1585. addChild(mChicletButton);
  1586. LLIconCtrl::Params new_msg_params = p.new_message_icon;
  1587. mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
  1588. addChild(mNewMessagesIcon);
  1589. LLIconCtrl::Params icon_params = p.icon;
  1590. mChicletIconCtrl = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
  1591. addChild(mChicletIconCtrl);
  1592. sendChildToFront(mNewMessagesIcon);
  1593. }
  1594. void LLScriptChiclet::setSessionId(const LLUUID& session_id)
  1595. {
  1596. setShowNewMessagesIcon( getSessionId() != session_id );
  1597. LLIMChiclet::setSessionId(session_id);
  1598. setToolTip(LLScriptFloaterManager::getObjectName(session_id));
  1599. }
  1600. void LLScriptChiclet::setCounter(S32 counter)
  1601. {
  1602. setShowNewMessagesIcon( counter > 0 );
  1603. }
  1604. void LLScriptChiclet::onMouseDown()
  1605. {
  1606. LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId());
  1607. }
  1608. //////////////////////////////////////////////////////////////////////////
  1609. //////////////////////////////////////////////////////////////////////////
  1610. //////////////////////////////////////////////////////////////////////////
  1611. static const std::string INVENTORY_USER_OFFER ("UserGiveItem");
  1612. LLInvOfferChiclet::Params::Params()
  1613.  : icon("icon")
  1614.  , chiclet_button("chiclet_button")
  1615.  , new_message_icon("new_message_icon")
  1616. {
  1617. }
  1618. LLInvOfferChiclet::LLInvOfferChiclet(const Params&p)
  1619.  : LLIMChiclet(p)
  1620.  , mChicletIconCtrl(NULL)
  1621. {
  1622. LLButton::Params button_params = p.chiclet_button;
  1623. mChicletButton = LLUICtrlFactory::create<LLButton>(button_params);
  1624. addChild(mChicletButton);
  1625. LLIconCtrl::Params new_msg_params = p.new_message_icon;
  1626. mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(new_msg_params);
  1627. addChild(mNewMessagesIcon);
  1628. LLChicletInvOfferIconCtrl::Params icon_params = p.icon;
  1629. mChicletIconCtrl = LLUICtrlFactory::create<LLChicletInvOfferIconCtrl>(icon_params);
  1630. addChild(mChicletIconCtrl);
  1631. sendChildToFront(mNewMessagesIcon);
  1632. }
  1633. void LLInvOfferChiclet::setSessionId(const LLUUID& session_id)
  1634. {
  1635. setShowNewMessagesIcon( getSessionId() != session_id );
  1636. setToolTip(LLScriptFloaterManager::getObjectName(session_id));
  1637. LLIMChiclet::setSessionId(session_id);
  1638. LLNotificationPtr notification = LLNotifications::getInstance()->find(session_id);
  1639. if ( notification && notification->getName() == INVENTORY_USER_OFFER )
  1640. {
  1641. mChicletIconCtrl->setValue(notification->getPayload()["from_id"]);
  1642. }
  1643. else
  1644. {
  1645. mChicletIconCtrl->setValue(LLUUID::null);
  1646. }
  1647. }
  1648. void LLInvOfferChiclet::setCounter(S32 counter)
  1649. {
  1650. setShowNewMessagesIcon( counter > 0 );
  1651. }
  1652. void LLInvOfferChiclet::onMouseDown()
  1653. {
  1654. LLScriptFloaterManager::instance().toggleScriptFloater(getSessionId());
  1655. }
  1656. // EOF