2 * Copyright(c) 2020 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 Tizen.NUI.Components;
21 using System.ComponentModel;
23 namespace Tizen.NUI.Wearable
26 /// The CircularProgress class of Wearable is used to show the ongoing status with a circular bar.
27 /// CircularProgress can be counted in its percentage.
29 [EditorBrowsable(EditorBrowsableState.Never)]
30 public class CircularProgress : Control
34 /// <summary>Bindable property of Thickness</summary>
35 [EditorBrowsable(EditorBrowsableState.Never)]
36 public static readonly BindableProperty ThicknessProperty = BindableProperty.Create(nameof(Thickness), typeof(float), typeof(CircularProgress), default(float), propertyChanged: (bindable, oldValue, newValue) =>
38 var instance = ((CircularProgress)bindable);
39 instance.CurrentStyle.Thickness = (float)newValue;
40 instance.UpdateVisualThickness((float)newValue);
42 defaultValueCreator: (bindable) =>
44 return ((CircularProgress)bindable).CurrentStyle.Thickness;
47 /// <summary>Bindable property of MaxValue</summary>
48 [EditorBrowsable(EditorBrowsableState.Never)]
49 public static readonly BindableProperty MaxValueProperty = BindableProperty.Create(nameof(MaxValue), typeof(float), typeof(CircularProgress), default(float), propertyChanged: (bindable, oldValue, newValue) =>
51 var instance = (CircularProgress)bindable;
54 instance.maxValue = (float)newValue;
55 instance.UpdateValue();
58 defaultValueCreator: (bindable) =>
60 var instance = (CircularProgress)bindable;
61 return instance.maxValue;
64 /// <summary>Bindable property of MinValue</summary>
65 [EditorBrowsable(EditorBrowsableState.Never)]
66 public static readonly BindableProperty MinValueProperty = BindableProperty.Create(nameof(MinValue), typeof(float), typeof(CircularProgress), default(float), propertyChanged: (bindable, oldValue, newValue) =>
68 var instance = (CircularProgress)bindable;
71 instance.minValue = (float)newValue;
72 instance.UpdateValue();
75 defaultValueCreator: (bindable) =>
77 var instance = (CircularProgress)bindable;
78 return instance.minValue;
81 /// <summary>Bindable property of CurrentValue</summary>
82 [EditorBrowsable(EditorBrowsableState.Never)]
83 public static readonly BindableProperty CurrentValueProperty = BindableProperty.Create(nameof(CurrentValue), typeof(float), typeof(CircularProgress), default(float), propertyChanged: (bindable, oldValue, newValue) =>
85 var instance = (CircularProgress)bindable;
88 if ((float)newValue > instance.maxValue || (float)newValue < instance.minValue)
92 instance.currentValue = (float)newValue;
93 instance.UpdateValue();
96 defaultValueCreator: (bindable) =>
98 var instance = (CircularProgress)bindable;
99 return instance.currentValue;
102 /// <summary>Bindable property of TrackColor</summary>
103 [EditorBrowsable(EditorBrowsableState.Never)]
104 public static readonly BindableProperty TrackColorProperty = BindableProperty.Create(nameof(TrackColor), typeof(Color), typeof(CircularProgress), null, propertyChanged: (bindable, oldValue, newValue) =>
106 var instance = (CircularProgress)bindable;
107 instance.CurrentStyle.TrackColor = (Color)newValue;
108 instance.UpdateTrackVisualColor((Color)newValue);
110 defaultValueCreator: (bindable) =>
112 return ((CircularProgress)bindable).CurrentStyle.TrackColor;
115 /// <summary>Bindable property of ProgressColor</summary>
116 [EditorBrowsable(EditorBrowsableState.Never)]
117 public static readonly BindableProperty ProgressColorProperty = BindableProperty.Create(nameof(ProgressColor), typeof(Color), typeof(CircularProgress), null, propertyChanged: (bindable, oldValue, newValue) =>
119 var instance = (CircularProgress)bindable;
120 instance.CurrentStyle.ProgressColor = (Color)newValue;
121 instance.UpdateProgressVisualColor((Color)newValue);
123 defaultValueCreator: (bindable) =>
125 return ((CircularProgress)bindable).CurrentStyle.ProgressColor;
128 /// <summary>Bindable property of IsEnabled</summary>
129 [EditorBrowsable(EditorBrowsableState.Never)]
130 public static readonly BindableProperty IsEnabledProperty = BindableProperty.Create(nameof(IsEnabled), typeof(bool), typeof(CircularProgress), true, propertyChanged: (bindable, oldValue, newValue) =>
132 var instance = (CircularProgress)bindable;
133 if (newValue != null)
135 instance.privateIsEnabled = (bool)newValue;
138 defaultValueCreator: (bindable) =>
140 var instance = (CircularProgress)bindable;
141 return instance.privateIsEnabled;
144 private const string TrackVisualName = "Track";
145 private const string ProgressVisualName = "Progress";
146 private ArcVisual trackVisual;
147 private ArcVisual progressVisual;
149 private float maxValue = 100;
150 private float minValue = 0;
151 private float currentValue = 0;
152 private bool isEnabled = true;
154 private Animation sweepAngleAnimation;
161 static CircularProgress() { }
163 /// The constructor of CircularProgress.
164 /// Basically, CircularProgress is for full screen. (360 x 360)
165 /// But, it also can be displayed on the button or the list for small size.
166 /// User can set its size.
168 [EditorBrowsable(EditorBrowsableState.Never)]
169 public CircularProgress() : base(new CircularProgressStyle())
175 /// The constructor of the CircularProgress class with specific style.
177 /// <param name="style">style name</param>
178 [EditorBrowsable(EditorBrowsableState.Never)]
179 public CircularProgress(string style) : base(style)
185 /// The constructor of the CircularProgress class with specific style.
187 /// <param name="progressStyle">The style object to initialize the CircularProgress.</param>
188 [EditorBrowsable(EditorBrowsableState.Never)]
189 public CircularProgress(CircularProgressStyle progressStyle) : base(progressStyle)
194 #endregion Constructors
200 /// Return a copied Style instance of CircularProgress
203 /// It returns copied Style instance and changing it does not effect to the CircularProgress.
204 /// Style setting is possible by using constructor or the function of ApplyStyle(ViewStyle viewStyle)
206 [EditorBrowsable(EditorBrowsableState.Never)]
207 public new CircularProgressStyle Style
211 var result = new CircularProgressStyle(ViewStyle as CircularProgressStyle);
212 result.CopyPropertiesFromView(this);
218 /// The thickness of the track and progress.
220 [EditorBrowsable(EditorBrowsableState.Never)]
221 public float Thickness
225 return (float)GetValue(ThicknessProperty);
229 SetValue(ThicknessProperty, value);
234 /// The property to get/set the maximum value of the CircularProgress.
235 /// The default value is 100.
237 [EditorBrowsable(EditorBrowsableState.Never)]
238 public float MaxValue
242 return (float)GetValue(MaxValueProperty);
246 SetValue(MaxValueProperty, value);
251 /// The property to get/set the minimum value of the CircularProgress.
252 /// The default value is 0.
254 [EditorBrowsable(EditorBrowsableState.Never)]
255 public float MinValue
259 return (float)GetValue(MinValueProperty);
263 SetValue(MinValueProperty, value);
268 /// The property to get/set the current value of the CircularProgress.
269 /// The default value is 0.
271 [EditorBrowsable(EditorBrowsableState.Never)]
272 public float CurrentValue
276 return (float)GetValue(CurrentValueProperty);
280 if (sweepAngleAnimation)
282 sweepAngleAnimation.Stop();
284 sweepAngleAnimation = AnimateVisual(progressVisual, "sweepAngle", progressVisual.SweepAngle, 0, 100, AlphaFunction.BuiltinFunctions.EaseIn);
286 SetValue(CurrentValueProperty, value);
293 /// The property to get/set Track object color of the CircularProgress.
295 [EditorBrowsable(EditorBrowsableState.Never)]
296 public Color TrackColor
300 return (Color)GetValue(TrackColorProperty);
304 SetValue(TrackColorProperty, value);
309 /// The property to get/set Progress object color of the CircularProgress.
311 [EditorBrowsable(EditorBrowsableState.Never)]
312 public Color ProgressColor
316 return (Color)GetValue(ProgressColorProperty);
320 SetValue(ProgressColorProperty, value);
325 /// Flag to be enabled or disabled in CircularProgress.
327 [EditorBrowsable(EditorBrowsableState.Never)]
328 public bool IsEnabled
332 return (bool)GetValue(IsEnabledProperty);
336 SetValue(IsEnabledProperty, value);
339 private bool privateIsEnabled
350 ControlState = ControlState.Normal;
352 UpdateTrackVisualColor(new Color(0.0f, 0.16f, 0.30f, 1.0f)); // #002A4D
356 ControlState = ControlState.Disabled;
358 UpdateTrackVisualColor(new Color(0.25f, 0.25f, 0.25f, 1.0f)); // #404040
363 private CircularProgressStyle CurrentStyle => ViewStyle as CircularProgressStyle;
365 #endregion Properties
371 /// Dispose Progress and all children on it.
373 /// <param name="type">Dispose type.</param>
374 [EditorBrowsable(EditorBrowsableState.Never)]
375 protected override void Dispose(DisposeTypes type)
382 if (type == DisposeTypes.Explicit)
385 progressVisual = null;
392 /// Update progress value
394 [EditorBrowsable(EditorBrowsableState.Never)]
395 protected virtual void UpdateValue()
397 if (null == trackVisual || null == progressVisual)
402 if (minValue >= maxValue || currentValue < minValue || currentValue > maxValue)
407 HandleProgressVisualVisibility();
409 UpdateProgressVisualSweepAngle();
413 /// Get Progress style.
415 /// <returns>The default progress style.</returns>
416 [EditorBrowsable(EditorBrowsableState.Never)]
417 protected override ViewStyle CreateViewStyle()
419 return new CircularProgressStyle();
423 [EditorBrowsable(EditorBrowsableState.Never)]
424 protected override void OnControlStateChanged(ControlStateChangedEventArgs controlStateChangedInfo)
426 base.OnControlStateChanged(controlStateChangedInfo);
428 var stateEnabled = !controlStateChangedInfo.CurrentState.Contains(ControlState.Disabled);
430 if (isEnabled != stateEnabled)
432 isEnabled = stateEnabled;
437 private void Initialize()
439 Size = new Size(360.0f, 360.0f);
441 sweepAngleAnimation?.Stop();
442 sweepAngleAnimation = null;
444 trackVisual = new ArcVisual
446 SuppressUpdateVisual = true,
447 Thickness = this.Thickness,
448 Cap = ArcVisual.CapType.Butt,
449 MixColor = TrackColor,
453 this.AddVisual(TrackVisualName, trackVisual);
455 progressVisual = new ArcVisual
457 SuppressUpdateVisual = true,
458 Thickness = this.Thickness,
459 Cap = ArcVisual.CapType.Butt,
460 MixColor = ProgressColor,
464 this.AddVisual(ProgressVisualName, progressVisual);
466 HandleProgressVisualVisibility();
468 UpdateProgressVisualSweepAngle();
471 private void HandleProgressVisualVisibility()
475 progressVisual.Opacity = 1.0f;
479 progressVisual.Opacity = 0.6f;
483 private void UpdateVisualThickness(float thickness)
485 if (trackVisual == null)
490 trackVisual.Thickness = thickness;
491 progressVisual.Thickness = thickness;
493 trackVisual.UpdateVisual(true);
494 progressVisual.UpdateVisual(true);
497 private void UpdateProgressVisualSweepAngle()
499 float progressRatio = (float)(currentValue - minValue) / (float)(maxValue - minValue);
500 float progressWidth = 360.0f * progressRatio; // Circle
501 progressVisual.SweepAngle = progressWidth;
503 if (!sweepAngleAnimation)
505 progressVisual.UpdateVisual(true);
509 private void UpdateAnimation()
511 // TODO : Currently not sure which effect is needed.
512 AlphaFunction.BuiltinFunctions builtinAlphaFunction = AlphaFunction.BuiltinFunctions.EaseIn;
514 if (sweepAngleAnimation)
516 sweepAngleAnimation.Stop();
519 sweepAngleAnimation = AnimateVisual(progressVisual, "sweepAngle", progressVisual.SweepAngle, 0, 100, builtinAlphaFunction);
521 if (sweepAngleAnimation)
523 sweepAngleAnimation.Play();
528 private void UpdateTrackVisualColor(Color trackColor)
530 if (trackVisual == null)
535 trackVisual.MixColor = trackColor;
536 trackVisual.UpdateVisual(true);
539 private void UpdateProgressVisualColor(Color progressColor)
541 if (progressVisual == null)
546 progressVisual.MixColor = progressColor;
547 if (!isEnabled) // Dim state
549 progressVisual.Opacity = 0.6f;
552 progressVisual.UpdateVisual(true);