Browse Source

Fix #2298: Allow to change the DecompilerTextView's font size through scrolling.

pull/2536/head
Siegfried Pammer 4 years ago
parent
commit
728d516a61
  1. 209
      ILSpy/Controls/CollapsiblePanel.cs
  2. 73
      ILSpy/Controls/ZoomButtons.cs
  3. 196
      ILSpy/Controls/ZoomScrollViewer.cs
  4. 128
      ILSpy/Controls/ZoomScrollViewer.xaml
  5. 65
      ILSpy/Images/ZoomIn.svg
  6. 27
      ILSpy/Images/ZoomIn.xaml
  7. 57
      ILSpy/Images/ZoomOut.svg
  8. 20
      ILSpy/Images/ZoomOut.xaml
  9. 35
      ILSpy/TextView/DecompilerTextView.xaml
  10. 38
      ILSpy/TextView/ZoomLevelToTextFormattingModeConverter.cs
  11. 1
      ILSpy/Themes/generic.xaml

209
ILSpy/Controls/CollapsiblePanel.cs

@ -0,0 +1,209 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Threading;
namespace ICSharpCode.ILSpy.Controls
{
/// <summary>
/// Allows animated collapsing of the content of this panel.
/// </summary>
public class CollapsiblePanel : ContentControl
{
static CollapsiblePanel()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CollapsiblePanel),
new FrameworkPropertyMetadata(typeof(CollapsiblePanel)));
FocusableProperty.OverrideMetadata(typeof(CollapsiblePanel),
new FrameworkPropertyMetadata(false));
}
public static readonly DependencyProperty IsCollapsedProperty = DependencyProperty.Register(
"IsCollapsed", typeof(bool), typeof(CollapsiblePanel),
new UIPropertyMetadata(false, new PropertyChangedCallback(OnIsCollapsedChanged)));
public bool IsCollapsed {
get { return (bool)GetValue(IsCollapsedProperty); }
set { SetValue(IsCollapsedProperty, value); }
}
public static readonly DependencyProperty CollapseOrientationProperty =
DependencyProperty.Register("CollapseOrientation", typeof(Orientation), typeof(CollapsiblePanel),
new FrameworkPropertyMetadata(Orientation.Vertical));
public Orientation CollapseOrientation {
get { return (Orientation)GetValue(CollapseOrientationProperty); }
set { SetValue(CollapseOrientationProperty, value); }
}
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
"Duration", typeof(TimeSpan), typeof(CollapsiblePanel),
new UIPropertyMetadata(TimeSpan.FromMilliseconds(250)));
/// <summary>
/// The duration in milliseconds of the animation.
/// </summary>
public TimeSpan Duration {
get { return (TimeSpan)GetValue(DurationProperty); }
set { SetValue(DurationProperty, value); }
}
protected internal static readonly DependencyProperty AnimationProgressProperty = DependencyProperty.Register(
"AnimationProgress", typeof(double), typeof(CollapsiblePanel),
new FrameworkPropertyMetadata(1.0));
/// <summary>
/// Value between 0 and 1 specifying how far the animation currently is.
/// </summary>
protected internal double AnimationProgress {
get { return (double)GetValue(AnimationProgressProperty); }
set { SetValue(AnimationProgressProperty, value); }
}
protected internal static readonly DependencyProperty AnimationProgressXProperty = DependencyProperty.Register(
"AnimationProgressX", typeof(double), typeof(CollapsiblePanel),
new FrameworkPropertyMetadata(1.0));
/// <summary>
/// Value between 0 and 1 specifying how far the animation currently is.
/// </summary>
protected internal double AnimationProgressX {
get { return (double)GetValue(AnimationProgressXProperty); }
set { SetValue(AnimationProgressXProperty, value); }
}
protected internal static readonly DependencyProperty AnimationProgressYProperty = DependencyProperty.Register(
"AnimationProgressY", typeof(double), typeof(CollapsiblePanel),
new FrameworkPropertyMetadata(1.0));
/// <summary>
/// Value between 0 and 1 specifying how far the animation currently is.
/// </summary>
protected internal double AnimationProgressY {
get { return (double)GetValue(AnimationProgressYProperty); }
set { SetValue(AnimationProgressYProperty, value); }
}
static void OnIsCollapsedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((CollapsiblePanel)d).SetupAnimation((bool)e.NewValue);
}
void SetupAnimation(bool isCollapsed)
{
if (this.IsLoaded)
{
// If the animation is already running, calculate remaining portion of the time
double currentProgress = AnimationProgress;
if (!isCollapsed)
{
currentProgress = 1.0 - currentProgress;
}
DoubleAnimation animation = new DoubleAnimation();
animation.To = isCollapsed ? 0.0 : 1.0;
animation.Duration = TimeSpan.FromSeconds(Duration.TotalSeconds * currentProgress);
animation.FillBehavior = FillBehavior.HoldEnd;
this.BeginAnimation(AnimationProgressProperty, animation);
if (CollapseOrientation == Orientation.Horizontal)
{
this.BeginAnimation(AnimationProgressXProperty, animation);
this.AnimationProgressY = 1.0;
}
else
{
this.AnimationProgressX = 1.0;
this.BeginAnimation(AnimationProgressYProperty, animation);
}
}
else
{
this.AnimationProgress = isCollapsed ? 0.0 : 1.0;
this.AnimationProgressX = (CollapseOrientation == Orientation.Horizontal) ? this.AnimationProgress : 1.0;
this.AnimationProgressY = (CollapseOrientation == Orientation.Vertical) ? this.AnimationProgress : 1.0;
}
}
}
sealed class CollapsiblePanelProgressToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is double)
return (double)value > 0 ? Visibility.Visible : Visibility.Collapsed;
else
return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class SelfCollapsingPanel : CollapsiblePanel
{
public static readonly DependencyProperty CanCollapseProperty =
DependencyProperty.Register("CanCollapse", typeof(bool), typeof(SelfCollapsingPanel),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnCanCollapseChanged)));
public bool CanCollapse {
get { return (bool)GetValue(CanCollapseProperty); }
set { SetValue(CanCollapseProperty, value); }
}
static void OnCanCollapseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SelfCollapsingPanel panel = (SelfCollapsingPanel)d;
if ((bool)e.NewValue)
{
if (!panel.HeldOpenByMouse)
panel.IsCollapsed = true;
}
else
{
panel.IsCollapsed = false;
}
}
bool HeldOpenByMouse {
get { return IsMouseOver || IsMouseCaptureWithin; }
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
if (CanCollapse && !HeldOpenByMouse)
IsCollapsed = true;
}
protected override void OnLostMouseCapture(MouseEventArgs e)
{
base.OnLostMouseCapture(e);
if (CanCollapse && !HeldOpenByMouse)
IsCollapsed = true;
}
}
}

