Skip to content

File UI.h

File List > external-docs > libDaisy > src > ui > UI.h

Go to the documentation of this file

Source Code

#pragma once
#include <initializer_list>
#include "UiEventQueue.h"
#include "../util/Stack.h"

namespace daisy
{
class UI;

enum class ArrowButtonType
{
    left = 0,
    right,
    up,
    down
};

struct UiCanvasDescriptor
{
    uint8_t id_;

    void* handle_;

    uint32_t updateRateMs_;

    uint32_t screenSaverTimeOut = 0;

    bool screenSaverOn = false;

    using ClearFuncPtr = void (*)(const UiCanvasDescriptor& canvasToClear);
    ClearFuncPtr clearFunction_;

    using FlushFuncPtr = void (*)(const UiCanvasDescriptor& canvasToFlush);
    FlushFuncPtr flushFunction_;
};

class OneBitGraphicsLookAndFeel;

class UiPage
{
  public:
    UiPage() : parent_(nullptr) {}

    virtual ~UiPage() {}

    virtual bool IsOpaque(const UiCanvasDescriptor& display)
    {
        (void)(display); // silence unused variable warnings
        return true;
    }

    bool IsActive() { return parent_ != nullptr; }

    virtual void OnUserInteraction() {}

    void Close();

    virtual bool OnOkayButton(uint8_t numberOfPresses, bool isRetriggering)
    {
        (void)(numberOfPresses); // silence unused variable warnings
        (void)(isRetriggering);  // silence unused variable warnings
        return true;
    }

    virtual bool OnCancelButton(uint8_t numberOfPresses, bool isRetriggering)
    {
        (void)(numberOfPresses); // silence unused variable warnings
        (void)(isRetriggering);  // silence unused variable warnings
        return true;
    }

    virtual bool OnArrowButton(ArrowButtonType arrowType,
                               uint8_t         numberOfPresses,
                               bool            isRetriggering)
    {
        (void)(arrowType);       // silence unused variable warnings
        (void)(numberOfPresses); // silence unused variable warnings
        (void)(isRetriggering);  // silence unused variable warnings
        return true;
    }

    virtual bool OnFunctionButton(uint8_t numberOfPresses, bool isRetriggering)
    {
        (void)(numberOfPresses); // silence unused variable warnings
        (void)(isRetriggering);  // silence unused variable warnings
        return true;
    }

    virtual bool
    OnButton(uint16_t buttonID, uint8_t numberOfPresses, bool isRetriggering)
    {
        (void)(buttonID);        // silence unused variable warnings
        (void)(numberOfPresses); // silence unused variable warnings
        (void)(isRetriggering);  // silence unused variable warnings
        return true;
    }

    virtual bool OnMenuEncoderTurned(int16_t turns, uint16_t stepsPerRevolution)
    {
        (void)(turns);              // silence unused variable warnings
        (void)(stepsPerRevolution); // silence unused variable warnings
        return true;
    }

    virtual bool OnValueEncoderTurned(int16_t  turns,
                                      uint16_t stepsPerRevolution)
    {
        (void)(turns);              // silence unused variable warnings
        (void)(stepsPerRevolution); // silence unused variable warnings
        return true;
    }

    virtual bool OnEncoderTurned(uint16_t encoderID,
                                 int16_t  turns,
                                 uint16_t stepsPerRevolution)
    {
        (void)(encoderID);          // silence unused variable warnings
        (void)(turns);              // silence unused variable warnings
        (void)(stepsPerRevolution); // silence unused variable warnings
        return true;
    }

    virtual bool OnMenuEncoderActivityChanged(bool isCurrentlyActive)
    {
        (void)(isCurrentlyActive); // silence unused variable warnings
        return true;
    }

    virtual bool OnValueEncoderActivityChanged(bool isCurrentlyActive)
    {
        (void)(isCurrentlyActive); // silence unused variable warnings
        return true;
    }

    virtual bool OnEncoderActivityChanged(uint16_t encoderID,
                                          bool     isCurrentlyActive)
    {
        (void)(encoderID);         // silence unused variable warnings
        (void)(isCurrentlyActive); // silence unused variable warnings
        return true;
    }

    virtual bool OnValuePotMoved(float newPosition)
    {
        (void)(newPosition); // silence unused variable warnings
        return true;
    }

    virtual bool OnPotMoved(uint16_t potID, float newPosition)
    {
        (void)(potID);       // silence unused variable warnings
        (void)(newPosition); // silence unused variable warnings
        return true;
    }

    virtual bool OnValuePotActivityChanged(bool isCurrentlyActive)
    {
        (void)(isCurrentlyActive); // silence unused variable warnings
        return true;
    }

    virtual bool OnPotActivityChanged(uint16_t potID, bool isCurrentlyActive)
    {
        (void)(potID);             // silence unused variable warnings
        (void)(isCurrentlyActive); // silence unused variable warnings
        return true;
    }

    virtual void OnShow(){};

    virtual void OnHide(){};

    virtual void OnFocusGained(){};

    virtual void OnFocusLost(){};

    virtual void Draw(const UiCanvasDescriptor& canvas) = 0;

    UI* GetParentUI() { return parent_; }
    const UI* GetParentUI() const { return parent_; }

  private:
    friend class UI;
    UI* parent_;
};

class UI
{
  public:
    UI();
    ~UI();

    struct SpecialControlIds
    {
        uint16_t funcBttnId   = UiEventQueue::invalidButtonId;
        uint16_t okBttnId     = UiEventQueue::invalidButtonId;
        uint16_t cancelBttnId = UiEventQueue::invalidButtonId;
        uint16_t upBttnId     = UiEventQueue::invalidButtonId;
        uint16_t downBttnId   = UiEventQueue::invalidButtonId;
        uint16_t leftBttnId   = UiEventQueue::invalidButtonId;
        uint16_t rightBttnId  = UiEventQueue::invalidButtonId;
        uint16_t menuEncoderId = UiEventQueue::invalidEncoderId;
        uint16_t valueEncoderId = UiEventQueue::invalidEncoderId;
        uint16_t valuePotId = UiEventQueue::invalidPotId;
    };

    static constexpr uint16_t invalidCanvasId = uint16_t(-1);

    void Init(UiEventQueue&                             inputQueue,
              const SpecialControlIds&                  specialControlIds,
              std::initializer_list<UiCanvasDescriptor> canvases,
              uint16_t primaryOneBitGraphicsDisplayId = invalidCanvasId);

    void Process();

    void Mute(bool shouldBeMuted, bool queueEvents = false);

    void OpenPage(UiPage& page);

    void ClosePage(UiPage& page);

    uint16_t GetPrimaryOneBitGraphicsDisplayId() const
    {
        return primaryOneBitGraphicsDisplayId_;
    }

    SpecialControlIds GetSpecialControlIds() const
    {
        return specialControlIds_;
    }

  private:
    bool                                       isMuted_;
    bool                                       queueEvents_;
    static constexpr int                       kMaxNumPages    = 32;
    static constexpr int                       kMaxNumCanvases = 8;
    Stack<UiPage*, kMaxNumPages>               pages_;
    Stack<UiCanvasDescriptor, kMaxNumCanvases> canvases_;
    uint32_t          lastUpdateTimes_[kMaxNumCanvases];
    uint32_t          lastEventTime_;
    UiEventQueue*     eventQueue_;
    SpecialControlIds specialControlIds_;
    uint16_t          primaryOneBitGraphicsDisplayId_ = invalidCanvasId;

    // internal
    void RemovePage(UiPage* page);
    void AddPage(UiPage* p);
    void ProcessEvent(const UiEventQueue::Event& m);
    void RedrawCanvas(uint8_t index, uint32_t currentTimeInMs);
    void ForwardToButtonHandler(uint16_t buttonID,
                                uint8_t  numberOfPresses,
                                bool     isRetriggering);
    void RebuildPageVisibilities();
};

} // namespace daisy