PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llsplitbutton.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 266 lines | 175 code | 55 blank | 36 comment | 17 complexity | a8769c22ed907282c4748dc6f4c30046 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llsplitbutton.cpp
  3. * @brief LLSplitButton base class
  4. *
  5. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. // A control that consolidates several buttons as options
  27. #include "llviewerprecompiledheaders.h"
  28. #include "llsplitbutton.h"
  29. #include "llinitparam.h"
  30. #include "llpanel.h"
  31. #include "llfocusmgr.h"
  32. #include "llviewerwindow.h"
  33. #include "llrootview.h"
  34. S32 BUTTON_PAD = 2; //pad between buttons on an items panel
  35. static LLDefaultChildRegistry::Register<LLSplitButton> split_button("split_button");
  36. void LLSplitButton::ArrowPositionValues::declareValues()
  37. {
  38. declare("left", LEFT);
  39. declare("right", RIGHT);
  40. }
  41. LLSplitButton::ItemParams::ItemParams()
  42. {
  43. }
  44. LLSplitButton::Params::Params()
  45. : arrow_position("arrow_position", LEFT),
  46. items("item"),
  47. arrow_button("arrow_button"),
  48. items_panel("items_panel")
  49. {
  50. }
  51. void LLSplitButton::onFocusLost()
  52. {
  53. hideButtons();
  54. LLUICtrl::onFocusLost();
  55. }
  56. void LLSplitButton::setFocus(BOOL b)
  57. {
  58. LLUICtrl::setFocus(b);
  59. if (b)
  60. {
  61. if (mItemsPanel && mItemsPanel->getVisible())
  62. {
  63. mItemsPanel->setFocus(TRUE);
  64. }
  65. }
  66. }
  67. void LLSplitButton::setEnabled(BOOL enabled)
  68. {
  69. LLView::setEnabled(enabled);
  70. mArrowBtn->setEnabled(enabled);
  71. }
  72. void LLSplitButton::onArrowBtnDown()
  73. {
  74. if (!mItemsPanel->getVisible())
  75. {
  76. showButtons();
  77. setFocus(TRUE);
  78. if (mArrowBtn->hasMouseCapture() || mShownItem->hasMouseCapture())
  79. {
  80. gFocusMgr.setMouseCapture(this);
  81. }
  82. }
  83. else
  84. {
  85. hideButtons();
  86. }
  87. }
  88. void LLSplitButton::onHeldDownShownButton()
  89. {
  90. if (!mItemsPanel->getVisible()) onArrowBtnDown();
  91. }
  92. void LLSplitButton::onItemSelected(LLUICtrl* ctrl)
  93. {
  94. if (!ctrl) return;
  95. hideButtons();
  96. // call the callback if it exists
  97. if(!mSelectionCallback.empty())
  98. {
  99. mSelectionCallback(this, ctrl->getName());
  100. }
  101. gFocusMgr.setKeyboardFocus(NULL);
  102. }
  103. BOOL LLSplitButton::handleMouseUp(S32 x, S32 y, MASK mask)
  104. {
  105. gFocusMgr.setMouseCapture(NULL);
  106. if (mShownItem->parentPointInView(x, y))
  107. {
  108. onItemSelected(mShownItem);
  109. return TRUE;
  110. }
  111. for (std::list<LLButton*>::const_iterator it = mHidenItems.begin(); it != mHidenItems.end(); ++it)
  112. {
  113. LLButton* item = *it;
  114. S32 panel_x = 0;
  115. S32 panel_y = 0;
  116. localPointToOtherView(x, y, &panel_x, &panel_y, mItemsPanel);
  117. if (item->parentPointInView(panel_x, panel_y))
  118. {
  119. onItemSelected(item);
  120. return TRUE;
  121. }
  122. }
  123. return TRUE;
  124. }
  125. void LLSplitButton::showButtons()
  126. {
  127. mItemsPanel->setOrigin(0, getRect().getHeight());
  128. // register ourselves as a "top" control
  129. // effectively putting us into a special draw layer
  130. gViewerWindow->addPopup(this);
  131. mItemsPanel->setFocus(TRUE);
  132. //push arrow button down and show the item buttons
  133. mArrowBtn->setToggleState(TRUE);
  134. mItemsPanel->setVisible(TRUE);
  135. setUseBoundingRect(TRUE);
  136. }
  137. void LLSplitButton::hideButtons()
  138. {
  139. mItemsPanel->setVisible(FALSE);
  140. mArrowBtn->setToggleState(FALSE);
  141. setUseBoundingRect(FALSE);
  142. gViewerWindow->removePopup(this);
  143. }
  144. // protected/private
  145. LLSplitButton::LLSplitButton(const LLSplitButton::Params& p)
  146. : LLUICtrl(p),
  147. mArrowBtn(NULL),
  148. mShownItem(NULL),
  149. mItemsPanel(NULL),
  150. mArrowPosition(p.arrow_position)
  151. {
  152. LLRect rc(p.rect);
  153. LLButton::Params arrow_params = p.arrow_button;
  154. S32 arrow_width = p.arrow_button.rect.width;
  155. //Default arrow rect values for LEFT arrow position
  156. S32 arrow_left = 0;
  157. S32 arrow_right = arrow_width;
  158. S32 btn_left = arrow_width;
  159. S32 btn_right = rc.getWidth();
  160. if (mArrowPosition == RIGHT)
  161. {
  162. arrow_left = rc.getWidth()- arrow_width;
  163. arrow_right = rc.getWidth();
  164. btn_left = 0;
  165. btn_right = arrow_left;
  166. }
  167. arrow_params.rect(LLRect(arrow_left, rc.getHeight(), arrow_right, 0));
  168. arrow_params.label("");
  169. arrow_params.mouse_down_callback.function(boost::bind(&LLSplitButton::onArrowBtnDown, this));
  170. mArrowBtn = LLUICtrlFactory::create<LLButton>(arrow_params);
  171. addChild(mArrowBtn);
  172. //a panel for hidden item buttons
  173. LLPanel::Params panel_params = p.items_panel;
  174. mItemsPanel= prepareItemsPanel(panel_params, p.items.numValidElements());
  175. addChild(mItemsPanel);
  176. LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items.begin();
  177. //processing shown item button
  178. mShownItem = prepareItemButton(*it);
  179. mShownItem->setHeldDownCallback(boost::bind(&LLSplitButton::onHeldDownShownButton, this));
  180. mShownItem->setMouseUpCallback(boost::bind(&LLSplitButton::onItemSelected, this, _1));
  181. mShownItem->setRect(LLRect(btn_left, rc.getHeight(), btn_right, 0));
  182. addChild(mShownItem);
  183. //processing hidden item buttons
  184. S32 item_top = mItemsPanel->getRect().getHeight();
  185. for (++it; it != p.items.end(); ++it)
  186. {
  187. LLButton* hidden_button = prepareItemButton(*it);
  188. hidden_button->setRect(LLRect(btn_left, item_top, btn_right, item_top - rc.getHeight()));
  189. hidden_button->setMouseDownCallback(boost::bind(&LLSplitButton::onItemSelected, this, _1));
  190. mHidenItems.push_back(hidden_button);
  191. mItemsPanel->addChild(hidden_button);
  192. //calculate next button's top
  193. item_top -= (rc.getHeight() + BUTTON_PAD);
  194. }
  195. setTopLostCallback(boost::bind(&LLSplitButton::hideButtons, this));
  196. }
  197. LLButton* LLSplitButton::prepareItemButton(LLButton::Params params)
  198. {
  199. params.label("");
  200. params.is_toggle(false);
  201. return LLUICtrlFactory::create<LLButton>(params);
  202. }
  203. LLPanel* LLSplitButton::prepareItemsPanel(LLPanel::Params params, S32 items_count)
  204. {
  205. S32 num_hiden_btns = items_count - 1;
  206. S32 panel_height = num_hiden_btns * (getRect().getHeight() + BUTTON_PAD);
  207. params.visible(false);
  208. params.rect.width(getRect().getWidth());
  209. params.rect.height(panel_height);
  210. return LLUICtrlFactory::create<LLPanel>(params);
  211. }