73
ILSpy/Controls/ZoomButtons.cs

@ -0,0 +1,73 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace ICSharpCode.ILSpy.Controls
{
public class ZoomButtons : RangeBase
{
static ZoomButtons()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ZoomButtons),
new FrameworkPropertyMetadata(typeof(ZoomButtons)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var uxPlus = (ButtonBase)Template.FindName("uxPlus", this);
var uxMinus = (ButtonBase)Template.FindName("uxMinus", this);
var uxReset = (ButtonBase)Template.FindName("uxReset", this);
if (uxPlus != null)
uxPlus.Click += OnZoomInClick;
if (uxMinus != null)
uxMinus.Click += OnZoomOutClick;
if (uxReset != null)
uxReset.Click += OnResetClick;
}
const double ZoomFactor = 1.1;
void OnZoomInClick(object sender, EventArgs e)
{
SetCurrentValue(ValueProperty, ZoomScrollViewer.RoundToOneIfClose(this.Value * ZoomFactor));
}
void OnZoomOutClick(object sender, EventArgs e)
{
SetCurrentValue(ValueProperty, ZoomScrollViewer.RoundToOneIfClose(this.Value / ZoomFactor));
}
void OnResetClick(object sender, EventArgs e)
{
SetCurrentValue(ValueProperty, 1.0);
}
}
}

