Editor.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. using System;
  2. using System.Text;
  3. using Terminal.Gui;
  4. namespace UICatalog {
  5. [ScenarioMetadata (Name: "Editor", Description: "A Terminal.Gui Text Editor via TextView")]
  6. [ScenarioCategory ("Controls")]
  7. [ScenarioCategory ("Dialogs")]
  8. [ScenarioCategory ("Text")]
  9. [ScenarioCategory ("Dialogs")]
  10. [ScenarioCategory ("TopLevel")]
  11. class Editor : Scenario {
  12. private string _fileName = "demo.txt";
  13. private TextView _textView;
  14. private bool _saved = true;
  15. private ScrollBarView _scrollBar;
  16. private byte [] _originalText;
  17. private string _textToFind;
  18. private string _textToReplace;
  19. private bool _matchCase;
  20. private bool _matchWholeWord;
  21. Window winDialog;
  22. public override void Init (Toplevel top, ColorScheme colorScheme)
  23. {
  24. Application.Init ();
  25. Top = top;
  26. if (Top == null) {
  27. Top = Application.Top;
  28. }
  29. var menu = new MenuBar (new MenuBarItem [] {
  30. new MenuBarItem ("_File", new MenuItem [] {
  31. new MenuItem ("_New", "", () => New()),
  32. new MenuItem ("_Open", "", () => Open()),
  33. new MenuItem ("_Save", "", () => Save()),
  34. new MenuItem ("_Save As", "", () => SaveAs()),
  35. new MenuItem ("_Close", "", () => CloseFile()),
  36. null,
  37. new MenuItem ("_Quit", "", () => Quit()),
  38. }),
  39. new MenuBarItem ("_Edit", new MenuItem [] {
  40. new MenuItem ("_Copy", "", () => Copy(),null,null, Key.CtrlMask | Key.C),
  41. new MenuItem ("C_ut", "", () => Cut(),null,null, Key.CtrlMask | Key.W),
  42. new MenuItem ("_Paste", "", () => Paste(),null,null, Key.CtrlMask | Key.Y),
  43. null,
  44. new MenuItem ("_Find", "", () => Find(),null,null, Key.CtrlMask | Key.S),
  45. new MenuItem ("Find _Next", "", () => FindNext(),null,null, Key.CtrlMask | Key.ShiftMask | Key.S),
  46. new MenuItem ("Find P_revious", "", () => FindPrevious(),null,null, Key.CtrlMask | Key.ShiftMask | Key.AltMask | Key.S),
  47. new MenuItem ("_Replace", "", () => Replace(),null,null, Key.CtrlMask | Key.R),
  48. new MenuItem ("Replace Ne_xt", "", () => ReplaceNext(),null,null, Key.CtrlMask | Key.ShiftMask | Key.R),
  49. new MenuItem ("Replace Pre_vious", "", () => ReplacePrevious(),null,null, Key.CtrlMask | Key.ShiftMask | Key.AltMask | Key.R),
  50. new MenuItem ("Replace _All", "", () => ReplaceAll(),null,null, Key.CtrlMask | Key.ShiftMask | Key.AltMask | Key.A),
  51. null,
  52. new MenuItem ("_Select All", "", () => SelectAll(),null,null, Key.CtrlMask | Key.T)
  53. }),
  54. new MenuBarItem ("_ScrollBarView", CreateKeepChecked ()),
  55. new MenuBarItem ("_Cursor", new MenuItem [] {
  56. new MenuItem ("_Invisible", "", () => SetCursor(CursorVisibility.Invisible)),
  57. new MenuItem ("_Box", "", () => SetCursor(CursorVisibility.Box)),
  58. new MenuItem ("_Underline", "", () => SetCursor(CursorVisibility.Underline)),
  59. new MenuItem ("", "", () => {}, () => { return false; }),
  60. new MenuItem ("xTerm :", "", () => {}, () => { return false; }),
  61. new MenuItem ("", "", () => {}, () => { return false; }),
  62. new MenuItem (" _Default", "", () => SetCursor(CursorVisibility.Default)),
  63. new MenuItem (" _Vertical", "", () => SetCursor(CursorVisibility.Vertical)),
  64. new MenuItem (" V_ertical Fix", "", () => SetCursor(CursorVisibility.VerticalFix)),
  65. new MenuItem (" B_ox Fix", "", () => SetCursor(CursorVisibility.BoxFix)),
  66. new MenuItem (" U_nderline Fix","", () => SetCursor(CursorVisibility.UnderlineFix))
  67. }),
  68. new MenuBarItem ("Forma_t", new MenuItem [] {
  69. CreateWrapChecked (),
  70. CreateAllowsTabChecked ()
  71. })
  72. });
  73. Top.Add (menu);
  74. var statusBar = new StatusBar (new StatusItem [] {
  75. new StatusItem(Key.F2, "~F2~ Open", () => Open()),
  76. new StatusItem(Key.F3, "~F3~ Save", () => Save()),
  77. new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
  78. });
  79. Top.Add (statusBar);
  80. CreateDemoFile (_fileName);
  81. Win = new Window (_fileName ?? "Untitled") {
  82. X = 0,
  83. Y = 1,
  84. Width = Dim.Fill (),
  85. Height = Dim.Fill (),
  86. ColorScheme = colorScheme,
  87. };
  88. Top.Add (Win);
  89. _textView = new TextView () {
  90. X = 0,
  91. Y = 0,
  92. Width = Dim.Fill (),
  93. Height = Dim.Fill (),
  94. BottomOffset = 1,
  95. RightOffset = 1
  96. };
  97. LoadFile ();
  98. Win.Add (_textView);
  99. _scrollBar = new ScrollBarView (_textView, true);
  100. _scrollBar.ChangedPosition += () => {
  101. _textView.TopRow = _scrollBar.Position;
  102. if (_textView.TopRow != _scrollBar.Position) {
  103. _scrollBar.Position = _textView.TopRow;
  104. }
  105. _textView.SetNeedsDisplay ();
  106. };
  107. _scrollBar.OtherScrollBarView.ChangedPosition += () => {
  108. _textView.LeftColumn = _scrollBar.OtherScrollBarView.Position;
  109. if (_textView.LeftColumn != _scrollBar.OtherScrollBarView.Position) {
  110. _scrollBar.OtherScrollBarView.Position = _textView.LeftColumn;
  111. }
  112. _textView.SetNeedsDisplay ();
  113. };
  114. _textView.DrawContent += (e) => {
  115. _scrollBar.Size = _textView.Lines;
  116. _scrollBar.Position = _textView.TopRow;
  117. if (_scrollBar.OtherScrollBarView != null) {
  118. _scrollBar.OtherScrollBarView.Size = _textView.Maxlength;
  119. _scrollBar.OtherScrollBarView.Position = _textView.LeftColumn;
  120. }
  121. _scrollBar.LayoutSubviews ();
  122. _scrollBar.Refresh ();
  123. };
  124. Win.KeyPress += (e) => {
  125. if (winDialog != null && (e.KeyEvent.Key == Key.Esc
  126. || e.KeyEvent.Key == (Key.Q | Key.CtrlMask))) {
  127. DisposeWinDialog ();
  128. } else if (e.KeyEvent.Key == (Key.Q | Key.CtrlMask)) {
  129. Quit ();
  130. e.Handled = true;
  131. }
  132. };
  133. }
  134. private void DisposeWinDialog ()
  135. {
  136. winDialog.Dispose ();
  137. Win.Remove (winDialog);
  138. winDialog = null;
  139. }
  140. public override void Setup ()
  141. {
  142. }
  143. private void New (bool checkChanges = true)
  144. {
  145. if (checkChanges && !CanCloseFile ()) {
  146. return;
  147. }
  148. Win.Title = "Untitled.txt";
  149. _fileName = null;
  150. _originalText = new System.IO.MemoryStream ().ToArray ();
  151. _textView.Text = _originalText;
  152. }
  153. private void LoadFile ()
  154. {
  155. if (_fileName != null) {
  156. // FIXED: BUGBUG: #452 TextView.LoadFile keeps file open and provides no way of closing it
  157. _textView.LoadFile (_fileName);
  158. //_textView.Text = System.IO.File.ReadAllText (_fileName);
  159. _originalText = _textView.Text.ToByteArray ();
  160. Win.Title = _fileName;
  161. _saved = true;
  162. }
  163. }
  164. private void Paste ()
  165. {
  166. if (_textView != null) {
  167. _textView.Paste ();
  168. }
  169. }
  170. private void Cut ()
  171. {
  172. if (_textView != null) {
  173. _textView.Cut ();
  174. }
  175. }
  176. private void Copy ()
  177. {
  178. if (_textView != null) {
  179. _textView.Copy ();
  180. }
  181. }
  182. private void SelectAll ()
  183. {
  184. _textView.SelectAll ();
  185. }
  186. private void Find ()
  187. {
  188. CreateFindReplace ();
  189. }
  190. private void FindNext ()
  191. {
  192. ContinueFind ();
  193. }
  194. private void FindPrevious ()
  195. {
  196. ContinueFind (false);
  197. }
  198. private void ContinueFind (bool next = true, bool replace = false)
  199. {
  200. if (!replace && string.IsNullOrEmpty (_textToFind)) {
  201. Find ();
  202. return;
  203. } else if (replace && (string.IsNullOrEmpty (_textToFind)
  204. || (winDialog == null && string.IsNullOrEmpty (_textToReplace)))) {
  205. Replace ();
  206. return;
  207. }
  208. bool found;
  209. bool gaveFullTurn;
  210. if (next) {
  211. if (!replace) {
  212. found = _textView.FindNextText (_textToFind, out gaveFullTurn, _matchCase, _matchWholeWord);
  213. } else {
  214. found = _textView.FindNextText (_textToFind, out gaveFullTurn, _matchCase, _matchWholeWord,
  215. _textToReplace, true);
  216. }
  217. } else {
  218. if (!replace) {
  219. found = _textView.FindPreviousText (_textToFind, out gaveFullTurn, _matchCase, _matchWholeWord);
  220. } else {
  221. found = _textView.FindPreviousText (_textToFind, out gaveFullTurn, _matchCase, _matchWholeWord,
  222. _textToReplace, true);
  223. }
  224. }
  225. if (!found) {
  226. MessageBox.Query ("Find", $"The following specified text was not found: '{_textToFind}'", "Ok");
  227. } else if (gaveFullTurn) {
  228. MessageBox.Query ("Find", $"No more occurrences were found for the following specified text: '{_textToFind}'", "Ok");
  229. }
  230. }
  231. private void Replace ()
  232. {
  233. CreateFindReplace (false);
  234. }
  235. private void ReplaceNext ()
  236. {
  237. ContinueFind (true, true);
  238. }
  239. private void ReplacePrevious ()
  240. {
  241. ContinueFind (false, true);
  242. }
  243. private void ReplaceAll ()
  244. {
  245. if (string.IsNullOrEmpty (_textToFind) || (string.IsNullOrEmpty (_textToReplace) && winDialog == null)) {
  246. Replace ();
  247. return;
  248. }
  249. if (_textView.ReplaceAllText (_textToFind, _matchCase, _matchWholeWord, _textToReplace)) {
  250. MessageBox.Query ("Replace All", $"All occurrences were replaced for the following specified text: '{_textToReplace}'", "Ok");
  251. } else {
  252. MessageBox.Query ("Replace All", $"None of the following specified text was found: '{_textToFind}'", "Ok");
  253. }
  254. }
  255. private void SetCursor (CursorVisibility visibility)
  256. {
  257. _textView.DesiredCursorVisibility = visibility;
  258. }
  259. private bool CanCloseFile ()
  260. {
  261. if (_textView.Text == _originalText) {
  262. return true;
  263. }
  264. var r = MessageBox.ErrorQuery ("Save File",
  265. $"Do you want save changes in {Win.Title}?", "Yes", "No", "Cancel");
  266. if (r == 0) {
  267. return Save ();
  268. } else if (r == 1) {
  269. return true;
  270. }
  271. return false;
  272. }
  273. private void Open ()
  274. {
  275. if (!CanCloseFile ()) {
  276. return;
  277. }
  278. var d = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = false };
  279. Application.Run (d);
  280. if (!d.Canceled && d.FilePaths.Count > 0) {
  281. _fileName = d.FilePaths [0];
  282. LoadFile ();
  283. }
  284. }
  285. private bool Save ()
  286. {
  287. if (_fileName != null) {
  288. // FIXED: BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
  289. // As a result files saved on Windows and then read back will show invalid chars.
  290. return SaveFile (Win.Title.ToString (), _fileName);
  291. } else {
  292. return SaveAs ();
  293. }
  294. }
  295. private bool SaveAs ()
  296. {
  297. var sd = new SaveDialog ("Save file", "Choose the path where to save the file.");
  298. sd.FilePath = System.IO.Path.Combine (sd.FilePath.ToString (), Win.Title.ToString ());
  299. Application.Run (sd);
  300. if (!sd.Canceled) {
  301. if (System.IO.File.Exists (sd.FilePath.ToString ())) {
  302. if (MessageBox.Query ("Save File",
  303. "File already exists. Overwrite any way?", "No", "Ok") == 1) {
  304. return SaveFile (sd.FileName.ToString (), sd.FilePath.ToString ());
  305. } else {
  306. _saved = false;
  307. return _saved;
  308. }
  309. } else {
  310. return SaveFile (sd.FileName.ToString (), sd.FilePath.ToString ());
  311. }
  312. } else {
  313. _saved = false;
  314. return _saved;
  315. }
  316. }
  317. private bool SaveFile (string title, string file)
  318. {
  319. try {
  320. Win.Title = title;
  321. _fileName = file;
  322. System.IO.File.WriteAllText (_fileName, _textView.Text.ToString ());
  323. _originalText = _textView.Text.ToByteArray ();
  324. _saved = true;
  325. MessageBox.Query ("Save File", "File was successfully saved.", "Ok");
  326. } catch (Exception ex) {
  327. MessageBox.ErrorQuery ("Error", ex.Message, "Ok");
  328. return false;
  329. }
  330. return true;
  331. }
  332. private void CloseFile ()
  333. {
  334. if (!CanCloseFile ()) {
  335. return;
  336. }
  337. try {
  338. _textView.CloseFile ();
  339. New (false);
  340. } catch (Exception ex) {
  341. MessageBox.ErrorQuery ("Error", ex.Message, "Ok");
  342. }
  343. }
  344. private void Quit ()
  345. {
  346. if (!CanCloseFile ()) {
  347. return;
  348. }
  349. Application.RequestStop ();
  350. }
  351. private void CreateDemoFile (string fileName)
  352. {
  353. var sb = new StringBuilder ();
  354. // FIXED: BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
  355. sb.Append ("Hello world.\n");
  356. sb.Append ("This is a test of the Emergency Broadcast System.\n");
  357. for (int i = 0; i < 30; i++) {
  358. sb.Append ($"{i} - This is a test with a very long line and many lines to test the ScrollViewBar against the TextView. - {i}\n");
  359. }
  360. var sw = System.IO.File.CreateText (fileName);
  361. sw.Write (sb.ToString ());
  362. sw.Close ();
  363. }
  364. private MenuItem [] CreateKeepChecked ()
  365. {
  366. var item = new MenuItem ();
  367. item.Title = "Keep Content Always In Viewport";
  368. item.CheckType |= MenuItemCheckStyle.Checked;
  369. item.Checked = true;
  370. item.Action += () => _scrollBar.KeepContentAlwaysInViewport = item.Checked = !item.Checked;
  371. return new MenuItem [] { item };
  372. }
  373. private MenuItem CreateWrapChecked ()
  374. {
  375. var item = new MenuItem {
  376. Title = "Word Wrap"
  377. };
  378. item.CheckType |= MenuItemCheckStyle.Checked;
  379. item.Checked = false;
  380. item.Action += () => {
  381. _textView.WordWrap = item.Checked = !item.Checked;
  382. if (_textView.WordWrap) {
  383. _scrollBar.AutoHideScrollBars = false;
  384. _scrollBar.OtherScrollBarView.ShowScrollIndicator = false;
  385. _textView.BottomOffset = 0;
  386. } else {
  387. _scrollBar.AutoHideScrollBars = true;
  388. _textView.BottomOffset = 1;
  389. }
  390. };
  391. return item;
  392. }
  393. private MenuItem CreateAllowsTabChecked ()
  394. {
  395. var item = new MenuItem {
  396. Title = "Allows Tab"
  397. };
  398. item.CheckType |= MenuItemCheckStyle.Checked;
  399. item.Checked = true;
  400. item.Action += () => {
  401. _textView.AllowsTab = item.Checked = !item.Checked;
  402. };
  403. return item;
  404. }
  405. private void CreateFindReplace (bool isFind = true)
  406. {
  407. winDialog = new Window (isFind ? "Find" : "Replace") {
  408. X = Win.Bounds.Width / 2 - 30,
  409. Y = Win.Bounds.Height / 2 - 10,
  410. ColorScheme = Colors.Menu
  411. };
  412. var tabView = new TabView () {
  413. X = 0,
  414. Y = 0,
  415. Width = Dim.Fill (),
  416. Height = Dim.Fill ()
  417. };
  418. tabView.AddTab (new TabView.Tab ("Find", FindTab ()), isFind);
  419. var replace = ReplaceTab ();
  420. tabView.AddTab (new TabView.Tab ("Replace", replace), !isFind);
  421. tabView.SelectedTabChanged += (s, e) => tabView.SelectedTab.View.FocusFirst ();
  422. winDialog.Add (tabView);
  423. Win.Add (winDialog);
  424. winDialog.Width = replace.Width + 4;
  425. winDialog.Height = replace.Height + 4;
  426. winDialog.SuperView.BringSubviewToFront (winDialog);
  427. winDialog.SetFocus ();
  428. }
  429. private void SetFindText ()
  430. {
  431. _textToFind = !_textView.SelectedText.IsEmpty
  432. ? _textView.SelectedText.ToString ()
  433. : string.IsNullOrEmpty (_textToFind) ? "" : _textToFind;
  434. _textToReplace = string.IsNullOrEmpty (_textToReplace) ? "" : _textToReplace;
  435. }
  436. private View FindTab ()
  437. {
  438. var d = new View () {
  439. X = 0,
  440. Y = 0,
  441. Width = Dim.Fill (),
  442. Height = Dim.Fill ()
  443. };
  444. d.DrawContent += (e) => {
  445. foreach (var v in d.Subviews) {
  446. v.SetNeedsDisplay ();
  447. }
  448. };
  449. var lblWidth = "Replace:".Length;
  450. var label = new Label (0, 1, "Find:") {
  451. Width = lblWidth,
  452. TextAlignment = TextAlignment.Right,
  453. LayoutStyle = LayoutStyle.Computed
  454. };
  455. d.Add (label);
  456. SetFindText ();
  457. var txtToFind = new TextField (_textToFind) {
  458. X = Pos.Right (label) + 1,
  459. Y = Pos.Top (label),
  460. Width = 20
  461. };
  462. txtToFind.Enter += (_) => txtToFind.Text = _textToFind;
  463. d.Add (txtToFind);
  464. var btnFindNext = new Button ("Find _Next") {
  465. X = Pos.Right (txtToFind) + 1,
  466. Y = Pos.Top (label),
  467. Width = 20,
  468. CanFocus = !txtToFind.Text.IsEmpty,
  469. TextAlignment = TextAlignment.Centered,
  470. IsDefault = true
  471. };
  472. btnFindNext.Clicked += () => FindNext ();
  473. d.Add (btnFindNext);
  474. var btnFindPrevious = new Button ("Find _Previous") {
  475. X = Pos.Right (txtToFind) + 1,
  476. Y = Pos.Top (btnFindNext) + 1,
  477. Width = 20,
  478. CanFocus = !txtToFind.Text.IsEmpty,
  479. TextAlignment = TextAlignment.Centered
  480. };
  481. btnFindPrevious.Clicked += () => FindPrevious ();
  482. d.Add (btnFindPrevious);
  483. txtToFind.TextChanged += (e) => {
  484. _textToFind = txtToFind.Text.ToString ();
  485. _textView.FindTextChanged ();
  486. btnFindNext.CanFocus = !txtToFind.Text.IsEmpty;
  487. btnFindPrevious.CanFocus = !txtToFind.Text.IsEmpty;
  488. };
  489. var btnCancel = new Button ("Cancel") {
  490. X = Pos.Right (txtToFind) + 1,
  491. Y = Pos.Top (btnFindPrevious) + 2,
  492. Width = 20,
  493. TextAlignment = TextAlignment.Centered
  494. };
  495. btnCancel.Clicked += () => {
  496. DisposeWinDialog ();
  497. };
  498. d.Add (btnCancel);
  499. var ckbMatchCase = new CheckBox ("Match c_ase") {
  500. X = 0,
  501. Y = Pos.Top (txtToFind) + 2,
  502. Checked = _matchCase
  503. };
  504. ckbMatchCase.Toggled += (e) => _matchCase = ckbMatchCase.Checked;
  505. d.Add (ckbMatchCase);
  506. var ckbMatchWholeWord = new CheckBox ("Match _whole word") {
  507. X = 0,
  508. Y = Pos.Top (ckbMatchCase) + 1,
  509. Checked = _matchWholeWord
  510. };
  511. ckbMatchWholeWord.Toggled += (e) => _matchWholeWord = ckbMatchWholeWord.Checked;
  512. d.Add (ckbMatchWholeWord);
  513. d.Width = label.Width + txtToFind.Width + btnFindNext.Width + 2;
  514. d.Height = btnFindNext.Height + btnFindPrevious.Height + btnCancel.Height + 4;
  515. return d;
  516. }
  517. private View ReplaceTab ()
  518. {
  519. var d = new View () {
  520. X = 0,
  521. Y = 0,
  522. Width = Dim.Fill (),
  523. Height = Dim.Fill ()
  524. };
  525. d.DrawContent += (e) => {
  526. foreach (var v in d.Subviews) {
  527. v.SetNeedsDisplay ();
  528. }
  529. };
  530. var lblWidth = "Replace:".Length;
  531. var label = new Label (0, 1, "Find:") {
  532. Width = lblWidth,
  533. TextAlignment = TextAlignment.Right,
  534. LayoutStyle = LayoutStyle.Computed
  535. };
  536. d.Add (label);
  537. SetFindText ();
  538. var txtToFind = new TextField (_textToFind) {
  539. X = Pos.Right (label) + 1,
  540. Y = Pos.Top (label),
  541. Width = 20
  542. };
  543. txtToFind.Enter += (_) => txtToFind.Text = _textToFind;
  544. d.Add (txtToFind);
  545. var btnFindNext = new Button ("Replace _Next") {
  546. X = Pos.Right (txtToFind) + 1,
  547. Y = Pos.Top (label),
  548. Width = 20,
  549. CanFocus = !txtToFind.Text.IsEmpty,
  550. TextAlignment = TextAlignment.Centered,
  551. IsDefault = true
  552. };
  553. btnFindNext.Clicked += () => ReplaceNext ();
  554. d.Add (btnFindNext);
  555. label = new Label ("Replace:") {
  556. X = Pos.Left (label),
  557. Y = Pos.Top (label) + 1,
  558. Width = lblWidth,
  559. TextAlignment = TextAlignment.Right
  560. };
  561. d.Add (label);
  562. SetFindText ();
  563. var txtToReplace = new TextField (_textToReplace) {
  564. X = Pos.Right (label) + 1,
  565. Y = Pos.Top (label),
  566. Width = 20
  567. };
  568. txtToReplace.TextChanged += (e) => _textToReplace = txtToReplace.Text.ToString ();
  569. d.Add (txtToReplace);
  570. var btnFindPrevious = new Button ("Replace _Previous") {
  571. X = Pos.Right (txtToFind) + 1,
  572. Y = Pos.Top (btnFindNext) + 1,
  573. Width = 20,
  574. CanFocus = !txtToFind.Text.IsEmpty,
  575. TextAlignment = TextAlignment.Centered
  576. };
  577. btnFindPrevious.Clicked += () => ReplacePrevious ();
  578. d.Add (btnFindPrevious);
  579. var btnReplaceAll = new Button ("Replace _All") {
  580. X = Pos.Right (txtToFind) + 1,
  581. Y = Pos.Top (btnFindPrevious) + 1,
  582. Width = 20,
  583. CanFocus = !txtToFind.Text.IsEmpty,
  584. TextAlignment = TextAlignment.Centered
  585. };
  586. btnReplaceAll.Clicked += () => ReplaceAll ();
  587. d.Add (btnReplaceAll);
  588. txtToFind.TextChanged += (e) => {
  589. _textToFind = txtToFind.Text.ToString ();
  590. _textView.FindTextChanged ();
  591. btnFindNext.CanFocus = !txtToFind.Text.IsEmpty;
  592. btnFindPrevious.CanFocus = !txtToFind.Text.IsEmpty;
  593. btnReplaceAll.CanFocus = !txtToFind.Text.IsEmpty;
  594. };
  595. var btnCancel = new Button ("Cancel") {
  596. X = Pos.Right (txtToFind) + 1,
  597. Y = Pos.Top (btnReplaceAll) + 1,
  598. Width = 20,
  599. TextAlignment = TextAlignment.Centered
  600. };
  601. btnCancel.Clicked += () => {
  602. DisposeWinDialog ();
  603. };
  604. d.Add (btnCancel);
  605. var ckbMatchCase = new CheckBox ("Match c_ase") {
  606. X = 0,
  607. Y = Pos.Top (txtToFind) + 2,
  608. Checked = _matchCase
  609. };
  610. ckbMatchCase.Toggled += (e) => _matchCase = ckbMatchCase.Checked;
  611. d.Add (ckbMatchCase);
  612. var ckbMatchWholeWord = new CheckBox ("Match _whole word") {
  613. X = 0,
  614. Y = Pos.Top (ckbMatchCase) + 1,
  615. Checked = _matchWholeWord
  616. };
  617. ckbMatchWholeWord.Toggled += (e) => _matchWholeWord = ckbMatchWholeWord.Checked;
  618. d.Add (ckbMatchWholeWord);
  619. d.Width = lblWidth + txtToFind.Width + btnFindNext.Width + 2;
  620. d.Height = btnFindNext.Height + btnFindPrevious.Height + btnCancel.Height + 4;
  621. return d;
  622. }
  623. }
  624. }