aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Scripting/Tango.Scripting.Editors
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2020-07-27 15:39:26 +0300
committerRoy Ben-Shabat <Roy@Twine-s.com>2020-07-27 15:39:26 +0300
commit5e59906df60d82248da4ae47677ed59d56fb605a (patch)
tree8585548197bfada234b7ded17028aba9563c32de /Software/Visual_Studio/Scripting/Tango.Scripting.Editors
parent3210901f7aa313cfe1eb2c303b539d6e7d1f2324 (diff)
parentc947fa4b4999b1368ee500c3349ef6e8fce3f0b5 (diff)
downloadTango-5e59906df60d82248da4ae47677ed59d56fb605a.tar.gz
Tango-5e59906df60d82248da4ae47677ed59d56fb605a.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors')
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Errors/ITextMarker.cs169
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Errors/TextMarkerService.cs365
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/OffsetColorizer.cs2
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/MarkDown-Mode.xshd7
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/XML-Mode.xshd14
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/TextView.cs2
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs236
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj5
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Themes/Generic.xaml9
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/XamlEditor.cs47
10 files changed, 837 insertions, 19 deletions
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/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/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="&gt; This is a\r\n&gt; 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="&lt;!-- comment --&gt;" />
- <Color foreground="Blue" name="CData" exampleText="&lt;![CDATA[data]]&gt;" />
- <Color foreground="Blue" name="DocType" exampleText="&lt;!DOCTYPE rootElement&gt;" />
- <Color foreground="Blue" name="XmlDeclaration" exampleText='&lt;?xml version="1.0"?&gt;' />
- <Color foreground="DarkMagenta" name="XmlTag" exampleText='&lt;tag attribute="value" /&gt;' />
- <Color foreground="Red" name="AttributeName" exampleText='&lt;tag attribute="value" /&gt;' />
- <Color foreground="Blue" name="AttributeValue" exampleText='&lt;tag attribute="value" /&gt;' />
+ <Color foreground="#3F92D6" name="CData" exampleText="&lt;![CDATA[data]]&gt;" />
+ <Color foreground="#C8C8C7" name="DocType" exampleText="&lt;!DOCTYPE rootElement&gt;" />
+ <Color foreground="#3F92D6" name="XmlDeclaration" exampleText='&lt;?xml version="1.0"?&gt;' />
+ <Color foreground="#3F92D6" name="XmlTag" exampleText='&lt;tag attribute="value" /&gt;' />
+ <Color foreground="#92CAF4" name="AttributeName" exampleText='&lt;tag attribute="value" /&gt;' />
+ <Color foreground="#C8C8C7" name="AttributeValue" exampleText='&lt;tag attribute="value" /&gt;' />
<Color foreground="Teal" name="Entity" exampleText="index.aspx?a=1&amp;amp;b=2" />
- <Color foreground="Olive" name="BrokenEntity" exampleText="index.aspx?a=1&amp;b=2" />
+ <Color foreground="Red" name="BrokenEntity" exampleText="index.aspx?a=1&amp;b=2" />
<RuleSet>
<Span color="Comment" multiline="true">
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 71a455f86..8cf615a7c 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;
@@ -56,6 +57,7 @@ namespace Tango.Scripting.Editors
private List<KnownType> _knownTypes;
private List<ScriptType> _declaredTypes;
private bool _isLoadingTypes;
+ private TextMarkerService errorMarkerService;
private static JsonSerializerSettings _jsonSettings;
private static Dictionary<Type, KnownType> _knownTypesCache;
private static String KNOWN_TYPES_CACHE_FOLDER;
@@ -69,6 +71,7 @@ namespace Tango.Scripting.Editors
public static event EventHandler<TangoProgressChangedEventArgs<int>> LoadingSymbolsProgress;
public static event EventHandler LoadingSymbolsStarted;
public static event EventHandler LoadingSymbolsCompleted;
+ private static event EventHandler KnownTypesAvailable;
#region Mini Classes
@@ -161,6 +164,14 @@ 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 }));
+
#endregion
#region Constructors
@@ -266,6 +277,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();
@@ -285,6 +298,18 @@ 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);
+ }
+
+ private void ScriptEditor_KnownTypesAvailable(object sender, EventArgs e)
+ {
+ if (sender != this)
+ {
+ InvalidateHighlightingPartial();
+ }
}
private bool preventCodeUpdate;
@@ -1357,7 +1382,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)
{
@@ -1390,6 +1415,9 @@ namespace Tango.Scripting.Editors
_knownTypesCache.Add(knownType.Type, knownType);
}
+ KnownTypesAvailable?.Invoke(this, new EventArgs());
+ InvalidateHighlightingPartial();
+
continue;
}
@@ -1575,6 +1603,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)
@@ -1964,7 +2086,7 @@ namespace Tango.Scripting.Editors
{
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();
@@ -2209,6 +2331,116 @@ 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)
+ {
+ ITextMarker marker = errorMarkerService.Create(position, length);
+ marker.MarkerTypes = TextMarkerTypes.SquigglyUnderline;
+ marker.MarkerColor = Colors.Red;
+ }
+
+ public void ClearErrors()
+ {
+ errorMarkerService.RemoveAll(m => true);
+ }
+
#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 94e3c4b0b..a70bbf3de 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
@@ -196,6 +196,8 @@
<Compile Include="CodeCompletion\OverloadViewer.cs" />
<Compile Include="Converters\BooleanToVisibilityConverter.cs" />
<Compile Include="Converters\BooleanToVisibilityInversedConverter.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" />
@@ -508,6 +510,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" />
@@ -650,7 +653,7 @@
</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" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UseGlobalSettings="True" />
</VisualStudio>
</ProjectExtensions>
</Project> \ 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 414006f3a..5de763df3 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Themes/Generic.xaml
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Themes/Generic.xaml
@@ -141,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;
+ }
+ }
+ }
+}