196
ILSpy/Controls/ZoomScrollViewer.cs

@ -0,0 +1,196 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace ICSharpCode.ILSpy.Controls
{
public class ZoomScrollViewer : ScrollViewer
{
static ZoomScrollViewer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ZoomScrollViewer),
new FrameworkPropertyMetadata(typeof(ZoomScrollViewer)));
}
public static readonly DependencyProperty CurrentZoomProperty =
DependencyProperty.Register("CurrentZoom", typeof(double), typeof(ZoomScrollViewer),
new FrameworkPropertyMetadata(1.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, CalculateZoomButtonCollapsed, CoerceZoom));
public double CurrentZoom {
get { return (double)GetValue(CurrentZoomProperty); }
set { SetValue(CurrentZoomProperty, value); }
}
static object CoerceZoom(DependencyObject d, object baseValue)
{
var zoom = (double)baseValue;
ZoomScrollViewer sv = (ZoomScrollViewer)d;
return Math.Max(sv.MinimumZoom, Math.Min(sv.MaximumZoom, zoom));
}
public static readonly DependencyProperty MinimumZoomProperty =
DependencyProperty.Register("MinimumZoom", typeof(double), typeof(ZoomScrollViewer),
new FrameworkPropertyMetadata(0.2));
public double MinimumZoom {
get { return (double)GetValue(MinimumZoomProperty); }
set { SetValue(MinimumZoomProperty, value); }
}
public static readonly DependencyProperty MaximumZoomProperty =
DependencyProperty.Register("MaximumZoom", typeof(double), typeof(ZoomScrollViewer),
new FrameworkPropertyMetadata(5.0));
public double MaximumZoom {
get { return (double)GetValue(MaximumZoomProperty); }
set { SetValue(MaximumZoomProperty, value); }
}
public static readonly DependencyProperty MouseWheelZoomProperty =
DependencyProperty.Register("MouseWheelZoom", typeof(bool), typeof(ZoomScrollViewer),
new FrameworkPropertyMetadata(true));
public bool MouseWheelZoom {
get { return (bool)GetValue(MouseWheelZoomProperty); }
set { SetValue(MouseWheelZoomProperty, value); }
}
public static readonly DependencyProperty AlwaysShowZoomButtonsProperty =
DependencyProperty.Register("AlwaysShowZoomButtons", typeof(bool), typeof(ZoomScrollViewer),
new FrameworkPropertyMetadata(false, CalculateZoomButtonCollapsed));
public bool AlwaysShowZoomButtons {
get { return (bool)GetValue(AlwaysShowZoomButtonsProperty); }
set { SetValue(AlwaysShowZoomButtonsProperty, value); }
}
static readonly DependencyPropertyKey ComputedZoomButtonCollapsedPropertyKey =
DependencyProperty.RegisterReadOnly("ComputedZoomButtonCollapsed", typeof(bool), typeof(ZoomScrollViewer),
new FrameworkPropertyMetadata(true));
public static readonly DependencyProperty ComputedZoomButtonCollapsedProperty = ComputedZoomButtonCollapsedPropertyKey.DependencyProperty;
public bool ComputedZoomButtonCollapsed {
get { return (bool)GetValue(ComputedZoomButtonCollapsedProperty); }
private set { SetValue(ComputedZoomButtonCollapsedPropertyKey, value); }
}
static void CalculateZoomButtonCollapsed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ZoomScrollViewer z = d as ZoomScrollViewer;
if (z != null)
z.ComputedZoomButtonCollapsed = (z.AlwaysShowZoomButtons == false) && (z.CurrentZoom == 1.0);
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
if (!e.Handled && Keyboard.Modifiers == ModifierKeys.Control && MouseWheelZoom)
{
double oldZoom = CurrentZoom;
double newZoom = RoundToOneIfClose(CurrentZoom * Math.Pow(1.001, e.Delta));
newZoom = Math.Max(this.MinimumZoom, Math.Min(this.MaximumZoom, newZoom));
// adjust scroll position so that mouse stays over the same virtual coordinate
ContentPresenter presenter = Template.FindName("PART_Presenter", this) as ContentPresenter;
Vector relMousePos;
if (presenter != null)
{
Point mousePos = e.GetPosition(presenter);
relMousePos = new Vector(mousePos.X / presenter.ActualWidth, mousePos.Y / presenter.ActualHeight);
}
else
{
relMousePos = new Vector(0.5, 0.5);
}
Point scrollOffset = new Point(this.HorizontalOffset, this.VerticalOffset);
Vector oldHalfViewport = new Vector(this.ViewportWidth / 2, this.ViewportHeight / 2);
Vector newHalfViewport = oldHalfViewport / newZoom * oldZoom;
Point oldCenter = scrollOffset + oldHalfViewport;
Point virtualMousePos = scrollOffset + new Vector(relMousePos.X * this.ViewportWidth, relMousePos.Y * this.ViewportHeight);
// As newCenter, we want to choose a point between oldCenter and virtualMousePos. The more we zoom in, the closer
// to virtualMousePos. We'll create the line x = oldCenter + lambda * (virtualMousePos-oldCenter).
// On this line, we need to choose lambda between -1 and 1:
// -1 = zoomed out completely
// 0 = zoom unchanged
// +1 = zoomed in completely
// But the zoom factor (newZoom/oldZoom) we have is in the range [0,+Infinity].
// Basically, I just played around until I found a function that maps this to [-1,1] and works well.
// "f" is squared because otherwise the mouse simply stays over virtualMousePos, but I wanted virtualMousePos
// to move towards the middle -> squaring f causes lambda to be closer to 1, giving virtualMousePos more weight
// then oldCenter.
double f = Math.Min(newZoom, oldZoom) / Math.Max(newZoom, oldZoom);
double lambda = 1 - f * f;
if (oldZoom > newZoom)
lambda = -lambda;
Debug.Print("old: " + oldZoom + ", new: " + newZoom);
Point newCenter = oldCenter + lambda * (virtualMousePos - oldCenter);
scrollOffset = newCenter - newHalfViewport;
SetCurrentValue(CurrentZoomProperty, newZoom);
this.ScrollToHorizontalOffset(scrollOffset.X);
this.ScrollToVerticalOffset(scrollOffset.Y);
e.Handled = true;
}
base.OnMouseWheel(e);
}
internal static double RoundToOneIfClose(double val)
{
if (Math.Abs(val - 1.0) < 0.001)
return 1.0;
else
return val;
}
}
sealed class IsNormalZoomConverter : IValueConverter
{
public static readonly IsNormalZoomConverter Instance = new IsNormalZoomConverter();
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (parameter is bool && (bool)parameter)
return true;
return ((double)value) == 1.0;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

128
ILSpy/Controls/ZoomScrollViewer.xaml

@ -0,0 +1,128 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:ICSharpCode.ILSpy.Controls">
<Style TargetType="{x:Type Controls:ZoomScrollViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ZoomScrollViewer}">
<Grid Background="{TemplateBinding Panel.Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Controls:SelfCollapsingPanel Grid.Column="0" Grid.Row="1" CollapseOrientation="Horizontal" CanCollapse="{Binding Path=ComputedZoomButtonCollapsed, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}">
<Controls:ZoomButtons x:Name="zoomButtons" Value="{Binding Path=CurrentZoom, RelativeSource={RelativeSource Mode=TemplatedParent}}" Minimum="{TemplateBinding MinimumZoom}" Maximum="{TemplateBinding MaximumZoom}" />
</Controls:SelfCollapsingPanel>
<Rectangle Grid.Column="2" Grid.Row="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
<ScrollContentPresenter Name="PART_Presenter" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Margin="{TemplateBinding Control.Padding}" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" CanContentScroll="{TemplateBinding ScrollViewer.CanContentScroll}">
<ScrollContentPresenter.LayoutTransform>
<ScaleTransform ScaleX="{Binding Path=CurrentZoom, RelativeSource={RelativeSource Mode=TemplatedParent}}" ScaleY="{Binding Path=CurrentZoom, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</ScrollContentPresenter.LayoutTransform>
</ScrollContentPresenter>
<ScrollBar Name="PART_VerticalScrollBar" Grid.Column="2" Grid.Row="0" Minimum="0" Maximum="{TemplateBinding ScrollableHeight}" ViewportSize="{TemplateBinding ViewportHeight}" Value="{TemplateBinding VerticalOffset}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar Name="PART_HorizontalScrollBar" Orientation="Horizontal" Grid.Column="1" Grid.Row="1" Minimum="0" Maximum="{TemplateBinding ScrollableWidth}" ViewportSize="{TemplateBinding ViewportWidth}" Value="{TemplateBinding HorizontalOffset}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Template for CollapsiblePanel -->
<Style TargetType="{x:Type Controls:CollapsiblePanel}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Controls:CollapsiblePanel">
<ControlTemplate.Resources>
<Controls:CollapsiblePanelProgressToVisibilityConverter x:Key="visibilityConverter"/>
</ControlTemplate.Resources>
<Border
BorderThickness="{TemplateBinding Border.BorderThickness}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
Name="PART_Border"
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=AnimationProgress, Converter={StaticResource visibilityConverter}}"
>
<Border.LayoutTransform>
<ScaleTransform ScaleX="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=AnimationProgressX}"
ScaleY="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=AnimationProgressY}"/>
</Border.LayoutTransform>
<ContentPresenter
Margin="{TemplateBinding Control.Padding}"
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ZoomButtonStyle"
TargetType="RepeatButton">
<Setter Property="Delay" Value="0" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Opacity" Value="0.5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<ContentPresenter />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="1" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Controls:ZoomButtons}">
<Setter Property="Minimum" Value="0.2"/>
<Setter Property="Maximum" Value="10"/>
<Setter Property="Value" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ZoomButtons}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel Orientation="Horizontal"
Background="#3000">
<RepeatButton x:Name="uxPlus"
Width="16" Height="16" Padding="0" BorderThickness="0"
Style="{StaticResource ZoomButtonStyle}">
<Image Source="{Controls:XamlResource Images/ZoomIn}"
Stretch="Uniform"/>
</RepeatButton>
<RepeatButton x:Name="uxMinus"
Width="16" Height="16" Padding="0" BorderThickness="0"
Style="{StaticResource ZoomButtonStyle}">
<Image Source="{Controls:XamlResource Images/ZoomOut}"
Stretch="Uniform" />
</RepeatButton>
<RepeatButton x:Name="uxReset"
Width="16" Height="16" Padding="0" BorderThickness="0"
Style="{StaticResource ZoomButtonStyle}">
<Border Background="#5000">
<TextBlock Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center">1</TextBlock>
</Border>
</RepeatButton>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

