/LSharp Studio/Fireball/Fireball.CodeEditor/Fireball.CodeEditor/Editors/Selection.cs

https://github.com/westybsa/MP.LSharp · C# · 440 lines · 325 code · 51 blank · 64 comment · 37 complexity · 212ac0f8597f4340ebd3dd50717ddfd6 MD5 · raw file

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