Files
ebbes-meme-clipboard/src/EbbesMemeClipboard/Views/PickerWindow.xaml
T

258 lines
15 KiB
XML

<Window x:Class="EbbesMemeClipboard.Views.PickerWindow"
x:Name="RootWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:EbbesMemeClipboard.ViewModels"
xmlns:models="clr-namespace:EbbesMemeClipboard.Models"
Title="Meme Clipboard"
Width="420" Height="520"
WindowStyle="None"
AllowsTransparency="True"
Background="Transparent"
ShowInTaskbar="False"
Topmost="True"
ResizeMode="NoResize"
WindowStartupLocation="Manual"
AllowDrop="True"
Deactivated="PickerWindow_OnDeactivated"
KeyDown="PickerWindow_OnKeyDown"
Drop="PickerWindow_OnDrop"
DragOver="PickerWindow_OnDragOver"
ContextMenuOpening="PickerWindow_OnContextMenuOpening"
ContextMenuClosing="PickerWindow_OnContextMenuClosing">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/>
<Style x:Key="FlatButtonStyle" TargetType="Button">
<Setter Property="Background" Value="#2B2D31"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}" CornerRadius="8" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#3A3D42"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#454952"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Tag carries "is this tab active", so one style can drive both tab buttons. -->
<Style x:Key="TabButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="#9A9CA3"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Padding" Value="14,6"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}" CornerRadius="6" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#2B2D31"/>
</Trigger>
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#3A3D42"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Shared by the favourites row and the main grid so both behave identically.
No fixed Width: the tile stretches to fill its UniformGrid cell, so a row always
spans the full panel width instead of leaving a ragged gap on the right. -->
<DataTemplate x:Key="MemeTileTemplate" DataType="{x:Type vm:MemeTileViewModel}">
<Grid Height="118" Margin="4">
<Button Padding="0"
Style="{StaticResource FlatButtonStyle}"
Command="{Binding DataContext.SelectItemCommand, ElementName=RootWindow}"
CommandParameter="{Binding}"
Tag="{Binding DataContext, ElementName=RootWindow}"
ToolTip="{Binding DisplayName}">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding PlacementTarget.DataContext.FavoriteActionLabel, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
Command="{Binding PlacementTarget.Tag.ToggleFavoriteCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
<Separator/>
<MenuItem Header="Remove"
IsEnabled="{Binding PlacementTarget.DataContext.IsLocal, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
Command="{Binding PlacementTarget.Tag.RemoveItemCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</Button.ContextMenu>
<Image Source="{Binding Thumbnail}" Stretch="Uniform" Margin="5"/>
</Button>
<!-- Star overlay: marks favourites at a glance without needing a second grid. -->
<TextBlock Text="★" FontSize="13" Foreground="#FFC72C"
HorizontalAlignment="Right" VerticalAlignment="Top"
Margin="0,4,6,0" IsHitTestVisible="False"
Visibility="{Binding IsFavorite, Converter={StaticResource BoolToVisibility}}"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Border Background="#F0202225" CornerRadius="10" BorderBrush="#3A3B3E" BorderThickness="1">
<Grid Margin="12,8,12,12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Title bar: doubles as the drag surface. -->
<Border Grid.Row="0" Background="Transparent" Cursor="SizeAll" Height="26"
MouseLeftButtonDown="DragHandle_OnMouseLeftButtonDown"
ToolTip="Drag to move">
<Grid>
<TextBlock Text="Meme Clipboard" Foreground="White" FontSize="13"
FontWeight="SemiBold" VerticalAlignment="Center"
HorizontalAlignment="Left"/>
<Border Width="36" Height="4" CornerRadius="2" Background="#4A4C52"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,4,0,8">
<Button Content="Local"
Style="{StaticResource TabButtonStyle}"
Tag="{Binding IsLocalSource}"
Command="{Binding SelectSourceCommand}"
CommandParameter="{x:Static models:MemeSource.Local}"/>
<Button Content="Giphy" Margin="6,0,0,0"
Style="{StaticResource TabButtonStyle}"
Tag="{Binding IsGiphySource}"
Command="{Binding SelectSourceCommand}"
CommandParameter="{x:Static models:MemeSource.Giphy}"/>
</StackPanel>
<Grid Grid.Row="2" Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="#2B2D31" CornerRadius="8">
<Grid>
<TextBox x:Name="SearchBox"
Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}"
Background="Transparent" Foreground="White" BorderThickness="0"
Padding="10,7" FontSize="14"
CaretBrush="White"/>
<!-- WPF has no native placeholder, so this sits behind the caret and
hides as soon as anything is typed. Not hit-testable, so clicking
it still focuses the box underneath. -->
<TextBlock Text="{Binding SearchPlaceholder}"
Foreground="#6E7078" FontSize="14"
Margin="11,0,10,0" VerticalAlignment="Center"
IsHitTestVisible="False"
TextTrimming="CharacterEllipsis">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SearchText}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<Button Grid.Column="1" Content="+" Width="36" Height="36" Margin="8,0,0,0"
FontSize="18" Style="{StaticResource FlatButtonStyle}"
Command="{Binding ImportFilesCommand}"
Visibility="{Binding IsLocalSource, Converter={StaticResource BoolToVisibility}}"
ToolTip="Add memes"/>
</Grid>
<ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto" Padding="0,0,4,0"
ScrollChanged="ResultsScrollViewer_OnScrollChanged">
<StackPanel>
<!-- Favourites for the active source. Scrolls with the content rather than
being pinned, so it doesn't permanently eat height in a 520px window. -->
<StackPanel Visibility="{Binding HasFavorites, Converter={StaticResource BoolToVisibility}}">
<TextBlock Text="★ Favourites" Foreground="#9A9CA3" FontSize="11"
FontWeight="SemiBold" Margin="4,0,0,4"/>
<ItemsControl ItemsSource="{Binding Favorites}"
ItemTemplate="{StaticResource MemeTileTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Border Height="1" Background="#3A3B3E" Margin="4,10,4,10"/>
</StackPanel>
<Grid>
<TextBlock Text="No memes yet. Click +, drag files in, or paste with Ctrl+V."
Foreground="#7B7D85" FontSize="13"
HorizontalAlignment="Center" VerticalAlignment="Center"
TextWrapping="Wrap" TextAlignment="Center" Width="260"
Margin="0,40,0,0">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Items.Count}" Value="0"/>
<Condition Binding="{Binding IsLocalSource}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ItemsControl ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource MemeTileTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</StackPanel>
</ScrollViewer>
<Grid Grid.Row="4" Margin="2,8,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding StatusMessage}" Foreground="#9A9CA3"
FontSize="11" TextTrimming="CharacterEllipsis" VerticalAlignment="Center"/>
<!-- Required by Giphy's API terms wherever their results are displayed. -->
<TextBlock Grid.Column="1" Text="Powered by GIPHY" Foreground="#7B7D85"
FontSize="10" FontWeight="SemiBold" VerticalAlignment="Center"
Margin="8,0,0,0"
Visibility="{Binding IsGiphySource, Converter={StaticResource BoolToVisibility}}"/>
</Grid>
</Grid>
</Border>
</Window>