aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs1
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/AddReferenceAssemblyViewVM.cs55
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/TestProject.cs22
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs240
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml226
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs16
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml1
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Basic/CompilationError.cs1
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs3
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Script.cs27
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs5
11 files changed, 486 insertions, 111 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs
index bba69bac1..ea87a4f19 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Contracts/ITestDesignerView.cs
@@ -10,5 +10,6 @@ namespace Tango.FSE.Stubs.Contracts
public interface ITestDesignerView : IFSEView
{
void FormatCode();
+ void HighlightCode(int position, int length);
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/AddReferenceAssemblyViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/AddReferenceAssemblyViewVM.cs
index aa32f6a03..cee06ed91 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/AddReferenceAssemblyViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/AddReferenceAssemblyViewVM.cs
@@ -17,6 +17,8 @@ namespace Tango.FSE.Stubs.Dialogs
{
public class AddReferenceAssemblyViewVM : FSEDialogViewVM
{
+ private List<ReferenceAssembly> _existing;
+
[TangoInject]
private IFSEApplicationManager ApplicationManager { get; set; }
@@ -24,42 +26,53 @@ namespace Tango.FSE.Stubs.Dialogs
public AddReferenceAssemblyViewVM(List<ReferenceAssembly> existing)
{
+ _existing = existing;
OKText = "DONE";
-
TangoIOC.Default.Inject(this);
+ }
- List<ReferenceAssembly> source = new List<ReferenceAssembly>();
-
- var startPath = ApplicationManager.StartPath;
+ public override void OnShow()
+ {
+ base.OnShow();
- foreach (var file in Directory.GetFiles(startPath, "*.dll"))
+ Task.Factory.StartNew(() =>
{
- if (Path.GetFileName(file).StartsWith("Tango"))
+ System.Threading.Thread.Sleep(200);
+ List<ReferenceAssembly> source = new List<ReferenceAssembly>();
+
+ var startPath = ApplicationManager.StartPath;
+
+ foreach (var file in Directory.GetFiles(startPath, "*.dll"))
{
- source.Add(ReferenceAssembly.FromFile(Path.GetFileName(file)));
+ if (Path.GetFileName(file).StartsWith("Tango"))
+ {
+ source.Add(ReferenceAssembly.FromFile(Path.GetFileName(file)));
+ }
}
- }
- String dotNetPath = AssemblyHelper.GetAssemblyTargetFrameworkFolder(Assembly.GetExecutingAssembly());
+ String dotNetPath = AssemblyHelper.GetAssemblyTargetFrameworkFolder(Assembly.GetExecutingAssembly());
- foreach (var file in Directory.GetFiles(dotNetPath, "*.dll"))
- {
- source.Add(ReferenceAssembly.FromFile(Path.GetFileName(file)));
- }
+ foreach (var file in Directory.GetFiles(dotNetPath, "*.dll"))
+ {
+ source.Add(ReferenceAssembly.FromFile(Path.GetFileName(file)));
+ }
- source = source.DistinctBy(x => x.Name).ToList();
+ source = source.DistinctBy(x => x.Name).ToList();
- List<ReferenceAssembly> existingReferences = new List<ReferenceAssembly>();
+ List<ReferenceAssembly> existingReferences = new List<ReferenceAssembly>();
- foreach (var asm in source)
- {
- if (existing.Exists(x => x.Name == asm.Name))
+ foreach (var asm in source)
{
- existingReferences.Add(asm);
+ if (_existing.Exists(x => x.Name == asm.Name))
+ {
+ existingReferences.Add(asm);
+ }
}
- }
- ReferenceAssemblies = new SelectedObjectCollection<ReferenceAssembly>(source.ToObservableCollection(), existingReferences.ToObservableCollection());
+ ReferenceAssemblies = new SelectedObjectCollection<ReferenceAssembly>(source.ToObservableCollection(), existingReferences.ToObservableCollection());
+
+ RaisePropertyChanged(nameof(ReferenceAssemblies));
+ });
}
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/TestProject.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/TestProject.cs
index 1600c9752..0bb4783dd 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/TestProject.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/TestProject.cs
@@ -1,4 +1,5 @@
using Google.Protobuf;
+using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -14,8 +15,19 @@ namespace Tango.FSE.Stubs
{
public class TestProject : Project<TestContext>
{
+ private static JsonSerializerSettings _jsonSettings;
+
public ObservableCollection<TestInput> Inputs { get; set; }
+ static TestProject()
+ {
+ _jsonSettings = new JsonSerializerSettings()
+ {
+ TypeNameHandling = TypeNameHandling.Auto,
+ PreserveReferencesHandling = PreserveReferencesHandling.All,
+ };
+ }
+
public TestProject() : base()
{
Inputs = new ObservableCollection<TestInput>();
@@ -41,5 +53,15 @@ namespace Tango.FSE.Stubs
return project;
}
+
+ public String ToJson()
+ {
+ return JsonConvert.SerializeObject(this, _jsonSettings);
+ }
+
+ public static TestProject FromJson(String json)
+ {
+ return JsonConvert.DeserializeObject<TestProject>(json, _jsonSettings);
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs
index e1fc8c539..1550da2ed 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ViewModels/TestDesignerViewVM.cs
@@ -1,7 +1,9 @@
using Google.Protobuf;
+using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -35,6 +37,10 @@ namespace Tango.FSE.Stubs.ViewModels
}
private DispatcherTimer _compileTimer;
+ private String _projectFile;
+ private String PROJECT_FILE_EXTENSION = ".tproj";
+ private String PROJECT_DIALOG_FILTER = $"Test Project Files|*.tproj";
+ private bool _isProjectChanged;
#region Properties
@@ -126,6 +132,14 @@ namespace Tango.FSE.Stubs.ViewModels
public RelayCommand AddProjectInputCommand { get; set; }
public RelayCommand<TestInput> RemoveProjectInputCommand { get; set; }
public RelayCommand FormatCodeCommand { get; set; }
+ public RelayCommand<CompilationError> HighlightErrorCommand { get; set; }
+ public RelayCommand NewProjectCommand { get; set; }
+ public RelayCommand SaveProjectCommand { get; set; }
+ public RelayCommand SaveAsProjectCommand { get; set; }
+ public RelayCommand OpenProjectCommand { get; set; }
+ public RelayCommand AddLibraryCommand { get; set; }
+ public RelayCommand<Script> DeleteLibraryCommand { get; set; }
+ public RelayCommand ClearOutputCommand { get; set; }
#endregion
@@ -136,7 +150,7 @@ namespace Tango.FSE.Stubs.ViewModels
Status = "Ready";
LoadedAssemblies = new ObservableCollection<Assembly>();
-
+ Results = new List<Result>();
CompilationErrors = new List<CompilationError>();
Logger = new TextController();
ScriptEditor.LoadingSymbolsProgress += ScriptEditor_LoadingSymbolsProgress;
@@ -156,18 +170,52 @@ namespace Tango.FSE.Stubs.ViewModels
AddProjectInputCommand = new RelayCommand(AddProjectInput);
RemoveProjectInputCommand = new RelayCommand<TestInput>(RemoveProjectInput);
FormatCodeCommand = new RelayCommand(FormatCode);
+ HighlightErrorCommand = new RelayCommand<CompilationError>(HighlightError);
+ NewProjectCommand = new RelayCommand(CreateNewProject, () => ProjectRunner == null || !ProjectRunner.IsRunning);
+ SaveProjectCommand = new RelayCommand(SaveProject);
+ SaveAsProjectCommand = new RelayCommand(SaveAsProject);
+ OpenProjectCommand = new RelayCommand(OpenProject);
+ AddLibraryCommand = new RelayCommand(AddNewLibrary);
+ ClearOutputCommand = new RelayCommand(ClearOutput);
+ DeleteLibraryCommand = new RelayCommand<Script>(DeleteLibrary);
+ }
+
+ private void HighlightError(CompilationError error)
+ {
+ var errorScript = Project.Scripts.SingleOrDefault(x => x.Name == error.File);
+
+ if (errorScript != null)
+ {
+ OpenScript(errorScript);
+ View.HighlightCode(error.Position, error.Length);
+ }
+ }
+
+ private void FormatCode()
+ {
+ View.FormatCode();
+ }
+
+ #endregion
+ #region Override Methods
+
+ public override void OnApplicationStarted()
+ {
_compileTimer = new DispatcherTimer(DispatcherPriority.ApplicationIdle);
_compileTimer.Interval = TimeSpan.FromSeconds(2);
_compileTimer.Tick += _compileTimer_Tick;
_compileTimer.Start();
-
- CreateNewProject();
}
- private void FormatCode()
+ public override void OnNavigatedTo()
{
- View.FormatCode();
+ base.OnNavigatedTo();
+
+ if (Project == null)
+ {
+ CreateStartupProject();
+ }
}
#endregion
@@ -293,6 +341,12 @@ namespace Tango.FSE.Stubs.ViewModels
SelectedScript = script;
}
+ private void ClearOpenedScripts()
+ {
+ OpenScripts.Clear();
+ SelectedScript = null;
+ }
+
#endregion
#region Event Handlers
@@ -337,22 +391,130 @@ namespace Tango.FSE.Stubs.ViewModels
Project.ReferenceAssemblies.Add(asm);
}
+ _isProjectChanged = true;
+
LoadReferenceAssemblies();
}
}
- private void CreateNewProject()
+ private async void CreateNewProject()
{
- Project = TestProject.New("test1");
- LoadReferenceAssemblies();
+ if (await CheckDiscardProjectChanges())
+ {
+ var result = await NotificationProvider.ShowInputBox("New Project", "Please specify the project name", PackIconKind.TestTube, "untitled", "Project Name", 100, "CREATE");
+ if (result.Confirmed)
+ {
+ Project = TestProject.New(result.Input);
+ _projectFile = null;
+ }
+ }
+ }
+
+ private void CreateStartupProject()
+ {
+ Project = TestProject.New("untitled");
+ _projectFile = null;
+ }
+
+ private void SaveProject()
+ {
+ if (Project != null)
+ {
+ if (_projectFile == null)
+ {
+ SaveAsProject();
+ return;
+ }
+
+ try
+ {
+ Status = "Saving project...";
+
+ File.WriteAllText(_projectFile, Project.ToJson());
+
+ Status = "Project saved.";
+
+ Project.Scripts.ToList().ForEach(x => x.IsChanged = false);
+ }
+ catch (Exception ex)
+ {
+ NotificationProvider.ShowError($"Error saving project\n{ex.FlattenMessage()}");
+ Status = "Ready";
+ }
+ }
+ }
+
+ private async void SaveAsProject()
+ {
+ if (Project != null)
+ {
+ var result = await StorageProvider.SaveFile("Save As Project", PROJECT_DIALOG_FILTER, Project.Name, PROJECT_FILE_EXTENSION);
+
+ if (result)
+ {
+ try
+ {
+ Status = "Saving project...";
+
+ File.WriteAllText(result.SelectedItem, Project.ToJson());
+ _projectFile = result.SelectedItem;
+
+ Status = "Project saved.";
+
+ Project.Scripts.ToList().ForEach(x => x.IsChanged = false);
+ }
+ catch (Exception ex)
+ {
+ await NotificationProvider.ShowError($"Error saving project\n{ex.FlattenMessage()}");
+ Status = "Ready";
+ }
+ }
+ }
+ }
+
+ private async void AddNewLibrary()
+ {
+ var result = await NotificationProvider.ShowInputBox("New Library File", "Please specify the library name", PackIconKind.Script, "MyLibrary", "Library Name", 100, "ADD LIBRARY");
+
+ if (result.Confirmed)
+ {
+ if (Project.Scripts.Any(x => x.Name.ToLower() == result.Input.ToLower() + ".csx"))
+ {
+ await NotificationProvider.ShowError($"The project already contains a file named '{result.Input}'.");
+ return;
+ }
+
+ try
+ {
+ var lib = Script.New(result.Input.ToTitleCase() + ".csx", Encoding.UTF8.GetString(Properties.Resources.lib_template));
+ Project.Scripts.Add(lib);
+ _isProjectChanged = true;
+ OpenScript(lib);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error adding new library to test project.");
+ await NotificationProvider.ShowError($"Could not add a new script to the project.\n{ex.FlattenMessage()}");
+ }
+ }
}
private void OnProjectChanged()
{
if (Project != null)
{
+ _isProjectChanged = false;
+ LoadReferenceAssemblies();
ProjectRunner = new ProjectRunner(Project);
ProjectRunner.StateChanged += ProjectRunner_StateChanged;
+ ClearOpenedScripts();
+
+ var programScript = Project.Scripts.SingleOrDefault(x => x.IsEntryPoint);
+
+ if (programScript != null)
+ {
+ OpenScript(programScript);
+ }
}
else
{
@@ -367,12 +529,74 @@ namespace Tango.FSE.Stubs.ViewModels
LoadedAssemblies = Project.LoadReferenceAssemblies().ToObservableCollection();
}
+ private async void OpenProject()
+ {
+ if (await CheckDiscardProjectChanges())
+ {
+ var result = await StorageProvider.OpenFile("Open Test Project", PROJECT_DIALOG_FILTER);
+
+ if (result)
+ {
+ OpenProject(result.SelectedItem);
+ }
+ }
+ }
+
+ private void OpenProject(String file)
+ {
+ try
+ {
+ Project = TestProject.FromJson(File.ReadAllText(file));
+ _projectFile = file;
+ Status = "Project loaded.";
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error opening test project.");
+ NotificationProvider.ShowError($"Error occurred while trying to open the project.\n{ex.FlattenMessage()}");
+ }
+ }
+
+ private async Task<bool> CheckDiscardProjectChanges()
+ {
+ if (Project != null && (Project.Scripts.Any(x => x.IsChanged) || _isProjectChanged))
+ {
+ return await NotificationProvider.ShowWarningQuestion("The current project contains unsaved changes. Discard the changes?");
+ }
+ else
+ {
+ return true;
+ }
+ }
+
private void RemoveReferenceAssembly(ReferenceAssembly assembly)
{
Project.ReferenceAssemblies.Remove(assembly);
+ _isProjectChanged = true;
LoadedAssemblies = Project.LoadReferenceAssemblies().ToObservableCollection();
}
+ private void ClearOutput()
+ {
+ Logger.Clear();
+ }
+
+ private async void DeleteLibrary(Script script)
+ {
+ if (script.IsEntryPoint)
+ {
+ await NotificationProvider.ShowWarning("Entry point file cannot be deleted.");
+ return;
+ }
+
+ if (await NotificationProvider.ShowWarningQuestion($"Are you sure you want to delete '{script.Name}'?"))
+ {
+ CloseScript(script);
+ Project.Scripts.Remove(script);
+ _isProjectChanged = true;
+ }
+ }
+
#endregion
#region ITestLogger
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml
index 4d31b9083..9af2b777b 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml
@@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:global="clr-namespace:Tango.FSE.Stubs"
+ xmlns:helpers="clr-namespace:Tango.SharedUI.Helpers;assembly=Tango.SharedUI"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:components="clr-namespace:Tango.SharedUI.Components;assembly=Tango.SharedUI"
xmlns:vm="clr-namespace:Tango.FSE.Stubs.ViewModels"
@@ -21,6 +22,10 @@
<UserControl.InputBindings>
<KeyBinding Key="F5" Command="{Binding RunProjectCommand}" />
<KeyBinding Key="F6" Command="{Binding CompileProjectCommand}" />
+ <KeyBinding Modifiers="Ctrl" Key="S" Command="{Binding SaveProjectCommand}" />
+ <KeyBinding Modifiers="Ctrl+Shift" Key="S" Command="{Binding SaveProjectCommand}" />
+ <KeyBinding Modifiers="Ctrl" Key="N" Command="{Binding NewProjectCommand}" />
+ <KeyBinding Modifiers="Ctrl" Key="O" Command="{Binding OpenProjectCommand}" />
</UserControl.InputBindings>
<Grid>
@@ -28,16 +33,33 @@
<DockPanel>
<Menu IsMainMenu="True" DockPanel.Dock="Top">
<MenuItem Header="_File">
- <MenuItem Header="_New" MinWidth="250" Command="{Binding NewProjectCommand}">
+ <MenuItem Header="_New" MinWidth="250" Command="{Binding NewProjectCommand}" InputGestureText="Ctrl+N">
<MenuItem.Icon>
<material:PackIcon Kind="FileDocument" />
</MenuItem.Icon>
</MenuItem>
- <MenuItem Header="_Open" Command="{Binding OpenProjectCommand}">
+ <MenuItem Header="_Open" Command="{Binding OpenProjectCommand}" InputGestureText="Ctrl+O">
<MenuItem.Icon>
<material:PackIcon Kind="FileEdit" />
</MenuItem.Icon>
</MenuItem>
+ <Separator/>
+ <MenuItem Header="_Save" Command="{Binding SaveProjectCommand}" InputGestureText="Ctrl+S">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="ContentSave" />
+ </MenuItem.Icon>
+ </MenuItem>
+ <MenuItem Header="_Save As" Command="{Binding SaveAsProjectCommand}" InputGestureText="Ctrl+Shift+S">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="ContentSaveAll" />
+ </MenuItem.Icon>
+ </MenuItem>
+ <Separator/>
+ <MenuItem Header="Add Library" Command="{Binding AddLibraryCommand}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="ScriptText" />
+ </MenuItem.Icon>
+ </MenuItem>
</MenuItem>
<MenuItem Header="_Edit">
<MenuItem MinWidth="250" Header="_Undo" Command="Undo">
@@ -96,8 +118,8 @@
<Grid DockPanel.Dock="Top">
<!--Toolbar-->
<ToolBar ClipToBounds="False" Background="Transparent" HorizontalAlignment="Center" ToolBarTray.IsLocked="True">
- <Button ToolTip="Save">
- <material:PackIcon Kind="ContentSave" />
+ <Button ToolTip="Save" Command="{Binding SaveProjectCommand}">
+ <material:PackIcon Kind="ContentSave" />
</Button>
<Separator />
<Button Command="Undo" ToolTip="Undo" ToolBar.OverflowMode="AsNeeded">
@@ -287,9 +309,15 @@
<!--Output & Error Tabs-->
<TabControl SelectedIndex="{Binding SelectedToolWindow,Mode=TwoWay,Converter={StaticResource EnumToIntConverter}}" ItemContainerStyle="{StaticResource FSE_TabItem_VisualStudio_Output}" TabStripPlacement="Bottom" Margin="0" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderThickness="0">
<TabItem Header="OUTPUT">
- <TextBox HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Padding="5" Style="{x:Null}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}" FontFamily="Consolas" components:TextController.Controller="{Binding Logger}" FontSize="{StaticResource FSE_SmallFontSize}" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderThickness="0" AcceptsReturn="True" IsReadOnly="True">
+ <DockPanel>
+ <Grid DockPanel.Dock="Top" Height="28" Background="{StaticResource FSE_PrimaryBackgroundBrush}">
+ <TextBlock VerticalAlignment="Center" Margin="5 0 0 0" FontFamily="{StaticResource hand}">Output</TextBlock>
+ <controls:IconButton Height="32" Cursor="Hand" ToolTip="Clear" Width="32" Icon="DeleteEmpty" Foreground="{StaticResource FSE_GrayBrush}" HorizontalAlignment="Right" VerticalAlignment="Center" />
- </TextBox>
+ <Rectangle VerticalAlignment="Bottom" Stroke="Black" StrokeThickness="2" />
+ </Grid>
+ <TextBox HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Padding="5" Style="{x:Null}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}" FontFamily="Consolas" components:TextController.Controller="{Binding Logger}" FontSize="{StaticResource FSE_SmallFontSize}" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderThickness="0" AcceptsReturn="True" IsReadOnly="True" TextWrapping="Wrap" />
+ </DockPanel>
</TabItem>
<TabItem>
<TabItem.Header>
@@ -298,21 +326,33 @@
<Run>(</Run><Run Text="{Binding CompilationErrors.Count,Mode=OneWay}"></Run><Run>)</Run>
</TextBlock>
</TabItem.Header>
- <DataGrid ItemsSource="{Binding CompilationErrors}" Style="{StaticResource FSE_LogsGridStyle}" CellStyle="{StaticResource FSE_LogsGridCellStyle}" HorizontalGridLinesBrush="{StaticResource FSE_PrimaryBackgroundBrush}" AutoGenerateColumns="False">
- <DataGrid.Columns>
- <DataGridTemplateColumn Width="40">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <material:PackIcon HorizontalAlignment="Center" VerticalAlignment="Center" Kind="Alert" Foreground="{StaticResource FSE_ErrorBrush}" />
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <DataGridTextColumn Header="DESCRIPTION" Binding="{Binding Message}" Width="1*" />
- <DataGridTextColumn Header="FILE" Binding="{Binding File}" />
- <DataGridTextColumn Header="LINE" Binding="{Binding Line}" />
- <DataGridTextColumn Header="COL" Binding="{Binding Column}" />
- </DataGrid.Columns>
- </DataGrid>
+ <DockPanel>
+ <Grid DockPanel.Dock="Top" Height="28" Background="{StaticResource FSE_PrimaryBackgroundBrush}">
+ <TextBlock VerticalAlignment="Center" Margin="5 0 0 0" FontFamily="{StaticResource hand}">Errors</TextBlock>
+
+ <Rectangle VerticalAlignment="Bottom" Stroke="Black" StrokeThickness="2" />
+ </Grid>
+ <DataGrid ItemsSource="{Binding CompilationErrors}"
+ Style="{StaticResource FSE_LogsGridStyle}"
+ CellStyle="{StaticResource FSE_LogsGridCellStyle}"
+ HorizontalGridLinesBrush="{StaticResource FSE_PrimaryBackgroundBrush}"
+ helpers:DataGridHelper.DoubleClickCommand="{Binding HighlightErrorCommand}"
+ AutoGenerateColumns="False">
+ <DataGrid.Columns>
+ <DataGridTemplateColumn Width="40">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <material:PackIcon HorizontalAlignment="Center" VerticalAlignment="Center" Kind="Alert" Foreground="{StaticResource FSE_ErrorBrush}" />
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ <DataGridTextColumn Header="DESCRIPTION" Binding="{Binding Message}" Width="1*" />
+ <DataGridTextColumn Header="FILE" Binding="{Binding File}" />
+ <DataGridTextColumn Header="LINE" Binding="{Binding Line}" />
+ <DataGridTextColumn Header="COL" Binding="{Binding Column}" />
+ </DataGrid.Columns>
+ </DataGrid>
+ </DockPanel>
</TabItem>
<TabItem>
<TabItem.Header>
@@ -322,30 +362,36 @@
</TextBlock>
</TabItem.Header>
- <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
- <StackPanel HorizontalAlignment="Left" TextElement.Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
- <ItemsControl ItemsSource="{Binding Project.Inputs}">
- <ItemsControl.ItemTemplate>
- <DataTemplate>
- <DockPanel Margin="15">
- <material:PackIcon Kind="Key" VerticalAlignment="Bottom" Margin="0 0 0 5" />
- <controls:IconButton VerticalAlignment="Bottom" DockPanel.Dock="Right" Margin="40 0 0 0" Icon="Close" Foreground="{StaticResource FSE_RedBrush}" ToolTip="Delete input" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RemoveProjectInputCommand}" CommandParameter="{Binding}"></controls:IconButton>
- <DockPanel Margin="10 0 0 0" Width="100">
- <TextBlock Margin="2 0 0 2" DockPanel.Dock="Top" FontSize="{StaticResource FSE_SmallerFontSize}">Key</TextBlock>
- <TextBox Style="{StaticResource FSE_Rounded_Corners_TextBox}" Text="{Binding Key}"></TextBox>
- </DockPanel>
- <DockPanel Margin="40 0 0 0" Width="500">
- <TextBlock Margin="2 0 0 2" DockPanel.Dock="Top" FontSize="{StaticResource FSE_SmallerFontSize}">Value</TextBlock>
- <TextBox Style="{StaticResource FSE_Rounded_Corners_TextBox}" Text="{Binding Value}"></TextBox>
+ <DockPanel>
+ <Grid DockPanel.Dock="Top" Height="28" Background="{StaticResource FSE_PrimaryBackgroundBrush}">
+ <TextBlock VerticalAlignment="Center" Margin="5 0 0 0" FontFamily="{StaticResource hand}">Inputs</TextBlock>
+ <controls:IconButton VerticalAlignment="Center" HorizontalAlignment="Right" Command="{Binding AddProjectInputCommand}" Icon="Add" Foreground="{StaticResource FSE_GrayBrush}" Cursor="Hand" ToolTip="Add input">Add Input</controls:IconButton>
+ <Rectangle VerticalAlignment="Bottom" Stroke="Black" StrokeThickness="2" />
+ </Grid>
+ <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
+ <StackPanel HorizontalAlignment="Left" TextElement.Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
+ <ItemsControl ItemsSource="{Binding Project.Inputs}">
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <DockPanel Margin="15">
+ <material:PackIcon Kind="Key" VerticalAlignment="Bottom" Margin="0 0 0 5" />
+ <controls:IconButton VerticalAlignment="Bottom" DockPanel.Dock="Right" Margin="40 0 0 0" Icon="Close" Foreground="{StaticResource FSE_RedBrush}" ToolTip="Delete input" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RemoveProjectInputCommand}" CommandParameter="{Binding}"></controls:IconButton>
+ <DockPanel Margin="10 0 0 0" Width="100">
+ <TextBlock Margin="2 0 0 2" DockPanel.Dock="Top" FontSize="{StaticResource FSE_SmallerFontSize}">Key</TextBlock>
+ <TextBox Style="{StaticResource FSE_Rounded_Corners_TextBox}" Text="{Binding Key}"></TextBox>
+ </DockPanel>
+ <material:PackIcon Kind="Equal" VerticalAlignment="Bottom" Margin="20 0 20 5" />
+ <DockPanel Width="500">
+ <TextBlock Margin="2 0 0 2" DockPanel.Dock="Top" FontSize="{StaticResource FSE_SmallerFontSize}">Value</TextBlock>
+ <TextBox Style="{StaticResource FSE_Rounded_Corners_TextBox}" Text="{Binding Value}"></TextBox>
+ </DockPanel>
</DockPanel>
- </DockPanel>
- </DataTemplate>
- </ItemsControl.ItemTemplate>
- </ItemsControl>
-
- <controls:IconButton HorizontalAlignment="Left" Command="{Binding AddProjectInputCommand}" Icon="Add" Foreground="{StaticResource FSE_GreenBrush}" ToolTip="Add input">Add Input</controls:IconButton>
- </StackPanel>
- </ScrollViewer>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </StackPanel>
+ </ScrollViewer>
+ </DockPanel>
</TabItem>
<TabItem>
<TabItem.Header>
@@ -354,39 +400,55 @@
<Run>(</Run><Run Text="{Binding Results.Count,Mode=OneWay}"></Run><Run>)</Run>
</TextBlock>
</TabItem.Header>
- <DataGrid ItemsSource="{Binding Results}" Style="{StaticResource FSE_LogsGridStyle}" CellStyle="{StaticResource FSE_LogsGridCellStyle}" HorizontalGridLinesBrush="{StaticResource FSE_PrimaryBackgroundBrush}" AutoGenerateColumns="False">
- <DataGrid.Columns>
- <DataGridTemplateColumn Width="40">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <material:PackIcon HorizontalAlignment="Center" VerticalAlignment="Center">
- <material:PackIcon.Style>
- <Style TargetType="material:PackIcon">
- <Setter Property="Kind" Value="Check"></Setter>
- <Setter Property="Foreground" Value="{StaticResource FSE_SuccessBrush}"></Setter>
- <Style.Triggers>
- <DataTrigger Binding="{Binding Type}" Value="Warning">
- <Setter Property="Kind" Value="Alert"></Setter>
- <Setter Property="Foreground" Value="{StaticResource FSE_WarningBrush}"></Setter>
- </DataTrigger>
- <DataTrigger Binding="{Binding Type}" Value="Failed">
- <Setter Property="Kind" Value="Alert"></Setter>
- <Setter Property="Foreground" Value="{StaticResource FSE_ErrorBrush}"></Setter>
- </DataTrigger>
- </Style.Triggers>
- </Style>
- </material:PackIcon.Style>
- </material:PackIcon>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- <DataGridTextColumn Header="NAME" Binding="{Binding Name}" />
- <DataGridTextColumn Header="VALUE" Binding="{Binding Value}" Width="1*" />
- </DataGrid.Columns>
- </DataGrid>
+ <DockPanel>
+ <Grid DockPanel.Dock="Top" Height="28" Background="{StaticResource FSE_PrimaryBackgroundBrush}">
+ <TextBlock VerticalAlignment="Center" Margin="5 0 0 0" FontFamily="{StaticResource hand}">Results</TextBlock>
+
+ <Rectangle VerticalAlignment="Bottom" Stroke="Black" StrokeThickness="2" />
+ </Grid>
+ <DataGrid ItemsSource="{Binding Results}" Style="{StaticResource FSE_LogsGridStyle}" CellStyle="{StaticResource FSE_LogsGridCellStyle}" HorizontalGridLinesBrush="{StaticResource FSE_PrimaryBackgroundBrush}" AutoGenerateColumns="False">
+ <DataGrid.Columns>
+ <DataGridTemplateColumn Width="40">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <material:PackIcon HorizontalAlignment="Center" VerticalAlignment="Center">
+ <material:PackIcon.Style>
+ <Style TargetType="material:PackIcon">
+ <Setter Property="Kind" Value="Check"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource FSE_SuccessBrush}"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Type}" Value="Warning">
+ <Setter Property="Kind" Value="Alert"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource FSE_WarningBrush}"></Setter>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding Type}" Value="Failed">
+ <Setter Property="Kind" Value="Alert"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource FSE_ErrorBrush}"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </material:PackIcon.Style>
+ </material:PackIcon>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ <DataGridTextColumn Header="NAME" Binding="{Binding Name}" />
+ <DataGridTextColumn Header="VALUE" Binding="{Binding Value}" Width="1*" />
+ </DataGrid.Columns>
+ </DataGrid>
+ </DockPanel>
</TabItem>
<TabItem Header="PUBLISH">
+ <DockPanel>
+ <Grid DockPanel.Dock="Top" Height="28" Background="{StaticResource FSE_PrimaryBackgroundBrush}">
+ <TextBlock VerticalAlignment="Center" Margin="5 0 0 0" FontFamily="{StaticResource hand}">Publish</TextBlock>
+ <Rectangle VerticalAlignment="Bottom" Stroke="Black" StrokeThickness="2" />
+ </Grid>
+ <Grid>
+
+ </Grid>
+ </DockPanel>
</TabItem>
</TabControl>
</Grid>
@@ -420,7 +482,7 @@
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
- <MenuItem Header="Remove" Command="{Binding Source={StaticResource proxy},Path=Data.RemoveReferenceAssemblyCommand}" CommandParameter="{Binding}">
+ <MenuItem MinWidth="180" Header="Remove" Command="{Binding Source={StaticResource proxy},Path=Data.RemoveReferenceAssemblyCommand}" CommandParameter="{Binding}">
<MenuItem.Icon>
<material:PackIcon Kind="Delete" Foreground="{StaticResource FSE_RedBrush}" />
</MenuItem.Icon>
@@ -440,10 +502,22 @@
</ListBox.ItemTemplate>
</ListBox>
- <ListBox Margin="5 5 0 0" ItemsSource="{Binding Project.Scripts}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
+ <ListBox Margin="5 5 0 0" ItemsSource="{Binding Project.Scripts,Converter={StaticResource ObservableCollectionToViewSourceConverter},ConverterParameter='Name'}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<EventSetter Event="PreviewMouseDoubleClick" Handler="OnScriptItemDoubleClick"></EventSetter>
+
+ <Setter Property="ContextMenu">
+ <Setter.Value>
+ <ContextMenu>
+ <MenuItem MinWidth="180" IsEnabled="{Binding IsEntryPoint,Converter={StaticResource BooleanInverseConverter}}" Header="Delete" Command="{Binding Source={StaticResource proxy},Path=Data.DeleteLibraryCommand}" CommandParameter="{Binding}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="Delete" Foreground="{StaticResource FSE_RedBrush}" />
+ </MenuItem.Icon>
+ </MenuItem>
+ </ContextMenu>
+ </Setter.Value>
+ </Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs
index 5bd798cc0..3636f7d50 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Views/TestDesignerView.xaml.cs
@@ -38,14 +38,20 @@ namespace Tango.FSE.Stubs.Views
_vm.OpenScript((sender as FrameworkElement).DataContext as Script);
}
- public void FormatCode()
+ private ScriptEditor GetCurrentEditor()
{
var editor = tabControl.FindVisualChildren<ScriptEditor>().FirstOrDefault(x => x.IsVisible);
+ return editor;
+ }
- if (editor != null)
- {
- editor.FormatCode();
- }
+ public void FormatCode()
+ {
+ GetCurrentEditor()?.FormatCode();
+ }
+
+ public void HighlightCode(int position, int length)
+ {
+ GetCurrentEditor()?.Highlight(position, length);
}
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml
index 04d8dc416..4917f9426 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml
@@ -36,4 +36,5 @@
<converters:StringToOneLineConverter x:Key="StringToOneLineConverter" />
<converters:FilePathToFileNameConverter x:Key="FilePathToFileNameConverter" />
<converters:EnumToIntConverter x:Key="EnumToIntConverter" />
+ <converters:ObservableCollectionToViewSourceConverter x:Key="ObservableCollectionToViewSourceConverter" />
</ResourceDictionary> \ No newline at end of file
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/CompilationError.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/CompilationError.cs
index 27c710b2f..eda72fa6e 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/CompilationError.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/CompilationError.cs
@@ -12,6 +12,7 @@ namespace Tango.Scripting.Basic
public String File { get; set; }
public String Message { get; set; }
public DiagnosticSeverity Severity { get; set; }
+ public int Position { get; set; }
public int Line { get; set; }
public int Column { get; set; }
public int Length { get; set; }
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs
index 776c21e53..7abcbb42d 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs
@@ -73,6 +73,7 @@ namespace Tango.Scripting.Basic
foreach (var script in Scripts)
{
script.LoadCount = 0;
+ script.LoadCharCount = 0;
String code = script.Code;
String codeFile = Path.Combine(tempFolder, script.Name);
@@ -82,6 +83,7 @@ namespace Tango.Scripting.Basic
{
loadingString = $"#load \"{file}\"\n";
script.LoadCount++;
+ script.LoadCharCount += loadingString.Length;
}
code = loadingString + code;
@@ -132,6 +134,7 @@ namespace Tango.Scripting.Basic
Script errorScript = Scripts.Single(x => x.Name == cError.File);
cError.Message = error.GetMessage();
cError.Severity = error.Severity;
+ cError.Position = error.Location.SourceSpan.Start - (errorScript != null ? errorScript.LoadCharCount : 0);
var line = error.Location.GetMappedLineSpan();
cError.Line = line.StartLinePosition.Line + 1 - (errorScript != null ? errorScript.LoadCount : 0);
cError.Column = line.StartLinePosition.Character + 1;
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Script.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Script.cs
index 753026149..69bc15468 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Script.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Script.cs
@@ -13,9 +13,32 @@ namespace Tango.Scripting.Basic
public class Script : ExtendedObject, IScriptSource
{
public String Name { get; set; }
- public String Code { get; set; }
public bool IsEntryPoint { get; set; }
+ private String _code;
+ public String Code
+ {
+ get { return _code; }
+ set
+ {
+ if (_code != null && _code != value)
+ {
+ IsChanged = true;
+ }
+
+ _code = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private bool _isChanged;
+ [JsonIgnore]
+ public bool IsChanged
+ {
+ get { return _isChanged; }
+ set { _isChanged = value; RaisePropertyChangedAuto(); }
+ }
+
private bool _isSelected;
[JsonIgnore]
public bool IsSelected
@@ -26,6 +49,8 @@ namespace Tango.Scripting.Basic
[JsonIgnore]
public int LoadCount { get; internal set; }
+ [JsonIgnore]
+ public int LoadCharCount { get; set; }
public static Script New(String file)
{
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs
index 42103a1b1..d7d72ec0b 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs
@@ -2121,6 +2121,11 @@ namespace Tango.Scripting.Editors
}
}
+ public void Highlight(int position, int length)
+ {
+ Select(position, Math.Max(length, 1));
+ }
+
#endregion
}
}