├── README.md ├── bMenu.h └── bMenu.c /README.md: -------------------------------------------------------------------------------- 1 | # bMenu 2 | --------- 3 | a common frame for menu, just for fun! 4 | -------- 5 | using process: 6 | -------- 7 | >>1. add bMenu.c and bMenu.h to your project .
8 | >>2. calling bM_Init() function. add malloc and free interface
9 | >>3. building your menu structure
10 | 11 | for example:
12 | ---------- 13 | 14 | 15 | item1----item2-----item3-----item4 16 | | 17 | item5----item6----item7 18 | | 19 | item8--item9 20 | | 21 | item10 22 | it's a four levels menu. then, divide it:
23 | create four objects by `bM_CreateObject();`
24 | add items and creating UI function to the object by `bM_AddItemToObject()`;
25 | 26 | object1 {item1----item2----item3----item4}
27 | object2 {item5----item6----item7}
28 | object3 {item8----item9}
29 | object4 {item10}
30 | 31 | 32 | user_id of every object and item must be different.
33 | maybe you can do that through enum:
34 | ```C 35 | enum 36 | { 37 | USER_ID_OBJECT_1, 38 | USER_ID_ITEM1, 39 | USER_ID_ITEM2, 40 | USER_ID_ITME3, 41 | USER_ID_ITEM4, 42 | USER_ID_OBJECT_2, 43 | USER_ID_ITEM5, 44 | USER_ID_ITEM6, 45 | USER_ID_ITEM7, 46 | USER_ID_OBJECT_3, 47 | USER_ID_ITEM8, 48 | USER_ID_ITEM9, 49 | USER_ID_OBJECT_4, 50 | USER_ID_ITEM10 51 | }; 52 | 53 | example_func 54 | { 55 | bM_OBJ_Handle hobj, hobj_tmp; 56 | bM_ITEM_Handle hItem; 57 | 58 | hobj = bM_CreateObject(bM_HANDLE_INVALID, USER_ID_OBJECT_1); 59 | bM_AddItemToObject(hobj, USER_ID_ITEM1, func1); 60 | hItem = bM_AddItemToObject(hobj, USER_ID_ITEM2, func2); 61 | bM_AddItemToObject(hobj, USER_ID_ITME3, func3); 62 | bM_AddItemToObject(hobj, USER_ID_ITEM4, func4); 63 | 64 | hobj_tmp = bM_CreateObject(hItem, USER_ID_OBJECT_2); 65 | bM_AddItemToObject(hobj_tmp, USER_ID_ITEM5, func5); 66 | hItem = bM_AddItemToObject(hobj_tmp, USER_ID_ITEM6, func6); 67 | bM_AddItemToObject(hobj_tmp, USER_ID_ITEM7, func7); 68 | 69 | hobj_tmp = bM_CreateObject(hItem, USER_ID_OBJECT_3); 70 | hItem = bM_AddItemToObject(hobj_tmp, USER_ID_ITEM8, func8); 71 | bM_AddItemToObject(hobj_tmp, USER_ID_ITEM9, func9); 72 | 73 | hobj_tmp = bM_CreateObject(hItem, USER_ID_OBJECT_4); 74 | bM_AddItemToObject(hobj_tmp, USER_ID_ITEM10, func10); 75 | 76 | //then set the entry point: 77 | bM_SetMenuEntryPoint(hobj); 78 | } 79 | ``` 80 | then the menu structure has been created. 81 | 82 | add `bM_BMenuModuleTask()` to `while(1)` 83 | 84 | then: 85 | you can call `bM_SendMessage()` to control switching. 86 | 87 | for example: 88 | ```c 89 | bM_SendMessage(BM_OPERATE_NEXT, 0); // to show the next item 90 | 91 | bM_SendMessage(BM_OPERATE_JUMP_TO, USER_ID_ITEM5); //to show the item5 92 | ``` 93 | 94 | 95 | Ok! you can try it by yourself now! 96 | 97 | if you have some suggestion, please contact me. 98 | `email: notrynohigh@outlook.com` 99 | 100 | 101 | Thanks! 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /bMenu.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * MIT License 3 | * File: bMenu.h Version: v0.1.1 4 | * Copyright (c) [2017-2018] [Bean email: notrynohigh@outlook.com] 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | *****************************************************************************/ 24 | /****************************************************************************** 25 | * Reserve ! 26 | ******************************************************************************/ 27 | #ifndef __BMENU_H__ 28 | #define __BMENU_H__ 29 | 30 | 31 | /****************************************************************************** 32 | * According to your CPU to change these. 33 | ******************************************************************************/ 34 | typedef unsigned char bM_U8; 35 | typedef signed char bM_S8; 36 | typedef unsigned short bM_U16; 37 | typedef signed short bM_S16; 38 | typedef unsigned int bM_U32; 39 | typedef signed int bM_S32; 40 | 41 | /** Debug interface */ 42 | #define BM_DEBUG_ENABLE 1 43 | 44 | #if BM_DEBUG_ENABLE 45 | #define bM_Debug(...) printf(__VA_ARGS__) 46 | #else 47 | #define bM_Debug(...) 48 | #endif 49 | 50 | /** OS support */ 51 | #define BM_OS_ENABLE 0 52 | #if BM_OS_ENABLE 53 | #include "xxxos.h" 54 | #endif 55 | /** 56 | * if your system supports OS, then please complete these two funcions : 57 | * bM_Result_t bM_GiveSemaphore(void); 58 | * bM_Result_t bM_TakeSemaphore(void); 59 | */ 60 | 61 | /****************************************************************************** 62 | * define 63 | ******************************************************************************/ 64 | #define bM_ID bM_U8 65 | #define bM_Handle bM_U32 66 | #define bM_OBJ_Handle bM_Handle 67 | #define bM_ITEM_Handle bM_Handle 68 | 69 | #define bM_NULL ((void *)0) 70 | #define bM_TRUE 1 71 | #define bM_FALSE 0 72 | 73 | #define bM_HANDLE_INVALID 0X0 74 | 75 | /****************************************************************************** 76 | * typedef 77 | ******************************************************************************/ 78 | /** typedef enum section ---------------------------------------------------*/ 79 | typedef enum 80 | { 81 | BM_FALSE = bM_FALSE, 82 | BM_TRUE = bM_TRUE, 83 | }bM_bool_t; 84 | 85 | 86 | /** 87 | * bM_Result: error number 88 | */ 89 | typedef enum 90 | { 91 | BM_ERROR, 92 | BM_SUCCESS, 93 | BM_MEMORY_ERR, 94 | BM_OTHER_FAULT 95 | }bM_Result_t; 96 | 97 | typedef enum 98 | { 99 | BM_OPERATE_NULL, //reserved 100 | BM_OPERATE_INIT, //reserved 101 | 102 | BM_OPERATE_NEXT, 103 | BM_OPERATE_PREV, 104 | BM_OPERATE_GOTO_CHILD, 105 | BM_OPERATE_BACK_PARENT, 106 | BM_OPERATE_JUMP_TO, 107 | }bM_Operation_t; 108 | 109 | 110 | /** typedef functions section ---------------------------------------------------*/ 111 | typedef void (*bM_CreateUI_t)(void); 112 | typedef void* (*bM_Malloc)(int); 113 | typedef void (*bM_Free)(void *); 114 | 115 | 116 | /** typedef struct section -----------------------------------------------------*/ 117 | 118 | /** 119 | * bM object struct 120 | */ 121 | struct bM_Object 122 | { 123 | struct bM_Object *prev; 124 | struct bM_Object *next; 125 | bM_OBJ_Handle handle; 126 | struct bM_Item *pParent; 127 | struct bM_Item *pFirstItem; 128 | bM_U8 item_number; 129 | }; 130 | typedef struct bM_Object bM_Object_t; 131 | /** 132 | * bM item struct 133 | */ 134 | struct bM_Item 135 | { 136 | struct bM_Item *prev; 137 | struct bM_Item *next; 138 | bM_Object_t *child; 139 | bM_CreateUI_t create_ui; 140 | bM_ITEM_Handle handle; 141 | bM_bool_t visible; 142 | }; 143 | typedef struct bM_Item bM_Item_t; 144 | 145 | typedef struct 146 | { 147 | bM_Handle handle; 148 | union 149 | { 150 | bM_Object_t *pobj; 151 | bM_Item_t *pitem; 152 | }result; 153 | }bM_UserIdResult_t; 154 | 155 | /** 156 | * message struct 157 | */ 158 | typedef struct 159 | { 160 | bM_Operation_t opt; 161 | bM_UserIdResult_t result; //result is valid when opt is BM_OPERATE_JUMP_TO 162 | }bM_Message_t; 163 | 164 | typedef struct 165 | { 166 | bM_Object_t *pCurrentObj; 167 | bM_Item_t *pCurrentItem; 168 | bM_Message_t NewMessage; 169 | }bM_TaskManage_t; 170 | 171 | /** 172 | * dynamic memory control interface 173 | */ 174 | typedef struct 175 | { 176 | bM_Malloc pMalloc; 177 | bM_Free pFree; 178 | }bM_DMC_Interface_t; 179 | 180 | 181 | /****************************************************************************** 182 | * public functions 183 | ******************************************************************************/ 184 | /** 185 | * initianize bM module 186 | * param: dynamic memory control interface 187 | */ 188 | bM_Result_t bM_Init(bM_DMC_Interface_t bM_DMC_Interface); 189 | 190 | /** 191 | * create a menu object. if it's independent, parent = bM_HANDLE_INVALID 192 | * param: the handle of parent or bM_HANDLE_INVALID 193 | * attach an identification : all identifications must be different; 194 | * return: handle (0: error) (> 0)success 195 | */ 196 | bM_OBJ_Handle bM_CreateObject(bM_ITEM_Handle hParent, bM_ID id); 197 | 198 | /** 199 | * add item to bM module. the items which at the same level can be added. 200 | * hobj: the bM object handle 201 | * id : the item identification. 202 | * func: the UI create function 203 | */ 204 | bM_ITEM_Handle bM_AddItemToObject(bM_OBJ_Handle hobj, bM_ID id, bM_CreateUI_t func); 205 | 206 | /** 207 | * appoint an object as the entry point. 208 | * hobj: the bM object handle 209 | */ 210 | bM_Result_t bM_SetMenuEntryPoint(bM_OBJ_Handle hobj); 211 | 212 | /** 213 | * send operation message to bM management 214 | * id is valid when opt == BM_OPERATE_JUMP_TO 215 | */ 216 | bM_Result_t bM_SendMessage(bM_Operation_t opt, bM_ID id); 217 | 218 | /** this module start running */ 219 | void bM_BMenuModuleTask(void); 220 | 221 | /** destroy bM module */ 222 | void bM_BMenuModuleEnd(void); 223 | 224 | /** 225 | * change item's visiable 226 | * id: user id 227 | * visible: BM_TRUE or BM_FALSE 228 | */ 229 | bM_Result_t bM_ChangeVisibleStatus(bM_ID id, bM_bool_t visible); 230 | 231 | /** 232 | * get userid of current item 233 | * return : userid 234 | */ 235 | bM_ID bM_GetUseridOfCurrentItem(void); 236 | 237 | /****************************************************************************** 238 | * Reserve ! 239 | ******************************************************************************/ 240 | #endif 241 | 242 | /****************************************************************************** 243 | * End ! 244 | ******************************************************************************/ 245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /bMenu.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * MIT License 3 | * File: bMenu.c Version: v0.1.1 4 | * Copyright (c) [2017-2018] [Bean email: notrynohigh@outlook.com] 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | *****************************************************************************/ 24 | /****************************************************************************** 25 | * include 26 | ******************************************************************************/ 27 | #include "stdio.h" 28 | #include "string.h" 29 | #include "bMenu.h" 30 | 31 | /****************************************************************************** 32 | * global variable 33 | ******************************************************************************/ 34 | 35 | static bM_DMC_Interface_t g_bM_DMC_Interface = {bM_NULL, bM_NULL}; 36 | static bM_Object_t g_bM_ManageRoot = {bM_NULL, bM_NULL, 0, 0, bM_NULL,0}; 37 | static bM_Object_t* const gp_bM_ManageRoot = &g_bM_ManageRoot; 38 | static bM_Object_t *gp_bM_MenuEntryPoint = bM_NULL; 39 | 40 | static volatile bM_TaskManage_t g_bM_TaskManage; 41 | /** be used to create handles */ 42 | static bM_U32 g_bM_OBJ_Number = 0; 43 | static bM_U32 g_bM_ItemNumber = 0; 44 | 45 | #if BM_OS_ENABLE == 0 46 | static bM_bool_t g_bM_Semaphor = BM_FALSE; 47 | #endif 48 | 49 | /****************************************************************************** 50 | * private defined 51 | ******************************************************************************/ 52 | /* bM module version number */ 53 | #define bM_VERSION "V0.1.1" 54 | 55 | /****************************************************************************** 56 | * private typedef 57 | ******************************************************************************/ 58 | typedef enum 59 | { 60 | BM_ID_USER, 61 | BM_ID_OBJ, 62 | BM_ID_ITEM, 63 | }bM_ID_Types_t; 64 | 65 | typedef enum 66 | { 67 | BM_HANDLE_OBJ, 68 | BM_HANDLE_ITEM, 69 | }bM_HANDLE_Types_t; 70 | 71 | /****************************************************************************** 72 | * private functions 73 | ******************************************************************************/ 74 | 75 | static bM_Result_t bM_GiveSemaphore() 76 | { 77 | #if BM_OS_ENABLE 78 | //add your code .... 79 | #else 80 | if (g_bM_Semaphor == BM_FALSE) 81 | { 82 | g_bM_Semaphor = BM_TRUE; 83 | return BM_SUCCESS; 84 | } 85 | else 86 | { 87 | return BM_ERROR; 88 | } 89 | #endif 90 | } 91 | 92 | static bM_Result_t bM_TakeSemaphore() 93 | { 94 | #if BM_OS_ENABLE 95 | //add your code .... 96 | #else 97 | if (g_bM_Semaphor == BM_TRUE) 98 | { 99 | g_bM_Semaphor = BM_FALSE; 100 | return BM_SUCCESS; 101 | } 102 | else 103 | { 104 | return BM_ERROR; 105 | } 106 | #endif 107 | } 108 | 109 | /** 110 | * assemble bM_Handle [8bits reserve][8bits id][8bits obj_index][8bits item_index] 111 | */ 112 | static bM_Handle _bM_CreateHandle(bM_ID id, bM_ID obj_index, bM_ID item_index) 113 | { 114 | bM_Handle handle = 0; 115 | handle = (id << 16) | (obj_index << 8) | item_index; 116 | return handle; 117 | } 118 | 119 | /** 120 | * add new object to manage list 121 | */ 122 | static bM_Result_t _bM_AddObjectToManage(bM_Object_t *pbM_OBJ) 123 | { 124 | if(pbM_OBJ == bM_NULL) 125 | { 126 | return BM_ERROR; 127 | } 128 | gp_bM_ManageRoot->prev->next = pbM_OBJ; 129 | pbM_OBJ->next = gp_bM_ManageRoot; 130 | pbM_OBJ->prev = gp_bM_ManageRoot->prev; 131 | gp_bM_ManageRoot->prev = pbM_OBJ; 132 | return BM_SUCCESS; 133 | } 134 | 135 | static bM_Result_t _bM_AddItemToObject(bM_Object_t *pobj, bM_Item_t *pitem) 136 | { 137 | if(pobj == bM_NULL || pitem == bM_NULL) 138 | { 139 | bM_Debug("[%s]param error\n\r", __func__); 140 | return BM_ERROR; 141 | } 142 | if(pobj->pFirstItem == bM_NULL) 143 | { 144 | pobj->pFirstItem = pitem; 145 | pitem->next = pitem; 146 | pitem->prev = pitem; 147 | } 148 | else 149 | { 150 | pobj->pFirstItem->prev->next = pitem; 151 | pitem->prev = pobj->pFirstItem->prev; 152 | pitem->next = pobj->pFirstItem; 153 | pobj->pFirstItem->prev = pitem; 154 | } 155 | pobj->item_number++; 156 | return BM_SUCCESS; 157 | } 158 | 159 | 160 | static bM_ID _bM_GetIdFromHandle(bM_Handle handle, bM_ID_Types_t t) 161 | { 162 | bM_ID id = 0; 163 | switch (t) 164 | { 165 | case BM_ID_USER: 166 | { 167 | id = (handle >> 16) & 0xff; 168 | break; 169 | } 170 | case BM_ID_OBJ: 171 | { 172 | id = (handle >> 8) & 0xff; 173 | break; 174 | } 175 | case BM_ID_ITEM: 176 | { 177 | id = (handle >> 0) & 0xff; 178 | break; 179 | } 180 | default: break; 181 | 182 | } 183 | return id; 184 | } 185 | 186 | 187 | static bM_Object_t *_bM_GetObjectFromManage(bM_OBJ_Handle hobj) 188 | { 189 | bM_Object_t *pobj = gp_bM_ManageRoot->next; 190 | bM_ID id = _bM_GetIdFromHandle(hobj, BM_ID_OBJ); 191 | 192 | if(hobj == bM_HANDLE_INVALID || pobj == gp_bM_ManageRoot) 193 | { 194 | return bM_NULL; 195 | } 196 | do 197 | { 198 | if(_bM_GetIdFromHandle(pobj->handle, BM_ID_OBJ) == id) 199 | { 200 | return pobj; 201 | } 202 | pobj = pobj->next; 203 | }while(pobj != gp_bM_ManageRoot); 204 | return bM_NULL; 205 | } 206 | 207 | static bM_Item_t *_bM_GetItemtFromManage(bM_ITEM_Handle hitem) 208 | { 209 | bM_Object_t *pobj = _bM_GetObjectFromManage(hitem); 210 | bM_Item_t *pitem = bM_NULL; 211 | if(pobj == bM_NULL) 212 | { 213 | return bM_NULL; 214 | } 215 | if(pobj->pFirstItem == bM_NULL) 216 | { 217 | return bM_NULL; 218 | } 219 | pitem = pobj->pFirstItem; 220 | do 221 | { 222 | if(pitem->handle == hitem) 223 | { 224 | return pitem; 225 | } 226 | pitem = pitem->next; 227 | }while(pitem != pobj->pFirstItem); 228 | return bM_NULL; 229 | } 230 | 231 | /** 232 | * find out object or item by user_id 233 | * id: user_id 234 | * result: output the result. 235 | * error: result->handle == bM_HANDLE_INVALID 236 | */ 237 | static void _bM_GetOBJorItemById(bM_ID id, bM_UserIdResult_t *result) 238 | { 239 | bM_Object_t *pobj = gp_bM_ManageRoot->next; 240 | bM_Item_t* pitem; 241 | bM_U32 i = 0; 242 | result->handle = bM_HANDLE_INVALID; 243 | if(pobj == gp_bM_ManageRoot || pobj == bM_NULL) 244 | { 245 | return; 246 | } 247 | while(pobj != gp_bM_ManageRoot) 248 | { 249 | if(_bM_GetIdFromHandle(pobj->handle, BM_ID_USER) == id) 250 | { 251 | result->handle = pobj->handle; 252 | result->result.pobj = pobj; 253 | return; 254 | } 255 | else if(pobj->item_number > 0) 256 | { 257 | pitem = pobj->pFirstItem; 258 | if(pitem != bM_NULL) 259 | { 260 | for(i = 0;i < pobj->item_number;i++) 261 | { 262 | if(_bM_GetIdFromHandle(pitem->handle, BM_ID_USER) == id) 263 | { 264 | result->handle = pitem->handle; 265 | result->result.pitem = pitem; 266 | return; 267 | } 268 | pitem = pitem->next; 269 | } 270 | } 271 | } 272 | pobj = pobj->next; 273 | } 274 | } 275 | 276 | static void _bM_FreeAllResource() 277 | { 278 | bM_Object_t *pobj = gp_bM_ManageRoot->next; 279 | bM_Item_t* pitem, *pitem_temp; 280 | 281 | while(pobj != gp_bM_ManageRoot && pobj != bM_NULL) 282 | { 283 | pitem = pobj->pFirstItem; 284 | while(pitem != bM_NULL) 285 | { 286 | pitem_temp = pitem->next; 287 | if(pitem_temp == pitem) 288 | { 289 | g_bM_DMC_Interface.pFree(pitem); 290 | pitem = bM_NULL; 291 | } 292 | else 293 | { 294 | pitem->next = pitem_temp->next; 295 | pitem_temp->next->prev = pitem; 296 | g_bM_DMC_Interface.pFree(pitem_temp); 297 | pitem_temp = bM_NULL; 298 | } 299 | } 300 | pobj->pFirstItem = bM_NULL; 301 | gp_bM_ManageRoot->next = pobj->next; 302 | pobj->next->prev = gp_bM_ManageRoot; 303 | g_bM_DMC_Interface.pFree(pobj); 304 | pobj = gp_bM_ManageRoot->next; 305 | } 306 | } 307 | 308 | /** 309 | * direction : BM_TRUE(next) BM_FALSE(prev) 310 | */ 311 | static bM_Item_t* _bM_FindOutNextItemToShow(bM_Item_t *pCurrentItem, bM_bool_t direction) 312 | { 313 | bM_Item_t *ptemp = bM_NULL; 314 | if (pCurrentItem == bM_NULL) 315 | { 316 | return bM_NULL; 317 | } 318 | ptemp = (direction == BM_TRUE) ? pCurrentItem->next : pCurrentItem->prev; 319 | while (ptemp != pCurrentItem) 320 | { 321 | if (ptemp->visible == BM_TRUE) 322 | { 323 | return ptemp; 324 | } 325 | ptemp = (direction == BM_TRUE) ? ptemp->next : ptemp->prev; 326 | } 327 | return bM_NULL; 328 | } 329 | 330 | static bM_Item_t* _bM_OperationGotoChild(bM_Object_t *pobj) 331 | { 332 | bM_Item_t *pitem = bM_NULL; 333 | if (pobj != bM_NULL) 334 | { 335 | /** child valid */ 336 | pitem = pobj->pFirstItem; 337 | if (pitem != bM_NULL) 338 | { 339 | /** the first item valid */ 340 | if (pitem->visible == BM_FALSE) 341 | { 342 | /** the first item can be shown, so find next */ 343 | pitem = _bM_FindOutNextItemToShow(pitem, BM_TRUE); 344 | } 345 | } 346 | } 347 | return pitem; 348 | } 349 | 350 | /****************************************************************************** 351 | * public functions 352 | ******************************************************************************/ 353 | 354 | /** 355 | * initianize bM module. this function should be called first 356 | */ 357 | bM_Result_t bM_Init(bM_DMC_Interface_t bM_DMC_Interface) 358 | { 359 | bM_Debug("bM version: %s\n\r", bM_VERSION); 360 | if(bM_DMC_Interface.pMalloc == bM_NULL || bM_DMC_Interface.pFree == bM_NULL) 361 | { 362 | return BM_ERROR; 363 | } 364 | g_bM_DMC_Interface.pFree = bM_DMC_Interface.pFree; 365 | g_bM_DMC_Interface.pMalloc = bM_DMC_Interface.pMalloc; 366 | 367 | gp_bM_ManageRoot->next = gp_bM_ManageRoot; 368 | gp_bM_ManageRoot->prev = gp_bM_ManageRoot; 369 | 370 | return BM_SUCCESS; 371 | } 372 | 373 | /** 374 | * create a new object and appoint its parent handle 375 | */ 376 | bM_OBJ_Handle bM_CreateObject(bM_ITEM_Handle hParent, bM_ID id) 377 | { 378 | bM_Object_t *pbM_ObjTmp = bM_NULL; 379 | bM_Item_t *pitem = bM_NULL; 380 | pitem = _bM_GetItemtFromManage(hParent); 381 | pbM_ObjTmp = (bM_Object_t*)g_bM_DMC_Interface.pMalloc(sizeof(bM_Object_t)); 382 | if(pbM_ObjTmp == bM_NULL) 383 | { 384 | return bM_HANDLE_INVALID; 385 | } 386 | pbM_ObjTmp->handle = _bM_CreateHandle(id, ++g_bM_OBJ_Number, 0); 387 | pbM_ObjTmp->pParent = pitem; 388 | pbM_ObjTmp->item_number = 0; 389 | pbM_ObjTmp->pFirstItem = bM_NULL; 390 | if(_bM_AddObjectToManage(pbM_ObjTmp) != BM_SUCCESS) 391 | { 392 | g_bM_DMC_Interface.pFree(pbM_ObjTmp); 393 | return bM_HANDLE_INVALID; 394 | } 395 | 396 | if(pitem != bM_NULL) 397 | { 398 | pitem->child = pbM_ObjTmp; 399 | } 400 | 401 | return pbM_ObjTmp->handle; 402 | } 403 | 404 | 405 | /** 406 | * Add items to bM object 407 | */ 408 | bM_ITEM_Handle bM_AddItemToObject(bM_OBJ_Handle hobj, bM_ID id, bM_CreateUI_t func) 409 | { 410 | bM_Item_t *pitem = bM_NULL; 411 | bM_Object_t *pobj = bM_NULL; 412 | 413 | pobj = _bM_GetObjectFromManage(hobj); 414 | if(pobj == bM_NULL) 415 | { 416 | bM_Debug("error: cant find obj\n\r"); 417 | return bM_HANDLE_INVALID; 418 | } 419 | pitem = (bM_Item_t *)g_bM_DMC_Interface.pMalloc(sizeof(bM_Item_t)); 420 | if(pitem == bM_NULL) 421 | { 422 | bM_Debug("memory error: %s\n\r", __func__); 423 | return bM_HANDLE_INVALID; 424 | } 425 | 426 | pitem->child = bM_NULL; 427 | pitem->create_ui = func; 428 | pitem->visible = BM_TRUE; 429 | pitem->handle = _bM_CreateHandle(id, _bM_GetIdFromHandle(hobj, BM_ID_OBJ), (++g_bM_ItemNumber)); 430 | if(_bM_AddItemToObject(pobj, pitem) != BM_SUCCESS) 431 | { 432 | bM_Debug("error: add item\n\r"); 433 | g_bM_DMC_Interface.pFree(pitem); 434 | return bM_HANDLE_INVALID; 435 | } 436 | return pitem->handle; 437 | } 438 | 439 | 440 | /** 441 | * appoint an object as the entry 442 | */ 443 | bM_Result_t bM_SetMenuEntryPoint(bM_OBJ_Handle hobj) 444 | { 445 | bM_Object_t *pobj_temp = bM_NULL; 446 | if(hobj == bM_HANDLE_INVALID) 447 | { 448 | return BM_ERROR; 449 | } 450 | pobj_temp = _bM_GetObjectFromManage(hobj); 451 | if(pobj_temp == bM_NULL) 452 | { 453 | return BM_ERROR; 454 | } 455 | gp_bM_MenuEntryPoint = pobj_temp; 456 | g_bM_TaskManage.NewMessage.opt = BM_OPERATE_INIT; 457 | g_bM_TaskManage.pCurrentObj = pobj_temp; 458 | g_bM_TaskManage.pCurrentItem = pobj_temp->pFirstItem; 459 | if (pobj_temp->pFirstItem != bM_NULL) 460 | { 461 | pobj_temp->pFirstItem->visible = BM_TRUE; 462 | } 463 | bM_GiveSemaphore(); 464 | return BM_SUCCESS; 465 | } 466 | 467 | /** 468 | * send operation message to bM management 469 | */ 470 | bM_Result_t bM_SendMessage(bM_Operation_t opt, bM_ID id) 471 | { 472 | bM_Message_t msg; 473 | if(opt == BM_OPERATE_INIT || opt == BM_OPERATE_NULL) 474 | { 475 | return BM_ERROR; 476 | } 477 | if(opt == BM_OPERATE_JUMP_TO) 478 | { 479 | _bM_GetOBJorItemById(id, &msg.result); 480 | if(msg.result.handle == bM_HANDLE_INVALID) 481 | { 482 | return BM_ERROR; 483 | } 484 | } 485 | msg.opt = opt; 486 | memcpy((void *)(&g_bM_TaskManage.NewMessage), &msg, sizeof(bM_Message_t)); 487 | return bM_GiveSemaphore(); 488 | } 489 | 490 | /** 491 | * free bM dynamic memory and deinit all global variable 492 | */ 493 | void bM_BMenuModuleEnd(void) 494 | { 495 | _bM_FreeAllResource(); 496 | g_bM_ItemNumber = 0; 497 | g_bM_OBJ_Number = 0; 498 | } 499 | 500 | /** 501 | * bM Main Task 502 | */ 503 | void bM_BMenuModuleTask(void) 504 | { 505 | bM_Item_t *pitem = bM_NULL; 506 | bM_Handle hTemp = bM_HANDLE_INVALID; 507 | if (BM_SUCCESS != bM_TakeSemaphore()) 508 | { 509 | return; 510 | } 511 | switch (g_bM_TaskManage.NewMessage.opt) 512 | { 513 | case BM_OPERATE_INIT: 514 | { 515 | pitem = g_bM_TaskManage.pCurrentItem; 516 | break; 517 | } 518 | case BM_OPERATE_NEXT: 519 | { 520 | pitem = _bM_FindOutNextItemToShow(g_bM_TaskManage.pCurrentItem, BM_TRUE); 521 | if (pitem != bM_NULL) 522 | { 523 | g_bM_TaskManage.pCurrentItem = pitem; 524 | } 525 | break; 526 | } 527 | case BM_OPERATE_PREV: 528 | { 529 | pitem = _bM_FindOutNextItemToShow(g_bM_TaskManage.pCurrentItem, BM_FALSE); 530 | if (pitem != bM_NULL) 531 | { 532 | g_bM_TaskManage.pCurrentItem = pitem; 533 | } 534 | break; 535 | } 536 | case BM_OPERATE_GOTO_CHILD: 537 | { 538 | pitem = _bM_OperationGotoChild(g_bM_TaskManage.pCurrentItem->child); 539 | if (pitem != bM_NULL) 540 | { 541 | g_bM_TaskManage.pCurrentObj = g_bM_TaskManage.pCurrentItem->child; 542 | g_bM_TaskManage.pCurrentItem = pitem; 543 | } 544 | break; 545 | } 546 | case BM_OPERATE_BACK_PARENT: 547 | { 548 | if(g_bM_TaskManage.pCurrentObj->pParent != bM_NULL && g_bM_TaskManage.pCurrentObj != gp_bM_MenuEntryPoint) 549 | { 550 | pitem = g_bM_TaskManage.pCurrentObj->pParent; 551 | g_bM_TaskManage.pCurrentItem = pitem; 552 | g_bM_TaskManage.pCurrentObj = _bM_GetObjectFromManage(pitem->handle); 553 | } 554 | break; 555 | } 556 | case BM_OPERATE_JUMP_TO: 557 | { 558 | hTemp = g_bM_TaskManage.NewMessage.result.handle; 559 | if (hTemp != bM_HANDLE_INVALID) 560 | { 561 | if (_bM_GetIdFromHandle(hTemp, BM_ID_ITEM) == 0x00) 562 | { 563 | pitem = _bM_OperationGotoChild(g_bM_TaskManage.NewMessage.result.result.pobj); 564 | if (pitem == bM_NULL || pitem == g_bM_TaskManage.pCurrentItem) 565 | { 566 | pitem = bM_NULL; 567 | } 568 | else 569 | { 570 | g_bM_TaskManage.pCurrentObj = g_bM_TaskManage.NewMessage.result.result.pobj; 571 | g_bM_TaskManage.pCurrentItem = pitem; 572 | } 573 | } 574 | else 575 | { 576 | pitem = g_bM_TaskManage.NewMessage.result.result.pitem; 577 | if (pitem == g_bM_TaskManage.pCurrentItem || pitem->visible == BM_FALSE) 578 | { 579 | pitem = bM_NULL; 580 | } 581 | else 582 | { 583 | g_bM_TaskManage.pCurrentObj = _bM_GetObjectFromManage(pitem->handle); 584 | g_bM_TaskManage.pCurrentItem = pitem; 585 | } 586 | } 587 | } 588 | } 589 | default: break; 590 | } 591 | g_bM_TaskManage.NewMessage.opt = BM_OPERATE_NULL; 592 | if(pitem != bM_NULL) 593 | { 594 | if (pitem->create_ui != bM_NULL) 595 | { 596 | pitem->create_ui(); 597 | } 598 | } 599 | } 600 | 601 | bM_Result_t bM_ChangeVisibleStatus(bM_ID id, bM_bool_t visible) 602 | { 603 | bM_UserIdResult_t tmp_result; 604 | _bM_GetOBJorItemById(id, &tmp_result); 605 | if(tmp_result.handle == BM_HANDLE_ITEM) 606 | { 607 | bM_Debug("invalid id !\n\r"); 608 | return BM_ERROR; 609 | } 610 | if (_bM_GetIdFromHandle(tmp_result.handle, BM_ID_ITEM) == 0x00) 611 | { 612 | bM_Debug("sorry, cant set for object !\n\r"); 613 | return BM_ERROR; 614 | } 615 | if (gp_bM_MenuEntryPoint->pFirstItem != bM_NULL) 616 | { 617 | if (_bM_GetIdFromHandle(gp_bM_MenuEntryPoint->pFirstItem->handle, BM_ID_USER) == id) 618 | { 619 | bM_Debug("sorry, cant set for entry first item !\n\r"); 620 | return BM_ERROR; 621 | } 622 | } 623 | tmp_result.result.pitem->visible = visible; 624 | return BM_SUCCESS; 625 | } 626 | 627 | 628 | bM_ID bM_GetUseridOfCurrentItem() 629 | { 630 | return _bM_GetIdFromHandle(g_bM_TaskManage.pCurrentItem->handle, BM_ID_USER); 631 | } 632 | 633 | 634 | 635 | /****************************************************************************** 636 | * End ! 637 | ******************************************************************************/ 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | --------------------------------------------------------------------------------