mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
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
This commit is contained in:
@@ -22,7 +22,7 @@ public partial class IconInfoViewModel : ObservableObject, IIconInfo
|
||||
|
||||
public IconDataViewModel Dark { get; private set; }
|
||||
|
||||
public IconDataViewModel IconForTheme(bool light) => Light = light ? Light : Dark;
|
||||
public IconDataViewModel IconForTheme(bool light) => light ? Light : Dark;
|
||||
|
||||
public bool HasIcon(bool light) => IconForTheme(light).HasIcon;
|
||||
|
||||
|
||||
@@ -92,13 +92,14 @@
|
||||
<StackPanel
|
||||
x:Name="TextPanel"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{TemplateBinding TextVisibility}">
|
||||
<TextBlock
|
||||
x:Name="TitleText"
|
||||
MinWidth="24"
|
||||
MaxWidth="100"
|
||||
HorizontalAlignment="Left"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="Segoe UI"
|
||||
FontSize="12"
|
||||
@@ -110,13 +111,13 @@
|
||||
x:Name="SubtitleText"
|
||||
MaxWidth="100"
|
||||
Margin="0,-2,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="Segoe UI"
|
||||
FontSize="10"
|
||||
Foreground="{ThemeResource TextFillColorTertiary}"
|
||||
Text="{TemplateBinding Subtitle}"
|
||||
TextAlignment="Center"
|
||||
TextAlignment="Left"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap" />
|
||||
</StackPanel>
|
||||
@@ -173,6 +174,21 @@
|
||||
<VisualState x:Name="IconHidden">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContentGrid.ColumnSpacing" Value="0" />
|
||||
<Setter Target="IconPresenter.Visibility" Value="Collapsed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="TextAlignmentStates">
|
||||
<VisualState x:Name="TextLeftAligned">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="TitleText.TextAlignment" Value="Left" />
|
||||
<Setter Target="SubtitleText.TextAlignment" Value="Left" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="TextCentered">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="TitleText.TextAlignment" Value="Center" />
|
||||
<Setter Target="SubtitleText.TextAlignment" Value="Center" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
@@ -138,50 +138,46 @@ public sealed partial class DockItemControl : Control
|
||||
|
||||
private void UpdateIconVisibility()
|
||||
{
|
||||
if (Icon is IconBox icon)
|
||||
var shouldShowIcon = ShouldShowIcon();
|
||||
if (_iconPresenter is not null)
|
||||
{
|
||||
var dt = icon.DataContext;
|
||||
var src = icon.Source;
|
||||
|
||||
if (_iconPresenter is not null)
|
||||
{
|
||||
// n.b. this might be wrong - I think we always have an Icon (an IconBox),
|
||||
// we need to check if the box has an icon
|
||||
_iconPresenter.Visibility = Icon is null ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
|
||||
UpdateIconVisibilityState();
|
||||
_iconPresenter.Visibility = shouldShowIcon ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
UpdateIconVisibilityState();
|
||||
}
|
||||
|
||||
private void UpdateIconVisibilityState()
|
||||
{
|
||||
var hasIcon = Icon is not null;
|
||||
VisualStateManager.GoToState(this, hasIcon ? "IconVisible" : "IconHidden", true);
|
||||
VisualStateManager.GoToState(this, ShouldShowIcon() ? "IconVisible" : "IconHidden", true);
|
||||
}
|
||||
|
||||
private void UpdateAlignment()
|
||||
{
|
||||
// If this item has both an icon and a label, left align so that the
|
||||
// icons don't wobble if the text changes.
|
||||
//
|
||||
// Otherwise, center align.
|
||||
var requestedTheme = ActualTheme;
|
||||
var isLight = requestedTheme == ElementTheme.Light;
|
||||
var showText = HasText;
|
||||
if (Icon is IconBox icoBox &&
|
||||
icoBox.DataContext is DockItemViewModel item &&
|
||||
item.Icon is IconInfoViewModel icon)
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
UpdateTextAlignmentState();
|
||||
}
|
||||
|
||||
private bool ShouldShowIcon()
|
||||
{
|
||||
if (Icon is IconBox icoBox)
|
||||
{
|
||||
var showIcon = icon is not null && icon.HasIcon(isLight);
|
||||
if (showText && showIcon)
|
||||
if (icoBox.SourceKey is IconInfoViewModel icon)
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Left;
|
||||
return;
|
||||
return icon.HasIcon(ActualTheme == ElementTheme.Light);
|
||||
}
|
||||
|
||||
return icoBox.Source is not null;
|
||||
}
|
||||
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
return Icon is not null;
|
||||
}
|
||||
|
||||
private void UpdateTextAlignmentState()
|
||||
{
|
||||
var verticalDock = _parentDock?.DockSide is DockSide.Left or DockSide.Right;
|
||||
var shouldCenterText = verticalDock && !ShouldShowIcon();
|
||||
VisualStateManager.GoToState(this, shouldCenterText ? "TextCentered" : "TextLeftAligned", true);
|
||||
}
|
||||
|
||||
private void UpdateAllVisibility()
|
||||
@@ -195,12 +191,14 @@ public sealed partial class DockItemControl : Control
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
IsEnabledChanged -= OnIsEnabledChanged;
|
||||
ActualThemeChanged -= DockItemControl_ActualThemeChanged;
|
||||
|
||||
PointerEntered -= Control_PointerEntered;
|
||||
PointerExited -= Control_PointerExited;
|
||||
Loaded -= DockItemControl_Loaded;
|
||||
Unloaded -= DockItemControl_Unloaded;
|
||||
|
||||
ActualThemeChanged += DockItemControl_ActualThemeChanged;
|
||||
PointerEntered += Control_PointerEntered;
|
||||
PointerExited += Control_PointerExited;
|
||||
Loaded += DockItemControl_Loaded;
|
||||
@@ -229,12 +227,19 @@ public sealed partial class DockItemControl : Control
|
||||
{
|
||||
_parentDock = dock;
|
||||
UpdateInnerMarginForDockSide(dock.DockSide);
|
||||
UpdateAllVisibility();
|
||||
_dockSideCallbackToken = dock.RegisterPropertyChangedCallback(
|
||||
DockControl.DockSideProperty,
|
||||
OnParentDockSideChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private void DockItemControl_ActualThemeChanged(FrameworkElement sender, object args)
|
||||
{
|
||||
UpdateIconVisibility();
|
||||
UpdateAlignment();
|
||||
}
|
||||
|
||||
private void DockItemControl_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_parentDock is not null && _dockSideCallbackToken >= 0)
|
||||
@@ -252,6 +257,7 @@ public sealed partial class DockItemControl : Control
|
||||
if (sender is DockControl dock)
|
||||
{
|
||||
UpdateInnerMarginForDockSide(dock.DockSide);
|
||||
UpdateAlignment();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,10 @@ public sealed partial class TimeDateCommandsProvider : CommandProvider
|
||||
var wrappedBand = new WrappedDockItem(
|
||||
[_bandItem],
|
||||
"com.microsoft.cmdpal.timedate.dockBand",
|
||||
Resources.Microsoft_plugin_timedate_dock_band_title);
|
||||
Resources.Microsoft_plugin_timedate_dock_band_title)
|
||||
{
|
||||
Icon = Icons.TimeDateExtIcon,
|
||||
};
|
||||
|
||||
return new ICommandItem[] { wrappedBand };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user