first round of design adjustments

This commit is contained in:
Royce551 2021-10-19 19:45:51 -05:00
parent b882cce628
commit d5284a8bc6
14 changed files with 950 additions and 761 deletions

View file

@ -136,6 +136,8 @@
<Compile Include="Handlers\Notifications\Notification.cs" />
<Compile Include="Handlers\PlaytimeTrackingHandler.cs" />
<Compile Include="Handlers\UpdateHandler.cs" />
<Compile Include="MainWindow_Controls.xaml.cs" />
<Compile Include="MainWindow_Logic.xaml.cs" />
<Compile Include="Pages\FullscreenPage.xaml.cs">
<DependentUpon>FullscreenPage.xaml</DependentUpon>
</Compile>

View file

@ -20,8 +20,8 @@ namespace FRESHMusicPlayer.Forms.Playlists
private readonly GUILibrary library;
private readonly PlaylistManagement window;
private readonly Menu selectedMenu;
public PlaylistEntry(string playlist, string path, GUILibrary library, PlaylistManagement window, Menu selectedMenu)
private readonly Tab selectedMenu;
public PlaylistEntry(string playlist, string path, GUILibrary library, PlaylistManagement window, Tab selectedMenu)
{
this.library = library;
this.window = window;
@ -30,7 +30,7 @@ namespace FRESHMusicPlayer.Forms.Playlists
if (path is null) trackExists = false;
TitleLabel.Text = playlist;
if (selectedMenu == Menu.Artists) AddThingButton.Content = $"+ {Properties.Resources.TAGEDITOR_ARTIST}";
if (selectedMenu == Tab.Artists) AddThingButton.Content = $"+ {Properties.Resources.TAGEDITOR_ARTIST}";
else AddThingButton.Content = $"+ {Properties.Resources.TRACKINFO_ALBUM}";
this.playlist = playlist;
@ -57,7 +57,7 @@ namespace FRESHMusicPlayer.Forms.Playlists
if (trackExists)
{
AddButton.Visibility = RemoveButton.Visibility = Visibility.Visible;
if (selectedMenu == Menu.Artists || selectedMenu == Menu.Albums)
if (selectedMenu == Tab.Artists || selectedMenu == Tab.Albums)
AddThingButton.Visibility = Visibility.Visible;
}
}
@ -118,7 +118,7 @@ namespace FRESHMusicPlayer.Forms.Playlists
private void AddThingButton_Click(object sender, RoutedEventArgs e)
{
List<DatabaseTrack> things;
if (selectedMenu == Menu.Artists)
if (selectedMenu == Tab.Artists)
things = library.ReadTracksForArtist(library.GetFallbackTrack(path).Artist);
else
things = library.ReadTracksForAlbum(library.GetFallbackTrack(path).Album);

View file

@ -18,8 +18,8 @@ namespace FRESHMusicPlayer.Forms.Playlists
private readonly GUILibrary library;
private readonly NotificationHandler notificationHandler;
private readonly Menu selectedMenu;
public PlaylistManagement(GUILibrary library, NotificationHandler notificationHandler, Menu selectedMenu, string track = null)
private readonly Tab selectedMenu;
public PlaylistManagement(GUILibrary library, NotificationHandler notificationHandler, Tab selectedMenu, string track = null)
{
this.library = library;
this.notificationHandler = notificationHandler;

View file

@ -66,7 +66,7 @@ namespace FRESHMusicPlayer.Handlers.Configuration
/// <summary>
/// The last menu FMP was on before closing
/// </summary>
public Menu CurrentMenu { get; set; } = Menu.Import;
public Tab CurrentMenu { get; set; } = Tab.Import;
public List<string> AutoImportPaths { get; set; } = new List<string>();
}

View file

@ -78,7 +78,7 @@
</Image.ToolTip>
</Image>
<TextBlock x:Name="TitleLabel" HorizontalAlignment="Stretch" Margin="5,5,40,0" TextWrapping="NoWrap" Text="{x:Static resx:Resources.MAINWINDOW_NOTHINGPLAYING}" VerticalAlignment="Top" FontWeight="Bold" FontSize="22" Grid.Column="1" Height="30" Foreground="{StaticResource PrimaryTextColor}" TextTrimming="CharacterEllipsis" MouseLeftButtonDown="TrackTitle_MouseLeftButtonDown" MouseRightButtonDown="TrackTitle_MouseRightButtonDown" Cursor="Hand" Grid.ColumnSpan="2" Panel.ZIndex="0"/>
<Slider x:Name="ProgressBar" Grid.Column="1" HorizontalAlignment="Stretch" Margin="37,54,45,0" VerticalAlignment="Top" Height="21" Style="{StaticResource Progress_Slider}" Value="9.8" Thumb.DragStarted="ProgressBar_DragStarted" Thumb.DragCompleted="ProgressBar_DragCompleted" ValueChanged="ProgressBar_ValueChanged" IsMoveToPointEnabled="True" MouseLeftButtonUp="ProgressBar_MouseLeftButtonUp"/>
<Slider x:Name="ProgressBar" Grid.Column="1" HorizontalAlignment="Stretch" Margin="37,54,45,0" VerticalAlignment="Top" Height="21" Style="{StaticResource Progress_Slider}" Value="9.8" Thumb.DragStarted="ProgressBar_DragStarted" Thumb.DragCompleted="ProgressBar_DragCompleted" ValueChanged="ProgressBar_ValueChanged" IsMoveToPointEnabled="True" MouseLeftButtonUp="ProgressBar_MouseLeftButtonUp" Cursor="Hand"/>
<TextBlock x:Name="ProgressIndicator1" Grid.Column="1" Margin="5,56,0,0" TextWrapping="NoWrap" Text="10:00" Foreground="{StaticResource SecondaryTextColor}" Height="15" VerticalAlignment="Top" HorizontalAlignment="Left" Width="28"/>
<TextBlock x:Name="ProgressIndicator2" Grid.Column="1" Margin="0,0,0,13" TextWrapping="NoWrap" Text="10:00" Foreground="{StaticResource SecondaryTextColor}" Height="15" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="40" MouseLeftButtonDown="ProgressIndicator2_MouseLeftButtonDown"/>
<TextBlock x:Name="ArtistLabel" HorizontalAlignment="Stretch" Margin="5,35,10,0" TextWrapping="NoWrap" Text="{x:Static resx:Resources.MAINWINDOW_NOTHINGPLAYING}" VerticalAlignment="Top" Grid.Column="1" Height="20" Foreground="{StaticResource SecondaryTextColor}" TextTrimming="CharacterEllipsis"/>

View file

@ -27,39 +27,21 @@ using WinForms = System.Windows.Forms;
namespace FRESHMusicPlayer
{
public enum Menu
{
Tracks,
Artists,
Albums,
Playlists,
Import,
Fullscreen,
Other
}
public enum AuxiliaryPane
{
None,
Settings,
QueueManagement,
Search,
Notifications,
TrackInfo,
Lyrics
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
// Initialization stuff
// _Logic - Main window, player, systemwide logic
// _Controls - Event handlers and other doo dads
public partial class MainWindow : Window
{
public Menu SelectedMenu = Menu.Tracks;
public AuxiliaryPane SelectedAuxiliaryPane = AuxiliaryPane.None;
public Player Player;
public NotificationHandler NotificationHandler = new NotificationHandler();
public GUILibrary Library;
public IMetadataProvider CurrentTrack;
public const string WindowName = "FRESHMusicPlayer [Blueprint 11 b.10.02.2021; Not stable!]";
public const string WindowName = "FRESHMusicPlayer [Blueprint 11 b.10.10.2021; Not stable!]";
public PlaytimeTrackingHandler TrackingHandler;
public bool PauseAfterCurrentTrack = false;
@ -140,660 +122,6 @@ namespace FRESHMusicPlayer
}
}
#region Controls
public void PlayPauseMethod()
{
if (!Player.FileLoaded) return;
if (Player.Paused)
{
Player.Resume();
SetIntegrations(PlaybackStatus.Playing);
ProgressTimer.Start();
}
else
{
Player.Pause();
SetIntegrations(PlaybackStatus.Paused);
ProgressTimer.Stop();
}
UpdatePlayButtonState();
}
public void StopMethod()
{
Player.Queue.Clear();
Player.Stop();
}
public async void NextTrackMethod() => await Player.NextAsync();
public async void PreviousTrackMethod()
{
if (!Player.FileLoaded) return;
if (Player.CurrentTime.TotalSeconds <= 5) await Player.PreviousAsync();
else
{
Player.CurrentTime = TimeSpan.FromSeconds(0);
ProgressTimer.Start(); // to resync the progress timer
}
}
public void ShuffleMethod()
{
if (Player.Queue.Shuffle)
{
Player.Queue.Shuffle = false;
ShuffleButton.Fill = (Brush)FindResource("PrimaryTextColor");
}
else
{
Player.Queue.Shuffle = true;
ShuffleButton.Fill = new LinearGradientBrush(Color.FromRgb(105, 181, 120), Color.FromRgb(51, 139, 193), 0);
}
}
public void RepeatOneMethod()
{
if (Player.Queue.RepeatMode == RepeatMode.None)
{
Player.Queue.RepeatMode = RepeatMode.RepeatAll;
RepeatOneButton.Data = (Geometry)FindResource("RepeatAllIcon");
RepeatOneButton.Fill = new LinearGradientBrush(Color.FromRgb(105, 181, 120), Color.FromRgb(51, 139, 193), 0);
}
else if (Player.Queue.RepeatMode == RepeatMode.RepeatAll)
{
Player.Queue.RepeatMode = RepeatMode.RepeatOne;
RepeatOneButton.Data = (Geometry)FindResource("RepeatOneIcon");
RepeatOneButton.Fill = new LinearGradientBrush(Color.FromRgb(105, 181, 120), Color.FromRgb(51, 139, 193), 0);
}
else
{
Player.Queue.RepeatMode = RepeatMode.None;
RepeatOneButton.Data = (Geometry)FindResource("RepeatAllIcon");
RepeatOneButton.Fill = (Brush)FindResource("PrimaryTextColor");
}
}
public void UpdatePlayButtonState()
{
if (!Player.Paused) PlayPauseButton.Data = (Geometry)FindResource("PauseIcon");
else PlayPauseButton.Data = (Geometry)FindResource("PlayIcon");
if (PauseAfterCurrentTrack) ProgressIndicator2.Foreground = new SolidColorBrush(Color.FromRgb(212, 70, 63));
else ProgressIndicator2.Foreground = (Brush)FindResource("SecondaryTextColor");
}
#endregion
#region Logic
public void SetCoverArtVisibility(bool mode)
{
if (!mode) CoverArtArea.Width = new GridLength(5);
else CoverArtArea.Width = new GridLength(75);
}
public async void ShowAuxilliaryPane(AuxiliaryPane pane, int width = 235, bool openleft = false)
{
LoggingHandler.Log($"Showing pane --> {pane}");
if (SelectedAuxiliaryPane == pane)
{
await HideAuxilliaryPane();
return;
}
if (SelectedAuxiliaryPane != AuxiliaryPane.None) await HideAuxilliaryPane(true);
switch (pane)
{
case AuxiliaryPane.Settings:
RightFrame.Content = new SettingsPage(this);
break;
case AuxiliaryPane.QueueManagement:
RightFrame.Content = new QueueManagement(this);
break;
case AuxiliaryPane.Search:
RightFrame.Content = new SearchPage(this);
break;
case AuxiliaryPane.Notifications:
RightFrame.Content = new NotificationPage(this);
break;
case AuxiliaryPane.TrackInfo:
RightFrame.Content = new TrackInfoPage(this);
break;
case AuxiliaryPane.Lyrics:
RightFrame.Content = new LyricsPage(this);
break;
default:
return;
}
if (!openleft) DockPanel.SetDock(RightFrame, Dock.Right); else DockPanel.SetDock(RightFrame, Dock.Left);
RightFrame.Visibility = Visibility.Visible;
RightFrame.Width = width;
var sb = InterfaceUtils.GetThicknessAnimation(
openleft ? new Thickness(width * -1 /*negate*/, 0, 0, 0) : new Thickness(0, 0, width * -1 /*negate*/, 0),
new Thickness(0),
TimeSpan.FromMilliseconds(120),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3 });
sb.Begin(RightFrame);
SelectedAuxiliaryPane = pane;
}
public async Task HideAuxilliaryPane(bool animate = true)
{
var sb = InterfaceUtils.GetThicknessAnimation(
new Thickness(0),
DockPanel.GetDock(RightFrame) == Dock.Left ? new Thickness(RightFrame.Width * -1, 0, 0, 0) : new Thickness(0, 0, RightFrame.Width * -1, 0),
TimeSpan.FromMilliseconds(120),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
if (animate) await sb.BeginStoryboardAsync(RightFrame);
RightFrame.Visibility = Visibility.Collapsed;
RightFrame.Content = null;
SelectedAuxiliaryPane = AuxiliaryPane.None;
}
public bool IsControlsBoxVisible { get; private set; } = false;
public async void ShowControlsBox()
{
var navBarStoryboard = InterfaceUtils.GetThicknessAnimation(
new Thickness(0, -25, 0, 0),
new Thickness(0),
TimeSpan.FromMilliseconds(500),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
var controlsBoxStoryboard = InterfaceUtils.GetThicknessAnimation(
new Thickness(0, 0, 0, -84),
new Thickness(0),
TimeSpan.FromMilliseconds(500),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
navBarStoryboard.Begin(MainBar);
await controlsBoxStoryboard.BeginStoryboardAsync(ControlsBoxBorder);
IsControlsBoxVisible = true;
}
public async void HideControlsBox()
{
var navBarStoryboard = InterfaceUtils.GetThicknessAnimation(
new Thickness(0),
new Thickness(0, -25, 0, 0),
TimeSpan.FromMilliseconds(500),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
var controlsBoxStoryboard = InterfaceUtils.GetThicknessAnimation(
new Thickness(0),
new Thickness(0, 0, 0, -84),
TimeSpan.FromMilliseconds(500),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
navBarStoryboard.Begin(MainBar);
await controlsBoxStoryboard.BeginStoryboardAsync(ControlsBoxBorder);
IsControlsBoxVisible = false;
}
public void ProcessSettings(bool initialize = false)
{
if (initialize)
{
VolumeBar.Value = App.Config.Volume;
ChangeTabs(App.Config.CurrentMenu);
}
if (App.Config.PlaybackTracking) TrackingHandler = new PlaytimeTrackingHandler(this);
else if (TrackingHandler != null)
{
TrackingHandler?.Close();
TrackingHandler = null;
}
}
public async void HandlePersistence()
{
var persistenceFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FRESHMusicPlayer", "Configuration", "FMP-WPF", "persistence");
if (File.Exists(persistenceFilePath))
{
var fields = File.ReadAllText(persistenceFilePath).Split(';');
var top = double.Parse(fields[2]);
var left = double.Parse(fields[3]);
var height = double.Parse(fields[4]);
var width = double.Parse(fields[5]);
var rect = new System.Drawing.Rectangle((int)left, (int)top, (int)width, (int)height);
if (WinForms.Screen.AllScreens.Any(y => y.WorkingArea.IntersectsWith(rect)))
{
Top = top;
Left = left;
Height = height;
Width = width;
}
if (fields[0] != string.Empty)
{
await Player.PlayAsync(fields[0]);
Player.RepositionMusic(int.Parse(fields[1]));
PlayPauseMethod();
ProgressTick();
}
}
}
public void WritePersistence()
{
if (Player.FileLoaded) // TODO: make this less shitty
{
File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FRESHMusicPlayer", "Configuration", "FMP-WPF", "persistence"),
$"{Player.FilePath};{(int)Player.CurrentBackend.CurrentTime.TotalSeconds};{Top};{Left};{Height};{Width}");
}
else
{
File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FRESHMusicPlayer", "Configuration", "FMP-WPF", "persistence"),
$";;{Top};{Left};{Height};{Width}");
}
}
public MemoryStream GetCoverArtFromDirectory()
{
if (File.Exists(Player.FilePath))
{
var currentDirectory = Path.GetDirectoryName(Player.FilePath);
foreach (var file in Directory.EnumerateFiles(currentDirectory))
{
if (Path.GetFileNameWithoutExtension(file).ToUpper() == "COVER" ||
Path.GetFileNameWithoutExtension(file).ToUpper() == "ARTWORK" ||
Path.GetFileNameWithoutExtension(file).ToUpper() == "FRONT" ||
Path.GetFileNameWithoutExtension(file).ToUpper() == "BACK" ||
Path.GetFileNameWithoutExtension(file).ToUpper() == Player.FilePath)
{
if (Path.GetExtension(file) == ".png" || Path.GetExtension(file) == ".jpg" || Path.GetExtension(file) == ".jpeg")
{
return new MemoryStream(File.ReadAllBytes(file));
}
}
}
}
return null;
}
public void UpdateIntegrations()
{
if (Environment.OSVersion.Version.Major >= 10 && App.Config.IntegrateSMTC)
{
smtcIntegration = new SMTCIntegration(this);
}
else smtcIntegration = null;
if (App.Config.IntegrateDiscordRPC) discordIntegration = new DiscordIntegration();
else
{
discordIntegration?.Close();
discordIntegration = null;
}
}
public void SetIntegrations(PlaybackStatus status)
{
if (Environment.OSVersion.Version.Major >= 10 && App.Config.IntegrateSMTC)
{
smtcIntegration?.Update(CurrentTrack, status);
}
if (App.Config.IntegrateDiscordRPC)
{
discordIntegration?.Update(CurrentTrack, status);
}
}
public void ChangeTabs(Menu tab, string search = null)
{
LoggingHandler.Log($"Changing tabs -> {tab}");
var previousMenu = SelectedMenu;
SelectedMenu = tab;
TextBlock tabLabel;
switch (SelectedMenu)
{
case Menu.Tracks:
ContentFrame.Content = new LibraryPage(this, search);
tabLabel = TracksTab;
break;
case Menu.Artists:
ContentFrame.Content = new LibraryPage(this, search);
tabLabel = ArtistsTab;
break;
case Menu.Albums:
ContentFrame.Content = new LibraryPage(this, search);
tabLabel = AlbumsTab;
break;
case Menu.Playlists:
ContentFrame.Content = new LibraryPage(this, search);
tabLabel = PlaylistsTab;
break;
case Menu.Import:
ContentFrame.Content = new ImportPage(this);
tabLabel = ImportTab;
break;
case Menu.Fullscreen:
ContentFrame.Content = new FullscreenPage(this, previousMenu);
tabLabel = ImportTab;
break;
default:
tabLabel = null;
break;
}
//TabChanged?.Invoke(null, search);
TracksTab.FontWeight = ArtistsTab.FontWeight = AlbumsTab.FontWeight = PlaylistsTab.FontWeight = ImportTab.FontWeight = FontWeights.Normal;
tabLabel.FontWeight = FontWeights.Bold;
}
#endregion
#region Events
#region Player
private void Player_SongStopped(object sender, EventArgs e)
{
Title = WindowName;
TitleLabel.Text = ArtistLabel.Text = Properties.Resources.MAINWINDOW_NOTHINGPLAYING;
ProgressTimer.Stop();
CoverArtBox.Source = null;
SetIntegrations(PlaybackStatus.Stopped);
SetCoverArtVisibility(false);
LoggingHandler.Log("Stopping!");
}
private void Player_SongLoading(object sender, EventArgs e) => Mouse.OverrideCursor = Cursors.AppStarting;
private void Player_SongChanged(object sender, EventArgs e)
{
Mouse.OverrideCursor = null;
CurrentTrack = Player.CurrentBackend.Metadata;
Title = $"{string.Join(", ", CurrentTrack.Artists)} - {CurrentTrack.Title} | {WindowName}";
TitleLabel.Text = CurrentTrack.Title;
ArtistLabel.Text = string.Join(", ", CurrentTrack.Artists) == "" ? Properties.Resources.MAINWINDOW_NOARTIST : string.Join(", ", CurrentTrack.Artists);
ProgressBar.Maximum = Player.CurrentBackend.TotalTime.TotalSeconds;
if (Player.CurrentBackend.TotalTime.TotalSeconds != 0) ProgressIndicator2.Text = Player.CurrentBackend.TotalTime.ToString(@"mm\:ss");
else ProgressIndicator2.Text = "∞";
SetIntegrations(PlaybackStatus.Playing);
UpdatePlayButtonState();
if (CurrentTrack.CoverArt is null)
{
var file = GetCoverArtFromDirectory();
if (file != null)
{
CoverArtBox.Source = BitmapFrame.Create(file, BitmapCreateOptions.None, BitmapCacheOption.None);
SetCoverArtVisibility(true);
}
else
{
CoverArtBox.Source = null;
SetCoverArtVisibility(false);
}
}
else
{
CoverArtBox.Source = BitmapFrame.Create(new MemoryStream(CurrentTrack.CoverArt), BitmapCreateOptions.None, BitmapCacheOption.None);
SetCoverArtVisibility(true);
}
ProgressTimer.Start();
if (PauseAfterCurrentTrack && !Player.Paused)
{
PlayPauseMethod();
PauseAfterCurrentTrack = false;
}
LoggingHandler.Log("Changing tracks");
}
private async void Player_SongException(object sender, PlaybackExceptionEventArgs e)
{
NotificationHandler.Add(new Notification
{
ContentText = string.Format(Properties.Resources.MAINWINDOW_PLAYBACK_ERROR_DETAILS, e.Details),
IsImportant = true,
DisplayAsToast = true,
Type = NotificationType.Failure
});
await Player.NextAsync();
}
#endregion
#region ControlsBox
private void ShuffleButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => ShuffleMethod();
private void RepeatOneButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => RepeatOneMethod();
private void PreviousButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => PreviousTrackMethod();
private void PlayPauseButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => PlayPauseMethod();
private void NextTrackButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => NextTrackMethod();
private bool isDragging = false;
private void ProgressBar_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
isDragging = true;
ProgressTimer.Stop();
}
private void ProgressBar_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
if (Player.FileLoaded)
{
ProgressTimer.Start();
}
isDragging = false;
}
private void ProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (isDragging && Player.FileLoaded)
{
Player.RepositionMusic((int)ProgressBar.Value);
ProgressTick();
}
}
private void ProgressBar_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (Player.FileLoaded && !isDragging)
{
Player.RepositionMusic((int)ProgressBar.Value);
ProgressTick();
}
}
private void VolumeBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Player.Volume = (float)(VolumeBar.Value / 100);
}
private void ProgressTimer_Tick(object sender, EventArgs e) => ProgressTick();
private void ProgressTick()
{
var time = Player.CurrentTime;
ProgressIndicator1.Text = time.ToString(@"mm\:ss");
if (App.Config.ShowRemainingProgress) ProgressIndicator2.Text
= $"-{TimeSpan.FromSeconds(time.TotalSeconds - Math.Floor(Player.CurrentBackend.TotalTime.TotalSeconds)):mm\\:ss}";
if (App.Config.ShowTimeInWindow) Title = $"{time:mm\\:ss}/{Player.CurrentBackend.TotalTime:mm\\:ss} | {WindowName}";
if (!isDragging) ProgressBar.Value = time.TotalSeconds;
Player.AvoidNextQueue = false;
ProgressTimer.Start(); // resync the progress timer
}
private void TrackTitle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(AuxiliaryPane.TrackInfo, 235, true);
private void TrackTitle_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
var cm = FindResource("MiscContext") as ContextMenu;
cm.PlacementTarget = sender as Button;
cm.IsOpen = true;
}
private void TrackContextTagEditor_Click(object sender, RoutedEventArgs e)
{
var tracks = new List<string>();
if (Player.FileLoaded) tracks.Add(Player.FilePath); // if playing, edit the file the user is playing
else tracks = Player.Queue.Queue;
var tagEditor = new TagEditor(tracks, Player, Library);
tagEditor.WindowStartupLocation = WindowStartupLocation.CenterOwner;
tagEditor.Owner = this;
tagEditor.Show();
}
private void TrackContentPlaylistManagement_Click(object sender, RoutedEventArgs e)
{
string track;
if (Player.FileLoaded) track = Player.FilePath;
else track = null;
var playlistManagement = new PlaylistManagement(Library, NotificationHandler, SelectedMenu, track);
playlistManagement.WindowStartupLocation = WindowStartupLocation.CenterOwner;
playlistManagement.Owner = this;
playlistManagement.Show();
}
private void TrackContextMiniplayer_Click(object sender, RoutedEventArgs e)
{
Hide();
var miniPlayer = new MiniPlayer(this);
miniPlayer.Owner = this;
miniPlayer.ShowDialog();
Top = miniPlayer.Top;
Left = miniPlayer.Left;
Show();
}
private void TrackContext_PauseAuto_Click(object sender, RoutedEventArgs e)
{
PauseAfterCurrentTrack = !PauseAfterCurrentTrack;
UpdatePlayButtonState();
}
private void TrackContextArtist_Click(object sender, RoutedEventArgs e) => ChangeTabs(Menu.Artists, CurrentTrack?.Artists[0]);
private void TrackContextAlbum_Click(object sender, RoutedEventArgs e) => ChangeTabs(Menu.Albums, CurrentTrack?.Album);
private void TrackContextLyrics_Click(object sender, RoutedEventArgs e) => ShowAuxilliaryPane(AuxiliaryPane.Lyrics, openleft: true);
private async void TrackContextOpenFile_Click(object sender, RoutedEventArgs e)
{
var dialog = new Forms.FMPTextEntryBox(Properties.Resources.IMPORT_MANUALENTRY);
dialog.ShowDialog();
if (dialog.OK)
{
await Player.PlayAsync(dialog.Response);
}
}
#endregion
#region MenuBar
private void TracksTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Menu.Tracks);
private void ArtistsTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Menu.Artists);
private void AlbumsTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Menu.Albums);
private void PlaylistsTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Menu.Playlists);
private void ImportTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Menu.Import);
private void SettingsButton_Click(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(AuxiliaryPane.Settings, 335);
private void SearchButton_Click(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(AuxiliaryPane.Search, 335);
private void QueueManagementButton_Click(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(AuxiliaryPane.QueueManagement, 335);
private void NotificationButton_Click(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(AuxiliaryPane.Notifications);
private void NotificationHandler_NotificationInvalidate(object sender, EventArgs e)
{
NotificationCounterLabel.Text = NotificationHandler.Notifications.Count.ToString();
if (NotificationHandler.Notifications.Count != 0)
{
NotificationButton.Visibility = Visibility.Visible;
NotificationCounterLabel.Visibility = Visibility.Visible;
}
else
{
NotificationButton.Visibility = Visibility.Collapsed;
NotificationCounterLabel.Visibility = Visibility.Collapsed;
}
foreach (Notification box in NotificationHandler.Notifications)
{
if (box.DisplayAsToast && !box.Read)
{
if (SelectedAuxiliaryPane != AuxiliaryPane.Notifications)
{
ShowAuxilliaryPane(AuxiliaryPane.Notifications);
break;
}
}
}
}
#endregion
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (!(e.OriginalSource is TextBox || e.OriginalSource is ListBoxItem) || Keyboard.IsKeyDown(Key.LeftCtrl))
switch (e.Key)
{
case Key.Q:
ShowAuxilliaryPane(AuxiliaryPane.Settings, 335);
break;
case Key.A:
ChangeTabs(Menu.Tracks);
break;
case Key.S:
ChangeTabs(Menu.Artists);
break;
case Key.D:
ChangeTabs(Menu.Albums);
break;
case Key.F:
ChangeTabs(Menu.Playlists);
break;
case Key.G:
ChangeTabs(Menu.Import);
break;
case Key.E:
ShowAuxilliaryPane(AuxiliaryPane.Search, 335);
break;
case Key.R:
ShowAuxilliaryPane(AuxiliaryPane.TrackInfo, 235, true);
break;
case Key.W:
ShowAuxilliaryPane(AuxiliaryPane.QueueManagement, 335);
break;
case Key.Space:
PlayPauseMethod();
break;
}
switch (e.Key)
{
case Key.F1:
Process.Start("https://royce551.github.io/FRESHMusicPlayer/docs/index.html");
break;
case Key.F11:
if (SelectedMenu != Menu.Fullscreen) ChangeTabs(Menu.Fullscreen);
else ChangeTabs(Menu.Playlists);
break;
case Key.F12:
NotificationHandler.Add(new Notification { ContentText = "Debug Tools" });
NotificationHandler.Add(new Notification
{
ButtonText = "Garbage Collect",
OnButtonClicked = () =>
{
GC.Collect(2);
return false;
}
});
NotificationHandler.Add(new Notification
{
ButtonText = "Throw exception",
OnButtonClicked = () =>
{
throw new Exception("Exception for debugging");
}
});
NotificationHandler.Add(new Notification
{
ButtonText = "Make FMP topmost",
OnButtonClicked = () =>
{
Topmost = !Topmost;
return false;
}
});
break;
}
}
private void Window_DragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Copy;
}
private async void ControlsBox_Drop(object sender, DragEventArgs e)
{
Player.Queue.Clear();
InterfaceUtils.DoDragDrop((string[])e.Data.GetData(DataFormats.FileDrop), Player, Library, import: false);
await Player.PlayAsync();
}
private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
{
VolumeBar.Value += e.Delta / 100 * 3;
}
private void ProgressIndicator2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (Player.FileLoaded)
{
if (App.Config.ShowRemainingProgress)
{
App.Config.ShowRemainingProgress = false;
if (Player.CurrentBackend.TotalTime.TotalSeconds != 0) ProgressIndicator2.Text = Player.CurrentBackend.TotalTime.ToString(@"mm\:ss");
else ProgressIndicator2.Text = "∞";
}
else App.Config.ShowRemainingProgress = true;
}
}
private async void Window_SourceInitialized(object sender, EventArgs e)
{
UpdateIntegrations();
@ -809,38 +137,11 @@ namespace FRESHMusicPlayer
await new UpdateHandler(NotificationHandler).UpdateApp();
await PerformAutoImport();
}
public async Task PerformAutoImport()
{
if (App.Config.AutoImportPaths.Count <= 0) return; // not really needed but prevents going through unneeded
// effort (and showing the notification)
var notification = new Notification { ContentText = Properties.Resources.NOTIFICATION_SCANNING };
NotificationHandler.Add(notification);
var filesToImport = new List<string>();
var library = Library.Read();
await Task.Run(() =>
{
foreach (var folder in App.Config.AutoImportPaths)
{
var files = Directory.EnumerateFiles(folder, "*", SearchOption.AllDirectories)
.Where(name => name.EndsWith(".mp3")
|| name.EndsWith(".wav") || name.EndsWith(".m4a") || name.EndsWith(".ogg")
|| name.EndsWith(".flac") || name.EndsWith(".aiff")
|| name.EndsWith(".wma")
|| name.EndsWith(".aac")).ToArray();
foreach (var file in files)
{
if (!library.Select(x => x.Path).Contains(file))
filesToImport.Add(file);
}
}
Library.Import(filesToImport);
});
NotificationHandler.Remove(notification);
}
private void Window_Closed(object sender, EventArgs e)
{
App.Config.Volume = (int)VolumeBar.Value;
App.Config.CurrentMenu = SelectedMenu;
App.Config.CurrentMenu = CurrentTab;
TrackingHandler?.Close();
ConfigurationHandler.Write(App.Config);
Library.Database?.Dispose();
@ -848,27 +149,5 @@ namespace FRESHMusicPlayer
watcher.Dispose();
WritePersistence();
}
#endregion
private void CoverArtBox_ToolTipOpening(object sender, ToolTipEventArgs e)
{
if (CurrentTrack != null)
CoverArtBoxToolTip.Source = BitmapFrame.Create(new MemoryStream(CurrentTrack.CoverArt), BitmapCreateOptions.None, BitmapCacheOption.None);
}
private void CoverArtBox_ToolTipClosing(object sender, ToolTipEventArgs e)
{
CoverArtBoxToolTip.Source = null;
}
private void Window_Activated(object sender, EventArgs e)
{
ProgressTimer.Interval = 100;
}
private void Window_Deactivated(object sender, EventArgs e)
{
ProgressTimer.Interval = 1000;
}
}
}

