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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llmultisliderctrl.cpp
  3.  * @brief LLMultiSliderCtrl base class
  4.  *
  5.  * $LicenseInfo:firstyear=2007&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2007-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 "llmultisliderctrl.h"
  34. #include "llmath.h"
  35. #include "llfontgl.h"
  36. #include "llgl.h"
  37. #include "llkeyboard.h"
  38. #include "lllineeditor.h"
  39. #include "llmultislider.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. static LLDefaultChildRegistry::Register<LLMultiSliderCtrl> r("multi_slider");
  49. const U32 MAX_STRING_LENGTH = 10;
  50. LLMultiSliderCtrl::Params::Params()
  51. : text_width("text_width"),
  52. label_width("label_width"),
  53. show_text("show_text", true),
  54. can_edit_text("can_edit_text", false),
  55. max_sliders("max_sliders", 1),
  56. allow_overlap("allow_overlap", false),
  57. draw_track("draw_track", true),
  58. use_triangle("use_triangle", false),
  59. decimal_digits("decimal_digits", 3),
  60. text_color("text_color"),
  61. text_disabled_color("text_disabled_color"),
  62. mouse_down_callback("mouse_down_callback"),
  63. mouse_up_callback("mouse_up_callback"),
  64. sliders("slider")
  65. {
  66. mouse_opaque = true;
  67. }
  68.  
  69. LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
  70. : LLF32UICtrl(p),
  71. mLabelBox( NULL ),
  72. mEditor( NULL ),
  73. mTextBox( NULL ),
  74. mTextEnabledColor(p.text_color()),
  75. mTextDisabledColor(p.text_disabled_color())
  76. {
  77. static LLUICachedControl<S32> multi_sliderctrl_spacing ("UIMultiSliderctrlSpacing", 0);
  78. S32 top = getRect().getHeight();
  79. S32 bottom = 0;
  80. S32 left = 0;
  81. S32 label_width = p.label_width;
  82. S32 text_width = p.text_width;
  83. // Label
  84. if( !p.label().empty() )
  85. {
  86. if (p.label_width == 0)
  87. {
  88. label_width = p.font()->getWidth(p.label);
  89. }
  90. LLRect label_rect( left, top, label_width, bottom );
  91. LLTextBox::Params params;
  92. params.name("MultiSliderCtrl Label");
  93. params.rect(label_rect);
  94. params.initial_value(p.label());
  95. params.font(p.font);
  96. mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
  97. addChild(mLabelBox);
  98. }
  99. S32 slider_right = getRect().getWidth();
  100. if (p.show_text)
  101. {
  102. if (!p.text_width.isProvided())
  103. {
  104. text_width = 0;
  105. // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
  106. if ( p.max_value() )
  107. text_width = p.font()->getWidth(std::string("0")) * ( static_cast < S32 > ( log10  ( p.max_value ) ) + p.decimal_digits + 1 );
  108. if ( p.increment < 1.0f )
  109. text_width += p.font()->getWidth(std::string(".")); // (mostly) take account of decimal point in value
  110. if ( p.min_value < 0.0f || p.max_value < 0.0f )
  111. text_width += p.font()->getWidth(std::string("-")); // (mostly) take account of minus sign 
  112. // padding to make things look nicer
  113. text_width += 8;
  114. }
  115. S32 text_left = getRect().getWidth() - text_width;
  116. slider_right = text_left - multi_sliderctrl_spacing;
  117. LLRect text_rect( text_left, top, getRect().getWidth(), bottom );
  118. if( p.can_edit_text )
  119. {
  120. LLLineEditor::Params params;
  121. params.name("MultiSliderCtrl Editor");
  122. params.rect(text_rect);
  123. params.font(p.font);
  124. params.max_length_bytes(MAX_STRING_LENGTH);
  125. params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
  126. params.prevalidate_callback(&LLTextValidate::validateFloat);
  127. params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
  128. mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
  129. mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) );
  130. // don't do this, as selecting the entire text is single clicking in some cases
  131. // and double clicking in others
  132. //mEditor->setSelectAllonFocusReceived(TRUE);
  133. addChild(mEditor);
  134. }
  135. else
  136. {
  137. LLTextBox::Params params;
  138. params.name("MultiSliderCtrl Text");
  139. params.rect(text_rect);
  140. params.font(p.font);
  141. params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
  142. mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
  143. addChild(mTextBox);
  144. }
  145. }
  146. S32 slider_left = label_width ? label_width + multi_sliderctrl_spacing : 0;
  147. LLRect slider_rect( slider_left, top, slider_right, bottom );
  148. LLMultiSlider::Params params;
  149. params.sliders = p.sliders;
  150. params.rect(slider_rect);
  151. params.commit_callback.function( LLMultiSliderCtrl::onSliderCommit );
  152. params.mouse_down_callback( p.mouse_down_callback );
  153. params.mouse_up_callback( p.mouse_up_callback );
  154. params.initial_value(p.initial_value());
  155. params.min_value(p.min_value);
  156. params.max_value(p.max_value);
  157. params.increment(p.increment);
  158. params.max_sliders(p.max_sliders);
  159. params.allow_overlap(p.allow_overlap);
  160. params.draw_track(p.draw_track);
  161. params.use_triangle(p.use_triangle);
  162. params.control_name(p.control_name);
  163. mMultiSlider = LLUICtrlFactory::create<LLMultiSlider> (params);
  164. addChild( mMultiSlider );
  165. mCurValue = mMultiSlider->getCurSliderValue();
  166. updateText();
  167. }
  168. LLMultiSliderCtrl::~LLMultiSliderCtrl()
  169. {
  170. // Children all cleaned up by default view destructor.
  171. }
  172. // static
  173. void LLMultiSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
  174. {
  175. LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
  176. llassert( caller == self->mEditor );
  177. self->onFocusReceived();
  178. }
  179. void LLMultiSliderCtrl::setValue(const LLSD& value)
  180. {
  181. mMultiSlider->setValue(value);
  182. mCurValue = mMultiSlider->getCurSliderValue();
  183. updateText();
  184. }
  185. void LLMultiSliderCtrl::setSliderValue(const std::string& name, F32 v, BOOL from_event)
  186. {
  187. mMultiSlider->setSliderValue(name, v, from_event );
  188. mCurValue = mMultiSlider->getCurSliderValue();
  189. updateText();
  190. }
  191. void LLMultiSliderCtrl::setCurSlider(const std::string& name)
  192. {
  193. mMultiSlider->setCurSlider(name);
  194. mCurValue = mMultiSlider->getCurSliderValue();
  195. }
  196. BOOL LLMultiSliderCtrl::setLabelArg( const std::string& key, const LLStringExplicit& text )
  197. {
  198. BOOL res = FALSE;
  199. if (mLabelBox)
  200. {
  201. res = mLabelBox->setTextArg(key, text);
  202. if (res && mLabelWidth == 0)
  203. {
  204. S32 label_width = mFont->getWidth(mLabelBox->getText());
  205. LLRect rect = mLabelBox->getRect();
  206. S32 prev_right = rect.mRight;
  207. rect.mRight = rect.mLeft + label_width;
  208. mLabelBox->setRect(rect);
  209. S32 delta = rect.mRight - prev_right;
  210. rect = mMultiSlider->getRect();
  211. S32 left = rect.mLeft + delta;
  212. static LLUICachedControl<S32> multi_slider_ctrl_spacing ("UIMultiSliderctrlSpacing", 0);
  213. left = llclamp(left, 0, rect.mRight - multi_slider_ctrl_spacing);
  214. rect.mLeft = left;
  215. mMultiSlider->setRect(rect);
  216. }
  217. }
  218. return res;
  219. }
  220. const std::string& LLMultiSliderCtrl::addSlider()
  221. {
  222. const std::string& name = mMultiSlider->addSlider();
  223. // if it returns null, pass it on
  224. if(name == LLStringUtil::null) {
  225. return LLStringUtil::null;
  226. }
  227. // otherwise, update stuff
  228. mCurValue = mMultiSlider->getCurSliderValue();
  229. updateText();
  230. return name;
  231. }
  232. const std::string& LLMultiSliderCtrl::addSlider(F32 val)
  233. {
  234. const std::string& name = mMultiSlider->addSlider(val);
  235. // if it returns null, pass it on
  236. if(name == LLStringUtil::null) {
  237. return LLStringUtil::null;
  238. }
  239. // otherwise, update stuff
  240. mCurValue = mMultiSlider->getCurSliderValue();
  241. updateText();
  242. return name;
  243. }
  244. void LLMultiSliderCtrl::deleteSlider(const std::string& name)
  245. {
  246. mMultiSlider->deleteSlider(name);
  247. mCurValue = mMultiSlider->getCurSliderValue();
  248. updateText();
  249. }
  250. void LLMultiSliderCtrl::clear()
  251. {
  252. setCurSliderValue(0.0f);
  253. if( mEditor )
  254. {
  255. mEditor->setText(std::string(""));
  256. }
  257. if( mTextBox )
  258. {
  259. mTextBox->setText(std::string(""));
  260. }
  261. // get rid of sliders
  262. mMultiSlider->clear();
  263. }
  264. BOOL LLMultiSliderCtrl::isMouseHeldDown()
  265. {
  266. return gFocusMgr.getMouseCapture() == mMultiSlider;
  267. }
  268. void LLMultiSliderCtrl::updateText()
  269. {
  270. if( mEditor || mTextBox )
  271. {
  272. LLLocale locale(LLLocale::USER_LOCALE);
  273. // Don't display very small negative values as -0.000
  274. F32 displayed_value = (F32)(floor(getCurSliderValue() * pow(10.0, (F64)mPrecision) + 0.5) / pow(10.0, (F64)mPrecision));
  275. std::string format = llformat("%%.%df", mPrecision);
  276. std::string text = llformat(format.c_str(), displayed_value);
  277. if( mEditor )
  278. {
  279. mEditor->setText( text );
  280. }
  281. else
  282. {
  283. mTextBox->setText( text );
  284. }
  285. }
  286. }
  287. // static
  288. void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata)
  289. {
  290. llassert(ctrl);
  291. if (!ctrl)
  292. return;
  293. LLMultiSliderCtrl* self = dynamic_cast<LLMultiSliderCtrl*>(ctrl->getParent());
  294. llassert(self);
  295. if (!self) // cast failed - wrong type! :O
  296. return;
  297. BOOL success = FALSE;
  298. F32 val = self->mCurValue;
  299. F32 saved_val = self->mCurValue;
  300. std::string text = self->mEditor->getText();
  301. if( LLLineEditor::postvalidateFloat( text ) )
  302. {
  303. LLLocale locale(LLLocale::USER_LOCALE);
  304. val = (F32) atof( text.c_str() );
  305. if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() )
  306. {
  307. self->setCurSliderValue( val );  // set the value temporarily so that the callback can retrieve it.
  308. if( !self->mValidateSignal || (*(self->mValidateSignal))( self, val ) )
  309. {
  310. success = TRUE;
  311. }
  312. }
  313. }
  314. if( success )
  315. {
  316. self->onCommit();
  317. }
  318. else
  319. {
  320. if( self->getCurSliderValue() != saved_val )
  321. {
  322. self->setCurSliderValue( saved_val );
  323. }
  324. self->reportInvalidData();
  325. }
  326. self->updateText();
  327. }
  328. // static
  329. void LLMultiSliderCtrl::onSliderCommit(LLUICtrl* ctrl, const LLSD& userdata)
  330. {
  331. LLMultiSliderCtrl* self = dynamic_cast<LLMultiSliderCtrl*>(ctrl->getParent());
  332. if (!self)
  333. return;
  334. BOOL success = FALSE;
  335. F32 saved_val = self->mCurValue;
  336. F32 new_val = self->mMultiSlider->getCurSliderValue();
  337. self->mCurValue = new_val;  // set the value temporarily so that the callback can retrieve it.
  338. if( !self->mValidateSignal || (*(self->mValidateSignal))( self, new_val ) )
  339. {
  340. success = TRUE;
  341. }
  342. if( success )
  343. {
  344. self->onCommit();
  345. }
  346. else
  347. {
  348. if( self->mCurValue != saved_val )
  349. {
  350. self->setCurSliderValue( saved_val );
  351. }
  352. self->reportInvalidData();
  353. }
  354. self->updateText();
  355. }
  356. void LLMultiSliderCtrl::setEnabled(BOOL b)
  357. {
  358. LLF32UICtrl::setEnabled( b );
  359. if( mLabelBox )
  360. {
  361. mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
  362. }
  363. mMultiSlider->setEnabled( b );
  364. if( mEditor )
  365. {
  366. mEditor->setEnabled( b );
  367. }
  368. if( mTextBox )
  369. {
  370. mTextBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
  371. }
  372. }
  373. void LLMultiSliderCtrl::setTentative(BOOL b)
  374. {
  375. if( mEditor )
  376. {
  377. mEditor->setTentative(b);
  378. }
  379. LLF32UICtrl::setTentative(b);
  380. }
  381. void LLMultiSliderCtrl::onCommit()
  382. {
  383. setTentative(FALSE);
  384. if( mEditor )
  385. {
  386. mEditor->setTentative(FALSE);
  387. }
  388. setControlValue(getValueF32());
  389. LLF32UICtrl::onCommit();
  390. }
  391. void LLMultiSliderCtrl::setPrecision(S32 precision)
  392. {
  393. if (precision < 0 || precision > 10)
  394. {
  395. llerrs << "LLMultiSliderCtrl::setPrecision - precision out of range" << llendl;
  396. return;
  397. }
  398. mPrecision = precision;
  399. updateText();
  400. }
  401. boost::signals2::connection LLMultiSliderCtrl::setSliderMouseDownCallback( const commit_signal_t::slot_type& cb )
  402. {
  403. return mMultiSlider->setMouseDownCallback( cb );
  404. }
  405. boost::signals2::connection LLMultiSliderCtrl::setSliderMouseUpCallback( const commit_signal_t::slot_type& cb )
  406. {
  407. return mMultiSlider->setMouseUpCallback( cb );
  408. }
  409. void LLMultiSliderCtrl::onTabInto()
  410. {
  411. if( mEditor )
  412. {
  413. mEditor->onTabInto(); 
  414. }
  415. }
  416. void LLMultiSliderCtrl::reportInvalidData()
  417. {
  418. make_ui_sound("UISndBadKeystroke");
  419. }
  420. // virtual
  421. void LLMultiSliderCtrl::setControlName(const std::string& control_name, LLView* context)
  422. {
  423. mMultiSlider->setControlName(control_name, context);
  424. }