65
ILSpy/Images/ZoomIn.svg

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 16 16"
version="1.1"
id="svg8"
sodipodi:docname="ZoomIn.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs12" />
<sodipodi:namedview
id="namedview10"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="52"
inkscape:cx="8"
inkscape:cy="7.7211538"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="2552"
inkscape:window-y="605"
inkscape:window-maximized="1"
inkscape:current-layer="svg8" />
<style
id="style2">.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style>
<path
class="icon-canvas-transparent"
d="M16 16H0V0h16v16z"
id="canvas" />
<path
class="icon-vs-out"
d="M16 5.833a5.84 5.84 0 0 1-5.833 5.833 5.688 5.688 0 0 1-2.913-.8L2.56 15.559a1.494 1.494 0 0 1-2.121.002 1.501 1.501 0 0 1 0-2.121l4.694-4.695a5.69 5.69 0 0 1-.8-2.911C4.333 2.617 6.95 0 10.167 0S16 2.617 16 5.833z"
id="outline" />
<path
class="icon-vs-fg"
d="M14 5.833a3.837 3.837 0 0 1-3.833 3.833c-2.114 0-3.833-1.72-3.833-3.833S8.053 2 10.167 2A3.838 3.838 0 0 1 14 5.833z"
id="iconFg" />
<path
class="icon-vs-bg"
d="M10.167 1a4.84 4.84 0 0 0-4.834 4.833c0 1.152.422 2.197 1.097 3.028l-5.284 5.285a.5.5 0 0 0 .708.708l5.284-5.285c.832.676 1.877 1.098 3.029 1.098 2.665 0 4.833-2.168 4.833-4.833S12.832 1 10.167 1zm0 8.667c-2.114 0-3.833-1.72-3.833-3.833S8.053 2 10.167 2C12.28 2 14 3.72 14 5.833s-1.72 3.834-3.833 3.834z"
id="iconBg" />
<rect
style="fill:#424242;fill-opacity:1"
id="rect884"
width="4.6153846"
height="0.88461536"
x="7.8649998"
y="5.3461561" />
<rect
style="fill:#424242;fill-opacity:1"
id="rect4051"
width="4.6153846"
height="0.88461536"
x="3.4807715"
y="-10.615"
transform="rotate(90)" />
</svg>

