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