diff --git a/src/modules/powerrename/PowerRenameUILib/App.xaml b/src/modules/powerrename/PowerRenameUILib/App.xaml
index 90faab2da7..370bbec8e7 100644
--- a/src/modules/powerrename/PowerRenameUILib/App.xaml
+++ b/src/modules/powerrename/PowerRenameUILib/App.xaml
@@ -1060,7 +1060,36 @@
-
+
+
diff --git a/src/modules/powerrename/PowerRenameUILib/App.xaml.cpp b/src/modules/powerrename/PowerRenameUILib/App.xaml.cpp
index 4d78b31a73..415acad0d4 100644
--- a/src/modules/powerrename/PowerRenameUILib/App.xaml.cpp
+++ b/src/modules/powerrename/PowerRenameUILib/App.xaml.cpp
@@ -5,6 +5,7 @@
#include
#include
+#include
#include
#include
@@ -18,8 +19,9 @@ using namespace winrt::Microsoft::UI::Xaml::Navigation;
using namespace PowerRenameUI;
using namespace PowerRenameUI::implementation;
-// To learn more about WinUI, the WinUI project structure,
-// and more about our project templates, see: http://aka.ms/winui-project-info.
+namespace fs = std::filesystem;
+
+//#define DEBUG_BENCHMARK_100K_ENTRIES
std::vector g_files;
@@ -34,8 +36,7 @@ App::App()
InitializeComponent();
#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
- UnhandledException([this](IInspectable const&, UnhandledExceptionEventArgs const& e)
- {
+ UnhandledException([this](IInspectable const&, UnhandledExceptionEventArgs const& e) {
if (IsDebuggerPresent())
{
auto errorMessage = e.Message();
@@ -112,6 +113,50 @@ void App::OnLaunched(LaunchActivatedEventArgs const&)
ExitProcess(1);
}
+#ifdef DEBUG_BENCHMARK_100K_ENTRIES
+ const std::wstring_view ROOT_PATH = L"R:\\PowerRenameBenchmark";
+
+ std::wstring subdirectory_name = L"0";
+ std::error_code _;
+
+#if 1
+ constexpr bool recreate_files = true;
+#else
+ constexpr bool recreate_files = false;
+#endif
+ if constexpr (recreate_files)
+ fs::remove_all(ROOT_PATH, _);
+
+ g_files.push_back(fs::path{ ROOT_PATH });
+ constexpr int pow2_threshold = 10;
+ constexpr int num_files = 100'000;
+ for (int i = 0; i < num_files; ++i)
+ {
+ fs::path file_path{ ROOT_PATH };
+ // Create a subdirectory for each subsequent 2^pow2_threshold files, o/w filesystem becomes too slow to create them in a reasonable time.
+ if ((i & ((1 << pow2_threshold) - 1)) == 0)
+ {
+ subdirectory_name = std::to_wstring(i >> pow2_threshold);
+ }
+
+ file_path /= subdirectory_name;
+
+ if constexpr (recreate_files)
+ {
+ fs::create_directories(file_path, _);
+ file_path /= std::to_wstring(i) + L".txt";
+ HANDLE hFile = CreateFileW(
+ file_path.c_str(),
+ GENERIC_WRITE,
+ 0,
+ nullptr,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ nullptr);
+ CloseHandle(hFile);
+ }
+ }
+#else
#define BUFSIZE 4096 * 4
BOOL bSuccess;
@@ -139,6 +184,7 @@ void App::OnLaunched(LaunchActivatedEventArgs const&)
break;
}
CloseHandle(hStdin);
+#endif
Logger::debug(L"Starting PowerRename with {} files selected", g_files.size());
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItem.cpp b/src/modules/powerrename/PowerRenameUILib/ExplorerItem.cpp
index 48cefa7e37..f30bb001cb 100644
--- a/src/modules/powerrename/PowerRenameUILib/ExplorerItem.cpp
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItem.cpp
@@ -41,10 +41,33 @@ namespace
namespace winrt::PowerRenameUI::implementation
{
- ExplorerItem::ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, uint32_t depth, bool checked) :
- m_id{ id }, m_idStr{ std::to_wstring(id) }, m_original{ original }, m_renamed{ renamed }, m_type{ type }, m_depth{ depth }, m_checked{ checked }
+ DependencyProperty ExplorerItem::_CheckedProperty{ nullptr };
+
+ void ExplorerItem::_InitializeProperties()
{
+ if (!_CheckedProperty)
+ {
+ _CheckedProperty =
+ DependencyProperty::Register(
+ L"Checked",
+ xaml_typename(),
+ xaml_typename(),
+ PropertyMetadata{ box_value(true) });
+ }
+ }
+
+ ExplorerItem::ExplorerItem()
+ {
+ _InitializeProperties();
+ }
+
+ ExplorerItem::ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, uint32_t depth, bool checked) :
+ m_id{ id }, m_idStr{ std::to_wstring(id) }, m_original{ original }, m_renamed{ renamed }, m_type{ type }, m_depth{ depth }
+ {
+ _InitializeProperties();
+
m_imagePath = (m_type == static_cast(ExplorerItemType::Folder)) ? folderImagePath : fileImagePath;
+ Checked(checked);
}
int32_t ExplorerItem::Id()
@@ -52,11 +75,29 @@ namespace winrt::PowerRenameUI::implementation
return m_id;
}
+ void ExplorerItem::Id(const int32_t value)
+ {
+ if (m_id != value)
+ {
+ m_id = value;
+ m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Id" });
+ }
+ }
+
hstring ExplorerItem::IdStr()
{
return m_idStr;
}
+ void ExplorerItem::IdStr(hstring const& value)
+ {
+ if (m_idStr != value)
+ {
+ m_idStr = value;
+ m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"IdStr" });
+ }
+ }
+
hstring ExplorerItem::Original()
{
return m_original;
@@ -90,11 +131,29 @@ namespace winrt::PowerRenameUI::implementation
return static_cast(m_depth) * 12;
}
+ void ExplorerItem::Indentation(double value)
+ {
+ if (m_depth != value)
+ {
+ m_depth = static_cast(value / 12);
+ m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Indentation" });
+ }
+ }
+
hstring ExplorerItem::ImagePath()
{
return m_imagePath;
}
+ void ExplorerItem::ImagePath(hstring const& value)
+ {
+ if (m_imagePath != value)
+ {
+ m_imagePath = value;
+ m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"ImagePath" });
+ }
+ }
+
int32_t ExplorerItem::Type()
{
return m_type;
@@ -109,29 +168,6 @@ namespace winrt::PowerRenameUI::implementation
}
}
- bool ExplorerItem::Checked()
- {
- return m_checked;
- }
-
- void ExplorerItem::Checked(bool value)
- {
- if (m_checked != value)
- {
- m_checked = value;
- m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Checked" });
-
- if (m_checked && !m_renamed.empty())
- {
- VisualStateManager::GoToState(*this, PowerRenameItemRenameStatusToString(m_state), false);
- }
- else
- {
- VisualStateManager::GoToState(*this, L"Normal", false);
- }
- }
- }
-
int32_t ExplorerItem::State()
{
return static_cast(m_state);
@@ -166,7 +202,7 @@ namespace winrt::PowerRenameUI::implementation
{
static auto factory = winrt::get_activation_factory();
static ResourceManager manager = factory.CreateInstance(L"resources.pri");
- static auto invalid_char_error = manager.MainResourceMap().GetValue(L"Resources/ErrorMessage_InvalidChar").ValueAsString();
+ static auto invalid_char_error = manager.MainResourceMap().GetValue(L"Resources/ErrorMessage_InvalidChar").ValueAsString();
static auto name_too_long_error = manager.MainResourceMap().GetValue(L"Resources/ErrorMessage_FileNameTooLong").ValueAsString();
switch (m_state)
@@ -182,7 +218,6 @@ namespace winrt::PowerRenameUI::implementation
default:
return {};
}
-
}
}
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItem.h b/src/modules/powerrename/PowerRenameUILib/ExplorerItem.h
index 293d059d7b..68f94edbaa 100644
--- a/src/modules/powerrename/PowerRenameUILib/ExplorerItem.h
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItem.h
@@ -6,6 +6,7 @@
#include "winrt/Microsoft.UI.Xaml.Controls.Primitives.h"
#include "ExplorerItem.g.h"
#include "PowerRenameInterfaces.h"
+#include "Utils.h"
namespace winrt::PowerRenameUI::implementation
{
@@ -17,27 +18,39 @@ namespace winrt::PowerRenameUI::implementation
File = 1
};
- ExplorerItem() = default;
+ ExplorerItem();
ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, uint32_t depth, bool checked);
int32_t Id();
+ void Id(int32_t);
+
hstring IdStr();
+ void IdStr(hstring const& value);
+
hstring Original();
void Original(hstring const& value);
+
hstring Renamed();
void Renamed(hstring const& value);
+
double Indentation();
+ void Indentation(double value);
+
hstring ImagePath();
+ void ImagePath(hstring const& value);
int32_t Type();
void Type(int32_t value);
- bool Checked();
- void Checked(bool value);
int32_t State();
void State(int32_t value);
winrt::event_token PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
void PropertyChanged(winrt::event_token const& token) noexcept;
+ DEPENDENCY_PROPERTY(bool, Checked);
+
private:
+
+ static void _InitializeProperties();
+
std::wstring StateToErrorMessage();
int32_t m_id{};
@@ -47,7 +60,6 @@ namespace winrt::PowerRenameUI::implementation
uint32_t m_depth{};
hstring m_imagePath;
int32_t m_type{};
- bool m_checked{};
PowerRenameItemRenameStatus m_state{};
winrt::event m_propertyChanged;
};
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItem.idl b/src/modules/powerrename/PowerRenameUILib/ExplorerItem.idl
index b302f4636b..56e8c01cde 100644
--- a/src/modules/powerrename/PowerRenameUILib/ExplorerItem.idl
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItem.idl
@@ -4,14 +4,17 @@ namespace PowerRenameUI
{
ExplorerItem();
ExplorerItem(Int32 id, String original, String renamed, Int32 type, UInt32 depth, Boolean checked);
- Int32 Id { get; };
- String IdStr { get; };
+
+ Int32 Id;
+ String IdStr;
String Original;
String Renamed;
- Double Indentation { get; };
- String ImagePath { get; };
+ Double Indentation;
+ String ImagePath;
Int32 Type;
Boolean Checked;
Int32 State;
+
+ static Microsoft.UI.Xaml.DependencyProperty CheckedProperty { get; };
}
}
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItem.xaml b/src/modules/powerrename/PowerRenameUILib/ExplorerItem.xaml
index e52a080939..93010cc4c0 100644
--- a/src/modules/powerrename/PowerRenameUILib/ExplorerItem.xaml
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItem.xaml
@@ -49,7 +49,9 @@
IsChecked="{x:Bind Checked, Mode=TwoWay}"
IsTabStop="True"
TabIndex="0"
+ Style="{StaticResource CheckBoxDefaultStyleOverride}"
XYFocusKeyboardNavigation="Enabled" />
+
+
+#include "ExplorerItemViewModel.h"
+#if __has_include("ExplorerItemViewModel.g.cpp")
+#include "ExplorerItemViewModel.g.cpp"
+#endif
+#include
+#include
+
+extern CComPtr g_prManager;
+extern std::function g_itemToggledCallback;
+
+namespace
+{
+ const wchar_t fileImagePath[] = L"ms-appx:///Assets/file.png";
+ const wchar_t folderImagePath[] = L"ms-appx:///Assets/folder.png";
+}
+
+namespace winrt::PowerRenameUI::implementation
+{
+ winrt::event_token ExplorerItemViewModel::PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
+ {
+ return m_propertyChanged.add(handler);
+ }
+
+ void ExplorerItemViewModel::PropertyChanged(winrt::event_token const& token) noexcept
+ {
+ m_propertyChanged.remove(token);
+ }
+ ExplorerItemViewModel::ExplorerItemViewModel(const uint32_t _index) :
+ _index{ _index }
+ {
+ }
+
+ int32_t ExplorerItemViewModel::IdVM()
+ {
+ return _index;
+ }
+ hstring ExplorerItemViewModel::IdStrVM()
+ {
+ return to_hstring(_index);
+ }
+ hstring ExplorerItemViewModel::OriginalVM()
+ {
+ CComPtr spItem;
+ winrt::check_hresult(g_prManager->GetItemByIndex(_index, &spItem));
+
+ PWSTR originalName = nullptr;
+ winrt::check_hresult(spItem->GetOriginalName(&originalName));
+
+ return hstring{ originalName };
+ }
+ hstring ExplorerItemViewModel::RenamedVM()
+ {
+ CComPtr spItem;
+ winrt::check_hresult(g_prManager->GetItemByIndex(_index, &spItem));
+
+ PWSTR newName = nullptr;
+ spItem->GetNewName(&newName);
+ if (!newName)
+ {
+ return L"";
+ }
+ else
+ {
+ hstring result{ newName };
+ SHFree(newName);
+
+ return result;
+ }
+ }
+
+ double ExplorerItemViewModel::IndentationVM()
+ {
+ CComPtr spItem;
+ winrt::check_hresult(g_prManager->GetItemByIndex(_index, &spItem));
+
+ UINT depth = 0;
+ spItem->GetDepth(&depth);
+
+ return static_cast(depth) * 12;
+ }
+ hstring ExplorerItemViewModel::ImagePathVM()
+ {
+ return TypeVM() ? fileImagePath : folderImagePath;
+ }
+ int32_t ExplorerItemViewModel::TypeVM()
+ {
+ CComPtr spItem;
+ winrt::check_hresult(g_prManager->GetItemByIndex(_index, &spItem));
+
+ bool isFolder = false;
+ spItem->GetIsFolder(&isFolder);
+ return isFolder ? 0 : 1;
+ }
+
+ bool ExplorerItemViewModel::CheckedVM()
+ {
+ CComPtr spItem;
+ winrt::check_hresult(g_prManager->GetItemByIndex(_index, &spItem));
+ bool result = false;
+ winrt::check_hresult(spItem->GetSelected(&result));
+ return result;
+ }
+ void ExplorerItemViewModel::CheckedVM(bool value)
+ {
+ CComPtr spItem;
+ winrt::check_hresult(g_prManager->GetItemByIndex(_index, &spItem));
+ winrt::check_hresult(spItem->PutSelected(value));
+ g_itemToggledCallback();
+ }
+
+ int32_t ExplorerItemViewModel::StateVM()
+ {
+ CComPtr spItem;
+ winrt::check_hresult(g_prManager->GetItemByIndex(_index, &spItem));
+ PowerRenameItemRenameStatus status {};
+ spItem->GetStatus(&status);
+ return static_cast(status);
+ }
+}
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItemViewModel.h b/src/modules/powerrename/PowerRenameUILib/ExplorerItemViewModel.h
new file mode 100644
index 0000000000..5cd1876e68
--- /dev/null
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItemViewModel.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "ExplorerItemViewModel.g.h"
+
+namespace winrt::PowerRenameUI::implementation
+{
+ struct ExplorerItemViewModel : ExplorerItemViewModelT
+ {
+ ExplorerItemViewModel() = default;
+ ExplorerItemViewModel(const uint32_t _index);
+
+ int32_t IdVM();
+ hstring IdStrVM();
+ hstring OriginalVM();
+ hstring RenamedVM();
+ double IndentationVM();
+ hstring ImagePathVM();
+ int32_t TypeVM();
+ bool CheckedVM();
+ void CheckedVM(bool value);
+ int32_t StateVM();
+
+ winrt::event_token PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
+ void PropertyChanged(winrt::event_token const& token) noexcept;
+
+ uint32_t _index = 0;
+ winrt::event m_propertyChanged;
+ };
+}
+
+namespace winrt::PowerRenameUI::factory_implementation
+{
+ struct ExplorerItemViewModel : ExplorerItemViewModelT
+ {
+ };
+}
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItemViewModel.idl b/src/modules/powerrename/PowerRenameUILib/ExplorerItemViewModel.idl
new file mode 100644
index 0000000000..e10e3d442f
--- /dev/null
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItemViewModel.idl
@@ -0,0 +1,18 @@
+namespace PowerRenameUI
+{
+ [bindable] [default_interface] runtimeclass ExplorerItemViewModel :
+ Microsoft.UI.Xaml.Data.INotifyPropertyChanged
+ {
+ ExplorerItemViewModel();
+
+ Int32 IdVM { get; };
+ String IdStrVM { get; };
+ String OriginalVM { get; };
+ String RenamedVM { get; };
+ Double IndentationVM { get; };
+ String ImagePathVM { get; };
+ Int32 TypeVM { get; };
+ Boolean CheckedVM;
+ Int32 StateVM { get; };
+ }
+}
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.cpp b/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.cpp
new file mode 100644
index 0000000000..b2d5c55286
--- /dev/null
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.cpp
@@ -0,0 +1,12 @@
+#include "pch.h"
+#include "ExplorerItemsSource.h"
+#if __has_include("ExplorerItemsSource.g.cpp")
+#include "ExplorerItemsSource.g.cpp"
+#endif
+
+using namespace winrt;
+using namespace Windows::UI::Xaml;
+
+namespace winrt::PowerRenameUI::implementation
+{
+}
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.h b/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.h
new file mode 100644
index 0000000000..9341f07f31
--- /dev/null
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.h
@@ -0,0 +1,287 @@
+#pragma once
+
+#include "winrt/Windows.UI.Xaml.h"
+#include "winrt/Windows.UI.Xaml.Markup.h"
+#include "winrt/Windows.UI.Xaml.Interop.h"
+#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
+#include "ExplorerItemsSource.g.h"
+#include "ExplorerItemViewModel.h"
+
+#include
+
+using winrt::Microsoft::UI::Xaml::Data::ItemIndexRange;
+using winrt::Windows::Foundation::IInspectable;
+using namespace winrt::Windows::Foundation::Collections;
+
+extern CComPtr g_prManager;
+
+namespace winrt::PowerRenameUI::implementation
+{
+ struct ExplorerItemProxyIterator
+ {
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = IInspectable;
+ using difference_type = std::ptrdiff_t;
+ using pointer = uint32_t;
+ using reference = IInspectable;
+
+ const bool* _filtered = nullptr;
+
+ ExplorerItemProxyIterator(pointer ptr, const bool* filtered) :
+ _index(ptr), _filtered{ filtered } {}
+
+ reference operator*() const
+ {
+ const uint32_t realIndex = g_prManager->GetVisibleItemRealIndex(_index);
+ if (*_filtered)
+ {
+ return winrt::make(realIndex);
+ }
+ else
+ return winrt::make(_index);
+ }
+
+ ExplorerItemProxyIterator& operator++()
+ {
+ _index++;
+ return *this;
+ }
+ ExplorerItemProxyIterator operator++(int)
+ {
+ ExplorerItemProxyIterator tmp = *this;
+ ++(*this);
+ return tmp;
+ }
+ ExplorerItemProxyIterator& operator--()
+ {
+ _index--;
+ return *this;
+ }
+ ExplorerItemProxyIterator operator--(int)
+ {
+ ExplorerItemProxyIterator tmp = *this;
+ --(*this);
+ return tmp;
+ }
+
+ friend bool operator==(const ExplorerItemProxyIterator& a, const ExplorerItemProxyIterator& b) { return a._index == b._index; };
+ friend bool operator!=(const ExplorerItemProxyIterator& a, const ExplorerItemProxyIterator& b) { return a._index != b._index; };
+
+ ExplorerItemProxyIterator& operator+=(difference_type n)
+ {
+ _index += static_cast(n);
+ return *this;
+ }
+ ExplorerItemProxyIterator operator+(difference_type n) const { return ExplorerItemProxyIterator{ static_cast(_index + n), _filtered }; }
+ friend ExplorerItemProxyIterator operator+(difference_type n, const ExplorerItemProxyIterator& iter) { return ExplorerItemProxyIterator(static_cast(n + iter._index), iter._filtered); }
+
+ ExplorerItemProxyIterator& operator-=(difference_type n)
+ {
+ _index -= static_cast(n);
+ return *this;
+ }
+ ExplorerItemProxyIterator operator-(difference_type n) const { return ExplorerItemProxyIterator{ static_cast(_index - n), _filtered }; }
+ difference_type operator-(const ExplorerItemProxyIterator& iter) const { return _index - iter._index; }
+
+ friend bool operator<(const ExplorerItemProxyIterator& a, const ExplorerItemProxyIterator& b) { return a._index < b._index; }
+ friend bool operator>(const ExplorerItemProxyIterator& a, const ExplorerItemProxyIterator& b) { return a._index > b._index; }
+ friend bool operator<=(const ExplorerItemProxyIterator& a, const ExplorerItemProxyIterator& b) { return a._index <= b._index; }
+ friend bool operator>=(const ExplorerItemProxyIterator& a, const ExplorerItemProxyIterator& b) { return a._index >= b._index; }
+
+ private:
+ pointer _index;
+ };
+
+ using ItemT = IInspectable;
+ struct ExplorerItemsSource : ExplorerItemsSourceT, winrt::vector_view_base
+ {
+ bool filtered = false;
+
+ struct Container
+ {
+ ExplorerItemProxyIterator first;
+ ExplorerItemProxyIterator last;
+
+ auto begin() const noexcept
+ {
+ return first;
+ }
+
+ auto end() const noexcept
+ {
+ return last;
+ }
+ } container = { { {}, {} }, { {}, {} } };
+
+ void SetIsFiltered(const bool value)
+ {
+ filtered = value;
+
+ if (!g_prManager)
+ return;
+
+ uint32_t item_count = 0;
+ if (value)
+ winrt::check_hresult(g_prManager->GetVisibleItemCount(&item_count));
+ else
+ winrt::check_hresult(g_prManager->GetItemCount(&item_count));
+
+ container = Container{ { 0, &filtered }, { item_count, &filtered } };
+ }
+
+ auto& get_container() const noexcept
+ {
+ return container;
+ }
+
+ // IObservableVector. We don't need a full implementation, since only the items' properties changes
+
+ Windows::Foundation::Collections::IVectorView GetView() const noexcept
+ {
+ return static_cast(*this);
+ }
+
+ winrt::event_token VectorChanged(Windows::Foundation::Collections::VectorChangedEventHandler const& handler)
+ {
+ return m_changed.add(handler);
+ }
+
+ void VectorChanged(event_token const cookie)
+ {
+ m_changed.remove(cookie);
+ }
+
+ winrt::event> m_changed;
+
+ struct args : implements
+ {
+ args(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index) noexcept :
+ m_change(change),
+ m_index(index)
+ {
+ }
+
+ Windows::Foundation::Collections::CollectionChange CollectionChange() const noexcept
+ {
+ return m_change;
+ }
+
+ uint32_t Index() const noexcept
+ {
+ return m_index;
+ }
+
+ private:
+ Windows::Foundation::Collections::CollectionChange const m_change;
+ uint32_t const m_index;
+ };
+
+ void call_changed(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index)
+ {
+ m_changed(static_cast(*this), make(change, index));
+ }
+
+ void InvalidateCollection()
+ {
+ SetIsFiltered(filtered);
+ call_changed(Windows::Foundation::Collections::CollectionChange::Reset, 0);
+ }
+
+ void InvalidateItemRange(uint32_t const startIdx, uint32_t const count)
+ {
+ for (uint32_t index = startIdx; index < startIdx + count; ++index)
+ call_changed(Windows::Foundation::Collections::CollectionChange::ItemChanged, index);
+ }
+
+ void SetAt(uint32_t const index, ItemT const& /*value*/)
+ {
+ call_changed(Windows::Foundation::Collections::CollectionChange::ItemChanged, index);
+ }
+
+ void InsertAt(uint32_t const index, ItemT const& /*value*/)
+ {
+ call_changed(Windows::Foundation::Collections::CollectionChange::ItemInserted, index);
+ }
+
+ void RemoveAt(uint32_t const index)
+ {
+ call_changed(Windows::Foundation::Collections::CollectionChange::ItemRemoved, index);
+ }
+
+ void Append(ItemT const& /*value*/)
+ {
+ call_changed(Windows::Foundation::Collections::CollectionChange::ItemInserted, this->Size() - 1);
+ }
+
+ void RemoveAtEnd()
+ {
+ call_changed(Windows::Foundation::Collections::CollectionChange::ItemRemoved, this->Size());
+ }
+
+ void Clear()
+ {
+ call_changed(Windows::Foundation::Collections::CollectionChange::Reset, 0);
+ }
+
+ void ReplaceAll(array_view /*value*/)
+ {
+ call_changed(Windows::Foundation::Collections::CollectionChange::Reset, 0);
+ }
+
+ // IClosable
+ void Close() noexcept
+ {
+ }
+
+ // ISelectionInfo
+ void SelectRange(const ItemIndexRange& /*itemIndexRange*/) noexcept
+ {
+ return;
+ }
+
+ void DeselectRange(const ItemIndexRange& /*itemIndexRange*/) noexcept
+ {
+ return;
+ }
+
+ bool IsSelected(int32_t /*index*/) noexcept
+ {
+ return false;
+ }
+
+ IVectorView GetSelectedRanges() noexcept
+ {
+ return {};
+ }
+
+ // IItemsRangeInfo
+ void RangesChanged(const ItemIndexRange& /*visibleRange*/, const IVectorView& /*trackedItems*/)
+ {
+ }
+
+ //INotifyPropertyChanged
+ winrt::event_token PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
+ {
+ return m_propertyChanged.add(handler);
+ }
+
+ void PropertyChanged(winrt::event_token const& token) noexcept
+ {
+ m_propertyChanged.remove(token);
+ }
+
+ winrt::event m_propertyChanged;
+
+ void RaisePropertyChanged(hstring const& propertyName)
+ {
+ m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs(propertyName));
+ }
+ };
+}
+
+namespace winrt::PowerRenameUI::factory_implementation
+{
+ struct ExplorerItemsSource : ExplorerItemsSourceT
+ {
+ };
+}
diff --git a/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.idl b/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.idl
new file mode 100644
index 0000000000..2f9640e169
--- /dev/null
+++ b/src/modules/powerrename/PowerRenameUILib/ExplorerItemsSource.idl
@@ -0,0 +1,12 @@
+namespace PowerRenameUI
+{
+ [default_interface] runtimeclass ExplorerItemsSource :
+ Microsoft.UI.Xaml.Data.IItemsRangeInfo,
+ Microsoft.UI.Xaml.Data.ISelectionInfo,
+ Windows.Foundation.Collections.IVectorView,
+ Windows.Foundation.Collections.IObservableVector,
+ Microsoft.UI.Xaml.Data.INotifyPropertyChanged
+ {
+ ExplorerItemsSource();
+ }
+}
diff --git a/src/modules/powerrename/PowerRenameUILib/MainWindow.idl b/src/modules/powerrename/PowerRenameUILib/MainWindow.idl
index 049fbcb9a4..50c2754e22 100644
--- a/src/modules/powerrename/PowerRenameUILib/MainWindow.idl
+++ b/src/modules/powerrename/PowerRenameUILib/MainWindow.idl
@@ -1,4 +1,5 @@
import "ExplorerItem.idl";
+import "ExplorerItemsSource.idl";
import "PatternSnippet.idl";
namespace PowerRenameUI
@@ -10,7 +11,7 @@ namespace PowerRenameUI
Windows.Foundation.Collections.IObservableVector SearchMRU { get; };
Windows.Foundation.Collections.IObservableVector ReplaceMRU { get; };
- Windows.Foundation.Collections.IObservableVector ExplorerItems { get; };
+ ExplorerItemsSource ExplorerItems { get; };
Windows.Foundation.Collections.IObservableVector SearchRegExShortcuts { get; };
Windows.Foundation.Collections.IObservableVector DateTimeShortcuts { get; };
diff --git a/src/modules/powerrename/PowerRenameUILib/MainWindow.xaml b/src/modules/powerrename/PowerRenameUILib/MainWindow.xaml
index 599ed71227..e50e4e74cf 100644
--- a/src/modules/powerrename/PowerRenameUILib/MainWindow.xaml
+++ b/src/modules/powerrename/PowerRenameUILib/MainWindow.xaml
@@ -48,6 +48,7 @@
Checked="SelectAll"
Content=""
IsChecked="True"
+ Style="{StaticResource CheckBoxDefaultStyleOverride}"
Unchecked="SelectAll" />
+
+ x:Name="listView_ExplorerItems"
+ XYFocusKeyboardNavigation="Enabled"
+ VirtualizingStackPanel.VirtualizationMode="Standard">
+
+
+
+
+
+
+
+
+
+
+