// *
// * Copyright (C) 2008 Roger Alsing : http://www.RogerAlsing.com
// *
// * This library is free software; you can redistribute it and/or modify it
// * under the terms of the GNU Lesser General Public License 2.1 or later, as
// * published by the Free Software Foundation. See the included license.txt
// * or http://www.gnu.org/copyleft/lesser.html for details.
// *
// *
using System;
using Alsing.SourceCode;
namespace Alsing.Windows.Forms.SyntaxBox
{
///
/// Selection class used by the SyntaxBoxControl
///
public class Selection
{
///
/// Event fired when the selection has changed.
///
public event EventHandler Change = null;
private void PositionChange(object s, EventArgs e)
{
OnChange();
}
private void OnChange()
{
if (Change != null)
Change(this, null);
}
#region Instance constructors
///
/// Selection Constructor.
///
/// Control that will use this selection
public Selection(EditViewControl control)
{
Control = control;
Bounds = new TextRange();
}
#endregion Instance constructors
#region Public instance properties
///
/// Gets the text of the active selection
///
public String Text
{
get
{
if (!IsValid)
{
return "";
}
else
{
return Control.Document.GetRange(LogicalBounds);
}
}
set
{
if (Text == value)
return;
//selection text bug fix
//
//selection gets too short if \n is used instead of newline
string tmp = value.Replace(Environment.NewLine, "\n");
tmp = tmp.Replace("\n", Environment.NewLine);
value = tmp;
//---
TextPoint oCaretPos = Control.Caret.Position;
int nCaretX = oCaretPos.X;
int nCaretY = oCaretPos.Y;
Control.Document.StartUndoCapture();
DeleteSelection();
Control.Document.InsertText(value, oCaretPos.X, oCaretPos.Y);
SelLength = value.Length;
if (nCaretX != oCaretPos.X || nCaretY != oCaretPos.Y)
{
Control.Caret.Position = new TextPoint(Bounds.LastColumn,
Bounds.LastRow);
}
Control.Document.EndUndoCapture();
Control.Document.InvokeChange();
}
}
///
/// Returns the normalized positions of the selection.
/// Swapping start and end values if the selection is reversed.
///
public TextRange LogicalBounds
{
get
{
var r = new TextRange();
if (Bounds.FirstRow < Bounds.LastRow)
{
return Bounds;
}
else if (Bounds.FirstRow == Bounds.LastRow &&
Bounds.FirstColumn < Bounds.LastColumn)
{
return Bounds;
}
else
{
r.FirstColumn = Bounds.LastColumn;
r.FirstRow = Bounds.LastRow;
r.LastColumn = Bounds.FirstColumn;
r.LastRow = Bounds.FirstRow;
return r;
}
}
}
///
/// Returns true if the selection contains One or more chars
///
public bool IsValid
{
get
{
return (LogicalBounds.FirstColumn != LogicalBounds.LastColumn
|| LogicalBounds.FirstRow != LogicalBounds.LastRow);
}
}
///
/// gets or sets the length of the selection in chars
///
public int SelLength
{
get
{
var p1 = new TextPoint(Bounds.FirstColumn,
Bounds.FirstRow);
var p2 = new TextPoint(Bounds.LastColumn,
Bounds.LastRow);
int i1 = Control.Document.PointToIntPos(p1);
int i2 = Control.Document.PointToIntPos(p2);
return i2 - i1;
}
set { SelEnd = SelStart + value; }
}
///
/// Gets or Sets the Selection end as an index in the document text.
///
public int SelEnd
{
get
{
var p = new TextPoint(Bounds.LastColumn, Bounds.LastRow)
;
return Control.Document.PointToIntPos(p);
}
set
{
TextPoint p = Control.Document.IntPosToPoint(value);
Bounds.LastColumn = p.X;
Bounds.LastRow = p.Y;
}
}
///
/// Gets or Sets the Selection start as an index in the document text.
///
public int SelStart
{
get
{
var p = new TextPoint(Bounds.FirstColumn,
Bounds.FirstRow);
return Control.Document.PointToIntPos(p);
}
set
{
TextPoint p = Control.Document.IntPosToPoint(value);
Bounds.FirstColumn = p.X;
Bounds.FirstRow = p.Y;
}
}
///
/// Gets or Sets the logical Selection start as an index in the document text.
///
public int LogicalSelStart
{
get
{
var p = new TextPoint(LogicalBounds.FirstColumn,
LogicalBounds.FirstRow);
return Control.Document.PointToIntPos(p);
}
set
{
TextPoint p = Control.Document.IntPosToPoint(value);
Bounds.FirstColumn = p.X;
Bounds.FirstRow = p.Y;
}
}
#endregion Public instance properties
#region Public instance methods
///
/// Indent the active selection one step.
///
public void Indent()
{
if (!IsValid)
return;
Row xtr = null;
var ActionGroup = new UndoBlockCollection();
for (int i = LogicalBounds.FirstRow;
i <=
LogicalBounds.LastRow;
i++)
{
xtr = Control.Document[i];
xtr.Text = "\t" + xtr.Text;
var b = new UndoBlock();
b.Action = UndoAction.InsertRange;
b.Text = "\t";
b.Position.X = 0;
b.Position.Y = i;
ActionGroup.Add(b);
}
if (ActionGroup.Count > 0)
Control.Document.AddToUndoList(ActionGroup);
Bounds = LogicalBounds;
Bounds.FirstColumn = 0;
Bounds.LastColumn = xtr.Text.Length;
Control.Caret.Position.X = LogicalBounds.LastColumn;
Control.Caret.Position.Y = LogicalBounds.LastRow;
}
///
/// Outdent the active selection one step
///
public void Outdent()
{
if (!IsValid)
return;
Row xtr = null;
var ActionGroup = new UndoBlockCollection();
for (int i = LogicalBounds.FirstRow;
i <=
LogicalBounds.LastRow;
i++)
{
xtr = Control.Document[i];
var b = new UndoBlock();
b.Action = UndoAction.DeleteRange;
b.Position.X = 0;
b.Position.Y = i;
ActionGroup.Add(b);
string s = xtr.Text;
if (s.StartsWith("\t"))
{
b.Text = s.Substring(0, 1);
s = s.Substring(1);
}
if (s.StartsWith(" "))
{
b.Text = s.Substring(0, 4);
s = s.Substring(4);
}
xtr.Text = s;
}
if (ActionGroup.Count > 0)
Control.Document.AddToUndoList(ActionGroup);
Bounds = LogicalBounds;
Bounds.FirstColumn = 0;
Bounds.LastColumn = xtr.Text.Length;
Control.Caret.Position.X = LogicalBounds.LastColumn;
Control.Caret.Position.Y = LogicalBounds.LastRow;
}
public void Indent(string Pattern)
{
if (!IsValid)
return;
Row xtr = null;
var ActionGroup = new UndoBlockCollection();
for (int i = LogicalBounds.FirstRow;
i <=
LogicalBounds.LastRow;
i++)
{
xtr = Control.Document[i];
xtr.Text = Pattern + xtr.Text;
var b = new UndoBlock();
b.Action = UndoAction.InsertRange;
b.Text = Pattern;
b.Position.X = 0;
b.Position.Y = i;
ActionGroup.Add(b);
}
if (ActionGroup.Count > 0)
Control.Document.AddToUndoList(ActionGroup);
Bounds = LogicalBounds;
Bounds.FirstColumn = 0;
Bounds.LastColumn = xtr.Text.Length;
Control.Caret.Position.X = LogicalBounds.LastColumn;
Control.Caret.Position.Y = LogicalBounds.LastRow;
}
///
/// Outdent the active selection one step
///
public void Outdent(string Pattern)
{
if (!IsValid)
return;
Row xtr = null;
var ActionGroup = new UndoBlockCollection();
for (int i = LogicalBounds.FirstRow;
i <=
LogicalBounds.LastRow;
i++)
{
xtr = Control.Document[i];
var b = new UndoBlock();
b.Action = UndoAction.DeleteRange;
b.Position.X = 0;
b.Position.Y = i;
ActionGroup.Add(b);
string s = xtr.Text;
if (s.StartsWith(Pattern))
{
b.Text = s.Substring(0, Pattern.Length);
s = s.Substring(Pattern.Length);
}
xtr.Text = s;
}
if (ActionGroup.Count > 0)
Control.Document.AddToUndoList(ActionGroup);
Bounds = LogicalBounds;
Bounds.FirstColumn = 0;
Bounds.LastColumn = xtr.Text.Length;
Control.Caret.Position.X = LogicalBounds.LastColumn;
Control.Caret.Position.Y = LogicalBounds.LastRow;
}
///
/// Delete the active selection.
///
///
public void DeleteSelection()
{
TextRange r = LogicalBounds;
int x = r.FirstColumn;
int y = r.FirstRow;
Control.Document.DeleteRange(r);
Control.Caret.Position.X = x;
Control.Caret.Position.Y = y;
ClearSelection();
Control.ScrollIntoView();
}
///
/// Clear the active selection
///
///
public void ClearSelection()
{
Bounds.FirstColumn = Control.Caret.Position.X;
Bounds.FirstRow = Control.Caret.Position.Y;
Bounds.LastColumn = Control.Caret.Position.X;
Bounds.LastRow = Control.Caret.Position.Y;
}
///
/// Make a selection from the current selection start to the position of the caret
///
public void MakeSelection()
{
Bounds.LastColumn = Control.Caret.Position.X;
Bounds.LastRow = Control.Caret.Position.Y;
}
///
/// Select all text.
///
public void SelectAll()
{
Bounds.FirstColumn = 0;
Bounds.FirstRow = 0;
Bounds.LastColumn = Control.Document[Control.Document.Count -
1].Text.Length;
Bounds.LastRow = Control.Document.Count - 1;
Control.Caret.Position.X = Bounds.LastColumn;
Control.Caret.Position.Y = Bounds.LastRow;
Control.ScrollIntoView();
}
#endregion Public instance methods
#region Public instance fields
///
/// The bounds of the selection
///
///
private TextRange _Bounds;
public TextRange Bounds
{
get { return _Bounds; }
set
{
if (_Bounds != null)
{
_Bounds.Change -= Bounds_Change;
}
_Bounds = value;
_Bounds.Change += Bounds_Change;
OnChange();
}
}
private void Bounds_Change(object s, EventArgs e)
{
OnChange();
}
#endregion Public instance fields
#region Protected instance fields
private readonly EditViewControl Control;
#endregion Protected instance fields
}
}