2020-01-03 21:09:11 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "stmlib/stmlib.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
// MenuItem without template so we can easily store pointers
|
|
|
|
class AbstractMenuItem {
|
|
|
|
public:
|
|
|
|
virtual const char* get_label();
|
|
|
|
virtual char* get_string_representation();
|
2020-02-21 00:39:20 +00:00
|
|
|
virtual void increase();
|
|
|
|
virtual void decrease();
|
2020-01-03 21:09:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
class MenuItem : public AbstractMenuItem {
|
|
|
|
private:
|
|
|
|
const char* label;
|
2020-02-23 13:25:36 +00:00
|
|
|
T* value;
|
2020-01-03 21:09:11 +00:00
|
|
|
T step;
|
|
|
|
char stringRepresentation[24];
|
|
|
|
|
|
|
|
protected:
|
2020-02-23 16:14:07 +00:00
|
|
|
MenuItem() {};
|
2020-02-23 13:25:36 +00:00
|
|
|
MenuItem(const char* _label, T* _value)
|
2020-01-03 21:09:11 +00:00
|
|
|
: label(_label)
|
2020-02-23 13:25:36 +00:00
|
|
|
, value(_value) {};
|
2020-01-03 21:09:11 +00:00
|
|
|
|
|
|
|
virtual void to_string(char* buf) = 0;
|
|
|
|
|
|
|
|
void set_value(T value)
|
|
|
|
{
|
2020-02-23 16:14:07 +00:00
|
|
|
if (!this->value)
|
|
|
|
return;
|
2020-02-23 13:25:36 +00:00
|
|
|
*this->value = value;
|
2020-01-03 21:09:11 +00:00
|
|
|
this->to_string(stringRepresentation);
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2020-02-23 13:25:36 +00:00
|
|
|
T* get_value_ptr()
|
2020-01-03 21:09:11 +00:00
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* get_label()
|
|
|
|
{
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* get_string_representation()
|
|
|
|
{
|
2020-02-23 16:14:07 +00:00
|
|
|
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:
|
2020-02-23 16:14:07 +00:00
|
|
|
NumberMenuItem() {};
|
2020-02-23 13:25:36 +00:00
|
|
|
NumberMenuItem(const char* _label, T* _value, T _minimumValue, T _maximumValue, T _step)
|
|
|
|
: MenuItem<T>(_label, _value)
|
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)
|
|
|
|
{
|
2020-02-23 13:25:36 +00:00
|
|
|
sprintf(buf, this->get_format_string(), *this->get_value_ptr());
|
2020-01-03 21:09:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
void increase()
|
|
|
|
{
|
2020-02-23 16:14:07 +00:00
|
|
|
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()
|
|
|
|
{
|
2020-02-23 16:14:07 +00:00
|
|
|
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
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2020-02-23 13:25:36 +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:
|
2020-02-23 13:25:36 +00:00
|
|
|
UInt32MenuItem(const char* _label, uint32_t* _value, uint32_t _minimumValue, uint32_t _maximumValue, uint32_t _step)
|
|
|
|
: NumberMenuItem(_label, _value, _minimumValue, _maximumValue, _step) {};
|
2020-02-23 16:14:07 +00:00
|
|
|
UInt32MenuItem() {};
|
2020-01-03 21:09:11 +00:00
|
|
|
};
|
|
|
|
|
2020-02-23 13:25:36 +00:00
|
|
|
class Int32MenuItem : public NumberMenuItem<int32_t> {
|
2020-02-22 23:58:21 +00:00
|
|
|
private:
|
|
|
|
protected:
|
|
|
|
const char* get_format_string()
|
|
|
|
{
|
|
|
|
return "%d";
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2020-02-23 13:25:36 +00:00
|
|
|
Int32MenuItem(const char* _label, int32_t* _value, int32_t _minimumValue, int32_t _maximumValue, int32_t _step)
|
|
|
|
: NumberMenuItem(_label, _value, _minimumValue, _maximumValue, _step) {};
|
2020-02-23 16:14:07 +00:00
|
|
|
Int32MenuItem();
|
2020-02-22 23:58:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class FloatMenuItem : public NumberMenuItem<float> {
|
|
|
|
private:
|
|
|
|
protected:
|
|
|
|
const char* get_format_string()
|
|
|
|
{
|
|
|
|
return "%.2f";
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2020-02-23 13:25:36 +00:00
|
|
|
FloatMenuItem(const char* _label, float* _value, float _minimumValue, float _maximumValue, float _step)
|
|
|
|
: NumberMenuItem(_label, _value, _minimumValue, _maximumValue, _step) {};
|
2020-02-23 16:14:07 +00:00
|
|
|
FloatMenuItem() {};
|
2020-02-22 23:58:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class BoolMenuItem : public NumberMenuItem<bool> {
|
|
|
|
|
|
|
|
private:
|
|
|
|
const char* on_string;
|
|
|
|
const char* off_string;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
const char* get_format_string()
|
|
|
|
{
|
2020-02-23 16:14:07 +00:00
|
|
|
bool value = false;
|
|
|
|
if (this->get_value_ptr())
|
|
|
|
value = *this->get_value_ptr();
|
2020-02-22 23:58:21 +00:00
|
|
|
if (value)
|
|
|
|
return this->on_string;
|
|
|
|
else
|
|
|
|
return this->off_string;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2020-02-23 13:25:36 +00:00
|
|
|
BoolMenuItem(const char* _label, bool* _value, const char* _on_string, const char* _off_string)
|
|
|
|
: NumberMenuItem(_label, _value, 0, 1, 1)
|
2020-02-22 23:58:21 +00:00
|
|
|
, on_string(_on_string)
|
|
|
|
, off_string(_off_string) {};
|
2020-02-23 16:14:07 +00:00
|
|
|
BoolMenuItem() {};
|
2020-02-22 23:58:21 +00:00
|
|
|
};
|
|
|
|
|
2020-02-23 13:25:36 +00:00
|
|
|
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()
|
|
|
|
{
|
2020-02-23 16:14:07 +00:00
|
|
|
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:
|
2020-02-23 13:25:36 +00:00
|
|
|
StringListMenuItem(const char* _label, uint8_t* _value, const char** _stringLabels, size_t _itemCount)
|
|
|
|
: NumberMenuItem(_label, _value, 0, _itemCount - 1, 1)
|
2020-02-23 00:34:26 +00:00
|
|
|
, string_labels(_stringLabels) {};
|
2020-02-23 16:14:07 +00:00
|
|
|
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[4];
|
|
|
|
const char* note_strings[12];
|
|
|
|
|
|
|
|
protected:
|
|
|
|
const char* get_format_string() { return ""; }
|
|
|
|
|
|
|
|
public:
|
|
|
|
char* get_string_representation()
|
|
|
|
{
|
2020-02-23 16:14:07 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-02-23 13:25:36 +00:00
|
|
|
MidiNoteMenuItem(const char* _label, uint8_t* _value)
|
|
|
|
: NumberMenuItem(_label, _value, 0, 127, 1)
|
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";
|
|
|
|
};
|
2020-02-23 16:14:07 +00:00
|
|
|
MidiNoteMenuItem() {};
|
2020-02-22 23:15:01 +00:00
|
|
|
};
|