freertos_f407/User/system/lib/lcd/gui/Widget/BUTTON.c

456 lines
13 KiB
C

/*
*********************************************************************************************************
* uC/GUI
* Universal graphic software for embedded applications
*
* (c) Copyright 2002, Micrium Inc., Weston, FL
* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
* µC/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 : BUTTON.c
Purpose : Implementation of button widget
---------------------------END-OF-HEADER------------------------------
*/
#include <stdlib.h>
#include <string.h>
#include "BUTTON_Private.h"
#if GUI_WINSUPPORT
/*********************************************************************
*
* Private config defaults
*
**********************************************************************
*/
/* Define default fonts */
#ifndef BUTTON_FONT_DEFAULT
#define BUTTON_FONT_DEFAULT &GUI_Font13_1
#endif
/* Support for 3D effects */
#ifndef BUTTON_USE_3D
#define BUTTON_USE_3D 1
#endif
#ifndef BUTTON_3D_MOVE_X
#define BUTTON_3D_MOVE_X 1
#endif
#ifndef BUTTON_3D_MOVE_Y
#define BUTTON_3D_MOVE_Y 1
#endif
/* Define colors */
#ifndef BUTTON_BKCOLOR0_DEFAULT
#define BUTTON_BKCOLOR0_DEFAULT 0xAAAAAA
#endif
#ifndef BUTTON_BKCOLOR1_DEFAULT
#define BUTTON_BKCOLOR1_DEFAULT GUI_WHITE
#endif
#ifndef BUTTON_BKCOLOR2_DEFAULT
#define BUTTON_BKCOLOR2_DEFAULT GUI_LIGHTGRAY
#endif
#ifndef BUTTON_TEXTCOLOR0_DEFAULT
#define BUTTON_TEXTCOLOR0_DEFAULT GUI_BLACK
#endif
#ifndef BUTTON_TEXTCOLOR1_DEFAULT
#define BUTTON_TEXTCOLOR1_DEFAULT GUI_BLACK
#endif
#ifndef BUTTON_TEXTCOLOR2_DEFAULT
#define BUTTON_TEXTCOLOR2_DEFAULT GUI_DARKGRAY
#endif
#ifndef BUTTON_REACT_ON_LEVEL
#define BUTTON_REACT_ON_LEVEL 0
#endif
#ifndef BUTTON_ALIGN_DEFAULT
#define BUTTON_ALIGN_DEFAULT GUI_TA_HCENTER | GUI_TA_VCENTER
#endif
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
BUTTON_PROPS BUTTON__DefaultProps = {
BUTTON_BKCOLOR0_DEFAULT,
BUTTON_BKCOLOR1_DEFAULT,
BUTTON_BKCOLOR2_DEFAULT,
BUTTON_TEXTCOLOR0_DEFAULT,
BUTTON_TEXTCOLOR1_DEFAULT,
BUTTON_TEXTCOLOR2_DEFAULT,
BUTTON_FONT_DEFAULT,
BUTTON_ALIGN_DEFAULT
};
/*********************************************************************
*
* Static routines
*
**********************************************************************
*/
/*********************************************************************
*
* _Paint
*/
static void _Paint(BUTTON_Obj* pObj, BUTTON_Handle hObj) {
const char* s = NULL;
unsigned int Index;
int State, PressedState, ColorIndex;
GUI_RECT rClient, rInside;
State = pObj->Widget.State;
PressedState = (State & BUTTON_STATE_PRESSED) ? 1 : 0;
ColorIndex = (WM__IsEnabled(hObj)) ? PressedState : 2;
GUI_SetFont(pObj->Props.pFont);
GUI_DEBUG_LOG("BUTTON: Paint(..)\n");
if (pObj->hpText) {
s = (const char*) GUI_ALLOC_h2p(pObj->hpText);
}
GUI_GetClientRect(&rClient);
/* Start drawing */
rInside = rClient;
/* Draw the 3D effect (if configured) */
#if BUTTON_USE_3D
{
int EffectSize;
if ((PressedState) == 0) {
pObj->Widget.pEffect->pfDrawUp(); /* _WIDGET_EFFECT_3D_DrawUp(); */
EffectSize = pObj->Widget.pEffect->EffectSize;
} else {
LCD_SetColor(0x000000);
GUI_DrawRect(rClient.y0, rClient.x0, rClient.x1, rClient.y1);
EffectSize = 1;
}
GUI__ReduceRect(&rInside, &rInside, EffectSize);
}
#endif
/* Draw background */
LCD_SetBkColor (pObj->Props.aBkColor[ColorIndex]);
LCD_SetColor (pObj->Props.aTextColor[ColorIndex]);
WM_SetUserClipRect(&rInside);
GUI_Clear();
/* Draw bitmap.
If we have only one, we will use it.
If we have to we will use the second one (Index 1) for the pressed state
*/
if (ColorIndex < 2) {
Index = (pObj->ahDrawObj[BUTTON_BI_PRESSED] && PressedState) ? BUTTON_BI_PRESSED : BUTTON_BI_UNPRESSED;
} else {
Index = pObj->ahDrawObj[BUTTON_BI_DISABLED] ? BUTTON_BI_DISABLED : BUTTON_BI_UNPRESSED;
}
GUI_DRAW__Draw(pObj->ahDrawObj[Index], 0, 0);
/* Draw the actual button (background and text) */
{
GUI_RECT r;
r = rInside;
#if BUTTON_USE_3D
if (PressedState) {
GUI_MoveRect(&r, BUTTON_3D_MOVE_X,BUTTON_3D_MOVE_Y);
}
#endif
GUI_SetTextMode(GUI_TM_TRANS);
GUI_DispStringInRect(s, &r, pObj->Props.Align);
}
/* Draw focus */
if (State & BUTTON_STATE_FOCUS) {
LCD_SetColor(GUI_BLACK);
GUI_DrawFocusRect(&rClient, 2);
}
WM_SetUserClipRect(NULL);
}
/*********************************************************************
*
* _Delete
*
* Delete attached objects (if any)
*/
static void _Delete(BUTTON_Obj* pObj) {
GUI_ALLOC_FreePtr(&pObj->hpText);
GUI_ALLOC_FreePtr(&pObj->ahDrawObj[0]);
GUI_ALLOC_FreePtr(&pObj->ahDrawObj[1]);
}
/*********************************************************************
*
* _ButtonPressed
*/
static void _ButtonPressed(BUTTON_Handle hObj, BUTTON_Obj* pObj) {
WIDGET_OrState(hObj, BUTTON_STATE_PRESSED);
if (pObj->Widget.Win.Status & WM_SF_ISVIS) {
WM_NotifyParent(hObj, WM_NOTIFICATION_CLICKED);
}
}
/*********************************************************************
*
* _ButtonReleased
*/
static void _ButtonReleased(BUTTON_Handle hObj, BUTTON_Obj* pObj, int Notification) {
WIDGET_AndState(hObj, BUTTON_STATE_PRESSED);
if (pObj->Widget.Win.Status & WM_SF_ISVIS) {
WM_NotifyParent(hObj, Notification);
}
if (Notification == WM_NOTIFICATION_RELEASED) {
GUI_DEBUG_LOG("BUTTON: Hit\n");
GUI_StoreKey(pObj->Widget.Id);
}
}
/*********************************************************************
*
* _OnTouch
*/
static void _OnTouch(BUTTON_Handle hObj, BUTTON_Obj* pObj, WM_MESSAGE*pMsg) {
const GUI_PID_STATE* pState = (const GUI_PID_STATE*)pMsg->Data.p;
#if BUTTON_REACT_ON_LEVEL
if (!pMsg->Data.p) { /* Mouse moved out */
_ButtonReleased(hObj, pObj, WM_NOTIFICATION_MOVED_OUT);
}
#else
if (pMsg->Data.p) { /* Something happened in our area (pressed or released) */
if (pState->Pressed) {
if ((pObj->Widget.State & BUTTON_STATE_PRESSED) == 0){
_ButtonPressed(hObj, pObj);
}
} else {
/* React only if button was pressed before ... avoid problems with moving / hiding windows above (such as dropdown) */
if (pObj->Widget.State & BUTTON_STATE_PRESSED) {
_ButtonReleased(hObj, pObj, WM_NOTIFICATION_RELEASED);
}
}
} else {
_ButtonReleased(hObj, pObj, WM_NOTIFICATION_MOVED_OUT);
}
#endif
}
/*********************************************************************
*
* _OnPidStateChange
*/
#if BUTTON_REACT_ON_LEVEL
static void _OnPidStateChange(BUTTON_Handle hObj, BUTTON_Obj * pObj, WM_MESSAGE * pMsg) {
const WM_PID_STATE_CHANGED_INFO * pState = (const WM_PID_STATE_CHANGED_INFO *)pMsg->Data.p;
if ((pState->StatePrev == 0) && (pState->State == 1)) {
if ((pObj->Widget.State & BUTTON_STATE_PRESSED) == 0){
_ButtonPressed(hObj, pObj);
}
} else if ((pState->StatePrev == 1) && (pState->State == 0)) {
if (pObj->Widget.State & BUTTON_STATE_PRESSED) {
_ButtonReleased(hObj, pObj, WM_NOTIFICATION_RELEASED);
}
}
}
#endif
/*********************************************************************
*
* BUTTON_Callback
*/
void BUTTON_Callback(WM_MESSAGE *pMsg) {
BUTTON_Handle hObj = pMsg->hWin;
BUTTON_Obj* pObj = BUTTON_H2P(hObj);
/* Let widget handle the standard messages */
if (WIDGET_HandleActive(hObj, pMsg) == 0) {
return;
}
switch (pMsg->MsgId) {
#if BUTTON_REACT_ON_LEVEL
case WM_PID_STATE_CHANGED:
_OnPidStateChange(hObj, pObj, pMsg);
return; /* Message handled. Do not call WM_DefaultProc, because the window may have been destroyed */
#endif
case WM_TOUCH:
_OnTouch(hObj, pObj, pMsg);
return; /* Message handled. Do not call WM_DefaultProc, because the window may have been destroyed */
case WM_PAINT:
GUI_DEBUG_LOG("BUTTON: _BUTTON_Callback(WM_PAINT)\n");
_Paint(pObj, hObj);
return;
case WM_DELETE:
GUI_DEBUG_LOG("BUTTON: _BUTTON_Callback(WM_DELETE)\n");
_Delete(pObj);
break; /* No return here ... WM_DefaultProc needs to be called */
#if 0 /* TBD: Button should react to space & Enter */
case WM_KEY:
{
int PressedCnt = ((WM_KEY_INFO*)(pMsg->Data.p))->PressedCnt;
int Key = ((WM_KEY_INFO*)(pMsg->Data.p))->Key;
if (PressedCnt > 0) { /* Key pressed? */
switch (Key) {
case ' ':
_ButtonPressed(hObj, pObj);
return;
}
} else {
switch (Key) {
case ' ':
_ButtonReleased(hObj, pObj, WM_NOTIFICATION_RELEASED);
return;
}
}
}
break;
#endif
}
WM_DefaultProc(pMsg);
}
/*********************************************************************
*
* Exported routines: Create
*
**********************************************************************
*/
/*********************************************************************
*
* BUTTON_CreateEx
*/
BUTTON_Handle BUTTON_CreateEx(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id) {
BUTTON_Handle hObj;
GUI_USE_PARA(ExFlags);
/* Create the window */
WM_LOCK();
hObj = WM_CreateWindowAsChild(x0, y0, xsize, ysize, hParent, WinFlags, BUTTON_Callback,
sizeof(BUTTON_Obj) - sizeof(WM_Obj));
if (hObj) {
BUTTON_Obj* pObj = BUTTON_H2P(hObj);
/* init widget specific variables */
WIDGET__Init(&pObj->Widget, Id, WIDGET_STATE_FOCUSSABLE);
/* init member variables */
BUTTON_INIT_ID(pObj);
pObj->Props = BUTTON__DefaultProps;
} else {
GUI_DEBUG_ERROROUT_IF(hObj==0, "BUTTON_Create failed")
}
WM_UNLOCK();
return hObj;
}
/*********************************************************************
*
* Exported routines: Various methods
*
**********************************************************************
*/
/*********************************************************************
*
* BUTTON_SetText
*/
void BUTTON_SetText(BUTTON_Handle hObj, const char* s) {
if (hObj) {
BUTTON_Obj* pObj;
WM_LOCK();
pObj = BUTTON_H2P(hObj);
if (GUI__SetText(&pObj->hpText, s)) {
BUTTON_Invalidate(hObj);
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* BUTTON_SetFont
*/
void BUTTON_SetFont(BUTTON_Handle hObj, const GUI_FONT GUI_UNI_PTR * pfont) {
if (hObj) {
BUTTON_Obj* pObj;
WM_LOCK();
pObj = BUTTON_H2P(hObj);
BUTTON_ASSERT_IS_VALID_PTR(pObj);
pObj->Props.pFont = pfont;
BUTTON_Invalidate(hObj);
WM_UNLOCK();
}
}
/*********************************************************************
*
* BUTTON_SetBkColor
*/
void BUTTON_SetBkColor(BUTTON_Handle hObj,unsigned int Index, GUI_COLOR Color) {
if (hObj && (Index <= 2)) {
BUTTON_Obj* pObj;
WM_LOCK();
pObj = BUTTON_H2P(hObj);
BUTTON_ASSERT_IS_VALID_PTR(pObj);
pObj->Props.aBkColor[Index] = Color;
BUTTON_Invalidate(hObj);
WM_UNLOCK();
}
}
/*********************************************************************
*
* BUTTON_SetTextColor
*/
void BUTTON_SetTextColor(BUTTON_Handle hObj,unsigned int Index, GUI_COLOR Color) {
if (hObj && (Index <= 2)) {
BUTTON_Obj* pObj;
WM_LOCK();
pObj = BUTTON_H2P(hObj);
BUTTON_ASSERT_IS_VALID_PTR(pObj);
pObj->Props.aTextColor[Index] = Color;
BUTTON_Invalidate(hObj);
WM_UNLOCK();
}
}
/*********************************************************************
*
* BUTTON_SetState
*/
void BUTTON_SetState(BUTTON_Handle hObj, int State) {
WIDGET_SetState(hObj, State);
}
/*********************************************************************
*
* BUTTON_SetPressed
*/
void BUTTON_SetPressed(BUTTON_Handle hObj, int State) {
if (State) {
WIDGET_OrState(hObj, BUTTON_STATE_PRESSED);
} else {
WIDGET_AndState(hObj, BUTTON_STATE_PRESSED);
}
}
/*********************************************************************
*
* BUTTON_SetFocussable
*/
void BUTTON_SetFocussable(BUTTON_Handle hObj, int State) {
if (State) {
WIDGET_OrState(hObj, WIDGET_STATE_FOCUSSABLE);
} else {
WIDGET_AndState(hObj, WIDGET_STATE_FOCUSSABLE);
}
}
#else /* Avoid problems with empty object modules */
void BUTTON_C(void) {}
#endif /* GUI_WINSUPPORT */