DROPDOWN - Custom (Sample)

From SEGGER Wiki
Jump to: navigation, search
DROPDOWN_Custom.c
DROPDOWN Custom.png
File(s) required
  • DROPDOWN_Custom.c
Runs in simulation Yes
Runs on target Yes
Download DROPDOWN_Custom.c

This sample demonstrates custom drawing of a DROPDOWN widget.

Demo

Code

/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2022  SEGGER Microcontroller GmbH                *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
**********************************************************************

** emWin V6.22 - Graphical user interface for embedded applications **
emWin is protected by international copyright laws.   Knowledge of the
source code may not be used to write a similar product.  This file may
only  be used  in accordance  with  a license  and should  not be  re-
distributed in any way. We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : DROPDOWN_Custom.c
Purpose     : Sample that demonstrates how a custom look can be
              applied to a DROPDOWN widget and its attached LISTBOX
              widget in emWin.
Requirements: WindowManager - (x)
              MemoryDevices - ( )
              AntiAliasing  - ( )
              VNC-Server    - ( )
              PNG-Library   - ( )
              TrueTypeFonts - ( )
Wiki link   : https://wiki.segger.com/DROPDOWN_-_Usage_%28Sample%29
---------------------------END-OF-HEADER------------------------------
*/

#include "DIALOG.h"
#include <stdio.h>

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
#define LB_COLOR_SEL GUI_MAKE_COLOR(0x00F39621)
//
// For emWin versions below 6.22
//
#ifndef DROPDOWN_NOTIFICATION_EXPANDED
  #define DROPDOWN_NOTIFICATION_EXPANDED  WM_NOTIFICATION_CLICKED
#endif

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
/*********************************************************************
*
*       _acContent
*/
static const char * _acContent[] = {
  "English",
  "Deutsch",
  "Espanol",
  "Francais",
  "Italiano",
  "Dansk",
  "Eesti",
  "Hrvatski",
  "Portugues",
  "Suomi",
  "Afrikaans",
  "Swahili",
  "Arabic",
  "Esperanto",
  "Russian",
};

/*********************************************************************
*
*       _acangle_arrow
*/
static GUI_CONST_STORAGE unsigned char _acangle_arrow[] = {
  /* ABS: 003 Pixels @ 00,00 */ 0, 3, 0xAC, 0x23, 0xC8,
  /* RLE: 011 Pixels @ 03,00 */ 11, 0xFF,
  /* ABS: 007 Pixels @ 14,00 */ 0, 7, 0xC8, 0x23, 0xAC, 0x22, 0x00, 0x1C, 0xCE,
  /* RLE: 009 Pixels @ 04,01 */ 9, 0xFF,
  /* ABS: 010 Pixels @ 13,01 */ 0, 10, 0xCE, 0x1C, 0x00, 0x22, 0xC1, 0x17, 0x00, 0x16, 0xCC, 0xFE,
  /* RLE: 005 Pixels @ 06,02 */ 5, 0xFF,
  /* ABS: 012 Pixels @ 11,02 */ 0, 12, 0xFE, 0xCC, 0x16, 0x00, 0x17, 0xC1, 0xFF, 0xC1, 0x11, 0x00, 0x1E, 0xD0,
  /* RLE: 005 Pixels @ 06,03 */ 5, 0xFF,
  /* ABS: 021 Pixels @ 11,03 */ 0, 21, 0xD0, 0x1E, 0x00, 0x12, 0xC1, 0xFF, 0xFF, 0xFF, 0xBF, 0x18, 0x00, 0x16, 0xC9, 0xFE, 0xFF, 0xFE, 0xC9, 0x16, 0x00, 0x18, 0xBF,
  /* RLE: 005 Pixels @ 15,04 */ 5, 0xFF,
  /* ABS: 011 Pixels @ 03,05 */ 0, 11, 0xC3, 0x15, 0x00, 0x1C, 0xCC, 0xFF, 0xCC, 0x1C, 0x00, 0x15, 0xC4,
  /* RLE: 007 Pixels @ 14,05 */ 7, 0xFF,
  /* ABS: 009 Pixels @ 04,06 */ 0, 9, 0xC0, 0x18, 0x00, 0x13, 0x9D, 0x13, 0x00, 0x19, 0xC0,
  /* RLE: 009 Pixels @ 13,06 */ 9, 0xFF,
  /* ABS: 007 Pixels @ 05,07 */ 0, 7, 0xC4, 0x16, 0x00, 0x02, 0x00, 0x16, 0xC4,
  /* RLE: 011 Pixels @ 12,07 */ 11, 0xFF,
  /* ABS: 005 Pixels @ 06,08 */ 0, 5, 0xBC, 0x16, 0x00, 0x16, 0xBC,
  /* RLE: 013 Pixels @ 11,08 */ 13, 0xFF,
  /* ABS: 003 Pixels @ 07,09 */ 0, 3, 0xC1, 0x2C, 0xC1,
  /* RLE: 007 Pixels @ 10,09 */ 7, 0xFF,
  0
};  // 129 bytes for 170 pixels

