Skip to content

Sort #256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 2, 2019
Merged

Sort #256

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified Files UWP/Assets/FilesDrive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Files UWP/Assets/FilesHome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Files UWP/Assets/logo.bmp
Binary file not shown.
10 changes: 10 additions & 0 deletions Files UWP/Enums/SortOption.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Files.Enums
{
public enum SortOption
{
Name,
DateModified,
Size,
FileType
}
}
1 change: 1 addition & 0 deletions Files UWP/FilesUWP.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
<Compile Include="Dialogs\RenameDialog.xaml.cs">
<DependentUpon>RenameDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Enums\SortOption.cs" />
<Compile Include="Enums\ThemeStyle.cs" />
<Compile Include="Enums\TimeStyle.cs" />
<Compile Include="Filesystem\DriveItem.cs" />
Expand Down
194 changes: 189 additions & 5 deletions Files UWP/Filesystem/ItemViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
using ByteSizeLib;
using Files.Interacts;
using Files.Enums;
using Files.Navigation;
using Microsoft.Toolkit.Uwp.UI;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -31,7 +33,7 @@

namespace Files.Filesystem
{
public class ItemViewModel
public class ItemViewModel : INotifyPropertyChanged
{
public ReadOnlyObservableCollection<ListedItem> FilesAndFolders { get; }
public CollectionViewSource viewSource;
Expand All @@ -44,10 +46,133 @@ public class ItemViewModel
private QueryOptions _options;
private volatile bool _filesRefreshing;
private const int _step = 250;
public event PropertyChangedEventHandler PropertyChanged;

private SortOption _directorySortOption = SortOption.Name;
private SortDirection _directorySortDirection = SortDirection.Ascending;

public SortOption DirectorySortOption
{
get
{
return _directorySortOption;
}
set
{
if (value != _directorySortOption)
{
_directorySortOption = value;
NotifyPropertyChanged("DirectorySortOption");
NotifyPropertyChanged("IsSortedByName");
NotifyPropertyChanged("IsSortedByDate");
NotifyPropertyChanged("IsSortedByType");
NotifyPropertyChanged("IsSortedBySize");
OrderFiles();
}
}
}

public SortDirection DirectorySortDirection
{
get
{
return _directorySortDirection;
}
set
{
if (value != _directorySortDirection)
{
_directorySortDirection = value;
NotifyPropertyChanged("DirectorySortDirection");
NotifyPropertyChanged("IsSortedAscending");
NotifyPropertyChanged("IsSortedDescending");
OrderFiles();
}
}
}

public bool IsSortedByName
{
get => DirectorySortOption == SortOption.Name;
set
{
if (value)
{
DirectorySortOption = SortOption.Name;
NotifyPropertyChanged("IsSortedByName");
NotifyPropertyChanged("DirectorySortOption");
}
}
}

public bool IsSortedByDate
{
get => DirectorySortOption == SortOption.DateModified;
set
{
if (value)
{
DirectorySortOption = SortOption.DateModified;
NotifyPropertyChanged("IsSortedByDate");
NotifyPropertyChanged("DirectorySortOption");
}
}
}

public bool IsSortedByType
{
get => DirectorySortOption == SortOption.FileType;
set
{
if (value)
{
DirectorySortOption = SortOption.FileType;
NotifyPropertyChanged("IsSortedByType");
NotifyPropertyChanged("DirectorySortOption");
}
}
}

public bool IsSortedBySize
{
get => DirectorySortOption == SortOption.Size;
set
{
if (value)
{
DirectorySortOption = SortOption.Size;
NotifyPropertyChanged("IsSortedBySize");
NotifyPropertyChanged("DirectorySortOption");
}
}
}

public bool IsSortedAscending
{
get => DirectorySortDirection == SortDirection.Ascending;
set
{
DirectorySortDirection = value ? SortDirection.Ascending : SortDirection.Descending;
NotifyPropertyChanged("IsSortedAscending");
NotifyPropertyChanged("IsSortedDescending");
NotifyPropertyChanged("DirectorySortDirection");
}
}

public bool IsSortedDescending
{
get => !IsSortedAscending;
set
{
DirectorySortDirection = value ? SortDirection.Descending : SortDirection.Ascending;
NotifyPropertyChanged("IsSortedAscending");
NotifyPropertyChanged("IsSortedDescending");
NotifyPropertyChanged("DirectorySortDirection");
}
}

public ItemViewModel()
{

_filesAndFolders = new ObservableCollection<ListedItem>();

FilesAndFolders = new ReadOnlyObservableCollection<ListedItem>(_filesAndFolders);
Expand Down Expand Up @@ -250,6 +375,59 @@ public void CancelLoadAndClearFiles()

}

public void OrderFiles()
{
if (_filesAndFolders.Count == 0)
return;

object orderByNameFunc(ListedItem item) => item.FileName;
Func<ListedItem, object> orderFunc = orderByNameFunc;
switch (DirectorySortOption)
{
case SortOption.Name:
orderFunc = orderByNameFunc;
break;
case SortOption.DateModified:
orderFunc = item => item.FileDateReal;
break;
case SortOption.FileType:
orderFunc = item => item.FileType;
break;
case SortOption.Size:
orderFunc = item => item.FileSizeBytes;
break;
}

// In ascending order, show folders first, then files.
// So, we use != "Folder" to make the value for "Folder" = 0, and for the rest, 1.
Func<ListedItem, bool> folderThenFile = listedItem => listedItem.FileType != "Folder";
IOrderedEnumerable<ListedItem> ordered;
List<ListedItem> orderedList;

if (DirectorySortDirection == SortDirection.Ascending)
ordered = _filesAndFolders.OrderBy(folderThenFile).ThenBy(orderFunc);
else
{
if (DirectorySortOption == SortOption.FileType)
ordered = _filesAndFolders.OrderBy(folderThenFile).ThenByDescending(orderFunc);
else
ordered = _filesAndFolders.OrderByDescending(folderThenFile).ThenByDescending(orderFunc);
}

// Further order by name if applicable
if (DirectorySortOption != SortOption.Name)
{
if (DirectorySortDirection == SortDirection.Ascending)
ordered = ordered.ThenBy(orderByNameFunc);
else
ordered = ordered.ThenByDescending(orderByNameFunc);
}
orderedList = ordered.ToList();
_filesAndFolders.Clear();
foreach (ListedItem i in orderedList)
_filesAndFolders.Add(i);
}

public static T GetCurrentSelectedTabInstance<T>()
{
Frame rootFrame = Window.Current.Content as Frame;
Expand Down Expand Up @@ -435,6 +613,7 @@ public async void AddItemsToCollectionAsync(string path)
(App.selectedTabInstance.accessibleContentFrame.Content as PhotoAlbum).TextState.isVisible = Visibility.Visible;
}
}
OrderFiles();
stopwatch.Stop();
Debug.WriteLine("Loading of items in " + Universal.path + " completed in " + stopwatch.ElapsedMilliseconds + " milliseconds.\n");
App.selectedTabInstance.RefreshButton.IsEnabled = true;
Expand Down Expand Up @@ -517,7 +696,7 @@ private async Task AddFolder(StorageFolder folder)
FilePath = folder.Path,
EmptyImgVis = Visibility.Collapsed,
FileSize = null,
RowIndex = _filesAndFolders.Count
FileSizeBytes = 0
});
if((App.selectedTabInstance.accessibleContentFrame.Content as GenericFileBrowser) != null)
{
Expand All @@ -538,6 +717,7 @@ private async Task AddFile(StorageFile file)
var itemDate = basicProperties.DateModified;
var itemPath = file.Path;
var itemSize = ByteSize.FromBytes(basicProperties.Size).ToString();
var itemSizeBytes = basicProperties.Size;
var itemType = file.DisplayType;
var itemFolderImgVis = Visibility.Collapsed;
var itemFileExtension = file.FileType;
Expand Down Expand Up @@ -616,7 +796,7 @@ private async Task AddFile(StorageFile file)
FileType = itemType,
FilePath = itemPath,
FileSize = itemSize,
RowIndex = _filesAndFolders.Count
FileSizeBytes = itemSizeBytes
});

