aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Stubs
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-19 23:12:56 +0300
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2020-04-19 23:12:56 +0300
commit9b7875d904456c34c3698d7fc569078f99ed5187 (patch)
treecb6ef38d0f2bde6b78d241e6a9a1ec4ba49ec82f /Software/Visual_Studio/Tango.Stubs
parent6e172dd3bc3e2388e532fd43381896f15abaed70 (diff)
downloadTango-9b7875d904456c34c3698d7fc569078f99ed5187.tar.gz
Tango-9b7875d904456c34c3698d7fc569078f99ed5187.zip
Scripting refactoring.
Diffstat (limited to 'Software/Visual_Studio/Tango.Stubs')
-rw-r--r--Software/Visual_Studio/Tango.Stubs/CSharp-Mode.xshd298
-rw-r--r--Software/Visual_Studio/Tango.Stubs/Controls/ScriptEditorControl.xaml113
-rw-r--r--Software/Visual_Studio/Tango.Stubs/Controls/ScriptEditorControl.xaml.cs488
-rw-r--r--Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj14
-rw-r--r--Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml3
5 files changed, 914 insertions, 2 deletions
diff --git a/Software/Visual_Studio/Tango.Stubs/CSharp-Mode.xshd b/Software/Visual_Studio/Tango.Stubs/CSharp-Mode.xshd
new file mode 100644
index 000000000..cb2520461
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Stubs/CSharp-Mode.xshd
@@ -0,0 +1,298 @@
+<?xml version="1.0"?>
+<SyntaxDefinition name="C#" extensions=".cs" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008">
+ <!-- The named colors 'Comment' and 'String' are used in SharpDevelop to detect if a line is inside a multiline string/comment -->
+ <Color name="Comment" foreground="#608B4E" exampleText="// comment" />
+ <Color name="String" foreground="#C67070" exampleText="string text = &quot;Hello, World!&quot;"/>
+ <Color name="Char" foreground="#C67070" exampleText="char linefeed = '\n';"/>
+ <Color name="Preprocessor" foreground="DimGray" exampleText="#region Title" />
+ <Color name="Punctuation" exampleText="a(b.c);" />
+ <Color name="ValueTypes" fontWeight="bold" foreground="#025DB4" exampleText="bool b = true;" />
+ <Color name="ReferenceTypes" foreground="#4EC9B0" exampleText="object o;" />
+ <Color name="MethodCall" foreground="Gainsboro" fontWeight="bold" exampleText="o.ToString();"/>
+ <Color name="NumberLiteral" foreground="#E7CA6C" exampleText="3.1415f"/>
+ <Color name="ThisOrBaseReference" fontWeight="bold" exampleText="this.Do(); base.Do();"/>
+ <Color name="NullOrValueKeywords" fontWeight="bold" exampleText="if (value == null)"/>
+ <Color name="Keywords" fontWeight="bold" foreground="#025DB4" exampleText="if (a) {} else {}"/>
+ <Color name="GotoKeywords" foreground="#3F8FD6" exampleText="continue; return null;"/>
+ <Color name="ContextKeywords" foreground="#3F8FD6" exampleText="var a = from x in y select z;"/>
+ <Color name="ExceptionKeywords" fontWeight="bold" foreground="#3F8FD6" exampleText="try {} catch {} finally {}"/>
+ <Color name="CheckedKeyword" fontWeight="bold" foreground="DarkGray" exampleText="checked {}"/>
+ <Color name="UnsafeKeywords" foreground="#3F8FD6" exampleText="unsafe { fixed (..) {} }"/>
+ <Color name="OperatorKeywords" fontWeight="bold" foreground="Pink" exampleText="public static implicit operator..."/>
+ <Color name="ParameterModifiers" fontWeight="bold" foreground="DeepPink" exampleText="(ref int a, params int[] b)"/>
+ <Color name="Modifiers" foreground="#3F8FD6" exampleText="static readonly int a;"/>
+ <Color name="CustomTypes" foreground="#3F8FD6" />
+ <Color name="Visibility" fontWeight="bold" foreground="#3F8FD6" exampleText="public override void ToString();"/>
+ <Color name="NamespaceKeywords" fontWeight="bold" foreground="#569CD6" exampleText="namespace A.B { using System; }"/>
+ <Color name="GetSetAddRemove" foreground="#3F8FD6" exampleText="int Prop { get; set; }"/>
+ <Color name="TrueFalse" fontWeight="bold" foreground="#3F8FD6" exampleText="b = false; a = true;" />
+ <Color name="TypeKeywords" fontWeight="bold" foreground="#3F8FD6" exampleText="if (x is int) { a = x as int; type = typeof(int); size = sizeof(int); c = new object(); }"/>
+
+ <Property name="DocCommentMarker" value="///" />
+
+ <RuleSet name="CommentMarkerSet">
+ <Keywords fontWeight="bold" foreground="Red">
+ <Word>TODO</Word>
+ <Word>FIXME</Word>
+ </Keywords>
+ <Keywords fontWeight="bold" foreground="#E0E000">
+ <Word>HACK</Word>
+ <Word>UNDONE</Word>
+ </Keywords>
+ </RuleSet>
+
+ <!-- This is the main ruleset. -->
+ <RuleSet>
+ <Span color="Preprocessor">
+ <Begin>\#</Begin>
+ <RuleSet name="PreprocessorSet">
+ <Span> <!-- preprocessor directives that allows comments -->
+ <Begin fontWeight="bold">
+ (define|undef|if|elif|else|endif|line)\b
+ </Begin>
+ <RuleSet>
+ <Span color="Comment" ruleSet="CommentMarkerSet">
+ <Begin>//</Begin>
+ </Span>
+ </RuleSet>
+ </Span>
+ <Span> <!-- preprocessor directives that don't allow comments -->
+ <Begin fontWeight="bold">
+ (region|endregion|error|warning|pragma)\b
+ </Begin>
+ </Span>
+ </RuleSet>
+ </Span>
+
+ <Span color="Comment">
+ <Begin color="XmlDoc/DocComment">///</Begin>
+ <RuleSet>
+ <Import ruleSet="XmlDoc/DocCommentSet"/>
+ <Import ruleSet="CommentMarkerSet"/>
+ </RuleSet>
+ </Span>
+
+ <Span color="Comment" ruleSet="CommentMarkerSet">
+ <Begin>//</Begin>
+ </Span>
+
+ <Span color="Comment" ruleSet="CommentMarkerSet" multiline="true">
+ <Begin>/\*</Begin>
+ <End>\*/</End>
+ </Span>
+
+ <Span color="String">
+ <Begin>"</Begin>
+ <End>"</End>
+ <RuleSet>
+ <!-- span for escape sequences -->
+ <Span begin="\\" end="."/>
+ </RuleSet>
+ </Span>
+
+ <Span color="Char">
+ <Begin>'</Begin>
+ <End>'</End>
+ <RuleSet>
+ <!-- span for escape sequences -->
+ <Span begin="\\" end="."/>
+ </RuleSet>
+ </Span>
+
+ <Span color="String" multiline="true">
+ <Begin>@"</Begin>
+ <End>"</End>
+ <RuleSet>
+ <!-- span for escape sequences -->
+ <Span begin='""' end=""/>
+ </RuleSet>
+ </Span>
+
+ <!-- don't highlight "@int" as keyword -->
+ <Rule>
+ @[\w\d_]+
+ </Rule>
+
+ <Keywords color="CustomTypes">
+ @CUSTOM_TYPES@
+ </Keywords>
+
+ <Keywords color="ThisOrBaseReference">
+ <Word>this</Word>
+ <Word>base</Word>
+ </Keywords>
+
+ <Keywords color="TypeKeywords">
+ <Word>as</Word>
+ <Word>is</Word>
+ <Word>new</Word>
+ <Word>sizeof</Word>
+ <Word>typeof</Word>
+ <Word>stackalloc</Word>
+ </Keywords>
+
+ <Keywords color="TrueFalse">
+ <Word>true</Word>
+ <Word>false</Word>
+ </Keywords>
+
+ <Keywords color="Keywords">
+ <Word>else</Word>
+ <Word>if</Word>
+ <Word>switch</Word>
+ <Word>case</Word>
+ <Word>default</Word>
+ <Word>do</Word>
+ <Word>for</Word>
+ <Word>foreach</Word>
+ <Word>in</Word>
+ <Word>while</Word>
+ <Word>lock</Word>
+ </Keywords>
+
+ <Keywords color="GotoKeywords">
+ <Word>break</Word>
+ <Word>continue</Word>
+ <Word>goto</Word>
+ <Word>return</Word>
+ </Keywords>
+
+ <Keywords color="ContextKeywords">
+ <Word>yield</Word>
+ <Word>partial</Word>
+ <Word>global</Word>
+ <Word>where</Word>
+ <Word>select</Word>
+ <Word>group</Word>
+ <Word>by</Word>
+ <Word>into</Word>
+ <Word>from</Word>
+ <Word>ascending</Word>
+ <Word>descending</Word>
+ <Word>orderby</Word>
+ <Word>let</Word>
+ <Word>join</Word>
+ <Word>on</Word>
+ <Word>equals</Word>
+ <Word>var</Word>
+ <Word>dynamic</Word>
+ <Word>await</Word>
+ </Keywords>
+
+ <Keywords color="ExceptionKeywords">
+ <Word>try</Word>
+ <Word>throw</Word>
+ <Word>catch</Word>
+ <Word>finally</Word>
+ </Keywords>
+
+ <Keywords color="CheckedKeyword">
+ <Word>checked</Word>
+ <Word>unchecked</Word>
+ </Keywords>
+
+ <Keywords color="UnsafeKeywords">
+ <Word>fixed</Word>
+ <Word>unsafe</Word>
+ </Keywords>
+
+ <Keywords color="ValueTypes">
+ <Word>bool</Word>
+ <Word>byte</Word>
+ <Word>char</Word>
+ <Word>decimal</Word>
+ <Word>double</Word>
+ <Word>enum</Word>
+ <Word>float</Word>
+ <Word>int</Word>
+ <Word>long</Word>
+ <Word>sbyte</Word>
+ <Word>short</Word>
+ <Word>struct</Word>
+ <Word>uint</Word>
+ <Word>ushort</Word>
+ <Word>ulong</Word>
+ </Keywords>
+
+ <Keywords color="ReferenceTypes">
+ <Word>class</Word>
+ <Word>interface</Word>
+ <Word>delegate</Word>
+ <Word>object</Word>
+ <Word>string</Word>
+ <Word>void</Word>
+ </Keywords>
+
+ <Keywords color="OperatorKeywords">
+ <Word>explicit</Word>
+ <Word>implicit</Word>
+ <Word>operator</Word>
+ </Keywords>
+
+ <Keywords color="ParameterModifiers">
+ <Word>params</Word>
+ <Word>ref</Word>
+ <Word>out</Word>
+ </Keywords>
+
+ <Keywords color="Modifiers">
+ <Word>abstract</Word>
+ <Word>const</Word>
+ <Word>event</Word>
+ <Word>extern</Word>
+ <Word>override</Word>
+ <Word>readonly</Word>
+ <Word>sealed</Word>
+ <Word>static</Word>
+ <Word>virtual</Word>
+ <Word>volatile</Word>
+ <Word>async</Word>
+ </Keywords>
+
+ <Keywords color="Visibility">
+ <Word>public</Word>
+ <Word>protected</Word>
+ <Word>private</Word>
+ <Word>internal</Word>
+ </Keywords>
+
+ <Keywords color="NamespaceKeywords">
+ <Word>namespace</Word>
+ <Word>using</Word>
+ <Word>include</Word>
+ </Keywords>
+
+ <Keywords color="GetSetAddRemove">
+ <Word>get</Word>
+ <Word>set</Word>
+ <Word>add</Word>
+ <Word>remove</Word>
+ </Keywords>
+
+ <Keywords color="NullOrValueKeywords">
+ <Word>null</Word>
+ <Word>value</Word>
+ </Keywords>
+
+ <!-- Mark previous rule-->
+ <Rule color="MethodCall">
+ \b
+ [\d\w_]+ # an identifier
+ (?=\s*\() # followed by (
+ </Rule>
+
+ <!-- Digits -->
+ <Rule color="NumberLiteral">
+ \b0[xX][0-9a-fA-F]+ # hex number
+ |
+ ( \b\d+(\.[0-9]+)? #number with optional floating point
+ | \.[0-9]+ #or just starting with floating point
+ )
+ ([eE][+-]?[0-9]+)? # optional exponent
+ </Rule>
+
+ <Rule color="Punctuation">
+ [?,.;()\[\]{}+\-/%*&lt;&gt;^+~!|&amp;]+
+ </Rule>
+ </RuleSet>
+</SyntaxDefinition>
diff --git a/Software/Visual_Studio/Tango.Stubs/Controls/ScriptEditorControl.xaml b/Software/Visual_Studio/Tango.Stubs/Controls/ScriptEditorControl.xaml
new file mode 100644
index 000000000..3c8796eca
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Stubs/Controls/ScriptEditorControl.xaml
@@ -0,0 +1,113 @@
+<UserControl x:Class="Tango.Stubs.Controls.ScriptEditorControl"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:fa="http://schemas.fontawesome.io/icons/"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ mc:Ignorable="d"
+ d:DesignHeight="400" d:DesignWidth="600" Background="#151515">
+
+ <UserControl.InputBindings>
+ <KeyBinding Key="F5" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=RunCommand}" />
+ </UserControl.InputBindings>
+
+ <Grid>
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="40"/>
+ <RowDefinition Height="1*"/>
+ </Grid.RowDefinitions>
+ <Border BorderThickness="0 0 0 1" BorderBrush="#545454">
+ <ToolBar Background="#202020">
+ <StackPanel Margin="20 0 0 0" Orientation="Horizontal">
+ <Button Cursor="Hand" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=SaveCommand}" ToolTip="Save" Style="{DynamicResource MetroCircleButtonStyle}" Width="16" Height="16">
+ <fa:ImageAwesome Icon="Save" Foreground="LightGray"></fa:ImageAwesome>
+ </Button>
+ <Rectangle Margin="20 7 10 5" HorizontalAlignment="Center" VerticalAlignment="Stretch" Stroke="#3E3E3E" StrokeThickness="2"></Rectangle>
+ <Button Cursor="Hand" Command="Undo" Margin="10 0 0 0" ToolTip="Undo" Style="{DynamicResource MetroCircleButtonStyle}" Width="16" Height="16">
+ <fa:ImageAwesome Icon="Undo" Foreground="LightGray"></fa:ImageAwesome>
+ </Button>
+ <Button Cursor="Hand" Command="Redo" Margin="10 0 0 0" ToolTip="Redo" Style="{DynamicResource MetroCircleButtonStyle}" Width="16" Height="16">
+ <fa:ImageAwesome Icon="Repeat" Foreground="LightGray"></fa:ImageAwesome>
+ </Button>
+ <Rectangle Margin="20 7 10 5" HorizontalAlignment="Center" VerticalAlignment="Stretch" Stroke="#3E3E3E" StrokeThickness="2"></Rectangle>
+ <Button Cursor="Hand" Command="Cut" Margin="10 0 0 0" ToolTip="Cut" Style="{DynamicResource MetroCircleButtonStyle}" Width="16" Height="16">
+ <fa:ImageAwesome Icon="Cut" Foreground="LightGray"></fa:ImageAwesome>
+ </Button>
+ <Button Cursor="Hand" Command="Copy" Margin="10 0 0 0" ToolTip="Copy" Style="{DynamicResource MetroCircleButtonStyle}" Width="20" Height="16">
+ <fa:ImageAwesome Icon="Copy" Foreground="LightGray"></fa:ImageAwesome>
+ </Button>
+ <Button Cursor="Hand" Command="Paste" Margin="10 0 0 0" ToolTip="Paste" Style="{DynamicResource MetroCircleButtonStyle}" Width="16" Height="20">
+ <fa:ImageAwesome Icon="Paste" Foreground="LightGray"></fa:ImageAwesome>
+ </Button>
+ <Rectangle Margin="20 7 10 5" HorizontalAlignment="Center" VerticalAlignment="Stretch" Stroke="#3E3E3E" StrokeThickness="2"></Rectangle>
+ <Button Cursor="Hand" Margin="10 0 0 0" ToolTip="Run (F5)" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=RunCommand}" Style="{DynamicResource MetroCircleButtonStyle}" Width="16" Height="16">
+ <fa:ImageAwesome Icon="Play">
+ <fa:ImageAwesome.Style>
+ <Style TargetType="fa:ImageAwesome">
+ <Setter Property="Foreground" Value="#8DD28A"></Setter>
+ <Style.Triggers>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter Property="Foreground" Value="Gray"></Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </fa:ImageAwesome.Style>
+ </fa:ImageAwesome>
+ </Button>
+ <Button Cursor="Hand" Margin="15 0 0 0" ToolTip="Stop" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=StopCommand}" Style="{DynamicResource MetroCircleButtonStyle}" Width="14" Height="14">
+ <fa:ImageAwesome Icon="Stop">
+ <fa:ImageAwesome.Style>
+ <Style TargetType="fa:ImageAwesome">
+ <Setter Property="Foreground" Value="#F38B76"></Setter>
+ <Style.Triggers>
+ <Trigger Property="IsEnabled" Value="False">
+ <Setter Property="Foreground" Value="Gray"></Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </fa:ImageAwesome.Style>
+ </fa:ImageAwesome>
+ </Button>
+ </StackPanel>
+ </ToolBar>
+ </Border>
+
+ <Border Grid.Row="1" CornerRadius="5" BorderThickness="0" BorderBrush="#404040">
+ <avalonEdit:TextEditor Padding="5" TextChanged="textEditor_TextChanged" Background="#151515" Foreground="Gainsboro" Margin="5 5 0 0" ScrollViewer.HorizontalScrollBarVisibility="Auto"
+ Name="textEditor"
+ FontFamily="Consolas"
+ FontSize="10pt"
+ SyntaxHighlighting="C#"
+ ShowLineNumbers="True">
+ <avalonEdit:TextEditor.ContextMenu>
+ <ContextMenu>
+ <ContextMenu.Resources>
+ <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}">
+ <Setter Property="Foreground" Value="Gainsboro"></Setter>
+ </Style>
+ </ContextMenu.Resources>
+ <MenuItem Header="Cut" MinWidth="150" Command="Cut">
+ <MenuItem.Icon>
+ <fa:ImageAwesome Icon="Cut" Width="12" Foreground="Gainsboro" Margin="2" />
+ </MenuItem.Icon>
+ </MenuItem>
+ <Separator/>
+ <MenuItem Header="Copy" Command="Copy">
+ <MenuItem.Icon>
+ <fa:ImageAwesome Icon="Copy" Width="12" Foreground="Gainsboro" Margin="2" />
+ </MenuItem.Icon>
+ </MenuItem>
+ <MenuItem Header="Paste" Command="Paste">
+ <MenuItem.Icon>
+ <fa:ImageAwesome Icon="Paste" Width="12" Foreground="Gainsboro" Margin="2" />
+ </MenuItem.Icon>
+ </MenuItem>
+ </ContextMenu>
+ </avalonEdit:TextEditor.ContextMenu>
+ </avalonEdit:TextEditor>
+ </Border>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/Tango.Stubs/Controls/ScriptEditorControl.xaml.cs b/Software/Visual_Studio/Tango.Stubs/Controls/ScriptEditorControl.xaml.cs
new file mode 100644
index 000000000..7628e5655
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Stubs/Controls/ScriptEditorControl.xaml.cs
@@ -0,0 +1,488 @@
+using ICSharpCode.AvalonEdit.CodeCompletion;
+using ICSharpCode.AvalonEdit.Document;
+using ICSharpCode.AvalonEdit.Editing;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using System.Windows.Threading;
+using System.Xml;
+using Tango.Core.Commands;
+using Tango.Scripting;
+using Tango.SharedUI;
+using Tango.SharedUI.Helpers;
+
+namespace Tango.Stubs.Controls
+{
+ /// <summary>
+ /// Represents a C# script editor control.
+ /// </summary>
+ /// <seealso cref="System.Windows.Controls.UserControl" />
+ /// <seealso cref="System.Windows.Markup.IComponentConnector" />
+ public partial class ScriptEditorControl : UserControl
+ {
+ #region Completion
+
+ /// <summary>
+ /// Represents an auto complete item.
+ /// </summary>
+ /// <seealso cref="ICSharpCode.AvalonEdit.CodeCompletion.ICompletionData" />
+ internal class CompletionData : ICompletionData
+ {
+ private String _description;
+
+ /// <summary>
+ /// Gets or sets the icon source.
+ /// </summary>
+ public BitmapSource Source { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CompletionData"/> class.
+ /// </summary>
+ /// <param name="text">The text.</param>
+ /// <param name="description">The description.</param>
+ public CompletionData(string text, String description)
+ {
+ this.Text = text;
+ _description = description;
+ }
+
+ /// <summary>
+ /// Gets the image.
+ /// </summary>
+ public System.Windows.Media.ImageSource Image
+ {
+ get { return Source; }
+ }
+
+ /// <summary>
+ /// Gets the text. This property is used to filter the list of visible elements.
+ /// </summary>
+ public string Text { get; private set; }
+
+ // Use this property if you want to show a fancy UIElement in the drop down list.
+ public object Content
+ {
+ get { return this.Text; }
+ }
+
+ /// <summary>
+ /// Gets the description.
+ /// </summary>
+ public object Description
+ {
+ get { return _description; }
+ }
+
+ /// <summary>
+ /// Gets the priority. This property is used in the selection logic. You can use it to prefer selecting those items
+ /// which the user is accessing most frequently.
+ /// </summary>
+ public double Priority { get { return 0; } }
+
+ /// <summary>
+ /// Perform the completion.
+ /// </summary>
+ /// <param name="textArea">The text area on which completion is performed.</param>
+ /// <param name="completionSegment">The text segment that was used by the completion window if
+ /// the user types (segment between CompletionWindow.StartOffset and CompletionWindow.EndOffset).</param>
+ /// <param name="insertionRequestEventArgs">The EventArgs used for the insertion request.
+ /// These can be TextCompositionEventArgs, KeyEventArgs, MouseEventArgs, depending on how
+ /// the insertion was triggered.</param>
+ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs)
+ {
+ textArea.Document.Replace(completionSegment, this.Text);
+ }
+
+ /// <summary>
+ /// Returns a <see cref="System.String" /> that represents this instance.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="System.String" /> that represents this instance.
+ /// </returns>
+ public override string ToString()
+ {
+ return Text;
+ }
+ }
+
+ #endregion
+
+ private CompletionWindow completionWindow; //Holds the auto-complete window instance.
+
+ #region Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ScriptEditorControl"/> class.
+ /// </summary>
+ public ScriptEditorControl()
+ {
+ InitializeComponent();
+
+ textEditor.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.CSharp.CSharpIndentationStrategy();
+ textEditor.TextArea.TextEntering += textEditor_TextArea_TextEntering;
+ textEditor.TextArea.TextEntered += textEditor_TextArea_TextEntered;
+
+ this.Loaded += ScriptEditorControl_Loaded;
+ }
+
+ #endregion
+
+ #region Event Handlers
+
+ /// <summary>
+ /// Handles the TextEntered event of the textEditor_TextArea control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="TextCompositionEventArgs"/> instance containing the event data.</param>
+ private void textEditor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
+ {
+ if (e.Text == ".")
+ {
+ String keyword = textEditor.TextArea.GetJustCurrentWord();
+
+ if (keyword != null)
+ {
+ completionWindow = new CompletionWindow(textEditor.TextArea);
+ completionWindow.WindowStyle = WindowStyle.None;
+ completionWindow.AllowsTransparency = true;
+ completionWindow.ResizeMode = ResizeMode.NoResize;
+
+ IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
+
+ bool ok = false;
+
+ List<KeyValuePair<String, Type>> types = new List<KeyValuePair<String, Type>>();
+
+ types.AddRange(IntellisenseTypes);
+
+
+ if (IntellisenseTypes != null)
+ {
+ ScriptParser parser = new ScriptParser();
+
+ try
+ {
+ var variables = parser.ParseScript(textEditor.Text);
+
+ foreach (var v in variables)
+ {
+ var hT = IntellisenseTypes.SingleOrDefault(x => x.Key == v.Type);
+
+ if (hT.Value != null)
+ {
+ types.Add(new KeyValuePair<string, Type>(v.Name, hT.Value));
+ }
+ }
+
+ }
+ catch { }
+ }
+
+ KeyValuePair<String, Type> type = types.LastOrDefault(x => keyword == x.Key);
+
+ if (type.Key != null)
+ {
+ ok = true;
+ FillType(type.Value, data);
+ }
+
+ if (ok)
+ {
+ completionWindow.Show();
+ completionWindow.Closed += delegate
+ {
+ completionWindow = null;
+ };
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Handles the TextEntering event of the textEditor_TextArea control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="TextCompositionEventArgs"/> instance containing the event data.</param>
+ private void textEditor_TextArea_TextEntering(object sender, TextCompositionEventArgs e)
+ {
+ if (e.Text.Length > 0 && completionWindow != null)
+ {
+ if (!char.IsLetterOrDigit(e.Text[0]))
+ {
+ // Whenever a non-letter is typed while the completion window is open,
+ // insert the currently selected element.
+ completionWindow.CompletionList.RequestInsertion(e);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Handles the TextChanged event of the textEditor control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
+ private void textEditor_TextChanged(object sender, EventArgs e)
+ {
+ Text = textEditor.Text;
+ }
+
+ private void ScriptEditorControl_Loaded(object sender, RoutedEventArgs e)
+ {
+ if (HighlightTypes != null)
+ {
+ Stream xshd_stream = typeof(ScriptEditorControl).Assembly.GetManifestResourceStream("Tango.Stubs.CSharp-Mode.xshd");
+
+ String text = String.Empty;
+
+ using (StreamReader reader = new StreamReader(xshd_stream))
+ {
+ text = reader.ReadToEnd();
+ }
+
+ String code = String.Empty;
+
+
+
+ foreach (var name in HighlightTypes.Select(x => x.Key))
+ {
+ code += String.Format("<Word>{0}</Word>", name) + Environment.NewLine;
+ }
+
+ text = text.Replace("@CUSTOM_TYPES@", code);
+
+ using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(text)))
+ {
+ XmlTextReader xshd_reader = new XmlTextReader(ms);
+ textEditor.SyntaxHighlighting = ICSharpCode.AvalonEdit.Highlighting.Xshd.HighlightingLoader.Load(xshd_reader, ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance);
+ xshd_reader.Close();
+ }
+ }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ /// <summary>
+ /// Fills the type.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <param name="data">The data.</param>
+ private void FillType(Type type, IList<ICompletionData> data)
+ {
+ List<CompletionData> items = new List<CompletionData>();
+
+ foreach (var method in type.GetMethods().Where(x => x.IsPublic && !x.IsSpecialName))
+ {
+ String desc = method.ReturnType.Name + " " + method.Name + "(" + String.Join(", ", method.GetParameters().Select(x => x.ParameterType.Name + " " + x.Name).ToArray()) + ")";
+ items.Add(new CompletionData(method.Name, desc) { Source = ResourceHelper.GetImageFromResources("Images/pubmethod.gif") });
+ }
+ foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
+ {
+ String desc = property.PropertyType.Name + " " + property.Name;
+ items.Add(new CompletionData(property.Name, desc) { Source = ResourceHelper.GetImageFromResources("Images/pubproperty.gif") });
+ }
+ foreach (var ev in type.GetEvents(BindingFlags.Instance | BindingFlags.Public))
+ {
+ try
+ {
+ String desc = ev.Name + " " + "(" + String.Join(", ", ev.EventHandlerType.GetMethod("Invoke").GetParameters().Select(x => x.ParameterType.Name + " " + x.Name).ToArray()) + ")";
+ items.Add(new CompletionData(ev.Name, desc) { Source = ResourceHelper.GetImageFromResources("Images/pubevent.gif") });
+ }
+ catch { }
+ }
+
+ foreach (var item in items.OrderBy(x => x.Text))
+ {
+ data.Add(item);
+ }
+ }
+
+ /// <summary>
+ /// Fills the assembly.
+ /// </summary>
+ /// <param name="asm">The asm.</param>
+ /// <param name="data">The data.</param>
+ private void FillAssembly(Assembly asm, IList<ICompletionData> data)
+ {
+ var q = from t in asm.GetTypes()
+ where t.IsClass
+ select t;
+
+ foreach (var type in q)
+ {
+ data.Add(new CompletionData(type.Name, "Class") { Source = ResourceHelper.GetImageFromResources("Images/pubclass.gif") });
+ }
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the text.
+ /// </summary>
+ public String Text
+ {
+ get { return (String)GetValue(TextProperty); }
+ set { SetValue(TextProperty, value); }
+ }
+ public static readonly DependencyProperty TextProperty =
+ DependencyProperty.Register("Text", typeof(String), typeof(ScriptEditorControl), new PropertyMetadata(null, (d, e) => (d as ScriptEditorControl).OnTextChanged()));
+
+ /// <summary>
+ /// Gets or sets the highlight types.
+ /// </summary>
+ public ObservableCollection<KeyValuePair<string, Type>> HighlightTypes
+ {
+ get { return (ObservableCollection<KeyValuePair<string, Type>>)GetValue(HighlightTypesProperty); }
+ set { SetValue(HighlightTypesProperty, value); }
+ }
+ public static readonly DependencyProperty HighlightTypesProperty =
+ DependencyProperty.Register("HighlightTypes", typeof(ObservableCollection<KeyValuePair<string, Type>>), typeof(ScriptEditorControl), new PropertyMetadata(null));
+
+ /// <summary>
+ /// Gets or sets the intellisense types.
+ /// </summary>
+ public ObservableCollection<KeyValuePair<String,Type>> IntellisenseTypes
+ {
+ get { return (ObservableCollection<KeyValuePair<String,Type>>)GetValue(IntellisenseTypesProperty); }
+ set { SetValue(IntellisenseTypesProperty, value); }
+ }
+ public static readonly DependencyProperty IntellisenseTypesProperty =
+ DependencyProperty.Register("IntellisenseTypes", typeof(ObservableCollection<KeyValuePair<String,Type>>), typeof(ScriptEditorControl), new PropertyMetadata(null));
+
+
+ #endregion
+
+ #region Virtual Methods
+
+ /// <summary>
+ /// Called when the text has changed.
+ /// </summary>
+ protected virtual void OnTextChanged()
+ {
+ if (textEditor.Text != Text)
+ {
+ textEditor.Text = Text;
+ }
+ }
+
+ /// <summary>
+ /// Called when the insert script command has changed.
+ /// </summary>
+ protected virtual void OnInsertScriptCommandChanged()
+ {
+ if (InsertSnippetCommand != null)
+ {
+ InsertSnippetCommand.Executed += (x, snippet) =>
+ {
+ textEditor.Document.Insert(textEditor.TextArea.Caret.Offset, snippet);
+ };
+ }
+ }
+
+ #endregion
+
+ #region Commands
+
+ /// <summary>
+ /// Gets or sets the run command.
+ /// </summary>
+ public RelayCommand RunCommand
+ {
+ get { return (RelayCommand)GetValue(RunCommandProperty); }
+ set { SetValue(RunCommandProperty, value); }
+ }
+ public static readonly DependencyProperty RunCommandProperty =
+ DependencyProperty.Register("RunCommand", typeof(RelayCommand), typeof(ScriptEditorControl), new PropertyMetadata(null));
+
+ /// <summary>
+ /// Gets or sets the stop command.
+ /// </summary>
+ public RelayCommand StopCommand
+ {
+ get { return (RelayCommand)GetValue(StopCommandProperty); }
+ set { SetValue(StopCommandProperty, value); }
+ }
+ public static readonly DependencyProperty StopCommandProperty =
+ DependencyProperty.Register("StopCommand", typeof(RelayCommand), typeof(ScriptEditorControl), new PropertyMetadata(null));
+
+ /// <summary>
+ /// Gets or sets the save command.
+ /// </summary>
+ public RelayCommand SaveCommand
+ {
+ get { return (RelayCommand)GetValue(SaveCommandProperty); }
+ set { SetValue(SaveCommandProperty, value); }
+ }
+ public static readonly DependencyProperty SaveCommandProperty =
+ DependencyProperty.Register("SaveCommand", typeof(RelayCommand), typeof(ScriptEditorControl), new PropertyMetadata(null));
+
+ /// <summary>
+ /// Gets or sets the insert snippet command.
+ /// </summary>
+ public RelayCommand<String> InsertSnippetCommand
+ {
+ get { return (RelayCommand<String>)GetValue(InsertSnippetCommandProperty); }
+ set { SetValue(InsertSnippetCommandProperty, value); }
+ }
+ public static readonly DependencyProperty InsertSnippetCommandProperty =
+ DependencyProperty.Register("InsertSnippetCommand", typeof(RelayCommand<String>), typeof(ScriptEditorControl), new PropertyMetadata(null, (d, e) => (d as ScriptEditorControl).OnInsertScriptCommandChanged()));
+
+ #endregion
+ }
+
+ internal static class DocumentUtils
+ {
+ private static Regex _wordRegex = new Regex(@"[^\W\d][\w]*(?<=\w)", RegexOptions.Compiled);
+
+ public static string GetJustCurrentWord(this TextArea textArea)
+ {
+ try
+ {
+ DocumentLine line = textArea.Document.GetLineByNumber(textArea.Caret.Line);
+ if (line.Length == 0)
+ return null;
+
+ int lineCaretPosition = textArea.Caret.Offset - line.Offset;
+ String l = textArea.Document.GetText(line);
+
+ String trimmed = l.Remove(lineCaretPosition, l.Length - lineCaretPosition);
+
+ return SplitToWords(trimmed).LastOrDefault(x => !String.IsNullOrWhiteSpace(x));
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ public static List<String> SplitToWords(String text)
+ {
+ text = text.Replace(".", " ");
+ text = text.Replace("(", " ");
+ text = text.Replace(")", " ");
+ text = text.Replace(",", " ");
+ var punctuation = text.Where(Char.IsPunctuation).Distinct().ToArray();
+ var words = text.Split().Select(x => x.Trim(punctuation));
+ return words.ToList();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj b/Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj
index 828248c9b..80c63b5d4 100644
--- a/Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj
+++ b/Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj
@@ -96,12 +96,16 @@
<Link>GlobalVersionInfo.cs</Link>
</Compile>
<Compile Include="ConnectionMode.cs" />
+ <Compile Include="Controls\ScriptEditorControl.xaml.cs">
+ <DependentUpon>ScriptEditorControl.xaml</DependentUpon>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
+ <EmbeddedResource Include="CSharp-Mode.xshd" />
<None Include="Resources\CodeTabTemplate.cs" />
<Compile Include="ViewModels\CodeTabVM.cs" />
<Compile Include="ViewModels\CreateGroupVM.cs" />
@@ -124,6 +128,10 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\SideChains\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj">
+ <Project>{6c55b776-26d4-4db3-a6ab-87e783b2f3d1}</Project>
+ <Name>ICSharpCode.AvalonEdit</Name>
+ </ProjectReference>
<ProjectReference Include="..\Tango.BL\Tango.BL.csproj">
<Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project>
<Name>Tango.BL</Name>
@@ -174,6 +182,10 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
+ <Page Include="Controls\ScriptEditorControl.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
<Page Include="Views\StubsView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -186,7 +198,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml b/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml
index 456a6718f..00dc806e3 100644
--- a/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml
+++ b/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml
@@ -11,6 +11,7 @@
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
+ xmlns:localControls="clr-namespace:Tango.Stubs.Controls"
xmlns:transport="clr-namespace:Tango.Transport.Adapters;assembly=Tango.Transport"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1280" Background="#202020" Foreground="Gainsboro" d:DataContext="{d:DesignInstance Type=vm:StubsViewVM, IsDesignTimeCreatable=False}">
@@ -82,7 +83,7 @@
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
- <controls:ScriptEditorControl Text="{Binding Code,Mode=TwoWay}" InsertSnippetCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.InsertSnippetCommand,Mode=TwoWay}" SaveCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.SaveCommand}" HighlightTypes="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.HighlightTypes}" IntellisenseTypes="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.IntellisenseTypes}" RunCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RunCommand}" StopCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.StopCommand}" />
+ <localControls:ScriptEditorControl Text="{Binding Code,Mode=TwoWay}" InsertSnippetCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.InsertSnippetCommand,Mode=TwoWay}" SaveCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.SaveCommand}" HighlightTypes="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.HighlightTypes}" IntellisenseTypes="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.IntellisenseTypes}" RunCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RunCommand}" StopCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.StopCommand}" />
<Grid Grid.Row="1">
<Grid.Style>