toolkit updated to support these

This commit is contained in:
Mike Griese
2025-11-24 09:02:50 -06:00
parent f63785d80d
commit acb933643a
13 changed files with 206 additions and 73 deletions

View File

@@ -0,0 +1,23 @@
// 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 Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Core.Common.Helpers;
public partial class PinnedDockItem : WrappedDockItem
{
public override string Title => $"{base.Title} ({Properties.Resources.PinnedItemSuffix})";
public PinnedDockItem(ICommand command)
: base(command, command.Name)
{
}
public PinnedDockItem(ICommandItem item, string id)
: base(item, id, item.Title)
{
}
}

View File

@@ -163,20 +163,27 @@ public sealed class CommandProviderWrapper
UnsafePreCacheApiAdditions(two);
}
if (model is IExtendedAttributesProvider iHaveProperties)
// if (model is IExtendedAttributesProvider iHaveProperties)
if (model is ICommandProvider3 supportsDockBands)
{
var props = iHaveProperties.GetProperties();
var hasBands = props.TryGetValue("DockBands", out var obj);
if (hasBands && obj is not null)
// var props = iHaveProperties.GetProperties();
// var hasBands = props.TryGetValue("DockBands", out var obj);
// if (hasBands && obj is not null)
// {
// // CoreLogger.LogDebug($"Found bands object on {DisplayName} ({ProviderId}) ");
// // var bands = (ICommandItem[])obj;
// var bands = obj as ICommandItem[];
// if (bands is not null)
// {
// CoreLogger.LogDebug($"Found {bands.Length} bands on {DisplayName} ({ProviderId}) ");
// dockBands = bands;
// }
// }
var bands = supportsDockBands.GetDockBands();
if (bands is not null)
{
// CoreLogger.LogDebug($"Found bands object on {DisplayName} ({ProviderId}) ");
// var bands = (ICommandItem[])obj;
var bands = obj as ICommandItem[];
if (bands is not null)
{
CoreLogger.LogDebug($"Found {bands.Length} bands on {DisplayName} ({ProviderId}) ");
dockBands = bands;
}
CoreLogger.LogDebug($"Found {bands.Length} bands on {DisplayName} ({ProviderId}) ");
dockBands = bands;
}
}

View File

@@ -13,7 +13,7 @@ namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
/// <summary>
/// Built-in Provider for a top-level command which can quit the application. Invokes the <see cref="QuitCommand"/>, which sends a <see cref="QuitMessage"/>.
/// </summary>
public sealed partial class BuiltInsCommandProvider : CommandProvider, IExtendedAttributesProvider
public sealed partial class BuiltInsCommandProvider : CommandProvider
{
private readonly OpenSettingsCommand openSettings = new();
private readonly QuitCommand quitCommand = new();
@@ -45,16 +45,13 @@ public sealed partial class BuiltInsCommandProvider : CommandProvider, IExtended
_rootPageService = rootPageService;
}
public IDictionary<string, object> GetProperties()
public override ICommandItem[]? GetDockBands()
{
var rootPage = _rootPageService.GetRootPage();
List<ICommandItem> bandItems = new();
bandItems.Add(new WrappedDockItem(rootPage, Properties.Resources.builtin_command_palette_title));
return new PropertySet()
{
{ "DockBands", bandItems.ToArray() },
};
return bandItems.ToArray();
}
public override void InitializeWithHost(IExtensionHost host) => BuiltinsExtensionHost.Instance.Initialize(host);

View File

@@ -67,12 +67,9 @@ public sealed partial class DockViewModel : IDisposable,
var commandId = band.Id;
var topLevelCommand = _topLevelCommandManager.LookupDockBand(commandId);
// TODO! temp hack: fallback to looking up a top-level command
// remove this once the API is added
if (topLevelCommand is null)
{
Logger.LogWarning($"Temporary fallback to loading top-level command '{commandId}'");
topLevelCommand = _topLevelCommandManager.LookupCommand(commandId);
Logger.LogWarning($"Failed to find band {commandId}");
}
if (topLevelCommand is not null)

View File

