ToggleSwitch.cs 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. using System;
  2. using System.ComponentModel;
  3. using System.Drawing;
  4. using System.Windows.Forms;
  5. namespace Optimizer
  6. {
  7. [DefaultValue("Checked"), DefaultEvent("CheckedChanged"), ToolboxBitmap(typeof(CheckBox))]
  8. internal class ToggleSwitch : Control
  9. {
  10. public delegate void CheckedChangedDelegate(Object sender, EventArgs e);
  11. [Description("Raised when the ToggleSwitch has changed state")]
  12. public event CheckedChangedDelegate CheckedChanged;
  13. private readonly Timer _animationTimer = new Timer();
  14. private ToggleSwitchRendererBase _renderer;
  15. private bool _checked = false;
  16. private bool _moving = false;
  17. private bool _animating = false;
  18. private bool _animationResult = false;
  19. private int _animationTarget = 0;
  20. private bool _useAnimation = true;
  21. private int _animationInterval = 1;
  22. private int _animationStep = 10;
  23. private bool _allowUserChange = true;
  24. private bool _isLeftFieldHovered = false;
  25. private bool _isButtonHovered = false;
  26. private bool _isRightFieldHovered = false;
  27. private bool _isLeftFieldPressed = false;
  28. private bool _isButtonPressed = false;
  29. private bool _isRightFieldPressed = false;
  30. private int _buttonValue = 0;
  31. private int _savedButtonValue = 0;
  32. private int _xOffset = 0;
  33. private int _xValue = 0;
  34. private int _thresholdPercentage = 50;
  35. private bool _grayWhenDisabled = true;
  36. private bool _toggleOnButtonClick = true;
  37. private bool _toggleOnSideClick = true;
  38. private MouseEventArgs _lastMouseEventArgs = null;
  39. private bool _buttonScaleImage;
  40. private ToggleSwitchButtonAlignment _buttonAlignment = ToggleSwitchButtonAlignment.Center;
  41. private Image _buttonImage = null;
  42. private Color _offForeColor = Color.Black;
  43. private Font _offFont;
  44. private Image _offSideImage = null;
  45. private bool _offSideScaleImage;
  46. private ToggleSwitchAlignment _offSideAlignment = ToggleSwitchAlignment.Center;
  47. private Image _offButtonImage = null;
  48. private bool _offButtonScaleImage;
  49. private ToggleSwitchButtonAlignment _offButtonAlignment = ToggleSwitchButtonAlignment.Center;
  50. private string _onText = "";
  51. private Color _onForeColor = Color.Black;
  52. private Font _onFont;
  53. private Image _onSideImage = null;
  54. private bool _onSideScaleImage;
  55. private ToggleSwitchAlignment _onSideAlignment = ToggleSwitchAlignment.Center;
  56. private Image _onButtonImage = null;
  57. private bool _onButtonScaleImage;
  58. private ToggleSwitchButtonAlignment _onButtonAlignment = ToggleSwitchButtonAlignment.Center;
  59. public ToggleSwitch()
  60. {
  61. SetStyle(ControlStyles.ResizeRedraw |
  62. ControlStyles.SupportsTransparentBackColor |
  63. ControlStyles.AllPaintingInWmPaint |
  64. ControlStyles.UserPaint |
  65. ControlStyles.OptimizedDoubleBuffer |
  66. ControlStyles.DoubleBuffer, true);
  67. OnFont = base.Font;
  68. OffFont = base.Font;
  69. SetRenderer(new ToggleSwitchRenderer());
  70. _animationTimer.Enabled = false;
  71. _animationTimer.Interval = _animationInterval;
  72. _animationTimer.Tick += AnimationTimer_Tick;
  73. }
  74. public void SetRenderer(ToggleSwitchRendererBase renderer)
  75. {
  76. renderer.SetToggleSwitch(this);
  77. _renderer = renderer;
  78. if (_renderer != null) Refresh();
  79. }
  80. [Bindable(true)]
  81. [DefaultValue(false)]
  82. [Category("Data")]
  83. [Description("Gets or sets the Checked value of the ToggleSwitch")]
  84. public bool Checked
  85. {
  86. get { return _checked; }
  87. set
  88. {
  89. if (value != _checked)
  90. {
  91. while (_animating)
  92. {
  93. Application.DoEvents();
  94. }
  95. if (value == true)
  96. {
  97. int buttonWidth = _renderer.GetButtonWidth();
  98. _animationTarget = Width - buttonWidth;
  99. BeginAnimation(true);
  100. }
  101. else
  102. {
  103. _animationTarget = 0;
  104. BeginAnimation(false);
  105. }
  106. }
  107. }
  108. }
  109. [Bindable(true)]
  110. [DefaultValue(true)]
  111. [Category("Behavior")]
  112. [Description("Gets or sets whether the user can change the value of the button or not")]
  113. public bool AllowUserChange
  114. {
  115. get { return _allowUserChange; }
  116. set { _allowUserChange = value; }
  117. }
  118. [Browsable(false)]
  119. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  120. public string CheckedString
  121. {
  122. get
  123. {
  124. return Checked ? (string.IsNullOrEmpty(OnText) ? "ON" : OnText) : (string.IsNullOrEmpty(OnText) ? "OFF" : OnText);
  125. }
  126. }
  127. [Browsable(false)]
  128. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  129. public Rectangle ButtonRectangle
  130. {
  131. get
  132. {
  133. return _renderer.GetButtonRectangle();
  134. }
  135. }
  136. [Bindable(false)]
  137. [DefaultValue(true)]
  138. [Category("Appearance")]
  139. [Description("Gets or sets if the ToggleSwitch should be grayed out when disabled")]
  140. public bool GrayWhenDisabled
  141. {
  142. get { return _grayWhenDisabled; }
  143. set
  144. {
  145. if (value != _grayWhenDisabled)
  146. {
  147. _grayWhenDisabled = value;
  148. if (!Enabled)
  149. Refresh();
  150. }
  151. }
  152. }
  153. [Bindable(false)]
  154. [DefaultValue(true)]
  155. [Category("Behavior")]
  156. [Description("Gets or sets if the ToggleSwitch should toggle when the button is clicked")]
  157. public bool ToggleOnButtonClick
  158. {
  159. get { return _toggleOnButtonClick; }
  160. set { _toggleOnButtonClick = value; }
  161. }
  162. [Bindable(false)]
  163. [DefaultValue(true)]
  164. [Category("Behavior")]
  165. [Description("Gets or sets if the ToggleSwitch should toggle when the track besides the button is clicked")]
  166. public bool ToggleOnSideClick
  167. {
  168. get { return _toggleOnSideClick; }
  169. set { _toggleOnSideClick = value; }
  170. }
  171. [Bindable(false)]
  172. [DefaultValue(50)]
  173. [Category("Behavior")]
  174. [Description("Gets or sets how much the button need to be on the other side (in peercept) before it snaps")]
  175. public int ThresholdPercentage
  176. {
  177. get { return _thresholdPercentage; }
  178. set { _thresholdPercentage = value; }
  179. }
  180. [Bindable(false)]
  181. [DefaultValue(typeof(Color), "Black")]
  182. [Category("Appearance")]
  183. [Description("Gets or sets the forecolor of the text when Checked=false")]
  184. public Color OffForeColor
  185. {
  186. get { return _offForeColor; }
  187. set
  188. {
  189. if (value != _offForeColor)
  190. {
  191. _offForeColor = value;
  192. Refresh();
  193. }
  194. }
  195. }
  196. [Bindable(false)]
  197. [DefaultValue(typeof(Font), "Microsoft Sans Serif, 8.25pt")]
  198. [Category("Appearance")]
  199. [Description("Gets or sets the font of the text when Checked=false")]
  200. public Font OffFont
  201. {
  202. get { return _offFont; }
  203. set
  204. {
  205. if (!value.Equals(_offFont))
  206. {
  207. _offFont = value;
  208. Refresh();
  209. }
  210. }
  211. }
  212. [Bindable(false)]
  213. [DefaultValue(null)]
  214. [Category("Appearance")]
  215. [Description("Gets or sets the side image when Checked=false - Note: Settings the OffSideImage overrules the OffText property. Only the image will be shown")]
  216. public Image OffSideImage
  217. {
  218. get { return _offSideImage; }
  219. set
  220. {
  221. if (value != _offSideImage)
  222. {
  223. _offSideImage = value;
  224. Refresh();
  225. }
  226. }
  227. }
  228. [Bindable(false)]
  229. [DefaultValue(false)]
  230. [Category("Behavior")]
  231. [Description("Gets or sets whether the side image visible when Checked=false should be scaled to fit")]
  232. public bool OffSideScaleImageToFit
  233. {
  234. get { return _offSideScaleImage; }
  235. set
  236. {
  237. if (value != _offSideScaleImage)
  238. {
  239. _offSideScaleImage = value;
  240. Refresh();
  241. }
  242. }
  243. }
  244. [Bindable(false)]
  245. [DefaultValue(typeof(ToggleSwitchAlignment), "Center")]
  246. [Category("Appearance")]
  247. [Description("Gets or sets how the text or side image visible when Checked=false should be aligned")]
  248. public ToggleSwitchAlignment OffSideAlignment
  249. {
  250. get { return _offSideAlignment; }
  251. set
  252. {
  253. if (value != _offSideAlignment)
  254. {
  255. _offSideAlignment = value;
  256. Refresh();
  257. }
  258. }
  259. }
  260. [Bindable(false)]
  261. [DefaultValue(null)]
  262. [Category("Appearance")]
  263. [Description("Gets or sets the button image when Checked=false and ButtonImage is not set")]
  264. public Image OffButtonImage
  265. {
  266. get { return _offButtonImage; }
  267. set
  268. {
  269. if (value != _offButtonImage)
  270. {
  271. _offButtonImage = value;
  272. Refresh();
  273. }
  274. }
  275. }
  276. [Bindable(false)]
  277. [DefaultValue(false)]
  278. [Category("Behavior")]
  279. [Description("Gets or sets whether the button image visible when Checked=false should be scaled to fit")]
  280. public bool OffButtonScaleImageToFit
  281. {
  282. get { return _offButtonScaleImage; }
  283. set
  284. {
  285. if (value != _offButtonScaleImage)
  286. {
  287. _offButtonScaleImage = value;
  288. Refresh();
  289. }
  290. }
  291. }
  292. [Bindable(false)]
  293. [DefaultValue(typeof(ToggleSwitchButtonAlignment), "Center")]
  294. [Category("Appearance")]
  295. [Description("Gets or sets how the button image visible when Checked=false should be aligned")]
  296. public ToggleSwitchButtonAlignment OffButtonAlignment
  297. {
  298. get { return _offButtonAlignment; }
  299. set
  300. {
  301. if (value != _offButtonAlignment)
  302. {
  303. _offButtonAlignment = value;
  304. Refresh();
  305. }
  306. }
  307. }
  308. [Bindable(false)]
  309. [DefaultValue(typeof(Color), "Black")]
  310. [Category("Appearance")]
  311. [Description("Gets or sets the forecolor of the text when Checked=true")]
  312. public Color OnForeColor
  313. {
  314. get { return _onForeColor; }
  315. set
  316. {
  317. if (value != _onForeColor)
  318. {
  319. _onForeColor = value;
  320. Refresh();
  321. }
  322. }
  323. }
  324. [Bindable(false)]
  325. [DefaultValue(typeof(Font), "Microsoft Sans Serif, 8,25pt")]
  326. [Category("Appearance")]
  327. [Description("Gets or sets the font of the text when Checked=true")]
  328. public Font OnFont
  329. {
  330. get { return _onFont; }
  331. set
  332. {
  333. if (!value.Equals(_onFont))
  334. {
  335. _onFont = value;
  336. Refresh();
  337. }
  338. }
  339. }
  340. [Bindable(false)]
  341. [DefaultValue("")]
  342. [Category("Appearance")]
  343. [Description("On-button text")]
  344. public string OnText
  345. {
  346. get { return _onText; }
  347. set
  348. {
  349. if (value != _onText)
  350. {
  351. _onText = value;
  352. Refresh();
  353. }
  354. }
  355. }
  356. [Bindable(false)]
  357. [DefaultValue(null)]
  358. [Category("Appearance")]
  359. [Description("Gets or sets the side image visible when Checked=true - Note: Settings the OnSideImage overrules the OnText property. Only the image will be shown.")]
  360. public Image OnSideImage
  361. {
  362. get { return _onSideImage; }
  363. set
  364. {
  365. if (value != _onSideImage)
  366. {
  367. _onSideImage = value;
  368. Refresh();
  369. }
  370. }
  371. }
  372. [Bindable(false)]
  373. [DefaultValue(false)]
  374. [Category("Behavior")]
  375. [Description("Gets or sets whether the side image visible when Checked=true should be scaled to fit")]
  376. public bool OnSideScaleImageToFit
  377. {
  378. get { return _onSideScaleImage; }
  379. set
  380. {
  381. if (value != _onSideScaleImage)
  382. {
  383. _onSideScaleImage = value;
  384. Refresh();
  385. }
  386. }
  387. }
  388. [Bindable(false)]
  389. [DefaultValue(null)]
  390. [Category("Appearance")]
  391. [Description("Gets or sets the button image")]
  392. public Image ButtonImage
  393. {
  394. get { return _buttonImage; }
  395. set
  396. {
  397. if (value != _buttonImage)
  398. {
  399. _buttonImage = value;
  400. Refresh();
  401. }
  402. }
  403. }
  404. [Bindable(false)]
  405. [DefaultValue(false)]
  406. [Category("Behavior")]
  407. [Description("Gets or sets whether the button image should be scaled to fit")]
  408. public bool ButtonScaleImageToFit
  409. {
  410. get { return _buttonScaleImage; }
  411. set
  412. {
  413. if (value != _buttonScaleImage)
  414. {
  415. _buttonScaleImage = value;
  416. Refresh();
  417. }
  418. }
  419. }
  420. [Bindable(false)]
  421. [DefaultValue(typeof(ToggleSwitchButtonAlignment), "Center")]
  422. [Category("Appearance")]
  423. [Description("Gets or sets how the button image should be aligned")]
  424. public ToggleSwitchButtonAlignment ButtonAlignment
  425. {
  426. get { return _buttonAlignment; }
  427. set
  428. {
  429. if (value != _buttonAlignment)
  430. {
  431. _buttonAlignment = value;
  432. Refresh();
  433. }
  434. }
  435. }
  436. [Bindable(false)]
  437. [DefaultValue(typeof(ToggleSwitchAlignment), "Center")]
  438. [Category("Appearance")]
  439. [Description("Gets or sets how the text or side image visible when Checked=true should be aligned")]
  440. public ToggleSwitchAlignment OnSideAlignment
  441. {
  442. get { return _onSideAlignment; }
  443. set
  444. {
  445. if (value != _onSideAlignment)
  446. {
  447. _onSideAlignment = value;
  448. Refresh();
  449. }
  450. }
  451. }
  452. [Bindable(false)]
  453. [DefaultValue(null)]
  454. [Category("Appearance")]
  455. [Description("Gets or sets the button image visible when Checked=true and ButtonImage is not set")]
  456. public Image OnButtonImage
  457. {
  458. get { return _onButtonImage; }
  459. set
  460. {
  461. if (value != _onButtonImage)
  462. {
  463. _onButtonImage = value;
  464. Refresh();
  465. }
  466. }
  467. }
  468. [Bindable(false)]
  469. [DefaultValue(false)]
  470. [Category("Behavior")]
  471. [Description("Gets or sets whether the button image visible when Checked=true should be scaled to fit")]
  472. public bool OnButtonScaleImageToFit
  473. {
  474. get { return _onButtonScaleImage; }
  475. set
  476. {
  477. if (value != _onButtonScaleImage)
  478. {
  479. _onButtonScaleImage = value;
  480. Refresh();
  481. }
  482. }
  483. }
  484. [Bindable(false)]
  485. [DefaultValue(typeof(ToggleSwitchButtonAlignment), "Center")]
  486. [Category("Appearance")]
  487. [Description("Gets or sets how the button image visible when Checked=true should be aligned")]
  488. public ToggleSwitchButtonAlignment OnButtonAlignment
  489. {
  490. get { return _onButtonAlignment; }
  491. set
  492. {
  493. if (value != _onButtonAlignment)
  494. {
  495. _onButtonAlignment = value;
  496. Refresh();
  497. }
  498. }
  499. }
  500. [Bindable(false)]
  501. [DefaultValue(true)]
  502. [Category("Behavior")]
  503. [Description("Gets or sets whether the toggle change should be animated or not")]
  504. public bool UseAnimation
  505. {
  506. get { return _useAnimation; }
  507. set { _useAnimation = value; }
  508. }
  509. [Bindable(false)]
  510. [DefaultValue(1)]
  511. [Category("Behavior")]
  512. [Description("Gets or sets the interval in ms between animation frames")]
  513. public int AnimationInterval
  514. {
  515. get { return _animationInterval; }
  516. set
  517. {
  518. if (value <= 0)
  519. {
  520. throw new ArgumentOutOfRangeException("AnimationInterval must larger than zero!");
  521. }
  522. _animationInterval = value;
  523. }
  524. }
  525. [Bindable(false)]
  526. [DefaultValue(10)]
  527. [Category("Behavior")]
  528. [Description("Gets or sets the step in pixes the button shouldbe moved between each animation interval")]
  529. public int AnimationStep
  530. {
  531. get { return _animationStep; }
  532. set
  533. {
  534. if (value <= 0)
  535. {
  536. throw new ArgumentOutOfRangeException("AnimationStep must larger than zero!");
  537. }
  538. _animationStep = value;
  539. }
  540. }
  541. [Browsable(false)]
  542. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  543. public new string Text
  544. {
  545. get { return ""; }
  546. set { base.Text = ""; }
  547. }
  548. [Browsable(false)]
  549. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  550. public new Color ForeColor
  551. {
  552. get { return Color.Black; }
  553. set { base.ForeColor = Color.Black; }
  554. }
  555. [Browsable(false)]
  556. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  557. public new Font Font
  558. {
  559. get { return base.Font; }
  560. set { base.Font = new Font(base.Font, FontStyle.Regular); }
  561. }
  562. [Browsable(false)]
  563. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  564. internal bool IsButtonHovered
  565. {
  566. get { return _isButtonHovered && !_isButtonPressed; }
  567. }
  568. [Browsable(false)]
  569. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  570. internal bool IsButtonPressed
  571. {
  572. get { return _isButtonPressed; }
  573. }
  574. [Browsable(false)]
  575. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  576. internal bool IsLeftSideHovered
  577. {
  578. get { return _isLeftFieldHovered && !_isLeftFieldPressed; }
  579. }
  580. [Browsable(false)]
  581. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  582. internal bool IsLeftSidePressed
  583. {
  584. get { return _isLeftFieldPressed; }
  585. }
  586. [Browsable(false)]
  587. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  588. internal bool IsRightSideHovered
  589. {
  590. get { return _isRightFieldHovered && !_isRightFieldPressed; }
  591. }
  592. [Browsable(false)]
  593. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  594. internal bool IsRightSidePressed
  595. {
  596. get { return _isRightFieldPressed; }
  597. }
  598. [Browsable(false)]
  599. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  600. internal int ButtonValue
  601. {
  602. get
  603. {
  604. if (_animating || _moving)
  605. return _buttonValue;
  606. else if (_checked)
  607. return Width - _renderer.GetButtonWidth();
  608. else
  609. return 0;
  610. }
  611. set
  612. {
  613. if (value != _buttonValue)
  614. {
  615. _buttonValue = value;
  616. Refresh();
  617. }
  618. }
  619. }
  620. [Browsable(false)]
  621. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  622. internal bool IsButtonOnLeftSide
  623. {
  624. get { return (ButtonValue <= 0); }
  625. }
  626. [Browsable(false)]
  627. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  628. internal bool IsButtonOnRightSide
  629. {
  630. get { return (ButtonValue >= (Width - _renderer.GetButtonWidth())); }
  631. }
  632. [Browsable(false)]
  633. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  634. internal bool IsButtonMovingLeft
  635. {
  636. get { return (_animating && !IsButtonOnLeftSide && _animationResult == false); }
  637. }
  638. [Browsable(false)]
  639. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  640. internal bool IsButtonMovingRight
  641. {
  642. get { return (_animating && !IsButtonOnRightSide && _animationResult == true); }
  643. }
  644. [Browsable(false)]
  645. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  646. internal bool AnimationResult
  647. {
  648. get { return _animationResult; }
  649. }
  650. protected override Size DefaultSize
  651. {
  652. get { return new Size(50, 19); }
  653. }
  654. protected override void OnPaintBackground(PaintEventArgs pevent)
  655. {
  656. pevent.Graphics.ResetClip();
  657. base.OnPaintBackground(pevent);
  658. if (_renderer != null)
  659. _renderer.RenderBackground(pevent);
  660. }
  661. protected override void OnPaint(PaintEventArgs e)
  662. {
  663. e.Graphics.ResetClip();
  664. base.OnPaint(e);
  665. if (_renderer != null)
  666. _renderer.RenderControl(e);
  667. }
  668. protected override void OnMouseMove(MouseEventArgs e)
  669. {
  670. _lastMouseEventArgs = e;
  671. int buttonWidth = _renderer.GetButtonWidth();
  672. Rectangle buttonRectangle = _renderer.GetButtonRectangle(buttonWidth);
  673. if (_moving)
  674. {
  675. int val = _xValue + (e.Location.X - _xOffset);
  676. if (val < 0)
  677. val = 0;
  678. if (val > Width - buttonWidth)
  679. val = Width - buttonWidth;
  680. ButtonValue = val;
  681. Refresh();
  682. return;
  683. }
  684. if (buttonRectangle.Contains(e.Location))
  685. {
  686. _isButtonHovered = true;
  687. _isLeftFieldHovered = false;
  688. _isRightFieldHovered = false;
  689. }
  690. else
  691. {
  692. if (e.Location.X > buttonRectangle.X + buttonRectangle.Width)
  693. {
  694. _isButtonHovered = false;
  695. _isLeftFieldHovered = false;
  696. _isRightFieldHovered = true;
  697. }
  698. else if (e.Location.X < buttonRectangle.X)
  699. {
  700. _isButtonHovered = false;
  701. _isLeftFieldHovered = true;
  702. _isRightFieldHovered = false;
  703. }
  704. }
  705. Refresh();
  706. }
  707. protected override void OnMouseDown(MouseEventArgs e)
  708. {
  709. if (_animating || !AllowUserChange)
  710. return;
  711. int buttonWidth = _renderer.GetButtonWidth();
  712. Rectangle buttonRectangle = _renderer.GetButtonRectangle(buttonWidth);
  713. _savedButtonValue = ButtonValue;
  714. if (buttonRectangle.Contains(e.Location))
  715. {
  716. _isButtonPressed = true;
  717. _isLeftFieldPressed = false;
  718. _isRightFieldPressed = false;
  719. _moving = true;
  720. _xOffset = e.Location.X;
  721. _buttonValue = buttonRectangle.X;
  722. _xValue = ButtonValue;
  723. }
  724. else
  725. {
  726. if (e.Location.X > buttonRectangle.X + buttonRectangle.Width)
  727. {
  728. _isButtonPressed = false;
  729. _isLeftFieldPressed = false;
  730. _isRightFieldPressed = true;
  731. }
  732. else if (e.Location.X < buttonRectangle.X)
  733. {
  734. _isButtonPressed = false;
  735. _isLeftFieldPressed = true;
  736. _isRightFieldPressed = false;
  737. }
  738. }
  739. Refresh();
  740. }
  741. protected override void OnMouseUp(MouseEventArgs e)
  742. {
  743. if (_animating || !AllowUserChange)
  744. return;
  745. int buttonWidth = _renderer.GetButtonWidth();
  746. bool wasLeftSidePressed = IsLeftSidePressed;
  747. bool wasRightSidePressed = IsRightSidePressed;
  748. _isButtonPressed = false;
  749. _isLeftFieldPressed = false;
  750. _isRightFieldPressed = false;
  751. if (_moving)
  752. {
  753. int percentage = (int)((100 * (double)ButtonValue) / ((double)Width - (double)buttonWidth));
  754. if (_checked)
  755. {
  756. if (percentage <= (100 - _thresholdPercentage))
  757. {
  758. _animationTarget = 0;
  759. BeginAnimation(false);
  760. }
  761. else if (ToggleOnButtonClick && _savedButtonValue == ButtonValue)
  762. {
  763. _animationTarget = 0;
  764. BeginAnimation(false);
  765. }
  766. else
  767. {
  768. _animationTarget = Width - buttonWidth;
  769. BeginAnimation(true);
  770. }
  771. }
  772. else
  773. {
  774. if (percentage >= _thresholdPercentage)
  775. {
  776. _animationTarget = Width - buttonWidth;
  777. BeginAnimation(true);
  778. }
  779. else if (ToggleOnButtonClick && _savedButtonValue == ButtonValue)
  780. {
  781. _animationTarget = Width - buttonWidth;
  782. BeginAnimation(true);
  783. }
  784. else
  785. {
  786. _animationTarget = 0;
  787. BeginAnimation(false);
  788. }
  789. }
  790. _moving = false;
  791. return;
  792. }
  793. if (IsButtonOnRightSide)
  794. {
  795. _buttonValue = Width - buttonWidth;
  796. _animationTarget = 0;
  797. }
  798. else
  799. {
  800. _buttonValue = 0;
  801. _animationTarget = Width - buttonWidth;
  802. }
  803. if (wasLeftSidePressed && ToggleOnSideClick)
  804. {
  805. SetValueInternal(false);
  806. }
  807. else if (wasRightSidePressed && ToggleOnSideClick)
  808. {
  809. SetValueInternal(true);
  810. }
  811. Refresh();
  812. }
  813. protected override void OnMouseLeave(EventArgs e)
  814. {
  815. _isButtonHovered = false;
  816. _isLeftFieldHovered = false;
  817. _isRightFieldHovered = false;
  818. _isButtonPressed = false;
  819. _isLeftFieldPressed = false;
  820. _isRightFieldPressed = false;
  821. Refresh();
  822. }
  823. protected override void OnEnabledChanged(EventArgs e)
  824. {
  825. base.OnEnabledChanged(e);
  826. Refresh();
  827. }
  828. protected override void OnRegionChanged(EventArgs e)
  829. {
  830. base.OnRegionChanged(e);
  831. Refresh();
  832. }
  833. protected override void OnSizeChanged(EventArgs e)
  834. {
  835. if (_animationTarget > 0)
  836. {
  837. int buttonWidth = _renderer.GetButtonWidth();
  838. _animationTarget = Width - buttonWidth;
  839. }
  840. base.OnSizeChanged(e);
  841. }
  842. private void SetValueInternal(bool checkedValue)
  843. {
  844. if (checkedValue == _checked)
  845. return;
  846. while (_animating)
  847. {
  848. Application.DoEvents();
  849. }
  850. BeginAnimation(checkedValue);
  851. }
  852. private void BeginAnimation(bool checkedValue)
  853. {
  854. _animating = true;
  855. _animationResult = checkedValue;
  856. if (_animationTimer != null && _useAnimation)
  857. {
  858. _animationTimer.Interval = _animationInterval;
  859. _animationTimer.Enabled = true;
  860. }
  861. else
  862. {
  863. AnimationComplete();
  864. }
  865. }
  866. private void AnimationTimer_Tick(object sender, EventArgs e)
  867. {
  868. _animationTimer.Enabled = false;
  869. bool animationDone = false;
  870. int newButtonValue;
  871. if (IsButtonMovingRight)
  872. {
  873. newButtonValue = ButtonValue + _animationStep;
  874. if (newButtonValue > _animationTarget)
  875. newButtonValue = _animationTarget;
  876. ButtonValue = newButtonValue;
  877. animationDone = ButtonValue >= _animationTarget;
  878. }
  879. else
  880. {
  881. newButtonValue = ButtonValue - _animationStep;
  882. if (newButtonValue < _animationTarget)
  883. newButtonValue = _animationTarget;
  884. ButtonValue = newButtonValue;
  885. animationDone = ButtonValue <= _animationTarget;
  886. }
  887. if (animationDone)
  888. AnimationComplete();
  889. else
  890. _animationTimer.Enabled = true;
  891. }
  892. private void AnimationComplete()
  893. {
  894. _animating = false;
  895. _moving = false;
  896. _checked = _animationResult;
  897. _isButtonHovered = false;
  898. _isButtonPressed = false;
  899. _isLeftFieldHovered = false;
  900. _isLeftFieldPressed = false;
  901. _isRightFieldHovered = false;
  902. _isRightFieldPressed = false;
  903. Refresh();
  904. if (CheckedChanged != null)
  905. CheckedChanged(this, new EventArgs());
  906. if (_lastMouseEventArgs != null)
  907. OnMouseMove(_lastMouseEventArgs);
  908. _lastMouseEventArgs = null;
  909. }
  910. }
  911. }