27-Simple_GUI-Library (STM32F429)

Diese Library ermöglicht es eine “einfache” Graphische Benutzeroberfläche
mit dem STM32F429 und einem Grafik-Display (mit Touch) zu realisieren.

Hier ein paar Bilder wie das ganze aussieht :

File-Aufbau :

Die SGUI-Library besteht aus mehreren Files.
Als Hierachiebaum sieht das ganze so aus :

User-Projekt
  |
  +stm32_ub_sgui
    |
    +ub_sgui_screen
    +ub_sgui_window
    +ub_sgui_text
    |
    +ub_sgui_panel
    +ub_sgui_button
    +ub_sgui_led
    +ub_sgui_label
    +ub_sgui_checkbox
    +ub_sgui_gauge
    +ub_sgui_radiobtn

Wie zu sehen ist, muss der User nur ein File includen “stm32_ub_sgui”
der Rest wird automatisch “angehängt”

“SGUI_SCREEN” , “SGUI_Window” und “SGUI_Text” muss im Projekt vorhanden sein
die anderen Objekte (Button, LED usw) können falls nicht benötigt
auch weggelassen werden.

Funktionsweise :

Der User muss folgende Dinge in seinem Programm einbauen :
1. Die Init-Funktion von SGUI muss als erstes nach Power-On aufgerufen werden
2. Alle Seiten (Windows) die später zu sehen sein sollen,
müssen einmal “erstellt” werden. (Erklärung folgt)
(das muss bzw. darf nur einmal nach Power-On gemacht werden)
3. Die Funktion “SGUI_DO” muss zyklisch aufgerufen werden
(die kümmert sich um das zeichen/touchabfrage usw)

Hello-World Beispiel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "stm32_ub_sgui.h"
 
int main(void) {
  SBUTTON_t* btn;
 
  SystemInit();
 
  SGUI_Init();
 
  SGUI_WindowCreateMain(1);
  btn=SGUI_ButtonCreate(10,20,100,50);
  SGUI_ButtonSetText(btn,"Hello");
 
  while(1) {
    SGUI_Do();
  }
}

Hier ein miminal Beispiel das ein leeres Fenster erzeugt (mit Nr. 1),
darauf einen Button platziert und die Beschriftung vom Button ändert.

Der Button hat zwar keine Funktion aber die SGUI-Library kümmert sich
(durch die SGUI_DO) das man den Button per Touch drücken kann.

Allgemeine Hinweise :

Alle Objekte besitzen Parameter die beim “Create” erstmal auf einen
Standardwert gesetzt werden (z.B. Farbe, Schriftart, Rahmendicke usw)

Alle Parameter können aber nachträglich (auch während dem Programmlauf)
geändert werden. Falls der User einen Parameter von einem Objekt ändert,
und dieses gerade sichtbar ist, wird es automatisch neu gezeichnet.

Die Software reserviert erst beim “Create” Speicherplatz im RAM für das Objekt.
So das es eigentlich (außer der RAM-Größe) kein oberes Limit für die Anzahl
der Objekte gibt. Ich habe aber eine “maximal Anzahl” für die Objekte
im jeweiligen H-File festgelegt (im Moment 100 von jeder Art). nur zur Info.

Wer das Display im Landscape-Mode betreiben will, muss den Define
im  File “ub_sgui_screen.h” ändern.

Objekt : Window

Ein “Window” ist die Zeichenunterlage für alle anderen Objekte (außer andere Windows)
Es gibt zwei Typen : “Main” und “Child”
Main-Windows füllen den kompletten Screen (Größe kann nicht eingestellt werden)
Child-Windows können eine beliebige Größe und Position besitzen.

Wenn ein Child-Window angezeigt wird, bleibt das darunter liegende Main-Window
zum Teil sichtbar. Das Child liegt also im Vordergrund.

Hinweis : ohne ein Window , kann kein anderes Objekt erzeugt werden.
Jedes Objekt wird beim erzeugen dem aktuellen Window zugeordnet.

Beim zeichnen von einem Window werden alle Objekte gezeichnet,
die diesem Window zugeordnet sind. Und nur diese Objekte reagieren
auf Touch eingaben.

Objekt-Liste :

Hier eine Liste aller im Moment verfügbaren Objekte
die auf einem Window platziert werden können.
Einige davon können per Touch gesteuert werden.
(Eine Doku zu allen Objekten ist in der Library dabei)

> Text
> Panel
> Button
> LED
> Label
> Checkbox
> Radio-Button
> Gauge
> Slider
> Select-Button
> Listbox
> DropDown-Box
> IntEdit
> FloatEdit
> Picture
> Graph

Beispiel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//--------------------------------------------------------------
// File     : main.c
// Datum    : 17.01.2015
// Version  : 1.0
// Autor    : UB
// EMail    : mc-4u(@)t-online.de
// Web      : www.mikrocontroller-4u.de
// CPU      : STM32F429
// IDE      : CooCox CoIDE 1.7.4
// GCC      : 4.7 2012q4
// Module   : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der SGUI
// Hinweis  : Diese zwei Files muessen auf 8MHz stehen
//              "cmsis_boot/stm32f4xx.h"
//              "cmsis_boot/system_stm32f4xx.c"
// In Configuration diese Define hinzufügen :
// "STM32F429_439xx" , "__ASSEMBLY__" , "USE_STDPERIPH_DRIVER"
//--------------------------------------------------------------
 
#include "main.h"
#include "stm32_ub_sgui.h"
 
SLABEL_t *label;
SBUTTON_t *btn1, *btn2;
 
//--------------------------------------------------------------
void create_Window1(void);
void create_Window2(void);
//--------------------------------------------------------------
void btn1_fkt(bool aktiv);
void btn2_fkt(bool aktiv);
//--------------------------------------------------------------
 
//--------------------------------------------------------------
// Demoprogramm der "Simple-GUI"
// es werden zwei Fenster erzeugt mit jeweil einem Button
// mit den Buttons kann zwischen den Fenstern gewechselt werden
//--------------------------------------------------------------
int main(void)
{
  SystemInit(); // Quarz Einstellungen aktivieren
 
  // init der SGUI
  SGUI_Init();
 
  // Fenster erzeugen
  create_Window1();
  create_Window2();
 
  // Window-1 anzeigen
  SGUI_WindowShow(1);
 
  while(1)
  {
	  SGUI_Do(); // SGUI bearbeiten
  }
}
 
//--------------------------------------------------------------
void create_Window1(void)
{
  // ein Window erstellen (Nr. 1)
  SGUI_WindowCreateMain(1);
  // ein Label platzieren und beschriften
  label=SGUI_LabelCreate(10,10,220,50);
  SGUI_LabelSetText(label,"Window-1");
  // einen Button platzieren und beschriften
  btn1=SGUI_ButtonCreate(10,100,100,50);
  SGUI_ButtonSetText(btn1,"Btn-1");
  // einen Handler fuer den Button einrichten
  SGUI_ButtonSetHandler(btn1,btn1_fkt);
}
//--------------------------------------------------------------
void create_Window2(void)
{
  // ein Window erstellen (Nr. 2)
  SGUI_WindowCreateMain(2);
  // ein Label platzieren und beschriften
  label=SGUI_LabelCreate(10,10,220,50);
  SGUI_LabelSetText(label,"Window-2");
  // einen Button platzieren und beschriften
  btn2=SGUI_ButtonCreate(10,100,100,50);
  SGUI_ButtonSetText(btn2,"Btn-2");
  // einen Handler fuer den Button einrichten
  SGUI_ButtonSetHandler(btn2,btn2_fkt);
}
 
//--------------------------------------------------------------
void btn1_fkt(bool aktiv) {
  // beim verlassen von Button-1 das Window-2 anzeigen
  if(aktiv==false) SGUI_WindowShow(2);
}
//--------------------------------------------------------------
void btn2_fkt(bool aktiv) {
  // beim verlassen von Button-2 das Window-1 anzeigen
  if(aktiv==false) SGUI_WindowShow(1);
}

Hier die komplette Doku als PDF-File (Danke an Michael dafür) :

SGUI_13

Hier die Library zum Download :

sgui_f429_v103

Hier der komplette CooCox-Projektordner zum Download : (Hello-World)

Demo_F429_27

Hier der komplette CooCox-Projektordner zum Download : (Demo aller Objekte)

Demo_F429_27b


53 Antworten auf 27-Simple_GUI-Library (STM32F429)

  1. Cortex-Einsteiger sagt:

    wow, das ist wirklich cool!
    Allerdings muss man sich dort definitiv mehr einlesen und probieren als in andere Projekte, nur includen und loslegen ist da nicht möglich.

    Ist die grüne Led PG13 unabhängig von der blinkenden Led auf dem Display?
    Die sind nämlich je nach Zustand nicht synchron.

    • admin_ub sagt:

      Ja, wenn man es richtig machen will brauchen Code und Doku ca 50:50 der Zeit vom Projekt. Ich spare mir meist die Doku und versuche das mit Kommentaren im Code auszugleichen. Versuche die Kommentare zu verstehen und ich versuche hier zu jedem Objekt zumindest ein Beispiel zu bringen.

  2. noone sagt:

    Nice,

    I’m waiting for function like SGUI_WindowGetPrevActive() to get previous active window.
    Why would this be good?
    If you make child window with “Are you sure?” box and “Close/OK” buttons, if you click “Close”, you get back previous window and you don’t need to take care for that.

    I’ve added already this in your implementation for testing, works great.

    • noone sagt:

      I’m also missing relative path.

      So if you make a child window (like alert message), then I’m expecting that all buttons/labels/whatever’s position is relative to this window.

      If window is at location 10,10, then if button has x,y = 10,10 then this is actual value in LCD at x,y = 20,20. If you understand.

      • admin_ub sagt:

        please try Version B.02 for “SGUI_WindowShowPrev” and offset in Child-Windows.
        I have also changed the touch behavior : to aktivate an object the touch must be released first. And the function “TextCreateDec” now needs a parameter for the digits and leading zeros can be enabled.

  3. noone sagt:

    You are going nice :)

    One feature will be to select whether LED is circle or rectangle.

    • admin_ub sagt:

      yep, no problem. what do you think about the syntax ? too many single
      functions to set the properties of one objekt ? Or should i use “global” settings
      like “SGUI_SetFont” and all other created objekts use this font ?

      • noone sagt:

        Use global functions and one structure with default settings.
        For single LED: SGUI_LedSetMode(ledpointer, LED_RECTANGLE);

        For global default led settings
        SGUI_LedSetDefaultMode(LED_RECTANGLE);

  4. noone sagt:

    Example on how you can use “Are you sure?” alert box for more than just 1 operation.

    http://pastebin.com/HRDxtNsW

    • admin_ub sagt:

      nice example

  5. noone sagt:

    Really nice.
    I was trying the one I was also expecting that it will be bug.

    If I use drowdown for example in child window, which is smaller than dropdown, then when I open dropdown, and close it back, not all is cleared, because it is on inactive window.

    This is hard to make easy to clean.
    I suggest you that you don’t allow that dropdown goes outside the child box.

    Keep up a great work!
    Also, I saw your great sollution for strings using double pointers! Nice work!

    • admin_ub sagt:

      thanks for testing, its hard to think at all combinations.
      You are right i must restrict the size of the box and i must add a scroll bar too.
      (or should i repaint both windows ?) i will add one more objekt to show decimal values with arrows to change
      and then i make a bugfix week. so please post all bugs you found in B.04
      (e.g how many objekts can you add before a RAM overflow :-)

      • noone sagt:

        I think that you don’t need to repaint both windows.
        Just add limit to where you can go.
        And maybe integrated slider for that if list is longer than window.

  6. noone sagt:

    Another very useful feature will be that every function returnes pointer.

    For example: If I work with buttons I would like that all button related functions returns button pointer.
    Then, this can be done:

    SGUI_ButtonSetColor(SGUI_ButtonSetText(SGUI_ButtonCreate(…),…));

    • admin_ub sagt:

      i think thats hard to read with all functions in one line.
      but you have the source, include it if you want.

  7. noone sagt:

    Hi UVE.
    I have found another bug.

    If I have slider akt_value set to 10 and then I changed Max to 100 and Min to greater than current, everything fails :D
    When you set min and max value, you should also check for actual current value.

    • admin_ub sagt:

      fixed in B.07
      DropDown-Box is now with scrollbar if too many items.
      The function “SGUI_WindowGetUsedRam” returns the used ram space.

  8. noone sagt:

    Try to set string larger than is dropdown’s width ;)
    You are going nice through, but you still need a lot of work for that.

    I have a lot of ideas but as I know you don’t allow your libs for production mode, so I won’t tell it here.
    Will do my own gui with them.

    • admin_ub sagt:

      of course you can spend 100 h to reprogram STemWin…but that was not my intent. the project name is “simple” gui ..so its a running base gui and the user can add the features he want and fix bugs like the string length limitation by its own :-)

  9. Markus sagt:

    Hallo,

    wird es die Möglichkeit geben, die GUI zu drehen (also Landscape Mode)?

    Gruß

    • Uwe sagt:

      Also Markus, genau das war auch meine erste Frage… ich hab mal kurz herumgespielt und habe folgende Zeile entdeckt:

      ub_sgui_screen.h

      in Zeile 28: SGUI_SCREEN_ORIENTATION 1 // 1=landscape

      Danach dreht sich die Orientierung von Display- Inhalt und Touch. Ob es noch andere Auswirkungen gibt, kann ich derzeit noch nicht sagen…

  10. Manuel sagt:

    Hi I could help, just ask him to place their information in English please in text files.
    Greetings …

  11. Manuel sagt:

    Very good job UB,
    I’m from Mexico and I’m learning to program in C language, I’m learning with ARM microcontrollers, and your libraries are helping me to make things easier.

    Thank you very much for their libraries.

    I wonder if you could develop something similar to the development environment “GUIBuilder” but focused on your graphics libraries.
    SGUI with SGUI_Builder.
    This would be very interesting.

    Again thank you very much.
    Greetings …
    Sorry for my bad English.

    • admin_ub sagt:

      hi,
      “sgui” is “simple”, so its not made to load an external file
      and create a gui out of this.
      the onle simplification with a computer-tool is to genereate
      “scripts-snippets” e.g. to add a buttton :

      SBUTTON_t* btn;
      btn=SGUI_ButtonCreate(10,20,100,25);
      SGUI_ButtonSetText(btn,"Text");

      and the user must cop&paste this script into the c-file.
      But thats a lot of work and in my opinion not usefull at all.

  12. Joe sagt:

    Hi,

    gibt es die Möglichkeit Bilder auf einem Window anzuzeigen?
    Ich habe versucht einfach in das Create eines Windows das Bild miteinzubinden, leider wird das Bild nur ganz am Anfang ganz kurz angezeigt.

    void create_Window1(void)
    {
    // ein Window erstellen (Nr. 1)
    SGUI_WindowCreateMain(1);
    // ein Label platzieren und beschriften
    label=SGUI_LabelCreate(10,10,220,50);
    SGUI_LabelSetText(label,”Window-1″);
    // einen Button platzieren und beschriften
    btn1=SGUI_ButtonCreate(10,100,100,50);
    SGUI_ButtonSetText(btn1,”Btn-1″);
    // einen Handler fuer den Button einrichten
    SGUI_ButtonSetHandler(btn1,btn1_fkt);
    // Ein Image (aus dem Flash) Zeichnen
    UB_Graphic_DrawImage(&Druck,50,50);
    }

    • admin_ub sagt:

      nein, das Bild (oder ein Text) wird immer wieder überschrieben bei redraw.
      Man müsste ein neues Objekt “Picture” zu diesem Zweck erstellen.
      Klingt nicht so schwer…besonders wenn es nur aus dem Flash gezeichnet werden muss…gib mir ein paar Tage.

  13. Joe sagt:

    Das wäre echt super wenn Du da etwas einbauen könntest.
    Ein Bild aus dem Flash reicht voll und ganz.
    Gruß

    • admin_ub sagt:

      probier mal die Version 1.2 aus. Es gibt zwei neue Befehle
      “CreatePicture” erstellt eine Picture-Objekt
      “PictureSetImage” teilt ein Bild aus dem Flash zu.

      • Joe sagt:

        Funktioniert super. Wäre toll wenn Du das bei Gelegenheit auch noch in die sgui Lib für den 407er integrieren könntest.
        Gruß

        • admin_ub sagt:

          theoretisch könnte man daraus auch einen “Button” machen. event. mit zwei gleich großen Bildern für die zwei Zustände.

          • Joe sagt:

            Das wäre natürlich absolut perfekt. So könnte man z.B. ein Zahnrad Bild für einen Einstellungsbutton nutzen.
            Wäre super wenn Du das einbauen könntest.

    • admin_ub sagt:

      schon fertig (Versionsnummer hab ich nicht hochgezählt)
      pro Picture können zwei Bilder definiert werden damit
      man gedrückt/nicht gedrückt unterscheiden kann.

      • Joe sagt:

        Super, konnte auf Anhieb einen Zahnrad Button erstellen.
        Danke für die schnelle Umsetzung.
        Kann ich die neuen Funktionen auch in die Lib für den 407er integrieren?
        Gruß

        • admin_ub sagt:

          die Version für den F407 ist auch schon fertig und online.

          • Joe sagt:

            Top, vielen Dank.
            Eine etwas spezifische Frage hätte ich jedoch noch.
            Wie würdest Du vorgehen wenn Du ähnlich dem Oszi Show Projekt einen kleinen Graphen in ein Main Window plotten wolltest?
            Gruß Joe

  14. admin_ub sagt:

    du kannst mit der Funktion “SGUI_ScreenDrawPixel(x,y,color)” beliebige
    Kurven auf das Display zeichnen. Damit diese allerdings sichtbar bleibt,
    muss das Window schon komplett gezeichnet sein.
    Ich würde in der Main-Loop unterhalb der “SGUI_Do”
    mit einem “if(SGUI_WindowGetActivNr()==oszi_page)”
    prüfen ob die richtige Seite angezeigt wird und dann mit einer For-n
    die Kurve plotten.

  15. admin_ub sagt:

    mir ist gerade eingefallen…natürlich könnte man auch ein Objekt daraus machen.
    Wenn es nicht auf die Updategeschwindigkeit ankommt sondern nur um das darstellen von einem Zahlen-Array geht. Mehr wie 300 Punkte machen eh keinen Sinn (weil das Display nur 320 Pixel breit ist) und ein uint8 pro Wert würde theoretisch auch reichen.
    Schreib mal was du genau vorhast und ob es eine statische Anzeige sein soll oder etwas das schnell refreshed werden muss.

    • Joe sagt:

      Ich logge u.a. die Werte eines externen Temperatursensors minütlich auf eine SD Karte. Ich dachte es wäre dann nicht schlecht den Temperaturverlauf auf dem Display darstellen zu können.
      Also schnell refreshed werden müsste es nicht, eher im Sekunden/Minutenbereich.
      Gruß

      • Joe sagt:

        Also die Werte wären dann wie von Dir schon geschrieben in einem Zahlenarray welches dann “nur” dargestellt werden müsste.
        Gruß

        • admin_ub sagt:

          ok, ich muss mal schauen wie man das am einfachsten implementieren kann.

          • Joe sagt:

            Das wäre super, danke.
            Gruß

  16. admin_ub sagt:

    ich habe mal eine Alpha hochgeladen (auf der Startseite) damit kannst du mal rumspielen. Die Grundfunktionen habe ich getestet. Das könnte man jetzt noch beliebig komplex machen (Grid, Y-Offset usw)

    • Joe sagt:

      Super, werde ich mal testen.
      Gruß

  17. Joerg B. sagt:

    Hallo Uwe,
    ich wollte mal eben schnell mit deiner Gui ein kleines Programm schreiben….

    Jetzt bin ich gerade etwas Ratlos. Wie gebe ich einen sich ständig ändernden Wert als Text in einem Fenster aus?

    Echt mal Hut ab, da hast du ein wirklich nettes Tool mal wieder geschrieben. Ich wünschte ich hätte so viel Zeit das selbst zu können ;)

    Grüße

    Jörg

    • Joerg B. sagt:

      Da ist zwar dein Beispiel:

      Beispiel-4 :
      —————————————-
      Wert von einer Zahl ändern

      void foo(void) {
      int a=12;
      STEXT_t *txt;

      SGUI_WindowCreateMain(1); // nr=1
      SGUI_TextCreateString(“Messwert=”);
      txt=SGUI_TextCreateInt(a,4,true); // mit 4 stellen mit führende Null
      SGUI_TextCreateString(“mV”); Anzeige = “Messwert=0012mV”

      a+=13;
      SGUI_TextSetInt(txt, a); // neuen Zahlenwert darstellen
      // Anzeige = “Messwert=0025mV”
      }

      Da wird der Wert ja aber in Foo geändert. Ich will / muss den Wert ja aus der while Schleife des Mains ändern

      • admin_ub sagt:

        mach einfach den Pointer auf den Text “global”

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        
        STEXT_t *txt; // globaler Pointer
         
        void create_fkt(int zahl) {
          SGUI_WindowCreateMain(1);
          SGUI_TextCreateString(“Messwert=);
          txt=SGUI_TextCreateInt(zahl,4,true);
          SGUI_TextCreateString(“mV”);
        }
         
        void main {
          int a=12;
          create_fkt(a);
         
          while(1) {
            SGUI_Do(); // SGUI bearbeiten
            SGUI_TextSetInt(txt, a);
            a+=13;    
          }
        }

      • Joerg B. sagt:

        Ok habs selbst raus bekommen… War mal wieder blind ;)

  18. Michael sagt:

    Hallo Uwe,

    an dieser Stelle möchte ich Dir ein dickes Lob aussprechen. Die SGUI ist genau das was ich gesucht habe.

    LG Michael DD4MS

  19. Pavel sagt:

    Hallo Uwe,
    erstmal ein großes Dankeschön für deine Bibliotheken.
    SGUI_FloatEditSetStyle funktioniert leider nicht mit STYLE_RAISED, es wird lowered angezeigt. Ich habe zwar hinbekommen, dass alle 3 Styles normal nutzbar sind, kommt mir aber ziemlich komisch vor. Vor allem weil ich unter anderem (ub_sgui_floatedit.c, Zeile 504)
    if((ptr->status&SFLOATEDIT_BIT_3DSTYLE)==0) zu
    if((ptr->status&SFLOATEDIT_BIT_3DSTYLE)!=0) ändern musste.
    Bei der Listbox müsste dann, glaube ich, das selbe Problem sein. Vielleicht auch noch bei paar anderen. Ich bitte um Nachbesserung.
    Schöne Grüße, Pavel

  20. Lisa sagt:

    Hi,
    I’m trying to understand how this library works, but I can’t find the definition of the UB_… functions like e.g. UB_Graphic2D_DrawPixelNormal. Where can I find them?

    Thanks

    • admin_ub sagt:

      sorry there is no english translation for the manual.
      please download the complete project files from “Demo_F429_27″
      So you have all necessary files included.
      You find all my “lolevel” libs in sub-folder “ub_lib”
      and the grafic-functions e.g.”UB_Graphic2D_DrawPixelNormal”
      in the file “stm32_ub_graphic2d.c”.
      dont hesitate to ask another question

  21. wissem sagt:

    Hello,
    First I’d like to thank you for your amazing work, I downloaded the SGUI library and demo project for STM32F429 disc, and after setting up the project for the lite version of atollic, I noticed that all objects work as expected but the integer ones , only letters are displayed instead of values (Integer=d, Integer=5d etc, while it should be Integer=123, Integer=00123), is this related to your library?
    PS: The coocox version is working out of the box
    Thanks in advance

    • wissem sagt:

      I fixed this, it’s because the Newlib-nano


Wie hat Dir dieser Artikel gefallen?

1 Stern2 Sterne3 Sterne4 Sterne5 Sterne (Noch keine Bewertungen)
Loading...

1 Antwort zu 27-Simple_GUI-Library (STM32F429)

  1. Jörg Boge sagt:

    Moin,
    ich versuche mich gerade an intedit, bin aber zu blöd dazu.
    Da sind ja 2 Beispiele in der Beschreibung.

    Für was steht num ? istwert=SGUI_IntEditGetValue(num);

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert