Skip to content

Commit

Permalink
[PowerRename] Show UI info if item cannot be renamed (#19934)
Browse files Browse the repository at this point in the history
* PowerRename cleanup

* Extract ExplorerItem as a UserControl

* Add VisualStateManager

* UI fixes

* Implement error UI logic

Highlight items that couldn't be renamed and add error message flyout

* Update src/modules/powerrename/lib/PowerRenameManager.cpp

Address PR comment

Co-authored-by: Jay <65828559+Jay-o-Way@users.noreply.github.com>

* Update src/modules/powerrename/lib/PowerRenameManager.cpp

Address PR comment

Co-authored-by: Jay <65828559+Jay-o-Way@users.noreply.github.com>

* Folder max path is 247

* Implement State() properly

Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Jay <65828559+Jay-o-Way@users.noreply.github.com>
  • Loading branch information
3 people committed Aug 24, 2022
1 parent c26e23b commit 13db857
Show file tree
Hide file tree
Showing 15 changed files with 688 additions and 228 deletions.
98 changes: 81 additions & 17 deletions src/modules/powerrename/PowerRenameUILib/ExplorerItem.cpp
@@ -1,10 +1,42 @@
#include "pch.h"
#include "pch.h"
#include "ExplorerItem.h"
#if __has_include("ExplorerItem.g.cpp")
#include "ExplorerItem.g.cpp"
#endif

namespace {
using namespace winrt;
using namespace Microsoft::UI::Xaml;
using namespace Microsoft::Windows::ApplicationModel::Resources;

namespace
{
const wchar_t fileImagePath[] = L"ms-appx:///Assets/file.png";
const wchar_t folderImagePath[] = L"ms-appx:///Assets/folder.png";

std::wstring PowerRenameItemRenameStatusToString(PowerRenameItemRenameStatus status)
{
switch (status)
{
case PowerRenameItemRenameStatus::Init:
{
return L"Normal";
}
case PowerRenameItemRenameStatus::ShouldRename:
{
return L"Highlight";
}
case PowerRenameItemRenameStatus::ItemNameInvalidChar:
{
return L"Error";
}
case PowerRenameItemRenameStatus::ItemNameTooLong:
{
return L"Error";
}
default:
return L"Normal";
}
}
}

namespace winrt::PowerRenameUI::implementation
Expand All @@ -13,7 +45,6 @@ namespace winrt::PowerRenameUI::implementation
m_id{ id }, m_idStr{ std::to_wstring(id) }, m_original{ original }, m_renamed{ renamed }, m_type{ type }, m_depth{ depth }, m_checked{ checked }
{
m_imagePath = (m_type == static_cast<UINT>(ExplorerItemType::Folder)) ? folderImagePath : fileImagePath;
m_highlight = m_checked && !m_renamed.empty() ? Microsoft::UI::Xaml::Visibility::Visible : Microsoft::UI::Xaml::Visibility::Collapsed;
}

int32_t ExplorerItem::Id()
Expand Down Expand Up @@ -51,17 +82,11 @@ namespace winrt::PowerRenameUI::implementation
{
m_renamed = value;
m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Renamed" });

auto visibility = m_checked && !m_renamed.empty() ? Microsoft::UI::Xaml::Visibility::Visible : Microsoft::UI::Xaml::Visibility::Collapsed;
if (m_highlight != visibility)
{
m_highlight = visibility;
m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Highlight" });
}
}
}

double ExplorerItem::Indentation() {
double ExplorerItem::Indentation()
{
return static_cast<double>(m_depth) * 12;
}

Expand Down Expand Up @@ -96,18 +121,35 @@ namespace winrt::PowerRenameUI::implementation
m_checked = value;
m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Checked" });

auto visibility = m_checked && !m_renamed.empty() ? Microsoft::UI::Xaml::Visibility::Visible : Microsoft::UI::Xaml::Visibility::Collapsed;
if (m_highlight != visibility)
if (m_checked && !m_renamed.empty())
{
VisualStateManager::GoToState(*this, PowerRenameItemRenameStatusToString(m_state), false);
}
else
{
m_highlight = visibility;
m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Highlight" });
VisualStateManager::GoToState(*this, L"Normal", false);
}
}
}