27
ILSpy/Images/ZoomIn.xaml

@ -0,0 +1,27 @@
<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<DrawingGroup.Transform>
<TranslateTransform X="0" Y="10.615" />
</DrawingGroup.Transform>
<DrawingGroup.Children>
<GeometryDrawing Geometry="F1 M16,16z M0,0z M16,16L0,16 0,0 16,0 16,16z">
<GeometryDrawing.Brush>
<SolidColorBrush Color="#FFF6F6F6" Opacity="0" />
</GeometryDrawing.Brush>
</GeometryDrawing>
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1 M16,16z M0,0z M16,5.833A5.84,5.84,0,0,1,10.167,11.666A5.688,5.688,0,0,1,7.254,10.866L2.56,15.559A1.494,1.494,0,0,1,0.439,15.561A1.501,1.501,0,0,1,0.439,13.44L5.133,8.745A5.69,5.69,0,0,1,4.333,5.834C4.333,2.617 6.95,0 10.167,0 13.384,0 16,2.617 16,5.833z" />
<GeometryDrawing Brush="#FFF0EFF1" Geometry="F1 M16,16z M0,0z M14,5.833A3.837,3.837,0,0,1,10.167,9.666C8.053,9.666 6.334,7.946 6.334,5.833 6.334,3.72 8.053,2 10.167,2A3.838,3.838,0,0,1,14,5.833z" />
<GeometryDrawing Brush="#FF424242" Geometry="F1 M16,16z M0,0z M10.167,1A4.84,4.84,0,0,0,5.333,5.833C5.333,6.985,5.755,8.03,6.43,8.861L1.146,14.146A0.5,0.5,0,0,0,1.854,14.854L7.138,9.569C7.97,10.245 9.015,10.667 10.167,10.667 12.832,10.667 15,8.499 15,5.834 15,3.169 12.832,1 10.167,1z M10.167,9.667C8.053,9.667 6.334,7.947 6.334,5.834 6.334,3.721 8.053,2 10.167,2 12.28,2 14,3.72 14,5.833 14,7.946 12.28,9.667 10.167,9.667z" />
<GeometryDrawing Brush="#FF424242">
<GeometryDrawing.Geometry>
<RectangleGeometry RadiusX="0" RadiusY="0" Rect="7.865,5.3462,4.6154,0.8846" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<DrawingGroup Transform="6.12303176911189E-17,1,-1,6.12303176911189E-17,0,0">
<GeometryDrawing Brush="#FF424242">
<GeometryDrawing.Geometry>
<RectangleGeometry RadiusX="0" RadiusY="0" Rect="3.4808,-10.615,4.6154,0.8846" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingGroup.Children>
</DrawingGroup>

