LCOV - code coverage report
Current view: top level - src/Selectors - Selector.hpp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 100.0 % 42 42
Test Date: 2026-06-06 17:44:35 Functions: 58.1 % 43 25
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 2.4-beta