mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 01:36:31 +02:00
CmdPal: Add a dock (#45824)
Add support for a "dock" window in CmdPal. The dock is a toolbar powered by the `APPBAR` APIs. This gives you a persistent region to display commands for quick shortcuts or glanceable widgets. The dock can be pinned to any side of the screen. The dock can be independently styled with any of the theming controls cmdpal already has The dock has three "regions" to pin to - the "start", the "center", and the "end". Elements on the dock are grouped as "bands", which contains a set of "items". Each "band" is one atomic unit. For example, the Media Player extension produces 4 items, but one _band_. The dock has only one size (for now) The dock will only appear on your primary display (for now) This PR includes support for pinning arbitrary top-level commands to the dock - however, we're planning on replacing that with a more universal ability to pin any command to the dock or top level. (see #45191). This is at least usable for now. This is definitely still _even more preview_ than usual PowerToys features, but it's more than usable. I'd love to get it out there and start collecting feedback on where to improve next. I'll probably add a follow-up issue for tracking the remaining bugs & nits. closes #45201 --------- Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
@@ -22,12 +22,12 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CsWinRTInputs Include="..\..\..\..\..\$(Platform)\$(Configuration)\CalculatorEngineCommon.winmd" />
|
||||
<Content Include="..\..\..\..\..\$(Platform)\$(Configuration)\CalculatorEngineCommon.winmd" Link="CalculatorEngineCommon.winmd">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\..\..\..\..\$(Platform)\$(Configuration)\CalculatorEngineCommon.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="..\..\..\..\..\$(Platform)\$(Configuration)\CalculatorEngineCommon.winmd" Link="CalculatorEngineCommon.winmd">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="..\..\..\..\..\$(Platform)\$(Configuration)\CalculatorEngineCommon.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 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.
|
||||
|
||||
@@ -16,7 +16,8 @@ public partial class ClipboardHistoryCommandsProvider : CommandProvider
|
||||
|
||||
public ClipboardHistoryCommandsProvider()
|
||||
{
|
||||
_clipboardHistoryListItem = new ListItem(new ClipboardHistoryListPage(_settingsManager))
|
||||
var page = new ClipboardHistoryListPage(_settingsManager);
|
||||
_clipboardHistoryListItem = new ListItem(page)
|
||||
{
|
||||
Title = Properties.Resources.list_item_title,
|
||||
Icon = Icons.ClipboardListIcon,
|
||||
@@ -24,7 +25,6 @@ public partial class ClipboardHistoryCommandsProvider : CommandProvider
|
||||
new CommandContextItem(_settingsManager.Settings.SettingsPage),
|
||||
],
|
||||
};
|
||||
|
||||
DisplayName = Properties.Resources.provider_display_name;
|
||||
Icon = Icons.ClipboardListIcon;
|
||||
Id = "Windows.ClipboardHistory";
|
||||
|
||||
@@ -32,9 +32,8 @@ public partial class PerformanceMonitorCommandsProvider : CommandProvider
|
||||
return _commands;
|
||||
}
|
||||
|
||||
// Soon...
|
||||
// public override ICommandItem[]? GetDockBands()
|
||||
// {
|
||||
// return new ICommandItem[] { _band };
|
||||
// }
|
||||
public override ICommandItem[]? GetDockBands()
|
||||
{
|
||||
return new ICommandItem[] { _band };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\Microsoft.CmdPal.Common\Microsoft.CmdPal.Common.csproj" />
|
||||
<!-- CmdPal Toolkit reference now included via Common.ExtDependencies.props -->
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Resources {
|
||||
@@ -159,6 +159,15 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Clock.
|
||||
/// </summary>
|
||||
public static string Microsoft_plugin_timedate_dock_band_title {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_dock_band_title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Era.
|
||||
/// </summary>
|
||||
@@ -932,5 +941,23 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_Year", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy date.
|
||||
/// </summary>
|
||||
public static string timedate_copy_date_command_name {
|
||||
get {
|
||||
return ResourceManager.GetString("timedate_copy_date_command_name", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy time.
|
||||
/// </summary>
|
||||
public static string timedate_copy_time_command_name {
|
||||
get {
|
||||
return ResourceManager.GetString("timedate_copy_time_command_name", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,4 +432,16 @@
|
||||
<data name="Microsoft_plugin_timedate_SettingEnableFallbackItems_Description" xml:space="preserve">
|
||||
<value>Show time and date results when typing keywords like "week", "year", "now", "time", or "date"</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_dock_band_title" xml:space="preserve">
|
||||
<value>Clock</value>
|
||||
<comment>Title for the time and date dock band</comment>
|
||||
</data>
|
||||
<data name="timedate_copy_time_command_name" xml:space="preserve">
|
||||
<value>Copy time</value>
|
||||
<comment>Name of a command to copy the current time to the clipboard</comment>
|
||||
</data>
|
||||
<data name="timedate_copy_date_command_name" xml:space="preserve">
|
||||
<value>Copy date</value>
|
||||
<comment>Name of a command to copy the current date to the clipboard</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -20,6 +20,8 @@ public sealed partial class TimeDateCommandsProvider : CommandProvider
|
||||
private static readonly TimeDateExtensionPage _timeDateExtensionPage = new(_settingsManager);
|
||||
private readonly FallbackTimeDateItem _fallbackTimeDateItem = new(_settingsManager);
|
||||
|
||||
private readonly ListItem _bandItem;
|
||||
|
||||
public TimeDateCommandsProvider()
|
||||
{
|
||||
DisplayName = Resources.Microsoft_plugin_timedate_plugin_name;
|
||||
@@ -33,6 +35,8 @@ public sealed partial class TimeDateCommandsProvider : CommandProvider
|
||||
|
||||
Icon = _timeDateExtensionPage.Icon;
|
||||
Settings = _settingsManager.Settings;
|
||||
|
||||
_bandItem = new NowDockBand();
|
||||
}
|
||||
|
||||
private string GetTranslatedPluginDescription()
|
||||
@@ -47,4 +51,85 @@ public sealed partial class TimeDateCommandsProvider : CommandProvider
|
||||
public override ICommandItem[] TopLevelCommands() => [_command];
|
||||
|
||||
public override IFallbackCommandItem[] FallbackCommands() => [_fallbackTimeDateItem];
|
||||
|
||||
public override ICommandItem[] GetDockBands()
|
||||
{
|
||||
var wrappedBand = new WrappedDockItem(
|
||||
[_bandItem],
|
||||
"com.microsoft.cmdpal.timedate.dockBand",
|
||||
Resources.Microsoft_plugin_timedate_dock_band_title);
|
||||
|
||||
return new ICommandItem[] { wrappedBand };
|
||||
}
|
||||
}
|
||||
#pragma warning disable SA1402 // File may only contain a single type
|
||||
|
||||
internal sealed partial class NowDockBand : ListItem
|
||||
{
|
||||
private static readonly TimeSpan UpdateInterval = TimeSpan.FromSeconds(60);
|
||||
private CopyTextCommand _copyTimeCommand;
|
||||
private CopyTextCommand _copyDateCommand;
|
||||
|
||||
public NowDockBand()
|
||||
{
|
||||
Command = new NoOpCommand() { Id = "com.microsoft.cmdpal.timedate.dockBand" };
|
||||
_copyTimeCommand = new CopyTextCommand(string.Empty) { Name = Resources.timedate_copy_time_command_name };
|
||||
_copyDateCommand = new CopyTextCommand(string.Empty) { Name = Resources.timedate_copy_date_command_name };
|
||||
MoreCommands = [
|
||||
new CommandContextItem(_copyTimeCommand),
|
||||
new CommandContextItem(_copyDateCommand)
|
||||
];
|
||||
UpdateText();
|
||||
|
||||
// Create a timer to update the time every minute
|
||||
System.Timers.Timer timer = new(UpdateInterval.TotalMilliseconds);
|
||||
|
||||
// but we want it to tick on the minute, so calculate the initial delay
|
||||
var now = DateTime.Now;
|
||||
timer.Interval = UpdateInterval.TotalMilliseconds - ((now.Second * 1000) + now.Millisecond);
|
||||
|
||||
// then after the first tick, set it to 60 seconds
|
||||
timer.Elapsed += Timer_ElapsedFirst;
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
private void Timer_ElapsedFirst(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
// After the first tick, set the interval to 60 seconds
|
||||
if (sender is System.Timers.Timer timer)
|
||||
{
|
||||
timer.Interval = UpdateInterval.TotalMilliseconds;
|
||||
timer.Elapsed -= Timer_ElapsedFirst;
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
|
||||
// Still call the callback, so that we update the clock
|
||||
Timer_Elapsed(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
UpdateText();
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
{
|
||||
var timeExtended = false; // timeLongFormat ?? settings.TimeWithSecond;
|
||||
var dateExtended = false; // dateLongFormat ?? settings.DateWithWeekday;
|
||||
var dateTimeNow = DateTime.Now;
|
||||
|
||||
var timeString = dateTimeNow.ToString(
|
||||
TimeAndDateHelper.GetStringFormat(FormatStringType.Time, timeExtended, dateExtended),
|
||||
CultureInfo.CurrentCulture);
|
||||
var dateString = dateTimeNow.ToString(
|
||||
TimeAndDateHelper.GetStringFormat(FormatStringType.Date, timeExtended, dateExtended),
|
||||
CultureInfo.CurrentCulture);
|
||||
|
||||
Title = timeString;
|
||||
Subtitle = dateString;
|
||||
|
||||
_copyDateCommand.Text = dateString;
|
||||
_copyTimeCommand.Text = timeString;
|
||||
}
|
||||
}
|
||||
#pragma warning restore SA1402 // File may only contain a single type
|
||||
|
||||
@@ -42,6 +42,7 @@ internal sealed partial class WinGetExtensionPage : DynamicListPage, IDisposable
|
||||
public WinGetExtensionPage(string tag = "")
|
||||
{
|
||||
Icon = tag == ExtensionsTag ? Icons.ExtensionsIcon : Icons.WinGetIcon;
|
||||
Id = tag == ExtensionsTag ? "com.microsoft.cmdpal.winget-extensions" : "com.microsoft.cmdpal.winget";
|
||||
Name = Properties.Resources.winget_page_name;
|
||||
_tag = tag;
|
||||
ShowDetails = true;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user