/verilog/jVerilog/Alsing.SyntaxBox/Classes/Selection.cs

https://github.com/bangonkali/electronics · C# · 460 lines · 341 code · 47 blank · 72 comment · 33 complexity · f2e64a9c0efa3b4b0c6a828d5206d584 MD5 · raw file

  1. // *
  2. // * Copyright (C) 2008 Roger Alsing : http://www.RogerAlsing.com
  3. // *
  4. // * This library is free software; you can redistribute it and/or modify it
  5. // * under the terms of the GNU Lesser General Public License 2.1 or later, as
  6. // * published by the Free Software Foundation. See the included license.txt
  7. // * or http://www.gnu.org/copyleft/lesser.html for details.
  8. // *
  9. // *
  10. using System;
  11. using Alsing.SourceCode;
  12. namespace Alsing.Windows.Forms.SyntaxBox
  13. {
  14. /// <summary>
  15. /// Selection class used by the SyntaxBoxControl
  16. /// </summary>
  17. public class Selection
  18. {
  19. /// <summary>
  20. /// Event fired when the selection has changed.
  21. /// </summary>
  22. public event EventHandler Change = null;
  23. private void PositionChange(object s, EventArgs e)
  24. {
  25. OnChange();
  26. }
  27. private void OnChange()
  28. {
  29. if (Change != null)
  30. Change(this, null);
  31. }
  32. #region Instance constructors
  33. /// <summary>
  34. /// Selection Constructor.
  35. /// </summary>
  36. /// <param name="control">Control that will use this selection</param>
  37. public Selection(EditViewControl control)
  38. {
  39. Control = control;
  40. Bounds = new TextRange();
  41. }
  42. #endregion Instance constructors
  43. #region Public instance properties
  44. /// <summary>
  45. /// Gets the text of the active selection
  46. /// </summary>
  47. public String Text
  48. {
  49. get
  50. {
  51. if (!IsValid)
  52. {
  53. return "";
  54. }
  55. else
  56. {
  57. return Control.Document.GetRange(LogicalBounds);
  58. }
  59. }
  60. set
  61. {
  62. if (Text == value)
  63. return;
  64. //selection text bug fix
  65. //
  66. //selection gets too short if \n is used instead of newline
  67. string tmp = value.Replace(Environment.NewLine, "\n");
  68. tmp = tmp.Replace("\n", Environment.NewLine);
  69. value = tmp;
  70. //---
  71. TextPoint oCaretPos = Control.Caret.Position;
  72. int nCaretX = oCaretPos.X;
  73. int nCaretY = oCaretPos.Y;
  74. Control.Document.StartUndoCapture();
  75. DeleteSelection();
  76. Control.Document.InsertText(value, oCaretPos.X, oCaretPos.Y);
  77. SelLength = value.Length;
  78. if (nCaretX != oCaretPos.X || nCaretY != oCaretPos.Y)
  79. {
  80. Control.Caret.Position = new TextPoint(Bounds.LastColumn,
  81. Bounds.LastRow);
  82. }
  83. Control.Document.EndUndoCapture();
  84. Control.Document.InvokeChange();
  85. }
  86. }
  87. /// <summary>
  88. /// Returns the normalized positions of the selection.
  89. /// Swapping start and end values if the selection is reversed.
  90. /// </summary>
  91. public TextRange LogicalBounds
  92. {
  93. get
  94. {
  95. var r = new TextRange();
  96. if (Bounds.FirstRow < Bounds.LastRow)
  97. {
  98. return Bounds;
  99. }
  100. else if (Bounds.FirstRow == Bounds.LastRow &&
  101. Bounds.FirstColumn < Bounds.LastColumn)
  102. {
  103. return Bounds;
  104. }
  105. else
  106. {
  107. r.FirstColumn = Bounds.LastColumn;
  108. r.FirstRow = Bounds.LastRow;
  109. r.LastColumn = Bounds.FirstColumn;
  110. r.LastRow = Bounds.FirstRow;
  111. return r;
  112. }
  113. }
  114. }
  115. /// <summary>
  116. /// Returns true if the selection contains One or more chars
  117. /// </summary>
  118. public bool IsValid
  119. {
  120. get
  121. {
  122. return (LogicalBounds.FirstColumn != LogicalBounds.LastColumn
  123. || LogicalBounds.FirstRow != LogicalBounds.LastRow);
  124. }
  125. }
  126. /// <summary>
  127. /// gets or sets the length of the selection in chars
  128. /// </summary>
  129. public int SelLength
  130. {
  131. get
  132. {
  133. var p1 = new TextPoint(Bounds.FirstColumn,
  134. Bounds.FirstRow);
  135. var p2 = new TextPoint(Bounds.LastColumn,
  136. Bounds.LastRow);
  137. int i1 = Control.Document.PointToIntPos(p1);
  138. int i2 = Control.Document.PointToIntPos(p2);
  139. return i2 - i1;
  140. }
  141. set { SelEnd = SelStart + value; }
  142. }
  143. /// <summary>
  144. /// Gets or Sets the Selection end as an index in the document text.
  145. /// </summary>
  146. public int SelEnd
  147. {
  148. get
  149. {
  150. var p = new TextPoint(Bounds.LastColumn, Bounds.LastRow)
  151. ;
  152. return Control.Document.PointToIntPos(p);
  153. }
  154. set
  155. {
  156. TextPoint p = Control.Document.IntPosToPoint(value);
  157. Bounds.LastColumn = p.X;
  158. Bounds.LastRow = p.Y;
  159. }
  160. }
  161. /// <summary>
  162. /// Gets or Sets the Selection start as an index in the document text.
  163. /// </summary>
  164. public int SelStart
  165. {
  166. get
  167. {
  168. var p = new TextPoint(Bounds.FirstColumn,
  169. Bounds.FirstRow);
  170. return Control.Document.PointToIntPos(p);
  171. }
  172. set
  173. {
  174. TextPoint p = Control.Document.IntPosToPoint(value);
  175. Bounds.FirstColumn = p.X;
  176. Bounds.FirstRow = p.Y;
  177. }
  178. }
  179. /// <summary>
  180. /// Gets or Sets the logical Selection start as an index in the document text.
  181. /// </summary>
  182. public int LogicalSelStart
  183. {
  184. get
  185. {
  186. var p = new TextPoint(LogicalBounds.FirstColumn,
  187. LogicalBounds.FirstRow);
  188. return Control.Document.PointToIntPos(p);
  189. }
  190. set
  191. {
  192. TextPoint p = Control.Document.IntPosToPoint(value);
  193. Bounds.FirstColumn = p.X;
  194. Bounds.FirstRow = p.Y;
  195. }
  196. }
  197. #endregion Public instance properties
  198. #region Public instance methods
  199. /// <summary>
  200. /// Indent the active selection one step.
  201. /// </summary>
  202. public void Indent()
  203. {
  204. if (!IsValid)
  205. return;
  206. Row xtr = null;
  207. var ActionGroup = new UndoBlockCollection();
  208. for (int i = LogicalBounds.FirstRow;
  209. i <=
  210. LogicalBounds.LastRow;
  211. i++)
  212. {
  213. xtr = Control.Document[i];
  214. xtr.Text = "\t" + xtr.Text;
  215. var b = new UndoBlock();
  216. b.Action = UndoAction.InsertRange;
  217. b.Text = "\t";
  218. b.Position.X = 0;
  219. b.Position.Y = i;
  220. ActionGroup.Add(b);
  221. }
  222. if (ActionGroup.Count > 0)
  223. Control.Document.AddToUndoList(ActionGroup);
  224. Bounds = LogicalBounds;
  225. Bounds.FirstColumn = 0;
  226. Bounds.LastColumn = xtr.Text.Length;
  227. Control.Caret.Position.X = LogicalBounds.LastColumn;
  228. Control.Caret.Position.Y = LogicalBounds.LastRow;
  229. }
  230. /// <summary>
  231. /// Outdent the active selection one step
  232. /// </summary>
  233. public void Outdent()
  234. {
  235. if (!IsValid)
  236. return;
  237. Row xtr = null;
  238. var ActionGroup = new UndoBlockCollection();
  239. for (int i = LogicalBounds.FirstRow;
  240. i <=
  241. LogicalBounds.LastRow;
  242. i++)
  243. {
  244. xtr = Control.Document[i];
  245. var b = new UndoBlock();
  246. b.Action = UndoAction.DeleteRange;
  247. b.Position.X = 0;
  248. b.Position.Y = i;
  249. ActionGroup.Add(b);
  250. string s = xtr.Text;
  251. if (s.StartsWith("\t"))
  252. {
  253. b.Text = s.Substring(0, 1);
  254. s = s.Substring(1);
  255. }
  256. if (s.StartsWith(" "))
  257. {
  258. b.Text = s.Substring(0, 4);
  259. s = s.Substring(4);
  260. }
  261. xtr.Text = s;
  262. }
  263. if (ActionGroup.Count > 0)
  264. Control.Document.AddToUndoList(ActionGroup);
  265. Bounds = LogicalBounds;
  266. Bounds.FirstColumn = 0;
  267. Bounds.LastColumn = xtr.Text.Length;
  268. Control.Caret.Position.X = LogicalBounds.LastColumn;
  269. Control.Caret.Position.Y = LogicalBounds.LastRow;
  270. }
  271. public void Indent(string Pattern)
  272. {
  273. if (!IsValid)
  274. return;
  275. Row xtr = null;
  276. var ActionGroup = new UndoBlockCollection();
  277. for (int i = LogicalBounds.FirstRow;
  278. i <=
  279. LogicalBounds.LastRow;
  280. i++)
  281. {
  282. xtr = Control.Document[i];
  283. xtr.Text = Pattern + xtr.Text;
  284. var b = new UndoBlock();
  285. b.Action = UndoAction.InsertRange;
  286. b.Text = Pattern;
  287. b.Position.X = 0;
  288. b.Position.Y = i;
  289. ActionGroup.Add(b);
  290. }
  291. if (ActionGroup.Count > 0)
  292. Control.Document.AddToUndoList(ActionGroup);
  293. Bounds = LogicalBounds;
  294. Bounds.FirstColumn = 0;
  295. Bounds.LastColumn = xtr.Text.Length;
  296. Control.Caret.Position.X = LogicalBounds.LastColumn;
  297. Control.Caret.Position.Y = LogicalBounds.LastRow;
  298. }
  299. /// <summary>
  300. /// Outdent the active selection one step
  301. /// </summary>
  302. public void Outdent(string Pattern)
  303. {
  304. if (!IsValid)
  305. return;
  306. Row xtr = null;
  307. var ActionGroup = new UndoBlockCollection();
  308. for (int i = LogicalBounds.FirstRow;
  309. i <=
  310. LogicalBounds.LastRow;
  311. i++)
  312. {
  313. xtr = Control.Document[i];
  314. var b = new UndoBlock();
  315. b.Action = UndoAction.DeleteRange;
  316. b.Position.X = 0;
  317. b.Position.Y = i;
  318. ActionGroup.Add(b);
  319. string s = xtr.Text;
  320. if (s.StartsWith(Pattern))
  321. {
  322. b.Text = s.Substring(0, Pattern.Length);
  323. s = s.Substring(Pattern.Length);
  324. }
  325. xtr.Text = s;
  326. }
  327. if (ActionGroup.Count > 0)
  328. Control.Document.AddToUndoList(ActionGroup);
  329. Bounds = LogicalBounds;
  330. Bounds.FirstColumn = 0;
  331. Bounds.LastColumn = xtr.Text.Length;
  332. Control.Caret.Position.X = LogicalBounds.LastColumn;
  333. Control.Caret.Position.Y = LogicalBounds.LastRow;
  334. }
  335. /// <summary>
  336. /// Delete the active selection.
  337. /// <seealso cref="ClearSelection"/>
  338. /// </summary>
  339. public void DeleteSelection()
  340. {
  341. TextRange r = LogicalBounds;
  342. int x = r.FirstColumn;
  343. int y = r.FirstRow;
  344. Control.Document.DeleteRange(r);
  345. Control.Caret.Position.X = x;
  346. Control.Caret.Position.Y = y;
  347. ClearSelection();
  348. Control.ScrollIntoView();
  349. }
  350. /// <summary>
  351. /// Clear the active selection
  352. /// <seealso cref="DeleteSelection"/>
  353. /// </summary>
  354. public void ClearSelection()
  355. {
  356. Bounds.FirstColumn = Control.Caret.Position.X;
  357. Bounds.FirstRow = Control.Caret.Position.Y;
  358. Bounds.LastColumn = Control.Caret.Position.X;
  359. Bounds.LastRow = Control.Caret.Position.Y;
  360. }
  361. /// <summary>
  362. /// Make a selection from the current selection start to the position of the caret
  363. /// </summary>
  364. public void MakeSelection()
  365. {
  366. Bounds.LastColumn = Control.Caret.Position.X;
  367. Bounds.LastRow = Control.Caret.Position.Y;
  368. }
  369. /// <summary>
  370. /// Select all text.
  371. /// </summary>
  372. public void SelectAll()
  373. {
  374. Bounds.FirstColumn = 0;
  375. Bounds.FirstRow = 0;
  376. Bounds.LastColumn = Control.Document[Control.Document.Count -
  377. 1].Text.Length;
  378. Bounds.LastRow = Control.Document.Count - 1;
  379. Control.Caret.Position.X = Bounds.LastColumn;
  380. Control.Caret.Position.Y = Bounds.LastRow;
  381. Control.ScrollIntoView();
  382. }
  383. #endregion Public instance methods
  384. #region Public instance fields
  385. /// <summary>
  386. /// The bounds of the selection
  387. /// </summary>
  388. ///
  389. private TextRange _Bounds;
  390. public TextRange Bounds
  391. {
  392. get { return _Bounds; }
  393. set
  394. {
  395. if (_Bounds != null)
  396. {
  397. _Bounds.Change -= Bounds_Change;
  398. }
  399. _Bounds = value;
  400. _Bounds.Change += Bounds_Change;
  401. OnChange();
  402. }
  403. }
  404. private void Bounds_Change(object s, EventArgs e)
  405. {
  406. OnChange();
  407. }
  408. #endregion Public instance fields
  409. #region Protected instance fields
  410. private readonly EditViewControl Control;
  411. #endregion Protected instance fields
  412. }
  413. }