diff options
| author | Avi Levkovich <avi@twine-s.com> | 2018-12-04 17:44:06 +0200 |
|---|---|---|
| committer | Avi Levkovich <avi@twine-s.com> | 2018-12-04 17:44:06 +0200 |
| commit | e64abeba3fd00cf6111b698384650b0e2a530436 (patch) | |
| tree | 9b44c7d5c160926e6bba548947547090f220b199 /Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage | |
| parent | e5d8713b456d335c19402360f0ba3e8a6db2c31e (diff) | |
| parent | 704146a52197741c1df351e48098b91ca69a2426 (diff) | |
| download | Tango-e64abeba3fd00cf6111b698384650b0e2a530436.tar.gz Tango-e64abeba3fd00cf6111b698384650b0e2a530436.zip | |
merge conflicts
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage')
20 files changed, 1541 insertions, 0 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Converters/StorageItemToImageConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Converters/StorageItemToImageConverter.cs new file mode 100644 index 000000000..e9d2c8c18 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Converters/StorageItemToImageConverter.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.Integration.Storage; +using Tango.SharedUI.Helpers; + +namespace Tango.MachineStudio.Storage.Converters +{ + public class StorageItemToImageConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + StorageItem item = value as StorageItem; + + if (item != null) + { + if (item is StorageFolder) + { + return ResourceHelper.GetImageFromResources("Images/folder.png"); + } + else + { + return Helpers.FileIconHelper.FindIconForFilename(item.Name, true); + } + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Helpers/FileIconHelper.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Helpers/FileIconHelper.cs new file mode 100644 index 000000000..47dab8e5e --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Helpers/FileIconHelper.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace Tango.MachineStudio.Storage.Helpers +{ + public static class FileIconHelper + { + private static readonly Dictionary<string, ImageSource> _smallIconCache = new Dictionary<string, ImageSource>(); + private static readonly Dictionary<string, ImageSource> _largeIconCache = new Dictionary<string, ImageSource>(); + /// <summary> + /// Get an icon for a given filename + /// </summary> + /// <param name="fileName">any filename</param> + /// <param name="large">16x16 or 32x32 icon</param> + /// <returns>null if path is null, otherwise - an icon</returns> + public static ImageSource FindIconForFilename(string fileName, bool large) + { + var extension = Path.GetExtension(fileName); + if (extension == null) + return null; + var cache = large ? _largeIconCache : _smallIconCache; + ImageSource icon; + if (cache.TryGetValue(extension, out icon)) + return icon; + icon = IconReader.GetFileIcon(fileName, large ? IconReader.IconSize.Large : IconReader.IconSize.Small, false).ToImageSource(); + cache.Add(extension, icon); + return icon; + } + /// <summary> + /// http://stackoverflow.com/a/6580799/1943849 + /// </summary> + static ImageSource ToImageSource(this Icon icon) + { + var imageSource = Imaging.CreateBitmapSourceFromHIcon( + icon.Handle, + Int32Rect.Empty, + BitmapSizeOptions.FromEmptyOptions()); + return imageSource; + } + /// <summary> + /// Provides static methods to read system icons for both folders and files. + /// </summary> + /// <example> + /// <code>IconReader.GetFileIcon("c:\\general.xls");</code> + /// </example> + static class IconReader + { + /// <summary> + /// Options to specify the size of icons to return. + /// </summary> + public enum IconSize + { + /// <summary> + /// Specify large icon - 32 pixels by 32 pixels. + /// </summary> + Large = 0, + /// <summary> + /// Specify small icon - 16 pixels by 16 pixels. + /// </summary> + Small = 1 + } + /// <summary> + /// Returns an icon for a given file - indicated by the name parameter. + /// </summary> + /// <param name="name">Pathname for file.</param> + /// <param name="size">Large or small</param> + /// <param name="linkOverlay">Whether to include the link icon</param> + /// <returns>System.Drawing.Icon</returns> + public static Icon GetFileIcon(string name, IconSize size, bool linkOverlay) + { + var shfi = new Shell32.Shfileinfo(); + var flags = Shell32.ShgfiIcon | Shell32.ShgfiUsefileattributes; + if (linkOverlay) flags += Shell32.ShgfiLinkoverlay; + /* Check the size specified for return. */ + if (IconSize.Small == size) + flags += Shell32.ShgfiSmallicon; + else + flags += Shell32.ShgfiLargeicon; + Shell32.SHGetFileInfo(name, + Shell32.FileAttributeNormal, + ref shfi, + (uint)Marshal.SizeOf(shfi), + flags); + // Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly + var icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone(); + User32.DestroyIcon(shfi.hIcon); // Cleanup + return icon; + } + } + /// <summary> + /// Wraps necessary Shell32.dll structures and functions required to retrieve Icon Handles using SHGetFileInfo. Code + /// courtesy of MSDN Cold Rooster Consulting case study. + /// </summary> + static class Shell32 + { + private const int MaxPath = 256; + [StructLayout(LayoutKind.Sequential)] + public struct Shfileinfo + { + private const int Namesize = 80; + public readonly IntPtr hIcon; + private readonly int iIcon; + private readonly uint dwAttributes; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxPath)] + private readonly string szDisplayName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Namesize)] + private readonly string szTypeName; + }; + public const uint ShgfiIcon = 0x000000100; // get icon + public const uint ShgfiLinkoverlay = 0x000008000; // put a link overlay on icon + public const uint ShgfiLargeicon = 0x000000000; // get large icon + public const uint ShgfiSmallicon = 0x000000001; // get small icon + public const uint ShgfiUsefileattributes = 0x000000010; // use passed dwFileAttribute + public const uint FileAttributeNormal = 0x00000080; + [DllImport("Shell32.dll")] + public static extern IntPtr SHGetFileInfo( + string pszPath, + uint dwFileAttributes, + ref Shfileinfo psfi, + uint cbFileInfo, + uint uFlags + ); + } + /// <summary> + /// Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example. + /// </summary> + static class User32 + { + /// <summary> + /// Provides access to function required to delete handle. This method is used internally + /// and is not required to be called separately. + /// </summary> + /// <param name="hIcon">Pointer to icon handle.</param> + /// <returns>N/A</returns> + [DllImport("User32.dll")] + public static extern int DestroyIcon(IntPtr hIcon); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/file.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/file.png Binary files differnew file mode 100644 index 000000000..a8cf88667 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/file.png diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/folder.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/folder.png Binary files differnew file mode 100644 index 000000000..1d32e80bf --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/folder.png diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/storage.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/storage.png Binary files differnew file mode 100644 index 000000000..1037998f1 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Images/storage.png diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerModel.cs new file mode 100644 index 000000000..764512e77 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerModel.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Integration.Storage; + +namespace Tango.MachineStudio.Storage.Models +{ + public class StorageFileHandlerModel : ExtendedObject + { + public StorageFileHandler Handler { get; set; } + + public StorageFileHandlerType Type { get; set; } + + public String FilePath { get; set; } + + public StorageFileHandlerModel(StorageFileHandler handler, String filePath, StorageFileHandlerType type) + { + FilePath = filePath; + Handler = handler; + Type = type; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerType.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerType.cs new file mode 100644 index 000000000..548b0fc86 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Models/StorageFileHandlerType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Storage.Models +{ + public enum StorageFileHandlerType + { + Download, + Upload + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/AssemblyInfo.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..e1da8d0cd --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/AssemblyInfo.cs @@ -0,0 +1,19 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +[assembly: AssemblyTitle("Tango - Machine Studio Storage Module")] +[assembly: AssemblyVersion("1.0.0.1737")] + +[assembly: ComVisible(false)] + +[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) +)] diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/Resources.Designer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/Resources.Designer.cs new file mode 100644 index 000000000..bd2484734 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/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.MachineStudio.Storage.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.MachineStudio.Storage.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/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/Resources.resx b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/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/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/Settings.Designer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/Settings.Designer.cs new file mode 100644 index 000000000..4076f7f8e --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/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.MachineStudio.Storage.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/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/Settings.settings b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Properties/Settings.settings new file mode 100644 index 000000000..033d7a5e9 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/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/MachineStudio/Modules/Tango.MachineStudio.Storage/StorageModule.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/StorageModule.cs new file mode 100644 index 000000000..f5b278627 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/StorageModule.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Tango.BL.Enumerations; +using Tango.MachineStudio.Common; +using Tango.MachineStudio.Storage.Views; +using Tango.SharedUI.Helpers; + +namespace Tango.MachineStudio.Storage +{ + [StudioModule(16)] + public class StorageModule : StudioModuleBase + { + public override string Name + { + get + { + return "Machine Storage"; + } + } + + public override string Description + { + get + { + return "Manage the machine flash file system storage using an interactive explorer."; + } + } + + public override BitmapSource Image + { + get + { + return ResourceHelper.GetImageFromResources("Images/storage.png"); + } + } + + public override Type MainViewType + { + get + { + return typeof(MainView); + } + } + + public override Permissions Permission + { + get + { + return Permissions.RunMachineStorageModule; + } + } + + public override void Dispose() + { + + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj new file mode 100644 index 000000000..bceaf7158 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Tango.MachineStudio.Storage.csproj @@ -0,0 +1,148 @@ +<?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>{5991F6B5-EA4E-41E9-A4F6-7D3A50010FD6}</ProjectGuid> + <OutputType>library</OutputType> + <RootNamespace>Tango.MachineStudio.Storage</RootNamespace> + <AssemblyName>Tango.MachineStudio.Storage</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>..\..\..\Build\Machine Studio\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>..\..\..\Build\Machine Studio\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="MahApps.Metro, Version=1.5.0.23, Culture=neutral, PublicKeyToken=f4fb5a3c4d1e5b4f, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\MahApps.Metro.1.5.0\lib\net45\MahApps.Metro.dll</HintPath> + </Reference> + <Reference Include="MaterialDesignColors, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\MaterialDesignColors.1.1.2\lib\net45\MaterialDesignColors.dll</HintPath> + </Reference> + <Reference Include="MaterialDesignThemes.Wpf, Version=2.3.1.953, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\MaterialDesignThemes.2.3.1.953\lib\net45\MaterialDesignThemes.Wpf.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\..\packages\MahApps.Metro.1.5.0\lib\net45\System.Windows.Interactivity.dll</HintPath> + </Reference> + <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="..\..\..\Versioning\GlobalVersionInfo.cs"> + <Link>GlobalVersionInfo.cs</Link> + </Compile> + <Compile Include="Converters\StorageItemToImageConverter.cs" /> + <Compile Include="Helpers\FileIconHelper.cs" /> + <Compile Include="Models\StorageFileHandlerModel.cs" /> + <Compile Include="Models\StorageFileHandlerType.cs" /> + <Compile Include="StorageModule.cs" /> + <Compile Include="ViewModelLocator.cs" /> + <Compile Include="ViewModels\MainViewVM.cs" /> + <Compile Include="Views\MainView.xaml.cs"> + <DependentUpon>MainView.xaml</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <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="app.config" /> + <None Include="packages.config" /> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\Tango.BL\Tango.BL.csproj"> + <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project> + <Name>Tango.BL</Name> + </ProjectReference> + <ProjectReference Include="..\..\..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</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.SharedUI\Tango.SharedUI.csproj"> + <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project> + <Name>Tango.SharedUI</Name> + </ProjectReference> + <ProjectReference Include="..\..\..\Tango.Transport\Tango.Transport.csproj"> + <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> + <Name>Tango.Transport</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.MachineStudio.Common\Tango.MachineStudio.Common.csproj"> + <Project>{cb0b0aa2-bb24-4bca-a720-45e397684e12}</Project> + <Name>Tango.MachineStudio.Common</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Page Include="Views\MainView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + </ItemGroup> + <ItemGroup> + <Resource Include="Images\file.png" /> + <Resource Include="Images\folder.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Images\storage.png" /> + </ItemGroup> + <ItemGroup /> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModelLocator.cs new file mode 100644 index 000000000..858fa9209 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModelLocator.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.DI; +using Tango.MachineStudio.Storage.ViewModels; + +namespace Tango.MachineStudio.Storage +{ + public static class ViewModelLocator + { + /// <summary> + /// Initializes a new instance of the ViewModelLocator class. + /// </summary> + static ViewModelLocator() + { + TangoIOC.Default.Register<MainViewVM>(); + } + + public static MainViewVM MainViewVM + { + get + { + return TangoIOC.Default.GetInstance<MainViewVM>(); + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs new file mode 100644 index 000000000..4db48c636 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/ViewModels/MainViewVM.cs @@ -0,0 +1,404 @@ +using Microsoft.Win32; +using System; +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 Tango.Core.Commands; +using Tango.Core.IO; +using Tango.Integration.ExternalBridge; +using Tango.Integration.Storage; +using Tango.MachineStudio.Common; +using Tango.MachineStudio.Common.FirmwareUpgrade; +using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.Common.StudioApplication; +using Tango.MachineStudio.Storage.Models; + +namespace Tango.MachineStudio.Storage.ViewModels +{ + public class MainViewVM : StudioViewModel + { + public event EventHandler CurrentFolderChanged; + + private IStudioApplicationManager _applicationManager; + private INotificationProvider _notification; + private IFirmwareUpgrader _firmwareUpgrader; + private bool _machine_operator_changed = true; + + private StorageManager _storageManager; + public StorageManager StorageManager + { + get { return _storageManager; } + set { _storageManager = value; RaisePropertyChangedAuto(); } + } + + private StorageItem _selectedStorageItem; + public StorageItem SelectedStorageItem + { + get { return _selectedStorageItem; } + set { _selectedStorageItem = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private String _currentPath; + public String CurrentPath + { + get { return _currentPath; } + set { _currentPath = value; RaisePropertyChangedAuto(); } + } + + public ObservableCollection<StorageFileHandlerModel> FileHandlers { get; set; } + + public RelayCommand BackCommand { get; set; } + + public RelayCommand RefreshCommand { get; set; } + + public RelayCommand GoCommand { get; set; } + + public RelayCommand<StorageFileHandlerModel> CancelFileHandlerCommand { get; set; } + + public RelayCommand<StorageFileHandlerModel> OpenFileHandlerCommand { get; set; } + + public RelayCommand<StorageFileHandlerModel> RemoveFileHandlerCommand { get; set; } + + public RelayCommand DownloadFileCommand { get; set; } + + public RelayCommand DeleteFileCommand { get; set; } + + public RelayCommand CreateFolderCommand { get; set; } + + public RelayCommand DeleteFolderCommand { get; set; } + + public RelayCommand UploadFileCommand { get; set; } + + public RelayCommand UploadVersionCommand { get; set; } + + public RelayCommand ValidateVersionCommand { get; set; } + + public RelayCommand ActivateVersionCommand { get; set; } + + public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, IFirmwareUpgrader firmwareUpgrader) + { + _applicationManager = applicationManager; + _notification = notificationProvider; + _firmwareUpgrader = firmwareUpgrader; + _applicationManager.ConnectedMachineChanged += _applicationManager_ConnectedMachineChanged; + + FileHandlers = new ObservableCollection<StorageFileHandlerModel>(); + + GoCommand = new RelayCommand(() => NavigateToPath(CurrentPath), () => StorageManager != null); + BackCommand = new RelayCommand(NavigateBack, () => StorageManager != null && StorageManager.CurrentFolder.Parent != null); + CancelFileHandlerCommand = new RelayCommand<StorageFileHandlerModel>(CancelFileHandler); + OpenFileHandlerCommand = new RelayCommand<StorageFileHandlerModel>(OpenFileHandler); + RefreshCommand = new RelayCommand(Refresh, () => StorageManager != null); + RemoveFileHandlerCommand = new RelayCommand<StorageFileHandlerModel>(RemoveFileHandler); + DownloadFileCommand = new RelayCommand(DownloadFile, () => StorageManager != null && SelectedStorageItem != null && SelectedStorageItem is StorageFile); + DeleteFileCommand = new RelayCommand(DeleteFile, () => StorageManager != null && SelectedStorageItem != null && SelectedStorageItem is StorageFile); + CreateFolderCommand = new RelayCommand(CreateFolder, () => StorageManager != null && StorageManager.CurrentFolder != null); + DeleteFolderCommand = new RelayCommand(DeleteFolder, () => StorageManager != null && SelectedStorageItem != null && SelectedStorageItem is StorageFolder); + UploadFileCommand = new RelayCommand(UploadFile, () => StorageManager != null && StorageManager.CurrentFolder != null); + UploadVersionCommand = new RelayCommand(UploadVersion, () => StorageManager != null && StorageManager.CurrentFolder != null); + ValidateVersionCommand = new RelayCommand(ValidateVersion, () => StorageManager != null && StorageManager.CurrentFolder != null); + ActivateVersionCommand = new RelayCommand(ActivateVersion, () => StorageManager != null && StorageManager.CurrentFolder != null); + } + + private void UploadFile() + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Title = "Selected a file to upload"; + if (dlg.ShowDialog().Value) + { + UploadFile(dlg.FileName); + } + } + + private async void DeleteFolder() + { + if (SelectedStorageItem == null) return; + + if (_notification.ShowQuestion("Are you sure you want to delete the selected folder?")) + { + try + { + IsFree = false; + await StorageManager.DeleteItem(SelectedStorageItem); + Refresh(); + } + catch (Exception ex) + { + _notification.ShowError($"Error deleting the selected folder.\n{ex.Message}"); + } + + IsFree = true; + } + } + + private async void CreateFolder() + { + try + { + var name = _notification.ShowTextInput("Enter Folder Name", ""); + + if (!String.IsNullOrWhiteSpace(name)) + { + IsFree = false; + await StorageManager.CreateFolder(Path.Combine(StorageManager.CurrentPath, name)); + Refresh(); + } + } + catch (Exception ex) + { + _notification.ShowError($"Error creating the new folder.\n{ex.Message}"); + } + + IsFree = true; + } + + private async void DeleteFile() + { + if (SelectedStorageItem == null) return; + + if (_notification.ShowQuestion("Are you sure you want to delete the selected file?")) + { + try + { + IsFree = false; + await StorageManager.DeleteItem(SelectedStorageItem); + Refresh(); + } + catch (Exception ex) + { + _notification.ShowError($"Error deleting the selected file.\n{ex.Message}"); + } + + IsFree = true; + } + } + + private void DownloadFile() + { + DownloadStorageItem(SelectedStorageItem as StorageFile); + } + + private void OpenFileHandler(StorageFileHandlerModel handler) + { + ShowInExplorer(handler.FilePath); + } + + private async void CancelFileHandler(StorageFileHandlerModel handler) + { + await handler.Handler.Cancel(); + } + + private void _applicationManager_ConnectedMachineChanged(object sender, IExternalBridgeClient e) + { + _machine_operator_changed = true; + + if (IsVisible) + { + Initialize(); + } + } + + public override void OnApplicationReady() + { + + } + + public override void OnNavigatedTo() + { + base.OnNavigatedTo(); + + if (_machine_operator_changed) + { + _machine_operator_changed = false; + Initialize(); + } + } + + private async void NavigateToPath(String path, bool raiseEvent = true) + { + IsFree = false; + + try + { + await StorageManager.GetFolder(path); + CurrentPath = StorageManager.CurrentPath; + + if (raiseEvent) + { + CurrentFolderChanged?.Invoke(this, new EventArgs()); + } + } + catch (Exception ex) + { + _notification.ShowError($"Error navigating to the specified path.\n{ex.Message}"); + } + + IsFree = true; + + InvalidateRelayCommands(); + } + + private async void Initialize() + { + if (_applicationManager.ConnectedMachine != null) + { + try + { + StorageManager = _applicationManager.ConnectedMachine.CreateStorageManager(); + await StorageManager.GetStorageDrive(); + await StorageManager.GetRootFolder(); + CurrentPath = StorageManager.StorageDrive.Root; + } + catch (Exception ex) + { + _notification.ShowError($"An error occurred while trying to initialize the storage manager.\n{ex.Message}"); + } + + InvalidateRelayCommands(); + } + } + + public void OnStorageItemDoubleClicked(StorageItem storageItem) + { + if (storageItem is StorageFolder && storageItem != null) + { + NavigateToPath(storageItem.Path); + } + else + { + DownloadStorageItem(storageItem as StorageFile); + } + } + + private void NavigateBack() + { + NavigateToPath(StorageManager.CurrentFolder.Parent); + } + + private void Refresh() + { + NavigateToPath(StorageManager.CurrentFolder.Path, false); + } + + private async void DownloadStorageItem(StorageFile storageFile) + { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Title = "Select download location"; + dlg.DefaultExt = Path.GetExtension(storageFile.Path); + dlg.FileName = storageFile.Name; + if (dlg.ShowDialog().Value) + { + FileStream fs = new FileStream(dlg.FileName, FileMode.Create); + var handler = await StorageManager.DownloadFile(storageFile, fs); + handler.Completed += (_, __) => + { + fs.Dispose(); + }; + + handler.Canceled += (_, __) => + { + fs.Dispose(); + File.Delete(dlg.FileName); + }; + + handler.Failed += (_, __) => + { + fs.Dispose(); + File.Delete(dlg.FileName); + }; + + FileHandlers.Insert(0, new StorageFileHandlerModel(handler, dlg.FileName, StorageFileHandlerType.Download)); + } + } + + private async void UploadFile(String path) + { + FileStream fs = new FileStream(path, FileMode.Open); + var handler = await StorageManager.UploadFile(Path.Combine(StorageManager.CurrentPath, Path.GetFileName(path)), fs); + handler.Completed += (_, __) => + { + fs.Dispose(); + }; + + handler.Canceled += (_, __) => + { + fs.Dispose(); + File.Delete(path); + }; + + handler.Failed += (_, __) => + { + fs.Dispose(); + File.Delete(path); + }; + + FileHandlers.Insert(0, new StorageFileHandlerModel(handler, path, StorageFileHandlerType.Upload)); + } + + /// <summary> + /// Shows the file in explorer. + /// </summary> + /// <param name="path">Name of the file/folder.</param> + public static void ShowInExplorer(String path) + { + Process.Start("explorer.exe", string.Format("/select,\"{0}\"", path)); + } + + private void RemoveFileHandler(StorageFileHandlerModel handler) + { + if (handler.Handler.Status == StorageFileHandlerStatus.Active) + { + if (_notification.ShowQuestion("Are you sure you want to cancel this file operation?")) + { + handler.Handler.Cancel(); + FileHandlers.Remove(handler); + } + } + else + { + FileHandlers.Remove(handler); + } + } + + private void UploadVersion() + { + _firmwareUpgrader.InvokeUpgradeUI(); + } + + private async void ValidateVersion() + { + using (_notification.PushTaskItem("Validating firmware version...")) + { + try + { + await _applicationManager.ConnectedMachine.ValidateFirmwareVersion(StorageManager.CurrentPath); + _notification.ShowInfo($"Version validated successfully!"); + } + catch (Exception ex) + { + _notification.ShowError($"Error validating firmware version.\n{ex.FlattenMessage()}"); + } + } + } + + private async void ActivateVersion() + { + using (_notification.PushTaskItem("Activating firmware version...")) + { + try + { + await _applicationManager.ConnectedMachine.ActivateFirmwareVersion(StorageManager.CurrentPath); + _notification.ShowInfo($"Version activated successfully!"); + } + catch (Exception ex) + { + _notification.ShowError($"Error activating firmware version.\n{ex.FlattenMessage()}"); + } + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml new file mode 100644 index 000000000..e59837d49 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml @@ -0,0 +1,332 @@ +<UserControl x:Class="Tango.MachineStudio.Storage.Views.MainView" + 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:vm="clr-namespace:Tango.MachineStudio.Storage.ViewModels" + xmlns:global="clr-namespace:Tango.MachineStudio.Storage" + xmlns:mahApps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:localConverters="clr-namespace:Tango.MachineStudio.Storage.Converters" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:local="clr-namespace:Tango.MachineStudio.Storage.Views" + mc:Ignorable="d" + d:DesignHeight="1080" x:Name="control" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}"> + + <UserControl.Resources> + <localConverters:StorageItemToImageConverter x:Key="StorageItemToImageConverter" /> + <converters:ByteArrayToFileSizeConverter x:Key="ByteArrayToFileSizeConverter" /> + </UserControl.Resources> + + <Grid> + <Grid> + <DockPanel> + + <Border Background="#ECECEC" Margin="20" Width="350" CornerRadius="5" IsEnabled="{Binding IsFree}"> + <Border.Effect> + <DropShadowEffect ShadowDepth="0" BlurRadius="10" Color="Gray" /> + </Border.Effect> + <DockPanel> + <TextBlock HorizontalAlignment="Left" DockPanel.Dock="Top" Margin="30 55 20 20" FontSize="30" FontStyle="Italic" Foreground="{StaticResource AccentColorBrush}" FontWeight="Bold">ACTIONS</TextBlock> + <StackPanel Margin="0 40 0 0"> + <Button Command="{Binding CreateFolderCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="FolderPlus" Foreground="#E79F20" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">CREATE FOLDER</TextBlock> + </DockPanel> + </Button> + <Button Command="{Binding DeleteFolderCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="FolderRemove" Foreground="#E14141" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">DELETE FOLDER</TextBlock> + </DockPanel> + </Button> + <Separator/> + <Button Command="{Binding UploadFileCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="Upload" Foreground="#E97E28" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">UPLOAD FILE</TextBlock> + </DockPanel> + </Button> + <Button Command="{Binding DownloadFileCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="Download" Foreground="#2DD42D" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">DOWNLOAD FILE</TextBlock> + </DockPanel> + </Button> + <Separator/> + <Button Command="{Binding DeleteFileCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="Delete" Foreground="#E14141" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">DELETE FILE</TextBlock> + </DockPanel> + </Button> + <Separator/> + <Button Command="{Binding UploadVersionCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="BriefcaseUpload" Foreground="#833CEC" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">UPGRADE VERSION</TextBlock> + </DockPanel> + </Button> + <Button Command="{Binding ValidateVersionCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="CheckAll" Foreground="#682EBE" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">VALIDATE VERSION</TextBlock> + </DockPanel> + </Button> + <Button Command="{Binding ActivateVersionCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="Flash" Foreground="#532990" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">ACTIVATE VERSION</TextBlock> + </DockPanel> + </Button> + <Separator/> + <Button Command="{Binding RefreshCommand}" Margin="0 5 0 0" Style="{StaticResource MaterialDesignFlatButton}" Padding="20 10" Height="Auto" Foreground="#363636" HorizontalContentAlignment="Left"> + <DockPanel> + <materialDesign:PackIcon Kind="Refresh" Foreground="{StaticResource AccentColorBrush}" Width="32" Height="32" /> + <TextBlock VerticalAlignment="Center" Margin="20 0 0 0" FontSize="18">REFRESH</TextBlock> + </DockPanel> + </Button> + </StackPanel> + </DockPanel> + </Border> + + <Grid> + <DockPanel> + <Border DockPanel.Dock="Top" Background="#ECECEC" Margin="20" Height="150" CornerRadius="5" Padding="20 0"> + <Border.Effect> + <DropShadowEffect ShadowDepth="0" BlurRadius="10" Color="Gray" /> + </Border.Effect> + <DockPanel> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center" DockPanel.Dock="Left"> + <Button Style="{StaticResource MaterialDesignFlatButton}" Width="80" Height="80" Padding="0" Command="{Binding BackCommand}" IsEnabled="{Binding IsFree}"> + <materialDesign:PackIcon Kind="ArrowLeft" Width="60" Height="60" /> + </Button> + + <Button Style="{StaticResource MaterialDesignFlatButton}" Width="80" Height="80" Padding="0" Command="{Binding RefreshCommand}" IsEnabled="{Binding IsFree}"> + <materialDesign:PackIcon Kind="Refresh" Width="60" Height="60" /> + </Button> + </StackPanel> + + <Border DockPanel.Dock="Right" Width="250" Margin="0 20" Background="{StaticResource AccentColorBrush}" TextElement.Foreground="White" CornerRadius="5" Padding="10"> + <DockPanel> + <TextBlock DockPanel.Dock="Top" FontSize="18" FontWeight="Bold" FontStyle="Italic" HorizontalAlignment="Center">STORAGE</TextBlock> + <StackPanel> + <TextBlock Margin="0 5 0 0"> + <Run>Root:</Run> + <Run FontWeight="Bold" FontStyle="Italic" Text="{Binding StorageManager.StorageDrive.Root}"></Run> + </TextBlock> + <TextBlock Margin="0 5 0 0"> + <Run>Capacity:</Run> + <Run FontWeight="Bold" FontStyle="Italic" Text="{Binding StorageManager.StorageDrive.Capacity,Converter={StaticResource ByteArrayToFileSizeConverter}}"></Run> + </TextBlock> + <TextBlock Margin="0 5 0 0"> + <Run>Free Space:</Run> + <Run FontWeight="Bold" FontStyle="Italic" Text="{Binding StorageManager.StorageDrive.FreeSpace,Converter={StaticResource ByteArrayToFileSizeConverter}}"></Run> + </TextBlock> + </StackPanel> + </DockPanel> + </Border> + + <DockPanel VerticalAlignment="Center" Margin="50 0 50 0"> + <Button Margin="10 0 0 0" DockPanel.Dock="Right" Style="{StaticResource MaterialDesignFlatButton}" Width="80" Height="80" Padding="0" Command="{Binding GoCommand}" IsEnabled="{Binding IsFree}"> + <materialDesign:PackIcon Kind="SubdirectoryArrowRight" Width="60" Height="60" /> + </Button> + <Border Height="35" Background="{StaticResource AccentColorBrush}" CornerRadius="5" Padding="5" IsEnabled="{Binding IsFree}"> + <TextBox Style="{x:Null}" Background="Transparent" Foreground="White" FontSize="18" BorderThickness="0" CaretBrush="White" Text="{Binding CurrentPath,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> + <TextBox.InputBindings> + <KeyBinding Command="{Binding Path=GoCommand}" Key="Enter"/> + </TextBox.InputBindings> + </TextBox> + </Border> + </DockPanel> + </DockPanel> + </Border> + + <Grid Margin="20"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="100*" MinHeight="150" /> + <RowDefinition Height="5" /> + <RowDefinition Height="40*" MinHeight="150" /> + </Grid.RowDefinitions> + <Border Background="#8BFFFFFF" CornerRadius="5" Padding="20"> + <DataGrid x:Name="gridStorageItems" IsEnabled="{Binding IsFree}" MouseDoubleClick="DataGrid_MouseDoubleClick" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserSortColumns="True" IsReadOnly="True" Background="Transparent" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding StorageManager.CurrentFolder.Items}" SelectedItem="{Binding SelectedStorageItem}"> + <DataGrid.CellStyle> + <Style 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> + </DataGrid.CellStyle> + <DataGrid.Columns> + <DataGridTemplateColumn Width="100"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <Image Width="32" Height="32" HorizontalAlignment="Left" Source="{Binding Converter={StaticResource StorageItemToImageConverter}}"></Image> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="NAME" Width="1*" SortMemberPath="Name"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding Name}" VerticalAlignment="Center" FontSize="14" /> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="TYPE" Width="150" SortMemberPath="Attribute"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding Attribute}" VerticalAlignment="Center" FontSize="14" /> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="SIZE" Width="150" SortMemberPath="Length"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding Length,Converter={StaticResource ByteArrayToFileSizeConverter},FallbackValue='',TargetNullValue=''}" VerticalAlignment="Center" FontSize="14" /> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="LAST MODIFIED" Width="200" SortMemberPath="LastModified"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding LastModified}" VerticalAlignment="Center" FontSize="14" /> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + </Border> + + <GridSplitter Grid.Row="1" Height="5" VerticalAlignment="Center" HorizontalAlignment="Stretch" Background="Gray" Margin="5 0" /> + + <Border Background="#8BFFFFFF" CornerRadius="5" Padding="20" Grid.Row="3"> + <DockPanel> + <TextBlock DockPanel.Dock="Top" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" FontStyle="Italic" Foreground="{StaticResource AccentColorBrush}" FontWeight="Bold">FILE TRANSFERS</TextBlock> + <DataGrid AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserSortColumns="False" IsReadOnly="True" Background="Transparent" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding FileHandlers}"> + <DataGrid.CellStyle> + <Style 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> + </DataGrid.CellStyle> + <DataGrid.Columns> + <DataGridTemplateColumn Width="100"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <materialDesign:PackIcon Width="32" Height="32" HorizontalAlignment="Left"> + <materialDesign:PackIcon.Style> + <Style TargetType="materialDesign:PackIcon"> + <Setter Property="Kind" Value="Download"></Setter> + <Setter Property="Foreground" Value="#20BB20"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Type}" Value="Upload"> + <Setter Property="Kind" Value="Upload"></Setter> + <Setter Property="Foreground" Value="#E76311"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </materialDesign:PackIcon.Style> + </materialDesign:PackIcon> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="FILE" Width="450"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding FilePath}" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" FontSize="14" /> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="PROGRESS" Width="1*"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <ProgressBar Height="15" Margin="0 0 30 0" VerticalAlignment="Center" Maximum="{Binding Handler.Total,Mode=OneWay}" Value="{Binding Handler.Current,Mode=OneWay}"> + <ProgressBar.Style> + <Style TargetType="ProgressBar"> + <Setter Property="Foreground" Value="#2FD42F"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Handler.Status}" Value="Canceled"> + <Setter Property="Foreground" Value="#EF832B"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding Handler.Status}" Value="Failed"> + <Setter Property="Foreground" Value="#E11A1A"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </ProgressBar.Style> + </ProgressBar> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="STATUS" Width="150"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock Text="{Binding Handler.Status}" VerticalAlignment="Center" FontSize="14" FontWeight="SemiBold" FontStyle="Italic" /> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Width="150"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <ContentControl Content="{Binding}"> + <ContentControl.Style> + <Style TargetType="ContentControl"> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate></DataTemplate> + </Setter.Value> + </Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Handler.Status}" Value="Active"> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Button Command="{Binding Source={x:Reference control},Path=DataContext.CancelFileHandlerCommand}" CommandParameter="{Binding}" Margin="5" Background="#FF6A6A" BorderBrush="#FF6A6A">CANCEL</Button> + </DataTemplate> + </Setter.Value> + </Setter> + </DataTrigger> + <MultiDataTrigger> + <MultiDataTrigger.Conditions> + <Condition Binding="{Binding Handler.Status}" Value="Completed"></Condition> + <Condition Binding="{Binding Type}" Value="Download"></Condition> + </MultiDataTrigger.Conditions> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Button Command="{Binding Source={x:Reference control},Path=DataContext.OpenFileHandlerCommand}" CommandParameter="{Binding}" Margin="5" Background="#2CC62C" BorderBrush="#2CC62C">OPEN</Button> + </DataTemplate> + </Setter.Value> + </Setter> + </MultiDataTrigger> + </Style.Triggers> + </Style> + </ContentControl.Style> + </ContentControl> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Width="60"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <Button Foreground="#FF5A5A" Style="{StaticResource MaterialDesignFlatButton}" Padding="0" Width="24" Height="24" Command="{Binding Source={x:Reference control},Path=DataContext.RemoveFileHandlerCommand}" CommandParameter="{Binding}" Margin="5"> + <materialDesign:PackIcon Kind="Close" Width="24" Height="24" /> + </Button> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + </DockPanel> + </Border> + </Grid> + </Grid> + </DockPanel> + </Grid> + </DockPanel> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml.cs new file mode 100644 index 000000000..5da808b8c --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/Views/MainView.xaml.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; +using Tango.Integration.Storage; +using Tango.MachineStudio.Storage.ViewModels; + +namespace Tango.MachineStudio.Storage.Views +{ + /// <summary> + /// Interaction logic for MainView.xaml + /// </summary> + public partial class MainView : UserControl + { + private MainViewVM _vm; + + public MainView() + { + InitializeComponent(); + Loaded += (_, __) => + { + _vm = DataContext as MainViewVM; + _vm.CurrentFolderChanged += _vm_CurrentFolderChanged; + }; + + } + + private void _vm_CurrentFolderChanged(object sender, EventArgs e) + { + ScrollViewer scrollViewer = gridStorageItems.FindChild<ScrollViewer>(); + scrollViewer.ScrollToVerticalOffset(0); + } + + private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) + { + _vm.OnStorageItemDoubleClicked(gridStorageItems.SelectedItem as StorageItem); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/app.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/app.config new file mode 100644 index 000000000..5d794b958 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/app.config @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> +</configuration>
\ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/packages.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/packages.config new file mode 100644 index 000000000..0580e26aa --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage/packages.config @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="MahApps.Metro" version="1.5.0" targetFramework="net461" /> + <package id="MaterialDesignColors" version="1.1.2" targetFramework="net461" /> + <package id="MaterialDesignThemes" version="2.3.1.953" targetFramework="net461" /> +</packages>
\ No newline at end of file |
