listbox.c
上传用户:zbk8730
上传日期:2017-08-10
资源大小:12168k
文件大小:14k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/GUI
  4. *                        Universal graphic software for embedded applications
  5. *
  6. *                       (c) Copyright 2002, Micrium Inc., Weston, FL
  7. *                       (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
  8. *
  9. *              礐/GUI is protected by international copyright laws. Knowledge of the
  10. *              source code may not be used to write a similar product. This file may
  11. *              only be used in accordance with a license and should not be redistributed
  12. *              in any way. We appreciate your understanding and fairness.
  13. *
  14. ----------------------------------------------------------------------
  15. File        : LISTBOX.c
  16. Purpose     : Multiple choice for emWin GSC
  17. ---------------------------END-OF-HEADER------------------------------
  18. */
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "LISTBOX.h"
  22. #include "SCROLLBAR.h"
  23. #include "WIDGET.h"
  24. #include "GUIDebug.h"
  25. #include "GUI_Protected.h"
  26. #include "WM_Intern.h"
  27. #if GUI_WINSUPPORT
  28. /*********************************************************************
  29. *
  30. *       Private config defaults
  31. *
  32. **********************************************************************
  33. */
  34. /* Support for 3D effects */
  35. #ifndef LISTBOX_USE_3D
  36.   #define LISTBOX_USE_3D 1
  37. #endif
  38. /* Define default fonts */
  39. #ifndef LISTBOX_FONT_DEFAULT
  40.   #define LISTBOX_FONT_DEFAULT &GUI_Font13_1
  41. #endif
  42. /* Define colors */
  43. #ifndef LISTBOX_BKCOLOR0_DEFAULT
  44.   #define LISTBOX_BKCOLOR0_DEFAULT GUI_WHITE
  45. #endif
  46. #ifndef LISTBOX_BKCOLOR1_DEFAULT
  47.   #define LISTBOX_BKCOLOR1_DEFAULT GUI_GRAY
  48. #endif
  49. #ifndef LISTBOX_BKCOLOR2_DEFAULT
  50.   #define LISTBOX_BKCOLOR2_DEFAULT GUI_WHITE
  51. #endif
  52. #ifndef LISTBOX_TEXTCOLOR0_DEFAULT
  53.   #define LISTBOX_TEXTCOLOR0_DEFAULT GUI_BLACK
  54. #endif
  55. #ifndef LISTBOX_TEXTCOLOR1_DEFAULT
  56.   #define LISTBOX_TEXTCOLOR1_DEFAULT GUI_BLACK
  57. #endif
  58. #ifndef LISTBOX_TEXTCOLOR2_DEFAULT
  59.   #define LISTBOX_TEXTCOLOR2_DEFAULT GUI_BLACK
  60. #endif
  61. /*********************************************************************
  62. *
  63. *       Object definition
  64. *
  65. **********************************************************************
  66. */
  67. typedef struct {
  68.   WIDGET Widget;
  69.   I16 Sel;                   /* current selection */
  70.   WM_SCROLL_STATE ScrollState;
  71.   const GUI_ConstString* ppText;
  72.   const GUI_FONT* pFont;
  73.   GUI_COLOR aBackColor[3];
  74.   GUI_COLOR aTextColor[3];
  75.   #if GUI_DEBUG_LEVEL >1
  76.     int DebugId;
  77.   #endif  
  78. } LISTBOX_Obj;
  79. /*********************************************************************
  80. *
  81. *       Static data
  82. *
  83. **********************************************************************
  84. */
  85. static const GUI_FONT* _pDefaultFont = LISTBOX_FONT_DEFAULT;
  86. /*********************************************************************
  87. *
  88. *       Macros for internal use
  89. *
  90. **********************************************************************
  91. */
  92. #define LISTBOX_H2P(h) (LISTBOX_Obj*) WM_HMEM2Ptr(h)
  93. #if GUI_DEBUG_LEVEL >1
  94.   #define OBJECT_ID 0x4C69   /* Magic numer, should be unique if possible */
  95.   #define ASSERT_IS_VALID_PTR(p) GUI_DEBUG_ERROROUT_IF(p->DebugId != OBJECT_ID, "EDIT.C: Wrong handle type or Object not init'ed")
  96.   #define INIT_ID(p)   p->DebugId = OBJECT_ID
  97.   #define DEINIT_ID(p) p->DebugId = 0
  98. #else
  99.   #define ASSERT_IS_VALID_PTR(p)
  100.   #define INIT_ID(p)
  101.   #define DEINIT_ID(p)
  102. #endif
  103. /*********************************************************************
  104. *
  105. *       Static routines
  106. *
  107. **********************************************************************
  108. */
  109. /*********************************************************************
  110. *
  111. *       _GetNumVisItems
  112.   Returns:
  113.     Number of fully or partially visible items
  114. */
  115. static int _GetNumVisItems(LISTBOX_Obj* pObj) {
  116.   int FontDist = GUI_GetYDistOfFont(pObj->pFont);
  117.   int ysize = WM__GetWindowSizeY(&pObj->Widget.Win);
  118.   ysize -= 2*  pObj->Widget.pEffect->EffectSize;
  119.   if (FontDist)
  120.     return ysize  / FontDist;
  121.   return 1;
  122. }
  123. /*********************************************************************
  124. *
  125. *       _GetNumItems
  126.   Returns:
  127.     Number of fully or partially visible items
  128. */
  129. static int _GetNumItems(LISTBOX_Obj* pObj) {
  130.   int i;
  131.   const GUI_ConstString* ppText = pObj->ppText;
  132.   if (ppText) {
  133.     for (i=0; *(ppText+i); i++);
  134.   return i;
  135.   }
  136.   return 0;
  137. }
  138. static void _SetScrollState(WM_HWIN hWin) {
  139.   LISTBOX_Obj* pObj    = LISTBOX_H2P(hWin);
  140.   WIDGET__SetScrollState(hWin, &pObj->ScrollState, NULL);
  141. }
  142. static void _CalcScrollParas(WM_HWIN hWin) {
  143.   LISTBOX_Obj* pObj    = LISTBOX_H2P(hWin);
  144.   pObj->ScrollState.NumItems = _GetNumItems(pObj);
  145.   pObj->ScrollState.PageSize = _GetNumVisItems(pObj);
  146. }
  147. static void _SetScroll(LISTBOX_Handle hObj, LISTBOX_Obj* pObj, int iScroll) {
  148.   pObj->ScrollState.v = iScroll;
  149.   _SetScrollState(hObj);
  150. }
  151. static void _CheckSel(LISTBOX_Handle hObj) {
  152.   int Sel;
  153.   LISTBOX_Obj* pObj = LISTBOX_H2P(hObj);
  154.   Sel = pObj->Sel;
  155.   /* Check if we have to scroll up */
  156.   if (Sel < pObj->ScrollState.v) {
  157.     _SetScroll(hObj, pObj, Sel);
  158.   } else {
  159.   /* Check if we have to scroll down */
  160.     if (Sel > pObj->ScrollState.v + pObj->ScrollState.PageSize -1) {
  161.       _SetScroll(hObj, pObj, Sel - (pObj->ScrollState.PageSize -1));
  162.     }
  163.   }   
  164. }
  165. static int _Tolower(int Key) {
  166.   if ((Key >= 0x41) && (Key <= 0x5a)) {
  167.     Key += 0x20;
  168.   }
  169.   return Key;
  170. }
  171. static void _SelectByKey(LISTBOX_Handle hObj, int Key) {
  172.   int i;
  173.   LISTBOX_Obj* pObj = LISTBOX_H2P(hObj);
  174.   Key = _Tolower(Key);
  175.   for (i = 0; i < _GetNumItems(pObj); i++) {
  176.     char c = _Tolower(*(*(pObj->ppText + i)));
  177.     if (c == Key) {
  178.       LISTBOX_SetSel(hObj, i);
  179.       break;
  180.     }
  181.   }
  182. }
  183. /*********************************************************************
  184. *
  185. *       _Paint
  186. */
  187. static void _Paint(LISTBOX_Handle hObj) {
  188.   int i;
  189.   int Border;
  190.   GUI_RECT r;
  191.   int FontDistY;
  192.   LISTBOX_Obj* pObj = LISTBOX_H2P(hObj);
  193.   int NumItems = _GetNumItems(pObj);
  194.   const GUI_ConstString* ppText = pObj->ppText;
  195.   Border = pObj->Widget.pEffect->EffectSize;
  196.   GUI_SetFont(pObj->pFont);
  197.   FontDistY = GUI_GetFontDistY();
  198.   if (Border) {
  199.     GUI_SetBkColor(pObj->aBackColor[0]);
  200.     GUI_Clear();
  201.   }
  202.   /* Calculate rect used for painting (subtract border) */
  203.   WM_GetClientRect(&r);
  204.   r.x1 -= Border;
  205.   r.y1 -= Border;
  206.   r.y0 -= Border;
  207.   WM_SetUserClipArea(&r);
  208.   for (i = pObj->ScrollState.v; i < NumItems; i++) {
  209.     int y, ColorIndex;
  210.     y = Border + (i - pObj->ScrollState.v) * FontDistY;
  211.     if (i == pObj->Sel) {
  212.       ColorIndex = (pObj->Widget.State & WIDGET_STATE_FOCUS) ? 2 : 1;
  213.     } else {
  214.       ColorIndex = 0;
  215.     }
  216.     GUI_SetBkColor(pObj->aBackColor[ColorIndex]);
  217.     GUI_SetColor  (pObj->aTextColor[ColorIndex]);
  218.     GUI_ClearRect(Border, y, Border, y + FontDistY -1);
  219.     GUI_DispStringAt(*(ppText+i), Border+1, y);
  220.     GUI_DispCEOL();
  221.   }
  222.   WM_SetUserClipArea(NULL);
  223.   /* Draw the 3D effect (if configured) */
  224.   WIDGET__EFFECT_DrawDown(&pObj->Widget);
  225. }
  226. /*********************************************************************
  227. *
  228. *       _OnTouch
  229. */
  230. static int _OnTouch(LISTBOX_Handle hObj, LISTBOX_Obj* pObj, WM_MESSAGE*pMsg) {
  231.   int Notification;
  232.   int Sel;
  233.   GUI_TOUCH_tState* pState = (GUI_TOUCH_tState*)pMsg->Data.p;
  234.   int FontDistY = GUI_GetYDistOfFont(pObj->pFont);
  235.   if (pMsg->Data.p) {  /* Something happened in our area (pressed or released) */
  236.     if (pState->Pressed) {
  237.       Sel = pState->y / FontDistY + pObj->ScrollState.v; 
  238.       WM_SetFocus(hObj);
  239.       Notification = WM_NOTIFICATION_CLICKED;
  240.       LISTBOX_SetSel(hObj, Sel);
  241.     } else {
  242.       Notification = WM_NOTIFICATION_RELEASED;
  243.     }
  244.   } else {     /* Mouse moved out */
  245.     Notification = WM_NOTIFICATION_MOVED_OUT;
  246.   }
  247.   WM_NotifyParent(hObj, Notification);
  248.   return 0;                        /* Message handled */
  249. }
  250. /*********************************************************************
  251. *
  252. *       Callback
  253. */
  254. static void _LISTBOX_Callback (WM_MESSAGE*pMsg) {
  255.   LISTBOX_Handle hObj = pMsg->hWin;
  256.   LISTBOX_Obj* pObj = LISTBOX_H2P(hObj);
  257.   WM_SCROLL_STATE ScrollState;
  258.   /* Let widget handle the standard messages */
  259.   if (WIDGET_HandleActive(hObj, pMsg) == 0) {
  260.     return;
  261.   }
  262.   switch (pMsg->MsgId) {
  263.   case WM_NOTIFY_PARENT:
  264.     if (pMsg->Data.v == WM_NOTIFICATION_VALUE_CHANGED) {
  265.       WM_GetScrollState(pMsg->hWinSrc, &ScrollState);
  266.     }
  267.     pObj->ScrollState.v = ScrollState.v;
  268.     WM_InvalidateWindow(hObj);
  269.     break;
  270.   case WM_ADD_SCROLLBAR:
  271.     _SetScrollState(hObj);
  272.     break;
  273.   case WM_PAINT:
  274.     _Paint(hObj);
  275.     break;
  276.   case WM_TOUCH:
  277.     if (_OnTouch(hObj, pObj, pMsg) == 0)
  278.       return;
  279.     break;
  280.   case WM_KEY:
  281.     if ( ((WM_KEY_INFO*)(pMsg->Data.p))->PressedCnt >0) {
  282.       int Key = ((WM_KEY_INFO*)(pMsg->Data.p))->Key;
  283.       switch (Key) {
  284.         case GUI_KEY_TAB:
  285.           break;                    /* Send to parent by not doing anything */
  286.         default:
  287.           LISTBOX_AddKey(hObj, Key);
  288.           return;
  289.       }
  290.     }
  291.     break;
  292.   }
  293.   WM_DefaultProc(pMsg);
  294. }
  295. /*********************************************************************
  296. *
  297. *       Exported routines:  Create
  298. *
  299. **********************************************************************
  300. */
  301. LISTBOX_Handle LISTBOX_CreateAsChild(
  302.   const GUI_ConstString* ppText,
  303.   WM_HWIN hWinParent,
  304.   int x0, int y0, int xsize, int ysize, int Flags)
  305. {
  306.   LISTBOX_Handle hObj = WM_CreateWindowAsChild(x0, y0, xsize, ysize, 
  307.                                                hWinParent, Flags, _LISTBOX_Callback,
  308.                                                sizeof(LISTBOX_Obj)-sizeof(WM_Obj));
  309.   if (hObj) {
  310.     LISTBOX_Obj* pObj   = LISTBOX_H2P(hObj);
  311.     /* init widget specific variables */
  312.     WIDGET__Init(&pObj->Widget, WIDGET_STATE_FOCUSSABLE | WIDGET_STATE_ENABLED);
  313.     /* pObj->ppText = 0; */   /* Zero init not required */
  314.     pObj->pFont  = _pDefaultFont;
  315.     pObj->aBackColor[0] = 0xffffff;            /* Non selected state */
  316.     pObj->aBackColor[1] = LISTBOX_BKCOLOR1_DEFAULT;    /* selected state */
  317.     pObj->aBackColor[2] = GUI_BLUE;            /* selected state with focus */
  318.     pObj->aTextColor[0] = 0x000000;            /* Non selected state */
  319.     pObj->aTextColor[1] = 0xffffff;            /* selected state */
  320.     pObj->aTextColor[2] = 0xffffff;            /* selected state with focus */
  321.     if (hObj && ppText) {
  322.       LISTBOX_Obj* pObj   = LISTBOX_H2P(hObj);
  323.       INIT_ID(pObj);
  324.       /* init member variables */
  325.       /* Check size */
  326.       if (!xsize) {
  327.         const GUI_FONT* pFontOld = GUI_SetFont(pObj->pFont);
  328.         int i;
  329.     for (i=0; *(ppText+i); i++) {
  330.           int Size = GUI_GetStringDistX(*(ppText+i));
  331.           if (Size>xsize)
  332.       xsize = Size;
  333.     }
  334.         GUI_SetFont(pFontOld);
  335.     }
  336.       /* Set non-zero attributes */
  337.       pObj->ppText = ppText;
  338.     }
  339.     _CalcScrollParas(hObj);
  340.   }
  341.   return hObj;
  342. }
  343. LISTBOX_Handle LISTBOX_Create(
  344.                     const GUI_ConstString* ppText,
  345.                     int x0, int y0, int xsize, int ysize, int Flags)
  346. {
  347.    return LISTBOX_CreateAsChild(ppText, WM_HWIN_NULL /*hWin*/, x0, y0, xsize, ysize, Flags);
  348. }
  349. LISTBOX_Handle LISTBOX_CreateIndirect(const GUI_WIDGET_CREATE_INFO* pCreateInfo, WM_HWIN hWinParent, int x0, int y0, WM_CALLBACK* cb) {
  350.   LISTBOX_Handle  hThis;
  351.   GUI_USE_PARA(cb);
  352.   hThis = LISTBOX_CreateAsChild(0,
  353.                                 hWinParent,
  354.                                 pCreateInfo->x0 + x0, 
  355.                                 pCreateInfo->y0 + y0, 
  356.                                 pCreateInfo->xSize, 
  357.                                 pCreateInfo->ySize, 
  358.                                 pCreateInfo->Flags);
  359.   if (hThis) {
  360.     LISTBOX_Obj* pObj = LISTBOX_H2P(hThis);
  361.     INIT_ID(pObj);
  362.     pObj->Widget.Id     = pCreateInfo->Id;
  363.     pObj->Widget.State  = LISTBOX_STATE_INACTIVE;
  364.   }
  365.   return hThis;
  366. }
  367. /*********************************************************************
  368. *
  369. *       Exported routines:  Various methods
  370. *
  371. **********************************************************************
  372. */
  373. void LISTBOX_AddKey(LISTBOX_Handle hObj, int Key) {
  374.   if (hObj) {
  375.     WM_LOCK();
  376.     switch (Key) {
  377.       case GUI_KEY_DOWN:
  378.         LISTBOX_IncSel(hObj);
  379.         break;
  380.       case GUI_KEY_UP:
  381.         LISTBOX_DecSel(hObj);
  382.         break;
  383.       default:
  384.         _SelectByKey(hObj, Key);
  385.         break;
  386.     }
  387.     WM_UNLOCK();
  388.   }
  389. }
  390. void LISTBOX_SetText(LISTBOX_Handle hObj, const GUI_ConstString* ppText) {
  391.   LISTBOX_Obj* pObj;
  392.   if (hObj) {
  393.     WM_LOCK();
  394.     pObj = LISTBOX_H2P(hObj);
  395.     ASSERT_IS_VALID_PTR(pObj);
  396.     pObj->ppText = ppText;
  397.     _CalcScrollParas(hObj);
  398.     LISTBOX_Invalidate(hObj);
  399.     WM_UNLOCK();
  400.   }
  401. }
  402. void LISTBOX_SetFont(LISTBOX_Handle hObj, const GUI_FONT* pfont) {
  403.   LISTBOX_Obj* pObj;
  404.   if (hObj) {
  405.     WM_LOCK();
  406.     pObj = LISTBOX_H2P(hObj);
  407.     ASSERT_IS_VALID_PTR(pObj);
  408.     pObj->pFont = pfont;
  409.     _CalcScrollParas(hObj);
  410.     LISTBOX_Invalidate(hObj);
  411.     WM_UNLOCK();
  412.   }
  413. }
  414. void LISTBOX_SetBackColor(LISTBOX_Handle hObj, int index, GUI_COLOR color) {
  415.   LISTBOX_Obj* pObj;
  416.   if (hObj) {
  417.     WM_LOCK();
  418.     pObj = LISTBOX_H2P(hObj);
  419.     ASSERT_IS_VALID_PTR(pObj);
  420.     pObj->aBackColor[index] = color;
  421.     LISTBOX_Invalidate(hObj);
  422.     WM_UNLOCK();
  423.   }
  424. }
  425. void LISTBOX_SetTextColor(LISTBOX_Handle hObj, int index, GUI_COLOR color) {
  426.   LISTBOX_Obj* pObj;
  427.   if (hObj) {
  428.     WM_LOCK();
  429.     pObj = LISTBOX_H2P(hObj);
  430.     ASSERT_IS_VALID_PTR(pObj);
  431.     pObj->aTextColor[index] = color;
  432.     LISTBOX_Invalidate(hObj);
  433.     WM_UNLOCK();
  434.   }
  435. }
  436. void LISTBOX_SetSel (LISTBOX_Handle hObj, int Sel) {
  437.   int NumItems, MaxSel;
  438.   LISTBOX_Obj* pObj;
  439.   if (hObj) {
  440.     WM_LOCK();
  441.     pObj = LISTBOX_H2P(hObj);
  442.     ASSERT_IS_VALID_PTR(pObj);
  443.     NumItems = _GetNumItems(pObj);
  444.     MaxSel = NumItems ? NumItems-1 : 0;
  445.     if (Sel>MaxSel) {
  446.       Sel = MaxSel;
  447.     }
  448.     if (Sel != pObj->Sel) {
  449.       pObj->Sel = Sel;
  450.       LISTBOX_Invalidate(hObj);
  451.       WM_NotifyParent(hObj, WM_NOTIFICATION_SEL_CHANGED);
  452.     }
  453.     _CheckSel(hObj);
  454.     WM_UNLOCK();
  455.   }
  456. }
  457. void LISTBOX_IncSel      (LISTBOX_Handle hObj) {
  458.   LISTBOX_Obj* pObj = LISTBOX_H2P(hObj);
  459.   int Sel = LISTBOX_GetSel(hObj);
  460.   pObj = pObj;
  461.   ASSERT_IS_VALID_PTR(pObj);
  462.   LISTBOX_SetSel(hObj, Sel+1);
  463. }
  464. void LISTBOX_DecSel      (LISTBOX_Handle hObj) {
  465.   int Sel = LISTBOX_GetSel(hObj);
  466.   if (Sel)
  467.   Sel--;
  468.   LISTBOX_SetSel(hObj, Sel);
  469. }
  470. int  LISTBOX_GetSel (LISTBOX_Handle hObj) {
  471.   int r = 0;
  472.   LISTBOX_Obj* pObj;
  473.   if (hObj) {
  474.     WM_LOCK();
  475.     pObj = LISTBOX_H2P(hObj);
  476.     ASSERT_IS_VALID_PTR(pObj);
  477.     r = pObj->Sel;
  478.     WM_UNLOCK();
  479.   }
  480.   return r;
  481. }
  482. void LISTBOX_SetDefaultFont(const GUI_FONT* pFont) {
  483.   _pDefaultFont = pFont;
  484. }
  485. const GUI_FONT* LISTBOX_GetDefaultFont(void) {
  486.   return _pDefaultFont;
  487. }
  488. #else                            /* Avoid problems with empty object modules */
  489.   void LISTBOX_C(void) {}
  490. #endif