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 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;
134 /// This needs to be considered more if public-open is necessary.
135 private ProgressStatusType state = ProgressStatusType.Determinate;
137 private Vector2 size = null;
138 private const float round = 0.5f;
139 private ImageView trackImage = null;
140 private ImageView progressImage = null;
141 private ImageView bufferImage = null;
142 private ImageVisual indeterminateImage = null;
143 private float maxValue = 100;
144 private float minValue = 0;
145 private float currentValue = 0;
146 private float bufferValue = 0;
147 private Animation indeterminateAnimation = null;
149 static Progress() { }
151 /// The constructor of Progress
153 /// <since_tizen> 6 </since_tizen>
154 public Progress() : base()
160 /// The constructor of the Progress class with specific style.
162 /// <param name="style">style name</param>
163 /// <since_tizen> 8 </since_tizen>
164 public Progress(string style) : base(style)
170 /// The constructor of the Progress class with specific style.
172 /// <param name="progressStyle">The style object to initialize the Progress.</param>
173 /// <since_tizen> 8 </since_tizen>
174 public Progress(ProgressStyle progressStyle) : base(progressStyle)
180 /// Prevents from showing child widgets in AT-SPI tree.
182 [EditorBrowsable(EditorBrowsableState.Never)]
183 protected override bool AccessibilityShouldReportZeroChildren()
191 [EditorBrowsable(EditorBrowsableState.Never)]
192 protected override double AccessibilityGetMinimum()
194 if (this.ProgressState == Components.Progress.ProgressStatusType.Determinate)
195 return (double)MinValue;
202 [EditorBrowsable(EditorBrowsableState.Never)]
203 protected override double AccessibilityGetCurrent()
205 if (this.ProgressState == Components.Progress.ProgressStatusType.Determinate)
206 return (double)CurrentValue;
213 [EditorBrowsable(EditorBrowsableState.Never)]
214 protected override double AccessibilityGetMaximum()
216 if (this.ProgressState == Components.Progress.ProgressStatusType.Determinate)
217 return (double)MaxValue;
222 /// The status type of the Progress.
224 /// <since_tizen> 6 </since_tizen>
225 public enum ProgressStatusType
230 /// <since_tizen> 6 </since_tizen>
234 /// Show ProgressImage and BufferImage
236 /// <since_tizen> 6 </since_tizen>
242 /// <since_tizen> 6 </since_tizen>
247 /// Return currently applied style.
250 /// Modifying contents in style may cause unexpected behaviour.
252 /// <since_tizen> 8 </since_tizen>
253 public ProgressStyle Style => (ProgressStyle)(ViewStyle as ProgressStyle)?.Clone();
256 /// The property to get/set Track image object URL of the Progress.
258 /// <since_tizen> 6 </since_tizen>
259 public string TrackImageURL
261 get => trackImage.ResourceUrl;
262 set => trackImage.ResourceUrl = value;
266 /// The property to get/set Progress object image URL of the Progress.
268 /// <since_tizen> 6 </since_tizen>
269 public string ProgressImageURL
271 get => progressImage.ResourceUrl;
272 set => progressImage.ResourceUrl = value;
276 /// The property to get/set Buffer object image resource URL of the Progress.
278 /// <since_tizen> 6 </since_tizen>
279 public string BufferImageURL
281 get => bufferImage.ResourceUrl;
282 set => bufferImage.ResourceUrl = value;
286 /// The property to get/set the indeterminate image.
288 /// <exception cref="NullReferenceException">Thrown when setting null value.</exception>
289 /// <since_tizen> 9 </since_tizen>
290 public string IndeterminateImageUrl
294 if (indeterminateImage == null)
300 return indeterminateImage?.URL;
305 if (value == null || indeterminateImage == null)
307 throw new NullReferenceException("Progress.IndeterminateImage is null");
311 indeterminateImage.URL = value;
317 /// The property to get/set Track object color of the Progress.
319 /// <since_tizen> 6 </since_tizen>
320 public Color TrackColor
322 get => trackImage.BackgroundColor;
323 set => trackImage.BackgroundColor = value;
327 /// The property to get/set Progress object color of the Progress.
329 /// <since_tizen> 6 </since_tizen>
330 public Color ProgressColor
332 get => progressImage.BackgroundColor;
333 set => progressImage.BackgroundColor = value;
337 /// The property to get/set Buffer object color of the Progress.
339 /// <since_tizen> 6 </since_tizen>
340 public Color BufferColor
342 get => bufferImage.BackgroundColor;
343 set => bufferImage.BackgroundColor = value;
347 /// The property to get/set the maximum value of the Progress.
349 /// <since_tizen> 6 </since_tizen>
350 public float MaxValue
354 return (float)GetValue(MaxValueProperty);
358 SetValue(MaxValueProperty, value);
363 /// The property to get/set the minim value of the Progress.
365 /// <since_tizen> 6 </since_tizen>
366 public float MinValue
370 return (float)GetValue(MinValueProperty);
374 SetValue(MinValueProperty, value);
379 /// The property to get/set the current value of the Progress.
381 /// <since_tizen> 6 </since_tizen>
382 public float CurrentValue
386 return (float)GetValue(CurrentValueProperty);
390 SetValue(CurrentValueProperty, value);
393 EmitAccessibilityEvent(AccessibilityPropertyChangeEvent.Value);
399 /// The property to get/set the buffer value of the Progress.
401 /// <since_tizen> 6 </since_tizen>
402 public float BufferValue
406 return (float)GetValue(BufferValueProperty);
410 SetValue(BufferValueProperty, value);
415 /// Gets or sets state of progress.
417 /// <since_tizen> 6 </since_tizen>
418 public ProgressStatusType ProgressState
422 return (ProgressStatusType)GetValue(ProgressStateProperty);
426 SetValue(ProgressStateProperty, value);
431 [EditorBrowsable(EditorBrowsableState.Never)]
432 public override void OnInitialize()
435 SetAccessibilityConstructor(Role.ProgressBar, AccessibilityInterface.Value);
436 // create necessary components
439 InitializeProgress();
440 InitializeIndeterminate();
442 indeterminateAnimation?.Stop();
443 indeterminateAnimation = null;
447 [EditorBrowsable(EditorBrowsableState.Never)]
448 public override void ApplyStyle(ViewStyle style)
450 base.ApplyStyle(style);
452 if (style is ProgressStyle progressStyle)
454 Debug.Assert(trackImage != null);
455 Debug.Assert(progressImage != null);
456 Debug.Assert(bufferImage != null);
458 trackImage.ApplyStyle(progressStyle.Track);
459 progressImage.ApplyStyle(progressStyle.Progress);
460 bufferImage.ApplyStyle(progressStyle.Buffer);
462 if (null != indeterminateImage && null != progressStyle.IndeterminateImageUrl)
464 indeterminateImage.URL = progressStyle.IndeterminateImageUrl;
470 /// Dispose Progress and all children on it.
472 /// <param name="type">Dispose type.</param>
473 /// <since_tizen> 6 </since_tizen>
474 protected override void Dispose(DisposeTypes type)
481 if (type == DisposeTypes.Explicit)
484 //Release your own managed resources here.
485 //You should release all of your own disposable objects here.
486 Utility.Dispose(trackImage);
487 Utility.Dispose(progressImage);
488 Utility.Dispose(bufferImage);
489 indeterminateImage = null;
492 //You must call base.Dispose(type) just before exit.
497 /// Change Image status. It can be override.
499 /// This needs to be considered more if public-open is necessary.
500 [EditorBrowsable(EditorBrowsableState.Never)]
501 private void UpdateStates()
503 ChangeImageState(state);
507 [EditorBrowsable(EditorBrowsableState.Never)]
508 public override void OnRelayout(Vector2 size, RelayoutContainer container)
510 if (size == null) return;
512 if (size.Equals(this.size))
517 this.size = new Vector2(size);
522 /// Update progress value
524 /// This needs to be considered more if public-open is necessary.
525 [EditorBrowsable(EditorBrowsableState.Never)]
526 private void UpdateValue()
528 if (null == trackImage || null == progressImage)
533 if (minValue >= maxValue || currentValue < minValue || currentValue > maxValue)
538 float width = this.SizeWidth;
539 float height = this.SizeHeight;
540 float progressRatio = (float)(currentValue - minValue) / (float)(maxValue - minValue);
541 float progressWidth = width * progressRatio;
542 progressImage.Size2D = new Size2D((int)(progressWidth + round), (int)height); //Add const round to reach Math.Round function.
543 if (null != bufferImage)
545 if (bufferValue < minValue || bufferValue > maxValue)
550 float bufferRatio = (float)(bufferValue - minValue) / (float)(maxValue - minValue);
551 float bufferWidth = width * bufferRatio;
552 bufferImage.Size2D = new Size2D((int)(bufferWidth + round), (int)height); //Add const round to reach Math.Round function.
556 private Vector4 destinationValue = new Vector4(-1.0f, 0.0f, 10.0f, 1.0f);
557 private Vector4 initialValue = new Vector4(0.0f, 0.0f, 10.0f, 1.0f);
560 /// Update Animation for Indeterminate mode.
562 /// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
563 [EditorBrowsable(EditorBrowsableState.Never)]
564 private void UpdateIndeterminateAnimation()
566 indeterminateAnimation?.Stop();
568 if (null != indeterminateImage)
570 indeterminateAnimation = AnimateVisual(indeterminateImage, "pixelArea", destinationValue, 0, 1000, AlphaFunction.BuiltinFunctions.Default, initialValue);
571 indeterminateAnimation.Looping = true;
572 indeterminateAnimation.Play();
577 /// Get Progress style.
579 /// <returns>The default progress style.</returns>
580 /// <since_tizen> 8 </since_tizen>
581 protected override ViewStyle CreateViewStyle()
583 return new ProgressStyle();
587 /// Change Image status
589 /// <since_tizen> 6 </since_tizen>
590 /// <param name="statusType">New status type</param>
591 protected void ChangeImageState(ProgressStatusType statusType)
593 if (statusType == ProgressStatusType.Buffering)
595 indeterminateAnimation?.Stop();
596 indeterminateAnimation = null;
598 if (null != indeterminateImage)
600 indeterminateImage.Opacity = 0.0f;
602 progressImage.Hide();
605 else if (statusType == ProgressStatusType.Determinate)
607 indeterminateAnimation?.Stop();
608 indeterminateAnimation = null;
610 if (null != indeterminateImage)
612 indeterminateImage.Opacity = 0.0f;
615 progressImage.Show();
619 else if (statusType == ProgressStatusType.Indeterminate)
622 progressImage.Hide();
623 if (null != indeterminateImage)
625 indeterminateImage.Opacity = 1.0f;
628 UpdateIndeterminateAnimation();
632 private void Initialize()
634 AccessibilityHighlightable = true;
637 private void InitializeTrack()
639 if (null == trackImage)
641 trackImage = new ImageView
643 WidthResizePolicy = ResizePolicyType.FillToParent,
644 HeightResizePolicy = ResizePolicyType.FillToParent,
645 PositionUsesPivotPoint = true,
646 ParentOrigin = NUI.ParentOrigin.TopLeft,
647 PivotPoint = NUI.PivotPoint.TopLeft
653 private void InitializeProgress()
655 if (null == progressImage)
657 progressImage = new ImageView
659 WidthResizePolicy = ResizePolicyType.FillToParent,
660 HeightResizePolicy = ResizePolicyType.FillToParent,
661 PositionUsesPivotPoint = true,
662 ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft,
663 PivotPoint = Tizen.NUI.PivotPoint.TopLeft
669 private void InitializeBuffer()
671 if (null == bufferImage)
673 bufferImage = new ImageView
675 WidthResizePolicy = ResizePolicyType.FillToParent,
676 HeightResizePolicy = ResizePolicyType.FillToParent,
677 PositionUsesPivotPoint = true,
678 ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft,
679 PivotPoint = Tizen.NUI.PivotPoint.TopLeft
682 bufferImage.Hide(); // At first, buffer image does not show.
686 private void InitializeIndeterminate()
688 indeterminateImage = new ImageVisual
690 PixelArea = new Vector4(0.0f, 0.0f, 10.0f, 1.0f),
691 WrapModeU = WrapModeType.Repeat,
692 SizePolicy = VisualTransformPolicyType.Relative,
693 Origin = Visual.AlignType.Center,
694 AnchorPoint = Visual.AlignType.Center,
696 Size = new Size2D(1, 1),
697 URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "nui_component_default_progress_indeterminate.png"
699 AddVisual("Indeterminate", indeterminateImage);
701 if (state == ProgressStatusType.Indeterminate)
703 indeterminateImage.Opacity = 1.0f;