-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUIHelper.cpp
More file actions
310 lines (260 loc) · 9.07 KB
/
Copy pathUIHelper.cpp
File metadata and controls
310 lines (260 loc) · 9.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
#include "UIHelper.h"
#include "SDF.h"
#include "TimeZone.h"
using namespace std;
//绘制添加按钮(右上角)
void UIHelper::draw_add_button(int x, int y, int radius, bool is_hovered)
{
//圆圈颜色(悬停时稍微变亮)
COLORREF circle_color = is_hovered ? RGB(80, 80, 80) : RGB(60, 60, 60);
SDF::draw_aa_circle(x, y, radius, circle_color);
//"+"号(浅灰色)
int line_len = radius - 6;
COLORREF plus_color = RGB(234, 234, 234);
SDF::draw_aa_line(x - line_len, y, x + line_len, y, 2, plus_color); //横线
SDF::draw_aa_line(x, y - line_len, x, y + line_len, 2, plus_color); //竖线
}
//检查鼠标是否在添加按钮上
bool UIHelper::is_mouse_on_add_button(int mouse_x, int mouse_y, int btn_x, int btn_y, int radius)
{
int dx = mouse_x - btn_x;
int dy = mouse_y - btn_y;
return (dx * dx + dy * dy <= radius * radius);
}
//绘制关闭按钮(缩小叉号)
void UIHelper::draw_close_button(int x, int y, int radius, bool is_hovered)
{
//红色圆圈(悬停时稍微变亮)
COLORREF circle_color = is_hovered ? RGB(246, 113, 111) : RGB(236, 103, 101);
SDF::draw_aa_circle(x, y, radius, circle_color);
//叉叉
int cross_size = radius / 2;
COLORREF cross_color = RGB(150, 50, 50);
SDF::draw_aa_line(x - cross_size, y - cross_size, x + cross_size, y + cross_size, 2, cross_color);
SDF::draw_aa_line(x - cross_size, y + cross_size, x + cross_size, y - cross_size, 2, cross_color);
}
//检查鼠标是否在关闭按钮上
bool UIHelper::is_mouse_on_close_button(int mouse_x, int mouse_y, int btn_x, int btn_y, int radius)
{
int dx = mouse_x - btn_x;
int dy = mouse_y - btn_y;
return (dx * dx + dy * dy <= radius * radius);
}
//检查鼠标在哪个标签上
int UIHelper::check_tab_hover(int mouse_x, int mouse_y, const NavigationBar& nav_bar)
{
//检查鼠标是否在跑道栏范围内
if (mouse_y < nav_bar.bar_y || mouse_y > nav_bar.bar_y + nav_bar.bar_height)
{
return -1; //不在跑道栏内
}
//计算每个标签的宽度(平分)
int tab_width = nav_bar.bar_width / 4;
for (int i = 0; i < 4; i++)
{
int tab_x = nav_bar.bar_x + i * tab_width;
if (mouse_x >= tab_x && mouse_x <= tab_x + tab_width)
{
return i; //返回标签索引
}
}
return -1;
}
//绘制顶部导航栏
void UIHelper::draw_navigation_bar(const NavigationBar& nav_bar)
{
//绘制导航栏背景(深灰色)
setfillcolor(RGB(30, 30, 30));
solidrectangle(0, 0, 520, 44); //高度44px(1.1cm)
//计算每个标签的宽度
int tab_width = nav_bar.bar_width / 4; //272 / 4 = 68px
int gap = 3; //与边框的缝隙(3像素)
//绘制跑道形状的背景栏
setfillcolor(RGB(27, 27, 27));
solidroundrect(nav_bar.bar_x, nav_bar.bar_y,
nav_bar.bar_x + nav_bar.bar_width,
nav_bar.bar_y + nav_bar.bar_height,
nav_bar.bar_height, nav_bar.bar_height); //圆角半径=高度(形成跑道形状)
//绘制跑道边框(1px,浅灰色)
setlinecolor(RGB(56, 56, 56));
setlinestyle(PS_SOLID, 1);
roundrect(nav_bar.bar_x, nav_bar.bar_y,
nav_bar.bar_x + nav_bar.bar_width,
nav_bar.bar_y + nav_bar.bar_height,
nav_bar.bar_height, nav_bar.bar_height);
//先判断哪些标签需要高亮
bool should_draw[4] = {false, false, false, false};
COLORREF bg_colors[4];
for (int i = 0; i < 4; i++)
{
if (i == nav_bar.current_tab)
{
//当前选中的标签
if (nav_bar.has_hover && i == nav_bar.hovered_tab)
{
bg_colors[i] = RGB(82, 82, 82); //选中+悬停:进一步高亮
}
else
{
bg_colors[i] = RGB(55, 55, 55); //仅选中
}
should_draw[i] = true;
}
else
{
//未选中的标签
if (nav_bar.has_hover && i == nav_bar.hovered_tab)
{
bg_colors[i] = RGB(49, 49, 49); //悬停
should_draw[i] = true;
}
}
}
//绘制每个标签的背景高亮(选中/悬停效果)
for (int i = 0; i < 4; i++)
{
if (!should_draw[i])
{
continue; //跳过不需要绘制的标签
}
int tab_x = nav_bar.bar_x + i * tab_width;
setfillcolor(bg_colors[i]);
//计算留出缝隙后的坐标
int inner_y1 = nav_bar.bar_y + gap;
int inner_y2 = nav_bar.bar_y + nav_bar.bar_height - gap;
int inner_height = inner_y2 - inner_y1;
//判断左右是否有相邻的高亮标签
bool has_left_neighbor = (i > 0) && should_draw[i - 1]; //左边有高亮
bool has_right_neighbor = (i < 3) && should_draw[i + 1]; //右边有高亮
//根据不同情况计算左右边界
int inner_x1, inner_x2;
if (i == 0)
{
//第一个标签左边留隙
inner_x1 = tab_x + gap;
//右边:如果右边有高亮,留出1.5px缝隙;否则不留
inner_x2 = has_right_neighbor ? (tab_x + tab_width - gap / 2) : (tab_x + tab_width);
}
else if (i == 3)
{
//最后一个标签右边留隙
//左边:如果左边有高亮,留出1.5px缝隙;否则不留
inner_x1 = has_left_neighbor ? (tab_x + gap / 2) : tab_x;
inner_x2 = tab_x + tab_width - gap;
}
else
{
//中间标签:根据左右邻居情况留隙
inner_x1 = has_left_neighbor ? (tab_x + gap / 2) : tab_x;
inner_x2 = has_right_neighbor ? (tab_x + tab_width - gap / 2) : (tab_x + tab_width);
}
//绘制跑道形状的高亮背景
solidroundrect(inner_x1, inner_y1, inner_x2, inner_y2,
inner_height, inner_height); //圆角半径=高度
}
//绘制标签文字
settextcolor(WHITE);
settextstyle(16, 0, L"微软雅黑");
setbkmode(TRANSPARENT);
for (int i = 0; i < 4; i++)
{
int tab_x = nav_bar.bar_x + i * tab_width;
int text_width = textwidth(nav_bar.tab_names[i].c_str());
int text_x = tab_x + (tab_width - text_width) / 2;
int text_y = nav_bar.bar_y + (nav_bar.bar_height - 16) / 2; //垂直居中
outtextxy(text_x, text_y, nav_bar.tab_names[i].c_str());
}
}
CityMenu::CityMenu()
{
menu_width = 200;
item_height = 35;
hovered_index = -1;
//获取城市列表
int count = 0;
TimeZoneInfo* all_zones = TimeZone::get_all_timezones(count);
city_count = count;
city_list = new wstring[city_count];
for (int i = 0; i < city_count; i++)
{
city_list[i] = all_zones[i].city_name;
}
menu_height = city_count * item_height;
}
CityMenu::~CityMenu()
{
delete[] city_list;
}
void CityMenu::show(int x, int y)
{
menu_x = x;
menu_y = y;
//确保菜单不超出屏幕
if (menu_x + menu_width > 520)
{
menu_x = 520 - menu_width;
}
if (menu_y + menu_height > 680)
{
menu_y = 680 - menu_height;
}
}
void CityMenu::draw()
{
//绘制菜单背景
setfillcolor(RGB(60, 60, 60));
solidroundrect(menu_x, menu_y, menu_x + menu_width, menu_y + menu_height, 5, 5);
//绘制边框
setlinecolor(RGB(100, 100, 100));
roundrect(menu_x, menu_y, menu_x + menu_width, menu_y + menu_height, 5, 5);
//绘制每个城市
for (int i = 0; i < city_count; i++)
{
int item_y = menu_y + i * item_height;
//悬停高亮
if (i == hovered_index)
{
setfillcolor(RGB(80, 80, 80));
solidrectangle(menu_x + 2, item_y + 2, menu_x + menu_width - 2, item_y + item_height - 2);
}
//绘制城市名称
settextcolor(WHITE);
settextstyle(16, 0, L"微软雅黑");
setbkmode(TRANSPARENT);
outtextxy(menu_x + 15, item_y + 8, city_list[i].c_str());
}
}
void CityMenu::update_hover(int mouse_x, int mouse_y)
{
hovered_index = -1;
if (mouse_x < menu_x || mouse_x > menu_x + menu_width || mouse_y < menu_y || mouse_y > menu_y + menu_height)
{
return; //鼠标不在菜单内
}
//算鼠标在哪个选项上
int relative_y = mouse_y - menu_y;
hovered_index = relative_y / item_height;
if (hovered_index >= city_count)
{
hovered_index = -1;
}
}
int CityMenu::check_click(int mouse_x, int mouse_y)
{
if (mouse_x < menu_x || mouse_x > menu_x + menu_width || mouse_y < menu_y || mouse_y > menu_y + menu_height)
{
return -1; //点击在菜单外
}
int relative_y = mouse_y - menu_y;
int index = relative_y / item_height;
if (index >= 0 && index < city_count)
{
return index;
}
return -1;
}
bool CityMenu::is_outside_click(int mouse_x, int mouse_y)
{
return (mouse_x < menu_x || mouse_x > menu_x + menu_width ||
mouse_y < menu_y || mouse_y > menu_y + menu_height);
}