/src/Controls/SETextBox.cs

https://gitlab.com/minaz922/subtitleedit · C# · 265 lines · 232 code · 24 blank · 9 comment · 99 complexity · 96bfae07d82cfb142fe6dbbaf174dac0 MD5 · raw file

  1. using System;
  2. using System.Drawing;
  3. using System.Windows.Forms;
  4. namespace Nikse.SubtitleEdit.Controls
  5. {
  6. /// <summary>
  7. /// TextBox where double click selects current word
  8. /// </summary>
  9. public class SETextBox : TextBox
  10. {
  11. private string breakChars = "\".!?,)([]<>:;♪{}-/#*| ¿¡" + Environment.NewLine + "\t";
  12. string _dragText = string.Empty;
  13. int _dragStartFrom = 0;
  14. long _dragStartTicks = 0;
  15. bool _dragRemoveOld = false;
  16. bool _dragFromThis = false;
  17. public SETextBox()
  18. {
  19. AllowDrop = true;
  20. DragEnter += new DragEventHandler(SETextBox_DragEnter);
  21. // DragOver += new DragEventHandler(SETextBox_DragOver); could draw some gfx where drop position is...
  22. DragDrop += new DragEventHandler(SETextBox_DragDrop);
  23. MouseDown += new MouseEventHandler(SETextBox_MouseDown);
  24. MouseUp += new MouseEventHandler(SETextBox_MouseUp);
  25. KeyDown += SETextBox_KeyDown;
  26. }
  27. void SETextBox_KeyDown(object sender, KeyEventArgs e)
  28. {
  29. if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Back)
  30. {
  31. int index = SelectionStart;
  32. if (SelectionLength == 0)
  33. {
  34. string s = Text;
  35. int deleteFrom = index-1;
  36. if (deleteFrom > 0 && deleteFrom < s.Length)
  37. {
  38. if (s[deleteFrom] == ' ')
  39. deleteFrom--;
  40. while (deleteFrom > 0 && !(breakChars).Contains(s.Substring(deleteFrom, 1)))
  41. {
  42. deleteFrom--;
  43. }
  44. if (deleteFrom == index - 1)
  45. {
  46. while (deleteFrom > 0 && (breakChars.Replace(" ", string.Empty)).Contains(s.Substring(deleteFrom - 1, 1)))
  47. {
  48. deleteFrom--;
  49. }
  50. }
  51. if (s[deleteFrom] == ' ')
  52. deleteFrom++;
  53. Text = s.Remove(deleteFrom, index - deleteFrom);
  54. SelectionStart = deleteFrom;
  55. }
  56. }
  57. e.SuppressKeyPress = true;
  58. }
  59. }
  60. void SETextBox_MouseUp(object sender, MouseEventArgs e)
  61. {
  62. _dragRemoveOld = false;
  63. _dragFromThis = false;
  64. }
  65. void SETextBox_MouseDown(object sender, MouseEventArgs e)
  66. {
  67. if (MouseButtons == System.Windows.Forms.MouseButtons.Left && !string.IsNullOrEmpty(_dragText))
  68. {
  69. Point pt = new Point(e.X, e.Y);
  70. int index = GetCharIndexFromPosition(pt);
  71. if (index >= _dragStartFrom && index <= _dragStartFrom + _dragText.Length)
  72. {
  73. // re-make selection
  74. SelectionStart = _dragStartFrom;
  75. SelectionLength = _dragText.Length;
  76. DataObject dataObject = new DataObject();
  77. dataObject.SetText(_dragText, TextDataFormat.UnicodeText);
  78. dataObject.SetText(_dragText, TextDataFormat.Text);
  79. _dragFromThis = true;
  80. if (Control.ModifierKeys == Keys.Control)
  81. {
  82. _dragRemoveOld = false;
  83. DoDragDrop(dataObject, DragDropEffects.Copy);
  84. }
  85. else if (Control.ModifierKeys == Keys.None)
  86. {
  87. _dragRemoveOld = true;
  88. DoDragDrop(dataObject, DragDropEffects.Move);
  89. }
  90. }
  91. }
  92. }
  93. void SETextBox_DragDrop(object sender, DragEventArgs e)
  94. {
  95. Point pt = new Point(e.X, e.Y);
  96. pt = PointToClient(pt);
  97. int index = GetCharIndexFromPosition(pt);
  98. string newText = string.Empty;
  99. if (e.Data.GetDataPresent(DataFormats.UnicodeText))
  100. newText = (string)e.Data.GetData(DataFormats.UnicodeText);
  101. else
  102. newText = (string)e.Data.GetData(DataFormats.Text);
  103. if (Text.Trim().Length == 0)
  104. {
  105. Text = newText;
  106. }
  107. else
  108. {
  109. bool justAppend = index == Text.Length - 1 && index > 0;
  110. if (_dragFromThis)
  111. {
  112. _dragFromThis = false;
  113. long milliseconds = (DateTime.Now.Ticks - _dragStartTicks) / 10000;
  114. if (milliseconds < 400)
  115. {
  116. SelectionLength = 0;
  117. if (index == Text.Length - 1 && index > 0)
  118. index++;
  119. SelectionStart = index;
  120. return; // too fast - nobody can drag'n'drop this fast
  121. }
  122. if (index >= _dragStartFrom && index <= _dragStartFrom + _dragText.Length)
  123. return; // don't drop same text at same position
  124. if (_dragRemoveOld)
  125. {
  126. _dragRemoveOld = false;
  127. Text = Text.Remove(_dragStartFrom, _dragText.Length);
  128. // fix spaces
  129. if (_dragStartFrom == 0 && Text.Length > 0 && Text[0] == ' ')
  130. {
  131. Text = Text.Remove(0, 1);
  132. index--;
  133. }
  134. else if (_dragStartFrom > 1 && Text.Length > _dragStartFrom + 1 && Text[_dragStartFrom] == ' ' && Text[_dragStartFrom - 1] == ' ')
  135. {
  136. Text = Text.Remove(_dragStartFrom, 1);
  137. if (_dragStartFrom < index)
  138. index--;
  139. }
  140. else if (_dragStartFrom > 0 && Text.Length > _dragStartFrom + 1 && Text[_dragStartFrom] == ' ' && ";:]<.!?".Contains(Text[_dragStartFrom + 1].ToString()))
  141. {
  142. Text = Text.Remove(_dragStartFrom, 1);
  143. if (_dragStartFrom < index)
  144. index--;
  145. }
  146. // fix index
  147. if (index > _dragStartFrom)
  148. index -= _dragText.Length;
  149. if (index < 0)
  150. index = 0;
  151. }
  152. }
  153. if (justAppend)
  154. {
  155. index = Text.Length;
  156. Text += newText;
  157. }
  158. else
  159. {
  160. Text = Text.Insert(index, newText);
  161. }
  162. // fix start spaces
  163. int endIndex = index + newText.Length;
  164. if (index > 0 && !newText.StartsWith(" ") && Text[index - 1] != ' ')
  165. {
  166. Text = Text.Insert(index, " ");
  167. endIndex++;
  168. }
  169. else if (index > 0 && newText.StartsWith(" ") && Text[index - 1] == ' ')
  170. {
  171. Text = Text.Remove(index, 1);
  172. endIndex--;
  173. }
  174. // fix end spaces
  175. if (endIndex < Text.Length && !newText.EndsWith(" ") && Text[endIndex] != ' ')
  176. {
  177. bool lastWord = ";:]<.!?".Contains(Text[endIndex].ToString());
  178. if (!lastWord)
  179. Text = Text.Insert(endIndex, " ");
  180. }
  181. else if (endIndex < Text.Length && newText.EndsWith(" ") && Text[endIndex] == ' ')
  182. {
  183. Text = Text.Remove(endIndex, 1);
  184. }
  185. SelectionStart = index+1;
  186. SelectCurrentWord(this);
  187. }
  188. _dragRemoveOld = false;
  189. _dragFromThis = false;
  190. }
  191. void SETextBox_DragEnter(object sender, DragEventArgs e)
  192. {
  193. if (e.Data.GetDataPresent(DataFormats.Text) || e.Data.GetDataPresent(DataFormats.UnicodeText))
  194. {
  195. if (Control.ModifierKeys == Keys.Control)
  196. e.Effect = DragDropEffects.Copy;
  197. else
  198. e.Effect = DragDropEffects.Move;
  199. }
  200. else
  201. {
  202. e.Effect = DragDropEffects.None;
  203. }
  204. }
  205. protected override void WndProc(ref Message m)
  206. {
  207. const int WM_DBLCLICK = 0xA3;
  208. const int WM_LBUTTONDBLCLK = 0x203;
  209. const int WM_LBUTTONDOWN = 0x0201;
  210. if (m.Msg == WM_DBLCLICK || m.Msg == WM_LBUTTONDBLCLK)
  211. {
  212. SelectCurrentWord(this);
  213. return;
  214. }
  215. if (m.Msg == WM_LBUTTONDOWN)
  216. {
  217. _dragText = SelectedText;
  218. _dragStartFrom = SelectionStart;
  219. _dragStartTicks = DateTime.Now.Ticks;
  220. }
  221. base.WndProc(ref m);
  222. }
  223. private void SelectCurrentWord(TextBox tb)
  224. {
  225. int selectionLength = 0;
  226. int i = tb.SelectionStart;
  227. while (i > 0 && breakChars.Contains(tb.Text.Substring(i - 1, 1)) == false)
  228. i--;
  229. tb.SelectionStart = i;
  230. for (; i < tb.Text.Length; i++)
  231. {
  232. if (breakChars.Contains(tb.Text.Substring(i, 1)))
  233. break;
  234. selectionLength++;
  235. }
  236. tb.SelectionLength = selectionLength;
  237. if (selectionLength > 0)
  238. this.OnMouseMove(null);
  239. }
  240. }
  241. }