if(App.selectedTabInstance.accessibleContentFrame.SourcePageType == typeof(GenericFileBrowser))
Expand Down Expand Up @@ -724,5 +904,9 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio
_filesRefreshing = false;
Debug.WriteLine("Filesystem refresh complete");
}
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
2 changes: 1 addition & 1 deletion Files UWP/Filesystem/ListedItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class ListedItem
public string DotFileExtension { get; set; }
public string FilePath { get; set; }
public string FileSize { get; set; }
public int RowIndex { get; set; }
public ulong FileSizeBytes { get; set; }

public DateTimeOffset FileDateReal
{
Expand Down
28 changes: 18 additions & 10 deletions Files UWP/GenericFileBrowser.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,24 @@
<Grid Background="Transparent" x:Name="RootGrid">
<Grid.ContextFlyout>
<MenuFlyout MenuFlyoutPresenterStyle="{StaticResource MenuFlyoutFluentThemeResources}">
<MenuFlyoutSubItem Text="Sort by" x:Name="SortByEmptySpace">
<MenuFlyoutSubItem.Icon>
<FontIcon Glyph="&#xE8CB;"/>
</MenuFlyoutSubItem.Icon>
<uilib:RadioMenuFlyoutItem Text="Name" GroupName="SortGroup" IsChecked="{x:Bind viewModelInstance.IsSortedByName, Mode=TwoWay}"/>
<uilib:RadioMenuFlyoutItem Text="Date modified" GroupName="SortGroup" IsChecked="{x:Bind viewModelInstance.IsSortedByDate, Mode=TwoWay}"/>
<uilib:RadioMenuFlyoutItem Text="Type" GroupName="SortGroup" IsChecked="{x:Bind viewModelInstance.IsSortedByType, Mode=TwoWay}"/>
<uilib:RadioMenuFlyoutItem Text="Size" GroupName="SortGroup" IsChecked="{x:Bind viewModelInstance.IsSortedBySize, Mode=TwoWay}"/>
<MenuFlyoutSeparator/>
<uilib:RadioMenuFlyoutItem Text="Ascending" GroupName="SortOrderGroup" IsChecked="{x:Bind viewModelInstance.IsSortedAscending, Mode=TwoWay}"/>
<uilib:RadioMenuFlyoutItem Text="Descending" GroupName="SortOrderGroup" IsChecked="{x:Bind viewModelInstance.IsSortedDescending, Mode=TwoWay}"/>
</MenuFlyoutSubItem>
<MenuFlyoutItem Text="Refresh" x:Name="RefreshEmptySpace">
<MenuFlyoutItem.Icon>
<FontIcon Glyph="&#xE72C;"/>
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
<MenuFlyoutSeparator/>
<MenuFlyoutItem Text="Paste" x:Name="PasteEmptySpace" IsEnabled="{x:Bind Mode=TwoWay, Path=local:App.PS.isEnabled, UpdateSourceTrigger=PropertyChanged}">
<MenuFlyoutItem.Icon>
<FontIcon Glyph="&#xE77F;"/>
Expand Down Expand Up @@ -199,7 +212,7 @@
</Grid.ContextFlyout>
<ProgressBar x:Name="progBar" Height="10" VerticalAlignment="Top" IsIndeterminate="True"/>
<TextBlock Visibility="{x:Bind Mode=TwoWay, Path=TextState.isVisible, UpdateSourceTrigger=PropertyChanged}" x:Name="EmptyText" HorizontalAlignment="Center" Text="This folder is empty." TextWrapping="Wrap" VerticalAlignment="Top" Margin="0,125,0,0"/>
<controls:DataGrid ItemsSource="{x:Bind viewModelInstance.FilesAndFolders}" PreviewKeyDown="AllView_PreviewKeyDown" ScrollViewer.IsScrollInertiaEnabled="True" ClipboardCopyMode="None" RowDetailsVisibilityMode="Collapsed" AllowDrop="True" Drop="AllView_DropAsync" DragLeave="AllView_DragLeave" DragStarting="AllView_DragStarting" SelectionChanged="AllView_SelectionChanged" Margin="24,24,0,0" Grid.Row="3" PreparingCellForEdit="AllView_PreparingCellForEdit" CellEditEnding="AllView_CellEditEnding" FocusVisualPrimaryThickness="0" SelectionMode="Extended" IsDoubleTapEnabled="True" x:FieldModifier="public" x:Name="AllView" AutoGenerateColumns="False" CanDrag="True" DragOver="AllView_DragOver" IsRightTapEnabled="True" CanUserReorderColumns="False" HorizontalAlignment="Left">
<controls:DataGrid ItemsSource="{x:Bind viewModelInstance.FilesAndFolders}" PreviewKeyDown="AllView_PreviewKeyDown" ScrollViewer.IsScrollInertiaEnabled="True" ClipboardCopyMode="None" RowDetailsVisibilityMode="Collapsed" AllowDrop="True" Drop="AllView_DropAsync" DragLeave="AllView_DragLeave" DragStarting="AllView_DragStarting" SelectionChanged="AllView_SelectionChanged" Margin="24,24,0,0" Grid.Row="3" PreparingCellForEdit="AllView_PreparingCellForEdit" CellEditEnding="AllView_CellEditEnding" FocusVisualPrimaryThickness="0" SelectionMode="Extended" IsDoubleTapEnabled="True" x:FieldModifier="public" x:Name="AllView" AutoGenerateColumns="False" CanDrag="True" DragOver="AllView_DragOver" IsRightTapEnabled="True" CanUserReorderColumns="False" CanUserSortColumns="True" Sorting="AllView_Sorting" HorizontalAlignment="Left">
<controls:DataGrid.Resources>
<SolidColorBrush x:Key="DataGridCellFocusVisualPrimaryBrush" Color="Transparent"/>
<SolidColorBrush x:Key="DataGridCellFocusVisualSecondaryBrush" Color="Transparent"/>
Expand Down Expand Up @@ -288,22 +301,17 @@
<KeyboardAccelerator Modifiers="Control" Key="C"/>
</MenuFlyoutItem.KeyboardAccelerators>
</MenuFlyoutItem>

<MenuFlyoutSeparator/>
<MenuFlyoutItem Text="Pin to sidebar" x:Name="SidebarPinItem">
<MenuFlyoutItem.Icon>
<SymbolIcon Symbol="Pin"/>
</MenuFlyoutItem.Icon>

</MenuFlyoutItem>

<MenuFlyoutItem Text="Properties" x:Name="PropertiesItem">
<MenuFlyoutItem.Icon>
<FontIcon Glyph="&#xE946;"/>
</MenuFlyoutItem.Icon>

</MenuFlyoutItem>

</MenuFlyout>
</Setter.Value>
</Setter>
Expand All @@ -319,7 +327,7 @@
</controls:DataGrid.CellStyle>

<controls:DataGrid.Columns>
<controls:DataGridTemplateColumn DisplayIndex="0" IsReadOnly="True">
<controls:DataGridTemplateColumn DisplayIndex="0" x:Name="iconColumn" IsReadOnly="True">
<controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid x:Name="Icon" Margin="0, 0, 0, 0">
Expand All @@ -331,9 +339,9 @@
</DataTemplate>
</controls:DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumn>
<controls:DataGridTextColumn DisplayIndex="1" Header="Name" Width="275" Binding="{Binding FileName}" Tag="Name"/>
<controls:DataGridTextColumn DisplayIndex="2" IsReadOnly="True" Header="Date modified" Width="Auto" Binding="{Binding FileDate}" Tag="Date"/>
<controls:DataGridTextColumn DisplayIndex="3" IsReadOnly="True" Header="Type" Width="150" Binding="{Binding FileType}" Tag="Type"/>
<controls:DataGridTextColumn DisplayIndex="1" x:Name="nameColumn" Header="Name" Width="275" Binding="{Binding FileName}" Tag="Name"/>
<controls:DataGridTextColumn DisplayIndex="2" x:Name="dateColumn" IsReadOnly="True" Header="Date modified" Width="Auto" Binding="{Binding FileDate}" Tag="Date"/>
<controls:DataGridTextColumn DisplayIndex="3" x:Name="typeColumn" IsReadOnly="True" Header="Type" Width="150" Binding="{Binding FileType}" Tag="Type"/>
<controls:DataGridTextColumn DisplayIndex="4" x:Name="sizeColumn" IsReadOnly="True" Header="Size" Width="Auto" MinWidth="100" Binding="{Binding FileSize}" Tag="Size"/>
</controls:DataGrid.Columns>
</controls:DataGrid>
Expand Down
Loading