Microsoft::UI::Xaml::Visibility ExplorerItem::Highlight()
int32_t ExplorerItem::State()
{
return m_highlight;
return static_cast<int32_t>(m_state);
}

void ExplorerItem::State(int32_t value)
{
m_state = static_cast<PowerRenameItemRenameStatus>(value);
ErrorMessageTxt().Text(StateToErrorMessage());

if (m_renamed == L"")
{
VisualStateManager::GoToState(*this, L"Normal", false);
}
else
{
VisualStateManager::GoToState(*this, PowerRenameItemRenameStatusToString(m_state), false);
}
}

winrt::event_token ExplorerItem::PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
Expand All @@ -119,4 +161,26 @@ namespace winrt::PowerRenameUI::implementation
{
m_propertyChanged.remove(token);
}

std::wstring ExplorerItem::StateToErrorMessage()
{
auto factory = winrt::get_activation_factory<ResourceManager, IResourceManagerFactory>();
ResourceManager manager = factory.CreateInstance(L"resources.pri");

switch (m_state)
{
case PowerRenameItemRenameStatus::ItemNameInvalidChar:
{
return std::wstring{ manager.MainResourceMap().GetValue(L"Resources/ErrorMessage_InvalidChar").ValueAsString() };
}
case PowerRenameItemRenameStatus::ItemNameTooLong:
{
return std::wstring{ manager.MainResourceMap().GetValue(L"Resources/ErrorMessage_FileNameTooLong").ValueAsString() };
}
default:
return {};
}

}

}
24 changes: 17 additions & 7 deletions src/modules/powerrename/PowerRenameUILib/ExplorerItem.h
@@ -1,5 +1,11 @@
#pragma once
#pragma once

#include "winrt/Microsoft.UI.Xaml.h"
#include "winrt/Microsoft.UI.Xaml.Markup.h"
#include "winrt/Microsoft.UI.Xaml.Interop.h"
#include "winrt/Microsoft.UI.Xaml.Controls.Primitives.h"
#include "ExplorerItem.g.h"
#include "PowerRenameInterfaces.h"

namespace winrt::PowerRenameUI::implementation
{
Expand All @@ -10,7 +16,7 @@ namespace winrt::PowerRenameUI::implementation
Folder = 0,
File = 1
};

ExplorerItem() = default;

ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, uint32_t depth, bool checked);
Expand All @@ -26,12 +32,14 @@ namespace winrt::PowerRenameUI::implementation
void Type(int32_t value);
bool Checked();
void Checked(bool value);
Microsoft::UI::Xaml::Visibility Highlight();
Windows::Foundation::Collections::IObservableVector<PowerRenameUI::ExplorerItem> Children();
winrt::event_token PropertyChanged(Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
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;

private:
std::wstring StateToErrorMessage();

int32_t m_id;
hstring m_idStr;
winrt::hstring m_original;
Expand All @@ -40,10 +48,12 @@ namespace winrt::PowerRenameUI::implementation
hstring m_imagePath;
int32_t m_type;
bool m_checked;
Microsoft::UI::Xaml::Visibility m_highlight;
PowerRenameItemRenameStatus m_state;
winrt::event<Microsoft::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;

};
}

namespace winrt::PowerRenameUI::factory_implementation
{
struct ExplorerItem : ExplorerItemT<ExplorerItem, implementation::ExplorerItem>
Expand Down
4 changes: 2 additions & 2 deletions src/modules/powerrename/PowerRenameUILib/ExplorerItem.idl
@@ -1,6 +1,6 @@
namespace PowerRenameUI
{
runtimeclass ExplorerItem : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
[default_interface] runtimeclass ExplorerItem : Microsoft.UI.Xaml.Controls.UserControl, Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
ExplorerItem();
ExplorerItem(Int32 id, String original, String renamed, Int32 type, UInt32 depth, Boolean checked);
Expand All @@ -12,6 +12,6 @@ namespace PowerRenameUI
String ImagePath { get; };
Int32 Type;
Boolean Checked;
Microsoft.UI.Xaml.Visibility Highlight { get; };
Int32 State;
}
}
123 changes: 123 additions & 0 deletions src/modules/powerrename/PowerRenameUILib/ExplorerItem.xaml
@@ -0,0 +1,123 @@
<UserControl
x:Class="PowerRenameUI.ExplorerItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:PowerRenameUI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Height="28" Padding="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="4" />
<!-- Some spacing in between -->
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<!-- Error tooltip -->
</Grid.ColumnDefinitions>

<Border
Name="HighlightBorder"
Grid.ColumnSpan="4"
Margin="0,0,0,-1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent" />

<Grid
Grid.Column="0"
Margin="10,4,0,4"
HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="{x:Bind Indentation}" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>


<CheckBox
Name="{x:Bind IdStr}"
Grid.Column="1"
Width="28"
Height="28"
MinWidth="0"
AutomationProperties.HelpText="{x:Bind Renamed}"
AutomationProperties.Name="{x:Bind Original}"
Content=""
IsChecked="{x:Bind Checked, Mode=TwoWay}"
IsTabStop="True"
TabIndex="0"
XYFocusKeyboardNavigation="Enabled" />
<Image
Grid.Column="2"
Width="16"
Margin="4,0,0,0"
HorizontalAlignment="Left"
Source="{x:Bind ImagePath}" />
<TextBlock
Grid.Column="3"
Margin="6,0,4,0"
VerticalAlignment="Center"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind Original, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
</Grid>
<TextBlock
Grid.Column="2"
Margin="0,0,4,0"
VerticalAlignment="Center"
FontSize="12"
FontWeight="SemiBold"
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
Text="{x:Bind Renamed, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />

<Border
x:Name="ErrorIcon"
Grid.Column="3"
Width="12"
Height="12"
CornerRadius="12"
Margin="4,0,8,0"
Background="{ThemeResource SystemFillColorCriticalBrush}"
Visibility="Collapsed">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Foreground="White"
FontSize="8"
Text="&#xE10A;" />
<ToolTipService.ToolTip>
<TextBlock
x:Name="ErrorMessageTxt"
Text="Error message goes here"
TextWrapping="Wrap" />
</ToolTipService.ToolTip>
</Border>

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Highlight">
<VisualState.Setters>
<Setter Target="HighlightBorder.Opacity" Value="0.1" />
<Setter Target="HighlightBorder.BorderBrush" Value="{ThemeResource AccentTextFillColorPrimaryBrush}" />
<Setter Target="HighlightBorder.Background" Value="{ThemeResource AccentTextFillColorPrimaryBrush}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Error">
<VisualState.Setters>
<Setter Target="HighlightBorder.Opacity" Value="1" />
<Setter Target="HighlightBorder.BorderBrush" Value="{ThemeResource SystemFillColorCriticalBackgroundBrush}" />
<Setter Target="HighlightBorder.Background" Value="{ThemeResource SystemFillColorCriticalBackgroundBrush}" />
<Setter Target="ErrorIcon.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</UserControl>
4 changes: 0 additions & 4 deletions src/modules/powerrename/PowerRenameUILib/MainWindow.idl
Expand Up @@ -16,9 +16,5 @@ namespace PowerRenameUI

String OriginalCount;
String RenamedCount;

void AddExplorerItem(Int32 id, String original, String renamed, Int32 type, UInt32 depth, Boolean checked);
void UpdateExplorerItem(Int32 id, String newName);
void UpdateRenamedExplorerItem(Int32 id, String newOriginalName);
}
}

0 comments on commit 13db857

Please sign in to comment.