📄 listbox.c
字号:
/*
*********************************************************************************************************
* uC/GUI V3.98
* Universal graphic software for embedded applications
*
* (c) Copyright 2002, Micrium Inc., Weston, FL
* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
* 礐/GUI 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 redistributed
* in any way. We appreciate your understanding and fairness.
*
----------------------------------------------------------------------
File : LISTBOX.c
Purpose : Implementation of listbox widget
---------------------------END-OF-HEADER------------------------------
*/
#include <stdlib.h>
#include <string.h>
#include "GUI_ARRAY.h"
#include "LISTBOX_Private.h"
#include "SCROLLBAR.h"
#include "GUIDebug.h"
#include "GUI_Protected.h"
#include "WM_Intern.h"
#if GUI_WINSUPPORT
/*********************************************************************
*
* Private config defaults
*
**********************************************************************
*/
/* Define default fonts */
#ifndef LISTBOX_FONT_DEFAULT
#if WIDGET_USE_SCHEME_SMALL
#define LISTBOX_FONT_DEFAULT &GUI_Font13_1
#elif WIDGET_USE_SCHEME_MEDIUM
#define LISTBOX_FONT_DEFAULT &GUI_Font16_1
#elif WIDGET_USE_SCHEME_LARGE
#define LISTBOX_FONT_DEFAULT &GUI_Font24_1
#endif
#endif
/* Define colors */
#ifndef LISTBOX_BKCOLOR0_DEFAULT
#define LISTBOX_BKCOLOR0_DEFAULT GUI_WHITE /* Not selected */
#endif
#ifndef LISTBOX_BKCOLOR1_DEFAULT
#define LISTBOX_BKCOLOR1_DEFAULT GUI_GRAY /* Selected, no focus */
#endif
#ifndef LISTBOX_BKCOLOR2_DEFAULT
#define LISTBOX_BKCOLOR2_DEFAULT GUI_BLUE /* Selected, focus */
#endif
#ifndef LISTBOX_BKCOLOR3_DEFAULT
#define LISTBOX_BKCOLOR3_DEFAULT 0xC0C0C0 /* Disabled */
#endif
#ifndef LISTBOX_TEXTCOLOR0_DEFAULT
#define LISTBOX_TEXTCOLOR0_DEFAULT GUI_BLACK /* Not selected */
#endif
#ifndef LISTBOX_TEXTCOLOR1_DEFAULT
#define LISTBOX_TEXTCOLOR1_DEFAULT GUI_WHITE /* Selected, no focus */
#endif
#ifndef LISTBOX_TEXTCOLOR2_DEFAULT
#define LISTBOX_TEXTCOLOR2_DEFAULT GUI_WHITE /* Selected, focus */
#endif
#ifndef LISTBOX_TEXTCOLOR3_DEFAULT
#define LISTBOX_TEXTCOLOR3_DEFAULT GUI_GRAY /* Disabled */
#endif
#ifndef LISTBOX_TEXTALIGN_DEFAULT
#define LISTBOX_TEXTALIGN_DEFAULT GUI_TA_LEFT /* Left aligned */
#endif
#ifndef LISTBOX_SCROLLSTEP_H_DEFAULT
#define LISTBOX_SCROLLSTEP_H_DEFAULT 10
#endif
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
LISTBOX_PROPS LISTBOX_DefaultProps = {
LISTBOX_FONT_DEFAULT,
LISTBOX_SCROLLSTEP_H_DEFAULT,
LISTBOX_BKCOLOR0_DEFAULT,
LISTBOX_BKCOLOR1_DEFAULT,
LISTBOX_BKCOLOR2_DEFAULT,
LISTBOX_BKCOLOR3_DEFAULT,
LISTBOX_TEXTCOLOR0_DEFAULT,
LISTBOX_TEXTCOLOR1_DEFAULT,
LISTBOX_TEXTCOLOR2_DEFAULT,
LISTBOX_TEXTCOLOR3_DEFAULT,
GUI_INVALID_COLOR,
GUI_INVALID_COLOR,
GUI_INVALID_COLOR,
LISTBOX_TEXTALIGN_DEFAULT
};
/*********************************************************************
*
* Static routines
*
**********************************************************************
*/
/*********************************************************************
*
* _CallOwnerDraw
*/
static int _CallOwnerDraw(LISTBOX_Handle hObj, const LISTBOX_Obj* pObj, int Cmd, int ItemIndex) {
WIDGET_ITEM_DRAW_INFO ItemInfo;
int r;
ItemInfo.Cmd = Cmd;
ItemInfo.hWin = hObj;
ItemInfo.ItemIndex = ItemIndex;
if (pObj->pfDrawItem) {
r = pObj->pfDrawItem(&ItemInfo);
} else {
r = LISTBOX_OwnerDraw(&ItemInfo);
}
return r;
}
/*********************************************************************
*
* _GetYSize
*/
static int _GetYSize(LISTBOX_Handle hObj) {
GUI_RECT Rect;
WM_GetInsideRectExScrollbar(hObj, &Rect);
return (Rect.y1 - Rect.y0 + 1);
}
/*********************************************************************
*
* _GetItemSizeX
*/
static int _GetItemSizeX(LISTBOX_Handle hObj, const LISTBOX_Obj* pObj, unsigned Index) {
LISTBOX_ITEM* pItem;
int xSize = 0;
pItem = (LISTBOX_ITEM*)GUI_ARRAY_GetpItem(&pObj->ItemArray, Index);
if (pItem) {
xSize = pItem->xSize;
}
if (xSize == 0) {
const GUI_FONT GUI_UNI_PTR* pOldFont;
pOldFont = GUI_SetFont(pObj->Props.pFont);
xSize = _CallOwnerDraw(hObj, pObj, WIDGET_ITEM_GET_XSIZE, Index);
GUI_SetFont(pOldFont);
}
if (pItem) {
pItem->xSize = xSize;
}
return xSize;
}
/*********************************************************************
*
* _GetItemSizeY
*/
static int _GetItemSizeY(LISTBOX_Handle hObj, const LISTBOX_Obj* pObj, unsigned Index) {
LISTBOX_ITEM* pItem;
int ySize = 0;
pItem = (LISTBOX_ITEM*)GUI_ARRAY_GetpItem(&pObj->ItemArray, Index);
if (pItem) {
ySize = pItem->ySize;
}
if (ySize == 0) {
const GUI_FONT GUI_UNI_PTR* pOldFont;
pOldFont = GUI_SetFont(pObj->Props.pFont);
ySize = _CallOwnerDraw(hObj, pObj, WIDGET_ITEM_GET_YSIZE, Index);
GUI_SetFont(pOldFont);
}
if (pItem) {
pItem->ySize = ySize;
}
return ySize;
}
/*********************************************************************
*
* _GetContentsSizeX
*/
static int _GetContentsSizeX(LISTBOX_Handle hObj) {
LISTBOX_Obj* pObj;
int i, NumItems, SizeX;
int Result = 0;
pObj = LISTBOX_H2P(hObj);
NumItems = LISTBOX__GetNumItems(pObj);
for (i = 0; i < NumItems; i++) {
SizeX = _GetItemSizeX(hObj, pObj, i);
if (Result < SizeX) {
Result = SizeX;
}
}
return Result;
}
/*********************************************************************
*
* _GetItemPosY
*/
static int _GetItemPosY(LISTBOX_Handle hObj, const LISTBOX_Obj* pObj, unsigned Index) {
if (Index < LISTBOX__GetNumItems(pObj)) {
if ((int)Index >= pObj->ScrollStateV.v) {
unsigned i;
int PosY = 0;
for (i = pObj->ScrollStateV.v; i < Index; i++) {
PosY += _GetItemSizeY(hObj, pObj, i);
}
return PosY;
}
}
return -1;
}
/*********************************************************************
*
* _IsPartiallyVis
*/
static int _IsPartiallyVis(LISTBOX_Handle hObj, const LISTBOX_Obj* pObj) {
int Index;
Index = pObj->Sel;
if (Index < (int)LISTBOX__GetNumItems(pObj)) {
if (Index >= pObj->ScrollStateV.v) {
int y;
y = _GetItemPosY (hObj, pObj, Index);
y += _GetItemSizeY(hObj, pObj, Index);
if (y > _GetYSize(hObj)) {
return 1;
}
}
}
return 0;
}
/*********************************************************************
*
* _GetNumVisItems
*
* Returns:
* Number of fully or partially visible items
*/
static unsigned _GetNumVisItems(const LISTBOX_Obj* pObj, LISTBOX_Handle hObj) {
int NumItems, r = 1;
NumItems = LISTBOX__GetNumItems(pObj);
if (NumItems > 1) {
int i, ySize, DistY = 0;
ySize = _GetYSize(hObj);
for (i = NumItems - 1; i >= 0; i--) {
DistY += _GetItemSizeY(hObj, pObj, i);
if (DistY > ySize) {
break;
}
}
r = NumItems - i - 1;
if (r < 1) {
return 1;
}
}
return r;
}
/*********************************************************************
*
* _NotifyOwner
*
* Purpose:
* Notify owner of the window by sending a WM_NOTIFY_PARENT message.
* If no owner is registered, the parent is considered owner.
*/
static void _NotifyOwner(WM_HWIN hObj, int Notification) {
WM_MESSAGE Msg = {0};
WM_HWIN hOwner;
LISTBOX_Obj* pObj = LISTBOX_H2P(hObj);
hOwner = pObj->hOwner ? pObj->hOwner : WM_GetParent(hObj);
Msg.MsgId = WM_NOTIFY_PARENT;
Msg.Data.v = Notification;
Msg.hWinSrc= hObj;
WM__SendMessage(hOwner, &Msg);
}
/*********************************************************************
*
* _SendToOwner
*
* Purpose:
* Sends the given emssage to the owner of the window.
* If no owner is registered, the parent is considered owner.
*/
static void _SendToOwner(WM_HWIN hObj, WM_MESSAGE * pMsg) {
WM_HWIN hOwner;
LISTBOX_Obj * pObj = LISTBOX_H2P(hObj);
hOwner = pObj->hOwner ? pObj->hOwner : WM_GetParent(hObj);
pMsg->hWinSrc= hObj;
WM__SendMessage(hOwner, pMsg);
}
/*********************************************************************
*
* LISTBOX_OwnerDraw
*/
int LISTBOX_OwnerDraw(const WIDGET_ITEM_DRAW_INFO* pDrawItemInfo) {
switch (pDrawItemInfo->Cmd) {
case WIDGET_ITEM_GET_XSIZE: {
LISTBOX_Obj* pObj;
const GUI_FONT GUI_UNI_PTR* pOldFont;
const char* s;
int DistX;
pObj = LISTBOX_H2P(pDrawItemInfo->hWin);
pOldFont = GUI_SetFont(pObj->Props.pFont);
s = LISTBOX__GetpString(pObj, pDrawItemInfo->ItemIndex);
DistX = GUI_GetStringDistX(s);
GUI_SetFont(pOldFont);
return DistX;
}
case WIDGET_ITEM_GET_YSIZE: {
LISTBOX_Obj* pObj;
pObj = LISTBOX_H2P(pDrawItemInfo->hWin);
return GUI_GetYDistOfFont(pObj->Props.pFont) + pObj->ItemSpacing;
}
case WIDGET_ITEM_DRAW: {
LISTBOX_Obj* pObj;
LISTBOX_ITEM* pItem;
WM_HMEM hItem;
GUI_RECT r, rText;
int FontDistY;
int ItemIndex = pDrawItemInfo->ItemIndex;
const char* s;
int ColorIndex;
char IsDisabled;
char IsSelected;
pObj = LISTBOX_H2P(pDrawItemInfo->hWin);
hItem = GUI_ARRAY_GethItem(&pObj->ItemArray, ItemIndex);
pItem = (LISTBOX_ITEM *)GUI_ALLOC_h2p(hItem);
WM_GetInsideRect(&r);
FontDistY = GUI_GetFontDistY();
/* Calculate color index */
IsDisabled = (pItem->Status & LISTBOX_ITEM_DISABLED) ? 1 : 0;
IsSelected = (pItem->Status & LISTBOX_ITEM_SELECTED) ? 1 : 0;
if (pObj->Flags & LISTBOX_SF_MULTISEL) {
if (IsDisabled) {
ColorIndex = LISTBOX_CI_DISABLED;
} else {
ColorIndex = (IsSelected) ? LISTBOX_CI_SELFOCUS : LISTBOX_CI_UNSEL;
}
} else {
if (IsDisabled) {
ColorIndex = LISTBOX_CI_DISABLED;
} else {
if (ItemIndex == pObj->Sel) {
ColorIndex = (pObj->Widget.State & WIDGET_STATE_FOCUS) ? LISTBOX_CI_SELFOCUS : LISTBOX_CI_SEL;
} else {
ColorIndex = LISTBOX_CI_UNSEL;
}
}
}
/* Display item */
LCD_SetBkColor(pObj->Props.aBackColor[ColorIndex]);
LCD_SetColor (pObj->Props.aTextColor[ColorIndex]);
s = LISTBOX__GetpString(pObj, ItemIndex);
GUI_SetTextMode(GUI_TM_TRANS);
GUI_Clear();
rText.y0 = pDrawItemInfo->y0;
rText.x0 = pDrawItemInfo->x0 + 1;
rText.y1 = rText.y0 + pItem->ySize - 1;
if (pObj->Props.Align & (GUI_TA_RIGHT | GUI_TA_CENTER)) {
GUI_RECT Rect;
WM_GetInsideRectExScrollbar(pDrawItemInfo->hWin, &Rect);
rText.x1 = rText.x0 + Rect.x1 - Rect.x0 - pObj->Widget.pEffect->EffectSize;
} else {
rText.x1 = rText.x0 + pItem->xSize - 1;
}
GUI_DispStringInRect(s, &rText, pObj->Props.Align);
/* Display focus rectangle */
if ((pObj->Flags & LISTBOX_SF_MULTISEL) && (ItemIndex == pObj->Sel)) {
GUI_RECT rFocus;
rFocus.x0 = pDrawItemInfo->x0;
rFocus.x1 = r.x1;
switch (pObj->Props.Align & GUI_TA_VERTICAL) {
case GUI_TA_TOP:
rFocus.y0 = pDrawItemInfo->y0;
rFocus.y1 = pDrawItemInfo->y0 + FontDistY - 1;
break;
case GUI_TA_VCENTER:
rFocus.y0 = pDrawItemInfo->y0 + (GUI_Context.WM__pUserClipRect->y1 - GUI_Context.WM__pUserClipRect->y0 - FontDistY) / 2;
rFocus.y1 = rFocus.y0 + FontDistY - 1;
break;
case GUI_TA_BOTTOM:
rFocus.y1 = pDrawItemInfo->y0 + (GUI_Context.WM__pUserClipRect->y1 - GUI_Context.WM__pUserClipRect->y0);
rFocus.y0 = rFocus.y1 - FontDistY + 1;
break;
}
LCD_SetColor(GUI_WHITE - pObj->Props.aBackColor[ColorIndex]);
GUI_DrawFocusRect(&rFocus, 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -