refactor: replace all window with custom ChromelessWindow

This commit is contained in:
leo 2024-06-13 11:54:10 +08:00
parent 68061f82b1
commit f5b35d3db2
No known key found for this signature in database
GPG key ID: B528468E49CD0E58
23 changed files with 414 additions and 649 deletions

View file

@ -1,34 +0,0 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data.Converters;
namespace SourceGit.Converters
{
public static class WindowStateConverters
{
public static readonly FuncValueConverter<WindowState, Thickness> ToContentMargin =
new FuncValueConverter<WindowState, Thickness>(state =>
{
if (OperatingSystem.IsWindows() && state == WindowState.Maximized)
return new Thickness(6);
else if (OperatingSystem.IsLinux() && state != WindowState.Maximized)
return new Thickness(6);
else
return new Thickness(0);
});
public static readonly FuncValueConverter<WindowState, GridLength> ToTitleBarHeight =
new FuncValueConverter<WindowState, GridLength>(state =>
{
if (state == WindowState.Maximized)
return new GridLength(OperatingSystem.IsMacOS() ? 34 : 30);
else
return new GridLength(38);
});
public static readonly FuncValueConverter<WindowState, bool> IsNormal =
new FuncValueConverter<WindowState, bool>(state => state == WindowState.Normal);
}
}

View file

@ -18,6 +18,129 @@
<Setter Property="HideDelay" Value="0:0:0.2"/>
</Style>
<Style Selector="Window">
<Setter Property="Background" Value="{DynamicResource Brush.Window}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/>
<Setter Property="ExtendClientAreaChromeHints" Value="NoChrome"/>
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True"/>
<Setter Property="SystemDecorations" Value="Full"/>
<Setter Property="Padding" Value="0"/>
</Style>
<Style Selector="Window[WindowState=Maximized]">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="6"/>
</Style>
<Style Selector="Window.custom_window_frame">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="ExtendClientAreaChromeHints" Value="Default"/>
<Setter Property="ExtendClientAreaToDecorationsHint" Value="False"/>
<Setter Property="SystemDecorations" Value="None"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="Template">
<ControlTemplate>
<Grid>
<Border x:Name="PART_ContentRoot"
Background="{DynamicResource Brush.Window}"
BorderBrush="{DynamicResource Brush.Border0}"
BorderThickness="1"
Margin="{TemplateBinding Padding}"
CornerRadius="8"
Effect="drop-shadow(0 0 12 #90000000)"
ClipToBounds="True">
<VisualLayerManager>
<ContentPresenter Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</VisualLayerManager>
</Border>
<Grid x:Name="PART_ResizeBorderContainer" Margin="{TemplateBinding Padding}" IsHitTestVisible="True">
<Border x:Name="PART_BorderTopLeft"
Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Top"
Cursor="TopLeftCorner"
Tag="{x:Static WindowEdge.NorthWest}"/>
<Border x:Name="PART_BorderTop"
Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Top"
Cursor="TopSide"
Tag="{x:Static WindowEdge.North}"/>
<Border x:Name="PART_BorderTopRight"
Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Top"
Cursor="TopRightCorner"
Tag="{x:Static WindowEdge.NorthEast}"/>
<Border x:Name="PART_BorderLeft"
Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Cursor="LeftSide"
Tag="{x:Static WindowEdge.West}"/>
<Border x:Name="PART_BorderRight"
Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Stretch"
Cursor="RightSide"
Tag="{x:Static WindowEdge.East}"/>
<Border x:Name="PART_BorderBottomLeft"
Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Bottom"
Cursor="BottomLeftCorner"
Tag="{x:Static WindowEdge.SouthWest}"/>
<Border x:Name="PART_BorderBottom"
Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
Cursor="BottomSide"
Tag="{x:Static WindowEdge.South}"/>
<Border x:Name="PART_BorderBottomRight"
Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Cursor="BottomRightCorner"
Tag="{x:Static WindowEdge.SouthEast}"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="Window.custom_window_frame[WindowState=Maximized]">
<Setter Property="Padding" Value="0"/>
</Style>
<Style Selector="Window.custom_window_frame[WindowState=Maximized] /template/ Border#PART_ContentRoot">
<Setter Property="BorderThickness" Value="0"/>
</Style>
<Style Selector="Window.custom_window_frame[WindowState=Maximized] /template/ Grid#PART_ResizeBorderContainer">
<Setter Property="IsVisible" Value="False"/>
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
<Style Selector="Window.custom_window_frame[CanResize=False] /template/ Grid#PART_ResizeBorderContainer">
<Setter Property="IsVisible" Value="False"/>
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
<Style Selector="ContentPresenter">
<Setter Property="FontFamily" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFont}"/>
<Setter Property="FontSize" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize}"/>

View file

@ -1,4 +1,4 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -9,20 +9,10 @@
x:DataType="v:About"
Icon="/App.ico"
Title="{DynamicResource Text.About}"
Background="Transparent"
SizeToContent="WidthAndHeight"
CanResize="False"
WindowStartupLocation="CenterScreen"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid RowDefinitions="Auto,*" Margin="{OnPlatform 0, Linux=6}">
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="2"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Border Grid.Column="0" Grid.ColumnSpan="3"
@ -59,7 +49,7 @@
</Button>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="Auto,*" Background="{DynamicResource Brush.Window}">
<Grid Grid.Row="1" ColumnDefinitions="Auto,*">
<Image Grid.Column="0"
Width="200" Height="200"
Margin="8,0"
@ -100,4 +90,4 @@
</StackPanel>
</Grid>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -1,12 +1,11 @@
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
{
public partial class About : Window
public partial class About : ChromelessWindow
{
public string Version
{

View file

@ -1,4 +1,4 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -10,20 +10,10 @@
x:DataType="vm:AssumeUnchangedManager"
Icon="/App.ico"
Title="{DynamicResource Text.AssumeUnchanged}"
Background="Transparent"
Width="600" Height="400"
CanResize="False"
WindowStartupLocation="CenterOwner"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid RowDefinitions="Auto,*" Margin="{OnPlatform 0, Linux=6}">
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="2"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Border Grid.Column="0" Grid.ColumnSpan="3"
@ -61,7 +51,7 @@
</Grid>
<!-- Unchanged Files -->
<Grid Grid.Row="1" Background="{DynamicResource Brush.Window}">
<Grid Grid.Row="1">
<DataGrid Margin="8"
Background="{DynamicResource Brush.Contents}"
ItemsSource="{Binding Files}"
@ -110,4 +100,4 @@
</StackPanel>
</Grid>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -4,7 +4,7 @@ using Avalonia.Interactivity;
namespace SourceGit.Views
{
public partial class AssumeUnchangedManager : Window
public partial class AssumeUnchangedManager : ChromelessWindow
{
public AssumeUnchangedManager()
{

View file

@ -1,4 +1,4 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -12,25 +12,15 @@
x:DataType="vm:Blame"
Icon="/App.ico"
Title="{DynamicResource Text.Blame}"
Background="Transparent"
WindowStartupLocation="CenterOwner"
MinWidth="1280" MinHeight="720"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid Margin="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToContentMargin}}">
MinWidth="1280" MinHeight="720">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="24"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="3"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
<!-- Bottom border -->
@ -58,12 +48,12 @@
</Grid>
<!-- File -->
<Border Grid.Row="1" Padding="8,0" Background="{DynamicResource Brush.Window}">
<Border Grid.Row="1" Padding="8,0">
<TextBlock Text="{Binding Title}" VerticalAlignment="Center"/>
</Border>
<!-- Body -->
<Grid Grid.Row="2" Background="{DynamicResource Brush.Window}">
<Grid Grid.Row="2">
<!-- Blame View -->
<v:BlameTextEditor HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
@ -86,64 +76,5 @@
<!-- Loading -->
<v:LoadingIcon Width="48" Height="48" IsVisible="{Binding Data, Converter={x:Static ObjectConverters.IsNull}}"/>
</Grid>
<!-- Custom window sizer for Linux -->
<Grid Grid.Row="0" Grid.RowSpan="3" IsVisible="{OnPlatform False, Linux=True}" IsHitTestVisible="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.IsNormal}}">
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Top"
Cursor="TopLeftCorner"
Tag="{x:Static WindowEdge.NorthWest}"
PointerPressed="CustomResizeWindow"/>
<Border Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Top"
Cursor="TopSide"
Tag="{x:Static WindowEdge.North}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Top"
Cursor="TopRightCorner"
Tag="{x:Static WindowEdge.NorthEast}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Cursor="LeftSide"
Tag="{x:Static WindowEdge.West}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Stretch"
Cursor="RightSide"
Tag="{x:Static WindowEdge.East}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Bottom"
Cursor="BottomLeftCorner"
Tag="{x:Static WindowEdge.SouthWest}"
PointerPressed="CustomResizeWindow"/>
<Border Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
Cursor="BottomSide"
Tag="{x:Static WindowEdge.South}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Cursor="BottomRightCorner"
Tag="{x:Static WindowEdge.SouthEast}"
PointerPressed="CustomResizeWindow"/>
</Grid>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -319,7 +319,7 @@ namespace SourceGit.Views
private TextMate.Installation _textMate = null;
}
public partial class Blame : Window
public partial class Blame : ChromelessWindow
{
public Blame()
{
@ -334,25 +334,11 @@ namespace SourceGit.Views
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
}
else
{
WindowState = WindowState.Maximized;
}
e.Handled = true;
}
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
{
if (sender is Border border)
{
if (border.Tag is WindowEdge edge)
{
BeginResizeDrag(edge, e);
}
}
e.Handled = true;
}
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)

View file

@ -1,4 +1,4 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -12,25 +12,15 @@
x:Name="me"
Icon="/App.ico"
Title="{DynamicResource Text.BranchCompare}"
Background="Transparent"
WindowStartupLocation="CenterOwner"
MinWidth="1280" MinHeight="720"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid Margin="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToContentMargin}}">
WindowStartupLocation="CenterOwner">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="64"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="3"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
<!-- Bottom border -->
@ -58,7 +48,7 @@
</Grid>
<!-- Compare Targets -->
<Border Grid.Row="1" Background="{DynamicResource Brush.Window}">
<Border Grid.Row="1">
<Grid Margin="48,8,48,8" ColumnDefinitions="*,48,*">
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Grid RowDefinitions="Auto,*">
@ -103,7 +93,7 @@
</Border>
<!-- Changes -->
<Border Grid.Row="2" Background="{DynamicResource Brush.Window}">
<Border Grid.Row="2">
<Grid Margin="8,0,8,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="256" MinWidth="200" MaxWidth="480"/>
@ -177,64 +167,5 @@
</Grid>
</Grid>
</Border>
<!-- Custom window sizer for Linux -->
<Grid Grid.Row="0" Grid.RowSpan="3" IsVisible="{OnPlatform False, Linux=True}" IsHitTestVisible="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.IsNormal}}">
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Top"
Cursor="TopLeftCorner"
Tag="{x:Static WindowEdge.NorthWest}"
PointerPressed="CustomResizeWindow"/>
<Border Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Top"
Cursor="TopSide"
Tag="{x:Static WindowEdge.North}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Top"
Cursor="TopRightCorner"
Tag="{x:Static WindowEdge.NorthEast}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Cursor="LeftSide"
Tag="{x:Static WindowEdge.West}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Stretch"
Cursor="RightSide"
Tag="{x:Static WindowEdge.East}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Bottom"
Cursor="BottomLeftCorner"
Tag="{x:Static WindowEdge.SouthWest}"
PointerPressed="CustomResizeWindow"/>
<Border Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
Cursor="BottomSide"
Tag="{x:Static WindowEdge.South}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Cursor="BottomRightCorner"
Tag="{x:Static WindowEdge.SouthEast}"
PointerPressed="CustomResizeWindow"/>
</Grid>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -3,7 +3,7 @@ using Avalonia.Input;
namespace SourceGit.Views
{
public partial class BranchCompare : Window
public partial class BranchCompare : ChromelessWindow
{
public BranchCompare()
{
@ -20,17 +20,6 @@ namespace SourceGit.Views
e.Handled = true;
}
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
{
if (sender is Border border)
{
if (border.Tag is WindowEdge edge)
{
BeginResizeDrag(edge, e);
}
}
}
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
{
BeginMoveDrag(e);

View file

@ -0,0 +1,54 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
namespace SourceGit.Views
{
public class ChromelessWindow : Window
{
protected override Type StyleKeyOverride => typeof(Window);
public ChromelessWindow()
{
if (OperatingSystem.IsLinux())
Classes.Add("custom_window_frame");
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
if (Classes.Contains("custom_window_frame") && CanResize)
{
string[] borderNames = [
"PART_BorderTopLeft",
"PART_BorderTop",
"PART_BorderTopRight",
"PART_BorderLeft",
"PART_BorderRight",
"PART_BorderBottomLeft",
"PART_BorderBottom",
"PART_BorderBottomRight",
];
foreach (var name in borderNames)
{
var border = e.NameScope.Find<Border>(name);
if (border != null)
{
border.PointerPressed -= OnWindowBorderPointerPressed;
border.PointerPressed += OnWindowBorderPointerPressed;
}
}
}
}
private void OnWindowBorderPointerPressed(object sender, PointerPressedEventArgs e)
{
if (sender is Border border && border.Tag is WindowEdge edge)
BeginResizeDrag(edge, e);
}
}
}

View file

@ -1,4 +1,4 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -12,23 +12,13 @@
x:Name="me"
Icon="/App.ico"
Title="{DynamicResource Text.FileHistory}"
Background="Transparent"
MinWidth="1280" MinHeight="720"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid Margin="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToContentMargin}}">
MinWidth="1280" MinHeight="720">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="2"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
<!-- Bottom border -->
@ -56,7 +46,7 @@
</Grid>
<!-- Body -->
<Grid Grid.Row="1" Background="{DynamicResource Brush.Window}">
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" MinWidth="300" MaxWidth="600"/>
<ColumnDefinition Width="4"/>
@ -143,64 +133,5 @@
</Grid>
</Grid>
</Grid>
<!-- Custom window sizer for Linux -->
<Grid Grid.Row="0" Grid.RowSpan="2" IsVisible="{OnPlatform False, Linux=True}" IsHitTestVisible="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.IsNormal}}">
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Top"
Cursor="TopLeftCorner"
Tag="{x:Static WindowEdge.NorthWest}"
PointerPressed="CustomResizeWindow"/>
<Border Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Top"
Cursor="TopSide"
Tag="{x:Static WindowEdge.North}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Top"
Cursor="TopRightCorner"
Tag="{x:Static WindowEdge.NorthEast}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Cursor="LeftSide"
Tag="{x:Static WindowEdge.West}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Stretch"
Cursor="RightSide"
Tag="{x:Static WindowEdge.East}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Bottom"
Cursor="BottomLeftCorner"
Tag="{x:Static WindowEdge.SouthWest}"
PointerPressed="CustomResizeWindow"/>
<Border Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
Cursor="BottomSide"
Tag="{x:Static WindowEdge.South}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Cursor="BottomRightCorner"
Tag="{x:Static WindowEdge.SouthEast}"
PointerPressed="CustomResizeWindow"/>
</Grid>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -3,7 +3,7 @@ using Avalonia.Input;
namespace SourceGit.Views
{
public partial class FileHistories : Window
public partial class FileHistories : ChromelessWindow
{
public FileHistories()
{
@ -13,25 +13,11 @@ namespace SourceGit.Views
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
}
else
{
WindowState = WindowState.Maximized;
}
e.Handled = true;
}
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
{
if (sender is Border border)
{
if (border.Tag is WindowEdge edge)
{
BeginResizeDrag(edge, e);
}
}
e.Handled = true;
}
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)

View file

@ -1,27 +1,18 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:c="using:SourceGit.Converters"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.Hotkeys"
Icon="/App.ico"
Title="{DynamicResource Text.Hotkeys}"
Background="Transparent"
SizeToContent="WidthAndHeight"
CanResize="False"
WindowStartupLocation="CenterOwner"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid RowDefinitions="Auto,*" Margin="{OnPlatform 0, Linux=6}">
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="2"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Border Grid.Column="0" Grid.ColumnSpan="3"
@ -59,7 +50,7 @@
</Grid>
<!-- Body -->
<Border Grid.Row="1" Background="{DynamicResource Brush.Window}">
<Border Grid.Row="1">
<StackPanel Orientation="Vertical" Margin="16,8,16,16">
<TextBlock Text="{DynamicResource Text.Hotkeys.Global}"
Foreground="{DynamicResource Brush.FG2}"
@ -135,4 +126,4 @@
</StackPanel>
</Border>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -1,10 +1,9 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
{
public partial class Hotkeys : Window
public partial class Hotkeys : ChromelessWindow
{
public Hotkeys()
{

View file

@ -1,4 +1,4 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -13,38 +13,24 @@
x:Name="me"
Icon="/App.ico"
Title="SourceGit"
Background="Transparent"
MinWidth="1280" MinHeight="720"
Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.LauncherWidth, Mode=TwoWay}"
Height="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.LauncherHeight, Mode=TwoWay}"
WindowState="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.LauncherWindowState, Mode=TwoWay}"
WindowStartupLocation="CenterScreen"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Window.Resources>
<SolidColorBrush x:Key="SystemControlErrorTextForegroundBrush" Color="Red"/>
</Window.Resources>
<Grid Margin="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToContentMargin}}">
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToTitleBarHeight}}"/>
<RowDefinition Height="{Binding #me.TitleBarHeight}"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="2"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
<!-- Custom TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
<!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
DoubleTapped="MaximizeOrRestoreWindow"
DoubleTapped="OnTitleBarDoubleTapped"
PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) -->
@ -97,7 +83,7 @@
x:Name="launcherTabsScroller"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Disabled"
DoubleTapped="MaximizeOrRestoreWindow"
DoubleTapped="OnTitleBarDoubleTapped"
PointerPressed="BeginMoveWindow"
PointerWheelChanged="ScrollTabs"
ScrollChanged="OnTabsScrollChanged">
@ -366,64 +352,5 @@
</ItemsControl>
</ScrollViewer>
</Grid>
<!-- Custom window sizer for Linux -->
<Grid Grid.Row="0" Grid.RowSpan="2" IsVisible="{OnPlatform False, Linux=True}" IsHitTestVisible="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.IsNormal}}">
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Top"
Cursor="TopLeftCorner"
Tag="{x:Static WindowEdge.NorthWest}"
PointerPressed="CustomResizeWindow"/>
<Border Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Top"
Cursor="TopSide"
Tag="{x:Static WindowEdge.North}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Top"
Cursor="TopRightCorner"
Tag="{x:Static WindowEdge.NorthEast}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Stretch"
Cursor="LeftSide"
Tag="{x:Static WindowEdge.West}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Margin="0,4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Stretch"
Cursor="RightSide"
Tag="{x:Static WindowEdge.East}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Left" VerticalAlignment="Bottom"
Cursor="BottomLeftCorner"
Tag="{x:Static WindowEdge.SouthWest}"
PointerPressed="CustomResizeWindow"/>
<Border Height="4" Margin="4,0"
Background="Transparent"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
Cursor="BottomSide"
Tag="{x:Static WindowEdge.South}"
PointerPressed="CustomResizeWindow"/>
<Border Width="4" Height="4"
Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Cursor="BottomRightCorner"
Tag="{x:Static WindowEdge.SouthEast}"
PointerPressed="CustomResizeWindow"/>
</Grid>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -7,8 +7,17 @@ using Avalonia.Interactivity;
namespace SourceGit.Views
{
public partial class Launcher : Window, Models.INotificationReceiver
public partial class Launcher : ChromelessWindow, Models.INotificationReceiver
{
public static readonly StyledProperty<GridLength> TitleBarHeightProperty =
AvaloniaProperty.Register<Launcher, GridLength>(nameof(TitleBarHeight), new GridLength(38, GridUnitType.Pixel));
public GridLength TitleBarHeight
{
get => GetValue(TitleBarHeightProperty);
set => SetValue(TitleBarHeightProperty, value);
}
public Launcher()
{
DataContext = new ViewModels.Launcher();
@ -34,6 +43,20 @@ namespace SourceGit.Views
}
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == WindowStateProperty)
{
var state = (WindowState)change.NewValue;
if (state == WindowState.Maximized)
SetCurrentValue(TitleBarHeightProperty, new GridLength(OperatingSystem.IsMacOS() ? 34 : 30));
else
SetCurrentValue(TitleBarHeightProperty, new GridLength(38, GridUnitType.Pixel));
}
}
protected override void OnKeyDown(KeyEventArgs e)
{
var vm = DataContext as ViewModels.Launcher;
@ -136,37 +159,21 @@ namespace SourceGit.Views
base.OnClosing(e);
}
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
private void OnTitleBarDoubleTapped(object sender, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
}
else
{
WindowState = WindowState.Maximized;
}
e.Handled = true;
}
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
{
if (sender is Border border)
{
if (border.Tag is WindowEdge edge)
{
BeginResizeDrag(edge, e);
}
}
e.Handled = true;
}
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
{
if (e.ClickCount != 2)
{
BeginMoveDrag(e);
}
}
private void ScrollTabs(object sender, PointerWheelEventArgs e)
{

View file

@ -1,4 +1,4 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -14,20 +14,10 @@
x:Name="me"
Icon="/App.ico"
Title="{DynamicResource Text.Preference}"
Background="Transparent"
Width="600" SizeToContent="Height"
CanResize="False"
WindowStartupLocation="CenterScreen"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid RowDefinitions="Auto,Auto" Margin="{OnPlatform 0, Linux=6}">
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="2"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,Auto">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Border Grid.Column="0" Grid.ColumnSpan="3"
@ -62,7 +52,7 @@
</Grid>
<!-- Body -->
<Border Grid.Row="1" Background="{DynamicResource Brush.Window}">
<Border Grid.Row="1">
<TabControl>
<TabItem>
<TabItem.Header>
@ -553,4 +543,4 @@
</TabControl>
</Border>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -5,7 +5,6 @@ using System.Threading.Tasks;
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
@ -14,7 +13,7 @@ using Avalonia.Threading;
namespace SourceGit.Views
{
public partial class Preference : Window
public partial class Preference : ChromelessWindow
{
public AvaloniaList<FontFamily> InstalledFonts
{

View file

@ -1,29 +1,20 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.SelfUpdate"
x:DataType="vm:SelfUpdate"
Title="{DynamicResource Text.SelfUpdate.Title}"
Icon="/App.ico"
Background="Transparent"
SizeToContent="WidthAndHeight"
CanResize="False"
WindowStartupLocation="CenterOwner"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid RowDefinitions="Auto,*" Margin="{OnPlatform 0, Linux=6}">
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="2"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Border Grid.Column="0" Grid.ColumnSpan="3"
@ -61,7 +52,7 @@
</Grid>
<!-- Body -->
<Grid Grid.Row="1" Background="{DynamicResource Brush.Window}">
<Grid Grid.Row="1">
<ContentControl Content="{Binding Data}">
<ContentControl.DataTemplates>
<DataTemplate DataType="m:Version">
@ -150,4 +141,4 @@
</ContentControl>
</Grid>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -4,7 +4,7 @@ using Avalonia.Interactivity;
namespace SourceGit.Views
{
public partial class SelfUpdate : Window
public partial class SelfUpdate : ChromelessWindow
{
public SelfUpdate()
{

View file

@ -1,4 +1,4 @@
<Window xmlns="https://github.com/avaloniaui"
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -9,25 +9,10 @@
x:Class="SourceGit.Views.Statistics"
x:DataType="vm:Statistics"
Title="{DynamicResource Text.Statistics}"
Background="Transparent"
Width="800" Height="450"
WindowStartupLocation="CenterOwner"
CanResize="False"
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
SystemDecorations="{OnPlatform Full, Linux=None}">
<Grid RowDefinitions="Auto,Auto,*" Margin="{OnPlatform 0, Linux=6}">
<!-- Custom window shadow for Linux -->
<Border Grid.Row="0" Grid.RowSpan="3"
Background="{DynamicResource Brush.Window}"
Effect="drop-shadow(0 0 6 #A0000000)"
IsVisible="{OnPlatform False, Linux=True}"/>
<!-- Window BG -->
<Border Grid.Row="1" Grid.RowSpan="2"
Background="{DynamicResource Brush.Window}"
IsVisible="{OnPlatform True, Linux=False}"/>
CanResize="False">
<Grid RowDefinitions="Auto,Auto,*">
<!-- Title bar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Border Grid.Column="0" Grid.ColumnSpan="3"
@ -185,4 +170,4 @@
HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsLoading}"/>
</Grid>
</Window>
</v:ChromelessWindow>

View file

@ -226,7 +226,7 @@ namespace SourceGit.Views
private int _lastHitIdx = -1;
}
public partial class Statistics : Window
public partial class Statistics : ChromelessWindow
{
public Statistics()
{