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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llbottomtray.cpp
  3.  * @brief LLBottomTray class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-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. #define LLBOTTOMTRAY_CPP
  34. #include "llbottomtray.h"
  35. #include "llagent.h"
  36. #include "llchiclet.h"
  37. #include "llfloaterreg.h"
  38. #include "llflyoutbutton.h"
  39. #include "llimfloater.h" // for LLIMFloater
  40. #include "lllayoutstack.h"
  41. #include "llnearbychatbar.h"
  42. #include "llnotificationsutil.h"
  43. #include "llspeakbutton.h"
  44. #include "llsplitbutton.h"
  45. #include "llsyswellwindow.h"
  46. #include "llfloatercamera.h"
  47. #include "lltexteditor.h"
  48. #include "llnotifications.h"
  49. // Build time optimization, generate extern template once in .cpp file
  50. template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();
  51. namespace
  52. {
  53. const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel";
  54. const std::string& PANEL_CHATBAR_NAME = "chat_bar";
  55. const std::string& PANEL_MOVEMENT_NAME = "movement_panel";
  56. const std::string& PANEL_CAMERA_NAME = "cam_panel";
  57. const std::string& PANEL_GESTURE_NAME = "gesture_panel";
  58. S32 get_panel_min_width(LLLayoutStack* stack, LLPanel* panel)
  59. {
  60. S32 minimal_width = 0;
  61. llassert(stack);
  62. if ( stack && panel && panel->getVisible() )
  63. {
  64. stack->getPanelMinSize(panel->getName(), &minimal_width, NULL);
  65. }
  66. return minimal_width;
  67. }
  68. S32 get_curr_width(LLUICtrl* ctrl)
  69. {
  70. S32 cur_width = 0;
  71. if ( ctrl && ctrl->getVisible() )
  72. {
  73. cur_width = ctrl->getRect().getWidth();
  74. }
  75. return cur_width;
  76. }
  77. }
  78. class LLBottomTrayLite
  79. : public LLPanel
  80. {
  81. public:
  82. LLBottomTrayLite()
  83. : mNearbyChatBar(NULL),
  84.   mGesturePanel(NULL)
  85. {
  86. mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
  87. LLUICtrlFactory::getInstance()->buildPanel(this, "panel_bottomtray_lite.xml");
  88. // Necessary for focus movement among child controls
  89. setFocusRoot(TRUE);
  90. }
  91. BOOL postBuild()
  92. {
  93. mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar");
  94. mGesturePanel = getChild<LLPanel>("gesture_panel");
  95. // Hide "show_nearby_chat" button 
  96. LLLineEditor* chat_box = mNearbyChatBar->getChatBox();
  97. LLUICtrl* show_btn = mNearbyChatBar->getChild<LLUICtrl>("show_nearby_chat");
  98. S32 delta_width = show_btn->getRect().getWidth();
  99. show_btn->setVisible(FALSE);
  100. chat_box->reshape(chat_box->getRect().getWidth() + delta_width, chat_box->getRect().getHeight());
  101. return TRUE;
  102. }
  103. void onFocusLost()
  104. {
  105. if (gAgent.cameraMouselook())
  106. {
  107. LLBottomTray::getInstance()->setVisible(FALSE);
  108. }
  109. }
  110. LLNearbyChatBar* mNearbyChatBar;
  111. LLPanel* mGesturePanel;
  112. };
  113. LLBottomTray::LLBottomTray(const LLSD&)
  114. : mChicletPanel(NULL),
  115. mSpeakPanel(NULL),
  116. mSpeakBtn(NULL),
  117. mNearbyChatBar(NULL),
  118. mToolbarStack(NULL)
  119. , mMovementButton(NULL)
  120. , mResizeState(RS_NORESIZE)
  121. , mBottomTrayContextMenu(NULL)
  122. , mMovementPanel(NULL)
  123. , mCamPanel(NULL)
  124. , mSnapshotPanel(NULL)
  125. , mGesturePanel(NULL)
  126. , mCamButton(NULL)
  127. , mBottomTrayLite(NULL)
  128. , mIsInLiteMode(false)
  129. {
  130. // Firstly add ourself to IMSession observers, so we catch session events
  131. // before chiclets do that.
  132. LLIMMgr::getInstance()->addSessionObserver(this);
  133. mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
  134. LLUICtrlFactory::getInstance()->buildPanel(this,"panel_bottomtray.xml");
  135. mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
  136. mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1));
  137. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraPresets, _2));
  138. //this is to fix a crash that occurs because LLBottomTray is a singleton
  139. //and thus is deleted at the end of the viewers lifetime, but to be cleanly
  140. //destroyed LLBottomTray requires some subsystems that are long gone
  141. //LLUI::getRootView()->addChild(this);
  142. initStateProcessedObjectMap();
  143. // Necessary for focus movement among child controls
  144. setFocusRoot(TRUE);
  145. {
  146. mBottomTrayLite = new LLBottomTrayLite();
  147. mBottomTrayLite->setFollowsAll();
  148. mBottomTrayLite->setVisible(FALSE);
  149. }
  150. }
  151. LLBottomTray::~LLBottomTray()
  152. {
  153. if (!LLSingleton<LLIMMgr>::destroyed())
  154. {
  155. LLIMMgr::getInstance()->removeSessionObserver(this);
  156. }
  157. }
  158. void LLBottomTray::onChicletClick(LLUICtrl* ctrl)
  159. {
  160. LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(ctrl);
  161. if (chiclet)
  162. {
  163. // Until you can type into an IM Window and have a conversation,
  164. // still show the old communicate window
  165. //LLFloaterReg::showInstance("communicate", chiclet->getSessionId());
  166. // Show after comm window so it is frontmost (and hence will not
  167. // auto-hide)
  168. // this logic has been moved to LLIMChiclet::handleMouseDown
  169. // LLIMFloater::show(chiclet->getSessionId());
  170. // chiclet->setCounter(0);
  171. }
  172. }
  173. // *TODO Vadim: why void* ?
  174. void* LLBottomTray::createNearbyChatBar(void* userdata)
  175. {
  176. return new LLNearbyChatBar();
  177. }
  178. LLNearbyChatBar* LLBottomTray::getNearbyChatBar()
  179. {
  180. return mIsInLiteMode ? mBottomTrayLite->mNearbyChatBar : mNearbyChatBar;
  181. }
  182. LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
  183. {
  184. LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id);
  185. switch (im_chiclet_type)
  186. {
  187. case LLIMChiclet::TYPE_IM:
  188. return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
  189. case LLIMChiclet::TYPE_GROUP:
  190. return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
  191. case LLIMChiclet::TYPE_AD_HOC:
  192. return getChicletPanel()->createChiclet<LLAdHocChiclet>(session_id);
  193. case LLIMChiclet::TYPE_UNKNOWN:
  194. break;
  195. }
  196. return NULL;
  197. }
  198. //virtual
  199. void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
  200. {
  201. if (!getChicletPanel()) return;
  202. LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
  203. if (!session) return;
  204. // no need to spawn chiclets for participants in P2P calls called through Avaline
  205. if (session->isP2P() && session->isOtherParticipantAvaline()) return;
  206. if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;
  207. LLIMChiclet* chiclet = createIMChiclet(session_id);
  208. if(chiclet)
  209. {
  210. chiclet->setIMSessionName(name);
  211. chiclet->setOtherParticipantId(other_participant_id);
  212. LLIMFloater::onIMChicletCreated(session_id);
  213. }
  214. else
  215. {
  216. llerrs << "Could not create chiclet" << llendl;
  217. }
  218. }
  219. //virtual
  220. void LLBottomTray::sessionRemoved(const LLUUID& session_id)
  221. {
  222. if(getChicletPanel())
  223. {
  224. // IM floater should be closed when session removed and associated chiclet closed
  225. LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>(
  226. "impanel", session_id);
  227. if (iMfloater != NULL)
  228. {
  229. iMfloater->closeFloater();
  230. }
  231. getChicletPanel()->removeChiclet(session_id);
  232. }
  233. }
  234. void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
  235. {
  236. //this is only needed in case of outgoing ad-hoc/group chat sessions
  237. LLChicletPanel* chiclet_panel = getChicletPanel();
  238. if (chiclet_panel)
  239. {
  240. //it should be ad-hoc im chiclet or group im chiclet
  241. LLChiclet* chiclet = chiclet_panel->findChiclet<LLChiclet>(old_session_id);
  242. if (chiclet) chiclet->setSessionId(new_session_id);
  243. }
  244. }
  245. S32 LLBottomTray::getTotalUnreadIMCount()
  246. {
  247. return getChicletPanel()->getTotalUnreadIMCount();
  248. }
  249. // virtual
  250. void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, bool proximal)
  251. {
  252. // Time it takes to connect to voice channel might be pretty long,
  253. // so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED.
  254. BOOL enable = FALSE;
  255. switch (status)
  256. {
  257. // Do not add STATUS_VOICE_ENABLED because voice chat is 
  258. // inactive until STATUS_JOINED
  259. case STATUS_JOINED:
  260. enable = TRUE;
  261. break;
  262. default:
  263. enable = FALSE;
  264. break;
  265. }
  266. // We have to enable/disable right and left parts of speak button separately (EXT-4648)
  267. mSpeakBtn->setSpeakBtnEnabled(enable);
  268. // skipped to avoid button blinking
  269. if (status != STATUS_JOINING && status!= STATUS_LEFT_CHANNEL)
  270. {
  271. mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
  272. }
  273. }
  274. void LLBottomTray::onMouselookModeOut()
  275. {
  276. mIsInLiteMode = false;
  277. mBottomTrayLite->setVisible(FALSE);
  278. mNearbyChatBar->getChatBox()->setText(mBottomTrayLite->mNearbyChatBar->getChatBox()->getText());
  279. setVisible(TRUE);
  280. }
  281. void LLBottomTray::onMouselookModeIn()
  282. {
  283. setVisible(FALSE);
  284. // Attach the lite bottom tray
  285. if (getParent() && mBottomTrayLite->getParent() != getParent())
  286. getParent()->addChild(mBottomTrayLite);
  287. mBottomTrayLite->setShape(getLocalRect());
  288. mBottomTrayLite->mNearbyChatBar->getChatBox()->setText(mNearbyChatBar->getChatBox()->getText());
  289. mBottomTrayLite->mGesturePanel->setVisible(gSavedSettings.getBOOL("ShowGestureButton"));
  290. mIsInLiteMode = true;
  291. }
  292. //virtual
  293. // setVisible used instead of onVisibilityChange, since LLAgent calls it on entering/leaving mouselook mode.
  294. // If bottom tray is already visible in mouselook mode, then onVisibilityChange will not be called from setVisible(true),
  295. void LLBottomTray::setVisible(BOOL visible)
  296. {
  297. if (mIsInLiteMode)
  298. {
  299. mBottomTrayLite->setVisible(visible);
  300. }
  301. else 
  302. {
  303. LLPanel::setVisible(visible);
  304. }
  305. if(visible)
  306. gFloaterView->setSnapOffsetBottom(getRect().getHeight());
  307. else
  308. gFloaterView->setSnapOffsetBottom(0);
  309. }
  310. void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask)
  311. {
  312. // We should show BottomTrayContextMenu in last  turn
  313. if (mBottomTrayContextMenu && !LLMenuGL::sMenuContainer->getVisibleMenu())
  314. {
  315.     //there are no other context menu (IM chiclet etc ), so we can show BottomTrayContextMenu
  316.     updateContextMenu(x, y, mask);
  317. mBottomTrayContextMenu->buildDrawLabels();
  318. mBottomTrayContextMenu->updateParent(LLMenuGL::sMenuContainer);
  319. LLMenuGL::showPopup(this, mBottomTrayContextMenu, x, y);
  320. }
  321. }
  322. void LLBottomTray::updateContextMenu(S32 x, S32 y, MASK mask)
  323. {
  324. LLUICtrl* edit_box = mNearbyChatBar->getChild<LLUICtrl>("chat_box");
  325. S32 local_x = x - mNearbyChatBar->getRect().mLeft - edit_box->getRect().mLeft;
  326. S32 local_y = y - mNearbyChatBar->getRect().mBottom - edit_box->getRect().mBottom;
  327. bool in_edit_box = edit_box->pointInView(local_x, local_y);
  328. LLMenuItemGL* menu_item;
  329. menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Cut");
  330. if(menu_item)
  331. menu_item->setVisible(in_edit_box);
  332. menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Copy");
  333. if(menu_item)
  334. menu_item->setVisible(in_edit_box);
  335. menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Paste");
  336. if(menu_item)
  337. menu_item->setVisible(in_edit_box);
  338. menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Delete");
  339. if(menu_item)
  340. menu_item->setVisible(in_edit_box);
  341. menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Select_All");
  342. if(menu_item)
  343. menu_item->setVisible(in_edit_box);
  344. }
  345. void LLBottomTray::showGestureButton(BOOL visible)
  346. {
  347. setTrayButtonVisibleIfPossible(RS_BUTTON_GESTURES, visible);
  348. }
  349. void LLBottomTray::showMoveButton(BOOL visible)
  350. {
  351. setTrayButtonVisibleIfPossible(RS_BUTTON_MOVEMENT, visible);
  352. }
  353. void LLBottomTray::showCameraButton(BOOL visible)
  354. {
  355. setTrayButtonVisibleIfPossible(RS_BUTTON_CAMERA, visible);
  356. }
  357. void LLBottomTray::showSnapshotButton(BOOL visible)
  358. {
  359. setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible);
  360. }
  361. void LLBottomTray::toggleMovementControls()
  362. {
  363. if (mMovementButton)
  364. mMovementButton->onCommit();
  365. }
  366. void LLBottomTray::toggleCameraControls()
  367. {
  368. if (mCamButton)
  369. mCamButton->onCommit();
  370. }
  371. BOOL LLBottomTray::postBuild()
  372. {
  373. LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("NearbyChatBar.Action", boost::bind(&LLBottomTray::onContextMenuItemClicked, this, _2));
  374. LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("NearbyChatBar.EnableMenuItem", boost::bind(&LLBottomTray::onContextMenuItemEnabled, this, _2));
  375. mBottomTrayContextMenu =  LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_bottomtray.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  376. gMenuHolder->addChild(mBottomTrayContextMenu);
  377. mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar");
  378. mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
  379. mMovementPanel = getChild<LLPanel>("movement_panel");
  380. mMovementButton = mMovementPanel->getChild<LLButton>("movement_btn");
  381. mGesturePanel = getChild<LLPanel>("gesture_panel");
  382. mCamPanel = getChild<LLPanel>("cam_panel");
  383. mCamButton = mCamPanel->getChild<LLButton>("camera_btn");
  384. mSnapshotPanel = getChild<LLPanel>("snapshot_panel");
  385. setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
  386. mSpeakPanel = getChild<LLPanel>("speak_panel");
  387. mSpeakBtn = getChild<LLSpeakButton>("talk");
  388. // Both parts of speak button should be initially disabled because
  389. // it takes some time between logging in to world and connecting to voice channel.
  390. mSpeakBtn->setSpeakBtnEnabled(false);
  391. mSpeakBtn->setFlyoutBtnEnabled(false);
  392. // Localization tool doesn't understand custom buttons like <talk_button>
  393. mSpeakBtn->setSpeakToolTip( getString("SpeakBtnToolTip") );
  394. mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") );
  395. // Registering Chat Bar to receive Voice client status change notifications.
  396. gVoiceClient->addObserver(this);
  397. mObjectDefaultWidthMap[RS_BUTTON_GESTURES] = mGesturePanel->getRect().getWidth();
  398. mObjectDefaultWidthMap[RS_BUTTON_MOVEMENT] = mMovementPanel->getRect().getWidth();
  399. mObjectDefaultWidthMap[RS_BUTTON_CAMERA]   = mCamPanel->getRect().getWidth();
  400. mObjectDefaultWidthMap[RS_BUTTON_SPEAK]    = mSpeakPanel->getRect().getWidth();
  401. mNearbyChatBar->getChatBox()->setContextMenu(NULL);
  402. return TRUE;
  403. }
  404. bool LLBottomTray::onContextMenuItemEnabled(const LLSD& userdata)
  405. {
  406. std::string item = userdata.asString();
  407. LLLineEditor* edit_box = mNearbyChatBar->findChild<LLLineEditor>("chat_box");
  408. if (item == "can_cut")
  409. {
  410. return edit_box->canCut();
  411. }
  412. else if (item == "can_copy")
  413. {
  414. return edit_box->canCopy();
  415. }
  416. else if (item == "can_paste")
  417. {
  418. return edit_box->canPaste();
  419. }
  420. else if (item == "can_delete")
  421. {
  422. return edit_box->canDoDelete();
  423. }
  424. else if (item == "can_select_all")
  425. {
  426. return edit_box->canSelectAll() && (edit_box->getLength()>0);
  427. }
  428. return true;
  429. }
  430. void LLBottomTray::onContextMenuItemClicked(const LLSD& userdata)
  431. {
  432. std::string item = userdata.asString();
  433. LLLineEditor* edit_box = mNearbyChatBar->findChild<LLLineEditor>("chat_box");
  434. if (item == "cut")
  435. {
  436. edit_box->cut();
  437. }
  438. else if (item == "copy")
  439. {
  440. edit_box->copy();
  441. }
  442. else if (item == "paste")
  443. {
  444. edit_box->paste();
  445. edit_box->setFocus(TRUE);
  446. }
  447. else if (item == "delete")
  448. {
  449. edit_box->doDelete();
  450. }
  451. else if (item == "select_all")
  452. {
  453. edit_box->selectAll();
  454. }
  455. }
  456. void LLBottomTray::log(LLView* panel, const std::string& descr)
  457. {
  458. if (NULL == panel) return;
  459. LLView* layout = panel->getParent();
  460. lldebugs << descr << ": "
  461. << "panel: " << panel->getName()
  462. << ", rect: " << panel->getRect()
  463.  
  464.  
  465. << "layout: " << layout->getName()
  466. << ", rect: " << layout->getRect()
  467. << llendl
  468. }
  469. void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent)
  470. {
  471. static S32 debug_calling_number = 0;
  472. lldebugs << "**************************************** " << ++debug_calling_number << llendl;
  473. S32 current_width = getRect().getWidth();
  474. S32 delta_width = width - current_width;
  475. lldebugs << "Reshaping: " 
  476. << ", width: " << width
  477. << ", cur width: " << current_width
  478. << ", delta_width: " << delta_width
  479. << ", called_from_parent: " << called_from_parent
  480. << llendl;
  481. if (mNearbyChatBar) log(mNearbyChatBar, "before");
  482. if (mChicletPanel) log(mChicletPanel, "before");
  483. // stores width size on which bottom tray is less than width required by its children. EXT-991
  484. static S32 extra_shrink_width = 0;
  485. bool should_be_reshaped = true;
  486. if (mChicletPanel && mToolbarStack && mNearbyChatBar)
  487. {
  488. // Firstly, update layout stack to ensure we deal with correct panel sizes.
  489. {
  490. BOOL saved_anim = mToolbarStack->getAnimate();
  491. // Set chiclet panel to be autoresized by default.
  492. mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE);
  493. // Disable animation to prevent layout updating in several frames.
  494. mToolbarStack->setAnimate(FALSE);
  495. // Force the updating of layout to reset panels collapse factor.
  496. mToolbarStack->updateLayout();
  497. // Restore animate state.
  498. mToolbarStack->setAnimate(saved_anim);
  499. }
  500. // bottom tray is narrowed
  501. if (delta_width < 0)
  502. {
  503. if (extra_shrink_width > 0)
  504. {
  505. // is world rect was extra shrunk and decreasing again only update this value
  506. // to delta_width negative
  507. extra_shrink_width -= delta_width; // use "-=" because delta_width is negative
  508. should_be_reshaped = false;
  509. }
  510. else
  511. {
  512. extra_shrink_width = processWidthDecreased(delta_width);
  513. // increase new width to extra_shrink_width value to not reshape less than bottom tray minimum
  514. width += extra_shrink_width;
  515. }
  516. }
  517. // bottom tray is widen
  518. else
  519. {
  520. if (extra_shrink_width > delta_width)
  521. {
  522. // Less than minimum width is more than increasing (delta_width) 
  523. // only reduce it value and make no reshape
  524. extra_shrink_width -= delta_width;
  525. should_be_reshaped = false;
  526. }
  527. else 
  528. {
  529. if (extra_shrink_width > 0)
  530. {
  531. // If we have some extra shrink width let's reduce delta_width & width
  532. delta_width -= extra_shrink_width;
  533. width -= extra_shrink_width;
  534. extra_shrink_width = 0;
  535. }
  536. processWidthIncreased(delta_width);
  537. }
  538. }
  539. }
  540. if (should_be_reshaped)
  541. {
  542. lldebugs << "Reshape all children with width: " << width << llendl;
  543. LLPanel::reshape(width, height, called_from_parent);
  544. }
  545. if (mNearbyChatBar) log(mNearbyChatBar, "after");
  546. if (mChicletPanel) log(mChicletPanel, "after");
  547. }
  548. S32 LLBottomTray::processWidthDecreased(S32 delta_width)
  549. {
  550. bool still_should_be_processed = true;
  551. const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
  552. const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
  553. if (chiclet_panel_width > chiclet_panel_min_width)
  554. {
  555. // we have some space to decrease chiclet panel
  556. S32 panel_delta_min = chiclet_panel_width - chiclet_panel_min_width;
  557. S32 delta_panel = llmin(-delta_width, panel_delta_min);
  558. lldebugs << "delta_width: " << delta_width
  559. << ", panel_delta_min: " << panel_delta_min
  560. << ", delta_panel: " << delta_panel
  561. << llendl;
  562. // is chiclet panel width enough to process resizing?
  563. delta_width += panel_delta_min;
  564. still_should_be_processed = delta_width < 0;
  565. mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - delta_panel, mChicletPanel->getParent()->getRect().getHeight());
  566. log(mChicletPanel, "after processing panel decreasing via chiclet panel");
  567. lldebugs << "RS_CHICLET_PANEL" 
  568. << ", delta_width: " << delta_width
  569. << llendl;
  570. }
  571. const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
  572. const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
  573. if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width)
  574. {
  575. // we have some space to decrease chatbar panel
  576. S32 panel_delta_min = chatbar_panel_width - chatbar_panel_min_width;
  577. S32 delta_panel = llmin(-delta_width, panel_delta_min);
  578. // whether chatbar panel width is enough to process resizing?
  579. delta_width += panel_delta_min;
  580. still_should_be_processed = delta_width < 0;
  581. mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mNearbyChatBar->getRect().getHeight());
  582. log(mNearbyChatBar, "after processing panel decreasing via nearby chatbar panel");
  583. lldebugs << "RS_CHATBAR_INPUT"
  584. << ", delta_panel: " << delta_panel
  585. << ", delta_width: " << delta_width
  586. << llendl;
  587. }
  588. S32 extra_shrink_width = 0;
  589. S32 buttons_freed_width = 0;
  590. if (still_should_be_processed)
  591. {
  592. processShrinkButtons(&delta_width, &buttons_freed_width);
  593. if (delta_width < 0)
  594. {
  595. processHideButton(RS_BUTTON_SNAPSHOT, &delta_width, &buttons_freed_width);
  596. }
  597. if (delta_width < 0)
  598. {
  599. processHideButton(RS_BUTTON_CAMERA, &delta_width, &buttons_freed_width);
  600. }
  601. if (delta_width < 0)
  602. {
  603. processHideButton(RS_BUTTON_MOVEMENT, &delta_width, &buttons_freed_width);
  604. }
  605. if (delta_width < 0)
  606. {
  607. processHideButton(RS_BUTTON_GESTURES, &delta_width, &buttons_freed_width);
  608. }
  609. if (delta_width < 0)
  610. {
  611. extra_shrink_width = -delta_width;
  612. llwarns << "There is no enough width to reshape all children: " 
  613. << extra_shrink_width << llendl;
  614. }
  615. if (buttons_freed_width > 0)
  616. {
  617. log(mNearbyChatBar, "before applying compensative width");
  618. mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() + buttons_freed_width, mNearbyChatBar->getRect().getHeight() );
  619. log(mNearbyChatBar, "after applying compensative width");
  620. lldebugs << buttons_freed_width << llendl;
  621. }
  622. }
  623. return extra_shrink_width;
  624. }
  625. void LLBottomTray::processWidthIncreased(S32 delta_width)
  626. {
  627. if (delta_width <= 0) return;
  628. const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
  629. const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
  630. const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
  631. const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
  632. const S32 chatbar_panel_max_width = mNearbyChatBar->getMaxWidth();
  633. const S32 chatbar_available_shrink_width = chatbar_panel_width - chatbar_panel_min_width;
  634. const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;
  635. // how many room we have to show hidden buttons
  636. S32 total_available_width = delta_width + chatbar_available_shrink_width + available_width_chiclet;
  637. lldebugs << "Processing extending, available width:"
  638. << ", chatbar - " << chatbar_available_shrink_width
  639. << ", chiclets - " << available_width_chiclet
  640. << ", total - " << total_available_width
  641. << llendl;
  642. S32 available_width = total_available_width;
  643. if (available_width > 0)
  644. {
  645. processShowButton(RS_BUTTON_GESTURES, &available_width);
  646. }
  647. if (available_width > 0)
  648. {
  649. processShowButton(RS_BUTTON_MOVEMENT, &available_width);
  650. }
  651. if (available_width > 0)
  652. {
  653. processShowButton(RS_BUTTON_CAMERA, &available_width);
  654. }
  655. if (available_width > 0)
  656. {
  657. processShowButton(RS_BUTTON_SNAPSHOT, &available_width);
  658. }
  659. processExtendButtons(&available_width);
  660. // if we have to show/extend some buttons but resized delta width is not enough...
  661. S32 processed_width = total_available_width - available_width;
  662. if (processed_width > delta_width)
  663. {
  664. // ... let's shrink nearby chat & chiclet panels
  665. S32 required_to_process_width = processed_width;
  666. // 1. use delta width of resizing
  667. required_to_process_width -= delta_width;
  668. // 2. use width available via decreasing of nearby chat panel
  669. S32 chatbar_shrink_width = required_to_process_width;
  670. if (chatbar_available_shrink_width < chatbar_shrink_width)
  671. {
  672. chatbar_shrink_width = chatbar_available_shrink_width;
  673. }
  674. log(mNearbyChatBar, "increase width: before applying compensative width");
  675. mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - chatbar_shrink_width, mNearbyChatBar->getRect().getHeight() );
  676. if (mNearbyChatBar) log(mNearbyChatBar, "after applying compensative width");
  677. lldebugs << chatbar_shrink_width << llendl;
  678. // 3. use width available via decreasing of chiclet panel
  679. required_to_process_width -= chatbar_shrink_width;
  680. if (required_to_process_width > 0)
  681. {
  682. mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_to_process_width, mChicletPanel->getParent()->getRect().getHeight());
  683. log(mChicletPanel, "after applying compensative width for chiclets: ");
  684. lldebugs << required_to_process_width << llendl;
  685. }
  686. }
  687. // shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels
  688. delta_width -= processed_width;
  689. // how many space can nearby chatbar take?
  690. S32 chatbar_panel_width_ = mNearbyChatBar->getRect().getWidth();
  691. if (delta_width > 0 && chatbar_panel_width_ < chatbar_panel_max_width)
  692. {
  693. S32 delta_panel_max = chatbar_panel_max_width - chatbar_panel_width_;
  694. S32 delta_panel = llmin(delta_width, delta_panel_max);
  695. lldebugs << "Unprocesed delta width: " << delta_width
  696. << ", can be applied to chatbar: " << delta_panel_max
  697. << ", will be applied: " << delta_panel
  698. << llendl;
  699. delta_width -= delta_panel_max;
  700. mNearbyChatBar->reshape(chatbar_panel_width_ + delta_panel, mNearbyChatBar->getRect().getHeight());
  701. log(mNearbyChatBar, "applied unprocessed delta width");
  702. }
  703. }
  704. bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* available_width)
  705. {
  706. lldebugs << "Trying to show object type: " << shown_object_type << llendl;
  707. LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
  708. if (NULL == panel)
  709. {
  710. lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
  711. return false;
  712. }
  713. bool can_be_shown = canButtonBeShown(shown_object_type);
  714. if (can_be_shown)
  715. {
  716. //validate if we have enough room to show this button
  717. const S32 required_width = panel->getRect().getWidth();
  718. can_be_shown = *available_width >= required_width;
  719. if (can_be_shown)
  720. {
  721. *available_width -= required_width;
  722. setTrayButtonVisible(shown_object_type, true);
  723. lldebugs << "processed object type: " << shown_object_type
  724. << ", rest available width: " << *available_width
  725. << llendl;
  726. mResizeState &= ~shown_object_type;
  727. }
  728. }
  729. return can_be_shown;
  730. }
  731. void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width)
  732. {
  733. lldebugs << "Trying to hide object type: " << processed_object_type << llendl;
  734. LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
  735. if (NULL == panel)
  736. {
  737. lldebugs << "There is no object to process for state: " << processed_object_type << llendl;
  738. return;
  739. }
  740. if (panel->getVisible())
  741. {
  742. *required_width += panel->getRect().getWidth();
  743. if (*required_width > 0)
  744. {
  745. *buttons_freed_width += *required_width;
  746. }
  747. setTrayButtonVisible(processed_object_type, false);
  748. mResizeState |= processed_object_type;
  749. lldebugs << "processing object type: " << processed_object_type
  750. << ", buttons_freed_width: " << *buttons_freed_width
  751. << llendl;
  752. }
  753. }
  754. void LLBottomTray::processShrinkButtons(S32* required_width, S32* buttons_freed_width)
  755. {
  756. processShrinkButton(RS_BUTTON_CAMERA, required_width);
  757. if (*required_width < 0)
  758. {
  759. processShrinkButton(RS_BUTTON_MOVEMENT, required_width);
  760. }
  761. if (*required_width < 0)
  762. {
  763. processShrinkButton(RS_BUTTON_GESTURES, required_width);
  764. }
  765. if (*required_width < 0)
  766. {
  767. S32 panel_min_width = 0;
  768. std::string panel_name = mSpeakPanel->getName();
  769. bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width, NULL);
  770. if (!success)
  771. {
  772. lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
  773. }
  774. else
  775. {
  776. //
  777. mSpeakBtn->setLabelVisible(false);
  778. S32 panel_width = mSpeakPanel->getRect().getWidth();
  779. S32 possible_shrink_width = panel_width - panel_min_width;
  780. if (possible_shrink_width > 0)
  781. {
  782. mSpeakPanel->reshape(panel_width - possible_shrink_width, mSpeakPanel->getRect().getHeight());
  783. *required_width += possible_shrink_width;
  784. if (*required_width > 0)
  785. {
  786. *buttons_freed_width += *required_width;
  787. }
  788. lldebugs << "Shrunk panel: " << panel_name
  789. << ", shrunk width: " << possible_shrink_width
  790. << ", rest width to process: " << *required_width
  791. << llendl;
  792. }
  793. }
  794. }
  795. }
  796. void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32* required_width)
  797. {
  798. LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
  799. if (NULL == panel)
  800. {
  801. lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
  802. return;
  803. }
  804. if (panel->getVisible())
  805. {
  806. S32 panel_width = panel->getRect().getWidth();
  807. S32 panel_min_width = 0;
  808. std::string panel_name = panel->getName();
  809. bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width, NULL);
  810. S32 possible_shrink_width = panel_width - panel_min_width;
  811. if (!success)
  812. {
  813. lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
  814. }
  815. // we have some space to free by shrinking the button
  816. else if (possible_shrink_width > 0)
  817. {
  818. // let calculate real width to shrink
  819. // 1. apply all possible width
  820. *required_width += possible_shrink_width;
  821. // 2. it it is too much... 
  822. if (*required_width > 0)
  823. {
  824. // reduce applied shrunk width to the excessive value.
  825. possible_shrink_width -= *required_width;
  826. *required_width = 0;
  827. }
  828. panel->reshape(panel_width - possible_shrink_width, panel->getRect().getHeight());
  829. lldebugs << "Shrunk panel: " << panel_name
  830. << ", shrunk width: " << possible_shrink_width
  831. << ", rest width to process: " << *required_width
  832. << llendl;
  833. }
  834. }
  835. }
  836. void LLBottomTray::processExtendButtons(S32* available_width)
  837. {
  838. // do not allow extending any buttons if we have some buttons hidden
  839. if (mResizeState & RS_BUTTONS_CAN_BE_HIDDEN) return;
  840. processExtendButton(RS_BUTTON_GESTURES, available_width);
  841. if (*available_width > 0)
  842. {
  843. processExtendButton(RS_BUTTON_CAMERA, available_width);
  844. }
  845. if (*available_width > 0)
  846. {
  847. processExtendButton(RS_BUTTON_MOVEMENT, available_width);
  848. }
  849. if (*available_width > 0)
  850. {
  851. S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK];
  852. S32 panel_width = mSpeakPanel->getRect().getWidth();
  853. S32 possible_extend_width = panel_max_width - panel_width;
  854. if (possible_extend_width > 0 && possible_extend_width <= *available_width)
  855. {
  856. mSpeakBtn->setLabelVisible(true);
  857. mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight());
  858. log(mSpeakBtn, "speak button is extended");
  859. *available_width -= possible_extend_width;
  860. lldebugs << "Extending panel: " << mSpeakPanel->getName()
  861. << ", extended width: " << possible_extend_width
  862. << ", rest width to process: " << *available_width
  863. << llendl;
  864. }
  865. }
  866. }
  867. void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32* available_width)
  868. {
  869. LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
  870. if (NULL == panel)
  871. {
  872. lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
  873. return;
  874. }
  875. if (!panel->getVisible()) return;
  876. S32 panel_max_width = mObjectDefaultWidthMap[processed_object_type];
  877. S32 panel_width = panel->getRect().getWidth();
  878. S32 possible_extend_width = panel_max_width - panel_width;
  879. if (possible_extend_width > 0)
  880. {
  881. // let calculate real width to extend
  882. // 1. apply all possible width
  883. *available_width -= possible_extend_width;
  884. // 2. it it is too much... 
  885. if (*available_width < 0)
  886. {
  887. // reduce applied extended width to the excessive value.
  888. possible_extend_width += *available_width;
  889. *available_width = 0;
  890. }
  891. panel->reshape(panel_width + possible_extend_width, panel->getRect().getHeight());
  892. lldebugs << "Extending panel: " << panel->getName()
  893. << ", extended width: " << possible_extend_width
  894. << ", rest width to process: " << *available_width
  895. << llendl;
  896. }
  897. }
  898. bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const
  899. {
  900. bool can_be_shown = mResizeState & processed_object_type;
  901. if (can_be_shown)
  902. {
  903. static MASK MOVEMENT_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES;
  904. static MASK CAMERA_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES | RS_BUTTON_MOVEMENT;
  905. static MASK SNAPSHOT_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES | RS_BUTTON_MOVEMENT | RS_BUTTON_CAMERA;
  906. switch(processed_object_type)
  907. {
  908. case RS_BUTTON_GESTURES: // Gestures should be shown first
  909. break;
  910. case RS_BUTTON_MOVEMENT: // Move only if gesture is shown
  911. can_be_shown = !(MOVEMENT_PREVIOUS_BUTTONS_MASK & mResizeState);
  912. break;
  913. case RS_BUTTON_CAMERA:
  914. can_be_shown = !(CAMERA_PREVIOUS_BUTTONS_MASK & mResizeState);
  915. break;
  916. case RS_BUTTON_SNAPSHOT:
  917. can_be_shown = !(SNAPSHOT_PREVIOUS_BUTTONS_MASK & mResizeState);
  918. break;
  919. default: // nothing to do here
  920. break;
  921. }
  922. }
  923. return can_be_shown;
  924. }
  925. void LLBottomTray::initStateProcessedObjectMap()
  926. {
  927. mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, mGesturePanel));
  928. mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, mMovementPanel));
  929. mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, mCamPanel));
  930. mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, mSnapshotPanel));
  931. mDummiesMap.insert(std::make_pair(RS_BUTTON_GESTURES, getChild<LLUICtrl>("after_gesture_panel")));
  932. mDummiesMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, getChild<LLUICtrl>("after_movement_panel")));
  933. mDummiesMap.insert(std::make_pair(RS_BUTTON_CAMERA,   getChild<LLUICtrl>("after_cam_panel")));
  934. mDummiesMap.insert(std::make_pair(RS_BUTTON_SPEAK,    getChild<LLUICtrl>("after_speak_panel")));
  935. }
  936. void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible)
  937. {
  938. LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
  939. if (NULL == panel)
  940. {
  941. lldebugs << "There is no object to show for state: " << shown_object_type << llendl;
  942. return;
  943. }
  944. panel->setVisible(visible);
  945. if (mDummiesMap.count(shown_object_type))
  946. {
  947. // Hide/show layout panel for dummy icon.
  948. mDummiesMap[shown_object_type]->getParent()->setVisible(visible);
  949. }
  950. }
  951. void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification)
  952. {
  953. if (!setVisibleAndFitWidths(shown_object_type, visible) && visible && raise_notification)
  954. {
  955. LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown",
  956.  LLSD(),
  957.  LLSD(),
  958.  LLNotificationFunctorRegistry::instance().DONOTHING);
  959. }
  960. }
  961. bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible)
  962. {
  963. LLPanel* cur_panel = mStateProcessedObjectMap[object_type];
  964. if (NULL == cur_panel)
  965. {
  966. lldebugs << "There is no object to process for state: " << object_type << llendl;
  967. return false;
  968. }
  969. const S32 dummy_width = mDummiesMap.count(object_type)
  970. ? mDummiesMap[object_type]->getParent()->getRect().getWidth()
  971. : 0;
  972. bool is_set = true;
  973. if (visible)
  974. {
  975. // Assume that only chiclet panel can be auto-resized and
  976. // don't take into account width of dummy widgets
  977. const S32 available_width =
  978. mChicletPanel->getParent()->getRect().getWidth() -
  979. mChicletPanel->getMinWidth() -
  980. dummy_width;
  981. S32 preferred_width = mObjectDefaultWidthMap[object_type];
  982. S32 current_width = cur_panel->getRect().getWidth();
  983. S32 result_width = 0;
  984. bool decrease_width = false;
  985. // Mark this button to be shown
  986. mResizeState |= object_type;
  987. if (preferred_width > 0 && available_width >= preferred_width)
  988. {
  989. result_width = preferred_width;
  990. }
  991. else if (available_width >= current_width)
  992. {
  993. result_width = current_width;
  994. }
  995. else
  996. {
  997. // Calculate the possible shrunk width as difference between current and minimal widths
  998. const S32 chatbar_shrunk_width =
  999. mNearbyChatBar->getRect().getWidth() - mNearbyChatBar->getMinWidth();
  1000. const S32 sum_of_min_widths =
  1001. get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_CAMERA])   +
  1002. get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_MOVEMENT]) +
  1003. get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_GESTURES]) +
  1004. get_panel_min_width(mToolbarStack, mSpeakPanel);
  1005. const S32 sum_of_curr_widths =
  1006. get_curr_width(mStateProcessedObjectMap[RS_BUTTON_CAMERA])   +
  1007. get_curr_width(mStateProcessedObjectMap[RS_BUTTON_MOVEMENT]) +
  1008. get_curr_width(mStateProcessedObjectMap[RS_BUTTON_GESTURES]) +
  1009. get_curr_width(mSpeakPanel);
  1010. const S32 possible_shrunk_width =
  1011. chatbar_shrunk_width + (sum_of_curr_widths - sum_of_min_widths);
  1012. // Minimal width of current panel
  1013. S32 minimal_width = 0;
  1014. mToolbarStack->getPanelMinSize(cur_panel->getName(), &minimal_width, NULL);
  1015. if ( (available_width + possible_shrunk_width) >= minimal_width)
  1016. {
  1017. // There is enough space for minimal width, but set the result_width
  1018. // to current_width so buttons widths decreasing will be done in predefined order
  1019. result_width = current_width;
  1020. decrease_width = true;
  1021. }
  1022. else
  1023. {
  1024. // Nothing can be done, give up...
  1025. return false;
  1026. }
  1027. }
  1028. if (result_width != current_width)
  1029. {
  1030. cur_panel->reshape(result_width, cur_panel->getRect().getHeight());
  1031. current_width = result_width;
  1032. }
  1033. is_set = processShowButton(object_type, &current_width);
  1034. // Shrink buttons if needed
  1035. if (is_set && decrease_width)
  1036. {
  1037. processWidthDecreased( -result_width - dummy_width );
  1038. }
  1039. }
  1040. else
  1041. {
  1042. const S32 delta_width = get_curr_width(cur_panel);
  1043. setTrayButtonVisible(object_type, false);
  1044. // Mark button NOT to show while future bottom tray extending
  1045. mResizeState &= ~object_type;
  1046. // Extend other buttons if need
  1047. if (delta_width)
  1048. {
  1049. processWidthIncreased(delta_width + dummy_width);
  1050. }
  1051. }
  1052. return is_set;
  1053. }
  1054. //EOF