6 changed files with 212 additions and 3 deletions
@ -0,0 +1,155 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.ComponentModel; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Controls.Primitives; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Diagnostics; |
||||||
|
using ICSharpCode.WpfDesign.Designer.Controls; |
||||||
|
|
||||||
|
namespace ICSharpCode.WpfDesign.Designer.ThumbnailView |
||||||
|
{ |
||||||
|
public class ThumbnailView : Control, INotifyPropertyChanged |
||||||
|
{ |
||||||
|
public DesignSurface DesignSurface |
||||||
|
{ |
||||||
|
get { return (DesignSurface)GetValue(DesignSurfaceProperty); } |
||||||
|
set { SetValue(DesignSurfaceProperty, value); } |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly DependencyProperty DesignSurfaceProperty = |
||||||
|
DependencyProperty.Register("DesignSurface", typeof(DesignSurface), typeof(ThumbnailView), new PropertyMetadata(OnDesignSurfaceChanged)); |
||||||
|
|
||||||
|
private static void OnDesignSurfaceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
||||||
|
{ |
||||||
|
var ctl = d as ThumbnailView; |
||||||
|
|
||||||
|
|
||||||
|
if (ctl.oldSurface != null) |
||||||
|
ctl.oldSurface.LayoutUpdated -= ctl.DesignSurface_LayoutUpdated; |
||||||
|
|
||||||
|
ctl.oldSurface = ctl.DesignSurface; |
||||||
|
ctl.scrollViewer = null; |
||||||
|
|
||||||
|
if (ctl.DesignSurface != null) |
||||||
|
{ |
||||||
|
ctl.DesignSurface.LayoutUpdated += ctl.DesignSurface_LayoutUpdated; |
||||||
|
} |
||||||
|
|
||||||
|
ctl.OnPropertyChanged("ScrollViewer"); |
||||||
|
} |
||||||
|
|
||||||
|
static ThumbnailView() |
||||||
|
{ |
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(ThumbnailView), new FrameworkPropertyMetadata(typeof(ThumbnailView))); |
||||||
|
} |
||||||
|
|
||||||
|
public ScrollViewer ScrollViewer |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
if (DesignSurface != null && scrollViewer == null) |
||||||
|
scrollViewer = DesignSurface.TryFindChild<ZoomControl>(); |
||||||
|
|
||||||
|
return scrollViewer; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void DesignSurface_LayoutUpdated(object sender, EventArgs e) |
||||||
|
{ |
||||||
|
if (this.scrollViewer == null) |
||||||
|
OnPropertyChanged("ScrollViewer"); |
||||||
|
|
||||||
|
if (this.scrollViewer != null) |
||||||
|
{ |
||||||
|
double scale, xOffset, yOffset; |
||||||
|
this.InvalidateScale(out scale, out xOffset, out yOffset); |
||||||
|
|
||||||
|
this.zoomThumb.Width = scrollViewer.ViewportWidth * scale; |
||||||
|
this.zoomThumb.Height = scrollViewer.ViewportHeight * scale; |
||||||
|
|
||||||
|
Canvas.SetLeft(this.zoomThumb, xOffset + this.ScrollViewer.HorizontalOffset*scale); |
||||||
|
Canvas.SetTop(this.zoomThumb, yOffset + this.ScrollViewer.VerticalOffset*scale); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private DesignSurface oldSurface; |
||||||
|
private ZoomControl scrollViewer; |
||||||
|
private Canvas zoomCanvas; |
||||||
|
private Thumb zoomThumb; |
||||||
|
|
||||||
|
public override void OnApplyTemplate() |
||||||
|
{ |
||||||
|
base.OnApplyTemplate(); |
||||||
|
|
||||||
|
this.zoomThumb = Template.FindName("PART_ZoomThumb", this) as Thumb; |
||||||
|
this.zoomCanvas = Template.FindName("PART_ZoomCanvas", this) as Canvas; |
||||||
|
|
||||||
|
this.zoomThumb.DragDelta += this.Thumb_DragDelta; |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void Thumb_DragDelta(object sender, DragDeltaEventArgs e) |
||||||
|
{ |
||||||
|
if (DesignSurface != null) |
||||||
|
{ |
||||||
|
if (scrollViewer != null) |
||||||
|
{ |
||||||
|
double scale, xOffset, yOffset; |
||||||
|
this.InvalidateScale(out scale, out xOffset, out yOffset); |
||||||
|
|
||||||
|
scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + e.HorizontalChange / scale); |
||||||
|
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + e.VerticalChange / scale); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void InvalidateScale(out double scale, out double xOffset, out double yOffset) |
||||||
|
{ |
||||||
|
var designedElement = this.DesignSurface.DesignContext.RootItem.Component as FrameworkElement; |
||||||
|
|
||||||
|
var fac1 = designedElement.ActualWidth / zoomCanvas.ActualWidth; |
||||||
|
var fac2 = designedElement.ActualHeight / zoomCanvas.ActualHeight; |
||||||
|
|
||||||
|
// zoom canvas size
|
||||||
|
double x = this.zoomCanvas.ActualWidth; |
||||||
|
double y = this.zoomCanvas.ActualHeight; |
||||||
|
|
||||||
|
if (fac1 < fac2) |
||||||
|
{ |
||||||
|
x = designedElement.ActualWidth / fac2; |
||||||
|
xOffset = (zoomCanvas.ActualWidth - x) / 2; |
||||||
|
yOffset = 0; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
y = designedElement.ActualHeight / fac1; |
||||||
|
xOffset = 0; |
||||||
|
yOffset = (zoomCanvas.ActualHeight - y) / 2; |
||||||
|
} |
||||||
|
|
||||||
|
double w = designedElement.ActualWidth; |
||||||
|
double h = designedElement.ActualHeight; |
||||||
|
|
||||||
|
double scaleX = x / w; |
||||||
|
double scaleY = y / h; |
||||||
|
|
||||||
|
scale = (scaleX < scaleY) ? scaleX : scaleY; |
||||||
|
|
||||||
|
xOffset += (x - scale * w) / 2; |
||||||
|
yOffset += (y - scale * h) / 2; |
||||||
|
} |
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged; |
||||||
|
protected virtual void OnPropertyChanged(string propertyName) |
||||||
|
{ |
||||||
|
PropertyChangedEventHandler handler = PropertyChanged; |
||||||
|
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
xmlns:thumbnailView="clr-namespace:ICSharpCode.WpfDesign.Designer.ThumbnailView"> |
||||||
|
|
||||||
|
<Style TargetType="{x:Type thumbnailView:ThumbnailView}"> |
||||||
|
<Setter Property="SnapsToDevicePixels" Value="true" /> |
||||||
|
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
||||||
|
<Setter Property="VerticalAlignment" Value="Stretch" /> |
||||||
|
<Setter Property="Padding" Value="5" /> |
||||||
|
<Setter Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate TargetType="{x:Type thumbnailView:ThumbnailView}"> |
||||||
|
<Border CornerRadius="1" |
||||||
|
ClipToBounds="True" |
||||||
|
BorderThickness="1" |
||||||
|
Background="#EEE" |
||||||
|
BorderBrush="DimGray"> |
||||||
|
<Grid> |
||||||
|
<Canvas Margin="{TemplateBinding Padding}" Name="PART_ZoomCanvas"> |
||||||
|
<Canvas.Background> |
||||||
|
<VisualBrush Stretch="Uniform" Visual="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ScrollViewer.Content}" /> |
||||||
|
</Canvas.Background> |
||||||
|
<Thumb Name="PART_ZoomThumb" Cursor="SizeAll"> |
||||||
|
<Thumb.Style> |
||||||
|
<Style TargetType="Thumb"> |
||||||
|
<Setter Property="Template"> |
||||||
|
<Setter.Value> |
||||||
|
<ControlTemplate TargetType="Thumb"> |
||||||
|
<Rectangle StrokeThickness="1" Stroke="Black" Fill="Transparent" /> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
</Thumb.Style> |
||||||
|
</Thumb> |
||||||
|
</Canvas> |
||||||
|
</Grid> |
||||||
|
</Border> |
||||||
|
</ControlTemplate> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
</ResourceDictionary> |
Loading…
Reference in new issue