57
ILSpy/Images/ZoomOut.svg

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 16 16"
version="1.1"
id="svg8"
sodipodi:docname="ZoomOut.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs12" />
<sodipodi:namedview
id="namedview10"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="52"
inkscape:cx="8"
inkscape:cy="7.7211538"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="2552"
inkscape:window-y="605"
inkscape:window-maximized="1"
inkscape:current-layer="svg8" />
<style
id="style2">.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}.icon-vs-fg{fill:#f0eff1}</style>
<path
class="icon-canvas-transparent"
d="M16 16H0V0h16v16z"
id="canvas" />
<path
class="icon-vs-out"
d="M16 5.833a5.84 5.84 0 0 1-5.833 5.833 5.688 5.688 0 0 1-2.913-.8L2.56 15.559a1.494 1.494 0 0 1-2.121.002 1.501 1.501 0 0 1 0-2.121l4.694-4.695a5.69 5.69 0 0 1-.8-2.911C4.333 2.617 6.95 0 10.167 0S16 2.617 16 5.833z"
id="outline" />
<path
class="icon-vs-fg"
d="M14 5.833a3.837 3.837 0 0 1-3.833 3.833c-2.114 0-3.833-1.72-3.833-3.833S8.053 2 10.167 2A3.838 3.838 0 0 1 14 5.833z"
id="iconFg" />
<path
class="icon-vs-bg"
d="M10.167 1a4.84 4.84 0 0 0-4.834 4.833c0 1.152.422 2.197 1.097 3.028l-5.284 5.285a.5.5 0 0 0 .708.708l5.284-5.285c.832.676 1.877 1.098 3.029 1.098 2.665 0 4.833-2.168 4.833-4.833S12.832 1 10.167 1zm0 8.667c-2.114 0-3.833-1.72-3.833-3.833S8.053 2 10.167 2C12.28 2 14 3.72 14 5.833s-1.72 3.834-3.833 3.834z"
id="iconBg" />
<rect
style="fill:#424242;fill-opacity:1"
id="rect884"
width="4.6153846"
height="0.88461536"
x="7.8649998"
y="5.3461561" />
</svg>

20
ILSpy/Images/ZoomOut.xaml

@ -0,0 +1,20 @@
<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<DrawingGroup.Transform>
<TranslateTransform X="0" Y="10.615" />
</DrawingGroup.Transform>
<DrawingGroup.Children>
<GeometryDrawing Geometry="F1 M16,16z M0,0z M16,16L0,16 0,0 16,0 16,16z">
<GeometryDrawing.Brush>
<SolidColorBrush Color="#FFF6F6F6" Opacity="0" />
</GeometryDrawing.Brush>
</GeometryDrawing>
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1 M16,16z M0,0z M16,5.833A5.84,5.84,0,0,1,10.167,11.666A5.688,5.688,0,0,1,7.254,10.866L2.56,15.559A1.494,1.494,0,0,1,0.439,15.561A1.501,1.501,0,0,1,0.439,13.44L5.133,8.745A5.69,5.69,0,0,1,4.333,5.834C4.333,2.617 6.95,0 10.167,0 13.384,0 16,2.617 16,5.833z" />
<GeometryDrawing Brush="#FFF0EFF1" Geometry="F1 M16,16z M0,0z M14,5.833A3.837,3.837,0,0,1,10.167,9.666C8.053,9.666 6.334,7.946 6.334,5.833 6.334,3.72 8.053,2 10.167,2A3.838,3.838,0,0,1,14,5.833z" />
<GeometryDrawing Brush="#FF424242" Geometry="F1 M16,16z M0,0z M10.167,1A4.84,4.84,0,0,0,5.333,5.833C5.333,6.985,5.755,8.03,6.43,8.861L1.146,14.146A0.5,0.5,0,0,0,1.854,14.854L7.138,9.569C7.97,10.245 9.015,10.667 10.167,10.667 12.832,10.667 15,8.499 15,5.834 15,3.169 12.832,1 10.167,1z M10.167,9.667C8.053,9.667 6.334,7.947 6.334,5.834 6.334,3.721 8.053,2 10.167,2 12.28,2 14,3.72 14,5.833 14,7.946 12.28,9.667 10.167,9.667z" />
<GeometryDrawing Brush="#FF424242">
<GeometryDrawing.Geometry>
<RectangleGeometry RadiusX="0" RadiusY="0" Rect="7.865,5.3462,4.6154,0.8846" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup.Children>
</DrawingGroup>

35
ILSpy/TextView/DecompilerTextView.xaml

@ -2,9 +2,11 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
xmlns:ae="clr-namespace:ICSharpCode.AvalonEdit;assembly=ICSharpCode.AvalonEdit"
xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit"
xmlns:styles="urn:TomsToolbox.Wpf.Styles">
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:local="clr-namespace:ICSharpCode.ILSpy.TextView"
xmlns:ae="clr-namespace:ICSharpCode.AvalonEdit;assembly=ICSharpCode.AvalonEdit"
xmlns:folding="clr-namespace:ICSharpCode.AvalonEdit.Folding;assembly=ICSharpCode.AvalonEdit"
xmlns:styles="urn:TomsToolbox.Wpf.Styles">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="boolToVisibility" />
<SolidColorBrush x:Key="waitAdornerBackgoundBrush" Color="{DynamicResource {x:Static SystemColors.WindowColorKey}}" Opacity=".75"/>
@ -47,6 +49,33 @@
</Style.Triggers>
</Style>
</ae:TextEditor.Resources>
<ae:TextEditor.Template>
<ControlTemplate TargetType="{x:Type ae:TextEditor}">
<controls:ZoomScrollViewer
Focusable="False"
x:Name="PART_ScrollViewer"
MouseWheelZoom="True"
CanContentScroll="True"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Visible"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TextArea}"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Left"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
TextOptions.TextFormattingMode="{Binding CurrentZoom, ElementName=PART_ScrollViewer, Converter={x:Static local:ZoomLevelToTextFormattingModeConverter.Instance}}" />
<ControlTemplate.Triggers>
<Trigger Property="WordWrap"
Value="True">
<Setter TargetName="PART_ScrollViewer"
Property="HorizontalScrollBarVisibility"
Value="Disabled" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ae:TextEditor.Template>
</ae:TextEditor>
<Border Name="waitAdorner" Background="{StaticResource waitAdornerBackgoundBrush}" Visibility="Collapsed">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">

38
ILSpy/TextView/ZoomLevelToTextFormattingModeConverter.cs

@ -0,0 +1,38 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows.Data;
using System.Windows.Media;
namespace ICSharpCode.ILSpy.TextView
{
sealed class ZoomLevelToTextFormattingModeConverter : IValueConverter
{
public static readonly ZoomLevelToTextFormattingModeConverter Instance = new ZoomLevelToTextFormattingModeConverter();
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return ((double)value) == 1.0 ? TextFormattingMode.Display : (object)TextFormattingMode.Ideal;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

1
ILSpy/Themes/generic.xaml

@ -4,6 +4,7 @@
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Controls/SearchBoxStyle.xaml" />
<ResourceDictionary Source="../Controls/ZoomScrollViewer.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- SortableGridViewColumn.

Loading…
Cancel
Save