Files
DTU-HMI/src/menu.c

165 lines
4.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "menu.h"
#include <stdio.h>
#include <string.h>
/* 简单的静态菜单树:
*
* 层级 0: [运行界面] [定值设置] [查看数据]
* │ │
* 层级 1: (子菜单...) (子菜单...)
*/
static MenuItem g_menuRun;
static MenuItem g_menuSet;
static MenuItem g_menuSee;
static MenuItem g_menuSet1;
static MenuItem g_menuSet2;
void Menu_InitPC(MenuCtrl *ctrl)
{
memset(&g_menuRun, 0, sizeof(g_menuRun));
memset(&g_menuSet, 0, sizeof(g_menuSet));
memset(&g_menuSee, 0, sizeof(g_menuSee));
memset(&g_menuSet1, 0, sizeof(g_menuSet1));
memset(&g_menuSet2, 0, sizeof(g_menuSet2));
/* 0 级菜单 */
g_menuRun.name = "运行界面";
g_menuRun.tip = "显示运行状态";
g_menuRun.level = 0;
g_menuRun.pos = 0;
g_menuSet.name = "定值设置";
g_menuSet.tip = "进入定值设置菜单";
g_menuSet.level = 0;
g_menuSet.pos = 1;
g_menuSee.name = "查看数据";
g_menuSee.tip = "查看测量值和记录";
g_menuSee.level = 0;
g_menuSee.pos = 2;
/* 0 级链表关系 */
g_menuRun.before = &g_menuSee;
g_menuRun.behind = &g_menuSet;
g_menuSet.before = &g_menuRun;
g_menuSet.behind = &g_menuSee;
g_menuSee.before = &g_menuSet;
g_menuSee.behind = &g_menuRun;
/* 1 级菜单:定值设置下的两个子菜单 */
g_menuSet1.name = "保护定值";
g_menuSet1.tip = "编辑保护定值";
g_menuSet1.level = 1;
g_menuSet1.pos = 0;
g_menuSet1.higher = &g_menuSet;
g_menuSet2.name = "通信参数";
g_menuSet2.tip = "编辑通信参数";
g_menuSet2.level = 1;
g_menuSet2.pos = 1;
g_menuSet2.higher = &g_menuSet;
g_menuSet1.before = &g_menuSet2;
g_menuSet1.behind = &g_menuSet2;
g_menuSet2.before = &g_menuSet1;
g_menuSet2.behind = &g_menuSet1;
g_menuSet.lower = &g_menuSet1;
/* 初始化控制结构 */
ctrl->head0 = &g_menuRun;
ctrl->current = &g_menuRun;
}
/* 控制台绘制当前菜单状态 */
static void Menu_Draw(const MenuCtrl *ctrl)
{
const MenuItem *cur = ctrl->current;
const MenuItem *p;
printf("\n==== PC HMI 菜单模拟 ====\n");
printf("使用 W/S/A/D/Enter/Esc 操作Ctrl+C 退出。\n\n");
/* 显示 0 级菜单 */
printf("[0级菜单]: ");
p = ctrl->head0;
if (!p) {
printf("(空)\n");
return;
}
const MenuItem *start = p;
do {
if (p == cur)
printf(" [*%s*] ", p->name);
else
printf(" %s ", p->name);
p = p->behind;
} while (p && p != start);
printf("\n");
/* 若当前有下级,则显示 1 级菜单 */
if (cur->lower) {
printf(" 子菜单:\n");
p = cur->lower;
start = p;
do {
printf(" - %s\n", p->name);
p = p->behind;
} while (p && p != start);
}
/* 提示信息 */
printf("\n提示: %s\n", cur->tip ? cur->tip : "");
}
void Menu_LoopStep(MenuCtrl *ctrl, int key)
{
MenuItem *cur = ctrl->current;
switch (key) {
case KEY_U:
if (cur->before)
cur = cur->before;
break;
case KEY_D:
if (cur->behind)
cur = cur->behind;
break;
case KEY_L:
if (cur->higher)
cur = cur->higher;
break;
case KEY_R:
case KEY_ENT:
if (cur->lower)
cur = cur->lower;
printf("\n>>> 进入 [%s] 功能(模拟用户层)...\n", cur->name);
break;
case KEY_ESC:
if (cur->higher)
cur = cur->higher;
break;
default:
break;
}
ctrl->current = cur;
Menu_Draw(ctrl);
}
int Menu_MapKey(int ch)
{
if (ch == 'w' || ch == 'W') return KEY_U;
if (ch == 's' || ch == 'S') return KEY_D;
if (ch == 'a' || ch == 'A') return KEY_L;
if (ch == 'd' || ch == 'D') return KEY_R;
if (ch == '\r' || ch == '\n') return KEY_ENT;
if (ch == 27) return KEY_ESC; /* ESC */
return KEY_NONE;
}