View file

@ -0,0 +1,301 @@
using FRESHMusicPlayer.Forms;
using FRESHMusicPlayer.Forms.Playlists;
using FRESHMusicPlayer.Forms.TagEditor;
using FRESHMusicPlayer.Handlers.Notifications;
using FRESHMusicPlayer.Utilities;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.IO;
using System.Windows.Media.Imaging;
namespace FRESHMusicPlayer
{
// Event handlers and other doo dads
public partial class MainWindow
{
// Controls Box
private void ShuffleButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => ShuffleMethod();
private void RepeatOneButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => RepeatOneMethod();
private void PreviousButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => PreviousTrackMethod();
private void PlayPauseButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => PlayPauseMethod();
private void NextTrackButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => NextTrackMethod();
private bool isDragging = false;
private void ProgressBar_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
isDragging = true;
ProgressTimer.Stop();
}
private void ProgressBar_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
if (Player.FileLoaded)
{
ProgressTimer.Start();
}
isDragging = false;
}
private void ProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (isDragging && Player.FileLoaded)
{
Player.RepositionMusic((int)ProgressBar.Value);
ProgressTick();
}
}
private void ProgressBar_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (Player.FileLoaded && !isDragging)
{
Player.RepositionMusic((int)ProgressBar.Value);
ProgressTick();
}
}
private void VolumeBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Player.Volume = (float)(VolumeBar.Value / 100);
}
private void ProgressTimer_Tick(object sender, EventArgs e) => ProgressTick();
private void ProgressTick()
{
var time = Player.CurrentTime;
ProgressIndicator1.Text = time.ToString(@"mm\:ss");
if (App.Config.ShowRemainingProgress) ProgressIndicator2.Text
= $"-{TimeSpan.FromSeconds(time.TotalSeconds - Math.Floor(Player.CurrentBackend.TotalTime.TotalSeconds)):mm\\:ss}";
if (App.Config.ShowTimeInWindow) Title = $"{time:mm\\:ss}/{Player.CurrentBackend.TotalTime:mm\\:ss} | {WindowName}";
if (!isDragging) ProgressBar.Value = time.TotalSeconds;
Player.AvoidNextQueue = false;
ProgressTimer.Start(); // resync the progress timer
}
private void TrackTitle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(Pane.TrackInfo, 235, true);
private void TrackTitle_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
var cm = FindResource("MiscContext") as ContextMenu;
cm.PlacementTarget = sender as Button;
cm.IsOpen = true;
}
private void TrackContextTagEditor_Click(object sender, RoutedEventArgs e)
{
var tracks = new List<string>();
if (Player.FileLoaded) tracks.Add(Player.FilePath); // if playing, edit the file the user is playing
else tracks = Player.Queue.Queue;
var tagEditor = new TagEditor(tracks, Player, Library);
tagEditor.WindowStartupLocation = WindowStartupLocation.CenterOwner;
tagEditor.Owner = this;
tagEditor.Show();
}
private void TrackContentPlaylistManagement_Click(object sender, RoutedEventArgs e)
{
string track;
if (Player.FileLoaded) track = Player.FilePath;
else track = null;
var playlistManagement = new PlaylistManagement(Library, NotificationHandler, CurrentTab, track);
playlistManagement.WindowStartupLocation = WindowStartupLocation.CenterOwner;
playlistManagement.Owner = this;
playlistManagement.Show();
}
private void TrackContextMiniplayer_Click(object sender, RoutedEventArgs e)
{
Hide();
var miniPlayer = new MiniPlayer(this);
miniPlayer.Owner = this;
miniPlayer.ShowDialog();
Top = miniPlayer.Top;
Left = miniPlayer.Left;
Show();
}
private void TrackContext_PauseAuto_Click(object sender, RoutedEventArgs e)
{
PauseAfterCurrentTrack = !PauseAfterCurrentTrack;
UpdatePlayButtonState();
}
private void TrackContextArtist_Click(object sender, RoutedEventArgs e) => ChangeTabs(Tab.Artists, CurrentTrack?.Artists[0]);
private void TrackContextAlbum_Click(object sender, RoutedEventArgs e) => ChangeTabs(Tab.Albums, CurrentTrack?.Album);
private void TrackContextLyrics_Click(object sender, RoutedEventArgs e) => ShowAuxilliaryPane(Pane.Lyrics, openleft: true);
private async void TrackContextOpenFile_Click(object sender, RoutedEventArgs e)
{
var dialog = new Forms.FMPTextEntryBox(Properties.Resources.IMPORT_MANUALENTRY);
dialog.ShowDialog();
if (dialog.OK)
{
await Player.PlayAsync(dialog.Response);
}
}
private void ProgressIndicator2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (Player.FileLoaded)
{
if (App.Config.ShowRemainingProgress)
{
App.Config.ShowRemainingProgress = false;
if (Player.CurrentBackend.TotalTime.TotalSeconds != 0) ProgressIndicator2.Text = Player.CurrentBackend.TotalTime.ToString(@"mm\:ss");
else ProgressIndicator2.Text = "∞";
}
else App.Config.ShowRemainingProgress = true;
}
}
private void CoverArtBox_ToolTipOpening(object sender, ToolTipEventArgs e)
{
if (CurrentTrack != null)
CoverArtBoxToolTip.Source = BitmapFrame.Create(new MemoryStream(CurrentTrack.CoverArt), BitmapCreateOptions.None, BitmapCacheOption.None);
}
private void CoverArtBox_ToolTipClosing(object sender, ToolTipEventArgs e)
{
CoverArtBoxToolTip.Source = null;
}
// NavBar
private void TracksTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Tab.Tracks);
private void ArtistsTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Tab.Artists);
private void AlbumsTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Tab.Albums);
private void PlaylistsTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Tab.Playlists);
private void ImportTab_MouseDown(object sender, MouseButtonEventArgs e) => ChangeTabs(Tab.Import);
private void SettingsButton_Click(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(Pane.Settings, 335);
private void SearchButton_Click(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(Pane.Search, 335);
private void QueueManagementButton_Click(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(Pane.QueueManagement, 335);
private void NotificationButton_Click(object sender, MouseButtonEventArgs e) => ShowAuxilliaryPane(Pane.Notifications);
private void NotificationHandler_NotificationInvalidate(object sender, EventArgs e)
{
NotificationCounterLabel.Text = NotificationHandler.Notifications.Count.ToString();
if (NotificationHandler.Notifications.Count != 0)
{
NotificationButton.Visibility = Visibility.Visible;
NotificationCounterLabel.Visibility = Visibility.Visible;
}
else
{
NotificationButton.Visibility = Visibility.Collapsed;
NotificationCounterLabel.Visibility = Visibility.Collapsed;
}
foreach (Notification box in NotificationHandler.Notifications)
{
if (box.DisplayAsToast && !box.Read)
{
if (CurrentPane != Pane.Notifications)
{
ShowAuxilliaryPane(Pane.Notifications);
break;
}
}
}
}
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (!(e.OriginalSource is TextBox || e.OriginalSource is ListBoxItem) || Keyboard.IsKeyDown(Key.LeftCtrl))
switch (e.Key)
{
case Key.Q:
ShowAuxilliaryPane(Pane.Settings, 335);
break;
case Key.A:
ChangeTabs(Tab.Tracks);
break;
case Key.S:
ChangeTabs(Tab.Artists);
break;
case Key.D:
ChangeTabs(Tab.Albums);
break;
case Key.F:
ChangeTabs(Tab.Playlists);
break;
case Key.G:
ChangeTabs(Tab.Import);
break;
case Key.E:
ShowAuxilliaryPane(Pane.Search, 335);
break;
case Key.R:
ShowAuxilliaryPane(Pane.TrackInfo, 235, true);
break;
case Key.W:
ShowAuxilliaryPane(Pane.QueueManagement, 335);
break;
case Key.Space:
PlayPauseMethod();
break;
}
switch (e.Key)
{
case Key.F1:
Process.Start("https://royce551.github.io/FRESHMusicPlayer/docs/index.html");
break;
case Key.F11:
if (CurrentTab != Tab.Fullscreen) ChangeTabs(Tab.Fullscreen);
else ChangeTabs(Tab.Playlists);
break;
case Key.F12:
NotificationHandler.Add(new Notification { ContentText = "Debug Tools" });
NotificationHandler.Add(new Notification
{
ButtonText = "Garbage Collect",
OnButtonClicked = () =>
{
GC.Collect(2);
return false;
}
});
NotificationHandler.Add(new Notification
{
ButtonText = "Throw exception",
OnButtonClicked = () =>
{
throw new Exception("Exception for debugging");
}
});
NotificationHandler.Add(new Notification
{
ButtonText = "Make FMP topmost",
OnButtonClicked = () =>
{
Topmost = !Topmost;
return false;
}
});
break;
}
}
// Window
private void Window_DragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Copy;
}
private async void ControlsBox_Drop(object sender, DragEventArgs e)
{
Player.Queue.Clear();
InterfaceUtils.DoDragDrop((string[])e.Data.GetData(DataFormats.FileDrop), Player, Library, import: false);
await Player.PlayAsync();
}
private void Window_MouseWheel(object sender, MouseWheelEventArgs e)
{
VolumeBar.Value += e.Delta / 100 * 3;
}
private void Window_Activated(object sender, EventArgs e)
{
ProgressTimer.Interval = 100;
}
private void Window_Deactivated(object sender, EventArgs e)
{
ProgressTimer.Interval = 1000;
}
}
}

View file

@ -0,0 +1,474 @@
using FRESHMusicPlayer.Handlers;
using FRESHMusicPlayer.Handlers.Integrations;
using FRESHMusicPlayer.Handlers.Notifications;
using FRESHMusicPlayer.Pages;
using FRESHMusicPlayer.Pages.Library;
using FRESHMusicPlayer.Pages.Lyrics;
using FRESHMusicPlayer.Utilities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using WinForms = System.Windows.Forms;
namespace FRESHMusicPlayer
{
public enum Tab
{
Tracks,
Artists,
Albums,
Playlists,
Import,
Fullscreen,
Other
}
public enum Pane
{
None,
Settings,
QueueManagement,
Search,
Notifications,
TrackInfo,
Lyrics
}
// Code for the "shell" parts of the main window, player, and systemwide logic
public partial class MainWindow
{
// Player
public void PlayPauseMethod()
{
if (!Player.FileLoaded) return;
if (Player.Paused)
{
Player.Resume();
SetIntegrations(PlaybackStatus.Playing);
ProgressTimer.Start();
}
else
{
Player.Pause();
SetIntegrations(PlaybackStatus.Paused);
ProgressTimer.Stop();
}
UpdatePlayButtonState();
}
public void StopMethod()
{
Player.Queue.Clear();
Player.Stop();
}
public async void NextTrackMethod() => await Player.NextAsync();
public async void PreviousTrackMethod()
{
if (!Player.FileLoaded) return;
if (Player.CurrentTime.TotalSeconds <= 5) await Player.PreviousAsync();
else
{
Player.CurrentTime = TimeSpan.FromSeconds(0);
ProgressTimer.Start(); // to resync the progress timer
}
}
public void ShuffleMethod()
{
if (Player.Queue.Shuffle)
{
Player.Queue.Shuffle = false;
ShuffleButton.Fill = (Brush)FindResource("PrimaryTextColor");
}
else
{
Player.Queue.Shuffle = true;
ShuffleButton.Fill = new LinearGradientBrush(Color.FromRgb(105, 181, 120), Color.FromRgb(51, 139, 193), 0);
}
}
public void RepeatOneMethod()
{
if (Player.Queue.RepeatMode == RepeatMode.None)
{
Player.Queue.RepeatMode = RepeatMode.RepeatAll;
RepeatOneButton.Data = (Geometry)FindResource("RepeatAllIcon");
RepeatOneButton.Fill = new LinearGradientBrush(Color.FromRgb(105, 181, 120), Color.FromRgb(51, 139, 193), 0);
}
else if (Player.Queue.RepeatMode == RepeatMode.RepeatAll)
{
Player.Queue.RepeatMode = RepeatMode.RepeatOne;
RepeatOneButton.Data = (Geometry)FindResource("RepeatOneIcon");
RepeatOneButton.Fill = new LinearGradientBrush(Color.FromRgb(105, 181, 120), Color.FromRgb(51, 139, 193), 0);
}
else
{
Player.Queue.RepeatMode = RepeatMode.None;
RepeatOneButton.Data = (Geometry)FindResource("RepeatAllIcon");
RepeatOneButton.Fill = (Brush)FindResource("PrimaryTextColor");
}
}
public void UpdatePlayButtonState()
{
if (!Player.Paused) PlayPauseButton.Data = (Geometry)FindResource("PauseIcon");
else PlayPauseButton.Data = (Geometry)FindResource("PlayIcon");
if (PauseAfterCurrentTrack) ProgressIndicator2.Foreground = new SolidColorBrush(Color.FromRgb(212, 70, 63));
else ProgressIndicator2.Foreground = (Brush)FindResource("SecondaryTextColor");
}
private void Player_SongStopped(object sender, EventArgs e)
{
Title = WindowName;
TitleLabel.Text = ArtistLabel.Text = Properties.Resources.MAINWINDOW_NOTHINGPLAYING;
ProgressTimer.Stop();
CoverArtBox.Source = null;
SetIntegrations(PlaybackStatus.Stopped);
SetCoverArtVisibility(false);
LoggingHandler.Log("Stopping!");
}
private void Player_SongLoading(object sender, EventArgs e) => Mouse.OverrideCursor = Cursors.AppStarting;
private void Player_SongChanged(object sender, EventArgs e)
{
Mouse.OverrideCursor = null;
CurrentTrack = Player.CurrentBackend.Metadata;
Title = $"{string.Join(", ", CurrentTrack.Artists)} - {CurrentTrack.Title} | {WindowName}";
TitleLabel.Text = CurrentTrack.Title;
ArtistLabel.Text = string.Join(", ", CurrentTrack.Artists) == "" ? Properties.Resources.MAINWINDOW_NOARTIST : string.Join(", ", CurrentTrack.Artists);
ProgressBar.Maximum = Player.CurrentBackend.TotalTime.TotalSeconds;
if (Player.CurrentBackend.TotalTime.TotalSeconds != 0) ProgressIndicator2.Text = Player.CurrentBackend.TotalTime.ToString(@"mm\:ss");
else ProgressIndicator2.Text = "∞";
SetIntegrations(PlaybackStatus.Playing);
UpdatePlayButtonState();
if (CurrentTrack.CoverArt is null)
{
var file = GetCoverArtFromDirectory();
if (file != null)
{
CoverArtBox.Source = BitmapFrame.Create(file, BitmapCreateOptions.None, BitmapCacheOption.None);
SetCoverArtVisibility(true);
}
else
{
CoverArtBox.Source = null;
SetCoverArtVisibility(false);
}
}
else
{
CoverArtBox.Source = BitmapFrame.Create(new MemoryStream(CurrentTrack.CoverArt), BitmapCreateOptions.None, BitmapCacheOption.None);
SetCoverArtVisibility(true);
}
ProgressTimer.Start();
if (PauseAfterCurrentTrack && !Player.Paused)
{
PlayPauseMethod();
PauseAfterCurrentTrack = false;
}
LoggingHandler.Log("Changing tracks");
}
private async void Player_SongException(object sender, PlaybackExceptionEventArgs e)
{
NotificationHandler.Add(new Notification
{
ContentText = string.Format(Properties.Resources.MAINWINDOW_PLAYBACK_ERROR_DETAILS, e.Details),
IsImportant = true,
DisplayAsToast = true,
Type = NotificationType.Failure
});
await Player.NextAsync();
}
// Shell
public Tab CurrentTab = Tab.Tracks;
public Pane CurrentPane = Pane.None;
public bool IsControlsBoxVisible { get; private set; } = false;
public void SetCoverArtVisibility(bool mode)
{
if (!mode) CoverArtArea.Width = new GridLength(5);
else CoverArtArea.Width = new GridLength(75);
}
public async void ShowAuxilliaryPane(Pane pane, int width = 235, bool openleft = false)
{
LoggingHandler.Log($"Showing pane --> {pane}");
if (CurrentPane == pane)
{
await HideAuxilliaryPane();
return;
}
if (CurrentPane != Pane.None) await HideAuxilliaryPane(true);
switch (pane)
{
case Pane.Settings:
RightFrame.Content = new SettingsPage(this);
break;
case Pane.QueueManagement:
RightFrame.Content = new QueueManagement(this);
break;
case Pane.Search:
RightFrame.Content = new SearchPage(this);
break;
case Pane.Notifications:
RightFrame.Content = new NotificationPage(this);
break;
case Pane.TrackInfo:
RightFrame.Content = new TrackInfoPage(this);
break;
case Pane.Lyrics:
RightFrame.Content = new LyricsPage(this);
break;
default:
return;
}
if (!openleft) DockPanel.SetDock(RightFrame, Dock.Right); else DockPanel.SetDock(RightFrame, Dock.Left);
RightFrame.Visibility = Visibility.Visible;
RightFrame.Width = width;
var sb = InterfaceUtils.GetThicknessAnimation(
openleft ? new Thickness(width * -1 /*negate*/, 0, 0, 0) : new Thickness(0, 0, width * -1 /*negate*/, 0),
new Thickness(0),
TimeSpan.FromMilliseconds(120),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3 });
sb.Begin(RightFrame);
CurrentPane = pane;
}
public async Task HideAuxilliaryPane(bool animate = true)
{
var sb = InterfaceUtils.GetThicknessAnimation(
new Thickness(0),
DockPanel.GetDock(RightFrame) == Dock.Left ? new Thickness(RightFrame.Width * -1, 0, 0, 0) : new Thickness(0, 0, RightFrame.Width * -1, 0),
TimeSpan.FromMilliseconds(120),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
if (animate) await sb.BeginStoryboardAsync(RightFrame);
RightFrame.Visibility = Visibility.Collapsed;
RightFrame.Content = null;
CurrentPane = Pane.None;
}
public async void ShowControlsBox()
{
var navBarStoryboard = InterfaceUtils.GetThicknessAnimation(
new Thickness(0, -25, 0, 0),
new Thickness(0),
TimeSpan.FromMilliseconds(500),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
var controlsBoxStoryboard = InterfaceUtils.GetThicknessAnimation(
new Thickness(0, 0, 0, -84),
new Thickness(0),
TimeSpan.FromMilliseconds(500),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
navBarStoryboard.Begin(MainBar);
await controlsBoxStoryboard.BeginStoryboardAsync(ControlsBoxBorder);
IsControlsBoxVisible = true;
}
public async void HideControlsBox()
{
var navBarStoryboard = InterfaceUtils.GetThicknessAnimation(
new Thickness(0),
new Thickness(0, -25, 0, 0),
TimeSpan.FromMilliseconds(500),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
var controlsBoxStoryboard = InterfaceUtils.GetThicknessAnimation(
new Thickness(0),
new Thickness(0, 0, 0, -84),
TimeSpan.FromMilliseconds(500),
new PropertyPath(MarginProperty),
new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 3 });
navBarStoryboard.Begin(MainBar);
await controlsBoxStoryboard.BeginStoryboardAsync(ControlsBoxBorder);
IsControlsBoxVisible = false;
}
public void ChangeTabs(Tab tab, string search = null)
{
LoggingHandler.Log($"Changing tabs -> {tab}");
var previousMenu = CurrentTab;
CurrentTab = tab;
TextBlock tabLabel;
switch (CurrentTab)
{
case Tab.Tracks:
ContentFrame.Content = new LibraryPage(this, search);
tabLabel = TracksTab;
break;
case Tab.Artists:
ContentFrame.Content = new LibraryPage(this, search);
tabLabel = ArtistsTab;
break;
case Tab.Albums:
ContentFrame.Content = new LibraryPage(this, search);
tabLabel = AlbumsTab;
break;
case Tab.Playlists:
ContentFrame.Content = new LibraryPage(this, search);
tabLabel = PlaylistsTab;
break;
case Tab.Import:
ContentFrame.Content = new ImportPage(this);
tabLabel = ImportTab;
break;
case Tab.Fullscreen:
ContentFrame.Content = new FullscreenPage(this, previousMenu);
tabLabel = ImportTab;
break;
default:
tabLabel = null;
break;
}
TracksTab.FontWeight = ArtistsTab.FontWeight = AlbumsTab.FontWeight = PlaylistsTab.FontWeight = ImportTab.FontWeight = FontWeights.Normal;
tabLabel.FontWeight = FontWeights.Bold;
}
// Systemwide logic
public void ProcessSettings(bool initialize = false)
{
if (initialize)
{
VolumeBar.Value = App.Config.Volume;
ChangeTabs(App.Config.CurrentMenu);
}
if (App.Config.PlaybackTracking) TrackingHandler = new PlaytimeTrackingHandler(this);
else if (TrackingHandler != null)
{
TrackingHandler?.Close();
TrackingHandler = null;
}
}
public async void HandlePersistence()
{
var persistenceFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FRESHMusicPlayer", "Configuration", "FMP-WPF", "persistence");
if (File.Exists(persistenceFilePath))
{
var fields = File.ReadAllText(persistenceFilePath).Split(';');
var top = double.Parse(fields[2]);
var left = double.Parse(fields[3]);
var height = double.Parse(fields[4]);
var width = double.Parse(fields[5]);
var rect = new System.Drawing.Rectangle((int)left, (int)top, (int)width, (int)height);
if (WinForms.Screen.AllScreens.Any(y => y.WorkingArea.IntersectsWith(rect)))
{
Top = top;
Left = left;
Height = height;
Width = width;
}
if (fields[0] != string.Empty)
{
await Player.PlayAsync(fields[0]);
Player.RepositionMusic(int.Parse(fields[1]));
PlayPauseMethod();
ProgressTick();
}
}
}
public void WritePersistence()
{
if (Player.FileLoaded) // TODO: make this less shitty
{
File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FRESHMusicPlayer", "Configuration", "FMP-WPF", "persistence"),
$"{Player.FilePath};{(int)Player.CurrentBackend.CurrentTime.TotalSeconds};{Top};{Left};{Height};{Width}");
}
else
{
File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FRESHMusicPlayer", "Configuration", "FMP-WPF", "persistence"),
$";;{Top};{Left};{Height};{Width}");
}
}
public MemoryStream GetCoverArtFromDirectory()
{
if (File.Exists(Player.FilePath))
{
var currentDirectory = Path.GetDirectoryName(Player.FilePath);
foreach (var file in Directory.EnumerateFiles(currentDirectory))
{
if (Path.GetFileNameWithoutExtension(file).ToUpper() == "COVER" ||
Path.GetFileNameWithoutExtension(file).ToUpper() == "ARTWORK" ||
Path.GetFileNameWithoutExtension(file).ToUpper() == "FRONT" ||
Path.GetFileNameWithoutExtension(file).ToUpper() == "BACK" ||
Path.GetFileNameWithoutExtension(file).ToUpper() == Player.FilePath)
{
if (Path.GetExtension(file) == ".png" || Path.GetExtension(file) == ".jpg" || Path.GetExtension(file) == ".jpeg")
{
return new MemoryStream(File.ReadAllBytes(file));
}
}
}
}
return null;
}
public void UpdateIntegrations()
{
if (Environment.OSVersion.Version.Major >= 10 && App.Config.IntegrateSMTC)
{
smtcIntegration = new SMTCIntegration(this);
}
else smtcIntegration = null;
if (App.Config.IntegrateDiscordRPC) discordIntegration = new DiscordIntegration();
else
{
discordIntegration?.Close();
discordIntegration = null;
}
}
public void SetIntegrations(PlaybackStatus status)
{
if (Environment.OSVersion.Version.Major >= 10 && App.Config.IntegrateSMTC)
{
smtcIntegration?.Update(CurrentTrack, status);
}
if (App.Config.IntegrateDiscordRPC)
{
discordIntegration?.Update(CurrentTrack, status);
}
}
public async Task PerformAutoImport()
{
if (App.Config.AutoImportPaths.Count <= 0) return; // not really needed but prevents going through unneeded
// effort (and showing the notification)
var notification = new Notification { ContentText = Properties.Resources.NOTIFICATION_SCANNING };
NotificationHandler.Add(notification);
var filesToImport = new List<string>();
var library = Library.Read();
await Task.Run(() =>
{
foreach (var folder in App.Config.AutoImportPaths)
{
var files = Directory.EnumerateFiles(folder, "*", SearchOption.AllDirectories)
.Where(name => name.EndsWith(".mp3")
|| name.EndsWith(".wav") || name.EndsWith(".m4a") || name.EndsWith(".ogg")
|| name.EndsWith(".flac") || name.EndsWith(".aiff")
|| name.EndsWith(".wma")
|| name.EndsWith(".aac")).ToArray();
foreach (var file in files)
{
if (!library.Select(x => x.Path).Contains(file))
filesToImport.Add(file);
}
}
Library.Import(filesToImport);
});
NotificationHandler.Remove(notification);
}
}
}

View file

@ -25,8 +25,8 @@ namespace FRESHMusicPlayer.Pages
public partial class FullscreenPage : UserControl
{
private readonly MainWindow window;
private readonly Menu previousMenu;
public FullscreenPage(MainWindow window, Menu previousMenu)
private readonly Tab previousMenu;
public FullscreenPage(MainWindow window, Tab previousMenu)
{
this.window = window;
this.previousMenu = previousMenu;
@ -118,8 +118,8 @@ namespace FRESHMusicPlayer.Pages
window.WindowStyle = WindowStyle.SingleBorderWindow;
window.TracksTab.Visibility = window.ArtistsTab.Visibility = window.AlbumsTab.Visibility = window.PlaylistsTab.Visibility = window.ImportTab.Visibility = Visibility.Visible;
if (!window.IsControlsBoxVisible) window.ShowControlsBox();
if (previousMenu != Menu.Fullscreen) window.ChangeTabs(previousMenu);
else window.ChangeTabs(Menu.Import);
if (previousMenu != Tab.Fullscreen) window.ChangeTabs(previousMenu);
else window.ChangeTabs(Tab.Import);
}
private readonly WinForms.Timer controlDismissTimer = new WinForms.Timer { Interval = 2000, Enabled = true };

View file

@ -35,18 +35,18 @@ namespace FRESHMusicPlayer.Pages.Library
TracksPanel.Items.Clear();
CategoryPanel.Items.Clear();
InfoLabel.Visibility = Visibility.Hidden;
switch (window.SelectedMenu) // all of this stuff is here so that i can avoid copying and pasting the same page thrice, maybe there's a better way?
switch (window.CurrentTab) // all of this stuff is here so that i can avoid copying and pasting the same page thrice, maybe there's a better way?
{
case Menu.Tracks:
case Tab.Tracks:
await ShowTracks();
break;
case Menu.Artists:
case Tab.Artists:
await ShowArtists();
break;
case Menu.Albums:
case Tab.Albums:
await ShowAlbums();
break;
case Menu.Playlists:
case Tab.Playlists:
await ShowPlaylists();
break;
}
@ -154,8 +154,8 @@ namespace FRESHMusicPlayer.Pages.Library
{
var selectedItem = (string)CategoryPanel.SelectedItem;
if (selectedItem == null) return;
if (window.SelectedMenu == Menu.Artists) await ShowTracksforArtist(selectedItem);
else if (window.SelectedMenu == Menu.Playlists) await ShowTracksforPlaylist(selectedItem);
if (window.CurrentTab == Tab.Artists) await ShowTracksforArtist(selectedItem);
else if (window.CurrentTab == Tab.Playlists) await ShowTracksforPlaylist(selectedItem);
else await ShowTracksforAlbum(selectedItem);
}
//private void MainWindow_TabChanged(object sender, string e)

View file

@ -116,7 +116,7 @@ namespace FRESHMusicPlayer.Pages.Library
otheritem.Header = Properties.Resources.PLAYLISTMANAGEMENT;
otheritem.Click += (object send, RoutedEventArgs eee) =>
{
var management = new PlaylistManagement(library, notificationHandler, ((Application.Current as App).MainWindow as MainWindow).SelectedMenu, FilePath);
var management = new PlaylistManagement(library, notificationHandler, ((Application.Current as App).MainWindow as MainWindow).CurrentTab, FilePath);
management.ShowDialog();
};
MiscContext.Items.Add(otheritem);

View file

@ -13,7 +13,7 @@
<RowDefinition Height="33"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ListBox x:Name="NotificationList" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch" VirtualizingPanel.IsVirtualizing="True" Background="{StaticResource SecondaryColor}" Grid.Row="1" BorderBrush="{x:Null}">
<ListBox x:Name="NotificationList" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch" VirtualizingPanel.IsVirtualizing="True" ScrollViewer.CanContentScroll="False" Background="{StaticResource SecondaryColor}" Grid.Row="1" BorderBrush="{x:Null}">
</ListBox>
<TextBlock TextWrapping="Wrap" Text="{x:Static resx:Resources.NOTIFICATIONS_TITLE}" Foreground="{StaticResource PrimaryTextColor}" FontWeight="Bold" FontSize="18" Margin="5,5,116,5"/>
<TextBlock Text="{x:Static resx:Resources.NOTIFICATIONS_CLEAR_ALL}" Foreground="{StaticResource PrimaryTextColor}" FontSize="10" Margin="0,10,6,8" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" HorizontalAlignment="Right"/>

View file

@ -21,7 +21,7 @@ namespace FRESHMusicPlayer.Pages
}
private void InvalidateNotifications(object sender, EventArgs e) => ShowNotifications();
private void ShowNotifications()
private async void ShowNotifications()
{
NotificationList.Items.Clear();
foreach (Notification box in window.NotificationHandler.Notifications)
@ -29,7 +29,7 @@ namespace FRESHMusicPlayer.Pages
box.Read = true;
NotificationList.Items.Add(new NotificationBox(box, window.NotificationHandler));
}
if (NotificationList.Items.Count == 0) (Application.Current.MainWindow as MainWindow)?.HideAuxilliaryPane();
if (NotificationList.Items.Count == 0) await window.HideAuxilliaryPane();
}
private void Page_Unloaded(object sender, RoutedEventArgs e)

View file

@ -16,23 +16,40 @@
CornerRadius="2"
BorderBrush="{TemplateBinding Background}"
TextElement.Foreground="{TemplateBinding Foreground}"
Tag="{TemplateBinding Background}"
BorderThickness="1"
Background="{TemplateBinding Background}">
Background="{TemplateBinding Background}"
RenderTransformOrigin="0.5,0.5">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
TextElement.FontWeight="Regular"
Margin="4,0" >
</ContentPresenter>
<Border.RenderTransform>
<ScaleTransform x:Name="buttonScaleTransform" />
</Border.RenderTransform>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="border" Value="#4E9ED0"/>
</Trigger>
<EventTrigger RoutedEvent="Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="buttonScaleTransform"
Storyboard.TargetProperty="ScaleX"
To="0.9" Duration="0:0:.10" AutoReverse="True"/>
<DoubleAnimation
Storyboard.TargetName="buttonScaleTransform"
Storyboard.TargetProperty="ScaleY"
To="0.9" Duration="0:0:.10" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="#FF338BC1"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF338BC1"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" TargetName="grid" Value="0.25"/>
@ -74,6 +91,9 @@
Property="Height"
Value="6" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="CornerScrollBarRectangle" Value="#FF338BC1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
@ -81,7 +101,7 @@
</Style>
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Stylus.IsFlicksEnabled"
Value="false" />
Value="True" />
<Setter Property="Foreground"
Value="{StaticResource ForegroundColor}" />
<Setter Property="Background"
@ -296,14 +316,13 @@
x:Name="Border"
Grid.ColumnSpan="2"
CornerRadius="2" Padding="5"
Background="{StaticResource ForegroundColor}"
/>
Background="{StaticResource ForegroundColor}"/>
<Border
x:Name="Border2"
Grid.Column="0"
CornerRadius="2"
Margin="1"
Background="{StaticResource ForegroundColor}"
/>
Background="{StaticResource ForegroundColor}" />
<Path
x:Name="Arrow"
Grid.Column="1"
@ -313,6 +332,12 @@
Data="M0,0 L0,2 L4,6 L8,2 L8,0 L4,4 z"
/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="Border" Value="#FF338BC1"/>
<Setter Property="Background" TargetName="Border2" Value="#FF338BC1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}">
@ -451,4 +476,112 @@
</Setter.Value>
</Setter>
</Style>
<!--CheckBox-->
<Style x:Key="{x:Type CheckBox}" TargetType="{x:Type CheckBox}">
<Setter Property="Background" Value="{StaticResource ForegroundColor}"/>
<Setter Property="BorderBrush" Value="{StaticResource ForegroundColor}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<Grid VerticalAlignment="Center" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Grid" VerticalAlignment="Top" Grid.Column="0" Margin="0,0,5,0" Width="22" Height="22"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="2"
CornerRadius="2"
RenderTransformOrigin="0.5,0.5"
SnapsToDevicePixels="True" Padding="3">
<Viewbox x:Name="Check" Stretch="UniformToFill" Visibility="Collapsed" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,-3,0,0">
<Path Fill="{StaticResource PrimaryTextColor}" Data="M 17.939453 5.439453 L 7.5 15.888672 L 2.060547 10.439453 L 2.939453 9.560547 L 7.5 14.111328 L 17.060547 4.560547 Z"/>
</Viewbox>
<Border.RenderTransform>
<ScaleTransform x:Name="ScaleTransform"/>
</Border.RenderTransform>
</Border>
<ContentPresenter Grid.Column="1" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<!--<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True"/>
<Condition Property="IsMouseOver" Value="True"/>
<Setter TargetName="Check" Property="Visibility" Value="Visible"/>
</MultiTrigger.Conditions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True"/>
<Condition Property="IsMouseOver" Value="False"/>
</MultiTrigger.Conditions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="False"/>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsChecked" Value="True"/>
<Condition Property="IsMouseOver" Value="False"/>
</MultiTrigger.Conditions>
</MultiTrigger>-->
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Check" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Grid" Property="BorderBrush" Value="#FF338BC1"/>
</Trigger>
<EventTrigger RoutedEvent="Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="ScaleTransform"
Storyboard.TargetProperty="ScaleX"
To="0.9" Duration="0:0:.10" AutoReverse="True"/>
<DoubleAnimation
Storyboard.TargetName="ScaleTransform"
Storyboard.TargetProperty="ScaleY"
To="0.9" Duration="0:0:.10" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--ListBox-->
<!--<Style x:Key="{x:Type ListBoxItem}" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="myBorder"
Padding="5,2,0,2"
CornerRadius="2"
SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="myBorder" Property="Background" Value="#FF338BC1"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="myBorder" Property="Background" Value="#FF338BC1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>-->
</ResourceDictionary>