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 /// <since_tizen> preview </since_tizen>
30 public class Image : Widget
32 bool _canScaleUp = true;
33 bool _canScaleDown = true;
35 Color _color = Color.Default;
37 EvasImage _imageObject = null;
40 /// Creates and initializes a new instance of the Image class.
42 /// <param name="parent">The parent is a given container, which will be attached by the image as a child. It's <see cref="EvasObject"/> type.</param>
43 /// <since_tizen> preview </since_tizen>
44 public Image(EvasObject parent) : base(parent)
46 _clicked = new SmartEvent(this, "clicked");
47 _clicked.On += (s, e) => Clicked?.Invoke(this, EventArgs.Empty);
51 /// Clicked will be triggered when the image is clicked.
53 /// <since_tizen> preview </since_tizen>
54 public event EventHandler Clicked;
57 /// LoadingCompleted will be triggered when the image is loaded completely.
59 /// <since_tizen> preview </since_tizen>
60 public event EventHandler LoadingCompleted;
63 /// Clicked will be triggered when the image fails to load.
65 /// <since_tizen> preview </since_tizen>
66 public event EventHandler LoadingFailed;
69 /// Gets the file that is used as an image.
71 /// <since_tizen> preview </since_tizen>
76 return Interop.Elementary.elm_image_file_get(RealHandle);
81 /// Sets or gets the smooth effect for an image.
83 /// <since_tizen> preview </since_tizen>
88 return Interop.Elementary.elm_image_smooth_get(RealHandle);
92 Interop.Elementary.elm_image_smooth_set(RealHandle, value);
97 /// Sets or gets whether scaling is disabled on the object.
99 /// <since_tizen> preview </since_tizen>
100 public bool IsScaling
104 return !Interop.Elementary.elm_image_no_scale_get(RealHandle);
108 Interop.Elementary.elm_image_no_scale_set(RealHandle, !value);
113 /// Sets or gets whether the object is down resizable.
115 /// <since_tizen> preview </since_tizen>
116 public bool CanScaleDown
120 return _canScaleDown;
124 _canScaleDown = value;
125 Interop.Elementary.elm_image_resizable_set(RealHandle, _canScaleUp, _canScaleDown);
130 /// Sets or gets whether the object is up resizable.
132 /// <since_tizen> preview </since_tizen>
133 public bool CanScaleUp
142 Interop.Elementary.elm_image_resizable_set(RealHandle, _canScaleUp, _canScaleDown);
147 /// Sets or gets whether the image fills the entire object area, when keeping the aspect ratio.
149 /// <since_tizen> preview </since_tizen>
150 public bool CanFillOutside
154 return Interop.Elementary.elm_image_fill_outside_get(RealHandle);
158 Interop.Elementary.elm_image_fill_outside_set(RealHandle, value);
163 /// Sets or gets the prescale size for the image.
165 /// <since_tizen> preview </since_tizen>
166 public int PrescaleSize
170 return Interop.Elementary.elm_image_prescale_get(RealHandle);
174 Interop.Elementary.elm_image_prescale_set(RealHandle, value);
179 /// Sets or gets whether the original aspect ratio of the image should be kept on resize.
181 /// <since_tizen> preview </since_tizen>
182 public bool IsFixedAspect
186 return Interop.Elementary.elm_image_aspect_fixed_get(RealHandle);
190 Interop.Elementary.elm_image_aspect_fixed_set(RealHandle, value);
195 /// Sets or gets whether an image object (which supports animation) is to animate itself.
197 /// <since_tizen> preview </since_tizen>
198 public bool IsAnimated
202 return Interop.Elementary.elm_image_animated_get(RealHandle);
206 Interop.Elementary.elm_image_animated_set(RealHandle, value);
211 /// Gets whether an image object supports animation.
213 /// <since_tizen> preview </since_tizen>
214 public bool IsAnimatedAvailable
218 return Interop.Elementary.elm_image_animated_available_get(RealHandle);
223 /// Sets or gets whether an image object is under animation.
226 /// An image object, even if it supports animation, will be displayed by default without animation.
227 /// To actually start playing any image object's animation, <see cref="IsAnimated"/> should be TRUE before setting this property true.
229 /// <since_tizen> preview </since_tizen>
230 public bool IsAnimationPlaying
234 return Interop.Elementary.elm_image_animated_play_get(RealHandle);
238 Interop.Elementary.elm_image_animated_play_set(RealHandle, value);
243 /// Sets or gets whether the image is 'editable'.
245 /// <since_tizen> preview </since_tizen>
246 public bool IsEditable
250 return Interop.Elementary.elm_image_editable_get(RealHandle);
254 Interop.Elementary.elm_image_editable_set(RealHandle, value);
259 /// Gets the current size of the image.
261 /// <since_tizen> preview </since_tizen>
262 public Size ObjectSize
266 Interop.Elementary.elm_image_object_size_get(RealHandle, out int w, out int h);
267 return new Size(w, h);
272 /// Sets or gets whether the alpha channel data is being used on the given image object.
274 /// <since_tizen> preview </since_tizen>
279 if (ImageObject != null)
281 return ImageObject.IsOpaque;
287 if (ImageObject != null)
289 ImageObject.IsOpaque = value;
295 /// Sets or gets the image orientation.
297 /// <since_tizen> preview </since_tizen>
298 public ImageOrientation Orientation
302 return (ImageOrientation)Interop.Elementary.elm_image_orient_get(RealHandle);
306 Interop.Elementary.elm_image_orient_set(RealHandle, (int)value);
311 /// Sets or gets the image color.
313 /// <since_tizen> preview </since_tizen>
314 public override Color Color
322 if (ImageObject != null)
326 ImageObject.Color = Color.FromRgba(255, 255, 255, 255);
330 ImageObject.Color = value;
338 /// Sets the background color.
340 /// <since_tizen> preview </since_tizen>
341 public override Color BackgroundColor
347 SetPartColor("bg", Color.Transparent);
351 SetPartColor("bg", value);
353 _backgroundColor = value;
358 /// Gets the inlined image object of the image widget.
359 /// This property allows one to get the underlying EvasObject of type Image from this elementary widget. It can be useful to do things like save the image to a file, etc.
361 /// <remarks>Be careful not to manipulate it, as it is under the control of the widget.</remarks>
362 /// <since_tizen> preview </since_tizen>
363 public EvasImage ImageObject
367 if (_imageObject == null)
369 IntPtr evasObj = Interop.Elementary.elm_image_object_get(RealHandle);
370 if (evasObj != IntPtr.Zero)
372 _imageObject = new EvasImage(this, evasObj);
373 _imageObject.Deleted += (s, e) => _imageObject = null;
381 /// Sets the dimensions for an image object's border, a region which is not scaled together with its center ever.
383 /// <param name="left">The border's left width.</param>
384 /// <param name="right">The border's right width.</param>
385 /// <param name="top">The border's top width.</param>
386 /// <param name="bottom">The border's bottom width.</param>
387 /// <since_tizen> preview </since_tizen>
388 public void SetBorder(int left, int right, int top, int bottom)
390 ImageObject?.SetBorder(left, right, top, bottom);
394 /// Sets or gets if the center part of the given image object (not the border) should be drawn.
397 /// When rendering, the image may be scaled to fit the size of the image object.
398 /// This function sets if the center part of the scaled image is to be drawn or left completely blank, or forced to be solid.
399 /// Very useful for frames and decorations.
401 /// <since_tizen> preview </since_tizen>
402 public ImageBorderFillMode BorderCenterFillMode
406 if (ImageObject != null)
408 return ImageObject.BorderCenterFillMode;
412 return default(ImageBorderFillMode);
418 if (ImageObject != null)
420 ImageObject.BorderCenterFillMode = value;
426 /// Sets the file that is used as the image's source.
428 /// <param name="file">The path to the file that is used as an image source.</param>
429 /// <returns>(true = success, false = error)</returns>
430 /// <since_tizen> preview </since_tizen>
431 public bool Load(string file)
434 throw new ArgumentNullException(nameof(file));
436 Interop.Elementary.elm_image_async_open_set(RealHandle, false);
437 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, true);
438 return Interop.Elementary.elm_image_file_set(RealHandle, file, null);
442 /// Sets the URI that is used as the image's source.
444 /// <param name="uri">The URI to the file that is used as an image source.</param>
445 /// <returns>(true = success, false = error)</returns>
446 /// <since_tizen> preview </since_tizen>
447 public bool Load(Uri uri)
450 throw new ArgumentNullException(nameof(uri));
452 return Load(uri.IsFile ? uri.LocalPath : uri.AbsoluteUri);
456 /// Sets a location in the memory to be used as an image object's source bitmap.
459 /// This function is handy when the contents of an image file are mapped into the memory, for example,
460 /// the format string should be something like "png", "jpg", "tga", "tiff", "bmp" etc, when provided (null, on the contrary).
461 /// This improves the loader performance as it tries the "correct" loader first, before trying a range of other possible loaders until one succeeds.
463 /// <param name="img">The binary data that is used as an image source.</param>
464 /// <param name="size">The size of the binary data blob img.</param>
465 /// <returns>(true = success, false = error)</returns>
466 /// <since_tizen> preview </since_tizen>
467 [Obsolete("This method will be removed. Use Load(Stream stream) instead.")]
468 public unsafe bool Load(byte* img, long size)
471 throw new ArgumentNullException(nameof(img));
473 Interop.Elementary.elm_image_async_open_set(RealHandle, false);
474 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, true);
475 return Interop.Elementary.elm_image_memfile_set(RealHandle, img, size, IntPtr.Zero, IntPtr.Zero);
479 /// Sets the stream that is used as the image's source.
481 /// <param name="stream">The stream that is used as an image source.</param>
482 /// <returns>(true = success, false = error)</returns>
483 /// <since_tizen> preview </since_tizen>
484 public bool Load(Stream stream)
487 throw new ArgumentNullException(nameof(stream));
489 Interop.Elementary.elm_image_async_open_set(RealHandle, false);
490 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, true);
491 MemoryStream memstream = new MemoryStream();
492 stream.CopyTo(memstream);
495 byte[] dataArr = memstream.ToArray();
496 fixed (byte* data = &dataArr[0])
498 return Interop.Elementary.elm_image_memfile_set(RealHandle, data, dataArr.Length, IntPtr.Zero, IntPtr.Zero);
504 /// Sets the file that is used as the image's source with async.
506 /// <param name="file">The path to the file that is used as an image source.</param>
507 /// <param name="cancellationToken">The cancellation token.</param>
508 /// <returns>(true = success, false = error)</returns>
509 /// <since_tizen> preview </since_tizen>
510 public async Task<bool> LoadAsync(string file, CancellationToken cancellationToken = default(CancellationToken))
513 throw new ArgumentNullException(nameof(file));
515 Interop.Elementary.elm_image_async_open_set(RealHandle, true);
516 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, false);
518 var tcs = new TaskCompletionSource<bool>();
520 cancellationToken.Register(() =>
522 if (tcs != null && !tcs.Task.IsCompleted)
528 SmartEvent loadReady = new SmartEvent(this, RealHandle, "load,ready");
529 loadReady.On += (s, e) =>
531 LoadingCompleted?.Invoke(this, EventArgs.Empty);
532 if (tcs != null && !tcs.Task.IsCompleted)
538 SmartEvent loadError = new SmartEvent(this, RealHandle, "load,error");
539 loadError.On += (s, e) =>
541 LoadingFailed?.Invoke(this, EventArgs.Empty);
542 if (tcs != null && !tcs.Task.IsCompleted)
544 tcs.SetResult(false);
551 bool ret = Interop.Elementary.elm_image_file_set(RealHandle, file, null);
554 throw new InvalidOperationException("Failed to set file to Image");
556 // it should be return on main thread, because SmartEvent should be disposed on main thread
557 return await tcs.Task.ConfigureAwait(true);
562 /// Sets the URI that is used as the image's source with async.
564 /// <param name="uri">The URI to the file that is used as an image source.</param>
565 /// <param name="cancellationToken">The cancellation token.</param>
566 /// <returns>(true = success, false = error)</returns>
567 /// <since_tizen> preview </since_tizen>
568 public Task<bool> LoadAsync(Uri uri, CancellationToken cancellationToken = default(CancellationToken))
571 throw new ArgumentNullException(nameof(uri));
573 return LoadAsync(uri.IsFile ? uri.LocalPath : uri.AbsoluteUri, cancellationToken);
577 /// Sets the stream that is used as the image's source with async.
579 /// <param name="stream">The stream that is used as an image source.</param>
580 /// <param name="cancellationToken">The cancellation token.</param>
581 /// <returns>(true = success, false = error)</returns>
582 /// <since_tizen> preview </since_tizen>
583 public async Task<bool> LoadAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
586 throw new ArgumentNullException(nameof(stream));
588 Interop.Elementary.elm_image_async_open_set(RealHandle, true);
589 Interop.Elementary.elm_image_preload_disabled_set(RealHandle, false);
591 var tcs = new TaskCompletionSource<bool>();
593 cancellationToken.Register(() =>
595 if (tcs != null && !tcs.Task.IsCompleted)
601 SmartEvent loadReady = new SmartEvent(this, RealHandle, "load,ready");
602 loadReady.On += (s, e) =>
604 LoadingCompleted?.Invoke(this, EventArgs.Empty);
605 if (tcs != null && !tcs.Task.IsCompleted)
611 SmartEvent loadError = new SmartEvent(this, RealHandle, "load,error");
612 loadError.On += (s, e) =>
614 LoadingFailed?.Invoke(this, EventArgs.Empty);
615 if (tcs != null && !tcs.Task.IsCompleted)
617 tcs.SetResult(false);
621 using (MemoryStream memstream = new MemoryStream())
625 await stream.CopyToAsync(memstream).ConfigureAwait(true);
629 byte[] dataArr = memstream.ToArray();
630 fixed (byte* data = &dataArr[0])
632 bool ret = Interop.Elementary.elm_image_memfile_set(RealHandle, data, dataArr.Length, IntPtr.Zero, IntPtr.Zero);
639 // it should be return on main thread, because SmartEvent should be disposed on main thread
640 return await tcs.Task.ConfigureAwait(true);
645 /// Sets the color of the Color class for a given widget.
647 /// <param name="part">The name of the Color class.</param>
648 /// <param name="color">The struct of the Color class.</param>
649 /// <since_tizen> preview </since_tizen>
650 public override void SetPartColor(string part, Color color)
652 Interop.Elementary.elm_object_color_class_color_set(Handle, part, color.R * color.A / 255,
653 color.G * color.A / 255,
654 color.B * color.A / 255,
659 /// Gets the color of the Color class for a given widget.
661 /// <param name="part">The name of the Color class.</param>
662 /// <returns>The color object.</returns>
663 /// <since_tizen> preview </since_tizen>
664 public override Color GetPartColor(string part)
666 Interop.Elementary.elm_object_color_class_color_get(Handle, part, out int r, out int g, out int b, out int a);
667 return new Color((int)(r / (a / 255.0)), (int)(g / (a / 255.0)), (int)(b / (a / 255.0)), a);
671 /// Sets the content at a part of a given container widget.
673 /// <param name="parent">The parent is a given container, which will be attached by the image as a child. It's <see cref="EvasObject"/> type.</param>
674 /// <returns>The new object, otherwise null if it cannot be created.</returns>
675 /// <since_tizen> preview </since_tizen>
676 protected override IntPtr CreateHandle(EvasObject parent)
678 IntPtr handle = Interop.Elementary.elm_layout_add(parent.Handle);
679 Interop.Elementary.elm_layout_theme_set(handle, "layout", "background", "default");
681 RealHandle = Interop.Elementary.elm_image_add(handle);
682 Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", RealHandle);
689 /// Enumeration for the fill mode of the image border.
691 /// <since_tizen> preview </since_tizen>
692 public enum ImageBorderFillMode
695 /// None mode of the image border.
700 /// Default mode of the image border.
705 /// Solid mode of the image border.
711 /// Enumeration for the possible orientation options.
713 /// <since_tizen> preview </since_tizen>
714 public enum ImageOrientation : int
717 /// No orientation change.
722 /// Rotate 90 degrees clockwise.
727 /// Rotate 180 degrees clockwise.
732 /// Rotate 90 degrees counter-clockwise (i.e., 270 degrees clockwise).
737 /// Flip the image horizontally.
742 /// Flip the image vertically.
747 /// Flip the image along the Y = (width - X) line (bottom-left to top-right).
752 /// Flip the image along the Y = X line (top-left to bottom-right).