stupid levels returning to nominal values

This commit is contained in:
Mike Griese
2025-08-08 05:57:58 -05:00
parent 36f85218e1
commit 940e71f2a8
14 changed files with 105 additions and 62 deletions

View File

@@ -83,7 +83,7 @@ public partial class CommandViewModel : ExtensionObjectViewModel
UpdateProperty(nameof(Icon));
}
if (model is ICommandWithProperties command2)
if (model is IHaveProperties command2)
{
Properties = command2.Properties;
}
@@ -121,8 +121,8 @@ public partial class CommandViewModel : ExtensionObjectViewModel
Icon = new(iconInfo);
Icon.InitializeProperties();
break;
case nameof(ICommandWithProperties.Properties):
if (model is ICommandWithProperties command2)
case nameof(IHaveProperties.Properties):
if (model is IHaveProperties command2)
{
Properties = command2.Properties;
}

View File

@@ -27,6 +27,8 @@ public partial class IconDataViewModel : ObservableObject, IIconData
IRandomAccessStreamReference? IIconData.Data => Data.Unsafe;
public string? FontFamily { get; private set; }
public IconDataViewModel(IIconData? icon)
{
_model = new(icon);
@@ -43,5 +45,13 @@ public partial class IconDataViewModel : ObservableObject, IIconData
Icon = model.Icon;
Data = new(model.Data);
if (model is IHaveProperties icon2)
{
if (icon2.Properties?.TryGetValue("FontFamily", out var family) ?? false)
{
FontFamily = family as string;
}
}
}
}

View File

@@ -214,9 +214,9 @@ public sealed class CommandProviderWrapper
Logger.LogDebug($"Provider supports {apiExtensions.Length} extensions");
foreach (var a in apiExtensions)
{
if (a is ICommandWithProperties command2)
if (a is IHaveProperties command2)
{
Logger.LogDebug($"{ProviderId}: Found an ICommand2");
Logger.LogDebug($"{ProviderId}: Found an IHaveProperties");
}
}
}

View File

