2 * Copyright(c) 2021 Samsung Electronics Co., Ltd.
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.
18 using Tizen.NUI.BaseComponents;
19 using Tizen.NUI.Binding;
20 using System.ComponentModel;
21 using System.Diagnostics;
23 namespace Tizen.NUI.Components
26 /// The Progress class is used to show the ongoing status with a long narrow bar.
28 /// <since_tizen> 6 </since_tizen>
29 public partial class Progress : Control
34 [EditorBrowsable(EditorBrowsableState.Never)]
35 public static readonly BindableProperty MaxValueProperty = BindableProperty.Create(nameof(MaxValue), typeof(float), typeof(Progress), default(float), propertyChanged: (bindable, oldValue, newValue) =>
37 var instance = (Progress)bindable;
40 instance.maxValue = (float)newValue;
41 instance.UpdateValue();
44 defaultValueCreator: (bindable) =>
46 var instance = (Progress)bindable;
47 return instance.maxValue;
53 [EditorBrowsable(EditorBrowsableState.Never)]
54 public static readonly BindableProperty MinValueProperty = BindableProperty.Create(nameof(MinValue), typeof(float), typeof(Progress), default(float), propertyChanged: (bindable, oldValue, newValue) =>
56 var instance = (Progress)bindable;
59 instance.minValue = (float)newValue;
60 instance.UpdateValue();
63 defaultValueCreator: (bindable) =>
65 var instance = (Progress)bindable;
66 return instance.minValue;
70 /// CurrentValueProperty
72 [EditorBrowsable(EditorBrowsableState.Never)]
73 public static readonly BindableProperty CurrentValueProperty = BindableProperty.Create(nameof(CurrentValue), typeof(float), typeof(Progress), default(float), propertyChanged: (bindable, oldValue, newValue) =>
75 var instance = (Progress)bindable;
78 if ((float)newValue > instance.maxValue || (float)newValue < instance.minValue)
82 instance.currentValue = (float)newValue;
83 instance.UpdateValue();
86 defaultValueCreator: (bindable) =>
88 var instance = (Progress)bindable;
89 return instance.currentValue;
93 /// BufferValueProperty
95 [EditorBrowsable(EditorBrowsableState.Never)]
96 public static readonly BindableProperty BufferValueProperty = BindableProperty.Create(nameof(BufferValue), typeof(float), typeof(Progress), default(float), propertyChanged: (bindable, oldValue, newValue) =>
98 var instance = (Progress)bindable;
101 if ((float)newValue > instance.maxValue || (float)newValue < instance.minValue)
105 instance.bufferValue = (float)newValue;
106 instance.UpdateValue();
109 defaultValueCreator: (bindable) =>
111 var instance = (Progress)bindable;
112 return instance.bufferValue;
116 /// ProgressStateProperty
118 [EditorBrowsable(EditorBrowsableState.Never)]
119 public static readonly BindableProperty ProgressStateProperty = BindableProperty.Create(nameof(ProgressState), typeof(ProgressStatusType), typeof(Progress), ProgressStatusType.Indeterminate, propertyChanged: (bindable, oldValue, newValue) =>
121 var instance = (Progress)bindable;
122 if (newValue != null)
124 instance.state = (ProgressStatusType)newValue;
125 instance.UpdateStates();
128 defaultValueCreator: (bindable) =>
130 var instance = (Progress)bindable;
131 return instance.state;
135 /// IsEnabledProperty
137 [EditorBrowsable(EditorBrowsableState.Never)]
138 public static readonly BindableProperty IsEnabledProperty = BindableProperty.Create(nameof(IsEnabled), typeof(bool), typeof(Progress), true, propertyChanged: (bindable, oldValue, newValue) =>
140 var instance = (Progress)bindable;
141 if (newValue != null)
143 bool newEnabled = (bool)newValue;
144 if (instance.isEnabled != newEnabled)
146 instance.isEnabled = newEnabled;
147 instance.Sensitive = newEnabled;
148 instance.UpdateStates();
152 defaultValueCreator: (bindable) => ((Progress)bindable).isEnabled);
154 /// This needs to be considered more if public-open is necessary.
155 private ProgressStatusType state = ProgressStatusType.Determinate;
157 private Vector2 size = null;
158 private const float round = 0.5f;
159 private ImageView trackImage = null;
160 private ImageView progressImage = null;
161 private ImageView bufferImage = null;
162 private ImageVisual indeterminateImage = null;
163 private float maxValue = 100;
164 private float minValue = 0;
165 private float currentValue = 0;
166 private float bufferValue = 0;
167 private Animation indeterminateAnimation = null;
168 bool isEnabled = true;
170 static Progress() { }
172 /// The constructor of Progress
174 /// <since_tizen> 6 </since_tizen>
175 public Progress() : base()
181 /// The constructor of the Progress class with specific style.
183 /// <param name="style">style name</param>
184 /// <since_tizen> 8 </since_tizen>
185 public Progress(string style) : base(style)
191 /// The constructor of the Progress class with specific style.
193 /// <param name="progressStyle">The style object to initialize the Progress.</param>
194 /// <since_tizen> 8 </since_tizen>
195 public Progress(ProgressStyle progressStyle) : base(progressStyle)
201 /// The status type of the Progress.
203 /// <since_tizen> 6 </since_tizen>
204 public enum ProgressStatusType
209 /// <since_tizen> 6 </since_tizen>
213 /// Show ProgressImage and BufferImage
215 /// <since_tizen> 6 </since_tizen>
221 /// <since_tizen> 6 </since_tizen>
226 /// Return currently applied style.
229 /// Modifying contents in style may cause unexpected behaviour.
231 /// <since_tizen> 8 </since_tizen>
232 public ProgressStyle Style => (ProgressStyle)(ViewStyle as ProgressStyle)?.Clone();
235 /// The property to get/set Track image object URL of the Progress.
237 /// <since_tizen> 6 </since_tizen>
238 public string TrackImageURL
242 return GetValue(TrackImageURLProperty) as string;
246 SetValue(TrackImageURLProperty, value);
247 NotifyPropertyChanged();
250 private string InternalTrackImageURL
252 get => trackImage.ResourceUrl;
253 set => trackImage.ResourceUrl = value;
257 /// The property to get/set Progress object image URL of the Progress.
259 /// <since_tizen> 6 </since_tizen>
260 public string ProgressImageURL
264 return GetValue(ProgressImageURLProperty) as string;
268 SetValue(ProgressImageURLProperty, value);
269 NotifyPropertyChanged();
272 private string InternalProgressImageURL
274 get => progressImage.ResourceUrl;
275 set => progressImage.ResourceUrl = value;
279 /// The property to get/set Buffer object image resource URL of the Progress.
281 /// <since_tizen> 6 </since_tizen>
282 public string BufferImageURL
286 return GetValue(BufferImageURLProperty) as string;
290 SetValue(BufferImageURLProperty, value);
291 NotifyPropertyChanged();
294 private string InternalBufferImageURL
296 get => bufferImage.ResourceUrl;
297 set => bufferImage.ResourceUrl = value;
301 /// The property to get/set the indeterminate image.
303 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
304 /// <since_tizen> 9 </since_tizen>
305 public string IndeterminateImageUrl
309 return GetValue(IndeterminateImageUrlProperty) as string;
313 SetValue(IndeterminateImageUrlProperty, value);
314 NotifyPropertyChanged();
317 private string InternalIndeterminateImageUrl
321 if (indeterminateImage == null)
327 return indeterminateImage?.URL;
332 if (value == null || indeterminateImage == null)
334 throw new NullReferenceException("Progress.IndeterminateImage is null");
338 indeterminateImage.URL = value;
344 /// The property to get/set Track object color of the Progress.
346 /// <since_tizen> 6 </since_tizen>
347 public Color TrackColor
351 return GetValue(TrackColorProperty) as Color;
355 SetValue(TrackColorProperty, value);
356 NotifyPropertyChanged();
359 private Color InternalTrackColor
361 get => trackImage.BackgroundColor;
362 set => trackImage.BackgroundColor = value;
366 /// The property to get/set Progress object color of the Progress.
368 /// <since_tizen> 6 </since_tizen>
369 public Color ProgressColor
373 return GetValue(ProgressColorProperty) as Color;
377 SetValue(ProgressColorProperty, value);
378 NotifyPropertyChanged();
381 private Color InternalProgressColor
383 get => progressImage.BackgroundColor;
384 set => progressImage.BackgroundColor = value;
388 /// The property to get/set Buffer object color of the Progress.
390 /// <since_tizen> 6 </since_tizen>
391 public Color BufferColor
395 return GetValue(BufferColorProperty) as Color;
399 SetValue(BufferColorProperty, value);
400 NotifyPropertyChanged();
403 private Color InternalBufferColor
405 get => bufferImage.BackgroundColor;
406 set => bufferImage.BackgroundColor = value;
410 /// The property to get/set the maximum value of the Progress.
412 /// <since_tizen> 6 </since_tizen>
413 public float MaxValue
417 return (float)GetValue(MaxValueProperty);
421 SetValue(MaxValueProperty, value);
426 /// The property to get/set the minim value of the Progress.
428 /// <since_tizen> 6 </since_tizen>
429 public float MinValue
433 return (float)GetValue(MinValueProperty);
437 SetValue(MinValueProperty, value);
442 /// The property to get/set the current value of the Progress.
444 /// <since_tizen> 6 </since_tizen>
445 public float CurrentValue
449 return (float)GetValue(CurrentValueProperty);
453 SetValue(CurrentValueProperty, value);
454 if (Accessibility.Accessibility.IsEnabled && IsHighlighted)
456 EmitAccessibilityEvent(AccessibilityPropertyChangeEvent.Value);
462 /// The property to get/set the buffer value of the Progress.
464 /// <since_tizen> 6 </since_tizen>
465 public float BufferValue
469 return (float)GetValue(BufferValueProperty);
473 SetValue(BufferValueProperty, value);
478 /// Gets or sets state of progress.
480 /// <since_tizen> 6 </since_tizen>
481 public ProgressStatusType ProgressState
485 return (ProgressStatusType)GetValue(ProgressStateProperty);
489 SetValue(ProgressStateProperty, value);
494 /// Flag to decide enable or disable in Progress.
496 [EditorBrowsable(EditorBrowsableState.Never)]
497 public bool IsEnabled
501 return (bool)GetValue(IsEnabledProperty);
505 SetValue(IsEnabledProperty, value);
510 [EditorBrowsable(EditorBrowsableState.Never)]
511 public override void OnInitialize()
514 SetAccessibilityConstructor(Role.ProgressBar, AccessibilityInterface.Value);
515 // create necessary components
518 InitializeProgress();
519 InitializeIndeterminate();
521 indeterminateAnimation?.Stop();
522 indeterminateAnimation = null;
526 [EditorBrowsable(EditorBrowsableState.Never)]
527 public override void ApplyStyle(ViewStyle style)
529 base.ApplyStyle(style);
531 if (style is ProgressStyle progressStyle)
533 Debug.Assert(trackImage != null);
534 Debug.Assert(progressImage != null);
535 Debug.Assert(bufferImage != null);
537 trackImage.ApplyStyle(progressStyle.Track);
538 progressImage.ApplyStyle(progressStyle.Progress);
539 bufferImage.ApplyStyle(progressStyle.Buffer);
541 if (null != indeterminateImage && null != progressStyle.IndeterminateImageUrl)
543 indeterminateImage.URL = progressStyle.IndeterminateImageUrl;
549 /// Prevents from showing child widgets in AT-SPI tree.
551 [EditorBrowsable(EditorBrowsableState.Never)]
552 protected override bool AccessibilityShouldReportZeroChildren()
558 /// Gets minimum value for Accessibility.
560 [EditorBrowsable(EditorBrowsableState.Never)]
561 protected override double AccessibilityGetMinimum()
563 if (this.ProgressState == Progress.ProgressStatusType.Determinate)
565 return (double)MinValue;
574 /// Gets the current value for Accessibility.
576 [EditorBrowsable(EditorBrowsableState.Never)]
577 protected override double AccessibilityGetCurrent()
579 if (this.ProgressState == Progress.ProgressStatusType.Determinate)
581 return (double)CurrentValue;
590 /// Gets maximum value for Accessibility.
592 [EditorBrowsable(EditorBrowsableState.Never)]
593 protected override double AccessibilityGetMaximum()
595 if (this.ProgressState == Progress.ProgressStatusType.Determinate)
597 return (double)MaxValue;
606 /// Dispose Progress and all children on it.
608 /// <param name="type">Dispose type.</param>
609 /// <since_tizen> 6 </since_tizen>
610 protected override void Dispose(DisposeTypes type)
617 if (type == DisposeTypes.Explicit)
620 //Release your own managed resources here.
621 //You should release all of your own disposable objects here.
622 Utility.Dispose(trackImage);
623 Utility.Dispose(progressImage);
624 Utility.Dispose(bufferImage);
625 indeterminateImage = null;
628 //You must call base.Dispose(type) just before exit.
633 /// Change Image status. It can be override.
635 /// This needs to be considered more if public-open is necessary.
636 [EditorBrowsable(EditorBrowsableState.Never)]
637 private void UpdateStates()
639 ChangeImageState(state);
643 [EditorBrowsable(EditorBrowsableState.Never)]
644 public override void OnRelayout(Vector2 size, RelayoutContainer container)
646 if (size == null) return;
648 if (size.Equals(this.size))
653 this.size = new Vector2(size);
658 /// Update progress value
660 /// This needs to be considered more if public-open is necessary.
661 [EditorBrowsable(EditorBrowsableState.Never)]
662 private void UpdateValue()
664 if (null == trackImage || null == progressImage)
669 if (minValue >= maxValue || currentValue < minValue || currentValue > maxValue)
674 float width = this.SizeWidth;
675 float height = this.SizeHeight;
676 float progressRatio = (float)(currentValue - minValue) / (float)(maxValue - minValue);
677 float progressWidth = width * progressRatio;
678 progressImage.Size2D = new Size2D((int)(progressWidth + round), (int)height); //Add const round to reach Math.Round function.
679 if (null != bufferImage)
681 if (bufferValue < minValue || bufferValue > maxValue)
686 float bufferRatio = (float)(bufferValue - minValue) / (float)(maxValue - minValue);
687 float bufferWidth = width * bufferRatio;
688 bufferImage.Size2D = new Size2D((int)(bufferWidth + round), (int)height); //Add const round to reach Math.Round function.
692 private Vector4 destinationValue = new Vector4(-1.0f, 0.0f, 10.0f, 1.0f);
693 private Vector4 initialValue = new Vector4(0.0f, 0.0f, 10.0f, 1.0f);
696 /// Update Animation for Indeterminate mode.
698 /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
699 [EditorBrowsable(EditorBrowsableState.Never)]
700 private void UpdateIndeterminateAnimation()
702 indeterminateAnimation?.Stop();
704 if (null != indeterminateImage)
706 indeterminateAnimation = AnimateVisual(indeterminateImage, "pixelArea", destinationValue, 0, 1000, AlphaFunction.BuiltinFunctions.Default, initialValue);
707 indeterminateAnimation.Looping = true;
708 indeterminateAnimation.Play();
713 /// Get Progress style.
715 /// <returns>The default progress style.</returns>
716 /// <since_tizen> 8 </since_tizen>
717 protected override ViewStyle CreateViewStyle()
719 return new ProgressStyle();
723 /// Change Image status
725 /// <since_tizen> 6 </since_tizen>
726 /// <param name="statusType">New status type</param>
727 protected void ChangeImageState(ProgressStatusType statusType)
731 ControlState = ControlState.Disabled;
733 indeterminateAnimation?.Stop();
734 indeterminateAnimation = null;
736 if (null != indeterminateImage)
738 indeterminateImage.Opacity = 0.0f;
740 progressImage.Hide();
745 if (statusType == ProgressStatusType.Buffering)
747 indeterminateAnimation?.Stop();
748 indeterminateAnimation = null;
750 if (null != indeterminateImage)
752 indeterminateImage.Opacity = 0.0f;
754 progressImage.Hide();
757 else if (statusType == ProgressStatusType.Determinate)
759 indeterminateAnimation?.Stop();
760 indeterminateAnimation = null;
762 if (null != indeterminateImage)
764 indeterminateImage.Opacity = 0.0f;
767 progressImage.Show();
771 else if (statusType == ProgressStatusType.Indeterminate)
774 progressImage.Hide();
775 if (null != indeterminateImage)
777 indeterminateImage.Opacity = 1.0f;
780 UpdateIndeterminateAnimation();
784 private void Initialize()
786 AccessibilityHighlightable = true;
789 private void InitializeTrack()
791 if (null == trackImage)
793 trackImage = new ImageView
795 WidthResizePolicy = ResizePolicyType.FillToParent,
796 HeightResizePolicy = ResizePolicyType.FillToParent,
797 PositionUsesPivotPoint = true,
798 ParentOrigin = NUI.ParentOrigin.TopLeft,
799 PivotPoint = NUI.PivotPoint.TopLeft
805 private void InitializeProgress()
807 if (null == progressImage)
809 progressImage = new ImageView
811 WidthResizePolicy = ResizePolicyType.FillToParent,
812 HeightResizePolicy = ResizePolicyType.FillToParent,
813 PositionUsesPivotPoint = true,
814 ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft,
815 PivotPoint = Tizen.NUI.PivotPoint.TopLeft
821 private void InitializeBuffer()
823 if (null == bufferImage)
825 bufferImage = new ImageView
827 WidthResizePolicy = ResizePolicyType.FillToParent,
828 HeightResizePolicy = ResizePolicyType.FillToParent,
829 PositionUsesPivotPoint = true,
830 ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft,
831 PivotPoint = Tizen.NUI.PivotPoint.TopLeft
834 bufferImage.Hide(); // At first, buffer image does not show.
838 private void InitializeIndeterminate()
840 indeterminateImage = new ImageVisual
842 PixelArea = new Vector4(0.0f, 0.0f, 10.0f, 1.0f),
843 WrapModeU = WrapModeType.Repeat,
844 SizePolicy = VisualTransformPolicyType.Relative,
845 Origin = Visual.AlignType.Center,
846 AnchorPoint = Visual.AlignType.Center,
848 Size = new Size2D(1, 1),
849 URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "nui_component_default_progress_indeterminate.png"
851 AddVisual("Indeterminate", indeterminateImage);
853 if (state == ProgressStatusType.Indeterminate)
855 indeterminateImage.Opacity = 1.0f;