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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llsliderctrl.cpp
  3.  * @brief LLSliderCtrl base class
  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 "linden_common.h"
  33. #include "llsliderctrl.h"
  34. #include "llmath.h"
  35. #include "llfontgl.h"
  36. #include "llgl.h"
  37. #include "llkeyboard.h"
  38. #include "lllineeditor.h"
  39. #include "llslider.h"
  40. #include "llstring.h"
  41. #include "lltextbox.h"
  42. #include "llui.h"
  43. #include "lluiconstants.h"
  44. #include "llcontrol.h"
  45. #include "llfocusmgr.h"
  46. #include "llresmgr.h"
  47. #include "lluictrlfactory.h"
  48. const U32 MAX_STRING_LENGTH = 10;
  49. static LLDefaultChildRegistry::Register<LLSliderCtrl> r("slider");
  50. LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
  51. : LLF32UICtrl(p),
  52. mLabelBox( NULL ),
  53. mEditor( NULL ),
  54. mTextBox( NULL ),
  55. mFont(p.font),
  56. mShowText(p.show_text),
  57. mCanEditText(p.can_edit_text),
  58. mPrecision(p.decimal_digits),
  59. mTextEnabledColor(p.text_color()),
  60. mTextDisabledColor(p.text_disabled_color())
  61. {
  62. S32 top = getRect().getHeight();
  63. S32 bottom = 0;
  64. S32 left = 0;
  65. S32 label_width = p.label_width;
  66. S32 text_width = p.text_width;
  67. // Label
  68. if( !p.label().empty() )
  69. {
  70. if (!p.label_width.isProvided())
  71. {
  72. label_width = p.font()->getWidth(p.label);
  73. }
  74. LLRect label_rect( left, top, label_width, bottom );
  75. LLTextBox::Params params(p.slider_label);
  76. params.rect.setIfNotProvided(label_rect);
  77. params.font.setIfNotProvided(p.font);
  78. params.initial_value(p.label());
  79. mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
  80. addChild(mLabelBox);
  81. }
  82. if (p.show_text && !p.text_width.isProvided())
  83. {
  84. // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
  85. if ( p.max_value )
  86. text_width = p.font()->getWidth(std::string("0")) * ( static_cast < S32 > ( log10  ( p.max_value ) ) + p.decimal_digits + 1 );
  87. if ( p.increment < 1.0f )
  88. text_width += p.font()->getWidth(std::string(".")); // (mostly) take account of decimal point in value
  89. if ( p.min_value < 0.0f || p.max_value < 0.0f )
  90. text_width += p.font()->getWidth(std::string("-")); // (mostly) take account of minus sign 
  91. // padding to make things look nicer
  92. text_width += 8;
  93. }
  94. S32 text_left = getRect().getWidth() - text_width;
  95. static LLUICachedControl<S32> sliderctrl_spacing ("UISliderctrlSpacing", 0);
  96. S32 slider_right = getRect().getWidth();
  97. if( p.show_text )
  98. {
  99. slider_right = text_left - sliderctrl_spacing;
  100. }
  101. S32 slider_left = label_width ? label_width + sliderctrl_spacing : 0;
  102. LLSlider::Params slider_p(p.slider_bar);
  103. slider_p.name("slider_bar");
  104. slider_p.rect.setIfNotProvided(LLRect(slider_left,top,slider_right,bottom));
  105. slider_p.initial_value.setIfNotProvided(p.initial_value().asReal());
  106. slider_p.min_value.setIfNotProvided(p.min_value);
  107. slider_p.max_value.setIfNotProvided(p.max_value);
  108. slider_p.increment.setIfNotProvided(p.increment);
  109. slider_p.orientation.setIfNotProvided(p.orientation);
  110. slider_p.commit_callback.function(&LLSliderCtrl::onSliderCommit);
  111. slider_p.control_name(p.control_name);
  112. slider_p.mouse_down_callback( p.mouse_down_callback );
  113. slider_p.mouse_up_callback( p.mouse_up_callback );
  114. mSlider = LLUICtrlFactory::create<LLSlider> (slider_p);
  115. addChild( mSlider );
  116. if( p.show_text() )
  117. {
  118. LLRect text_rect( text_left, top, getRect().getWidth(), bottom );
  119. if( p.can_edit_text() )
  120. {
  121. LLLineEditor::Params line_p(p.value_editor);
  122. line_p.rect.setIfNotProvided(text_rect);
  123. line_p.font.setIfNotProvided(p.font);
  124. line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit);
  125. line_p.prevalidate_callback(&LLTextValidate::validateFloat);
  126. mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p);
  127. mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this ));
  128. // don't do this, as selecting the entire text is single clicking in some cases
  129. // and double clicking in others
  130. //mEditor->setSelectAllonFocusReceived(TRUE);
  131. addChild(mEditor);
  132. }
  133. else
  134. {
  135. LLTextBox::Params text_p(p.value_text);
  136. text_p.rect.setIfNotProvided(text_rect);
  137. text_p.font.setIfNotProvided(p.font);
  138. mTextBox = LLUICtrlFactory::create<LLTextBox>(text_p);
  139. addChild(mTextBox);
  140. }
  141. }
  142. updateText();
  143. }
  144. // static
  145. void LLSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
  146. {
  147. LLSliderCtrl* self = (LLSliderCtrl*) userdata;
  148. llassert( caller == self->mEditor );
  149. self->onFocusReceived();
  150. }
  151. void LLSliderCtrl::setValue(F32 v, BOOL from_event)
  152. {
  153. mSlider->setValue( v, from_event );
  154. mValue = mSlider->getValueF32();
  155. updateText();
  156. }
  157. BOOL LLSliderCtrl::setLabelArg( const std::string& key, const LLStringExplicit& text )
  158. {
  159. BOOL res = FALSE;
  160. if (mLabelBox)
  161. {
  162. res = mLabelBox->setTextArg(key, text);
  163. if (res && mLabelWidth == 0)
  164. {
  165. S32 label_width = mFont->getWidth(mLabelBox->getText());
  166. LLRect rect = mLabelBox->getRect();
  167. S32 prev_right = rect.mRight;
  168. rect.mRight = rect.mLeft + label_width;
  169. mLabelBox->setRect(rect);
  170. S32 delta = rect.mRight - prev_right;
  171. rect = mSlider->getRect();
  172. S32 left = rect.mLeft + delta;
  173. static LLUICachedControl<S32> sliderctrl_spacing ("UISliderctrlSpacing", 0);
  174. left = llclamp(left, 0, rect.mRight - sliderctrl_spacing);
  175. rect.mLeft = left;
  176. mSlider->setRect(rect);
  177. }
  178. }
  179. return res;
  180. }
  181. void LLSliderCtrl::clear()
  182. {
  183. setValue(0.0f);
  184. if( mEditor )
  185. {
  186. mEditor->setText( LLStringUtil::null );
  187. }
  188. if( mTextBox )
  189. {
  190. mTextBox->setText( LLStringUtil::null );
  191. }
  192. }
  193. void LLSliderCtrl::updateText()
  194. {
  195. if( mEditor || mTextBox )
  196. {
  197. LLLocale locale(LLLocale::USER_LOCALE);
  198. // Don't display very small negative values as -0.000
  199. F32 displayed_value = (F32)(floor(getValueF32() * pow(10.0, (F64)mPrecision) + 0.5) / pow(10.0, (F64)mPrecision));
  200. std::string format = llformat("%%.%df", mPrecision);
  201. std::string text = llformat(format.c_str(), displayed_value);
  202. if( mEditor )
  203. {
  204. mEditor->setText( text );
  205. }
  206. else
  207. {
  208. mTextBox->setText( text );
  209. }
  210. }
  211. }
  212. // static
  213. void LLSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata )
  214. {
  215. LLSliderCtrl* self = dynamic_cast<LLSliderCtrl*>(ctrl->getParent());
  216. if (!self)
  217. return;
  218. BOOL success = FALSE;
  219. F32 val = self->mValue;
  220. F32 saved_val = self->mValue;
  221. std::string text = self->mEditor->getText();
  222. if( LLLineEditor::postvalidateFloat( text ) )
  223. {
  224. LLLocale locale(LLLocale::USER_LOCALE);
  225. val = (F32) atof( text.c_str() );
  226. if( self->mSlider->getMinValue() <= val && val <= self->mSlider->getMaxValue() )
  227. {
  228. self->setValue( val );  // set the value temporarily so that the callback can retrieve it.
  229. if( !self->mValidateSignal || (*(self->mValidateSignal))( self, val ) )
  230. {
  231. success = TRUE;
  232. }
  233. }
  234. }
  235. if( success )
  236. {
  237. self->onCommit();
  238. }
  239. else
  240. {
  241. if( self->getValueF32() != saved_val )
  242. {
  243. self->setValue( saved_val );
  244. }
  245. self->reportInvalidData();
  246. }
  247. self->updateText();
  248. }
  249. // static
  250. void LLSliderCtrl::onSliderCommit( LLUICtrl* ctrl, const LLSD& userdata )
  251. {
  252. LLSliderCtrl* self = dynamic_cast<LLSliderCtrl*>(ctrl->getParent());
  253. if (!self)
  254. return;
  255. BOOL success = FALSE;
  256. F32 saved_val = self->mValue;
  257. F32 new_val = self->mSlider->getValueF32();
  258. self->mValue = new_val;  // set the value temporarily so that the callback can retrieve it.
  259. if( !self->mValidateSignal || (*(self->mValidateSignal))( self, new_val ) )
  260. {
  261. success = TRUE;
  262. }
  263. if( success )
  264. {
  265. self->onCommit();
  266. }
  267. else
  268. {
  269. if( self->mValue != saved_val )
  270. {
  271. self->setValue( saved_val );
  272. }
  273. self->reportInvalidData();
  274. }
  275. self->updateText();
  276. }
  277. void LLSliderCtrl::setEnabled(BOOL b)
  278. {
  279. LLView::setEnabled( b );
  280. if( mLabelBox )
  281. {
  282. mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
  283. }
  284. mSlider->setEnabled( b );
  285. if( mEditor )
  286. {
  287. mEditor->setEnabled( b );
  288. }
  289. if( mTextBox )
  290. {
  291. mTextBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
  292. }
  293. }
  294. void LLSliderCtrl::setTentative(BOOL b)
  295. {
  296. if( mEditor )
  297. {
  298. mEditor->setTentative(b);
  299. }
  300. LLF32UICtrl::setTentative(b);
  301. }
  302. void LLSliderCtrl::onCommit()
  303. {
  304. setTentative(FALSE);
  305. if( mEditor )
  306. {
  307. mEditor->setTentative(FALSE);
  308. }
  309. setControlValue(getValueF32());
  310. LLF32UICtrl::onCommit();
  311. }
  312. void LLSliderCtrl::setPrecision(S32 precision)
  313. {
  314. if (precision < 0 || precision > 10)
  315. {
  316. llerrs << "LLSliderCtrl::setPrecision - precision out of range" << llendl;
  317. return;
  318. }
  319. mPrecision = precision;
  320. updateText();
  321. }
  322. boost::signals2::connection LLSliderCtrl::setSliderMouseDownCallback( const commit_signal_t::slot_type& cb )
  323. {
  324. return mSlider->setMouseDownCallback( cb );
  325. }
  326. boost::signals2::connection LLSliderCtrl::setSliderMouseUpCallback( const commit_signal_t::slot_type& cb )
  327. {
  328. return mSlider->setMouseUpCallback( cb );
  329. }
  330. void LLSliderCtrl::onTabInto()
  331. {
  332. if( mEditor )
  333. {
  334. mEditor->onTabInto(); 
  335. }
  336. }
  337. void LLSliderCtrl::reportInvalidData()
  338. {
  339. make_ui_sound("UISndBadKeystroke");
  340. }