/// <summary> /// 任意の位置に文字列を挿入 /// </summary> /// <param name="nLine">Line number. 0 origin</param> /// <param name="pos"></param> /// <param name="str"></param> public Task Insert(int nLine, int pos, string str) { //nLineがまだ存在しない行番号だった場合に備えて、その行までの存在しない行を全て作成 // 例えば、現在0-4行目が存在、8行目に文字を挿入する場合、 // 5-8行目を作成する。 for (int i = list.Count; i < nLine + 1; i++) { MyLine newLine = new MyLine(); list.Add(newLine); } MyLine line = list[nLine]; line.Insert(pos, str); // 任意の位置に挿入するのだから、キャレットとは違う位置に行を増やさないように挿入した時にはキャレットに影響は無い。従って、現状ではバグがある。 CurrentPhysicalPosition = new PhysicalPosition(CurrentPhysicalPosition.Line, CurrentPhysicalPosition.Pos + str.Length); Task task = new Insert(); task.fromLine = nLine; task.fromPos = pos; task.length = str.Length; task.str = str; history.Add(task); if (MyTaskEvent != null) { TaskEventArgs args = new TaskEventArgs(); args.task = task; MyTaskEvent(this, args); } return task; }
/// <summary> /// 文字列を削除 /// </summary> /// <param name="nLine"></param> /// <param name="index">開始点</param> /// <param name="count">削除する長さ</param> public void Delete(int nLine, int index, int count) { if (index < 0) { // 行の先頭でBackspaceを押すとここに来る。 // (0, 0)であれば無視。 // それ以外であれば前の行の改行コードを消して、前の行と結合する。 if (nLine == 0) { // 無視する。 return; } else { CurrentPhysicalPosition = new PhysicalPosition(nLine - 1, list[nLine - 1].Length); MyLine line = new MyLine(list[nLine - 1].TextWithoutReturnValue + list[nLine].TextWithoutReturnValue, list[nLine].ReturnCode); list[nLine - 1] = line; list.RemoveAt(nLine); Invalidate(); } } else { // 現状、0点で実行すると-1になるバグあり MyLine line = list[nLine]; line.Delete(index, count); CurrentPhysicalPosition = new PhysicalPosition(nLine, index); } // 履歴に登録し、タスクイベントを起こす Task task = new Delete(); task.fromLine = nLine; task.fromPos = index; task.length = count; history.Add(task); if (MyTaskEvent != null) { TaskEventArgs args = new TaskEventArgs(); args.task = task; MyTaskEvent(this, args); } Invalidate(); }
/// <summary> /// /// </summary> public MyTextbox() { vScrollBar = new VScrollBar(); hScrollBar = new HScrollBar(); vScrollBar.Dock = DockStyle.Right; hScrollBar.Dock = DockStyle.Bottom; vScrollBar.Value = 0; vScrollBar.Minimum = 0; vScrollBar.Scroll += vScrollBar_Scroll; vScrollBar.ValueChanged += vScrollBar_ValueChanged; this.Controls.Add(vScrollBar); this.Controls.Add(hScrollBar); list = new List<MyLine>(); MyLine firstLine = new MyLine(); list.Add(firstLine); this.Font = MyTextboxDefaultValue.Font; this._returnCode = MyTextboxDefaultValue.ReturnCode; this.AllowDrop = true; this.DragDrop += new DragEventHandler(MyTextbox_DragDrop); caret = new Caret(this.Handle, 2, this.Font.Height); CurrentPhysicalPosition = new PhysicalPosition(0, 0); history = new List<Task>(); }
private bool isShowLine(MyLine line) { return false; }
/// <summary> /// キーが押された時。特定のキーが押された時の動作を定義する。 /// </summary> /// <param name="e"></param> protected override void OnKeyDown(KeyEventArgs e) { switch (e.KeyCode) { case Keys.Up: CurrentPhysicalPosition = new PhysicalPosition(CurrentPhysicalPosition.Line - 1, CurrentPhysicalPosition.Pos); e.SuppressKeyPress = true; break; case Keys.Down: CurrentPhysicalPosition = new PhysicalPosition(CurrentPhysicalPosition.Line + 1, CurrentPhysicalPosition.Pos); e.SuppressKeyPress = true; break; case Keys.Right: if (CurrentPhysicalPosition.Pos == CurrentPhysicalLine.Length) { CurrentPhysicalPosition = new PhysicalPosition(CurrentPhysicalPosition.Line + 1, 0); } else { CurrentPhysicalPosition = new PhysicalPosition(CurrentPhysicalPosition.Line, CurrentPhysicalPosition.Pos + 1); } e.SuppressKeyPress = true; break; case Keys.Left: if (CurrentPhysicalPosition.Pos == 0) { // pos == 0にいる時は、上の行の一番後ろに移動 MyLine upperLine = list[CurrentPhysicalPosition.Line - 1]; CurrentPhysicalPosition = new PhysicalPosition(CurrentPhysicalPosition.Line - 1, upperLine.Length); } else { // 左隣に移動 CurrentPhysicalPosition = new PhysicalPosition(CurrentPhysicalPosition.Line, CurrentPhysicalPosition.Pos - 1); } e.SuppressKeyPress = true; break; case Keys.Enter: // 現在の行(Enterキーを押した行) MyLine currentLine = list[CurrentPhysicalPosition.Line]; // 新しく作られる行。現在の行のEnterキーを押した場所(キャレットの位置)から後ろの文字列と現在の行の改行コードを移す。 MyLine newLine = new MyLine(currentLine.TextWithoutReturnValue.Substring(CurrentPhysicalPosition.Pos),currentLine.ReturnCode); // 現在の行のEnterキーを押した場所(キャレットの位置)から後ろの文字列を削除する。 currentLine.Delete(CurrentPhysicalPosition.Pos, currentLine.Length - CurrentPhysicalPosition.Pos); // 現在の行の改行コードにはMyTextboxのデフォルトの改行コードを入れる。 currentLine.ReturnCode = this._returnCode; // リストに新しい行を追加する。 list.Insert(CurrentPhysicalPosition.Line + 1, newLine); // キャレットの位置を新しく作成した行の先頭に設定する。 CurrentPhysicalPosition = new PhysicalPosition(CurrentPhysicalPosition.Line + 1, 0); // Keyイベントをコントロールに渡さない場合はtrue。これをtrueにすると、同時にHandledもtrueとなる。 e.SuppressKeyPress = true; // 再描画する。 Invalidate(); break; case Keys.Back: // 1文字deleteする。キャレット操作もDelete()でやる。 this.Delete(CurrentPhysicalPosition.Line, CurrentPhysicalPosition.Pos - 1, 1); e.SuppressKeyPress = true; break; case Keys.Tab: break; case Keys.Delete: break; case Keys.Home: break; case Keys.End: break; } //base.OnKeyDown(e); }
/// <summary> /// 任意の位置に文字列を挿入 /// </summary> /// <param name="nLine">Line number. 0 origin</param> /// <param name="pos"></param> /// <param name="str"></param> public Task Insert(int nLine, int pos, string str) { //nLineがまだ存在しない行番号だった場合に備えて、その行までの存在しない行を全て作成 // 例えば、現在0-4行目が存在、8行目に文字を挿入する場合、 // 5-8行目を作成する。 for (int i = list.Count; i < nLine + 1; i++) { MyLine newLine = new MyLine(); list.Add(newLine); } MyLine line = list[nLine]; line.Insert(pos, str); CurrentPos = new Position(CurrentPos.Line, CurrentPos.Pos + str.Length); Task task = new Insert(); task.fromLine = nLine; task.fromPos = pos; task.length = str.Length; task.str = str; history.Add(task); if (MyTaskEvent != null) { TaskEventArgs args = new TaskEventArgs(); args.task = task; MyTaskEvent(this, args); } return task; }