diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-03-22 14:53:04 +0200 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-03-22 14:53:04 +0200 |
| commit | 5a5b63afd5c4ff1d6a1dbd6996ed0a5a494387d0 (patch) | |
| tree | 365313831f036950a1878a8ccd92ab938a7bfabb | |
| parent | d48b2d23515d06a21ad241380986bf8f31773195 (diff) | |
| download | Tango-5a5b63afd5c4ff1d6a1dbd6996ed0a5a494387d0.tar.gz Tango-5a5b63afd5c4ff1d6a1dbd6996ed0a5a494387d0.zip | |
Working on storage provider.
16 files changed, 732 insertions, 4 deletions
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 index f074294b2..4e2ca1882 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/ViewModels/FileSystemViewVM.cs @@ -336,9 +336,13 @@ namespace Tango.FSE.PPCConsole.ViewModels } } - private void DownloadSelectedItems(List<FileSystemItem> items) + private async void DownloadSelectedItems(List<FileSystemItem> items) { - + var result = await StorageProvider.SelectFolder("Select download destination folder"); + if (result) + { + Debug.WriteLine($"Download to {result.SelectedItem}"); + } } private async void RenameFileSystemItem(FileSystemItem item) diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml index 62de7cf48..fcea26001 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Controls/FileSystemControl.xaml @@ -93,7 +93,7 @@ </Border.ContextMenu> <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 x:Name="PART_listbox" IsTextSearchEnabled="True" TextSearch.TextPath="Name" 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> @@ -164,7 +164,7 @@ </Style.Triggers> </Style> </Grid.Style> - <local:FileSystemDataGrid x:Name="PART_datagrid" ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=CurrentItem.Items}" CellStyle="{StaticResource FileSystemCellStyle}"> + <local:FileSystemDataGrid x:Name="PART_datagrid" IsTextSearchEnabled="True" TextSearch.TextPath="Name" 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> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs index b3e832b58..232d1bd45 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs @@ -26,6 +26,7 @@ using Tango.FSE.Common.Notifications; using Tango.FSE.Common.Performance; using Tango.FSE.Common.RemoteDesktop; using Tango.FSE.Common.Resolution; +using Tango.FSE.Common.Storage; using Tango.FSE.Common.SystemInfo; using Tango.Settings; using Tango.SharedUI; @@ -126,6 +127,12 @@ namespace Tango.FSE.Common public IFileSystemProvider FileSystemProvider { get; set; } /// <summary> + /// Gets or sets the storage provider. + /// </summary> + [TangoInject] + public IStorageProvider StorageProvider { get; set; } + + /// <summary> /// Gets or sets the FSE service. /// </summary> [TangoInject] diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/IStorageProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/IStorageProvider.cs new file mode 100644 index 000000000..00ec312a5 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/IStorageProvider.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.Commands; +using Tango.FileSystem; + +namespace Tango.FSE.Common.Storage +{ + public interface IStorageProvider + { + bool UseNativeDialogs { get; set; } + bool IsOpened { get; } + bool IsBusy { get; } + String Title { get; } + String FileName { get; set; } + FileSystemItem CurrentItem { get; set; } + String CurrentPath { get; set; } + ObservableCollection<FileSystemItem> SelectedItems { get; set; } + List<DriveItem> Drives { get; } + RelayCommand OKCommand { get; } + RelayCommand CancelCommand { get; } + RelayCommand BackCommand { get; } + RelayCommand NavigateCommand { get; } + RelayCommand<FileSystemItem> OpenCommand { get; } + RelayCommand<String> NavigateSpecialFolderCommand { get; set; } + RelayCommand<String> NavigateToFolderCommand { get; set; } + + Task<SingleStorageResult> OpenFile(String title, String filter = null, String initialFolder = null); + Task<MultiStorageResult> OpenFiles(String title, String filter = null, String initialFolder = null); + Task<SingleStorageResult> SaveFile(String title, String filter = null, String defaultFileName = null, String defaultExtension = null, String initialFolder = null); + Task<SingleStorageResult> SelectFolder(String title, String initialFolder = null); + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/IStorageResult.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/IStorageResult.cs new file mode 100644 index 000000000..f3c7ddb15 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/IStorageResult.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.Storage +{ + public interface IStorageResult + { + bool Confirmed { get; set; } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/MultiStorageResult.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/MultiStorageResult.cs new file mode 100644 index 000000000..0331d021b --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/MultiStorageResult.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.Storage +{ + public class MultiStorageResult : IStorageResult + { + public bool Confirmed { get; set; } + public List<String> SelectedItems { get; set; } + + public MultiStorageResult() + { + SelectedItems = new List<string>(); + } + + public static implicit operator bool(MultiStorageResult result) + { + return result.SelectedItems != null && result.SelectedItems.Count > 0 && result.Confirmed; + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/SingleStorageResult.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/SingleStorageResult.cs new file mode 100644 index 000000000..0b63aa030 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Storage/SingleStorageResult.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.FSE.Common.Storage +{ + public class SingleStorageResult : IStorageResult + { + public String SelectedItem { get; set; } + public bool Confirmed { get; set; } + + public static implicit operator bool(SingleStorageResult result) + { + return result.SelectedItem != null && result.Confirmed; + } + } +} 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 02df7140f..11a308e3e 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 @@ -140,6 +140,10 @@ <Compile Include="Resolution\IResolutionService.cs" /> <Compile Include="Resolution\ResolutionHelper.cs" /> <Compile Include="Resolution\ResolutionMode.cs" /> + <Compile Include="Storage\IStorageProvider.cs" /> + <Compile Include="Storage\IStorageResult.cs" /> + <Compile Include="Storage\SingleStorageResult.cs" /> + <Compile Include="Storage\MultiStorageResult.cs" /> <Compile Include="SystemInfo\ISystemInfoProvider.cs" /> <Compile Include="Threading\IDispatcherProvider.cs" /> <Compile Include="Web\FSEWebClient.cs" /> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/DefaultStorageProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/DefaultStorageProvider.cs new file mode 100644 index 000000000..c37400cf6 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Storage/DefaultStorageProvider.cs @@ -0,0 +1,389 @@ +using Microsoft.Win32; +using Microsoft.WindowsAPICodePack.Dialogs; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using Tango.Core; +using Tango.Core.Commands; +using Tango.Core.DI; +using Tango.FileSystem; +using Tango.FileSystem.Network; +using Tango.FSE.Common.Notifications; +using Tango.FSE.Common.Storage; + +namespace Tango.FSE.UI.Storage +{ + public class DefaultStorageProvider : ExtendedObject, IStorageProvider + { + private FileSystemManager _manager; + private Action _okCompletionAction; + private Action _cancelCompletionAction; + + [TangoInject(Mode = TangoInjectMode.WhenAvailable)] + private INotificationProvider NotificationProvider { get; set; } + + public bool UseNativeDialogs { get; set; } = false; + + private bool _isOpened; + public bool IsOpened + { + get { return _isOpened; } + private set { _isOpened = value; RaisePropertyChangedAuto(); } + } + + private String _title; + public String Title + { + get { return _title; } + private set { _title = value; RaisePropertyChangedAuto(); } + } + + private String _fileName; + public String FileName + { + get { return _fileName; } + set { _fileName = value; RaisePropertyChangedAuto(); } + } + + 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(); } + } + + private bool _isBusy; + public bool IsBusy + { + get { return _isBusy; } + private set { _isBusy = value; RaisePropertyChangedAuto(); } + } + + private List<DriveItem> _drives; + public List<DriveItem> Drives + { + get { return _drives; } + set { _drives = value; RaisePropertyChangedAuto(); } + } + + public ObservableCollection<FileSystemItem> SelectedItems { get; set; } + + public RelayCommand OKCommand { get; } + public RelayCommand CancelCommand { get; } + public RelayCommand BackCommand { get; set; } + public RelayCommand NavigateCommand { get; set; } + public RelayCommand<FileSystemItem> OpenCommand { get; set; } + public RelayCommand<String> NavigateSpecialFolderCommand { get; set; } + public RelayCommand<String> NavigateToFolderCommand { get; set; } + + public DefaultStorageProvider() + { + _manager = new FileSystemManager(); + SelectedItems = new ObservableCollection<FileSystemItem>(); + + NavigateCommand = new RelayCommand(NavigateToCurrentPath); + OpenCommand = new RelayCommand<FileSystemItem>(OpenFileSystemItem); + BackCommand = new RelayCommand(NavigateBack, () => !(CurrentItem is FolderItem) || !(CurrentItem as FolderItem).IsRoot); + NavigateSpecialFolderCommand = new RelayCommand<string>(NavigateToSpecialFolder); + NavigateToFolderCommand = new RelayCommand<string>(async (x) => await Navigate(x)); + OKCommand = new RelayCommand(OnAccept); + CancelCommand = new RelayCommand(OnCancel); + } + + public Task<SingleStorageResult> OpenFile(string title, string filter = null, string initialFolder = null) + { + if (UseNativeDialogs) + { + return OpenFileNative(title, filter, initialFolder); + } + else + { + return null; + } + } + + public Task<MultiStorageResult> OpenFiles(string title, string filter = null, string initialFolder = null) + { + if (UseNativeDialogs) + { + return OpenFilesNative(title, filter, initialFolder); + } + else + { + return null; + } + } + + public Task<SingleStorageResult> SaveFile(string title, string filter = null, string defaultFileName = null, string defaultExtension = null, string initialFolder = null) + { + if (UseNativeDialogs) + { + return SaveFileNative(title, filter, defaultFileName, defaultExtension, initialFolder); + } + else + { + return null; + } + } + + public async Task<SingleStorageResult> SelectFolder(string title, string initialFolder = null) + { + if (UseNativeDialogs) + { + return await SelectFolderNative(title, initialFolder); + } + else + { + var _completionSource = new TaskCompletionSource<SingleStorageResult>(); + + var root = await _manager.GetFolder(String.Empty); + Drives = (root as IFileSystemContainer).Items.Cast<DriveItem>().ToList(); + + CurrentItem = await _manager.GetFolder(Environment.CurrentDirectory); + IsOpened = true; + + _okCompletionAction = () => + { + SingleStorageResult result = new SingleStorageResult() + { + Confirmed = true, + SelectedItem = SelectedItems.First().Path, + }; + + _completionSource.SetResult(result); + }; + + _cancelCompletionAction = () => + { + _completionSource.SetResult(new SingleStorageResult()); + }; + + return await _completionSource.Task; + } + } + + #region Private Methods + + private void OnAccept() + { + IsOpened = false; + _okCompletionAction?.Invoke(); + } + + private void OnCancel() + { + IsOpened = false; + _cancelCompletionAction?.Invoke(); + } + + private async void NavigateToSpecialFolder(string folder) + { + Environment.SpecialFolder specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), folder); + await Navigate(null, specialFolder); + } + + private async void NavigateBack() + { + if (CurrentItem.Path.Length == 3) + { + await Navigate(null); + } + else + { + String parent = Path.GetDirectoryName(CurrentItem.Path); + await Navigate(parent); + } + } + + private async void NavigateToCurrentPath() + { + await Navigate(CurrentPath); + } + + private async void OpenFileSystemItem(FileSystemItem item) + { + if (item == null) return; + + if (item.Type == FileSystemItemType.Folder || item.Type == FileSystemItemType.Drive) + { + await Navigate(item.Path); + } + else if (item.Type == FileSystemItemType.File) + { + //TODO: Download/Open file?... + } + } + + private async Task Navigate(String path, Environment.SpecialFolder? specialFolder = null) + { + try + { + IsBusy = true; + + Mouse.OverrideCursor = Cursors.AppStarting; + + if (path != null) + { + CurrentItem = await _manager.GetFolder(path) as FileSystemItem; + } + else if (specialFolder != null) + { + CurrentItem = await _manager.GetFolder(specialFolder.Value) as FileSystemItem; + } + else + { + CurrentItem = await _manager.GetFolder(String.Empty) as FileSystemItem; + } + } + catch (Exception ex) + { + IsBusy = false; + Mouse.OverrideCursor = null; + await NotificationProvider.ShowError($"Error navigating to the specified path.\n{ex.FlattenMessage()}"); + } + finally + { + IsBusy = false; + Mouse.OverrideCursor = null; + } + } + + private void OnCurrentItemChanged() + { + CurrentPath = CurrentItem.Path; + InvalidateRelayCommands(); + } + + #endregion + + #region Native + + public Task<SingleStorageResult> OpenFileNative(string title, string filter = null, string initialFolder = null) + { + SingleStorageResult result = new SingleStorageResult(); + + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Multiselect = false; + dlg.Title = title; + + if (filter != null) + { + dlg.Filter = filter; + } + + if (initialFolder != null) + { + dlg.InitialDirectory = initialFolder; + } + + if (dlg.ShowDialog(Application.Current.MainWindow).Value) + { + result.Confirmed = true; + result.SelectedItem = dlg.FileName; + } + + return Task.FromResult(result); + } + + public Task<MultiStorageResult> OpenFilesNative(string title, string filter = null, string initialFolder = null) + { + MultiStorageResult result = new MultiStorageResult(); + + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Multiselect = false; + dlg.Title = title; + dlg.Multiselect = true; + + if (filter != null) + { + dlg.Filter = filter; + } + + if (initialFolder != null) + { + dlg.InitialDirectory = initialFolder; + } + + if (dlg.ShowDialog(Application.Current.MainWindow).Value) + { + result.Confirmed = true; + result.SelectedItems = dlg.FileNames.ToList(); + } + + return Task.FromResult(result); + } + + public Task<SingleStorageResult> SaveFileNative(string title, string filter = null, string defaultFileName = null, string defaultExtension = null, string initialFolder = null) + { + SingleStorageResult result = new SingleStorageResult(); + + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Title = title; + + if (defaultFileName != null) + { + dlg.FileName = defaultFileName; + } + + if (defaultExtension != null) + { + dlg.DefaultExt = defaultExtension; + } + + if (filter != null) + { + dlg.Filter = filter; + } + + if (initialFolder != null) + { + dlg.InitialDirectory = initialFolder; + } + + if (dlg.ShowDialog(Application.Current.MainWindow).Value) + { + result.Confirmed = true; + result.SelectedItem = dlg.FileName; + } + + return Task.FromResult(result); + } + + public Task<SingleStorageResult> SelectFolderNative(string title, string initialFolder = null) + { + SingleStorageResult result = new SingleStorageResult(); + + CommonOpenFileDialog dlg = new CommonOpenFileDialog(); + dlg.Title = title; + dlg.IsFolderPicker = true; + + if (initialFolder != null) + { + dlg.InitialDirectory = initialFolder; + } + + if (dlg.ShowDialog(Application.Current.MainWindow) == CommonFileDialogResult.Ok) + { + result.Confirmed = true; + result.SelectedItem = dlg.FileName; + } + + return Task.FromResult(result); + } + + #endregion + } +} 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 5a73dba99..ef32b02e5 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 @@ -26,6 +26,7 @@ <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> + <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> @@ -61,6 +62,12 @@ <Reference Include="MaterialDesignThemes.Wpf, Version=3.0.1.920, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\packages\MaterialDesignThemes.3.0.1\lib\net45\MaterialDesignThemes.Wpf.dll</HintPath> </Reference> + <Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\..\packages\WindowsAPICodePack-Core.1.1.1\lib\Microsoft.WindowsAPICodePack.dll</HintPath> + </Reference> + <Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\..\packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath> + </Reference> <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> </Reference> @@ -161,6 +168,7 @@ <Compile Include="Performance\DefaultPerformanceProvider.cs" /> <Compile Include="RemoteDesktop\DefaultRemoteDesktopProvider.cs" /> <Compile Include="Resolution\DefaultResolutionService.cs" /> + <Compile Include="Storage\DefaultStorageProvider.cs" /> <Compile Include="SystemInfo\DefaultSystemInfoProvider.cs" /> <Compile Include="Threading\DefaultDispatcherProvider.cs" /> <Compile Include="ViewModelLocator.cs" /> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs index 6a3cf610a..b7edc40a8 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs @@ -20,6 +20,7 @@ using Tango.FSE.Common.Notifications; using Tango.FSE.Common.Performance; using Tango.FSE.Common.RemoteDesktop; using Tango.FSE.Common.Resolution; +using Tango.FSE.Common.Storage; using Tango.FSE.Common.SystemInfo; using Tango.FSE.Common.Threading; using Tango.FSE.Common.Web; @@ -37,6 +38,7 @@ using Tango.FSE.UI.Notifications; using Tango.FSE.UI.Performance; using Tango.FSE.UI.RemoteDesktop; using Tango.FSE.UI.Resolution; +using Tango.FSE.UI.Storage; using Tango.FSE.UI.SystemInfo; using Tango.FSE.UI.Threading; using Tango.FSE.UI.ViewModels; @@ -64,6 +66,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Unregister<ISystemInfoProvider>(); TangoIOC.Default.Unregister<ILoggingProvider>(); TangoIOC.Default.Unregister<IFileSystemProvider>(); + TangoIOC.Default.Unregister<IStorageProvider>(); //TangoIOC.Default.Unregister<ExternalBridgeScanner>(); //TangoIOC.Default.Unregister<IDiagnosticsFrameProvider>(); //TangoIOC.Default.Unregister<IEventLogger>(); @@ -89,6 +92,7 @@ namespace Tango.FSE.UI TangoIOC.Default.Register<ISystemInfoProvider, DefaultSystemInfoProvider>(); TangoIOC.Default.Register<ILoggingProvider, DefaultLoggingProvider>(); TangoIOC.Default.Register<IFileSystemProvider, DefaultFileSystemProvider>(); + TangoIOC.Default.Register<IStorageProvider, DefaultStorageProvider>(); TangoIOC.Default.Register<MainWindowVM>(); TangoIOC.Default.Register<MainViewVM>(); diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs index 4472bbf1b..1c6a0b5a8 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs @@ -130,6 +130,11 @@ namespace Tango.FSE.UI.ViewModels { try { + + var s = await StorageProvider.SelectFolder("Select download destination folder"); + + return; + if (!Validate()) { return; 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 07f40d18c..6a386947f 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml @@ -180,6 +180,184 @@ </Grid> <!--DIALOGS--> + <!--STORAGE--> + <Grid x:Name="gridStorage" Background="{StaticResource FSE_SemiTransparentBrush}" Visibility="{Binding StorageProvider.IsOpened,Converter={StaticResource BooleanToVisibilityConverter}}"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="1*" /> + <ColumnDefinition Width="10*" /> + <ColumnDefinition Width="1*" /> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="1*" /> + <RowDefinition Height="10*" /> + <RowDefinition Height="1*" /> + </Grid.RowDefinitions> + <Grid RenderTransformOrigin="0.5,0.5" Grid.Column="1" Grid.Row="1"> + <Grid.Style> + <Style TargetType="Grid"> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="0" ScaleY="0" /> + </Setter.Value> + </Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding StorageProvider.IsOpened}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" From="0" To="1" Duration="00:00:0.1" /> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="0" To="1" Duration="00:00:0.1" /> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + <DataTrigger.ExitActions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" From="1" To="0" Duration="00:00:0.1" /> + <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="1" To="0" Duration="00:00:0.1" /> + </Storyboard> + </BeginStoryboard> + </DataTrigger.ExitActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Grid.Style> + + <Border Background="{StaticResource FSE_PrimaryBackgroundBrush}" CornerRadius="5" Margin="10"> + <Border.Effect> + <DropShadowEffect BlurRadius="10" /> + </Border.Effect> + <Grid ClipToBounds="True"> + <Grid> + <DockPanel> + <Grid DockPanel.Dock="Bottom"> + <Border Background="{StaticResource FSE_PrimaryBackgroundBrush}" CornerRadius="0 0 5 5" Padding="10"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> + <Button Height="40" MinWidth="150" Margin="0 0 5 0" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Command="{Binding StorageProvider.CancelCommand}" Visibility="{Binding DataContext.CanClose,Converter={StaticResource BooleanToVisibilityConverter}}">CANCEL</Button> + <Button Height="40" MinWidth="150" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Command="{Binding StorageProvider.OKCommand}">OK</Button> + </StackPanel> + </Border> + <Rectangle VerticalAlignment="Top" DockPanel.Dock="Bottom" Stroke="{StaticResource FSE_BorderBrush}" StrokeThickness="1" StrokeDashArray="5" /> + </Grid> + + <!--FILE SYSTEM CONTROL HERE--> + <DockPanel Margin="40 40 40 20"> + + <DockPanel DockPanel.Dock="Top" Height="30"> + <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 StorageProvider.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 Command="{Binding StorageProvider.BackCommand}" 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> + <Grid> + <Border IsHitTestVisible="False" Visibility="{Binding StorageProvider.IsBusy,Converter={StaticResource BooleanToVisibilityConverter}}"> + <Border.Background> + <LinearGradientBrush> + <GradientStop Offset="0" Color="Transparent" /> + <GradientStop Offset="0.5" Color="#6303A9F4" /> + <GradientStop Offset="1" Color="Transparent" /> + </LinearGradientBrush> + </Border.Background> + <Border.Style> + <Style TargetType="Border"> + <Style.Triggers> + <DataTrigger Binding="{Binding StorageProvider.IsBusy}" Value="True"> + <DataTrigger.EnterActions> + <BeginStoryboard Name="loadingStory"> + <Storyboard> + <DoubleAnimation Storyboard.TargetProperty="Background.GradientStops[1].Offset" From="0" To="1" AutoReverse="True" RepeatBehavior="Forever" /> + </Storyboard> + </BeginStoryboard> + </DataTrigger.EnterActions> + <DataTrigger.ExitActions> + <RemoveStoryboard BeginStoryboardName="loadingStory" /> + </DataTrigger.ExitActions> + </DataTrigger> + </Style.Triggers> + </Style> + </Border.Style> + </Border> + + <TextBox IsEnabled="{Binding StorageProvider.IsBusy,Converter={StaticResource BooleanInverseConverter}}" Padding="5 0 0 0" Text="{Binding StorageProvider.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 StorageProvider.NavigateCommand}" /> + </TextBox.InputBindings> + </TextBox> + </Grid> + </Border> + </Border> + </DockPanel> + </DockPanel> + + <DockPanel Margin="0 10 0 0"> + + <Border Margin="0 15 20 0" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderBrush="{StaticResource FSE_PrimaryBackgroundLightBrush}" BorderThickness="3" CornerRadius="3" Padding="10 5"> + <StackPanel> + <commonControls:TextIconButton HorizontalContentAlignment="Left" Padding="5" Icon="Computer" Background="Transparent" BorderThickness="0" FocusVisualStyle="{x:Null}">Devices</commonControls:TextIconButton> + <StackPanel Margin="30 0 0 0"> + <ItemsControl ItemsSource="{Binding StorageProvider.Drives}"> + <ItemsControl.ItemTemplate> + <DataTemplate> + <commonControls:TextIconButton HorizontalContentAlignment="Left" Padding="5" Icon="Harddisk" Background="Transparent" BorderThickness="0" FocusVisualStyle="{x:Null}" Content="{Binding Label}" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.StorageProvider.NavigateToFolderCommand}" CommandParameter="{Binding Path}"></commonControls:TextIconButton> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </StackPanel> + + <commonControls:TextIconButton HorizontalContentAlignment="Left" Padding="5" Icon="Computer" Background="Transparent" BorderThickness="0" FocusVisualStyle="{x:Null}">Computer</commonControls:TextIconButton> + <StackPanel Margin="30 0 0 0"> + <commonControls:TextIconButton HorizontalContentAlignment="Left" Padding="5" Icon="DesktopMac" Background="Transparent" BorderThickness="0" FocusVisualStyle="{x:Null}" Command="{Binding StorageProvider.NavigateSpecialFolderCommand}" CommandParameter="DesktopDirectory">Desktop</commonControls:TextIconButton> + <commonControls:TextIconButton HorizontalContentAlignment="Left" Padding="5" Icon="FileDocument" Background="Transparent" BorderThickness="0" FocusVisualStyle="{x:Null}" Command="{Binding StorageProvider.NavigateSpecialFolderCommand}" CommandParameter="MyDocuments">Documents</commonControls:TextIconButton> + <commonControls:TextIconButton HorizontalContentAlignment="Left" Padding="5" Icon="Application" Background="Transparent" BorderThickness="0" FocusVisualStyle="{x:Null}" Command="{Binding StorageProvider.NavigateToFolderCommand}" CommandParameter='%appdata%\Twine\Tango'>Application Data</commonControls:TextIconButton> + </StackPanel> + </StackPanel> + </Border> + + <commonControls:FileSystemControl + AllowDrag="False" + AllowDrop="False" + Mode="{Binding ElementName=listView,Path=SelectedItem.Tag}" + CurrentItem="{Binding StorageProvider.CurrentItem,Mode=TwoWay}" + SelectedItems="{Binding StorageProvider.SelectedItems}" + BackCommand="{Binding StorageProvider.BackCommand}" + ItemDoubleClickedCommand="{Binding StorageProvider.OpenCommand}" + OpenCommand="{Binding StorageProvider.OpenCommand}"/> + </DockPanel> + </DockPanel> + </DockPanel> + + <Grid HorizontalAlignment="Right" VerticalAlignment="Top"> + <commonControls:IconButton Icon="Close" Padding="8" Margin="0 0 5 0" Command="{Binding StorageProvider.CancelCommand}" Width="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight}"/> + </Grid> + </Grid> + </Grid> + </Border> + </Grid> + </Grid> + <!--STORAGE--> + <!--TASK ITEMS--> <Grid x:Name="gridTaskItems" Cursor="AppStarting" Background="{StaticResource FSE_SemiTransparentBrush}"> <Grid.Style> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml.cs index 3d29032b1..b98ad1a52 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml.cs @@ -21,6 +21,7 @@ namespace Tango.FSE.UI.Views public partial class MainView : UserControl { private UIElement _previousFocusedElement; + private object _lastSelectedItem; public static MainView Instance { get; set; } @@ -105,5 +106,17 @@ namespace Tango.FSE.UI.Views e.Handled = true; } } + + 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/Tango.FSE.UI/packages.config b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config index c795da787..fda2f4d3f 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config @@ -14,4 +14,6 @@ <package id="System.Reactive.Linq" version="3.1.1" targetFramework="net461" /> <package id="System.Reactive.PlatformServices" version="3.1.1" targetFramework="net461" /> <package id="System.Reactive.Windows.Threading" version="3.1.1" targetFramework="net461" /> + <package id="WindowsAPICodePack-Core" version="1.1.1" targetFramework="net461" /> + <package id="WindowsAPICodePack-Shell" version="1.1.1" targetFramework="net461" /> </packages>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs b/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs index b8e59c322..c18df97c9 100644 --- a/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs +++ b/Software/Visual_Studio/Tango.FileSystem/FileSystemManager.cs @@ -92,6 +92,28 @@ namespace Tango.FileSystem }; } + public Task<FileSystemItem> GetFolder(String path) + { + return Task.Factory.StartNew<FileSystemItem>(() => + { + return FileSystemItem.FromDTO(GetFolder(new GetFileSystemItemRequest() + { + Path = path, + })); + }); + } + + public Task<FileSystemItem> GetFolder(Environment.SpecialFolder specialFolder) + { + return Task.Factory.StartNew<FileSystemItem>(() => + { + return FileSystemItem.FromDTO(GetFolder(new GetFileSystemItemRequest() + { + SpecialFolder = specialFolder + })); + }); + } + public void Delete(String path) { if (Directory.Exists(path)) |
