diff options
Diffstat (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors')
22 files changed, 3570 insertions, 1278 deletions
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/BreakPointSymbolPressedEventArgs.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/BreakPointSymbolPressedEventArgs.cs new file mode 100644 index 000000000..1728bb565 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/BreakPointSymbolPressedEventArgs.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using Tango.Scripting.Core; + +namespace Tango.Scripting.Editors +{ + public class BreakPointSymbolPressedEventArgs : EventArgs + { + public ScriptBreakPointSymbol BreakPointSymbol { get; set; } + public Point Position { get; set; } + } +} diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/BreakPointMargin.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/BreakPointMargin.cs new file mode 100644 index 000000000..e566e6aa9 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/BreakPointMargin.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Media.TextFormatting; +using Tango.Scripting.Core; +using Tango.Scripting.Editors.Document; +using Tango.Scripting.Editors.Rendering; +using Tango.Scripting.Editors.Utils; + +namespace Tango.Scripting.Editors.Editing +{ + public class BreakPointMargin : AbstractMargin, IWeakEventListener + { + private TextArea textArea; + private int maxLineNumberLength = 1; + private BitmapSource _arrowBitmap; + private ScriptEditor _editor; + + public ObservableCollection<BreakPoint> BreakPoints { get; set; } + + public Brush Background + { + get { return (Brush)GetValue(BackgroundProperty); } + set { SetValue(BackgroundProperty, value); } + } + public static readonly DependencyProperty BackgroundProperty = + DependencyProperty.Register("Background", typeof(Brush), typeof(BreakPointMargin), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(50, 50, 50)))); + + public Brush Foreground + { + get { return (Brush)GetValue(ForegroundProperty); } + set { SetValue(ForegroundProperty, value); } + } + public static readonly DependencyProperty ForegroundProperty = + DependencyProperty.Register("Foreground", typeof(Brush), typeof(BreakPointMargin), new PropertyMetadata(Brushes.Red)); + + static BreakPointMargin() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(BreakPointMargin), + new FrameworkPropertyMetadata(typeof(BreakPointMargin))); + } + + public BreakPointMargin(ScriptEditor editor) + { + _editor = editor; + BreakPoints = new ObservableCollection<BreakPoint>(); + BreakPoints.CollectionChanged += BreakPoints_CollectionChanged; + RenderOptions.SetEdgeMode(this, EdgeMode.Unspecified); + + _arrowBitmap = new BitmapImage(new Uri($"pack://application:,,,/Tango.Scripting.Editors;component/Images/break_point_arrow.png", UriKind.Absolute)); + } + + private void BreakPoints_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + InvalidateVisual(); + } + + protected override Size MeasureOverride(Size availableSize) + { + return new Size(20, 0); + } + + protected override void OnRender(DrawingContext drawingContext) + { + TextView textView = this.TextView; + Size renderSize = this.RenderSize; + if (textView != null && textView.VisualLinesValid) + { + drawingContext.DrawRectangle(Background, new Pen(Background, 1), new Rect(0, 0, ActualWidth, ActualHeight)); + + var foreground = Foreground; + foreach (VisualLine line in textView.VisualLines) + { + int lineNumber = line.FirstDocumentLine.LineNumber; + + BreakPoint b = BreakPoints.FirstOrDefault(x => x.LineNumber == lineNumber); + + if (b != null) + { + double y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextTop); + drawingContext.DrawEllipse(Foreground, new Pen(Brushes.Gainsboro, 1), new Point(10, y - textView.VerticalOffset + 8), 6, 6); + + if (b.IsActive) + { + drawingContext.DrawImage(_arrowBitmap, new Rect(6, y - textView.VerticalOffset + 2.5, 8.5, 10)); + } + } + } + } + } + + protected override void OnTextViewChanged(TextView oldTextView, TextView newTextView) + { + if (oldTextView != null) + { + oldTextView.VisualLinesChanged -= TextViewVisualLinesChanged; + } + base.OnTextViewChanged(oldTextView, newTextView); + if (newTextView != null) + { + newTextView.VisualLinesChanged += TextViewVisualLinesChanged; + + // find the text area belonging to the new text view + textArea = newTextView.Services.GetService(typeof(TextArea)) as TextArea; + } + else + { + textArea = null; + } + InvalidateVisual(); + } + + protected override void OnDocumentChanged(TextDocument oldDocument, TextDocument newDocument) + { + if (oldDocument != null) + { + PropertyChangedEventManager.RemoveListener(oldDocument, this, "LineCount"); + } + base.OnDocumentChanged(oldDocument, newDocument); + if (newDocument != null) + { + PropertyChangedEventManager.AddListener(newDocument, this, "LineCount"); + } + OnDocumentLineCountChanged(); + } + + protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) + { + if (managerType == typeof(PropertyChangedEventManager)) + { + OnDocumentLineCountChanged(); + return true; + } + return false; + } + + bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) + { + return ReceiveWeakEvent(managerType, sender, e); + } + + private void OnDocumentLineCountChanged() + { + int documentLineCount = Document != null ? Document.LineCount : 1; + int newLength = documentLineCount.ToString(CultureInfo.CurrentCulture).Length; + + foreach (var breakPoint in BreakPoints.ToList()) + { + if (breakPoint.LineNumber > documentLineCount) + { + BreakPoints.Remove(breakPoint); + } + else + { + try + { + var line = Document.GetLineByNumber(breakPoint.LineNumber); + if (line != null) + { + String lineText = Document.GetText(line.Offset, line.Length); + if (!IsBreakPointValid(lineText)) + { + BreakPoints.Remove(breakPoint); + } + } + } + catch { } + } + } + + // The margin looks too small when there is only one digit, so always reserve space for + // at least two digits + if (newLength < 2) + newLength = 2; + + if (newLength != maxLineNumberLength) + { + maxLineNumberLength = newLength; + InvalidateMeasure(); + } + } + + private void TextViewVisualLinesChanged(object sender, EventArgs e) + { + InvalidateVisual(); + } + + protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) + { + // accept clicks even when clicking on the background + return new PointHitTestResult(this, hitTestParameters.HitPoint); + } + + private VisualLine GetLineNumberByMousePosition(MouseEventArgs e) + { + Point pos = e.GetPosition(TextView); + pos.X = 0; + pos.Y += TextView.VerticalOffset; + VisualLine vl = TextView.GetVisualLineFromVisualTop(pos.Y); + return vl; + } + + private bool IsBreakPointValid(String lineText) + { + if (lineText.EndsWith(";") && !lineText.StartsWith("using")) + { + return true; + } + + return false; + } + + protected override void OnPreviewMouseMove(MouseEventArgs e) + { + base.OnPreviewMouseMove(e); + + if (_editor.DisableBreakPoints) + { + Cursor = Cursors.No; + } + else + { + Cursor = Cursors.Arrow; + } + } + + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonDown(e); + + if (_editor.DisableBreakPoints) + { + return; + } + + try + { + if (!e.Handled && TextView != null && textArea != null) + { + e.Handled = true; + textArea.Focus(); + + var visualLine = GetLineNumberByMousePosition(e); + + int? lineNumber = visualLine != null ? (int?)visualLine.FirstDocumentLine.LineNumber : null; + + if (lineNumber != null) + { + var breakPoint = BreakPoints.FirstOrDefault(x => x.LineNumber == lineNumber.Value); + if (breakPoint != null) + { + BreakPoints.Remove(breakPoint); + } + else + { + var lineText = Document.GetText(visualLine.FirstDocumentLine.Offset, visualLine.FirstDocumentLine.Length).Trim(); + + if (IsBreakPointValid(lineText)) + { + BreakPoint newBreakPoint = new BreakPoint(); + newBreakPoint.LineNumber = lineNumber.Value; + BreakPoints.Add(newBreakPoint); + } + } + } + } + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + } +} diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Errors/ITextMarker.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Errors/ITextMarker.cs new file mode 100644 index 000000000..dcbf8388a --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Errors/ITextMarker.cs @@ -0,0 +1,169 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Media; + +namespace Tango.Scripting.Editors +{ + /// <summary> + /// Represents a text marker. + /// </summary> + public interface ITextMarker + { + /// <summary> + /// Gets the start offset of the marked text region. + /// </summary> + int StartOffset { get; } + + /// <summary> + /// Gets the end offset of the marked text region. + /// </summary> + int EndOffset { get; } + + /// <summary> + /// Gets the length of the marked region. + /// </summary> + int Length { get; } + + /// <summary> + /// Deletes the text marker. + /// </summary> + void Delete(); + + /// <summary> + /// Gets whether the text marker was deleted. + /// </summary> + bool IsDeleted { get; } + + /// <summary> + /// Event that occurs when the text marker is deleted. + /// </summary> + event EventHandler Deleted; + + /// <summary> + /// Gets/Sets the background color. + /// </summary> + Color? BackgroundColor { get; set; } + + /// <summary> + /// Gets/Sets the foreground color. + /// </summary> + Color? ForegroundColor { get; set; } + + /// <summary> + /// Gets/Sets the font weight. + /// </summary> + FontWeight? FontWeight { get; set; } + + /// <summary> + /// Gets/Sets the font style. + /// </summary> + FontStyle? FontStyle { get; set; } + + /// <summary> + /// Gets/Sets the type of the marker. Use TextMarkerType.None for normal markers. + /// </summary> + TextMarkerTypes MarkerTypes { get; set; } + + /// <summary> + /// Gets/Sets the color of the marker. + /// </summary> + Color MarkerColor { get; set; } + + /// <summary> + /// Gets/Sets an object with additional data for this text marker. + /// </summary> + object Tag { get; set; } + + /// <summary> + /// Gets/Sets an object that will be displayed as tooltip in the text editor. + /// </summary> + /// <remarks>Not supported in this sample!</remarks> + object ToolTip { get; set; } + } + + [Flags] + public enum TextMarkerTypes + { + /// <summary> + /// Use no marker + /// </summary> + None = 0x0000, + /// <summary> + /// Use squiggly underline marker + /// </summary> + SquigglyUnderline = 0x001, + /// <summary> + /// Normal underline. + /// </summary> + NormalUnderline = 0x002, + /// <summary> + /// Dotted underline. + /// </summary> + DottedUnderline = 0x004, + + /// <summary> + /// Horizontal line in the scroll bar. + /// </summary> + LineInScrollBar = 0x0100, + /// <summary> + /// Small triangle in the scroll bar, pointing to the right. + /// </summary> + ScrollBarRightTriangle = 0x0400, + /// <summary> + /// Small triangle in the scroll bar, pointing to the left. + /// </summary> + ScrollBarLeftTriangle = 0x0800, + /// <summary> + /// Small circle in the scroll bar. + /// </summary> + CircleInScrollBar = 0x1000 + } + + public interface ITextMarkerService + { + /// <summary> + /// Creates a new text marker. The text marker will be invisible at first, + /// you need to set one of the Color properties to make it visible. + /// </summary> + ITextMarker Create(int startOffset, int length); + + /// <summary> + /// Gets the list of text markers. + /// </summary> + IEnumerable<ITextMarker> TextMarkers { get; } + + /// <summary> + /// Removes the specified text marker. + /// </summary> + void Remove(ITextMarker marker); + + /// <summary> + /// Removes all text markers that match the condition. + /// </summary> + void RemoveAll(Predicate<ITextMarker> predicate); + + /// <summary> + /// Finds all text markers at the specified offset. + /// </summary> + IEnumerable<ITextMarker> GetMarkersAtOffset(int offset); + } +} diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Errors/TextMarkerService.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Errors/TextMarkerService.cs new file mode 100644 index 000000000..2bb3d8e03 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Errors/TextMarkerService.cs @@ -0,0 +1,365 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Windows; +using System.Windows.Media; +using System.Windows.Threading; +using Tango.Scripting.Editors.Document; +using Tango.Scripting.Editors.Rendering; + +namespace Tango.Scripting.Editors +{ + /// <summary> + /// Handles the text markers for a code editor. + /// </summary> + public sealed class TextMarkerService : DocumentColorizingTransformer, IBackgroundRenderer, ITextMarkerService, ITextViewConnect + { + TextSegmentCollection<TextMarker> markers; + TextDocument document; + + public TextMarkerService(TextDocument document) + { + if (document == null) + throw new ArgumentNullException("document"); + this.document = document; + this.markers = new TextSegmentCollection<TextMarker>(document); + } + + #region ITextMarkerService + public ITextMarker Create(int startOffset, int length) + { + if (markers == null) + throw new InvalidOperationException("Cannot create a marker when not attached to a document"); + + int textLength = document.TextLength; + if (startOffset < 0 || startOffset > textLength) + throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be between 0 and " + textLength); + if (length < 0 || startOffset + length > textLength) + throw new ArgumentOutOfRangeException("length", length, "length must not be negative and startOffset+length must not be after the end of the document"); + + TextMarker m = new TextMarker(this, startOffset, length); + markers.Add(m); + // no need to mark segment for redraw: the text marker is invisible until a property is set + return m; + } + + public IEnumerable<ITextMarker> GetMarkersAtOffset(int offset) + { + if (markers == null) + return Enumerable.Empty<ITextMarker>(); + else + return markers.FindSegmentsContaining(offset); + } + + public IEnumerable<ITextMarker> TextMarkers { + get { return markers ?? Enumerable.Empty<ITextMarker>(); } + } + + public void RemoveAll(Predicate<ITextMarker> predicate) + { + if (predicate == null) + throw new ArgumentNullException("predicate"); + if (markers != null) { + foreach (TextMarker m in markers.ToArray()) { + if (predicate(m)) + Remove(m); + } + } + } + + public void Remove(ITextMarker marker) + { + if (marker == null) + throw new ArgumentNullException("marker"); + TextMarker m = marker as TextMarker; + if (markers != null && markers.Remove(m)) { + Redraw(m); + m.OnDeleted(); + } + } + + /// <summary> + /// Redraws the specified text segment. + /// </summary> + internal void Redraw(ISegment segment) + { + foreach (var view in textViews) { + view.Redraw(segment, DispatcherPriority.Normal); + } + if (RedrawRequested != null) + RedrawRequested(this, EventArgs.Empty); + } + + public event EventHandler RedrawRequested; + #endregion + + #region DocumentColorizingTransformer + protected override void ColorizeLine(DocumentLine line) + { + if (markers == null) + return; + int lineStart = line.Offset; + int lineEnd = lineStart + line.Length; + foreach (TextMarker marker in markers.FindOverlappingSegments(lineStart, line.Length)) { + Brush foregroundBrush = null; + if (marker.ForegroundColor != null) { + foregroundBrush = new SolidColorBrush(marker.ForegroundColor.Value); + foregroundBrush.Freeze(); + } + ChangeLinePart( + Math.Max(marker.StartOffset, lineStart), + Math.Min(marker.EndOffset, lineEnd), + element => { + if (foregroundBrush != null) { + element.TextRunProperties.SetForegroundBrush(foregroundBrush); + } + Typeface tf = element.TextRunProperties.Typeface; + element.TextRunProperties.SetTypeface(new Typeface( + tf.FontFamily, + marker.FontStyle ?? tf.Style, + marker.FontWeight ?? tf.Weight, + tf.Stretch + )); + } + ); + } + } + #endregion + + #region IBackgroundRenderer + public KnownLayer Layer { + get { + // draw behind selection + return KnownLayer.Selection; + } + } + + public void Draw(TextView textView, DrawingContext drawingContext) + { + if (textView == null) + throw new ArgumentNullException("textView"); + if (drawingContext == null) + throw new ArgumentNullException("drawingContext"); + if (markers == null || !textView.VisualLinesValid) + return; + var visualLines = textView.VisualLines; + if (visualLines.Count == 0) + return; + int viewStart = visualLines.First().FirstDocumentLine.Offset; + int viewEnd = visualLines.Last().LastDocumentLine.EndOffset; + foreach (TextMarker marker in markers.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { + if (marker.BackgroundColor != null) { + BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder(); + geoBuilder.AlignToWholePixels = true; + geoBuilder.CornerRadius = 3; + geoBuilder.AddSegment(textView, marker); + Geometry geometry = geoBuilder.CreateGeometry(); + if (geometry != null) { + Color color = marker.BackgroundColor.Value; + SolidColorBrush brush = new SolidColorBrush(color); + brush.Freeze(); + drawingContext.DrawGeometry(brush, null, geometry); + } + } + var underlineMarkerTypes = TextMarkerTypes.SquigglyUnderline | TextMarkerTypes.NormalUnderline | TextMarkerTypes.DottedUnderline; + if ((marker.MarkerTypes & underlineMarkerTypes) != 0) { + foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker)) { + Point startPoint = r.BottomLeft; + Point endPoint = r.BottomRight; + + Brush usedBrush = new SolidColorBrush(marker.MarkerColor); + usedBrush.Freeze(); + if ((marker.MarkerTypes & TextMarkerTypes.SquigglyUnderline) != 0) { + double offset = 2.5; + + int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4); + + StreamGeometry geometry = new StreamGeometry(); + + using (StreamGeometryContext ctx = geometry.Open()) { + ctx.BeginFigure(startPoint, false, false); + ctx.PolyLineTo(CreatePoints(startPoint, endPoint, offset, count).ToArray(), true, false); + } + + geometry.Freeze(); + + Pen usedPen = new Pen(usedBrush, 1); + usedPen.Freeze(); + drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry); + } + if ((marker.MarkerTypes & TextMarkerTypes.NormalUnderline) != 0) { + Pen usedPen = new Pen(usedBrush, 1); + usedPen.Freeze(); + drawingContext.DrawLine(usedPen, startPoint, endPoint); + } + if ((marker.MarkerTypes & TextMarkerTypes.DottedUnderline) != 0) { + Pen usedPen = new Pen(usedBrush, 1); + usedPen.DashStyle = DashStyles.Dot; + usedPen.Freeze(); + drawingContext.DrawLine(usedPen, startPoint, endPoint); + } + } + } + } + } + + IEnumerable<Point> CreatePoints(Point start, Point end, double offset, int count) + { + for (int i = 0; i < count; i++) + yield return new Point(start.X + i * offset, start.Y - ((i + 1) % 2 == 0 ? offset : 0)); + } + #endregion + + #region ITextViewConnect + readonly List<TextView> textViews = new List<TextView>(); + + void ITextViewConnect.AddToTextView(TextView textView) + { + if (textView != null && !textViews.Contains(textView)) { + Debug.Assert(textView.Document == document); + textViews.Add(textView); + } + } + + void ITextViewConnect.RemoveFromTextView(TextView textView) + { + if (textView != null) { + Debug.Assert(textView.Document == document); + textViews.Remove(textView); + } + } + #endregion + } + + public sealed class TextMarker : TextSegment, ITextMarker + { + readonly TextMarkerService service; + + public TextMarker(TextMarkerService service, int startOffset, int length) + { + if (service == null) + throw new ArgumentNullException("service"); + this.service = service; + this.StartOffset = startOffset; + this.Length = length; + this.markerTypes = TextMarkerTypes.None; + } + + public event EventHandler Deleted; + + public bool IsDeleted { + get { return !this.IsConnectedToCollection; } + } + + public void Delete() + { + service.Remove(this); + } + + internal void OnDeleted() + { + if (Deleted != null) + Deleted(this, EventArgs.Empty); + } + + void Redraw() + { + service.Redraw(this); + } + + Color? backgroundColor; + + public Color? BackgroundColor { + get { return backgroundColor; } + set { + if (backgroundColor != value) { + backgroundColor = value; + Redraw(); + } + } + } + + Color? foregroundColor; + + public Color? ForegroundColor { + get { return foregroundColor; } + set { + if (foregroundColor != value) { + foregroundColor = value; + Redraw(); + } + } + } + + FontWeight? fontWeight; + + public FontWeight? FontWeight { + get { return fontWeight; } + set { + if (fontWeight != value) { + fontWeight = value; + Redraw(); + } + } + } + + FontStyle? fontStyle; + + public FontStyle? FontStyle { + get { return fontStyle; } + set { + if (fontStyle != value) { + fontStyle = value; + Redraw(); + } + } + } + + public object Tag { get; set; } + + TextMarkerTypes markerTypes; + + public TextMarkerTypes MarkerTypes { + get { return markerTypes; } + set { + if (markerTypes != value) { + markerTypes = value; + Redraw(); + } + } + } + + Color markerColor; + + public Color MarkerColor { + get { return markerColor; } + set { + if (markerColor != value) { + markerColor = value; + Redraw(); + } + } + } + + public object ToolTip { get; set; } + } +} diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ExtensionMethods.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ExtensionMethods.cs index 1605ff281..d112c6141 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ExtensionMethods.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ExtensionMethods.cs @@ -22,7 +22,7 @@ namespace Tango.Scripting.Editors { List<String> args = new List<string>(); - foreach (var lGenericArgument in type.GetGenericTypeDefinition().GetGenericArguments()) + foreach (var lGenericArgument in type.GetGenericArguments()) { args.Add(lGenericArgument.Name); } diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/OffsetColorizer.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/OffsetColorizer.cs index a05d1fc75..72c27f9a9 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/OffsetColorizer.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/OffsetColorizer.cs @@ -30,7 +30,7 @@ namespace Tango.Scripting.Editors.Highlighting { try { - ChangeLinePart(StartOffset, EndOffset, element => element.TextRunProperties.SetForegroundBrush(Brush)); + ChangeLinePart(StartOffset, EndOffset, element => element.TextRunProperties.SetBackgroundBrush(Brush)); } catch { } } diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd index 6f400c4f5..1f6139ff6 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd @@ -11,7 +11,7 @@ <Color name="InterfaceTypes" foreground="#B5CE8A" exampleText="object o;" /> <Color name="MethodCall" foreground="Gainsboro" exampleText="o.ToString();"/> <Color name="NumberLiteral" foreground="#B5CE8A" exampleText="3.1415f"/> - <Color name="ThisOrBaseReference" exampleText="this.Do(); base.Do();"/> + <Color name="ThisOrBaseReference" foreground="#3F8FD6" exampleText="this.Do(); base.Do();"/> <Color name="NullOrValueKeywords" exampleText="if (value == null)"/> <Color name="Keywords" foreground="#3F8FD6" exampleText="if (a) {} else {}"/> <Color name="GotoKeywords" foreground="#3F8FD6" exampleText="continue; return null;"/> diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/MarkDown-Mode.xshd b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/MarkDown-Mode.xshd index ead5045ab..8e02db898 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/MarkDown-Mode.xshd +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/MarkDown-Mode.xshd @@ -5,7 +5,6 @@ <Color name="StrongEmphasis" fontWeight="bold" exampleText="**this** is more important!" /> <Color name="Code" exampleText="this is `int.GetHashCode()`" /> <Color name="BlockQuote" foreground="DarkBlue" exampleText="> This is a\r\n> quote." /> - <Color name="Link" foreground="Blue" exampleText="[text](http://example.com)" /> <Color name="Image" foreground="Green" exampleText="[text][http://example.com/test.png]" /> <Color name="LineBreak" background="LightGray" exampleText="end of line \r\n2nd line " /> @@ -43,12 +42,6 @@ <Rule color="Image"> \!\[.*\]\[.*\] </Rule> - <Rule color="Link"> - \[.*\]\(.*\) - </Rule> - <Rule color="Link"> - \[.*\]\[.*\] - </Rule> <Rule color="LineBreak"> [ ]{2}$ </Rule> diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/XML-Mode.xshd b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/XML-Mode.xshd index 8f0bdef76..50fdc0e2c 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/XML-Mode.xshd +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/XML-Mode.xshd @@ -1,13 +1,13 @@ <SyntaxDefinition name="XML" extensions=".xml;.xsl;.xslt;.xsd;.manifest;.config;.addin;.xshd;.wxs;.wxi;.wxl;.proj;.csproj;.vbproj;.ilproj;.booproj;.build;.xfrm;.targets;.xaml;.xpt;.xft;.map;.wsdl;.disco;.ps1xml;.nuspec" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"> <Color foreground="Green" name="Comment" exampleText="<!-- comment -->" /> - <Color foreground="Blue" name="CData" exampleText="<![CDATA[data]]>" /> - <Color foreground="Blue" name="DocType" exampleText="<!DOCTYPE rootElement>" /> - <Color foreground="Blue" name="XmlDeclaration" exampleText='<?xml version="1.0"?>' /> - <Color foreground="DarkMagenta" name="XmlTag" exampleText='<tag attribute="value" />' /> - <Color foreground="Red" name="AttributeName" exampleText='<tag attribute="value" />' /> - <Color foreground="Blue" name="AttributeValue" exampleText='<tag attribute="value" />' /> + <Color foreground="#3F92D6" name="CData" exampleText="<![CDATA[data]]>" /> + <Color foreground="#C8C8C7" name="DocType" exampleText="<!DOCTYPE rootElement>" /> + <Color foreground="#3F92D6" name="XmlDeclaration" exampleText='<?xml version="1.0"?>' /> + <Color foreground="#3F92D6" name="XmlTag" exampleText='<tag attribute="value" />' /> + <Color foreground="#92CAF4" name="AttributeName" exampleText='<tag attribute="value" />' /> + <Color foreground="#C8C8C7" name="AttributeValue" exampleText='<tag attribute="value" />' /> <Color foreground="Teal" name="Entity" exampleText="index.aspx?a=1&amp;b=2" /> - <Color foreground="Olive" name="BrokenEntity" exampleText="index.aspx?a=1&b=2" /> + <Color foreground="Red" name="BrokenEntity" exampleText="index.aspx?a=1&b=2" /> <RuleSet> <Span color="Comment" multiline="true"> diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/break_point_arrow.png b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/break_point_arrow.png Binary files differnew file mode 100644 index 000000000..e8d367028 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/break_point_arrow.png diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/snippet.png b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/snippet.png Binary files differnew file mode 100644 index 000000000..fe4d71eb4 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/snippet.png diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/CompletionItem.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/CompletionItem.cs index c8beebd28..191f99b6c 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/CompletionItem.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/CompletionItem.cs @@ -31,7 +31,7 @@ namespace Tango.Scripting.Editors.Intellisense int index = editor.GetCurrentWordStartIndex(); int max = editor.GetCurrentLine().EndOffset; - editor.Document.Replace(index, word.Length,Text); + editor.Document.Replace(index, word.Length, GetCode()); } public abstract BitmapSource Image { get; } @@ -41,6 +41,11 @@ namespace Tango.Scripting.Editors.Intellisense return new BitmapImage(new Uri($"pack://application:,,,/Tango.Scripting.Editors;component/Images/{name}", UriKind.Absolute)); } + protected virtual String GetCode() + { + return Text; + } + public override string ToString() { return Text; diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/HideIntellisenseAttribute.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/HideIntellisenseAttribute.cs new file mode 100644 index 000000000..548bd909e --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/HideIntellisenseAttribute.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting.Editors.Intellisense +{ + public class HideIntellisenseAttribute : Attribute + { + } +} diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs index 3dc465541..8010dc689 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs @@ -1,6 +1,8 @@ -using System; +using Newtonsoft.Json; +using System; using System.Collections; using System.Collections.Generic; +using System.Drawing; using System.IO; using System.Linq; using System.Reflection; @@ -42,6 +44,13 @@ namespace Tango.Scripting.Editors.Intellisense } public List<KnownTypeField> Fields { get; set; } + public static List<Assembly> ExtensionMethodsAssemblies { get; set; } + + static KnownType() + { + ExtensionMethodsAssemblies = new List<Assembly>(); + } + public KnownType(Type type) { Summary = "Loading documentation..."; @@ -123,9 +132,31 @@ namespace Tango.Scripting.Editors.Intellisense { var methods = Type.GetRuntimeMethods().Where(x => x.IsPublic && !x.IsSpecialName).ToList(); + if (Type.IsInterface) + { + foreach (var inter in Type.GetInterfaces()) + { + methods.AddRange(inter.GetRuntimeMethods().Where(x => x.IsPublic && !x.IsSpecialName).ToList()); + } + methods = methods.Distinct().ToList(); + + if (!methods.Exists(x => x.Name == "ToString")) + { + methods.Add(typeof(Object).GetMethod("ToString")); + } + } + //TODO: Separate extension methods! methods.AddRange(Type.GetExtensionMethods(Type.Assembly).ToList()); + if (Type.Namespace.StartsWith("Tango")) + { + foreach (var asm in ExtensionMethodsAssemblies.Where(x => x != Type.Assembly)) + { + methods.AddRange(Type.GetExtensionMethods(asm).ToList()); + } + } + if (typeof(IEnumerable).IsAssignableFrom(Type)) { var linqMethods = typeof(System.Linq.Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).ToList(); @@ -136,11 +167,13 @@ namespace Tango.Scripting.Editors.Intellisense { var method = methods[i]; + if (method.GetCustomAttribute<HideIntellisenseAttribute>() != null) continue; + KnownTypeMethod m = new KnownTypeMethod(this); m.Name = method.Name; m.ReturnType = method.ReturnType; m.ReturnTypeFriendlyName = method.ReturnType.GetFriendlyName(); - m.IsStatic = method.IsStatic; + m.IsStatic = method.IsStatic && !method.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false); if (method.IsGenericMethod) { @@ -182,12 +215,14 @@ namespace Tango.Scripting.Editors.Intellisense //Load Properties { - var properties = Type.GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance).ToList(); + var properties = Type.GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static).ToList(); for (int i = 0; i < properties.Count; i++) { var property = properties[i]; + if (property.GetCustomAttribute<HideIntellisenseAttribute>() != null) continue; + KnownTypeProperty p = new KnownTypeProperty(this); p.Name = property.Name; p.ReturnType = property.PropertyType; @@ -205,6 +240,8 @@ namespace Tango.Scripting.Editors.Intellisense { var ev = events[i]; + if (ev.GetCustomAttribute<HideIntellisenseAttribute>() != null) continue; + KnownTypeEvent p = new KnownTypeEvent(this); p.Name = ev.Name; diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/SnippetCompletionItem.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/SnippetCompletionItem.cs new file mode 100644 index 000000000..97807ed19 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/SnippetCompletionItem.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; + +namespace Tango.Scripting.Editors.Intellisense +{ + public class SnippetCompletionItem : CompletionItem + { + private static BitmapSource image = GetImage("snippet.png"); + + public override string Text => Name; + public override CompletionItemPopupControl PopupControl => new FieldCompletionItemPopup(); + public override BitmapSource Image => image; + + public String Name { get; set; } + public String Code { get; set; } + + protected override string GetCode() + { + return Code; + } + } +} diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/TextView.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/TextView.cs index 3dabb6b7a..1b1f12ff3 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/TextView.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/TextView.cs @@ -554,7 +554,7 @@ namespace Tango.Scripting.Editors.Rendering /// </summary> public static readonly DependencyProperty LinkTextForegroundBrushProperty = DependencyProperty.Register("LinkTextForegroundBrush", typeof(Brush), typeof(TextView), - new FrameworkPropertyMetadata(Brushes.Blue)); + new FrameworkPropertyMetadata(Brushes.Gray)); /// <summary> /// Gets/sets the Brush used for displaying link texts. diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs index f63cedcdc..e65ff671d 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel.Design; using System.Diagnostics; using System.IO; using System.Linq; @@ -46,7 +47,10 @@ namespace Tango.Scripting.Editors private char[] word_separators = { ' ', '\t', '\n', '.', '(', ',', '-', '*', '/', '+', '$', '=', '<', '>' }; private string[] _blocking_type_words = { "class", "void" }; + public event EventHandler<BreakPointSymbolPressedEventArgs> BreakPointSymbolPressed; + private DispatcherTimer _update_timer; + private BreakPointMargin breakPointMargin; private Popup _popup; private FoldingManager foldingManager; private BraceFoldingStrategy foldingStrategy; @@ -56,6 +60,12 @@ namespace Tango.Scripting.Editors private List<KnownType> _knownTypes; private List<ScriptType> _declaredTypes; private bool _isLoadingTypes; + private TextMarkerService errorMarkerService; + private List<ScriptBreakPointSymbol> _breakPointSymbols; + private int _breakPointLineNumber; + private ScriptBreakPointSymbol _currentBreakPointSymbol; + private Point _currentBreakPointSymbolPosition; + private static JsonSerializerSettings _jsonSettings; private static Dictionary<Type, KnownType> _knownTypesCache; private static String KNOWN_TYPES_CACHE_FOLDER; @@ -63,14 +73,35 @@ namespace Tango.Scripting.Editors private static List<CachedUsing> _cachedUsings; private static bool _isLoadingCachedAssemblies; private static bool _isCacheAssembliesLoaded; + private static bool _isUsingsLoadingStarted; private static object _loadUsingsLock = new object(); + private static List<SnippetCompletionItem> snippets; public static event EventHandler<TangoProgressChangedEventArgs<int>> LoadingSymbolsProgress; public static event EventHandler LoadingSymbolsStarted; public static event EventHandler LoadingSymbolsCompleted; + private static event EventHandler KnownTypesAvailable; + public static event EventHandler UsingsLoadingStarted; + public static event EventHandler UsingsLoadingCompleted; #region Mini Classes + private class KnownTypeResult + { + public KnownType KnownType { get; set; } + public bool IsStatic { get; set; } + + public KnownTypeResult() + { + + } + + public KnownTypeResult(KnownType knownType) + { + KnownType = knownType; + } + } + private class ScriptClass { public String Name { get; set; } @@ -160,6 +191,55 @@ namespace Tango.Scripting.Editors public static readonly DependencyProperty AdditionalScriptsProperty = DependencyProperty.Register("AdditionalScripts", typeof(ObservableCollection<IScriptSource>), typeof(ScriptEditor), new PropertyMetadata(null)); + public Brush ColorizeBrush + { + get { return (Brush)GetValue(ColorizeBrushProperty); } + set { SetValue(ColorizeBrushProperty, value); } + } + public static readonly DependencyProperty ColorizeBrushProperty = + DependencyProperty.Register("ColorizeBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.YellowGreen) { Opacity = 0.5 })); + + public Brush ErrorLineBrush + { + get { return (Brush)GetValue(ErrorLineBrushProperty); } + set { SetValue(ErrorLineBrushProperty, value); } + } + public static readonly DependencyProperty ErrorLineBrushProperty = + DependencyProperty.Register("ErrorLineBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.Red) { Opacity = 0.5 })); + + public Brush DebugLineBrush + { + get { return (Brush)GetValue(DebugLineBrushProperty); } + set { SetValue(DebugLineBrushProperty, value); } + } + public static readonly DependencyProperty DebugLineBrushProperty = + DependencyProperty.Register("DebugLineBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.Gray) { Opacity = 0.5 })); + + public Brush BreakPointLineBrush + { + get { return (Brush)GetValue(BreakPointLineBrushProperty); } + set { SetValue(BreakPointLineBrushProperty, value); } + } + public static readonly DependencyProperty BreakPointLineBrushProperty = + DependencyProperty.Register("BreakPointLineBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.Yellow) { Opacity = 0.5 })); + + public IScriptSource ScriptSource + { + get { return (IScriptSource)GetValue(ScriptSourceProperty); } + set { SetValue(ScriptSourceProperty, value); } + } + public static readonly DependencyProperty ScriptSourceProperty = + DependencyProperty.Register("ScriptSource", typeof(IScriptSource), typeof(ScriptEditor), new PropertyMetadata(null)); + + public bool DisableBreakPoints + { + get { return (bool)GetValue(DisableBreakPointsProperty); } + set { SetValue(DisableBreakPointsProperty, value); } + } + public static readonly DependencyProperty DisableBreakPointsProperty = + DependencyProperty.Register("DisableBreakPoints", typeof(bool), typeof(ScriptEditor), new PropertyMetadata(false)); + + #endregion #region Constructors @@ -171,6 +251,8 @@ namespace Tango.Scripting.Editors { DefaultStyleKeyProperty.OverrideMetadata(typeof(ScriptEditor), new FrameworkPropertyMetadata(typeof(ScriptEditor))); + snippets = new List<SnippetCompletionItem>(); + BlockedUsingsCache = new List<string>(); if (KNOWN_TYPES_CACHE_FOLDER == null) @@ -188,6 +270,67 @@ namespace Tango.Scripting.Editors _knownTypesCache = new Dictionary<Type, KnownType>(); _cachedAssemblies = new List<CachedAssembly>(); _cachedUsings = new List<CachedUsing>(); + + snippets.Add(new SnippetCompletionItem() + { + Name = "for", + Code = @"for (int i = 0; i < 10; i++) + { + + }" + }); + + snippets.Add(new SnippetCompletionItem() + { + Name = "while", + Code = @"while (true) + { + + }" + }); + + snippets.Add(new SnippetCompletionItem() + { + Name = "foreach", + Code = @"foreach (var item in items) + { + + }" + }); + + snippets.Add(new SnippetCompletionItem() + { + Name = "prop", + Code = @"public int MyProperty { get; set; }" + }); + + snippets.Add(new SnippetCompletionItem() + { + Name = "do", + Code = @"do + { + + } while (true)" + }); + + snippets.Add(new SnippetCompletionItem() + { + Name = "try", + Code = @"try + { + + } + catch (Exception ex) + { + + }" + }); + + snippets.Add(new SnippetCompletionItem() + { + Name = "cw", + Code = "context.WriteLine(\"\");" + }); } /// <summary> @@ -208,6 +351,8 @@ namespace Tango.Scripting.Editors _knownTypes = new List<KnownType>(); _parser = new ScriptParser(); + KnownTypesAvailable += ScriptEditor_KnownTypesAvailable; + TextArea.IndentationStrategy = new Indentation.CSharp.CSharpIndentationStrategy(Options); foldingStrategy = new BraceFoldingStrategy(); @@ -227,6 +372,36 @@ namespace Tango.Scripting.Editors completionWindow.InsertionRequest += CompletionWindow_InsertionRequest; TextChanged += ScriptEditor_TextChanged; + + errorMarkerService = new TextMarkerService(Document); + TextArea.TextView.BackgroundRenderers.Add(errorMarkerService); + TextArea.TextView.LineTransformers.Add(errorMarkerService); + + Unloaded += ScriptEditor_Unloaded; + + breakPointMargin = new BreakPointMargin(this); + _breakPointSymbols = new List<ScriptBreakPointSymbol>(); + Loaded += ScriptEditor_Loaded; + + MouseMove += ScriptEditor_MouseMove; + } + + private void ScriptEditor_Loaded(object sender, RoutedEventArgs e) + { + TextArea.LeftMargins.Insert(0, breakPointMargin); + } + + private void ScriptEditor_Unloaded(object sender, RoutedEventArgs e) + { + _update_timer.Stop(); + } + + private void ScriptEditor_KnownTypesAvailable(object sender, EventArgs e) + { + if (sender != this) + { + InvalidateHighlightingPartial(); + } } private bool preventCodeUpdate; @@ -377,6 +552,8 @@ namespace Tango.Scripting.Editors private void TextArea_TextEntered(object sender, TextCompositionEventArgs e) { + if (IsReadOnly) return; + try { List<Object> items = new List<object>(); @@ -394,19 +571,19 @@ namespace Tango.Scripting.Editors if (e.Text == " " && previousWords.Count > 2 && previousWords[previousWords.Count - 2] == "=") { var expression = previousWords.First(); - var knownType = GetKnownTypeFromExpression(expression + "."); + var knownTypeResult = GetKnownTypeFromExpression(expression + "."); - if (knownType != null && knownType.Type.IsEnum) + if (knownTypeResult != null && knownTypeResult.KnownType.Type.IsEnum) { completionWindow.HideCompletion(); IList<ICompletionData> data = new List<ICompletionData>(); - foreach (var field in knownType.Fields) + foreach (var field in knownTypeResult.KnownType.Fields) { data.Add(new FieldCompletionItem() { - Class = knownType.FriendlyName, - Name = knownType.FriendlyName + "." + field.Name, + Class = knownTypeResult.KnownType.FriendlyName, + Name = knownTypeResult.KnownType.FriendlyName + "." + field.Name, Type = field.ReturnTypeFriendlyName, Description = field.Summary, }); @@ -441,25 +618,25 @@ namespace Tango.Scripting.Editors } else if (e.Text == ".") { - var knownType = GetCurrentKnownType(); + var knownTypeResult = GetCurrentKnownType(); IList<ICompletionData> data = new List<ICompletionData>(); - if (knownType != null) + if (knownTypeResult != null) { completionWindow.HideCompletion(); - if (!knownType.Type.IsEnum) + if (!knownTypeResult.KnownType.Type.IsEnum) { - var typeMembers = knownType.Members.ToList(); + var typeMembers = knownTypeResult.KnownType.Members.ToList(); - foreach (var methodGroup in typeMembers.OfType<KnownTypeMethod>().Where(x => !x.IsStatic).GroupBy(x => x.NameWithTypeArguments)) + foreach (var methodGroup in typeMembers.OfType<KnownTypeMethod>().Where(x => (!knownTypeResult.IsStatic && !x.IsStatic) || (knownTypeResult.IsStatic && x.IsStatic)).GroupBy(x => x.NameWithTypeArguments)) { var method = methodGroup.First(); data.Add(new MethodCompletionItem() { - Class = knownType.FriendlyName, + Class = knownTypeResult.KnownType.FriendlyName, Name = method.NameWithTypeArguments, ReturnType = method.ReturnTypeFriendlyName, Description = method.Summary, @@ -472,7 +649,7 @@ namespace Tango.Scripting.Editors { data.Add(new EventCompletionItem() { - Class = knownType.FriendlyName, + Class = knownTypeResult.KnownType.FriendlyName, Name = ev.Name, Description = ev.Summary, }); @@ -484,7 +661,7 @@ namespace Tango.Scripting.Editors data.Add(new PropertyCompletionItem() { - Class = knownType.FriendlyName, + Class = knownTypeResult.KnownType.FriendlyName, Name = member.Name, Type = member.ReturnTypeFriendlyName, Description = member.Summary, @@ -493,11 +670,11 @@ namespace Tango.Scripting.Editors } else { - foreach (var field in knownType.Fields) + foreach (var field in knownTypeResult.KnownType.Fields) { data.Add(new FieldCompletionItem() { - Class = knownType.FriendlyName, + Class = knownTypeResult.KnownType.FriendlyName, Name = field.Name, Type = field.ReturnTypeFriendlyName, Description = field.Summary, @@ -573,34 +750,6 @@ namespace Tango.Scripting.Editors ShowCompletionWindow(data, GetCurrentWord()); } - else - { - //Maybe static ... - var typeText = GetPreviousWord(); - knownType = _knownTypes.FirstOrDefault(x => x.FriendlyName == typeText || x.Alias == typeText); - - if (knownType != null) - { - var typeMembers = knownType.Members.ToList(); - - foreach (var methodGroup in typeMembers.OfType<KnownTypeMethod>().Where(x => x.IsStatic).GroupBy(x => x.NameWithTypeArguments)) - { - var method = methodGroup.First(); - - data.Add(new MethodCompletionItem() - { - Class = knownType.FriendlyName, - Name = method.NameWithTypeArguments, - ReturnType = method.ReturnTypeFriendlyName, - Description = method.Summary, - Parameters = method.Parameters, - Overloads = methodGroup.Count() - 1, - }); - } - - ShowCompletionWindow(data.OrderBy(x => x.Text).ToList(), GetCurrentWord()); - } - } } } else if (e.Text == "(" || e.Text == ",") @@ -746,6 +895,11 @@ namespace Tango.Scripting.Editors { IList<ICompletionData> data = new List<ICompletionData>(); + foreach (var snippet in snippets) + { + data.Add(snippet); + } + foreach (var type in _declaredTypes.Where(x => x.Name.StartsWith(word))) { if (type.Kind == TypeKind.Struct) @@ -993,13 +1147,13 @@ namespace Tango.Scripting.Editors return list; } - private KnownType GetCurrentKnownType() + private KnownTypeResult GetCurrentKnownType() { var expression = GetPreviousWords().LastOrDefault(); return GetKnownTypeFromExpression(expression); } - private KnownType GetKnownTypeFromExpression(String expression) + private KnownTypeResult GetKnownTypeFromExpression(String expression) { if (expression != null) { @@ -1020,7 +1174,7 @@ namespace Tango.Scripting.Editors if (enumType != null) { - return enumType; + return new KnownTypeResult(enumType); } tree.RemoveAt(0); @@ -1048,9 +1202,37 @@ namespace Tango.Scripting.Editors knownType = _knownTypes.FirstOrDefault(x => x.Type.Namespace + "." + x.Type.Name == member.ReturnType.Namespace + "." + member.ReturnType.Name); } - return knownType; + return new KnownTypeResult(knownType); + } + else //Maybe a variable of a declared type... + { + if (tree.Count > 0) + { + var memberName = tree[0]; + var declaredType = _declaredTypes.SingleOrDefault(x => x.Name == name); + + if (declaredType != null) + { + var member = declaredType.Symbols.FirstOrDefault(x => x.Name == memberName); + if (member != null) + { + knownType = _knownTypes.SingleOrDefault(x => x.Name.ToLower() == member.Type.ToLower()); + + if (knownType != null) + { + return new KnownTypeResult(knownType); + } + } + } + } } } + else + { + //Maybe static... + var type = _knownTypes.FirstOrDefault(x => x.Name == variableName || x.Alias == variableName); + return type != null ? new KnownTypeResult(type) { IsStatic = true } : null; + } } } @@ -1102,6 +1284,11 @@ namespace Tango.Scripting.Editors return declaredType; } } + else + { + //Maybe static... + return _declaredTypes.FirstOrDefault(x => x.Name == variableName); + } } } @@ -1191,7 +1378,7 @@ namespace Tango.Scripting.Editors foreach (var m in session.Type.Methods.Where(x => x.Name == session.MethodName)) { MethodDescription method = new MethodDescription(); - method.ReturnType = session.Type.Name; + method.ReturnType = m.ReturnTypeFriendlyName; method.Description = m.Summary; method.Name = m.NameWithTypeArguments; method.Class = session.Type.FriendlyName; @@ -1284,7 +1471,7 @@ namespace Tango.Scripting.Editors return popup; } - public static void LoadUsingsSymbols(List<Assembly> assemblies, List<String> usings) + public void LoadUsingsSymbols(List<Assembly> assemblies, List<String> usings) { lock (_loadUsingsLock) { @@ -1296,6 +1483,12 @@ namespace Tango.Scripting.Editors { if (!_cachedUsings.Exists(x => x.Namespace == use)) { + if (!_isUsingsLoadingStarted) + { + _isUsingsLoadingStarted = true; + UsingsLoadingStarted?.Invoke(this, new EventArgs()); + } + var useFileName = System.IO.Path.Combine(KNOWN_TYPES_CACHE_FOLDER, use + ".json"); if (File.Exists(useFileName)) @@ -1317,6 +1510,9 @@ namespace Tango.Scripting.Editors _knownTypesCache.Add(knownType.Type, knownType); } + KnownTypesAvailable?.Invoke(this, new EventArgs()); + InvalidateHighlightingPartial(); + continue; } @@ -1370,13 +1566,17 @@ namespace Tango.Scripting.Editors knownType.Alias = "uint"; } } + else if (type == typeof(String)) + { + knownType.Alias = "string"; + } _knownTypesCache.Add(type, knownType); cachedUsing.KnownTypes.Add(knownType); knownType.LoadDocumentation(); } - if (!BlockedUsingsCache.Exists(x => x == use)) + if (!BlockedUsingsCache.Exists(x => use.StartsWith(x))) { Task.Factory.StartNew(() => { @@ -1387,6 +1587,11 @@ namespace Tango.Scripting.Editors } } + if (_isUsingsLoadingStarted) + { + UsingsLoadingCompleted?.Invoke(this, new EventArgs()); + } + LoadingSymbolsCompleted?.Invoke(null, new EventArgs()); } } @@ -1502,6 +1707,100 @@ namespace Tango.Scripting.Editors // _isLoadingCachedAssemblies = false; //} + private void InvalidateHighlightingPartial() + { + List<Assembly> assemblies = new List<Assembly>(); + Dispatcher.Invoke(() => + { + assemblies = ReferenceAssemblies.ToList(); + }); + + var usings = _current_usings.ToList(); + + _knownTypes.Clear(); + + foreach (var knownType in _knownTypesCache.ToList().Select(x => x.Value).ToList()) + { + if (usings.Exists(x => knownType.Type.Namespace == x) && assemblies.Exists(x => x == knownType.Type.Assembly)) + { + lock (_knownTypes) + { + _knownTypes.Add(knownType); + } + } + } + + if (_knownTypes.Count > 0 || _declaredTypes.Count > 0) + { + String text = String.Empty; + + Stream xshd_stream = typeof(ScriptEditor).Assembly.GetManifestResourceStream("Tango.Scripting.Editors.Highlighting.Resources.CSharp-Mode.xshd"); + + using (StreamReader reader = new StreamReader(xshd_stream)) + { + text = reader.ReadToEnd(); + } + + List<String> referenceTypes = new List<string>(); + List<String> interfaceTypes = new List<string>(); + + lock (_knownTypes) + { + foreach (var type in _knownTypes.ToList().Where(x => x != null)) + { + String name = type.Name; + + if (type.Type.ContainsGenericParameters) + { + name = new String(name.TakeWhile(x => x != '`').ToArray()); + } + + if (type.Type.IsInterface || type.Type.IsEnum) + { + interfaceTypes.Add(String.Format("<Word>{0}</Word>", name)); + } + else if (type.Type.IsClass || (type.Type.IsValueType)) + { + referenceTypes.Add(String.Format("<Word>{0}</Word>", name)); + } + } + } + + foreach (var type in _declaredTypes) + { + if (type.Kind == TypeKind.Interface || type.Kind == TypeKind.Enum) + { + interfaceTypes.Add(String.Format("<Word>{0}</Word>", type.Name)); + } + else if (type.Kind == TypeKind.Class) + { + referenceTypes.Add(String.Format("<Word>{0}</Word>", type.Name)); + } + } + + if (referenceTypes.Count > 0) + { + text = text.Replace("<Word>@ReferenceTypes@</Word>", String.Join(Environment.NewLine, referenceTypes.Distinct())); + } + + if (interfaceTypes.Count > 0) + { + text = text.Replace("<Word>@InterfaceTypes@</Word>", String.Join(Environment.NewLine, interfaceTypes.Distinct())); + } + + MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(text)); + + XmlTextReader xshd_reader = new XmlTextReader(ms); + + Dispatcher.Invoke(new Action(() => + { + SyntaxHighlighting = HighlightingLoader.Load(xshd_reader, HighlightingManager.Instance); + xshd_reader.Close(); + ms.Dispose(); + })); + } + } + public void InvalidateHighlighting(bool loadKnownTypes = true) { if (!_isLoadingTypes) @@ -1509,6 +1808,7 @@ namespace Tango.Scripting.Editors _isLoadingTypes = true; var assemblies = ReferenceAssemblies.ToList(); + KnownType.ExtensionMethodsAssemblies = assemblies.ToList(); var usings = _current_usings.ToList(); Thread t = new Thread(() => @@ -1876,6 +2176,8 @@ namespace Tango.Scripting.Editors currentLine = currentLine.Split('(')[currentLine.Split('(').Length - 2]; } + currentLine = Regex.Replace(currentLine, "(?<=\")(.*?)(?=\")", string.Empty); + var words = currentLine.Split(' '); if (words.Count() > 0 && (words.First() == "private" || words.First() == "public" || words.First() == "void")) @@ -1888,6 +2190,8 @@ namespace Tango.Scripting.Editors if (expression != null) { int parameterIndex = expression.Count(x => x == ','); + + expression = new string(expression.TakeWhile(x => x != '(').ToArray()); var tree = expression.Split('.').Select(x => x.Remove(@"\n|\r|\s|\t|\(|\)|\[|\]|<.*>")).ToList(); @@ -2132,6 +2436,363 @@ namespace Tango.Scripting.Editors Document.Insert(TextArea.Caret.Offset, code); } + public int Find(String text) + { + if (String.IsNullOrEmpty(text)) return -1; + + string txt = Document.Text; + int index = txt.IndexOf(text, TextArea.Caret.Offset); + + if (index > -1) + { + Select(index, text.Length); + ScrollToLine(TextArea.Selection.StartPosition.Line); + } + else + { + index = txt.IndexOf(text, 0); + + if (index > -1) + { + Select(index, text.Length); + ScrollToLine(TextArea.Selection.StartPosition.Line); + } + else + { + Select(0, 0); + System.Media.SystemSounds.Beep.Play(); + } + } + + return index; + } + + public int ReplaceNext(String text, String replace) + { + if (String.IsNullOrEmpty(text)) return -1; + + String selectedText = TextArea.Selection.GetText(); + + if (selectedText == text) + { + TextArea.Selection.ReplaceSelectionWithText(replace); + } + + return Find(text); + } + + public int ReplaceAll(String text, String replace) + { + int counter = 0; + + Select(0, 0); + + while (ReplaceNext(text, replace) > -1) + { + counter++; + }; + + return counter; + } + + public void ColorizeByKeyword(String text) + { + ResetColorizationByKeyword(); + + if (String.IsNullOrEmpty(text)) return; + + var txt = Document.Text; + + var indexes = txt.AllIndexesOf(text).ToList(); + + foreach (var index in indexes) + { + Document.BeginUpdate(); + + var line = Document.GetLineByOffset(index); + + OffsetColorizer colorizer = new OffsetColorizer(line, index, index + text.Length, ColorizeBrush); + TextArea.TextView.LineTransformers.Add(colorizer); + + Document.EndUpdate(); + } + } + + public void ResetColorizationByKeyword() + { + Document.BeginUpdate(); + + for (int i = 0; i < TextArea.TextView.LineTransformers.Count; i++) + { + if (TextArea.TextView.LineTransformers[i] is OffsetColorizer) + { + TextArea.TextView.LineTransformers.RemoveAt(i); + i--; + } + } + + Document.EndUpdate(); + } + + public void HighlighError(int position, int length) + { + try + { + ITextMarker marker = errorMarkerService.Create(position, length); + marker.MarkerTypes = TextMarkerTypes.SquigglyUnderline; + marker.MarkerColor = Colors.Red; + } + catch (Exception ex) + { + Debug.WriteLine($"Error highlighting script error.\n{ex.ToString()}"); + } + } + + public void ClearErrors() + { + errorMarkerService.RemoveAll(m => true); + } + + public void HighlightErrorLine(int lineNumber) + { + Document.BeginUpdate(); + + var line = Document.GetLineByNumber(lineNumber); + OffsetColorizer errorLineColrizer = new OffsetColorizer(line, line.Offset, line.EndOffset, ErrorLineBrush); + TextArea.TextView.LineTransformers.Add(errorLineColrizer); + + Document.EndUpdate(); + } + + public void HighlightDebugLine(int lineNumber) + { + Document.BeginUpdate(); + + var line = Document.GetLineByNumber(lineNumber); + OffsetColorizer errorLineColrizer = new OffsetColorizer(line, line.Offset, line.EndOffset, DebugLineBrush); + TextArea.TextView.LineTransformers.Add(errorLineColrizer); + + Document.EndUpdate(); + } + + public void HighlightBreakPoint(int lineNumber, List<ScriptBreakPointSymbol> symbols) + { + _breakPointLineNumber = lineNumber; + _breakPointSymbols = symbols.ToList(); + _currentBreakPointSymbol = null; + + Document.BeginUpdate(); + + var line = Document.GetLineByNumber(lineNumber); + OffsetColorizer errorLineColrizer = new OffsetColorizer(line, line.Offset, line.EndOffset, BreakPointLineBrush); + TextArea.TextView.LineTransformers.Add(errorLineColrizer); + + var breakPoint = breakPointMargin.BreakPoints.FirstOrDefault(x => x.LineNumber == lineNumber); + breakPoint.IsActive = true; + breakPointMargin.InvalidateVisual(); + + Document.EndUpdate(); + } + + public void ResetBreakPointLine() + { + _breakPointSymbols = new List<ScriptBreakPointSymbol>(); + _currentBreakPointSymbol = null; + ResetColorizationByKeyword(); + breakPointMargin.BreakPoints.ToList().ForEach(x => x.IsActive = false); + Mouse.OverrideCursor = null; + ClearErrors(); + breakPointMargin.InvalidateVisual(); + } + + public Point? GetLineVisualPosition(int lineNumber) + { + double top = TextArea.TextView.GetVisualTopByDocumentLine(lineNumber); + var visualLine = TextArea.TextView.GetVisualLine(lineNumber); + + if (visualLine != null) + { + var textLine = visualLine.GetTextLine(0); + var x = visualLine.GetTextLineVisualXPosition(textLine, visualLine.VisualLengthWithEndOfLineMarker); + var left = visualLine.VisualLengthWithEndOfLineMarker; + return new Point(x, top); + } + + return null; + } + + public List<ScriptBreakPoint> GetBreakPoints() + { + List<ScriptBreakPoint> breakPoints = new List<ScriptBreakPoint>(); + + foreach (var b in breakPointMargin.BreakPoints) + { + ScriptBreakPoint breakPoint = new ScriptBreakPoint(); + breakPoint.Script = ScriptSource; + breakPoint.LineNumber = b.LineNumber; + + var line = Document.GetLineByNumber(b.LineNumber); + breakPoint.LineStartOffset = line.Offset; + breakPoint.LineEndOffset = line.EndOffset; + + var symbols = _parser.GetContextSymbols(Document.Text, line.Offset); + + foreach (var symbol in symbols.Where(x => (x.Kind == SymbolKind.Property || x.Kind == SymbolKind.Field || x.Kind == SymbolKind.Local || x.Kind == SymbolKind.Parameter) && !x.IsUnassigned)) + { + if (symbol.Offset < line.Offset) + { + breakPoint.ContextSymbols.Add(new ScriptBreakPointSymbol() + { + Name = symbol.Name, + Offset = symbol.Offset, + Length = symbol.Length, + }); + } + } + + breakPoints.Add(breakPoint); + } + + return breakPoints; + } + + #endregion + + #region BreakPoint Symbols Search + + private void ScriptEditor_MouseMove(object sender, MouseEventArgs e) + { + if (IsReadOnly && _breakPointSymbols.Count > 0) + { + try + { + var word_separators_plus = word_separators.ToList(); + word_separators_plus.Add(')'); + word_separators_plus.Add(';'); + + var textView = TextArea.TextView; + Point position = e.GetPosition(textView); + position.Y += textView.VerticalOffset; + VisualLine visualLine = textView.GetVisualLineFromVisualTop(position.Y); + int columnIndex = visualLine.GetVisualColumnFloor(position, false); + String line = Document.GetText(visualLine.FirstDocumentLine.Offset, visualLine.FirstDocumentLine.Length); + if (columnIndex < line.Length) + { + int wordStartIndex = columnIndex; + int wordEndIndex = columnIndex; + + while (wordStartIndex > 0) + { + if (word_separators_plus.Contains(line[wordStartIndex])) break; + wordStartIndex--; + } + + while (wordEndIndex < line.Length) + { + if (word_separators_plus.Contains(line[wordEndIndex])) break; + wordEndIndex++; + } + + if (wordStartIndex > 0) + { + wordStartIndex++; + } + + String word = line.Substring(wordStartIndex, wordEndIndex - wordStartIndex); + + var breakPointSymbol = _breakPointSymbols.FirstOrDefault(x => x.Name == word); + + if (breakPointSymbol != null) + { + int wordStartOffset = visualLine.FirstDocumentLine.Offset + wordStartIndex; + + ClearErrors(); + ITextMarker marker = errorMarkerService.Create(wordStartOffset, word.Length); + marker.MarkerTypes = TextMarkerTypes.NormalUnderline; + marker.MarkerColor = Colors.Yellow; + Mouse.OverrideCursor = Cursors.Hand; + + _currentBreakPointSymbol = breakPointSymbol; + _currentBreakPointSymbolPosition = visualLine.GetVisualPosition(wordEndIndex, VisualYPosition.LineTop); + } + else + { + _currentBreakPointSymbol = null; + Mouse.OverrideCursor = null; + ClearErrors(); + } + } + else + { + _currentBreakPointSymbol = null; + Mouse.OverrideCursor = null; + ClearErrors(); + } + } + catch (Exception ex) + { + _currentBreakPointSymbol = null; + Mouse.OverrideCursor = null; + ClearErrors(); + Debug.WriteLine(ex.Message); + } + } + } + + protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnPreviewMouseLeftButtonUp(e); + + if (_currentBreakPointSymbol != null) + { + Mouse.OverrideCursor = null; + Debug.WriteLine($"Pressed on break point symbol: {_currentBreakPointSymbol.Name}"); + BreakPointSymbolPressed?.Invoke(this, new BreakPointSymbolPressedEventArgs() + { + BreakPointSymbol = _currentBreakPointSymbol, + Position = _currentBreakPointSymbolPosition + }); + } + } + + public String GetCaretWord() + { + try + { + var word_separators_plus = word_separators.ToList(); + word_separators_plus.Add(')'); + word_separators_plus.Add(';'); + + int wordStartOffset = CaretOffset; + int wordEndOffset = CaretOffset; + + while (wordStartOffset > 0) + { + if (word_separators_plus.Contains(Document.Text[wordStartOffset])) break; + wordStartOffset--; + } + + while (wordEndOffset < Document.Text.Length) + { + if (word_separators_plus.Contains(Document.Text[wordEndOffset])) break; + wordEndOffset++; + } + + if (wordStartOffset > 0) + { + wordStartOffset++; + } + + String word = Document.Text.Substring(wordStartOffset, wordEndOffset - wordStartOffset); + + return word; + } + catch + { + return null; + } + } + #endregion } } diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj index 5f9548262..11e023f86 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj @@ -180,6 +180,7 @@ <Link>GlobalVersionInfo.cs</Link> </Compile> <Compile Include="AvalonEditCommands.cs" /> + <Compile Include="BreakPointSymbolPressedEventArgs.cs" /> <Compile Include="CachedAssembly.cs" /> <Compile Include="CachedUsing.cs" /> <Compile Include="CodeCompletion\CompletionListBox.cs" /> @@ -196,6 +197,9 @@ <Compile Include="CodeCompletion\OverloadViewer.cs" /> <Compile Include="Converters\BooleanToVisibilityConverter.cs" /> <Compile Include="Converters\BooleanToVisibilityInversedConverter.cs" /> + <Compile Include="Editing\BreakPointMargin.cs" /> + <Compile Include="Errors\ITextMarker.cs" /> + <Compile Include="Errors\TextMarkerService.cs" /> <Compile Include="ExtensionMethods.cs" /> <Compile Include="Intellisense\ClassCompletionItemPopup.cs" /> <Compile Include="Intellisense\CompletionItem.cs" /> @@ -205,6 +209,7 @@ <Compile Include="Intellisense\EventCompletionItem.cs" /> <Compile Include="Intellisense\FieldCompletionItem.cs" /> <Compile Include="Intellisense\FieldCompletionItemPopup.cs" /> + <Compile Include="Intellisense\HideIntellisenseAttribute.cs" /> <Compile Include="Intellisense\ICompletionItem.cs" /> <Compile Include="Intellisense\ICompletionProvider.cs" /> <Compile Include="Intellisense\InterfaceCompletionItem.cs" /> @@ -355,6 +360,7 @@ <Compile Include="Intellisense\NamespaceCompletionItemPopup.cs" /> <Compile Include="Intellisense\PropertyCompletionItem.cs" /> <Compile Include="Intellisense\PropertyCompletionItemPopup.cs" /> + <Compile Include="Intellisense\SnippetCompletionItem.cs" /> <Compile Include="Intellisense\StructCompletionItem.cs" /> <Compile Include="Intellisense\StructCompletionItemPopup.cs" /> <Compile Include="Intellisense\Utils.cs" /> @@ -507,6 +513,7 @@ <Compile Include="Utils\ThrowUtil.cs" /> <Compile Include="Utils\Win32.cs" /> <CodeAnalysisDictionary Include="Properties\CodeAnalysisDictionary.xml" /> + <Compile Include="XamlEditor.cs" /> <Compile Include="Xml\AbstractAXmlVisitor.cs" /> <Compile Include="Xml\AXmlAttribute.cs" /> <Compile Include="Xml\AXmlAttributeCollection.cs" /> @@ -644,6 +651,12 @@ <ItemGroup> <Resource Include="Images\event.png" /> </ItemGroup> + <ItemGroup> + <Resource Include="Images\snippet.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Images\break_point_arrow.png" /> + </ItemGroup> <ProjectExtensions> <VisualStudio> <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UseGlobalSettings="True" /> diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors_di35u2uj_wpftmp.csproj b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors_di35u2uj_wpftmp.csproj new file mode 100644 index 000000000..70a4840c4 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors_di35u2uj_wpftmp.csproj @@ -0,0 +1,628 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectGuid>{DA62FA39-668B-47A6-B0F2-D2C1DAF777B0}</ProjectGuid> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <OutputType>Library</OutputType> + <RootNamespace>Tango.Scripting.Editors</RootNamespace> + <AssemblyName>Tango.Scripting.Editors</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <AppDesignerFolder>Properties</AppDesignerFolder> + <SourceAnalysisOverrideSettingsFile>"C:\Program Files\SharpDevelop\3.0\bin\..\AddIns\AddIns\Misc\SourceAnalysis\Settings.SourceAnalysis"</SourceAnalysisOverrideSettingsFile> + <AllowUnsafeBlocks>False</AllowUnsafeBlocks> + <NoStdLib>False</NoStdLib> + <WarningLevel>4</WarningLevel> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + <SignAssembly>false</SignAssembly> + <AssemblyOriginatorKeyFile>ICSharpCode.AvalonEdit.snk</AssemblyOriginatorKeyFile> + <DelaySign>False</DelaySign> + <AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode> + <RunCodeAnalysis>False</RunCodeAnalysis> + <CodeAnalysisRules>-Microsoft.Design#CA1020;-Microsoft.Design#CA1033;-Microsoft.Performance#CA1805;-Microsoft.Performance#CA1810</CodeAnalysisRules> + <OutputPath>..\bin\$(Configuration)</OutputPath> + <DocumentationFile>..\bin\$(Configuration)\ICSharpCode.AvalonEdit.xml</DocumentationFile> + <NoWarn>1607</NoWarn> + <TargetFrameworkProfile> + </TargetFrameworkProfile> + <SccProjectName>SAK</SccProjectName> + <SccLocalPath>SAK</SccLocalPath> + <SccAuxPath>SAK</SccAuxPath> + <SccProvider>SAK</SccProvider> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>Full</DebugType> + <Optimize>False</Optimize> + <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> + <DefineConstants>DEBUG;TRACE;DOTNET4</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> + <DebugSymbols>false</DebugSymbols> + <DebugType>PdbOnly</DebugType> + <Optimize>True</Optimize> + <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow> + <DefineConstants>TRACE;DOTNET4</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' "> + <RegisterForComInterop>False</RegisterForComInterop> + <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies> + <BaseAddress>4194304</BaseAddress> + <PlatformTarget>AnyCPU</PlatformTarget> + <FileAlignment>4096</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'"> + <OutputPath>..\..\Build\Scripting\Debug\</OutputPath> + <DocumentationFile> + </DocumentationFile> + <Prefer32Bit>false</Prefer32Bit> + <DefineConstants>TRACE;DEBUG</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> + <Prefer32Bit>false</Prefer32Bit> + <OutputPath>..\..\Build\Scripting\Release\</OutputPath> + <DocumentationFile /> + </PropertyGroup> + <PropertyGroup> + <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + </PropertyGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> + <ItemGroup> + </ItemGroup> + <ItemGroup> + <Compile Include="..\..\Versioning\GlobalVersionInfo.cs"> + <Link>GlobalVersionInfo.cs</Link> + </Compile> + <Compile Include="AvalonEditCommands.cs" /> + <Compile Include="CachedAssembly.cs" /> + <Compile Include="CachedUsing.cs" /> + <Compile Include="CodeCompletion\CompletionListBox.cs" /> + <Compile Include="CodeCompletion\CompletionListBoxItem.cs" /> + <Compile Include="CodeCompletion\CompletionWindowBase.cs" /> + <Compile Include="CodeCompletion\CompletionList.cs" /> + <Compile Include="CodeCompletion\CompletionWindow.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="CodeCompletion\ICompletionData.cs" /> + <Compile Include="CodeCompletion\InsightWindow.cs" /> + <Compile Include="CodeCompletion\IOverloadProvider.cs" /> + <Compile Include="CodeCompletion\OverloadInsightWindow.cs" /> + <Compile Include="CodeCompletion\OverloadViewer.cs" /> + <Compile Include="Converters\BooleanToVisibilityConverter.cs" /> + <Compile Include="Converters\BooleanToVisibilityInversedConverter.cs" /> + <Compile Include="Editing\BreakPoint.cs" /> + <Compile Include="Editing\BreakPointMargin.cs" /> + <Compile Include="Errors\ITextMarker.cs" /> + <Compile Include="Errors\TextMarkerService.cs" /> + <Compile Include="ExtensionMethods.cs" /> + <Compile Include="Intellisense\ClassCompletionItemPopup.cs" /> + <Compile Include="Intellisense\CompletionItem.cs" /> + <Compile Include="Intellisense\CompletionItemPopupControl.cs" /> + <Compile Include="Intellisense\EnumCompletionItem.cs" /> + <Compile Include="Intellisense\EnumCompletionItemPopup.cs" /> + <Compile Include="Intellisense\EventCompletionItem.cs" /> + <Compile Include="Intellisense\FieldCompletionItem.cs" /> + <Compile Include="Intellisense\FieldCompletionItemPopup.cs" /> + <Compile Include="Intellisense\ICompletionItem.cs" /> + <Compile Include="Intellisense\ICompletionProvider.cs" /> + <Compile Include="Intellisense\InterfaceCompletionItem.cs" /> + <Compile Include="Intellisense\InterfaceCompletionItemPopup.cs" /> + <Compile Include="Intellisense\KnownType.cs" /> + <Compile Include="Document\ChangeTrackingCheckpoint.cs" /> + <Compile Include="Document\DocumentChangeOperation.cs"> + <DependentUpon>UndoStack.cs</DependentUpon> + </Compile> + <Compile Include="Document\ILineTracker.cs" /> + <Compile Include="Document\ISegment.cs" /> + <Compile Include="Document\ITextSource.cs" /> + <Compile Include="Document\IUndoableOperation.cs"> + <DependentUpon>UndoStack.cs</DependentUpon> + </Compile> + <Compile Include="Document\LineNode.cs"> + <DependentUpon>DocumentLine.cs</DependentUpon> + </Compile> + <Compile Include="Document\NewLineFinder.cs" /> + <Compile Include="Document\OffsetChangeMap.cs" /> + <Compile Include="Document\TextDocumentWeakEventManager.cs"> + <DependentUpon>TextDocument.cs</DependentUpon> + </Compile> + <Compile Include="Document\TextSegmentCollection.cs" /> + <Compile Include="Document\TextAnchor.cs" /> + <Compile Include="Document\TextAnchorNode.cs"> + <DependentUpon>TextAnchor.cs</DependentUpon> + </Compile> + <Compile Include="Document\TextAnchorTree.cs"> + <DependentUpon>TextAnchor.cs</DependentUpon> + </Compile> + <Compile Include="Document\TextLocation.cs" /> + <Compile Include="Document\TextSegment.cs" /> + <Compile Include="Document\TextUtilities.cs" /> + <Compile Include="Document\UndoOperationGroup.cs"> + <DependentUpon>UndoStack.cs</DependentUpon> + </Compile> + <Compile Include="Document\UndoStack.cs"> + </Compile> + <Compile Include="Document\WeakLineTracker.cs"> + <DependentUpon>ILineTracker.cs</DependentUpon> + </Compile> + <Compile Include="Editing\AbstractMargin.cs" /> + <Compile Include="Editing\Caret.cs" /> + <Compile Include="Editing\CaretLayer.cs"> + </Compile> + <Compile Include="Editing\CaretNavigationCommandHandler.cs"> + </Compile> + <Compile Include="Editing\CaretWeakEventHandler.cs" /> + <Compile Include="Editing\DottedLineMargin.cs" /> + <Compile Include="Editing\DragDropException.cs" /> + <Compile Include="Editing\EditingCommandHandler.cs" /> + <Compile Include="Editing\EmptySelection.cs"> + <DependentUpon>Selection.cs</DependentUpon> + </Compile> + <Compile Include="Editing\ImeNativeWrapper.cs" /> + <Compile Include="Editing\SelectionSegment.cs" /> + <Compile Include="Editing\ImeSupport.cs" /> + <Compile Include="Folding\AbstractFoldingStrategy.cs" /> + <Compile Include="Folding\BraceFoldingStrategy.cs" /> + <Compile Include="Folding\FoldingElementGenerator.cs" /> + <Compile Include="Folding\FoldingManager.cs" /> + <Compile Include="Folding\FoldingMargin.cs" /> + <Compile Include="Folding\FoldingMarginMarker.cs" /> + <Compile Include="Folding\FoldingSection.cs" /> + <Compile Include="Editing\IReadOnlySectionProvider.cs" /> + <Compile Include="Editing\LineNumberMargin.cs" /> + <Compile Include="Editing\NoReadOnlySections.cs"> + <DependentUpon>IReadOnlySectionProvider.cs</DependentUpon> + </Compile> + <Compile Include="Editing\RectangleSelection.cs"> + <DependentUpon>Selection.cs</DependentUpon> + </Compile> + <Compile Include="Editing\Selection.cs" /> + <Compile Include="Editing\SelectionColorizer.cs"> + <DependentUpon>Selection.cs</DependentUpon> + </Compile> + <Compile Include="Editing\SelectionLayer.cs"> + <DependentUpon>Selection.cs</DependentUpon> + </Compile> + <Compile Include="Editing\SelectionMouseHandler.cs"> + <DependentUpon>Selection.cs</DependentUpon> + </Compile> + <Compile Include="Editing\SimpleSelection.cs"> + <DependentUpon>Selection.cs</DependentUpon> + </Compile> + <Compile Include="Editing\TextArea.cs" /> + <Compile Include="Editing\TextAreaDefaultInputHandlers.cs" /> + <Compile Include="Editing\TextAreaInputHandler.cs" /> + <Compile Include="Editing\TextSegmentReadOnlySectionProvider.cs"> + <DependentUpon>IReadOnlySectionProvider.cs</DependentUpon> + </Compile> + <Compile Include="Folding\NewFolding.cs" /> + <Compile Include="Folding\XmlFoldingStrategy.cs" /> + <Compile Include="Highlighting\DocumentHighlighter.cs" /> + <Compile Include="Highlighting\HighlightedInlineBuilder.cs" /> + <Compile Include="Highlighting\HighlightedLine.cs" /> + <Compile Include="Highlighting\HighlightedSection.cs" /> + <Compile Include="Highlighting\HighlightingBrush.cs" /> + <Compile Include="Highlighting\HighlightingColor.cs" /> + <Compile Include="Highlighting\HighlightingColorizer.cs" /> + <Compile Include="Highlighting\HighlightingDefinitionInvalidException.cs" /> + <Compile Include="Highlighting\HighlightingDefinitionTypeConverter.cs" /> + <Compile Include="Highlighting\HighlightingManager.cs" /> + <Compile Include="Highlighting\HtmlClipboard.cs" /> + <Compile Include="Highlighting\IHighlighter.cs" /> + <Compile Include="Highlighting\IHighlightingDefinition.cs" /> + <Compile Include="Highlighting\HighlightingRule.cs" /> + <Compile Include="Highlighting\OffsetColorizer.cs" /> + <Compile Include="Highlighting\Resources\Resources.cs" /> + <Compile Include="Highlighting\HighlightingRuleSet.cs" /> + <Compile Include="Highlighting\HighlightingSpan.cs" /> + <Compile Include="Highlighting\IHighlightingDefinitionReferenceResolver.cs"> + </Compile> + <Compile Include="Highlighting\Xshd\HighlightingLoader.cs" /> + <Compile Include="Highlighting\Xshd\IXshdVisitor.cs" /> + <Compile Include="Highlighting\Xshd\SaveXshdVisitor.cs" /> + <Compile Include="Highlighting\Xshd\V1Loader.cs" /> + <Compile Include="Highlighting\Xshd\V2Loader.cs" /> + <Compile Include="Highlighting\Xshd\XmlHighlightingDefinition.cs" /> + <Compile Include="Highlighting\Xshd\XshdColor.cs" /> + <Compile Include="Highlighting\Xshd\XshdImport.cs" /> + <Compile Include="Highlighting\Xshd\XshdProperty.cs" /> + <Compile Include="Highlighting\Xshd\XshdReference.cs" /> + <Compile Include="Highlighting\Xshd\XshdElement.cs" /> + <Compile Include="Highlighting\Xshd\XshdKeywords.cs" /> + <Compile Include="Highlighting\Xshd\XshdRule.cs" /> + <Compile Include="Highlighting\Xshd\XshdRuleSet.cs" /> + <Compile Include="Highlighting\Xshd\XshdSpan.cs" /> + <Compile Include="Highlighting\Xshd\XshdSyntaxDefinition.cs" /> + <Compile Include="Indentation\CSharp\CSharpIndentationHelper.cs" /> + <Compile Include="Indentation\CSharp\IndentationReformatter.cs" /> + <Compile Include="Indentation\CSharp\CSharpIndentationStrategy.cs" /> + <Compile Include="Indentation\CSharp\DocumentAccessor.cs" /> + <Compile Include="Indentation\DefaultIndentationStrategy.cs" /> + <Compile Include="Indentation\IIndentationStrategy.cs" /> + <Compile Include="Intellisense\KnownTypeConstructor.cs" /> + <Compile Include="Intellisense\KnownTypeEvent.cs" /> + <Compile Include="Intellisense\KnownTypeField.cs" /> + <Compile Include="Intellisense\KnownTypeMember.cs" /> + <Compile Include="Intellisense\KnownTypeMethodParameter.cs" /> + <Compile Include="Intellisense\KnownTypeMethod.cs" /> + <Compile Include="Intellisense\KnownTypeProperty.cs" /> + <Compile Include="Intellisense\ClassCompletionItem.cs" /> + <Compile Include="Intellisense\MethodCompletionItem.cs" /> + <Compile Include="Intellisense\MethodCompletionItemPopup.cs" /> + <Compile Include="Intellisense\NamespaceCompletionItem.cs" /> + <Compile Include="Intellisense\NamespaceCompletionItemPopup.cs" /> + <Compile Include="Intellisense\PropertyCompletionItem.cs" /> + <Compile Include="Intellisense\PropertyCompletionItemPopup.cs" /> + <Compile Include="Intellisense\SnippetCompletionItem.cs" /> + <Compile Include="Intellisense\StructCompletionItem.cs" /> + <Compile Include="Intellisense\StructCompletionItemPopup.cs" /> + <Compile Include="Intellisense\Utils.cs" /> + <Compile Include="Popups\MethodDescription.cs" /> + <Compile Include="Popups\MethodPopup.cs" /> + <Compile Include="Popups\ParameterDescription.cs" /> + <Compile Include="Rendering\BackgroundGeometryBuilder.cs"> + <DependentUpon>IBackgroundRenderer.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\CollapsedLineSection.cs"> + <DependentUpon>HeightTree.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\ColorizingTransformer.cs"> + <DependentUpon>IVisualLineTransformer.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\ColumnRulerRenderer.cs" /> + <Compile Include="Rendering\DefaultTextRunTypographyProperties.cs" /> + <Compile Include="Rendering\DocumentColorizingTransformer.cs"> + <DependentUpon>IVisualLineTransformer.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\FormattedTextElement.cs" /> + <Compile Include="Rendering\GlobalTextRunProperties.cs"> + <DependentUpon>TextView.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\HeightTree.cs" /> + <Compile Include="Rendering\HeightTreeLineNode.cs"> + <DependentUpon>HeightTree.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\HeightTreeNode.cs"> + <DependentUpon>HeightTree.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\IBackgroundRenderer.cs" /> + <Compile Include="Rendering\InlineObjectRun.cs" /> + <Compile Include="Rendering\ITextRunConstructionContext.cs"> + <DependentUpon>VisualLineElementGenerator.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\ITextViewConnect.cs"> + <DependentUpon>TextView.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\IVisualLineTransformer.cs" /> + <Compile Include="Rendering\Layer.cs"> + <DependentUpon>TextView.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\LayerPosition.cs"> + <DependentUpon>TextView.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\LinkElementGenerator.cs" /> + <Compile Include="Rendering\MouseHoverLogic.cs" /> + <Compile Include="Rendering\SimpleTextSource.cs"> + <DependentUpon>FormattedTextElement.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\SingleCharacterElementGenerator.cs" /> + <Compile Include="Rendering\TextLayer.cs"> + <DependentUpon>TextView.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\TextView.cs" /> + <Compile Include="Rendering\TextViewCachedElements.cs" /> + <Compile Include="Rendering\TextViewWeakEventManager.cs"> + <DependentUpon>TextView.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\VisualLine.cs" /> + <Compile Include="Rendering\VisualLineConstructionStartEventArgs.cs" /> + <Compile Include="Rendering\VisualLineElement.cs" /> + <Compile Include="Rendering\VisualLineElementGenerator.cs" /> + <Compile Include="Rendering\VisualLineElementTextRunProperties.cs"> + <DependentUpon>VisualLine.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\VisualLineLinkText.cs" /> + <Compile Include="Rendering\VisualLinesInvalidException.cs" /> + <Compile Include="Rendering\VisualLineText.cs" /> + <Compile Include="Rendering\VisualLineTextParagraphProperties.cs"> + <DependentUpon>VisualLine.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\VisualLineTextSource.cs"> + <DependentUpon>VisualLineElementGenerator.cs</DependentUpon> + </Compile> + <Compile Include="Rendering\VisualYPosition.cs"> + <DependentUpon>VisualLine.cs</DependentUpon> + </Compile> + <Compile Include="ScriptEditor.cs" /> + <Compile Include="Search\Localization.cs" /> + <Compile Include="Search\RegexSearchStrategy.cs" /> + <Compile Include="Search\DropDownButton.cs" /> + <Compile Include="Search\ISearchStrategy.cs" /> + <Compile Include="Search\SearchCommands.cs" /> + <Compile Include="Search\SearchResultBackgroundRenderer.cs" /> + <Compile Include="Search\SearchPanel.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="Search\SearchStrategyFactory.cs" /> + <Compile Include="Snippets\IActiveElement.cs" /> + <Compile Include="Snippets\SnippetAnchorElement.cs" /> + <Compile Include="Snippets\SnippetEventArgs.cs" /> + <Compile Include="Snippets\SnippetInputHandler.cs" /> + <Compile Include="Snippets\Snippet.cs" /> + <Compile Include="Snippets\SnippetBoundElement.cs" /> + <Compile Include="Snippets\SnippetCaretElement.cs" /> + <Compile Include="Snippets\SnippetContainerElement.cs" /> + <Compile Include="Snippets\SnippetElement.cs" /> + <Compile Include="Snippets\InsertionContext.cs" /> + <Compile Include="Snippets\SnippetReplaceableTextElement.cs" /> + <Compile Include="Snippets\SnippetSelectionElement.cs" /> + <Compile Include="Snippets\SnippetTextElement.cs" /> + <Compile Include="TextEditor.cs" /> + <Compile Include="TextEditorAutomationPeer.cs" /> + <Compile Include="TextEditorComponent.cs"> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Document\DocumentChangeEventArgs.cs" /> + <Compile Include="Document\GapTextBuffer.cs"> + <DependentUpon>TextDocument.cs</DependentUpon> + </Compile> + <Compile Include="Document\LineManager.cs"> + <DependentUpon>TextDocument.cs</DependentUpon> + </Compile> + <Compile Include="Document\DocumentLine.cs" /> + <Compile Include="Document\DocumentLineTree.cs"> + <DependentUpon>DocumentLine.cs</DependentUpon> + </Compile> + <Compile Include="Document\TextDocument.cs" /> + <Compile Include="TextEditorOptions.cs" /> + <Compile Include="TextEditorWeakEventManager.cs"> + <DependentUpon>TextEditor.cs</DependentUpon> + </Compile> + <Compile Include="TextViewPosition.cs" /> + <Compile Include="Utils\Boxes.cs" /> + <Compile Include="Utils\BusyManager.cs"> + <DependentUpon>ObserveAddRemoveCollection.cs</DependentUpon> + </Compile> + <Compile Include="Utils\CharRope.cs" /> + <Compile Include="Utils\CompressingTreeList.cs" /> + <Compile Include="Utils\Constants.cs" /> + <Compile Include="Utils\DelayedEvents.cs" /> + <Compile Include="Utils\CallbackOnDispose.cs" /> + <Compile Include="Utils\Deque.cs" /> + <Compile Include="Utils\Empty.cs" /> + <Compile Include="Utils\ExtensionMethods.cs" /> + <Compile Include="Utils\FileReader.cs" /> + <Compile Include="Utils\ImmutableStack.cs" /> + <Compile Include="Utils\NullSafeCollection.cs" /> + <Compile Include="Utils\ObserveAddRemoveCollection.cs" /> + <Compile Include="Utils\PropertyChangedWeakEventManager.cs" /> + <Compile Include="Utils\Rope.cs" /> + <Compile Include="Utils\RopeNode.cs" /> + <Compile Include="Utils\RopeTextReader.cs" /> + <Compile Include="Utils\StringSegment.cs" /> + <Compile Include="Utils\TextFormatterFactory.cs" /> + <Compile Include="Utils\WeakEventManagerBase.cs" /> + <Compile Include="Utils\PixelSnapHelpers.cs" /> + <Compile Include="Utils\ThrowUtil.cs" /> + <Compile Include="Utils\Win32.cs" /> + <CodeAnalysisDictionary Include="Properties\CodeAnalysisDictionary.xml" /> + <Compile Include="XamlEditor.cs" /> + <Compile Include="Xml\AbstractAXmlVisitor.cs" /> + <Compile Include="Xml\AXmlAttribute.cs" /> + <Compile Include="Xml\AXmlAttributeCollection.cs" /> + <Compile Include="Xml\AXmlContainer.cs" /> + <Compile Include="Xml\AXmlDocument.cs" /> + <Compile Include="Xml\AXmlElement.cs" /> + <Compile Include="Xml\AXmlObject.cs" /> + <Compile Include="Xml\AXmlObjectCollection.cs" /> + <Compile Include="Xml\AXmlObjectEventArgs.cs" /> + <Compile Include="Xml\AXmlParser.cs" /> + <Compile Include="Xml\AXmlTag.cs" /> + <Compile Include="Xml\AXmlText.cs" /> + <Compile Include="Xml\CanonicalPrintAXmlVisitor.cs" /> + <Compile Include="Xml\InternalException.cs" /> + <Compile Include="Xml\TrackedSegmentCollection.cs"> + <DependentUpon>AXmlParser.cs</DependentUpon> + </Compile> + <Compile Include="Xml\ExtensionMethods.cs" /> + <Compile Include="Xml\FilteredCollection.cs" /> + <Compile Include="Xml\IAXmlVisitor.cs" /> + <Compile Include="Xml\MergedCollection.cs" /> + <Compile Include="Xml\PrettyPrintAXmlVisitor.cs" /> + <Compile Include="Xml\SyntaxError.cs" /> + <Compile Include="Xml\TagMatchingHeuristics.cs"> + <DependentUpon>AXmlParser.cs</DependentUpon> + </Compile> + <Compile Include="Xml\TagReader.cs"> + <DependentUpon>AXmlParser.cs</DependentUpon> + </Compile> + <Compile Include="Xml\TextType.cs"> + <DependentUpon>AXmlText.cs</DependentUpon> + </Compile> + <Compile Include="Xml\TokenReader.cs"> + <DependentUpon>AXmlParser.cs</DependentUpon> + </Compile> + <EmbeddedResource Include="Highlighting\Resources\ASPX.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\Boo.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\Coco-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\CPP-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\HTML-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\Java-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\JavaScript-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\Patch-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\PHP-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\Tex-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\VBNET-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\XML-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\ModeV1.xsd" /> + <EmbeddedResource Include="Highlighting\Resources\ModeV2.xsd" /> + <EmbeddedResource Include="Highlighting\Resources\CSharp-Mode.xshd" /> + <EmbeddedResource Include="Highlighting\Resources\XmlDoc.xshd" /> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Highlighting\Resources\CSS-Mode.xshd" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.Scripting.Core\Tango.Scripting.Core.csproj"> + <Project>{5812E1C6-ABAA-4066-94AC-971C27B4F46A}</Project> + <Name>Tango.Scripting.Core</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.Scripting.Formatting\Tango.Scripting.Formatting.csproj"> + <Project>{8d8f06ed-7f75-4933-b0c5-829b0ff654d0}</Project> + <Name>Tango.Scripting.Formatting</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.Scripting\Tango.Scripting.csproj"> + <Project>{1e938fd2-c669-4738-98c9-77f96ce4d451}</Project> + <Name>Tango.Scripting</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Highlighting\Resources\PowerShell.xshd" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Highlighting\Resources\MarkDown-Mode.xshd" /> + </ItemGroup> + <ItemGroup> + <None Include="app.config" /> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + <Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" /> + <Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" /> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <ProjectExtensions> + <VisualStudio> + <UserProperties BuildVersion_UseGlobalSettings="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_StartDate="2000/1/1" /> + </VisualStudio> + </ProjectExtensions> + <ItemGroup> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\Microsoft.CodeAnalysis.CSharp.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\Microsoft.CodeAnalysis.Common.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\PresentationCore.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\PresentationFramework.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.ComponentModel.Composition.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Console.4.3.0\lib\net46\System.Console.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Core.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Data.DataSetExtensions.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Data.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Drawing.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Numerics.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Windows.Forms.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Xaml.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Xml.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Xml.Linq.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\Build\Core\Debug\Tango.Core.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\Scripting\Tango.Scripting.Core\bin\Debug\Tango.Scripting.Core.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\Build\Scripting\Debug\Tango.Scripting.dll" /> + <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\Scripting\Tango.Scripting.Formatting\bin\Debug\Tango.Scripting.Formatting.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\UIAutomationProvider.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\UIAutomationTypes.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\WindowsBase.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Collections.Concurrent.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Collections.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ComponentModel.Annotations.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ComponentModel.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ComponentModel.EventBasedAsync.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Diagnostics.Contracts.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Diagnostics.Debug.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Diagnostics.Tools.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Diagnostics.Tracing.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Dynamic.Runtime.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Globalization.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.IO.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Linq.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Linq.Expressions.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Linq.Parallel.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Linq.Queryable.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Net.NetworkInformation.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Net.Primitives.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Net.Requests.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Net.WebHeaderCollection.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ObjectModel.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Emit.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Emit.ILGeneration.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Emit.Lightweight.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Extensions.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Primitives.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Resources.ResourceManager.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Extensions.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Handles.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.InteropServices.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.InteropServices.WindowsRuntime.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Numerics.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Serialization.Json.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Serialization.Primitives.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Serialization.Xml.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Security.Principal.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.Duplex.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.Http.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.NetTcp.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.Primitives.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.Security.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Text.Encoding.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Text.Encoding.Extensions.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Text.RegularExpressions.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Threading.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Threading.Tasks.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Threading.Tasks.Parallel.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Threading.Timer.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Xml.XDocument.dll" /> + <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Xml.XmlSerializer.dll" /> + </ItemGroup> + <ItemGroup> + <Compile Include="C:\DATA\Development\Tango\Software\Visual_Studio\Scripting\Tango.Scripting.Editors\obj\Debug\GeneratedInternalTypeHelper.g.cs" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs index d2fc9e02b..cd9977520 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs @@ -3,6 +3,7 @@ using System; using System.ComponentModel; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; @@ -24,1121 +25,1229 @@ using Tango.Scripting.Editors.Utils; namespace Tango.Scripting.Editors { - /// <summary> - /// The text editor control. - /// Contains a scrollable TextArea. - /// </summary> - [Localizability(LocalizationCategory.Text), ContentProperty("Text")] - public class TextEditor : Control, ITextEditorComponent, IServiceProvider, IWeakEventListener - { - #region Constructors - static TextEditor() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(TextEditor), - new FrameworkPropertyMetadata(typeof(TextEditor))); - FocusableProperty.OverrideMetadata(typeof(TextEditor), - new FrameworkPropertyMetadata(Boxes.True)); - } - - /// <summary> - /// Creates a new TextEditor instance. - /// </summary> - public TextEditor() : this(new TextArea()) - { - } - - /// <summary> - /// Creates a new TextEditor instance. - /// </summary> - protected TextEditor(TextArea textArea) - { - if (textArea == null) - throw new ArgumentNullException("textArea"); - this.textArea = textArea; - - textArea.TextView.Services.AddService(typeof(TextEditor), this); - - SetCurrentValue(OptionsProperty, textArea.Options); - SetCurrentValue(DocumentProperty, new TextDocument()); - } - - #endregion - - /// <inheritdoc/> - protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() - { - return new TextEditorAutomationPeer(this); - } - - /// Forward focus to TextArea. - /// <inheritdoc/> - protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) - { - base.OnGotKeyboardFocus(e); - if (e.NewFocus == this) { - Keyboard.Focus(this.TextArea); - e.Handled = true; - } - } - - #region Document property - /// <summary> - /// Document property. - /// </summary> - public static readonly DependencyProperty DocumentProperty - = TextView.DocumentProperty.AddOwner( - typeof(TextEditor), new FrameworkPropertyMetadata(OnDocumentChanged)); - - /// <summary> - /// Gets/Sets the document displayed by the text editor. - /// This is a dependency property. - /// </summary> - public TextDocument Document { - get { return (TextDocument)GetValue(DocumentProperty); } - set { SetValue(DocumentProperty, value); } - } - - /// <summary> - /// Occurs when the document property has changed. - /// </summary> - public event EventHandler DocumentChanged; - - /// <summary> - /// Raises the <see cref="DocumentChanged"/> event. - /// </summary> - protected virtual void OnDocumentChanged(EventArgs e) - { - if (DocumentChanged != null) { - DocumentChanged(this, e); - } - } - - static void OnDocumentChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e) - { - ((TextEditor)dp).OnDocumentChanged((TextDocument)e.OldValue, (TextDocument)e.NewValue); - } - - void OnDocumentChanged(TextDocument oldValue, TextDocument newValue) - { - if (oldValue != null) { - TextDocumentWeakEventManager.TextChanged.RemoveListener(oldValue, this); - PropertyChangedEventManager.RemoveListener(oldValue.UndoStack, this, "IsOriginalFile"); - } - textArea.Document = newValue; - if (newValue != null) { - TextDocumentWeakEventManager.TextChanged.AddListener(newValue, this); - PropertyChangedEventManager.AddListener(newValue.UndoStack, this, "IsOriginalFile"); - } - OnDocumentChanged(EventArgs.Empty); - OnTextChanged(EventArgs.Empty); - } - #endregion - - #region Options property - /// <summary> - /// Options property. - /// </summary> - public static readonly DependencyProperty OptionsProperty - = TextView.OptionsProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(OnOptionsChanged)); - - /// <summary> - /// Gets/Sets the options currently used by the text editor. - /// </summary> - public TextEditorOptions Options { - get { return (TextEditorOptions)GetValue(OptionsProperty); } - set { SetValue(OptionsProperty, value); } - } - - /// <summary> - /// Occurs when a text editor option has changed. - /// </summary> - public event PropertyChangedEventHandler OptionChanged; - - /// <summary> - /// Raises the <see cref="OptionChanged"/> event. - /// </summary> - protected virtual void OnOptionChanged(PropertyChangedEventArgs e) - { - if (OptionChanged != null) { - OptionChanged(this, e); - } - } - - static void OnOptionsChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e) - { - ((TextEditor)dp).OnOptionsChanged((TextEditorOptions)e.OldValue, (TextEditorOptions)e.NewValue); - } - - void OnOptionsChanged(TextEditorOptions oldValue, TextEditorOptions newValue) - { - if (oldValue != null) { - PropertyChangedWeakEventManager.RemoveListener(oldValue, this); - } - textArea.Options = newValue; - if (newValue != null) { - PropertyChangedWeakEventManager.AddListener(newValue, this); - } - OnOptionChanged(new PropertyChangedEventArgs(null)); - } - - /// <inheritdoc cref="IWeakEventListener.ReceiveWeakEvent"/> - protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) - { - if (managerType == typeof(PropertyChangedWeakEventManager)) { - OnOptionChanged((PropertyChangedEventArgs)e); - return true; - } else if (managerType == typeof(TextDocumentWeakEventManager.TextChanged)) { - OnTextChanged(e); - return true; - } else if (managerType == typeof(PropertyChangedEventManager)) { - return HandleIsOriginalChanged((PropertyChangedEventArgs)e); - } - return false; - } - - bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) - { - return ReceiveWeakEvent(managerType, sender, e); - } - #endregion - - #region Text property - /// <summary> - /// Gets/Sets the text of the current document. - /// </summary> - [Localizability(LocalizationCategory.Text), DefaultValue("")] - public string Text { - get { - TextDocument document = this.Document; - return document != null ? document.Text : string.Empty; - } - set { - TextDocument document = GetDocument(); - document.Text = value ?? string.Empty; - // after replacing the full text, the caret is positioned at the end of the document - // - reset it to the beginning. - this.CaretOffset = 0; - document.UndoStack.ClearAll(); - } - } - - TextDocument GetDocument() - { - TextDocument document = this.Document; - if (document == null) - throw ThrowUtil.NoDocumentAssigned(); - return document; - } - - /// <summary> - /// Occurs when the Text property changes. - /// </summary> - public event EventHandler TextChanged; - - /// <summary> - /// Raises the <see cref="TextChanged"/> event. - /// </summary> - protected virtual void OnTextChanged(EventArgs e) - { - if (TextChanged != null) { - TextChanged(this, e); - } - } - #endregion - - #region TextArea / ScrollViewer properties - readonly TextArea textArea; - ScrollViewer scrollViewer; - - /// <summary> - /// Is called after the template was applied. - /// </summary> - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - scrollViewer = (ScrollViewer)Template.FindName("PART_ScrollViewer", this); - } - - /// <summary> - /// Gets the text area. - /// </summary> - public TextArea TextArea { - get { - return textArea; - } - } - - /// <summary> - /// Gets the scroll viewer used by the text editor. - /// This property can return null if the template has not been applied / does not contain a scroll viewer. - /// </summary> - internal ScrollViewer ScrollViewer { - get { return scrollViewer; } - } - - bool CanExecute(RoutedUICommand command) - { - TextArea textArea = this.TextArea; - if (textArea == null) - return false; - else - return command.CanExecute(null, textArea); - } - - void Execute(RoutedUICommand command) - { - TextArea textArea = this.TextArea; - if (textArea != null) - command.Execute(null, textArea); - } - #endregion - - #region Syntax highlighting - /// <summary> - /// The <see cref="SyntaxHighlighting"/> property. - /// </summary> - public static readonly DependencyProperty SyntaxHighlightingProperty = - DependencyProperty.Register("SyntaxHighlighting", typeof(IHighlightingDefinition), typeof(TextEditor), - new FrameworkPropertyMetadata(OnSyntaxHighlightingChanged)); - - - /// <summary> - /// Gets/sets the syntax highlighting definition used to colorize the text. - /// </summary> - public IHighlightingDefinition SyntaxHighlighting { - get { return (IHighlightingDefinition)GetValue(SyntaxHighlightingProperty); } - set { SetValue(SyntaxHighlightingProperty, value); } - } - - IVisualLineTransformer colorizer; - - static void OnSyntaxHighlightingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((TextEditor)d).OnSyntaxHighlightingChanged(e.NewValue as IHighlightingDefinition); - } - - void OnSyntaxHighlightingChanged(IHighlightingDefinition newValue) - { - if (colorizer != null) { - this.TextArea.TextView.LineTransformers.Remove(colorizer); - colorizer = null; - } - if (newValue != null) { - colorizer = CreateColorizer(newValue); - this.TextArea.TextView.LineTransformers.Insert(0, colorizer); - } - } - - /// <summary> - /// Creates the highlighting colorizer for the specified highlighting definition. - /// Allows derived classes to provide custom colorizer implementations for special highlighting definitions. - /// </summary> - /// <returns></returns> - protected virtual IVisualLineTransformer CreateColorizer(IHighlightingDefinition highlightingDefinition) - { - if (highlightingDefinition == null) - throw new ArgumentNullException("highlightingDefinition"); - return new HighlightingColorizer(highlightingDefinition.MainRuleSet); - } - #endregion - - #region WordWrap - /// <summary> - /// Word wrap dependency property. - /// </summary> - public static readonly DependencyProperty WordWrapProperty = - DependencyProperty.Register("WordWrap", typeof(bool), typeof(TextEditor), - new FrameworkPropertyMetadata(Boxes.False)); - - /// <summary> - /// Specifies whether the text editor uses word wrapping. - /// </summary> - /// <remarks> - /// Setting WordWrap=true has the same effect as setting HorizontalScrollBarVisibility=Disabled and will override the - /// HorizontalScrollBarVisibility setting. - /// </remarks> - public bool WordWrap { - get { return (bool)GetValue(WordWrapProperty); } - set { SetValue(WordWrapProperty, Boxes.Box(value)); } - } - #endregion - - #region IsReadOnly - /// <summary> - /// IsReadOnly dependency property. - /// </summary> - public static readonly DependencyProperty IsReadOnlyProperty = - DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(TextEditor), - new FrameworkPropertyMetadata(Boxes.False, OnIsReadOnlyChanged)); - - /// <summary> - /// Specifies whether the user can change the text editor content. - /// Setting this property will replace the - /// <see cref="Editing.TextArea.ReadOnlySectionProvider">TextArea.ReadOnlySectionProvider</see>. - /// </summary> - public bool IsReadOnly { - get { return (bool)GetValue(IsReadOnlyProperty); } - set { SetValue(IsReadOnlyProperty, Boxes.Box(value)); } - } - - static void OnIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TextEditor editor = d as TextEditor; - if (editor != null) { - if ((bool)e.NewValue) - editor.TextArea.ReadOnlySectionProvider = ReadOnlyDocument.Instance; - else - editor.TextArea.ReadOnlySectionProvider = NoReadOnlySections.Instance; - - TextEditorAutomationPeer peer = TextEditorAutomationPeer.FromElement(editor) as TextEditorAutomationPeer; - if (peer != null) { - peer.RaiseIsReadOnlyChanged((bool)e.OldValue, (bool)e.NewValue); - } - } - } - #endregion - - #region IsModified - /// <summary> - /// Dependency property for <see cref="IsModified"/> - /// </summary> - public static readonly DependencyProperty IsModifiedProperty = - DependencyProperty.Register("IsModified", typeof(bool), typeof(TextEditor), - new FrameworkPropertyMetadata(Boxes.False, OnIsModifiedChanged)); - - /// <summary> - /// Gets/Sets the 'modified' flag. - /// </summary> - public bool IsModified { - get { return (bool)GetValue(IsModifiedProperty); } - set { SetValue(IsModifiedProperty, Boxes.Box(value)); } - } - - static void OnIsModifiedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TextEditor editor = d as TextEditor; - if (editor != null) { - TextDocument document = editor.Document; - if (document != null) { - UndoStack undoStack = document.UndoStack; - if ((bool)e.NewValue) { - if (undoStack.IsOriginalFile) - undoStack.DiscardOriginalFileMarker(); - } else { - undoStack.MarkAsOriginalFile(); - } - } - } - } - - bool HandleIsOriginalChanged(PropertyChangedEventArgs e) - { - if (e.PropertyName == "IsOriginalFile") { - TextDocument document = this.Document; - if (document != null) { - SetCurrentValue(IsModifiedProperty, Boxes.Box(!document.UndoStack.IsOriginalFile)); - } - return true; - } else { - return false; - } - } - #endregion - - #region ShowLineNumbers - /// <summary> - /// ShowLineNumbers dependency property. - /// </summary> - public static readonly DependencyProperty ShowLineNumbersProperty = - DependencyProperty.Register("ShowLineNumbers", typeof(bool), typeof(TextEditor), - new FrameworkPropertyMetadata(Boxes.False, OnShowLineNumbersChanged)); - - /// <summary> - /// Specifies whether line numbers are shown on the left to the text view. - /// </summary> - public bool ShowLineNumbers { - get { return (bool)GetValue(ShowLineNumbersProperty); } - set { SetValue(ShowLineNumbersProperty, Boxes.Box(value)); } - } - - static void OnShowLineNumbersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TextEditor editor = (TextEditor)d; - var leftMargins = editor.TextArea.LeftMargins; - if ((bool)e.NewValue) { - LineNumberMargin lineNumbers = new LineNumberMargin(); - Line line = (Line)DottedLineMargin.Create(); - leftMargins.Insert(0, lineNumbers); - leftMargins.Insert(1, line); - var lineNumbersForeground = new Binding("LineNumbersForeground") { Source = editor }; - line.SetBinding(Line.StrokeProperty, lineNumbersForeground); - lineNumbers.SetBinding(Control.ForegroundProperty, lineNumbersForeground); - } else { - for (int i = 0; i < leftMargins.Count; i++) { - if (leftMargins[i] is LineNumberMargin) { - leftMargins.RemoveAt(i); - if (i < leftMargins.Count && DottedLineMargin.IsDottedLineMargin(leftMargins[i])) { - leftMargins.RemoveAt(i); - } - break; - } - } - } - } - #endregion - - #region LineNumbersForeground - /// <summary> - /// LineNumbersForeground dependency property. - /// </summary> - public static readonly DependencyProperty LineNumbersForegroundProperty = - DependencyProperty.Register("LineNumbersForeground", typeof(Brush), typeof(TextEditor), - new FrameworkPropertyMetadata(Brushes.Gray, OnLineNumbersForegroundChanged)); - - /// <summary> - /// Gets/sets the Brush used for displaying the foreground color of line numbers. - /// </summary> - public Brush LineNumbersForeground { - get { return (Brush)GetValue(LineNumbersForegroundProperty); } - set { SetValue(LineNumbersForegroundProperty, value); } - } - - static void OnLineNumbersForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - TextEditor editor = (TextEditor)d; - var lineNumberMargin = editor.TextArea.LeftMargins.FirstOrDefault(margin => margin is LineNumberMargin) as LineNumberMargin;; - - if (lineNumberMargin != null) { - lineNumberMargin.SetValue(Control.ForegroundProperty, e.NewValue); - } - } - #endregion - - #region TextBoxBase-like methods - /// <summary> - /// Appends text to the end of the document. - /// </summary> - public void AppendText(string textData) - { - var document = GetDocument(); - document.Insert(document.TextLength, textData); - } - - /// <summary> - /// Begins a group of document changes. - /// </summary> - public void BeginChange() - { - GetDocument().BeginUpdate(); - } - - /// <summary> - /// Copies the current selection to the clipboard. - /// </summary> - public void Copy() - { - Execute(ApplicationCommands.Copy); - } - - /// <summary> - /// Removes the current selection and copies it to the clipboard. - /// </summary> - public void Cut() - { - Execute(ApplicationCommands.Cut); - } - - /// <summary> - /// Begins a group of document changes and returns an object that ends the group of document - /// changes when it is disposed. - /// </summary> - public IDisposable DeclareChangeBlock() - { - return GetDocument().RunUpdate(); - } - - /// <summary> - /// Ends the current group of document changes. - /// </summary> - public void EndChange() - { - GetDocument().EndUpdate(); - } - - /// <summary> - /// Scrolls one line down. - /// </summary> - public void LineDown() - { - if (scrollViewer != null) - scrollViewer.LineDown(); - } - - /// <summary> - /// Scrolls to the left. - /// </summary> - public void LineLeft() - { - if (scrollViewer != null) - scrollViewer.LineLeft(); - } - - /// <summary> - /// Scrolls to the right. - /// </summary> - public void LineRight() - { - if (scrollViewer != null) - scrollViewer.LineRight(); - } - - /// <summary> - /// Scrolls one line up. - /// </summary> - public void LineUp() - { - if (scrollViewer != null) - scrollViewer.LineUp(); - } - - /// <summary> - /// Scrolls one page down. - /// </summary> - public void PageDown() - { - if (scrollViewer != null) - scrollViewer.PageDown(); - } - - /// <summary> - /// Scrolls one page up. - /// </summary> - public void PageUp() - { - if (scrollViewer != null) - scrollViewer.PageUp(); - } - - /// <summary> - /// Scrolls one page left. - /// </summary> - public void PageLeft() - { - if (scrollViewer != null) - scrollViewer.PageLeft(); - } - - /// <summary> - /// Scrolls one page right. - /// </summary> - public void PageRight() - { - if (scrollViewer != null) - scrollViewer.PageRight(); - } - - /// <summary> - /// Pastes the clipboard content. - /// </summary> - public void Paste() - { - Execute(ApplicationCommands.Paste); - } - - /// <summary> - /// Redoes the most recent undone command. - /// </summary> - /// <returns>True is the redo operation was successful, false is the redo stack is empty.</returns> - public bool Redo() - { - if (CanExecute(ApplicationCommands.Redo)) { - Execute(ApplicationCommands.Redo); - return true; - } - return false; - } - - /// <summary> - /// Scrolls to the end of the document. - /// </summary> - public void ScrollToEnd() - { - ApplyTemplate(); // ensure scrollViewer is created - if (scrollViewer != null) - scrollViewer.ScrollToEnd(); - } - - /// <summary> - /// Scrolls to the start of the document. - /// </summary> - public void ScrollToHome() - { - ApplyTemplate(); // ensure scrollViewer is created - if (scrollViewer != null) - scrollViewer.ScrollToHome(); - } - - /// <summary> - /// Scrolls to the specified position in the document. - /// </summary> - public void ScrollToHorizontalOffset(double offset) - { - ApplyTemplate(); // ensure scrollViewer is created - if (scrollViewer != null) - scrollViewer.ScrollToHorizontalOffset(offset); - } - - /// <summary> - /// Scrolls to the specified position in the document. - /// </summary> - public void ScrollToVerticalOffset(double offset) - { - ApplyTemplate(); // ensure scrollViewer is created - if (scrollViewer != null) - scrollViewer.ScrollToVerticalOffset(offset); - } - - /// <summary> - /// Selects the entire text. - /// </summary> - public void SelectAll() - { - Execute(ApplicationCommands.SelectAll); - } - - /// <summary> - /// Undoes the most recent command. - /// </summary> - /// <returns>True is the undo operation was successful, false is the undo stack is empty.</returns> - public bool Undo() - { - if (CanExecute(ApplicationCommands.Undo)) { - Execute(ApplicationCommands.Undo); - return true; - } - return false; - } - - /// <summary> - /// Gets if the most recent undone command can be redone. - /// </summary> - public bool CanRedo { - get { return CanExecute(ApplicationCommands.Redo); } - } - - /// <summary> - /// Gets if the most recent command can be undone. - /// </summary> - public bool CanUndo { - get { return CanExecute(ApplicationCommands.Undo); } - } - - /// <summary> - /// Gets the vertical size of the document. - /// </summary> - public double ExtentHeight { - get { - return scrollViewer != null ? scrollViewer.ExtentHeight : 0; - } - } - - /// <summary> - /// Gets the horizontal size of the current document region. - /// </summary> - public double ExtentWidth { - get { - return scrollViewer != null ? scrollViewer.ExtentWidth : 0; - } - } - - /// <summary> - /// Gets the horizontal size of the viewport. - /// </summary> - public double ViewportHeight { - get { - return scrollViewer != null ? scrollViewer.ViewportHeight : 0; - } - } - - /// <summary> - /// Gets the horizontal size of the viewport. - /// </summary> - public double ViewportWidth { - get { - return scrollViewer != null ? scrollViewer.ViewportWidth : 0; - } - } - - /// <summary> - /// Gets the vertical scroll position. - /// </summary> - public double VerticalOffset { - get { - return scrollViewer != null ? scrollViewer.VerticalOffset : 0; - } - } - - /// <summary> - /// Gets the horizontal scroll position. - /// </summary> - public double HorizontalOffset { - get { - return scrollViewer != null ? scrollViewer.HorizontalOffset : 0; - } - } - #endregion - - #region TextBox methods - /// <summary> - /// Gets/Sets the selected text. - /// </summary> - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public string SelectedText { - get { - TextArea textArea = this.TextArea; - // We'll get the text from the whole surrounding segment. - // This is done to ensure that SelectedText.Length == SelectionLength. - if (textArea != null && textArea.Document != null && !textArea.Selection.IsEmpty) - return textArea.Document.GetText(textArea.Selection.SurroundingSegment); - else - return string.Empty; - } - set { - if (value == null) - throw new ArgumentNullException("value"); - TextArea textArea = this.TextArea; - if (textArea != null && textArea.Document != null) { - int offset = this.SelectionStart; - int length = this.SelectionLength; - textArea.Document.Replace(offset, length, value); - // keep inserted text selected - textArea.Selection = SimpleSelection.Create(textArea, offset, offset + value.Length); - } - } - } - - /// <summary> - /// Gets/sets the caret position. - /// </summary> - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int CaretOffset { - get { - TextArea textArea = this.TextArea; - if (textArea != null) - return textArea.Caret.Offset; - else - return 0; - } - set { - TextArea textArea = this.TextArea; - if (textArea != null) - textArea.Caret.Offset = value; - } - } - - /// <summary> - /// Gets/sets the start position of the selection. - /// </summary> - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int SelectionStart { - get { - TextArea textArea = this.TextArea; - if (textArea != null) { - if (textArea.Selection.IsEmpty) - return textArea.Caret.Offset; - else - return textArea.Selection.SurroundingSegment.Offset; - } else { - return 0; - } - } - set { - Select(value, SelectionLength); - } - } - - /// <summary> - /// Gets/sets the length of the selection. - /// </summary> - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int SelectionLength { - get { - TextArea textArea = this.TextArea; - if (textArea != null && !textArea.Selection.IsEmpty) - return textArea.Selection.SurroundingSegment.Length; - else - return 0; - } - set { - Select(SelectionStart, value); - } - } - - /// <summary> - /// Selects the specified text section. - /// </summary> - public void Select(int start, int length) - { - int documentLength = Document != null ? Document.TextLength : 0; - if (start < 0 || start > documentLength) - throw new ArgumentOutOfRangeException("start", start, "Value must be between 0 and " + documentLength); - if (length < 0 || start + length > documentLength) - throw new ArgumentOutOfRangeException("length", length, "Value must be between 0 and " + (documentLength - length)); - textArea.Selection = SimpleSelection.Create(textArea, start, start + length); - textArea.Caret.Offset = start + length; - } - - /// <summary> - /// Gets the number of lines in the document. - /// </summary> - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public int LineCount { - get { - TextDocument document = this.Document; - if (document != null) - return document.LineCount; - else - return 1; - } - } - - /// <summary> - /// Clears the text. - /// </summary> - public void Clear() - { - this.Text = string.Empty; - } - #endregion - - #region Loading from stream - /// <summary> - /// Loads the text from the stream, auto-detecting the encoding. - /// </summary> - /// <remarks> - /// This method sets <see cref="IsModified"/> to false. - /// </remarks> - public void Load(Stream stream) - { - using (StreamReader reader = FileReader.OpenStream(stream, this.Encoding ?? Encoding.UTF8)) { - this.Text = reader.ReadToEnd(); - this.Encoding = reader.CurrentEncoding; // assign encoding after ReadToEnd() so that the StreamReader can autodetect the encoding - } - this.IsModified = false; - } - - /// <summary> - /// Loads the text from the stream, auto-detecting the encoding. - /// </summary> - public void Load(string fileName) - { - if (fileName == null) - throw new ArgumentNullException("fileName"); - using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { - Load(fs); - } - } - - /// <summary> - /// Gets/sets the encoding used when the file is saved. - /// </summary> - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public Encoding Encoding { get; set; } - - /// <summary> - /// Saves the text to the stream. - /// </summary> - /// <remarks> - /// This method sets <see cref="IsModified"/> to false. - /// </remarks> - public void Save(Stream stream) - { - if (stream == null) - throw new ArgumentNullException("stream"); - StreamWriter writer = new StreamWriter(stream, this.Encoding ?? Encoding.UTF8); - writer.Write(this.Text); - writer.Flush(); - // do not close the stream - this.IsModified = false; - } - - /// <summary> - /// Saves the text to the file. - /// </summary> - public void Save(string fileName) - { - if (fileName == null) - throw new ArgumentNullException("fileName"); - using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { - Save(fs); - } - } - #endregion - - #region MouseHover events - /// <summary> - /// The PreviewMouseHover event. - /// </summary> - public static readonly RoutedEvent PreviewMouseHoverEvent = - TextView.PreviewMouseHoverEvent.AddOwner(typeof(TextEditor)); - - /// <summary> - /// The MouseHover event. - /// </summary> - public static readonly RoutedEvent MouseHoverEvent = - TextView.MouseHoverEvent.AddOwner(typeof(TextEditor)); - - - /// <summary> - /// The PreviewMouseHoverStopped event. - /// </summary> - public static readonly RoutedEvent PreviewMouseHoverStoppedEvent = - TextView.PreviewMouseHoverStoppedEvent.AddOwner(typeof(TextEditor)); - - /// <summary> - /// The MouseHoverStopped event. - /// </summary> - public static readonly RoutedEvent MouseHoverStoppedEvent = - TextView.MouseHoverStoppedEvent.AddOwner(typeof(TextEditor)); - - - /// <summary> - /// Occurs when the mouse has hovered over a fixed location for some time. - /// </summary> - public event MouseEventHandler PreviewMouseHover { - add { AddHandler(PreviewMouseHoverEvent, value); } - remove { RemoveHandler(PreviewMouseHoverEvent, value); } - } - - /// <summary> - /// Occurs when the mouse has hovered over a fixed location for some time. - /// </summary> - public event MouseEventHandler MouseHover { - add { AddHandler(MouseHoverEvent, value); } - remove { RemoveHandler(MouseHoverEvent, value); } - } - - /// <summary> - /// Occurs when the mouse had previously hovered but now started moving again. - /// </summary> - public event MouseEventHandler PreviewMouseHoverStopped { - add { AddHandler(PreviewMouseHoverStoppedEvent, value); } - remove { RemoveHandler(PreviewMouseHoverStoppedEvent, value); } - } - - /// <summary> - /// Occurs when the mouse had previously hovered but now started moving again. - /// </summary> - public event MouseEventHandler MouseHoverStopped { - add { AddHandler(MouseHoverStoppedEvent, value); } - remove { RemoveHandler(MouseHoverStoppedEvent, value); } - } - #endregion - - #region ScrollBarVisibility - /// <summary> - /// Dependency property for <see cref="HorizontalScrollBarVisibility"/> - /// </summary> - public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty = ScrollViewer.HorizontalScrollBarVisibilityProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible)); - - /// <summary> - /// Gets/Sets the horizontal scroll bar visibility. - /// </summary> - public ScrollBarVisibility HorizontalScrollBarVisibility { - get { return (ScrollBarVisibility)GetValue(HorizontalScrollBarVisibilityProperty); } - set { SetValue(HorizontalScrollBarVisibilityProperty, value); } - } - - /// <summary> - /// Dependency property for <see cref="VerticalScrollBarVisibility"/> - /// </summary> - public static readonly DependencyProperty VerticalScrollBarVisibilityProperty = ScrollViewer.VerticalScrollBarVisibilityProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible)); - - /// <summary> - /// Gets/Sets the vertical scroll bar visibility. - /// </summary> - public ScrollBarVisibility VerticalScrollBarVisibility { - get { return (ScrollBarVisibility)GetValue(VerticalScrollBarVisibilityProperty); } - set { SetValue(VerticalScrollBarVisibilityProperty, value); } - } - #endregion - - object IServiceProvider.GetService(Type serviceType) - { - return textArea.GetService(serviceType); - } - - /// <summary> - /// Gets the text view position from a point inside the editor. - /// </summary> - /// <param name="point">The position, relative to top left - /// corner of TextEditor control</param> - /// <returns>The text view position, or null if the point is outside the document.</returns> - public TextViewPosition? GetPositionFromPoint(Point point) - { - if (this.Document == null) - return null; - TextView textView = this.TextArea.TextView; - return textView.GetPosition(TranslatePoint(point, textView) + textView.ScrollOffset); - } - - /// <summary> - /// Scrolls to the specified line. - /// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior). - /// </summary> - public void ScrollToLine(int line) - { - ScrollTo(line, -1); - } - - /// <summary> - /// Scrolls to the specified line/column. - /// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior). - /// </summary> - public void ScrollTo(int line, int column) - { - const double MinimumScrollPercentage = 0.3; - - TextView textView = textArea.TextView; - TextDocument document = textView.Document; - if (scrollViewer != null && document != null) { - if (line < 1) - line = 1; - if (line > document.LineCount) - line = document.LineCount; - - IScrollInfo scrollInfo = textView; - if (!scrollInfo.CanHorizontallyScroll) { - // Word wrap is enabled. Ensure that we have up-to-date info about line height so that we scroll - // to the correct position. - // This avoids that the user has to repeat the ScrollTo() call several times when there are very long lines. - VisualLine vl = textView.GetOrConstructVisualLine(document.GetLineByNumber(line)); - double remainingHeight = scrollViewer.ViewportHeight / 2; - while (remainingHeight > 0) { - DocumentLine prevLine = vl.FirstDocumentLine.PreviousLine; - if (prevLine == null) - break; - vl = textView.GetOrConstructVisualLine(prevLine); - remainingHeight -= vl.Height; - } - } - - Point p = textArea.TextView.GetVisualPosition(new TextViewPosition(line, Math.Max(1, column)), VisualYPosition.LineMiddle); - double verticalPos = p.Y - scrollViewer.ViewportHeight / 2; - if (Math.Abs(verticalPos - scrollViewer.VerticalOffset) > MinimumScrollPercentage * scrollViewer.ViewportHeight) { - scrollViewer.ScrollToVerticalOffset(Math.Max(0, verticalPos)); - } - if (column > 0) { - if (p.X > scrollViewer.ViewportWidth - Caret.MinimumDistanceToViewBorder * 2) { - double horizontalPos = Math.Max(0, p.X - scrollViewer.ViewportWidth / 2); - if (Math.Abs(horizontalPos - scrollViewer.HorizontalOffset) > MinimumScrollPercentage * scrollViewer.ViewportWidth) { - scrollViewer.ScrollToHorizontalOffset(horizontalPos); - } - } else { - scrollViewer.ScrollToHorizontalOffset(0); - } - } - } - } - } + /// <summary> + /// The text editor control. + /// Contains a scrollable TextArea. + /// </summary> + [Localizability(LocalizationCategory.Text), ContentProperty("Text")] + public class TextEditor : Control, ITextEditorComponent, IServiceProvider, IWeakEventListener + { + #region Constructors + static TextEditor() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(TextEditor), + new FrameworkPropertyMetadata(typeof(TextEditor))); + FocusableProperty.OverrideMetadata(typeof(TextEditor), + new FrameworkPropertyMetadata(Boxes.True)); + } + + /// <summary> + /// Creates a new TextEditor instance. + /// </summary> + public TextEditor() : this(new TextArea()) + { + } + + /// <summary> + /// Creates a new TextEditor instance. + /// </summary> + protected TextEditor(TextArea textArea) + { + if (textArea == null) + throw new ArgumentNullException("textArea"); + this.textArea = textArea; + + textArea.TextView.Services.AddService(typeof(TextEditor), this); + + SetCurrentValue(OptionsProperty, textArea.Options); + SetCurrentValue(DocumentProperty, new TextDocument()); + } + + #endregion + + /// <inheritdoc/> + protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() + { + return new TextEditorAutomationPeer(this); + } + + /// Forward focus to TextArea. + /// <inheritdoc/> + protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) + { + base.OnGotKeyboardFocus(e); + if (e.NewFocus == this) + { + Keyboard.Focus(this.TextArea); + e.Handled = true; + } + } + + #region Document property + /// <summary> + /// Document property. + /// </summary> + public static readonly DependencyProperty DocumentProperty + = TextView.DocumentProperty.AddOwner( + typeof(TextEditor), new FrameworkPropertyMetadata(OnDocumentChanged)); + + /// <summary> + /// Gets/Sets the document displayed by the text editor. + /// This is a dependency property. + /// </summary> + public TextDocument Document + { + get { return (TextDocument)GetValue(DocumentProperty); } + set { SetValue(DocumentProperty, value); } + } + + /// <summary> + /// Occurs when the document property has changed. + /// </summary> + public event EventHandler DocumentChanged; + + /// <summary> + /// Raises the <see cref="DocumentChanged"/> event. + /// </summary> + protected virtual void OnDocumentChanged(EventArgs e) + { + if (DocumentChanged != null) + { + DocumentChanged(this, e); + } + } + + static void OnDocumentChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e) + { + ((TextEditor)dp).OnDocumentChanged((TextDocument)e.OldValue, (TextDocument)e.NewValue); + } + + void OnDocumentChanged(TextDocument oldValue, TextDocument newValue) + { + if (oldValue != null) + { + TextDocumentWeakEventManager.TextChanged.RemoveListener(oldValue, this); + PropertyChangedEventManager.RemoveListener(oldValue.UndoStack, this, "IsOriginalFile"); + } + textArea.Document = newValue; + if (newValue != null) + { + TextDocumentWeakEventManager.TextChanged.AddListener(newValue, this); + PropertyChangedEventManager.AddListener(newValue.UndoStack, this, "IsOriginalFile"); + } + OnDocumentChanged(EventArgs.Empty); + OnTextChanged(EventArgs.Empty); + } + #endregion + + #region Options property + /// <summary> + /// Options property. + /// </summary> + public static readonly DependencyProperty OptionsProperty + = TextView.OptionsProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(OnOptionsChanged)); + + /// <summary> + /// Gets/Sets the options currently used by the text editor. + /// </summary> + public TextEditorOptions Options + { + get { return (TextEditorOptions)GetValue(OptionsProperty); } + set { SetValue(OptionsProperty, value); } + } + + /// <summary> + /// Occurs when a text editor option has changed. + /// </summary> + public event PropertyChangedEventHandler OptionChanged; + + /// <summary> + /// Raises the <see cref="OptionChanged"/> event. + /// </summary> + protected virtual void OnOptionChanged(PropertyChangedEventArgs e) + { + if (OptionChanged != null) + { + OptionChanged(this, e); + } + } + + static void OnOptionsChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e) + { + ((TextEditor)dp).OnOptionsChanged((TextEditorOptions)e.OldValue, (TextEditorOptions)e.NewValue); + } + + void OnOptionsChanged(TextEditorOptions oldValue, TextEditorOptions newValue) + { + if (oldValue != null) + { + PropertyChangedWeakEventManager.RemoveListener(oldValue, this); + } + textArea.Options = newValue; + if (newValue != null) + { + PropertyChangedWeakEventManager.AddListener(newValue, this); + } + OnOptionChanged(new PropertyChangedEventArgs(null)); + } + + /// <inheritdoc cref="IWeakEventListener.ReceiveWeakEvent"/> + protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) + { + if (managerType == typeof(PropertyChangedWeakEventManager)) + { + OnOptionChanged((PropertyChangedEventArgs)e); + return true; + } + else if (managerType == typeof(TextDocumentWeakEventManager.TextChanged)) + { + OnTextChanged(e); + return true; + } + else if (managerType == typeof(PropertyChangedEventManager)) + { + return HandleIsOriginalChanged((PropertyChangedEventArgs)e); + } + return false; + } + + bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) + { + return ReceiveWeakEvent(managerType, sender, e); + } + #endregion + + #region Text property + /// <summary> + /// Gets/Sets the text of the current document. + /// </summary> + [Localizability(LocalizationCategory.Text), DefaultValue("")] + public string Text + { + get + { + TextDocument document = this.Document; + return document != null ? document.Text : string.Empty; + } + set + { + TextDocument document = GetDocument(); + document.Text = value ?? string.Empty; + // after replacing the full text, the caret is positioned at the end of the document + // - reset it to the beginning. + this.CaretOffset = 0; + document.UndoStack.ClearAll(); + } + } + + TextDocument GetDocument() + { + TextDocument document = this.Document; + if (document == null) + throw ThrowUtil.NoDocumentAssigned(); + return document; + } + + /// <summary> + /// Occurs when the Text property changes. + /// </summary> + public event EventHandler TextChanged; + + /// <summary> + /// Raises the <see cref="TextChanged"/> event. + /// </summary> + protected virtual void OnTextChanged(EventArgs e) + { + if (TextChanged != null) + { + TextChanged(this, e); + } + } + #endregion + + #region TextArea / ScrollViewer properties + readonly TextArea textArea; + ScrollViewer scrollViewer; + + /// <summary> + /// Is called after the template was applied. + /// </summary> + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + scrollViewer = (ScrollViewer)Template.FindName("PART_ScrollViewer", this); + } + + /// <summary> + /// Gets the text area. + /// </summary> + public TextArea TextArea + { + get + { + return textArea; + } + } + + /// <summary> + /// Gets the scroll viewer used by the text editor. + /// This property can return null if the template has not been applied / does not contain a scroll viewer. + /// </summary> + internal ScrollViewer ScrollViewer + { + get { return scrollViewer; } + } + + bool CanExecute(RoutedUICommand command) + { + TextArea textArea = this.TextArea; + if (textArea == null) + return false; + else + return command.CanExecute(null, textArea); + } + + void Execute(RoutedUICommand command) + { + TextArea textArea = this.TextArea; + if (textArea != null) + command.Execute(null, textArea); + } + #endregion + + #region Syntax highlighting + /// <summary> + /// The <see cref="SyntaxHighlighting"/> property. + /// </summary> + public static readonly DependencyProperty SyntaxHighlightingProperty = + DependencyProperty.Register("SyntaxHighlighting", typeof(IHighlightingDefinition), typeof(TextEditor), + new FrameworkPropertyMetadata(OnSyntaxHighlightingChanged)); + + + /// <summary> + /// Gets/sets the syntax highlighting definition used to colorize the text. + /// </summary> + public IHighlightingDefinition SyntaxHighlighting + { + get { return (IHighlightingDefinition)GetValue(SyntaxHighlightingProperty); } + set { SetValue(SyntaxHighlightingProperty, value); } + } + + IVisualLineTransformer colorizer; + + static void OnSyntaxHighlightingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((TextEditor)d).OnSyntaxHighlightingChanged(e.NewValue as IHighlightingDefinition); + } + + void OnSyntaxHighlightingChanged(IHighlightingDefinition newValue) + { + if (colorizer != null) + { + this.TextArea.TextView.LineTransformers.Remove(colorizer); + colorizer = null; + } + if (newValue != null) + { + colorizer = CreateColorizer(newValue); + this.TextArea.TextView.LineTransformers.Insert(0, colorizer); + } + } + + /// <summary> + /// Creates the highlighting colorizer for the specified highlighting definition. + /// Allows derived classes to provide custom colorizer implementations for special highlighting definitions. + /// </summary> + /// <returns></returns> + protected virtual IVisualLineTransformer CreateColorizer(IHighlightingDefinition highlightingDefinition) + { + if (highlightingDefinition == null) + throw new ArgumentNullException("highlightingDefinition"); + return new HighlightingColorizer(highlightingDefinition.MainRuleSet); + } + #endregion + + #region WordWrap + /// <summary> + /// Word wrap dependency property. + /// </summary> + public static readonly DependencyProperty WordWrapProperty = + DependencyProperty.Register("WordWrap", typeof(bool), typeof(TextEditor), + new FrameworkPropertyMetadata(Boxes.False)); + + /// <summary> + /// Specifies whether the text editor uses word wrapping. + /// </summary> + /// <remarks> + /// Setting WordWrap=true has the same effect as setting HorizontalScrollBarVisibility=Disabled and will override the + /// HorizontalScrollBarVisibility setting. + /// </remarks> + public bool WordWrap + { + get { return (bool)GetValue(WordWrapProperty); } + set { SetValue(WordWrapProperty, Boxes.Box(value)); } + } + #endregion + + #region IsReadOnly + /// <summary> + /// IsReadOnly dependency property. + /// </summary> + public static readonly DependencyProperty IsReadOnlyProperty = + DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(TextEditor), + new FrameworkPropertyMetadata(Boxes.False, OnIsReadOnlyChanged)); + + /// <summary> + /// Specifies whether the user can change the text editor content. + /// Setting this property will replace the + /// <see cref="Editing.TextArea.ReadOnlySectionProvider">TextArea.ReadOnlySectionProvider</see>. + /// </summary> + public bool IsReadOnly + { + get { return (bool)GetValue(IsReadOnlyProperty); } + set { SetValue(IsReadOnlyProperty, Boxes.Box(value)); } + } + + static void OnIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TextEditor editor = d as TextEditor; + if (editor != null) + { + if ((bool)e.NewValue) + editor.TextArea.ReadOnlySectionProvider = ReadOnlyDocument.Instance; + else + editor.TextArea.ReadOnlySectionProvider = NoReadOnlySections.Instance; + + TextEditorAutomationPeer peer = TextEditorAutomationPeer.FromElement(editor) as TextEditorAutomationPeer; + if (peer != null) + { + peer.RaiseIsReadOnlyChanged((bool)e.OldValue, (bool)e.NewValue); + } + } + } + #endregion + + #region IsModified + /// <summary> + /// Dependency property for <see cref="IsModified"/> + /// </summary> + public static readonly DependencyProperty IsModifiedProperty = + DependencyProperty.Register("IsModified", typeof(bool), typeof(TextEditor), + new FrameworkPropertyMetadata(Boxes.False, OnIsModifiedChanged)); + + /// <summary> + /// Gets/Sets the 'modified' flag. + /// </summary> + public bool IsModified + { + get { return (bool)GetValue(IsModifiedProperty); } + set { SetValue(IsModifiedProperty, Boxes.Box(value)); } + } + + static void OnIsModifiedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TextEditor editor = d as TextEditor; + if (editor != null) + { + TextDocument document = editor.Document; + if (document != null) + { + UndoStack undoStack = document.UndoStack; + if ((bool)e.NewValue) + { + if (undoStack.IsOriginalFile) + undoStack.DiscardOriginalFileMarker(); + } + else + { + undoStack.MarkAsOriginalFile(); + } + } + } + } + + bool HandleIsOriginalChanged(PropertyChangedEventArgs e) + { + if (e.PropertyName == "IsOriginalFile") + { + TextDocument document = this.Document; + if (document != null) + { + SetCurrentValue(IsModifiedProperty, Boxes.Box(!document.UndoStack.IsOriginalFile)); + } + return true; + } + else + { + return false; + } + } + #endregion + + #region ShowLineNumbers + /// <summary> + /// ShowLineNumbers dependency property. + /// </summary> + public static readonly DependencyProperty ShowLineNumbersProperty = + DependencyProperty.Register("ShowLineNumbers", typeof(bool), typeof(TextEditor), + new FrameworkPropertyMetadata(Boxes.False, OnShowLineNumbersChanged)); + + /// <summary> + /// Specifies whether line numbers are shown on the left to the text view. + /// </summary> + public bool ShowLineNumbers + { + get { return (bool)GetValue(ShowLineNumbersProperty); } + set { SetValue(ShowLineNumbersProperty, Boxes.Box(value)); } + } + + static void OnShowLineNumbersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TextEditor editor = (TextEditor)d; + var leftMargins = editor.TextArea.LeftMargins; + if ((bool)e.NewValue) + { + LineNumberMargin lineNumbers = new LineNumberMargin(); + Line line = (Line)DottedLineMargin.Create(); + leftMargins.Insert(0, lineNumbers); + leftMargins.Insert(1, line); + var lineNumbersForeground = new Binding("LineNumbersForeground") { Source = editor }; + line.SetBinding(Line.StrokeProperty, lineNumbersForeground); + lineNumbers.SetBinding(Control.ForegroundProperty, lineNumbersForeground); + } + else + { + for (int i = 0; i < leftMargins.Count; i++) + { + if (leftMargins[i] is LineNumberMargin) + { + leftMargins.RemoveAt(i); + if (i < leftMargins.Count && DottedLineMargin.IsDottedLineMargin(leftMargins[i])) + { + leftMargins.RemoveAt(i); + } + break; + } + } + } + } + #endregion + + #region LineNumbersForeground + /// <summary> + /// LineNumbersForeground dependency property. + /// </summary> + public static readonly DependencyProperty LineNumbersForegroundProperty = + DependencyProperty.Register("LineNumbersForeground", typeof(Brush), typeof(TextEditor), + new FrameworkPropertyMetadata(Brushes.Gray, OnLineNumbersForegroundChanged)); + + /// <summary> + /// Gets/sets the Brush used for displaying the foreground color of line numbers. + /// </summary> + public Brush LineNumbersForeground + { + get { return (Brush)GetValue(LineNumbersForegroundProperty); } + set { SetValue(LineNumbersForegroundProperty, value); } + } + + static void OnLineNumbersForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TextEditor editor = (TextEditor)d; + var lineNumberMargin = editor.TextArea.LeftMargins.FirstOrDefault(margin => margin is LineNumberMargin) as LineNumberMargin; ; + + if (lineNumberMargin != null) + { + lineNumberMargin.SetValue(Control.ForegroundProperty, e.NewValue); + } + } + #endregion + + #region TextBoxBase-like methods + /// <summary> + /// Appends text to the end of the document. + /// </summary> + public void AppendText(string textData) + { + var document = GetDocument(); + document.Insert(document.TextLength, textData); + } + + /// <summary> + /// Begins a group of document changes. + /// </summary> + public void BeginChange() + { + GetDocument().BeginUpdate(); + } + + /// <summary> + /// Copies the current selection to the clipboard. + /// </summary> + public void Copy() + { + Execute(ApplicationCommands.Copy); + } + + /// <summary> + /// Removes the current selection and copies it to the clipboard. + /// </summary> + public void Cut() + { + Execute(ApplicationCommands.Cut); + } + + /// <summary> + /// Begins a group of document changes and returns an object that ends the group of document + /// changes when it is disposed. + /// </summary> + public IDisposable DeclareChangeBlock() + { + return GetDocument().RunUpdate(); + } + + /// <summary> + /// Ends the current group of document changes. + /// </summary> + public void EndChange() + { + GetDocument().EndUpdate(); + } + + /// <summary> + /// Scrolls one line down. + /// </summary> + public void LineDown() + { + if (scrollViewer != null) + scrollViewer.LineDown(); + } + + /// <summary> + /// Scrolls to the left. + /// </summary> + public void LineLeft() + { + if (scrollViewer != null) + scrollViewer.LineLeft(); + } + + /// <summary> + /// Scrolls to the right. + /// </summary> + public void LineRight() + { + if (scrollViewer != null) + scrollViewer.LineRight(); + } + + /// <summary> + /// Scrolls one line up. + /// </summary> + public void LineUp() + { + if (scrollViewer != null) + scrollViewer.LineUp(); + } + + /// <summary> + /// Scrolls one page down. + /// </summary> + public void PageDown() + { + if (scrollViewer != null) + scrollViewer.PageDown(); + } + + /// <summary> + /// Scrolls one page up. + /// </summary> + public void PageUp() + { + if (scrollViewer != null) + scrollViewer.PageUp(); + } + + /// <summary> + /// Scrolls one page left. + /// </summary> + public void PageLeft() + { + if (scrollViewer != null) + scrollViewer.PageLeft(); + } + + /// <summary> + /// Scrolls one page right. + /// </summary> + public void PageRight() + { + if (scrollViewer != null) + scrollViewer.PageRight(); + } + + /// <summary> + /// Pastes the clipboard content. + /// </summary> + public void Paste() + { + Execute(ApplicationCommands.Paste); + } + + /// <summary> + /// Redoes the most recent undone command. + /// </summary> + /// <returns>True is the redo operation was successful, false is the redo stack is empty.</returns> + public bool Redo() + { + if (CanExecute(ApplicationCommands.Redo)) + { + Execute(ApplicationCommands.Redo); + return true; + } + return false; + } + + /// <summary> + /// Scrolls to the end of the document. + /// </summary> + public void ScrollToEnd() + { + ApplyTemplate(); // ensure scrollViewer is created + if (scrollViewer != null) + scrollViewer.ScrollToEnd(); + } + + /// <summary> + /// Scrolls to the start of the document. + /// </summary> + public void ScrollToHome() + { + ApplyTemplate(); // ensure scrollViewer is created + if (scrollViewer != null) + scrollViewer.ScrollToHome(); + } + + /// <summary> + /// Scrolls to the specified position in the document. + /// </summary> + public void ScrollToHorizontalOffset(double offset) + { + ApplyTemplate(); // ensure scrollViewer is created + if (scrollViewer != null) + scrollViewer.ScrollToHorizontalOffset(offset); + } + + /// <summary> + /// Scrolls to the specified position in the document. + /// </summary> + public void ScrollToVerticalOffset(double offset) + { + ApplyTemplate(); // ensure scrollViewer is created + if (scrollViewer != null) + scrollViewer.ScrollToVerticalOffset(offset); + } + + /// <summary> + /// Selects the entire text. + /// </summary> + public void SelectAll() + { + Execute(ApplicationCommands.SelectAll); + } + + /// <summary> + /// Undoes the most recent command. + /// </summary> + /// <returns>True is the undo operation was successful, false is the undo stack is empty.</returns> + public bool Undo() + { + if (CanExecute(ApplicationCommands.Undo)) + { + Execute(ApplicationCommands.Undo); + return true; + } + return false; + } + + /// <summary> + /// Gets if the most recent undone command can be redone. + /// </summary> + public bool CanRedo + { + get { return CanExecute(ApplicationCommands.Redo); } + } + + /// <summary> + /// Gets if the most recent command can be undone. + /// </summary> + public bool CanUndo + { + get { return CanExecute(ApplicationCommands.Undo); } + } + + /// <summary> + /// Gets the vertical size of the document. + /// </summary> + public double ExtentHeight + { + get + { + return scrollViewer != null ? scrollViewer.ExtentHeight : 0; + } + } + + /// <summary> + /// Gets the horizontal size of the current document region. + /// </summary> + public double ExtentWidth + { + get + { + return scrollViewer != null ? scrollViewer.ExtentWidth : 0; + } + } + + /// <summary> + /// Gets the horizontal size of the viewport. + /// </summary> + public double ViewportHeight + { + get + { + return scrollViewer != null ? scrollViewer.ViewportHeight : 0; + } + } + + /// <summary> + /// Gets the horizontal size of the viewport. + /// </summary> + public double ViewportWidth + { + get + { + return scrollViewer != null ? scrollViewer.ViewportWidth : 0; + } + } + + /// <summary> + /// Gets the vertical scroll position. + /// </summary> + public double VerticalOffset + { + get + { + return scrollViewer != null ? scrollViewer.VerticalOffset : 0; + } + } + + /// <summary> + /// Gets the horizontal scroll position. + /// </summary> + public double HorizontalOffset + { + get + { + return scrollViewer != null ? scrollViewer.HorizontalOffset : 0; + } + } + #endregion + + #region TextBox methods + /// <summary> + /// Gets/Sets the selected text. + /// </summary> + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string SelectedText + { + get + { + TextArea textArea = this.TextArea; + // We'll get the text from the whole surrounding segment. + // This is done to ensure that SelectedText.Length == SelectionLength. + if (textArea != null && textArea.Document != null && !textArea.Selection.IsEmpty) + return textArea.Document.GetText(textArea.Selection.SurroundingSegment); + else + return string.Empty; + } + set + { + if (value == null) + throw new ArgumentNullException("value"); + TextArea textArea = this.TextArea; + if (textArea != null && textArea.Document != null) + { + int offset = this.SelectionStart; + int length = this.SelectionLength; + textArea.Document.Replace(offset, length, value); + // keep inserted text selected + textArea.Selection = SimpleSelection.Create(textArea, offset, offset + value.Length); + } + } + } + + /// <summary> + /// Gets/sets the caret position. + /// </summary> + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int CaretOffset + { + get + { + TextArea textArea = this.TextArea; + if (textArea != null) + return textArea.Caret.Offset; + else + return 0; + } + set + { + TextArea textArea = this.TextArea; + if (textArea != null) + textArea.Caret.Offset = value; + } + } + + /// <summary> + /// Gets/sets the start position of the selection. + /// </summary> + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int SelectionStart + { + get + { + TextArea textArea = this.TextArea; + if (textArea != null) + { + if (textArea.Selection.IsEmpty) + return textArea.Caret.Offset; + else + return textArea.Selection.SurroundingSegment.Offset; + } + else + { + return 0; + } + } + set + { + Select(value, SelectionLength); + } + } + + /// <summary> + /// Gets/sets the length of the selection. + /// </summary> + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int SelectionLength + { + get + { + TextArea textArea = this.TextArea; + if (textArea != null && !textArea.Selection.IsEmpty) + return textArea.Selection.SurroundingSegment.Length; + else + return 0; + } + set + { + Select(SelectionStart, value); + } + } + + /// <summary> + /// Selects the specified text section. + /// </summary> + public void Select(int start, int length) + { + int documentLength = Document != null ? Document.TextLength : 0; + + if (start < 0 || start > documentLength) + { + Debug.WriteLine(new ArgumentOutOfRangeException("start", start, "Value must be between 0 and " + documentLength)); + return; + } + + if (length < 0 || start + length > documentLength) + { + Debug.WriteLine(new ArgumentOutOfRangeException("length", length, "Value must be between 0 and " + (documentLength - length))); + return; + } + + textArea.Selection = SimpleSelection.Create(textArea, start, start + length); + textArea.Caret.Offset = start + length; + } + + /// <summary> + /// Gets the number of lines in the document. + /// </summary> + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public int LineCount + { + get + { + TextDocument document = this.Document; + if (document != null) + return document.LineCount; + else + return 1; + } + } + + /// <summary> + /// Clears the text. + /// </summary> + public void Clear() + { + this.Text = string.Empty; + } + #endregion + + #region Loading from stream + /// <summary> + /// Loads the text from the stream, auto-detecting the encoding. + /// </summary> + /// <remarks> + /// This method sets <see cref="IsModified"/> to false. + /// </remarks> + public void Load(Stream stream) + { + using (StreamReader reader = FileReader.OpenStream(stream, this.Encoding ?? Encoding.UTF8)) + { + this.Text = reader.ReadToEnd(); + this.Encoding = reader.CurrentEncoding; // assign encoding after ReadToEnd() so that the StreamReader can autodetect the encoding + } + this.IsModified = false; + } + + /// <summary> + /// Loads the text from the stream, auto-detecting the encoding. + /// </summary> + public void Load(string fileName) + { + if (fileName == null) + throw new ArgumentNullException("fileName"); + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + Load(fs); + } + } + + /// <summary> + /// Gets/sets the encoding used when the file is saved. + /// </summary> + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public Encoding Encoding { get; set; } + + /// <summary> + /// Saves the text to the stream. + /// </summary> + /// <remarks> + /// This method sets <see cref="IsModified"/> to false. + /// </remarks> + public void Save(Stream stream) + { + if (stream == null) + throw new ArgumentNullException("stream"); + StreamWriter writer = new StreamWriter(stream, this.Encoding ?? Encoding.UTF8); + writer.Write(this.Text); + writer.Flush(); + // do not close the stream + this.IsModified = false; + } + + /// <summary> + /// Saves the text to the file. + /// </summary> + public void Save(string fileName) + { + if (fileName == null) + throw new ArgumentNullException("fileName"); + using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) + { + Save(fs); + } + } + #endregion + + #region MouseHover events + /// <summary> + /// The PreviewMouseHover event. + /// </summary> + public static readonly RoutedEvent PreviewMouseHoverEvent = + TextView.PreviewMouseHoverEvent.AddOwner(typeof(TextEditor)); + + /// <summary> + /// The MouseHover event. + /// </summary> + public static readonly RoutedEvent MouseHoverEvent = + TextView.MouseHoverEvent.AddOwner(typeof(TextEditor)); + + + /// <summary> + /// The PreviewMouseHoverStopped event. + /// </summary> + public static readonly RoutedEvent PreviewMouseHoverStoppedEvent = + TextView.PreviewMouseHoverStoppedEvent.AddOwner(typeof(TextEditor)); + + /// <summary> + /// The MouseHoverStopped event. + /// </summary> + public static readonly RoutedEvent MouseHoverStoppedEvent = + TextView.MouseHoverStoppedEvent.AddOwner(typeof(TextEditor)); + + + /// <summary> + /// Occurs when the mouse has hovered over a fixed location for some time. + /// </summary> + public event MouseEventHandler PreviewMouseHover + { + add { AddHandler(PreviewMouseHoverEvent, value); } + remove { RemoveHandler(PreviewMouseHoverEvent, value); } + } + + /// <summary> + /// Occurs when the mouse has hovered over a fixed location for some time. + /// </summary> + public event MouseEventHandler MouseHover + { + add { AddHandler(MouseHoverEvent, value); } + remove { RemoveHandler(MouseHoverEvent, value); } + } + + /// <summary> + /// Occurs when the mouse had previously hovered but now started moving again. + /// </summary> + public event MouseEventHandler PreviewMouseHoverStopped + { + add { AddHandler(PreviewMouseHoverStoppedEvent, value); } + remove { RemoveHandler(PreviewMouseHoverStoppedEvent, value); } + } + + /// <summary> + /// Occurs when the mouse had previously hovered but now started moving again. + /// </summary> + public event MouseEventHandler MouseHoverStopped + { + add { AddHandler(MouseHoverStoppedEvent, value); } + remove { RemoveHandler(MouseHoverStoppedEvent, value); } + } + #endregion + + #region ScrollBarVisibility + /// <summary> + /// Dependency property for <see cref="HorizontalScrollBarVisibility"/> + /// </summary> + public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty = ScrollViewer.HorizontalScrollBarVisibilityProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible)); + + /// <summary> + /// Gets/Sets the horizontal scroll bar visibility. + /// </summary> + public ScrollBarVisibility HorizontalScrollBarVisibility + { + get { return (ScrollBarVisibility)GetValue(HorizontalScrollBarVisibilityProperty); } + set { SetValue(HorizontalScrollBarVisibilityProperty, value); } + } + + /// <summary> + /// Dependency property for <see cref="VerticalScrollBarVisibility"/> + /// </summary> + public static readonly DependencyProperty VerticalScrollBarVisibilityProperty = ScrollViewer.VerticalScrollBarVisibilityProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible)); + + /// <summary> + /// Gets/Sets the vertical scroll bar visibility. + /// </summary> + public ScrollBarVisibility VerticalScrollBarVisibility + { + get { return (ScrollBarVisibility)GetValue(VerticalScrollBarVisibilityProperty); } + set { SetValue(VerticalScrollBarVisibilityProperty, value); } + } + #endregion + + object IServiceProvider.GetService(Type serviceType) + { + return textArea.GetService(serviceType); + } + + /// <summary> + /// Gets the text view position from a point inside the editor. + /// </summary> + /// <param name="point">The position, relative to top left + /// corner of TextEditor control</param> + /// <returns>The text view position, or null if the point is outside the document.</returns> + public TextViewPosition? GetPositionFromPoint(Point point) + { + if (this.Document == null) + return null; + TextView textView = this.TextArea.TextView; + return textView.GetPosition(TranslatePoint(point, textView) + textView.ScrollOffset); + } + + /// <summary> + /// Scrolls to the specified line. + /// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior). + /// </summary> + public void ScrollToLine(int line) + { + ScrollTo(line, -1); + } + + /// <summary> + /// Scrolls to the specified line/column. + /// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior). + /// </summary> + public void ScrollTo(int line, int column) + { + const double MinimumScrollPercentage = 0.3; + + TextView textView = textArea.TextView; + TextDocument document = textView.Document; + if (scrollViewer != null && document != null) + { + if (line < 1) + line = 1; + if (line > document.LineCount) + line = document.LineCount; + + IScrollInfo scrollInfo = textView; + if (!scrollInfo.CanHorizontallyScroll) + { + // Word wrap is enabled. Ensure that we have up-to-date info about line height so that we scroll + // to the correct position. + // This avoids that the user has to repeat the ScrollTo() call several times when there are very long lines. + VisualLine vl = textView.GetOrConstructVisualLine(document.GetLineByNumber(line)); + double remainingHeight = scrollViewer.ViewportHeight / 2; + while (remainingHeight > 0) + { + DocumentLine prevLine = vl.FirstDocumentLine.PreviousLine; + if (prevLine == null) + break; + vl = textView.GetOrConstructVisualLine(prevLine); + remainingHeight -= vl.Height; + } + } + + Point p = textArea.TextView.GetVisualPosition(new TextViewPosition(line, Math.Max(1, column)), VisualYPosition.LineMiddle); + double verticalPos = p.Y - scrollViewer.ViewportHeight / 2; + if (Math.Abs(verticalPos - scrollViewer.VerticalOffset) > MinimumScrollPercentage * scrollViewer.ViewportHeight) + { + scrollViewer.ScrollToVerticalOffset(Math.Max(0, verticalPos)); + } + if (column > 0) + { + if (p.X > scrollViewer.ViewportWidth - Caret.MinimumDistanceToViewBorder * 2) + { + double horizontalPos = Math.Max(0, p.X - scrollViewer.ViewportWidth / 2); + if (Math.Abs(horizontalPos - scrollViewer.HorizontalOffset) > MinimumScrollPercentage * scrollViewer.ViewportWidth) + { + scrollViewer.ScrollToHorizontalOffset(horizontalPos); + } + } + else + { + scrollViewer.ScrollToHorizontalOffset(0); + } + } + } + } + } }
\ No newline at end of file diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Themes/Generic.xaml b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Themes/Generic.xaml index 6455b8fcb..5de763df3 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Themes/Generic.xaml +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Themes/Generic.xaml @@ -48,12 +48,18 @@ <BitmapImage x:Key="method" UriSource="pack://application:,,,/Tango.Scripting.Editors;component/Images/method.png" /> <BitmapImage x:Key="property" UriSource="pack://application:,,,/Tango.Scripting.Editors;component/Images/property.png" /> <BitmapImage x:Key="event" UriSource="pack://application:,,,/Tango.Scripting.Editors;component/Images/event.png" /> + <BitmapImage x:Key="snippet" UriSource="pack://application:,,,/Tango.Scripting.Editors;component/Images/snippet.png" /> <!--Converters--> <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> <converters:BooleanToVisibilityInversedConverter x:Key="BooleanToVisibilityInversedConverter" /> <Style TargetType="{x:Type completion:CompletionList}"> + <Style.Resources> + <Style TargetType="ToolTip"> + + </Style> + </Style.Resources> <Setter Property="Background" Value="{StaticResource CompletionBackgroundBrush}"></Setter> <Setter Property="BorderThickness" Value="0"></Setter> @@ -84,95 +90,6 @@ <Setter.Value> <DataTemplate> <Border Background="{StaticResource CompletionToolTipBackgroundBrush}" CornerRadius="3" BorderThickness="0.5" BorderBrush="#434343" Padding="10 5" TextElement.Foreground="{StaticResource ScriptForegroundBrush}" TextElement.FontSize="12"> - <!--<ContentControl Content="{Binding}"> - <ContentControl.Style> - <Style TargetType="ContentControl"> - <Setter Property="ContentTemplate"> - <Setter.Value> - <DataTemplate> - <ContentPresenter Content="{Binding PopupControl}" /> - </DataTemplate> - </Setter.Value> - </Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding Type}" Value="method"> - <Setter Property="ContentTemplate"> - <Setter.Value> - <DataTemplate> - <StackPanel> - <StackPanel Orientation="Horizontal"> - <TextBlock Text="{Binding ReturnType}" Foreground="{StaticResource ScriptReferenceTypesBrush}"></TextBlock> - <TextBlock Margin="5 0 0 0" Text="{Binding Class}" Foreground="{StaticResource ScriptReferenceTypesBrush}"></TextBlock> - <TextBlock>.</TextBlock> - <TextBlock Text="{Binding Text}"></TextBlock> - <TextBlock>(</TextBlock> - <ItemsControl ItemsSource="{Binding Parameters}"> - <ItemsControl.ItemsPanel> - <ItemsPanelTemplate> - <StackPanel Orientation="Horizontal"></StackPanel> - </ItemsPanelTemplate> - </ItemsControl.ItemsPanel> - <ItemsControl.ItemTemplate> - <DataTemplate> - <StackPanel Orientation="Horizontal"> - <TextBlock Text="{Binding Type.Name}" Foreground="{StaticResource ScriptReferenceTypesBrush}"></TextBlock> - <TextBlock Margin="5 0 0 0" Text="{Binding Name}"></TextBlock> - <TextBlock Margin="0 0 5 0" Text="," Visibility="{Binding IsLast,Converter={StaticResource BooleanToVisibilityInversedConverter}}"></TextBlock> - </StackPanel> - </DataTemplate> - </ItemsControl.ItemTemplate> - </ItemsControl> - <TextBlock>)</TextBlock> - - <StackPanel Margin="5 0 0 0" Orientation="Horizontal" Visibility="{Binding HasOverloads,Converter={StaticResource BooleanToVisibilityConverter}}"> - <TextBlock>(+</TextBlock> - <TextBlock Margin="2 0" Text="{Binding Overloads}"></TextBlock> - <TextBlock>overloads)</TextBlock> - </StackPanel> - </StackPanel> - - <TextBlock Text="{Binding Description}"></TextBlock> - </StackPanel> - </DataTemplate> - </Setter.Value> - </Setter> - </DataTrigger> - - <DataTrigger Binding="{Binding Type}" Value="property"> - <Setter Property="ContentTemplate"> - <Setter.Value> - <DataTemplate> - <StackPanel> - <StackPanel Orientation="Horizontal"> - <TextBlock Text="{Binding ReturnType}" Foreground="{StaticResource ScriptReferenceTypesBrush}"></TextBlock> - <TextBlock Margin="5 0 0 0" Text="{Binding Class}" Foreground="{StaticResource ScriptReferenceTypesBrush}"></TextBlock> - <TextBlock>.</TextBlock> - <TextBlock Text="{Binding Text}"></TextBlock> - <TextBlock Margin="5 0 0 0"> - <Run>{</Run> - <Run Foreground="{StaticResource ScriptKeywordBrush}">get</Run><Run>;</Run> - <Run Foreground="{StaticResource ScriptKeywordBrush}">set</Run><Run>;</Run> - <Run>}</Run> - </TextBlock> - </StackPanel> - - <TextBlock Text="{Binding Description}"></TextBlock> - </StackPanel> - </DataTemplate> - </Setter.Value> - </Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </ContentControl.Style> - - <ContentControl.ContentTemplate> - <DataTemplate> - <ContentPresenter Content="{Binding PopupControl}" /> - </DataTemplate> - </ContentControl.ContentTemplate> - </ContentControl>--> - <ContentPresenter DataContext="{Binding}" Content="{Binding PopupControl}" /> </Border> </DataTemplate> @@ -224,6 +141,15 @@ <Setter Property="Control.Cursor" Value="/Tango.Scripting.Editors;component/themes/RightArrow.cur"/> </Style> + <Style TargetType="{x:Type local:XamlEditor}"> + <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"></Setter> + <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"></Setter> + <Setter Property="FontFamily" Value="Consolas"></Setter> + <Setter Property="FontSize" Value="13"></Setter> + <Setter Property="SyntaxHighlighting" Value="XML"></Setter> + <Setter Property="ShowLineNumbers" Value="True"></Setter> + </Style> + <Style TargetType="{x:Type local:ScriptEditor}"> <Setter Property="Background" Value="{StaticResource ScriptBackgroundBrush}"></Setter> <Setter Property="Foreground" Value="{StaticResource ScriptForegroundBrush}"></Setter> diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/XamlEditor.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/XamlEditor.cs new file mode 100644 index 000000000..22b425ba2 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/XamlEditor.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace Tango.Scripting.Editors +{ + public class XamlEditor : TextEditor + { + private bool preventCodeUpdate; + + public String Xaml + { + get { return (String)GetValue(XamlProperty); } + set { SetValue(XamlProperty, value); } + } + public static readonly DependencyProperty XamlProperty = + DependencyProperty.Register("Xaml", typeof(String), typeof(XamlEditor), new PropertyMetadata(null, (d, e) => (d as XamlEditor).OnXamlChanged())); + + public XamlEditor() + { + TextChanged += XamlEditor_TextChanged; + } + + private void XamlEditor_TextChanged(object sender, EventArgs e) + { + if (!preventCodeUpdate) + { + preventCodeUpdate = true; + Xaml = Text; + preventCodeUpdate = false; + } + } + + private void OnXamlChanged() + { + if (!preventCodeUpdate) + { + preventCodeUpdate = true; + Text = Xaml; + preventCodeUpdate = false; + } + } + } +} |
