Last active
May 8, 2017 11:33
-
-
Save Guevara-chan/d0b532eb0e95bf37c3558b5b0b543e9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require('clr').init parms = | |
assemblies: ['System', 'mscorlib', 'PresentationFramework', 'Microsoft.VisualBasic', 'WindowsBase'] | |
#- Requires node-clr v0.0.17+ to work correctly. | |
Δimport = (namespace) -> Object.assign global, namespace | |
Δexport = (entity) -> module.exports[entity.name] = entity | |
repack = (array) -> array.GetValue idx for idx in [0...array.Length] | |
Function::getter = (name, proc) -> Object.defineProperty @prototype, name, {get: proc, configurable: true} | |
Function::setter = (name, proc) -> Object.defineProperty @prototype, name, {set: proc, configurable: true} | |
Function::new_branch = (name, body) -> @getter name, -> new BranchProxy @, body | |
BranchProxy = (root, body) -> | |
Object.setPrototypeOf (new Proxy body, | |
{get: (self, key) -> if typeof (val = self[key]) is 'function' then val.bind(self) else val}), root | |
# - | |
Δimport System.Windows | |
Δimport System.Windows.Input | |
Δimport System.Windows.Media | |
#.{ [Classes] | |
Δexport class XamlWindow | |
# --Methods goes here. | |
constructor: (markup) -> | |
@form = Markup.XamlReader.Parse(markup) | |
destroy: () -> | |
@form.Dispose() | |
find_child: (id) -> | |
@form.FindName id | |
find_res: (id) -> | |
@form.FindResource id | |
center: () -> | |
@x = (SystemParameters.PrimaryScreenWidth - @width) / 2 | |
@y = (SystemParameters.PrimaryScreenHeight - @height) / 2 | |
show: (modal = true) -> | |
if modal then @form.ShowDialog() else @form.Show() | |
request_file: (filter = 'All Files|*.*', mod) -> | |
dlg = | |
if mod is 'save' then new Microsoft.Win32.SaveFileDialog | |
else new Microsoft.Win32.OpenFileDialog | |
dlg.Multiselect = true if mod is 'multi' | |
dlg.Filter = filter | |
if dlg.ShowDialog @form then return if dlg.Multiselect then repack dlg.FileNames else dlg.FileName | |
request_text: (prompt, title = @title, responce = '') -> | |
Microsoft.VisualBasic.Interaction.InputBox prompt, title, responce, -1, -1 | |
bind_key: (key, proc, mod = 'None', cmd = new RoutedCommand) -> | |
key = Key[key] if typeof key is 'string' | |
mod = ModifierKeys[mod] if typeof mod is 'string' | |
@form.InputBindings.Add new KeyBinding cmd, key, mod | |
if proc? then @form.CommandBindings.Add new CommandBinding(cmd, proc) | |
# --Getters/setters. | |
@getter 'title', () -> @form.Title | |
@setter 'title', (val) -> @form.Title = val | |
@getter 'x', () -> @form.Left | |
@setter 'x', (val) -> @form.Left = val | |
@getter 'y', () -> @form.Top | |
@setter 'y', (val) -> @form.Top = val | |
@getter 'width', () -> @form.Width | |
@setter 'width', (val) -> @form.Width = val | |
@getter 'height', () -> @form.Height | |
@setter 'height', (val) -> @form.Height = val | |
# -------------------- # | |
Δexport class PlayerWindow extends XamlWindow | |
# --Methods goes here. | |
constructor: () -> | |
super @res.template | |
@[id.name] = new id(@) for id in [Δtime, Δbuttons, Δplaylist, Δvolume] | |
@center() | |
@show true | |
# --Buttons protobranch. | |
class Δbuttons | |
constructor: (host) -> | |
# Initial setup. | |
Object.setPrototypeOf (Object.getPrototypeOf @), host | |
@ui = | |
styles: | |
off: @find_res 'round_button_switch' | |
on: @find_res 'round_button' | |
# Layout reparsing: | |
for id, index in ['add', 'import', 'export', 'clear', 'switch', 'prev', 'next', 'shuffler', 'repeater'] | |
(@ui[id] = @find_child "btn_#{id}").Click.add @on[id] | |
if hotkey = ['A', 'I', 'E', 'Delete', '', 'P', 'N', 'S', 'R'][index] | |
@bind_key hotkey, @on[id], 'Control' | |
# Finalization. | |
@bind_key 'Space', @on.switch # Space -> play. | |
@shuffle = @repeat = @playing = false | |
sync: () -> | |
iif = (bool, val_true = "Disable", val_false = "Enable") -> if bool then val_true else val_false | |
[@ui.switch.Content , @ui.switch.ToolTip] = iif @playing, ["❚❚", "Halt [Space]"], ["▶", "Play [Space]"] | |
[@ui.shuffler.Style , @ui.shuffler.ToolTip] = | |
[@ui.styles[iif @shuffle, 'on', 'off'], "#{iif @shuffle} shuffle play [Ctrl+S]"] | |
[@ui.repeater.Style , @ui.repeater.ToolTip] = | |
[@ui.styles[iif @repeat, 'on', 'off'], "#{iif @repeat} repeat mode [Ctrl+R]"] | |
return @ | |
@new_branch 'on', | |
add: () -> @Δplaylist.add(); @ | |
import: () -> @Δplaylist.import(); @ | |
export: () -> @Δplaylist.export(); @ | |
clear: () -> @Δplaylist.clear(); @ | |
prev: () -> @Δplaylist.step(true); @ | |
next: () -> @Δplaylist.step(); @ | |
switch: () -> @playing = not @playing; @ | |
shuffler: () -> @shuffle = not @shuffle; @ | |
repeater: () -> @repeat = not @repeat; @ | |
@getter 'shuffle', () -> @__shuffle | |
@setter 'shuffle', (val) -> @__shuffle = val; @sync() | |
@getter 'repeat', () -> @__repeat | |
@setter 'repeat', (val) -> @__repeat = val; @sync() | |
@getter 'playing', () -> @__playing | |
@setter 'playing', (val) -> @__playing = val; @sync() | |
# --Playlist protobranch. | |
class Δplaylist | |
constructor: (host) -> | |
Object.setPrototypeOf (Object.getPrototypeOf @), host | |
@ui = {view: @find_child "playlist"} | |
@sync() | |
sync: () -> | |
new_entry = (title, len) => | |
item = new Controls.ListViewItem() | |
item.PreviewMouseRightButtonDown.add @on.context_menu | |
item.Content = | |
idx: @ui.view.Items.Count + 1 + "⋮" | |
title: title | |
len: "⋮#{len.ToString 'm\\:ss'}" | |
@listing.Add item | |
@listing.Clear() | |
new_entry "No_more_tears.mp3", System.TimeSpan.FromSeconds 90 | |
new_entry "Panda_hero.mp3", System.TimeSpan.FromSeconds 112 | |
@selected = 0 | |
return @ | |
add: (sources = @request_file @res.audio_formats, 'multi') -> | |
@sync() | |
import: (sources = @request_file @res.list_formats, 'multi') -> | |
@sync() | |
export: (dest = @request_file @res.list_formats, 'save') -> | |
@sync() | |
clear: () -> | |
@sync() | |
step: (backwards) -> | |
@selected = (@selected + if backwards then -1 else 1) % @length | |
select: (idx = 0) -> | |
if idx isnt @selected | |
@__selected = idx | |
@ui.view.SelectedIndex = @selected | |
@Δtime.sync() | |
return @ | |
@new_branch 'on', | |
context_menu: (src, e) -> e.Handled = true; @ | |
@getter 'listing', () -> @ui.view.Items | |
@getter 'length', () -> @listing.Count | |
@getter 'is_empty', () -> @length == 0 | |
@getter 'selected_item', () -> @listing.get(@selected) if @selected >= 0 | |
@getter 'selected', () -> @__selected | |
@setter 'selected', (val) -> @select(val) | |
# --Timeline protobranch. | |
class Δtime | |
constructor: (host) -> | |
# Initial setup. | |
Object.setPrototypeOf (Object.getPrototypeOf @), host | |
@ui = {} | |
for id in ['line', 'played', 'remains'] | |
@ui[id] = @find_child "time_#{id}" | |
# Event handling. | |
@ui.line.MouseLeftButtonDown.add @on.change | |
@ui.line.MouseMove.add (src, e) => @on.change(src, e) if e.LeftButton.Equals(MouseButtonState.Pressed) | |
# Finalization. | |
[@__total, @played] = [(System.TimeSpan.FromSeconds 90), (System.TimeSpan.FromSeconds 60)] | |
@sync() | |
sync: () -> | |
[@ui.played.Content, @ui.remains.Content] = | |
("■「#{span.ToString 'm\\:ss'}」■" for span in [@played, @remains]) | |
@ui.line.Maximum = @total.TotalSeconds | |
@ui.line.Value = @played.TotalSeconds | |
return @ | |
@new_branch 'on', | |
change: (src, e) -> @progress = e.GetPosition(src).X / src.ActualWidth * 100; @ | |
@getter 'remains', () -> @total.Subtract(@played) | |
@getter 'total', () -> @__total | |
@getter 'played', () -> @__played | |
@setter 'played', (val) -> @__played = val; @sync() | |
@getter 'progress', () -> @played / @total * 100 | |
@setter 'progress', (val) -> @played = System.TimeSpan.FromSeconds(@total.TotalSeconds * val/100); @sync() | |
# --Volume protobranch. | |
class Δvolume | |
constructor: (host) -> | |
# Initial setup. | |
Object.setPrototypeOf (Object.getPrototypeOf @), host | |
@ui = | |
styles: | |
off: @find_res 'ghost_button_red' | |
on: @find_res 'ghost_button' | |
# Layout reparsing: | |
for id in ['bar', 'symbol'] | |
@ui[id] = @find_child "vol_#{id}" | |
@ui.bar.ValueChanged.add @on.change | |
@ui.symbol.Click.add @on.switcher | |
@bind_key 'V', @on.switcher, 'Control' | |
# Finalization. | |
@switch on | |
sync: () -> | |
@ui.bar.Value = @level | |
[@ui.bar.ToolTip, @ui.symbol.ToolTip, @ui.symbol.Content, @ui.symbol.Style, @ui.symbol.Margin] = | |
if @is_muted | |
["Muted", "Enable sound [Ctrl+V]", "🔇", @ui.styles.off, new Thickness -1] | |
else ["Volume = #{@level.toFixed(1)}%", "Mute [Ctrl+V]", "🔊", @ui.styles.on | |
new Thickness 1, -3, 1, -3] | |
return @ | |
switch: (turn_on = @is_muted) -> | |
@level = if turn_on then 100 else 0 | |
return @ | |
@new_branch 'on', | |
change: () -> @level = @ui.bar.Value; @ | |
switcher: () -> @switch(); @ | |
@getter 'is_muted', () -> @level is 0 | |
@getter 'level', () -> @__level * 100 | |
@setter 'level', (val) -> @__level = val / 100; @sync() | |
# --Embedded resources. | |
@getter 'res', -> | |
template: """ | |
<Window | |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
Title="PlayerWindow" Height="330" Width="330" Background='#1f1f1f'> | |
<Window.Resources> | |
<Style x:Key="ghost_button" TargetType="Button"> | |
<Setter Property="BorderThickness" Value="0" /> | |
<Setter Property="Content" Value="¿" /> | |
<Setter Property="Background" Value="Transparent" /> | |
<Setter Property="Foreground" Value="Gainsboro" /> | |
<Setter Property="FontSize" Value="12" /> | |
<Setter Property="ToolTipService.InitialShowDelay" Value="1000"/> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="Button"> | |
<Grid> | |
<ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" | |
VerticalAlignment="Center"/> | |
</Grid> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
<Style.Triggers> | |
<Trigger Property="IsMouseOver" Value="True"> | |
<Trigger.EnterActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" | |
Duration="0:0:0.2" To="LightCoral " /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.EnterActions> | |
<Trigger.ExitActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" | |
Duration="0:0:0.2" /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.ExitActions> | |
</Trigger> | |
</Style.Triggers> | |
</Style> | |
<Style x:Key="ghost_button_red" TargetType="Button" BasedOn="{StaticResource ghost_button}"> | |
<Setter Property="FontSize" Value="14" /> | |
<Setter Property="Foreground" Value="OrangeRed" /> | |
<Setter Property="Margin" Value="0" /> | |
<Style.Triggers> | |
<Trigger Property="IsMouseOver" Value="True"> | |
<Trigger.EnterActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" | |
Duration="0:0:0.2" To="LightCoral " /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.EnterActions> | |
<Trigger.ExitActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" | |
Duration="0:0:0.2" /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.ExitActions> | |
</Trigger> | |
</Style.Triggers> | |
</Style> | |
<Style x:Key="round_button" TargetType="Button"> | |
<Style.Resources> | |
<Storyboard x:Key="round_button_unhl"> | |
<ColorAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Foreground.Color"/> | |
</Storyboard> | |
</Style.Resources> | |
<Setter Property="Margin" Value="1,0" /> | |
<Setter Property="Width" Value="25" /> | |
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Self}, Path=Width}" /> | |
<Setter Property="Foreground" Value="SandyBrown" /> | |
<Setter Property="FontSize" Value="15" /> | |
<Setter Property="FontFamily" Value="Segoe UI Symbol" /> | |
<Setter Property="ToolTipService.InitialShowDelay" Value="1000"/> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="Button"> | |
<Grid> | |
<Ellipse Stroke="{TemplateBinding Foreground}" Fill="transparent"/> | |
<ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" | |
VerticalAlignment="Center"/> | |
</Grid> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
<Style.Triggers> | |
<Trigger Property="IsMouseOver" Value="True"> | |
<Trigger.EnterActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation To="Tomato" Duration="0:0:0.2" | |
Storyboard.TargetProperty="Foreground.Color"/> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.EnterActions> | |
<Trigger.ExitActions> | |
<BeginStoryboard Storyboard="{StaticResource round_button_unhl}" /> | |
</Trigger.ExitActions> | |
</Trigger> | |
</Style.Triggers> | |
</Style> | |
<Style x:Key="round_button_io" TargetType="Button" BasedOn="{StaticResource round_button}"> | |
<Setter Property="Foreground" Value="#99d4ff" /> | |
<Style.Triggers> | |
<Trigger Property="IsMouseOver" Value="True"> | |
<Trigger.EnterActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation To="Aqua" Duration="0:0:0.2" | |
Storyboard.TargetProperty="Foreground.Color"/> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.EnterActions> | |
<Trigger.ExitActions> | |
<BeginStoryboard Storyboard="{StaticResource round_button_unhl}" /> | |
</Trigger.ExitActions> | |
</Trigger> | |
</Style.Triggers> | |
</Style> | |
<Style x:Key="round_button_switch" TargetType="Button" BasedOn="{StaticResource round_button}"> | |
<Setter Property="Foreground" Value="Gray" /> | |
<Style.Triggers> | |
<Trigger Property="IsMouseOver" Value="True"> | |
<Trigger.EnterActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation To="#BA9270" Duration="0:0:0.2" | |
Storyboard.TargetProperty="Foreground.Color"/> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.EnterActions> | |
<Trigger.ExitActions> | |
<BeginStoryboard Storyboard="{StaticResource round_button_unhl}" /> | |
</Trigger.ExitActions> | |
</Trigger> | |
</Style.Triggers> | |
</Style> | |
<Style x:Key="SliderRepeatButton" TargetType="RepeatButton"> | |
<Setter Property="SnapsToDevicePixels" Value="true" /> | |
<Setter Property="OverridesDefaultStyle" Value="true" /> | |
<Setter Property="IsTabStop" Value="false" /> | |
<Setter Property="Focusable" Value="false" /> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="RepeatButton"> | |
<Border BorderThickness="1" BorderBrush="Black" Background="Black" Height="3"/> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
<Style x:Key="SliderRepeatButton1" TargetType="RepeatButton"> | |
<Setter Property="SnapsToDevicePixels" Value="true" /> | |
<Setter Property="OverridesDefaultStyle" Value="true" /> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="RepeatButton"> | |
<Border SnapsToDevicePixels="True" Background="Aquamarine" BorderThickness="1" BorderBrush="DarkSlateBlue " Height="3"/> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
<Style x:Key="SliderThumb" TargetType="Thumb"> | |
<Setter Property="SnapsToDevicePixels" Value="true" /> | |
<Setter Property="OverridesDefaultStyle" Value="true" /> | |
<Setter Property="Background" Value="#99d4ff" /> | |
<Setter Property="Foreground" Value="black" /> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="Thumb"> | |
<Ellipse Height="10" Width="10" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}"></Ellipse> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
<Style.Triggers> | |
<Trigger Property="IsMouseOver" Value="True"> | |
<Trigger.EnterActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation Storyboard.TargetProperty="Background.Color" | |
Duration="0:0:0.2" To="PaleGreen" /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.EnterActions> | |
<Trigger.ExitActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ColorAnimation Storyboard.TargetProperty="Background.Color" | |
Duration="0:0:0.2" /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.ExitActions> | |
</Trigger> | |
</Style.Triggers> | |
</Style> | |
<ControlTemplate x:Key="Slider" TargetType="Slider"> | |
<Grid> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="Auto" /> | |
<RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}" /> | |
<RowDefinition Height="Auto" /> | |
</Grid.RowDefinitions> | |
<Track Grid.Row="1" x:Name="PART_Track"> | |
<Track.DecreaseRepeatButton> | |
<RepeatButton Style="{StaticResource SliderRepeatButton1}" Command="Slider.DecreaseLarge" /> | |
</Track.DecreaseRepeatButton> | |
<Track.Thumb> | |
<Thumb Style="{StaticResource SliderThumb}"/> | |
</Track.Thumb> | |
<Track.IncreaseRepeatButton> | |
<RepeatButton Style="{StaticResource SliderRepeatButton}" Command="Slider.IncreaseLarge" /> | |
</Track.IncreaseRepeatButton> | |
</Track> | |
</Grid> | |
</ControlTemplate> | |
<Style x:Key="Horizontal_Slider" TargetType="Slider"> | |
<Setter Property="Focusable" Value="false"/> | |
<Setter Property="SnapsToDevicePixels" Value="true" /> | |
<Setter Property="OverridesDefaultStyle" Value="true" /> | |
<Style.Triggers> | |
<Trigger Property="Orientation" Value="Horizontal"> | |
<Setter Property="Template" Value="{StaticResource Slider}" /> | |
</Trigger> | |
</Style.Triggers> | |
</Style> | |
</Window.Resources> | |
<DockPanel> | |
<Grid DockPanel.Dock="Bottom" Margin="0,-3"> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition/><ColumnDefinition/><ColumnDefinition/> | |
</Grid.ColumnDefinitions> | |
<Border Grid.Column="0" BorderThickness="1,0,0,0" BorderBrush="DarkOrange"> | |
<Label BorderBrush="Black" BorderThickness="0,0,2,0" Name="time_played" | |
Foreground="DarkOrange" FontFamily="Verdana" FontSize="11" HorizontalAlignment="Left" | |
VerticalAlignment="Center" /> | |
</Border> | |
<Border Grid.Column="2" BorderThickness="0,0,1,0" Margin="0,2" BorderBrush="Khaki"> | |
<Label BorderBrush="Black" BorderThickness="2,0,0,0" Name="time_remains" | |
Foreground="Khaki" FontFamily="Verdana" FontSize="11" HorizontalAlignment="Right" | |
VerticalAlignment="Center" /> | |
</Border> | |
<Grid Grid.Column="1"> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="Auto"/><ColumnDefinition/> | |
</Grid.ColumnDefinitions> | |
<Button Grid.Column="0" Name="vol_symbol" Style="{StaticResource ghost_button}" /> | |
<Slider Grid.Column="1" Name="vol_bar" VerticalAlignment="Center" Maximum="100" | |
Minimum="0" Style="{StaticResource Horizontal_Slider}" /> | |
</Grid> | |
</Grid> | |
<Border DockPanel.Dock="Bottom" BorderThickness="0,1,0,0" BorderBrush="Black"> | |
<ProgressBar Name="time_line" Foreground="DarkOrange" | |
Background="Khaki" Height="5" Value='50'/> | |
</Border> | |
<Grid DockPanel.Dock="Bottom"> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition /><ColumnDefinition /><ColumnDefinition /> | |
</Grid.ColumnDefinitions> | |
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"> | |
<TextBlock FontSize="20" Foreground="DimGray">「</TextBlock> | |
<Button Content="➕" Name='btn_add' ToolTip="Add to playlist [Ctrl+A]" Style="{StaticResource round_button_io}" Width="30" FontSize="17"/> | |
<Button Content="⏬" Name='btn_import' ToolTip="Import playlist [Ctrl+I]" Style="{StaticResource round_button_io}"/> | |
<Button Content="🔀" Name='btn_shuffler' /> | |
<TextBlock FontSize="20" Foreground="DimGray">」</TextBlock> | |
</StackPanel> | |
<Border Grid.Column="1" Padding="0,3" BorderThickness="2,0" BorderBrush="Black"> | |
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> | |
<TextBlock FontSize="20" Foreground="AliceBlue">⋮</TextBlock> | |
<Button Content="⏮" Name='btn_prev' ToolTip="Previous track [Ctrl+P]" Style="{StaticResource round_button}"/> | |
<Button Content="¿" Name='btn_switch' Style="{StaticResource round_button}" Width="30" FontSize="17"/> | |
<Button Content="⏭" Name='btn_next' ToolTip="Next track [Ctrl+N]" Style="{StaticResource round_button}"/> | |
<TextBlock FontSize="20" Foreground="AliceBlue">⋮</TextBlock> | |
</StackPanel> | |
</Border> | |
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"> | |
<TextBlock FontSize="20" Foreground="DimGray">「</TextBlock> | |
<Button Content="🔁" Name='btn_repeater' /> | |
<Button Content="⏫" Name='btn_export' ToolTip="Export playlist [Ctrl+E]" Style="{StaticResource round_button_io}"/> | |
<Button Content="✖" Name='btn_clear' ToolTip="Clear playlist [Ctrl+Del]" Style="{StaticResource round_button_io}" Width="30" FontSize="17"/> | |
<TextBlock FontSize="20" Foreground="DimGray">」</TextBlock> | |
</StackPanel> | |
</Grid> | |
<ListView Name="playlist" Padding="0" Background="Transparent" Foreground="Khaki" BorderThickness="5,5,5,2" BorderBrush="Black"> | |
<ListView.View> | |
<GridView> | |
<GridViewColumn> | |
<GridViewColumn.CellTemplate> | |
<DataTemplate> | |
<TextBlock Text="{Binding idx}" Foreground="Gray" TextAlignment="Right" /> | |
</DataTemplate> | |
</GridViewColumn.CellTemplate> | |
</GridViewColumn> | |
<GridViewColumn DisplayMemberBinding="{Binding title}"/> | |
<GridViewColumn> | |
<GridViewColumn.CellTemplate> | |
<DataTemplate> | |
<TextBlock Text="{Binding len}" Foreground="DarkTurquoise" /> | |
</DataTemplate> | |
</GridViewColumn.CellTemplate> | |
</GridViewColumn> | |
</GridView> | |
</ListView.View> | |
<ListView.ItemContainerStyle> | |
<Style TargetType="ListViewItem"> | |
<Setter Property="HorizontalContentAlignment" Value="Stretch" /> | |
<Setter Property="SnapsToDevicePixels" Value="true"/> | |
<Setter Property="OverridesDefaultStyle" Value="true"/> | |
<Setter Property="Template"> | |
<Setter.Value> | |
<ControlTemplate TargetType="ListBoxItem"> | |
<Border Name="HL" Margin="0,1" Padding="2" SnapsToDevicePixels="true" Background="#181818"> | |
<Border Name="Active" BorderThickness="0" BorderBrush="Coral"> | |
<GridViewRowPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> | |
</Border> | |
<Border.BorderBrush> | |
<DrawingBrush Viewport="0,0,8,8" ViewportUnits="Absolute" TileMode="Tile"> | |
<DrawingBrush.Drawing> | |
<DrawingGroup> | |
<GeometryDrawing Brush="#050505"> | |
<GeometryDrawing.Geometry> | |
<GeometryGroup> | |
<RectangleGeometry Rect="0,0,50,50" /> | |
<RectangleGeometry Rect="50,50,50,50" /> | |
</GeometryGroup> | |
</GeometryDrawing.Geometry> | |
</GeometryDrawing> | |
</DrawingGroup> | |
</DrawingBrush.Drawing> | |
</DrawingBrush> | |
</Border.BorderBrush> | |
</Border> | |
<ControlTemplate.Triggers> | |
<Trigger Property="IsSelected" Value="True"> | |
<Trigger.EnterActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ThicknessAnimation | |
Storyboard.TargetName="Active" | |
Storyboard.TargetProperty="BorderThickness" | |
Duration="0:0:0.2" To="4,0,0,0" /> | |
<ColorAnimation | |
Storyboard.TargetProperty="Foreground.Color" | |
Duration="0:0:0.2" To="Coral" /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.EnterActions> | |
<Trigger.ExitActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ThicknessAnimation | |
Storyboard.TargetName="Active" | |
Storyboard.TargetProperty="BorderThickness" | |
Duration="0:0:0.2" /> | |
<ColorAnimation | |
Storyboard.TargetProperty="Foreground.Color" | |
Duration="0:0:0.2" /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.ExitActions> | |
</Trigger> | |
<Trigger Property="IsMouseOver" Value="True"> | |
<Trigger.EnterActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ThicknessAnimation | |
Storyboard.TargetName="HL" | |
Storyboard.TargetProperty="BorderThickness" | |
Duration="0:0:0.2" To="0,2" /> | |
<ThicknessAnimation | |
Storyboard.TargetName="HL" | |
Storyboard.TargetProperty="Margin" | |
Duration="0:0:0.2" To="0" /> | |
<ColorAnimation | |
Storyboard.TargetName="HL" | |
Storyboard.TargetProperty="Background.Color" | |
Duration="0:0:0.2" To="Black" /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.EnterActions> | |
<Trigger.ExitActions> | |
<BeginStoryboard> | |
<Storyboard> | |
<ThicknessAnimation | |
Storyboard.TargetName="HL" | |
Storyboard.TargetProperty="BorderThickness" | |
Duration="0:0:0.2" /> | |
<ThicknessAnimation | |
Storyboard.TargetName="HL" | |
Storyboard.TargetProperty="Margin" | |
Duration="0:0:0.2" /> | |
<ColorAnimation | |
Storyboard.TargetName="HL" | |
Storyboard.TargetProperty="Background.Color" | |
Duration="0:0:0.2" /> | |
</Storyboard> | |
</BeginStoryboard> | |
</Trigger.ExitActions> | |
</Trigger> | |
</ControlTemplate.Triggers> | |
</ControlTemplate> | |
</Setter.Value> | |
</Setter> | |
</Style> | |
</ListView.ItemContainerStyle> | |
<ListView.Resources> | |
<Style TargetType="GridViewColumnHeader"> | |
<Setter Property="Visibility" Value="Collapsed" /> | |
</Style> | |
</ListView.Resources> | |
</ListView> | |
</DockPanel> | |
</Window> | |
""" | |
audio_formats: "MPEG-1/2/2.5 Layer 3 (*.mp3)|*.mp3|Waveform Audio File Format (*.wav)|*.wav| | |
Windows Media Audio (*.wma)|*.wma|Dolby Digital (*.ac3)|*.ac3|Advanced Audio Codings (*.aac)|*.aac| | |
Free Lossless Audio Codec (*.flac)|(*.flac)|Ogg Vorbis (*.ogg)|*.ogg|All Files|*.*" | |
list_formats: "Vy:nil listing (*.nil)|*.nil|All Files|*.*" | |
#.} | |
# ==Usage sandbox== | |
new PlayerWindow() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment