1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2007 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //	Chris Toshok (toshok@novell.com)
24 //
25 
26 using System;
27 using System.ComponentModel;
28 using System.Globalization;
29 using System.Windows.Converters;
30 using System.Windows.Markup;
31 
32 namespace System.Windows {
33 
34 	[Serializable]
35 	[ValueSerializer (typeof (SizeValueSerializer))]
36 	[TypeConverter (typeof (SizeConverter))]
37 	public struct Size : IFormattable
38 	{
SizeSystem.Windows.Size39 		public Size (double width, double height)
40 		{
41 			if (width < 0 || height < 0)
42 				throw new ArgumentException ("Width and Height must be non-negative.");
43 
44 			this._width = width;
45 			this._height = height;
46 		}
47 
EqualsSystem.Windows.Size48 		public bool Equals (Size value)
49 		{
50 			return _width == value.Width && _height == value.Height;
51 		}
52 
EqualsSystem.Windows.Size53 		public override bool Equals (object o)
54 		{
55 			if (!(o is Size))
56 				return false;
57 
58 			return Equals ((Size)o);
59 		}
60 
EqualsSystem.Windows.Size61 		public static bool Equals (Size size1, Size size2)
62 		{
63 			return size1.Equals (size2);
64 		}
65 
GetHashCodeSystem.Windows.Size66 		public override int GetHashCode ()
67 		{
68 			unchecked
69 			{
70 				return (_width.GetHashCode () * 397) ^ _height.GetHashCode ();
71 			}
72 		}
73 
ParseSystem.Windows.Size74 		public static Size Parse (string source)
75 		{
76 			if (source == null)
77 				throw new ArgumentNullException ("source");
78 			Size value;
79 			if (source.Trim () == "Empty")
80 			{
81 				return Empty;
82 			}
83 			var tokenizer = new NumericListTokenizer (source, CultureInfo.InvariantCulture);
84 			double width;
85 			double height;
86 			if (!double.TryParse (tokenizer.GetNextToken (), NumberStyles.Float, CultureInfo.InvariantCulture, out width) ||
87 			    !double.TryParse (tokenizer.GetNextToken (), NumberStyles.Float, CultureInfo.InvariantCulture, out height))
88 			{
89 				throw new FormatException (string.Format ("Invalid Size format: {0}", source));
90 			}
91 			if (!tokenizer.HasNoMoreTokens ())
92 			{
93 				throw new InvalidOperationException ("Invalid Size format: " + source);
94 			}
95 			return new Size(width, height);
96 		}
97 
ToStringSystem.Windows.Size98 		public override string ToString ()
99 		{
100 			return ConvertToString (null, null);
101 		}
102 
ToStringSystem.Windows.Size103 		public string ToString (IFormatProvider provider)
104 		{
105 			return ConvertToString (null, provider);
106 		}
107 
IFormattable.ToStringSystem.Windows.Size108 		string IFormattable.ToString (string format, IFormatProvider provider)
109 		{
110 			return ConvertToString (format, provider);
111 		}
112 
ConvertToStringSystem.Windows.Size113 		private string ConvertToString (string format, IFormatProvider provider)
114 		{
115 			if (IsEmpty)
116 				return "Empty";
117 
118 			if (provider == null)
119 				provider = CultureInfo.CurrentCulture;
120 			if (format == null)
121 				format = string.Empty;
122 			var separator = NumericListTokenizer.GetSeparator (provider);
123 			var vectorFormat  = string.Format ("{{0:{0}}}{1}{{1:{0}}}", format, separator);
124 			return string.Format (provider, vectorFormat, _width, _height);
125 		}
126 
127 		public bool IsEmpty {
128 			get {
129 				return (_width == Double.NegativeInfinity &&
130 					_height == Double.NegativeInfinity);
131 			}
132 		}
133 
134 		public double Height {
135 			get { return _height; }
136 			set {
137 				if (IsEmpty)
138 					throw new InvalidOperationException ("Cannot modify this property on the Empty Size.");
139 
140 				if (value < 0)
141 					throw new ArgumentException ("height must be non-negative.");
142 
143 				_height = value;
144 			}
145 		}
146 
147 		public double Width {
148 			get { return _width; }
149 			set {
150 				if (IsEmpty)
151 					throw new InvalidOperationException ("Cannot modify this property on the Empty Size.");
152 
153 				if (value < 0)
154 					throw new ArgumentException ("width must be non-negative.");
155 
156 				_width = value;
157 			}
158 		}
159 
160 		public static Size Empty {
161 			get {
162 				Size s = new Size ();
163 				s._width = s._height = Double.NegativeInfinity;
164 				return s;
165 			}
166 		}
167 
168 		/* operators */
operator PointSystem.Windows.Size169 		public static explicit operator Point (Size size)
170 		{
171 			return new Point (size.Width, size.Height);
172 		}
173 
operator VectorSystem.Windows.Size174 		public static explicit operator Vector (Size size)
175 		{
176 			return new Vector (size.Width, size.Height);
177 		}
178 
operator ==System.Windows.Size179 		public static bool operator ==(Size size1, Size size2)
180 		{
181 			return size1.Equals (size2);
182 		}
183 
operator !=System.Windows.Size184 		public static bool operator !=(Size size1, Size size2)
185 		{
186 			return !size1.Equals (size2);
187 		}
188 
189 		double _width;
190 		double _height;
191 	}
192 }
193