Number_Slider

Beschreibung

Diese Klasse ermöglicht das Erstellen von einfachen Schiebereglern. Sie erbt von Number_Input.

Beispielbild

Diese Bild dient nur der Veranschaulichung, wie Objekte dieser Klasse aussehen können.

../_images/number_slider-ex.jpg
new Number_Slider(COLOR_BLUE, TML_empty_slider, &numberValue2)

new Number_Slider((COLOR_RED|COLOR_LIGHT_YELLOW|COLOR_GRAY) + COLOR_DARK_GREEN, TML_empty_slider, &numberValue)

Funktionen

inline

Number_Slider (const Color& color, const std::function<void(int)> slider_callback, ExternalNumberValue* value=nullptr)

inline void

draw ()

inline void

setTouch (Inputs& input) override

inline bool

checkSize (uint16_t sizeX, uint16_t sizeY, uint8_t rotation) override

Variablen und Konstanten

const „Color

color

bool

isVertical = false

const uint16_t

t = 5

const uint16_t

b = 4

const uint16_t

r = 6

Funktionen Beschreibung

inline Number_Slider(const Color& color, const std::function<void(int)> slider_callback, ExternalNumberValue* value=nullptr)

1    inline Number_Slider(const Color& color, const std::function<void(int)> slider_callback, ExternalNumberValue* value=nullptr):
2        NumberInput(slider_callback, value),
3        color(color)
4    {}
5
6    inline void draw() {
7

Diese Funktion ist ein Konstruktor, der einen rechteckigen Slider erzeugt. Als Parameter nimmt der Konstruktor eine Farbe (color), die „Callback“ Funktion slider_callback und einem value, der angibt, ob das Objekt aktiviert oder deaktiviert ist.

In der Initialisierungsliste erfolgt zuerst der Aufruf vom „NumberInput Konstruktor“. Außerdem erfolgt die Initialisierung von color mit dem entsprechenden Parameter.

inline void draw();

 1            LOGGER_ERROR("DISPLAY IS NULLPTR!")
 2            return;
 3        }
 4
 5        uint16_t size = isVertical? sizeY : sizeX;
 6        uint16_t boxes = (uint16_t)(getMaxValue() - getMinValue()) / steps;
 7        
 8        // calculate position for the slider
 9        if (getMaxValue() == getMinValue()) 
10            sliderPos = size/2;
11
12        else if (boxes * r > size) 
13            sliderPos = map(value, minValue-1, maxValue+1, 0, size); 
14
15        else {
16            uint16_t boxSize = size / boxes;
17            sliderPos = boxSize * value/steps + boxSize/2;   
18        } 
19
20        uint16_t sy = sizeY - (2*b) - (2*t); // Slider movement length

Diese Funktion zeichnet Objekte der Number_Slider Klasse. Für den Zeichenprozess ist es relevant, ob das Objekt vertikal oder horizontal ausgerichtet ist (isVertical).

        }

        uint16_t size = isVertical? sizeY : sizeX;
        uint16_t boxes = (uint16_t)(getMaxValue() - getMinValue()) / steps;
        
        // calculate position for the slider
        if (getMaxValue() == getMinValue()) 
            sliderPos = size/2;

Sollte isVertical==true gelten, soll das Objekt auch vertikal gezeichnet werden. Dafür wird zuerst die Variable sy erstellt, welche den Wert von sizeY annimmt abzüglich der Breite der Umrandung (“b“) und dem Abstand zur Umrandung (“t“). Beide werden mit 2 multipliziert, da sich die Umrandung auf beiden Seiten des Elements befindet. Mit sliderPos wird die Y-Koordinate des Schiebereglers berechnet, bei welcher sich der Regler momentan befindet. Zuerst zeichnent wir mit dem Funktionsaufruf von „rect_center“ auf dem „display“ Objekt den deaktivierten Bereich des Sliders, um dann beim „rect“ Funktionsaufruf den aktivierten Bereich des Sliders über Teile des deaktivierten Bereichs überzuzeichnen. Schließlich wird durch den folgenden „rect_center“ Funktionsaufruf der Schieberegler zwischen dem aktivierten und deaktivierten Bereich gezeichnet.


        else if (boxes * r > size) 
            sliderPos = map(value, minValue-1, maxValue+1, 0, size); 

        else {
            uint16_t boxSize = size / boxes;
            sliderPos = boxSize * value/steps + boxSize/2;   
        } 

Sollte isVertical==false gelten, soll das Objekt horizontal statt vertikal gezeichnet werden. Der prinzipielle Ablauf bleibt aber der selbe.

inline void setTouch(Inputs& input) override;

 1
 2        if (isVertical) {
 3            display->rect_center(posX + sizeX/2, posY + sizeY/2, sizeX - t*2, sizeY - t*2, b, r, color.getBorderColor(), color.getSecondaryColor());        // 
 4            display->rect(posX + t + b, posY + t + b + sliderPos, sx, sy - sliderPos, 0, r, color.getBorderColor(), color);   // 
 5            display->rect_center(posX + sizeX/2, posY + t + b + sliderPos, sx + b, r * 2, 0, r, color.getBorderColor(), color.getItemColor());     // Slider
 6
 7            // // Dubug Hitboxes:
 8            // if (getMinValue() != getMaxValue()) {
 9            //     uint16_t boxes = (uint16_t)(getMaxValue() - getMinValue()) / steps;
10            //     for (int i = 0; i < boxes; i++)
11            //         display->line(posX, sizeY/boxes*i + posY + t + b, posX+sizeX, sizeY/boxes*i + posY + t + b, COLOR_RED);
12            //     LOGGER(boxes)
13            // }
14
15        } else {
16            display->rect_center(posX + sizeX/2, posY + sizeY/2, sizeX - t*2, sizeY - t*2, b, r, color.getBorderColor(), color.getSecondaryColor());
17            display->rect(posX + t + b, posY + t + b, sliderPos, sy, 0, r, color.getBorderColor(), color);
18            display->rect_center(posX + t + b + sliderPos, posY + sizeY/2, r * 2, sy + b, 0, r, color.getBorderColor(), color.getItemColor());
19        }
20    }
21
22
23    // value soll 0 - 10 in 2er schritten abbilden können (also 0, 2, 4, 6, 8, 10)
24    // Slider soll dabei auf der Mitte anhalten

Um den Schieberegler des Number_Slider Objekts auch verschieben zu können, muss mit dieser Funktion ermittelt werden, ob und wo der Benutzer das Objekt berührt. Die Parameter x und y geben an, wo „Display“ berührt wird.

            display->rect(posX + t + b, posY + t + b + sliderPos, sx, sy - sliderPos, 0, r, color.getBorderColor(), color);   // 
            display->rect_center(posX + sizeX/2, posY + t + b + sliderPos, sx + b, r * 2, 0, r, color.getBorderColor(), color.getItemColor());     // Slider

            // // Dubug Hitboxes:
            // if (getMinValue() != getMaxValue()) {
Zuerst werden einige Variablen definiert, die den Code leserlicher machen sollen:
x1 entspricht der X-Koordinate, bei dem das Objekt anfängt.
xr entspricht der X-Koordinate, bei dem das Objekt endet.
y1 entspricht der Y-Koordinate, bei dem das Objekt anfängt.
yr entspricht der Y-Koordinate, bei dem das Objekt endet.
            //     for (int i = 0; i < boxes; i++)
            //         display->line(posX, sizeY/boxes*i + posY + t + b, posX+sizeX, sizeY/boxes*i + posY + t + b, COLOR_RED);

Sollte sich y nicht zwischen y1 und yr befinden, wird das Objekt nicht berührt und der Schieberegler wird nicht angepasst. Selbiges gilt, wenn x sich nicht zwischen x1 und xr befindet. Andernfalls wird das Objekt berührt.

            //     LOGGER(boxes)
            // }

Bei einem vertikalen (isVertical) Objekt, muss nur die Y-Koordinate des Schiebereglers beachtet werden, da dieser sich von oben nach unten bzw. umgekehrt bewegen lässt. Dafür wird für value die neue Y-Koordinate des Reglerposition gespeichert.

        } else {
            display->rect_center(posX + sizeX/2, posY + sizeY/2, sizeX - t*2, sizeY - t*2, b, r, color.getBorderColor(), color.getSecondaryColor());
            display->rect(posX + t + b, posY + t + b, sliderPos, sy, 0, r, color.getBorderColor(), color);
            display->rect_center(posX + t + b + sliderPos, posY + sizeY/2, r * 2, sy + b, 0, r, color.getBorderColor(), color.getItemColor());

Bei einem horizontalen (isVertical) Objekt, muss nur die X-Koordinate des Schiebereglers beachtet werden, da dieser sich von rechts nach links bzw. umgekehrt bewegen lässt. Dafür wird für value die neue X-Koordinate der Reglerposition gespeichert.

        }
    }

Sollte „externalValue“ nicht null sein, so wird er mit dem neuen „value“ aktualisiert. Anschließend wird die „Callback Funktion“ aufgerufen.


Zum Schluss folgt ein Aufruf der „draw“ Funktion, um die neue Schiebereglerposition zu zeichnen.

inline bool checkSize(uint16_t sizeX, uint16_t sizeY, uint8_t rotation) override;

 1        uint16_t xr = xl + sizeX - (2*b) - (2*t);   // Right X value
 2
 3        uint16_t yl = posY + t + b;                 // Left  Y value
 4        uint16_t yr = yl + sizeY - (2*b) - (2*t);   // Right Y value
 5
 6        if (!(xl < input.touchX && input.touchX < xr)) return;
 7        if (!(yl < input.touchY && input.touchY < yr)) return;
 8
 9        int new_value;
10        if (isVertical) new_value = map(input.touchY, yl, yr, minValue, maxValue);
11        else            new_value = map(input.touchX, xl, xr, minValue, maxValue);
12
13        if (new_value == value) return;
14        else value = getMinValue() + (int)((new_value - getMinValue()) / steps) * steps;
15

Diese Funktion testet, ob die Höhe (sizeX) und Breite (sizeY) eines Objektes in einem bestimmten Größenverhältnis zueinander stehen, um das Objekt zeichnen zu können.


        uint16_t yl = posY + t + b;                 // Left  Y value
        uint16_t yr = yl + sizeY - (2*b) - (2*t);   // Right Y value

        if (!(xl < input.touchX && input.touchX < xr)) return;

Wenn ein Objekt mindestens 1.5 mal so hoch ist, wie es breit ist, dann ist das Objekt „vertikal“ und zeichenbar.


        int new_value;
        if (isVertical) new_value = map(input.touchY, yl, yr, minValue, maxValue);
        else            new_value = map(input.touchX, xl, xr, minValue, maxValue);

Wenn ein Objekt mindestens 1.5 mal so breit ist, wie es hoch ist, dann ist das Objekt horizontal und zeichenbar.

        if (new_value == value) return;
        else value = getMinValue() + (int)((new_value - getMinValue()) / steps) * steps;

Stimmt das Verhältnis nicht, ist das Objekt weder vertikal noch horizontal.

Variablen und Konstanten Beschreibung

const Color color

Gibt die Farbe (Color) des Objektes an.

bool isVertical = false;

Gibt an, ob das Objekt horizontal oder vertikal ist.

const uint16_t t = 10

Gibt den Abstand zur Umrandung an.

const uint16_t b = 10

Gibt die Breite der Umrandung an.

const uint16_t r = 6

Gibt den Radius der Umrandung (bzw. den Krümmungsgrad) an.