@@ -25,7 +25,7 @@ public sealed class IconCacheService(DispatcherQueue dispatcherQueue)
{
if (!string.IsNullOrEmpty(icon.Icon))
{
var source = IconPathConverter.IconSourceMUX(icon.Icon, false);
var source = IconPathConverter.IconSourceMUX(icon.Icon, false, icon.FontFamily);
return source;
}
else if (icon.Data != null)

View File

@@ -158,7 +158,7 @@ namespace winrt::Microsoft::Terminal::UI::implementation
// Return Value:
// - An IconElement with its IconSource set, if possible.
template<typename TIconSource>
TIconSource _getIconSource(const winrt::hstring& iconPath, bool monochrome, const int targetSize)
TIconSource _getIconSource(const winrt::hstring& iconPath, bool monochrome, const winrt::hstring& fontFamily, const int targetSize)
{
TIconSource iconSource{ nullptr };
@@ -187,6 +187,11 @@ namespace winrt::Microsoft::Terminal::UI::implementation
{
icon.FontFamily(winrt::Microsoft::UI::Xaml::Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" });
}
else if (!fontFamily.empty())
{
icon.FontFamily(winrt::Microsoft::UI::Xaml::Media::FontFamily{ fontFamily });
}
else
{
// Note: you _do_ need to manually set the font here.
@@ -225,9 +230,9 @@ namespace winrt::Microsoft::Terminal::UI::implementation
// return _getIconSource<Windows::UI::Xaml::Controls::IconSource>(path, false);
// }
static Microsoft::UI::Xaml::Controls::IconSource _IconSourceMUX(const hstring& path, bool monochrome, const int targetSize)
static Microsoft::UI::Xaml::Controls::IconSource _IconSourceMUX(const hstring& path, bool monochrome, const winrt::hstring& fontFamily, const int targetSize)
{
return _getIconSource<Microsoft::UI::Xaml::Controls::IconSource>(path, monochrome, targetSize);
return _getIconSource<Microsoft::UI::Xaml::Controls::IconSource>(path, monochrome, fontFamily, targetSize);
}
static SoftwareBitmap _convertToSoftwareBitmap(HICON hicon,
@@ -343,13 +348,14 @@ namespace winrt::Microsoft::Terminal::UI::implementation
MUX::Controls::IconSource IconPathConverter::IconSourceMUX(const winrt::hstring& iconPath,
const bool monochrome,
const winrt::hstring& fontFamily,
const int targetSize)
{
std::wstring_view iconPathWithoutIndex;
const auto indexOpt = _getIconIndex(iconPath, iconPathWithoutIndex);
if (!indexOpt.has_value())
{
return _IconSourceMUX(iconPath, monochrome, targetSize);
return _IconSourceMUX(iconPath, monochrome, fontFamily, targetSize);
}
const auto bitmapSource = _getImageIconSourceForBinary(iconPathWithoutIndex, indexOpt.value(), targetSize);
@@ -369,7 +375,7 @@ namespace winrt::Microsoft::Terminal::UI::implementation
const auto indexOpt = _getIconIndex(iconPath, iconPathWithoutIndex);
if (!indexOpt.has_value())
{
auto source = IconSourceMUX(iconPath, false, targetSize);
auto source = IconSourceMUX(iconPath, false, L"", targetSize);
Microsoft::UI::Xaml::Controls::IconSourceElement icon;
icon.IconSource(source);
return icon;

View File

@@ -10,7 +10,7 @@ namespace winrt::Microsoft::Terminal::UI::implementation
//static Windows::UI::Xaml::Controls::IconElement IconWUX(const winrt::hstring& iconPath);
//static Windows::UI::Xaml::Controls::IconSource IconSourceWUX(const winrt::hstring& iconPath);
static Microsoft::UI::Xaml::Controls::IconSource IconSourceMUX(const winrt::hstring& iconPath, bool convertToGrayscale, const int targetSize=24);
static Microsoft::UI::Xaml::Controls::IconSource IconSourceMUX(const winrt::hstring& iconPath, bool convertToGrayscale, const winrt::hstring& fontFamily, const int targetSize=24);
static Microsoft::UI::Xaml::Controls::IconElement IconMUX(const winrt::hstring& iconPath);
static Microsoft::UI::Xaml::Controls::IconElement IconMUX(const winrt::hstring& iconPath, const int targetSize);

View File

@@ -7,7 +7,7 @@ namespace Microsoft.Terminal.UI
{
// static Windows.UI.Xaml.Controls.IconElement IconWUX(String path);
// static Windows.UI.Xaml.Controls.IconSource IconSourceWUX(String path);
static Microsoft.UI.Xaml.Controls.IconSource IconSourceMUX(String path, Boolean convertToGrayscale);
static Microsoft.UI.Xaml.Controls.IconSource IconSourceMUX(String path, Boolean convertToGrayscale, String fontFamily);
static Microsoft.UI.Xaml.Controls.IconElement IconMUX(String path);
static Microsoft.UI.Xaml.Controls.IconElement IconMUX(String path, Int32 targetSize);
};

View File

@@ -1969,7 +1969,7 @@ So that's exactly what we're going to do, because it works. As an example,
we're going to add the following interface to our API:
```csharp
interface ICommandWithProperties requires ICommand
interface IHaveProperties
{
Windows.Foundation.Collections.IPropertySet Properties { get; };
};
@@ -1980,30 +1980,30 @@ interface ICommandProvider2 requires ICommandProvider
};
```
`ICommandWithProperties` is just a simple interface, indicating that there's
some property bag of additional values that the host could read. `ICommand`
proves uniquely challenging to extend, because it has both the
`IInvokableCommand` and `IPage` family trees of interfaces which extend from
it.
Typically, it would be impossible for a class to be defined as
`IHaveProperties` is just a simple interface, indicating that there's
some property bag of additional values that the host could read.
AS an example, `ICommand` proves uniquely challenging to extend, because it has
both the `IInvokableCommand` and `IPage` family trees of interfaces which
extend from it. Typically, it would be impossible for a class to be defined as
```cs
class MyCommandWithProperties : IInvokableCommand, ICommandWithProperties { ... }
class MyCommandWithProperties : IInvokableCommand, IHaveProperties { ... }
```
because Command Palette would only ever see the _first_ interface
(`IInvokableCommand`) via MBM, and would never be able to check if an extension
object was an `ICommandWithProperties`. But a class defined like
object was an `IHaveProperties`. But a class defined like
```cs
class CommandWithOnlyProperties : ICommandWithProperties { ... }
class CommandWithOnlyProperties : IHaveProperties { ... }
```
will populate the WinRT type cache in Command Palette with the type information
for `ICommandWithProperties`. In fact, if Command Palette has the
`ICommandWithProperties` type info in it's cache, and then later recieves a new
`IHaveProperties` type info in it's cache, and then later recieves a new
`MyCommandWithProperties` object, it'll actually be able to know that
`MyCommandWithProperties` is an `ICommandWithProperties`. WinRT is just weird
`MyCommandWithProperties` is an `IHaveProperties`. WinRT is just weird
like that some times.
`ICommandProvider2` is where the magic happens. This is a _linear_ addition to
@@ -2031,7 +2031,7 @@ public partial class SamplePagesCommandsProvider : CommandProvider, ICommandProv
public object[] GetApiExtensionStubs() {
return [new SupportCommandsWithProperties()];
}
private sealed partial class SupportCommandsWithProperties : ICommand2 {
private sealed partial class SupportCommandsWithProperties : IHaveProperties {
public IPropertySet OtherProperties => null;
public IIconInfo Icon => null;
public string Id => string.Empty;

View File

@@ -172,10 +172,6 @@ internal sealed partial class SampleListPage : ListPage
Title = "Get the name of the Foreground window",
},
// new ListItem(new JustHasProps())
// {
// Title = "Not actually invokable",
// },
new ListItem(new CommandWithProperties())
{
Title = "I have properties",
@@ -187,8 +183,12 @@ internal sealed partial class SampleListPage : ListPage
];
}
internal sealed partial class CommandWithProperties : InvokableCommand, ICommandWithProperties
internal sealed partial class CommandWithProperties : InvokableCommand, IHaveProperties
{
private FontIconData _icon = new("\u0026", "Wingdings");
public override IconInfo Icon => new IconInfo(_icon, _icon);
public override string Name => "Whatever";
public IPropertySet Properties => new PropertySet()
@@ -200,7 +200,7 @@ internal sealed partial class SampleListPage : ListPage
}
#nullable enable
internal sealed partial class OtherCommandWithProperties : ICommandWithProperties, IInvokableCommand
internal sealed partial class OtherCommandWithProperties : IHaveProperties, IInvokableCommand
{
public string Name => "Whatever 2";
@@ -216,13 +216,11 @@ internal sealed partial class SampleListPage : ListPage
return CommandResult.ShowToast("whoop");
}
public IPropertySet OtherProperties => new PropertySet()
public IPropertySet Properties => new PropertySet()
{
{ "yo", "dawg" },
{ "Secret", 12345 },
{ "hmm?", null },
};
public IPropertySet Properties => throw new System.NotImplementedException();
}
}

View File

@@ -4,12 +4,10 @@
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace SamplePagesExtension;
public partial class SamplePagesCommandsProvider : CommandProvider, ICommandProvider2
public partial class SamplePagesCommandsProvider : CommandProvider
{
public SamplePagesCommandsProvider()
{
@@ -29,26 +27,4 @@ public partial class SamplePagesCommandsProvider : CommandProvider, ICommandProv
{
return _commands;
}
public object[] GetApiExtensionStubs()
{
return [new SupportCommandsWithProperties()];
}
private sealed partial class SupportCommandsWithProperties : ICommandWithProperties
{
public IPropertySet Properties => null;
public IIconInfo Icon => null;
public string Id => string.Empty;
public string Name => string.Empty;
public event TypedEventHandler<object, IPropChangedEventArgs> PropChanged
{
add { }
remove { }
}
}
}

View File

@@ -3,10 +3,11 @@
// See the LICENSE file in the project root for more information.
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace Microsoft.CommandPalette.Extensions.Toolkit;
public abstract partial class CommandProvider : ICommandProvider
public abstract partial class CommandProvider : ICommandProvider, ICommandProvider2
{
public virtual string Id { get; protected set; } = string.Empty;
@@ -47,4 +48,26 @@ public abstract partial class CommandProvider : ICommandProvider
{
}
}
/// <summary>
/// This is used to manually populate the WinRT type cache in CmdPal with
/// any interfaces that might not follow a straight linear path of requires.
///
/// You don't need to call this as an extension author.
/// </summary>
/// <returns>an array of objects that implement all the leaf interfaces we support</returns>
public object[] GetApiExtensionStubs()
{
return [new SupportCommandsWithProperties()];
}
/// <summary>
/// A stub class which implements IHaveProperties. Just marshalling this
/// across the ABI will be enough for CmdPal to store IHaveProperties in
/// its type cache.
/// </summary>
private sealed partial class SupportCommandsWithProperties : IHaveProperties
{
public IPropertySet? Properties => null;
}
}

View File

@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.Foundation.Collections;
using Windows.Storage.Streams;
namespace Microsoft.CommandPalette.Extensions.Toolkit;
public partial class FontIconData : IconData, IHaveProperties
{
public string FontFace { get; set; }
public FontIconData(string glyph, string fontFace)
: base(glyph)
{
FontFace = fontFace;
}
public IPropertySet Properties => new PropertySet()
{
{ "FontFamily", FontFace },
};
}

View File

@@ -27,6 +27,12 @@ public partial class IconInfo : IIconInfo
Dark = dark;
}
public IconInfo(IconData icon)
{
Light = icon;
Dark = icon;
}
internal IconInfo()
: this(string.Empty)
{

View File

@@ -365,7 +365,7 @@ namespace Microsoft.CommandPalette.Extensions
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface ICommandWithProperties requires ICommand
interface IHaveProperties
{
Windows.Foundation.Collections.IPropertySet Properties { get; };
};