@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Microsoft.CmdPal.Core.Common.Helpers;
@@ -11,11 +10,10 @@ using Microsoft.CmdPal.Ext.TimeDate.Helpers;
using Microsoft.CmdPal.Ext.TimeDate.Pages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation.Collections;
namespace Microsoft.CmdPal.Ext.TimeDate;
public sealed partial class TimeDateCommandsProvider : CommandProvider, IExtendedAttributesProvider
public sealed partial class TimeDateCommandsProvider : CommandProvider
{
private readonly CommandItem _command;
private static readonly SettingsManager _settingsManager = new SettingsManager();
@@ -56,17 +54,14 @@ public sealed partial class TimeDateCommandsProvider : CommandProvider, IExtende
public override IFallbackCommandItem[] FallbackCommands() => [_fallbackTimeDateItem];
public IDictionary<string, object> GetProperties()
public override ICommandItem[] GetDockBands()
{
var wrappedBand = new WrappedDockItem(
_bandItem,
"com.microsoft.cmdpal.timedate.dockband",
Resources.Microsoft_plugin_timedate_dock_band_title);
return new PropertySet()
{
{ "DockBands", new ICommandItem[] { wrappedBand } },
};
return new ICommandItem[] { wrappedBand };
}
}
#pragma warning disable SA1402 // File may only contain a single type

View File

@@ -1,15 +1,13 @@
// Copyright (c) Microsoft Corporation
// 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 System;
using System.Collections.Generic;
using Microsoft.CmdPal.Ext.WindowWalker.Helpers;
using Microsoft.CmdPal.Ext.WindowWalker.Pages;
using Microsoft.CmdPal.Ext.WindowWalker.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Windows.Foundation.Collections;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.Accessibility;
@@ -17,7 +15,7 @@ using Windows.Win32.UI.WindowsAndMessaging;
namespace Microsoft.CmdPal.Ext.WindowWalker;
public partial class WindowWalkerCommandsProvider : CommandProvider, IExtendedAttributesProvider
public partial class WindowWalkerCommandsProvider : CommandProvider
{
private readonly CommandItem _windowWalkerPageItem;
private readonly CommandItem _bandItem;
@@ -45,12 +43,9 @@ public partial class WindowWalkerCommandsProvider : CommandProvider, IExtendedAt
public override ICommandItem[] TopLevelCommands() => [_windowWalkerPageItem];
public IDictionary<string, object> GetProperties()
public override ICommandItem[]? GetDockBands()
{
return new PropertySet()
{
{ "DockBands", new ICommandItem[] { _bandItem } },
};
return new ICommandItem[] { _bandItem };
}
}

View File

@@ -0,0 +1,30 @@
// 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 System.Collections.Generic;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace SamplePagesExtension;
/// <summary>
/// A sample dock band with multiple buttons.
/// Each button shows a toast message when clicked.
/// </summary>
internal sealed partial class SampleButtonsDockBand : WrappedDockItem
{
public SampleButtonsDockBand()
: base([], "com.microsoft.cmdpal.samples.buttons_band", "Sample Buttons Band")
{
ListItem[] buttons = [
new(new ShowToastCommand("Button 1")) { Title = "1" },
new(new ShowToastCommand("Button B")) { Icon = new IconInfo("\uF094") }, // B button
new(new ShowToastCommand("Button 3")) { Title = "Items have Icons &", Icon = new IconInfo("\uED1E"), Subtitle = "titles & subtitles" }, // Subtitles
];
Icon = new IconInfo("\uEECA"); // ButtonView2
Items = buttons;
}
}
#pragma warning restore SA1402 // File may only contain a single type

View File

@@ -0,0 +1,22 @@
// 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 Microsoft.CommandPalette.Extensions.Toolkit;
namespace SamplePagesExtension;
#pragma warning disable SA1402 // File may only contain a single type
/// <summary>
/// A sample dock band with one button.
/// Clicking on this button will open the palette to the samples list page
/// </summary>
internal sealed partial class SampleDockBand : WrappedDockItem
{
public SampleDockBand()
: base(new SamplesListPage(), "Command Palette Samples")
{
}
}
#pragma warning restore SA1402 // File may only contain a single type

View File

@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -27,4 +28,15 @@ public partial class SamplePagesCommandsProvider : CommandProvider
{
return _commands;
}
public override ICommandItem[] GetDockBands()
{
List<ICommandItem> bands = new()
{
new SampleDockBand(),
new SampleButtonsDockBand(),
};
return bands.ToArray();
}
}

View File

@@ -0,0 +1,19 @@
// 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 System.Collections.Generic;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace SamplePagesExtension;
internal sealed partial class ShowToastCommand(string message) : InvokableCommand
{
public override ICommandResult Invoke()
{
return CommandResult.ShowToast(message);
}
}
#pragma warning restore SA1402 // File may only contain a single type

View File

