diff options
| author | Victoria Plitt <Victoria.Plitt@twine-s.com> | 2020-03-15 16:22:40 +0200 |
|---|---|---|
| committer | Victoria Plitt <Victoria.Plitt@twine-s.com> | 2020-03-15 16:22:40 +0200 |
| commit | e5accfce2c661fab649bb57c33b63c679a67e60c (patch) | |
| tree | 1f29c4d77fd8e70736f4745b86a30abcf9bb3fd0 /Software/Visual_Studio | |
| parent | 56678ae530fe45b0880053793ab46f47051e4dc6 (diff) | |
| parent | b188d7bfd91062f65474bd139bb8a434694f117b (diff) | |
| download | Tango-e5accfce2c661fab649bb57c33b63c679a67e60c.tar.gz Tango-e5accfce2c661fab649bb57c33b63c679a67e60c.zip | |
merge
Diffstat (limited to 'Software/Visual_Studio')
200 files changed, 10127 insertions, 230 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/App.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/App.xaml index cfb949890..cf17cb88e 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/App.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/App.xaml @@ -39,6 +39,7 @@ <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Images.xaml" /> <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Styles.xaml" /> <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Controls.xaml" /> + <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Graphs.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Converters/DoubleToChartValuesConverter.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Converters/DoubleToChartValuesConverter.cs new file mode 100644 index 000000000..1ac86b849 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Converters/DoubleToChartValuesConverter.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace Tango.FSE.PPCConsole.Converters +{ + public class DoubleToChartValuesConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return new LiveCharts.ChartValues<double>() { (double)value }; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj index 0948b8f5c..be14e05f1 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Tango.FSE.PPCConsole.csproj @@ -49,6 +49,12 @@ <Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> <HintPath>..\..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath> </Reference> + <Reference Include="LiveCharts, Version=0.9.7.0, Culture=neutral, PublicKeyToken=0bc1f845d1ebb8df, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\LiveCharts.0.9.7\lib\net45\LiveCharts.dll</HintPath> + </Reference> + <Reference Include="LiveCharts.Wpf, Version=0.9.7.0, Culture=neutral, PublicKeyToken=0bc1f845d1ebb8df, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\LiveCharts.Wpf.0.9.7\lib\net45\LiveCharts.Wpf.dll</HintPath> + </Reference> <Reference Include="MahApps.Metro, Version=1.6.5.1, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\..\packages\MahApps.Metro.1.6.5\lib\net46\MahApps.Metro.dll</HintPath> </Reference> @@ -98,17 +104,26 @@ <Reference Include="PresentationFramework" /> </ItemGroup> <ItemGroup> + <Compile Include="Converters\DoubleToChartValuesConverter.cs" /> <Compile Include="ViewModelLocator.cs" /> <Compile Include="PPCConsoleModule.cs" /> <Compile Include="ViewModels\ConsoleViewVM.cs" /> + <Compile Include="ViewModels\FileSystemViewVM.cs" /> <Compile Include="ViewModels\MainViewVM.cs" /> + <Compile Include="ViewModels\MonitoringViewVM.cs" /> <Compile Include="ViewModels\RemoteDesktopViewVM.cs" /> <Compile Include="Views\ConsoleView.xaml.cs"> <DependentUpon>ConsoleView.xaml</DependentUpon> </Compile> + <Compile Include="Views\FileSystemView.xaml.cs"> + <DependentUpon>FileSystemView.xaml</DependentUpon> + </Compile> <Compile Include="Views\MainView.xaml.cs"> <DependentUpon>MainView.xaml</DependentUpon> </Compile> + <Compile Include="Views\MonitoringView.xaml.cs"> + <DependentUpon>MonitoringView.xaml</DependentUpon> + </Compile> <Compile Include="Views\RemoteDesktopView.xaml.cs"> <DependentUpon>RemoteDesktopView.xaml</DependentUpon> </Compile> @@ -143,6 +158,14 @@ </None> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\..\..\SideChains\RealTimeGraphX-master\RealTimeGraphX.WPF\RealTimeGraphX.WPF.csproj"> + <Project>{6b9774f7-960d-438e-ad81-c6b9be328d50}</Project> + <Name>RealTimeGraphX.WPF</Name> + </ProjectReference> + <ProjectReference Include="..\..\..\SideChains\RealTimeGraphX-master\RealTimeGraphX\RealTimeGraphX.csproj"> + <Project>{f13a489c-80ee-4cd0-bdd4-92d959215646}</Project> + <Name>RealTimeGraphX</Name> + </ProjectReference> <ProjectReference Include="..\..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj"> <Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project> <Name>Tango.AutoComplete</Name> @@ -159,6 +182,10 @@ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> <Name>Tango.Core</Name> </ProjectReference> + <ProjectReference Include="..\..\..\Tango.FileSystem\Tango.FileSystem.csproj"> + <Project>{c6ebbbbe-2123-44dc-aef7-a0d47d736ac0}</Project> + <Name>Tango.FileSystem</Name> + </ProjectReference> <ProjectReference Include="..\..\..\Tango.Integration\Tango.Integration.csproj"> <Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project> <Name>Tango.Integration</Name> @@ -183,6 +210,10 @@ <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project> <Name>Tango.SharedUI</Name> </ProjectReference> + <ProjectReference Include="..\..\..\Tango.SystemInfo\Tango.SystemInfo.csproj"> + <Project>{997a961c-beda-4b56-aa0f-c39e532f7ffa}</Project> + <Name>Tango.SystemInfo</Name> + </ProjectReference> <ProjectReference Include="..\..\..\Tango.Transport\Tango.Transport.csproj"> <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> <Name>Tango.Transport</Name> @@ -209,10 +240,18 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\FileSystemView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\MainView.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\MonitoringView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\RemoteDesktopView.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs index 1d07a1684..93317651c 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModelLocator.cs @@ -15,6 +15,8 @@ namespace Tango.FSE.PPCConsole TangoIOC.Default.Register<MainViewVM>(); TangoIOC.Default.Register<ConsoleViewVM>(); TangoIOC.Default.Register<RemoteDesktopViewVM>(); + TangoIOC.Default.Register<MonitoringViewVM>(); + TangoIOC.Default.Register<FileSystemViewVM>(); } public static MainViewVM MainViewVM @@ -40,5 +42,21 @@ namespace Tango.FSE.PPCConsole return TangoIOC.Default.GetInstance<RemoteDesktopViewVM>(); } } + + public static MonitoringViewVM MonitoringViewVM + { + get + { + return TangoIOC.Default.GetInstance<MonitoringViewVM>(); + } + } + + public static FileSystemViewVM FileSystemViewVM + { + get + { + return TangoIOC.Default.GetInstance<FileSystemViewVM>(); + } + } } } diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/ConsoleViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/ConsoleViewVM.cs index fd1567e0d..4c6eb9958 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/ConsoleViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/ConsoleViewVM.cs @@ -4,7 +4,10 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Console; +using Tango.Console.Network; +using Tango.Core.DI; using Tango.FSE.Common; +using Tango.FSE.Common.Console; namespace Tango.FSE.PPCConsole.ViewModels { @@ -12,6 +15,9 @@ namespace Tango.FSE.PPCConsole.ViewModels { private List<ConsoleSuggestion> _lastSuggestions; + [TangoInject] + public IConsoleService ConsoleService { get; set; } + private ConsoleControlVM _consoleVM; public ConsoleControlVM ConsoleVM { @@ -27,17 +33,35 @@ namespace Tango.FSE.PPCConsole.ViewModels ConsoleVM.Clear(); } + public override void OnApplicationStarted() + { + ConsoleService.Initialized += ConsoleService_Initialized1; + } + + private void ConsoleService_Initialized1(object sender, GetCurrentDirectoryResponse e) + { + ConsoleVM.Clear(); + ConsoleVM.CurrentCommand.WorkingFolder = e.CurrentDirectory; + ConsoleVM.AppendSuggestions(e.Suggestions); + } + private async void ConsoleVM_CommandExecuting(object sender, ConsoleCommandExecutingEventArgs e) { try { - var result = await MachineProvider.MachineOperator.SendGenericRequest<ConsoleCommandDTO, ConsoleCommandExecutionResult>(new ConsoleCommandDTO() + var response = await ConsoleService.ExecuteCommand(new ConsoleCommandRequest() { Command = e.Command.CommandText, WorkingFolder = e.Command.WorkingFolder, }); - _lastSuggestions = result.Suggestions; - e.Complete(result); + + _lastSuggestions = response.Suggestions; + e.Complete(new ConsoleCommandExecutionResult() + { + Output = response.Output, + Suggestions = response.Suggestions, + WorkingFolder = response.WorkingFolder + }); } catch (Exception ex) { diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs new file mode 100644 index 000000000..44bd03c39 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.Commands; +using Tango.FileSystem; +using Tango.FSE.Common; + +namespace Tango.FSE.PPCConsole.ViewModels +{ + public class FileSystemViewVM : FSEViewModel + { + private FileSystemItem _currentItem; + public FileSystemItem CurrentItem + { + get { return _currentItem; } + set { _currentItem = value; RaisePropertyChangedAuto(); OnCurrentItemChanged(); } + } + + private String _currentPath; + public String CurrentPath + { + get { return _currentPath; } + set { _currentPath = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand NavigateCommand { get; set; } + + public FileSystemViewVM() + { + NavigateCommand = new RelayCommand(Navigate); + } + + public override void OnApplicationReady() + { + base.OnApplicationReady(); + + FileSystemManager manager = new FileSystemManager(); + CurrentItem = FileSystemItem.FromDTO(manager.GetFolder(@"C:\")); + } + + private void Navigate() + { + if (CurrentPath.IsNotNullOrEmpty()) + { + FileSystemManager manager = new FileSystemManager(); + CurrentItem = FileSystemItem.FromDTO(manager.GetFolder(CurrentPath)); + } + } + + private void OnCurrentItemChanged() + { + CurrentPath = CurrentItem.Path; + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs index cd12bcdd9..5c73f70cc 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MainViewVM.cs @@ -13,6 +13,30 @@ namespace Tango.FSE.PPCConsole.ViewModels { public class MainViewVM : FSEViewModel { + public enum NavigationView + { + ConsoleView, + RemoteDesktopView, + MonitoringView, + FileSystemView, + } + + private NavigationView _selectedView; + public NavigationView SelectedView + { + get { return _selectedView; } + set + { + _selectedView = value; + RaisePropertyChangedAuto(); + } + } + + public override void OnNavigatedTo() + { + base.OnNavigatedTo(); + } + public override void OnApplicationReady() { base.OnApplicationReady(); diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MonitoringViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MonitoringViewVM.cs new file mode 100644 index 000000000..229a7ad61 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/MonitoringViewVM.cs @@ -0,0 +1,185 @@ +using LiveCharts; +using RealTimeGraphX.DataPoints; +using RealTimeGraphX.WPF; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media; +using Tango.FSE.Common; +using Tango.FSE.Common.Graphs; +using Tango.FSE.Common.Performance; +using Tango.Integration.ExternalBridge.Network.Information; +using Tango.SystemInfo; +using static Tango.SharedUI.Controls.NavigationControl; + +namespace Tango.FSE.PPCConsole.ViewModels +{ + public class MonitoringViewVM : FSEViewModel, INavigationViewModel + { + public WpfGraphController<DateTimeDataPoint, DoubleDataPoint> CPUController { get; set; } + + public WpfGraphController<DateTimeDataPoint, DoubleDataPoint> RAMController { get; set; } + + public Func<ChartPoint, string> DiskSpacePointLabel { get; set; } + + private InformationPackage _systemInfo; + public InformationPackage SystemInfo + { + get { return _systemInfo; } + set { _systemInfo = value; RaisePropertyChangedAuto(); } + } + + private SystemObjectsCollection _selectedSystemObjectCollection; + public SystemObjectsCollection SelectedSystemObjectCollection + { + get { return _selectedSystemObjectCollection; } + set { _selectedSystemObjectCollection = value; RaisePropertyChangedAuto(); } + } + + private bool _fetchingSystemInfo; + public bool FetchingSystemInfo + { + get { return _fetchingSystemInfo; } + set { _fetchingSystemInfo = value; RaisePropertyChangedAuto(); } + } + + private double _usedDiskSpace; + public double UsedDiskSpace + { + get { return _usedDiskSpace; } + set + { + if (_usedDiskSpace != value) + { + _usedDiskSpace = value; + RaisePropertyChangedAuto(); + } + } + } + + private double _availableDiskSpace; + public double AvailableDiskSpace + { + get { return _availableDiskSpace; } + set + { + if (_availableDiskSpace != value) + { + _availableDiskSpace = value; + RaisePropertyChangedAuto(); + } + } + } + + public MonitoringViewVM() + { + CPUController = CreateController(CreateSeries("Total", GraphHelper.GraphColor.White), CreateSeries("Application", GraphHelper.GraphColor.Red)); + RAMController = CreateController(CreateSeries("Total", GraphHelper.GraphColor.White), CreateSeries("Application", GraphHelper.GraphColor.Yellow)); + UsedDiskSpace = 1000 * 40; + AvailableDiskSpace = 1000 * 60; + DiskSpacePointLabel = (point) => + { + return $"{(point.Y / 1000d).ToString("0.0")} GB"; + }; + } + + private WpfGraphController<DateTimeDataPoint, DoubleDataPoint> CreateController(params WpfGraphDataSeries[] seriesCollection) + { + var controller = new WpfGraphController<DateTimeDataPoint, DoubleDataPoint>(); + + foreach (var series in seriesCollection) + { + controller.DataSeriesCollection.Add(series); + } + + controller.Range.AutoY = false; + controller.Range.MaximumY = 100; + controller.Range.MinimumY = 0; + controller.Range.MaximumX = new DateTime(0).AddMinutes(1); + + controller.RefreshRate = TimeSpan.FromMilliseconds(100); + + return controller; + } + + private WpfGraphDataSeries CreateSeries(String name, GraphHelper.GraphColor fill) + { + WpfGraphDataSeries series = new WpfGraphDataSeries(); + series.Name = name; + series.Fill = GraphHelper.GetGraphBrush(fill); + series.StrokeThickness = 1; + series.Stroke = GraphHelper.GetGraphStrokeColor(); + return series; + } + + public override void OnApplicationStarted() + { + base.OnApplicationStarted(); + PerformanceProvider.PerformancePackageAvailable += PerformanceProvider_PerformancePackageAvailable; + MachineProvider.MachineDisconnected += MachineProvider_MachineDisconnected; + } + + private void MachineProvider_MachineDisconnected(object sender, Common.Connection.MachineDisconnectedEventArgs e) + { + SystemInfo = null; + } + + private void PerformanceProvider_PerformancePackageAvailable(object sender, PerformancePackageEventArgs e) + { + List<DateTimeDataPoint> xx = new List<DateTimeDataPoint>() + { + DateTime.Now, + DateTime.Now + }; + + //CPU + CPUController.PushData(xx, new List<DoubleDataPoint>() + { + e.Package.CPU, + e.Package.ApplicationCPU + }); + + //App RAM + RAMController.Range.MaximumY = e.Package.MaxRAM; + RAMController.PushData(xx, new List<DoubleDataPoint>() + { + e.Package.RAM, + e.Package.ApplicationRAM + }); + + UsedDiskSpace = e.Package.DiskCapacity - e.Package.AvailableDiskSpace; + AvailableDiskSpace = e.Package.AvailableDiskSpace; + } + + public override async void OnNavigatedTo() + { + base.OnNavigatedTo(); + + if (MachineProvider.IsConnected) + { + if (SystemInfo == null) + { + try + { + FetchingSystemInfo = true; + SystemInfo = await SystemInfoProvider.GetSystemInformationPackage(); + SelectedSystemObjectCollection = SystemInfo.System.FirstOrDefault(); + } + catch (Exception ex) + { + FetchingSystemInfo = false; + LogManager.Log(ex, "Error retrieving system information from remote machine."); + await NotificationProvider.ShowWarning("Error retrieving the remote machine tablet system information."); + } + finally + { + FetchingSystemInfo = false; + } + } + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml index 0a26fc8b4..1aad6fa58 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/ConsoleView.xaml @@ -11,8 +11,8 @@ mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:ConsoleViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.ConsoleViewVM}"> <Grid> - <Border Background="#121212" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1"> - <console:ConsoleControl Background="#121212" Margin="10" BorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsBackground="{StaticResource FSE_PrimaryBackgroundBrush}" SuggestionsBorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsForeground="Silver" DataContext="{Binding ConsoleVM}"> + <Border Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1" CornerRadius="5"> + <console:ConsoleControl Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" Margin="10" BorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsBackground="{StaticResource FSE_PrimaryBackgroundBrush}" SuggestionsBorderBrush="{StaticResource FSE_BorderBrush}" SuggestionsForeground="Silver" DataContext="{Binding ConsoleVM}"> <console:ConsoleControl.BusyTemplate> <DataTemplate> <ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" IsIndeterminate="True" Width="16" Height="16" /> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml new file mode 100644 index 000000000..ad503c7de --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml @@ -0,0 +1,61 @@ +<UserControl x:Class="Tango.FSE.PPCConsole.Views.FileSystemView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:global="clr-namespace:Tango.FSE.PPCConsole" + xmlns:vm="clr-namespace:Tango.FSE.PPCConsole.ViewModels" + xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:Tango.FSE.PPCConsole.Views" + xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:FileSystemViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.FileSystemViewVM}"> + <Grid> + <Grid Margin="0 20 0 0"> + <Grid.RowDefinitions> + <RowDefinition Height="30" /> + <RowDefinition Height="1*" /> + </Grid.RowDefinitions> + + <DockPanel> + <ListBox x:Name="listView" SelectedIndex="1" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" SelectionChanged="ListView_SelectionChanged" Style="{StaticResource MaterialDesignToolToggleListBox}" Margin="50 0 0 0" DockPanel.Dock="Right"> + <ListBox.Resources> + <SolidColorBrush x:Key="MaterialDesignDivider" Color="{StaticResource FSE_PrimaryBackgroundDarkColor}"/> + </ListBox.Resources> + <ListBoxItem Width="60" HorizontalContentAlignment="Center" Tag="Large"> + <material:PackIcon Kind="ViewList" Width="Auto" Height="20" /> + </ListBoxItem> + <ListBoxItem Width="60" HorizontalContentAlignment="Center" Tag="Details"> + <material:PackIcon Kind="FormatListBulleted" Width="Auto" Height="20" /> + </ListBoxItem> + </ListBox> + <DockPanel> + <StackPanel DockPanel.Dock="Right" Orientation="Horizontal"> + <Button Command="{Binding NavigateCommand}" material:ButtonAssist.CornerRadius="0 3 3 0" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Padding="0" Width="60" Height="Auto"> + <material:PackIcon Kind="Refresh" Width="Auto" Height="20" /> + </Button> + </StackPanel> + <StackPanel DockPanel.Dock="Left" Orientation="Horizontal"> + <Button material:ButtonAssist.CornerRadius="3 0 0 3" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Padding="0" Width="60" Height="Auto"> + <material:PackIcon Kind="ChevronLeft" Width="Auto" Height="20" /> + </Button> + </StackPanel> + <Border> + <Border BorderThickness="3" BorderBrush="{StaticResource FSE_PrimaryBackgroundLightBrush}" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}"> + <Border.Effect> + <DropShadowEffect BlurRadius="2" ShadowDepth="2" Opacity="0.3" Direction="270" /> + </Border.Effect> + <TextBox Padding="5 0 0 0" Text="{Binding CurrentPath,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}" CaretBrush="{StaticResource FSE_PrimaryForegroundBrush}" Background="Transparent" BorderThickness="0" VerticalContentAlignment="Center" Style="{x:Null}"> + <TextBox.InputBindings> + <KeyBinding Key="Return" Command="{Binding NavigateCommand}" /> + </TextBox.InputBindings> + </TextBox> + </Border> + </Border> + </DockPanel> + </DockPanel> + + <controls:FileSystemControl Margin="0 10 0 0" CurrentItem="{Binding CurrentItem}" Grid.Row="1" Mode="{Binding ElementName=listView,Path=SelectedItem.Tag}" /> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml.cs new file mode 100644 index 000000000..87fc7e30c --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/FileSystemView.xaml.cs @@ -0,0 +1,42 @@ +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.PPCConsole.Views +{ + /// <summary> + /// Interaction logic for FileSystemView.xaml + /// </summary> + public partial class FileSystemView : UserControl + { + private object _lastSelectedItem; + + public FileSystemView() + { + InitializeComponent(); + } + + private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (listView.SelectedItem != null) + { + _lastSelectedItem = listView.SelectedItem; + } + else + { + listView.SelectedItem = _lastSelectedItem; + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml index 1f47bf832..e11014515 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MainView.xaml @@ -4,42 +4,41 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:global="clr-namespace:Tango.FSE.PPCConsole" + xmlns:resolution="clr-namespace:Tango.FSE.Common.Resolution;assembly=Tango.FSE.Common" xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz" xmlns:vm="clr-namespace:Tango.FSE.PPCConsole.ViewModels" xmlns:local="clr-namespace:Tango.FSE.PPCConsole.Views" xmlns:console="clr-namespace:Tango.Console;assembly=Tango.Console" + xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" + xmlns:commonControls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common" + xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> <Grid Margin="10"> <Grid> - <!--<Grid.ColumnDefinitions> - <ColumnDefinition Width="200" /> - <ColumnDefinition Width="1*" /> - </Grid.ColumnDefinitions>--> + <Grid> + <Grid.Style> + <Style TargetType="Grid"> + <Setter Property="Margin" Value="100 40"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding ResolutionService.IsLowResolution}" Value="True"> + <Setter Property="Margin" Value="20"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Grid.Style> + <commonControls:FSETabControl TabsWidth="900" x:Name="tabs" SelectedObject="{Binding SelectedView,Mode=TwoWay}"> + <local:MonitoringView Tag="MONITORING" /> + <local:RemoteDesktopView Tag="REMOTE DESKTOP" /> + <local:ConsoleView Tag="COMMAND PROMPT" /> + <local:FileSystemView Tag="FILE SYSTEM" /> + <ContentControl Tag="UPDATES" /> + </commonControls:FSETabControl> - <!--<Grid> - <ListBox x:Name="listMenu" HorizontalContentAlignment="Stretch" Focusable="False"> - <Button Margin="5" HorizontalContentAlignment="Right" IsHitTestVisible="False" Style="{StaticResource FSE_FlatButton_ForegroundAccentHover}">CONSOLE</Button> - <Button Margin="5" HorizontalContentAlignment="Right" IsHitTestVisible="False" Style="{StaticResource FSE_FlatButton_ForegroundAccentHover}">REMOTE DESKTOP</Button> - </ListBox> - </Grid>--> - - <TabControl Margin="10 0 0 0" Background="Transparent" BorderThickness="0" Padding="0" Grid.Column="1" SelectedIndex="{Binding ElementName=listMenu,Path=SelectedIndex,Mode=TwoWay}"> - <TabItem Header="REMOTE DESKTOP" Visibility="Collapsed"> - <!--REMOTE DESKTOP--> - <Grid Grid.Column="1"> - <local:RemoteDesktopView /> - </Grid> - </TabItem> - <TabItem Header="CONSOLE" Visibility="Collapsed"> - <!--CONSOLE--> - <Grid> - <local:ConsoleView /> - </Grid> - </TabItem> - </TabControl> + <TextBlock resolution:ResolutionHelper.MinWidth="1500" Margin="10 0 0 0" FontFamily="{StaticResource hand}" FontSize="{StaticResource FSE_ModuleHeaderFontSize}" Foreground="{StaticResource FSE_PrimaryAccentDarkBrush}" VerticalAlignment="Top" HorizontalAlignment="Left" Text="{Binding ElementName=tabs,Path=SelectedElement.Tag,Converter={StaticResource StringToTitleCaseConverter}}"></TextBlock> + </Grid> </Grid> </Grid> </UserControl> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml new file mode 100644 index 000000000..79077d0b9 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml @@ -0,0 +1,205 @@ +<UserControl x:Class="Tango.FSE.PPCConsole.Views.MonitoringView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:graphs="clr-namespace:Tango.FSE.Common.Graphs;assembly=Tango.FSE.Common" + xmlns:global="clr-namespace:Tango.FSE.PPCConsole" + xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf" + xmlns:vm="clr-namespace:Tango.FSE.PPCConsole.ViewModels" + xmlns:converters="clr-namespace:Tango.FSE.PPCConsole.Converters" + xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common" + xmlns:local="clr-namespace:Tango.FSE.PPCConsole.Views" + mc:Ignorable="d" + d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:MonitoringViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MonitoringViewVM}"> + + <UserControl.Resources> + + <converters:DoubleToChartValuesConverter x:Key="DoubleToChartValuesConverter" /> + + <Style x:Key="DynamicResolutionGraph" TargetType="graphs:RealTimeGraph" BasedOn="{StaticResource {x:Type graphs:RealTimeGraph}}"> + <Setter Property="VerticalTicks" Value="11"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding ResolutionService.IsLowResolution}" Value="True"> + <Setter Property="VerticalTicks" Value="5"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + + <Style x:Key="ItemsPanel_Legends" TargetType="ItemsControl"> + <Setter Property="Margin" Value="40"></Setter> + <Setter Property="HorizontalAlignment" Value="Right"></Setter> + <Setter Property="VerticalAlignment" Value="Top"></Setter> + <Setter Property="ItemsPanel"> + <Setter.Value> + <ItemsPanelTemplate> + <StackPanel Orientation="Horizontal"></StackPanel> + </ItemsPanelTemplate> + </Setter.Value> + </Setter> + <Setter Property="ItemTemplate"> + <Setter.Value> + <DataTemplate> + <StackPanel Orientation="Horizontal" Margin="0 0 20 0"> + <Ellipse Width="10" Height="10" Fill="{Binding Fill}" /> + <TextBlock Opacity="0.5" FontWeight="SemiBold" Margin="5 0 0 0" FontSize="{StaticResource FSE_SmallFontSize}" Text="{Binding Name}"></TextBlock> + </StackPanel> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + </UserControl.Resources> + + <Grid> + <Grid Margin="20 20 20 0"> + <Grid.RowDefinitions> + <RowDefinition Height="1*"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="1*"/> + <ColumnDefinition Width="1*"/> + </Grid.ColumnDefinitions> + + <Grid Margin="0 0 20 0"> + <graphs:RealTimeGraph Style="{StaticResource DynamicResolutionGraph}" Controller="{Binding CPUController}" StringFormat="0\%"/> + + <ItemsControl Style="{StaticResource ItemsPanel_Legends}" ItemsSource="{Binding CPUController.DataSeriesCollection}"/> + + <Viewbox IsHitTestVisible="False" Margin="90 50 90 90" Stretch="Uniform"> + <Grid Width="200" Height="200"> + <Ellipse Stroke="#38FFFFFF" StrokeThickness="20" /> + + <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Opacity="0.8" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="SemiBold" FontSize="25" Text="{Binding CPUController.DataSeriesCollection[0].CurrentValue,StringFormat='\{0\}%'}"></TextBlock> + <Rectangle Width="120" Margin="0 5" VerticalAlignment="Center" Stroke="{StaticResource FSE_PrimaryForegroundBrush}" StrokeThickness="1" /> + <TextBlock Opacity="0.8" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="SemiBold" FontSize="25" Text="{Binding CPUController.DataSeriesCollection[1].CurrentValue,StringFormat='\{0\}%'}"></TextBlock> + </StackPanel> + </Grid> + </Viewbox> + + <TextBlock Foreground="{StaticResource FSE_PrimaryAccentBrush}" Margin="100 30" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="{StaticResource FSE_LargeFontSize}" FontWeight="SemiBold">CPU</TextBlock> + </Grid> + + <Grid Margin="20 0 0 0" Grid.Column="1"> + <graphs:RealTimeGraph Style="{StaticResource DynamicResolutionGraph}" Controller="{Binding RAMController}" StringFormat="0 \MB" /> + + <ItemsControl Style="{StaticResource ItemsPanel_Legends}" ItemsSource="{Binding RAMController.DataSeriesCollection}"/> + + <Viewbox IsHitTestVisible="False" Margin="90 50 90 90" Stretch="Uniform"> + <Grid Width="200" Height="200"> + <Ellipse Stroke="#38FFFFFF" StrokeThickness="20" /> + + <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Opacity="0.8" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="SemiBold" FontSize="25" Text="{Binding RAMController.DataSeriesCollection[0].CurrentValue,StringFormat='\{0\} MB'}"></TextBlock> + <Rectangle Width="120" Margin="0 5" VerticalAlignment="Center" Stroke="{StaticResource FSE_PrimaryForegroundBrush}" StrokeThickness="1" /> + <TextBlock Opacity="0.8" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="SemiBold" FontSize="25" Text="{Binding RAMController.DataSeriesCollection[1].CurrentValue,StringFormat='\{0\} MB'}"></TextBlock> + </StackPanel> + </Grid> + </Viewbox> + + <TextBlock Foreground="{StaticResource FSE_PrimaryAccentBrush}" Margin="100 30" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="{StaticResource FSE_LargeFontSize}" FontWeight="SemiBold">RAM</TextBlock> + </Grid> + + <Grid Grid.Row="1" Grid.ColumnSpan="2" Margin="0 40 0 0"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="2*"/> + <ColumnDefinition Width="8*"/> + </Grid.ColumnDefinitions> + + <Grid> + <DockPanel> + + <TextBlock DockPanel.Dock="Top" Foreground="{StaticResource FSE_GrayBrush}" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="{StaticResource FSE_LargeFontSize}" FontWeight="SemiBold">AVAILABLE DISK SPACE</TextBlock> + + <lvc:PieChart Opacity="0.7" DisableAnimations="True" LegendLocation="Bottom" Hoverable="False" DataTooltip="{x:Null}" HorizontalAlignment="Left" Width="250"> + <lvc:PieChart.Series> + <lvc:PieSeries Foreground="{StaticResource FSE_PrimaryForegroundBrush}" Stroke="{StaticResource FSE_PrimaryBackgroundBrush}" Fill="#F47FD121" FontSize="16" Title="Free" Values="{Binding AvailableDiskSpace,Converter={StaticResource DoubleToChartValuesConverter}}" DataLabels="True" + LabelPoint="{Binding DiskSpacePointLabel}"/> + <lvc:PieSeries Foreground="{StaticResource FSE_PrimaryForegroundBrush}" Stroke="{StaticResource FSE_PrimaryBackgroundBrush}" Fill="#FF4F4F" FontSize="16" Title="Used" Values="{Binding UsedDiskSpace,Converter={StaticResource DoubleToChartValuesConverter}}" DataLabels="True" + LabelPoint="{Binding DiskSpacePointLabel}"/> + </lvc:PieChart.Series> + </lvc:PieChart> + </DockPanel> + </Grid> + + <Grid Grid.Column="1"> + <DockPanel> + <TextBlock DockPanel.Dock="Top" Foreground="{StaticResource FSE_GrayBrush}" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="{StaticResource FSE_LargeFontSize}" FontWeight="SemiBold">SYSTEM INFORMATION</TextBlock> + + <controls:FSEPanel Margin="0 10 0 0" Padding="20" > + <Grid> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="270"/> + <ColumnDefinition Width="1*"/> + </Grid.ColumnDefinitions> + + <ListBox ItemsSource="{Binding SystemInfo.System}" SelectedItem="{Binding SelectedSystemObjectCollection}"> + <ListBox.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel/> + </ItemsPanelTemplate> + </ListBox.ItemsPanel> + <ListBox.ItemTemplate> + <DataTemplate> + <TextBlock Width="115" Text="{Binding Name}"></TextBlock> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + + <ScrollViewer Margin="40 0 0 0" Grid.Column="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"> + <ItemsControl ItemsSource="{Binding SelectedSystemObjectCollection.Objects}"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Horizontal" IsItemsHost="True"></WrapPanel> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate> + <DockPanel Margin="10 0 10 10" Width="400"> + <TextBlock TextTrimming="CharacterEllipsis" DockPanel.Dock="Top" Text="{Binding Name}" Foreground="{StaticResource FSE_GrayBrush}"></TextBlock> + <Border TextElement.FontSize="{StaticResource FSE_SmallFontSize}" Margin="0 5 0 0" Padding="3" BorderThickness="0" BorderBrush="{StaticResource FSE_BorderBrush}" CornerRadius="5"> + <ItemsControl Opacity="0.7" ItemsSource="{Binding Properties}"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Vertical" /> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate> + <DockPanel> + <DockPanel.ToolTip> + <TextBlock> + <Run FontWeight="SemiBold" Text="{Binding Name}"></Run><Run>:</Run> + <Run Text="{Binding Value}"></Run> + </TextBlock> + </DockPanel.ToolTip> + <TextBlock TextTrimming="CharacterEllipsis" Width="100" FontWeight="SemiBold" HorizontalAlignment="Left"> + <Run Text="{Binding Name}"></Run><Run>:</Run> + </TextBlock> + <TextBlock TextTrimming="CharacterEllipsis" Margin="20 0 0 0" HorizontalAlignment="Left" Text="{Binding Value}"></TextBlock> + </DockPanel> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </Border> + </DockPanel> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </ScrollViewer> + </Grid> + + <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding FetchingSystemInfo,Converter={StaticResource BooleanToVisibilityConverter}}"> + <ProgressBar HorizontalAlignment="Center" Style="{StaticResource FSE_CircularProgressBar}" IsIndeterminate="{Binding FetchingSystemInfo}" Width="100" Height="100" /> + <TextBlock HorizontalAlignment="Center" Margin="0 10 0 0" Text="Fetching System Information..."></TextBlock> + </StackPanel> + </Grid> + </controls:FSEPanel> + </DockPanel> + </Grid> + </Grid> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml.cs new file mode 100644 index 000000000..84672dd50 --- /dev/null +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/MonitoringView.xaml.cs @@ -0,0 +1,33 @@ +using LiveCharts; +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.PPCConsole.Views +{ + /// <summary> + /// Interaction logic for MonitoringView.xaml + /// </summary> + public partial class MonitoringView : UserControl + { + public Func<ChartPoint, string> PointLabel { get; set; } + + public MonitoringView() + { + PointLabel = chartPoint => string.Format("{0} ({1:P})", chartPoint.Y, chartPoint.Participation); + + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml index 110fcbcbd..644bfabba 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml @@ -5,11 +5,13 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:global="clr-namespace:Tango.FSE.PPCConsole" xmlns:vm="clr-namespace:Tango.FSE.PPCConsole.ViewModels" + xmlns:resolution="clr-namespace:Tango.FSE.Common.Resolution;assembly=Tango.FSE.Common" xmlns:local="clr-namespace:Tango.FSE.PPCConsole.Views" + xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common" xmlns:console="clr-namespace:Tango.Console;assembly=Tango.Console" xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" - d:DesignHeight="800" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:RemoteDesktopViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.RemoteDesktopViewVM}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> + d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:RemoteDesktopViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.RemoteDesktopViewVM}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> <Grid> <DockPanel> <Border DockPanel.Dock="Right" CornerRadius="15" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1"> @@ -39,36 +41,147 @@ </Border> <Grid IsHitTestVisible="False"> - <material:PackIcon Visibility="{Binding RemoteDesktopProvider.IsWebRtcActive,Converter={StaticResource BooleanToVisibilityConverter}}" Kind="LightningBolt" HorizontalAlignment="Right" VerticalAlignment="Top" Width="16" Height="16" Margin="10" Foreground="{StaticResource FSE_GreenBrush}" /> + <material:PackIcon Visibility="{Binding RemoteDesktopProvider.IsWebRtcActive,Converter={StaticResource BooleanToVisibilityConverter}}" Kind="LightningBoltCircle" HorizontalAlignment="Right" VerticalAlignment="Top" Width="16" Height="16" Margin="10 8 30 10" Foreground="{StaticResource FSE_GreenBrush}" /> </Grid> </Grid> </Border> <Grid> - <DockPanel MaxWidth="700" Margin="0 100 0 0"> + <DockPanel> + <DockPanel.Style> + <Style TargetType="DockPanel"> + <Setter Property="Margin" Value="0 100 100 50"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding ResolutionService.IsLowResolution}" Value="True"> + <Setter Property="Margin" Value="0 20 100 0"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </DockPanel.Style> <StackPanel DockPanel.Dock="Top"> <DockPanel> - <TextBlock VerticalAlignment="Center" FontSize="{StaticResource FSE_ModuleHeaderFontSize}">REMOTE DESKTOP</TextBlock> - <Grid HorizontalAlignment="Right" Margin="0 0 100 0" Width="150" Height="150"> - <Image Source="{StaticResource FSE_Machine_Full}" VerticalAlignment="Top" HorizontalAlignment="Right" RenderOptions.BitmapScalingMode="Fant" Width="120" Stretch="Uniform" /> - <Image Source="../Images/desktop.png" Stretch="Uniform" Width="90" HorizontalAlignment="Left" VerticalAlignment="Bottom" /> - </Grid> + <TextBlock VerticalAlignment="Center" FontStyle="Italic" FontSize="{StaticResource FSE_ModuleHeaderFontSize}">REMOTE DESKTOP</TextBlock> + <Viewbox Stretch="Uniform" HorizontalAlignment="Right" Margin="0 0 100 0"> + <Viewbox.Style> + <Style TargetType="Viewbox"> + <Setter Property="Width" Value="100"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding ResolutionService.IsLowResolution}" Value="True"> + <Setter Property="Width" Value="50"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Viewbox.Style> + <Grid Width="100" Height="100"> + <Image Source="{StaticResource FSE_Machine_Full}" VerticalAlignment="Top" HorizontalAlignment="Right" RenderOptions.BitmapScalingMode="Fant" Width="90" Stretch="Uniform" /> + <Image Source="../Images/desktop.png" Stretch="Uniform" Width="60" HorizontalAlignment="Left" VerticalAlignment="Bottom" /> + </Grid> + </Viewbox> </DockPanel> <Rectangle StrokeThickness="1" Stroke="{StaticResource FSE_BorderBrush}" Height="1" StrokeDashArray="4" Margin="0 20 0 0" /> </StackPanel> <Grid> - + <DockPanel Margin="0 20 0 0"> + <StackPanel DockPanel.Dock="Top"> + <TextBlock TextWrapping="Wrap"> + <Run>Remote desktop allows you to view and control the currently connected machine tablet PC screen.</Run> + <LineBreak/> + <Run>Press 'start' to start a remote desktop session.</Run> + </TextBlock> + </StackPanel> + <Grid DockPanel.Dock="Bottom"> + + <Grid HorizontalAlignment="Left"> + <Grid.Style> + <Style TargetType="Grid"> + <Setter Property="Margin" Value="0 0 0 0"></Setter> + <Setter Property="VerticalAlignment" Value="Bottom"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding ResolutionService.IsLowResolution}" Value="True"> + <Setter Property="VerticalAlignment" Value="Top"></Setter> + <Setter Property="Margin" Value="0 -40 0 0"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Grid.Style> + + <StackPanel Orientation="Horizontal"> + <material:PackIcon> + <material:PackIcon.Style> + <Style TargetType="material:PackIcon"> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryBackgroundLighterBrush}"></Setter> + <Setter Property="Kind" Value="Circle"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RemoteDesktopProvider.InSession}" Value="True"> + <Setter Property="Foreground" Value="{StaticResource FSE_SuccessBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding RemoteDesktopProvider.IsWebRtcActive}" Value="True"> + <Setter Property="Kind" Value="LightningBoltCircle"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </material:PackIcon.Style> + </material:PackIcon> + <TextBlock Margin="10 0 0 0"> + <TextBlock.Style> + <Style TargetType="TextBlock"> + <Setter Property="Text" Value="Remote desktop disabled. No active machine connection."></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_BorderBrush}"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding MachineProvider.IsConnected}" Value="False"> + <Setter Property="Text" Value="Remote desktop disabled. No active machine connection."></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding MachineProvider.IsConnected}" Value="True"> + <Setter Property="Text" Value="Remote desktop session is ready to start."></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding RemoteDesktopProvider.InSession}" Value="True"> + <Setter Property="Text" Value="Remote desktop session is active."></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding RemoteDesktopProvider.IsWebRtcActive}" Value="True"> + <Setter Property="Text" Value="Remote desktop session is active using a fast communication channel."></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBlock.Style> + </TextBlock> + </StackPanel> + </Grid> + + <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Height="50"> + <controls:TextIconButton Icon="Stop" Padding="0 12" Width="200" Command="{Binding StopCommand}" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Grid.Column="1" Style="{StaticResource FSE_TextIconButton_Dark}">STOP</controls:TextIconButton> + <controls:TextIconButton Icon="Play" Padding="0 12" Width="200" Command="{Binding StartCommand}" IsEnabled="{Binding RemoteDesktopProvider.CanStartSession}" Grid.Column="2" Margin="10 0 0 0" Height="Auto">START</controls:TextIconButton> + </StackPanel> + </Grid> + <Grid> + <StackPanel Margin="0 40 0 0"> + <TextBlock FontStyle="Italic" Foreground="{StaticResource FSE_PrimaryAccentBrush}" FontSize="{StaticResource FSE_LargeFontSize}">Actions</TextBlock> + + <UniformGrid Margin="0 10 0 0" HorizontalAlignment="Left"> + <UniformGrid.Style> + <Style TargetType="UniformGrid"> + <Setter Property="Rows" Value="3"></Setter> + <Setter Property="Columns" Value="1"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding ResolutionService.IsLowResolution}" Value="True"> + <Setter Property="Columns" Value="2"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </UniformGrid.Style> + <Button IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Hide PPC and open shell"/> + + <Button IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Restart application"/> + + <Button IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Something else"/> + + <CheckBox Margin="5" HorizontalAlignment="Center" IsEnabled="{Binding RemoteDesktopProvider.InSession,Converter={StaticResource BooleanInverseConverter}}" IsChecked="{Binding RemoteDesktopProvider.EnableWebRtc}">Enable fast communication channel</CheckBox> + </UniformGrid> + </StackPanel> + </Grid> + </DockPanel> </Grid> </DockPanel> - <!--<Grid> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="1*" /> - <ColumnDefinition Width="50*" /> - <ColumnDefinition Width="50*" /> - </Grid.ColumnDefinitions> - <Button Command="{Binding StopCommand}" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Grid.Column="1" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">STOP</Button> - <Button Command="{Binding StartCommand}" IsEnabled="{Binding RemoteDesktopProvider.CanStartSession}" Grid.Column="2" Margin="10 0 0 0" Style="{StaticResource FSE_RaisedButton_Dark_Hover}">START</Button> - </Grid>--> </Grid> </DockPanel> </Grid> diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/packages.config b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/packages.config index c795da787..626240206 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/packages.config +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/packages.config @@ -4,6 +4,8 @@ <package id="Dragablz" version="0.0.3.203" targetFramework="net461" /> <package id="EntityFramework" version="6.2.0" targetFramework="net461" /> <package id="Google.Protobuf" version="3.4.1" targetFramework="net461" /> + <package id="LiveCharts" version="0.9.7" targetFramework="net461" /> + <package id="LiveCharts.Wpf" version="0.9.7" targetFramework="net461" /> <package id="MahApps.Metro" version="1.6.5" targetFramework="net461" /> <package id="MaterialDesignColors" version="1.2.2" targetFramework="net461" /> <package id="MaterialDesignThemes" version="3.0.1" targetFramework="net461" /> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Console/IConsoleService.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Console/IConsoleService.cs new file mode 100644 index 000000000..321b183d8 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Console/IConsoleService.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Console.Network; + +namespace Tango.FSE.Common.Console +{ + public interface IConsoleService + { + event EventHandler<GetCurrentDirectoryResponse> Initialized; + String CurrentDirectory { get; } + Task<ConsoleCommandResponse> ExecuteCommand(ConsoleCommandRequest request, TimeSpan? timeout = null); + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSEPanel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSEPanel.cs new file mode 100644 index 000000000..3eaabb595 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSEPanel.cs @@ -0,0 +1,49 @@ +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.Common.Controls +{ + public class FSEPanel : ContentControl + { + public CornerRadius CornerRadius + { + get { return (CornerRadius)GetValue(CornerRadiusProperty); } + set { SetValue(CornerRadiusProperty, value); } + } + public static readonly DependencyProperty CornerRadiusProperty = + DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(FSEPanel), new PropertyMetadata(default(CornerRadius))); + + public double ScrewSize + { + get { return (double)GetValue(ScrewSizeProperty); } + set { SetValue(ScrewSizeProperty, value); } + } + public static readonly DependencyProperty ScrewSizeProperty = + DependencyProperty.Register("ScrewSize", typeof(double), typeof(FSEPanel), new PropertyMetadata(10.0)); + + public Thickness ScrewMargin + { + get { return (Thickness)GetValue(ScrewMarginProperty); } + set { SetValue(ScrewMarginProperty, value); } + } + public static readonly DependencyProperty ScrewMarginProperty = + DependencyProperty.Register("ScrewMargin", typeof(Thickness), typeof(FSEPanel), new PropertyMetadata(default(Thickness))); + + static FSEPanel() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(FSEPanel), new FrameworkPropertyMetadata(typeof(FSEPanel))); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSEPanel.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSEPanel.xaml new file mode 100644 index 000000000..986899490 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSEPanel.xaml @@ -0,0 +1,36 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="clr-namespace:Tango.FSE.Common.Controls"> + + <Style TargetType="{x:Type local:FSEPanel}"> + <Setter Property="BorderBrush" Value="{StaticResource FSE_Panel_BorderBrush}"></Setter> + <Setter Property="BorderThickness" Value="1"></Setter> + <Setter Property="Background" Value="{StaticResource FSE_Panel_BackgroundBrush}"></Setter> + <Setter Property="CornerRadius" Value="5"></Setter> + <Setter Property="ScrewSize" Value="10"></Setter> + <Setter Property="ScrewMargin" Value="8"></Setter> + <Setter Property="Padding" Value="15"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type local:FSEPanel}"> + <Grid> + <Border Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}" + Padding="{TemplateBinding Padding}" + CornerRadius="{TemplateBinding CornerRadius}"> + <ContentPresenter Content="{TemplateBinding Content}"/> + </Border> + + <Image HorizontalAlignment="Left" VerticalAlignment="Top" Margin="{TemplateBinding ScrewMargin}" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="{TemplateBinding ScrewSize}" Height="{TemplateBinding ScrewSize}" /> + <Image HorizontalAlignment="Right" VerticalAlignment="Top" Margin="{TemplateBinding ScrewMargin}" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="{TemplateBinding ScrewSize}" Height="{TemplateBinding ScrewSize}" /> + + <Image HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="{TemplateBinding ScrewMargin}" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="{TemplateBinding ScrewSize}" Height="{TemplateBinding ScrewSize}" /> + <Image HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="{TemplateBinding ScrewMargin}" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="{TemplateBinding ScrewSize}" Height="{TemplateBinding ScrewSize}" /> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + +</ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSETabControl.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSETabControl.cs new file mode 100644 index 000000000..44cfd4872 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSETabControl.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +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.Markup; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Tango.SharedUI; +using Tango.SharedUI.Controls; +using static Tango.SharedUI.Controls.NavigationControl; + +namespace Tango.FSE.Common.Controls +{ + [ContentProperty(nameof(Elements))] + public class FSETabControl : Control + { + private NavigationControl _navigationControl; + + public ObservableCollection<FrameworkElement> Elements + { + get { return (ObservableCollection<FrameworkElement>)GetValue(ElementsProperty); } + set { SetValue(ElementsProperty, value); } + } + public static readonly DependencyProperty ElementsProperty = + DependencyProperty.Register("Elements", typeof(ObservableCollection<FrameworkElement>), typeof(FSETabControl), new PropertyMetadata(null)); + + public FrameworkElement SelectedElement + { + get { return (FrameworkElement)GetValue(SelectedElementProperty); } + set { SetValue(SelectedElementProperty, value); } + } + public static readonly DependencyProperty SelectedElementProperty = + DependencyProperty.Register("SelectedElement", typeof(FrameworkElement), typeof(FSETabControl), new PropertyMetadata(null)); + + public TransitionTypes TransitionType + { + get { return (TransitionTypes)GetValue(TransitionTypeProperty); } + set { SetValue(TransitionTypeProperty, value); } + } + public static readonly DependencyProperty TransitionTypeProperty = + DependencyProperty.Register("TransitionType", typeof(TransitionTypes), typeof(FSETabControl), new PropertyMetadata(TransitionTypes.Slide)); + + public bool TransitionAlwaysFades + { + get { return (bool)GetValue(TransitionAlwaysFadesProperty); } + set { SetValue(TransitionAlwaysFadesProperty, value); } + } + public static readonly DependencyProperty TransitionAlwaysFadesProperty = + DependencyProperty.Register("TransitionAlwaysFades", typeof(bool), typeof(FSETabControl), new PropertyMetadata(false)); + + public Duration TransitionDuration + { + get { return (Duration)GetValue(TransitionDurationProperty); } + set { SetValue(TransitionDurationProperty, value); } + } + public static readonly DependencyProperty TransitionDurationProperty = + DependencyProperty.Register("TransitionDuration", typeof(Duration), typeof(FSETabControl), new PropertyMetadata(new Duration(TimeSpan.FromSeconds(0.2)))); + + public object SelectedObject + { + get { return (object)GetValue(SelectedObjectProperty); } + set { SetValue(SelectedObjectProperty, value); } + } + public static readonly DependencyProperty SelectedObjectProperty = + DependencyProperty.Register("SelectedObject", typeof(object), typeof(FSETabControl), new PropertyMetadata(null)); + + public double TabsWidth + { + get { return (double)GetValue(TabsWidthProperty); } + set { SetValue(TabsWidthProperty, value); } + } + public static readonly DependencyProperty TabsWidthProperty = + DependencyProperty.Register("TabsWidth", typeof(double), typeof(FSETabControl), new PropertyMetadata(double.NaN)); + + public FSETabControl() + { + Elements = new ObservableCollection<FrameworkElement>(); + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + _navigationControl = GetTemplateChild("navigation") as NavigationControl; + _navigationControl.SelectedElementChanged += (x, e) => + { + SelectedElement = e; + }; + + _navigationControl.Elements = Elements; + } + + static FSETabControl() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(FSETabControl), new FrameworkPropertyMetadata(typeof(FSETabControl))); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSETabControl.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSETabControl.xaml new file mode 100644 index 000000000..73aa05931 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FSETabControl.xaml @@ -0,0 +1,106 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" + xmlns:local="clr-namespace:Tango.FSE.Common.Controls"> + + <Style TargetType="{x:Type local:FSETabControl}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type local:FSETabControl}"> + <Border Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}"> + + <DockPanel> + <Grid DockPanel.Dock="Top" Height="50"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="1*" /> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="1*" /> + </Grid.ColumnDefinitions> + <Rectangle Grid.Column="0" VerticalAlignment="Bottom" StrokeThickness="2" Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" /> + <ListBox x:Name="listTabs" Grid.Column="1" DisplayMemberPath="Tag" ItemsSource="{Binding ElementName=navigation,Path=Elements}" SelectedItem="{Binding ElementName=navigation,Path=SelectedElement,Mode=TwoWay}" SelectedIndex="0" Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=TabsWidth}"> + <ListBox.Style> + <Style TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}"> + <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"></Setter> + <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"></Setter> + <Setter Property="ItemsPanel"> + <Setter.Value> + <ItemsPanelTemplate> + <UniformGrid Margin="15 0 0 0" Columns="{Binding RelativeSource={RelativeSource AncestorType=ListBox},Path=Items.Count}" IsItemsHost="True"></UniformGrid> + </ItemsPanelTemplate> + </Setter.Value> + </Setter> + <Setter Property="ItemContainerStyle"> + <Setter.Value> + <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}"> + <Setter Property="HorizontalContentAlignment" Value="Center"></Setter> + <Setter Property="VerticalContentAlignment" Value="Center"></Setter> + <Setter Property="Background" Value="{StaticResource FSE_PrimaryBackgroundBrush}"></Setter> + <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_GrayBrush}"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="ListBoxItem"> + <Grid x:Name="grid" Margin="-15 0 0 0" Background="Transparent"> + <Viewbox Stretch="Fill"> + <Grid> + <Polygon Fill="{TemplateBinding Background}" Stretch="Fill" Points="0,30 15,0 85,0 100,30"></Polygon> + <Polygon Fill="White" Stretch="Fill" Points="0,30 15,0 85,0 100,30" IsHitTestVisible="False" Opacity="0.1"> + <Polygon.Style> + <Style TargetType="Polygon"> + <Setter Property="Visibility" Value="Hidden"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem},Path=IsMouseOver}" Value="True"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Polygon.Style> + </Polygon> + <Polyline Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" StrokeThickness="1" Stretch="Fill" Points="0,30 15,0 85,0 100,30" /> + <Rectangle VerticalAlignment="Bottom" Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" StrokeThickness="1" /> + </Grid> + </Viewbox> + <ContentPresenter Content="{Binding Tag}" TextElement.Foreground="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center" /> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="IsSelected" Value="True"> + + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + <Style.Triggers> + <Trigger Property="IsSelected" Value="True"> + <Setter Property="Background" Value="{StaticResource FSE_PrimaryAccentDarkBrush}"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Setter Property="FontWeight" Value="SemiBold"></Setter> + <Setter Property="Panel.ZIndex" Value="200"></Setter> + </Trigger> + <Trigger Property="IsSelected" Value="False"> + <Setter Property="Panel.ZIndex" Value="-1"></Setter> + </Trigger> + </Style.Triggers> + </Style> + </Setter.Value> + </Setter> + </Style> + </ListBox.Style> + </ListBox> + <Rectangle Grid.Column="2" VerticalAlignment="Bottom" StrokeThickness="2" Stroke="{StaticResource FSE_PrimaryAccentDarkBrush}" /> + </Grid> + + <Border Margin="0 -2 0 0" Padding="10"> + <controls:NavigationControl x:Name="navigation" SelectedObject="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=SelectedObject,Mode=TwoWay}" TransitionAlwaysFades="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=TransitionAlwaysFades}" TransitionType="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=TransitionType}" TransitionDuration="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=TransitionDuration}"/> + </Border> + </DockPanel> + + </Border> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + +</ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.cs new file mode 100644 index 000000000..dc1da7384 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.cs @@ -0,0 +1,26 @@ +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; +using Tango.FileSystem; + +namespace Tango.FSE.Common.Controls +{ + public class FileSystemControl : FileExplorerControl + { + static FileSystemControl() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(FileSystemControl), new FrameworkPropertyMetadata(typeof(FileSystemControl))); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml new file mode 100644 index 000000000..ec490e893 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml @@ -0,0 +1,212 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:local="clr-namespace:Tango.FileSystem;assembly=Tango.FileSystem" + xmlns:l="clr-namespace:Tango.FSE.Common.Controls"> + + <converters:ByteArrayToFileSizeConverter x:Key="ByteArrayToFileSizeConverter" /> + <converters:DateTimeUtcToLocalDateTime x:Key="DateTimeUtcToLocalDateTime" /> + + <Style x:Key="FileSystemCellStyle" TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"> + <Setter Property="BorderThickness" Value="0"/> + <Setter Property="FocusVisualStyle" Value="{x:Null}"/> + <Setter Property="VerticalContentAlignment" Value="Center"></Setter> + </Style> + + <Style TargetType="{x:Type l:FileSystemControl}"> + <Setter Property="DriveIcon" Value="pack://application:,,,/Tango.FileSystem;component/Images/drive.png"></Setter> + <Setter Property="FolderIcon" Value="pack://application:,,,/Tango.FileSystem;component/Images/folder.png"></Setter> + <Setter Property="Mode" Value="Details"></Setter> + <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter> + <Setter Property="Focusable" Value="True"></Setter> + <Setter Property="AllowDrop" Value="True"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type l:FileSystemControl}"> + <Border Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}"> + + <Grid Background="Transparent"> + <ListBox x:Name="PART_listbox" Background="Transparent" SelectionMode="Extended" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CurrentItem.Items}" SelectedItem="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=SelectedItem,Mode=TwoWay}"> + <ListBox.Style> + <Style TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}"> + <Setter Property="Visibility" Value="Collapsed"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Mode}" Value="Large"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </ListBox.Style> + <ListBox.ItemContainerStyle> + <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}"> + <Setter Property="Padding" Value="5"></Setter> + <Setter Property="Margin" Value="0 10 20 10"></Setter> + </Style> + </ListBox.ItemContainerStyle> + <ListBox.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Horizontal" IsItemsHost="True" /> + </ItemsPanelTemplate> + </ListBox.ItemsPanel> + <ListBox.ItemTemplate> + <DataTemplate> + <DockPanel Width="70" Height="115" Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <Image DockPanel.Dock="Top" RenderOptions.BitmapScalingMode="Fant" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Top"> + <Image.Style> + <Style TargetType="Image"> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="Folder"> + <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=FolderIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="Drive"> + <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=DriveIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="File"> + <Setter Property="Source" Value="{Binding Icon}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Image.Style> + </Image> + <TextBlock Text="{Binding Name}" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" HorizontalAlignment="Center" TextAlignment="Center" Margin="0 10 0 0"></TextBlock> + </DockPanel> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + + <Grid> + <Grid.Style> + <Style TargetType="Grid"> + <Setter Property="Visibility" Value="Collapsed"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Mode}" Value="Details"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Grid.Style> + <DataGrid x:Name="PART_datagrid" ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CurrentItem.Items}" CellStyle="{StaticResource FileSystemCellStyle}"> + <DataGrid.Style> + <Style TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}"> + <Setter Property="Background" Value="Transparent"></Setter> + <Setter Property="AutoGenerateColumns" Value="False"></Setter> + <Setter Property="CanUserAddRows" Value="False"></Setter> + <Setter Property="CanUserDeleteRows" Value="False"></Setter> + <Setter Property="CanUserReorderColumns" Value="False"></Setter> + <Setter Property="CanUserResizeColumns" Value="True"></Setter> + <Setter Property="CanUserResizeRows" Value="False"></Setter> + <Setter Property="CanUserSortColumns" Value="True"></Setter> + <Setter Property="IsReadOnly" Value="True"></Setter> + <Setter Property="SelectionMode" Value="Extended"></Setter> + <Setter Property="SelectionUnit" Value="FullRow"></Setter> + <Setter Property="RowHeight" Value="30"></Setter> + <Setter Property="HorizontalGridLinesBrush" Value="Transparent"></Setter> + <Setter Property="VerticalGridLinesBrush" Value="Transparent"></Setter> + <Setter Property="HorizontalScrollBarVisibility" Value="Disabled"></Setter> + <Setter Property="CellStyle" Value="{StaticResource FileSystemCellStyle}" /> + </Style> + </DataGrid.Style> + + <DataGrid.Columns> + <DataGridTemplateColumn Header="NAME" Width="300*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <DockPanel Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <Image Width="18" Height="18" RenderOptions.BitmapScalingMode="Fant" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center"> + <Image.Style> + <Style TargetType="Image"> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="Drive"> + <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=DriveIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="File"> + <Setter Property="Source" Value="{Binding SmallIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="Folder"> + <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=FolderIcon}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Image.Style> + </Image> + <TextBlock Text="{Binding Name}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Margin="5 0 0 0"></TextBlock> + </DockPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="DATE MODIFIED" Width="170*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <DockPanel Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <TextBlock Text="{Binding DateModified,Converter={StaticResource DateTimeUtcToLocalDateTime}}" VerticalAlignment="Center"></TextBlock> + </DockPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="TYPE" Width="140*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <DockPanel Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <TextBlock Text="{Binding Description}" VerticalAlignment="Center"></TextBlock> + </DockPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="SIZE" Width="100*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <DockPanel Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <TextBlock Text="{Binding Size,Converter={StaticResource ByteArrayToFileSizeConverter}}" VerticalAlignment="Center"> + <TextBlock.Style> + <Style TargetType="TextBlock"> + <Setter Property="Visibility" Value="Hidden"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="File"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBlock.Style> + </TextBlock> + </DockPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + </Grid> + </Grid> + </Border> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + +</ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/TextIconButton.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/TextIconButton.cs new file mode 100644 index 000000000..31bcee5cd --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/TextIconButton.cs @@ -0,0 +1,34 @@ +using MaterialDesignThemes.Wpf; +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.Common.Controls +{ + public class TextIconButton : Button + { + static TextIconButton() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(TextIconButton), new FrameworkPropertyMetadata(typeof(TextIconButton))); + } + + public PackIconKind Icon + { + get { return (PackIconKind)GetValue(IconProperty); } + set { SetValue(IconProperty, value); } + } + public static readonly DependencyProperty IconProperty = + DependencyProperty.Register("Icon", typeof(PackIconKind), typeof(TextIconButton), new PropertyMetadata(PackIconKind.BorderNone)); + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/TextIconButton.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/TextIconButton.xaml new file mode 100644 index 000000000..eb8d823f7 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/TextIconButton.xaml @@ -0,0 +1,32 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:local="clr-namespace:Tango.FSE.Common.Controls"> + + <Style TargetType="{x:Type local:TextIconButton}" BasedOn="{StaticResource {x:Type Button}}"> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <DockPanel> + <material:PackIcon Margin="-5 0 0 0" Width="Auto" Height="Auto" Kind="{Binding RelativeSource={RelativeSource AncestorType=local:TextIconButton},Path=Icon}" VerticalAlignment="Center" /> + <Label VerticalAlignment="Center" Content="{Binding}"></Label> + </DockPanel> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="FSE_TextIconButton_Dark" TargetType="{x:Type local:TextIconButton}" BasedOn="{StaticResource FSE_RaisedButton_Dark_Hover}"> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <DockPanel> + <material:PackIcon Margin="-5 0 0 0" Width="Auto" Height="Auto" Kind="{Binding RelativeSource={RelativeSource AncestorType=local:TextIconButton},Path=Icon}" VerticalAlignment="Center" /> + <Label VerticalAlignment="Center" Content="{Binding}"></Label> + </DockPanel> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + +</ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/ToggleIconButton.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/ToggleIconButton.cs new file mode 100644 index 000000000..a8d3f7f1a --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/ToggleIconButton.cs @@ -0,0 +1,84 @@ +using MaterialDesignThemes.Wpf; +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.Controls.Primitives; +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.Common.Controls +{ + public class ToggleIconButton : ToggleButton + { + public PackIconKind CheckedIcon + { + get { return (PackIconKind)GetValue(CheckedIconProperty); } + set { SetValue(CheckedIconProperty, value); } + } + public static readonly DependencyProperty CheckedIconProperty = + DependencyProperty.Register("CheckedIcon", typeof(PackIconKind), typeof(ToggleIconButton), new PropertyMetadata(PackIconKind.Circle)); + + public PackIconKind UncheckedIcon + { + get { return (PackIconKind)GetValue(UncheckedIconProperty); } + set { SetValue(UncheckedIconProperty, value); } + } + public static readonly DependencyProperty UncheckedIconProperty = + DependencyProperty.Register("UncheckedIcon", typeof(PackIconKind), typeof(ToggleIconButton), new PropertyMetadata(PackIconKind.CircleOutline)); + + public Brush CheckedForeground + { + get { return (Brush)GetValue(CheckedForegroundProperty); } + set { SetValue(CheckedForegroundProperty, value); } + } + public static readonly DependencyProperty CheckedForegroundProperty = + DependencyProperty.Register("CheckedForeground", typeof(Brush), typeof(ToggleIconButton), new PropertyMetadata(null)); + + public Brush UncheckedForeground + { + get { return (Brush)GetValue(UncheckedForegroundProperty); } + set { SetValue(UncheckedForegroundProperty, value); } + } + public static readonly DependencyProperty UncheckedForegroundProperty = + DependencyProperty.Register("UncheckedForeground", typeof(Brush), typeof(ToggleIconButton), new PropertyMetadata(null)); + + public String CheckedText + { + get { return (String)GetValue(CheckedTextProperty); } + set { SetValue(CheckedTextProperty, value); } + } + public static readonly DependencyProperty CheckedTextProperty = + DependencyProperty.Register("CheckedText", typeof(String), typeof(ToggleIconButton), new PropertyMetadata(null)); + + public String UncheckedText + { + get { return (String)GetValue(UncheckedTextProperty); } + set { SetValue(UncheckedTextProperty, value); } + } + public static readonly DependencyProperty UncheckedTextProperty = + DependencyProperty.Register("UncheckedText", typeof(String), typeof(ToggleIconButton), new PropertyMetadata(null)); + + + public TextAlignment TextAlignment + { + get { return (TextAlignment)GetValue(TextAlignmentProperty); } + set { SetValue(TextAlignmentProperty, value); } + } + public static readonly DependencyProperty TextAlignmentProperty = + DependencyProperty.Register("TextAlignment", typeof(TextAlignment), typeof(ToggleIconButton), new PropertyMetadata(TextAlignment.Center)); + + static ToggleIconButton() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ToggleIconButton), new FrameworkPropertyMetadata(typeof(ToggleIconButton))); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/ToggleIconButton.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/ToggleIconButton.xaml new file mode 100644 index 000000000..5eb3ef368 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/ToggleIconButton.xaml @@ -0,0 +1,113 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:local="clr-namespace:Tango.FSE.Common.Controls"> + + + <Style TargetType="{x:Type local:ToggleIconButton}"> + <Setter Property="CheckedForeground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Setter Property="UncheckedForeground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type local:ToggleIconButton}"> + <Grid Background="Transparent"> + <StackPanel Orientation="Horizontal"> + <TextBlock Margin="0 0 5 0" VerticalAlignment="Center"> + <TextBlock.Style> + <Style TargetType="TextBlock"> + <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=UncheckedText}"></Setter> + <Setter Property="Visibility" Value="Collapsed"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=TextAlignment}" Value="Left"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=IsChecked}" Value="True"> + <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CheckedText}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBlock.Style> + </TextBlock> + <material:PackIcon IsHitTestVisible="False" RenderTransformOrigin="0.5, 0.5" Width="Auto" Height="Auto"> + <material:PackIcon.Style> + <Style TargetType="material:PackIcon"> + <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=UncheckedForeground}"></Setter> + <Setter Property="Kind" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=UncheckedIcon}"></Setter> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="1" ScaleY="1" /> + </Setter.Value> + </Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=IsChecked}" Value="True"> + <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CheckedForeground}"></Setter> + <Setter Property="Kind" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CheckedIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=local:ToggleIconButton},Path=IsMouseOver}" Value="True"> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="1.2" ScaleY="1.2" /> + </Setter.Value> + </Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </material:PackIcon.Style> + </material:PackIcon> + + <TextBlock Margin="5 0 0 0" VerticalAlignment="Center"> + <TextBlock.Style> + <Style TargetType="TextBlock"> + <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=UncheckedText}"></Setter> + <Setter Property="Visibility" Value="Collapsed"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=TextAlignment}" Value="Right"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=IsChecked}" Value="True"> + <Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CheckedText}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBlock.Style> + </TextBlock> + </StackPanel> + <Canvas IsHitTestVisible="False"> + <Grid Width="{Binding RelativeSource={RelativeSource AncestorType=Canvas},Path=ActualWidth}" Height="{Binding RelativeSource={RelativeSource AncestorType=Canvas},Path=ActualWidth}"> + <Ellipse x:Name="ellipse" Fill="White" RenderTransformOrigin="0.5,0.5"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Setter Property="Opacity" Value="0.2"></Setter> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="0" ScaleY="0" /> + </Setter.Value> + </Setter> + <Setter Property="Visibility" Value="Hidden"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=local:ToggleIconButton},Path=IsMouseOver}" Value="True"> + <Setter Property="Visibility" Value="Visible"></Setter> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" From="0" To="4" Duration="00:00:0.5" DecelerationRatio="0.8" /> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="0" To="4" Duration="00:00:0.5" DecelerationRatio="0.8" /> + <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0.2" To="0.001" Duration="00:00:0.5" DecelerationRatio="0.8" /> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> + </Grid> + </Canvas> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + +</ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs index 91aeb3d64..997eca676 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs @@ -19,9 +19,13 @@ using Tango.FSE.Common.Connection; using Tango.FSE.Common.Diagnostics; using Tango.FSE.Common.FSEApplication; using Tango.FSE.Common.Gateway; +using Tango.FSE.Common.Logging; using Tango.FSE.Common.Navigation; using Tango.FSE.Common.Notifications; +using Tango.FSE.Common.Performance; using Tango.FSE.Common.RemoteDesktop; +using Tango.FSE.Common.Resolution; +using Tango.FSE.Common.SystemInfo; using Tango.Settings; using Tango.SharedUI; using static Tango.SharedUI.Controls.NavigationControl; @@ -91,6 +95,30 @@ namespace Tango.FSE.Common public IRemoteDesktopProvider RemoteDesktopProvider { get; set; } /// <summary> + /// Gets or sets the performance provider. + /// </summary> + [TangoInject] + public IPerformanceProvider PerformanceProvider { get; set; } + + /// <summary> + /// Gets or sets the system information provider. + /// </summary> + [TangoInject] + public ISystemInfoProvider SystemInfoProvider { get; set; } + + /// <summary> + /// Gets or sets the logging provider. + /// </summary> + [TangoInject] + public ILoggingProvider LoggingProvider { get; set; } + + /// <summary> + /// Gets or sets the resolution service. + /// </summary> + [TangoInject] + public IResolutionService ResolutionService { get; set; } + + /// <summary> /// Gets or sets the FSE service. /// </summary> [TangoInject] diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Fonts/Caveat-Bold.ttf b/Software/Visual_Studio/FSE/Tango.FSE.Common/Fonts/Caveat-Bold.ttf Binary files differnew file mode 100644 index 000000000..e7e6a8377 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Fonts/Caveat-Bold.ttf diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Fonts/Caveat-Regular.ttf b/Software/Visual_Studio/FSE/Tango.FSE.Common/Fonts/Caveat-Regular.ttf Binary files differnew file mode 100644 index 000000000..278a61c8f --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Fonts/Caveat-Regular.ttf diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/GraphHelper.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/GraphHelper.cs new file mode 100644 index 000000000..7227f5f0d --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/GraphHelper.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media; + +namespace Tango.FSE.Common.Graphs +{ + public static class GraphHelper + { + public enum GraphColor + { + White, + Red, + Yellow, + Green, + Orange + } + + public static Color GetGraphColor(GraphColor graphColor) + { + return (Color)Application.Current.Resources[$"FSE_RealTimeGraph_{graphColor.ToString()}"]; + } + + public static Brush GetGraphBrush(GraphColor graphColor) + { + return new SolidColorBrush(GetGraphColor(graphColor)); + } + + public static Color GetGraphStrokeColor() + { + return (Color)Application.Current.Resources["FSE_RealTimeGraph_ForegroundColor"]; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/RealTimeGraph.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/RealTimeGraph.cs new file mode 100644 index 000000000..5a2dd3eed --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/RealTimeGraph.cs @@ -0,0 +1,101 @@ +using RealTimeGraphX; +using System; +using System.Windows; +using System.Windows.Controls; + +namespace Tango.FSE.Common.Graphs +{ + public class RealTimeGraph : Control + { + /// <summary> + /// Gets or sets the graph controller. + /// </summary> + public IGraphController Controller + { + get { return (IGraphController)GetValue(ControllerProperty); } + set { SetValue(ControllerProperty, value); } + } + public static readonly DependencyProperty ControllerProperty = + DependencyProperty.Register("Controller", typeof(IGraphController), typeof(RealTimeGraph), new PropertyMetadata(null)); + + + /// <summary> + /// Gets or sets the string format of the y-axis. + /// </summary> + public String StringFormat + { + get { return (String)GetValue(StringFormatProperty); } + set { SetValue(StringFormatProperty, value); } + } + public static readonly DependencyProperty StringFormatProperty = + DependencyProperty.Register("StringFormat", typeof(String), typeof(RealTimeGraph), new PropertyMetadata("0.0")); + + + /// <summary> + /// Gets or sets the display name. + /// </summary> + public String DisplayName + { + get { return (String)GetValue(DisplayNameProperty); } + set { SetValue(DisplayNameProperty, value); } + } + public static readonly DependencyProperty DisplayNameProperty = + DependencyProperty.Register("DisplayName", typeof(String), typeof(RealTimeGraph), new PropertyMetadata(null)); + + + /// <summary> + /// Gets or sets the display units. + /// </summary> + public String DisplayUnits + { + get { return (String)GetValue(DisplayUnitsProperty); } + set { SetValue(DisplayUnitsProperty, value); } + } + public static readonly DependencyProperty DisplayUnitsProperty = + DependencyProperty.Register("DisplayUnits", typeof(String), typeof(RealTimeGraph), new PropertyMetadata(null)); + + /// <summary> + /// Gets or sets the graph label visibility. + /// </summary> + public Visibility GraphLabelVisibility + { + get { return (Visibility)GetValue(GraphLabelVisibilityProperty); } + set { SetValue(GraphLabelVisibilityProperty, value); } + } + public static readonly DependencyProperty GraphLabelVisibilityProperty = + DependencyProperty.Register("GraphLabelVisibility", typeof(Visibility), typeof(RealTimeGraph), new PropertyMetadata(Visibility.Visible)); + + + /// <summary> + /// Gets or sets the vertical ticks. + /// </summary> + public int VerticalTicks + { + get { return (int)GetValue(VerticalTicksProperty); } + set { SetValue(VerticalTicksProperty, value); } + } + public static readonly DependencyProperty VerticalTicksProperty = + DependencyProperty.Register("VerticalTicks", typeof(int), typeof(RealTimeGraph), new PropertyMetadata(10)); + + + /// <summary> + /// Gets or sets the horizontal ticks. + /// </summary> + public int HorizontalTicks + { + get { return (int)GetValue(HorizontalTicksProperty); } + set { SetValue(HorizontalTicksProperty, value); } + } + public static readonly DependencyProperty HorizontalTicksProperty = + DependencyProperty.Register("HorizontalTicks", typeof(int), typeof(RealTimeGraph), new PropertyMetadata(10)); + + + /// <summary> + /// Initializes the <see cref="RealTimeGraph"/> class. + /// </summary> + static RealTimeGraph() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(RealTimeGraph), new FrameworkPropertyMetadata(typeof(RealTimeGraph))); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/RealTimeGraph.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/RealTimeGraph.xaml new file mode 100644 index 000000000..64f7e300e --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Graphs/RealTimeGraph.xaml @@ -0,0 +1,62 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:realTimeGraphX="clr-namespace:RealTimeGraphX.WPF;assembly=RealTimeGraphX.WPF" + xmlns:local="clr-namespace:Tango.FSE.Common.Graphs"> + + + <Style TargetType="{x:Type local:RealTimeGraph}"> + <Setter Property="BorderThickness" Value="1"></Setter> + <Setter Property="BorderBrush" Value="{StaticResource FSE_RealTimeGraph_OuterBorderBrush}"></Setter> + <Setter Property="Padding" Value="20 20 30 20"></Setter> + <Setter Property="FontSize" Value="11"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_RealTimeGraph_ForegroundBrush}"></Setter> + <Setter Property="Background" Value="{StaticResource FSE_RealTimeGraph_BackgroundBrush}"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type local:RealTimeGraph}"> + <Grid> + <Border Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}" + CornerRadius="5" + Padding="{TemplateBinding Padding}"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="1*"/> + <RowDefinition Height="35"/> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="70"/> + <ColumnDefinition Width="1*"/> + </Grid.ColumnDefinitions> + + <Grid Grid.Column="1"> + <realTimeGraphX:WpfGraphGridLines Controller="{TemplateBinding Controller}" Foreground="{StaticResource FSE_RealTimeGraph_GridLinesBrush}" /> + <realTimeGraphX:WpfGraphSurface x:Name="surface" Controller="{TemplateBinding Controller}" BorderThickness="1 0 0 1" BorderBrush="{StaticResource FSE_RealTimeGraph_InnerBorderBrush}" /> + + <!--<Grid IsHitTestVisible="False" Visibility="{TemplateBinding GraphLabelVisibility}"> + <Label Style="{StaticResource graphLabel}"> + <StackPanel Orientation="Horizontal"> + <TextBlock Foreground="Gainsboro" FontSize="11" VerticalAlignment="Center" Text="{TemplateBinding DisplayName}"></TextBlock> + <TextBlock Foreground="Gray" Margin="10 0 0 0" FontSize="11" FontFamily="Sylfaen Regular" VerticalAlignment="Center" Text="{TemplateBinding DisplayUnits}"></TextBlock> + </StackPanel> + </Label> + </Grid>--> + </Grid> + + <realTimeGraphX:WpfGraphAxisControl Orientation="Vertical" Controller="{TemplateBinding Controller}" StringFormat="{TemplateBinding StringFormat}" Ticks="{TemplateBinding VerticalTicks}" /> + <realTimeGraphX:WpfGraphAxisControl Orientation="Horizontal" Controller="{TemplateBinding Controller}" Grid.Column="1" Grid.Row="1" Ticks="{TemplateBinding HorizontalTicks}" StringFormat="hh\:mm\:ss"/> + </Grid> + </Border> + <Image HorizontalAlignment="Left" VerticalAlignment="Top" Margin="8" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="10" Height="10" /> + <Image HorizontalAlignment="Right" VerticalAlignment="Top" Margin="8" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="10" Height="10" /> + + <Image HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="8" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="10" Height="10" /> + <Image HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="8" Source="{StaticResource FSE_Screw}" RenderOptions.BitmapScalingMode="Fant" Width="10" Height="10" /> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + +</ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Images/screw.png b/Software/Visual_Studio/FSE/Tango.FSE.Common/Images/screw.png Binary files differnew file mode 100644 index 000000000..46a8134fe --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Images/screw.png diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Logging/ILoggingProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Logging/ILoggingProvider.cs new file mode 100644 index 000000000..917720233 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Logging/ILoggingProvider.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Integration.Logging; +using Tango.Logging; + +namespace Tango.FSE.Common.Logging +{ + public interface ILoggingProvider + { + event EventHandler<LogItemBase> ApplicationLogAvailable; + event EventHandler<EmbeddedLogItem> EmbeddedLogAvailable; + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Performance/IPerformanceProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Performance/IPerformanceProvider.cs new file mode 100644 index 000000000..c9c4f3a9d --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Performance/IPerformanceProvider.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.Performance +{ + public interface IPerformanceProvider + { + event EventHandler<PerformancePackageEventArgs> PerformancePackageAvailable; + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Performance/PerformancePackageEventArgs.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Performance/PerformancePackageEventArgs.cs new file mode 100644 index 000000000..669890a29 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Performance/PerformancePackageEventArgs.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Integration.ExternalBridge.Network.Performance; + +namespace Tango.FSE.Common.Performance +{ + public class PerformancePackageEventArgs : EventArgs + { + public PerformancePackage Package { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/IResolutionService.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/IResolutionService.cs new file mode 100644 index 000000000..9b9f04bbc --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/IResolutionService.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace Tango.FSE.Common.Resolution +{ + public interface IResolutionService + { + event EventHandler<ResolutionMode> ResolutionModeChanged; + event EventHandler<SizeChangedEventArgs> ResolutionChanged; + ResolutionMode Resolution { get; } + bool IsLowResolution { get; } + bool IsHighResolution { get; } + double ResolutionWidth { get; } + double ResolutionHeight { get; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/ResolutionHelper.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/ResolutionHelper.cs new file mode 100644 index 000000000..6caee944a --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/ResolutionHelper.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using Tango.Core.DI; + +namespace Tango.FSE.Common.Resolution +{ + public static class ResolutionHelper + { + private static List<FrameworkElement> _elements; + private static IResolutionService _resolutionService; + + static ResolutionHelper() + { + _elements = new List<FrameworkElement>(); + var resolutionService = TangoIOC.Default.GetInstance<IResolutionService>(); + _resolutionService = resolutionService; + + if (resolutionService != null) + { + resolutionService.ResolutionModeChanged += ResolutionService_ResolutionModeChanged; + resolutionService.ResolutionChanged += ResolutionService_ResolutionChanged; + } + } + + private static void ResolutionService_ResolutionChanged(object sender, SizeChangedEventArgs e) + { + foreach (var element in _elements) + { + ApplyElementSetting(element); + } + } + + private static void ResolutionService_ResolutionModeChanged(object sender, ResolutionMode mode) + { + foreach (var element in _elements) + { + ApplyElementSetting(element); + } + } + + private static void ApplyElementSetting(FrameworkElement element) + { + if (_resolutionService != null) + { + var mode = GetMode(element); + if (mode != ResolutionMode.None) + { + if (mode == _resolutionService.Resolution) + { + element.Visibility = Visibility.Visible; + } + else + { + element.Visibility = Visibility.Collapsed; + } + } + + var width = GetMinWidth(element); + + if (!Double.IsNaN(width)) + { + if (_resolutionService.ResolutionWidth >= width) + { + element.Visibility = Visibility.Visible; + } + else + { + element.Visibility = Visibility.Collapsed; + } + } + + var height = GetMinHeight(element); + + if (!Double.IsNaN(height)) + { + if (_resolutionService.ResolutionHeight >= height) + { + element.Visibility = Visibility.Visible; + } + else + { + element.Visibility = Visibility.Collapsed; + } + } + + if (!Double.IsNaN(width) && !Double.IsNaN(height)) + { + if (_resolutionService.ResolutionWidth >= width && _resolutionService.ResolutionHeight >= height) + { + element.Visibility = Visibility.Visible; + } + else + { + element.Visibility = Visibility.Collapsed; + } + } + } + } + + #region Mode + + /// <summary> + /// Determined the resolution mode for the trigger. + /// </summary> + public static readonly DependencyProperty ModeProperty = + DependencyProperty.RegisterAttached("Mode", + typeof(ResolutionMode), typeof(ResolutionHelper), + new FrameworkPropertyMetadata(ResolutionMode.None, OnModeChanged)); + + private static void OnModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (!_elements.Contains(d as FrameworkElement)) + { + _elements.Add(d as FrameworkElement); + ApplyElementSetting(d as FrameworkElement); + } + } + + /// <summary> + /// Sets the Mode attached property. + /// </summary> + /// <param name="element">The element.</param> + /// <param name="value">if set to <c>true</c> [value].</param> + public static void SetMode(FrameworkElement element, ResolutionMode value) + { + element.SetValue(ModeProperty, value); + } + + /// <summary> + /// Gets the Mode attached property. + /// </summary> + /// <param name="element">The element.</param> + /// <returns></returns> + public static ResolutionMode GetMode(FrameworkElement element) + { + return (ResolutionMode)element.GetValue(ModeProperty); + } + + #endregion + + #region MinWidth + + /// <summary> + /// Determined the resolution MinWidth for the trigger. + /// </summary> + public static readonly DependencyProperty MinWidthProperty = + DependencyProperty.RegisterAttached("MinWidth", + typeof(double), typeof(ResolutionHelper), + new FrameworkPropertyMetadata(double.NaN, OnMinWidthChanged)); + + private static void OnMinWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (!_elements.Contains(d as FrameworkElement)) + { + _elements.Add(d as FrameworkElement); + ApplyElementSetting(d as FrameworkElement); + } + } + + /// <summary> + /// Sets the MinWidth attached property. + /// </summary> + /// <param name="element">The element.</param> + /// <param name="value">if set to <c>true</c> [value].</param> + public static void SetMinWidth(FrameworkElement element, double value) + { + element.SetValue(MinWidthProperty, value); + } + + /// <summary> + /// Gets the MinWidth attached property. + /// </summary> + /// <param name="element">The element.</param> + /// <returns></returns> + public static double GetMinWidth(FrameworkElement element) + { + return (double)element.GetValue(MinWidthProperty); + } + + #endregion + + #region MinHeight + + /// <summary> + /// Determined the resolution MinHeight for the trigger. + /// </summary> + public static readonly DependencyProperty MinHeightProperty = + DependencyProperty.RegisterAttached("MinHeight", + typeof(double), typeof(ResolutionHelper), + new FrameworkPropertyMetadata(double.NaN, OnMinHeightChanged)); + + private static void OnMinHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (!_elements.Contains(d as FrameworkElement)) + { + _elements.Add(d as FrameworkElement); + ApplyElementSetting(d as FrameworkElement); + } + } + + /// <summary> + /// Sets the MinHeight attached property. + /// </summary> + /// <param name="element">The element.</param> + /// <param name="value">if set to <c>true</c> [value].</param> + public static void SetMinHeight(FrameworkElement element, double value) + { + element.SetValue(MinHeightProperty, value); + } + + /// <summary> + /// Gets the MinHeight attached property. + /// </summary> + /// <param name="element">The element.</param> + /// <returns></returns> + public static double GetMinHeight(FrameworkElement element) + { + return (double)element.GetValue(MinHeightProperty); + } + + #endregion + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/ResolutionMode.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/ResolutionMode.cs new file mode 100644 index 000000000..b770bbc71 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resolution/ResolutionMode.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.Resolution +{ + public enum ResolutionMode + { + None, + High, + Low + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Colors.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Colors.xaml index b21cd9ac6..1a355ebf0 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Colors.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Colors.xaml @@ -12,7 +12,8 @@ <Color x:Key="FSE_SemiTransparentColor">#76000000</Color> <Color x:Key="FSE_BorderColor">#707070</Color> <Color x:Key="FSE_PrimaryAccentColor">#03A9F4</Color> - + <Color x:Key="FSE_PrimaryAccentDarkColor">#009FE7</Color> + <Color x:Key="FSE_ErrorColor">#FF4C4C</Color> <Color x:Key="FSE_WarningColor">#FF914C</Color> <Color x:Key="FSE_SuccessColor">#6DFF72</Color> @@ -26,6 +27,21 @@ <Color x:Key="FSE_RedColor">#FF6F6F</Color> <Color x:Key="FSE_GreenColor">#8EFF6F</Color> <Color x:Key="FSE_OrangeColor">#FA9252</Color> + <Color x:Key="FSE_YellowColor">#FFB84B</Color> + + <Color x:Key="FSE_RealTimeGraph_White">#18FFFFFF</Color> + <Color x:Key="FSE_RealTimeGraph_Red">#B6FF6F6F</Color> + <Color x:Key="FSE_RealTimeGraph_Yellow">#BBFFB84B</Color> + <Color x:Key="FSE_RealTimeGraph_Green">#B958C13B</Color> + <Color x:Key="FSE_RealTimeGraph_Orange">#BBFA9252</Color> + + <Color x:Key="FSE_RealTimeGraph_ForegroundColor">#7C98B3</Color> + <Color x:Key="FSE_RealTimeGraph_OuterBorderColor">#202020</Color> + <Color x:Key="FSE_RealTimeGraph_InnerBorderColor">#505050</Color> + <Color x:Key="FSE_RealTimeGraph_GridLinesColor">#303030</Color> + + <Color x:Key="FSE_Panel_BorderColor">#202020</Color> + <Color x:Key="FSE_Panel_BackgroundColor">#252525</Color> <!--BRUSHES--> <SolidColorBrush x:Key="FSE_PrimaryBackgroundDarkBrush" Color="{StaticResource FSE_PrimaryBackgroundDarkColor}"></SolidColorBrush> @@ -37,7 +53,8 @@ <SolidColorBrush x:Key="FSE_BorderBrush" Color="{StaticResource FSE_BorderColor}"></SolidColorBrush> <SolidColorBrush x:Key="FSE_GrayBrush" Color="{StaticResource FSE_GrayColor}"></SolidColorBrush> <SolidColorBrush x:Key="FSE_PrimaryAccentBrush" Color="{StaticResource FSE_PrimaryAccentColor}"></SolidColorBrush> - + <SolidColorBrush x:Key="FSE_PrimaryAccentDarkBrush" Color="{StaticResource FSE_PrimaryAccentDarkColor}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_ErrorBrush" Color="{StaticResource FSE_ErrorColor}"></SolidColorBrush> <SolidColorBrush x:Key="FSE_WarningBrush" Color="{StaticResource FSE_WarningColor}"></SolidColorBrush> <SolidColorBrush x:Key="FSE_SuccessBrush" Color="{StaticResource FSE_SuccessColor}"></SolidColorBrush> @@ -52,7 +69,27 @@ <SolidColorBrush x:Key="FSE_RedBrush" Color="{StaticResource FSE_RedColor}"></SolidColorBrush> <SolidColorBrush x:Key="FSE_GreenBrush" Color="{StaticResource FSE_GreenColor}"></SolidColorBrush> <SolidColorBrush x:Key="FSE_OrangeBrush" Color="{StaticResource FSE_OrangeColor}"></SolidColorBrush> - + <SolidColorBrush x:Key="FSE_YellowBrush" Color="{StaticResource FSE_YellowColor}"></SolidColorBrush> + + <SolidColorBrush x:Key="FSE_RealTimeGraph_ForegroundBrush" Color="{StaticResource FSE_RealTimeGraph_ForegroundColor}" /> + <SolidColorBrush x:Key="FSE_RealTimeGraph_OuterBorderBrush" Color="{StaticResource FSE_RealTimeGraph_OuterBorderColor}" /> + <SolidColorBrush x:Key="FSE_RealTimeGraph_InnerBorderBrush" Color="{StaticResource FSE_RealTimeGraph_InnerBorderColor}" /> + <SolidColorBrush x:Key="FSE_RealTimeGraph_GridLinesBrush" Color="{StaticResource FSE_RealTimeGraph_GridLinesColor}" /> + + <LinearGradientBrush x:Key="FSE_RealTimeGraph_BackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0" > + <GradientStop Color="#202020"/> + <GradientStop Color="#FF333333" Offset="1"/> + </LinearGradientBrush> + + <SolidColorBrush x:Key="FSE_RealTimeGraph_WhiteBrush" Color="{StaticResource FSE_RealTimeGraph_White}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_RealTimeGraph_RedBrush" Color="{StaticResource FSE_RealTimeGraph_Red}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_RealTimeGraph_YellowBrush" Color="{StaticResource FSE_RealTimeGraph_Yellow}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_RealTimeGraph_GreenBrush" Color="{StaticResource FSE_RealTimeGraph_Green}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_RealTimeGraph_OrangeBrush" Color="{StaticResource FSE_RealTimeGraph_Orange}"></SolidColorBrush> + + <SolidColorBrush x:Key="FSE_Panel_BorderBrush" Color="{StaticResource FSE_Panel_BorderColor}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_Panel_BackgroundBrush" Color="{StaticResource FSE_Panel_BackgroundColor}"></SolidColorBrush> + <!--IMAGE BRUSHES--> <ImageBrush x:Key="FSE_AbstractBrush" ImageSource="{StaticResource FSE_Abstract}" Stretch="UniformToFill"></ImageBrush> @@ -67,7 +104,7 @@ <!-- primary --> <!--<SolidColorBrush x:Key="PrimaryHueDarkBrush" Color="#4D1DCF"/> <SolidColorBrush x:Key="PrimaryHueDarkForegroundBrush" Color="#FFFFFF"/>--> - <!--accent--> + <!--accent--> <SolidColorBrush x:Key="SecondaryAccentBrush" Color="{StaticResource FSE_PrimaryAccentColor}"/> <SolidColorBrush x:Key="SecondaryAccentForegroundBrush" Color="{StaticResource FSE_PrimaryForegroundColor}"/> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Controls.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Controls.xaml index b750437c6..420af935c 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Controls.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Controls.xaml @@ -4,6 +4,11 @@ <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Controls/IconButton.xaml" /> + <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Controls/TextIconButton.xaml" /> + <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Controls/FSETabControl.xaml" /> + <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Controls/FSEPanel.xaml" /> + <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Controls/ToggleIconButton.xaml" /> + <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Controls/FileSystemControl.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary>
\ No newline at end of file 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 ab98ef01c..19bf643c4 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Converters.xaml @@ -32,4 +32,6 @@ <converters:DateTimeUTCToShortDateTimeConverter x:Key="DateTimeUTCToShortDateTimeConverter" /> <converters:TimeSpanToMinutesConverter x:Key="TimeSpanToMinutesConverter" /> <converters:TimeSpanToSecondsConverter x:Key="TimeSpanToSecondsConverter" /> + <converters:StringToTitleCaseConverter x:Key="StringToTitleCaseConverter" /> + <converters:StringToOneLineConverter x:Key="StringToOneLineConverter" /> </ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Fonts.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Fonts.xaml index 6d8c0d272..d7b6e7635 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Fonts.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Fonts.xaml @@ -5,6 +5,7 @@ <FontFamily x:Key="digital-7">../Fonts/#digital-7</FontFamily> <FontFamily x:Key="flexo">../Fonts/#flexo</FontFamily> + <FontFamily x:Key="hand">../Fonts/#Caveat</FontFamily> <sys:Double x:Key="FSE_DefaultFontSize">14</sys:Double> <sys:Double x:Key="FSE_SmallFontSize">12</sys:Double> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Graphs.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Graphs.xaml new file mode 100644 index 000000000..813fb9841 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Graphs.xaml @@ -0,0 +1,9 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="clr-namespace:Tango.FSE.Common.Resources"> + + <ResourceDictionary.MergedDictionaries> + <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Graphs/RealTimeGraph.xaml" /> + </ResourceDictionary.MergedDictionaries> + +</ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Images.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Images.xaml index cad9b5f0d..c0ce6434d 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Images.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Images.xaml @@ -10,5 +10,6 @@ <BitmapImage x:Key="FSE_PPC" UriSource="../Images/tablet.png" /> <BitmapImage x:Key="FSE_PPC_Back" UriSource="../Images/tablet_background.png" /> <BitmapImage x:Key="FSE_Abstract" UriSource="../Images/abstract1.png" /> + <BitmapImage x:Key="FSE_Screw" UriSource="../Images/screw.png" /> </ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml index 997b100e1..5ff141bd7 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml @@ -53,6 +53,74 @@ <Setter Property="BorderBrush" Value="{StaticResource FSE_OrangeBrush}"></Setter> </Style> + <Style x:Key="FSE_Button_Polygon" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}"> + <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter> + <Setter Property="Background" Value="{StaticResource FSE_PrimaryBackgroundLightBrush}"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Setter Property="BorderBrush" Value="{StaticResource FSE_BorderBrush}"></Setter> + <Setter Property="BorderThickness" Value="1"></Setter> + <Setter Property="FontSize" Value="{StaticResource FSE_SmallFontSize}"></Setter> + <Setter Property="Height" Value="30"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Button"> + <ControlTemplate.Triggers> + <Trigger Property="IsMouseOver" Value="True"> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryAccentBrush}"></Setter> + </Trigger> + <Trigger Property="IsPressed" Value="True"> + <Setter Property="Background" Value="{StaticResource FSE_PrimaryAccentBrush}"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Setter Property="BorderBrush" Value="{StaticResource FSE_PrimaryAccentBrush}"></Setter> + </Trigger> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Foreground" Value="{StaticResource FSE_BorderBrush}"></Setter> + </Trigger> + </ControlTemplate.Triggers> + <Grid TextElement.Foreground="{TemplateBinding Foreground}"> + <Viewbox Stretch="Fill"> + <Polygon Points="0,15 15,0 285,0 300,15 285,30 15,30" Fill="{TemplateBinding Background}" Height="30" Stroke="{TemplateBinding BorderBrush}"/> + </Viewbox> + <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" /> + <Canvas IsHitTestVisible="False" HorizontalAlignment="Center"> + <Grid Width="{Binding RelativeSource={RelativeSource AncestorType=Canvas},Path=ActualHeight}" Height="{Binding RelativeSource={RelativeSource AncestorType=Canvas},Path=ActualHeight}"> + <Ellipse x:Name="ellipse" Fill="White" RenderTransformOrigin="0.5,0.5"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Setter Property="Opacity" Value="0.2"></Setter> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="0" ScaleY="0" /> + </Setter.Value> + </Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Button},Path=IsPressed}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" From="0" To="10" Duration="00:00:0.5" DecelerationRatio="0.8" /> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="0" To="10" Duration="00:00:0.5" DecelerationRatio="0.8" /> + <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0.2" To="0.001" Duration="00:00:0.5" DecelerationRatio="0.8" /> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> + </Grid> + </Canvas> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="FSE_CircularProgressBar" TargetType="ProgressBar" BasedOn="{StaticResource MaterialDesignCircularProgressBar}"> + + </Style> + <Style TargetType="editors:AutoCompleteTextBox" > <Setter Property="Focusable" Value="True" /> <Setter Property="BorderThickness" Value="0 0 0 1"/> @@ -357,4 +425,72 @@ </Setter> </Style> + <DataTemplate x:Key="FSE_LogIcon_Cell"> + <material:PackIcon Height="16" Width="14" Margin="0 0 0 0"> + <material:PackIcon.Style> + <Style TargetType="material:PackIcon"> + <Setter Property="Kind" Value="InfoCircleOutline"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Category}" Value="Info"> + <Setter Property="Kind" Value="InfoCircleOutline"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Warning"> + <Setter Property="Kind" Value="Alert"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_WarningBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Error"> + <Setter Property="Kind" Value="Alert"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_ErrorBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Critical"> + <Setter Property="Kind" Value="Bell"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_ErrorBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Category}" Value="Debug"> + <Setter Property="Kind" Value="Bug"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_GrayBrush}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding CallerMethodName}" Value="OnStartup"> + <Setter Property="Kind" Value="ClockOutline"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryAccentBrush}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </material:PackIcon.Style> + </material:PackIcon> + </DataTemplate> + + + <Style x:Key="FSE_Rounded_Corners_TextBox" TargetType="TextBox"> + <Setter Property="Background" Value="{StaticResource FSE_PrimaryBackgroundDarkBrush}"></Setter> + <Setter Property="BorderBrush" Value="{StaticResource FSE_BorderBrush}"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter> + <Setter Property="VerticalContentAlignment" Value="Center"></Setter> + <Setter Property="Padding" Value="3"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type TextBoxBase}"> + <Border Background="{TemplateBinding Background}" x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5"> + <material:Ripple Feedback="{StaticResource FSE_PrimaryForegroundBrush}"> + <ScrollViewer x:Name="PART_ContentHost"/> + </material:Ripple> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" TargetName="Bd"/> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> + </Trigger> + <Trigger Property="Width" Value="Auto"> + <Setter Property="MinWidth" Value="100"/> + </Trigger> + <Trigger Property="Height" Value="Auto"> + <Setter Property="MinHeight" Value="20"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + </ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/SystemInfo/ISystemInfoProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/SystemInfo/ISystemInfoProvider.cs new file mode 100644 index 000000000..d21224c4d --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/SystemInfo/ISystemInfoProvider.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Integration.ExternalBridge.Network.Information; + +namespace Tango.FSE.Common.SystemInfo +{ + public interface ISystemInfoProvider + { + Task<InformationPackage> GetSystemInformationPackage(); + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj index cb27cce2d..f61b59da3 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj @@ -87,10 +87,16 @@ <Compile Include="Connection\IMachineProvider.cs" /> <Compile Include="Connection\MachineConnectedEventArgs.cs" /> <Compile Include="Connection\MachineDisconnectedEventArgs.cs" /> + <Compile Include="Console\IConsoleService.cs" /> <Compile Include="Controls\ConnectedMachineIcon.xaml.cs"> <DependentUpon>ConnectedMachineIcon.xaml</DependentUpon> </Compile> + <Compile Include="Controls\FileSystemControl.cs" /> + <Compile Include="Controls\FSEPanel.cs" /> + <Compile Include="Controls\FSETabControl.cs" /> <Compile Include="Controls\IconButton.cs" /> + <Compile Include="Controls\TextIconButton.cs" /> + <Compile Include="Controls\ToggleIconButton.cs" /> <Compile Include="Core\FSEProgress.cs" /> <Compile Include="Diagnostics\DiagnosticsFrame.cs" /> <Compile Include="Diagnostics\DiagnosticsFrameReceivedEventArgs.cs" /> @@ -104,8 +110,11 @@ <Compile Include="FSEModuleAttribute.cs" /> <Compile Include="Gateway\GatewayClient.cs" /> <Compile Include="Gateway\IGatewayService.cs" /> + <Compile Include="Graphs\RealTimeGraph.cs" /> + <Compile Include="Graphs\GraphHelper.cs" /> <Compile Include="Helpers\DesignModeHelper.cs" /> <Compile Include="Helpers\EncryptionHelper.cs" /> + <Compile Include="Logging\ILoggingProvider.cs" /> <Compile Include="Modules\IFSEModuleLoader.cs" /> <Compile Include="Navigation\NavigationMenuItem.cs" /> <Compile Include="Notifications\AppBarItem.cs" /> @@ -118,8 +127,14 @@ <Compile Include="Notifications\SnackbarItem.cs" /> <Compile Include="Notifications\TaskItem.cs" /> <Compile Include="FSEModuleBase.cs" /> + <Compile Include="Performance\IPerformanceProvider.cs" /> + <Compile Include="Performance\PerformancePackageEventArgs.cs" /> <Compile Include="RemoteDesktop\DesktopFrameReceivedEventArgs.cs" /> <Compile Include="RemoteDesktop\IRemoteDesktopProvider.cs" /> + <Compile Include="Resolution\IResolutionService.cs" /> + <Compile Include="Resolution\ResolutionHelper.cs" /> + <Compile Include="Resolution\ResolutionMode.cs" /> + <Compile Include="SystemInfo\ISystemInfoProvider.cs" /> <Compile Include="Threading\IDispatcherProvider.cs" /> <Compile Include="Web\FSEWebClient.cs" /> <Compile Include="Web\FSEWebClientBase.cs" /> @@ -131,10 +146,34 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Controls\FileSystemControl.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Controls\FSEPanel.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Controls\FSETabControl.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Controls\IconButton.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Controls\TextIconButton.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Controls\ToggleIconButton.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Graphs\RealTimeGraph.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Resources\Colors.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -151,6 +190,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Resources\Graphs.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Resources\Images.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -159,6 +202,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Themes\Generic.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> </ItemGroup> <ItemGroup> <Compile Include="FSESettings.cs" /> @@ -207,6 +254,8 @@ <Resource Include="Fonts\Flexo-Regular.otf" /> <Resource Include="Fonts\Flexo-Thin.otf" /> <Resource Include="Fonts\Flexo-ThinIt.otf" /> + <Resource Include="Fonts\Caveat-Bold.ttf" /> + <Resource Include="Fonts\Caveat-Regular.ttf" /> <None Include="packages.config" /> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> @@ -214,6 +263,14 @@ </None> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\..\SideChains\RealTimeGraphX-master\RealTimeGraphX.WPF\RealTimeGraphX.WPF.csproj"> + <Project>{6b9774f7-960d-438e-ad81-c6b9be328d50}</Project> + <Name>RealTimeGraphX.WPF</Name> + </ProjectReference> + <ProjectReference Include="..\..\SideChains\RealTimeGraphX-master\RealTimeGraphX\RealTimeGraphX.csproj"> + <Project>{f13a489c-80ee-4cd0-bdd4-92d959215646}</Project> + <Name>RealTimeGraphX</Name> + </ProjectReference> <ProjectReference Include="..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj"> <Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project> <Name>Tango.AutoComplete</Name> @@ -222,6 +279,10 @@ <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project> <Name>Tango.BL</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.Console\Tango.Console.csproj"> + <Project>{199E8359-CAD3-433D-9EED-2027652B24A4}</Project> + <Name>Tango.Console</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj"> <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> <Name>Tango.Core</Name> @@ -230,10 +291,18 @@ <Project>{63561e19-ff5a-414b-a5ef-e30711543e1d}</Project> <Name>Tango.Emulations</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.FileSystem\Tango.FileSystem.csproj"> + <Project>{c6ebbbbe-2123-44dc-aef7-a0d47d736ac0}</Project> + <Name>Tango.FileSystem</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Integration\Tango.Integration.csproj"> <Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project> <Name>Tango.Integration</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.Logging\Tango.Logging.csproj"> + <Project>{BC932DBD-7CDB-488C-99E4-F02CF441F55E}</Project> + <Name>Tango.Logging</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.PMR\Tango.PMR.csproj"> <Project>{E4927038-348D-4295-AAF4-861C58CB3943}</Project> <Name>Tango.PMR</Name> @@ -285,6 +354,9 @@ <ItemGroup> <Resource Include="Images\abstract1.png" /> </ItemGroup> + <ItemGroup> + <Resource Include="Images\screw.png" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <PropertyGroup> <PreBuildEvent>REM nswag run "$(SolutionDir)Web\Tango.MachineService.Gateway\Nswag\GatewayClient.nswag" /variables:assembly="$(SolutionDir)Web\Tango.MachineService.Gateway\bin\Tango.MachineService.Gateway.dll",output="$(ProjectDir)Gateway\GatewayClient.cs"</PreBuildEvent> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Themes/Generic.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Themes/Generic.xaml new file mode 100644 index 000000000..9b1bd93cf --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Themes/Generic.xaml @@ -0,0 +1,7 @@ +<ResourceDictionary + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="clr-namespace:Tango.FSE.Common"> + + +</ResourceDictionary> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml index de6694069..7b311a10a 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml @@ -57,6 +57,7 @@ <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Fonts.xaml" /> <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Styles.xaml" /> <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Controls.xaml" /> + <ResourceDictionary Source="pack://application:,,,/Tango.FSE.Common;component/Resources/Graphs.xaml" /> </ResourceDictionary.MergedDictionaries> <!-- tell Dragablz tab control to use the Material Design theme --> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs index 5b5cdba88..f4ee8c461 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs @@ -316,6 +316,11 @@ namespace Tango.FSE.UI.Connection MachineOperator.JobRunsLogger.JobSource = Tango.BL.Enumerations.JobSource.Remote; MachineOperator.RequestTimeout = TimeSpan.FromSeconds(5); MachineOperator.ContinuousRequestTimeout = TimeSpan.FromSeconds(5); + + if (MachineOperator is ExternalBridgeTcpClient) + { + (MachineOperator as ExternalBridgeTcpClient).EnableApplicationLogs = true; + } } protected virtual void OnMachineConnected(IExternalBridgeClient machineOperator) diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Console/DefaultConsoleService.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Console/DefaultConsoleService.cs new file mode 100644 index 000000000..640b547a9 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Console/DefaultConsoleService.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Console.Network; +using Tango.Core; +using Tango.Core.DI; +using Tango.FSE.Common.Connection; +using Tango.FSE.Common.Console; + +namespace Tango.FSE.UI.Console +{ + [TangoCreateWhenRegistered] + public class DefaultConsoleService : ExtendedObject, IConsoleService + { + public event EventHandler<GetCurrentDirectoryResponse> Initialized; + + public string CurrentDirectory { get; private set; } + + private IMachineProvider MachineProvider { get; set; } + + public DefaultConsoleService(IMachineProvider machineProvider) + { + MachineProvider = machineProvider; + MachineProvider.MachineConnected += MachineProvider_MachineConnected; + } + + private async void MachineProvider_MachineConnected(object sender, MachineConnectedEventArgs e) + { + try + { + var response = await MachineProvider.MachineOperator.SendGenericRequest<GetCurrentDirectoryRequest, GetCurrentDirectoryResponse>(new GetCurrentDirectoryRequest(), new Transport.TransportRequestConfig() { Timeout = TimeSpan.FromSeconds(10) }); + Initialized?.Invoke(this, response); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error getting remote machine current console directory."); + } + } + + public async Task<ConsoleCommandResponse> ExecuteCommand(ConsoleCommandRequest request, TimeSpan? timeout = null) + { + var response = await MachineProvider.MachineOperator.SendGenericRequest<ConsoleCommandRequest, ConsoleCommandResponse>(request, new Transport.TransportRequestConfig() + { + ShouldLog = true, + Timeout = timeout + }); + + return response; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Logging/DefaultLoggingProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Logging/DefaultLoggingProvider.cs new file mode 100644 index 000000000..56ec08cbd --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Logging/DefaultLoggingProvider.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FSE.Common.Connection; +using Tango.FSE.Common.Logging; +using Tango.Integration.ExternalBridge; +using Tango.Integration.Logging; +using Tango.Logging; + +namespace Tango.FSE.UI.Logging +{ + public class DefaultLoggingProvider : ILoggingProvider + { + public event EventHandler<LogItemBase> ApplicationLogAvailable; + public event EventHandler<EmbeddedLogItem> EmbeddedLogAvailable; + + public DefaultLoggingProvider(IMachineProvider machineProvider) + { + if (machineProvider.MachineOperator is ExternalBridgeTcpClient) + { + (machineProvider.MachineOperator as ExternalBridgeTcpClient).ApplicationLogAvailable += DefaultLoggingProvider_ApplicationLogAvailable; + } + + machineProvider.MachineOperator.DebugLogAvailable += MachineOperator_DebugLogAvailable; + } + + private void DefaultLoggingProvider_ApplicationLogAvailable(object sender, LogItemBase log) + { + ApplicationLogAvailable?.Invoke(this, log); + } + + private void MachineOperator_DebugLogAvailable(object sender, PMR.Debugging.StartDebugLogResponse log) + { + EmbeddedLogAvailable?.Invoke(this, new EmbeddedLogItem(log) { TimeStamp = DateTime.Now}); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/MainWindow.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/MainWindow.xaml index 25919916b..aa6413cab 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/MainWindow.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/MainWindow.xaml @@ -10,7 +10,9 @@ xmlns:local="clr-namespace:Tango.FSE.UI" xmlns:commonControls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common" mc:Ignorable="d" - Title="Tango FSE" Height="720" Width="1280" + Title="Tango FSE" + Height="720" + Width="1280" WindowStartupLocation="CenterScreen" TextElement.Foreground="{StaticResource FSE_PrimaryForegroundBrush}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" @@ -18,8 +20,8 @@ TitleCharacterCasing="Normal" UseNoneWindowStyle="True" EnableDWMDropShadow="True" - MinWidth="800" - MinHeight="600" + MinWidth="1280" + MinHeight="720" BorderThickness="1" BorderBrush="Gray" FontFamily="{StaticResource flexo}" diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml new file mode 100644 index 000000000..babc4f9fa --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml @@ -0,0 +1,148 @@ +<UserControl x:Class="Tango.FSE.UI.Panes.LogViewerPane" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:local="clr-namespace:Tango.FSE.UI.Panes" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=local:LogViewerPaneVM, IsDesignTimeCreatable=False}"> + + <UserControl.Resources> + + <Style x:Key="LogsGridCellStyle" TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"> + <Setter Property="BorderThickness" Value="0"/> + <Setter Property="FocusVisualStyle" Value="{x:Null}"/> + <Setter Property="VerticalContentAlignment" Value="Center"></Setter> + </Style> + + <Style x:Key="LogsGridStyle" TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}"> + <Setter Property="Background" Value="Transparent"></Setter> + <Setter Property="Foreground" Value="{StaticResource FSE_GrayBrush}"></Setter> + <Setter Property="AutoGenerateColumns" Value="False"></Setter> + <Setter Property="CanUserAddRows" Value="False"></Setter> + <Setter Property="CanUserDeleteRows" Value="False"></Setter> + <Setter Property="CanUserReorderColumns" Value="False"></Setter> + <Setter Property="CanUserResizeColumns" Value="False"></Setter> + <Setter Property="CanUserResizeRows" Value="False"></Setter> + <Setter Property="CanUserSortColumns" Value="False"></Setter> + <Setter Property="IsReadOnly" Value="True"></Setter> + <Setter Property="SelectionMode" Value="Single"></Setter> + <Setter Property="SelectionUnit" Value="FullRow"></Setter> + <Setter Property="RowHeight" Value="35"></Setter> + <Setter Property="HorizontalGridLinesBrush" Value="{StaticResource FSE_PrimaryBackgroundBrush}"></Setter> + <Setter Property="HorizontalScrollBarVisibility" Value="Disabled"></Setter> + <Setter Property="CellStyle" Value="{StaticResource LogsGridCellStyle}" /> + </Style> + </UserControl.Resources> + + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="1*"/> + <ColumnDefinition Width="1*"/> + </Grid.ColumnDefinitions> + + <DockPanel Margin="10"> + <Grid DockPanel.Dock="Top" Margin="55 5 0 0" Panel.ZIndex="100"> + <TextBlock Foreground="{StaticResource FSE_PrimaryAccentBrush}" FontWeight="SemiBold">APPLICATION LOGS</TextBlock> + <StackPanel Margin="0 0 0 -70" HorizontalAlignment="Right" > + <StackPanel Margin="8 0 0 0" HorizontalAlignment="Left" Orientation="Horizontal"> + <controls:ToggleIconButton ToolTip="Pause/Resume application logs" CheckedIcon="Play" UncheckedIcon="Pause" Width="24" Height="24" IsChecked="{Binding ApplicationLogsPaused}" /> + <controls:IconButton Icon="CircleArrows" ToolTip="Clear application logs" Width="24" Height="24" Command="{Binding ClearApplicationLogsCommand}" /> + </StackPanel> + <StackPanel Margin="0 8 0 0" Orientation="Horizontal"> + <ItemsControl VerticalAlignment="Center" ItemsSource="{Binding SelectedApplicationLogsCategories}" Visibility="{Binding ResolutionService.IsHighResolution,Converter={StaticResource BooleanToVisibilityConverter}}"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <StackPanel Orientation="Horizontal" /> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal" Margin="10 0 0 0"> + <CheckBox FocusVisualStyle="{x:Null}" IsChecked="{Binding IsSelected,Delay=200}" VerticalAlignment="Center"> + <CheckBox.Content> + <TextBlock Text="{Binding Data}" VerticalAlignment="Center"></TextBlock> + </CheckBox.Content> + </CheckBox> + </StackPanel> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + + <DockPanel Margin="20 0 0 0" VerticalAlignment="Center"> + <material:PackIcon Kind="Search" VerticalAlignment="Center" Width="18" Height="18" /> + <TextBox Margin="5 0 0 0" Style="{StaticResource FSE_Rounded_Corners_TextBox}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" FontSize="{StaticResource FSE_SmallFontSize}" material:HintAssist.Hint="filter" material:TextFieldAssist.RippleOnFocusEnabled="True" Text="{Binding ApplicationLogsFilter,UpdateSourceTrigger=PropertyChanged,Delay=1000}" Width="200"/> + </DockPanel> + </StackPanel> + </StackPanel> + </Grid> + + <DataGrid Margin="0 5 0 0" Style="{StaticResource LogsGridStyle}" ItemsSource="{Binding ApplicationLogs}" CellStyle="{StaticResource LogsGridCellStyle}"> + <DataGrid.Columns> + <DataGridTemplateColumn Header="#" Width="40" CellTemplate="{StaticResource FSE_LogIcon_Cell}"/> + <DataGridTextColumn Header="DATE TIME" Binding="{Binding TimeStamp,StringFormat='HH:mm:ss.ff'}" Width="100" /> + <DataGridTemplateColumn Header="MESSAGE" Width="1*" > + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding Message,Converter={StaticResource StringToOneLineConverter},ConverterParameter='120'}"></TextBlock> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + </DockPanel> + + <DockPanel Grid.Column="1" Margin="10"> + <Grid DockPanel.Dock="Top" Margin="55 5 0 0" Panel.ZIndex="100"> + <TextBlock Foreground="{StaticResource FSE_PrimaryAccentBrush}" FontWeight="SemiBold">MACHINE LOGS</TextBlock> + <StackPanel Margin="0 0 0 -70" HorizontalAlignment="Right" > + <StackPanel Margin="8 0 0 0" HorizontalAlignment="Left" Orientation="Horizontal"> + <controls:ToggleIconButton ToolTip="Pause/Resume machine logs" CheckedIcon="Play" UncheckedIcon="Pause" Width="24" Height="24" IsChecked="{Binding MachineLogsPaused}" /> + <controls:IconButton Icon="CircleArrows" ToolTip="Clear machine logs" Width="24" Height="24" Command="{Binding ClearMachineLogsCommand}" /> + </StackPanel> + <StackPanel Margin="0 8 0 0" Orientation="Horizontal"> + <ItemsControl VerticalAlignment="Center" ItemsSource="{Binding SelectedMachineLogsCategories}" Visibility="{Binding ResolutionService.IsHighResolution,Converter={StaticResource BooleanToVisibilityConverter}}"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <StackPanel Orientation="Horizontal" /> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal" Margin="10 0 0 0"> + <CheckBox FocusVisualStyle="{x:Null}" IsChecked="{Binding IsSelected,Delay=200}" VerticalAlignment="Center"> + <CheckBox.Content> + <TextBlock Text="{Binding Data}" VerticalAlignment="Center"/> + </CheckBox.Content> + </CheckBox> + </StackPanel> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + + <DockPanel Margin="20 0 0 0" VerticalAlignment="Center"> + <material:PackIcon Kind="Search" VerticalAlignment="Center" Width="18" Height="18" /> + <TextBox Margin="5 0 0 0" Style="{StaticResource FSE_Rounded_Corners_TextBox}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" FontSize="{StaticResource FSE_SmallFontSize}" material:HintAssist.Hint="filter" material:TextFieldAssist.RippleOnFocusEnabled="True" Text="{Binding MachineLogsFilter,UpdateSourceTrigger=PropertyChanged,Delay=1000}" Width="200"/> + </DockPanel> + </StackPanel> + </StackPanel> + </Grid> + + <DataGrid Margin="0 5 0 0" Style="{StaticResource LogsGridStyle}" ItemsSource="{Binding MachineLogs}" CellStyle="{StaticResource LogsGridCellStyle}"> + <DataGrid.Columns> + <DataGridTemplateColumn Header="#" Width="40" CellTemplate="{StaticResource FSE_LogIcon_Cell}"/> + <DataGridTextColumn Header="DATE TIME" Binding="{Binding TimeStamp,StringFormat='HH:mm:ss.ff'}" Width="100" /> + <DataGridTemplateColumn Header="MESSAGE" Width="1*" > + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding Message,Converter={StaticResource StringToOneLineConverter},ConverterParameter='120'}"></TextBlock> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + </DockPanel> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml.cs new file mode 100644 index 000000000..3c09421ca --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.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.UI.Panes +{ + /// <summary> + /// Interaction logic for LogViewerPane.xaml + /// </summary> + public partial class LogViewerPane : UserControl + { + public LogViewerPane() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPaneVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPaneVM.cs new file mode 100644 index 000000000..64e73babf --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPaneVM.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.Core.Commands; +using Tango.Core.DI; +using Tango.FSE.Common; +using Tango.Integration.Logging; +using Tango.Logging; +using Tango.SharedUI.Components; + +namespace Tango.FSE.UI.Panes +{ + public class LogViewerPaneVM : FSEViewModel + { + private List<LogItemBase> _pausedApplicationLogs; + private List<EmbeddedLogItem> _pausedMachineLogs; + + public ObservableCollection<LogItemBase> ApplicationLogs { get; set; } + public ObservableCollection<EmbeddedLogItem> MachineLogs { get; set; } + public ICollectionView ApplicationLogsView { get; set; } + public ICollectionView MachineLogsView { get; set; } + public SelectedObjectCollection<LogCategory> SelectedApplicationLogsCategories { get; set; } + public SelectedObjectCollection<LogCategory> SelectedMachineLogsCategories { get; set; } + public bool ApplicationLogsPaused { get; set; } + public bool MachineLogsPaused { get; set; } + + private String _applicationLogsFilter; + public String ApplicationLogsFilter + { + get { return _applicationLogsFilter; } + set { _applicationLogsFilter = value; RaisePropertyChangedAuto(); ApplicationLogsView.Refresh(); } + } + + private String _machineLogsFilter; + public String MachineLogsFilter + { + get { return _machineLogsFilter; } + set { _machineLogsFilter = value; RaisePropertyChangedAuto(); MachineLogsView.Refresh(); } + } + + + public RelayCommand ClearApplicationLogsCommand { get; set; } + public RelayCommand ClearMachineLogsCommand { get; set; } + + public LogViewerPaneVM() + { + _pausedApplicationLogs = new List<LogItemBase>(); + _pausedMachineLogs = new List<EmbeddedLogItem>(); + + ApplicationLogs = new ObservableCollection<LogItemBase>(); + MachineLogs = new ObservableCollection<EmbeddedLogItem>(); + ApplicationLogsView = CollectionViewSource.GetDefaultView(ApplicationLogs); + MachineLogsView = CollectionViewSource.GetDefaultView(MachineLogs); + + ApplicationLogsView.Filter = FilterApplicationLogs; + MachineLogsView.Filter = FilterMachineLogs; + + SelectedApplicationLogsCategories = new SelectedObjectCollection<LogCategory>(new ObservableCollection<LogCategory>() + { + LogCategory.Info, + LogCategory.Warning, + LogCategory.Error, + LogCategory.Critical, + }, new ObservableCollection<LogCategory>() + { + LogCategory.Info, + LogCategory.Warning, + LogCategory.Error, + LogCategory.Critical, + }); + + SelectedMachineLogsCategories = new SelectedObjectCollection<LogCategory>(new ObservableCollection<LogCategory>() + { + LogCategory.Info, + LogCategory.Warning, + LogCategory.Error, + LogCategory.Critical, + LogCategory.Debug, + }, new ObservableCollection<LogCategory>() + { + LogCategory.Info, + LogCategory.Warning, + LogCategory.Error, + LogCategory.Critical, + LogCategory.Debug, + }); + + SelectedApplicationLogsCategories.SynchedSource.CollectionChanged += (_, __) => ApplicationLogsView.Refresh(); + SelectedMachineLogsCategories.SynchedSource.CollectionChanged += (_, __) => MachineLogsView.Refresh(); + + ClearApplicationLogsCommand = new RelayCommand(ClearApplicationLogs); + ClearMachineLogsCommand = new RelayCommand(ClearMachineLogs); + + TangoIOC.Default.Inject(this); + + LoggingProvider.ApplicationLogAvailable += LoggingProvider_ApplicationLogAvailable; + LoggingProvider.EmbeddedLogAvailable += LoggingProvider_EmbeddedLogAvailable; + } + + private bool FilterApplicationLogs(object obj) + { + var log = obj as LogItemBase; + return SelectedApplicationLogsCategories.SynchedSource.Contains(log.Category) && (String.IsNullOrWhiteSpace(ApplicationLogsFilter) || log.Message.ToLower().Contains(ApplicationLogsFilter.ToLower())); + } + + private bool FilterMachineLogs(object obj) + { + var log = obj as EmbeddedLogItem; + return SelectedMachineLogsCategories.SynchedSource.Contains(log.Category) && (String.IsNullOrWhiteSpace(MachineLogsFilter) || log.Message.ToLower().Contains(MachineLogsFilter.ToLower())); + } + + private void ClearApplicationLogs() + { + _pausedApplicationLogs.Clear(); + ApplicationLogs.Clear(); + } + + private void ClearMachineLogs() + { + _pausedMachineLogs.Clear(); + MachineLogs.Clear(); + } + + private void LoggingProvider_ApplicationLogAvailable(object sender, LogItemBase logItem) + { + if (ApplicationLogsPaused) + { + _pausedApplicationLogs.Add(logItem); + } + else + { + InvokeUI(() => + { + if (_pausedApplicationLogs.Count > 0) + { + foreach (var pausedItem in _pausedApplicationLogs) + { + ApplicationLogs.Insert(0, pausedItem); + } + + _pausedApplicationLogs.Clear(); + } + + ApplicationLogs.Insert(0, logItem); + }); + } + } + + private void LoggingProvider_EmbeddedLogAvailable(object sender, EmbeddedLogItem logItem) + { + if (MachineLogsPaused) + { + _pausedMachineLogs.Add(logItem); + } + else + { + InvokeUI(() => + { + if (_pausedMachineLogs.Count > 0) + { + foreach (var pausedItem in _pausedMachineLogs) + { + MachineLogs.Insert(0, pausedItem); + } + + _pausedMachineLogs.Clear(); + } + + MachineLogs.Insert(0, logItem); + }); + } + } + } +}
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Performance/DefaultPerformanceProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Performance/DefaultPerformanceProvider.cs new file mode 100644 index 000000000..c9b5d8bbb --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Performance/DefaultPerformanceProvider.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Core.DI; +using Tango.FSE.Common.Connection; +using Tango.FSE.Common.Performance; +using Tango.Integration.ExternalBridge.Network.Performance; + +namespace Tango.FSE.UI.Performance +{ + [TangoCreateWhenRegistered] + public class DefaultPerformanceProvider : ExtendedObject, IPerformanceProvider + { + public event EventHandler<PerformancePackageEventArgs> PerformancePackageAvailable; + + private IMachineProvider MachineProvider { get; set; } + + public DefaultPerformanceProvider(IMachineProvider machineProvider) + { + MachineProvider = machineProvider; + MachineProvider.MachineConnected += MachineProvider_MachineConnected; + } + + private void MachineProvider_MachineConnected(object sender, MachineConnectedEventArgs e) + { + MachineProvider.MachineOperator.SendGenericContinuousRequest<StartPerformanceUpdatesRequest, StartPerformanceUpdatesResponse>(new StartPerformanceUpdatesRequest()).Subscribe((response) => + { + OnPerformancePackageAvailable(response.Package); + }, (ex) => + { + LogManager.Log(ex, "Error starting performance updates."); + }, () => + { + //Do nothing. + }); + } + + protected virtual void OnPerformancePackageAvailable(PerformancePackage package) + { + PerformancePackageAvailable?.Invoke(this, new PerformancePackageEventArgs() { Package = package }); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Resolution/DefaultResolutionService.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Resolution/DefaultResolutionService.cs new file mode 100644 index 000000000..de3d2c356 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Resolution/DefaultResolutionService.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using Tango.Core; +using Tango.Core.DI; +using Tango.FSE.Common.Resolution; + +namespace Tango.FSE.UI.Resolution +{ + [TangoCreateWhenRegistered] + public class DefaultResolutionService : ExtendedObject, IResolutionService + { + public event EventHandler<ResolutionMode> ResolutionModeChanged; + public event EventHandler<SizeChangedEventArgs> ResolutionChanged; + + private ResolutionMode resolution; + public ResolutionMode Resolution + { + get + { + return resolution; + } + private set + { + resolution = value; + RaisePropertyChangedAuto(); + } + } + + private bool isLowResolution; + public bool IsLowResolution + { + get + { + return isLowResolution; + } + private set + { + isLowResolution = value; + RaisePropertyChangedAuto(); + } + } + + + private bool isHighResolution; + public bool IsHighResolution + { + get + { + return isHighResolution; + } + private set + { + isHighResolution = value; + RaisePropertyChangedAuto(); + } + } + + private double resolutionWidth; + public double ResolutionWidth + { + get + { + return resolutionWidth; + } + private set + { + resolutionWidth = value; + RaisePropertyChangedAuto(); + } + } + + private double resolutionHeight; + public double ResolutionHeight + { + get + { + return resolutionHeight; + } + private set + { + resolutionHeight = value; + RaisePropertyChangedAuto(); + } + } + + public DefaultResolutionService() + { + var window = Application.Current.MainWindow; + if (window != null) + { + window.SizeChanged += Window_SizeChanged; + } + } + + private void Window_SizeChanged(object sender, SizeChangedEventArgs e) + { + var size = e.NewSize; + + ResolutionWidth = size.Width; + ResolutionHeight = size.Height; + + IsHighResolution = ResolutionWidth > 1280 && ResolutionHeight > 800; + IsLowResolution = !isHighResolution; + + ResolutionMode previousMode = Resolution; + + Resolution = IsHighResolution ? ResolutionMode.High : ResolutionMode.Low; + + if (Resolution != previousMode) + { + ResolutionModeChanged?.Invoke(this, Resolution); + } + + ResolutionChanged?.Invoke(this, e); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/SystemInfo/DefaultSystemInfoProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/SystemInfo/DefaultSystemInfoProvider.cs new file mode 100644 index 000000000..cfa840793 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/SystemInfo/DefaultSystemInfoProvider.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Core.DI; +using Tango.FSE.Common.Connection; +using Tango.FSE.Common.SystemInfo; +using Tango.Integration.ExternalBridge.Network.Information; + +namespace Tango.FSE.UI.SystemInfo +{ + public class DefaultSystemInfoProvider : ExtendedObject, ISystemInfoProvider + { + private InformationPackage _package; + + [TangoInject] + private IMachineProvider MachineProvider { get; set; } + + public async Task<InformationPackage> GetSystemInformationPackage() + { + if (_package == null) + { + var response = await MachineProvider.MachineOperator.SendGenericRequest<GetMachineInformationRequest, GetMachineInformationResponse>(new GetMachineInformationRequest(), new Transport.TransportRequestConfig() + { + Timeout = TimeSpan.FromSeconds(30) + }); + + _package = response.Package; + return _package; + } + else + { + return _package; + } + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index 7c6679549..61f0f2e70 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -109,6 +109,7 @@ </ApplicationDefinition> <Compile Include="Authentication\DefaultAuthenticationProvider.cs" /> <Compile Include="Connection\DefaultMachineProvider.cs" /> + <Compile Include="Console\DefaultConsoleService.cs" /> <Compile Include="Contracts\ILayoutView.cs" /> <Compile Include="Diagnostics\DefaultDiagnosticsProvider.cs" /> <Compile Include="Dialogs\MachineConnectionBaseViewVM.cs" /> @@ -134,6 +135,7 @@ <Compile Include="Dialogs\MachineConnectionWifiViewVM.cs" /> <Compile Include="Gateway\DefaultGatewayService.cs" /> <Compile Include="InternalModule.cs" /> + <Compile Include="Logging\DefaultLoggingProvider.cs" /> <Compile Include="MainWindowVM.cs" /> <Compile Include="Modules\DefaultFSEModuleLoader.cs" /> <Compile Include="Navigation\DefaultNavigationManager.cs" /> @@ -145,11 +147,18 @@ <DependentUpon>ConnectedMachinePane.xaml</DependentUpon> </Compile> <Compile Include="Panes\ConnectedMachinePaneVM.cs" /> + <Compile Include="Panes\LogViewerPane.xaml.cs"> + <DependentUpon>LogViewerPane.xaml</DependentUpon> + </Compile> + <Compile Include="Panes\LogViewerPaneVM.cs" /> <Compile Include="Panes\MachineConnectionPane.xaml.cs"> <DependentUpon>MachineConnectionPane.xaml</DependentUpon> </Compile> <Compile Include="Panes\MachineConnectionPaneVM.cs" /> + <Compile Include="Performance\DefaultPerformanceProvider.cs" /> <Compile Include="RemoteDesktop\DefaultRemoteDesktopProvider.cs" /> + <Compile Include="Resolution\DefaultResolutionService.cs" /> + <Compile Include="SystemInfo\DefaultSystemInfoProvider.cs" /> <Compile Include="Threading\DefaultDispatcherProvider.cs" /> <Compile Include="ViewModelLocator.cs" /> <Compile Include="ViewModels\AccountViewVM.cs" /> @@ -220,6 +229,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Panes\LogViewerPane.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Panes\MachineConnectionPane.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -299,6 +312,10 @@ <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project> <Name>Tango.BL</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.Console\Tango.Console.csproj"> + <Project>{199E8359-CAD3-433D-9EED-2027652B24A4}</Project> + <Name>Tango.Console</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj"> <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> <Name>Tango.Core</Name> @@ -425,6 +442,7 @@ <ItemGroup> <Resource Include="Images\logout.png" /> </ItemGroup> + <ItemGroup /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets" Condition="Exists('..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets')" /> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs index 536a42ae6..f24a0cf99 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs @@ -8,24 +8,34 @@ using Tango.Core.DI; using Tango.FSE.BL; using Tango.FSE.Common.Authentication; using Tango.FSE.Common.Connection; +using Tango.FSE.Common.Console; using Tango.FSE.Common.Diagnostics; using Tango.FSE.Common.FSEApplication; using Tango.FSE.Common.Gateway; +using Tango.FSE.Common.Logging; using Tango.FSE.Common.Modules; using Tango.FSE.Common.Navigation; using Tango.FSE.Common.Notifications; +using Tango.FSE.Common.Performance; using Tango.FSE.Common.RemoteDesktop; +using Tango.FSE.Common.Resolution; +using Tango.FSE.Common.SystemInfo; using Tango.FSE.Common.Threading; using Tango.FSE.Common.Web; using Tango.FSE.UI.Authentication; using Tango.FSE.UI.Connection; +using Tango.FSE.UI.Console; using Tango.FSE.UI.Diagnostics; using Tango.FSE.UI.FSEApplication; using Tango.FSE.UI.Gateway; +using Tango.FSE.UI.Logging; using Tango.FSE.UI.Modules; using Tango.FSE.UI.Navigation; using Tango.FSE.UI.Notifications; +using Tango.FSE.UI.Performance; using Tango.FSE.UI.RemoteDesktop; +using Tango.FSE.UI.Resolution; +using Tango.FSE.UI.SystemInfo; using Tango.FSE.UI.Threading; using Tango.FSE.UI.ViewModels; @@ -46,6 +56,11 @@ namespace Tango.FSE.UI TangoIOC.Default.Unregister<IFSEApplicationManager>(); TangoIOC.Default.Unregister<IDiagnosticsProvider>(); TangoIOC.Default.Unregister<IRemoteDesktopProvider>(); + TangoIOC.Default.Unregister<IResolutionService>(); + TangoIOC.Default.Unregister<IConsoleService>(); + TangoIOC.Default.Unregister<IPerformanceProvider>(); + TangoIOC.Default.Unregister<ISystemInfoProvider>(); + TangoIOC.Default.Unregister<ILoggingProvider>(); //TangoIOC.Default.Unregister<ExternalBridgeScanner>(); //TangoIOC.Default.Unregister<IDiagnosticsFrameProvider>(); //TangoIOC.Default.Unregister<IEventLogger>(); @@ -65,6 +80,11 @@ namespace Tango.FSE.UI TangoIOC.Default.Register<INavigationManager, DefaultNavigationManager>(); TangoIOC.Default.Register<IFSEApplicationManager, DefaultFSEApplicationManager>(); TangoIOC.Default.Register<IRemoteDesktopProvider, DefaultRemoteDesktopProvider>(); + TangoIOC.Default.Register<IResolutionService, DefaultResolutionService>(); + TangoIOC.Default.Register<IConsoleService, DefaultConsoleService>(); + TangoIOC.Default.Register<IPerformanceProvider, DefaultPerformanceProvider>(); + TangoIOC.Default.Register<ISystemInfoProvider, DefaultSystemInfoProvider>(); + TangoIOC.Default.Register<ILoggingProvider, DefaultLoggingProvider>(); TangoIOC.Default.Register<MainWindowVM>(); TangoIOC.Default.Register<MainViewVM>(); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs index 701ff4b79..4e6621b9e 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LayoutViewVM.cs @@ -5,17 +5,22 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core.Commands; +using Tango.Core.Threading; using Tango.FSE.Common; using Tango.FSE.Common.Navigation; using Tango.FSE.Common.Notifications; using Tango.FSE.UI.Panes; using Tango.Integration.ExternalBridge; using Tango.SharedUI.Helpers; +using Tango.Transport; namespace Tango.FSE.UI.ViewModels { public class LayoutViewVM : FSEViewModel { + private ActionTimer _transportOutActionTimer; + private ActionTimer _transportInActionTimer; + private bool _isConnectionPaneOpened; public bool IsConnectionPaneOpened { @@ -37,6 +42,13 @@ namespace Tango.FSE.UI.ViewModels set { _connectedMachinePaneVM = value; RaisePropertyChangedAuto(); } } + private LogViewerPaneVM _logViewPaneVM; + public LogViewerPaneVM LogViewerPaneVM + { + get { return _logViewPaneVM; } + set { _logViewPaneVM = value; RaisePropertyChangedAuto(); } + } + private bool _isMenuOpened; public bool IsMenuOpened { @@ -44,6 +56,27 @@ namespace Tango.FSE.UI.ViewModels set { _isMenuOpened = value; RaisePropertyChangedAuto(); } } + private bool _isLogsOpened; + public bool IsLogsOpened + { + get { return _isLogsOpened; } + set { _isLogsOpened = value; RaisePropertyChangedAuto(); } + } + + private bool _transportOut; + public bool TransportOut + { + get { return _transportOut; } + set { _transportOut = value; RaisePropertyChanged(nameof(TransportOut)); } + } + + private bool _transportIn; + public bool TransportIn + { + get { return _transportIn; } + set { _transportIn = value; RaisePropertyChanged(nameof(TransportIn)); } + } + public RelayCommand ToggleConnectionPaneCommand { get; set; } public RelayCommand LogoutCommand { get; set; } @@ -57,7 +90,40 @@ namespace Tango.FSE.UI.ViewModels ConnectedMachinePaneVM = new ConnectedMachinePaneVM(); ConnectedMachinePaneVM.DisconnectedFromMachine += ConnectedMachinePaneVM_DisconnectedFromMachine; + LogViewerPaneVM = new LogViewerPaneVM(); + LogoutCommand = new RelayCommand(Logout); + + _transportOutActionTimer = new ActionTimer(TimeSpan.FromMilliseconds(50)); + _transportInActionTimer = new ActionTimer(TimeSpan.FromMilliseconds(50)); + } + + private void MachineProvider_MachineDisconnected(object sender, Common.Connection.MachineDisconnectedEventArgs e) + { + if (e.MachineOperator.Adapter != null) + { + e.MachineOperator.Adapter.PropertyChanged -= Adapter_PropertyChanged; + } + } + + private void MachineProvider_MachineConnected(object sender, Common.Connection.MachineConnectedEventArgs e) + { + e.MachineOperator.Adapter.PropertyChanged -= Adapter_PropertyChanged; + e.MachineOperator.Adapter.PropertyChanged += Adapter_PropertyChanged; + } + + private void Adapter_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(ITransportAdapter.TotalBytesSent)) + { + TransportOut = true; + _transportOutActionTimer.ResetReplace(() => TransportOut = false); + } + else if (e.PropertyName == nameof(ITransportAdapter.TotalBytesReceived)) + { + TransportIn = true; + _transportInActionTimer.ResetReplace(() => TransportIn = false); + } } private async void ConnectedMachinePaneVM_DisconnectedFromMachine(object sender, EventArgs e) @@ -99,6 +165,9 @@ namespace Tango.FSE.UI.ViewModels public override void OnApplicationStarted() { DiagnosticsProvider.FrameReceived += DiagnosticsProvider_FrameReceived; + + MachineProvider.MachineDisconnected += MachineProvider_MachineDisconnected; + MachineProvider.MachineConnected += MachineProvider_MachineConnected; } private void DiagnosticsProvider_FrameReceived(object sender, Common.Diagnostics.DiagnosticsFrameReceivedEventArgs e) diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs index 6f2693e5a..6517025b6 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoadingViewVM.cs @@ -46,10 +46,5 @@ namespace Tango.FSE.UI.ViewModels IsLoading = false; } } - - public override void OnApplicationReady() - { - - } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml index 2a4db030b..cbe57e8dc 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml @@ -23,11 +23,92 @@ </Grid.RowDefinitions> <Grid Grid.Row="1"> - <controls:NavigationControl x:Name="NavigationControl" TransitionAlwaysFades="True"> - <!--MODULES--> - </controls:NavigationControl> - <Grid x:Name="paneMask" Background="{StaticResource FSE_SemiTransparentBrush}" Visibility="{Binding IsConnectionPaneOpened,Converter={StaticResource BooleanToVisibilityConverter}}"> + <Grid x:Name="layoutGrid"> + <Grid.RowDefinitions> + <RowDefinition Height="1*" /> + <!--DO NOT DO MIN HEIGHT HERE!--> + <RowDefinition Height="3" /> + <RowDefinition x:Name="logsRowDefinition" MinHeight="30" Height="30" MaxHeight="{Binding ElementName=NavigationControl,Path=ActualHeight}" /> + </Grid.RowDefinitions> + + <ScrollViewer Focusable="False" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> + <controls:NavigationControl Focusable="False" x:Name="NavigationControl" VerticalAlignment="Top" TransitionAlwaysFades="True" Height="{Binding ElementName=layoutGrid,Path=ActualHeight,Converter={StaticResource MathOperatorConverter},ConverterParameter='-33'}"> + <!--MODULES--> + </controls:NavigationControl> + </ScrollViewer> + + <GridSplitter x:Name="gridLogsSplitter" Focusable="False" Grid.Row="1" Visibility="Collapsed" HorizontalAlignment="Stretch" VerticalAlignment="Center" Background="Transparent" Height="3" /> + + <Grid x:Name="gridLogs" Grid.Row="2" Grid.RowSpan="2" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}"> + <Border BorderThickness="0 1 0 0" BorderBrush="{StaticResource FSE_BorderBrush}"> + <DockPanel> + <Grid Height="30" DockPanel.Dock="Top"> + <StackPanel Margin="10 0 0 0" HorizontalAlignment="Left" Orientation="Horizontal"> + <StackPanel.Resources> + <RadialGradientBrush x:Key="FSE_LED_GrayBrush"> + <GradientStop Offset="0" Color="Gray" /> + <GradientStop Offset="1" Color="#4E4E4E" /> + </RadialGradientBrush> + <RadialGradientBrush x:Key="FSE_LED_GreenBrush"> + <GradientStop Offset="0" Color="#25E122" /> + <GradientStop Offset="1" Color="#096D07" /> + </RadialGradientBrush> + <RadialGradientBrush x:Key="FSE_LED_RedBrush"> + <GradientStop Offset="0" Color="#FA6565" /> + <GradientStop Offset="1" Color="#A32323" /> + </RadialGradientBrush> + </StackPanel.Resources> + <Grid Width="14" Height="14" ToolTip="Communication In"> + <Ellipse Stroke="#353535" Fill="{StaticResource FSE_LED_GrayBrush}" /> + <Ellipse Stroke="#353535"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Setter Property="Opacity" Value="0"></Setter> + <Setter Property="Fill" Value="{StaticResource FSE_LED_RedBrush}"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding TransportOut}" Value="True"> + <Setter Property="Opacity" Value="1"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> + </Grid> + + <Grid Margin="5 0 0 0" Width="14" Height="14" ToolTip="Communication Out"> + <Ellipse Stroke="#353535" Fill="{StaticResource FSE_LED_GrayBrush}" /> + <Ellipse Stroke="#353535"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Setter Property="Opacity" Value="0"></Setter> + <Setter Property="Fill" Value="{StaticResource FSE_LED_GreenBrush}"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding TransportIn}" Value="True"> + <Setter Property="Opacity" Value="1"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> + </Grid> + </StackPanel> + + <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 0 5 0"> + <TextBlock FontSize="{StaticResource FSE_SmallerFontSize}" VerticalAlignment="Center"></TextBlock> + <commonControls:ToggleIconButton FontSize="{StaticResource FSE_SmallerFontSize}" Margin="5 0 0 0" UncheckedText="Open Log Viewer" CheckedText="Close Log Viewer" TextAlignment="Left" Height="24" Width="Auto" Checked="OnLogsChecked" Unchecked="OnLogsUnChecked" VerticalAlignment="Center" IsChecked="{Binding IsLogsOpened}" CheckedIcon="ChevronDoubleDown" UncheckedIcon="ChevronDoubleUp" /> + </StackPanel> + </Grid> + + <Grid Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}"> + <panes:LogViewerPane DataContext="{Binding LogViewerPaneVM}" /> + </Grid> + </DockPanel> + </Border> + </Grid> + </Grid> + + <Grid x:Name="paneMask" Background="{StaticResource FSE_SemiTransparentBrush}" Visibility="{Binding IsConnectionPaneOpened,Converter={StaticResource BooleanToVisibilityConverter},FallbackValue=Collapsed}"> <i:Interaction.Triggers> <i:EventTrigger EventName="PreviewMouseUp"> <i:InvokeCommandAction Command="{Binding ToggleConnectionPaneCommand}" /> @@ -467,7 +548,7 @@ </Border.Style> <Grid> <Canvas HorizontalAlignment="Right"> - <Polygon Fill="#545454" Points="0,0 20,20 20,55 0,75"> + <Polygon IsHitTestVisible="False" Fill="#545454" Points="0,0 20,20 20,55 0,75"> </Polygon> </Canvas> @@ -511,7 +592,7 @@ </Border.Style> <Grid> <Canvas HorizontalAlignment="Right"> - <Polygon Fill="#545454" Points="0,0 20,20 20,55 0,75"> + <Polygon IsHitTestVisible="False" Fill="#545454" Points="0,0 20,20 20,55 0,75"> </Polygon> </Canvas> @@ -522,7 +603,7 @@ <Grid Width="55" Height="55" Margin="10 10" HorizontalAlignment="Left"> <Image Source="{Binding Image}" RenderOptions.BitmapScalingMode="Fant" Width="35" Stretch="Uniform" /> </Grid> - <TextBlock Margin="10 0 0 0" FontSize="{StaticResource FSE_LargeFontSize}" Text="{Binding Name}" VerticalAlignment="Center"></TextBlock> + <TextBlock IsHitTestVisible="False" Margin="10 0 0 0" FontSize="{StaticResource FSE_LargeFontSize}" Text="{Binding Name}" VerticalAlignment="Center"></TextBlock> </DockPanel> </Grid> </DataTemplate> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml.cs index f25e85e0c..28d88c923 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/LayoutView.xaml.cs @@ -24,6 +24,8 @@ namespace Tango.FSE.UI.Views public partial class LayoutView : UserControl, ILayoutView { public static LayoutView Instance { get; set; } + private GridLength gridLogsCheckedHeight = new GridLength(300,GridUnitType.Pixel); + private GridLength gridLogsUncheckedHeight; private LayoutViewVM _vm; @@ -61,5 +63,21 @@ namespace Tango.FSE.UI.Views ani.To = to; segment.BeginAnimation(LineSegment.PointProperty, ani); } + + private void OnLogsChecked(object sender, RoutedEventArgs e) + { + gridLogsUncheckedHeight = logsRowDefinition.Height; + logsRowDefinition.Height = gridLogsCheckedHeight; + logsRowDefinition.MinHeight = 200; + gridLogsSplitter.Visibility = Visibility.Visible; + } + + private void OnLogsUnChecked(object sender, RoutedEventArgs e) + { + gridLogsCheckedHeight = logsRowDefinition.Height; + logsRowDefinition.MinHeight = 30; + logsRowDefinition.Height = gridLogsUncheckedHeight; + gridLogsSplitter.Visibility = Visibility.Collapsed; + } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml index 4b6af539f..3961d303b 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml @@ -26,7 +26,7 @@ </controls:NavigationControl> <!--SNACK BARS--> - <Grid Margin="10" Opacity="0.7" HorizontalAlignment="Right" VerticalAlignment="Bottom" MaxHeight="400" Width="300" Visibility="{Binding NotificationProvider.HasSnackbarItems,Converter={StaticResource BooleanToVisibilityConverter}}"> + <Grid Margin="10 10 10 40" Opacity="0.7" HorizontalAlignment="Right" VerticalAlignment="Bottom" MaxHeight="400" Width="300" Visibility="{Binding NotificationProvider.HasSnackbarItems,Converter={StaticResource BooleanToVisibilityConverter}}"> <ScrollViewer Padding="0 0 5 0" FocusVisualStyle="{x:Null}" HorizontalScrollBarVisibility="Disabled"> <ScrollViewer.Style> <Style TargetType="ScrollViewer"> diff --git a/Software/Visual_Studio/Installers/VS Extensions/PropMan.vsix b/Software/Visual_Studio/Installers/VS Extensions/PropMan.vsix Binary files differnew file mode 100644 index 000000000..23b380931 --- /dev/null +++ b/Software/Visual_Studio/Installers/VS Extensions/PropMan.vsix diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs index 534bb364f..df2643d88 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/ViewModels/MainViewVM.cs @@ -16,12 +16,15 @@ using Tango.BL.ValueObjects; using Tango.Core.Commands; using Tango.Core.ExtensionMethods; using Tango.MachineStudio.Common; +using Tango.MachineStudio.Common.Notifications; using Tango.SharedUI.Components; namespace Tango.MachineStudio.ActionLogs.ViewModels { public class MainViewVM : StudioViewModel { + private INotificationProvider _notification; + #region Properties private DateTime _startSelectedDate; @@ -83,30 +86,23 @@ namespace Tango.MachineStudio.ActionLogs.ViewModels set { _differenceObject = value; RaisePropertyChangedAuto(); } } - - private bool _isRunning; - public bool IsRunning - { - get { return _isRunning; } - set { _isRunning = value; } - } - #endregion public RelayCommand SearchCommand { get; set; } public RelayCommand CopyToClipBoardCommand { get; set; } public RelayCommand CopyRelateObjectIDCommand { get; set; } - public MainViewVM() + public MainViewVM(INotificationProvider notification) { + _notification = notification; + ActionLogs = new ObservableCollection<ActionLog>(); - SearchCommand = new RelayCommand(GetActionLogs, () => !IsRunning); + SearchCommand = new RelayCommand(GetActionLogs, () => IsFree); CopyRelateObjectIDCommand = new RelayCommand(CopyRelateObjectID); CopyToClipBoardCommand = new RelayCommand(CopyToClipBoard, () => SelectedActionLog != null && SelectedActionLog.DifferenceObject != null); DateTime now = DateTime.Now; StartSelectedDate = now.AddMonths(-1); EndSelectedDate = now; - _isRunning = false; var source = Enum.GetValues(typeof(ActionLogType)).Cast<ActionLogType>().ToObservableCollection(); var syncedSource = Enum.GetValues(typeof(ActionLogType)).Cast<ActionLogType>().ToObservableCollection(); @@ -139,27 +135,40 @@ namespace Tango.MachineStudio.ActionLogs.ViewModels if (String.IsNullOrWhiteSpace(filter)) filter = null; - using (ObservablesContext db = ObservablesContext.CreateDefault()) + try { - - DateTime startUtc = new DateTime(StartSelectedDate.Date.Ticks, DateTimeKind.Utc); - TimeSpan offsetTime = (EndSelectedDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(24, 0, 0); - DateTime endUtc = new DateTime(EndSelectedDate.Date.Ticks + offsetTime.Ticks, DateTimeKind.Utc); + IsFree = false; - Debug.Write($"TEST TIME {startUtc} from {endUtc} " + System.Environment.NewLine); + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { - IsRunning = true; - ActionLogs = await new ActionLogsCollectionBuilder(db).Set(x => x.LastUpdated <= DbFunctions.TruncateTime(endUtc) && x.LastUpdated >= DbFunctions.TruncateTime(startUtc)) - .WithUsers() - .WithActionType(SelectedActionLogTypes.SynchedSource.ToArray()) - .Query(y => y.Where - (x => filter == null || - (x.ID.ToString().ToLower().StartsWith(filter) - || (x.RelatedObjectName != null && x.RelatedObjectName.ToLower().StartsWith(filter)) - || (x.RelatedObjectGuid != null && x.RelatedObjectGuid.ToLower().StartsWith(filter)) - || (x.User != null && x.User.Contact != null && x.User.Contact.FullName.ToLower().StartsWith(filter))))) - .BuildAsync(); - IsRunning = false; + DateTime startUtc = new DateTime(StartSelectedDate.Date.Ticks, DateTimeKind.Utc); + TimeSpan offsetTime = (EndSelectedDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(24, 0, 0); + DateTime endUtc = new DateTime(EndSelectedDate.Date.Ticks + offsetTime.Ticks, DateTimeKind.Utc); + + Debug.Write($"TEST TIME {startUtc} from {endUtc} " + System.Environment.NewLine); + + ActionLogs = await new ActionLogsCollectionBuilder(db).Set(x => x.LastUpdated <= DbFunctions.TruncateTime(endUtc) && x.LastUpdated >= DbFunctions.TruncateTime(startUtc)) + .WithUsers() + .WithActionType(SelectedActionLogTypes.SynchedSource.ToArray()) + .Query(y => y.Where + (x => filter == null || + (x.ID.ToString().ToLower().StartsWith(filter) + || (x.RelatedObjectName != null && x.RelatedObjectName.ToLower().StartsWith(filter)) + || (x.RelatedObjectGuid != null && x.RelatedObjectGuid.ToLower().StartsWith(filter)) + || (x.User != null && x.User.Contact != null && x.User.Contact.FullName.ToLower().StartsWith(filter))))) + .BuildAsync(); + } + } + catch (Exception ex) + { + IsFree = true; + LogManager.Log(ex, "Error getting action logs."); + _notification.ShowError($"Error occurred while trying to retrieve the action logs.\n{ex.Message}"); + } + finally + { + IsFree = true; } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml index 3a7eaa802..fd640bae5 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml @@ -207,7 +207,7 @@ </DataGrid.Columns> </DataGrid> </Grid> - <Grid Grid.Row="1" Grid.Column="0" Visibility="{Binding IsRunning,Converter={StaticResource BooleanToVisibilityConverter}}"> + <Grid Grid.Row="1" Grid.Column="0" Visibility="{Binding IsBusy,Converter={StaticResource BooleanToVisibilityConverter}}"> <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <mahapps:ProgressRing Margin="20 60 20 40" Width="80" Height="80" IsActive="{Binding IsRunning}"></mahapps:ProgressRing> <TextBlock Text="Loading..." HorizontalAlignment="Center" FontSize="20" FontStyle="Italic" VerticalAlignment="Center" Margin="0 20 0 0"></TextBlock> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs index ed52c2352..ed7bbec56 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs @@ -256,7 +256,7 @@ namespace Tango.MachineStudio.Statistics.ViewModels { using (ObservablesContext db = ObservablesContext.CreateDefault()) { - return db.Jobs.Where(x => x.Name!= null && x.Name.ToLower().Contains(filter.ToLower())).ToList(); + return db.Jobs.Where(x => x.Name != null && x.Name.ToLower().Contains(filter.ToLower())).ToList(); } } else @@ -270,7 +270,7 @@ namespace Tango.MachineStudio.Statistics.ViewModels return null; } }); - + StatisticsValueCollection = new StatisticsValueCollection(); } @@ -329,7 +329,7 @@ namespace Tango.MachineStudio.Statistics.ViewModels .WithJobStatus(JobRunSelectedStatuses.SynchedSource) .WithGradient(IsGradientSelection.SynchedSource) .WithRmls(SelectedThreads.SynchedSource.Select(x => x.Guid).ToList()) - .Query(y => y.Where(x => ( String.IsNullOrEmpty(jobName) || x.JobName.ToLower().StartsWith(jobName.ToLower())) + .Query(y => y.Where(x => (String.IsNullOrEmpty(jobName) || x.JobName.ToLower().StartsWith(jobName.ToLower())) && (x.JobLength < LengthUpperValue && x.JobLength >= LengthLowerValue))) .BuildListAsync(); @@ -346,7 +346,7 @@ namespace Tango.MachineStudio.Statistics.ViewModels GenerateStatistics(); } - + } catch (Exception ex) { @@ -404,8 +404,8 @@ namespace Tango.MachineStudio.Statistics.ViewModels /// </summary> protected void GenerateAverageUploadDuration() { - var average = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.UploadDuration != null && z.UploadDuration.Value.Ticks > 0).Average(x => x.UploadDuration.Value.TotalMinutes); - StatisticsValueCollection.AddStatisticsValue("Average Upload Duration", Math.Max(average, 0), " minutes"); + var val = (long)JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.UploadDuration != null).Average(x => x.UploadDuration.Value.TotalMilliseconds); + StatisticsValueCollection.AddStatisticsValue("Average Upload Duration", Math.Max(TimeSpan.FromMilliseconds(val).TotalMinutes, 0), " minutes"); } /// <summary> @@ -452,7 +452,7 @@ namespace Tango.MachineStudio.Statistics.ViewModels protected void CreateThreadConsumptionPerThread() { var temp = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.Rml != null).GroupBy(x => x.Rml.Name); - List <StatisticsValue> result = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.Rml != null && !String.IsNullOrEmpty(z.Rml.Name)).GroupBy(x => x.Rml.Name).Select(y => new StatisticsValue { Name = y.Key, Value = y.Sum(x => x.JobRun.EndPosition), Unit="m" }).ToList(); + List<StatisticsValue> result = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.Rml != null && !String.IsNullOrEmpty(z.Rml.Name)).GroupBy(x => x.Rml.Name).Select(y => new StatisticsValue { Name = y.Key, Value = y.Sum(x => x.JobRun.EndPosition), Unit = "m" }).ToList(); StatisticsValueCollection.CreateThreadConsumptionPerThread(result); } @@ -461,12 +461,12 @@ namespace Tango.MachineStudio.Statistics.ViewModels /// </summary> protected void GenerateAllLiquidQuantities() { - var db_liquidQuantities = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.JobRun.LiquidQuantities.Count > 0).Select(y=> y.JobRun.LiquidQuantities).ToList(); + var db_liquidQuantities = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.JobRun.LiquidQuantities.Count > 0).Select(y => y.JobRun.LiquidQuantities).ToList(); List<JobRunLiquidQuantity> allLiquidQuantities = new List<JobRunLiquidQuantity>(); - + foreach (LiquidTypes ltype in (LiquidTypes[])Enum.GetValues(typeof(LiquidTypes))) { - var liquidQuantityByTypeList = db_liquidQuantities.Select(x => x.FirstOrDefault(y => y.LiquidType == ltype)).Where(x=>x!=null); + var liquidQuantityByTypeList = db_liquidQuantities.Select(x => x.SingleOrDefault(y => y.LiquidType == ltype)).Where(x => x != null); var count = liquidQuantityByTypeList != null ? liquidQuantityByTypeList.Sum(x => x.Quantity) : 0; JobRunLiquidQuantity lq = new JobRunLiquidQuantity() { LiquidType = ltype, Quantity = count }; allLiquidQuantities.Add(lq); diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Console/DefaultConsoleEngineService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Console/DefaultConsoleEngineService.cs index 42228614e..4a9ee468a 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Console/DefaultConsoleEngineService.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Console/DefaultConsoleEngineService.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Console; +using Tango.Console.Network; using Tango.Core.DI; using Tango.Integration.ExternalBridge; using Tango.PPC.Common.ExternalBridge; @@ -21,16 +22,31 @@ namespace Tango.PPC.Common.Console externalBridge.RegisterRequestHandler(this); } - [ExternalBridgeRequestHandlerMethod(typeof(ConsoleCommandDTO))] - public async void OnConsoleCommandReceived(ConsoleCommandDTO command, String token, ITransporter transporter) + [ExternalBridgeRequestHandlerMethod(typeof(GetCurrentDirectoryRequest))] + public async void OnGetCurrentDirectoryRequest(GetCurrentDirectoryRequest request, String token, ITransporter transporter) + { + await transporter.SendGenericResponse(new GetCurrentDirectoryResponse() + { + CurrentDirectory = Environment.CurrentDirectory, + Suggestions = ConsoleExecutionEngine.GetSuggestions(Environment.CurrentDirectory) + }, token); + } + + [ExternalBridgeRequestHandlerMethod(typeof(ConsoleCommandRequest))] + public async void OnConsoleCommandRequest(ConsoleCommandRequest request, String token, ITransporter transporter) { if (Enabled) { try { ConsoleExecutionEngine engine = new ConsoleExecutionEngine(); - var result = await engine.Execute(command); - await transporter.SendGenericResponse<ConsoleCommandExecutionResult>(result, token, new TransportResponseConfig() + var result = await engine.Execute(request); + await transporter.SendGenericResponse<ConsoleCommandResponse>(new ConsoleCommandResponse() + { + Output = result.Output, + Suggestions = result.Suggestions, + WorkingFolder = result.WorkingFolder + }, token, new TransportResponseConfig() { Immediate = true, }); @@ -44,7 +60,7 @@ namespace Tango.PPC.Common.Console public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) { - + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Performance/DefaultPerformanceService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Performance/DefaultPerformanceService.cs new file mode 100644 index 000000000..2279d204c --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Performance/DefaultPerformanceService.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Core.DI; +using Tango.Integration.ExternalBridge; +using Tango.Integration.ExternalBridge.Network.Performance; +using Tango.PPC.Common.ExternalBridge; + +namespace Tango.PPC.Common.Performance +{ + [TangoCreateWhenRegistered] + public class DefaultPerformanceService : ExtendedObject, IPerformanceService + { + #region Nested Classes + + public static class PerformanceInfo + { + [DllImport("psapi.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetPerformanceInfo([Out] out PerformanceInformation PerformanceInformation, [In] int Size); + + [StructLayout(LayoutKind.Sequential)] + public struct PerformanceInformation + { + public int Size; + public IntPtr CommitTotal; + public IntPtr CommitLimit; + public IntPtr CommitPeak; + public IntPtr PhysicalTotal; + public IntPtr PhysicalAvailable; + public IntPtr SystemCache; + public IntPtr KernelTotal; + public IntPtr KernelPaged; + public IntPtr KernelNonPaged; + public IntPtr PageSize; + public int HandlesCount; + public int ProcessCount; + public int ThreadCount; + } + + public static Int64 GetPhysicalAvailableMemoryInMiB() + { + PerformanceInformation pi = new PerformanceInformation(); + if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi))) + { + return Convert.ToInt64((pi.PhysicalAvailable.ToInt64() * pi.PageSize.ToInt64() / 1048576)); + } + else + { + return -1; + } + + } + + public static Int64 GetTotalMemoryInMiB() + { + PerformanceInformation pi = new PerformanceInformation(); + if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi))) + { + return Convert.ToInt64((pi.PhysicalTotal.ToInt64() * pi.PageSize.ToInt64() / 1048576)); + } + else + { + return -1; + } + + } + } + + #endregion + + private class PerformanceClient + { + public ExternalBridgeReceiver Receiver { get; set; } + public String Token { get; set; } + } + + private List<PerformanceClient> _clients; + private PerformancePackage _package; + private bool _isStarted; + private Thread _performanceThread; + + public bool Enabled { get; set; } = true; + + public DefaultPerformanceService(IPPCExternalBridgeService externalBridge) + { + _package = new PerformancePackage(); + _clients = new List<PerformanceClient>(); + externalBridge.RegisterRequestHandler(this); + } + + [ExternalBridgeRequestHandlerMethod(typeof(StartPerformanceUpdatesRequest))] + public async void OnStartPerformanceUpdatesRequest(StartPerformanceUpdatesRequest request, String token, ExternalBridgeReceiver receiver) + { + if (Enabled) + { + try + { + if (!_clients.Exists(x => x.Receiver == receiver)) + { + _clients.Add(new PerformanceClient() { Receiver = receiver, Token = token }); + OnReceiversChanged(); + } + + await receiver.SendGenericResponse(new StartPerformanceUpdatesResponse() { Package = _package }, token); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error sending performance package."); + } + } + } + + public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) + { + _clients.RemoveAll(x => x.Receiver == receiver); + OnReceiversChanged(); + } + + private void OnReceiversChanged() + { + if (_clients.Count > 0 && !_isStarted) + { + _isStarted = true; + _performanceThread = new Thread(PerformanceThreadMethod); + _performanceThread.IsBackground = true; + _performanceThread.Start(); + } + else if (_clients.Count == 0 && _isStarted) + { + _isStarted = false; + } + } + + private async void PerformanceThreadMethod() + { + while (_isStarted) + { + try + { + _package.ApplicationCPU = (int)GetAppCPU(); + _package.CPU = (int)GetTotalCPU(); + _package.ApplicationRAM = (int)BytesToMegaBytes(GetAppRam()); + _package.MaxRAM = (int)BytesToMegaBytes((long)new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory); + _package.RAM = _package.MaxRAM - (int)PerformanceInfo.GetPhysicalAvailableMemoryInMiB(); + + DriveInfo info = new DriveInfo("C"); + _package.DiskCapacity = (int)BytesToMegaBytes(info.TotalSize); + _package.AvailableDiskSpace = (int)BytesToMegaBytes(info.AvailableFreeSpace); + _package.DateTime = DateTime.Now; + + foreach (var client in _clients.ToList()) + { + try + { + await client.Receiver.SendGenericResponse(new StartPerformanceUpdatesResponse() { Package = _package }, client.Token); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error sending performance package."); + } + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error creating performance package."); + } + + Thread.Sleep(200); + } + } + + #region Helpers + + private float BytesToMegaBytes(long bytes) + { + return bytes / 1024f / 1024f; + } + + public float GetAppCPU() + { + PerformanceCounter cpuCounter = new PerformanceCounter(); + cpuCounter.CategoryName = "Process"; + cpuCounter.CounterName = "% Processor Time"; + cpuCounter.InstanceName = Process.GetCurrentProcess().ProcessName; + + // will always start at 0 + float firstValue = cpuCounter.NextValue(); + System.Threading.Thread.Sleep(1000); + // now matches task manager reading + float secondValue = cpuCounter.NextValue(); + + return secondValue / Environment.ProcessorCount; + } + + public float GetTotalCPU() + { + PerformanceCounter cpuCounter = new PerformanceCounter(); + cpuCounter.CategoryName = "Processor"; + cpuCounter.CounterName = "% Processor Time"; + cpuCounter.InstanceName = "_Total"; + + // will always start at 0 + float firstValue = cpuCounter.NextValue(); + System.Threading.Thread.Sleep(1000); + // now matches task manager reading + float secondValue = cpuCounter.NextValue(); + + return secondValue; + } + + public long GetAppRam() + { + Process proc = Process.GetCurrentProcess(); + return proc.PrivateMemorySize64; + } + + #endregion + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Performance/IPerformanceService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Performance/IPerformanceService.cs new file mode 100644 index 000000000..c3bfd1543 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Performance/IPerformanceService.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Integration.ExternalBridge; + +namespace Tango.PPC.Common.Performance +{ + public interface IPerformanceService : IExternalBridgeRequestHandler + { + bool Enabled { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/SystemInfo/DefaultSystemInfoService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/SystemInfo/DefaultSystemInfoService.cs new file mode 100644 index 000000000..0f1c81416 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/SystemInfo/DefaultSystemInfoService.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Core.DI; +using Tango.Integration.ExternalBridge; +using Tango.Integration.ExternalBridge.Network.Information; +using Tango.PPC.Common.ExternalBridge; + +namespace Tango.PPC.Common.SystemInfo +{ + [TangoCreateWhenRegistered] + public class DefaultSystemInfoService : ExtendedObject, ISystemInfoService, IExternalBridgeRequestHandler + { + public bool Enabled { get; set; } = true; + + private GetMachineInformationResponse response; + + public DefaultSystemInfoService(IPPCExternalBridgeService externalBridge) + { + externalBridge.RegisterRequestHandler(this); + } + + [ExternalBridgeRequestHandlerMethod(typeof(GetMachineInformationRequest))] + public async void OnGetMachineInformationRequest(GetMachineInformationRequest request, String token, ExternalBridgeReceiver receiver) + { + try + { + if (response == null) + { + response = new GetMachineInformationResponse() + { + Package = new InformationPackage() + { + System = Tango.SystemInfo.SystemObjectsCollection.Create(), + } + }; + } + + await receiver.SendGenericResponse(response, token); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error sending system information."); + } + } + + public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) + { + + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/SystemInfo/ISystemInfoService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/SystemInfo/ISystemInfoService.cs new file mode 100644 index 000000000..0cc493891 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/SystemInfo/ISystemInfoService.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Common.SystemInfo +{ + public interface ISystemInfoService + { + bool Enabled { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj index f7b3f9e4c..4551fe427 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj @@ -72,6 +72,7 @@ <Reference Include="Microsoft.Azure.Common.NetFramework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> <Reference Include="Microsoft.Azure.ResourceManager, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> <Reference Include="Microsoft.SqlServer.AzureStorageEnum, Version=14.100.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL" /> + <Reference Include="Microsoft.VisualBasic" /> <Reference Include="Microsoft.WindowsAzure.Storage, Version=4.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> @@ -159,6 +160,8 @@ <Compile Include="MachineSetup\MachineSetupManager.cs" /> <Compile Include="MachineSetup\MachineSetupProgress.cs" /> <Compile Include="MachineSetup\MachineSetupResult.cs" /> + <Compile Include="Performance\DefaultPerformanceService.cs" /> + <Compile Include="Performance\IPerformanceService.cs" /> <Compile Include="RemoteDesktop\DefaultRemoteDesktopService.cs" /> <Compile Include="RemoteDesktop\IRemoteDesktopService.cs" /> <Compile Include="Synchronization\DefaultMachineDataSynchronizer.cs" /> @@ -167,6 +170,8 @@ <Compile Include="Synchronization\SynchronizationState.cs" /> <Compile Include="Synchronization\SynchronizationStatus.cs" /> <Compile Include="Synchronization\SynchronizationStatusChangedEventArgs.cs" /> + <Compile Include="SystemInfo\DefaultSystemInfoService.cs" /> + <Compile Include="SystemInfo\ISystemInfoService.cs" /> <Compile Include="UpdatePackages\DefaultPackageRunner.cs" /> <Compile Include="UpdatePackages\IPackageRunner.cs" /> <Compile Include="UpdatePackages\IPPCPackage.cs" /> @@ -391,6 +396,10 @@ <Project>{e1e66ed9-597d-45fa-8048-de90a6930484}</Project> <Name>Tango.SQLExaminer</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.SystemInfo\Tango.SystemInfo.csproj"> + <Project>{997a961c-beda-4b56-aa0f-c39e532f7ffa}</Project> + <Name>Tango.SystemInfo</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Touch\Tango.Touch.csproj"> <Project>{fd86424c-6e84-491b-8df9-3d0f5c236a2a}</Project> <Name>Tango.Touch</Name> diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs index a8cbcfe2d..9e150221d 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs @@ -20,11 +20,13 @@ using Tango.PPC.Common.Modules; using Tango.PPC.Common.Navigation; using Tango.PPC.Common.Notifications; using Tango.PPC.Common.OS; +using Tango.PPC.Common.Performance; using Tango.PPC.Common.Printing; using Tango.PPC.Common.RemoteAssistance; using Tango.PPC.Common.RemoteDesktop; using Tango.PPC.Common.Storage; using Tango.PPC.Common.Synchronization; +using Tango.PPC.Common.SystemInfo; using Tango.PPC.Common.Threading; using Tango.PPC.Common.UpdatePackages; using Tango.PPC.Common.UWF; @@ -82,6 +84,8 @@ namespace Tango.PPC.UI TangoIOC.Default.Unregister<IMachineDataSynchronizer>(); TangoIOC.Default.Unregister<IConsoleEngineService>(); TangoIOC.Default.Unregister<IRemoteDesktopService>(); + TangoIOC.Default.Unregister<IPerformanceService>(); + TangoIOC.Default.Unregister<ISystemInfoService>(); if (App.StartupArgs.Contains("-webDebug")) { @@ -117,6 +121,8 @@ namespace Tango.PPC.UI TangoIOC.Default.Register<IUnifiedWriteFilterManager, AlternativeUnifiedWriteFilterManager>(); TangoIOC.Default.Register<IOperationSystemManager, DefaultOperationSystemManager>(); TangoIOC.Default.Register<IBackupManager, DefaultBackupManager>(); + TangoIOC.Default.Register<IPerformanceService, DefaultPerformanceService>(); + TangoIOC.Default.Register<ISystemInfoService, DefaultSystemInfoService>(); TangoIOC.Default.Register<LoadingViewVM>(); TangoIOC.Default.Register<MainViewVM>(); diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/Themes/Generic.xaml b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/Themes/Generic.xaml index 1070736ef..64145bcfa 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/Themes/Generic.xaml +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/Themes/Generic.xaml @@ -34,7 +34,7 @@ <ItemsControl x:Name="PART_ItemsControl" ItemsSource="{TemplateBinding Items}" ItemTemplate="{TemplateBinding ItemTemplate}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> - <local:WpfGraphAxisPanel Orientation="{Binding RelativeSource={RelativeSource AncestorType=local:WpfGraphAxisControl},Path=Orientation}"></local:WpfGraphAxisPanel> + <local:WpfGraphAxisPanel x:Name="PART_AxisPanel" Orientation="{Binding RelativeSource={RelativeSource AncestorType=local:WpfGraphAxisControl},Path=Orientation}"></local:WpfGraphAxisPanel> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphAxisControl.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphAxisControl.cs index 23b831abe..aa738b203 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphAxisControl.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphAxisControl.cs @@ -25,6 +25,7 @@ namespace RealTimeGraphX.WPF public class WpfGraphAxisControl : WpfGraphComponentBase { private ItemsControl _items_control; + private WpfGraphAxisPanel _axisPanel; /// <summary> /// Initializes the <see cref="WpfGraphAxisControl"/> class. @@ -97,9 +98,37 @@ namespace RealTimeGraphX.WPF base.OnApplyTemplate(); _items_control = GetTemplateChild("PART_ItemsControl") as ItemsControl; + + _items_control.Loaded += (x, e) => + { + ItemsPresenter itemsPresenter = GetVisualChild<ItemsPresenter>(_items_control); + _axisPanel = VisualTreeHelper.GetChild(itemsPresenter, 0) as WpfGraphAxisPanel; + }; + OnTicksChanged(); } + private static T GetVisualChild<T>(DependencyObject parent) where T : Visual + { + T child = default(T); + + int numVisuals = VisualTreeHelper.GetChildrenCount(parent); + for (int i = 0; i < numVisuals; i++) + { + Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); + child = v as T; + if (child == null) + { + child = GetVisualChild<T>(v); + } + if (child != null) + { + break; + } + } + return child; + } + /// <summary> /// Called when the <see cref="Ticks"/> property has changed. /// </summary> @@ -107,16 +136,15 @@ namespace RealTimeGraphX.WPF { Items = new ObservableCollection<WpfGraphAxisTickData>(Enumerable.Range(0, Ticks).Select(x => new WpfGraphAxisTickData())); - if (Controller != null) - { - Controller.RequestVirtualRangeChange(); - } + Controller?.RequestVirtualRangeChange(); + + _axisPanel?.UpdatePanel(); } protected override void OnControllerChanged(IGraphController oldController, IGraphController newController) { base.OnControllerChanged(oldController, newController); - + if (newController != null) { newController.RequestVirtualRangeChange(); diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphAxisPanel.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphAxisPanel.cs index f10b583f4..4fb6d94bc 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphAxisPanel.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphAxisPanel.cs @@ -46,7 +46,7 @@ namespace RealTimeGraphX.WPF /// <summary> /// Updates the panel. /// </summary> - private void UpdatePanel() + public void UpdatePanel() { RowDefinitions.Clear(); ColumnDefinitions.Clear(); diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphDataSeries.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphDataSeries.cs index 15a99ab54..8eab3eabe 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphDataSeries.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphDataSeries.cs @@ -135,5 +135,15 @@ namespace RealTimeGraphX.WPF { get { return Fill != null; } } + + private object _currentValue; + /// <summary> + /// Gets the current value. + /// </summary> + public object CurrentValue + { + get { return _currentValue; } + set { _currentValue = value; RaisePropertyChangedAuto(); } + } } } diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphSurface.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphSurface.cs index ebcff3472..1a3015728 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphSurface.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX.WPF/WpfGraphSurface.cs @@ -40,6 +40,20 @@ namespace RealTimeGraphX.WPF private Point _last_mouse_position; private Grid _grid; + #region Events + + /// <summary> + /// Occurs when the surface size has changed. + /// </summary> + public event EventHandler SurfaceSizeChanged; + + /// <summary> + /// Occurs when the surface zoom rectangle has changed. + /// </summary> + public event EventHandler ZoomRectChanged; + + #endregion + #region Properties /// <summary> @@ -177,6 +191,8 @@ namespace RealTimeGraphX.WPF } _zoom_rect = new System.Drawing.RectangleF((float)x, (float)y, _zoom_rect.Width, _zoom_rect.Height); + + ZoomRectChanged?.Invoke(this, new EventArgs()); } _last_mouse_position = _current_mouse_position; @@ -202,6 +218,7 @@ namespace RealTimeGraphX.WPF _zoom_rect = new System.Drawing.RectangleF((float)Canvas.GetLeft(_selection_rectangle), (float)Canvas.GetTop(_selection_rectangle), (float)_selection_rectangle.Width, (float)_selection_rectangle.Height); _selection_rectangle.Visibility = Visibility.Hidden; _is_scaled = true; + ZoomRectChanged?.Invoke(this, new EventArgs()); } } @@ -222,6 +239,7 @@ namespace RealTimeGraphX.WPF { _zoom_rect = new System.Drawing.RectangleF(); _is_scaled = false; + ZoomRectChanged?.Invoke(this, new EventArgs()); } else if (Keyboard.IsKeyDown(Key.LeftCtrl)) { @@ -301,7 +319,7 @@ namespace RealTimeGraphX.WPF /// <param name="points">The points.</param> public void DrawSeries(WpfGraphDataSeries dataSeries, IEnumerable<System.Drawing.PointF> points) { - _g.DrawCurve(dataSeries.GdiPen, points.ToArray()); + _g.DrawPolygon(dataSeries.GdiPen, points.ToArray()); } /// <summary> @@ -373,6 +391,7 @@ namespace RealTimeGraphX.WPF { _size = new System.Drawing.SizeF((float)e.NewSize.Width, (float)e.NewSize.Height); _size_changed = true; + SurfaceSizeChanged?.Invoke(this, new EventArgs()); } #endregion diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/DataPoints/DateTimeDataPoint.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/DataPoints/DateTimeDataPoint.cs new file mode 100644 index 000000000..9ec750af9 --- /dev/null +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/DataPoints/DateTimeDataPoint.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RealTimeGraphX.DataPoints +{ + public class DateTimeDataPoint : GraphDataPoint<DateTime, DateTimeDataPoint> + { + /// <summary> + /// Initializes a new instance of the <see cref="DateTimeDataPoint"/> class. + /// </summary> + public DateTimeDataPoint() : base() + { + + } + + /// <summary> + /// Initializes a new instance of the <see cref="DateTimeDataPoint"/> class. + /// </summary> + /// <param name="value">The value.</param> + public DateTimeDataPoint(DateTime value) : base(value) + { + + } + + /// <summary> + /// Performs an implicit conversion from <see cref="System.TimeSpan"/> to <see cref="DateTimeDataPoint"/>. + /// </summary> + /// <param name="value">The value.</param> + /// <returns> + /// The result of the conversion. + /// </returns> + public static implicit operator DateTimeDataPoint(DateTime value) + { + return new DateTimeDataPoint(value); + } + + /// <summary> + /// Implements the operator -. + /// </summary> + /// <param name="a">a.</param> + /// <param name="b">The b.</param> + /// <returns> + /// The result of the operator. + /// </returns> + public static DateTimeDataPoint operator -(DateTimeDataPoint a, DateTimeDataPoint b) + { + return new DateTimeDataPoint(new DateTime(a.Value.Ticks - b.Value.Ticks)); + } + + /// <summary> + /// Implements the operator +. + /// </summary> + /// <param name="a">a.</param> + /// <param name="b">The b.</param> + /// <returns> + /// The result of the operator. + /// </returns> + public static DateTimeDataPoint operator +(DateTimeDataPoint a, DateTimeDataPoint b) + { + return new DateTimeDataPoint(new DateTime(a.Value.Ticks + b.Value.Ticks)); + } + + /// <summary> + /// Sums the value of this instance with another instance value and returns the result. + /// </summary> + /// <param name="other">The other instance.</param> + /// <returns></returns> + public override IGraphDataPoint Add(IGraphDataPoint other) + { + return new DateTimeDataPoint(new DateTime(this.Value.Ticks + (other as DateTimeDataPoint).Value.Ticks)); + } + + /// <summary> + /// Subtract the value of another instance from this instance and returns the result. + /// </summary> + /// <param name="other">The other instance.</param> + /// <returns></returns> + public override IGraphDataPoint Subtract(IGraphDataPoint other) + { + return new DateTimeDataPoint(new DateTime(this.Value.Ticks - (other as DateTimeDataPoint).Value.Ticks)); + } + + /// <summary> + /// Multiplies the value of this instance with another instance value and returns the result. + /// </summary> + /// <param name="other">The other instance.</param> + /// <returns></returns> + public override IGraphDataPoint Multiply(IGraphDataPoint other) + { + return new DateTimeDataPoint(new DateTime(this.Value.Ticks * (other as DateTimeDataPoint).Value.Ticks)); + } + + /// <summary> + /// Divides the value of this instance with another instance value and returns the result. + /// </summary> + /// <param name="other">The other instance.</param> + /// <returns></returns> + public override IGraphDataPoint Divide(IGraphDataPoint other) + { + return new DateTimeDataPoint(new DateTime(this.Value.Ticks / (other as DateTimeDataPoint).Value.Ticks)); + } + + /// <summary> + /// Returns the percentage value of this instance between the specified minimum and maximum values. + /// </summary> + /// <param name="min">The minimum.</param> + /// <param name="max">The maximum.</param> + /// <returns></returns> + public override double ComputeRelativePosition(IGraphDataPoint min, IGraphDataPoint max) + { + DateTime dMin = min as DateTimeDataPoint; + DateTime dMax = max as DateTimeDataPoint; + + if (dMax.Ticks - dMin.Ticks == 0) //Prevent divide by zero + { + return dMin.Ticks; + } + + var result = ((Value.Ticks - dMin.Ticks) * 100) / (dMax.Ticks - dMin.Ticks); + + return double.IsNaN(result) ? dMin.Ticks : result; + } + + /// <summary> + /// Returns the absolute value of the specified percentage value between the specified minimum and maximum values. + /// </summary> + /// <param name="min">The minimum.</param> + /// <param name="max">The maximum.</param> + /// <param name="percentage">The percentage.</param> + /// <returns></returns> + public override IGraphDataPoint ComputeAbsolutePosition(IGraphDataPoint min, IGraphDataPoint max, double percentage) + { + double minimum = ((DateTime)min.GetValue()).Ticks; + double maximum = ((DateTime)max.GetValue()).Ticks; + + return new DateTimeDataPoint(new DateTime((long)(minimum + (maximum - minimum) * percentage))); + } + + /// <summary> + /// Creates a range of values from the specified minimum and maximum. + /// </summary> + /// <param name="min">The minimum.</param> + /// <param name="max">The maximum.</param> + /// <param name="count">The count.</param> + /// <returns></returns> + public override IEnumerable<IGraphDataPoint> CreateRange(IGraphDataPoint min, IGraphDataPoint max, int count) + { + double minimum = ((DateTime)min.GetValue()).Ticks; + double maximum = ((DateTime)max.GetValue()).Ticks; + + return Enumerable.Range(0, count). + Select(i => minimum + (maximum - minimum) * ((double)i / (count - 1))). + Select(x => new DateTimeDataPoint(new DateTime((long)x))); + } + + /// <summary> + /// Returns a formated string of this data point. + /// </summary> + /// <param name="format">The format.</param> + /// <returns></returns> + public override string ToString(string format) + { + return Value.ToString(format); + } + + /// <summary> + /// Parses the specified value and returns a new instance of <see cref="!:TDataType" /> data point. + /// </summary> + /// <param name="value">The value.</param> + /// <returns></returns> + public override IGraphDataPoint Parse(string value) + { + return new DateTimeDataPoint(DateTime.Parse(value)); + } + } +} diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/DataPoints/Int32DataPoint.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/DataPoints/Int32DataPoint.cs index 4bccdcb74..787e59aae 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/DataPoints/Int32DataPoint.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/DataPoints/Int32DataPoint.cs @@ -118,6 +118,11 @@ namespace RealTimeGraphX.DataPoints Int32DataPoint dMin = min as Int32DataPoint; Int32DataPoint dMax = max as Int32DataPoint; + if (dMax - dMin == 0) //Prevent divide by zero + { + return dMin; + } + var result = ((Value - dMin) * 100) / (dMax - dMin); return result; @@ -147,12 +152,12 @@ namespace RealTimeGraphX.DataPoints /// <returns></returns> public override IEnumerable<IGraphDataPoint> CreateRange(IGraphDataPoint min, IGraphDataPoint max, int count) { - int minimum = (int)min.GetValue(); - int maximum = (int)max.GetValue(); + double minimum = (int)min.GetValue(); + double maximum = (int)max.GetValue(); return Enumerable.Range(0, count). - Select(i => minimum + (maximum - minimum) * ((int)i / (count - 1))). - Select(x => new Int32DataPoint(x)); + Select(i => minimum + (maximum - minimum) * ((double)i / (count - 1))). + Select(x => new Int32DataPoint((int)x)); } /// <summary> diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/GraphController.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/GraphController.cs index 328f0736e..1b452df57 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/GraphController.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/GraphController.cs @@ -47,6 +47,8 @@ namespace RealTimeGraphX public int RenderedItems { get; set; } public bool IsClearSeries { get; set; } + + public bool IsUpdateSeries { get; set; } } #endregion @@ -113,8 +115,10 @@ namespace RealTimeGraphX get { return _surface; } set { + var previous = _surface; _surface = value; RequestVirtualRangeChange(); + OnSurfaceChanged(previous, _surface); } } @@ -227,11 +231,8 @@ namespace RealTimeGraphX { List<List<PendingSeries>> pending_lists = new List<List<PendingSeries>>(); - if (_pending_series_collection.Count == 0) - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - continue; - } + var pending_list_first = _pending_series_collection.BlockDequeue(); + pending_lists.Add(pending_list_first); while (_pending_series_collection.Count > 0) { @@ -247,24 +248,24 @@ namespace RealTimeGraphX { _pending_series_collection = new GraphDataQueue<List<PendingSeries>>(); _to_render.Clear(); - break; } - - if (_to_render.ContainsKey(pending_series.Series)) + else if (!pending_series.IsUpdateSeries) { - var s = _to_render[pending_series.Series]; - s.XX.AddRange(pending_series.XX); - s.YY.AddRange(pending_series.YY); - } - else - { - _to_render[pending_series.Series] = pending_series; + if (_to_render.ContainsKey(pending_series.Series)) + { + var s = _to_render[pending_series.Series]; + s.XX.AddRange(pending_series.XX); + s.YY.AddRange(pending_series.YY); + } + else + { + _to_render[pending_series.Series] = pending_series; + } } } } if (_to_render.Count > 0) - //if (DateTime.Now > _last_render_time.AddMilliseconds(RefreshRate.TotalMilliseconds) && _to_render.Count > 0) { GraphDataPoint min_x = _range.MaximumX - _range.MaximumX; GraphDataPoint max_x = _range.MaximumX; @@ -346,6 +347,11 @@ namespace RealTimeGraphX foreach (var item in to_render) { + if (item.YY.Count > 0) + { + item.Series.CurrentValue = item.YY.Last().GetValue(); + } + var points = Renderer.Render(Surface, item.Series, _range, item.XX, item.YY, min_x, max_x, min_y, max_y); to_draw.Add(new Tuple<TDataSeries, IEnumerable<PointF>>(item.Series, points)); } @@ -385,6 +391,26 @@ namespace RealTimeGraphX #region Protected Methods /// <summary> + /// Called when the surface has changed. + /// </summary> + /// <param name="previous">The previous.</param> + /// <param name="surface">The surface.</param> + protected virtual void OnSurfaceChanged(IGraphSurface<TDataSeries> previous, IGraphSurface<TDataSeries> surface) + { + if (previous != null) + { + previous.SurfaceSizeChanged += Surface_SurfaceSizeChanged; + previous.ZoomRectChanged += Surface_ZoomRectChanged; + } + + if (surface != null) + { + surface.SurfaceSizeChanged += Surface_SurfaceSizeChanged; + surface.ZoomRectChanged += Surface_ZoomRectChanged; + } + } + + /// <summary> /// Raises the <see cref="EffectiveRangeChanged"/> event. /// </summary> /// <param name="minimumX">The minimum x.</param> @@ -431,6 +457,62 @@ namespace RealTimeGraphX #endregion + #region Surface Event Handlers + + /// <summary> + /// Handles the ZoomRectChanged event of the Surface 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 Surface_ZoomRectChanged(object sender, EventArgs e) + { + if (!_pending_series_collection.ToList().SelectMany(x => x).ToList().Exists(x => x.IsUpdateSeries)) + { + List<PendingSeries> updateSeries = new List<PendingSeries>(); + + foreach (var pending_Series in _to_render) + { + updateSeries.Add(new PendingSeries() + { + IsUpdateSeries = true, + Series = pending_Series.Value.Series, + XX = new List<GraphDataPoint>(), + YY = new List<GraphDataPoint>(), + }); + } + + _pending_series_collection.BlockEnqueue(updateSeries); + } + } + + /// <summary> + /// Handles the SurfaceSizeChanged event of the Surface 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 Surface_SurfaceSizeChanged(object sender, EventArgs e) + { + if (!_pending_series_collection.ToList().SelectMany(x => x).ToList().Exists(x => x.IsUpdateSeries)) + { + List<PendingSeries> updateSeries = new List<PendingSeries>(); + + foreach (var pending_Series in _to_render) + { + updateSeries.Add(new PendingSeries() + { + IsUpdateSeries = true, + Series = pending_Series.Value.Series, + XX = new List<GraphDataPoint>(), + YY = new List<GraphDataPoint>(), + }); + } + + _pending_series_collection.BlockEnqueue(updateSeries); + } + } + + #endregion + #region Public Methods /// <summary> diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/IGraphDataSeries.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/IGraphDataSeries.cs index dd05da92b..03640e44a 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/IGraphDataSeries.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/IGraphDataSeries.cs @@ -27,5 +27,10 @@ namespace RealTimeGraphX /// Gets or sets a value indicating whether this series should be visible. /// </summary> bool IsVisible { get; set; } + + /// <summary> + /// Gets the current value. + /// </summary> + Object CurrentValue { get; set; } } } diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/IGraphSurface.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/IGraphSurface.cs index 310bc7c3d..a3aeb90d9 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/IGraphSurface.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/IGraphSurface.cs @@ -12,6 +12,16 @@ namespace RealTimeGraphX public interface IGraphSurface : IGraphComponent { /// <summary> + /// Occurs when the surface size has changed. + /// </summary> + event EventHandler SurfaceSizeChanged; + + /// <summary> + /// Occurs when the surface zoom rectangle has changed. + /// </summary> + event EventHandler ZoomRectChanged; + + /// <summary> /// Returns the actual size of the surface. /// </summary> /// <returns></returns> diff --git a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/Renderers/ScrollingLineRenderer.cs b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/Renderers/ScrollingLineRenderer.cs index 82e80aa0f..0a4ac8368 100644 --- a/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/Renderers/ScrollingLineRenderer.cs +++ b/Software/Visual_Studio/SideChains/RealTimeGraphX-master/RealTimeGraphX/Renderers/ScrollingLineRenderer.cs @@ -78,7 +78,7 @@ namespace RealTimeGraphX.Renderers surface.FillSeries(series, GetFillPoints(surface, points)); } - surface.DrawSeries(series, points); + surface.DrawSeries(series, GetFillPoints(surface, points)); } } } diff --git a/Software/Visual_Studio/Tango.Console/ConsoleControlVM.cs b/Software/Visual_Studio/Tango.Console/ConsoleControlVM.cs index ed32bd321..1cb4118b9 100644 --- a/Software/Visual_Studio/Tango.Console/ConsoleControlVM.cs +++ b/Software/Visual_Studio/Tango.Console/ConsoleControlVM.cs @@ -106,13 +106,18 @@ namespace Tango.Console CreateNew(result.WorkingFolder, true); - Suggestions = _knownSuggestions.Concat(result.Suggestions).OrderBy(x => x.Name).ToList(); + AppendSuggestions(result.Suggestions); }); CommandExecuting?.Invoke(this, args); } } + public void AppendSuggestions(List<ConsoleSuggestion> suggestions) + { + Suggestions = _knownSuggestions.Concat(suggestions).OrderBy(x => x.Name).ToList(); + } + public void Clear() { Commands.Clear(); diff --git a/Software/Visual_Studio/Tango.Console/ConsoleDictionary.cs b/Software/Visual_Studio/Tango.Console/ConsoleDictionary.cs index f0e1ab3f6..00e4a865d 100644 --- a/Software/Visual_Studio/Tango.Console/ConsoleDictionary.cs +++ b/Software/Visual_Studio/Tango.Console/ConsoleDictionary.cs @@ -25,7 +25,7 @@ namespace Tango.Console { ConsoleKnownCommand command = new ConsoleKnownCommand(); String[] args = line.Split('\t'); - command.Name = args[0]; + command.Name = args[0].ToLower(); command.Description = args[1].Replace("\"", ""); _knownCommands.Add(command); } diff --git a/Software/Visual_Studio/Tango.Console/ConsoleExecutionEngine.cs b/Software/Visual_Studio/Tango.Console/ConsoleExecutionEngine.cs index c4bdee0a8..02b58a658 100644 --- a/Software/Visual_Studio/Tango.Console/ConsoleExecutionEngine.cs +++ b/Software/Visual_Studio/Tango.Console/ConsoleExecutionEngine.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.Console.Network; namespace Tango.Console { @@ -15,19 +16,19 @@ namespace Tango.Console public String Command { get; set; } public String Arguments { get; set; } - public ParsedCommand(ConsoleCommandDTO dto) + public ParsedCommand(ConsoleCommandRequest request) { - String[] s = dto.Command.Split(' '); + String[] s = request.Command.Split(' '); Command = s.First(); Arguments = String.Join(" ", s.Skip(1)); } } - public Task<ConsoleCommandExecutionResult> Execute(ConsoleCommandDTO command) + public Task<ConsoleCommandExecutionResult> Execute(ConsoleCommandRequest request) { return Task.Factory.StartNew<ConsoleCommandExecutionResult>(() => { - ParsedCommand parsedCommand = new ParsedCommand(command); + ParsedCommand parsedCommand = new ParsedCommand(request); if (parsedCommand.Command.ToLower() == "cd") { @@ -35,9 +36,9 @@ namespace Tango.Console { return CreateResult(parsedCommand.Arguments, String.Empty); } - else if (Directory.Exists(Path.Combine(command.WorkingFolder, parsedCommand.Arguments))) + else if (Directory.Exists(Path.Combine(request.WorkingFolder, parsedCommand.Arguments))) { - return CreateResult(Path.GetFullPath(Path.Combine(command.WorkingFolder, parsedCommand.Arguments)), String.Empty); + return CreateResult(Path.GetFullPath(Path.Combine(request.WorkingFolder, parsedCommand.Arguments)), String.Empty); } else { @@ -54,16 +55,16 @@ namespace Tango.Console process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; - if (command.WorkingFolder != null) + if (request.WorkingFolder != null) { - process.StartInfo.WorkingDirectory = command.WorkingFolder; + process.StartInfo.WorkingDirectory = request.WorkingFolder; } //process.StartInfo.Verb = "runas"; - if (ConsoleDictionary.GetKnownCommands().Exists(x => x.Name.ToLower() == parsedCommand.Command)) + if (ConsoleDictionary.GetKnownCommands().Exists(x => x.Name.ToLower() == parsedCommand.Command.ToLower())) { process.StartInfo.FileName = "cmd.exe"; - process.StartInfo.Arguments = "/C " + command.Command; + process.StartInfo.Arguments = "/C " + request.Command; } else { @@ -88,34 +89,42 @@ namespace Tango.Console error = process.StandardError.ReadToEnd(); } - return CreateResult(command.WorkingFolder, String.IsNullOrWhiteSpace(error) ? output.Replace(command.WorkingFolder + ">", "") : error); + return CreateResult(request.WorkingFolder, String.IsNullOrWhiteSpace(error) ? output.Replace(request.WorkingFolder + ">", "") : error); }); } - private ConsoleCommandExecutionResult CreateResult(String workingFolder, String output) + public static List<ConsoleSuggestion> GetSuggestions(String folder) { - ConsoleCommandExecutionResult result = new ConsoleCommandExecutionResult(); - result.WorkingFolder = workingFolder; - result.Output = output; + List<ConsoleSuggestion> suggestions = new List<ConsoleSuggestion>(); - foreach (var dir in Directory.GetDirectories(Path.GetFullPath(workingFolder))) + foreach (var dir in Directory.GetDirectories(Path.GetFullPath(folder))) { - result.Suggestions.Add(new ConsoleSuggestion() + suggestions.Add(new ConsoleSuggestion() { Type = ConsoleSuggestionType.Folder, Name = Path.GetFileName(dir) }); } - foreach (var file in Directory.GetFiles(Path.GetFullPath(workingFolder))) + foreach (var file in Directory.GetFiles(Path.GetFullPath(folder))) { - result.Suggestions.Add(new ConsoleSuggestion() + suggestions.Add(new ConsoleSuggestion() { Type = ConsoleSuggestionType.File, Name = Path.GetFileName(file), }); } + return suggestions; + } + + private ConsoleCommandExecutionResult CreateResult(String workingFolder, String output) + { + ConsoleCommandExecutionResult result = new ConsoleCommandExecutionResult(); + result.WorkingFolder = workingFolder; + result.Output = output; + result.Suggestions.AddRange(GetSuggestions(workingFolder)); + return result; } } diff --git a/Software/Visual_Studio/Tango.Console/ConsoleTextBox.cs b/Software/Visual_Studio/Tango.Console/ConsoleTextBox.cs index 2802c0fe6..d2d20b629 100644 --- a/Software/Visual_Studio/Tango.Console/ConsoleTextBox.cs +++ b/Software/Visual_Studio/Tango.Console/ConsoleTextBox.cs @@ -22,6 +22,7 @@ namespace Tango.Console private Border _caret; private ListBox _listSuggestions; private Popup _popup; + private Popup _suggestionsPopup; static ConsoleTextBox() { @@ -44,13 +45,13 @@ namespace Tango.Console public static readonly DependencyProperty CaretPositionProperty = DependencyProperty.Register("CaretPosition", typeof(double), typeof(ConsoleTextBox), new PropertyMetadata(0.0)); - public Visibility SuggestionsVisibility + public bool IsSuggestionsOpened { - get { return (Visibility)GetValue(SuggestionsVisibilityProperty); } - set { SetValue(SuggestionsVisibilityProperty, value); } + get { return (bool)GetValue(IsSuggestionsOpenedProperty); } + set { SetValue(IsSuggestionsOpenedProperty, value); } } - public static readonly DependencyProperty SuggestionsVisibilityProperty = - DependencyProperty.Register("SuggestionsVisibility", typeof(Visibility), typeof(ConsoleTextBox), new PropertyMetadata(Visibility.Collapsed)); + public static readonly DependencyProperty IsSuggestionsOpenedProperty = + DependencyProperty.Register("IsSuggestionsOpened", typeof(bool), typeof(ConsoleTextBox), new PropertyMetadata(false)); public List<ConsoleSuggestion> FilteredSuggestions { @@ -125,7 +126,7 @@ namespace Tango.Console protected override void OnPreviewKeyDown(KeyEventArgs e) { - if (SuggestionsVisibility == Visibility.Visible) + if (IsSuggestionsOpened) { if (e.Key == Key.Down) { @@ -179,13 +180,13 @@ namespace Tango.Console Text = selectedItem.Name; } - SuggestionsVisibility = Visibility.Collapsed; + IsSuggestionsOpened = false; CaretIndex = Text.Length; e.Handled = true; return; } - SuggestionsVisibility = Visibility.Collapsed; + IsSuggestionsOpened = false; } } @@ -203,21 +204,21 @@ namespace Tango.Console if (Suggestions != null) { - FilteredSuggestions = Suggestions.Where(x => lastWord.IsNotNullOrEmpty() && x.Name.ToLower().StartsWith(lastWord.ToLower())).OrderBy(x => x.Name).Take(MaxSuggestions).ToList(); + FilteredSuggestions = Suggestions.Where(x => (lastWord.IsNotNullOrEmpty() && x.Name.ToLower().StartsWith(lastWord.ToLower())) || Text.EndsWith(" ")).OrderBy(x => x.Name).Take(MaxSuggestions).ToList(); if (Text.Contains(" ")) { FilteredSuggestions = FilteredSuggestions.Where(x => x.Type != ConsoleSuggestionType.Command).ToList(); } - SuggestionsVisibility = FilteredSuggestions.Count > 0 ? Visibility.Visible : Visibility.Collapsed; + IsSuggestionsOpened = FilteredSuggestions.Count > 0; _popup.IsOpen = false; _popup.IsOpen = FilteredSuggestions.Count > 0 && SelectedSuggestion != null; } } else { - SuggestionsVisibility = Visibility.Collapsed; + IsSuggestionsOpened = false; _popup.IsOpen = false; } } @@ -228,7 +229,7 @@ namespace Tango.Console if (CaretIndex < Text.Length) { - SuggestionsVisibility = Visibility.Collapsed; + IsSuggestionsOpened = false; _popup.IsOpen = false; } } @@ -240,6 +241,7 @@ namespace Tango.Console _caret = GetTemplateChild("PART_Caret") as Border; _listSuggestions = GetTemplateChild("PART_listSuggestions") as ListBox; _popup = GetTemplateChild("PART_popup") as Popup; + _suggestionsPopup = GetTemplateChild("PART_SuggestionsPopup") as Popup; } private void MoveCustomCaret() @@ -250,6 +252,8 @@ namespace Tango.Console { Canvas.SetLeft(_caret, caretLocation.X); CaretPosition = caretLocation.X; + + _suggestionsPopup.PlacementRectangle = new Rect(CaretPosition + 10, 20, 0, 0); } } } diff --git a/Software/Visual_Studio/Tango.Console/ConsoleCommandDTO.cs b/Software/Visual_Studio/Tango.Console/Network/ConsoleCommandRequest.cs index 1d96fccc2..d7541506c 100644 --- a/Software/Visual_Studio/Tango.Console/ConsoleCommandDTO.cs +++ b/Software/Visual_Studio/Tango.Console/Network/ConsoleCommandRequest.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Tango.Console +namespace Tango.Console.Network { - public class ConsoleCommandDTO + public class ConsoleCommandRequest { public String WorkingFolder { get; set; } public String Command { get; set; } diff --git a/Software/Visual_Studio/Tango.Console/Network/ConsoleCommandResponse.cs b/Software/Visual_Studio/Tango.Console/Network/ConsoleCommandResponse.cs new file mode 100644 index 000000000..70b72e703 --- /dev/null +++ b/Software/Visual_Studio/Tango.Console/Network/ConsoleCommandResponse.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Console.Network +{ + public class ConsoleCommandResponse + { + public String WorkingFolder { get; set; } + public String Output { get; set; } + public List<ConsoleSuggestion> Suggestions { get; set; } + + public ConsoleCommandResponse() + { + Suggestions = new List<ConsoleSuggestion>(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Console/Network/GetCurrentDirectoryRequest.cs b/Software/Visual_Studio/Tango.Console/Network/GetCurrentDirectoryRequest.cs new file mode 100644 index 000000000..f5abfda70 --- /dev/null +++ b/Software/Visual_Studio/Tango.Console/Network/GetCurrentDirectoryRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Console.Network +{ + public class GetCurrentDirectoryRequest + { + + } +} diff --git a/Software/Visual_Studio/Tango.Console/Network/GetCurrentDirectoryResponse.cs b/Software/Visual_Studio/Tango.Console/Network/GetCurrentDirectoryResponse.cs new file mode 100644 index 000000000..7b6eedda0 --- /dev/null +++ b/Software/Visual_Studio/Tango.Console/Network/GetCurrentDirectoryResponse.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Console.Network +{ + public class GetCurrentDirectoryResponse + { + public String CurrentDirectory { get; set; } + public List<ConsoleSuggestion> Suggestions { get; set; } + + public GetCurrentDirectoryResponse() + { + Suggestions = new List<ConsoleSuggestion>(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Console/Tango.Console.csproj b/Software/Visual_Studio/Tango.Console/Tango.Console.csproj index 00b2042f8..9c4819389 100644 --- a/Software/Visual_Studio/Tango.Console/Tango.Console.csproj +++ b/Software/Visual_Studio/Tango.Console/Tango.Console.csproj @@ -49,7 +49,6 @@ </ItemGroup> <ItemGroup> <Compile Include="ConsoleCommand.cs" /> - <Compile Include="ConsoleCommandDTO.cs" /> <Compile Include="ConsoleCommandExecutingEventArgs.cs" /> <Compile Include="ConsoleCommandExecutionResult.cs" /> <Compile Include="ConsoleControl.xaml.cs"> @@ -63,6 +62,10 @@ <Compile Include="ConsoleSuggestionType.cs" /> <Compile Include="ConsoleTextBox.cs" /> <Compile Include="ConsoleTextBoxMaxWidthConverter.cs" /> + <Compile Include="Network\ConsoleCommandRequest.cs" /> + <Compile Include="Network\ConsoleCommandResponse.cs" /> + <Compile Include="Network\GetCurrentDirectoryRequest.cs" /> + <Compile Include="Network\GetCurrentDirectoryResponse.cs" /> <Compile Include="Properties\AssemblyInfo.cs"> <SubType>Code</SubType> </Compile> diff --git a/Software/Visual_Studio/Tango.Console/Themes/Generic.xaml b/Software/Visual_Studio/Tango.Console/Themes/Generic.xaml index e2a9e2b8f..cc62cbbf5 100644 --- a/Software/Visual_Studio/Tango.Console/Themes/Generic.xaml +++ b/Software/Visual_Studio/Tango.Console/Themes/Generic.xaml @@ -47,41 +47,43 @@ </EventTrigger> </Border.Triggers> </Border> - <Border x:Name="PART_borderSuggestions" BorderThickness="1" BorderBrush="{TemplateBinding SuggestionsBorderBrush}" Background="{TemplateBinding SuggestionsBackground}" MinWidth="200" MaxHeight="300" Canvas.Left="{TemplateBinding CaretPosition}" Canvas.Top="20" Visibility="{TemplateBinding SuggestionsVisibility}"> - <Grid> - <ListBox Foreground="{TemplateBinding SuggestionsForeground}" x:Name="PART_listSuggestions" FocusVisualStyle="{x:Null}" Background="Transparent" ItemsSource="{TemplateBinding FilteredSuggestions}" SelectedItem="{Binding RelativeSource={RelativeSource AncestorType=local:ConsoleTextBox},Path=SelectedSuggestion,Mode=TwoWay}"> - <ListBox.ItemTemplate> - <DataTemplate> - <StackPanel Orientation="Horizontal"> - <Image Stretch="Uniform" Width="16" Height="16" VerticalAlignment="Center"> - <Image.Style> - <Style TargetType="Image"> - <Setter Property="Source" Value="pack://application:,,,/Tango.Console;component/Images/thunder.png"></Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding Type}" Value="Folder"> - <Setter Property="Source" Value="pack://application:,,,/Tango.Console;component/Images/folder.png"></Setter> - </DataTrigger> - <DataTrigger Binding="{Binding Type}" Value="File"> - <Setter Property="Source" Value="pack://application:,,,/Tango.Console;component/Images/file.png"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </Image.Style> - </Image> - <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" FontSize="11" Text="{Binding Name}"></TextBlock> - </StackPanel> - </DataTemplate> - </ListBox.ItemTemplate> - </ListBox> - <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> - <Popup x:Name="PART_popup" IsOpen="False" Placement="Right" HorizontalOffset="10"> - <Border Padding="5" CornerRadius="3" MaxWidth="500" BorderThickness="1" BorderBrush="{TemplateBinding SuggestionsBorderBrush}" Background="{TemplateBinding SuggestionsBackground}"> - <TextBlock FontSize="11" Foreground="{TemplateBinding SuggestionsForeground}" TextWrapping="Wrap" Text="{Binding ElementName=PART_listSuggestions,Path=SelectedItem.Description}"></TextBlock> - </Border> - </Popup> - </Canvas> - </Grid> - </Border> + <Popup x:Name="PART_SuggestionsPopup" MinWidth="200" MaxHeight="300" Placement="RelativePoint" StaysOpen="False" IsOpen="{TemplateBinding IsSuggestionsOpened}"> + <Border BorderThickness="1" BorderBrush="{TemplateBinding SuggestionsBorderBrush}" Background="{TemplateBinding SuggestionsBackground}" MinWidth="200" MaxHeight="300"> + <Grid> + <ListBox Foreground="{TemplateBinding SuggestionsForeground}" x:Name="PART_listSuggestions" FocusVisualStyle="{x:Null}" Background="Transparent" ItemsSource="{TemplateBinding FilteredSuggestions}" SelectedItem="{Binding RelativeSource={RelativeSource AncestorType=local:ConsoleTextBox},Path=SelectedSuggestion,Mode=TwoWay}"> + <ListBox.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal"> + <Image Stretch="Uniform" Width="16" Height="16" VerticalAlignment="Center"> + <Image.Style> + <Style TargetType="Image"> + <Setter Property="Source" Value="pack://application:,,,/Tango.Console;component/Images/thunder.png"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="Folder"> + <Setter Property="Source" Value="pack://application:,,,/Tango.Console;component/Images/folder.png"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="File"> + <Setter Property="Source" Value="pack://application:,,,/Tango.Console;component/Images/file.png"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Image.Style> + </Image> + <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" FontSize="11" Text="{Binding Name}"></TextBlock> + </StackPanel> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> + <Popup x:Name="PART_popup" IsOpen="False" Placement="Right" HorizontalOffset="10"> + <Border Padding="5" CornerRadius="3" MaxWidth="500" BorderThickness="1" BorderBrush="{TemplateBinding SuggestionsBorderBrush}" Background="{TemplateBinding SuggestionsBackground}"> + <TextBlock FontSize="11" Foreground="{TemplateBinding SuggestionsForeground}" TextWrapping="Wrap" Text="{Binding ElementName=PART_listSuggestions,Path=SelectedItem.Description}"></TextBlock> + </Border> + </Popup> + </Canvas> + </Grid> + </Border> + </Popup> </Canvas> </Grid> <ControlTemplate.Triggers> diff --git a/Software/Visual_Studio/Tango.FileSystem/DragItem.cs b/Software/Visual_Studio/Tango.FileSystem/DragItem.cs new file mode 100644 index 000000000..e71b095e1 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/DragItem.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem +{ + public class DragItem + { + public FileSystemItem FileSystemItem { get; set; } + public String Destination { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/DriveItem.cs b/Software/Visual_Studio/Tango.FileSystem/DriveItem.cs new file mode 100644 index 000000000..9c4494fec --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/DriveItem.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem +{ + public class DriveItem : FileSystemItem, IFileSystemContainer + { + public ObservableCollection<FileSystemItem> Items { get; set; } + + public String Label { get; set; } + + public DriveType DriveType { get; set; } + + public DriveItem() + { + Type = FileSystemItemType.Drive; + Items = new ObservableCollection<FileSystemItem>(); + } + + protected override string OnGetName() + { + return Label; + } + + public override string Description + { + get + { + return DriveType.ToString().ToTitle(); + } + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs b/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs new file mode 100644 index 000000000..23cac7733 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/FileExplorerControl.cs @@ -0,0 +1,423 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +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; +using Tango.Core.IO; + +namespace Tango.FileSystem +{ + public class FileExplorerControl : Control + { + private ListBox _listBox; + private DataGrid _datagrid; + private bool _preventSynchronization; + private Point _dragOutStartPoint; + private bool _isMouseDown; + private List<FileSystemItem> _selectedItemsBeforeDrag; + + public IFileSystemContainer CurrentItem + { + get { return (IFileSystemContainer)GetValue(CurrentItemProperty); } + set { SetValue(CurrentItemProperty, value); } + } + public static readonly DependencyProperty CurrentItemProperty = + DependencyProperty.Register("CurrentItem", typeof(IFileSystemContainer), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public FileSystemItem SelectedItem + { + get { return (FileSystemItem)GetValue(SelectedItemProperty); } + set { SetValue(SelectedItemProperty, value); } + } + public static readonly DependencyProperty SelectedItemProperty = + DependencyProperty.Register("SelectedItem", typeof(FileSystemItem), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public ICommand ItemDoubleClickedCommand + { + get { return (ICommand)GetValue(ItemDoubleClickedCommandProperty); } + set { SetValue(ItemDoubleClickedCommandProperty, value); } + } + public static readonly DependencyProperty ItemDoubleClickedCommandProperty = + DependencyProperty.Register("ItemDoubleClickedCommand", typeof(ICommand), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public ICommand DeleteCommand + { + get { return (ICommand)GetValue(DeleteCommandProperty); } + set { SetValue(DeleteCommandProperty, value); } + } + public static readonly DependencyProperty DeleteCommandProperty = + DependencyProperty.Register("DeleteCommand", typeof(ICommand), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public ICommand DropCommand + { + get { return (ICommand)GetValue(DropCommandProperty); } + set { SetValue(DropCommandProperty, value); } + } + public static readonly DependencyProperty DropCommandProperty = + DependencyProperty.Register("DropCommand", typeof(ICommand), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public ICommand DragCommand + { + get { return (ICommand)GetValue(DragCommandProperty); } + set { SetValue(DragCommandProperty, value); } + } + public static readonly DependencyProperty DragCommandProperty = + DependencyProperty.Register("DragCommand", typeof(ICommand), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public ImageSource DriveIcon + { + get { return (ImageSource)GetValue(DriveIconProperty); } + set { SetValue(DriveIconProperty, value); } + } + public static readonly DependencyProperty DriveIconProperty = + DependencyProperty.Register("DriveIcon", typeof(ImageSource), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public ImageSource FolderIcon + { + get { return (ImageSource)GetValue(FolderIconProperty); } + set { SetValue(FolderIconProperty, value); } + } + public static readonly DependencyProperty FolderIconProperty = + DependencyProperty.Register("FolderIcon", typeof(ImageSource), typeof(FileExplorerControl), new PropertyMetadata(null)); + + public FileExplorerControlMode Mode + { + get { return (FileExplorerControlMode)GetValue(ModeProperty); } + set { SetValue(ModeProperty, value); } + } + public static readonly DependencyProperty ModeProperty = + DependencyProperty.Register("Mode", typeof(FileExplorerControlMode), typeof(FileExplorerControl), new PropertyMetadata(FileExplorerControlMode.Large)); + + public ObservableCollection<FileSystemItem> SelectedItems + { + get { return (ObservableCollection<FileSystemItem>)GetValue(SelectedItemsProperty); } + set { SetValue(SelectedItemsProperty, value); } + } + public static readonly DependencyProperty SelectedItemsProperty = + DependencyProperty.Register("SelectedItems", typeof(ObservableCollection<FileSystemItem>), typeof(FileExplorerControl), new PropertyMetadata(null, (d, e) => (d as FileExplorerControl).OnSelectedItemsChanged())); + + public bool AllowDrag + { + get { return (bool)GetValue(AllowDragProperty); } + set { SetValue(AllowDragProperty, value); } + } + public static readonly DependencyProperty AllowDragProperty = + DependencyProperty.Register("AllowDrag", typeof(bool), typeof(FileExplorerControl), new PropertyMetadata(null)); + + static FileExplorerControl() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(FileExplorerControl), new FrameworkPropertyMetadata(typeof(FileExplorerControl))); + } + + public FileExplorerControl() + { + _selectedItemsBeforeDrag = new List<FileSystemItem>(); + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _listBox = GetTemplateChild("PART_listbox") as ListBox; + _datagrid = GetTemplateChild("PART_datagrid") as DataGrid; + + _listBox.SelectionChanged += _listBox_SelectionChanged; + _datagrid.SelectionChanged += _datagrid_SelectionChanged; + } + + protected override void OnPreviewKeyUp(KeyEventArgs e) + { + base.OnPreviewKeyUp(e); + + if (e.Key == Key.Delete) + { + if (SelectedItems != null && SelectedItems.Count > 0) + { + DeleteCommand?.Execute(SelectedItems); + } + } + } + + private void _datagrid_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (!_preventSynchronization) + { + _preventSynchronization = true; + + _listBox.SelectedItems.Clear(); + + foreach (var item in _datagrid.SelectedItems) + { + _listBox.SelectedItems.Add(item); + } + + SynchronizeSelectedItems(_listBox.SelectedItems); + + _preventSynchronization = false; + } + } + + private void _listBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (!_preventSynchronization) + { + _preventSynchronization = true; + + _datagrid.SelectedItems.Clear(); + + foreach (var item in _listBox.SelectedItems) + { + _datagrid.SelectedItems.Add(item); + } + + SynchronizeSelectedItems(_listBox.SelectedItems); + + _preventSynchronization = false; + } + } + + private void SynchronizeSelectedItems(IList items) + { + if (SelectedItems == null) + { + SelectedItems = items.Cast<FileSystemItem>().ToObservableCollection(); + } + else + { + SelectedItems.Clear(); + + foreach (var item in items.Cast<FileSystemItem>().ToList()) + { + SelectedItems.Add(item); + } + } + } + + private void OnSelectedItemsChanged() + { + if (SelectedItems != null) + { + SelectedItems.CollectionChanged -= SelectedItems_CollectionChanged; + SelectedItems.CollectionChanged += SelectedItems_CollectionChanged; + SynchronizeControls(); + } + } + + private void SelectedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + SynchronizeControls(); + } + + private void SynchronizeControls() + { + if (_listBox == null) return; + + if (!_preventSynchronization) + { + _preventSynchronization = true; + + _listBox.SelectedItems.Clear(); + _datagrid.SelectedItems.Clear(); + + foreach (var item in SelectedItems) + { + _listBox.SelectedItems.Add(item); + _datagrid.SelectedItems.Add(item); + } + + _preventSynchronization = false; + } + } + + protected override void OnDrop(DragEventArgs e) + { + base.OnDrop(e); + + try + { + string[] items = (string[])e.Data.GetData(DataFormats.FileDrop, false); + + if (items != null && items.Length > 0) + { + List<FileSystemItem> fItems = new List<FileSystemItem>(); + + foreach (var item in items) + { + if (Directory.Exists(item)) + { + fItems.Add(new FolderItem() { Path = item }); + } + else if (File.Exists(item)) + { + fItems.Add(new FileItem() { Path = item }); + } + } + + if (fItems.Count > 0) + { + DropCommand?.Execute(fItems); + } + } + } + catch { } //Ignore + } + + protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) + { + base.OnPreviewMouseLeftButtonDown(e); + + if (!AllowDrag) return; + + if (e.OriginalSource is FrameworkElement) + { + var listBoxItem = (e.OriginalSource as FrameworkElement).FindAncestor<ListBoxItem>(); + var dataGridRow = (e.OriginalSource as FrameworkElement).FindAncestor<DataGridRow>(); + if (listBoxItem == null && dataGridRow == null) + { + return; + } + } + + _selectedItemsBeforeDrag.Clear(); + _selectedItemsBeforeDrag.AddRange(SelectedItems); + _isMouseDown = true; + AllowDrop = false; + _dragOutStartPoint = e.GetPosition(null); + } + + protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnPreviewMouseLeftButtonUp(e); + AllowDrop = true; + _isMouseDown = false; + } + + protected async override void OnPreviewMouseMove(MouseEventArgs e) + { + base.OnPreviewMouseMove(e); + + if (_isMouseDown) + { + Point mpos = e.GetPosition(null); + Vector diff = this._dragOutStartPoint - mpos; + + if (e.LeftButton == MouseButtonState.Pressed && + Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || + Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance) + { + if (SelectedItems.Count == 0) + { + return; + } + + + SelectedItems.Clear(); + + foreach (var item in _selectedItemsBeforeDrag) + { + SelectedItems.Add(item); + } + + List<Tuple<FileSystemItem, TemporaryFile>> dropItems = new List<Tuple<FileSystemItem, TemporaryFile>>(); + + foreach (var item in SelectedItems) + { + var tempFile = TemporaryManager.Default.CreateFile(".remote"); + dropItems.Add(new Tuple<FileSystemItem, TemporaryFile>(item, tempFile)); + } + + List<DragItem> notifyItems = new List<DragItem>(); + + List<FileSystemWatcher> watchers = new List<FileSystemWatcher>(); + + FileSystemEventHandler handler = (x, args) => + { + var detectedDropItem = dropItems.SingleOrDefault(y => y.Item2.FileName == System.IO.Path.GetFileName(args.FullPath)); + + Debug.WriteLine($"File Created: {args.FullPath}"); + + if (detectedDropItem != null) + { + try + { + detectedDropItem.Item2.Delete(); //Delete temp file. + + if (File.Exists(args.FullPath)) + { + File.Delete(args.FullPath); //Delete dropped fake file. + + dropItems.Remove(detectedDropItem); + + notifyItems.Add(new DragItem() + { + FileSystemItem = detectedDropItem.Item1, + Destination = System.IO.Path.GetDirectoryName(args.FullPath), + }); + + if (dropItems.Count == 0) + { + foreach (var watcher in watchers) + { + watcher.Dispose(); + } + + //Notify to user with all items! + Dispatcher.BeginInvoke(new Action(() => + { + DragCommand?.Execute(notifyItems); + })); + } + } + } + catch { } + } + else + { + Debug.WriteLine($"Not Found: {args.FullPath}"); + } + }; + + foreach (var drive in DriveInfo.GetDrives().Where(x => x.IsReady && (x.DriveType == DriveType.Fixed || x.DriveType == DriveType.Removable))) + { + FileSystemWatcher watcher = new FileSystemWatcher(drive.RootDirectory.FullName, "*.remote"); + watcher.IncludeSubdirectories = true; + watcher.EnableRaisingEvents = true; + watcher.Created += handler; + watchers.Add(watcher); + } + + string[] files = dropItems.Select(x => x.Item2.Path).ToArray(); + var ef = DragDrop.DoDragDrop(this, new DataObject(DataFormats.FileDrop, files, false), DragDropEffects.Copy); + + await Task.Delay(3000); + + foreach (var watcher in watchers) + { + watcher.Dispose(); + } + + if (dropItems.Count > 0) + { + //Notify about problem! + } + + _isMouseDown = false; + AllowDrop = true; + } + } + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/FileExplorerControlMode.cs b/Software/Visual_Studio/Tango.FileSystem/FileExplorerControlMode.cs new file mode 100644 index 000000000..b11c93845 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/FileExplorerControlMode.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem +{ + public enum FileExplorerControlMode + { + Large, + Details + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/FileItem.cs b/Software/Visual_Studio/Tango.FileSystem/FileItem.cs new file mode 100644 index 000000000..cbc90ce06 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/FileItem.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Tango.Core.IO; + +namespace Tango.FileSystem +{ + public class FileItem : FileSystemItem + { + private static Dictionary<String, BitmapSource> iconCache; + private static Dictionary<String, BitmapSource> smallIconCache; + private static Dictionary<String, String> typeDescriptionCache; + + static FileItem() + { + iconCache = new Dictionary<string, BitmapSource>(); + smallIconCache = new Dictionary<string, BitmapSource>(); + typeDescriptionCache = new Dictionary<string, string>(); + } + + public FileItem() + { + Type = FileSystemItemType.File; + } + + public String Extension + { + get { return System.IO.Path.GetExtension(Path); } + } + + private BitmapSource _icon; + public BitmapSource Icon + { + get + { + if (_icon == null) + { + _icon = GetFileIcon(); + } + + return _icon; + } + } + + private BitmapSource _smallIcon; + public BitmapSource SmallIcon + { + get + { + if (_smallIcon == null) + { + _smallIcon = GetSmallFileIcon(); + } + + return _smallIcon; + } + } + + public override string Description + { + get + { + if (typeDescriptionCache.ContainsKey(Extension)) + { + return typeDescriptionCache[Extension]; + } + else + { + var tempFile = TemporaryManager.Default.CreateFile(Extension); + var shellFile = Microsoft.WindowsAPICodePack.Shell.ShellFile.FromFilePath(tempFile); + var text = shellFile.Properties.System.ItemTypeText.Value.ToStringSafe(); + shellFile.Dispose(); + tempFile.Delete(); + typeDescriptionCache.Add(Extension, text); + return text; + } + } + } + + protected BitmapSource GetFileIcon() + { + if (iconCache.ContainsKey(Extension)) + { + return iconCache[Extension]; + } + else + { + var tempFile = TemporaryManager.Default.CreateFile(Extension); + var shellFile = Microsoft.WindowsAPICodePack.Shell.ShellFile.FromFilePath(tempFile); + var source = shellFile.Thumbnail.MediumBitmapSource; + shellFile.Dispose(); + tempFile.Delete(); + iconCache.Add(Extension, source); + return source; + } + } + + private BitmapSource GetSmallFileIcon() + { + if (smallIconCache.ContainsKey(Extension)) + { + return smallIconCache[Extension]; + } + else + { + var tempFile = TemporaryManager.Default.CreateFile(Extension); + var shellFile = Microsoft.WindowsAPICodePack.Shell.ShellFile.FromFilePath(tempFile); + var source = shellFile.Thumbnail.SmallBitmapSource; + shellFile.Dispose(); + tempFile.Delete(); + smallIconCache.Add(Extension, source); + return source; + } + } + + private BitmapSource IconToBitmapSource(Icon icon) + { + var imageSource = Imaging.CreateBitmapSourceFromHIcon( + icon.Handle, + Int32Rect.Empty, + BitmapSizeOptions.FromEmptyOptions()); + return imageSource; + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs b/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs new file mode 100644 index 000000000..6f8190f6c --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/FileSystemItem.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Tango.FileSystem.Network; + +namespace Tango.FileSystem +{ + public abstract class FileSystemItem + { + public String Path { get; set; } + + public FileSystemItemType Type { get; protected set; } + + public abstract String Description { get; } + + public DateTime DateModified { get; set; } + + public long Size { get; set; } + + public String Name + { + get { return OnGetName(); } + } + + public FileSystemItem() + { + DateModified = DateTime.Now; + Size = 1000 * 1000; + } + + protected virtual String OnGetName() + { + return System.IO.Path.GetFileName(Path); + } + + public override string ToString() + { + return Name; + } + + public static FileSystemItem FromDTO(FileSystemItemDTO dto) + { + FileSystemItem item = null; + + if (dto.Type == FileSystemItemType.Drive) + { + item = new DriveItem() + { + DriveType = dto.DriveType, + Label = dto.DriveLabel, + Items = dto.Items.Select(x => FromDTO(x)).ToObservableCollection() + }; + } + else if (dto.Type == FileSystemItemType.Folder) + { + item = new FolderItem() + { + Items = dto.Items.Select(x => FromDTO(x)).ToObservableCollection() + }; + } + else if (dto.Type == FileSystemItemType.File) + { + item = new FileItem(); + } + + item.DateModified = dto.DateModified; + item.Path = dto.Path; + item.Size = dto.Size; + item.Type = dto.Type; + + return item; + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/FileSystemItemType.cs b/Software/Visual_Studio/Tango.FileSystem/FileSystemItemType.cs new file mode 100644 index 000000000..5af1858a9 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/FileSystemItemType.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem +{ + public enum FileSystemItemType + { + Drive, + Folder, + File, + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs b/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs new file mode 100644 index 000000000..9a051793d --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.FileSystem.Network; + +namespace Tango.FileSystem +{ + public class FileSystemManager + { + public FileSystemItemDTO GetRoot() + { + FileSystemItemDTO folder = new FileSystemItemDTO(); + folder.Path = "This PC"; + folder.IsRoot = true; + folder.Type = FileSystemItemType.Folder; + folder.Items = DriveInfo.GetDrives().Select(x => new FileSystemItemDTO() + { + Path = x.RootDirectory.FullName, + DriveType = x.DriveType, + DriveLabel = x.Name, + Type = FileSystemItemType.Drive, + }).Cast<FileSystemItemDTO>().ToList(); + + return folder; + } + + public FileSystemItemDTO GetFolder(String path) + { + List<FileSystemItemDTO> items = new List<FileSystemItemDTO>(); + + if (String.IsNullOrWhiteSpace(path)) + { + return GetRoot(); + } + + if (!Directory.Exists(path)) + { + throw new DirectoryNotFoundException("The specified directory could not be located."); + } + + foreach (var directory in Directory.GetDirectories(path)) + { + items.Add(new FileSystemItemDTO() + { + Path = directory, + Type = FileSystemItemType.Folder, + DateModified = Directory.GetLastWriteTimeUtc(directory), + }); + } + + foreach (var file in Directory.GetFiles(path)) + { + items.Add(new FileSystemItemDTO() + { + Path = file, + Type = FileSystemItemType.File, + DateModified = File.GetLastWriteTimeUtc(file), + Size = new FileInfo(file).Length + }); + } + + return new FileSystemItemDTO() + { + Path = path, + Type = path.Length == 3 ? FileSystemItemType.Drive : FileSystemItemType.Folder, + Items = items + }; + } + + public void Delete(String path) + { + if (Directory.Exists(path)) + { + Directory.Delete(path); + } + else if (File.Exists(path)) + { + File.Delete(path); + } + else + { + throw new FileNotFoundException("Could not locate the specified file or directory."); + } + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/FolderItem.cs b/Software/Visual_Studio/Tango.FileSystem/FolderItem.cs new file mode 100644 index 000000000..95b065a2d --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/FolderItem.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem +{ + public class FolderItem : FileSystemItem, IFileSystemContainer + { + public ObservableCollection<FileSystemItem> Items { get; set; } + + public bool IsRoot { get; set; } + + public object Icon { get; set; } //Fake for binding error. + + public object SmallIcon { get; set; } //Fake for binding error. + + public FolderItem() + { + Type = FileSystemItemType.Folder; + Items = new ObservableCollection<FileSystemItem>(); + } + + public override string Description + { + get + { + return "Folder"; + } + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/IFileSystemContainer.cs b/Software/Visual_Studio/Tango.FileSystem/IFileSystemContainer.cs new file mode 100644 index 000000000..a75764a14 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/IFileSystemContainer.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem +{ + public interface IFileSystemContainer + { + ObservableCollection<FileSystemItem> Items { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Images/drive.png b/Software/Visual_Studio/Tango.FileSystem/Images/drive.png Binary files differnew file mode 100644 index 000000000..b0cda6195 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Images/drive.png diff --git a/Software/Visual_Studio/Tango.FileSystem/Images/folder.png b/Software/Visual_Studio/Tango.FileSystem/Images/folder.png Binary files differnew file mode 100644 index 000000000..800af7186 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Images/folder.png diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/FileSystemItemDTO.cs b/Software/Visual_Studio/Tango.FileSystem/Network/FileSystemItemDTO.cs new file mode 100644 index 000000000..900ba0628 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/FileSystemItemDTO.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class FileSystemItemDTO + { + public String Path { get; set; } + + public String DriveLabel { get; set; } + + public FileSystemItemType Type { get; set; } + + public DriveType DriveType { get; set; } + + public DateTime DateModified { get; set; } + + public long Size { get; set; } + + public bool IsRoot { get; set; } + + public List<FileSystemItemDTO> Items { get; set; } + + public FileSystemItemDTO() + { + Items = new List<FileSystemItemDTO>(); + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/FileUploadRequest.cs b/Software/Visual_Studio/Tango.FileSystem/Network/FileUploadRequest.cs new file mode 100644 index 000000000..50c35c584 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/FileUploadRequest.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class FileUploadRequest + { + public String Path { get; set; } + public byte[] Data { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/FileUploadResponse.cs b/Software/Visual_Studio/Tango.FileSystem/Network/FileUploadResponse.cs new file mode 100644 index 000000000..4f4bc0d52 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/FileUploadResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class FileUploadResponse + { + + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/GetFileSystemItemRequest.cs b/Software/Visual_Studio/Tango.FileSystem/Network/GetFileSystemItemRequest.cs new file mode 100644 index 000000000..f69c7bd98 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/GetFileSystemItemRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class GetFileSystemItemRequest + { + public String Path { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/GetFileSystemItemResponse.cs b/Software/Visual_Studio/Tango.FileSystem/Network/GetFileSystemItemResponse.cs new file mode 100644 index 000000000..8b82e41fc --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/GetFileSystemItemResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class GetFileSystemItemResponse + { + public FileSystemItemDTO FileSystemItem { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/StartFileDownloadRequest.cs b/Software/Visual_Studio/Tango.FileSystem/Network/StartFileDownloadRequest.cs new file mode 100644 index 000000000..aac03af38 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/StartFileDownloadRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class StartFileDownloadRequest + { + public String Path { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/StartFileDownloadResponse.cs b/Software/Visual_Studio/Tango.FileSystem/Network/StartFileDownloadResponse.cs new file mode 100644 index 000000000..187d15254 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/StartFileDownloadResponse.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class StartFileDownloadResponse + { + public byte[] Data { get; set; } + public long Position { get; set; } + public long Length { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/StartFolderDownloadRequest.cs b/Software/Visual_Studio/Tango.FileSystem/Network/StartFolderDownloadRequest.cs new file mode 100644 index 000000000..e7989bd98 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/StartFolderDownloadRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class StartFolderDownloadRequest + { + public String Path { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Network/StartFolderDownloadResponse.cs b/Software/Visual_Studio/Tango.FileSystem/Network/StartFolderDownloadResponse.cs new file mode 100644 index 000000000..c48d4c04c --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Network/StartFolderDownloadResponse.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FileSystem.Network +{ + public class StartFolderDownloadResponse + { + public byte[] ZipData { get; set; } + public long Position { get; set; } + public long Length { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.FileSystem/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..6daf8a3bd --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tango.FileSystem")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tango.FileSystem")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file +//inside a <PropertyGroup>. For example, if you are using US english +//in your source files, set the <UICulture> to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Software/Visual_Studio/Tango.FileSystem/Properties/Resources.Designer.cs b/Software/Visual_Studio/Tango.FileSystem/Properties/Resources.Designer.cs new file mode 100644 index 000000000..10db63263 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Tango.FileSystem.Properties { + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if ((resourceMan == null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Tango.FileSystem.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Properties/Resources.resx b/Software/Visual_Studio/Tango.FileSystem/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Properties/Resources.resx @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.FileSystem/Properties/Settings.Designer.cs b/Software/Visual_Studio/Tango.FileSystem/Properties/Settings.Designer.cs new file mode 100644 index 000000000..ddac2a111 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Tango.FileSystem.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Software/Visual_Studio/Tango.FileSystem/Properties/Settings.settings b/Software/Visual_Studio/Tango.FileSystem/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> + <Settings /> +</SettingsFile>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj b/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj new file mode 100644 index 000000000..90dfd78d2 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Tango.FileSystem.csproj @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}</ProjectGuid> + <OutputType>library</OutputType> + <RootNamespace>Tango.FileSystem</RootNamespace> + <AssemblyName>Tango.FileSystem</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <WarningLevel>4</WarningLevel> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Xml" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xaml"> + <RequiredTargetFramework>4.0</RequiredTargetFramework> + </Reference> + <Reference Include="WindowsBase" /> + <Reference Include="PresentationCore" /> + <Reference Include="PresentationFramework" /> + </ItemGroup> + <ItemGroup> + <Compile Include="DragItem.cs" /> + <Compile Include="VirtualFileDataObject.cs" /> + <Page Include="Themes\Generic.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Compile Include="DriveItem.cs" /> + <Compile Include="FileExplorerControl.cs"> + <SubType>Code</SubType> + </Compile> + </ItemGroup> + <ItemGroup> + <Compile Include="FileExplorerControlMode.cs" /> + <Compile Include="FileItem.cs" /> + <Compile Include="FileSystemItem.cs" /> + <Compile Include="FileSystemItemType.cs" /> + <Compile Include="FileSystemManager.cs" /> + <Compile Include="FolderItem.cs" /> + <Compile Include="IFileSystemContainer.cs" /> + <Compile Include="Network\FileSystemItemDTO.cs" /> + <Compile Include="Network\FileUploadRequest.cs" /> + <Compile Include="Network\FileUploadResponse.cs" /> + <Compile Include="Network\GetFileSystemItemRequest.cs" /> + <Compile Include="Network\GetFileSystemItemResponse.cs" /> + <Compile Include="Network\StartFileDownloadRequest.cs" /> + <Compile Include="Network\StartFileDownloadResponse.cs" /> + <Compile Include="Network\StartFolderDownloadRequest.cs" /> + <Compile Include="Network\StartFolderDownloadResponse.cs" /> + <Compile Include="Properties\AssemblyInfo.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="Properties\Settings.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Settings.settings</DependentUpon> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + </Compile> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> + </ItemGroup> + <ItemGroup> + <Resource Include="Images\drive.png" /> + <Resource Include="Images\folder.png" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="WindowsAPICodePack-Shell"> + <Version>1.1.1</Version> + </PackageReference> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + <ProjectReference Include="..\Tango.SharedUI\Tango.SharedUI.csproj"> + <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project> + <Name>Tango.SharedUI</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.FileSystem/Themes/Generic.xaml b/Software/Visual_Studio/Tango.FileSystem/Themes/Generic.xaml new file mode 100644 index 000000000..c9e561e29 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/Themes/Generic.xaml @@ -0,0 +1,211 @@ +<ResourceDictionary + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:local="clr-namespace:Tango.FileSystem"> + + <converters:ByteArrayToFileSizeConverter x:Key="ByteArrayToFileSizeConverter" /> + <converters:DateTimeUtcToLocalDateTime x:Key="DateTimeUtcToLocalDateTime" /> + + <Style x:Key="FileSystemCellStyle" TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"> + <Setter Property="BorderThickness" Value="0"/> + <Setter Property="FocusVisualStyle" Value="{x:Null}"/> + <Setter Property="VerticalContentAlignment" Value="Center"></Setter> + </Style> + + <Style TargetType="{x:Type local:FileExplorerControl}"> + <Setter Property="DriveIcon" Value="pack://application:,,,/Tango.FileSystem;component/Images/drive.png"></Setter> + <Setter Property="FolderIcon" Value="pack://application:,,,/Tango.FileSystem;component/Images/folder.png"></Setter> + <Setter Property="Mode" Value="Details"></Setter> + <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter> + <Setter Property="Focusable" Value="True"></Setter> + <Setter Property="AllowDrop" Value="True"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type local:FileExplorerControl}"> + <Border Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}"> + + <Grid Background="Transparent"> + <ListBox x:Name="PART_listbox" Background="Transparent" SelectionMode="Extended" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CurrentItem.Items}" SelectedItem="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=SelectedItem,Mode=TwoWay}"> + <ListBox.Style> + <Style TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}"> + <Setter Property="Visibility" Value="Collapsed"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Mode}" Value="Large"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </ListBox.Style> + <ListBox.ItemContainerStyle> + <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}"> + <Setter Property="Padding" Value="5"></Setter> + <Setter Property="Margin" Value="10"></Setter> + </Style> + </ListBox.ItemContainerStyle> + <ListBox.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Horizontal" IsItemsHost="True" /> + </ItemsPanelTemplate> + </ListBox.ItemsPanel> + <ListBox.ItemTemplate> + <DataTemplate> + <DockPanel Width="70" Height="115" Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <Image DockPanel.Dock="Top" RenderOptions.BitmapScalingMode="Fant" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Top"> + <Image.Style> + <Style TargetType="Image"> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="Folder"> + <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=FolderIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="Drive"> + <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=DriveIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="File"> + <Setter Property="Source" Value="{Binding Icon}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Image.Style> + </Image> + <TextBlock Text="{Binding Name}" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" HorizontalAlignment="Center" TextAlignment="Center" Margin="0 10 0 0"></TextBlock> + </DockPanel> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + + <Grid> + <Grid.Style> + <Style TargetType="Grid"> + <Setter Property="Visibility" Value="Collapsed"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Mode}" Value="Details"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Grid.Style> + <DataGrid x:Name="PART_datagrid" ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CurrentItem.Items}" CellStyle="{StaticResource FileSystemCellStyle}"> + <DataGrid.Style> + <Style TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}"> + <Setter Property="Background" Value="Transparent"></Setter> + <Setter Property="AutoGenerateColumns" Value="False"></Setter> + <Setter Property="CanUserAddRows" Value="False"></Setter> + <Setter Property="CanUserDeleteRows" Value="False"></Setter> + <Setter Property="CanUserReorderColumns" Value="False"></Setter> + <Setter Property="CanUserResizeColumns" Value="True"></Setter> + <Setter Property="CanUserResizeRows" Value="False"></Setter> + <Setter Property="CanUserSortColumns" Value="True"></Setter> + <Setter Property="IsReadOnly" Value="True"></Setter> + <Setter Property="SelectionMode" Value="Extended"></Setter> + <Setter Property="SelectionUnit" Value="FullRow"></Setter> + <Setter Property="RowHeight" Value="22"></Setter> + <Setter Property="HorizontalGridLinesBrush" Value="Transparent"></Setter> + <Setter Property="VerticalGridLinesBrush" Value="Transparent"></Setter> + <Setter Property="HorizontalScrollBarVisibility" Value="Disabled"></Setter> + <Setter Property="CellStyle" Value="{StaticResource FileSystemCellStyle}" /> + </Style> + </DataGrid.Style> + + <DataGrid.Columns> + <DataGridTemplateColumn Header="Name" Width="300*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <DockPanel Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <Image Width="18" Height="18" RenderOptions.BitmapScalingMode="Fant" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center"> + <Image.Style> + <Style TargetType="Image"> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="Drive"> + <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=DriveIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="File"> + <Setter Property="Source" Value="{Binding SmallIcon}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Type}" Value="Folder"> + <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=FolderIcon}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Image.Style> + </Image> + <TextBlock Text="{Binding Name}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" Margin="5 0 0 0"></TextBlock> + </DockPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="Date Modified" Width="170*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <DockPanel Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <TextBlock Text="{Binding DateModified,Converter={StaticResource DateTimeUtcToLocalDateTime}}" VerticalAlignment="Center"></TextBlock> + </DockPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="Type" Width="140*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <DockPanel Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <TextBlock Text="{Binding Description}" VerticalAlignment="Center"></TextBlock> + </DockPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="Size" Width="100*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <DockPanel Background="Transparent"> + <DockPanel.InputBindings> + <MouseBinding MouseAction="LeftDoubleClick" + Command="{Binding RelativeSource={RelativeSource AncestorType=local:FileExplorerControl},Path=ItemDoubleClickedCommand}" + CommandParameter="{Binding}" /> + </DockPanel.InputBindings> + <TextBlock Text="{Binding Size,Converter={StaticResource ByteArrayToFileSizeConverter}}" VerticalAlignment="Center"> + <TextBlock.Style> + <Style TargetType="TextBlock"> + <Setter Property="Visibility" Value="Hidden"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="File"> + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </TextBlock.Style> + </TextBlock> + </DockPanel> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + </Grid> + </Grid> + </Border> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> +</ResourceDictionary> diff --git a/Software/Visual_Studio/Tango.FileSystem/VirtualFileDataObject.cs b/Software/Visual_Studio/Tango.FileSystem/VirtualFileDataObject.cs new file mode 100644 index 000000000..a4a065792 --- /dev/null +++ b/Software/Visual_Studio/Tango.FileSystem/VirtualFileDataObject.cs @@ -0,0 +1,983 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Windows; + +namespace Tango.FileSystem +{ + /// <summary> + /// Class implementing drag/drop and clipboard support for virtual files. + /// Also offers an alternate interface to the IDataObject interface. + /// </summary> + public sealed class VirtualFileDataObject : System.Runtime.InteropServices.ComTypes.IDataObject, IAsyncOperation + { + /// <summary> + /// Gets or sets a value indicating whether the data object can be used asynchronously. + /// </summary> + public bool IsAsynchronous { get; set; } + + /// <summary> + /// Identifier for CFSTR_FILECONTENTS. + /// </summary> + private static short FILECONTENTS = (short)(DataFormats.GetDataFormat(NativeMethods.CFSTR_FILECONTENTS).Id); + + /// <summary> + /// Identifier for CFSTR_FILEDESCRIPTORW. + /// </summary> + private static short FILEDESCRIPTORW = (short)(DataFormats.GetDataFormat(NativeMethods.CFSTR_FILEDESCRIPTORW).Id); + + /// <summary> + /// Identifier for CFSTR_PASTESUCCEEDED. + /// </summary> + private static short PASTESUCCEEDED = (short)(DataFormats.GetDataFormat(NativeMethods.CFSTR_PASTESUCCEEDED).Id); + + /// <summary> + /// Identifier for CFSTR_PERFORMEDDROPEFFECT. + /// </summary> + private static short PERFORMEDDROPEFFECT = (short)(DataFormats.GetDataFormat(NativeMethods.CFSTR_PERFORMEDDROPEFFECT).Id); + + /// <summary> + /// Identifier for CFSTR_PREFERREDDROPEFFECT. + /// </summary> + private static short PREFERREDDROPEFFECT = (short)(DataFormats.GetDataFormat(NativeMethods.CFSTR_PREFERREDDROPEFFECT).Id); + + /// <summary> + /// In-order list of registered data objects. + /// </summary> + private List<DataObject> _dataObjects = new List<DataObject>(); + + /// <summary> + /// Tracks whether an asynchronous operation is ongoing. + /// </summary> + private bool _inOperation; + + /// <summary> + /// Stores the user-specified start action. + /// </summary> + private Action<VirtualFileDataObject> _startAction; + + /// <summary> + /// Stores the user-specified end action. + /// </summary> + private Action<VirtualFileDataObject> _endAction; + + /// <summary> + /// Initializes a new instance of the VirtualFileDataObject class. + /// </summary> + public VirtualFileDataObject() + { + IsAsynchronous = true; + } + + /// <summary> + /// Initializes a new instance of the VirtualFileDataObject class. + /// </summary> + /// <param name="startAction">Optional action to run at the start of the data transfer.</param> + /// <param name="endAction">Optional action to run at the end of the data transfer.</param> + public VirtualFileDataObject(Action<VirtualFileDataObject> startAction, Action<VirtualFileDataObject> endAction) + : this() + { + _startAction = startAction; + _endAction = endAction; + } + + #region IDataObject Members + // Explicit interface implementation hides the technical details from users of VirtualFileDataObject. + + /// <summary> + /// Creates a connection between a data object and an advisory sink. + /// </summary> + /// <param name="pFormatetc">A FORMATETC structure that defines the format, target device, aspect, and medium that will be used for future notifications.</param> + /// <param name="advf">One of the ADVF values that specifies a group of flags for controlling the advisory connection.</param> + /// <param name="adviseSink">A pointer to the IAdviseSink interface on the advisory sink that will receive the change notification.</param> + /// <param name="connection">When this method returns, contains a pointer to a DWORD token that identifies this connection.</param> + /// <returns>HRESULT success code.</returns> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")] + int System.Runtime.InteropServices.ComTypes.IDataObject.DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection) + { + Marshal.ThrowExceptionForHR(NativeMethods.OLE_E_ADVISENOTSUPPORTED); + throw new NotImplementedException(); + } + + /// <summary> + /// Destroys a notification connection that had been previously established. + /// </summary> + /// <param name="connection">A DWORD token that specifies the connection to remove.</param> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")] + void System.Runtime.InteropServices.ComTypes.IDataObject.DUnadvise(int connection) + { + Marshal.ThrowExceptionForHR(NativeMethods.OLE_E_ADVISENOTSUPPORTED); + throw new NotImplementedException(); + } + + /// <summary> + /// Creates an object that can be used to enumerate the current advisory connections. + /// </summary> + /// <param name="enumAdvise">When this method returns, contains an IEnumSTATDATA that receives the interface pointer to the new enumerator object.</param> + /// <returns>HRESULT success code.</returns> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")] + int System.Runtime.InteropServices.ComTypes.IDataObject.EnumDAdvise(out IEnumSTATDATA enumAdvise) + { + Marshal.ThrowExceptionForHR(NativeMethods.OLE_E_ADVISENOTSUPPORTED); + throw new NotImplementedException(); + } + + /// <summary> + /// Creates an object for enumerating the FORMATETC structures for a data object. + /// </summary> + /// <param name="direction">One of the DATADIR values that specifies the direction of the data.</param> + /// <returns>IEnumFORMATETC interface.</returns> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")] + IEnumFORMATETC System.Runtime.InteropServices.ComTypes.IDataObject.EnumFormatEtc(DATADIR direction) + { + if (direction == DATADIR.DATADIR_GET) + { + if (0 == _dataObjects.Count) + { + // Note: SHCreateStdEnumFmtEtc fails for a count of 0; throw helpful exception + throw new InvalidOperationException("VirtualFileDataObject requires at least one data object to enumerate."); + } + + // Create enumerator and return it + IEnumFORMATETC enumerator; + if (NativeMethods.SUCCEEDED(NativeMethods.SHCreateStdEnumFmtEtc((uint)(_dataObjects.Count), _dataObjects.Select(d => d.FORMATETC).ToArray(), out enumerator))) + { + return enumerator; + } + + // Returning null here can cause an AV in the caller; throw instead + Marshal.ThrowExceptionForHR(NativeMethods.E_FAIL); + } + throw new NotImplementedException(); + } + + /// <summary> + /// Provides a standard FORMATETC structure that is logically equivalent to a more complex structure. + /// </summary> + /// <param name="formatIn">A pointer to a FORMATETC structure that defines the format, medium, and target device that the caller would like to use to retrieve data in a subsequent call such as GetData.</param> + /// <param name="formatOut">When this method returns, contains a pointer to a FORMATETC structure that contains the most general information possible for a specific rendering, making it canonically equivalent to formatetIn.</param> + /// <returns>HRESULT success code.</returns> + int System.Runtime.InteropServices.ComTypes.IDataObject.GetCanonicalFormatEtc(ref FORMATETC formatIn, out FORMATETC formatOut) + { + throw new NotImplementedException(); + } + + /// <summary> + /// Obtains data from a source data object. + /// </summary> + /// <param name="format">A pointer to a FORMATETC structure that defines the format, medium, and target device to use when passing the data.</param> + /// <param name="medium">When this method returns, contains a pointer to the STGMEDIUM structure that indicates the storage medium containing the returned data through its tymed member, and the responsibility for releasing the medium through the value of its pUnkForRelease member.</param> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")] + void System.Runtime.InteropServices.ComTypes.IDataObject.GetData(ref FORMATETC format, out STGMEDIUM medium) + { + medium = new STGMEDIUM(); + var hr = ((System.Runtime.InteropServices.ComTypes.IDataObject)this).QueryGetData(ref format); + if (NativeMethods.SUCCEEDED(hr)) + { + // Find the best match + var formatCopy = format; // Cannot use ref or out parameter inside an anonymous method, lambda expression, or query expression + var dataObject = _dataObjects + .Where(d => + (d.FORMATETC.cfFormat == formatCopy.cfFormat) && + (d.FORMATETC.dwAspect == formatCopy.dwAspect) && + (0 != (d.FORMATETC.tymed & formatCopy.tymed) && + (d.FORMATETC.lindex == formatCopy.lindex))) + .FirstOrDefault(); + if (dataObject != null) + { + if (!IsAsynchronous && (FILEDESCRIPTORW == dataObject.FORMATETC.cfFormat) && !_inOperation) + { + // Enter the operation and call the start action + _inOperation = true; + if (null != _startAction) + { + _startAction(this); + } + } + + // Populate the STGMEDIUM + medium.tymed = dataObject.FORMATETC.tymed; + var result = dataObject.GetData(); // Possible call to user code + hr = result.Item2; + if (NativeMethods.SUCCEEDED(hr)) + { + medium.unionmember = result.Item1; + } + } + else + { + // Couldn't find a match + hr = NativeMethods.DV_E_FORMATETC; + } + } + if (!NativeMethods.SUCCEEDED(hr)) // Not redundant; hr gets updated in the block above + { + Marshal.ThrowExceptionForHR(hr); + } + } + + /// <summary> + /// Obtains data from a source data object. + /// </summary> + /// <param name="format">A pointer to a FORMATETC structure that defines the format, medium, and target device to use when passing the data.</param> + /// <param name="medium">A STGMEDIUM that defines the storage medium containing the data being transferred.</param> + void System.Runtime.InteropServices.ComTypes.IDataObject.GetDataHere(ref FORMATETC format, ref STGMEDIUM medium) + { + throw new NotImplementedException(); + } + + /// <summary> + /// Determines whether the data object is capable of rendering the data described in the FORMATETC structure. + /// </summary> + /// <param name="format">A pointer to a FORMATETC structure that defines the format, medium, and target device to use for the query.</param> + /// <returns>HRESULT success code.</returns> + int System.Runtime.InteropServices.ComTypes.IDataObject.QueryGetData(ref FORMATETC format) + { + var formatCopy = format; // Cannot use ref or out parameter inside an anonymous method, lambda expression, or query expression + var formatMatches = _dataObjects.Where(d => d.FORMATETC.cfFormat == formatCopy.cfFormat); + if (!formatMatches.Any()) + { + return NativeMethods.DV_E_FORMATETC; + } + var tymedMatches = formatMatches.Where(d => 0 != (d.FORMATETC.tymed & formatCopy.tymed)); + if (!tymedMatches.Any()) + { + return NativeMethods.DV_E_TYMED; + } + var aspectMatches = tymedMatches.Where(d => d.FORMATETC.dwAspect == formatCopy.dwAspect); + if (!aspectMatches.Any()) + { + return NativeMethods.DV_E_DVASPECT; + } + return NativeMethods.S_OK; + } + + /// <summary> + /// Transfers data to the object that implements this method. + /// </summary> + /// <param name="formatIn">A FORMATETC structure that defines the format used by the data object when interpreting the data contained in the storage medium.</param> + /// <param name="medium">A STGMEDIUM structure that defines the storage medium in which the data is being passed.</param> + /// <param name="release">true to specify that the data object called, which implements SetData, owns the storage medium after the call returns.</param> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")] + void System.Runtime.InteropServices.ComTypes.IDataObject.SetData(ref FORMATETC formatIn, ref STGMEDIUM medium, bool release) + { + var handled = false; + if ((formatIn.dwAspect == DVASPECT.DVASPECT_CONTENT) && + (formatIn.tymed == TYMED.TYMED_HGLOBAL) && + (medium.tymed == formatIn.tymed)) + { + // Supported format; capture the data + var ptr = NativeMethods.GlobalLock(medium.unionmember); + if (IntPtr.Zero != ptr) + { + try + { + var length = NativeMethods.GlobalSize(ptr).ToInt32(); + var data = new byte[length]; + Marshal.Copy(ptr, data, 0, length); + // Store it in our own format + SetData(formatIn.cfFormat, data); + handled = true; + } + finally + { + NativeMethods.GlobalUnlock(medium.unionmember); + } + } + + // Release memory if we now own it + if (release) + { + Marshal.FreeHGlobal(medium.unionmember); + } + } + + // Handle synchronous mode + if (!IsAsynchronous && (PERFORMEDDROPEFFECT == formatIn.cfFormat) && _inOperation) + { + // Call the end action and exit the operation + if (null != _endAction) + { + _endAction(this); + } + _inOperation = false; + } + + // Throw if unhandled + if (!handled) + { + throw new NotImplementedException(); + } + } + + #endregion + + /// <summary> + /// Provides data for the specified data format (HGLOBAL). + /// </summary> + /// <param name="dataFormat">Data format.</param> + /// <param name="data">Sequence of data.</param> + public void SetData(short dataFormat, IEnumerable<byte> data) + { + _dataObjects.Add( + new DataObject + { + FORMATETC = new FORMATETC + { + cfFormat = dataFormat, + ptd = IntPtr.Zero, + dwAspect = DVASPECT.DVASPECT_CONTENT, + lindex = -1, + tymed = TYMED.TYMED_HGLOBAL + }, + GetData = () => + { + var dataArray = data.ToArray(); + var ptr = Marshal.AllocHGlobal(dataArray.Length); + Marshal.Copy(dataArray, 0, ptr, dataArray.Length); + return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK); + }, + }); + } + + /// <summary> + /// Provides data for the specified data format and index (ISTREAM). + /// </summary> + /// <param name="dataFormat">Data format.</param> + /// <param name="index">Index of data.</param> + /// <param name="streamData">Action generating the data.</param> + /// <remarks> + /// Uses Stream instead of IEnumerable(T) because Stream is more likely + /// to be natural for the expected scenarios. + /// </remarks> + public void SetData(short dataFormat, int index, Action<Stream> streamData) + { + _dataObjects.Add( + new DataObject + { + FORMATETC = new FORMATETC + { + cfFormat = dataFormat, + ptd = IntPtr.Zero, + dwAspect = DVASPECT.DVASPECT_CONTENT, + lindex = index, + tymed = TYMED.TYMED_ISTREAM + }, + GetData = () => + { + // Create IStream for data + var ptr = IntPtr.Zero; + var iStream = NativeMethods.CreateStreamOnHGlobal(IntPtr.Zero, true); + if (streamData != null) + { + // Wrap in a .NET-friendly Stream and call provided code to fill it + using (var stream = new IStreamWrapper(iStream)) + { + streamData(stream); + } + } + // Return an IntPtr for the IStream + ptr = Marshal.GetComInterfaceForObject(iStream, typeof(IStream)); + Marshal.ReleaseComObject(iStream); + return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK); + }, + }); + } + + /// <summary> + /// Provides data for the specified data format (FILEGROUPDESCRIPTOR/FILEDESCRIPTOR) + /// </summary> + /// <param name="fileDescriptors">Collection of virtual files.</param> + public void SetData(IEnumerable<FileDescriptor> fileDescriptors) + { + // Prepare buffer + var bytes = new List<byte>(); + // Add FILEGROUPDESCRIPTOR header + bytes.AddRange(StructureBytes(new NativeMethods.FILEGROUPDESCRIPTOR { cItems = (uint)(fileDescriptors.Count()) })); + // Add n FILEDESCRIPTORs + foreach (var fileDescriptor in fileDescriptors) + { + // Set required fields + var FILEDESCRIPTOR = new NativeMethods.FILEDESCRIPTOR + { + cFileName = fileDescriptor.Name, + }; + // Set optional timestamp + if (fileDescriptor.ChangeTimeUtc.HasValue) + { + FILEDESCRIPTOR.dwFlags |= NativeMethods.FD_CREATETIME | NativeMethods.FD_WRITESTIME; + var changeTime = fileDescriptor.ChangeTimeUtc.Value.ToLocalTime().ToFileTime(); + var changeTimeFileTime = new System.Runtime.InteropServices.ComTypes.FILETIME + { + dwLowDateTime = (int)(changeTime & 0xffffffff), + dwHighDateTime = (int)(changeTime >> 32), + }; + FILEDESCRIPTOR.ftLastWriteTime = changeTimeFileTime; + FILEDESCRIPTOR.ftCreationTime = changeTimeFileTime; + } + // Set optional length + if (fileDescriptor.Length.HasValue) + { + FILEDESCRIPTOR.dwFlags |= NativeMethods.FD_FILESIZE; + FILEDESCRIPTOR.nFileSizeLow = (uint)(fileDescriptor.Length & 0xffffffff); + FILEDESCRIPTOR.nFileSizeHigh = (uint)(fileDescriptor.Length >> 32); + } + // Add structure to buffer + bytes.AddRange(StructureBytes(FILEDESCRIPTOR)); + } + + // Set CFSTR_FILEDESCRIPTORW + SetData(FILEDESCRIPTORW, bytes); + // Set n CFSTR_FILECONTENTS + var index = 0; + foreach (var fileDescriptor in fileDescriptors) + { + SetData(FILECONTENTS, index, fileDescriptor.StreamContents); + index++; + } + } + + /// <summary> + /// Gets or sets the CFSTR_PASTESUCCEEDED value for the object. + /// </summary> + public DragDropEffects? PasteSucceeded + { + get { return GetDropEffect(PASTESUCCEEDED); } + set { SetData(PASTESUCCEEDED, BitConverter.GetBytes((UInt32)value)); } + } + + /// <summary> + /// Gets or sets the CFSTR_PERFORMEDDROPEFFECT value for the object. + /// </summary> + public DragDropEffects? PerformedDropEffect + { + get { return GetDropEffect(PERFORMEDDROPEFFECT); } + set { SetData(PERFORMEDDROPEFFECT, BitConverter.GetBytes((UInt32)value)); } + } + + /// <summary> + /// Gets or sets the CFSTR_PREFERREDDROPEFFECT value for the object. + /// </summary> + public DragDropEffects? PreferredDropEffect + { + get { return GetDropEffect(PREFERREDDROPEFFECT); } + set { SetData(PREFERREDDROPEFFECT, BitConverter.GetBytes((UInt32)value)); } + } + + /// <summary> + /// Gets the DragDropEffects value (if any) previously set on the object. + /// </summary> + /// <param name="format">Clipboard format.</param> + /// <returns>DragDropEffects value or null.</returns> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")] + private DragDropEffects? GetDropEffect(short format) + { + // Get the most recent setting + var dataObject = _dataObjects + .Where(d => + (format == d.FORMATETC.cfFormat) && + (DVASPECT.DVASPECT_CONTENT == d.FORMATETC.dwAspect) && + (TYMED.TYMED_HGLOBAL == d.FORMATETC.tymed)) + .LastOrDefault(); + if (null != dataObject) + { + // Read the value and return it + var result = dataObject.GetData(); + if (NativeMethods.SUCCEEDED(result.Item2)) + { + var ptr = NativeMethods.GlobalLock(result.Item1); + if (IntPtr.Zero != ptr) + { + try + { + var length = NativeMethods.GlobalSize(ptr).ToInt32(); + if (4 == length) + { + var data = new byte[length]; + Marshal.Copy(ptr, data, 0, length); + return (DragDropEffects)(BitConverter.ToUInt32(data, 0)); + } + } + finally + { + NativeMethods.GlobalUnlock(result.Item1); + } + } + } + } + return null; + } + + #region IAsyncOperation Members + // Explicit interface implementation hides the technical details from users of VirtualFileDataObject. + + /// <summary> + /// Called by a drop source to specify whether the data object supports asynchronous data extraction. + /// </summary> + /// <param name="fDoOpAsync">A Boolean value that is set to VARIANT_TRUE to indicate that an asynchronous operation is supported, or VARIANT_FALSE otherwise.</param> + void IAsyncOperation.SetAsyncMode(int fDoOpAsync) + { + IsAsynchronous = !(NativeMethods.VARIANT_FALSE == fDoOpAsync); + } + + /// <summary> + /// Called by a drop target to determine whether the data object supports asynchronous data extraction. + /// </summary> + /// <param name="pfIsOpAsync">A Boolean value that is set to VARIANT_TRUE to indicate that an asynchronous operation is supported, or VARIANT_FALSE otherwise.</param> + void IAsyncOperation.GetAsyncMode(out int pfIsOpAsync) + { + pfIsOpAsync = IsAsynchronous ? NativeMethods.VARIANT_TRUE : NativeMethods.VARIANT_FALSE; + } + + /// <summary> + /// Called by a drop target to indicate that asynchronous data extraction is starting. + /// </summary> + /// <param name="pbcReserved">Reserved. Set this value to NULL.</param> + void IAsyncOperation.StartOperation(IBindCtx pbcReserved) + { + _inOperation = true; + if (null != _startAction) + { + _startAction(this); + } + } + + /// <summary> + /// Called by the drop source to determine whether the target is extracting data asynchronously. + /// </summary> + /// <param name="pfInAsyncOp">Set to VARIANT_TRUE if data extraction is being handled asynchronously, or VARIANT_FALSE otherwise.</param> + void IAsyncOperation.InOperation(out int pfInAsyncOp) + { + pfInAsyncOp = _inOperation ? NativeMethods.VARIANT_TRUE : NativeMethods.VARIANT_FALSE; + } + + /// <summary> + /// Notifies the data object that that asynchronous data extraction has ended. + /// </summary> + /// <param name="hResult">An HRESULT value that indicates the outcome of the data extraction. Set to S_OK if successful, or a COM error code otherwise.</param> + /// <param name="pbcReserved">Reserved. Set to NULL.</param> + /// <param name="dwEffects">A DROPEFFECT value that indicates the result of an optimized move. This should be the same value that would be passed to the data object as a CFSTR_PERFORMEDDROPEFFECT format with a normal data extraction operation.</param> + void IAsyncOperation.EndOperation(int hResult, IBindCtx pbcReserved, uint dwEffects) + { + if (null != _endAction) + { + _endAction(this); + } + _inOperation = false; + } + + #endregion + + /// <summary> + /// Returns the in-memory representation of an interop structure. + /// </summary> + /// <param name="source">Structure to return.</param> + /// <returns>In-memory representation of structure.</returns> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method doesn't decrease security.")] + private static IEnumerable<byte> StructureBytes(object source) + { + // Set up for call to StructureToPtr + var size = Marshal.SizeOf(source.GetType()); + var ptr = Marshal.AllocHGlobal(size); + var bytes = new byte[size]; + try + { + Marshal.StructureToPtr(source, ptr, false); + // Copy marshalled bytes to buffer + Marshal.Copy(ptr, bytes, 0, size); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + return bytes; + } + + /// <summary> + /// Class representing a virtual file for use by drag/drop or the clipboard. + /// </summary> + [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "Deliberate to provide obvious coupling.")] + public class FileDescriptor + { + /// <summary> + /// Gets or sets the name of the file. + /// </summary> + public string Name { get; set; } + + /// <summary> + /// Gets or sets the (optional) length of the file. + /// </summary> + public Int64? Length { get; set; } + + /// <summary> + /// Gets or sets the (optional) change time of the file. + /// </summary> + public DateTime? ChangeTimeUtc { get; set; } + + /// <summary> + /// Gets or sets an Action that returns the contents of the file. + /// </summary> + public Action<Stream> StreamContents { get; set; } + } + + /// <summary> + /// Class representing the result of a SetData call. + /// </summary> + private class DataObject + { + /// <summary> + /// FORMATETC structure for the data. + /// </summary> + public FORMATETC FORMATETC { get; set; } + + /// <summary> + /// Func returning the data as an IntPtr and an HRESULT success code. + /// </summary> + public Func<Tuple<IntPtr, int>> GetData { get; set; } + } + + /// <summary> + /// Represents a 2-tuple, or pair. + /// </summary> + /// <remarks> + /// Minimal implementation of the .NET 4 Tuple class; remove if running on .NET 4. + /// </remarks> + /// <typeparam name="T1">The type of the tuple's first component.</typeparam> + /// <typeparam name="T2">The type of the tuple's second component.</typeparam> + private class Tuple<T1, T2> + { + /// <summary> + /// Gets the value of the current Tuple(T1, T2) object's first component. + /// </summary> + public T1 Item1 { get; private set; } + + /// <summary> + /// Gets the value of the current Tuple(T1, T2) object's second component. + /// </summary> + public T2 Item2 { get; private set; } + + /// <summary> + /// Initializes a new instance of the Tuple(T1, T2) class. + /// </summary> + /// <param name="item1">The value of the tuple's first component.</param> + /// <param name="item2">The value of the tuple's second component.</param> + public Tuple(T1 item1, T2 item2) + { + Item1 = item1; + Item2 = item2; + } + } + + /// <summary> + /// Simple class that exposes a write-only IStream as a Stream. + /// </summary> + private class IStreamWrapper : Stream + { + /// <summary> + /// IStream instance being wrapped. + /// </summary> + private IStream _iStream; + + /// <summary> + /// Initializes a new instance of the IStreamWrapper class. + /// </summary> + /// <param name="iStream">IStream instance to wrap.</param> + public IStreamWrapper(IStream iStream) + { + _iStream = iStream; + } + + /// <summary> + /// Gets a value indicating whether the current stream supports reading. + /// </summary> + public override bool CanRead + { + get { return false; } + } + + /// <summary> + /// Gets a value indicating whether the current stream supports seeking. + /// </summary> + public override bool CanSeek + { + get { return false; } + } + + /// <summary> + /// Gets a value indicating whether the current stream supports writing. + /// </summary> + public override bool CanWrite + { + get { return true; } + } + + /// <summary> + /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. + /// </summary> + public override void Flush() + { + throw new NotImplementedException(); + } + + /// <summary> + /// Gets the length in bytes of the stream. + /// </summary> + public override long Length + { + get { throw new NotImplementedException(); } + } + + /// <summary> + /// Gets or sets the position within the current stream. + /// </summary> + public override long Position + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + /// <summary> + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// </summary> + /// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source.</param> + /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param> + /// <param name="count">The maximum number of bytes to be read from the current stream.</param> + /// <returns>The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.</returns> + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotImplementedException(); + } + + /// <summary> + /// Sets the position within the current stream. + /// </summary> + /// <param name="offset">A byte offset relative to the origin parameter.</param> + /// <param name="origin">A value of type SeekOrigin indicating the reference point used to obtain the new position.</param> + /// <returns>The new position within the current stream.</returns> + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotImplementedException(); + } + + /// <summary> + /// Sets the length of the current stream. + /// </summary> + /// <param name="value">The desired length of the current stream in bytes.</param> + public override void SetLength(long value) + { + throw new NotImplementedException(); + } + + /// <summary> + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// </summary> + /// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param> + /// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param> + /// <param name="count">The number of bytes to be written to the current stream.</param> + public override void Write(byte[] buffer, int offset, int count) + { + if (offset == 0) + { + // Optimize common case to avoid creating extra buffers + _iStream.Write(buffer, count, IntPtr.Zero); + } + else + { + // Easy way to provide the relevant byte[] + _iStream.Write(buffer.Skip(offset).ToArray(), count, IntPtr.Zero); + } + } + } + + /// <summary> + /// Initiates a drag-and-drop operation. + /// </summary> + /// <param name="dragSource">A reference to the dependency object that is the source of the data being dragged.</param> + /// <param name="dataObject">A data object that contains the data being dragged.</param> + /// <param name="allowedEffects">One of the DragDropEffects values that specifies permitted effects of the drag-and-drop operation.</param> + /// <returns>One of the DragDropEffects values that specifies the final effect that was performed during the drag-and-drop operation.</returns> + /// <remarks> + /// Call this method instead of System.Windows.DragDrop.DoDragDrop because this method handles IDataObject better. + /// </remarks> + [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "dragSource", Justification = "Parameter is present so the signature matches that of System.Windows.DragDrop.DoDragDrop.")] + public static DragDropEffects DoDragDrop(DependencyObject dragSource, System.Runtime.InteropServices.ComTypes.IDataObject dataObject, DragDropEffects allowedEffects) + { + int[] finalEffect = new int[1]; + try + { + NativeMethods.DoDragDrop(dataObject, new DropSource(), (int)allowedEffects, finalEffect); + } + finally + { + var virtualFileDataObject = dataObject as VirtualFileDataObject; + if ((null != virtualFileDataObject) && !virtualFileDataObject.IsAsynchronous && virtualFileDataObject._inOperation) + { + // Call the end action and exit the operation + if (null != virtualFileDataObject._endAction) + { + virtualFileDataObject._endAction(virtualFileDataObject); + } + virtualFileDataObject._inOperation = false; + } + } + return (DragDropEffects)(finalEffect[0]); + } + + /// <summary> + /// Contains the methods for generating visual feedback to the end user and for canceling or completing the drag-and-drop operation. + /// </summary> + private class DropSource : NativeMethods.IDropSource + { + /// <summary> + /// Determines whether a drag-and-drop operation should continue. + /// </summary> + /// <param name="fEscapePressed">Indicates whether the Esc key has been pressed since the previous call to QueryContinueDrag or to DoDragDrop if this is the first call to QueryContinueDrag. A TRUE value indicates the end user has pressed the escape key; a FALSE value indicates it has not been pressed.</param> + /// <param name="grfKeyState">The current state of the keyboard modifier keys on the keyboard. Possible values can be a combination of any of the flags MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON, MK_MBUTTON, and MK_RBUTTON.</param> + /// <returns>This method returns S_OK/DRAGDROP_S_DROP/DRAGDROP_S_CANCEL on success.</returns> + public int QueryContinueDrag(int fEscapePressed, uint grfKeyState) + { + var escapePressed = (0 != fEscapePressed); + var keyStates = (DragDropKeyStates)grfKeyState; + if (escapePressed) + { + return NativeMethods.DRAGDROP_S_CANCEL; + } + else if (DragDropKeyStates.None == (keyStates & DragDropKeyStates.LeftMouseButton)) + { + return NativeMethods.DRAGDROP_S_DROP; + } + return NativeMethods.S_OK; + } + + /// <summary> + /// Gives visual feedback to an end user during a drag-and-drop operation. + /// </summary> + /// <param name="dwEffect">The DROPEFFECT value returned by the most recent call to IDropTarget::DragEnter, IDropTarget::DragOver, or IDropTarget::DragLeave. </param> + /// <returns>This method returns S_OK on success.</returns> + public int GiveFeedback(uint dwEffect) + { + return NativeMethods.DRAGDROP_S_USEDEFAULTCURSORS; + } + } + + /// <summary> + /// Provides access to Win32-level constants, structures, and functions. + /// </summary> + private static class NativeMethods + { + public const int DRAGDROP_S_DROP = 0x00040100; + public const int DRAGDROP_S_CANCEL = 0x00040101; + public const int DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102; + public const int DV_E_DVASPECT = -2147221397; + public const int DV_E_FORMATETC = -2147221404; + public const int DV_E_TYMED = -2147221399; + public const int E_FAIL = -2147467259; + public const uint FD_CREATETIME = 0x00000008; + public const uint FD_WRITESTIME = 0x00000020; + public const uint FD_FILESIZE = 0x00000040; + public const int OLE_E_ADVISENOTSUPPORTED = -2147221501; + public const int S_OK = 0; + public const int S_FALSE = 1; + public const int VARIANT_FALSE = 0; + public const int VARIANT_TRUE = -1; + + public const string CFSTR_FILECONTENTS = "FileContents"; + public const string CFSTR_FILEDESCRIPTORW = "FileGroupDescriptorW"; + public const string CFSTR_PASTESUCCEEDED = "Paste Succeeded"; + public const string CFSTR_PERFORMEDDROPEFFECT = "Performed DropEffect"; + public const string CFSTR_PREFERREDDROPEFFECT = "Preferred DropEffect"; + + [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "Structure exists for interop.")] + [StructLayout(LayoutKind.Sequential)] + public struct FILEGROUPDESCRIPTOR + { + public UInt32 cItems; + // Followed by 0 or more FILEDESCRIPTORs + } + + [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "Structure exists for interop.")] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct FILEDESCRIPTOR + { + public UInt32 dwFlags; + public Guid clsid; + public Int32 sizelcx; + public Int32 sizelcy; + public Int32 pointlx; + public Int32 pointly; + public UInt32 dwFileAttributes; + public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime; + public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime; + public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime; + public UInt32 nFileSizeHigh; + public UInt32 nFileSizeLow; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string cFileName; + } + + [ComImport] + [Guid("00000121-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IDropSource + { + [PreserveSig] + int QueryContinueDrag(int fEscapePressed, uint grfKeyState); + [PreserveSig] + int GiveFeedback(uint dwEffect); + } + + [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "Win32 API.")] + [DllImport("shell32.dll")] + public static extern int SHCreateStdEnumFmtEtc(uint cfmt, FORMATETC[] afmt, out IEnumFORMATETC ppenumFormatEtc); + + [return: MarshalAs(UnmanagedType.Interface)] + [DllImport("ole32.dll", PreserveSig = false)] + public static extern IStream CreateStreamOnHGlobal(IntPtr hGlobal, [MarshalAs(UnmanagedType.Bool)] bool fDeleteOnRelease); + + [DllImport("ole32.dll", CharSet = CharSet.Auto, ExactSpelling = true, PreserveSig = false)] + public static extern void DoDragDrop(System.Runtime.InteropServices.ComTypes.IDataObject dataObject, IDropSource dropSource, int allowedEffects, int[] finalEffect); + + [DllImport("kernel32.dll")] + public static extern IntPtr GlobalLock(IntPtr hMem); + + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll")] + public static extern bool GlobalUnlock(IntPtr hMem); + + [DllImport("kernel32.dll")] + public static extern IntPtr GlobalSize(IntPtr handle); + + /// <summary> + /// Returns true iff the HRESULT is a success code. + /// </summary> + /// <param name="hr">HRESULT to check.</param> + /// <returns>True iff a success code.</returns> + public static bool SUCCEEDED(int hr) + { + return (0 <= hr); + } + } + } + + /// <summary> + /// Definition of the IAsyncOperation COM interface. + /// </summary> + /// <remarks> + /// Pseudo-public because VirtualFileDataObject implements it. + /// </remarks> + [ComImport] + [Guid("3D8B0590-F691-11d2-8EA9-006097DF5BD4")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IAsyncOperation + { + void SetAsyncMode([In] Int32 fDoOpAsync); + void GetAsyncMode([Out] out Int32 pfIsOpAsync); + void StartOperation([In] IBindCtx pbcReserved); + void InOperation([Out] out Int32 pfInAsyncOp); + void EndOperation([In] Int32 hResult, [In] IBindCtx pbcReserved, [In] UInt32 dwEffects); + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeTcpClient.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeTcpClient.cs index 5b59429d7..fbfa6b0ca 100644 --- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeTcpClient.cs +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeTcpClient.cs @@ -31,6 +31,8 @@ namespace Tango.Integration.ExternalBridge { private bool _logs_sent; + public event EventHandler<LogItemBase> ApplicationLogAvailable; + #region Properties private String _serialNumber; @@ -72,6 +74,8 @@ namespace Tango.Integration.ExternalBridge } } + public bool InjectApplicationLogsToDefaultLogManager { get; set; } = true; + /// <summary> /// Gets a value indicating whether this client requires authentication. /// </summary> @@ -205,7 +209,13 @@ namespace Tango.Integration.ExternalBridge { LogItemBase log = LogItemBase.Deserialize(response.Message.LogItem.ToArray()); log.LogObject = "External Bridge"; - LogManager.Log(log); + + if (InjectApplicationLogsToDefaultLogManager) + { + LogManager.Log(log); + } + + ApplicationLogAvailable?.Invoke(this, log); } } catch (Exception ex) diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/GetMachineInformationRequest.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/GetMachineInformationRequest.cs new file mode 100644 index 000000000..38c06b024 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/GetMachineInformationRequest.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.ExternalBridge.Network.Information +{ + public class GetMachineInformationRequest + { + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/GetMachineInformationResponse.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/GetMachineInformationResponse.cs new file mode 100644 index 000000000..5ae1aa440 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/GetMachineInformationResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.ExternalBridge.Network.Information +{ + public class GetMachineInformationResponse + { + public InformationPackage Package { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/InformationPackage.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/InformationPackage.cs new file mode 100644 index 000000000..afa23492e --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Information/InformationPackage.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.SystemInfo; + +namespace Tango.Integration.ExternalBridge.Network.Information +{ + public class InformationPackage + { + public List<SystemObjectsCollection> System { get; set; } + + public InformationPackage() + { + System = new List<SystemObjectsCollection>(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/PerformancePackage.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/PerformancePackage.cs new file mode 100644 index 000000000..56921e0c5 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/PerformancePackage.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.ExternalBridge.Network.Performance +{ + public class PerformancePackage + { + public int CPU { get; set; } + public int ApplicationCPU { get; set; } + + public int RAM { get; set; } + public int ApplicationRAM { get; set; } + public int MaxRAM { get; set; } + + public int Temperature { get; set; } + + public int AvailableDiskSpace { get; set; } + public int DiskCapacity { get; set; } + + public DateTime DateTime { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/StartPerformanceUpdatesRequest.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/StartPerformanceUpdatesRequest.cs new file mode 100644 index 000000000..2c036e937 --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/StartPerformanceUpdatesRequest.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.ExternalBridge.Network.Performance +{ + public class StartPerformanceUpdatesRequest + { + } +} diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/StartPerformanceUpdatesResponse.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/StartPerformanceUpdatesResponse.cs new file mode 100644 index 000000000..8eb22bdef --- /dev/null +++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/Network/Performance/StartPerformanceUpdatesResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Integration.ExternalBridge.Network.Performance +{ + public class StartPerformanceUpdatesResponse + { + public PerformancePackage Package { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs b/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs index f2fb2f16e..0fadd1baa 100644 --- a/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs +++ b/Software/Visual_Studio/Tango.Integration/JobRuns/BasicJobRunsLogger.cs @@ -17,7 +17,6 @@ namespace Tango.Integration.JobRuns /// <seealso cref="Tango.Integration.JobRuns.IJobRunsLogger" /> public class BasicJobRunsLogger : ExtendedObject, IJobRunsLogger { - private DateTime _start_date; private Job _job; #region Properties @@ -96,7 +95,7 @@ namespace Tango.Integration.JobRuns JobRun run = new JobRun(); run.UserGuid = _job.UserGuid; - run.StartDate = _start_date; + run.StartDate = e.StartDate; run.UploadingStartDate = e.UploadingStartTime; run.HeatingStartDate = e.HeatingStartTime; run.ActualStartDate = e.ActualStartTime; @@ -187,7 +186,6 @@ namespace Tango.Integration.JobRuns private void Machine_PrintingStarted(object sender, PrintingEventArgs e) { _job = e.Job; - _start_date = DateTime.UtcNow; } #endregion diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index 9768498c6..b17321942 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -75,6 +75,8 @@ namespace Tango.Integration.Operation private List<BL.ValueObjects.JobRunLiquidQuantity> _currentJobLiquidQuantities; private DateTime _diagnosticsTime; private MachineStatus _machineStatusBeforeJobStart; + + private DateTime _jobStartDate; private DateTime? _jobUploadingStartDate; private DateTime? _jobHeatingStartDate; private DateTime? _jobActualStartDate; @@ -1050,6 +1052,7 @@ namespace Tango.Integration.Operation PrintingStarted?.Invoke(this, new PrintingEventArgs(handler, job) { LiquidQuantities = _currentJobLiquidQuantities.ToList(), + StartDate = _jobStartDate, }); } @@ -1063,6 +1066,7 @@ namespace Tango.Integration.Operation PrintingCompleted?.Invoke(this, new PrintingEventArgs(handler, job) { LiquidQuantities = _currentJobLiquidQuantities.ToList(), + StartDate = _jobStartDate, UploadingStartTime = _jobUploadingStartDate, HeatingStartTime = _jobHeatingStartDate, ActualStartTime = _jobActualStartDate, @@ -1082,6 +1086,7 @@ namespace Tango.Integration.Operation PrintingFailed?.Invoke(this, new PrintingFailedEventArgs(handler, job, exception) { LiquidQuantities = _currentJobLiquidQuantities.ToList(), + StartDate = _jobStartDate, UploadingStartTime = _jobUploadingStartDate, HeatingStartTime = _jobHeatingStartDate, ActualStartTime = _jobActualStartDate, @@ -1099,6 +1104,7 @@ namespace Tango.Integration.Operation PrintingAborted?.Invoke(this, new PrintingEventArgs(handler, job) { LiquidQuantities = _currentJobLiquidQuantities.ToList(), + StartDate = _jobStartDate, UploadingStartTime = _jobUploadingStartDate, HeatingStartTime = _jobHeatingStartDate, ActualStartTime = _jobActualStartDate, @@ -1116,6 +1122,7 @@ namespace Tango.Integration.Operation PrintingEnded?.Invoke(this, new PrintingEventArgs(handler, job) { LiquidQuantities = _currentJobLiquidQuantities.ToList(), + StartDate = _jobStartDate, UploadingStartTime = _jobUploadingStartDate, HeatingStartTime = _jobHeatingStartDate, ActualStartTime = _jobActualStartDate, @@ -2159,6 +2166,8 @@ namespace Tango.Integration.Operation throw new InvalidOperationException("Could not print while status = " + Status); } + _jobStartDate = DateTime.UtcNow; + LogManager.Log($"Executing job '{job.Name}'..."); _currentJobLiquidQuantities = new List<BL.ValueObjects.JobRunLiquidQuantity>(); diff --git a/Software/Visual_Studio/Tango.Integration/Operation/PrintingEventArgs.cs b/Software/Visual_Studio/Tango.Integration/Operation/PrintingEventArgs.cs index f68204127..b088b9046 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/PrintingEventArgs.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/PrintingEventArgs.cs @@ -13,6 +13,7 @@ namespace Tango.Integration.Operation public JobHandler JobHandler { get; private set; } public Job Job { get; private set; } public List<JobRunLiquidQuantity> LiquidQuantities { get; set; } + public DateTime StartDate { get; set; } public DateTime? UploadingStartTime { get; set; } public DateTime? HeatingStartTime { get; set; } public DateTime? ActualStartTime { get; set; } diff --git a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj index 04b2903ce..1356c115c 100644 --- a/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj +++ b/Software/Visual_Studio/Tango.Integration/Tango.Integration.csproj @@ -106,6 +106,12 @@ <Compile Include="ExternalBridge\IExternalBridgeRequestHandler.cs" /> <Compile Include="ExternalBridge\ExternalBridgeSignalRConfiguration.cs" /> <Compile Include="ExternalBridge\ExternalBridgeSignalRClient.cs" /> + <Compile Include="ExternalBridge\Network\Information\GetMachineInformationRequest.cs" /> + <Compile Include="ExternalBridge\Network\Information\GetMachineInformationResponse.cs" /> + <Compile Include="ExternalBridge\Network\Information\InformationPackage.cs" /> + <Compile Include="ExternalBridge\Network\Performance\PerformancePackage.cs" /> + <Compile Include="ExternalBridge\Network\Performance\StartPerformanceUpdatesRequest.cs" /> + <Compile Include="ExternalBridge\Network\Performance\StartPerformanceUpdatesResponse.cs" /> <Compile Include="ExternalBridge\Web\MachineInfo.cs" /> <Compile Include="IntegrationSettings.cs" /> <Compile Include="JobRuns\BasicJobRunsLogger.cs" /> @@ -198,6 +204,10 @@ <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project> <Name>Tango.Settings</Name> </ProjectReference> + <ProjectReference Include="..\Tango.SystemInfo\Tango.SystemInfo.csproj"> + <Project>{997a961c-beda-4b56-aa0f-c39e532f7ffa}</Project> + <Name>Tango.SystemInfo</Name> + </ProjectReference> <ProjectReference Include="..\Tango.Transport\Tango.Transport.csproj"> <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> <Name>Tango.Transport</Name> diff --git a/Software/Visual_Studio/Tango.SharedUI/Binding/BindingEventArgs.cs b/Software/Visual_Studio/Tango.SharedUI/Binding/BindingEventArgs.cs new file mode 100644 index 000000000..06ea61019 --- /dev/null +++ b/Software/Visual_Studio/Tango.SharedUI/Binding/BindingEventArgs.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media; + +namespace Tango.SharedUI +{ + /// <summary> + /// Represents the <see cref="BindingEventContainer.ValueChanged"/> event arguments. + /// </summary> + /// <seealso cref="System.EventArgs" /> + public class BindingEventArgs : EventArgs + { + internal Action _renewAction; + + /// <summary> + /// Gets or sets the element. + /// </summary> + public DependencyObject DependencyObject { get; set; } + + /// <summary> + /// Gets or sets the binding property. + /// </summary> + public BindingProperty BindingProperty { get; set; } + + /// <summary> + /// Gets or sets the value. + /// </summary> + public Object Value { get; set; } + + public void Renew() + { + _renewAction?.Invoke(); + } + } +} diff --git a/Software/Visual_Studio/Tango.SharedUI/Binding/BindingEventContainer.cs b/Software/Visual_Studio/Tango.SharedUI/Binding/BindingEventContainer.cs new file mode 100644 index 000000000..a74a9b085 --- /dev/null +++ b/Software/Visual_Studio/Tango.SharedUI/Binding/BindingEventContainer.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; +using System.Windows.Media; + +namespace Tango.SharedUI +{ + /// <summary> + /// Represents a binding event container. + /// </summary> + /// <seealso cref="System.Windows.DependencyObject" /> + public class BindingEventContainer : DependencyObject + { + private Action _renewAction; + + /// <summary> + /// Occurs when the dependency property value has changed. + /// </summary> + public event EventHandler<BindingEventArgs> ValueChanged; + + /// <summary> + /// Gets or sets the value. + /// </summary> + public Object Value + { + get { return (Object)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + public static readonly DependencyProperty ValueProperty = + DependencyProperty.Register("Value", typeof(Object), typeof(BindingEventContainer), new PropertyMetadata(null, (d, e) => (d as BindingEventContainer).OnValueChanged())); + + /// <summary> + /// Gets or sets the binding property. + /// </summary> + public BindingProperty BindingProperty { get; set; } + + /// <summary> + /// Gets or sets the dependency object. + /// </summary> + public DependencyObject DependencyObject { get; set; } + + /// <summary> + /// Initializes a new instance of the <see cref="BindingEventContainer"/> class. + /// </summary> + /// <param name="takeElement">The dependency object.</param> + /// <param name="bindingProperty">The binding property.</param> + public BindingEventContainer(DependencyObject dependencyObject, BindingProperty bindingProperty) + { + DependencyObject = dependencyObject; + BindingProperty = bindingProperty; + } + + /// <summary> + /// Called when the value has been changed + /// </summary> + protected virtual void OnValueChanged() + { + ValueChanged?.Invoke(this, new BindingEventArgs() + { + BindingProperty = BindingProperty, + DependencyObject = DependencyObject, + Value = Value, + _renewAction = _renewAction + }); + } + + /// <summary> + /// Generates a new <see cref="BindingEventContainer"/> for the specified Take element and binding property. + /// </summary> + /// <param name="dependencyObject">The take element.</param> + /// <param name="dependencyProperty">The binding property.</param> + /// <returns></returns> + public static BindingEventContainer Generate(DependencyObject dependencyObject, DependencyProperty dependencyProperty) + { + BindingEventContainer container = new BindingEventContainer(dependencyObject, new BindingProperty(dependencyProperty)); + + container._renewAction = () => + { + Binding binding = new Binding(); + binding.Mode = BindingMode.OneWay; + binding.Source = dependencyObject; + binding.Path = new PropertyPath(dependencyProperty); + BindingOperations.SetBinding(container, BindingEventContainer.ValueProperty, binding); + }; + + container._renewAction.Invoke(); + + return container; + } + } +} diff --git a/Software/Visual_Studio/Tango.SharedUI/Binding/BindingProperty.cs b/Software/Visual_Studio/Tango.SharedUI/Binding/BindingProperty.cs new file mode 100644 index 000000000..79d4f1c71 --- /dev/null +++ b/Software/Visual_Studio/Tango.SharedUI/Binding/BindingProperty.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace Tango.SharedUI +{ + /// <summary> + /// Represents a binding property. + /// </summary> + public class BindingProperty + { + /// <summary> + /// Gets or sets the dependency property. + /// </summary> + public DependencyProperty DependencyProperty { get; set; } + + /// <summary> + /// Initializes a new instance of the <see cref="BindingProperty"/> class. + /// </summary> + public BindingProperty() + { + + } + + /// <summary> + /// Initializes a new instance of the <see cref="BindingProperty"/> class. + /// </summary> + /// <param name="dp">The dependency property.</param> + /// <param name="mode">The mode.</param> + public BindingProperty(DependencyProperty dp) : this() + { + DependencyProperty = dp; + } + } +} diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs index 15d15decb..ce1fca7ac 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs +++ b/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs @@ -22,7 +22,9 @@ namespace Tango.SharedUI.Controls public class NavigationControl : UserControl { private event Action NavigationCompleted; + public event EventHandler<FrameworkElement> SelectedElementChanged; private Thread _navigationThread; + private bool _preventSelectedObjectNavigation; private ProducerConsumerQueue<NavigationQueueItem> _navigationQueue; private class NavigationQueueItem @@ -191,14 +193,12 @@ namespace Tango.SharedUI.Controls get { return (object)GetValue(SelectedObjectProperty); } set { SetValue(SelectedObjectProperty, value); } } - - // Using a DependencyProperty as the backing store for SelectedObject. This enables animation, styling, binding, etc... public static readonly DependencyProperty SelectedObjectProperty = - DependencyProperty.Register("SelectedObject", typeof(object), typeof(NavigationControl), new PropertyMetadata(null, (d, e) => (d as NavigationControl).OnSelectedObjectChanged())); + DependencyProperty.Register("SelectedObject", typeof(object), typeof(NavigationControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (d, e) => (d as NavigationControl).OnSelectedObjectChanged())); private void OnSelectedObjectChanged() { - if (SelectedObject != null) + if (SelectedObject != null && !_preventSelectedObjectNavigation) { NavigateTo(SelectedObject); } @@ -218,7 +218,7 @@ namespace Tango.SharedUI.Controls set { SetValue(SelectedElementProperty, value); } } public static readonly DependencyProperty SelectedElementProperty = - DependencyProperty.Register("SelectedElement", typeof(FrameworkElement), typeof(NavigationControl), new PropertyMetadata(null, (d, e) => (d as NavigationControl).OnSelectedElementChanged(e.OldValue as FrameworkElement, e.NewValue as FrameworkElement))); + DependencyProperty.Register("SelectedElement", typeof(FrameworkElement), typeof(NavigationControl), new FrameworkPropertyMetadata(null, (d, e) => (d as NavigationControl).OnSelectedElementChanged(e.OldValue as FrameworkElement, e.NewValue as FrameworkElement))); public TransitionTypes TransitionType { @@ -310,7 +310,9 @@ namespace Tango.SharedUI.Controls /// <returns></returns> public static String GetNavigationName(FrameworkElement element) { - return element.GetValue(NavigationName).ToStringSafe(); + var name = element.GetValue(NavigationName).ToStringSafe(); + if (String.IsNullOrEmpty(name)) name = element.GetType().Name; + return name; } #endregion @@ -383,6 +385,8 @@ namespace Tango.SharedUI.Controls } else { + Elements.ToList().ForEach(x => x.FocusVisualStyle = null); + var toRemove = _grid.Children.OfType<NavigationElement>().ToList().Where(x => !Elements.Contains(x.Element)).ToList(); var toAdd = Elements.Where(x => !_grid.Children.OfType<NavigationElement>().Select(y => y.Element).ToList().Contains(x)).ToList(); @@ -622,6 +626,14 @@ namespace Tango.SharedUI.Controls protected virtual void OnSelectedElementChanged(FrameworkElement fromElement, FrameworkElement toElement) { Navigate(GetElementContainer(fromElement), GetElementContainer(toElement)); + SelectedElementChanged?.Invoke(this, toElement); + + if (toElement != null) + { + _preventSelectedObjectNavigation = true; + SelectedObject = GetNavigationName(toElement); + _preventSelectedObjectNavigation = false; + } } #endregion @@ -696,7 +708,7 @@ namespace Tango.SharedUI.Controls FrameworkElement view = null; - view = NavigateTo(navigationName, () => + view = NavigateTo(navigationName, () => { source.SetResult(view); }); diff --git a/Software/Visual_Studio/Tango.SharedUI/Converters/ByteArrayToFileSizeConverter.cs b/Software/Visual_Studio/Tango.SharedUI/Converters/ByteArrayToFileSizeConverter.cs index 5a2975535..d26ea5a0a 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Converters/ByteArrayToFileSizeConverter.cs +++ b/Software/Visual_Studio/Tango.SharedUI/Converters/ByteArrayToFileSizeConverter.cs @@ -39,7 +39,7 @@ namespace Tango.SharedUI.Converters long bytes = Math.Abs(byteCount); int place = System.Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024))); double num = Math.Round(bytes / Math.Pow(1024, place), 1); - return (Math.Sign(byteCount) * num).ToString() + suf[place]; + return (Math.Sign(byteCount) * num).ToString() + " " + suf[place]; } } } diff --git a/Software/Visual_Studio/Tango.SharedUI/Converters/DateTimeUtcToLocalDateTime.cs b/Software/Visual_Studio/Tango.SharedUI/Converters/DateTimeUtcToLocalDateTime.cs new file mode 100644 index 000000000..7ce4a6532 --- /dev/null +++ b/Software/Visual_Studio/Tango.SharedUI/Converters/DateTimeUtcToLocalDateTime.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace Tango.SharedUI.Converters +{ + public class DateTimeUtcToLocalDateTime : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + try + { + return ((DateTime)value).ToLocalTime(); + } + catch + { + return value; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/Tango.SharedUI/Converters/StringToTitleCaseConverter.cs b/Software/Visual_Studio/Tango.SharedUI/Converters/StringToTitleCaseConverter.cs new file mode 100644 index 000000000..6bafd1fd0 --- /dev/null +++ b/Software/Visual_Studio/Tango.SharedUI/Converters/StringToTitleCaseConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace Tango.SharedUI.Converters +{ + public class StringToTitleCaseConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value != null) + { + return value.ToString().ToTitleCase(); + } + else + { + return value; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj b/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj index 2170b6d58..4764d0eac 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj +++ b/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj @@ -64,6 +64,9 @@ <Compile Include="..\Versioning\GlobalVersionInfo.cs"> <Link>GlobalVersionInfo.cs</Link> </Compile> + <Compile Include="Binding\BindingEventArgs.cs" /> + <Compile Include="Binding\BindingEventContainer.cs" /> + <Compile Include="Binding\BindingProperty.cs" /> <Compile Include="Components\SelectedObject.cs" /> <Compile Include="Components\SelectedObjectCollection.cs" /> <Compile Include="Components\TextController.cs" /> @@ -96,6 +99,7 @@ <Compile Include="Converters\ColorComponentToOpacityConverter.cs" /> <Compile Include="Converters\ColorToComponentsConverter.cs" /> <Compile Include="Converters\ColorToIntegerConverter.cs" /> + <Compile Include="Converters\DateTimeUtcToLocalDateTime.cs" /> <Compile Include="Converters\DateTimeUTCToShortDateConverter.cs" /> <Compile Include="Converters\DateTimeUTCToShortDateTimeConverter.cs" /> <Compile Include="Converters\DateTimeUTCToStringConverter.cs" /> @@ -133,6 +137,7 @@ <Compile Include="Converters\StringNullOrEmptyToBooleanConverter.cs" /> <Compile Include="Converters\StringToLinesConverter.cs" /> <Compile Include="Converters\StringToOneLineConverter.cs" /> + <Compile Include="Converters\StringToTitleCaseConverter.cs" /> <Compile Include="Converters\StringToWordsConverter.cs" /> <Compile Include="Converters\TimeSpanToMinutesConverter.cs" /> <Compile Include="Converters\TimeSpanToSecondsConverter.cs" /> @@ -249,7 +254,7 @@ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <ProjectExtensions> <VisualStudio> - <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" /> + <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" /> </VisualStudio> </ProjectExtensions> </Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.SystemInfo/Connection.cs b/Software/Visual_Studio/Tango.SystemInfo/Connection.cs new file mode 100644 index 000000000..3e4e1e73d --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Connection.cs @@ -0,0 +1,83 @@ +using System; +using System.Management; +using System.Collections.Generic; +using System.Text; + +//Tango.SystemInfo +namespace Tango.SystemInfo +{ + class Connection + { + ManagementScope connectionScope; + ConnectionOptions options; + + #region "properties" + public ManagementScope GetConnectionScope + { + get { return connectionScope; } + } + public ConnectionOptions GetOptions + { + get { return options; } + } + #endregion + + #region "static helpers" + public static ConnectionOptions SetConnectionOptions() + { + ConnectionOptions options = new ConnectionOptions(); + options.Impersonation = ImpersonationLevel.Impersonate; + options.Authentication = AuthenticationLevel.Default; + options.EnablePrivileges = true; + return options; + } + + public static ManagementScope SetConnectionScope(string machineName, + ConnectionOptions options) + { + ManagementScope connectScope = new ManagementScope(); + connectScope.Path = new ManagementPath(@"\\" + machineName + @"\root\CIMV2"); + connectScope.Options = options; + + try + { + connectScope.Connect(); + } + catch (ManagementException e) + { + Console.WriteLine("An Error Occurred: " + e.Message.ToString()); + } + return connectScope; + } + #endregion + + #region "constructors" + public Connection() + { + EstablishConnection(null, null, null, Environment.MachineName); + } + + public Connection(string userName, + string password, + string domain, + string machineName) + { + EstablishConnection(userName, password, domain, machineName); + } + #endregion + + #region "private helpers" + private void EstablishConnection(string userName, string password, string domain, string machineName) + { + options = Connection.SetConnectionOptions(); + if (domain != null || userName != null) + { + options.Username = domain + "\\" + userName; + options.Password = password; + } + connectionScope = Connection.SetConnectionScope(machineName, options); + } + #endregion + + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/IWMI.cs b/Software/Visual_Studio/Tango.SystemInfo/IWMI.cs new file mode 100644 index 000000000..06252731f --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/IWMI.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + interface IWMI + { + IList<SystemObject> GetHardwareInfoList(); + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.SystemInfo/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..1ff929bce --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tango.SystemInfo")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tango.SystemInfo")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("997a961c-beda-4b56-aa0f-c39e532f7ffa")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Software/Visual_Studio/Tango.SystemInfo/SystemObject.cs b/Software/Visual_Studio/Tango.SystemInfo/SystemObject.cs new file mode 100644 index 000000000..be1c74fe5 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/SystemObject.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + public class SystemObject + { + public String Name { get; set; } + public List<SystemObjectProperty> Properties { get; set; } + + public SystemObject() + { + Properties = new List<SystemObjectProperty>(); + } + + public override string ToString() + { + String msg = String.Empty; + + msg = $"Name: {Name}\n"; + + foreach (var prop in Properties) + { + msg += $"{prop.Name}: {prop.Value}\n"; + } + + return msg; + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/SystemObjectProperty.cs b/Software/Visual_Studio/Tango.SystemInfo/SystemObjectProperty.cs new file mode 100644 index 000000000..c2d04e2a5 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/SystemObjectProperty.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + public class SystemObjectProperty + { + public String Name { get; set; } + public String Value { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/SystemObjectsCollection.cs b/Software/Visual_Studio/Tango.SystemInfo/SystemObjectsCollection.cs new file mode 100644 index 000000000..92937f561 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/SystemObjectsCollection.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.SystemInfo +{ + public class SystemObjectsCollection + { + public String Name { get; set; } + + public List<SystemObject> Objects { get; set; } + + public SystemObjectsCollection() + { + Objects = new List<SystemObject>(); + } + + public override string ToString() + { + String str = String.Empty; + + str += Name + "\n\n"; + + foreach (var obj in Objects) + { + str += obj.ToString(); + str += "\n"; + } + + str += "\n"; + + return str; + } + + public static List<SystemObjectsCollection> Create() + { + List<SystemObjectsCollection> list = new List<SystemObjectsCollection>(); + + Connection wmiConnection = new Connection(); + + SystemObjectsCollection os = new SystemObjectsCollection() { Name = "Operation System" }; + Win32_OperatingSystem osConnection = new Win32_OperatingSystem(wmiConnection); + os.Objects = osConnection.GetHardwareInfoList().ToList(); + list.Add(os); + + SystemObjectsCollection board = new SystemObjectsCollection() { Name = "Board" }; + Win32_BaseBoard boardConnection = new Win32_BaseBoard(wmiConnection); + board.Objects = boardConnection.GetHardwareInfoList().ToList(); + list.Add(board); + + SystemObjectsCollection bios = new SystemObjectsCollection() { Name = "BIOS" }; + Win32_BIOS biosConnection = new Win32_BIOS(wmiConnection); + bios.Objects = biosConnection.GetHardwareInfoList().ToList(); + list.Add(bios); + + SystemObjectsCollection processor = new SystemObjectsCollection() { Name = "Processor" }; + Win32_Processor processorConnection = new Win32_Processor(wmiConnection); + processor.Objects = processorConnection.GetHardwareInfoList().ToList(); + list.Add(processor); + + SystemObjectsCollection memory = new SystemObjectsCollection() { Name = "Memory" }; + Win32_PhysicalMemory memoryConnection = new Win32_PhysicalMemory(wmiConnection); + memory.Objects = memoryConnection.GetHardwareInfoList().ToList(); + list.Add(memory); + + SystemObjectsCollection video = new SystemObjectsCollection() { Name = "Video Controller" }; + Win32_VideoController videoConnection = new Win32_VideoController(wmiConnection); + video.Objects = videoConnection.GetHardwareInfoList().ToList(); + list.Add(video); + + SystemObjectsCollection disk = new SystemObjectsCollection() { Name = "Disk Drives" }; + Win32_DiskDrive diskConnection = new Win32_DiskDrive(wmiConnection); + disk.Objects = diskConnection.GetHardwareInfoList().ToList(); + list.Add(disk); + + SystemObjectsCollection network = new SystemObjectsCollection() { Name = "Network" }; + Win32_NetworkAdapter networkConnection = new Win32_NetworkAdapter(wmiConnection); + network.Objects = networkConnection.GetHardwareInfoList().ToList(); + list.Add(network); + + SystemObjectsCollection sound = new SystemObjectsCollection() { Name = "Sound" }; + Win32_SoundDevice soundConnection = new Win32_SoundDevice(wmiConnection); + sound.Objects = soundConnection.GetHardwareInfoList().ToList(); + list.Add(sound); + + SystemObjectsCollection serial = new SystemObjectsCollection() { Name = "Serial Ports" }; + Win32_SerialPort serialConnection = new Win32_SerialPort(wmiConnection); + serial.Objects = serialConnection.GetHardwareInfoList().ToList(); + list.Add(serial); + + SystemObjectsCollection fan = new SystemObjectsCollection() { Name = "Fan" }; + Win32_Fan fanConnection = new Win32_Fan(wmiConnection); + fan.Objects = fanConnection.GetHardwareInfoList().ToList(); + list.Add(fan); + + SystemObjectsCollection temp = new SystemObjectsCollection() { Name = "Temperature" }; + Win32_TemperatureProbe tempConnection = new Win32_TemperatureProbe(wmiConnection); + temp.Objects = tempConnection.GetHardwareInfoList().ToList(); + list.Add(temp); + + SystemObjectsCollection power = new SystemObjectsCollection() { Name = "Power Supply" }; + Win32_UninterruptiblePowerSupply powerConnection = new Win32_UninterruptiblePowerSupply(wmiConnection); + power.Objects = powerConnection.GetHardwareInfoList().ToList(); + list.Add(power); + + SystemObjectsCollection voltage = new SystemObjectsCollection() { Name = "Voltage" }; + Win32_VoltageProbe voltageConnection = new Win32_VoltageProbe(wmiConnection); + voltage.Objects = voltageConnection.GetHardwareInfoList().ToList(); + list.Add(voltage); + + return list; + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Tango.SystemInfo.csproj b/Software/Visual_Studio/Tango.SystemInfo/Tango.SystemInfo.csproj new file mode 100644 index 000000000..90cf14c29 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Tango.SystemInfo.csproj @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{997A961C-BEDA-4B56-AA0F-C39E532F7FFA}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Tango.SystemInfo</RootNamespace> + <AssemblyName>Tango.SystemInfo</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Management" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Connection.cs" /> + <Compile Include="SystemObject.cs" /> + <Compile Include="SystemObjectProperty.cs" /> + <Compile Include="SystemObjectsCollection.cs" /> + <Compile Include="WMIReader.cs" /> + <Compile Include="XMLConfig.cs" /> + <Compile Include="IWMI.cs" /> + <Compile Include="Win32_BaseBoard.cs" /> + <Compile Include="Win32_Battery.cs" /> + <Compile Include="Win32_BIOS.cs" /> + <Compile Include="Win32_Bus.cs" /> + <Compile Include="Win32_CDROMDrive.cs" /> + <Compile Include="Win32_DiskDrive.cs" /> + <Compile Include="Win32_DMAChannel.cs" /> + <Compile Include="Win32_Fan.cs" /> + <Compile Include="Win32_FloppyController.cs" /> + <Compile Include="Win32_FloppyDrive.cs" /> + <Compile Include="Win32_IDEController.cs" /> + <Compile Include="Win32_IRQResource.cs" /> + <Compile Include="Win32_Keyboard.cs" /> + <Compile Include="Win32_MemoryDevice.cs" /> + <Compile Include="Win32_NetworkAdapter.cs" /> + <Compile Include="Win32_NetworkAdapterConfiguration.cs" /> + <Compile Include="Win32_OnBoardDevice.cs" /> + <Compile Include="Win32_OperatingSystem.cs" /> + <Compile Include="Win32_ParallelPort.cs" /> + <Compile Include="Win32_PCMCIController.cs" /> + <Compile Include="Win32_PhysicalMedia.cs" /> + <Compile Include="Win32_PhysicalMemory.cs" /> + <Compile Include="Win32_PortConnector.cs" /> + <Compile Include="Win32_PortResource.cs" /> + <Compile Include="Win32_POTSModem.cs" /> + <Compile Include="Win32_Processor.cs" /> + <Compile Include="Win32_SCSIController.cs" /> + <Compile Include="Win32_SerialPort.cs" /> + <Compile Include="Win32_SerialPortConfiguration.cs" /> + <Compile Include="Win32_SoundDevice.cs" /> + <Compile Include="Win32_SystemEnclosure.cs" /> + <Compile Include="Win32_TapeDrive.cs" /> + <Compile Include="Win32_TemperatureProbe.cs" /> + <Compile Include="Win32_UninterruptiblePowerSupply.cs" /> + <Compile Include="Win32_USBController.cs" /> + <Compile Include="Win32_USBHub.cs" /> + <Compile Include="Win32_VideoController.cs" /> + <Compile Include="Win32_VoltageProbe.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="settings.xml" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.SystemInfo/WMIReader.cs b/Software/Visual_Studio/Tango.SystemInfo/WMIReader.cs new file mode 100644 index 000000000..d7d909089 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/WMIReader.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Management; + +namespace Tango.SystemInfo +{ + class WMIReader + { + public static IList<SystemObject> GetPropertyValues(Connection WMIConnection, + string SelectQuery, + string className) + { + List<SystemObject> hardwareList = new List<SystemObject>(); + + ManagementScope connectionScope = WMIConnection.GetConnectionScope; + List<string> alProperties = new List<string>(); + SelectQuery msQuery = new SelectQuery(SelectQuery); + ManagementObjectSearcher searchProcedure = new ManagementObjectSearcher(connectionScope, msQuery); + + try + { + foreach (ManagementObject item in searchProcedure.Get()) + { + SystemObject hardware = new SystemObject(); + + try + { + hardware.Name = item["Name"].ToString(); + } + catch + { + hardware.Name = item.ToString(); + } + + hardwareList.Add(hardware); + + foreach (string property in XMLConfig.GetSettings(className)) + { + try + { + hardware.Properties.Add(new SystemObjectProperty() + { + Name = property, + Value = item[property].ToString() + }); + } + catch (SystemException) { /* ignore error */ } + } + } + } + catch (ManagementException e) + { + /* Do Nothing */ + } + + return hardwareList; + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_BIOS.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_BIOS.cs new file mode 100644 index 000000000..f86c0d5ca --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_BIOS.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_BIOS : IWMI + { + Connection WMIConnection; + + public Win32_BIOS(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_BaseBoard.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_BaseBoard.cs new file mode 100644 index 000000000..f9030ff54 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_BaseBoard.cs @@ -0,0 +1,27 @@ +using System; +using System.Management; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_BaseBoard: IWMI + { + Connection WMIConnection; + + public Win32_BaseBoard(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_Battery.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_Battery.cs new file mode 100644 index 000000000..91700d678 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_Battery.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_Battery : IWMI + { + Connection WMIConnection; + + public Win32_Battery(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_Bus.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_Bus.cs new file mode 100644 index 000000000..8aba00430 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_Bus.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_Bus : IWMI + { + Connection WMIConnection; + + public Win32_Bus(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_CDROMDrive.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_CDROMDrive.cs new file mode 100644 index 000000000..e6eaa08a9 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_CDROMDrive.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_CDROMDrive : IWMI + { + Connection WMIConnection; + + public Win32_CDROMDrive(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_DMAChannel.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_DMAChannel.cs new file mode 100644 index 000000000..12e0228fb --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_DMAChannel.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_DMAChannel : IWMI + { + Connection WMIConnection; + + public Win32_DMAChannel(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_DiskDrive.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_DiskDrive.cs new file mode 100644 index 000000000..8600a663d --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_DiskDrive.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_DiskDrive : IWMI + { + Connection WMIConnection; + + public Win32_DiskDrive(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_Fan.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_Fan.cs new file mode 100644 index 000000000..afc241c37 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_Fan.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_Fan : IWMI + { + Connection WMIConnection; + + public Win32_Fan(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_FloppyController.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_FloppyController.cs new file mode 100644 index 000000000..5ac1f9d8f --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_FloppyController.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_FloppyController : IWMI + { + Connection WMIConnection; + + public Win32_FloppyController(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_FloppyDrive.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_FloppyDrive.cs new file mode 100644 index 000000000..10b1b8fde --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_FloppyDrive.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_FloppyDrive : IWMI + { + Connection WMIConnection; + + public Win32_FloppyDrive(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_IDEController.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_IDEController.cs new file mode 100644 index 000000000..899a4ad5e --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_IDEController.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_IDEController : IWMI + { + Connection WMIConnection; + + public Win32_IDEController(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_IRQResource.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_IRQResource.cs new file mode 100644 index 000000000..ff39c68fd --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_IRQResource.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_IRQResource : IWMI + { + Connection WMIConnection; + + public Win32_IRQResource(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_Keyboard.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_Keyboard.cs new file mode 100644 index 000000000..2657b5954 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_Keyboard.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_Keyboard : IWMI + { + Connection WMIConnection; + + public Win32_Keyboard(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_MemoryDevice.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_MemoryDevice.cs new file mode 100644 index 000000000..8ed21c13d --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_MemoryDevice.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_MemoryDevice : IWMI + { + Connection WMIConnection; + + public Win32_MemoryDevice(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_NetworkAdapter.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_NetworkAdapter.cs new file mode 100644 index 000000000..561919a2d --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_NetworkAdapter.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_NetworkAdapter : IWMI + { + Connection WMIConnection; + + public Win32_NetworkAdapter(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_NetworkAdapterConfiguration.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_NetworkAdapterConfiguration.cs new file mode 100644 index 000000000..ba22e1d01 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_NetworkAdapterConfiguration.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_NetworkAdapterConfiguration : IWMI + { + Connection WMIConnection; + + public Win32_NetworkAdapterConfiguration(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_OnBoardDevice.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_OnBoardDevice.cs new file mode 100644 index 000000000..7c4bea2a3 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_OnBoardDevice.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_OnBoardDevice : IWMI + { + Connection WMIConnection; + + public Win32_OnBoardDevice(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_OperatingSystem.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_OperatingSystem.cs new file mode 100644 index 000000000..24b93d92c --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_OperatingSystem.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_OperatingSystem : IWMI + { + Connection WMIConnection; + + public Win32_OperatingSystem(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + + public IList<SystemObject> GetHardwareInfoList() + { + return WMIReader.GetPropertyValues(WMIConnection, "select * from Win32_OperatingSystem", "Win32_OperatingSystem"); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_PCMCIController.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_PCMCIController.cs new file mode 100644 index 000000000..772af0a28 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_PCMCIController.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_PCMCIController : IWMI + { + Connection WMIConnection; + + public Win32_PCMCIController(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_POTSModem.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_POTSModem.cs new file mode 100644 index 000000000..29f9549ca --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_POTSModem.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_POTSModem : IWMI + { + Connection WMIConnection; + + public Win32_POTSModem(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_ParallelPort.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_ParallelPort.cs new file mode 100644 index 000000000..81244c588 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_ParallelPort.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_ParallelPort : IWMI + { + Connection WMIConnection; + + public Win32_ParallelPort(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_PhysicalMedia.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_PhysicalMedia.cs new file mode 100644 index 000000000..816944da4 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_PhysicalMedia.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_PhysicalMedia : IWMI + { + Connection WMIConnection; + + public Win32_PhysicalMedia(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_PhysicalMemory.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_PhysicalMemory.cs new file mode 100644 index 000000000..d319a3fa7 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_PhysicalMemory.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_PhysicalMemory : IWMI + { + Connection WMIConnection; + + public Win32_PhysicalMemory(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_PortConnector.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_PortConnector.cs new file mode 100644 index 000000000..20288cec7 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_PortConnector.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_PortConnector : IWMI + { + Connection WMIConnection; + + public Win32_PortConnector(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_PortResource.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_PortResource.cs new file mode 100644 index 000000000..8a8da41e7 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_PortResource.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_PortResource : IWMI + { + Connection WMIConnection; + + public Win32_PortResource(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_Processor.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_Processor.cs new file mode 100644 index 000000000..e8387c2bd --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_Processor.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_Processor : IWMI + { + Connection WMIConnection; + + public Win32_Processor(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_SCSIController.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_SCSIController.cs new file mode 100644 index 000000000..dfe689951 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_SCSIController.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_SCSIController : IWMI + { + Connection WMIConnection; + + public Win32_SCSIController(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_SerialPort.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_SerialPort.cs new file mode 100644 index 000000000..6b20763f9 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_SerialPort.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_SerialPort : IWMI + { + Connection WMIConnection; + + public Win32_SerialPort(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_SerialPortConfiguration.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_SerialPortConfiguration.cs new file mode 100644 index 000000000..d1efe826b --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_SerialPortConfiguration.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_SerialPortConfiguration : IWMI + { + Connection WMIConnection; + + public Win32_SerialPortConfiguration(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_SoundDevice.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_SoundDevice.cs new file mode 100644 index 000000000..bece1f169 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_SoundDevice.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_SoundDevice : IWMI + { + Connection WMIConnection; + + public Win32_SoundDevice(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_SystemEnclosure.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_SystemEnclosure.cs new file mode 100644 index 000000000..184ee3b99 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_SystemEnclosure.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_SystemEnclosure : IWMI + { + Connection WMIConnection; + + public Win32_SystemEnclosure(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_TapeDrive.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_TapeDrive.cs new file mode 100644 index 000000000..94600d518 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_TapeDrive.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_TapeDrive : IWMI + { + Connection WMIConnection; + + public Win32_TapeDrive(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_TemperatureProbe.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_TemperatureProbe.cs new file mode 100644 index 000000000..579203237 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_TemperatureProbe.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_TemperatureProbe : IWMI + { + Connection WMIConnection; + + public Win32_TemperatureProbe(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_USBController.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_USBController.cs new file mode 100644 index 000000000..6df7b4799 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_USBController.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_USBController : IWMI + { + Connection WMIConnection; + + public Win32_USBController(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_USBHub.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_USBHub.cs new file mode 100644 index 000000000..b0f812ebe --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_USBHub.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_USBHub : IWMI + { + Connection WMIConnection; + + public Win32_USBHub(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_UninterruptiblePowerSupply.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_UninterruptiblePowerSupply.cs new file mode 100644 index 000000000..d8dc7bacd --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_UninterruptiblePowerSupply.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_UninterruptiblePowerSupply : IWMI + { + Connection WMIConnection; + + public Win32_UninterruptiblePowerSupply(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_VideoController.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_VideoController.cs new file mode 100644 index 000000000..973303b98 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_VideoController.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_VideoController : IWMI + { + Connection WMIConnection; + + public Win32_VideoController(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/Win32_VoltageProbe.cs b/Software/Visual_Studio/Tango.SystemInfo/Win32_VoltageProbe.cs new file mode 100644 index 000000000..818898aa8 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/Win32_VoltageProbe.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tango.SystemInfo +{ + class Win32_VoltageProbe : IWMI + { + Connection WMIConnection; + + public Win32_VoltageProbe(Connection WMIConnection) + { + this.WMIConnection = WMIConnection; + } + public IList<SystemObject> GetHardwareInfoList() + { + string className = System.Text.RegularExpressions.Regex.Match( + this.GetType().ToString(), "Win32_.*").Value; + + return WMIReader.GetPropertyValues(WMIConnection, + "SELECT * FROM " + className, + className); + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/XMLConfig.cs b/Software/Visual_Studio/Tango.SystemInfo/XMLConfig.cs new file mode 100644 index 000000000..a6113a0cb --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/XMLConfig.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace Tango.SystemInfo +{ + class XMLConfig + { + private static List<string> propNames; + + public static List<string> GetSettings(string WMIClassName) + { + if (propNames == null) + { + propNames = new List<string>(); + System.Xml.XmlDocument xmldoc = new System.Xml.XmlDocument(); + xmldoc.Load(Tango.Core.Helpers.EmbeddedResourceHelper.GetEmbeddedResourceStream("Tango.SystemInfo.settings.xml")); + System.Xml.XmlNode properties = xmldoc.SelectSingleNode("//" + WMIClassName); + + for (int i = 0; i < properties.ChildNodes.Count; i++) + propNames.Add(properties.ChildNodes[i].InnerText); + + } + + return propNames; + } + } +} diff --git a/Software/Visual_Studio/Tango.SystemInfo/settings.xml b/Software/Visual_Studio/Tango.SystemInfo/settings.xml new file mode 100644 index 000000000..ae3059407 --- /dev/null +++ b/Software/Visual_Studio/Tango.SystemInfo/settings.xml @@ -0,0 +1,1347 @@ +<?xmlversion = "1.0"encoding="utf-8"?> +<AppSettings> + <WMI> + <Win32_OperatingSystem> + <property>BootDevice</property> + <property>BuildNumber</property> + <property>BuildType</property> + <property>Caption</property> + <property>CodeSet</property> + <property>CountryCode</property> + <property>CreationClassName</property> + <property>CSCreationClassName</property> + <property>CSDVersion</property> + <property>CSName</property> + <property>CurrentTimeZone</property> + <property>DataExecutionPrevention_Available</property> + <property>DataExecutionPrevention_32BitApplications</property> + <property>DataExecutionPrevention_Drivers</property> + <property>DataExecutionPrevention_SupportPolicy</property> + <property>Debug</property> + <property>Description</property> + <property>Distributed</property> + <property>EncryptionLevel</property> + <property>FreePhysicalMemory</property> + <property>FreeSpaceInPagingFiles</property> + <property>FreeVirtualMemory</property> + <property>InstallDate</property> + <property>LargeSystemCache</property> + <property>LastBootUpTime</property> + <property>LocalDateTime</property> + <property>Locale</property> + <property>Manufacturer</property> + <property>MaxNumberOfProcesses</property> + <property>MaxProcessMemorySize</property> + <property>Name</property> + <property>NumberOfLicensedUsers</property> + <property>NumberOfProcesses</property> + <property>NumberOfUsers</property> + <property>OperatingSystemSKU</property> + <property>Organization</property> + <property>OSArchitecture</property> + <property>OSLanguage</property> + <property>OSProductSuite</property> + <property>OSType</property> + <property>OtherTypeDescription</property> + <property>PAEEnabled</property> + <property>PlusProductID</property> + <property>PlusVersionNumber</property> + <property>PortableOperatingSystem</property> + <property>Primary</property> + <property>ProductType</property> + <property>RegisteredUser</property> + <property>SerialNumber</property> + <property>ServicePackMajorVersion</property> + <property>ServicePackMinorVersion</property> + <property>SizeStoredInPagingFiles</property> + <property>Status</property> + <property>SuiteMask</property> + <property>SystemDevice</property> + <property>SystemDirectory</property> + <property>SystemDrive</property> + <property>TotalSwapSpaceSize</property> + <property>TotalVirtualMemorySize</property> + <property>TotalVisibleMemorySize</property> + <property>Version</property> + <property>WindowsDirectory</property> + <property>QuantumLength</property> + <property>QuantumType</property> + </Win32_OperatingSystem> + <Win32_BaseBoard> + <property>Caption</property> + <property>CreationClassName</property> + <property>Depth</property> + <property>Description</property> + <property>Height</property> + <property>HostingBoard</property> + <property>HotSwappable</property> + <property>InstallDate</property> + <property>Manufacturer</property> + <property>Model</property> + <property>Name</property> + <property>OtherIdentifyingInfo</property> + <property>PartNumber</property> + <property>PoweredOn</property> + <property>Product</property> + <property>Removable</property> + <property>Replaceable</property> + <property>RequirementsDescription</property> + <property>RequiresDaughterBoard</property> + <property>SerialNumber</property> + <property>SKU</property> + <property>SlotLayout</property> + <property>SpecialRequirements</property> + <property>Status</property> + <property>Tag</property> + <property>Version</property> + <property>Weight</property> + <property>Width</property> + </Win32_BaseBoard> + <Win32_Battery> + <property>Availability</property> + <property>BatteryRechargeTime</property> + <property>BatteryStatus</property> + <property>Caption</property> + <property>Chemistry</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DesignCapacity</property> + <property>DesignVoltage</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>EstimatedChargeRemaining</property> + <property>EstimatedRunTime</property> + <property>ExpectedBatteryLife</property> + <property>ExpectedLife</property> + <property>FullChargeCapacity</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>MaxRechargeTime</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementSupported</property> + <property>SmartBatteryVersion</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOnBattery</property> + <property>TimeToFullCharge</property> + </Win32_Battery> + <Win32_BIOS> + <property>BuildNumber</property> + <property>Caption</property> + <property>CodeSet</property> + <property>CurrentLanguage</property> + <property>Description</property> + <property>IdentificationCode</property> + <property>InstallableLanguages</property> + <property>InstallDate</property> + <property>LanguageEdition</property> + <property>Manufacturer</property> + <property>Name</property> + <property>OtherTargetOS</property> + <property>PrimaryBIOS</property> + <property>ReleaseDate</property> + <property>SerialNumber</property> + <property>SMBIOSBIOSVersion</property> + <property>SMBIOSMajorVersion</property> + <property>SMBIOSMinorVersion</property> + <property>SMBIOSPresent</property> + <property>SoftwareElementID</property> + <property>SoftwareElementState</property> + <property>Status</property> + <property>TargetOperatingSystem</property> + <property>Version</property> + </Win32_BIOS> + <Win32_Bus> + <property>Availability</property> + <property>BusNum</property> + <property>BusType</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + </Win32_Bus> + <Win32_CDROMDrive> + <property>Availability</property> + <property>Caption</property> + <property>CompressionMethod</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>DefaultBlockSize</property> + <property>Description</property> + <property>DeviceID</property> + <property>Drive</property> + <property>DriveIntegrity</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>ErrorMethodology</property> + <property>FileSystemFlags</property> + <property>FileSystemFlagsEx</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxBlockSize</property> + <property>MaximumComponentLength</property> + <property>MaxMediaSize</property> + <property>MediaLoaded</property> + <property>MediaType</property> + <property>MfrAssignedRevisionLevel</property> + <property>MinBlockSize</property> + <property>Name</property> + <property>NeedsCleaning</property> + <property>NumberOfMediaSupported</property> + <property>PNPDeviceID</property> + <property>PowerManagementSupported</property> + <property>RevisionLevel</property> + <property>SCSIBus</property> + <property>SCSILogicalUnit</property> + <property>SCSIPort</property> + <property>SCSITargetId</property> + <property>SerialNumber</property> + <property>Size</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TransferRate</property> + <property>VolumeName</property> + <property>VolumeSerialNumber</property> + </Win32_CDROMDrive> + <Win32_DiskDrive> + <property>Availability</property> + <property>BytesPerSector</property> + <property>Capabilities[]</property> + <property>CapabilityDescriptions[]</property> + <property>Caption</property> + <property>CompressionMethod</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>DefaultBlockSize</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>ErrorMethodology</property> + <property>FirmwareRevision</property> + <property>Index</property> + <property>InstallDate</property> + <property>InterfaceType</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxBlockSize</property> + <property>MaxMediaSize</property> + <property>MediaLoaded</property> + <property>MediaType</property> + <property>MinBlockSize</property> + <property>Model</property> + <property>Name</property> + <property>NeedsCleaning</property> + <property>NumberOfMediaSupported</property> + <property>Partitions</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>SCSIBus</property> + <property>SCSILogicalUnit</property> + <property>SCSIPort</property> + <property>SCSITargetId</property> + <property>SectorsPerTrack</property> + <property>SerialNumber</property> + <property>Signature</property> + <property>Size</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TotalCylinders</property> + <property>TotalHeads</property> + <property>TotalSectors</property> + <property>TotalTracks</property> + <property>TracksPerCylinder</property> + </Win32_DiskDrive> + <Win32_DMAChannel> + <property>16AddressSize</property> + <property>16Availability</property> + <property>BurstMode</property> + <property>16ByteMode</property> + <property>Caption</property> + <property>16ChannelTiming</property> + <property>CreationClassName</property> + <property>CSCreationClassName</property> + <property>CSName</property> + <property>Description</property> + <property>32DMAChannel</property> + <property>InstallDate</property> + <property>32MaxTransferSize</property> + <property>Name</property> + <property>32Port</property> + <property>Status</property> + <property>16TransferWidths[]</property> + <property>16TypeCTiming</property> + <property>16WordMode</property> + </Win32_DMAChannel> + <Win32_Fan> + <property>ActiveCooling</property> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DesiredSpeed</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>VariableSpeed</property> + </Win32_Fan> + <Win32_FloppyController> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxNumberControlled</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementSupported</property> + <property>ProtocolSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOfLastReset</property> + </Win32_FloppyController> + <Win32_FloppyDrive> + <property>Availability</property> + <property>Caption</property> + <property>CompressionMethod</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>DefaultBlockSize</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>ErrorMethodology</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxBlockSize</property> + <property>MaxMediaSize</property> + <property>MinBlockSize</property> + <property>Name</property> + <property>NeedsCleaning</property> + <property>NumberOfMediaSupported</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + </Win32_FloppyDrive> + <Win32_IDEController> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxNumberControlled</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProtocolSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOfLastReset</property> + </Win32_IDEController> + <Win32_IRQResource> + <property>Availability</property> + <property>Caption</property> + <property>CreationClassName</property> + <property>CSCreationClassName</property> + <property>CSName</property> + <property>Description</property> + <property>Hardware</property> + <property>InstallDate</property> + <property>IRQNumber</property> + <property>Name</property> + <property>Shareable</property> + <property>Status</property> + <property>TriggerLevel</property> + <property>TriggerType</property> + <property>Vector</property> + </Win32_IRQResource> + <Win32_Keyboard> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>IsLocked</property> + <property>LastErrorCode</property> + <property>Layout</property> + <property>Name</property> + <property>NumberOfFunctionKeys</property> + <property>Password</property> + <property>PNPDeviceID</property> + <property>PowerManagementSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + </Win32_Keyboard> + <Win32_MemoryDevice> + <property>Access</property> + <property>AdditionalErrorData[]</property> + <property>Availability</property> + <property>BlockSize</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CorrectableError</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>EndingAddress</property> + <property>ErrorAccess</property> + <property>ErrorAddress</property> + <property>ErrorCleared</property> + <property>ErrorDataOrder</property> + <property>ErrorDescription</property> + <property>ErrorGranularity</property> + <property>ErrorInfo</property> + <property>ErrorMethodology</property> + <property>ErrorResolution</property> + <property>ErrorTime</property> + <property>ErrorTransferSize</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Name</property> + <property>NumberOfBlocks</property> + <property>OtherErrorDescription</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>Purpose</property> + <property>StartingAddress</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemLevelAddress</property> + <property>SystemName</property> + </Win32_MemoryDevice> + <Win32_NetworkAdapter> + <property>AdapterType</property> + <property>AdapterTypeID</property> + <property>AutoSense</property> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>GUID</property> + <property>Index</property> + <property>InstallDate</property> + <property>Installed</property> + <property>InterfaceIndex</property> + <property>LastErrorCode</property> + <property>MACAddress</property> + <property>Manufacturer</property> + <property>MaxNumberControlled</property> + <property>MaxSpeed</property> + <property>Name</property> + <property>NetConnectionID</property> + <property>NetConnectionStatus</property> + <property>NetEnabled</property> + <property>NetworkAddresses[]</property> + <property>PermanentAddress</property> + <property>PhysicalAdapter</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProductName</property> + <property>ServiceName</property> + <property>Speed</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOfLastReset</property> + </Win32_NetworkAdapter> + <Win32_NetworkAdapterConfiguration> + <property>ArpAlwaysSourceRoute</property> + <property>ArpUseEtherSNAP</property> + <property>Caption</property> + <property>DatabasePath</property> + <property>DeadGWDetectEnabled</property> + <property>DefaultIPGateway[]</property> + <property>DefaultTOS</property> + <property>DefaultTTL</property> + <property>Description</property> + <property>DHCPEnabled</property> + <property>DHCPLeaseExpires</property> + <property>DHCPLeaseObtained</property> + <property>DHCPServer</property> + <property>DNSDomain</property> + <property>DNSDomainSuffixSearchOrder[]</property> + <property>DNSEnabledForWINSResolution</property> + <property>DNSHostName</property> + <property>DNSServerSearchOrder[]</property> + <property>DomainDNSRegistrationEnabled</property> + <property>ForwardBufferMemory</property> + <property>FullDNSRegistrationEnabled</property> + <property>GatewayCostMetric[]</property> + <property>IGMPLevel</property> + <property>Index</property> + <property>InterfaceIndex</property> + <property>IPAddress[]</property> + <property>IPConnectionMetric</property> + <property>IPEnabled</property> + <property>IPFilterSecurityEnabled</property> + <property>IPPortSecurityEnabled</property> + <property>IPSecPermitIPProtocols[]</property> + <property>IPSecPermitTCPPorts[]</property> + <property>IPSecPermitUDPPorts[]</property> + <property>IPSubnet[]</property> + <property>IPUseZeroBroadcast</property> + <property>IPXAddress</property> + <property>IPXEnabled</property> + <property>IPXFrameType[]</property> + <property>IPXMediaType</property> + <property>IPXNetworkNumber[]</property> + <property>IPXVirtualNetNumber</property> + <property>KeepAliveInterval</property> + <property>KeepAliveTime</property> + <property>MACAddress</property> + <property>MTU</property> + <property>NumForwardPackets</property> + <property>PMTUBHDetectEnabled</property> + <property>PMTUDiscoveryEnabled</property> + <property>ServiceName</property> + <property>SettingID</property> + <property>TcpipNetbiosOptions</property> + <property>TcpMaxConnectRetransmissions</property> + <property>TcpMaxDataRetransmissions</property> + <property>TcpNumConnections</property> + <property>TcpUseRFC1122UrgentPointer</property> + <property>TcpWindowSize</property> + <property>WINSEnableLMHostsLookup</property> + <property>WINSHostLookupFile</property> + <property>WINSPrimaryServer</property> + <property>WINSScopeID</property> + <property>WINSSecondaryServer</property> + </Win32_NetworkAdapterConfiguration> + <Win32_OnBoardDevice> + <property>Caption</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceType</property> + <property>Enabled</property> + <property>HotSwappable</property> + <property>InstallDate</property> + <property>Manufacturer</property> + <property>Model</property> + <property>Name</property> + <property>OtherIdentifyingInfo</property> + <property>PartNumber</property> + <property>PoweredOn</property> + <property>Removable</property> + <property>Replaceable</property> + <property>SerialNumber</property> + <property>SKU</property> + <property>Status</property> + <property>Tag</property> + <property>Version</property> + </Win32_OnBoardDevice> + <Win32_ParallelPort> + <property>Availability</property> + <property>Capabilities[]</property> + <property>CapabilityDescriptions[]</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>DMASupport</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>MaxNumberControlled</property> + <property>Name</property> + <property>OSAutoDiscovered</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProtocolSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOfLastReset</property> + </Win32_ParallelPort> + <Win32_PCMCIAController> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxNumberControlled</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProtocolSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOfLastReset</property> + </Win32_PCMCIAController> + <Win32_PhysicalMedia> + <property>Caption</property> + <property>Description</property> + <property>InstallDate</property> + <property>Name</property> + <property>Status</property> + <property>CreationClassName</property> + <property>Manufacturer</property> + <property>Model</property> + <property>SKU</property> + <property>SerialNumber</property> + <property>Tag</property> + <property>Version</property> + <property>PartNumber</property> + <property>OtherIdentifyingInfo</property> + <property>PoweredOn</property> + <property>Removable</property> + <property>Replaceable</property> + <property>HotSwappable</property> + <property>Capacity</property> + <property>MediaType</property> + <property>MediaDescription</property> + <property>WriteProtectOn</property> + <property>CleanerMedia</property> + </Win32_PhysicalMedia> + <Win32_PhysicalMemory> + <property>BankLabel</property> + <property>Capacity</property> + <property>Caption</property> + <property>CreationClassName</property> + <property>DataWidth</property> + <property>Description</property> + <property>DeviceLocator</property> + <property>FormFactor</property> + <property>HotSwappable</property> + <property>InstallDate</property> + <property>InterleaveDataDepth</property> + <property>InterleavePosition</property> + <property>Manufacturer</property> + <property>MemoryType</property> + <property>Model</property> + <property>Name</property> + <property>OtherIdentifyingInfo</property> + <property>PartNumber</property> + <property>PositionInRow</property> + <property>PoweredOn</property> + <property>Removable</property> + <property>Replaceable</property> + <property>SerialNumber</property> + <property>SKU</property> + <property>Speed</property> + <property>Status</property> + <property>Tag</property> + <property>TotalWidth</property> + <property>TypeDetail</property> + <property>Version</property> + </Win32_PhysicalMemory> + <Win32_PortConnector> + <property>Caption</property> + <property>ConnectorPinout</property> + <property>ConnectorType[]</property> + <property>CreationClassName</property> + <property>Description</property> + <property>ExternalReferenceDesignator</property> + <property>InstallDate</property> + <property>InternalReferenceDesignator</property> + <property>Manufacturer</property> + <property>Model</property> + <property>Name</property> + <property>OtherIdentifyingInfo</property> + <property>PartNumber</property> + <property>PortType</property> + <property>PoweredOn</property> + <property>SerialNumber</property> + <property>SKU</property> + <property>Status</property> + <property>Tag</property> + <property>Version</property> + </Win32_PortConnector> + <Win32_PortResource> + <property>Alias</property> + <property>Caption</property> + <property>CreationClassName</property> + <property>CSCreationClassName</property> + <property>CSName</property> + <property>Description</property> + <property>EndingAddress</property> + <property>InstallDate</property> + <property>Name</property> + <property>StartingAddress</property> + <property>Status</property> + </Win32_PortResource> + <Win32_POTSModem> + <property>AnswerMode</property> + <property>AttachedTo</property> + <property>Availability</property> + <property>BlindOff</property> + <property>BlindOn</property> + <property>Caption</property> + <property>CompatibilityFlags</property> + <property>CompressionInfo</property> + <property>CompressionOff</property> + <property>CompressionOn</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>ConfigurationDialog</property> + <property>CountriesSupported[]</property> + <property>CountrySelected</property> + <property>CreationClassName</property> + <property>CurrentPasswords[]</property> + <property>DCB[]</property> + <property>Default[]</property> + <property>Description</property> + <property>DeviceID</property> + <property>DeviceLoader</property> + <property>DeviceType</property> + <property>DialType</property> + <property>DriverDate</property> + <property>ErrorCleared</property> + <property>ErrorControlForced</property> + <property>ErrorControlInfo</property> + <property>ErrorControlOff</property> + <property>ErrorControlOn</property> + <property>ErrorDescription</property> + <property>FlowControlHard</property> + <property>FlowControlOff</property> + <property>FlowControlSoft</property> + <property>InactivityScale</property> + <property>InactivityTimeout</property> + <property>Index</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>MaxBaudRateToPhone</property> + <property>MaxBaudRateToSerialPort</property> + <property>MaxNumberOfPasswords</property> + <property>Model</property> + <property>ModemInfPath</property> + <property>ModemInfSection</property> + <property>ModulationBell</property> + <property>ModulationCCITT</property> + <property>ModulationScheme</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PortSubClass</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>Prefix</property> + <property>Properties[]</property> + <property>ProviderName</property> + <property>Pulse</property> + <property>Reset</property> + <property>ResponsesKeyName</property> + <property>RingsBeforeAnswer</property> + <property>SpeakerModeDial</property> + <property>SpeakerModeOff</property> + <property>SpeakerModeOn</property> + <property>SpeakerModeSetup</property> + <property>SpeakerVolumeHigh</property> + <property>SpeakerVolumeInfo</property> + <property>SpeakerVolumeLow</property> + <property>SpeakerVolumeMed</property> + <property>Status</property> + <property>StatusInfo</property> + <property>StringFormat</property> + <property>SupportsCallback</property> + <property>SupportsSynchronousConnect</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>Terminator</property> + <property>TimeOfLastReset</property> + <property>Tone</property> + <property>VoiceSwitchFeature</property> + </Win32_POTSModem> + <Win32_Processor> + <property>AddressWidth</property> + <property>Architecture</property> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CpuStatus</property> + <property>CreationClassName</property> + <property>CurrentClockSpeed</property> + <property>CurrentVoltage</property> + <property>DataWidth</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>ExtClock</property> + <property>Family</property> + <property>InstallDate</property> + <property>L2CacheSize</property> + <property>L2CacheSpeed</property> + <property>L3CacheSize</property> + <property>L3CacheSpeed</property> + <property>LastErrorCode</property> + <property>Level</property> + <property>LoadPercentage</property> + <property>Manufacturer</property> + <property>MaxClockSpeed</property> + <property>Name</property> + <property>NumberOfCores</property> + <property>NumberOfLogicalProcessors</property> + <property>OtherFamilyDescription</property> + <property>PNPDeviceID</property> + <property>PowerManagementSupported</property> + <property>ProcessorId</property> + <property>ProcessorType</property> + <property>Revision</property> + <property>Role</property> + <property>SocketDesignation</property> + <property>Status</property> + <property>StatusInfo</property> + <property>Stepping</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>UniqueId</property> + <property>UpgradeMethod</property> + <property>Version</property> + <property>VoltageCaps</property> + </Win32_Processor> + <Win32_SCSIController> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>ControllerTimeouts</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>DeviceMap</property> + <property>DriverName</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>HardwareVersion</property> + <property>Index</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxDataWidth</property> + <property>MaxNumberControlled</property> + <property>MaxTransferRate</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProtectionManagement</property> + <property>ProtocolSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOfLastReset</property> + </Win32_SCSIController> + <Win32_SerialPort> + <property>Availability</property> + <property>Binary</property> + <property>Capabilities[]</property> + <property>CapabilityDescriptions[]</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>MaxBaudRate</property> + <property>MaximumInputBufferSize</property> + <property>MaximumOutputBufferSize</property> + <property>MaxNumberControlled</property> + <property>Name</property> + <property>OSAutoDiscovered</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProtocolSupported</property> + <property>ProviderType</property> + <property>SettableBaudRate</property> + <property>SettableDataBits</property> + <property>SettableFlowControl</property> + <property>SettableParity</property> + <property>SettableParityCheck</property> + <property>SettableRLSD</property> + <property>SettableStopBits</property> + <property>Status</property> + <property>StatusInfo</property> + <property>Supports16BitMode</property> + <property>SupportsDTRDSR</property> + <property>SupportsElapsedTimeouts</property> + <property>SupportsIntTimeouts</property> + <property>SupportsParityCheck</property> + <property>SupportsRLSD</property> + <property>SupportsRTSCTS</property> + <property>SupportsSpecialCharacters</property> + <property>SupportsXOnXOff</property> + <property>SupportsXOnXOffSet</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOfLastReset</property> + </Win32_SerialPort> + <Win32_SerialPortConfiguration> + <property>AbortReadWriteOnError</property> + <property>BaudRate</property> + <property>BinaryModeEnabled</property> + <property>BitsPerByte</property> + <property>Caption</property> + <property>ContinueXMitOnXOff</property> + <property>CTSOutflowControl</property> + <property>Description</property> + <property>DiscardNULLBytes</property> + <property>DSROutflowControl</property> + <property>DSRSensitivity</property> + <property>DTRFlowControlType</property> + <property>EOFCharacter</property> + <property>ErrorReplaceCharacter</property> + <property>ErrorReplacementEnabled</property> + <property>EventCharacter</property> + <property>IsBusy</property> + <property>Name</property> + <property>Parity</property> + <property>ParityCheckEnabled</property> + <property>RTSFlowControlType</property> + <property>SettingID</property> + <property>StopBits</property> + <property>XOffCharacter</property> + <property>XOffXMitThreshold</property> + <property>XOnCharacter</property> + <property>XOnXMitThreshold</property> + <property>XOnXOffInFlowControl</property> + <property>XOnXOffOutFlowControl</property> + </Win32_SerialPortConfiguration> + <Win32_SoundDevice> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>DMABufferSize</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MPU401Address</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProductName</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + </Win32_SoundDevice> + <Win32_SystemEnclosure> + <property>AudibleAlarm</property> + <property>BreachDescription</property> + <property>CableManagementStrategy</property> + <property>Caption</property> + <property>ChassisTypes[]</property> + <property>CreationClassName</property> + <property>CurrentRequiredOrProduced</property> + <property>Depth</property> + <property>Description</property> + <property>HeatGeneration</property> + <property>Height</property> + <property>HotSwappable</property> + <property>InstallDate</property> + <property>LockPresent</property> + <property>Manufacturer</property> + <property>Model</property> + <property>Name</property> + <property>NumberOfPowerCords</property> + <property>OtherIdentifyingInfo</property> + <property>PartNumber</property> + <property>PoweredOn</property> + <property>Removable</property> + <property>Replaceable</property> + <property>SecurityBreach</property> + <property>SecurityStatus</property> + <property>SerialNumber</property> + <property>ServiceDescriptions[]</property> + <property>ServicePhilosophy[]</property> + <property>SKU</property> + <property>SMBIOSAssetTag</property> + <property>Status</property> + <property>Tag</property> + <property>TypeDescriptions[]</property> + <property>Version</property> + <property>VisibleAlarm</property> + <property>Weight</property> + <property>Width</property> + </Win32_SystemEnclosure> + <Win32_TapeDrive> + <property>Availability</property> + <property>Capabilities[]</property> + <property>CapabilityDescriptions[]</property> + <property>Caption</property> + <property>Compression</property> + <property>CompressionMethod</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>DefaultBlockSize</property> + <property>Description</property> + <property>DeviceID</property> + <property>ECC</property> + <property>EOTWarningZoneSize</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>ErrorMethodology</property> + <property>FeaturesHigh</property> + <property>FeaturesLow</property> + <property>Id</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxBlockSize</property> + <property>MaxMediaSize</property> + <property>MaxPartitionCount</property> + <property>MediaType</property> + <property>MinBlockSize</property> + <property>Name</property> + <property>NeedsCleaning</property> + <property>NumberOfMediaSupported</property> + <property>Padding</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ReportSetMarks</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + </Win32_TapeDrive> + <Win32_TemperatureProbe> + <property>Accuracy</property> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>CurrentReading</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>IsLinear</property> + <property>LastErrorCode</property> + <property>LowerThresholdCritical</property> + <property>LowerThresholdFatal</property> + <property>LowerThresholdNonCritical</property> + <property>MaxReadable</property> + <property>MinReadable</property> + <property>Name</property> + <property>NominalReading</property> + <property>NormalMax</property> + <property>NormalMin</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>Resolution</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>Tolerance</property> + <property>UpperThresholdCritical</property> + <property>UpperThresholdFatal</property> + <property>UpperThresholdNonCritical</property> + </Win32_TemperatureProbe> + <Win32_UninterruptiblePowerSupply> + <property>ActiveInputVoltage</property> + <property>Availability</property> + <property>BatteryInstalled</property> + <property>CanTurnOffRemotely</property> + <property>Caption</property> + <property>CommandFile</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>EstimatedChargeRemaining</property> + <property>EstimatedRunTime</property> + <property>FirstMessageDelay</property> + <property>InstallDate</property> + <property>IsSwitchingSupply</property> + <property>LastErrorCode</property> + <property>LowBatterySignal</property> + <property>MessageInterval</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerFailSignal</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>Range1InputFrequencyHigh</property> + <property>Range1InputFrequencyLow</property> + <property>Range1InputVoltageHigh</property> + <property>Range1InputVoltageLow</property> + <property>Range2InputFrequencyHigh</property> + <property>Range2InputFrequencyLow</property> + <property>Range2InputVoltageHigh</property> + <property>Range2InputVoltageLow</property> + <property>RemainingCapacityStatus</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOnBackup</property> + <property>TotalOutputPower</property> + <property>TypeOfRangeSwitching</property> + <property>UPSPort</property> + </Win32_UninterruptiblePowerSupply> + <Win32_USBController> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Manufacturer</property> + <property>MaxNumberControlled</property> + <property>Name</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProtocolSupported</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>TimeOfLastReset</property> + </Win32_USBController> + <Win32_USBHub> + <property>Availability</property> + <property>Caption</property> + <property>ClassCode</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserCode</property> + <property>CreationClassName</property> + <property>CurrentAlternativeSettings</property> + <property>CurrentConfigValue</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>GangSwitched</property> + <property>InstallDate</property> + <property>LastErrorCode</property> + <property>Name</property> + <property>NumberOfConfigs</property> + <property>NumberOfPorts</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProtocolCode</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SubclassCode</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>USBVersion</property> + </Win32_USBHub> + <Win32_VideoController> + <property>AcceleratorCapabilities[]</property> + <property>AdapterCompatibility</property> + <property>AdapterDACType</property> + <property>AdapterRAM</property> + <property>Availability</property> + <property>CapabilityDescriptions[]</property> + <property>Caption</property> + <property>ColorTableEntries</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>CurrentBitsPerPixel</property> + <property>CurrentHorizontalResolution</property> + <property>CurrentNumberOfColors</property> + <property>CurrentNumberOfColumns</property> + <property>CurrentNumberOfRows</property> + <property>CurrentRefreshRate</property> + <property>CurrentScanMode</property> + <property>CurrentVerticalResolution</property> + <property>Description</property> + <property>DeviceID</property> + <property>DeviceSpecificPens</property> + <property>DitherType</property> + <property>DriverDate</property> + <property>DriverVersion</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>ICMIntent</property> + <property>ICMMethod</property> + <property>InfFilename</property> + <property>InfSection</property> + <property>InstallDate</property> + <property>InstalledDisplayDrivers</property> + <property>LastErrorCode</property> + <property>MaxMemorySupported</property> + <property>MaxNumberControlled</property> + <property>MaxRefreshRate</property> + <property>MinRefreshRate</property> + <property>Monochrome</property> + <property>Name</property> + <property>NumberOfColorPlanes</property> + <property>NumberOfVideoPages</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>ProtocolSupported</property> + <property>ReservedSystemPaletteEntries</property> + <property>SpecificationVersion</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>SystemPaletteEntries</property> + <property>TimeOfLastReset</property> + <property>VideoArchitecture</property> + <property>VideoMemoryType</property> + <property>VideoMode</property> + <property>VideoModeDescription</property> + <property>VideoProcessor</property> + </Win32_VideoController> + <Win32_VoltageProbe> + <property>Accuracy</property> + <property>Availability</property> + <property>Caption</property> + <property>ConfigManagerErrorCode</property> + <property>ConfigManagerUserConfig</property> + <property>CreationClassName</property> + <property>CurrentReading</property> + <property>Description</property> + <property>DeviceID</property> + <property>ErrorCleared</property> + <property>ErrorDescription</property> + <property>InstallDate</property> + <property>IsLinear</property> + <property>LastErrorCode</property> + <property>LowerThresholdCritical</property> + <property>LowerThresholdFatal</property> + <property>LowerThresholdNonCritical</property> + <property>MaxReadable</property> + <property>MinReadable</property> + <property>Name</property> + <property>NominalReading</property> + <property>NormalMax</property> + <property>NormalMin</property> + <property>PNPDeviceID</property> + <property>PowerManagementCapabilities[]</property> + <property>PowerManagementSupported</property> + <property>Resolution</property> + <property>Status</property> + <property>StatusInfo</property> + <property>SystemCreationClassName</property> + <property>SystemName</property> + <property>Tolerance</property> + <property>UpperThresholdCritical</property> + <property>UpperThresholdFatal</property> + <property>UpperThresholdNonCritical</property> + </Win32_VoltageProbe> + + </WMI> + +</AppSettings> + diff --git a/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs b/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs index c1d3d4967..a8f272292 100644 --- a/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs +++ b/Software/Visual_Studio/Tango.Transport/Adapters/SignalRTransportAdapter.cs @@ -56,10 +56,16 @@ namespace Tango.Transport.Adapters public bool EnableCompression { get; set; } /// <summary> + /// Gets or sets the adapter connection timeout. + /// </summary> + public TimeSpan ConnectionTimeout { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="SignalRTransportAdapter"/> class. /// </summary> public SignalRTransportAdapter() : base() { + ConnectionTimeout = TimeSpan.FromSeconds(30); WriteInterval = TimeSpan.FromMilliseconds(10); ComponentName = $"SignalR Adapter {_component_counter++}"; } @@ -137,10 +143,10 @@ namespace Tango.Transport.Adapters if (!completed) { completed = true; - completionSource.SetException(new TimeoutException("Could not connect the SignalR adapter.")); + completionSource.SetException(new TimeoutException("Could not reach the remote machine after the given timeout.")); } - }, TimeSpan.FromSeconds(5)); + }, ConnectionTimeout); if (Mode == SignalRTransportAdapterMode.CreateSession) { diff --git a/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs b/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs index 3cfd1ca48..d77ad1ed4 100644 --- a/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs +++ b/Software/Visual_Studio/Tango.Transport/ITransportAdapter.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Reactive; using System.Reactive.Linq; @@ -12,7 +13,7 @@ namespace Tango.Transport /// Represents a transport adapter capable of connecting, writing and receiving data from a stream. /// </summary> /// <seealso cref="Tango.Transport.ITransportComponent" /> - public interface ITransportAdapter : ITransportComponent + public interface ITransportAdapter : ITransportComponent, INotifyPropertyChanged { /// <summary> /// Gets the total bytes received. diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index f29a631e2..921301cc0 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -365,6 +365,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebRtc.NET", "SideChains\We EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.WebRTC", "Tango.WebRTC\Tango.WebRTC.csproj", "{09F81A12-0F77-4336-854D-9E0A74A17F9E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.SystemInfo", "Tango.SystemInfo\Tango.SystemInfo.csproj", "{997A961C-BEDA-4B56-AA0F-C39E532F7FFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.FileSystem", "Tango.FileSystem\Tango.FileSystem.csproj", "{C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AppVeyor|Any CPU = AppVeyor|Any CPU @@ -6491,6 +6495,86 @@ Global {09F81A12-0F77-4336-854D-9E0A74A17F9E}.Release|x64.Build.0 = Release|Any CPU {09F81A12-0F77-4336-854D-9E0A74A17F9E}.Release|x86.ActiveCfg = Release|Any CPU {09F81A12-0F77-4336-854D-9E0A74A17F9E}.Release|x86.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|Any CPU.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|Any CPU.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|ARM.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|ARM.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|ARM64.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|ARM64.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|x64.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|x64.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|x86.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.AppVeyor|x86.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|ARM.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|ARM.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|ARM64.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|x64.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|x64.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|x86.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Debug|x86.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|Any CPU.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|ARM.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|ARM.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|ARM64.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|ARM64.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|x64.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|x64.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|x86.ActiveCfg = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.DefaultBuild|x86.Build.0 = Debug|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|Any CPU.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|ARM.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|ARM.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|ARM64.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|ARM64.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|x64.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|x64.Build.0 = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|x86.ActiveCfg = Release|Any CPU + {997A961C-BEDA-4B56-AA0F-C39E532F7FFA}.Release|x86.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|Any CPU.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|Any CPU.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|ARM.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|ARM.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|ARM64.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|ARM64.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|x64.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|x64.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|x86.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.AppVeyor|x86.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|ARM.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|ARM64.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|x64.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|x64.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|x86.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Debug|x86.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|Any CPU.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|ARM.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|ARM.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|ARM64.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|ARM64.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|x64.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|x64.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|x86.ActiveCfg = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.DefaultBuild|x86.Build.0 = Debug|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|Any CPU.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|ARM.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|ARM.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|ARM64.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|ARM64.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|x64.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|x64.Build.0 = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|x86.ActiveCfg = Release|Any CPU + {C6EBBBBE-2123-44DC-AEF7-A0D47D736AC0}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Software/Visual_Studio/Utilities/Tango.LogViewer.UI/MainWindow.xaml b/Software/Visual_Studio/Utilities/Tango.LogViewer.UI/MainWindow.xaml index f1c947402..a4fc6a628 100644 --- a/Software/Visual_Studio/Utilities/Tango.LogViewer.UI/MainWindow.xaml +++ b/Software/Visual_Studio/Utilities/Tango.LogViewer.UI/MainWindow.xaml @@ -227,7 +227,7 @@ </Style> </DataGrid.Resources> <DataGrid.Columns> - <DataGridTemplateColumn Header="ICON" CellTemplate="{StaticResource LogIconStyle}"/> + <DataGridTemplateColumn Header="" CellTemplate="{StaticResource LogIconStyle}"/> <DataGridTextColumn Header="DATE TIME" Binding="{Binding TimeStamp,StringFormat=' HH:mm:ss.ff '}" Foreground="Gainsboro"/> <DataGridTextColumn Header="FILE" Binding="{Binding RelativeCallerFile}" ElementStyle="{StaticResource DataGridTextColumnElementStyle}"/> <DataGridTextColumn Header="METHOD" Binding="{Binding CallerMethodName}" ElementStyle="{StaticResource DataGridTextColumnElementStyle}"/> |
