summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Tizen/Native/Image.cs
blob: 5b64c4357e7bfe8af2a4054f92159dba3c9eee62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using System.Threading.Tasks;
using ElmSharp;
using EImage = ElmSharp.Image;
using ESize = ElmSharp.Size;
using EColor = ElmSharp.Color;

namespace Xamarin.Forms.Platform.Tizen.Native
{
	/// <summary>
	/// Extends the ElmSharp.Image class with functionality useful to renderer.
	/// </summary>
	public class Image : EImage, IMeasurable
	{
		Aspect _aspect;
		bool _imageLoadCompleted;

		/// <summary>
		/// Initializes a new instance of the <see cref="Xamarin.Forms.Platform.Tizen.Native.Image"/> class.
		/// </summary>
		/// <param name="parent">The parent EvasObject.</param>
		public Image(EvasObject parent) : base(parent)
		{
			IsScaling = true;
			CanScaleUp = true;
			CanScaleDown = true;

			ApplyAspect(Aspect.AspectFit);
		}

		/// <summary>
		/// Gets or sets the image aspect ratio preserving option.
		/// </summary>
		/// <value>The aspect option.</value>
		public Aspect Aspect
		{
			get
			{
				return _aspect;
			}

			set
			{
				if (_aspect != value)
				{
					ApplyAspect(value);
				}
			}
		}

		/// <summary>
		/// Gets or sets the image color.
		/// </summary>
		public override EColor Color
		{
			get
			{
				return base.Color;
			}
			set
			{
				if (_imageLoadCompleted)
				{
					base.Color = value;
				}
			}
		}

		/// <summary>
		/// Loads image data from the given <see cref="Xamarin.Forms.ImageSource"/> asynchronously.
		/// </summary>
		/// <returns>A task which will be completed when image data is loaded.</returns>
		/// <param name="source">Image source specifying from where the image data has to be loaded.</param>
		public async Task<bool> LoadFromImageSourceAsync(ImageSource source)
		{
			IImageSourceHandler handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType());

			_imageLoadCompleted = false;

			if (source != null && handler != null)
			{
				_imageLoadCompleted = await handler.LoadImageAsync(this, source);
			}
			return _imageLoadCompleted;
		}

		/// <summary>
		/// Implements the <see cref="Xamarin.Forms.Platform.Tizen.Native.IMeasurable"/> interface.
		/// </summary>
		/// <param name="availableWidth">Available width.</param>
		/// <param name="availableHeight">Available height.</param>
		public ESize Measure(int availableWidth, int availableHeight)
		{
			var imageSize = ObjectSize;

			var size = new ESize()
			{
				Width = imageSize.Width,
				Height = imageSize.Height,
			};

			if (0 != availableWidth && 0 != availableHeight
				&& (imageSize.Width > availableWidth || imageSize.Height > availableHeight))
			{
				// when available size is limited and insufficient for the image ...
				double imageRatio = (double)imageSize.Width / (double)imageSize.Height;
				double availableRatio = (double)availableWidth / (double)availableHeight;
				// depending on the relation between availableRatio and imageRatio, copy the availableWidth or availableHeight
				// and calculate the size which preserves the image ratio, but does not exceed the available size
				size.Width = availableRatio > imageRatio ? imageSize.Width * availableHeight / imageSize.Height : availableWidth;
				size.Height = availableRatio > imageRatio ? availableHeight : imageSize.Height * availableWidth / imageSize.Width;
			}

			return size;
		}

		/// <summary>
		/// Sets the <c>IsFixedAspect</c> and <c>CanFillOutside</c> properties according to the given <paramref name="aspect"/>.
		/// </summary>
		/// <param name="aspect">The aspect setting to be applied to the image.</param>
		void ApplyAspect(Aspect aspect)
		{
			_aspect = aspect;

			switch (_aspect)
			{
				case Aspect.AspectFit:
					IsFixedAspect = true;
					CanFillOutside = false;
					break;

				case Aspect.AspectFill:
					IsFixedAspect = true;
					CanFillOutside = true;
					break;

				case Aspect.Fill:
					IsFixedAspect = false;
					CanFillOutside = false;
					break;

				default:
					Log.Warn("Invalid Aspect value: {0}", _aspect);
					break;
			}
		}
	}
}