2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 using System.Threading;
20 using System.Threading.Tasks;
25 /// The Image is a widget that allows one to load and display an image file on it,
26 /// be it from a disk file or from a memory region.
29 public class Image : Widget
31 bool _canScaleUp = true;
32 bool _canScaleDown = true;
34 Color _color = Color.Default;
37 /// Creates and initializes a new instance of Image class.
39 /// <param name="parent">The parent is a given container which will be attached by Image as a child. It's <see cref="EvasObject"/> type.</param>
40 public Image(EvasObject parent) : base(parent)
42 _clicked = new SmartEvent(this, "clicked");
43 _clicked.On += (s, e) => Clicked?.Invoke(this, EventArgs.Empty);
47 /// Clicked will be triggered when the image is clicked.
49 public event EventHandler Clicked;
52 /// LoadingCompleted will be triggered when the image is loaded completely.
54 public event EventHandler LoadingCompleted;
57 /// Clicked will be triggered when the image is fail to load.
59 public event EventHandler LoadingFailed;
62 /// Gets the file that is used as an image.
68 return Interop.Elementary.elm_image_file_get(RealHandle);
73 /// Sets or gets the smooth effect for an image.
79 return Interop.Elementary.elm_image_smooth_get(RealHandle);
83 Interop.Elementary.elm_image_smooth_set(RealHandle, value);
88 /// Sets or gets whether scaling is disabled on the object.
94 return !Interop.Elementary.elm_image_no_scale_get(RealHandle);
98 Interop.Elementary.elm_image_no_scale_set(RealHandle, !value);
103 /// Sets or gets whether the object is down resizeable.
105 public bool CanScaleDown
109 return _canScaleDown;
113 _canScaleDown = value;
114 Interop.Elementary.elm_image_resizable_set(RealHandle, _canScaleUp, _canScaleDown);
119 /// Sets or gets whether the object is up resizeable.
121 public bool CanScaleUp
130 Interop.Elementary.elm_image_resizable_set(RealHandle, _canScaleUp, _canScaleDown);
135 /// Sets or gets whether the image fills the entire object area, when keeping the aspect ratio.
137 public bool CanFillOutside
141 return Interop.Elementary.elm_image_fill_outside_get(RealHandle);
145 Interop.Elementary.elm_image_fill_outside_set(RealHandle, value);
150 /// Sets or gets the prescale size for the image.
152 public int PrescaleSize
156 return Interop.Elementary.elm_image_prescale_get(RealHandle);
160 Interop.Elementary.elm_image_prescale_set(RealHandle, value);
165 /// Sets or gets whether the original aspect ratio of the image should be kept on resize.
167 public bool IsFixedAspect
171 return Interop.Elementary.elm_image_aspect_fixed_get(RealHandle);
175 Interop.Elementary.elm_image_aspect_fixed_set(RealHandle, value);
180 /// Sets or gets whether an image object (which supports animation) is to animate itself.
182 public bool IsAnimated
186 return Interop.Elementary.elm_image_animated_get(RealHandle);
190 Interop.Elementary.elm_image_animated_set(RealHandle, value);
195 /// Gets whether an image object supports animation.
197 public bool IsAnimatedAvailable
201 return Interop.Elementary.elm_image_animated_available_get(RealHandle);
206 /// Sets or gets whether an image object is under animation.
209 /// An image object, even if it supports animation, will be displayed by default without animation.
210 /// To actually start playing any image object's animation, <see cref="IsAnimated"/> should be TRUE before setting this property true.
212 public bool IsAnimationPlaying
216 return Interop.Elementary.elm_image_animated_play_get(RealHandle);
220 Interop.Elementary.elm_image_animated_play_set(RealHandle, value);
225 /// Sets or gets whether the image is 'editable'.
227 public bool IsEditable
231 return Interop.Elementary.elm_image_editable_get(RealHandle);
235 Interop.Elementary.elm_image_editable_set(RealHandle, value);
240 /// Gets the current size of the image.
242 public Size ObjectSize
246 Interop.Elementary.elm_image_object_size_get(RealHandle, out int w, out int h);
247 return new Size(w, h);
252 /// Sets or gets whether alpha channel data is being used on the given image object.
258 IntPtr evasObj = Interop.Elementary.elm_image_object_get(RealHandle);
259 if (evasObj != IntPtr.Zero)
261 return !Interop.Evas.evas_object_image_alpha_get(evasObj);
267 IntPtr evasObj = Interop.Elementary.elm_image_object_get(RealHandle);
268 if (evasObj != IntPtr.Zero)
270 Interop.Evas.evas_object_image_alpha_set(evasObj, !value);
276 /// Sets or gets the image orientation.
278 public ImageOrientation Orientation
282 return (ImageOrientation)Interop.Elementary.elm_image_orient_get(RealHandle);
286 Interop.Elementary.elm_image_orient_set(RealHandle, (int)value);
291 /// Sets or gets the image color
293 public override Color Color
301 IntPtr evasObj = Interop.Elementary.elm_image_object_get(RealHandle);
302 if (evasObj != IntPtr.Zero)
306 // Currently, we assume the Image.Color property as a blending color (actually, multiply blending).
307 // Thus we are using Color.White (255,255,255,255) as a default color to ensure original image color. (255/255 * original = original)
308 Interop.Evas.evas_object_color_set(evasObj, 255, 255, 255, 255);
312 Interop.Evas.SetPremultipliedColor(evasObj, value.R, value.G, value.B, value.A);
320 /// Sets the background color
322 public override Color BackgroundColor
328 SetPartColor("bg", Color.Transparent);
332 SetPartColor("bg", value);
334 _backgroundColor = value;
339 /// Sets the dimensions for an image object's border, a region which is not scaled together with its center ever.
341 /// <param name="left">The border's left width</param>
342 /// <param name="right">The border's right width</param>
343 /// <param name="top">The border's top width</param>
344 /// <param name="bottom">The border's bottom width</param>
345 public void SetBorder(int left, int right, int top, int bottom)
347 IntPtr evasObj = Interop.Elementary.elm_image_object_get(RealHandle);
348 Interop.Evas.evas_object_image_border_set(evasObj, left, right, top, bottom);
352 /// Sets or gets if the center part of the given image object (not the border) should be drawn.
355 /// When rendering, the image may be scaled to fit the size of the image object.
356 /// This function sets if the center part of the scaled image is to be drawn or left completely blank, or forced to be solid.
357 /// Very useful for frames and decorations.
359 public ImageBorderFillMode BorderCenterFillMode
363 IntPtr evasObj = Interop.Elementary.elm_image_object_get(RealHandle);
364 return (ImageBorderFillMode)Interop.Evas.evas_object_image_border_center_fill_get(evasObj);
368 IntPtr evasObj = Interop.Elementary.elm_image_object_get(RealHandle);
369 Interop.Evas.evas_object_image_border_center_fill_set(evasObj, (int)value);
374 /// Sets the file that is used as the image's source.
376 /// <param name="file">The path to the file that is used as an image source</param>
377 /// <returns>(true = success, false = error)</returns>
378 public bool Load(string file)
381 throw new ArgumentNullException("file");
383 Interop.Elementary.elm_image_async_open_set(RealHandle, false);
384 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, true);
385 return Interop.Elementary.elm_image_file_set(RealHandle, file, null);
389 /// Sets the uri that is used as the image's source.
391 /// <param name="uri">The uri to the file that is used as an image source</param>
392 /// <returns>(true = success, false = error)</returns>
393 public bool Load(Uri uri)
396 throw new ArgumentNullException("uri");
398 return Load(uri.IsFile ? uri.LocalPath : uri.AbsoluteUri);
402 /// Sets a location in the memory to be used as an image object's source bitmap.
405 /// This function is handy when the contents of an image file are mapped into the memory, for example.
406 /// The format string should be something like "png", "jpg", "tga", "tiff", "bmp" etc, when provided (null, on the contrary).
407 /// This improves the loader performance as it tries the "correct" loader first, before trying a range of other possible loaders until one succeeds.
409 /// <param name="img">The binary data that is used as an image source</param>
410 /// <param name="size">The size of the binary data blob img</param>
411 /// <returns>(true = success, false = error)</returns>
412 [Obsolete("This method will be removed. Use Load(Stream stream) instead.")]
413 public unsafe bool Load(byte* img, long size)
416 throw new ArgumentNullException("img");
418 Interop.Elementary.elm_image_async_open_set(RealHandle, false);
419 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, true);
420 return Interop.Elementary.elm_image_memfile_set(RealHandle, img, size, IntPtr.Zero, IntPtr.Zero);
424 /// Sets the stream that is used as the image's source.
426 /// <param name="stream">The stream that is used as an image source</param>
427 /// <returns>(true = success, false = error)</returns>
428 public bool Load(Stream stream)
431 throw new ArgumentNullException("stream");
433 Interop.Elementary.elm_image_async_open_set(RealHandle, false);
434 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, true);
435 MemoryStream memstream = new MemoryStream();
436 stream.CopyTo(memstream);
439 byte[] dataArr = memstream.ToArray();
440 fixed (byte* data = &dataArr[0])
442 return Interop.Elementary.elm_image_memfile_set(RealHandle, data, dataArr.Length, IntPtr.Zero, IntPtr.Zero);
448 /// Sets the file that is used as the image's source with async.
450 /// <param name="file">The path to the file that is used as an image source</param>
451 /// <param name="cancellationToken">cancellation token</param>
452 /// <returns>(true = success, false = error)</returns>
453 public Task<bool> LoadAsync(string file, CancellationToken cancellationToken = default(CancellationToken))
456 throw new ArgumentNullException("file");
458 Interop.Elementary.elm_image_async_open_set(RealHandle, true);
459 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, false);
461 var tcs = new TaskCompletionSource<bool>();
463 cancellationToken.Register(() =>
465 if (tcs != null && !tcs.Task.IsCompleted)
471 SmartEvent loadReady = new SmartEvent(this, RealHandle, "load,ready");
472 loadReady.On += (s, e) =>
475 LoadingCompleted?.Invoke(this, EventArgs.Empty);
476 if (tcs != null && !tcs.Task.IsCompleted)
482 SmartEvent loadError = new SmartEvent(this, RealHandle, "load,error");
483 loadError.On += (s, e) =>
486 LoadingFailed?.Invoke(this, EventArgs.Empty);
487 if (tcs != null && !tcs.Task.IsCompleted)
489 tcs.SetResult(false);
493 bool ret = Interop.Elementary.elm_image_file_set(RealHandle, file, null);
496 throw new InvalidOperationException("Failed to set file to Image");
503 /// Sets the uri that is used as the image's source with async.
505 /// <param name="uri">The uri to the file that is used as an image source</param>
506 /// <param name="cancellationToken">cancellation token</param>
507 /// <returns>(true = success, false = error)</returns>
508 public Task<bool> LoadAsync(Uri uri, CancellationToken cancellationToken = default(CancellationToken))
511 throw new ArgumentNullException("uri");
513 return LoadAsync(uri.IsFile ? uri.LocalPath : uri.AbsoluteUri, cancellationToken);
517 /// Sets the stream that is used as the image's source with async.
519 /// <param name="stream">The stream that is used as an image source</param>
520 /// <param name="cancellationToken">cancellation token</param>
521 /// <returns>(true = success, false = error)</returns>
522 public async Task<bool> LoadAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
525 throw new ArgumentNullException("stream");
527 Interop.Elementary.elm_image_async_open_set(RealHandle, true);
528 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, false);
530 var tcs = new TaskCompletionSource<bool>();
532 cancellationToken.Register(() =>
534 if (tcs != null && !tcs.Task.IsCompleted)
540 SmartEvent loadReady = new SmartEvent(this, RealHandle, "load,ready");
541 loadReady.On += (s, e) =>
544 LoadingCompleted?.Invoke(this, EventArgs.Empty);
545 if (tcs != null && !tcs.Task.IsCompleted)
551 SmartEvent loadError = new SmartEvent(this, RealHandle, "load,error");
552 loadError.On += (s, e) =>
555 LoadingFailed?.Invoke(this, EventArgs.Empty);
556 if (tcs != null && !tcs.Task.IsCompleted)
558 tcs.SetResult(false);
562 MemoryStream memstream = new MemoryStream();
563 await stream.CopyToAsync(memstream);
567 byte[] dataArr = memstream.ToArray();
568 fixed (byte* data = &dataArr[0])
570 bool ret = Interop.Elementary.elm_image_memfile_set(RealHandle, data, dataArr.Length, IntPtr.Zero, IntPtr.Zero);
578 return await tcs.Task;
582 /// Sets the color of color class for a given widget.
584 /// <param name="part">The name of color class.</param>
585 /// <param name="color">The struct of color</param>
586 public override void SetPartColor(string part, Color color)
588 Interop.Elementary.elm_object_color_class_color_set(Handle, part, color.R * color.A / 255,
589 color.G * color.A / 255,
590 color.B * color.A / 255,
595 /// Gets the color of color class for a given widget.
597 /// <param name="part">The name of color class.</param>
598 /// <returns>color object</returns>
599 public override Color GetPartColor(string part)
601 Interop.Elementary.elm_object_color_class_color_get(Handle, part, out int r, out int g, out int b, out int a);
602 return new Color((int)(r / (a / 255.0)), (int)(g / (a / 255.0)), (int)(b / (a / 255.0)), a);
606 /// Sets the content at a part of a given container widget.
608 /// <param name="parent">The parent is a given container which will be attached by Image as a child. It's <see cref="EvasObject"/> type.</param>
609 /// <returns>The new object, otherwise null if it cannot be created</returns>
610 protected override IntPtr CreateHandle(EvasObject parent)
612 IntPtr handle = Interop.Elementary.elm_layout_add(parent);
613 Interop.Elementary.elm_layout_theme_set(handle, "layout", "background", "default");
615 RealHandle = Interop.Elementary.elm_image_add(handle);
616 Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", RealHandle);
623 /// Enumeration for the fill mode of image border
625 public enum ImageBorderFillMode
628 /// None mode of image border
633 /// Default mode of image border
638 /// Solid mode of image border
644 /// Enumeration for the possible orientation options
646 public enum ImageOrientation : int
649 /// No orientation change
654 /// Rotate 90 degrees clockwise
659 /// Rotate 180 degrees clockwise
664 /// Rotate 90 degrees counter-clockwise (i.e. 270 degrees clockwise)
669 /// Flip image horizontally
674 /// Flip image vertically
679 /// Flip the image along the y = (width - x) line (bottom-left to top-right)
684 /// Flip the image along the y = x line (top-left to bottom-right)