├── 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 |
--------------------------------------------------------------------------------