前回は複数行選択されているとき、各行の先頭にタブ文字を挿入する方法を考えました。今回はその逆をやります。
1 2 3 4 5 6 |
public partial class Undobuf { // 以下を追加 internal List<int> tabRemoveIndexes = new List<int>(); internal List<int> tabRemoveIndexesUndo = new List<int>(); } |
行頭がどこにあるか知る方法は前回のとおりです。そして行頭がほんとうにタブ文字なのかどうかを確認して削除リストのなかにいれています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
public partial class SyncRichTextBox : UserControl { void RemoveTab() { List<int> vs = GetSelectedLineHeads(); int start = vs.Min(); int len = GetSelectedLineTail() - start; SelectionStart = start; SelectionLength = len; Undobuf buf = new Undobuf(); buf.oldSelectionStart = start; buf.oldSelectionLength = len; List<int> vs1 = new List<int>(); foreach (int i in vs) { SelectionStart = i; SelectionLength = 1; if (SelectedText == "\t") vs1.Add(i); } if (vs1.Count == 0) return; // 対象が存在しない buf.tabRemoveIndexes = vs1; buf.newSelectionLength = len - vs1.Count; buf.newSelectionStart = start; List<int> vs0 = new List<int>(); for (int i = 0; i < vs1.Count; i++) { vs0.Add(vs1[i] - i); } buf.tabRemoveIndexesUndo = vs0; buf.action = "RemoveTab"; if(DoRemoveTab(buf)) Data.InsertUndobuf(buf); } bool DoRemoveTab(Undobuf buf) { foreach (var sync in Data.SyncRichTextBoxes) { var info = Data.GetRichTextBoxInfo(sync); if (info != null) { info.SelectionStart = sync.richTextBoxEx1.SelectionStart; } } OnTextChanging(buf); if (buf.IsCancel) return false; var vs1 = buf.tabRemoveIndexes.OrderByDescending(x => x).ToList(); foreach (var sync in Data.SyncRichTextBoxes) { var info = Data.GetRichTextBoxInfo(sync); int oldStart = info.SelectionStart; if (sync.Data == this.Data && sync != this) { foreach (int i in vs1) { sync.richTextBoxEx1.Select(i, 1); sync.richTextBoxEx1.SelectedText = ""; } int count = vs1.Where(x => x <= oldStart).Count(); if(oldStart - count > 0) sync.richTextBoxEx1.Select(oldStart - count, 0); else sync.richTextBoxEx1.Select(0, 0); } else if (sync.Data == this.Data && sync == this) { foreach (int i in vs1) { sync.richTextBoxEx1.Select(i, 1); sync.richTextBoxEx1.SelectedText = ""; } sync.richTextBoxEx1.Select(buf.NewSelectionStart, buf.NewSelectionLength); } else if (sync.Data != this.Data) { if (info != null) { int i = info.SelectionStart; int count = vs1.Where(x => x <= oldStart).Count(); if(i - count > 0) info.SelectionStart = i - count; else info.SelectionStart = 0; } } } return true; } } |
Undo用のメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
public partial class SyncRichTextBox : UserControl { public void Undo() { var buf = Data.GetUndobuf(); buf.IsUndo = true; if (buf.tabInsertIndexesUndo.Count > 0) UndoInsertTab(buf); else if (buf.tabRemoveIndexesUndo.Count > 0) UndoRemoveTab(buf); else DoUndo(buf); buf.IsUndo = false; Data.MoveToRedobufs(); } public void Redo() { var buf = Data.GetRedobuf(); if (buf.tabInsertIndexes.Count > 0) DoInsertTab(buf); else if (buf.tabRemoveIndexes.Count > 0) DoRemoveTab(buf); else DoUndo(buf); Data.MoveToUndobufs(); } void UndoRemoveTab(Undobuf buf) { var vs1 = buf.tabRemoveIndexesUndo.OrderByDescending(x => x).ToList(); foreach (var sync in Data.SyncRichTextBoxes) { int oldStart = sync.richTextBoxEx1.SelectionStart; int oldLen = sync.richTextBoxEx1.SelectionLength; if (sync.Data == this.Data && sync != this) { foreach (int i in vs1) { sync.richTextBoxEx1.Select(i, 0); sync.richTextBoxEx1.SelectedText = "\t"; } int count = vs1.Where(x => x <= oldStart).Count(); sync.richTextBoxEx1.Select(oldStart + count, 0); } else if (sync.Data == this.Data && sync == this) { foreach (int i in vs1) { sync.richTextBoxEx1.Select(i, 0); sync.richTextBoxEx1.SelectedText = "\t"; } sync.richTextBoxEx1.Select(buf.NewSelectionStart, buf.NewSelectionLength); } else if (sync.Data != this.Data) { var info = Data.GetRichTextBoxInfo(sync); if (info != null) { int i = info.SelectionStart; int count = vs1.Where(x => x <= oldStart).Count(); info.SelectionStart = i + count; } } } } } public partial class SyncRichTextBox : UserControl { protected override void OnKeyDown(KeyEventArgs e) { // 他のキーに関する処理は省略 if (e.KeyCode == Keys.Tab && e.Shift) { e.Handled = true; RemoveTab(); return; } } } |