From 84b3861addbb2f60c8b45e74d2748d4de5c39d86 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Thu, 23 Jul 2020 22:07:44 +0300 Subject: Implemented find & replace. Improved symbols loading and highlighting. Implemented font +/-. --- .../Highlighting/OffsetColorizer.cs | 2 +- .../Tango.Scripting.Editors/ScriptEditor.cs | 218 ++++++++++++++++++++- 2 files changed, 217 insertions(+), 3 deletions(-) (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors') 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/ScriptEditor.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs index 71a455f86..7b5c38a2b 100644 --- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs @@ -69,6 +69,7 @@ namespace Tango.Scripting.Editors public static event EventHandler> LoadingSymbolsProgress; public static event EventHandler LoadingSymbolsStarted; public static event EventHandler LoadingSymbolsCompleted; + private static event EventHandler KnownTypesAvailable; #region Mini Classes @@ -161,6 +162,14 @@ namespace Tango.Scripting.Editors public static readonly DependencyProperty AdditionalScriptsProperty = DependencyProperty.Register("AdditionalScripts", typeof(ObservableCollection), 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 +275,8 @@ namespace Tango.Scripting.Editors _knownTypes = new List(); _parser = new ScriptParser(); + KnownTypesAvailable += ScriptEditor_KnownTypesAvailable; + TextArea.IndentationStrategy = new Indentation.CSharp.CSharpIndentationStrategy(Options); foldingStrategy = new BraceFoldingStrategy(); @@ -287,6 +298,14 @@ namespace Tango.Scripting.Editors TextChanged += ScriptEditor_TextChanged; } + private void ScriptEditor_KnownTypesAvailable(object sender, EventArgs e) + { + if (sender != this) + { + InvalidateHighlightingPartial(); + } + } + private bool preventCodeUpdate; private void ScriptEditor_TextChanged(object sender, EventArgs e) { @@ -1357,7 +1376,7 @@ namespace Tango.Scripting.Editors return popup; } - public static void LoadUsingsSymbols(List assemblies, List usings) + public void LoadUsingsSymbols(List assemblies, List usings) { lock (_loadUsingsLock) { @@ -1390,6 +1409,9 @@ namespace Tango.Scripting.Editors _knownTypesCache.Add(knownType.Type, knownType); } + KnownTypesAvailable?.Invoke(this, new EventArgs()); + InvalidateHighlightingPartial(); + continue; } @@ -1575,6 +1597,100 @@ namespace Tango.Scripting.Editors // _isLoadingCachedAssemblies = false; //} + private void InvalidateHighlightingPartial() + { + List assemblies = new List(); + 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 referenceTypes = new List(); + List interfaceTypes = new List(); + + 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("{0}", name)); + } + else if (type.Type.IsClass || (type.Type.IsValueType)) + { + referenceTypes.Add(String.Format("{0}", name)); + } + } + } + + foreach (var type in _declaredTypes) + { + if (type.Kind == TypeKind.Interface || type.Kind == TypeKind.Enum) + { + interfaceTypes.Add(String.Format("{0}", type.Name)); + } + else if (type.Kind == TypeKind.Class) + { + referenceTypes.Add(String.Format("{0}", type.Name)); + } + } + + if (referenceTypes.Count > 0) + { + text = text.Replace("@ReferenceTypes@", String.Join(Environment.NewLine, referenceTypes.Distinct())); + } + + if (interfaceTypes.Count > 0) + { + text = text.Replace("@InterfaceTypes@", 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 +2080,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 +2325,104 @@ 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(); + } + #endregion } } -- cgit v1.3.1 From b885adb509065d964d628f90a3800f519f49f622 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sat, 25 Jul 2020 01:58:40 +0300 Subject: Procedure custom dialogs ! --- .../Modules/Tango.FSE.Stubs/DialogController.cs | 95 +++++++++++ .../Modules/Tango.FSE.Stubs/DialogControllerVM.cs | 18 +++ .../Dialogs/ProcedureDialogEditorView.xaml | 55 +++++++ .../Dialogs/ProcedureDialogEditorView.xaml.cs | 28 ++++ .../Dialogs/ProcedureDialogEditorViewVM.cs | 177 +++++++++++++++++++++ .../Modules/Tango.FSE.Stubs/IDialogController.cs | 16 ++ .../Modules/Tango.FSE.Stubs/IProcedureContext.cs | 9 ++ .../FSE/Modules/Tango.FSE.Stubs/Images/blend.png | Bin 0 -> 5062 bytes .../Modules/Tango.FSE.Stubs/ProcedureContext.cs | 166 +++++++++++++------ .../FSE/Modules/Tango.FSE.Stubs/ProcedureDialog.cs | 21 +++ .../Modules/Tango.FSE.Stubs/ProcedureProject.cs | 4 + .../Properties/Resources.Designer.cs | 11 ++ .../Tango.FSE.Stubs/Properties/Resources.resx | 3 + .../Tango.FSE.Stubs/Resources/dialog_template.txt | 3 + .../Resources/procedure_dialog_template.zip | Bin 0 -> 8597 bytes .../Tango.FSE.Stubs/Tango.FSE.Procedures.csproj | 20 +++ .../ViewModels/ProcedureDesignerViewVM.cs | 45 +++++- .../Views/ProcedureDesignerView.xaml | 38 +++++ .../Views/ProcedureDesignerView.xaml.cs | 5 + .../Modules/Tango.FSE.Stubs/WindowController.cs | 92 +++++++++++ .../Threading/IDispatcherProvider.cs | 5 + .../Threading/DefaultDispatcherProvider.cs | 9 ++ .../Scripting/Tango.Scripting.Basic/Project.cs | 6 +- .../Highlighting/Resources/MarkDown-Mode.xshd | 7 - .../Highlighting/Resources/XML-Mode.xshd | 14 +- .../Tango.Scripting.Editors/Rendering/TextView.cs | 2 +- .../Tango.Scripting.Editors.csproj | 3 +- .../Tango.Scripting.Editors/Themes/Generic.xaml | 9 ++ .../Tango.Scripting.Editors/XamlEditor.cs | 47 ++++++ 29 files changed, 844 insertions(+), 64 deletions(-) create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/DialogController.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/DialogControllerVM.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorView.xaml create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorView.xaml.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorViewVM.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/IDialogController.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Images/blend.png create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureDialog.cs create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Resources/dialog_template.txt create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Resources/procedure_dialog_template.zip create mode 100644 Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/WindowController.cs create mode 100644 Software/Visual_Studio/Scripting/Tango.Scripting.Editors/XamlEditor.cs (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors') diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/DialogController.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/DialogController.cs new file mode 100644 index 000000000..8d32f93c2 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/DialogController.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Markup; +using Tango.Core.DI; +using Tango.FSE.Common.Notifications; +using Tango.FSE.Common.Threading; + +namespace Tango.FSE.Procedures +{ + public class DialogController : IDialogController + { + private String _xaml; + private FrameworkElement _rootElement; + private DialogControllerVM _dialogVM; + + [TangoInject] + private INotificationProvider NotificationProvider { get; set; } + + [TangoInject] + private IDispatcherProvider DispatcherProvider { get; set; } + + internal DialogController(String xaml) + { + _xaml = xaml; + _dialogVM = new DialogControllerVM(); + TangoIOC.Default.Inject(this); + } + + internal void Init() + { + TaskCompletionSource completion = new TaskCompletionSource(); + + DispatcherProvider.Invoke(() => + { + FrameworkElement rootElement; + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(_xaml); + writer.Flush(); + stream.Position = 0; + rootElement = (FrameworkElement)XamlReader.Load(stream); + _rootElement = rootElement; + stream.Dispose(); + + completion.SetResult(true); + }); + + completion.Task.GetAwaiter().GetResult(); + } + + public void Show() + { + TaskCompletionSource completion = new TaskCompletionSource(); + + DispatcherProvider.Invoke(async () => + { + await NotificationProvider.ShowDialog(_dialogVM, _rootElement); + completion.SetResult(true); + }); + + completion.Task.GetAwaiter().GetResult(); + } + + public void Close() + { + _dialogVM?.Close(true); + } + + public T FindControl(String name) where T : DependencyObject + { + bool completed = false; + T child = null; + + DispatcherProvider.Invoke(() => + { + child = _rootElement.FindChild(name) as T; + completed = true; + }); + + while (!completed) + { + Thread.Sleep(10); + } + + return child; + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/DialogControllerVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/DialogControllerVM.cs new file mode 100644 index 000000000..7adf7d4c0 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/DialogControllerVM.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FSE.Common; + +namespace Tango.FSE.Procedures +{ + internal class DialogControllerVM : FSEDialogViewVM + { + public DialogControllerVM() + { + AutoMode = false; + CanClose = true; + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorView.xaml new file mode 100644 index 000000000..729ff2831 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorView.xaml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorView.xaml.cs new file mode 100644 index 000000000..bff461593 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +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; + +namespace Tango.FSE.Procedures.Dialogs +{ + /// + /// Interaction logic for ProcedureDialogEditorView.xaml + /// + public partial class ProcedureDialogEditorView : UserControl + { + public ProcedureDialogEditorView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorViewVM.cs new file mode 100644 index 000000000..8c95df985 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Dialogs/ProcedureDialogEditorViewVM.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Markup; +using System.Xml; +using System.Xml.Linq; +using Tango.Core.Commands; +using Tango.FSE.Common; + +namespace Tango.FSE.Procedures.Dialogs +{ + public class ProcedureDialogEditorViewVM : FSEDialogViewVM + { + private FileSystemWatcher _watcher; + + private String _name; + public String Name + { + get { return _name; } + set { _name = value; RaisePropertyChangedAuto(); } + } + + private String _xaml; + public String Xaml + { + get { return _xaml; } + set { _xaml = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(Content)); } + } + + private FrameworkElement _content; + public FrameworkElement Content + { + get + { + try + { + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(Xaml); + writer.Flush(); + stream.Position = 0; + FrameworkElement rootElement = (FrameworkElement)XamlReader.Load(stream); + stream.Dispose(); + HasError = false; + Error = null; + _content = rootElement; + return rootElement; + } + catch (Exception ex) + { + Error = ex.Message; + HasError = true; + return _content; + } + } + } + + private bool _hasError; + public bool HasError + { + get { return _hasError; } + set { _hasError = value; RaisePropertyChangedAuto(); } + } + + private String _error; + public String Error + { + get { return _error; } + set { _error = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand OpenInBlendCommand { get; set; } + + public ProcedureDialogEditorViewVM() + { + OpenInBlendCommand = new RelayCommand(OpenInBlend); + } + + private void OpenInBlend() + { + if (this._watcher != null) + { + return; + } + + String blendPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Blend.exe"; + + if (!File.Exists(blendPath)) + { + blendPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\Blend.exe"; + } + + if (!File.Exists(blendPath)) + { + throw new FileNotFoundException("Could not locate Blend for Visual Studio location."); + } + + var tempFolder = TemporaryManager.CreateFolder(); + + var stream = Core.Helpers.EmbeddedResourceHelper.GetEmbeddedResourceStream("Tango.FSE.Procedures.Resources.procedure_dialog_template.zip"); + stream.Position = 0; + using (ZipArchive zip = new ZipArchive(stream)) + { + zip.ExtractToDirectory(tempFolder, true); + } + + String mainWindowFile = Path.Combine(tempFolder, "MainWindow.xaml"); + String mainWindowContent = File.ReadAllText(mainWindowFile); + mainWindowContent = mainWindowContent.Replace("@", Xaml); + File.WriteAllText(mainWindowFile, mainWindowContent); + + _watcher = new FileSystemWatcher(tempFolder); + _watcher.Changed += (sender, e) => + { + if (e.ChangeType == WatcherChangeTypes.Changed) + { + try + { + String newContent = File.ReadAllText(e.FullPath); + + if (newContent.Contains(" x.Name.LocalName == "Window"); + + if (windowNode != null) + { + var firstChild = windowNode.Descendants().FirstOrDefault(); + + if (firstChild != null) + { + var newXaml = firstChild.ToString(); + Xaml = newXaml; + } + } + } + } + } + catch (Exception ex) + { + Debug.WriteLine($"Error updating xaml from blend.\n{ex.ToString()}"); + } + } + }; + + _watcher.EnableRaisingEvents = true; + + Task.Factory.StartNew(() => + { + var p = Process.Start(blendPath, Path.Combine(tempFolder, "ProcedureDialog.csproj")); + p.WaitForExit(); + _watcher.Dispose(); + }); + } + + protected override void Accept() + { + _watcher?.Dispose(); + base.Accept(); + } + + protected override void Cancel() + { + _watcher?.Dispose(); + base.Cancel(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/IDialogController.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/IDialogController.cs new file mode 100644 index 000000000..50865e66d --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/IDialogController.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace Tango.FSE.Procedures +{ + public interface IDialogController + { + void Show(); + T FindControl(String name) where T : DependencyObject; + void Close(); + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/IProcedureContext.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/IProcedureContext.cs index 90bbc9911..4469ff9da 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/IProcedureContext.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/IProcedureContext.cs @@ -361,5 +361,14 @@ namespace Tango.FSE.Procedures /// The action. /// Thread RunAsync(Action action); + + /// + /// Loads the specified procedure dialog. + /// + /// The name of the dialog file. + /// + IDialogController LoadDialog(String name); + + IDialogController LoadDialogAsWindow(String name); } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Images/blend.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Images/blend.png new file mode 100644 index 000000000..91b19da4c Binary files /dev/null and b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Images/blend.png differ diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureContext.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureContext.cs index 5663e0443..df314425c 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureContext.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureContext.cs @@ -12,6 +12,7 @@ using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Windows; using Google.Protobuf; using Tango.Core; using Tango.Core.DI; @@ -370,67 +371,27 @@ namespace Tango.FSE.Procedures public void ShowInfo(string message) { - TaskCompletionSource completion = new TaskCompletionSource(); - - DispatcherProvider.Invoke(async () => - { - await NotificationProvider.ShowInfo(message); - completion.SetResult(true); - }); - - completion.Task.GetAwaiter().GetResult(); + AutoInvoke(NotificationProvider.ShowInfo(message)); } public void ShowWarning(string message) { - TaskCompletionSource completion = new TaskCompletionSource(); - - DispatcherProvider.Invoke(async () => - { - await NotificationProvider.ShowWarning(message); - completion.SetResult(true); - }); - - completion.Task.GetAwaiter().GetResult(); + AutoInvoke(NotificationProvider.ShowWarning(message)); } public void ShowError(string message) { - TaskCompletionSource completion = new TaskCompletionSource(); - - DispatcherProvider.Invoke(async () => - { - await NotificationProvider.ShowError(message); - completion.SetResult(true); - }); - - completion.Task.GetAwaiter().GetResult(); + AutoInvoke(NotificationProvider.ShowError(message)); } public bool ShowQuestion(string message) { - TaskCompletionSource completion = new TaskCompletionSource(); - - DispatcherProvider.Invoke(async () => - { - var result = await NotificationProvider.ShowQuestion(message); - completion.SetResult(result); - }); - - return completion.Task.GetAwaiter().GetResult(); + return AutoInvoke(NotificationProvider.ShowQuestion(message)); } public bool ShowWarningQuestion(string message) { - TaskCompletionSource completion = new TaskCompletionSource(); - - DispatcherProvider.Invoke(async () => - { - var result = await NotificationProvider.ShowWarningQuestion(message); - completion.SetResult(result); - }); - - return completion.Task.GetAwaiter().GetResult(); + return AutoInvoke(NotificationProvider.ShowWarningQuestion(message)); } public T RequestUserInputFor(string title, string message) @@ -600,5 +561,120 @@ namespace Tango.FSE.Procedures { return Graphics.FromImage(bitmap); } + + public IDialogController LoadDialog(string name) + { + var dialog = _project.Dialogs.SingleOrDefault(x => x.Name == name); + if (dialog == null) + { + throw new FileNotFoundException($"The specified dialog '{name}' could not be found in the project."); + } + + DialogController controller = new DialogController(dialog.Xaml); + controller.Init(); + return controller; + } + + public IDialogController LoadDialogAsWindow(string name) + { + var dialog = _project.Dialogs.SingleOrDefault(x => x.Name == name); + if (dialog == null) + { + throw new FileNotFoundException($"The specified dialog '{name}' could not be found in the project."); + } + + WindowController controller = new WindowController(dialog.Xaml); + controller.Init(); + return controller; + } + + private void AutoInvoke(Task task) + { + bool completed = false; + + if (Application.Current.Dispatcher.Thread == Thread.CurrentThread) + { + task.ContinueWith((x) => + { + completed = true; + }); + + DispatcherProvider.Invoke((Action)(async () => + { + await task; + })); + + while (!completed) + { + Thread.Sleep(2); + DispatcherProvider.DoEvents(); + } + } + else + { + task.ContinueWith((x) => + { + completed = true; + }); + + DispatcherProvider.Invoke((Action)(async () => + { + await task; + })); + + while (!completed) + { + Thread.Sleep(10); + } + } + } + + private T AutoInvoke(Task task) + { + bool completed = false; + T result = default(T); + + if (Application.Current.Dispatcher.Thread == Thread.CurrentThread) + { + task.ContinueWith((x) => + { + result = x.Result; + completed = true; + }); + + DispatcherProvider.Invoke(async () => + { + await task; + }); + + while (!completed) + { + Thread.Sleep(2); + DispatcherProvider.DoEvents(); + } + + return result; + } + else + { + task.ContinueWith((x) => + { + result = x.Result; + completed = true; + }); + + DispatcherProvider.Invoke(async () => + { + await task; + }); + + while (!completed) + { + Thread.Sleep(10); + } + + return result; + } + } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureDialog.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureDialog.cs new file mode 100644 index 000000000..347848cf1 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureDialog.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; + +namespace Tango.FSE.Procedures +{ + public class ProcedureDialog : ExtendedObject + { + private String _name; + public String Name + { + get { return _name; } + set { _name = value; RaisePropertyChangedAuto(); } + } + + public String Xaml { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureProject.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureProject.cs index 218c4336a..6d6483b3b 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureProject.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/ProcedureProject.cs @@ -21,6 +21,8 @@ namespace Tango.FSE.Procedures public ObservableCollection Inputs { get; set; } + public ObservableCollection Dialogs { get; set; } + static ProcedureProject() { _jsonSettings = new JsonSerializerSettings() @@ -32,7 +34,9 @@ namespace Tango.FSE.Procedures public ProcedureProject() : base() { + ApartmentState = System.Threading.ApartmentState.STA; Inputs = new ObservableCollection(); + Dialogs = new ObservableCollection(); } public static ProcedureProject New(String name) diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Properties/Resources.Designer.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Properties/Resources.Designer.cs index 98d6091ba..9ccc8b2d8 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Properties/Resources.Designer.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Properties/Resources.Designer.cs @@ -60,6 +60,17 @@ namespace Tango.FSE.Procedures.Properties { } } + /// + /// Looks up a localized string similar to <Grid Width="300" Height="300" Background="Gray"> + /// <Button x:Name="btn" Content="Click Me" HorizontalAlignment="Left" VerticalAlignment="Top" Width="195.481" Height="54.971" Margin="56.636,122.539,0,0"/> + /// </Grid>. + /// + internal static string dialog_template { + get { + return ResourceManager.GetString("dialog_template", resourceCulture); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Properties/Resources.resx b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Properties/Resources.resx index 87094c4e4..074580fcd 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Properties/Resources.resx +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Properties/Resources.resx @@ -118,6 +118,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\dialog_template.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + ..\Resources\lib_template.csx;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Resources/dialog_template.txt b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Resources/dialog_template.txt new file mode 100644 index 000000000..002689ca5 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Stubs/Resources/dialog_template.txt @@ -0,0 +1,3 @@ + +