📄 plxdyncmenu.c
字号:
/***************************************************************************
*
* Pollex Mobile Platform
*
* Copyright (c) 2004 by Pollex Mobile Software Co., Ltd.
* All Rights Reserved
*
* Module :
*
* Purpose :
*
\**************************************************************************/
#include "MMI_features.h"
#include "gui.h"
#include "CommonScreens.h"
#include "PlxPublic.h"
#include "PlxPubDefs.h"
#include "EventsGprot.h"
#include "GUI_SETTING.h"
#include "HistoryGprot.h"
#include "gui_themes.h"
#include "wgui_categories.h"
#ifdef __MMI_TOUCH_SCREEN__
#include "wgui_touch_screen.h"
#endif
#include "GlobalDefs.h"
#if defined (__MMI_MAINLCD_240X320__)
#define OD_ICON_WIDTH 26
#else
#define OD_ICON_WIDTH 14
#endif
#define SUB_ICON_WIDTH 10 //14
#define INDENT_VALUE 12
#define TIMER_ID 41
#define TIMER_DELAY 500
#define ONCE_ROLL_VALUE 4
#define DF_FOCUSITEM_ROLL_SPACE_INTERVAL 35
#if defined(__MMI_MAINLCD_128X128__)
#define SPACE_IN_ICON_AND_TEXT 5
#define MENUS_IN_SCREEN 5
#elif defined(__MMI_MAINLCD_128X160__)
#define SPACE_IN_ICON_AND_TEXT 5 //status bar's height
#define MENUS_IN_SCREEN 7
#elif defined(__MMI_MAINLCD_176X220__)
#define SPACE_IN_ICON_AND_TEXT 9
#define MENUS_IN_SCREEN 7
// chm debug
#elif defined(__MMI_MAINLCD_240X320__)
#define SPACE_IN_ICON_AND_TEXT 13
#define MENUS_IN_SCREEN 8
#endif
struct tag_Menu_Obj;
typedef struct{
unsigned short wFlags;
unsigned long hIDorGroup;
unsigned short cbItemStr; //string size
const char *pStr;
unsigned short imageID;
struct tag_Menu_Obj *pOwner;
}DMENUITEM, *PDMENUITEM;
typedef struct tag_Menu_Obj{
unsigned short wFlags;
unsigned short wUsedItems;
unsigned short wItems;
unsigned short level;
int firstLine;
int focuseItem;
PDMENUITEM hParent;
PDMENUITEM pItemsMemBlock;
}DMENUOBJ, *PDMENUOBJ;
typedef enum{
WAY_FORWARD,
WAY_BACKWARD
}MOVWAY;
typedef struct{
long left;
long top;
long right;
long bottom;
}DM_RC, *PDM_RC;
/*for display the menu*/
typedef struct {
BOOL bEnable;
S32 strWidth;
S32 startX;
S32 restartX;
int nRollCount;
}ROLLSTR;
typedef struct {
PDMENUOBJ pMenu;
U16 screenID;
STRING_ID title;
S32 txtHeight;
int itemHeight;
int itemCount; //in global screen, the count of all the items
int firstLine;
int linesInScreen;
int focuseItem; //in global screen, the focused item
DM_RC rcList; //the rect of the list area
DM_RC rcOrderIcon; //the rect of order icon
DM_RC rcTxt; //the rect of the listed text
DM_RC rcSubIcon; //the rect of sub menu icon
DM_RC rcFocus; //the rect of the focused item text
DM_RC rcVScroll; //the rect of the vertical scrollbar
DMENUNOTIFY NotifyFunc; //callback function to notify something
ROLLSTR rollStr;
vertical_scrollbar vScroll;
}DMENUDISP, *PDMENUDISP;
static DMENUDISP menuDisp = {0};
static U16 keyNeeded[] = {KEY_LEFT_ARROW, KEY_RIGHT_ARROW, KEY_UP_ARROW, KEY_DOWN_ARROW, KEY_ENTER, KEY_END,KEY_VOL_UP,KEY_VOL_DOWN
/*,KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,*/ };
#define SIZE_ONCE_REALLOC 5
static BOOL bVirtualKeyPressed = FALSE;
static U16 virtualKey;
static BOOL bIsShortcutDisabled;
static U16 nDMTitleID = 0;
static U16 nDMTitleIconID = 0;
static U16 nDMLeftKey=0;
static U16 nDMLeftKeyIcon = 0;
static U16 nDMRightKey = 0;
static U16 nDMRightKeyIcon = 0;
static void MoveItemsInMemBlock(PDMENUITEM pMemBlock, MOVWAY movWay, unsigned short hasItems, unsigned short wPos);
static unsigned long GetCountToDisplay(PDMENUOBJ pObj);
static void ResetMenuState(PDMENUOBJ pObj);
extern S32 UCS2Strlen (const S8 *arrOut);
void EntryOfDyncMenuScreen(FuncPtr DMenuEntry);
void ExitOfDyncMenuScreen(void);
static void DrawDyncMenuScreen(void);
static void DrawMenuList(PDM_RC pRcDraw);
static PDMENUITEM GetItemFromLine(PDMENUOBJ pObj, int* pCount, int line);
static int GetLineFromItem(int* line, PDMENUOBJ pObj, PDMENUITEM pItem);
static void DrawLines(int line1, int line2);
static void DrawOneLine(int line, PDMENUITEM pItem);
static void DMenuProcessKeyEvent (void);
static void ShortcutSelectOnlyHandler(S32 index);
static void ProcessFocusItem(void);
static void RollTimerFunc(void);
static void ProcessScrollInfo(void);
static void OnDMenuCofirm(void);
static void OnDMenuBack(void);
static void OnDMenuNotify( unsigned long id, unsigned long event);
#ifdef __MMI_TOUCH_SCREEN__
static void OnTouchPenDown(mmi_pen_point_struct pos);
static void OnTouchPenMove(mmi_pen_point_struct pos);
static void OnTouchPenUp(mmi_pen_point_struct pos);
static void OnTouchPenRepeat(mmi_pen_point_struct pos);
static BOOL ProcessPenOnScrollbar(mmi_pen_point_struct pos, mmi_pen_event_type_enum pen_event);
static BOOL ProcessPenOnSoftkey(mmi_pen_point_struct pos, mmi_pen_event_type_enum pen_event);
static BOOL PenPointInRect(PDM_RC pRc, mmi_pen_point_struct pos);
static BOOL UsePenSelectItem(mmi_pen_point_struct pos);
#endif //__MMI_TOUCH_SCREEN__
/*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*
<> Function PlxCreateDyncMenu
<> Purpose create a dynamic menu object
<> Params
<> Return the menu's handle, or 0 when failed to create.
<> Remarks
\*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/
HDMENU PlxCreateDMenu(unsigned short wFlags){
PDMENUOBJ hRet;
hRet = PlxAppMalloc(sizeof(DMENUOBJ));
if (0 == hRet) {
return 0;
}
hRet->wFlags = wFlags;
hRet->hParent = 0;
hRet->wItems = 0;
hRet->wUsedItems = 0;
hRet->pItemsMemBlock = 0;
hRet->level = 0;
hRet->firstLine = 0;
hRet->focuseItem = 0;
return (HDMENU)hRet;
}
/*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*
<> Function PlxInsertDyncMenuItem
<> Purpose insert a menu item to a existent menu object
<> Params
<> Return 0 successed; other failed
<> Remarks
\*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/
int PlxInsertDMenuItem(HDMENU hDMenu, int wPosition, unsigned short wFlags,
unsigned long menuId, const char *pItemStr, unsigned short imageID){
PDMENUOBJ pMenuObj = (PDMENUOBJ)hDMenu, pObj;
PDMENUITEM pTmpMemBlock, pInstPos;
int i;
unsigned short wNeedtoMov = 0;
int itemCount;
/*make sure that the memory block is big enough*/
// pTmpMemBlock = pMenuObj->pItemsMemBlock;
if (pMenuObj->wUsedItems + 1 > pMenuObj->wItems) {
pTmpMemBlock = PlxAppRealloc(pMenuObj->pItemsMemBlock, (pMenuObj->wItems + SIZE_ONCE_REALLOC) * sizeof(DMENUITEM));
if (0 == pTmpMemBlock) {
return -1; //realloc failed
}
pMenuObj->pItemsMemBlock = pTmpMemBlock;
pMenuObj->wItems += SIZE_ONCE_REALLOC;
for (pInstPos = pMenuObj->pItemsMemBlock, i = 0; i < pMenuObj->wUsedItems; ++ i) {
if (pInstPos->wFlags & MF_POPUP) {
pObj = (PDMENUOBJ)pInstPos->hIDorGroup;
pObj->hParent = pInstPos;
}
++ pInstPos;
}
}
// pMenuObj->pItemsMemBlock = pTmpMemBlock;
/*find the position to insert*/
if (wFlags & MF_BYPOSITION) {
if (-1 == wPosition || wPosition > pMenuObj->wUsedItems) {
pInstPos = pMenuObj->pItemsMemBlock + pMenuObj->wUsedItems;
}
else{
pInstPos = pMenuObj->pItemsMemBlock + wPosition;
wNeedtoMov = pMenuObj->wUsedItems - wPosition;
}
}
else{
for (pInstPos = pMenuObj->pItemsMemBlock, i = 0; i < pMenuObj->wUsedItems; ++ i) {
if ((unsigned long)wPosition == pInstPos->hIDorGroup) {
break;
}
++ pInstPos;
}
wNeedtoMov = pMenuObj->wUsedItems - i;
}
/*make room for the new item*/
if (wNeedtoMov > 0) {
MoveItemsInMemBlock(pInstPos, WAY_FORWARD, wNeedtoMov, 1);
}
/*save the new item*/
pInstPos->cbItemStr = UCS2Strlen(pItemStr);
pInstPos->hIDorGroup = menuId;
pInstPos->pStr = pItemStr;
pInstPos->imageID = imageID;
pInstPos->wFlags = wFlags;
pInstPos->pOwner = (PDMENUOBJ)hDMenu;
if (wFlags & MF_POPUP) {
((PDMENUOBJ)menuId)->hParent = pInstPos;
((PDMENUOBJ)menuId)->level = pMenuObj->level + 1;
}
++ pMenuObj->wUsedItems;
if(pMenuObj->focuseItem > 0 )
{
i = pInstPos - pMenuObj->pItemsMemBlock;
itemCount = GetCountToDisplay(pMenuObj);
if(i >=0 && i<= pMenuObj->focuseItem)
{
pMenuObj->focuseItem++;
if(i <= pMenuObj->firstLine)
pMenuObj->firstLine ++;
else
{
if (pMenuObj->focuseItem - pMenuObj->firstLine >= MENUS_IN_SCREEN)
{
if (pMenuObj->focuseItem < itemCount - 1)
{
pMenuObj->firstLine += 2;
}
else
{
++ pMenuObj->firstLine;
}
}
}
}
}
return 0;
}
/*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*
<> Function PlxDestroyDMenu
<> Purpose destroy a menu object
<> Params
<> Return
<> Remarks
\*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/
int PlxDestroyDMenu(HDMENU hDMenu){
PDMENUOBJ pMenuObj = (PDMENUOBJ)hDMenu;
int i;
for (i = 0; i < pMenuObj->wUsedItems; ++ i) {
if (pMenuObj->pItemsMemBlock[i].wFlags & MF_POPUP) {
PlxDestroyDMenu((HDMENU)pMenuObj->pItemsMemBlock[i].hIDorGroup);
}
}
if(pMenuObj->pItemsMemBlock)
PlxAppFree(pMenuObj->pItemsMemBlock);
PlxAppFree(pMenuObj);
return 0;
}
/*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*
<> Function PlxDeleteDMenuItem
<> Purpose delete a menu item from a menu object
<> Params
<> Return 0 successed; other failed
<> Remarks
\*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/
int PlxDeleteDMenuItem(HDMENU hDMenu, int wPos, unsigned short wFlags){
PDMENUOBJ pMenuObj = (PDMENUOBJ)hDMenu;
PDMENUITEM pItemToDel;
unsigned short wNeedtoMov = 0;
int i;
int itemCount;
if (pMenuObj->wUsedItems == 0) {
return -1; //no item in the menu
}
pItemToDel = pMenuObj->pItemsMemBlock;
if (wFlags & MF_BYPOSITION) {
if (wPos < 0 || wPos >= pMenuObj->wUsedItems) {
return -2; //no this menu item
}
pItemToDel = pMenuObj->pItemsMemBlock + wPos;
wNeedtoMov = pMenuObj->wUsedItems - wPos - 1;
}
else{
for (pItemToDel = pMenuObj->pItemsMemBlock, i = 0; i < pMenuObj->wUsedItems; ++ i) {
if ((unsigned long)wPos == pItemToDel->hIDorGroup) {
break;
}
++ pItemToDel;
}
if (i >= pMenuObj->wUsedItems) {
return -2; //no this menu item
}
wNeedtoMov = pMenuObj->wUsedItems - i -1;
}
if (pItemToDel->wFlags & MF_POPUP) {
PlxDestroyDMenu((HDMENU)pItemToDel->hIDorGroup);
}
if (wNeedtoMov > 0) {
MoveItemsInMemBlock(pItemToDel+1, WAY_BACKWARD, wNeedtoMov, 1);
}
-- pMenuObj->wUsedItems;
if(pMenuObj->focuseItem > 0)
{
i = pItemToDel - pMenuObj->pItemsMemBlock;
itemCount = GetCountToDisplay(pMenuObj);
if(i >=0 && i == pMenuObj->focuseItem)
{
if(pMenuObj->focuseItem > 0 && pMenuObj->focuseItem == itemCount)
pMenuObj->focuseItem --;
if(pMenuObj->firstLine > 0 && pMenuObj->firstLine < pMenuObj->focuseItem )
{
pMenuObj->firstLine -=MENUS_IN_SCREEN;
if(pMenuObj->firstLine < 0)
pMenuObj->firstLine = 0;
}
}
else if(i >=0 && i < pMenuObj->focuseItem )
{
if(pMenuObj->focuseItem > 0)
pMenuObj->focuseItem --;
if(pMenuObj->firstLine > 0 && pMenuObj->firstLine <= i)
pMenuObj->firstLine --;
}
}
return 0;
}
/*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*
<> Function PlxModifyDMenuItem
<> Purpose modify a menu item
<> Params
<> Return
<> Remarks
\*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/
int PlxModifyDMenuItem(HDMENU hMenu, int wPos, unsigned short wFlags, unsigned long wIDNewItem,
const char *strNewItem, unsigned short imageID){
PDMENUOBJ pMenuObj = (PDMENUOBJ)hMenu;
PDMENUOBJ pSub;
PDMENUITEM pMenuItem;
int i;
if (pMenuObj->wUsedItems == 0) {
return -1; //no item in the menu
}
if (wFlags & MF_BYPOSITION) {
if (wPos < 0 || wPos >= pMenuObj->wUsedItems) {
return -2; //no this item in the menu
}
pMenuItem = pMenuObj->pItemsMemBlock + wPos;
pMenuItem->hIDorGroup = wIDNewItem; //if pMenuItem is a submenu, itis the user's duty to free it.
if (wFlags & MF_POPUP) {
pSub = (PDMENUOBJ)wIDNewItem;
pSub->hParent = pMenuItem;
pSub->level = pMenuObj->level + 1;
}
}
else{
for (pMenuItem = pMenuObj->pItemsMemBlock, i = 0; i < pMenuObj->wUsedItems; ++ i) {
if (pMenuItem->hIDorGroup == (unsigned long)wPos) {
break;
}
++ pMenuItem;
}
if (i >= pMenuObj->wUsedItems) {
return -2; //no this item in the menu
}
}
pMenuItem->wFlags = wFlags;
pMenuItem->pStr = strNewItem;
if (imageID > 0 || IMG_ID_PLX_PUBLIC_GLOBAL_NUMBERICON == imageID) {
pMenuItem->imageID = imageID;
}
return 0;
}
/*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*
<> Function MoveItemsInMemBlock
<> Purpose move the items' position in the memory block
<> Params hasItems how many items need to be moved
<> wPos how many pos should move with
<> Return void
<> Remarks
\*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/
static void MoveItemsInMemBlock(PDMENUITEM pMemBlock, MOVWAY movWay, unsigned short hasItems, unsigned short wPos){
PDMENUITEM pOldPos, pNewPos;
int i;
if (WAY_FORWARD == movWay) {
pOldPos = pMemBlock + hasItems - 1;
pNewPos = pOldPos + wPos;
//i = wPos; modified by jhzhao
i = hasItems;
}
else if (WAY_BACKWARD == movWay) {
pOldPos = pMemBlock;
pNewPos = pOldPos - wPos;
i = 0;
}
do {
pixtel_UI_memcpy(pNewPos, pOldPos, sizeof(DMENUITEM));
if (WAY_FORWARD == movWay) {
-- pOldPos;
-- pNewPos;
-- i;
}
else if (WAY_BACKWARD == movWay) {
++ pOldPos;
++ pNewPos;
++ i;
}
} while(i > 0 && i < hasItems/*i < wPos modifid by jhzhao*/);
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
>
> following is the UI part
>
\*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
/*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*
<> Function PlxSetDMenuDispInfo
<> Purpose Set menu icon and string info ,call this func before PlxShowDMenu
<> Params
<> Return
<> Remarks
\*<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -