eurorack/deprecated/midi2cv/menu/menu_items.h

263 lines
6.9 KiB
C
Raw Normal View History

2020-01-03 21:09:11 +00:00
#pragma once
#include "stmlib/stmlib.h"
#include <functional>
2020-01-03 21:09:11 +00:00
#include <stdio.h>
static auto always_visible = [] { return true; };
2020-01-03 21:09:11 +00:00
// MenuItem without template so we can easily store pointers
class AbstractMenuItem {
private:
std::function<bool()> visibility_indicator;
2020-01-03 21:09:11 +00:00
public:
AbstractMenuItem(std::function<bool()> visibility_indicator = always_visible)
: visibility_indicator(visibility_indicator) {};
bool visible()
{
if (visibility_indicator)
return visibility_indicator();
return true;
}
virtual const char* get_label() = 0;
virtual char* get_string_representation() = 0;
virtual void increase() = 0;
virtual void decrease() = 0;
2020-01-03 21:09:11 +00:00
};
template <class T>
class MenuItem : public AbstractMenuItem {
private:
const char* label;
T* value;
2020-01-03 21:09:11 +00:00
T step;
char stringRepresentation[24];
protected:
MenuItem()
: AbstractMenuItem(always_visible) {};
MenuItem(const char* _label, T* _value, std::function<bool()> visibility_indicator = always_visible)
: AbstractMenuItem(visibility_indicator)
, label(_label)
, value(_value) {};
2020-01-03 21:09:11 +00:00
virtual void to_string(char* buf) = 0;
void set_value(T value)
{
if (!this->value)
return;
*this->value = value;
2020-01-03 21:09:11 +00:00
this->to_string(stringRepresentation);
};
public:
bool visible()
{
if (this->visibility_indicator)
return this->visibility_indicator();
return true;
}
T* get_value_ptr()
2020-01-03 21:09:11 +00:00
{
return value;
}
const char* get_label()
{
return label;
}
char* get_string_representation()
{
if (!this->value) {
sprintf(stringRepresentation, "ERROR");
} else if (!stringRepresentation[0])
2020-02-17 19:33:01 +00:00
this->to_string(stringRepresentation);
2020-01-03 21:09:11 +00:00
return stringRepresentation;
}
};
template <class T>
class NumberMenuItem : public MenuItem<T> {
private:
T minimumValue;
T maximumValue;
2020-02-21 00:39:20 +00:00
T step;
2020-01-03 21:09:11 +00:00
protected:
NumberMenuItem() {};
NumberMenuItem(const char* _label, T* _value, T _minimumValue, T _maximumValue, T _step, std::function<bool()> visibility_indicator = always_visible)
: MenuItem<T>(_label, _value, visibility_indicator)
2020-01-03 21:09:11 +00:00
, minimumValue(_minimumValue)
2020-02-21 00:39:20 +00:00
, maximumValue(_maximumValue)
, step(_step) {};
2020-01-03 21:09:11 +00:00
virtual const char* get_format_string() = 0;
void to_string(char* buf)
{
sprintf(buf, this->get_format_string(), *this->get_value_ptr());
2020-01-03 21:09:11 +00:00
}
public:
void increase()
{
if (this->get_value_ptr())
if (*this->get_value_ptr() + step <= maximumValue && *this->get_value_ptr() + step >= minimumValue)
this->set_value(*this->get_value_ptr() + step);
2020-01-03 21:09:11 +00:00
};
void decrease()
{
if (this->get_value_ptr())
if (*this->get_value_ptr() - step >= minimumValue && *this->get_value_ptr() - step <= maximumValue)
this->set_value(*this->get_value_ptr() - step);
2020-01-03 21:09:11 +00:00
};
};
class UInt32MenuItem : public NumberMenuItem<uint32_t> {
2020-01-03 21:09:11 +00:00
private:
protected:
const char* get_format_string()
{
return "%u";
}
public:
UInt32MenuItem(const char* _label, uint32_t* _value, uint32_t _minimumValue, uint32_t _maximumValue, uint32_t _step, std::function<bool()> visibility_indicator = always_visible)
: NumberMenuItem(_label, _value, _minimumValue, _maximumValue, _step, visibility_indicator) {};
UInt32MenuItem() {};
2020-01-03 21:09:11 +00:00
};
class UInt8MenuItem : public NumberMenuItem<uint8_t> {
private:
protected:
const char* get_format_string()
{
return "%u";
}
public:
UInt8MenuItem(const char* _label, uint8_t* _value, uint8_t _minimumValue, uint8_t _maximumValue, uint8_t _step, std::function<bool()> visibility_indicator = always_visible)
: NumberMenuItem(_label, _value, _minimumValue, _maximumValue, _step, visibility_indicator) {};
UInt8MenuItem() {};
};
class Int32MenuItem : public NumberMenuItem<int32_t> {
private:
protected:
const char* get_format_string()
{
return "%d";
}
public:
Int32MenuItem(const char* _label, int32_t* _value, int32_t _minimumValue, int32_t _maximumValue, int32_t _step, std::function<bool()> visibility_indicator = always_visible)
: NumberMenuItem(_label, _value, _minimumValue, _maximumValue, _step, visibility_indicator) {};
Int32MenuItem();
};
class FloatMenuItem : public NumberMenuItem<float> {
private:
protected:
const char* get_format_string()
{
return "%.2f";
}
public:
FloatMenuItem(const char* _label, float* _value, float _minimumValue, float _maximumValue, float _step, std::function<bool()> visibility_indicator = always_visible)
: NumberMenuItem(_label, _value, _minimumValue, _maximumValue, _step, visibility_indicator) {};
FloatMenuItem() {};
};
class BoolMenuItem : public NumberMenuItem<bool> {
private:
const char* on_string;
const char* off_string;
protected:
const char* get_format_string()
{
bool value = false;
if (this->get_value_ptr())
value = *this->get_value_ptr();
if (value)
return this->on_string;
else
return this->off_string;
}
public:
BoolMenuItem(const char* _label, bool* _value, const char* _on_string, const char* _off_string, std::function<bool()> visibility_indicator = always_visible)
: NumberMenuItem(_label, _value, 0, 1, 1, visibility_indicator)
, on_string(_on_string)
, off_string(_off_string) {};
BoolMenuItem() {};
};
class StringListMenuItem : public NumberMenuItem<uint8_t> {
2020-02-23 00:34:26 +00:00
private:
const char** string_labels;
protected:
const char* get_format_string()
{
size_t index = 0;
if (this->get_value_ptr())
index = *this->get_value_ptr();
return this->string_labels[index];
2020-02-23 00:34:26 +00:00
}
public:
StringListMenuItem(const char* _label, uint8_t* _value, const char** _stringLabels, size_t _itemCount, std::function<bool()> visibility_indicator = always_visible)
: NumberMenuItem(_label, _value, 0, _itemCount - 1, 1, visibility_indicator)
2020-02-23 00:34:26 +00:00
, string_labels(_stringLabels) {};
StringListMenuItem() {};
2020-02-23 00:34:26 +00:00
};
2020-02-22 23:15:01 +00:00
class MidiNoteMenuItem : public NumberMenuItem<uint8_t> {
private:
char string_buffer[5];
2020-02-22 23:15:01 +00:00
const char* note_strings[12];
protected:
const char* get_format_string() { return ""; }
public:
char* get_string_representation()
{
uint8_t currentNote = 0;
if (this->get_value_ptr())
currentNote = *this->get_value_ptr();
2020-02-22 23:15:01 +00:00
int note = currentNote % 12;
int octave = (currentNote / 12) - 1;
sprintf(this->string_buffer, "%s%d", note_strings[note], octave);
return this->string_buffer;
}
MidiNoteMenuItem(const char* _label, uint8_t* _value, std::function<bool()> visibility_indicator = always_visible)
: NumberMenuItem(_label, _value, 0, 127, 1, visibility_indicator)
2020-02-22 23:15:01 +00:00
{
note_strings[0] = "C";
note_strings[1] = "C#";
note_strings[2] = "D";
note_strings[3] = "D#";
note_strings[4] = "E";
note_strings[5] = "F";
note_strings[6] = "F#";
note_strings[7] = "G";
note_strings[8] = "G#";
note_strings[9] = "A";
note_strings[10] = "A#";
note_strings[11] = "B";
};
MidiNoteMenuItem() {};
2020-02-22 23:15:01 +00:00
};