📄 graph.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 : GRAPH.c
Purpose : Implementation of GRAPH widget
---------------------------END-OF-HEADER------------------------------
*/
#include <string.h>
#include "GRAPH_Private.h"
#if GUI_WINSUPPORT
/*********************************************************************
*
* Private config defaults
*
**********************************************************************
*/
#ifndef GRAPH_BKCOLOR_DEFAULT
#define GRAPH_BKCOLOR_DEFAULT GUI_BLACK
#endif
#ifndef GRAPH_BORDERCOLOR_DEFAULT
#define GRAPH_BORDERCOLOR_DEFAULT 0xc0c0c0
#endif
#ifndef GRAPH_FRAMECOLOR_DEFAULT
#define GRAPH_FRAMECOLOR_DEFAULT GUI_WHITE
#endif
#ifndef GRAPH_GRIDCOLOR_DEFAULT
#define GRAPH_GRIDCOLOR_DEFAULT GUI_DARKGRAY
#endif
#ifndef GRAPH_GRIDSPACING_X_DEFAULT
#define GRAPH_GRIDSPACING_X_DEFAULT 50
#endif
#ifndef GRAPH_GRIDSPACING_Y_DEFAULT
#define GRAPH_GRIDSPACING_Y_DEFAULT 50
#endif
#ifndef GRAPH_BORDER_L_DEFAULT
#define GRAPH_BORDER_L_DEFAULT 0
#endif
#ifndef GRAPH_BORDER_T_DEFAULT
#define GRAPH_BORDER_T_DEFAULT 0
#endif
#ifndef GRAPH_BORDER_R_DEFAULT
#define GRAPH_BORDER_R_DEFAULT 0
#endif
#ifndef GRAPH_BORDER_B_DEFAULT
#define GRAPH_BORDER_B_DEFAULT 0
#endif
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
GRAPH_PROPS GRAPH__DefaultProps = {
GRAPH_BKCOLOR_DEFAULT,
GRAPH_BORDERCOLOR_DEFAULT,
GRAPH_FRAMECOLOR_DEFAULT,
GRAPH_GRIDCOLOR_DEFAULT,
GRAPH_GRIDSPACING_X_DEFAULT,
GRAPH_GRIDSPACING_Y_DEFAULT,
GRAPH_BORDER_L_DEFAULT,
GRAPH_BORDER_T_DEFAULT,
GRAPH_BORDER_R_DEFAULT,
GRAPH_BORDER_B_DEFAULT,
};
/*********************************************************************
*
* Static routines
*
**********************************************************************
*/
/*********************************************************************
*
* _DrawGrid
*/
static void _DrawGrid(GRAPH_OBJ * pObj, GRAPH_Handle hObj, unsigned BorderL, unsigned BorderT, unsigned BorderR, unsigned BorderB) {
GUI_RECT Rect;
U8 LineStyleOld;
int i, xSize, ySize, xSpace, ySpace, EffectSize;
WM_GetInsideRectExScrollbar(hObj, &Rect);
EffectSize = pObj->Widget.pEffect->EffectSize;
xSpace = pObj->Props.GridSpacingX;
ySpace = pObj->Props.GridSpacingY;
xSize = Rect.x1 - Rect.x0 + 1 - BorderL - BorderR;
ySize = Rect.y1 - Rect.y0 + 1 - BorderT - BorderB;
GUI_SetColor(pObj->Props.aColor[GRAPH_CI_GRID]);
LineStyleOld = GUI_GetLineStyle();
if (xSpace) {
int FirstPosX;
FirstPosX = xSpace + pObj->Props.GridOffX + ((pObj->Flags & GRAPH_CF_GRID_FIXED_X) ? 0 : pObj->ScrollStateH.v);
while (FirstPosX >= xSpace) FirstPosX -= xSpace;
GUI_SetLineStyle(pObj->LineStyleV);
for (i = FirstPosX; i < xSize; i += xSpace) {
int x, y0, y1;
x = i + BorderL + EffectSize;
y0 = Rect.y0 + BorderT;
y1 = Rect.y1 - BorderB;
if (pObj->LineStyleV != GUI_LS_SOLID) {
GUI_DrawLine(x, y0, x, y1);
} else {
GUI_DrawVLine(x, y0, y1);
}
}
}
if (ySpace) {
int FirstPosY;
FirstPosY = ySpace + pObj->Props.GridOffY - pObj->ScrollStateV.v;
while (FirstPosY >= ySpace) FirstPosY -= ySpace;
GUI_SetLineStyle(pObj->LineStyleH);
for (i = FirstPosY; i < ySize; i += ySpace) {
int y, x0, x1;
y = Rect.y1 - BorderB - i;
x0 = Rect.x0 + BorderL;
x1 = Rect.x1 - BorderR;
if (pObj->LineStyleH != GUI_LS_SOLID) {
GUI_DrawLine(x0, y, x1, y);
} else {
GUI_DrawHLine(y, x0, x1);
}
}
}
GUI_SetLineStyle(LineStyleOld);
}
/*********************************************************************
*
* _DrawBorder
*/
static void _DrawBorder(GRAPH_OBJ * pObj, GRAPH_Handle hObj, unsigned BorderL, unsigned BorderT, unsigned BorderR, unsigned BorderB, GUI_RECT * pRectInvalid) {
if (BorderL || BorderT || BorderR || BorderB) {
int OrgX, OrgY, x0, y0, x1, y1, x0_Clear, y0_Clear, x1_Clear, y1_Clear;
GUI_RECT Rect;
int EffectSize;
EffectSize = pObj->Widget.pEffect->EffectSize;
WM_GetInsideRectExScrollbar(hObj, &Rect);
OrgX = WM_GetOrgX();
OrgY = WM_GetOrgY();
x0 = Rect.x0 + BorderL;
y0 = Rect.y0 + BorderT;
x1 = Rect.x1 - BorderR;
y1 = Rect.y1 - BorderB;
GUI_SetBkColor(pObj->Props.aColor[GRAPH_CI_BORDER]);
GUI_SetColor(pObj->Props.aColor[GRAPH_CI_FRAME]);
if (BorderL) {
x1_Clear = BorderL - 1 + EffectSize;
if ((pRectInvalid->x0 - OrgX) <= x1_Clear) {
x0_Clear = Rect.x0;
y0_Clear = BorderT + EffectSize;
y1_Clear = Rect.y1 - BorderB + 1;
GUI_ClearRect(x0_Clear, y0_Clear, x1_Clear, y1_Clear);
GUI_DrawVLine(x0 - 1, y0 - 1, y1 + 1);
}
}
if (BorderT) {
y1_Clear = BorderT - 1 + EffectSize;
if ((pRectInvalid->y0 - OrgY) <= y1_Clear) {
x0_Clear = Rect.x0;
y0_Clear = Rect.y0;
x1_Clear = Rect.x1;
GUI_ClearRect(x0_Clear, y0_Clear, x1_Clear, y1_Clear);
GUI_DrawHLine(y0 - 1, x0 - 1, x1 + 1);
}
}
if (BorderR) {
x0_Clear = Rect.x1 - BorderR + 1;
if ((pRectInvalid->x1 - OrgX) >= x0_Clear) {
y0_Clear = BorderT + EffectSize;
x1_Clear = Rect.x1;
y1_Clear = Rect.y1 - BorderB + 1;
GUI_ClearRect(x0_Clear, y0_Clear, x1_Clear, y1_Clear);
GUI_DrawVLine(x1 + 1, y0 - 1, y1 + 1);
}
}
if (BorderB) {
y0_Clear = Rect.y1 - BorderB + 1;
if ((pRectInvalid->y1 - OrgY) >= y0_Clear) {
x0_Clear = Rect.x0;
x1_Clear = Rect.x1;
y1_Clear = Rect.y1;
GUI_ClearRect(x0_Clear, y0_Clear, x1_Clear, y1_Clear);
GUI_DrawHLine(y1 + 1, x0 - 1, x1 + 1);
}
}
}
}
/*********************************************************************
*
* _GetParams
*/
static void _GetParams(GRAPH_OBJ * pObj, unsigned * pBorderL, unsigned * pBorderT, unsigned * pBorderR, unsigned * pBorderB, unsigned * pEffectSize) {
*pBorderL = pObj->Props.BorderL;
*pBorderT = pObj->Props.BorderT;
*pBorderR = pObj->Props.BorderR;
*pBorderB = pObj->Props.BorderB;
*pEffectSize = pObj->Widget.pEffect->EffectSize;
}
/*********************************************************************
*
* _OnPaint
*/
static void _OnPaint(GRAPH_OBJ * pObj, GRAPH_Handle hObj, GUI_RECT * pRectInvalid) {
unsigned BorderL, BorderT, BorderR, BorderB, EffectSize, i, NumItems;
GUI_RECT RectClient, Rect;
_GetParams(pObj, &BorderL, &BorderT, &BorderR, &BorderB, &EffectSize);
WM_GetClientRect(&RectClient);
WIDGET__EFFECT_DrawDownRect(&pObj->Widget, &RectClient);
Rect = RectClient;
Rect.y0 += BorderT + EffectSize;
Rect.y1 -= BorderB + EffectSize;
Rect.x0 += BorderL + EffectSize;
Rect.x1 -= BorderR + EffectSize;
WM_SetUserClipRect(&Rect);
GUI_SetBkColor(pObj->Props.aColor[GRAPH_CI_BK]);
GUI_Clear();
if (pObj->pUserDraw) {
pObj->pUserDraw(hObj, GRAPH_DRAW_FIRST);
}
if (pObj->ShowGrid) {
_DrawGrid(pObj, hObj, BorderL, BorderT, BorderR, BorderB);
}
NumItems = pObj->GraphArray.NumItems;
for (i = 0; i < NumItems; i++) {
WM_HMEM hMem;
WM_HMEM * phMem;
hMem = GUI_ARRAY_GethItem(&pObj->GraphArray, i); /* Handle of array item */
phMem = (WM_HMEM *)GUI_ALLOC_h2p(hMem); /* Pointer to handle */
if (phMem) {
GRAPH_DATA_Handle hDataObj;
GRAPH_DATA_OBJ * pDataObj;
hDataObj = *(WM_HMEM *)phMem;
pDataObj = (GRAPH_DATA_OBJ *)GUI_ALLOC_h2p(hDataObj);
if (pDataObj) {
pDataObj->PaintObj.pfOnPaint(hDataObj, pRectInvalid);
}
}
}
GUI__ReduceRect(&Rect, &RectClient, EffectSize);
WM_SetUserClipRect(&Rect);
_DrawBorder(pObj, hObj, BorderL, BorderT, BorderR, BorderB, pRectInvalid);
NumItems = pObj->ScaleArray.NumItems;
for (i = 0; i < NumItems; i++) {
WM_HMEM hMem;
WM_HMEM * phMem;
hMem = GUI_ARRAY_GethItem(&pObj->ScaleArray, i); /* Handle of array item */
phMem = (WM_HMEM *)GUI_ALLOC_h2p(hMem); /* Pointer to handle */
if (phMem) {
GRAPH_SCALE_Handle hScaleObj;
GRAPH_SCALE_OBJ * pScaleObj;
hScaleObj = *(WM_HMEM *)phMem;
pScaleObj = (GRAPH_SCALE_OBJ *)GUI_ALLOC_h2p(hScaleObj);
if (pScaleObj) {
pScaleObj->PaintObj.pfOnPaint(hScaleObj, pRectInvalid);
}
}
}
WM_SetUserClipRect(0);
if (pObj->pUserDraw) {
pObj->pUserDraw(hObj, GRAPH_DRAW_LAST);
}
}
/*********************************************************************
*
* _OnDelete
*/
static void _OnDelete(GRAPH_OBJ * pObj) {
int i, NumItems;
NumItems = pObj->GraphArray.NumItems;
for (i = 0; i < NumItems; i++) {
WM_HMEM hMem;
WM_HMEM * phMem;
hMem = GUI_ARRAY_GethItem(&pObj->GraphArray, i); /* Handle of array item */
phMem = (WM_HMEM *)GUI_ALLOC_h2p(hMem); /* Pointer to handle */
if (phMem) {
GRAPH_DATA_Handle hDataObj;
GRAPH_DATA_OBJ * pDataObj;
hDataObj = *(WM_HMEM *)phMem;
pDataObj = (GRAPH_DATA_OBJ *)GUI_ALLOC_h2p(hDataObj);
if (pDataObj) {
pDataObj->PaintObj.pfOnDelete(hDataObj);
}
GUI_ALLOC_Free(hDataObj);
}
}
NumItems = pObj->ScaleArray.NumItems;
for (i = 0; i < NumItems; i++) {
WM_HMEM hMem;
WM_HMEM * phMem;
hMem = GUI_ARRAY_GethItem(&pObj->ScaleArray, i); /* Handle of array item */
phMem = (WM_HMEM *)GUI_ALLOC_h2p(hMem); /* Pointer to handle */
if (phMem) {
GRAPH_SCALE_Handle hScaleObj;
hScaleObj = *(WM_HMEM *)phMem;
GUI_ALLOC_Free(hScaleObj);
}
}
GUI_ARRAY_Delete(&pObj->GraphArray);
GUI_ARRAY_Delete(&pObj->ScaleArray);
}
/*********************************************************************
*
* _InvalidateGraph
*/
static void _InvalidateGraph(GRAPH_Handle hObj) {
unsigned BorderL, BorderT, BorderR, BorderB, EffectSize;
GUI_RECT Rect;
GRAPH_OBJ * pObj;
pObj = GRAPH_H2P(hObj);
_GetParams(pObj, &BorderL, &BorderT, &BorderR, &BorderB, &EffectSize);
WM_GetInsideRectExScrollbar(hObj, &Rect);
Rect.x0 += BorderL;
Rect.y0 += BorderT;
Rect.x1 -= BorderR;
Rect.y1 -= BorderB;
WM_InvalidateRect(hObj, &Rect);
}
/*********************************************************************
*
* _ManageScrollBars
*/
static void _ManageScrollBars(GRAPH_OBJ * pObj, GRAPH_Handle hObj) {
int IsRequired, PageSize;
GUI_RECT Rect;
unsigned BorderL, BorderT, BorderR, BorderB, EffectSize;
WM_GetInsideRectExScrollbar(hObj, &Rect);
_GetParams(pObj, &BorderL, &BorderT, &BorderR, &BorderB, &EffectSize);
PageSize = Rect.y1 - Rect.y0 - BorderT - BorderB;
IsRequired = ((int)pObj->RangeY > PageSize) ? 1 : 0;
WM_SetScrollbarV(hObj, IsRequired);
pObj->ScrollStateV.NumItems = pObj->RangeY;
pObj->ScrollStateV.PageSize = PageSize;
PageSize = Rect.x1 - Rect.x0 - BorderL - BorderR;
IsRequired = ((int)pObj->RangeX > PageSize) ? 1 : 0;
WM_SetScrollbarH(hObj, IsRequired);
pObj->ScrollStateH.NumItems = pObj->RangeX;
pObj->ScrollStateH.PageSize = PageSize;
WM_CheckScrollBounds(&pObj->ScrollStateV);
WM_CheckScrollBounds(&pObj->ScrollStateH);
WIDGET__SetScrollState(hObj, &pObj->ScrollStateV, &pObj->ScrollStateH);
}
/*********************************************************************
*
* _SetGridOffY
*/
static unsigned _SetGridOffY(GRAPH_OBJ * pObj, GRAPH_Handle hObj, unsigned Value) {
unsigned OldValue = 0;
if (pObj) {
OldValue = pObj->Props.GridOffY;
if (pObj->Props.GridOffY != Value) {
pObj->Props.GridOffY = Value;
_InvalidateGraph(hObj);
}
}
return OldValue;
}
/*********************************************************************
*
* _OnScrollValueChanged
*/
static void _OnScrollValueChanged(GRAPH_OBJ * pObj, GRAPH_Handle hObj, WM_HWIN hScroll) {
int Value, Id;
Value = SCROLLBAR_GetValue(hScroll);
Id = WM_GetId(hScroll);
if (Id == GUI_ID_VSCROLL) {
pObj->ScrollStateV.v = Value;
} else {
pObj->ScrollStateH.v = Value;
}
WM_InvalidateWindow(hObj);
}
/*********************************************************************
*
* Private routines
*
**********************************************************************
*/
/*********************************************************************
*
* GRAPH_h2p
*/
#if GUI_DEBUG_LEVEL >= GUI_DEBUG_LEVEL_CHECK_ALL
GRAPH_OBJ * GRAPH_h2p(GRAPH_Handle h) {
GRAPH_OBJ * p = (GRAPH_OBJ *)GUI_ALLOC_h2p(h);
if (p) {
if (p->DebugId != GRAPH_ID) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -