LCOV - code coverage report
Current view: top level - src/Selectors - Selector.hpp (source / functions) Hit Total Coverage
Test: 90a1b9beff85a60dc6ebcea034a947a845e56960 Lines: 44 44 100.0 %
Date: 2019-11-30 15:53:32 Functions: 31 55 56.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "Selectable.hpp"
       4             : #include <AH/Containers/Updatable.hpp>
       5             : #include <AH/Debug/Debug.hpp>
       6             : #include <Def/Def.hpp>
       7             : 
       8             : BEGIN_CS_NAMESPACE
       9             : 
      10             : /**
      11             :  * @brief   An enumeration to set the behavior of selectors that are incremented
      12             :  *          (decremented) beyond their maximum (minimum) setting.
      13             :  */
      14             : enum class Wrap : bool {
      15             :     Clamp = false, ///< When the maximum (minimum) setting is reached,
      16             :                    ///< clamp to the maximum (minimum) setting.
      17             :                    ///< @todo  Rename to `Clamp`?
      18             :     Wrap = true,   ///< When the maximum (minimum) setting is reached,
      19             :                    ///< wrap around to the minimum (maximum) setting.
      20             :     NoWrap = false,
      21             : };
      22             : 
      23             : /// A callback for the GenericSelector class that does nothing.
      24             : struct EmptySelectorCallback {
      25             :     /// Initialize.
      26           8 :     void begin() {}
      27             :     /// Refresh, called periodically.
      28          20 :     void update() {}
      29             :     /// Called when the setting changes.
      30          18 :     void update(setting_t oldSetting, setting_t newSetting) {
      31             :         (void)oldSetting, (void)newSetting;
      32          18 :     }
      33             : };
      34             : 
      35             : /// Base class for all Selectors exposing the `get` method, so it can be used
      36             : /// by display elements etc, without having to provide the full generic type.
      37             : ///
      38             : /// A `set` method is not provided, because that would require either more
      39             : /// virtual functions, or a rather large refactoring.
      40             : class SelectorBase {
      41             :   protected:
      42             :     /// Constructor.
      43          20 :     SelectorBase() = default;
      44             : 
      45             :   public:
      46             :     /// Get the current selection/setting.
      47          61 :     setting_t get() const { return setting; }
      48             : 
      49             :   protected:
      50             :     /// The selection of the selector. It is saved in the selector as well as
      51             :     /// the selectable, because you need it in order to implement
      52             :     /// increment/decrement methods.
      53          20 :     setting_t setting = 0;
      54             : };
      55             : 
      56             : template <setting_t N, class Callback = EmptySelectorCallback>
      57          20 : class GenericSelector : public SelectorBase, public AH::Updatable<> {
      58             :   public:
      59             :     /**
      60             :      * @brief   Constructor.
      61             :      * 
      62             :      * @param   selectable
      63             :      *          The selectable object to manage. When the value of the selector
      64             :      *          changes, it changes the selection of this selectable.
      65             :      * @param   callback
      66             :      *          The callback to call when the value changes. Used for (visual)
      67             :      *          feedback from the selector (e.g. LEDs or some different kind of
      68             :      *          display).
      69             :      */
      70          20 :     GenericSelector(Selectable<N> &selectable, const Callback &callback)
      71          60 :         : selectable(selectable), callback(callback) {}
      72             : 
      73           8 :     void begin() override {
      74           8 :         callback.begin();
      75           8 :         reset();
      76           8 :     }
      77             : 
      78          20 :     void update() override { callback.update(); }
      79             : 
      80             :     /// Reset the selection to the initial selection.
      81           9 :     void reset() { set(selectable.getInitialSelection()); }
      82             : 
      83             :     /** 
      84             :      * @brief   Select the given selection
      85             :      * 
      86             :      * @param   newSetting
      87             :      *          The new setting to select [0, N-1].
      88             :      */
      89          26 :     void set(setting_t newSetting) {
      90          26 :         newSetting = selectable.validateSetting(newSetting);
      91          26 :         selectable.select(newSetting);
      92          26 :         if (get() != newSetting) {
      93          18 :             callback.update(get(), newSetting);
      94          18 :             setting = newSetting;
      95          18 :         }
      96          26 :     }
      97             : 
      98             :     /**
      99             :      * @brief   Add one to the setting, wrap around or clamp, depending on the
     100             :      *          parameter, if the new setting would be out of range.
     101             :      * 
     102             :      * @param   wrap 
     103             :      *          Wrap or clamp if the new setting would be out of range.
     104             :      */
     105          11 :     void increment(Wrap wrap) {
     106          11 :         setting_t setting = this->get();
     107          11 :         setting++;
     108          11 :         if (setting == N) {
     109           4 :             if (wrap == Wrap::Wrap)
     110           2 :                 setting = 0;
     111             :             else
     112           2 :                 return;
     113           2 :         }
     114           9 :         this->set(setting);
     115          11 :     }
     116             : 
     117             :     /**
     118             :      * @brief   Subtract one from the setting, wrap around or clamp, depending 
     119             :      *          on the parameter, if the new setting would be out of range.
     120             :      * 
     121             :      * @param   wrap 
     122             :      *          Wrap or clamp if the new setting would be out of range.
     123             :      */
     124           5 :     void decrement(Wrap wrap) {
     125           5 :         setting_t setting = this->get();
     126           5 :         if (setting == 0) {
     127           2 :             if (wrap == Wrap::Wrap)
     128           1 :                 setting = N;
     129             :             else
     130           1 :                 return;
     131           1 :         }
     132           4 :         setting--;
     133           4 :         this->set(setting);
     134           5 :     }
     135             : 
     136             :   private:
     137             :     Selectable<N> &selectable;
     138             : 
     139             :   public:
     140             :     Callback callback;
     141             : };
     142             : 
     143             : /** 
     144             :  * @brief   A Selector with an empty callback.
     145             :  * 
     146             :  * @tparam  N
     147             :  *          The number of possible settings.
     148             :  */
     149             : template <setting_t N>
     150             : class Selector : public GenericSelector<N> {
     151             :   public:
     152             :     /// Constructor
     153             :     Selector(Selectable<N> &selectable) : GenericSelector<N>{selectable, {}} {}
     154             : };
     155             : 
     156             : END_CS_NAMESPACE

Generated by: LCOV version 1.14-5-g4ff2ed6