importing messaging-2008 branch to trunk.
[mono.git] / mcs / class / System.Drawing / System.Drawing.Drawing2D / LinearGradientBrush.jvm.cs
1 using System;
2 using java.awt;
3 using awt = java.awt;
4 using geom = java.awt.geom;
5 using image = java.awt.image;
6
7 namespace System.Drawing.Drawing2D {
8         /// <summary>
9         /// Summary description for LinearGradientBrush.
10         /// </summary>
11         public sealed class LinearGradientBrush : Brush {
12                 Blend _blend;
13                 bool _gammaCorrection;
14                 ColorBlend _interpolationColors;
15                 WrapMode _wrapmode;
16                 RectangleF _gradientRectangle;
17
18                 // gradient brush data
19                 float _x1 = 0;
20                 float _y1 = 0;
21
22                 float _x2 = 0;
23                 float _y2 = 0;
24
25                 Color _color1, _color2;
26                 bool _cyclic;
27
28                 #region NativeObject
29
30                 GradientPaint _nativeObject = null;
31                 protected override Paint NativeObject {
32                         get {
33                                 if ( _nativeObject == null )
34                                         _nativeObject = new GradientPaint(
35                                                 _x1, _y1,
36                                                 new java.awt.Color(_color1.R, _color1.G, _color1.B, _color1.A),
37                                                 _x2, _y2, 
38                                                 new java.awt.Color(_color2.R, _color2.G, _color2.B, _color2.A), _cyclic);
39
40                                 return _nativeObject;
41                         }
42                 }
43
44                 #endregion
45
46                 #region Initialization
47
48                 private void Init(float x1, float y1, Color color1, float x2, float y2, Color color2, bool cyclic) {
49                         _x1 = x1;
50                         _y1 = y1;
51                         _color1 = color1;
52
53                         _x2 = x2;
54                         _y2 = y2;
55                         _color2 = color2;
56
57                         _cyclic = cyclic;
58                         _nativeObject = null;
59                 }
60
61                 private void Init(float x1, float y1, Color color1, float x2, float y2, Color color2, float angle) {
62                         _gradientRectangle = new RectangleF(x1, y1, x2-x1, y2-y1);
63                         PointF [] points = GetMedianeEnclosingRect(x1, y1, x2, y2, angle);
64                         Init(points[0].X, points[0].Y, color1, points[1].X, points[1].Y, color2, false);
65                 }
66
67                 private void Init(float x1, float y1, Color color1, float x2, float y2, Color color2, LinearGradientMode linearGradientMode) {
68                         _gradientRectangle = new RectangleF(x1, y1, x2-x1, y2-y1);
69                         PointF [] points;
70
71                         switch (linearGradientMode) {
72                                 case LinearGradientMode.Horizontal :
73                                         Init(x1, y1, color1, x2, y1, color2, false);
74                                         break;
75
76                                 case LinearGradientMode.Vertical :
77                                         Init(x1, y1, color1, x1, y2, color2, false);
78                                         break;
79
80                                 case LinearGradientMode.BackwardDiagonal :
81                                         points = GetMedianeEnclosingRect(x1, y1, x2, y2, false);
82                                         Init(points[0].X, points[0].Y, color2, points[1].X, points[1].Y, color1, false);
83                                         break;
84
85                                 case LinearGradientMode.ForwardDiagonal :
86                                         points = GetMedianeEnclosingRect(x1, y1, x2, y2, true);
87                                         Init(points[0].X, points[0].Y, color1, points[1].X, points[1].Y, color2, false);
88                                         break;
89
90                                 default :
91                                         throw new ArgumentException("LinearGradientMode");
92                         }
93                 }
94
95                 #endregion
96
97                 #region Constructors
98
99                 private LinearGradientBrush (float x1, float y1, Color color1, float x2, float y2, Color color2, bool cyclic) {
100                         Init(x1, y1, color1, x2, y2, color2, cyclic);
101                 }
102
103                 internal LinearGradientBrush (float x1, float y1, Color color1, float x2, float y2, Color color2, LinearGradientMode mode) {
104                         Init(x1, y1, color1, x2, y2, color2, mode);
105                 }
106                 internal LinearGradientBrush (float x1, float y1, Color color1, float x2, float y2, Color color2) {
107                         Init(x1, y2, color1, x1, y2, color2, false);
108                 }
109                 public LinearGradientBrush (Point point1, Point point2, Color color1, Color color2) {
110                         _gradientRectangle = new RectangleF(point1.X, point1.Y, point2.X - point1.X, point2.Y - point2.Y);
111                         Init(point1.X, point1.Y, color1, point2.X, point2.Y, color2, false);
112                 }
113                 public LinearGradientBrush (PointF point1, PointF point2, Color color1, Color color2) { 
114                         _gradientRectangle = new RectangleF(point1.X, point1.Y, point2.X - point1.X, point2.Y - point2.Y);
115                         Init(point1.X, point1.Y, color1, point2.X, point2.Y, color2, false);
116                 }
117                 public LinearGradientBrush (Rectangle rect, Color color1, Color color2, LinearGradientMode linearGradientMode) {
118                         Init(rect.X, rect.Y, color1, rect.X + rect.Width, rect.Y + rect.Height, color2, linearGradientMode);
119                 }
120                 public LinearGradientBrush (RectangleF rect, Color color1, Color color2, LinearGradientMode linearGradientMode) {       
121                         Init(rect.X, rect.Y, color1, rect.X + rect.Width, rect.Y + rect.Height, color2, linearGradientMode);
122                 }
123                 public LinearGradientBrush (Rectangle rect, Color color1, Color color2, float angle) {
124                         Init(rect.X, rect.Y, color1, rect.X + rect.Width, rect.Y + rect.Height, color2, angle);
125                 }
126                 public LinearGradientBrush (RectangleF rect, Color color1, Color color2, float angle) {
127                         Init(rect.X, rect.Y, color1, rect.X + rect.Width, rect.Y + rect.Height, color2, angle);
128                 }
129                 public LinearGradientBrush (Rectangle rect, Color color1, Color color2, float angle, bool isAngleScaleable):
130                         this(rect, color1, color2, angle) {
131                 }
132                 public LinearGradientBrush (RectangleF rect, Color color1, Color color2, float angle, bool isAngleScaleable):
133                         this(rect, color1, color2, angle) {
134                 }
135                 #endregion
136
137                 #region GetMedianeEnclosingRect
138
139                 internal PointF [] GetMedianeEnclosingRect(float x1, float y1, float x2, float y2, float rotateAngle) {
140                         float width = x2 - x1;
141                         float height = y2 - y1;
142                         PointF rectCenter = new PointF(x1 + width/2, y1 + height/2);
143                         float gradLen = width * Math.Abs((float)Math.Cos(rotateAngle * Math.PI / 180)) + 
144                                 height * Math.Abs((float)Math.Sin(rotateAngle * Math.PI / 180));
145
146                         PointF [] points = new PointF []{       new PointF(rectCenter.X - gradLen/2, rectCenter.Y),
147                                                                                                 new PointF(rectCenter.X + gradLen/2, rectCenter.Y) };
148
149                         Matrix mx = new Matrix();
150                         mx.RotateAt((float)rotateAngle, rectCenter);
151                         mx.TransformPoints(points);
152                         return points;
153                 }
154                 internal PointF [] GetMedianeEnclosingRect(float x1, float y1, float x2, float y2, bool forwardDiagonal) {
155                         float width = x2 - x1;
156                         float height = y2 - y1;
157                         PointF rectCenter = new PointF(x1 + width/2, y1 + height/2);
158                         float rotateAngle = (float)Math.Atan2(width, height);
159                         float gradLen = width * (float)Math.Cos(rotateAngle);
160
161                         if (!forwardDiagonal)
162                                 rotateAngle = -rotateAngle;
163                         
164                         PointF [] points = new PointF []{       new PointF(rectCenter.X - gradLen, rectCenter.Y),
165                                                                                                 new PointF(rectCenter.X + gradLen, rectCenter.Y) };
166
167                         Matrix mx = new Matrix();
168                         mx.RotateAt((float)rotateAngle * (float)(180/Math.PI), rectCenter);
169                         mx.TransformPoints(points);
170                         return points;
171                 }
172
173                 #endregion
174
175                 #region Public Properties
176
177                 // FALLBACK: no functionality implemented for this property
178                 [MonoTODO]
179                 public Blend Blend {
180                         get {
181                                 return _blend;
182                         }
183                         set {
184                                 _blend = value;
185                         }
186                 }
187
188                 // FALLBACK: no functionality implemented for this property
189                 [MonoTODO]
190                 public bool GammaCorrection {
191                         get {
192                                 return _gammaCorrection;
193                         }
194                         set {
195                                 _gammaCorrection = value;
196                         }
197                 }
198
199                 // FALLBACK: functionality of two color gradient is implemented
200                 [MonoTODO]
201                 public ColorBlend InterpolationColors {
202                         get {
203                                 return _interpolationColors;
204                         }
205                         set {
206                                 if (value == null)
207                                         throw new ArgumentNullException("ColorBlend");
208
209                                 if ( (value.Colors == null) || (value.Colors.Length == 0) )
210                                         throw new ArgumentException("ColorBlend");
211
212                                 _interpolationColors = value;
213
214                                 _color1 = value.Colors[0];
215                                 _color2 = value.Colors[value.Colors.Length - 1];
216                                 _nativeObject = null;
217                         }
218                 }
219
220                 public Color [] LinearColors {
221                         get {
222                                 Color [] cl = new Color[2];
223                                 cl[0] = _color1;
224                                 cl[1] = _color2;
225                                 return cl;
226                         }
227                         set {
228                                 if (value == null)
229                                         throw new ArgumentNullException("colors");
230
231                                 _color1 = value[0];
232                                 _color2 = value[1];
233                                 _nativeObject = null;
234                         }
235                 }
236
237                 public RectangleF Rectangle {
238                         get {
239                                 return _gradientRectangle;
240                         }
241                 }
242
243                 public Matrix Transform {
244                         get { return BrushTransform; }
245                         set { BrushTransform = value; }
246                 }
247
248                 // FALLBACK: not functionality implemented for this property
249                 [MonoTODO]
250                 public WrapMode WrapMode {
251                         get {
252                                 return _wrapmode;
253                         }
254                         set {
255                                 _wrapmode = value;
256                         }
257                 }
258                 #endregion
259
260                 #region Public Methods
261
262                 public void MultiplyTransform (Matrix matrix) {
263                         BrushMultiplyTransform(matrix, MatrixOrder.Prepend);
264                 }
265
266                 public void MultiplyTransform (Matrix matrix, MatrixOrder order) {
267                         BrushMultiplyTransform(matrix, order);                  
268                 }
269
270                 public void ResetTransform () {
271                         BrushResetTransform();
272                 }
273
274                 public void RotateTransform (float angle) {
275                         BrushRotateTransform(angle, MatrixOrder.Prepend);
276                 }
277
278                 public void RotateTransform (float angle, MatrixOrder order) {
279                         BrushRotateTransform(angle, order);
280                 }
281
282                 public void ScaleTransform (float sx, float sy) {
283                         BrushScaleTransform(sx, sy, MatrixOrder.Prepend);
284                 }
285
286                 public void ScaleTransform (float sx, float sy, MatrixOrder order) {
287                         BrushScaleTransform(sx, sy, order);
288                 }
289
290                 public void SetBlendTriangularShape (float focus) {
291                         SetBlendTriangularShape (focus, 1.0F);
292                 }
293
294                 public void SetBlendTriangularShape (float focus, float scale) {
295                         _x2 = (_x1 + _x2) / 2;
296                         _y2 = (_y1 + _y2) / 2;
297                         _cyclic = true;
298                         _nativeObject = null;
299                 }
300
301                 public void SetSigmaBellShape (float focus) {
302                         SetSigmaBellShape (focus, 1.0F);
303                 }
304
305                 [MonoTODO]
306                 public void SetSigmaBellShape (float focus, float scale) {
307                         // FALLBACK: Triangle shape used
308                         SetBlendTriangularShape (focus, scale);
309                 }
310
311                 public void TranslateTransform (float dx, float dy) {
312                         BrushTranslateTransform (dx, dy);
313                 }
314
315                 public void TranslateTransform (float dx, float dy, MatrixOrder order) {
316                         BrushTranslateTransform(dx, dy, order);
317                 }
318
319                 public override object Clone () {
320                         LinearGradientBrush copy = (LinearGradientBrush)InternalClone();
321                         
322                         if (copy._nativeObject != null)
323                                 copy._nativeObject = null;
324
325                         if (_interpolationColors != null) {
326                                 copy._interpolationColors = new ColorBlend();
327                                 if (_interpolationColors.Colors != null)
328                                         copy._interpolationColors.Colors = (Color[])_interpolationColors.Colors.Clone();
329                                 if (_interpolationColors.Positions != null)
330                                         copy._interpolationColors.Positions = (float[])_interpolationColors.Positions.Clone();
331                         }
332
333                         if (_blend != null) {
334                                 copy._blend = new Blend();
335                                 if (_blend.Factors != null)
336                                         copy._blend.Factors = (float[])_blend.Factors.Clone();
337                                 if (_blend.Positions != null)
338                                         copy._blend.Positions = (float[])_blend.Positions.Clone();
339                         }
340
341                         copy.LinearColors = (Color[])LinearColors.Clone();
342                         return copy;
343                 }
344                 #endregion
345         }
346 }