@@ -6,7 +6,10 @@ using Windows.Foundation;
namespace Microsoft.CommandPalette.Extensions.Toolkit;
public abstract partial class CommandProvider : ICommandProvider, ICommandProvider2
public abstract partial class CommandProvider :
ICommandProvider,
ICommandProvider2,
ICommandProvider3
{
public virtual string Id { get; protected set; } = string.Empty;
@@ -48,6 +51,11 @@ public abstract partial class CommandProvider : ICommandProvider, ICommandProvid
}
}
public virtual ICommandItem[]? GetDockBands()
{
return null;
}
/// <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.

View File

@@ -2,10 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Core.Common.Helpers;
namespace Microsoft.CommandPalette.Extensions.Toolkit;
#pragma warning disable SA1402 // File may only contain a single type
@@ -15,14 +12,19 @@ public partial class WrappedDockItem : CommandItem
public override IIconInfo? Icon => _icon;
public override ICommand? Command => _backingList;
private readonly string _itemTitle;
private readonly IIconInfo? _icon;
private readonly WrappedDockList _backingList;
public IListItem[] Items { get => _backingList.GetItems(); set => _backingList.SetItems(value); }
public WrappedDockItem(
ICommand command,
string displayTitle)
{
Command = new WrappedDockList(command);
_backingList = new WrappedDockList(command);
_itemTitle = string.IsNullOrEmpty(displayTitle) ? command.Name : displayTitle;
_icon = command.Icon;
}
@@ -32,55 +34,44 @@ public partial class WrappedDockItem : CommandItem
string id,
string displayTitle)
{
Command = new WrappedDockList(item, id);
_backingList = new WrappedDockList(item, id);
_itemTitle = string.IsNullOrEmpty(displayTitle) ? item.Title : displayTitle;
_icon = item.Icon;
}
}
public partial class PinnedDockItem : WrappedDockItem
{
public override string Title => $"{base.Title} ({Properties.Resources.PinnedItemSuffix})";
public PinnedDockItem(ICommand command)
: base(command, command.Name)
{
}
public PinnedDockItem(ICommandItem item, string id)
: base(item, id, item.Title)
public WrappedDockItem(IListItem[] items, string id, string displayTitle)
{
_backingList = new WrappedDockList(items, id, displayTitle);
_itemTitle = displayTitle;
}
}
public partial class WrappedDockList : ListPage
{
public override string Name => _command.Name;
private string _id;
public override string Id => _id;
private ICommand _command;
private IListItem[] _items;
// private ICommand _command;
private List<IListItem> _items;
public WrappedDockList(ICommand command)
{
_command = command;
_items = new IListItem[] { new ListItem(command) };
Name = _command.Name;
_id = _command.Id;
// _command = command;
_items = new() { new ListItem(command) };
Name = command.Name;
_id = command.Id;
}
public WrappedDockList(ICommandItem item, string id)
{
_command = item.Command;
var command = item.Command;
// TODO! This isn't _totally correct, because the wrapping item will not
// listen for property changes on the inner item.
_items = new IListItem[]
_items = new()
{
new ListItem(_command)
new ListItem(command)
{
Title = item.Title,
Subtitle = item.Subtitle,
@@ -88,13 +79,45 @@ public partial class WrappedDockList : ListPage
MoreCommands = item.MoreCommands,
},
};
Name = _command.Name;
_id = string.IsNullOrEmpty(id) ? _command.Id : id;
Name = command.Name;
_id = string.IsNullOrEmpty(id) ? command.Id : id;
}
public WrappedDockList(IListItem[] items, string id, string name)
{
_items = new(items);
Name = name;
_id = id;
}
public WrappedDockList(ICommand[] items, string id, string name)
{
_items = new();
foreach (var item in items)
{
_items.Add(new ListItem(item));
}
Name = name;
_id = id;
}
public override IListItem[] GetItems()
{
return _items;
return _items.ToArray();
}
internal void SetItems(IListItem[]? newItems)
{
if (newItems == null)
{
_items = [];
RaiseItemsChanged(0);
return;
}
ListHelpers.InPlaceUpdateList(_items, newItems);
RaiseItemsChanged(_items.Count);
}
}

View File

@@ -391,6 +391,11 @@ namespace Microsoft.CommandPalette.Extensions
{
Object[] GetApiExtensionStubs();
};
[contract(Microsoft.CommandPalette.Extensions.ExtensionsContract, 1)]
interface ICommandProvider3 requires ICommandProvider2
{
ICommandItem[] GetDockBands();
};
}