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

Generated by: LCOV version 1.15