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"> + + + + + + + + + + +