/*********************************************************************
*
*       bmangle_arrow
*/
static GUI_CONST_STORAGE GUI_BITMAP bmangle_arrow = {
  17, // xSize
  10, // ySize
  17, // BytesPerLine
  GUI_COMPRESS_RLE8, // BitsPerPixel
  (const unsigned char*)_acangle_arrow,  // Pointer to picture data
  NULL,  // Pointer to palette
  GUI_DRAW_RLEALPHA
};

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _DrawRectFlat
*/
static void _DrawRectFlat(const GUI_RECT* pRect) {
  GUI_CONTEXT Context;
  GUI_SaveContext(&Context);
  //
  // Fill corners with white
  //
  GUI_SetColor(GUI_WHITE);
  GUI_DrawRoundedFrameEx(pRect, 1, 2);
  //
  // Draws a gray rounded frame
  //
  LCD_SetColor(GUI_GRAY_C0);
  GUI_SetPenSize(2);
  GUI_AA_DrawRoundedFrameEx(pRect, 8);
  //
  // Leftover pixels of rectangle
  //
  GUI_SetColor(0xFFD8D8D8);
  GUI_DrawPixel(pRect->x0 + 2, pRect->y0 + 2);
  GUI_DrawPixel(pRect->x0 + 2, pRect->y1 - 2);
  GUI_DrawPixel(pRect->x1 - 2, pRect->y1 - 2);
  GUI_DrawPixel(pRect->x1 - 2, pRect->y0 + 2);
  GUI_RestoreContext(&Context);
}

/*********************************************************************
*
*       _ListboxEffect
*/
static const WIDGET_EFFECT _ListboxEffect = {
  2,             // EffectSize
  NULL,          // pfDrawUp
  NULL,          // pfDrawUpRect
  NULL,          // pfDrawDown
  _DrawRectFlat, // pfDrawDownRect
  NULL,          // pfDrawFlat
  NULL           // pfDrawFlatRect
};

/*********************************************************************
*
*       _DropdownSkin
*/
static int _DropdownSkin(const WIDGET_ITEM_DRAW_INFO* pInfo) {
  char acText[64];
  int  Sel;

  switch (pInfo->Cmd) {
  case WIDGET_ITEM_DRAW_ARROW:
    GUI_DrawBitmap(&bmangle_arrow, pInfo->x1 - 10 - bmangle_arrow.XSize, pInfo->y0 + 10);
    return 0;
  case WIDGET_ITEM_DRAW_BACKGROUND:
    //
    // Draw frame
    //
    GUI_SetColor(GUI_GRAY_C0);
    GUI_SetPenSize(2);
    GUI_AA_DrawRoundedFrame(pInfo->x0, pInfo->y0, pInfo->x1, pInfo->y1, 8);
    return 0;
  case WIDGET_ITEM_DRAW_TEXT:
    Sel = DROPDOWN_GetSel(pInfo->hWin);
    DROPDOWN_GetItemText(pInfo->hWin, Sel, acText, sizeof(acText));
    GUI_SetColor(GUI_BLACK);
    GUI_SetTextMode(GUI_TM_TRANS);
    GUI_SetFont(DROPDOWN_GetFont(pInfo->hWin));
    GUI_DispStringAt(acText, pInfo->x0 + 10, pInfo->y0 + 2);
    return 0;
  }
  return 0;
}

/*********************************************************************
*
*       _OwnerDrawListbox
*/
static int _OwnerDrawListbox(const WIDGET_ITEM_DRAW_INFO* pDrawItemInfo) {
  int  Sel;
  char acBuffer[32];

  switch (pDrawItemInfo->Cmd) {
  case WIDGET_ITEM_DRAW:
    //
    // Draw background
    //
    if (pDrawItemInfo->ItemIndex != -1) {
      Sel = LISTBOX_GetSel(pDrawItemInfo->hWin);
      if (pDrawItemInfo->ItemIndex == Sel) {
        GUI_SetColor(LB_COLOR_SEL);
      }
      else {
        GUI_SetColor(GUI_WHITE);
      }
      GUI_FillRect(pDrawItemInfo->x0, pDrawItemInfo->y0, pDrawItemInfo->x1, pDrawItemInfo->y1);
      //
      // Draw item text
      //
      LISTBOX_GetItemText(pDrawItemInfo->hWin, pDrawItemInfo->ItemIndex, acBuffer, sizeof(acBuffer));
      GUI_SetTextMode(GUI_TM_TRANS);
      if (pDrawItemInfo->ItemIndex == Sel) {
        GUI_SetColor(GUI_WHITE);
      }
      else {
        GUI_SetColor(GUI_BLACK);
      }
      GUI_DispStringAt(acBuffer, pDrawItemInfo->x0 + 8, pDrawItemInfo->y0);
    } else {
      GUI_SetColor(GUI_WHITE);
      GUI_FillRect(pDrawItemInfo->x0, pDrawItemInfo->y0, pDrawItemInfo->x1, pDrawItemInfo->y1);
    }
    return 0;
  default:
    return LISTBOX_OwnerDraw(pDrawItemInfo);
  }
}

/*********************************************************************
*
*       _cbListbox
*/
static void _cbListbox(WM_MESSAGE * pMsg) {
  GUI_RECT Rect;

  switch (pMsg->MsgId) {
  case WM_PAINT:
    //
    // Handle paint
    //
    LISTBOX_Callback(pMsg);
    //
    // Force redrawing of effect
    // Necessary because we draw a rounded rectangle as the effect instead of a normal rectangle.
    // 
    WM_GetClientRect(&Rect);
    _ListboxEffect.pfDrawDownRect(&Rect);
    break;
  default:
    LISTBOX_Callback(pMsg);
  }
}

/*********************************************************************
*
*       _cbWin
*/
static void _cbWin(WM_MESSAGE * pMsg) {
  char                   acBuffer[128];
  int                    Sel;
  static DROPDOWN_Handle hDropdown;
  int                    i;
  int                    NCode, Id;
  int                    NumItems;
  WM_HWIN                hList;

  switch (pMsg->MsgId) {
  case WM_CREATE:
    //
    // Create DROPDOWN widget
    //
    hDropdown = DROPDOWN_CreateEx(10, 10, 200, 130, pMsg->hWin, WM_CF_SHOW, 0, GUI_ID_DROPDOWN0);
    DROPDOWN_EnableMotion(hDropdown, 1);
    //
    // Add items to widget
    //
    for (i = 0; i < GUI_COUNTOF(_acContent); i++) {
      DROPDOWN_AddString(hDropdown, *(_acContent + i));
    }
    //
    // Change appearance of DROPDOWN
    //
    DROPDOWN_SetFont(hDropdown, &GUI_Font24_1);
    DROPDOWN_SetSkin(hDropdown, _DropdownSkin);
    break;
  case WM_PAINT:
    GUI_SetBkColor(GUI_WHITE);
    GUI_Clear();
    GUI_SetColor(GUI_BLACK);
    GUI_SetFont(&GUI_Font13B_1);
    GUI_SetTextMode(GUI_TM_TRANS);
    //
    // Display current selection
    //
    Sel = DROPDOWN_GetSel(hDropdown);
    sprintf(acBuffer, "Currently selected item (%d): %s", Sel, *(_acContent + Sel));
    GUI_DispStringAt(acBuffer, 250, 10);
    //
    // Display number of items
    //
    NumItems = DROPDOWN_GetNumItems(hDropdown);
    sprintf(acBuffer, "Number of items: %d", NumItems);
    GUI_DispStringAt(acBuffer, 250, 30);
    break;
  case WM_NOTIFY_PARENT:
    //
    // Save ID of sender window and notification code
    //
    Id    = WM_GetId(pMsg->hWinSrc);
    NCode = pMsg->Data.v;
    switch (Id) {
    case GUI_ID_DROPDOWN0:
      switch (NCode) {
      case DROPDOWN_NOTIFICATION_EXPANDED:
        hList = DROPDOWN_GetListbox(hDropdown);
        if (hList) {
          //
          // Set custom appearance to LISTBOX
          //
          LISTBOX_SetOwnerDraw(hList, _OwnerDrawListbox);
          WIDGET_SetEffect(hList, &_ListboxEffect);
          WM_SetCallback(hList, _cbListbox);
        }
        break;
      case WM_NOTIFICATION_SEL_CHANGED:
        //
        // Invalidate parent window when a new item has been selected to display the new selection.
        //
        WM_InvalidateWindow(pMsg->hWin);
        break;
      }
      break;
    }
    break;
  default:
    WM_DefaultProc(pMsg);
    break;
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void) {
  WM_HWIN hWin;

  //
  // Init GUI
  //
  GUI_Init();
  WM_MULTIBUF_Enable(1);
  //
  // Create parent window
  //
  hWin = WM_CreateWindowAsChild(0, 0, LCD_GetXSize(), LCD_GetYSize(), WM_HBKWIN, WM_CF_SHOW, _cbWin, 0);

  while (1) {
    GUI_Delay(100);
  }
}

/*************************** End of file ****************************/