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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llsplitbutton.cpp
  3.  * @brief LLSplitButton base class
  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. // A control that consolidates several buttons as options
  33. #include "llviewerprecompiledheaders.h"
  34. #include "llsplitbutton.h"
  35. #include "llinitparam.h"
  36. #include "llpanel.h"
  37. #include "llfocusmgr.h"
  38. #include "llviewerwindow.h"
  39. #include "llrootview.h"
  40. S32 BUTTON_PAD = 2; //pad between buttons on an items panel
  41. static LLDefaultChildRegistry::Register<LLSplitButton> split_button("split_button");
  42. void LLSplitButton::ArrowPositionValues::declareValues()
  43. {
  44. declare("left", LEFT);
  45. declare("right", RIGHT);
  46. }
  47. LLSplitButton::ItemParams::ItemParams()
  48. {
  49. }
  50. LLSplitButton::Params::Params()
  51. : arrow_position("arrow_position", LEFT),
  52. items("item"),
  53. arrow_button("arrow_button"),
  54. items_panel("items_panel")
  55. {
  56. }
  57. void LLSplitButton::onFocusLost()
  58. {
  59. hideButtons();
  60. LLUICtrl::onFocusLost();
  61. }
  62. void LLSplitButton::setFocus(BOOL b)
  63. {
  64. LLUICtrl::setFocus(b);
  65. if (b)
  66. {
  67. if (mItemsPanel && mItemsPanel->getVisible())
  68. {
  69. mItemsPanel->setFocus(TRUE);
  70. }
  71. }
  72. }
  73. void LLSplitButton::setEnabled(BOOL enabled)
  74. {
  75. LLView::setEnabled(enabled);
  76. mArrowBtn->setEnabled(enabled);
  77. }
  78. void LLSplitButton::onArrowBtnDown()
  79. {
  80. if (!mItemsPanel->getVisible())
  81. {
  82. showButtons();
  83. setFocus(TRUE);
  84. if (mArrowBtn->hasMouseCapture() || mShownItem->hasMouseCapture())
  85. {
  86. gFocusMgr.setMouseCapture(this);
  87. }
  88. }
  89. else
  90. {
  91. hideButtons();
  92. }
  93. }
  94. void LLSplitButton::onHeldDownShownButton()
  95. {
  96. if (!mItemsPanel->getVisible()) onArrowBtnDown();
  97. }
  98. void LLSplitButton::onItemSelected(LLUICtrl* ctrl)
  99. {
  100. if (!ctrl) return;
  101. hideButtons();
  102. // call the callback if it exists
  103. if(!mSelectionCallback.empty())
  104. {
  105. mSelectionCallback(this, ctrl->getName());
  106. }
  107. gFocusMgr.setKeyboardFocus(NULL);
  108. }
  109. BOOL LLSplitButton::handleMouseUp(S32 x, S32 y, MASK mask)
  110. {
  111. gFocusMgr.setMouseCapture(NULL);
  112. if (mShownItem->parentPointInView(x, y))
  113. {
  114. onItemSelected(mShownItem);
  115. return TRUE;
  116. }
  117. for (std::list<LLButton*>::const_iterator it = mHidenItems.begin(); it != mHidenItems.end(); ++it)
  118. {
  119. LLButton* item = *it;
  120. S32 panel_x = 0;
  121. S32 panel_y = 0;
  122. localPointToOtherView(x, y, &panel_x, &panel_y, mItemsPanel);
  123. if (item->parentPointInView(panel_x, panel_y))
  124. {
  125. onItemSelected(item);
  126. return TRUE;
  127. }
  128. }
  129. return TRUE;
  130. }
  131. void LLSplitButton::showButtons()
  132. {
  133. mItemsPanel->setOrigin(0, getRect().getHeight());
  134. // register ourselves as a "top" control
  135. // effectively putting us into a special draw layer
  136. gFocusMgr.setTopCtrl(this);
  137. mItemsPanel->setFocus(TRUE);
  138. //push arrow button down and show the item buttons
  139. mArrowBtn->setToggleState(TRUE);
  140. mItemsPanel->setVisible(TRUE);
  141. setUseBoundingRect(TRUE);
  142. }
  143. void LLSplitButton::hideButtons()
  144. {
  145. mItemsPanel->setVisible(FALSE);
  146. mArrowBtn->setToggleState(FALSE);
  147. setUseBoundingRect(FALSE);
  148. if(gFocusMgr.getTopCtrl() == this)
  149. {
  150. gFocusMgr.setTopCtrl(NULL);
  151. }
  152. }
  153. // protected/private
  154. LLSplitButton::LLSplitButton(const LLSplitButton::Params& p)
  155. : LLUICtrl(p),
  156. mArrowBtn(NULL),
  157. mShownItem(NULL),
  158. mItemsPanel(NULL),
  159. mArrowPosition(p.arrow_position)
  160. {
  161. LLRect rc(p.rect);
  162. LLButton::Params arrow_params = p.arrow_button;
  163. S32 arrow_width = p.arrow_button.rect.width;
  164. //Default arrow rect values for LEFT arrow position
  165. S32 arrow_left = 0;
  166. S32 arrow_right = arrow_width;
  167. S32 btn_left = arrow_width;
  168. S32 btn_right = rc.getWidth();
  169. if (mArrowPosition == RIGHT)
  170. {
  171. arrow_left = rc.getWidth()- arrow_width;
  172. arrow_right = rc.getWidth();
  173. btn_left = 0;
  174. btn_right = arrow_left;
  175. }
  176. arrow_params.rect(LLRect(arrow_left, rc.getHeight(), arrow_right, 0));
  177. arrow_params.label("");
  178. arrow_params.mouse_down_callback.function(boost::bind(&LLSplitButton::onArrowBtnDown, this));
  179. mArrowBtn = LLUICtrlFactory::create<LLButton>(arrow_params);
  180. addChild(mArrowBtn);
  181. //a panel for hidden item buttons
  182. LLPanel::Params panel_params = p.items_panel;
  183. mItemsPanel= prepareItemsPanel(panel_params, p.items.numValidElements());
  184. addChild(mItemsPanel);
  185. LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items().begin();
  186. //processing shown item button
  187. mShownItem = prepareItemButton(*it);
  188. mShownItem->setHeldDownCallback(boost::bind(&LLSplitButton::onHeldDownShownButton, this));
  189. mShownItem->setMouseUpCallback(boost::bind(&LLSplitButton::onItemSelected, this, _1));
  190. mShownItem->setRect(LLRect(btn_left, rc.getHeight(), btn_right, 0));
  191. addChild(mShownItem);
  192. //processing hidden item buttons
  193. S32 item_top = mItemsPanel->getRect().getHeight();
  194. for (++it; it != p.items().end(); ++it)
  195. {
  196. LLButton* hidden_button = prepareItemButton(*it);
  197. hidden_button->setRect(LLRect(btn_left, item_top, btn_right, item_top - rc.getHeight()));
  198. hidden_button->setMouseDownCallback(boost::bind(&LLSplitButton::onItemSelected, this, _1));
  199. mHidenItems.push_back(hidden_button);
  200. mItemsPanel->addChild(hidden_button);
  201. //calculate next button's top
  202. item_top -= (rc.getHeight() + BUTTON_PAD);
  203. }
  204. setTopLostCallback(boost::bind(&LLSplitButton::hideButtons, this));
  205. }
  206. LLButton* LLSplitButton::prepareItemButton(LLButton::Params params)
  207. {
  208. params.label("");
  209. params.is_toggle(false);
  210. return LLUICtrlFactory::create<LLButton>(params); 
  211. }
  212. LLPanel* LLSplitButton::prepareItemsPanel(LLPanel::Params params, S32 items_count)
  213. {
  214. S32 num_hiden_btns = items_count - 1;
  215. S32 panel_height = num_hiden_btns * (getRect().getHeight() + BUTTON_PAD);
  216. params.visible(false);
  217. params.rect.width(getRect().getWidth());
  218. params.rect.height(panel_height);
  219. return LLUICtrlFactory::create<LLPanel>(params);
  220. }