Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions FluentFlyoutWPF/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -490,9 +490,14 @@ private static double GetBottomCenterFlyoutBottomMargin(bool reserveNativeVolume
return SettingsManager.Current.VolumeControlEnabled && SettingsManager.Current.VolumeControlAboveMediaFlyout ? 16 : 80;
}

private (double left, double top) GetFinalPosition(Rect windowRect, Rect workArea, bool reserveNativeVolumeOsdSpace = false)
private static int NormalizeFlyoutPosition(int position)
{
int position = SettingsManager.Current.Position;
return position is >= 0 and <= 5 ? position : 0;
}

private (double left, double top) GetFinalPosition(Rect windowRect, Rect workArea, bool reserveNativeVolumeOsdSpace = false, int? positionOverride = null)
{
int position = NormalizeFlyoutPosition(positionOverride ?? SettingsManager.Current.Position);
double left = position switch
{
0 or 3 => workArea.Left + 16,
Expand All @@ -508,7 +513,7 @@ private static double GetBottomCenterFlyoutBottomMargin(bool reserveNativeVolume
return (left, top);
}

public void OpenAnimation(MicaWindow window, bool alwaysBottom = false, MonitorInfo? selectedMonitor = null, MicaWindow? aboveReference = null, bool reserveNativeVolumeOsdSpace = false)
public void OpenAnimation(MicaWindow window, bool alwaysBottom = false, MonitorInfo? selectedMonitor = null, MicaWindow? aboveReference = null, bool reserveNativeVolumeOsdSpace = false, int? positionOverride = null)
{
var eventTriggers = window.Triggers[0] as EventTrigger;
var beginStoryboard = eventTriggers.Actions[0] as BeginStoryboard;
Expand All @@ -517,6 +522,7 @@ public void OpenAnimation(MicaWindow window, bool alwaysBottom = false, MonitorI
DoubleAnimation moveAnimation = (DoubleAnimation)storyboard.Children[0];
var monitor = selectedMonitor != null ? selectedMonitor.Value : getSelectedMonitor();
var workArea = monitor.workArea;
int position = NormalizeFlyoutPosition(positionOverride ?? SettingsManager.Current.Position);

// prevent flickering
WindowHelper.SetVisibility(window, false); // window.Visibility = Visibility.Hidden works with some delay
Expand All @@ -534,11 +540,11 @@ public void OpenAnimation(MicaWindow window, bool alwaysBottom = false, MonitorI
double refWidth = aboveReference.Width * monitor.dpiX / 96.0;
double refHeight = aboveReference.Height * monitor.dpiY / 96.0;
var refRect = new Rect(0, 0, refWidth, refHeight);
var (refLeft, refTop) = GetFinalPosition(refRect, workArea, reserveNativeVolumeOsdSpace);
var (refLeft, refTop) = GetFinalPosition(refRect, workArea, reserveNativeVolumeOsdSpace, position);

window_left = refLeft + refWidth / 2 - windowRect.Width / 2;
double aboveTop = refTop - windowRect.Height - 8;
bool isTop = SettingsManager.Current.Position switch
bool isTop = position switch
{
3 or 4 or 5 => true,
_ => false
Expand All @@ -557,7 +563,7 @@ public void OpenAnimation(MicaWindow window, bool alwaysBottom = false, MonitorI
// default behavior: position the flyout based on the user's settings
else if (alwaysBottom == false)
{
_position = SettingsManager.Current.Position;
_position = position;
if (_position == 0)
{
window_left = workArea.Left + 16;
Expand Down
36 changes: 35 additions & 1 deletion FluentFlyoutWPF/Pages/NextUpPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="0,0,0,24">
<Border CornerRadius="10" ClipToBounds="True" Width="164" Height="98">
Expand All @@ -39,7 +41,22 @@
</ui:CardControl.Header>
<ui:ToggleSwitch Name="NextUpSwitch" IsChecked="{Binding NextUpEnabled, Mode=TwoWay}" />
</ui:CardControl>
<ui:CardControl x:Name="NextUpStayDurationTitleCard" Tag="Indexable" Grid.Row="3" Icon="{ui:SymbolIcon Timer24}" Margin="0,0,0,76">
<ui:CardControl x:Name="NextUpPositionTitleCard" Tag="Indexable" Grid.Row="2" Icon="{ui:SymbolIcon ArrowMove24}" Margin="0,0,0,12">
<ui:CardControl.Header>
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource NextUpPositionTitle}" FontSize="14" FontWeight="Regular" VerticalAlignment="Center" />
</StackPanel>
</ui:CardControl.Header>
<ComboBox Name="NextUpPositionComboBox" SelectedIndex="{Binding NextUpPosition, Mode=TwoWay}">
<ComboBoxItem Content="{DynamicResource PositionBottomLeft}" />
<ComboBoxItem Content="{DynamicResource PositionBottomCenter}" />
<ComboBoxItem Content="{DynamicResource PositionBottomRight}" />
<ComboBoxItem Content="{DynamicResource PositionTopLeft}" />
<ComboBoxItem Content="{DynamicResource PositionTopCenter}" />
<ComboBoxItem Content="{DynamicResource PositionTopRight}" />
</ComboBox>
</ui:CardControl>
<ui:CardControl x:Name="NextUpStayDurationTitleCard" Tag="Indexable" Grid.Row="3" Icon="{ui:SymbolIcon Timer24}" Margin="0,0,0,3">
<ui:CardControl.Header>
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource NextUpStayDurationTitle}" FontSize="14" FontWeight="Regular" VerticalAlignment="Center" />
Expand All @@ -51,6 +68,23 @@
<TextBlock Text="{DynamicResource MillisecondsUnit}" FontSize="14" FontWeight="Regular" Margin="10,0,0,0" VerticalAlignment="Center" />
</StackPanel>
</ui:CardControl>
<ui:CardControl x:Name="NextUpCenterTitleArtistTitleCard" Tag="Indexable" Grid.Row="4" Icon="{ui:SymbolIcon AlignLeft24}" Margin="0,0,0,3">
<ui:CardControl.Header>
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource NextUpCenterTitleArtistTitle}" FontSize="14" FontWeight="Regular" VerticalAlignment="Center" />
</StackPanel>
</ui:CardControl.Header>
<ui:ToggleSwitch Name="NextUpCenterTitleArtistSwitch" IsChecked="{Binding NextUpCenterTitleArtist, Mode=TwoWay}" />
</ui:CardControl>
<ui:CardControl x:Name="NextUpShowUpNextTextTitleCard" Tag="Indexable" Grid.Row="5" Icon="{ui:SymbolIcon Subtitles24}" Margin="0,0,0,76">
<ui:CardControl.Header>
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource NextUpShowUpNextTextTitle}" FontSize="14" FontWeight="Regular" VerticalAlignment="Center" />
<TextBlock Text="{DynamicResource NextUpShowUpNextTextDescription}" FontSize="12" Opacity="0.5" />
</StackPanel>
</ui:CardControl.Header>
<ui:ToggleSwitch Name="NextUpShowUpNextTextSwitch" IsChecked="{Binding NextUpShowUpNextText, Mode=TwoWay}" />
</ui:CardControl>
</Grid>
</StackPanel>
</Page>
4 changes: 4 additions & 0 deletions FluentFlyoutWPF/Resources/Localization/Dictionary-en-US.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ Note: As an open-source project, these features are also available for free via
<System:String x:Key="EnableNextUpDescription">Shows what's next when a song/video ends</System:String>
<System:String x:Key="NextUpStayDurationTitle">Next Up Stay Duration</System:String>
<System:String x:Key="NextUpStayDurationDescription">(default: 2000 ms)</System:String>
<System:String x:Key="NextUpPositionTitle">Flyout Position</System:String>
<System:String x:Key="NextUpCenterTitleArtistTitle">Center Title and Artist</System:String>
<System:String x:Key="NextUpShowUpNextTextTitle">Show Label</System:String>
<System:String x:Key="NextUpShowUpNextTextDescription">Show the Up next label before the song info</System:String>
<System:String x:Key="LockKeysCustomizationTitle">Lock Keys Flyout</System:String>
<System:String x:Key="LockKeysDescription" xml:space="preserve">Check your lock key status at a glance. Appears after pressing Caps Lock, Num Lock or Scroll Lock. Convenient for laptops/keyboards without lock key indicators.</System:String>
<System:String x:Key="EnableLockKeysTitle">Enable Lock Keys Flyout</System:String>
Expand Down
4 changes: 4 additions & 0 deletions FluentFlyoutWPF/Resources/Localization/Dictionary-zh-CN.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
<system:String x:Key="EnableNextUpDescription">显示当前歌曲 / 视频结束后的下一项内容</system:String>
<system:String x:Key="NextUpStayDurationTitle">“接下来” 浮窗停留时间</system:String>
<system:String x:Key="NextUpStayDurationDescription">(默认:2000 毫秒)</system:String>
<system:String x:Key="NextUpPositionTitle">浮窗位置</system:String>
<system:String x:Key="NextUpCenterTitleArtistTitle">居中显示标题和艺术家</system:String>
<system:String x:Key="NextUpShowUpNextTextTitle">显示标签</system:String>
<system:String x:Key="NextUpShowUpNextTextDescription">在歌曲信息前显示 “接下来” 标签</system:String>
<system:String x:Key="LockKeysCustomizationTitle">键盘锁定键浮窗</system:String>
<system:String x:Key="LockKeysDescription" xml:space="preserve">快速查看键盘锁定键状态。按下大写锁定键、数字锁定键或滚动锁定键后显示。对于没有锁定键指示灯的笔记本电脑 / 键盘来说很实用。</system:String>
<system:String x:Key="EnableLockKeysTitle">启用键盘锁定键浮窗</system:String>
Expand Down
35 changes: 35 additions & 0 deletions FluentFlyoutWPF/ViewModels/UserSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,24 @@ public string DurationText
[NotifyPropertyChangedFor(nameof(NextUpDurationText))]
public partial int NextUpDuration { get; set; }

/// <summary>
/// 'Next Up' flyout position on screen
/// </summary>
[ObservableProperty]
public partial int NextUpPosition { get; set; }

/// <summary>
/// Center the title and artist text in the 'Next Up' flyout
/// </summary>
[ObservableProperty]
public partial bool NextUpCenterTitleArtist { get; set; }

/// <summary>
/// Show the 'Up next' label in the 'Next Up' flyout
/// </summary>
[ObservableProperty]
public partial bool NextUpShowUpNextText { get; set; }

[XmlIgnore]
public string NextUpDurationText
{
Expand Down Expand Up @@ -717,6 +735,9 @@ public UserSettings()
Duration = 3000;
NextUpEnabled = false;
NextUpDuration = 2000;
NextUpPosition = -1;
NextUpCenterTitleArtist = false;
NextUpShowUpNextText = true;
NIconLeftClick = 0;
CenterTitleArtist = false;
FlyoutAnimationEasingStyle = 2;
Expand Down Expand Up @@ -847,7 +868,21 @@ private async void OnPropertyChangedSaveSettings(object? sender, System.Componen
/// </summary>
internal void CompleteInitialization()
{
bool settingsChanged = NormalizeDeserializedSettings();
_initializing = false;

if (settingsChanged)
{
SettingsManager.SaveSettings();
}
}

private bool NormalizeDeserializedSettings()
{
if (NextUpPosition is >= 0 and <= 5) return false;

NextUpPosition = Position is >= 0 and <= 5 ? Position : 0;
return true;
}

partial void OnAppLanguageChanged(string oldValue, string newValue)
Expand Down
6 changes: 3 additions & 3 deletions FluentFlyoutWPF/Windows/NextUpWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
</Window.Triggers>

<Grid Margin="12,0,12,0" ColumnDefinitions="Auto, Auto, *">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<StackPanel x:Name="UpNextStackPanel" Orientation="Horizontal" VerticalAlignment="Center">
<ui:SymbolIcon Symbol="MusicNote120" Filled="True" Width="14" Height="14" FontSize="14" VerticalAlignment="Center" Margin="0,0,2,0"/>
<TextBlock x:Name="UpNextTextBlock" Text="{DynamicResource NextUpWindow_UpNextText}" FontSize="12" VerticalAlignment="Center" FontWeight="Medium"/>
</StackPanel>
Expand All @@ -50,8 +50,8 @@
</Border.Background>
</Border>
<StackPanel Grid.Column="2" Name="SongInfoStackPanel" Margin="6,0,0,0" Orientation="Vertical" VerticalAlignment="Center">
<TextBlock Name="SongTitle" Text="Song Title" FontSize="14" FontWeight="Medium" TextTrimming="CharacterEllipsis"/>
<TextBlock Name="SongArtist" Text="Artist Name" FontSize="14" FontWeight="Medium" Opacity="0.5" TextTrimming="CharacterEllipsis"/>
<TextBlock Name="SongTitle" Text="Song Title" FontSize="14" FontWeight="Medium" TextTrimming="CharacterEllipsis" HorizontalAlignment="Stretch"/>
<TextBlock Name="SongArtist" Text="Artist Name" FontSize="14" FontWeight="Medium" Opacity="0.5" TextTrimming="CharacterEllipsis" HorizontalAlignment="Stretch"/>
</StackPanel>
</Grid>
</controls:MicaWindow>
54 changes: 46 additions & 8 deletions FluentFlyoutWPF/Windows/NextUpWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ namespace FluentFlyoutWPF.Windows;
/// </summary>
public partial class NextUpWindow : MicaWindow
{
private const double MaxWindowWidth = 400;
private const double MinWindowWidth = 160;
private const int TextPadding = 8;

MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
public NextUpWindow(string title, string artist, BitmapImage thumbnail)
{
Expand All @@ -37,19 +41,14 @@ public NextUpWindow(string title, string artist, BitmapImage thumbnail)
WindowBlurHelper.DisableBlur(this);
}

int additionalMargin = 8; // additional margin to avoid text clipping
var upNextWidth = StringWidth.GetStringWidth(UpNextTextBlock.Text) + additionalMargin;
var titleWidth = StringWidth.GetStringWidth(title) + additionalMargin;
var artistWidth = StringWidth.GetStringWidth(artist) + additionalMargin;

Width = titleWidth > artistWidth ? titleWidth + 76 + upNextWidth : artistWidth + 76 + upNextWidth;
if (Width > 400) Width = 400; // max width to prevent window from being too wide
ApplyCustomization();
Width = GetWindowWidth(title, artist);
SongTitle.Text = title;
SongArtist.Text = artist;
UpdateThumbnail(thumbnail);
Show();

mainWindow.OpenAnimation(this);
mainWindow.OpenAnimation(this, positionOverride: SettingsManager.Current.NextUpPosition);

async void wait()
{
Expand All @@ -62,6 +61,45 @@ async void wait()
wait();
}

private void ApplyCustomization()
{
var settings = SettingsManager.Current;

UpNextStackPanel.Visibility = settings.NextUpShowUpNextText ? Visibility.Visible : Visibility.Collapsed;
SongImageBorder.Margin = settings.NextUpShowUpNextText
? new Thickness(12, 1, 0, 0)
: new Thickness(0, 1, 0, 0);

var textAlignment = settings.NextUpCenterTitleArtist ? TextAlignment.Center : TextAlignment.Left;
SongTitle.TextAlignment = textAlignment;
SongArtist.TextAlignment = textAlignment;
}

private double GetWindowWidth(string title, string artist)
{
double leadingWidth = 0;

if (SettingsManager.Current.NextUpShowUpNextText)
{
const double iconWidth = 14;
const double iconRightMargin = 2;
const double thumbnailLeftMargin = 12;
leadingWidth = iconWidth
+ iconRightMargin
+ StringWidth.GetStringWidth(UpNextTextBlock.Text, fontSize: 12)
+ thumbnailLeftMargin;
}

const double windowHorizontalMargin = 24;
const double thumbnailWidth = 38;
const double songInfoLeftMargin = 6;

double songTextWidth = Math.Max(StringWidth.GetStringWidth(title), StringWidth.GetStringWidth(artist)) + TextPadding;
double width = windowHorizontalMargin + leadingWidth + thumbnailWidth + songInfoLeftMargin + songTextWidth;

return Math.Min(Math.Max(width, MinWindowWidth), MaxWindowWidth);
}

public void UpdateThumbnail(BitmapImage thumbnail)
{
SongImage.ImageSource = thumbnail;
Expand Down
Loading