ToggleSwitch.cs 31 KB

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