namespace FooEditEngine
{
- internal enum MoveFlow
+ /// <summary>
+ /// 移動量の単位を表す
+ /// </summary>
+ public enum MoveFlow
{
- Horizontical,
- Vertical,
+ /// <summary>
+ /// 文字
+ /// </summary>
+ Character,
+ /// <summary>
+ /// 単語単位
+ /// </summary>
+ Word,
+ /// <summary>
+ /// 行単位
+ /// </summary>
+ Line,
+ /// <summary>
+ /// パラグラフ単位
+ /// </summary>
+ Paragraph
}
internal enum ScrollDirection
{
/// </summary>
public enum IndentMode
{
+ /// <summary>
+ /// タブ
+ /// </summary>
Tab,
+ /// <summary>
+ /// スペース
+ /// </summary>
Space,
}
internal sealed class Controller
{
EditView View;
- Document Document;
- int AnchorIndex;
+ Document _Document;
public Controller(Document doc, EditView view)
{
this.Document = doc;
- this.Document.Update += new DocumentUpdateEventHandler(Document_Update);
- this.Document.RightToLeftChanged += (s, e) =>
- {
- this.AdjustCaret();
- };
this.View = view;
this.View.render.ChangedRenderResource += render_ChangedRenderResource;
- this.View.PerformLayouted += View_LineBreakChanged;
this.View.PageBoundChanged += View_PageBoundChanged;
- this.SelectionChanged += new EventHandler((s, e) => { });
- this.Document.Clear();
+ //this.Document.Clear();
}
- /// <summary>
- /// 選択領域変更時に通知される
- /// </summary>
- public event EventHandler SelectionChanged;
+ public Document Document
+ {
+ get
+ {
+ return this._Document;
+ }
+ set
+ {
+ //メモリリークを防ぐためにパンドラーを除く
+ if (this._Document != null)
+ {
+ this._Document.Update -= Document_Update;
+ this._Document.StatusUpdate -= Document_StatusChanged;
+ this._Document.SelectionChanged -= Document_SelectionChanged;
+ this._Document.PerformLayouted -= View_LineBreakChanged;
+ this._Document.CaretChanged -= _Document_CaretChanged;
+ }
+
+ this._Document = value;
+
+ this._Document.Update += new DocumentUpdateEventHandler(Document_Update);
+ this._Document.StatusUpdate += Document_StatusChanged;
+ this._Document.SelectionChanged += Document_SelectionChanged;
+ this._Document.PerformLayouted += View_LineBreakChanged;
+ this._Document.CaretChanged += _Document_CaretChanged;
+ }
+ }
+
+ private void _Document_CaretChanged(object sender, EventArgs e)
+ {
+ TextPoint pos = this.Document.CaretPostion;
+ this.JumpCaret(pos.row, pos.col);
+ }
+
+ private void Document_SelectionChanged(object sender, EventArgs e)
+ {
+ if (this.IsReverseSelect())
+ {
+ if (this.Document.SelectGrippers.BottomRight.Enabled)
+ this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart);
+ if (this.Document.SelectGrippers.BottomLeft.Enabled)
+ this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
+ }
+ else
+ {
+ if (this.Document.SelectGrippers.BottomLeft.Enabled)
+ this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart);
+ if (this.Document.SelectGrippers.BottomRight.Enabled)
+ this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
+ }
+ }
+
+ void Document_StatusChanged(object sender,EventArgs e)
+ {
+ this.AdjustCaret();
+ }
/// <summary>
/// 矩形選択モードなら真を返し、そうでない場合は偽を返す
get
{
if (this.View.Selections.Count == 0)
- return this.AnchorIndex;
+ return this.Document.AnchorIndex;
else
return this.View.Selections.First().start;
}
/// <returns>逆転しているなら真を返す</returns>
public bool IsReverseSelect()
{
- int index = this.View.LayoutLines.GetIndexFromTextPoint(this.View.CaretPostion);
- return index < this.AnchorIndex;
- }
-
- /// <summary>
- /// 指定された範囲を選択する
- /// </summary>
- /// <param name="start"></param>
- /// <param name="length"></param>
- /// <remarks>RectSelectionの値によって動作が変わります。真の場合は矩形選択モードに、そうでない場合は行ごとに選択されます</remarks>
- public void Select(int start, int length)
- {
- if (this.Document.FireUpdateEvent == false)
- throw new InvalidOperationException("");
- if (start < 0 || start + length < 0 || start + length > this.Document.Length)
- throw new ArgumentOutOfRangeException("startかendが指定できる範囲を超えてます");
- this.View.Selections.Clear();
- if (length < 0)
- {
- int oldStart = start;
- start += length;
- length = oldStart - start;
- }
- if (this.RectSelection && length != 0)
- {
- TextPoint startTextPoint = this.View.GetLayoutLineFromIndex(start);
- TextPoint endTextPoint = this.View.GetLayoutLineFromIndex(start + length);
- this.SelectByRectangle(new TextRectangle(startTextPoint, endTextPoint));
- }
- else if(length != 0)
- {
- this.View.Selections.Add(Selection.Create(start, length));
- }
- this.SelectionChanged(this, null);
- }
-
- public void Select(TextPoint tp, int width, int height)
- {
- if (this.Document.FireUpdateEvent == false || !this.RectSelection)
- throw new InvalidOperationException("");
- TextPoint end = tp;
-
- end.row = tp.row + height;
- end.col = tp.col + width;
-
- if (end.row > this.View.LayoutLines.Count - 1)
- throw new ArgumentOutOfRangeException("");
-
- this.View.Selections.Clear();
-
- this.SelectByRectangle(new TextRectangle(tp,end));
-
- this.SelectionChanged(this, null);
- }
-
- private void SelectByRectangle(TextRectangle rect)
- {
- if (this.Document.FireUpdateEvent == false)
- throw new InvalidOperationException("");
- if (rect.TopLeft <= rect.BottomRight)
- {
- for (int i = rect.TopLeft.row; i <= rect.BottomLeft.row; i++)
- {
- int length = this.View.LayoutLines.GetLengthFromLineNumber(i);
- int leftCol = rect.TopLeft.col, rightCol = rect.TopRight.col, lastCol = length;
- if(length > 0 && this.View.LayoutLines[i][length - 1] == Document.NewLine)
- lastCol = length - 1;
- if (lastCol < 0)
- lastCol = 0;
- if (rect.TopLeft.col > lastCol)
- leftCol = lastCol;
- if (rect.TopRight.col > lastCol)
- rightCol = lastCol;
-
- int StartIndex = this.View.LayoutLines.GetIndexFromTextPoint(new TextPoint(i, leftCol));
- int EndIndex = this.View.LayoutLines.GetIndexFromTextPoint(new TextPoint(i, rightCol));
-
- Selection sel;
- sel = Selection.Create(StartIndex, EndIndex - StartIndex);
-
- this.View.Selections.Add(sel);
- }
- }
- }
-
- /// <summary>
- /// 単語単位で選択する
- /// </summary>
- /// <param name="index">探索を開始するインデックス</param>
- /// <param name="changeAnchor">選択の起点となるとインデックスを変更するなら真。そうでなければ偽</param>
- public void SelectWord(int index, bool changeAnchor = false)
- {
- if (this.Document.FireUpdateEvent == false)
- throw new InvalidOperationException("");
-
- if (this.Document.Length <= 0 || index >= this.Document.Length)
- return;
-
- Document str = this.Document;
-
- int start = index;
- while (start > 0 && !Util.IsWordSeparator(str[start]))
- start--;
-
- if (Util.IsWordSeparator(str[start]))
- start++;
-
- int end = index;
- while (end < this.Document.Length && !Util.IsWordSeparator(str[end]))
- end++;
-
- this.Select(start, end - start);
-
- if(changeAnchor)
- this.AnchorIndex = start;
+ int index = this.View.LayoutLines.GetIndexFromTextPoint(this.Document.CaretPostion);
+ return index < this.Document.AnchorIndex;
}
/// <summary>
else
return false;
}
- this.Document.Lock();
this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());
- this.Document.UnLock();
return true;
}
else
i++;
}
- this.Document.Lock();
this.Document.Replace(this.SelectionStart, this.SelectionLength, result.ToString());
- this.Document.UnLock();
}
/// <summary>
{
foreach(int id in this.Document.Markers.IDs)
{
- foreach (Marker m in this.Document.GetMarkers(index, id))
+ foreach (Marker m in this.Document.GetMarkers(id, index))
{
if (m.hilight == type)
return true;
/// </summary>
public void AdjustCaret()
{
- int row = this.View.CaretPostion.row;
+ int row = this.Document.CaretPostion.row;
if (row > this.View.LayoutLines.Count - 1)
row = this.View.LayoutLines.Count - 1;
- int col = this.View.CaretPostion.col;
+ int col = this.Document.CaretPostion.col;
if (col > 0 && col > this.View.LayoutLines[row].Length)
col = this.View.LayoutLines[row].Length;
+
+ //選択領域が消えてしまうので覚えておく
+ int sel_start = this.SelectionStart;
+ int sel_length = this.SelectionLength;
+
this.JumpCaret(row, col);
+
+ this.Document.Select(sel_start, sel_length);
}
/// <summary>
/// スクロールする
/// </summary>
/// <param name="dir">方向を指定する</param>
+ /// <param name="delta">ピクセル単位の値でスクロール量を指定する</param>
+ /// <param name="isSelected">選択状態にするなら真</param>
+ /// <param name="withCaret">同時にキャレットを移動させるなら真</param>
+ public void ScrollByPixel(ScrollDirection dir,double delta, bool isSelected, bool withCaret)
+ {
+ if (this.Document.FireUpdateEvent == false)
+ throw new InvalidOperationException("");
+
+ if (dir == ScrollDirection.Left || dir == ScrollDirection.Right)
+ {
+ this.View.TryScroll(delta, 0);
+ return;
+ }
+
+ if(dir == ScrollDirection.Up)
+ {
+ this.View.TryScroll(0, -delta);
+ }
+ else if (dir == ScrollDirection.Down)
+ {
+ this.View.TryScroll(0, delta);
+ }
+
+ if (withCaret)
+ {
+ //カーソルを適切な位置に移動させる必要がある
+ TextPoint tp = this.View.GetTextPointFromPostion(this.View.CaretLocation);
+ this.View.JumpCaret(tp.row, tp.col);
+ this.View.AdjustCaretAndSrc();
+ this.SelectWithMoveCaret(isSelected);
+ }
+
+ this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart);
+ this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
+ }
+
+ /// <summary>
+ /// スクロールする
+ /// </summary>
+ /// <param name="dir">方向を指定する</param>
/// <param name="delta">スクロールする量。ScrollDirectionの値がUpやDownなら行数。LeftやRightならピクセル単位の値となる</param>
/// <param name="isSelected">選択状態にするなら真</param>
/// <param name="withCaret">同時にキャレットを移動させるなら真</param>
else
{
this.View.Scroll(toX, toRow);
- this.View.IsFocused = false;
}
+
+ this.Document.SelectGrippers.BottomLeft.MoveByIndex(this.View, this.SelectionStart);
+ this.Document.SelectGrippers.BottomRight.MoveByIndex(this.View, this.SelectionStart + this.SelectionLength);
}
/// <summary>
/// <param name="alignWord">単語単位で移動するなら真。そうでないなら偽</param>
public void MoveCaretHorizontical(int realLength, bool isSelected,bool alignWord = false)
{
- for (int i = Math.Abs(realLength); i > 0; i--)
- {
- bool MoveFlow = realLength > 0;
- if (this.Document.RightToLeft)
- MoveFlow = !MoveFlow;
- this.MoveCaretHorizontical(MoveFlow);
+ TextPoint caret = this.Document.CaretPostion;
+ int moved;
+ caret = GetNextCaret(caret, realLength, alignWord ? MoveFlow.Word : MoveFlow.Character,out moved);
+ this.View.JumpCaret(caret.row, caret.col, false);
+ this.View.AdjustCaretAndSrc(AdjustFlow.Both);
+ this.SelectWithMoveCaret(isSelected);
+ }
- if (alignWord)
- this.AlignNearestWord(MoveFlow);
+ /// <summary>
+ /// 移動後のキャレット位置を求める
+ /// </summary>
+ /// <param name="caret">起点となるキャレット位置</param>
+ /// <param name="count">移動量</param>
+ /// <param name="method">移動方法</param>
+ /// <param name="moved">実際に移動した量</param>
+ /// <returns>移動後のキャレット位置</returns>
+ public TextPoint GetNextCaret(TextPoint caret, int count,MoveFlow method,out int moved)
+ {
+ moved = 0;
+ if(method == MoveFlow.Character || method == MoveFlow.Word)
+ {
+ for (int i = Math.Abs(count); i > 0; i--)
+ {
+ bool moveFlow = count > 0;
+ if (this.Document.RightToLeft)
+ moveFlow = !moveFlow;
+ caret = this.MoveCaretHorizontical(caret, moveFlow);
+
+ if (method == FooEditEngine.MoveFlow.Word)
+ caret = this.AlignNearestWord(caret, moveFlow);
+ moved++;
+ }
}
- this.View.AdjustCaretAndSrc(AdjustFlow.Col);
- this.SelectWithMoveCaret(isSelected);
+ if(method == MoveFlow.Line || method == MoveFlow.Paragraph)
+ {
+ for (int i = Math.Abs(count); i > 0; i--)
+ {
+ caret = this.MoveCaretVertical(caret, count > 0, method == MoveFlow.Paragraph);
+ moved++;
+ }
+ }
+ if (count < 0)
+ moved = -moved;
+ return caret;
}
- void AlignNearestWord(bool MoveFlow)
+ TextPoint AlignNearestWord(TextPoint caret,bool MoveFlow)
{
- string str = this.View.LayoutLines[this.View.CaretPostion.row];
- while (this.View.CaretPostion.col > 0 &&
- this.View.CaretPostion.col < str.Length &&
- str[this.View.CaretPostion.col] != Document.NewLine)
+ string str = this.View.LayoutLines[caret.row];
+ while (caret.col > 0 &&
+ caret.col < str.Length &&
+ str[caret.col] != Document.NewLine)
{
- if (!Util.IsWordSeparator(str[this.View.CaretPostion.col]))
+ if (!Util.IsWordSeparator(str[caret.col]))
{
- this.MoveCaretHorizontical(MoveFlow);
+ caret = this.MoveCaretHorizontical(caret, MoveFlow);
}
else
{
if(MoveFlow)
- this.MoveCaretHorizontical(MoveFlow);
+ caret = this.MoveCaretHorizontical(caret, MoveFlow);
break;
}
}
+ return caret;
}
/// <summary>
/// <param name="isSelected"></param>
public void MoveCaretVertical(int deltarow,bool isSelected)
{
- for (int i = Math.Abs(deltarow); i > 0; i--)
- this.MoveCaretVertical(deltarow > 0);
+ TextPoint caret = this.Document.CaretPostion;
+ int moved;
+ caret = this.GetNextCaret(caret, deltarow, MoveFlow.Line,out moved);
+ this.View.JumpCaret(caret.row, caret.col, true);
this.View.AdjustCaretAndSrc(AdjustFlow.Both);
this.SelectWithMoveCaret(isSelected);
}
if (this.Document.FireUpdateEvent == false)
throw new InvalidOperationException("");
- TextPoint CaretPostion = this.View.CaretPostion;
+ TextPoint CaretPostion = this.Document.CaretPostion;
int index = this.View.GetIndexFromLayoutLine(CaretPostion);
if (index == this.Document.Length)
if (this.Document[index] == Document.NewLine)
next = index + 1;
- this.Document.Lock();
- this.Document.Replace(index, next - index, "");
- this.Document.UnLock();
+ this.Document.Replace(index, next - index, "", true);
}
public bool IsRectInsertMode()
if (this.Document.FireUpdateEvent == false)
throw new InvalidOperationException("");
- TextPoint CurrentPostion = this.View.CaretPostion;
+ TextPoint CurrentPostion = this.Document.CaretPostion;
if (CurrentPostion.row == 0 && CurrentPostion.col == 0)
return;
newIndex--;
}
- this.Document.Lock();
- this.Document.Replace(newIndex, oldIndex - newIndex, "");
- this.Document.UnLock();
+ this.Document.Replace(newIndex, oldIndex - newIndex, "", true);
}
/// <summary>
string GetIndentSpace(int col_index)
{
- int space_count = this.View.TabStops - (col_index % this.View.TabStops);
+ int space_count = this.Document.TabStops - (col_index % this.Document.TabStops);
return new string(Enumerable.Repeat(' ',space_count).ToArray());
}
/// <summary>
/// キャレット位置に文字列を挿入し、その分だけキャレットを進める。isInsertModeの値により動作が変わります
/// </summary>
- /// <param name="str"></param>
- /// <param name="fromTip"></param>
+ /// <param name="str">挿入したい文字列</param>
+ /// <param name="fromTip">真の場合、矩形選択の幅にかかわらず矩形編集モードとして動作します。そうでない場合は選択領域を文字列で置き換えます</param>
public void DoInputString(string str,bool fromTip = false)
{
- TextPoint CaretPos = this.View.CaretPostion;
+ TextPoint CaretPos = this.Document.CaretPostion;
if (str == "\t" && this.IndentMode == IndentMode.Space)
str = this.GetIndentSpace(CaretPos.col);
if (this.Document.FireUpdateEvent == false)
throw new InvalidOperationException("");
- int index = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);
+ int index = this.View.GetIndexFromLayoutLine(this.Document.CaretPostion);
int length = 0;
if (this.View.InsertMode == false && index < this.Document.Length && this.Document[index] != Document.NewLine)
{
if (foldingData != null && !foldingData.Expand && index > foldingData.Start && index <= foldingData.End)
index = foldingData.End + 1;
}
- this.Document.Lock();
- this.Document.Replace(index, length, str);
- this.Document.UnLock();
+ this.Document.Replace(index, length, str, true);
}
/// <summary>
/// </remarks>
void SelectWithMoveCaret(bool isSelected)
{
- if (this.View.CaretPostion.col < 0 || this.View.CaretPostion.row < 0)
+ if (this.Document.CaretPostion.col < 0 || this.Document.CaretPostion.row < 0)
return;
if (this.Document.FireUpdateEvent == false)
throw new InvalidOperationException("");
- int CaretPostion = this.View.GetIndexFromLayoutLine(this.View.CaretPostion);
+ int CaretPostion = this.View.GetIndexFromLayoutLine(this.Document.CaretPostion);
SelectCollection Selections = this.View.Selections;
if (isSelected)
{
- this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);
+ this.Document.Select(this.Document.AnchorIndex, CaretPostion - this.Document.AnchorIndex);
}else{
- this.AnchorIndex = CaretPostion;
- this.Select(CaretPostion, 0);
+ this.Document.AnchorIndex = CaretPostion;
+ this.Document.Select(CaretPostion, 0);
}
}
/// JumpCaretで移動した位置からキャレットを移動し、選択状態にする
/// </summary>
/// <param name="tp"></param>
- public void MoveCaretAndSelect(TextPoint tp)
+ /// <param name="alignWord">単語単位で選択するかどうか</param>
+ public void MoveCaretAndSelect(TextPoint tp,bool alignWord = false)
{
+ TextPoint endSelectPostion = tp;
int CaretPostion = this.View.GetIndexFromLayoutLine(tp);
- this.Select(this.AnchorIndex, CaretPostion - this.AnchorIndex);
- this.View.JumpCaret(tp.row, tp.col);
+ if (alignWord)
+ {
+ if (this.IsReverseSelect())
+ while (CaretPostion >= 0 && CaretPostion < this.Document.Length && !Util.IsWordSeparator(this.Document[CaretPostion])) CaretPostion--;
+ else
+ while (CaretPostion < this.Document.Length && !Util.IsWordSeparator(this.Document[CaretPostion])) CaretPostion++;
+ if (CaretPostion < 0)
+ CaretPostion = 0;
+ endSelectPostion = this.View.LayoutLines.GetTextPointFromIndex(CaretPostion);
+ }
+ this.Document.Select(this.Document.AnchorIndex, CaretPostion - this.Document.AnchorIndex);
+ this.View.JumpCaret(endSelectPostion.row, endSelectPostion.col);
this.View.AdjustCaretAndSrc();
}
/// <param name="hittedGripper">動かす対象となるグリッパー</param>
/// <returns>移動できた場合は真を返す。そうでなければ偽を返す</returns>
/// <remarks>グリッパー内にポインターが存在しない場合、グリッパーはポインターの座標近くの行に移動する</remarks>
- public bool MoveCaretAndGripper(Point p, GripperView hittedGripper)
+ public bool MoveCaretAndGripper(Point p, Gripper hittedGripper)
{
bool HittedCaret = false;
TextPoint tp = this.View.GetTextPointFromPostion(p);
- if (tp == this.View.CaretPostion)
+ if (tp == this.Document.CaretPostion)
{
HittedCaret = true;
}
if (HittedCaret || hittedGripper != null)
{
+ TextPointSearchRange searchRange;
+ if (this.View.HitTextArea(p.X, p.Y))
+ searchRange = TextPointSearchRange.TextAreaOnly;
+ else if (this.SelectionLength > 0)
+ searchRange = TextPointSearchRange.Full;
+ else
+ return false;
+
if (hittedGripper != null)
{
- tp = this.View.GetTextPointFromPostion(hittedGripper.AdjustPoint(p));
- if (this.IsReverseSelect())
- {
- if (Object.ReferenceEquals(hittedGripper, this.View.SelectGrippers.BottomRight))
- this.MoveSelectBefore(tp);
- else
- this.MoveCaretAndSelect(tp);
- }
- else
- {
- if (Object.ReferenceEquals(hittedGripper, this.View.SelectGrippers.BottomLeft))
- this.MoveSelectBefore(tp);
- else
- this.MoveCaretAndSelect(tp);
- }
- hittedGripper.Move(this.View, tp);
+ tp = this.View.GetTextPointFromPostion(hittedGripper.AdjustPoint(p), searchRange);
+ if (tp == TextPoint.Null)
+ return false;
+ if (Object.ReferenceEquals(hittedGripper, this.Document.SelectGrippers.BottomRight))
+ this.MoveCaretAndSelect(tp);
+ else if(Object.ReferenceEquals(hittedGripper, this.Document.SelectGrippers.BottomLeft))
+ this.MoveSelectBefore(tp);
}
else
{
- tp = this.View.GetTextPointFromPostion(p);
+ tp = this.View.GetTextPointFromPostion(p, searchRange);
if (tp != TextPoint.Null)
+ {
this.MoveCaretAndSelect(tp);
+ }
+ else
+ {
+ return false;
+ }
}
- this.View.SelectGrippers.BottomLeft.Enabled = this.SelectionLength != 0;
+ this.Document.SelectGrippers.BottomLeft.Enabled = this.SelectionLength != 0;
return true;
}
return false;
if (this.IsReverseSelect())
{
NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);
- SelectionLength = this.SelectionLength + NewAnchorIndex - this.AnchorIndex;
- this.Select(this.SelectionStart, SelectionLength);
+ SelectionLength = this.SelectionLength + NewAnchorIndex - this.Document.AnchorIndex;
+ this.Document.Select(this.SelectionStart, SelectionLength);
}
else
{
NewAnchorIndex = this.View.GetIndexFromLayoutLine(tp);
- SelectionLength = this.SelectionLength + this.AnchorIndex - NewAnchorIndex;
- this.Select(NewAnchorIndex, SelectionLength);
+ SelectionLength = this.SelectionLength + this.Document.AnchorIndex - NewAnchorIndex;
+ this.Document.Select(NewAnchorIndex, SelectionLength);
}
- this.AnchorIndex = NewAnchorIndex;
- }
-
- /// <summary>
- /// キャレット位置を既定の位置に戻す
- /// </summary>
- public void ResetCaretPostion()
- {
- this.JumpCaret(0);
+ this.Document.AnchorIndex = NewAnchorIndex;
}
/// <summary>
/// </summary>
/// <param name="count">移動量</param>
/// <param name="current">現在のキャレット位置</param>
+ /// <param name="move_pargraph">パラグラフ単位で移動するなら真</param>
/// <returns>移動後のキャレット位置</returns>
- public TextPoint GetTextPointAfterMoveLine(int count, TextPoint current)
+ public TextPoint GetTextPointAfterMoveLine(int count, TextPoint current, bool move_pargraph = false)
{
- int row = current.row + count;
+ if(this.Document.LineBreak == LineBreakMethod.None || move_pargraph == true)
+ {
+ int row = current.row + count;
- if (row < 0)
- row = 0;
- else if (row >= this.View.LayoutLines.Count)
- row = this.View.LayoutLines.Count - 1;
+ if (row < 0)
+ row = 0;
+ else if (row >= this.View.LayoutLines.Count)
+ row = this.View.LayoutLines.Count - 1;
- row = this.View.AdjustRow(row, count > 0);
+ row = this.View.AdjustRow(row, count > 0);
- double colpos = this.View.GetColPostionFromIndex(current.row, current.col);
- int col = this.View.GetIndexFromColPostion(row, colpos);
+ Point pos = this.View.LayoutLines.GetLayout(current.row).GetPostionFromIndex(current.col);
+ int col = this.View.LayoutLines.GetLayout(row).GetIndexFromPostion(pos.X, pos.Y);
+ return new TextPoint(row, col);
+ }
+ else
+ {
+ Point pos = this.View.GetPostionFromTextPoint(current);
+ pos.Y += this.View.render.emSize.Height * count;
+ //この値を足さないとうまく動作しない
+ pos.Y += this.View.render.emSize.Height / 2;
+ var new_tp = this.View.GetTextPointFromPostion(pos,TextPointSearchRange.Full);
+ return new_tp;
- return new TextPoint(row, col);
+ }
+ }
+
+
+ /// <summary>
+ /// キャレット位置を既定の位置に戻す
+ /// </summary>
+ public void ResetCaretPostion()
+ {
+ this.JumpCaret(0);
}
/// <summary>
string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";
string text = this.InsertLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);
this.RepleaceSelectionArea(this.View.Selections,text);
- this.Select(selectionStart, text.Length);
+ this.Document.Select(selectionStart, text.Length);
}
/// <summary>
return;
int selectionStart = this.SelectionStart;
string insertStr = this.IndentMode == IndentMode.Space ? this.GetIndentSpace(0) : "\t";
- string text = this.RemoveLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr);
+ string text = this.RemoveLineHead(GetTextFromLineSelectArea(this.View.Selections), insertStr, insertStr.Length);
this.RepleaceSelectionArea(this.View.Selections, text);
- this.Select(selectionStart, text.Length);
+ this.Document.Select(selectionStart, text.Length);
}
string InsertLineHead(string s, string str)
return output.ToString();
}
- public string RemoveLineHead(string s, string str)
+ public string RemoveLineHead(string s, string str,int remove_count)
{
string[] lines = s.Split(new string[] { Document.NewLine.ToString() }, StringSplitOptions.None);
StringBuilder output = new StringBuilder();
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].StartsWith(str))
- output.Append(lines[i].Substring(1) + Document.NewLine);
+ output.Append(lines[i].Substring(remove_count) + Document.NewLine);
else if (i < lines.Length - 1)
output.Append(lines[i] + Document.NewLine);
}
/// <summary>
/// キャレットを一文字移動させる
/// </summary>
+ /// <param name="caret">キャレット</param>
/// <param name="isMoveNext">真なら1文字すすめ、そうでなければ戻す</param>
/// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>
- void MoveCaretHorizontical(bool isMoveNext)
+ TextPoint MoveCaretHorizontical(TextPoint caret,bool isMoveNext)
{
if (this.Document.FireUpdateEvent == false)
throw new InvalidOperationException("");
int delta = isMoveNext ? 0 : -1;
- int prevcol = this.View.CaretPostion.col;
- int col = this.View.CaretPostion.col + delta;
- string lineString = this.View.LayoutLines[this.View.CaretPostion.row];
- if (col < 0 || this.View.CaretPostion.row >= this.View.LayoutLines.Count)
+ int prevcol = caret.col;
+ int col = caret.col + delta;
+ string lineString = this.View.LayoutLines[caret.row];
+ if (col < 0 || caret.row >= this.View.LayoutLines.Count)
{
- if (this.View.CaretPostion.row == 0)
+ if (caret.row == 0)
{
- col = 0;
- return;
+ caret.col = 0;
+ return caret;
}
- this.MoveCaretVertical(false);
- this.View.AdjustCaretAndSrc(AdjustFlow.Row); //この段階で調整しないとスクロールされない
- col = this.View.LayoutLines.GetLengthFromLineNumber(this.View.CaretPostion.row) - 1; //最終行以外はすべて改行コードが付くはず
+ caret = this.MoveCaretVertical(caret,false);
+ caret.col = this.View.LayoutLines.GetLengthFromLineNumber(caret.row) - 1; //最終行以外はすべて改行コードが付くはず
}
else if (col >= lineString.Length || lineString[col] == Document.NewLine)
{
- if (this.View.CaretPostion.row < this.View.LayoutLines.Count - 1)
+ if (caret.row < this.View.LayoutLines.Count - 1)
{
- this.MoveCaretVertical(true);
- this.View.AdjustCaretAndSrc(AdjustFlow.Row); //この段階で調整しないとスクロールされない
- col = 0;
+ caret = this.MoveCaretVertical(caret, true);
+ caret.col = 0;
}
}
else
{
AlignDirection direction = isMoveNext ? AlignDirection.Forward : AlignDirection.Back;
- col = this.View.LayoutLines.GetLayout(this.View.CaretPostion.row).AlignIndexToNearestCluster(col, direction);
+ caret.col = this.View.LayoutLines.GetLayout(caret.row).AlignIndexToNearestCluster(col, direction);
}
-
- this.View.JumpCaret(this.View.CaretPostion.row, col,false);
+ return caret;
}
/// <summary>
/// キャレットを行方向に移動させる
/// </summary>
+ /// <param name="caret">計算の起点となるテキストポイント</param>
/// <param name="isMoveNext">プラス方向に移動するなら真</param>
+ /// <param name="move_pargraph">パラグラフ単位で移動するするなら真</param>
/// <remarks>このメソッドを呼び出した後でScrollToCaretメソッドとSelectWithMoveCaretメソッドを呼び出す必要があります</remarks>
- void MoveCaretVertical(bool isMoveNext)
+ TextPoint MoveCaretVertical(TextPoint caret,bool isMoveNext, bool move_pargraph = false)
{
if (this.Document.FireUpdateEvent == false)
throw new InvalidOperationException("");
- TextPoint nextPoint = this.GetTextPointAfterMoveLine(isMoveNext ? 1 : -1, this.View.CaretPostion);
-
- this.View.JumpCaret(nextPoint.row, nextPoint.col,false);
+ return this.GetTextPointAfterMoveLine(isMoveNext ? 1 : -1, this.Document.CaretPostion, move_pargraph);
}
private void ReplaceBeforeSelectionArea(SelectCollection Selections, int removeLength, string insertStr)
else
this.JumpCaret(end.row, end.col);
- this.Select(start, 0, end.row - start.row);
+ this.Document.Select(start, 0, end.row - start.row);
}
private void ReplaceBeforeSelection(Selection sel, int removeLength, string insertStr)
{
sel = Util.NormalizeIMaker<Selection>(sel);
- this.Document.Lock();
this.Document.Replace(sel.start - removeLength, removeLength, insertStr);
- this.Document.UnLock();
}
private void RepleaceSelectionArea(SelectCollection Selections, string value,bool updateInsertPoint = false)
if (this.RectSelection == false)
{
- Selection sel = Selection.Create(this.AnchorIndex, 0);
+ Selection sel = Selection.Create(this.Document.AnchorIndex, 0);
if (Selections.Count > 0)
sel = Util.NormalizeIMaker<Selection>(this.View.Selections.First());
- this.Document.Lock();
this.Document.Replace(sel.start, sel.length, value);
- this.Document.UnLock();
return;
}
{
int i;
- this.Document.Lock();
-
this.Document.UndoManager.BeginUndoGroup();
this.Document.FireUpdateEvent = false;
this.Document.FireUpdateEvent = true;
this.Document.UndoManager.EndUndoGroup();
-
- this.Document.UnLock();
}
else
{
SelectCollection temp = new SelectCollection(this.View.Selections); //コピーしないとReplaceCommandを呼び出した段階で書き換えられてしまう
- this.Document.Lock();
-
this.Document.UndoManager.BeginUndoGroup();
this.Document.FireUpdateEvent = false;
this.Document.FireUpdateEvent = true;
this.Document.UndoManager.EndUndoGroup();
-
- this.Document.UnLock();
}
this.JumpCaret(StartIndex);
if (updateInsertPoint && newInsertPoint.Count > 0)
void View_PageBoundChanged(object sender, EventArgs e)
{
- if (this.View.LineBreak == LineBreakMethod.PageBound && this.View.PageBound.Width - this.View.LineBreakingMarginWidth > 0)
- this.View.PerfomLayouts();
+ if (this.Document.LineBreak == LineBreakMethod.PageBound && this.View.PageBound.Width - this.View.LineBreakingMarginWidth > 0)
+ this.Document.PerformLayout();
this.AdjustCaret();
}
{
if (e.type == ResourceType.Font)
{
- if (this.View.LineBreak == LineBreakMethod.PageBound)
- this.View.PerfomLayouts();
+ if (this.Document.LineBreak == LineBreakMethod.PageBound)
+ this.Document.PerformLayout();
this.AdjustCaret();
}
if (e.type == ResourceType.InlineChar)
switch (e.type)
{
case UpdateType.Replace:
- if(e.startIndex < this.Document.Length && this.Document[e.startIndex] == Document.NewLine)
- this.View.CalculateLineCountOnScreen();
this.JumpCaret(e.startIndex + e.insertLength,true);
break;
case UpdateType.Clear: