#if !defined (__GUI_COMMON_H__)
  /*****************************************************************************************************************************
   * File:     GUIcommon.h
   * Purpose:
   * Author:   Erno Gilissen Belgium
   * Created:  October 31, 2025
   * Description:
   * - Defines RGB565 colors for the display (it's also possible to use direct hexadecimal values, but that doesn't read well to many people.
   * - Creates dedicated macros for Flash Data access on AVR microcontroller (Arduino Uno or Mega).
   * - Defines the different data types used in the GUI driver.
   *
   * Dependencies:
   * - There is indirect dependency to <avr/pgmspace.h> since it creates Flash access macro's (since not used here, basically search&replace for the preprocessor).
   */

  #define __GUI_COMMON_H__
  /*****************************************************************************************************************************
   * \ingroup declare
   * Font & color definitions.
   */
  #define FONT_WIDTH           (8)                                      //Font is proportional, this is not correct but OK for short texts in buttons.
  #define FONT_HEIGHT         (12)
  #define BLACK           (0x0000)
  #define BLUE            (0x001F)                                      //0b0000.0000.0001.1111 (RGB565).
  #define BLUE_MID        (0x000F)
  #define BLUE_DARK       (0x0007)
  #define RED             (0xF800)                                      //0b1111.1000.0000.0000 (RGB565).
  #define RED_MID         (0x7800)
  #define RED_DARK        (0x3800)
  #define GREEN           (0x07E0)                                      //0b0000.0111.1110.0000 (RGB565).
  #define GREEN_MID       (0x03E0)                                      //0b0000.0011.1110.0000.
  #define GREEN_DARK      (0x01E0)                                      //0b0000.0001.1110.0000.
  #define CYAN            (0x07FF)
  #define MAGENTA         (0xF81F)
  #define YELLOW          (0xFFE0)
  #define WHITE           (0xFFFF)

  #define PORTRAIT             (0)
  #define LANDSCAPE            (1)
  #define USE_XPT2046          (0)
  #define USE_LOCAL_KBV        (1)

  #if defined(RAMPZ)                                                    //RAMPZ present on devices with >64KB flash
    #define FRbu(addr) pgm_read_byte_far(addr)                          //Read FLASH Byte unsigned.
    #define FRbs(addr) ((int8_t)(pgm_read_byte_near(addr)))             //Read FLASH Byte signed.
    #define FRwu(addr) pgm_read_word_far(addr)                          //Read FLASH Word Unsigned (16bit - MC68K naming still in my head).
    #define FRws(addr) (int16_t)(pgm_read_word_far(addr))               //Read FLASH Word Signed (16bit - MC68K naming still in my head).
    #define FLRlu(addr) pgm_read_dword_far(addr)                        //Read FLASH Long (32bit).
    #define FLRp(addr) ((void*)((uint32_t)pgm_read_word_far((uint32_t)(addr)) | \
                       ((uint32_t)pgm_read_word_far((uint32_t)(addr) + 2) << 16)))
    #define FLRfp(addr) pgm_read_dword_far(addr)
    #define MEMCPY(dest,src,size) memcpy_PF(dest,src,size)
    #define STRNCPY(dest,src,size) strncpy_PF(dest,src,size)
  //const void (* const flashFuncs[])() PROGMEM = { function1, function2 };
  //void (*func)() = READ_FLASH_FUNC_PTR(&flashFuncs[1]);               //Example to call function2.
  //func ();
  #else
    #define FRbu(addr) pgm_read_byte_near(addr)
    #define FRbs(addr) ((int8_t)(pgm_read_byte_near(addr)))
    #define FRwu(addr) pgm_read_word_near(addr)
    #define FRws(addr) ((int16_t)(pgm_read_word_near(addr)))
    #define FLRlu(addr) pgm_read_double_near(addr)
    #define FLRp(addr) ((void*)((uint16_t)pgm_read_word_near((const void*)(addr))))
    #define FLRfp(addr) pgm_read_word_near(addr)
    #define MEMCPY(dest,src,size) memcpy_P(dest,src,size)
    #define STRNCPY(dest,src,size) strncpy_P(dest,src,size)
  #endif
  #define EEPROM __attribute__ ((section ( ".eeprom ")))



  /*****************************************************************************************************************************
   * \ingroup declare
   * These are subject to be (partially) removed (ex. remove Serial.print a from it to ensure the preprocessor removes the statements from compiling.
   */
  #define __DEBUG__
  #define DEBUGPRINT(a) Serial.print a                                  //DEBUGPRINT (default has no function).
  #define DEBUGPRINTN(a) Serial.println a                               //DEBUGPRINT (default has no function).
  #define DEBUGPRINTLL(a) //Serial.println a                            //Ignore Low Level DEBUGPRINT that might still be somewhere in the code.
  #define DEBUGPRINTLLN(a) //Serial.println a

  /*****************************************************************************************************************************
   * \ingroup declare
   * When the user touches the display, the touch position is used to determine what must be changed on the screen (since this requires minimal calculations).
   * If the object is bar or slider and must be re-drawn at a specific percentage, the correlating touch position gets calculated.
   */
  typedef enum
  {
    TOUCHPOS_REF,                                                       //BARs switchover position is taken from xTouch or yTouch coordinate.
    TOUCHPOS_CALC,                                                      //Compute SLIDERVAR switchover position (can be used to preset a SLIDERBAR when no touch involved).
  } TOUCH_REFERENCE;



  /*****************************************************************************************************************************
   * \ingroup declare
   * The different objects the GUI can handle. For FLASH space saving, consider to remove or comment out unused objects.
   * Note:
   * - LINE is slower than LINE_V or LINE_H, but can draw lines under angle.
   */
  typedef enum                                                          //Each screen can be build out of these 'objects'.
  {
    BACKGROUND =        0,                                              //Only as 1st statement (clears screen). Only uses Object Color.
    BUTTON_RECT,                                                        //Button (Filled) Rectangle.
    BUTTON_RECT_RND,                                                    //Button (Filled) Rectangle with Rounded Corners.
    BUTTON_ROUND,                                                       //Round Button.
    CHECKBOX,                                                           //Check Box.
    INPUT_DATA,                                                         //Used to mark an area for input values (ignored if 1st member in array).
    LABEL,                                                              //Label w/o shape.
    LINE,                                                               //Exception: sl=X0; sw=X1; st=Y0; sh=Y1.
    LINE_H,                                                             //Uses only sl, sw and st (X, Width, Y).
    LINE_V,                                                             //Uses only sl, st and sh (X, Y, Height).
    RECTANGLE,                                                          //Hollow Rectangle.
    RECTANGLE_FILL,                                                     //Filled Rectangle.
    BUTTON_SLH,
    BUTTON_SLV,
  //#if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega328PB__)   //Example how to exclude functions unused (also exclude source code).
      SLIDERBAR_H,                                                      //Horizontal Slider Bar.
      SLIDERBAR_V,                                                      //Vertical Slider bar..
  //#endif
  } SCR_OBJECT;




  /*****************************************************************************************************************************
   * \ingroup declare
   * If the screen built-up function is called, there are 3 options supported:
   *                        | Requested Screen already on top | Actual Screen Different
   * SCR_DRAW               |        Do nothing               | Clear screen & draw the requested screen.
   * SCR_REDRAW,            |    Clear screen & re-draw       | Clear screen & draw the requested screen.
   * SCR_REDRAW_W_CLR       |   Re-draw w/o clearing first    | Clear screen & draw the requested screen.
   */
  typedef enum
  {
    SCR_DRAW =          0,
    SCR_REDRAW,
    SCR_REDRAW_W_CLR,
  } SCR_UPDATE;





  /*****************************************************************************************************************************
   * \ingroup declare
   * Below structure is placed in FLASH memory. Since AVR is Harvard architecture, it defaults not to use FLASH
   * for data handling (in assembler, the LPM instruction must be used to read data from FLASH). Instead, AVR duplicates in the
   * startup file const data to RAM and leaves it there untouched. To avoid RAM is wasted to store this struct, all use cases
   * must declare it PROGMEM. This excludes the struct from being duplicated to RAM on startup (see file GUIuser.h.
   * - The structure is compiled packed, so that every type is stored in the most dense format.
   * - The offsets in the structure are in the driver computed as byte offsets.
   * - Every reference tot he struct must be converted to uint8_t* pointer, what results in a byte based pointer arithmetic.
   */
  typedef struct __attribute__((__packed__))
  {
    const SCR_OBJECT       obj;                                           //Screen Object (uint16_t).
    const uint16_t         tX0;                                           //X-ABS Touch Left (LABEL, LINE: keep 0).
    const uint16_t         tX1;                                           //X-ABS Touch Right (LABEL, LINE: keep 0).
    const uint16_t         tY0;                                           //Y-ABS Touch Top (LABEL, LINE: keep 0).
    const uint16_t         tY1;                                           //Y-ABS Touch Bottom (LABEL, LINE: keep 0).
    const uint16_t         oX0;                                           //X-ABS Object Left.
    const uint16_t          oW;                                           //X-REL Object Width (BUTTON_ROUND: Diameter; LINE: X-endpoint).
    const uint16_t         oY0;                                           //Y-ABS Object Top.
    const uint16_t          oH;                                           //X-REL Object Height (BUTTON_ROUND: N/A; LINE: Y-endpoint)).
    const uint16_t          oE;                                           //Object Extra: - Rounding (BUTTON_RECT_RND)
                                                                          //              - division (SLIDERBAR_?)
                                                                          //              - 3D effect (BUTTON_RECT; 0 = none);
    const uint16_t          oC;                                           //Object Color.
    const uint16_t         lX0;                                           //Label X Pos (0 = automatic).
    const uint16_t         lY0;                                           //Label Y Pos (0 = automatic).
    const char*            txt PROGMEM;                                   //Pointer to Text (text cannot exceed 31 chars, see \ref screen_obj_draw).
    const uint16_t          fS;                                           //Font Size (1 ... 4).
    const uint16_t          lC;                                           //Label Text Color.
    void  (*onClick) (int8_t) PROGMEM;                                    //Pointer to callback function when the object is selected by touch.
    const int8_t        oLoPct;                                           //Value passed when pressed; SLIDERBAR_?: left / bottom value (= lowest).
    const int8_t        oHiPct;                                           //SLIDERBAR_?: right / top value (= highest).
  } SCR_DATA;
                                                                         //Uno.  Notes:
#endif