134b9f20a5f5f64b3c398f2a64b76ea8830cead0
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / slider / slider-impl.h
1 #ifndef DALI_TOOLKIT_INTERNAL_SLIDER_H
2 #define DALI_TOOLKIT_INTERNAL_SLIDER_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/adaptor-framework/timer.h>
23 #include <dali/public-api/object/property-array.h>
24 #include <dali/public-api/object/property-map.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/devel-api/controls/control-devel.h>
28 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
29 #include <dali-toolkit/public-api/controls/control-impl.h>
30 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
31 #include <dali-toolkit/public-api/controls/slider/slider.h>
32 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
33
34 namespace Dali
35 {
36 namespace Toolkit
37 {
38 class Button;
39
40 namespace Internal
41 {
42 class Slider;
43
44 typedef Dali::IntrusivePtr<Slider> SliderPtr;
45
46 /**
47  * @copydoc Toolkit::Slider
48  */
49 class Slider : public Control
50 {
51 public:
52   typedef Property::Array MarkList;
53
54   /**
55    * Create a new Slider.
56    *
57    * @return A public handle to the newly allocated Slider.
58    */
59   static Dali::Toolkit::Slider New();
60
61 public:
62   // Properties
63
64   /**
65    * Set marks from a list
66    *
67    * @param[in] marks The list of marks to set
68    */
69   void SetMarks(const MarkList& marks);
70
71   /**
72    * Get the list of marks
73    *
74    * @return The marks list
75    */
76   const MarkList& GetMarks() const;
77
78   /**
79    * Set if should snap to marks or not
80    *
81    * @param[in] snap Flag to snap to marks or not
82    */
83   void SetSnapToMarks(bool snap);
84
85   /**
86    * Return if snap to marks is set or not
87    *
88    * @return If snap to marks is set
89    */
90   bool GetSnapToMarks() const;
91
92   /**
93    * Set the value of the slider
94    *
95    * @param[in] value The value to set. Will be clamped to [lowerBound .. upperBound]
96    */
97   void SetValue(float value);
98
99   /**
100    * Get the value of the slider
101    *
102    * @return The current value of the slider
103    */
104   float GetValue() const;
105
106   /**
107    * Set hit region
108    *
109    * @param[in] region The hit region
110    */
111   void SetHitRegion(const Vector2& region);
112
113   /**
114    * Get hit region
115    *
116    * @return The hit region
117    */
118   const Vector2& GetHitRegion() const;
119
120   /**
121    * Set the track region
122    *
123    * @param[in] region The track region
124    */
125   void SetTrackRegion(const Vector2& region);
126
127   /**
128    * Get the track region
129    *
130    * @return The track region
131    */
132   const Vector2& GetTrackRegion() const;
133
134   /**
135    * @brief Set the disabled color.
136    *
137    * @param[in] color The disabled color.
138    */
139   void SetDisabledColor(const Vector4& color);
140
141   /**
142    * @brief Get disabled color
143    *
144    * @return The disabled color
145    */
146   Vector4 GetDisabledColor() const;
147
148   /**
149    * Set the value precision to be used for numbers in the slider
150    *
151    * @param[in] precision The number of decimal places to use for printing numbers
152    */
153   void SetValuePrecision(int precision);
154
155   /**
156    * Get value precision
157    *
158    * @return The value precision
159    */
160   int GetValuePrecision() const;
161
162   /**
163    * Show the popup
164    *
165    * @param[in] showPopup The show popup flag
166    */
167   void SetShowPopup(bool showPopup);
168
169   /**
170    * Get show value in popup
171    *
172    * @return The show value flag
173    */
174   bool GetShowPopup() const;
175
176   /**
177    * Set show value on handle
178    *
179    * @param[in] showValue The show value flag
180    */
181   void SetShowValue(bool showValue);
182
183   /**
184    * Get show value on handle
185    *
186    * @return The show value flag
187    */
188   bool GetShowValue() const;
189
190   /**
191    * Set enabled
192    *
193    * param[in] enabled Set the enabled flag
194    */
195   void SetEnabled(bool enabled);
196
197   /**
198    * Return if enabled or not
199    *
200    * @return If enabled
201    */
202   bool IsEnabled() const;
203
204   /**
205    * @brief Set the mark tolerance
206    *
207    * The tolerance is the percentage of the slider width for which snapping to
208    * marks occurs
209    *
210    * @param[in] tolerance The percentage of width for which to snap
211    */
212   void SetMarkTolerance(float tolerance);
213
214   /**
215    * Return the mark tolerance
216    *
217    * @return The tolerance set for snapping to marks
218    */
219   float GetMarkTolerance() const;
220
221 public:
222   //Signals
223
224   /**
225    * @copydoc Toolkit::Slider::ValueChangedSignal()
226    */
227   Toolkit::Slider::ValueChangedSignalType& ValueChangedSignal();
228
229   /**
230    * copydoc Toolkit::Slider::SlidingFinishedSignal()
231    */
232   Toolkit::Slider::ValueChangedSignalType& SlidingFinishedSignal();
233
234   /**
235    * @copydoc Toolkit::Slider::MarkReachedSignal()
236    */
237   Toolkit::Slider::MarkReachedSignalType& MarkReachedSignal();
238
239   /**
240    * Connects a callback function with the object's signals.
241    * @param[in] object The object providing the signal.
242    * @param[in] tracker Used to disconnect the signal.
243    * @param[in] signalName The signal to connect to.
244    * @param[in] functor A newly allocated FunctorDelegate.
245    * @return True if the signal was connected.
246    * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
247    */
248   static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
249
250   // Properties
251
252   /**
253    * Called when a property of an object of this type is set.
254    * @param[in] object The object whose property is set.
255    * @param[in] index The property index.
256    * @param[in] value The new property value.
257    */
258   static void SetProperty(BaseObject* object, Property::Index index, const Property::Value& value);
259
260   /**
261    * Called to retrieve a property of an object of this type.
262    * @param[in] object The object whose property is to be retrieved.
263    * @param[in] index The property index.
264    * @return The current value of the property.
265    */
266   static Property::Value GetProperty(BaseObject* object, Property::Index propertyIndex);
267
268 protected:
269   /**
270    * Construct a new Slider.
271    */
272   Slider();
273
274   /**
275    * A reference counted object may only be deleted by calling Unreference()
276    */
277   virtual ~Slider();
278
279   /**
280    * @copydoc CustomActorImpl::OnRelayout
281    */
282   void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
283
284 private:
285   /**
286    * Domain is a from/to pair
287    */
288   struct Domain
289   {
290     Vector2 from;
291     Vector2 to;
292
293     Domain()
294     {
295     }
296     Domain(Vector2 fromVal, Vector2 toVal)
297     : from(fromVal),
298       to(toVal)
299     {
300     }
301   };
302
303   /**
304    * Slider states
305    */
306   enum SliderState
307   {
308     NORMAL,
309     DISABLED,
310     PRESSED,
311     FOCUSED
312   };
313
314 private:
315   /**
316    * @copydoc Toolkit::Control::OnInitialize()
317    */
318   void OnInitialize() override;
319
320   /**
321    * Hit region touch
322    *
323    * @param[in] actor The actor the event is raised for
324    * @param[in] touch The touch info
325    * @return If touch is handled or not
326    */
327   bool OnTouch(Actor actor, const TouchEvent& touch);
328
329   /**
330    * Pan gesture event
331    *
332    * @param[in] actor The actor the event is raised for
333    * @param[in] gesture The pan event info
334    */
335   void OnPan(Actor actor, const PanGesture& gesture);
336
337   /**
338    * Map a position onto a domain and return the result as a percentage
339    *
340    * @param[in] point The point to map onto the domain
341    * @return The result as a percentage [0..1]
342    */
343   float MapPercentage(const Vector2& point);
344
345   /**
346    * Map a value in the range to a percentage
347    *
348    * @param[in] point The value in range [lowerBound..upperBound]
349    * @return The result as a percentage [0..1]
350    */
351   float MapValuePercentage(float value);
352
353   /**
354    * Convert a point in local hit space into domain space
355    *
356    * @param[in] x The x position to convert
357    * @return The x position in domain space
358    */
359   float HitSpaceToDomain(float x);
360
361   /**
362    * Map a percentage onto the slider's bounds
363    *
364    * @param[in] percent The current value of slider in percent
365    * @param[in] lowerBound The lower bound to map onto
366    * @param[in] upperBound The upper bound to map onto
367    * @return The value of percent mapped from lowerBound to upperBound
368    */
369   float MapBounds(float percent, float lowerBound, float upperBound);
370
371   /**
372    * Get the range of the valid values the slider handle can move between
373    *
374    * @param[in] currentSize The current size of the slider
375    * @return The range as a domain pair
376    */
377   Domain CalcDomain(const Vector2& currentSize);
378
379   /**
380    * Create the hit region
381    *
382    * @return The hit region actor
383    */
384   Actor CreateHitRegion();
385
386   /**
387    * Create the track for the slider
388    *
389    * @return The track actor
390    */
391   Toolkit::ImageView CreateTrack();
392
393   /**
394    * Create the progress track for the slider
395    *
396    * @return The track actor
397    */
398   Toolkit::ImageView CreateProgress();
399
400   /**
401    * Create the handle for the slider
402    *
403    * @return The created image handle
404    */
405   Toolkit::ImageView CreateHandle();
406
407   /**
408    * Create the popup arrow
409    *
410    * @return The created image handle
411    */
412   Toolkit::ImageView CreatePopupArrow();
413
414   /**
415    * Create the popup
416    *
417    * @return The created image handle
418    */
419   Toolkit::ImageView CreatePopup();
420
421   /**
422    * Create the textview for the popup
423    *
424    * @return The textview created for the popup
425    */
426   Toolkit::TextLabel CreatePopupText();
427
428   /**
429    * Create the value display for the slider
430    *
431    * @return The created root actor of the display
432    */
433   Actor CreateValueDisplay();
434
435   /**
436    * Set the skin based on the current state
437    */
438   void UpdateSkin();
439
440   /**
441    * Create all the children
442    */
443   void CreateChildren();
444
445   /**
446    * Create value popup
447    */
448   void AddPopup();
449
450   /**
451    * Remove value popup
452    */
453   void RemovePopup();
454
455   /**
456    * Display the popup for a set duration with the given value
457    *
458    * @param[in] value The value to display in the popup
459    */
460   void DisplayPopup(float value);
461
462   /**
463    * If there are marks present, filter the incoming percent based on snapping to any nearby marks
464    *
465    * @param[in] value The incoming value on the slider to filter
466    * @return The filtered percentage snapped to any nearby marks
467    */
468   float MarkFilter(float value);
469
470   /**
471    * If there are marks present, snap the incoming percent to the nearest mark
472    *
473    * @param[in] value The incoming value on the slider to snap
474    * @return The filtered percentage snapped to the nearest mark
475    */
476   float SnapToMark(float value);
477
478   /**
479    * Search for if a mark has been reached
480    *
481    * @param[in] value The value to search against
482    * @param[out] outIndex The index of the mark if found
483    * @return If a mark has been found to match percent
484    */
485   bool MarkReached(float value, int& outIndex);
486
487   /**
488    * Handler for when the value view needs to be hidden
489    *
490    * @return If handled or not
491    */
492   bool HideValueView();
493
494   /**
495    * Set value choosing whether to fire signals or not
496    *
497    * @paramp[in] value The value to set
498    * @param[in] raiseSignals Configure signals to be raised or not.
499    */
500   void DisplayValue(float value, bool raiseSignals);
501
502   /**
503    * Create the image for the track
504    *
505    * @param[in] filename The track image
506    */
507   void SetTrackVisual(const std::string& filename);
508
509   /**
510    * @brief Set the track visual from an Dali::Property::Map
511    *
512    * @param[in] map The Dali::Property::Map to use for to display
513    */
514   void SetTrackVisual(Dali::Property::Map map);
515
516   /**
517    * @brief Return the track image.
518    *
519    * @return The track image.
520    */
521   std::string GetTrackVisual();
522
523   /**
524    * Create the image for the progress bar
525    *
526    * @param[in] filename The progress bar image
527    */
528   void SetProgressVisual(const std::string& filename);
529
530   /**
531    * @brief Set the progress visual from an Dali::Property::Map
532    *
533    * @param[in] map The Dali::Property::Map to use for to display
534    */
535   void SetProgressVisual(Dali::Property::Map map);
536
537   /**
538    * @brief Return the progress bar image.
539    *
540    * @return The progress bar image if it exists.
541    */
542   std::string GetProgressVisual();
543
544   /**
545    * @brief Create the image for the popup
546    *
547    * @param[in] filename The popup image
548    */
549   void CreatePopupImage(const std::string& filename);
550
551   /**
552    * @brief Set the popup image
553    *
554    * @param[in] filename The popup image to set
555    */
556   void SetPopupVisual(const std::string& filename);
557
558   /**
559    * @brief Set the popup from an Dali::Property::Map
560    *
561    * @param[in] map The Dali::Property::Map to use for to display
562    */
563   void SetPopupVisual(Dali::Property::Map map);
564
565   /**
566    * @brief Return the popup image.
567    *
568    * @return The popup image if it exists.
569    */
570   std::string GetPopupVisual();
571
572   /**
573    * @brief Set the popup arrow image
574    *
575    * @param[in] filename The popup arrow image to set
576    */
577   void SetPopupArrowVisual(const std::string& filename);
578
579   /**
580    * @brief Set the popup arrow from an Dali::Property::Map
581    *
582    * @param[in] map The Dali::Property::Map to use for to display
583    */
584   void SetPopupArrowVisual(Dali::Property::Map map);
585
586   /**
587    * @brief Return the popup arrow image.
588    *
589    * @return The popup arrow image if it exists.
590    */
591   std::string GetPopupArrowVisual();
592
593   /**
594    * Create the image for the popup arrow
595    *
596    * @param[in] filename The popup arrow image to load and set
597    */
598   void CreatePopupArrowImage(const std::string& filename);
599
600   /**
601    * Set the size of the progress bar region
602    *
603    * @param[in] region The size of the region to set
604    */
605   void ResizeProgressRegion(const Vector2& region);
606
607   /**
608    * Create the image for the handle
609    *
610    * @param[in] filename The handle image
611    */
612   void SetHandleVisual(const std::string& filename);
613
614   /**
615    * @brief Set the handle visual from an Dali::Property::Map
616    *
617    * @param[in] map The Dali::Property::Map to use for to display
618    */
619   void SetHandleVisual(Property::Map map);
620
621   /**
622    * @brief Return the handle image.
623    *
624    * @return The handle image if it exists.
625    */
626   std::string GetHandleVisual();
627
628   /**
629    * Reset the size of the handle
630    *
631    * @param[in] size The size of the handle to set
632    */
633   void ResizeHandleSize(const Vector2& size);
634
635   /**
636    * Create and display the value on the handle
637    */
638   void CreateHandleValueDisplay();
639
640   /**
641    * Remove and destroy the handle value display
642    */
643   void DestroyHandleValueDisplay();
644
645   /**
646    * Set the size of the handle
647    *
648    * @param[in] size The handle size
649    */
650   void SetHandleSize(const Vector2& size);
651
652   /**
653    * Get the size of the handle
654    *
655    * @return The handle size
656    */
657   const Vector2& GetHandleSize() const;
658
659   /**
660    * Set the lower bound of the slider's value
661    *
662    * @param[in] bound The value to set for the lower bound
663    */
664   void SetLowerBound(float bound);
665
666   /**
667    * Get the lower bound of the slider's value
668    *
669    * @return The lower bound value
670    */
671   float GetLowerBound() const;
672
673   /**
674    * Set the upper bound of the slider's value
675    *
676    * @param[in] bound The value to set for the upper bound
677    */
678   void SetUpperBound(float bound);
679
680   /**
681    * Get the upper bound of the slider's value
682    *
683    * @return The upper bound value
684    */
685   float GetUpperBound() const;
686
687 private:
688   // Undefined
689   Slider(const Slider&);
690
691   // Undefined
692   Slider& operator=(const Slider& rhs);
693
694 private:
695   Domain mDomain; ///< Current domain of the handle
696
697   Actor              mHitArea;      ///< The input handler
698   Actor              mValueDisplay; ///< Display of the value
699   Toolkit::ImageView mTrack;        ///< Track image
700   Toolkit::ImageView mHandle;       ///< Slider handle
701   Toolkit::ImageView mProgress;     ///< Progress bar
702   Toolkit::ImageView mPopup;        ///< Popup backing
703   Toolkit::ImageView mPopupArrow;   ///< Popup arrow backing
704
705   Toolkit::TextLabel mValueTextLabel;       //< The text value in popup
706   Toolkit::TextLabel mHandleValueTextLabel; ///< The text value on handle
707   Vector2            mHandleLastTouchPoint; ///< The last touch point for the handle
708   Timer              mValueTimer;           ///< Timer used to hide value view
709
710   Toolkit::Slider::ValueChangedSignalType mValueChangedSignal;    ///< Signal emitted when the value is changed
711   Toolkit::Slider::ValueChangedSignalType mSlidingFinishedSignal; ///< Signal emitted when a sliding is finished
712   Toolkit::Slider::MarkReachedSignalType  mMarkReachedSignal;     ///< Signal emitted when a mark is reached
713
714   SliderState mState; ///< The state of the slider
715
716   PanGestureDetector mPanDetector; ///< Hit region pan detector
717
718   MarkList mMarks; ///< List of discreet marks
719
720   std::string mPopupVisual;      ///< Image for popup image
721   std::string mPopupArrowVisual; ///< Image for popup arrow image
722   std::string mTrackVisual;      ///< Image for track image
723   std::string mHandleVisual;     ///< Image for handle image
724   std::string mProgressVisual;   ///< Image for progress bar image
725
726   Property::Map mPopupMap;      ///< the Property::Map if the image came from a Property::Map, empty otherwise
727   Property::Map mTrackMap;      ///< the Property::Map if the image came from a Property::Map, empty otherwise
728   Property::Map mHandleMap;     ///< the Property::Map if the image came from a Property::Map, empty otherwise
729   Property::Map mProgressMap;   ///< the Property::Map if the image came from a Property::Map, empty otherwise
730   Property::Map mPopupArrowMap; ///< the Property::Map if the image came from a Property::Map, empty otherwise
731
732   Vector4 mDisabledColor; ///< The color to tint the slider when disabled
733
734   Vector2 mHitRegion;   ///< Size of hit region
735   Vector2 mTrackRegion; ///< Size of track region
736   Vector2 mHandleSize;  ///< Size of the handle
737
738   float mLowerBound = 0.0f; ///< Lower bound on value
739   float mUpperBound = 1.0f; ///< Upper bound on value
740   float mValue      = 0.0f; ///< Current value of slider
741
742   float mMarkTolerance = 0.05f; ///< Tolerance in percentage of slider width for which to snap to marks
743
744   int mValuePrecision; ///< The precision to use for outputting the value
745
746   bool mShowPopup : 1, ///< Show the popup or not
747     mShowValue : 1,    ///< Whether to display the value number or not on the handle
748     mSnapToMarks : 1;  ///< Turn on or off snapping to marks
749
750 protected:
751   struct AccessibleImpl : public DevelControl::AccessibleImpl,
752                           public virtual Dali::Accessibility::Value
753   {
754     using DevelControl::AccessibleImpl::AccessibleImpl;
755     double GetMinimum() override;
756     double GetCurrent() override;
757     double GetMaximum() override;
758     bool   SetCurrent(double) override;
759     double GetMinimumIncrement() override;
760   };
761 };
762
763 } // namespace Internal
764
765 // Helpers for public-api forwarding methods
766
767 inline Toolkit::Internal::Slider& GetImpl(Toolkit::Slider& pub)
768 {
769   DALI_ASSERT_ALWAYS(pub);
770
771   Dali::RefObject& handle = pub.GetImplementation();
772
773   return static_cast<Toolkit::Internal::Slider&>(handle);
774 }
775
776 inline const Toolkit::Internal::Slider& GetImpl(const Toolkit::Slider& pub)
777 {
778   DALI_ASSERT_ALWAYS(pub);
779
780   const Dali::RefObject& handle = pub.GetImplementation();
781
782   return static_cast<const Toolkit::Internal::Slider&>(handle);
783 }
784
785 } // namespace Toolkit
786
787 } // namespace Dali
788
789 #endif // DALI_TOOLKIT_INTERNAL_SLIDER_H