1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 using System;
15 using System.Drawing;
16 using System.Drawing.Drawing2D;
17 using System.Windows.Forms;
18 
19 namespace Graphviz
20 {
21 	public partial class ScrollableImageControl : ScrollableControl
22 	{
23 		public Image Image
24 		{
25 			get
26 			{
27 				return _image;
28 			}
29 
30 			set
31 			{
32 				_image = value;
33 				UpdateAutoScroll();
34 			}
35 		}
36 
37 		public float Zoom
38 		{
39 			get
40 			{
41 				return _zoom;
42 			}
43 
44 			set
45 			{
46 				_zoom = value;
47 				UpdateAutoScroll();
48 			}
49 		}
50 
ScrollableImageControl()51 		public ScrollableImageControl()
52 		{
53 			InitializeComponent();
54 
55 			SetStyle(ControlStyles.AllPaintingInWmPaint |
56 				ControlStyles.DoubleBuffer |
57 				ControlStyles.ResizeRedraw |
58 				ControlStyles.UserMouse |
59 				ControlStyles.UserPaint,
60 				true);
61 			_image = null;
62 			_zoom = 1.0f;
63 			_lastScroll = new Point(0, 0);
64 		}
65 
ActualSize()66 		public void ActualSize()
67 		{
68 			Zoom = 1.0f;
69 		}
70 
ZoomToFit()71 		public void ZoomToFit()
72 		{
73 			Size imageSize = Image.Size;
74 			Size controlSize = Size;
75 			Zoom = Math.Min((float)controlSize.Width / (float)imageSize.Width, (float)controlSize.Height / (float)imageSize.Height);
76 		}
77 
ZoomIn()78 		public void ZoomIn()
79 		{
80 			Zoom *= _squareRootOfTwo;
81 		}
82 
ZoomOut()83 		public void ZoomOut()
84 		{
85 			Zoom /= _squareRootOfTwo;
86 		}
87 
OnMouseDown(MouseEventArgs e)88 		protected override void OnMouseDown(MouseEventArgs e)
89 		{
90 			/* if potentially panning with the mouse, record last scroll position */
91 			/* NOTE: Autoscroll should be set to +ve values but always returns -ve values */
92 			if (e.Button == MouseButtons.Left)
93 				_lastScroll = new Point(
94 					e.X - AutoScrollPosition.X,
95 					e.Y - AutoScrollPosition.Y);
96 			base.OnMouseDown(e);
97 		}
98 
OnMouseMove(MouseEventArgs e)99 		protected override void OnMouseMove(MouseEventArgs e)
100 		{
101 			/* if panning with the mouse, scroll to position */
102 			/* NOTE: Autoscroll should be set to +ve values but always returns -ve values */
103 			if (e.Button == MouseButtons.Left)
104 				AutoScrollPosition = new Point(
105 					_lastScroll.X - e.X,
106 					_lastScroll.Y - e.Y);
107 			base.OnMouseMove(e);
108 		}
109 
OnPaintBackground(PaintEventArgs e)110 		protected override void OnPaintBackground(PaintEventArgs e)
111 		{
112 			/* fill clip rectangle with background color */
113 			e.Graphics.FillRectangle(new SolidBrush(BackColor), e.ClipRectangle);
114 		}
115 
OnPaint(PaintEventArgs pe)116 		protected override void OnPaint(PaintEventArgs pe)
117 		{
118 			if (_image != null) {
119 				Matrix oldMatrix = pe.Graphics.Transform;
120 
121 				/* if the zoomed image size is smaller than the control size, center the display */
122 				/* adjust by the scroll position, then scale by the zoom factor */
123 				pe.Graphics.TranslateTransform(
124 					Math.Max((Width - _image.Width * _zoom) / 2.0f, 0.0f) + AutoScrollPosition.X,
125 					Math.Max((Height - _image.Height * _zoom) / 2.0f, 0.0f)	+ AutoScrollPosition.Y);
126 				pe.Graphics.ScaleTransform(_zoom, _zoom);
127 
128 				/* blit the image onto the graphics */
129 				pe.Graphics.DrawImage(_image, 0.0f, 0.0f);
130 
131 				pe.Graphics.Transform = oldMatrix;
132 			}
133 			base.OnPaint(pe);
134 
135 		}
136 
UpdateAutoScroll()137 		private void UpdateAutoScroll()
138 		{
139 			if (_image == null)
140 				AutoScrollMinSize = Size;
141 			else
142 				AutoScrollMinSize = new Size(
143 					(int)(_image.Width * _zoom + 0.5f),
144 					(int)(_image.Height * _zoom + 0.5f));
145 			Invalidate();
146 		}
147 
148 		private readonly float _squareRootOfTwo = (float)Math.Sqrt(2.0);
149 		private Image _image;
150 		private float _zoom;
151 		private Point _lastScroll;
152 	}
153 }
154