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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llmultifloater.cpp
  3.  * @brief LLFloater that hosts other floaters
  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. // Floating "windows" within the GL display, like the inventory floater,
  33. // mini-map floater, etc.
  34. #include "linden_common.h"
  35. #include "llmultifloater.h"
  36. #include "llresizehandle.h"
  37. //
  38. // LLMultiFloater
  39. //
  40. LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params)
  41. : LLFloater(key),
  42.   mTabContainer(NULL),
  43.   mTabPos(LLTabContainer::TOP),
  44.   mAutoResize(TRUE),
  45.   mOrigMinWidth(0),
  46.   mOrigMinHeight(0)
  47. {
  48. }
  49. void LLMultiFloater::buildTabContainer()
  50. {
  51. const LLFloater::Params& default_params = LLFloater::getDefaultParams();
  52. S32 floater_header_size = default_params.header_height;
  53. LLTabContainer::Params p;
  54. p.name(std::string("Preview Tabs"));
  55. p.rect(LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - floater_header_size, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0));
  56. p.tab_position(mTabPos);
  57. p.follows.flags(FOLLOWS_ALL);
  58. p.commit_callback.function(boost::bind(&LLMultiFloater::onTabSelected, this));
  59. mTabContainer = LLUICtrlFactory::create<LLTabContainer>(p);
  60. addChild(mTabContainer);
  61. if (isResizable())
  62. {
  63. mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
  64. }
  65. }
  66. void LLMultiFloater::onOpen(const LLSD& key)
  67. {
  68. //  if (mTabContainer->getTabCount() <= 0)
  69. //  {
  70. //  // for now, don't allow multifloaters
  71. //  // without any child floaters
  72. //  closeFloater();
  73. //  }
  74. }
  75. void LLMultiFloater::draw()
  76. {
  77. if (mTabContainer->getTabCount() == 0)
  78. {
  79. //RN: could this potentially crash in draw hierarchy?
  80. closeFloater();
  81. }
  82. else
  83. {
  84. LLFloater::draw();
  85. }
  86. }
  87. BOOL LLMultiFloater::closeAllFloaters()
  88. {
  89. S32 tabToClose = 0;
  90. S32 lastTabCount = mTabContainer->getTabCount();
  91. while (tabToClose < mTabContainer->getTabCount())
  92. {
  93. LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose);
  94. first_floater->closeFloater();
  95. if(lastTabCount == mTabContainer->getTabCount())
  96. {
  97. //Tab did not actually close, possibly due to a pending Save Confirmation dialog..
  98. //so try and close the next one in the list...
  99. tabToClose++;
  100. }
  101. else
  102. {
  103. //Tab closed ok.
  104. lastTabCount = mTabContainer->getTabCount();
  105. }
  106. }
  107. if( mTabContainer->getTabCount() != 0 )
  108. return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE.
  109. return TRUE; //else all tabs were successfully closed...
  110. }
  111. void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
  112. {
  113. static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
  114. const LLFloater::Params& default_params = LLFloater::getDefaultParams();
  115. S32 floater_header_size = default_params.header_height;
  116. S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
  117. S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
  118. S32 new_height = llmax(getRect().getHeight(), content_height + floater_header_size + tabcntr_header_height);
  119.     if (isMinimized())
  120.     {
  121.         LLRect newrect;
  122.         newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height);
  123.         setExpandedRect(newrect);
  124.     }
  125. else
  126. {
  127. S32 old_height = getRect().getHeight();
  128. reshape(new_width, new_height);
  129. // keep top left corner in same position
  130. translate(0, old_height - new_height);
  131. }
  132. }
  133. /**
  134.   void addFloater(LLFloater* floaterp, BOOL select_added_floater)
  135.   Adds the LLFloater pointed to by floaterp to this.
  136.   If floaterp is already hosted by this, then it is re-added to get
  137.   new titles, etc.
  138.   If select_added_floater is true, the LLFloater pointed to by floaterp will
  139.   become the selected tab in this
  140.   Affects: mTabContainer, floaterp
  141. **/
  142. void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point)
  143. {
  144. if (!floaterp)
  145. {
  146. return;
  147. }
  148. if (!mTabContainer)
  149. {
  150. llerrs << "Tab Container used without having been initialized." << llendl;
  151. return;
  152. }
  153. if (floaterp->getHost() == this)
  154. {
  155. // already hosted by me, remove
  156. // do this so we get updated title, etc.
  157. mFloaterDataMap.erase(floaterp->getHandle());
  158. mTabContainer->removeTabPanel(floaterp);
  159. }
  160. else if (floaterp->getHost())
  161. {
  162. // floaterp is hosted by somebody else and
  163. // this is adding it, so remove it from it's old host
  164. floaterp->getHost()->removeFloater(floaterp);
  165. }
  166. else if (floaterp->getParent() == gFloaterView)
  167. {
  168. // rehost preview floater as child panel
  169. gFloaterView->removeChild(floaterp);
  170. }
  171. // store original configuration
  172. LLFloaterData floater_data;
  173. floater_data.mWidth = floaterp->getRect().getWidth();
  174. floater_data.mHeight = floaterp->getRect().getHeight();
  175. floater_data.mCanMinimize = floaterp->isMinimizeable();
  176. floater_data.mCanResize = floaterp->isResizable();
  177. // remove minimize and close buttons
  178. floaterp->setCanMinimize(FALSE);
  179. floaterp->setCanResize(FALSE);
  180. floaterp->setCanDrag(FALSE);
  181. floaterp->storeRectControl();
  182. // avoid double rendering of floater background (makes it more opaque)
  183. floaterp->setBackgroundVisible(FALSE);
  184. if (mAutoResize)
  185. {
  186. growToFit(floater_data.mWidth, floater_data.mHeight);
  187. }
  188. //add the panel, add it to proper maps
  189. mTabContainer->addTabPanel(
  190. LLTabContainer::TabPanelParams()
  191. .panel(floaterp)
  192. .label(floaterp->getShortTitle())
  193. .insert_at(insertion_point));
  194. mFloaterDataMap[floaterp->getHandle()] = floater_data;
  195. updateResizeLimits();
  196. if ( select_added_floater )
  197. {
  198. mTabContainer->selectTabPanel(floaterp);
  199. }
  200. else
  201. {
  202. // reassert visible tab (hiding new floater if necessary)
  203. mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
  204. }
  205. floaterp->setHost(this);
  206. if (isMinimized())
  207. {
  208. floaterp->setVisible(FALSE);
  209. }
  210. // Tabs sometimes overlap resize handle
  211. moveResizeHandlesToFront();
  212. }
  213. /**
  214. BOOL selectFloater(LLFloater* floaterp)
  215. If the LLFloater pointed to by floaterp is hosted by this,
  216. then its tab is selected and returns true.  Otherwise returns false.
  217. Affects: mTabContainer
  218. **/
  219. BOOL LLMultiFloater::selectFloater(LLFloater* floaterp)
  220. {
  221. return mTabContainer->selectTabPanel(floaterp);
  222. }
  223. // virtual
  224. void LLMultiFloater::selectNextFloater()
  225. {
  226. mTabContainer->selectNextTab();
  227. }
  228. // virtual
  229. void LLMultiFloater::selectPrevFloater()
  230. {
  231. mTabContainer->selectPrevTab();
  232. }
  233. void LLMultiFloater::showFloater(LLFloater* floaterp, LLTabContainer::eInsertionPoint insertion_point)
  234. {
  235. if(!floaterp) return;
  236. // we won't select a panel that already is selected
  237. // it is hard to do this internally to tab container
  238. // as tab selection is handled via index and the tab at a given
  239. // index might have changed
  240. if (floaterp != mTabContainer->getCurrentPanel() &&
  241. !mTabContainer->selectTabPanel(floaterp))
  242. {
  243. addFloater(floaterp, TRUE, insertion_point);
  244. }
  245. }
  246. void LLMultiFloater::removeFloater(LLFloater* floaterp)
  247. {
  248. if (!floaterp || floaterp->getHost() != this )
  249. return;
  250. floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle());
  251. if (found_data_it != mFloaterDataMap.end())
  252. {
  253. LLFloaterData& floater_data = found_data_it->second;
  254. floaterp->setCanMinimize(floater_data.mCanMinimize);
  255. if (!floater_data.mCanResize)
  256. {
  257. // restore original size
  258. floaterp->reshape(floater_data.mWidth, floater_data.mHeight);
  259. }
  260. floaterp->setCanResize(floater_data.mCanResize);
  261. mFloaterDataMap.erase(found_data_it);
  262. }
  263. mTabContainer->removeTabPanel(floaterp);
  264. floaterp->setBackgroundVisible(TRUE);
  265. floaterp->setCanDrag(TRUE);
  266. floaterp->setHost(NULL);
  267. floaterp->applyRectControl();
  268. updateResizeLimits();
  269. tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
  270. }
  271. void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click)
  272. {
  273. // default implementation does nothing
  274. }
  275. void LLMultiFloater::tabClose()
  276. {
  277. if (mTabContainer->getTabCount() == 0)
  278. {
  279. // no more children, close myself
  280. closeFloater();
  281. }
  282. }
  283. void LLMultiFloater::setVisible(BOOL visible)
  284. {
  285. // *FIX: shouldn't have to do this, fix adding to minimized multifloater
  286. LLFloater::setVisible(visible);
  287. if (mTabContainer)
  288. {
  289. LLPanel* cur_floaterp = mTabContainer->getCurrentPanel();
  290. if (cur_floaterp)
  291. {
  292. cur_floaterp->setVisible(visible);
  293. }
  294. // if no tab selected, and we're being shown,
  295. // select last tab to be added
  296. if (visible && !cur_floaterp)
  297. {
  298. mTabContainer->selectLastTab();
  299. }
  300. }
  301. }
  302. BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask)
  303. {
  304. if (key == 'W' && mask == MASK_CONTROL)
  305. {
  306. LLFloater* floater = getActiveFloater();
  307. // is user closeable and is system closeable
  308. if (floater && floater->canClose() && floater->isCloseable())
  309. {
  310. floater->closeFloater();
  311. }
  312. return TRUE;
  313. }
  314. return LLFloater::handleKeyHere(key, mask);
  315. }
  316. bool LLMultiFloater::addChild(LLView* child, S32 tab_group)
  317. {
  318. LLTabContainer* tab_container = dynamic_cast<LLTabContainer*>(child);
  319. if (tab_container)
  320. {
  321. // store pointer to tab container
  322. setTabContainer(tab_container);
  323. }
  324. // then go ahead and add child as usual
  325. return LLFloater::addChild(child, tab_group);
  326. }
  327. LLFloater* LLMultiFloater::getActiveFloater()
  328. {
  329. return (LLFloater*)mTabContainer->getCurrentPanel();
  330. }
  331. S32 LLMultiFloater::getFloaterCount()
  332. {
  333. return mTabContainer->getTabCount();
  334. }
  335. /**
  336. BOOL isFloaterFlashing(LLFloater* floaterp)
  337. Returns true if the LLFloater pointed to by floaterp
  338. is currently in a flashing state and is hosted by this.
  339. False otherwise.
  340. Requires: floaterp != NULL
  341. **/
  342. BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp)
  343. {
  344. if ( floaterp && floaterp->getHost() == this )
  345. return mTabContainer->getTabPanelFlashing(floaterp);
  346. return FALSE;
  347. }
  348. /**
  349. BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
  350. Sets the current flashing state of the LLFloater pointed
  351. to by floaterp to be the BOOL flashing if the LLFloater pointed
  352. to by floaterp is hosted by this.
  353. Requires: floaterp != NULL
  354. **/
  355. void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
  356. {
  357. if ( floaterp && floaterp->getHost() == this )
  358. mTabContainer->setTabPanelFlashing(floaterp, flashing);
  359. }
  360. void LLMultiFloater::onTabSelected()
  361. {
  362. LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getCurrentPanel());
  363. if (floaterp)
  364. {
  365. tabOpen(floaterp, true);
  366. }
  367. }
  368. void LLMultiFloater::setCanResize(BOOL can_resize)
  369. {
  370. LLFloater::setCanResize(can_resize);
  371. if (!mTabContainer) return;
  372. if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
  373. {
  374. mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
  375. }
  376. else
  377. {
  378. mTabContainer->setRightTabBtnOffset(0);
  379. }
  380. }
  381. BOOL LLMultiFloater::postBuild()
  382. {
  383. mCloseSignal.connect(boost::bind(&LLMultiFloater::closeAllFloaters, this));
  384. // remember any original xml minimum size
  385. getResizeLimits(&mOrigMinWidth, &mOrigMinHeight);
  386. if (mTabContainer)
  387. {
  388. return TRUE;
  389. }
  390. mTabContainer = getChild<LLTabContainer>("Preview Tabs");
  391. setCanResize(mResizable);
  392. return TRUE;
  393. }
  394. void LLMultiFloater::updateResizeLimits()
  395. {
  396. static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
  397. const LLFloater::Params& default_params = LLFloater::getDefaultParams();
  398. S32 floater_header_size = default_params.header_height;
  399. S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
  400. // initialize minimum size constraint to the original xml values.
  401. S32 new_min_width = mOrigMinWidth;
  402. S32 new_min_height = mOrigMinHeight;
  403. // possibly increase minimum size constraint due to children's minimums.
  404. for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
  405. {
  406. LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
  407. if (floaterp)
  408. {
  409. new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
  410. new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height);
  411. }
  412. }
  413. setResizeLimits(new_min_width, new_min_height);
  414. S32 cur_height = getRect().getHeight();
  415. S32 new_width = llmax(getRect().getWidth(), new_min_width);
  416. S32 new_height = llmax(getRect().getHeight(), new_min_height);
  417. if (isMinimized())
  418. {
  419. const LLRect& expanded = getExpandedRect();
  420. LLRect newrect;
  421. newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height));
  422. setExpandedRect(newrect);
  423. }
  424. else
  425. {
  426. reshape(new_width, new_height);
  427. // make sure upper left corner doesn't move
  428. translate(0, cur_height - getRect().getHeight());
  429. // make sure this window is visible on screen when it has been modified
  430. // (tab added, etc)
  431. gFloaterView->adjustToFitScreen(this, TRUE);
  432. }
  433. }