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