Files
PowerToys/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/IconInfoViewModel.cs
Jiří Polášek c6f1a09fa2 CmdPal: Handle an empty icon in dock items (#45968)
## Summary of the Pull Request

This PR allows dock to handle items without an icon better:

- Hides the icon element when a dock item is not visible and center text
labels in vertical dock modes.
- Adds an icon to clock dock wrapper, so it appears in settings.
- Stretches buttons with icon and labels in the vertical docks to the
full width.
- Fixes `IconInfoViewModel.IconForTheme` method implementation.

## Pictures? Pictures!

Horizontal Dock:

<img width="393" height="84" alt="image"
src="https://github.com/user-attachments/assets/d12aa406-da9d-4bd2-b464-595deab41d2e"
/>

<img width="390" height="105" alt="image"
src="https://github.com/user-attachments/assets/c28d65c0-1023-47d0-9ff5-85c74a18c342"
/>


Vertical Dock:

<img width="153" height="258" alt="image"
src="https://github.com/user-attachments/assets/e1be59d9-fa1f-4a24-b0c1-e8cff4211906"
/>

Settings:

<img width="1266" height="713" alt="image"
src="https://github.com/user-attachments/assets/722d47da-c668-4df2-9f1d-bf7808333be4"
/>



<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #45955
2026-03-09 06:17:56 -05:00

58 lines
1.7 KiB
C#

// 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 CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class IconInfoViewModel : ObservableObject, IIconInfo
{
private readonly ExtensionObject<IIconInfo> _model = new(null);
// These are properties that are "observable" from the extension object
// itself, in the sense that they get raised by PropChanged events from the
// extension. However, we don't want to actually make them
// [ObservableProperty]s, because PropChanged comes in off the UI thread,
// and ObservableProperty is not smart enough to raise the PropertyChanged
// on the UI thread.
public IconDataViewModel Light { get; private set; }
public IconDataViewModel Dark { get; private set; }
public IconDataViewModel IconForTheme(bool light) => light ? Light : Dark;
public bool HasIcon(bool light) => IconForTheme(light).HasIcon;
public bool IsSet => _model.Unsafe is not null;
IIconData? IIconInfo.Dark => Dark;
IIconData? IIconInfo.Light => Light;
public IconInfoViewModel(IIconInfo? icon)
{
_model = new(icon);
Light = new(null);
Dark = new(null);
}
// Unsafe, needs to be called on BG thread
public void InitializeProperties()
{
var model = _model.Unsafe;
if (model is null)
{
return;
}
Light = new(model.Light);
Light.InitializeProperties();
Dark = new(model.Dark);
Dark.InitializeProperties();
}
}