private void Navigate(IListItemEx destination, Boolean isInSameTab = false, Boolean refresh = false, Boolean isCancel = false) {
this.SaveSettingsToDatabase(this.CurrentFolder);
// TODO: Document isCancel Param better
if (destination == null) {
return;
}
destination = FileSystemListItem.ToFileSystemItem(destination.ParentHandle, destination.PIDL);
if (this.RequestedCurrentLocation == destination && !refresh) {
return;
}
//if (this.RequestedCurrentLocation != destination) {
// this.IsCancelRequested = true;
//}
this.LargeImageList.ResetEvent.Set();
this.SmallImageList.ResetEvent.Set();
this._ResetEvent.Set();
if (this._Threads.Count > 0) {
this._Mre.Set();
this._ResetEvent.Set();
this.LargeImageList.ResetEvent.Set();
this.SmallImageList.ResetEvent.Set();
foreach (var thread in this._Threads.ToArray()) {
thread.Abort();
this._Threads.Remove(thread);
}
}
this._UnvalidateTimer.Stop();
this._IsDisplayEmptyText = false;
User32.SendMessage(this.LVHandle, MSG.LVM_SETITEMCOUNT, 0, 0);
this.DisableGroups();
this.Focus(false, true);
this._ItemForRename = -1;
this._LastItemForRename = -1;
this.Items.Clear();
this._AddedItems.Clear();
this.LargeImageList.ReInitQueues();
this.SmallImageList.ReInitQueues();
this._CuttedIndexes.Clear();
FolderSettings folderSettings;
var isThereSettings = false;
isThereSettings = LoadSettingsFromDatabase(destination, out folderSettings);
this.RequestedCurrentLocation = destination;
if (!refresh)
Navigating?.Invoke(this, new NavigatingEventArgs(destination, isInSameTab));
var columns = new Collumns();
Int32 CurrentI = 0, LastI = 0, K = 0;
this.IsNavigationInProgress = true;
_ResetTimer.Stop();
if (isThereSettings) {
if (folderSettings.Columns != null) {
this.RemoveAllCollumns();
foreach (var collumn in folderSettings.Columns.Elements()) {
var theColumn = this.AllAvailableColumns.FirstOrDefault(w => w.Value.ID == collumn.Attribute("ID").Value).Value;//.Single();
if (theColumn == null) continue;
if (this.Collumns.Any(c => c.ID == theColumn?.ID)) continue;
if (collumn.Attribute("Width").Value != "0") theColumn.Width = Convert.ToInt32(collumn.Attribute("Width").Value);
this.Collumns.Add(theColumn);
var column = theColumn.ToNativeColumn(folderSettings.View == ShellViewStyle.Details);
User32.SendMessage(this.LVHandle, MSG.LVM_INSERTCOLUMN, this.Collumns.Count - 1, ref column);
if (folderSettings.View != ShellViewStyle.Details) this.AutosizeColumn(this.Collumns.Count - 1, -2);
}
}
} else {
this.RemoveAllCollumns();
this.AddDefaultColumns(false, true);
}
if (!String.IsNullOrEmpty(folderSettings.GroupCollumn)) {
var colData = this.AllAvailableColumns.FirstOrDefault(w => w.Value.ID == folderSettings.GroupCollumn).Value;
if (colData != null)
this.EnableGroups();
else
this.DisableGroups();
} else {
this.DisableGroups();
}
columns = this.AllAvailableColumns.FirstOrDefault(w => w.Value.ID == folderSettings.SortColumn).Value;
this.IsViewSelectionAllowed = false;
if (!isThereSettings) {
this.View = ShellViewStyle.Details;
}
if (folderSettings.View == ShellViewStyle.Details || folderSettings.View == ShellViewStyle.SmallIcon || folderSettings.View == ShellViewStyle.List) {
this.ResizeIcons(16);
this.View = folderSettings.View;
} else if (folderSettings.IconSize >= 16) {
this.ResizeIcons(folderSettings.IconSize);
var view = (ShellViewStyle)folderSettings.IconSize;
if (folderSettings.IconSize != 48 && folderSettings.IconSize != 96 && folderSettings.IconSize != 256)
this.View = ShellViewStyle.Thumbnail;
else
this.View = folderSettings.View;
}
this.IsViewSelectionAllowed = true;
this.Invoke((Action)(() => this._NavWaitTimer.Start()));
var navigationThread = new Thread(() => {
this.IsCancelRequested = false;
destination = FileSystemListItem.ToFileSystemItem(destination.ParentHandle, destination.PIDL);
if (destination.IsFileSystem) {
if (this._FsWatcher != null) {
this._FsWatcher.EnableRaisingEvents = false;
this._FsWatcher.Dispose();
try {
this._FsWatcher = new FileSystemWatcher(@destination.ParsingName);
//this._FsWatcher.InternalBufferSize = 64 * 1024 * 1024;
this._FsWatcher.Changed += (sender, args) => {
try {
var objUpdateItem = FileSystemListItem.ToFileSystemItem(this.LVHandle, args.FullPath);
if (objUpdateItem.IsInCurrentFolder(this.CurrentFolder)) {
var exisitingUItem = this.Items.ToArray().FirstOrDefault(w => w.Equals(objUpdateItem));
if (exisitingUItem != null)
this.RefreshItem(exisitingUItem.ItemIndex, true);
if (this.RequestedCurrentLocation != null && objUpdateItem.Equals(this.RequestedCurrentLocation))
this.UnvalidateDirectory();
}
} catch (FileNotFoundException) {
//Probably a temporary file
this._TemporaryFiles.Add(args.FullPath);
} catch {
}
};
this._FsWatcher.Error += (sender, args) => {
var ex = args.GetException();
};
this._FsWatcher.Created += (sender, args) => {
try {
//var existing = this.Items.FirstOrDefault(s => s.ParsingName.Equals(args.FullPath));
//if (existing != null) return;
if (Path.GetExtension(args.FullPath).ToLowerInvariant() == ".tmp" ||
Path.GetExtension(args.FullPath) == String.Empty) {
if (!this._TemporaryFiles.Contains(args.FullPath))
this._TemporaryFiles.Add(args.FullPath);
}
var obj = FileSystemListItem.ToFileSystemItem(this.LVHandle, args.FullPath);
if (obj.IsInCurrentFolder(this.CurrentFolder)) {
if (this.IsRenameNeeded) {
var existingItem = this.Items.ToArray().FirstOrDefault(s => s.Equals(obj));
if (existingItem == null) {
var itemIndex = this.InsertNewItem(obj);
this.SelectItemByIndex(itemIndex, true, true);
this.RenameSelectedItem(itemIndex);
this.IsRenameNeeded = false;
} else {
this.RenameSelectedItem(existingItem.ItemIndex);
}
} else {
if (this._ItemsQueue.Enqueue(new Tuple<ItemUpdateType, IListItemEx>(ItemUpdateType.Created, obj)))
this.UnvalidateDirectory();
}
}
} catch (FileNotFoundException) {
this.QueueDeleteItem(args);
} catch { }
};
this._FsWatcher.Deleted += (sender, args) => this.QueueDeleteItem(args);
this._FsWatcher.Renamed += (sender, args) => { };
this._FsWatcher.IncludeSubdirectories = false;
this._FsWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.Attributes |
NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
} catch (ArgumentException) {
this._FsWatcher = new FileSystemWatcher();
}
}
try {
if (this._FsWatcher != null && !String.IsNullOrEmpty(this._FsWatcher.Path)) {
this._FsWatcher.EnableRaisingEvents = true;
}
} catch (FileNotFoundException) { }
}
this.RequestedCurrentLocation = destination;
var column = columns ?? this.AllAvailableColumns.Single(s => s.Value.ID == "A0").Value;
var order = folderSettings.SortOrder;
var content = destination;
foreach (var shellItem in destination.IsNetworkPath ? destination.TakeWhile(shellItem => !this.IsCancelRequested) : content.TakeWhile(shellItem => !this.IsCancelRequested)) {
CurrentI++;
if (!this.RequestedCurrentLocation.Equals(shellItem.Parent) && this.IsNavigationCancelRequested) {
this.IsNavigationCancelRequested = false;
return;
}
if (this.ShowHidden || !shellItem.IsHidden) {
shellItem.ItemIndex = K++;
this.Items.Add(shellItem);
if (CurrentI == 1) {
this.Invoke((Action)(() => {
this._NavWaitTimer.Stop();
this._IsDisplayEmptyText = false;
this._IIListView.ResetEmptyText();
}));
}
}
var delta = CurrentI - LastI;
if (delta >= 4750) {
LastI = CurrentI;
this.BeginInvoke((MethodInvoker)(() => this._IIListView.SetItemCount(this.Items.Count, 0x2)));
}
}
this.IsCancelRequested = false;
this.IsNavigationInProgress = false;
if (this.RequestedCurrentLocation.NavigationStatus != HResult.S_OK) {
GC.Collect();
Shell32.SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
if (this._Threads.Count <= 1) return;
_Mre.Set();
this._ResetEvent.Set();
this._Threads[0].Abort();
this._Threads.RemoveAt(0);
return;
}
var headerhandle = User32.SendMessage(this.LVHandle, MSG.LVM_GETHEADER, 0, 0);
for (var i = 0; i < this.Collumns.Count; i++) {
this.Collumns[i].SetSplitButton(headerhandle, i);
}
if (this.View != ShellViewStyle.Details) AutosizeAllColumns(-2);
//User32.SendMessage(this.LVHandle, MSG.LVM_SETITEMCOUNT, this.Items.Count, 0x2);
var sortColIndex = this.Collumns.SingleOrDefault(s => s.ID == columns?.ID)?.Index;
if (sortColIndex != null) {
this.SetSortIcon(sortColIndex.Value, folderSettings.SortOrder == SortOrder.None ? SortOrder.Ascending : folderSettings.SortOrder);
}
if (isThereSettings) {
if (columns?.ID == "A0" && String.Equals(this.RequestedCurrentLocation.ParsingName, KnownFolders.Computer.ParsingName, StringComparison.InvariantCultureIgnoreCase))
this.SetSortCollumn(true, this.AvailableColumns().Single(s => s.Value.ID == "A180").Value, SortOrder.Ascending, false);
else
this.SetSortCollumn(true, columns, folderSettings.SortOrder, false);
} else if (String.Equals(this.RequestedCurrentLocation.ParsingName, KnownFolders.Computer.ParsingName, StringComparison.InvariantCultureIgnoreCase)) {
this.Items = this.Items.OrderBy(o => o.ParsingName).ToList();
var i = 0;
this.Items.ForEach(e => e.ItemIndex = i++);
User32.SendMessage(this.LVHandle, MSG.LVM_SETITEMCOUNT, this.Items.Count, 0x2);
} else {
this.Items = this.Items.OrderByDescending(o => o.IsFolder).ThenBy(o => o.DisplayName).ToList();
var i = 0;
this.Items.ToList().ForEach(e => e.ItemIndex = i++);
User32.SendMessage(this.LVHandle, MSG.LVM_SETITEMCOUNT, this.Items.Count, 0x2);
}
if (this.IsGroupsEnabled) {
var colData = this.AllAvailableColumns.FirstOrDefault(w => w.Value.ID == folderSettings.GroupCollumn).Value;
this.GenerateGroupsFromColumn(colData, folderSettings.GroupOrder == SortOrder.Descending);
}
if (!isThereSettings) {
this.LastSortedColumnId = "A0";
this.LastSortOrder = SortOrder.Ascending;
this.SetSortIcon(0, SortOrder.Ascending);
User32.SendMessage(this.LVHandle, MSG.LVM_SETSELECTEDCOLUMN, 0, 0);
}
this._IsDisplayEmptyText = false;
this.BeginInvoke((Action)(() => {
var navArgs = new NavigatedEventArgs(this.RequestedCurrentLocation, this.CurrentFolder, isInSameTab);
this.CurrentFolder = this.RequestedCurrentLocation;
if (!refresh)
Navigated?.Invoke(this, navArgs);
}));
this.Invoke((Action)(() => {
this._NavWaitTimer.Stop();
this._IsDisplayEmptyText = false;
this._IIListView.ResetEmptyText();
}));
GC.Collect();
Shell32.SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
this.Invoke((Action)(() => {
if (this._SearchTimer.Enabled)
this._SearchTimer.Stop();
}));
_Mre.Reset();
_Mre.WaitOne();
});
navigationThread.SetApartmentState(ApartmentState.STA);
this._Threads.Add(navigationThread);
navigationThread.Start();
}