Skip to content

Commit b556239

Browse files
authored
Merge pull request #256 from duke7553/sort
Sort
2 parents 2e93cfb + d791cd2 commit b556239

File tree

77 files changed

+419
-95
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+419
-95
lines changed

Files UWP/Assets/FilesDrive.png

622 Bytes
Loading

Files UWP/Assets/FilesHome.png

-19.5 KB
Loading

Files UWP/Assets/logo.bmp

-615 KB
Binary file not shown.

Files UWP/Enums/SortOption.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Files.Enums
2+
{
3+
public enum SortOption
4+
{
5+
Name,
6+
DateModified,
7+
Size,
8+
FileType
9+
}
10+
}

Files UWP/FilesUWP.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
<Compile Include="Dialogs\RenameDialog.xaml.cs">
141141
<DependentUpon>RenameDialog.xaml</DependentUpon>
142142
</Compile>
143+
<Compile Include="Enums\SortOption.cs" />
143144
<Compile Include="Enums\ThemeStyle.cs" />
144145
<Compile Include="Enums\TimeStyle.cs" />
145146
<Compile Include="Filesystem\DriveItem.cs" />

Files UWP/Filesystem/ItemViewModel.cs

Lines changed: 189 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
using ByteSizeLib;
2-
using Files.Interacts;
2+
using Files.Enums;
33
using Files.Navigation;
44
using Microsoft.Toolkit.Uwp.UI;
55
using Microsoft.UI.Xaml.Controls;
66
using System;
77
using System.Collections.Generic;
88
using System.Collections.ObjectModel;
9+
using System.ComponentModel;
910
using System.Diagnostics;
1011
using System.Globalization;
1112
using System.IO;
1213
using System.Linq;
14+
using System.Runtime.CompilerServices;
1315
using System.Runtime.InteropServices;
1416
using System.Threading;
1517
using System.Threading.Tasks;
@@ -31,7 +33,7 @@
3133

3234
namespace Files.Filesystem
3335
{
34-
public class ItemViewModel
36+
public class ItemViewModel : INotifyPropertyChanged
3537
{
3638
public ReadOnlyObservableCollection<ListedItem> FilesAndFolders { get; }
3739
public CollectionViewSource viewSource;
@@ -44,10 +46,133 @@ public class ItemViewModel
4446
private QueryOptions _options;
4547
private volatile bool _filesRefreshing;
4648
private const int _step = 250;
49+
public event PropertyChangedEventHandler PropertyChanged;
50+
51+
private SortOption _directorySortOption = SortOption.Name;
52+
private SortDirection _directorySortDirection = SortDirection.Ascending;
53+
54+
public SortOption DirectorySortOption
55+
{
56+
get
57+
{
58+
return _directorySortOption;
59+
}
60+
set
61+
{
62+
if (value != _directorySortOption)
63+
{
64+
_directorySortOption = value;
65+
NotifyPropertyChanged("DirectorySortOption");
66+
NotifyPropertyChanged("IsSortedByName");
67+
NotifyPropertyChanged("IsSortedByDate");
68+
NotifyPropertyChanged("IsSortedByType");
69+
NotifyPropertyChanged("IsSortedBySize");
70+
OrderFiles();
71+
}
72+
}
73+
}
74+
75+
public SortDirection DirectorySortDirection
76+
{
77+
get
78+
{
79+
return _directorySortDirection;
80+
}
81+
set
82+
{
83+
if (value != _directorySortDirection)
84+
{
85+
_directorySortDirection = value;
86+
NotifyPropertyChanged("DirectorySortDirection");
87+
NotifyPropertyChanged("IsSortedAscending");
88+
NotifyPropertyChanged("IsSortedDescending");
89+
OrderFiles();
90+
}
91+
}
92+
}
93+
94+
public bool IsSortedByName
95+
{
96+
get => DirectorySortOption == SortOption.Name;
97+
set
98+
{
99+
if (value)
100+
{
101+
DirectorySortOption = SortOption.Name;
102+
NotifyPropertyChanged("IsSortedByName");
103+
NotifyPropertyChanged("DirectorySortOption");
104+
}
105+
}
106+
}
107+
108+
public bool IsSortedByDate
109+
{
110+
get => DirectorySortOption == SortOption.DateModified;
111+
set
112+
{
113+
if (value)
114+
{
115+
DirectorySortOption = SortOption.DateModified;
116+
NotifyPropertyChanged("IsSortedByDate");
117+
NotifyPropertyChanged("DirectorySortOption");
118+
}
119+
}
120+
}
121+
122+
public bool IsSortedByType
123+
{
124+
get => DirectorySortOption == SortOption.FileType;
125+
set
126+
{
127+
if (value)
128+
{
129+
DirectorySortOption = SortOption.FileType;
130+
NotifyPropertyChanged("IsSortedByType");
131+
NotifyPropertyChanged("DirectorySortOption");
132+
}
133+
}
134+
}
135+
136+
public bool IsSortedBySize
137+
{
138+
get => DirectorySortOption == SortOption.Size;
139+
set
140+
{
141+
if (value)
142+
{
143+
DirectorySortOption = SortOption.Size;
144+
NotifyPropertyChanged("IsSortedBySize");
145+
NotifyPropertyChanged("DirectorySortOption");
146+
}
147+
}
148+
}
149+
150+
public bool IsSortedAscending
151+
{
152+
get => DirectorySortDirection == SortDirection.Ascending;
153+
set
154+
{
155+
DirectorySortDirection = value ? SortDirection.Ascending : SortDirection.Descending;
156+
NotifyPropertyChanged("IsSortedAscending");
157+
NotifyPropertyChanged("IsSortedDescending");
158+
NotifyPropertyChanged("DirectorySortDirection");
159+
}
160+
}
161+
162+
public bool IsSortedDescending
163+
{
164+
get => !IsSortedAscending;
165+
set
166+
{
167+
DirectorySortDirection = value ? SortDirection.Descending : SortDirection.Ascending;
168+
NotifyPropertyChanged("IsSortedAscending");
169+
NotifyPropertyChanged("IsSortedDescending");
170+
NotifyPropertyChanged("DirectorySortDirection");
171+
}
172+
}
47173

48174
public ItemViewModel()
49175
{
50-
51176
_filesAndFolders = new ObservableCollection<ListedItem>();
52177

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

251376
}
252377

378+
public void OrderFiles()
379+
{
380+
if (_filesAndFolders.Count == 0)
381+
return;
382+
383+
object orderByNameFunc(ListedItem item) => item.FileName;
384+
Func<ListedItem, object> orderFunc = orderByNameFunc;
385+
switch (DirectorySortOption)
386+
{
387+
case SortOption.Name:
388+
orderFunc = orderByNameFunc;
389+
break;
390+
case SortOption.DateModified:
391+
orderFunc = item => item.FileDateReal;
392+
break;
393+
case SortOption.FileType:
394+
orderFunc = item => item.FileType;
395+
break;
396+
case SortOption.Size:
397+
orderFunc = item => item.FileSizeBytes;
398+
break;
399+
}
400+
401+
// In ascending order, show folders first, then files.
402+
// So, we use != "Folder" to make the value for "Folder" = 0, and for the rest, 1.
403+
Func<ListedItem, bool> folderThenFile = listedItem => listedItem.FileType != "Folder";
404+
IOrderedEnumerable<ListedItem> ordered;
405+
List<ListedItem> orderedList;
406+
407+
if (DirectorySortDirection == SortDirection.Ascending)
408+
ordered = _filesAndFolders.OrderBy(folderThenFile).ThenBy(orderFunc);
409+
else
410+
{
411+
if (DirectorySortOption == SortOption.FileType)
412+
ordered = _filesAndFolders.OrderBy(folderThenFile).ThenByDescending(orderFunc);
413+
else
414+
ordered = _filesAndFolders.OrderByDescending(folderThenFile).ThenByDescending(orderFunc);
415+
}
416+
417+
// Further order by name if applicable
418+
if (DirectorySortOption != SortOption.Name)
419+
{
420+
if (DirectorySortDirection == SortDirection.Ascending)
421+
ordered = ordered.ThenBy(orderByNameFunc);
422+
else
423+
ordered = ordered.ThenByDescending(orderByNameFunc);
424+
}
425+
orderedList = ordered.ToList();
426+
_filesAndFolders.Clear();
427+
foreach (ListedItem i in orderedList)
428+
_filesAndFolders.Add(i);
429+
}
430+
253431
public static T GetCurrentSelectedTabInstance<T>()
254432
{
255433
Frame rootFrame = Window.Current.Content as Frame;
@@ -435,6 +613,7 @@ public async void AddItemsToCollectionAsync(string path)
435613
(App.selectedTabInstance.accessibleContentFrame.Content as PhotoAlbum).TextState.isVisible = Visibility.Visible;
436614
}
437615
}
616+
OrderFiles();
438617
stopwatch.Stop();
439618
Debug.WriteLine("Loading of items in " + Universal.path + " completed in " + stopwatch.ElapsedMilliseconds + " milliseconds.\n");
440619
App.selectedTabInstance.RefreshButton.IsEnabled = true;
@@ -517,7 +696,7 @@ private async Task AddFolder(StorageFolder folder)
517696
FilePath = folder.Path,
518697
EmptyImgVis = Visibility.Collapsed,
519698
FileSize = null,
520-
RowIndex = _filesAndFolders.Count
699+
FileSizeBytes = 0
521700
});
522701
if((App.selectedTabInstance.accessibleContentFrame.Content as GenericFileBrowser) != null)
523702
{
@@ -538,6 +717,7 @@ private async Task AddFile(StorageFile file)
538717
var itemDate = basicProperties.DateModified;
539718
var itemPath = file.Path;
540719
var itemSize = ByteSize.FromBytes(basicProperties.Size).ToString();
720+
var itemSizeBytes = basicProperties.Size;
541721
var itemType = file.DisplayType;
542722
var itemFolderImgVis = Visibility.Collapsed;
543723
var itemFileExtension = file.FileType;
@@ -616,7 +796,7 @@ private async Task AddFile(StorageFile file)
616796
FileType = itemType,
617797
FilePath = itemPath,
618798
FileSize = itemSize,
619-
RowIndex = _filesAndFolders.Count
799+
FileSizeBytes = itemSizeBytes
620800
});
621801

622802
if(App.selectedTabInstance.accessibleContentFrame.SourcePageType == typeof(GenericFileBrowser))
@@ -724,5 +904,9 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPrio
724904
_filesRefreshing = false;
725905
Debug.WriteLine("Filesystem refresh complete");
726906
}
907+
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
908+
{
909+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
910+
}
727911
}
728912
}

Files UWP/Filesystem/ListedItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class ListedItem
1818
public string DotFileExtension { get; set; }
1919
public string FilePath { get; set; }
2020
public string FileSize { get; set; }
21-
public int RowIndex { get; set; }
21+
public ulong FileSizeBytes { get; set; }
2222

2323
public DateTimeOffset FileDateReal
2424
{

Files UWP/GenericFileBrowser.xaml

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,24 @@
154154
<Grid Background="Transparent" x:Name="RootGrid">
155155
<Grid.ContextFlyout>
156156
<MenuFlyout MenuFlyoutPresenterStyle="{StaticResource MenuFlyoutFluentThemeResources}">
157+
<MenuFlyoutSubItem Text="Sort by" x:Name="SortByEmptySpace">
158+
<MenuFlyoutSubItem.Icon>
159+
<FontIcon Glyph="&#xE8CB;"/>
160+
</MenuFlyoutSubItem.Icon>
161+
<uilib:RadioMenuFlyoutItem Text="Name" GroupName="SortGroup" IsChecked="{x:Bind viewModelInstance.IsSortedByName, Mode=TwoWay}"/>
162+
<uilib:RadioMenuFlyoutItem Text="Date modified" GroupName="SortGroup" IsChecked="{x:Bind viewModelInstance.IsSortedByDate, Mode=TwoWay}"/>
163+
<uilib:RadioMenuFlyoutItem Text="Type" GroupName="SortGroup" IsChecked="{x:Bind viewModelInstance.IsSortedByType, Mode=TwoWay}"/>
164+
<uilib:RadioMenuFlyoutItem Text="Size" GroupName="SortGroup" IsChecked="{x:Bind viewModelInstance.IsSortedBySize, Mode=TwoWay}"/>
165+
<MenuFlyoutSeparator/>
166+
<uilib:RadioMenuFlyoutItem Text="Ascending" GroupName="SortOrderGroup" IsChecked="{x:Bind viewModelInstance.IsSortedAscending, Mode=TwoWay}"/>
167+
<uilib:RadioMenuFlyoutItem Text="Descending" GroupName="SortOrderGroup" IsChecked="{x:Bind viewModelInstance.IsSortedDescending, Mode=TwoWay}"/>
168+
</MenuFlyoutSubItem>
157169
<MenuFlyoutItem Text="Refresh" x:Name="RefreshEmptySpace">
158170
<MenuFlyoutItem.Icon>
159171
<FontIcon Glyph="&#xE72C;"/>
160172
</MenuFlyoutItem.Icon>
161173
</MenuFlyoutItem>
174+
<MenuFlyoutSeparator/>
162175
<MenuFlyoutItem Text="Paste" x:Name="PasteEmptySpace" IsEnabled="{x:Bind Mode=TwoWay, Path=local:App.PS.isEnabled, UpdateSourceTrigger=PropertyChanged}">
163176
<MenuFlyoutItem.Icon>
164177
<FontIcon Glyph="&#xE77F;"/>
@@ -199,7 +212,7 @@
199212
</Grid.ContextFlyout>
200213
<ProgressBar x:Name="progBar" Height="10" VerticalAlignment="Top" IsIndeterminate="True"/>
201214
<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"/>
202-
<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">
215+
<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">
203216
<controls:DataGrid.Resources>
204217
<SolidColorBrush x:Key="DataGridCellFocusVisualPrimaryBrush" Color="Transparent"/>
205218
<SolidColorBrush x:Key="DataGridCellFocusVisualSecondaryBrush" Color="Transparent"/>
@@ -288,22 +301,17 @@
288301
<KeyboardAccelerator Modifiers="Control" Key="C"/>
289302
</MenuFlyoutItem.KeyboardAccelerators>
290303
</MenuFlyoutItem>
291-
292304
<MenuFlyoutSeparator/>
293305
<MenuFlyoutItem Text="Pin to sidebar" x:Name="SidebarPinItem">
294306
<MenuFlyoutItem.Icon>
295307
<SymbolIcon Symbol="Pin"/>
296308
</MenuFlyoutItem.Icon>
297-
298309
</MenuFlyoutItem>
299-
300310
<MenuFlyoutItem Text="Properties" x:Name="PropertiesItem">
301311
<MenuFlyoutItem.Icon>
302312
<FontIcon Glyph="&#xE946;"/>
303313
</MenuFlyoutItem.Icon>
304-
305314
</MenuFlyoutItem>
306-
307315
</MenuFlyout>
308316
</Setter.Value>
309317
</Setter>
@@ -319,7 +327,7 @@
319327
</controls:DataGrid.CellStyle>
320328

321329
<controls:DataGrid.Columns>
322-
<controls:DataGridTemplateColumn DisplayIndex="0" IsReadOnly="True">
330+
<controls:DataGridTemplateColumn DisplayIndex="0" x:Name="iconColumn" IsReadOnly="True">
323331
<controls:DataGridTemplateColumn.CellTemplate>
324332
<DataTemplate>
325333
<Grid x:Name="Icon" Margin="0, 0, 0, 0">
@@ -331,9 +339,9 @@
331339
</DataTemplate>
332340
</controls:DataGridTemplateColumn.CellTemplate>
333341
</controls:DataGridTemplateColumn>
334-
<controls:DataGridTextColumn DisplayIndex="1" Header="Name" Width="275" Binding="{Binding FileName}" Tag="Name"/>
335-
<controls:DataGridTextColumn DisplayIndex="2" IsReadOnly="True" Header="Date modified" Width="Auto" Binding="{Binding FileDate}" Tag="Date"/>
336-
<controls:DataGridTextColumn DisplayIndex="3" IsReadOnly="True" Header="Type" Width="150" Binding="{Binding FileType}" Tag="Type"/>
342+
<controls:DataGridTextColumn DisplayIndex="1" x:Name="nameColumn" Header="Name" Width="275" Binding="{Binding FileName}" Tag="Name"/>
343+
<controls:DataGridTextColumn DisplayIndex="2" x:Name="dateColumn" IsReadOnly="True" Header="Date modified" Width="Auto" Binding="{Binding FileDate}" Tag="Date"/>
344+
<controls:DataGridTextColumn DisplayIndex="3" x:Name="typeColumn" IsReadOnly="True" Header="Type" Width="150" Binding="{Binding FileType}" Tag="Type"/>
337345
<controls:DataGridTextColumn DisplayIndex="4" x:Name="sizeColumn" IsReadOnly="True" Header="Size" Width="Auto" MinWidth="100" Binding="{Binding FileSize}" Tag="Size"/>
338346
</controls:DataGrid.Columns>
339347
</controls:DataGrid>

0 commit comments

Comments
 (0)