Button

Beschreibung

Buttons sind Elemente, bei denen ein einmaliger Input zum Ausführen einer bestimmten Aktivität führt. Vom Button erben die Klassen Button_Blank, Button_Rect und Button_Round. Objekte dieser Klasse können in zwei verschiedenen Varianten erstellt werden: als Button oder als Switch. Dabei sind Buttons Objekte der Button Klasse, die beim Drücken ihr Aussehen bzw. nur kurz ändern oder durch durch Drücken andere Screens aufrufen können. Switches sind Objekte der Button Klasse, die nach Betätigung ihr Aussehen und Zustand so lange verändern, bis erneut auf dieses Objekt gedrückt wird.

Funktionen

Button (std::function<void()> button_callback, ExternalButtonValue* externalValue)

Button (std::function<void()> button_callback, std::function<void()> longpress_callback, ExternalButtonValue* externalValue)

Button (std::function<void(bool)> swich_callback, ExternalButtonValue* externalValue)

Button (std::function<void(bool)> swich_callback, std::function<void()> longpress_callback, ExternalButtonValue* externalValue)

Button (std::function<void()> button_callback, std::function<void(bool)> swich_callback, std::function<void()> longpress_callback, const bool isButton, const bool hasLongPress, ExternalButtonValue* externalValue)

virtual

~Button ()

void

loop (Inputs& input)

bool

select ()

void

setTouch (Inputs& input) override

bool

getValue () const

bool

isInsideHitbox (uint16_t x, uint16_t y, uint16_t posX, uint16_t posY, uint16_t sizeX, uint16_t sizeY)

Variablen und Konstanten

const std::function<void()>

button_callback = [](){}

const std::function<void(bool)>

switch_callback = [](bool){}

const std::function<void()>

longpress_callback = [](){}

ExternalButtonValue

externalValue = nullptr

const bool

isButton

const bool

hasLongPress = false

bool

value = false

bool

blocked = false

bool

hasButtonAnimation = true

unsigned long

animationTimer = 0

unsigned long

longPressTimer = 0

Makros

TML_goTo

TML_goTo_without_History

TML_back

TML_empty_button

TML_empty_switch

BUTTON_ON_TIME

BUTTON_LONG_TIME

Funktionen Beschreibung

Button(std::function<void()> button_callback, ExternalButtonValue* externalValue = nullptr)

1Button::Button(std::function<void()> button_callback, ExternalButtonValue* externalValue) : 
2    button_callback(button_callback),
3    externalValue(externalValue),
4    isButton(true),
5    value(true)
6    {}

Diese Funktion ist ein Konstruktor für ein Objekt der Klasse Button, welcher Buttons erzeugt. Als Parameter nimmt der Konstruktor eine Button Callback Funktion (siehe button_callback) und ein externalValue, welches den Zustand des Objektes angibt (also ob es aktiviert oder deaktiviert ist).

In der Initialisierungsliste werden button_callback und externalValue mit den entsprechenden Parametern initialisiert. Außerdem werden sowohl isButton und value mit true initialisiert, weil das Objekt ein Button und kein Switch ist und standarmäßig aktiviert sein soll, sollte kein externalValue vorliegen.

Button(std::function<void()> button_callback, std::function<void()> longpress_callback, ExternalButtonValue* externalValue = nullptr)

1Button::Button(std::function<void()> button_callback, std::function<void()> longpress_callback, ExternalButtonValue* externalValue) :
2    button_callback(button_callback),
3    longpress_callback(longpress_callback),
4    externalValue(externalValue),
5    isButton(true),
6    hasLongPress(true),
7    value(true)
8    {}

Diese Funktion ist ein Konstruktor für ein Objekt der Klasse Button, welcher Buttons erzeugt. Als Parameter nimmt der Konstruktor eine Button Callback Funktion (siehe button_callback), eine Longpress Callback Funktion (siehe longpress_callback) und ein externalValue, welches den Zustand des Objektes angibt (also ob es aktiviert oder deaktiviert ist).

In der Initialisierungsliste werden button_callback, longpress_callback<buttonlongpresscallback> und externalValue mit den entsprechenden Parametern initialisiert. Außerdem werden sowohl isButton, hasLongPress und value mit true initialisiert, weil das Objekt ein Button und kein Switch ist, beim gedrückhalten eine Aktion ausführen soll und standarmäßig aktiviert sein soll, sollte kein externalValue vorliegen.

Button(std::function<void(bool)> swich_callback, ExternalButtonValue* externalValue = nullptr)

1Button::Button(std::function<void(bool)> swich_callback, ExternalButtonValue* externalValue) : 
2    switch_callback(swich_callback),
3    externalValue(externalValue),
4    isButton(false)
5    {}

Diese Funktion ist ein Konstruktor für ein Objekt der Klasse Button, welcher Switches erzeugt. Als Parameter nimmt der Konstruktor eine Switch Callback Funktion (siehe switch_callback) und ein externalValue, welches den Zustand des Objektes angibt (also ob es aktiviert oder deaktiviert ist).

In der Initialisierungsliste werden switch_callback und externalValue mit den entsprechenden Parametern initialisiert. Außerdem wird isButton mit false initialisiert, weil das Objekt ein Switch und kein Button ist.

Button(std::function<void(bool)> swich_callback, std::function<void()> longpress_callback, ExternalButtonValue* externalValue = nullptr)

1Button::Button(std::function<void(bool)> swich_callback, std::function<void()> longpress_callback, ExternalButtonValue* externalValue) :
2    switch_callback(swich_callback),
3    longpress_callback(longpress_callback),
4    externalValue(externalValue),
5    isButton(false),
6    hasLongPress(true)
7    {}

Diese Funktion ist ein Konstruktor für ein Objekt der Klasse Button, welcher Switches erzeugt. Als Parameter nimmt der Konstruktor eine SwitchCallback Funktion (siehe switch_callback), eine Longpress Callback Funktion (siehe longpress_callback) und ein externalValue, welches den Zustand des Objektes angibt (also ob es aktiviert oder deaktiviert ist).

In der Initialisierungsliste werden switch_callback, longpress_callback<buttonlongpresscallback> und externalValue mit den entsprechenden Parametern initialisiert. Außerdem wird isButton mit false initialisiert, weil das Objekt ein Switch und kein Button ist und hasLongPress mit true, da das beim gedrückhalten eine Aktion ausführen soll.

Button(std::function<void()> button_callback, std::function<void(bool)> swich_callback, std::function<void()> longpress_callback, const bool isButton, const bool hasLongPress, ExternalButtonValue* externalValue = nullptr)

1Button::Button(std::function<void()> button_callback, std::function<void(bool)> swich_callback, std::function<void()> longpress_callback, const bool isButton, const bool hasLongPress, ExternalButtonValue* externalValue):
2    button_callback(button_callback), 
3    switch_callback(swich_callback),
4    longpress_callback(longpress_callback),
5    externalValue(externalValue),
6    isButton(isButton),
7    hasLongPress(hasLongPress)
8    {}

Dieser Konstruktor unterscheidet sich von den anderen vier Konstruktoren der Klasse, da hier jede einzelne Variable per Hand festgelegt werden kann. Dies ermöglicht die unterschiedlichsten Objekte zu erstellen, um individuelle Bedürfnisse bei der Funktionsweise von Objekten der Button Klasse` zu erfüllen.

virtual ~Button()

1Button::~Button(){};

Der Destruktor wird bei der Zerstörung eines Button Objektes aufgerufen.

void loop(Inputs& input)

 1void Button::loop(Inputs& input) {
 2    if (input.enter) {
 3        LOGGER("Enter")
 4        Button::setTouch(input);
 5    }
 6
 7    if (externalValue && externalValue->getValue() != value) {
 8        value = externalValue->getValue();
 9        draw();
10        LOGGER("Externer Wert unterscheidet sich")
11
12        if (isButton && value) animationTimer = millis();
13    }

Diese Funktion dient dazu, den Zustand eines Buttons bzw. Switches zu aktualisieren, um auf Benuzereingaben zu reagieren.

    if (input.enter) {
        LOGGER("Enter")
        Button::setTouch(input);
    }

Sollte der als Argument übergebene Input input.enter==true gelten, so wird mit input die setTouch Funktion aufgerufen.

    if (externalValue && externalValue->getValue() != value) {
        value = externalValue->getValue();
        draw();
        LOGGER("Externer Wert unterscheidet sich")

        if (isButton && value) animationTimer = millis();
    }

Sollte externalValue nicht null sein und sollte der darin gespeicherte Wert nicht dem value entsprechen, so übernimmt value die Referenz auf den Wert von externalValue. Anschließend wird das Objekt mit draw gezeichnet. Sollte das aktuelle Objekt ein Button (und kein Switch) sein und sollte zusätzlich value nicht null sein, so wird animationTimer mit neuen Zeitangaben aktualisiert. Er speichert wie viele Millisekunden seit Start vergangen sind (siehe millis() ).

    if (animationTimer > 0 && isButton && millis() - animationTimer > BUTTON_ON_TIME) {
        // LOGGER("Timer ist zuende")
        animationTimer = 0;
        if (!value) {
            value = true;
            draw();
        }
    }

Sollte der animationTimer eines Buttons (keines Switches) im vorherigen Codeabschnitt aktualisiert worden sein und seitdem mehr Millisekunden vergangen sein, als in BUTTON_ON_TIME, so wird der animationTimer wieder zurückgesetzt und, sollte dies nicht schon der Fall sein, value auf true gesetzt, um den Button wieder in seinem aktivierten Zustand mit draw zu zeichnen.

    if (externalValue && externalValue->hasUpdate()) {
        draw();
        externalValue->resetUpdate();
        LOGGER("ExternalValue was changed")
    }

Sollten Änderungen durch den externalValue vorgenommen worden sein (hasUpdate), so werden diese Änderungen mit draw gezeichnet und resetUpdate aufgerufen.

    if (!input.isTouched && blocked) {
        blocked = false;

Sollte das Objekt nicht länger berührt werden, aber weiterhin blocked==true sein, so wird blocked wieder auf false gesetzt, um den Button wieder freizusetzen.

    } else if (hasLongPress && input.isTouched && longPressTimer > 0 && isInsideHitbox(input.touchX, input.touchY, posX, posY, sizeX, sizeY) && millis() - longPressTimer > BUTTON_LONG_TIME) {
        LOGGER("---> LONG Press Timer ist zuende")
        longPressTimer = 0;
        longpress_callback();
        blocked = true;

Dieser Codeabschnitt testet, ob das Objekt lange drückbar ist und lang genug gedrückt wurde, bereit ist und auch innerhalb der Grenzen des Buttons gedrückt wurde (isInsideHitbox). Wenn dies der Fall ist, wird der longPressTimer zurückgesetzt und die longpress_callback Funktion aufgerufen.

    } else if (hasLongPress && input.isTouched && longPressTimer > 0 && !isInsideHitbox(input.touchX, input.touchY, posX, posY, sizeX, sizeY)) {
        LOGGER("LONG Press Timer wurde abgebrochen, da Touchpunkt aus Hitbox raus")
        longPressTimer = 0;

Wenn der Touchpoint allerdings nicht mehr innerhalb der Grenzen des Objektes liegt, wird der longPressTimer zurückgesetzt ohne die Callback Funktion aufzurufen. Der Prozess wurde vom Benutzer abgebrochen.

    } else if (hasLongPress && !input.isTouched && longPressTimer > 0) {
        LOGGER("Short Press")
        longPressTimer = 0;
        select(input);
        blocked = true;
    } 

Drückt der Nutzer hingegen nicht kontinuierlich auf den Button, wird der Prozess ebenso abgebrochen und statt der Aktion, die durch langes Drücken ausgeführt wird, wird die Aktion für kurzes Drücken ausgeführt, indem select mit dem input aufgerufen wird.

bool select ()

 1bool Button::select(Inputs& input) {
 2    if (isButton) {
 3        if (hasButtonAnimation) {
 4            animationTimer = millis();
 5            value = false;
 6        }
 7        button_callback();
 8        if (externalValue) externalValue->setValue(value);
 9    } else {
10        value = !value;
11        switch_callback(value);
12    }
13    draw();
14
15    return false;
16}

Diese Funktion ist für den Aufruf der entsprechenden Callback Funktionen von Objekten der Button Klasse zuständig, wenn diese ausgewählt werden.

    if (isButton) {
        if (hasButtonAnimation) {
            animationTimer = millis();
            value = false;
        }
        button_callback();
        if (externalValue) externalValue->setValue(value);

Dieser Codeabschnitt gilt für Buttons (also nicht für Switches). Wenn Buttons eine Button Animation haben(hasButtonAnimation), dann wird der animationTimer die Millisekunden seit Start speichert (siehe millis() ). Der Button wird außerdem deaktiviert (value). Es folgt der Aufruf der Callback Funktion button_callback. Sollte durch den externalValue ein gewünschter Zustand für den Button angegeben sein, so wird setValue aufgerufen.

    } else {
        value = !value;
        switch_callback(value);
    }

Bei einem Switch, wird der aktuelle Zustand gewechselt, also vom aktivierten in den deaktivierten und umgekehrt. Danach wird die switch_callback Callback Funktion aufgerufen.

    draw();

Das Objekt wird mit draw sofort neugezeichnet.

void setTouch(Inputs& input)

 1void Button::setTouch(Inputs& input) {
 2    if (input.touchX < posX || input.touchX > posX + sizeX || input.touchY < posY || input.touchY > posY + sizeY) return;
 3    
 4    if (hasLongPress && longPressTimer == 0 && !blocked) {
 5        LOGGER("Aktiviere long press timer")
 6        longPressTimer = millis();
 7    } else if (!hasLongPress && !blocked) {
 8        select(input);
 9        blocked = true;
10    }
11}

Diese Funktion verarbeitet Toucheingaben auf das Button Objekt auf dem Display.

    if (input.touchX < posX || input.touchX > posX + sizeX || input.touchY < posY || input.touchY > posY + sizeY) return;

Bei Toucheingaben, die außerhalb des Buttons geschehen, wird die Funktion abgebrochen.

    if (hasLongPress && longPressTimer == 0 && !blocked) {
        LOGGER("Aktiviere long press timer")
        longPressTimer = millis();

Sollte es möglich sein, das Objekt länger gedrückt zu halten (hasLongPress), sollte noch kein longPressTimer gestartet worden sein und sollte blocked false sein, so wird der longPressTimer gestartet, indem dieser die Millisekunden seit Start (siehe millis() ) speichert.

    } else if (!hasLongPress && !blocked) {
        select(input);
        blocked = true;
    }

Sollte man das Objekt allerdings nicht länger gedrückthalten können und sollte blocked false sein, so wird lediglich die select Funktion aufgerufen und blocked auf true gesetzt.

bool getValue()

1    bool getValue() const { return value; }

Gibt den value des aktuellen Objektes zurück.

bool isInsideHitbox(uint16_t x, uint16_t y, uint16_t posX, uint16_t posY, uint16_t sizeX, uint16_t sizeY)

1bool Button::isInsideHitbox(uint16_t x, uint16_t y, uint16_t posX, uint16_t posY, uint16_t sizeX, uint16_t sizeY) {
2  return (x >= posX && x <= posX + sizeX && y >= posY && y <= posY + sizeY);
3}

Diese Funktion testet, ob, wenn das Display berührt wird, auch das aktuelle Objekt der Button Klasse berührt wird. Dabei sind x und y die Koordinaten, bei welchem das Display berührt wird, posX und posY die Position des Objektes und sizeX und sizeY die Breite und Höhe des Objektes.

const std::function<void()> button_callback = [](){}

1    const std::function<void()> button_callback = [](){};

Diese Funktion ist die Callback Funktion für Buttons (für Switches siehe switch_callback). Standardmäßig tut diese Funktion nichts, sie erhält erst eine Bedeutung, wenn bei der Erstellung eines Button Objektes eine Funktion als button_callback übergeben wird, die aufgerufen wird, wenn der Button aktiviert wird.

const std::function<void(bool)> switch_callback = [](bool){}

1    const std::function<void(bool)> switch_callback = [](bool){};

Diese Funktion ist die Callback Funktion für Switches (für Buttons siehe button_callback). Standardmäßig tut diese Funktion nichts (akzeptiert aber ein bool Argument, da ein Switch einen aktivierten und deaktivierten Zustand hat), sie erhält erst eine Bedeutung, wenn bei der Erstellung eines Button Objektes eine Funktion als button_callback übergeben wird, die aufgerufen wird, wenn der Switch aktiviert wird.

const std::function<void()> longpress_callback = [](){};

1    const std::function<void()> longpress_callback = [](){};

Diese Funktion ist die Callback Funktion für Buttons und Switches, welche beim längeren Gedrückthalten auf das Objekt verwendet wird. Standardmäßig tut diese Funktion nichts, sie erhält erst eine Bedeutung, wenn bei der Erstellung eines Button Objektes eine Funktion als longpress_callback übergeben wird, die aufgerufen wird, wenn der Button/Switch aktiviert wird.

Variablen und Konstanten Beschreibung

bool value = false;

Speichert den aktuellen Zustand des Buttons bzw. Switches. Standardmäßig befinden sie sich in einem deaktivierten Zustand.

ExternalButtonValue* externalValue = nullptr

Ermöglicht eine externe Steuerung des Zustands des Buttons bzw. Switches, indem es auf einen bool-Wert zeigt, die den gewünschten Zustand repräsentiert.

const bool isButton

Gibt an, ob ein Objekt der Button Klasse ein Button oder ein Switch ist.

const bool hasLongPress = false

Gibt an, ob bei einem Objekt der Button Klasse die longpress_callback Callback Funktion vorliegt, also ob man den Button/ Switch gedrückthalten kann.

bool blocked = false

Gibt an, ob der Button gerade blockiert ist, also gerade nicht ausgelöst werden kann.

bool hasButtonAnimation = true

Gibt an, ob beim Drücken des Objektes eine kleine Animation abgespielt wird.

unsigned long animationTimer = 0

Gibt an, wie lang eine Animation beim Drücken eines Buttons dauert bzw. wie lange es dauert, einen Button zu drücken.

unsigned long longPressTimer = 0

Gibt an, wie lange ein Button gedrückt wird.

Makros Beschreibung

TML_goTo (tml, id) [](){tml.goTo(id);}

Mit diesem Macro lässt sich der aktuell angezeigte Screen schnell wechseln auf den Screen mit der eingetragenen id (siehe goTo der TouchMenuLib Klasse). Dabei ist tml eine Instanz der TouchMenuLib Klasse.

TML_goTo_without_History (tml, id) [](){tml.goTo(id, false);}

Mit diesem Macro lässt sich der aktuell angezeigte Screen schnell wechseln auf den Screen mit der eingetragenen id. Dabei ist tml eine Instanz der TouchMenuLib Klasse. Beim Verwenden dieses Macros wird der aufgerufene Screen nicht auf

TML_back (tml) [](){tml.back();}

Mit diesem Macro wird die back Funktion ausgeführt.

TML_empty_button [](){}

Mit diesem Macro lässt sich ein Button erstellen, der keine weitere Funktionalität (also einen anderen Screen aufzurufen) haben soll.

TML_empty_switch [](bool){}

Mit diesem Macro lässt sich ein Switch erstellen, der keine weitere Funktionalität (also einen anderen Screen aufzurufen) haben soll.

BUTTON_ON_TIME 400

Stellt die Zeit in Millisekunden dar, die beim Drücken eines Buttons vergehen.

BUTTON_LONG_TIME 500

Stellt die Zeit in Millisekunden dar, die vergehen müssen, damit ein Drücken auf einem Button als Gedrückthalten gewertet wird