system/lib/lcd/gui/Widget/HEADER.c

715 lines
20 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 : HEADER.c
Purpose : Implementation of header widget
---------------------------END-OF-HEADER------------------------------
*/
#include <stdlib.h>
#include <string.h>
#include "HEADER_Private.h"
#include "SCROLLBAR.h"
#include "GUI.h"
#if GUI_WINSUPPORT
/*********************************************************************
*
* Private config defaults
*
**********************************************************************
*/
#ifndef HEADER_SUPPORT_DRAG
#define HEADER_SUPPORT_DRAG 1
#endif
#ifndef HEADER_BORDER_V_DEFAULT
#define HEADER_BORDER_V_DEFAULT 0
#endif
#ifndef HEADER_BORDER_H_DEFAULT
#define HEADER_BORDER_H_DEFAULT 2
#endif
/* Define default fonts */
#ifndef HEADER_FONT_DEFAULT
#define HEADER_FONT_DEFAULT &GUI_Font13_1
#endif
/* Define colors */
#ifndef HEADER_BKCOLOR_DEFAULT
#define HEADER_BKCOLOR_DEFAULT 0xAAAAAA
#endif
#ifndef HEADER_TEXTCOLOR_DEFAULT
#define HEADER_TEXTCOLOR_DEFAULT GUI_BLACK
#endif
/* Define cursors */
#ifndef HEADER_CURSOR_DEFAULT
#define HEADER_CURSOR_DEFAULT &GUI_CursorHeaderM
#endif
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
/* Remember the old cursor */
static const GUI_CURSOR GUI_UNI_PTR * _pOldCursor;
/* Default values */
static const GUI_CURSOR GUI_UNI_PTR * _pDefaultCursor = HEADER_CURSOR_DEFAULT;
static GUI_COLOR _DefaultBkColor = HEADER_BKCOLOR_DEFAULT;
static GUI_COLOR _DefaultTextColor = HEADER_TEXTCOLOR_DEFAULT;
static int _DefaultBorderH = HEADER_BORDER_H_DEFAULT;
static int _DefaultBorderV = HEADER_BORDER_V_DEFAULT;
static const GUI_FONT GUI_UNI_PTR * _pDefaultFont = HEADER_FONT_DEFAULT;
/*********************************************************************
*
* static routines
*
**********************************************************************
*/
/*********************************************************************
*
* _Paint
*/
static void _Paint(/*HEADER_Handle hObj, */HEADER_Obj* pObj) {
GUI_RECT Rect;
int i, xPos = -pObj->ScrollPos;
int NumItems = GUI_ARRAY_GetNumItems(&pObj->Columns);
int EffectSize = pObj->Widget.pEffect->EffectSize;
LCD_SetBkColor(pObj->BkColor);
GUI_SetFont(pObj->pFont);
GUI_Clear();
for (i = 0; i < NumItems; i++) {
HEADER_COLUMN * pColumn = (HEADER_COLUMN*)GUI_ARRAY_GetpItem(&pObj->Columns, i);
GUI_GetClientRect(&Rect);
Rect.x0 = xPos;
Rect.x1 = Rect.x0 + pColumn->Width;
if (pColumn->hDrawObj) {
int xOff = 0, yOff = 0;
switch (pColumn->Align & GUI_TA_HORIZONTAL) {
case GUI_TA_RIGHT:
xOff = (pColumn->Width - GUI_DRAW__GetXSize(pColumn->hDrawObj));
break;
case GUI_TA_HCENTER:
xOff = (pColumn->Width - GUI_DRAW__GetXSize(pColumn->hDrawObj)) / 2;
break;
}
switch (pColumn->Align & GUI_TA_VERTICAL) {
case GUI_TA_BOTTOM:
yOff = ((Rect.y1 - Rect.y0 + 1) - GUI_DRAW__GetYSize(pColumn->hDrawObj));
break;
case GUI_TA_VCENTER:
yOff = ((Rect.y1 - Rect.y0 + 1) - GUI_DRAW__GetYSize(pColumn->hDrawObj)) / 2;
break;
}
WM_SetUserClipRect(&Rect);
GUI_DRAW__Draw(pColumn->hDrawObj, xPos + xOff, yOff);
WM_SetUserClipRect(NULL);
}
WIDGET__EFFECT_DrawUpRect(&pObj->Widget, &Rect);
xPos += Rect.x1 - Rect.x0;
Rect.x0 += EffectSize + _DefaultBorderH;
Rect.x1 -= EffectSize + _DefaultBorderH;
Rect.y0 += EffectSize + _DefaultBorderV;
Rect.y1 -= EffectSize + _DefaultBorderV;
LCD_SetColor(pObj->TextColor);
GUI_DispStringInRect(pColumn->acText, &Rect, pColumn->Align);
}
GUI_GetClientRect(&Rect);
Rect.x0 = xPos;
Rect.x1 = 0xfff;
WIDGET__EFFECT_DrawUpRect(&pObj->Widget, &Rect);
}
/*********************************************************************
*
* _RestoreOldCursor
*/
static void _RestoreOldCursor(void) {
if (_pOldCursor) {
#if GUI_SUPPORT_CURSOR
GUI_CURSOR_Select(_pOldCursor);
#endif
_pOldCursor = 0;
}
}
/*********************************************************************
*
* _FreeAttached
*
* Delete attached objects (if any)
*/
static void _FreeAttached(HEADER_Obj * pObj) {
int i, NumItems;
NumItems = GUI_ARRAY_GetNumItems(&pObj->Columns);
for (i = 0; i < NumItems; i++) {
HEADER_COLUMN * pColumn = (HEADER_COLUMN*)GUI_ARRAY_GetpItem(&pObj->Columns, i);
if (pColumn->hDrawObj) {
GUI_ALLOC_Free(pColumn->hDrawObj);
}
}
/* Delete attached objects (if any) */
GUI_ARRAY_Delete(&pObj->Columns);
_RestoreOldCursor();
}
/*********************************************************************
*
* _GetItemIndex
*/
#if (HEADER_SUPPORT_DRAG)
static int _GetItemIndex(HEADER_Handle hObj, HEADER_Obj * pObj, int x, int y) {
int Item = -1;
if ((y >= 0) && (y < WM_GetWindowSizeY(hObj))) {
if (hObj) {
int Index, xPos = 0, NumColumns;
NumColumns = GUI_ARRAY_GetNumItems(&pObj->Columns);
for (Index = 0; Index < NumColumns; Index++) {
HEADER_COLUMN * pColumn;
pColumn = (HEADER_COLUMN *)GUI_ARRAY_GetpItem(&pObj->Columns, Index);
xPos += pColumn->Width;
if ((xPos >= (x - 4)) && (xPos <= (x + 4))) {
Item = Index;
if ((Index < (NumColumns - 1)) && (x < xPos)) {
pColumn = (HEADER_COLUMN *)GUI_ARRAY_GetpItem(&pObj->Columns, Index + 1);
if (pColumn->Width == 0) {
break;
}
}
}
}
}
}
return Item;
}
#endif
/*********************************************************************
*
* _HandlePID
*/
#if (HEADER_SUPPORT_DRAG)
static void _HandlePID(HEADER_Handle hObj, HEADER_Obj * pObj, int x, int y, int Pressed) {
int Hit = _GetItemIndex(hObj, pObj, x, y);
/* set capture position () */
if ((Pressed == 1) && (Hit >= 0) && (pObj->CapturePosX == -1)) {
pObj->CapturePosX = x;
pObj->CaptureItem = Hit;
}
/* set mouse cursor and capture () */
if (Hit >= 0) {
WM_SetCapture(hObj, 1);
#if GUI_SUPPORT_CURSOR
if (!_pOldCursor) {
_pOldCursor = GUI_CURSOR_Select(_pDefaultCursor);
}
#endif
}
/* modify header */
if ((pObj->CapturePosX >= 0) && (x != pObj->CapturePosX) && (Pressed == 1)) {
int NewSize = HEADER_GetItemWidth(hObj, pObj->CaptureItem) + x - pObj->CapturePosX;
if (NewSize >= 0) {
HEADER_SetItemWidth(hObj, pObj->CaptureItem, NewSize);
pObj->CapturePosX = x;
}
}
/* release capture & restore cursor */
if (Pressed <= 0) {
#if (GUI_SUPPORT_MOUSE)
if (Hit == -1)
#endif
{
_RestoreOldCursor();
pObj->CapturePosX = -1;
WM_ReleaseCapture();
}
}
}
#endif
/*********************************************************************
*
* _OnMouseOver
*/
#if (HEADER_SUPPORT_DRAG & GUI_SUPPORT_MOUSE)
static void _OnMouseOver(HEADER_Handle hObj, HEADER_Obj * pObj, WM_MESSAGE * pMsg) {
const GUI_PID_STATE * pState = (const GUI_PID_STATE *)pMsg->Data.p;
if (pState) {
_HandlePID(hObj, pObj, pState->x + pObj->ScrollPos, pState->y, -1);
}
}
#endif
/*********************************************************************
*
* _OnTouch
*/
#if (HEADER_SUPPORT_DRAG)
static void _OnTouch(HEADER_Handle hObj, HEADER_Obj * pObj, WM_MESSAGE * pMsg) {
int Notification;
const GUI_PID_STATE * pState = (const GUI_PID_STATE *)pMsg->Data.p;
if (pState) {
_HandlePID(hObj, pObj, pState->x + pObj->ScrollPos, pState->y, pState->Pressed);
}
if (pMsg->Data.p) { /* Something happened in our area (pressed or released) */
if (pState->Pressed) {
Notification = WM_NOTIFICATION_CLICKED;
} else {
Notification = WM_NOTIFICATION_RELEASED;
}
} else {
Notification = WM_NOTIFICATION_MOVED_OUT;
}
WM_NotifyParent(hObj, Notification);
}
#endif
/*********************************************************************
*
* _HEADER_Callback
*/
static void _HEADER_Callback (WM_MESSAGE *pMsg) {
HEADER_Handle hObj;
HEADER_Obj * pObj;
hObj = pMsg->hWin;
/* Let widget handle the standard messages */
if (WIDGET_HandleActive(hObj, pMsg) == 0) {
return;
}
WM_LOCK();
pObj = HEADER_H2P(hObj);
switch (pMsg->MsgId) {
case WM_PAINT:
_Paint(/*hObj, */pObj);
break;
#if (HEADER_SUPPORT_DRAG)
case WM_TOUCH:
_OnTouch(hObj, pObj, pMsg);
break;
#endif
#if (HEADER_SUPPORT_DRAG & GUI_SUPPORT_MOUSE)
case WM_MOUSEOVER:
_OnMouseOver(hObj, pObj, pMsg);
break;
#endif
case WM_DELETE:
_FreeAttached(pObj); /* No return here ... WM_DefaultProc needs to be called */
default:
WM_DefaultProc(pMsg);
}
WM_UNLOCK();
}
/*********************************************************************
*
* Exported routines: Create
*
**********************************************************************
*/
/*********************************************************************
*
* HEADER_Create
*/
HEADER_Handle HEADER_Create(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int Id, int Flags, int ExFlags) {
return HEADER_CreateEx(x0, y0, xsize, ysize, hParent, Flags, ExFlags, Id);
}
/*********************************************************************
*
* HEADER_CreateEx
*/
HEADER_Handle HEADER_CreateEx(int x0, int y0, int xsize, int ysize, WM_HWIN hParent,
int WinFlags, int ExFlags, int Id)
{
HEADER_Handle hObj;
GUI_USE_PARA(ExFlags);
/* Create the window */
WM_LOCK();
if ((xsize == 0) && (x0 == 0) && (y0 == 0)) {
GUI_RECT Rect;
WM_GetInsideRectEx(hParent, &Rect);
xsize = Rect.x1 - Rect.x0 + 1;
x0 = Rect.x0;
y0 = Rect.y0;
}
if (ysize == 0) {
const WIDGET_EFFECT* pEffect = WIDGET_GetDefaultEffect();
ysize = GUI_GetYDistOfFont(_pDefaultFont);
ysize += 2 * _DefaultBorderV;
ysize += 2 * (unsigned)pEffect->EffectSize;
}
WinFlags |= WM_CF_ANCHOR_LEFT | WM_CF_ANCHOR_RIGHT;
hObj = WM_CreateWindowAsChild(x0, y0, xsize, ysize, hParent, WinFlags, &_HEADER_Callback,
sizeof(HEADER_Obj) - sizeof(WM_Obj));
if (hObj) {
HEADER_Obj* pObj = HEADER_H2P(hObj);
/* Init sub-classes */
GUI_ARRAY_CREATE(&pObj->Columns);
/* init widget specific variables */
WIDGET__Init(&pObj->Widget, Id, 0);
/* init member variables */
HEADER_INIT_ID(pObj);
pObj->BkColor = _DefaultBkColor;
pObj->TextColor = _DefaultTextColor;
pObj->pFont = _pDefaultFont;
pObj->CapturePosX = -1;
pObj->CaptureItem = -1;
pObj->ScrollPos = 0;
} else {
GUI_DEBUG_ERROROUT_IF(hObj==0, "HEADER_Create failed")
}
WM_UNLOCK();
return hObj;
}
/*********************************************************************
*
* Exported routines: Global functions
*
**********************************************************************
*/
/*********************************************************************
*
* HEADER_SetDefautCursor
*/
const GUI_CURSOR GUI_UNI_PTR * HEADER_SetDefaultCursor(const GUI_CURSOR * pCursor) {
const GUI_CURSOR GUI_UNI_PTR * pOldCursor = _pDefaultCursor;
_pDefaultCursor = pCursor;
return pOldCursor;
}
/*********************************************************************
*
* HEADER_SetDefaultBkColor
*/
GUI_COLOR HEADER_SetDefaultBkColor(GUI_COLOR Color) {
GUI_COLOR OldColor = _DefaultBkColor;
_DefaultBkColor = Color;
return OldColor;
}
/*********************************************************************
*
* HEADER_SetDefaultTextColor
*/
GUI_COLOR HEADER_SetDefaultTextColor(GUI_COLOR Color) {
GUI_COLOR OldColor = _DefaultTextColor;
_DefaultTextColor = Color;
return OldColor;
}
/*********************************************************************
*
* HEADER_SetDefaultBorderH
*/
int HEADER_SetDefaultBorderH(int Spacing) {
int OldSpacing = _DefaultBorderH;
_DefaultBorderH = Spacing;
return OldSpacing;
}
/*********************************************************************
*
* HEADER_SetDefaultBorderV
*/
int HEADER_SetDefaultBorderV(int Spacing) {
int OldSpacing = _DefaultBorderV;
_DefaultBorderV = Spacing;
return OldSpacing;
}
/*********************************************************************
*
* HEADER_SetDefaultFont
*/
const GUI_FONT GUI_UNI_PTR * HEADER_SetDefaultFont(const GUI_FONT GUI_UNI_PTR * pFont) {
const GUI_FONT GUI_UNI_PTR * pOldFont = _pDefaultFont;
_pDefaultFont = pFont;
return pOldFont;
}
/*********************************************************************
*
* HEADER_GetDefault...
*/
const GUI_CURSOR GUI_UNI_PTR * HEADER_GetDefaultCursor(void) { return _pDefaultCursor; }
GUI_COLOR HEADER_GetDefaultBkColor(void) { return _DefaultBkColor; }
GUI_COLOR HEADER_GetDefaultTextColor(void) { return _DefaultTextColor; }
int HEADER_GetDefaultBorderH(void) { return _DefaultBorderH; }
int HEADER_GetDefaultBorderV(void) { return _DefaultBorderV; }
const GUI_FONT GUI_UNI_PTR * HEADER_GetDefaultFont(void) { return _pDefaultFont; }
/*********************************************************************
*
* Exported routines: Member functions
*
**********************************************************************
*/
/*********************************************************************
*
* HEADER_SetFont
*/
void HEADER_SetFont(HEADER_Handle hObj, const GUI_FONT GUI_UNI_PTR * pFont) {
if (hObj) {
HEADER_Obj * pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
pObj->pFont = pFont;
WM_InvalidateWindow(hObj);
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_SetHeight
*/
void HEADER_SetHeight(HEADER_Handle hObj, int Height) {
if (hObj) {
GUI_RECT Rect;
WM_GetClientRectEx(hObj, &Rect);
WM_SetSize(hObj, Rect.x1 - Rect.x0 + 1, Height);
WM_InvalidateWindow(WM_GetParent(hObj));
}
}
/*********************************************************************
*
* HEADER_SetTextColor
*/
void HEADER_SetTextColor(HEADER_Handle hObj, GUI_COLOR Color) {
if (hObj) {
HEADER_Obj * pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
pObj->TextColor = Color;
WM_InvalidateWindow(hObj);
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_SetBkColor
*/
void HEADER_SetBkColor(HEADER_Handle hObj, GUI_COLOR Color) {
if (hObj) {
HEADER_Obj * pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
pObj->BkColor = Color;
WM_InvalidateWindow(hObj);
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_SetTextAlign
*/
void HEADER_SetTextAlign(HEADER_Handle hObj, unsigned int Index, int Align) {
if (hObj) {
HEADER_Obj * pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
if (Index <= GUI_ARRAY_GetNumItems(&pObj->Columns)) {
HEADER_COLUMN * pColumn;
pColumn = (HEADER_COLUMN *)GUI_ARRAY_GetpItem(&pObj->Columns, Index);
pColumn->Align = Align;
WM_InvalidateWindow(hObj);
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_SetScrollPos
*/
void HEADER_SetScrollPos(HEADER_Handle hObj, int ScrollPos) {
if (hObj && (ScrollPos >= 0)) {
HEADER_Obj* pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
if (ScrollPos != pObj->ScrollPos) {
pObj->ScrollPos = ScrollPos;
WM_Invalidate(hObj);
WM_InvalidateWindow(WM_GetParent(hObj));
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_AddItem
*/
void HEADER_AddItem(HEADER_Handle hObj, int Width, const char * s, int Align) {
if (hObj) {
HEADER_Obj * pObj;
HEADER_COLUMN Column;
int Index;
WM_LOCK();
pObj = HEADER_H2P(hObj);
if (!Width) {
const GUI_FONT GUI_UNI_PTR * pFont = GUI_SetFont(pObj->pFont);
Width = GUI_GetStringDistX(s) + 2 * (pObj->Widget.pEffect->EffectSize + _DefaultBorderH);
GUI_SetFont(pFont);
}
Column.Width = Width;
Column.Align = Align;
Column.hDrawObj = 0;
Index = GUI_ARRAY_GetNumItems(&pObj->Columns);
if (GUI_ARRAY_AddItem(&pObj->Columns, &Column, sizeof(HEADER_COLUMN) + strlen(s) + 1) == 0) {
HEADER_COLUMN * pColumn;
pObj = HEADER_H2P(hObj);
pColumn = (HEADER_COLUMN *)GUI_ARRAY_GetpItem(&pObj->Columns, Index);
strcpy(pColumn->acText, s);
WM_InvalidateWindow(hObj);
WM_InvalidateWindow(WM_GetParent(hObj));
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_DeleteItem
*/
void HEADER_DeleteItem(HEADER_Handle hObj, unsigned Index) {
if (hObj) {
HEADER_Obj* pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
if (Index < GUI_ARRAY_GetNumItems(&pObj->Columns)) {
GUI_ARRAY_DeleteItem(&pObj->Columns, Index);
WM_InvalidateWindow(hObj);
WM_InvalidateWindow(WM_GetParent(hObj));
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_SetItemText
*/
void HEADER_SetItemText(HEADER_Handle hObj, unsigned int Index, const char* s) {
if (hObj) {
HEADER_Obj* pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
if (Index < GUI_ARRAY_GetNumItems(&pObj->Columns)) {
HEADER_COLUMN* pColumn;
pColumn = (HEADER_COLUMN*)GUI_ARRAY_ResizeItem(&pObj->Columns, Index, sizeof(HEADER_COLUMN) + strlen(s));
if (pColumn) {
strcpy(pColumn->acText, s);
}
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_SetItemWidth
*/
void HEADER_SetItemWidth(HEADER_Handle hObj, unsigned int Index, int Width) {
if (hObj && (Width >= 0)) {
HEADER_Obj * pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
if (Index <= GUI_ARRAY_GetNumItems(&pObj->Columns)) {
HEADER_COLUMN * pColumn;
pColumn = (HEADER_COLUMN *)GUI_ARRAY_GetpItem(&pObj->Columns, Index);
if (pColumn) {
pColumn->Width = Width;
WM_InvalidateWindow(hObj);
WM__SendMsgNoData(WM_GetParent(hObj), WM_NOTIFY_CLIENTCHANGE);
WM_InvalidateWindow(WM_GetParent(hObj));
}
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* HEADER_GetHeight
*/
int HEADER_GetHeight(HEADER_Handle hObj) {
int Height = 0;
if (hObj) {
GUI_RECT Rect;
WM_GetClientRectEx(hObj, &Rect);
GUI_MoveRect(&Rect, -Rect.x0, -Rect.y0);
Height = Rect.y1 - Rect.y0 + 1;
}
return Height;
}
/*********************************************************************
*
* HEADER_GetItemWidth
*/
int HEADER_GetItemWidth(HEADER_Handle hObj, unsigned int Index) {
int Width = 0;
if (hObj) {
HEADER_Obj * pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
if (Index <= GUI_ARRAY_GetNumItems(&pObj->Columns)) {
HEADER_COLUMN * pColumn;
pColumn = (HEADER_COLUMN *)GUI_ARRAY_GetpItem(&pObj->Columns, Index);
Width = pColumn->Width;
}
WM_UNLOCK();
}
return Width;
}
/*********************************************************************
*
* HEADER_GetNumItems
*/
int HEADER_GetNumItems(HEADER_Handle hObj) {
int NumCols = 0;
if (hObj) {
HEADER_Obj * pObj;
WM_LOCK();
pObj = HEADER_H2P(hObj);
NumCols = GUI_ARRAY_GetNumItems(&pObj->Columns);
WM_UNLOCK();
}
return NumCols;
}
#else /* avoid empty object files */
void HEADER_C(void);
void HEADER_C(void){}
#endif /* #if GUI_WINSUPPORT */