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