Apollo 10.0
自动驾驶开放平台
screen.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <unistd.h>
20
21#include <algorithm>
22#include <cstdio>
23#include <cstring>
24#include <iostream>
25#include <mutex>
26#include <thread>
27#include <utility>
28
32
33#include <ncurses.h> // NOLINT
34
35namespace {
36constexpr double MinHalfFrameRatio = 12.5;
37}
38
40 static Screen s;
41 return &s;
42}
43
44const char Screen::InteractiveCmdStr[] =
45 "Common Commands for all:\n"
46 " q | Q | Esc -- quit\n"
47 " Backspace -- go back\n"
48 " h | H -- go to show help info\n"
49 "\n"
50 "Common Commands for Topology and Channel Message:\n"
51 " PgDn | ^d -- show next page\n"
52 " PgUp | ^u -- show previous page\n"
53 "\n"
54 " Up Arrow -- move up one line\n"
55 " Down Arrow -- move down one line\n"
56 " Right Arrow -- enter the selected Channel or Repeated Datum\n"
57 " Left Arrow -- go back to the upper level\n"
58 "\n"
59 " Enter -- the same with Right Arrow key\n"
60 " a | A -- the same with Left Arrow key\n"
61 " d | D -- the same with Right Arrow key\n"
62 " w | W -- the same with Up Arrow key\n"
63 " s | S -- the same with Down Arrow key\n"
64 "\n"
65 "Commands for Topology message:\n"
66 " f | F -- show frame ratio for all channel messages\n"
67 " t | T -- show channel message type\n"
68 "\n"
69 " Space -- Enable|Disable channel Message\n"
70 "\n"
71 "Commands for Channel:\n"
72 " i | I -- show Reader and Writers of Channel\n"
73 " b | B -- show Debug String of Channel Message\n"
74 "\n"
75 "Commands for Channel Repeated Datum:\n"
76 " n | N -- next repeated data item\n"
77 " m | M -- previous repeated data item\n"
78 " , -- enable|disable to show all repeated items\n";
79
80Screen::Screen()
81 : current_color_pair_(INVALID),
82 canRun_(false),
83 current_state_(State::RenderMessage),
84 highlight_direction_(0),
85 current_render_obj_(nullptr) {}
86
88 current_render_obj_ = nullptr;
89 endwin();
90}
91
92inline bool Screen::IsInit(void) const { return (stdscr != nullptr); }
93
94void Screen::Init(void) {
95 initscr();
96 if (stdscr == nullptr) {
97 return;
98 }
99 nodelay(stdscr, true);
100 keypad(stdscr, true);
101 meta(stdscr, true);
102 curs_set(0);
103 noecho();
104
105 bkgd(COLOR_BLACK);
106
107 start_color();
108 init_pair(GREEN_BLACK, COLOR_GREEN, COLOR_BLACK);
109 init_pair(YELLOW_BLACK, COLOR_YELLOW, COLOR_BLACK);
110 init_pair(RED_BLACK, COLOR_RED, COLOR_BLACK);
111 init_pair(WHITE_BLACK, COLOR_WHITE, COLOR_BLACK);
112 init_pair(BLACK_WHITE, COLOR_BLACK, COLOR_WHITE);
113
114 refresh();
115 clear();
116
117 canRun_ = true;
118}
119
120int Screen::Width(void) const { return COLS; }
121
122int Screen::Height(void) const { return LINES; }
123
125 if (color == INVALID) {
126 return;
127 }
128 if (IsInit()) {
129 current_color_pair_ = color;
130 attron(COLOR_PAIR(color));
131 }
132}
133void Screen::AddStr(int x, int y, const char* str) const {
134 if (IsInit()) {
135 mvaddstr(y, x, str);
136 }
137}
138
139void Screen::AddStr(const char* str) const {
140 if (IsInit()) {
141 addstr(str);
142 }
143}
144
146 if (IsInit()) {
147 attroff(COLOR_PAIR(current_color_pair_));
148 current_color_pair_ = INVALID;
149 }
150}
151
152void Screen::AddStr(int x, int y, ColorPair color, const char* str) const {
153 if (IsInit()) {
154 attron(COLOR_PAIR(color));
155 mvaddstr(y, x, str);
156 attroff(COLOR_PAIR(color));
157 }
158}
159
160void Screen::MoveOffsetXY(int offsetX, int offsetY) const {
161 if (IsInit()) {
162 int x, y;
163 getyx(stdscr, y, x);
164 move(y + offsetY, x + offsetX);
165 }
166}
167
168void Screen::HighlightLine(int line_no) {
169 if (IsInit() && line_no < Height()) {
171 for (int x = 0; x < Width(); ++x) {
172 chtype ch = mvinch(line_no + highlight_direction_, x);
173 ch &= A_CHARTEXT;
174 if (ch == ' ') {
175 mvaddch(line_no + highlight_direction_, x, ch);
176 }
177 }
179
181 for (int x = 0; x < Width(); ++x) {
182 chtype ch = mvinch(line_no, x);
183 mvaddch(line_no, x, ch & A_CHARTEXT);
184 }
186 }
187}
188
189int Screen::SwitchState(int ch) {
190 switch (current_state_) {
191 case State::RenderInterCmdInfo:
192 if (KEY_BACKSPACE == ch) {
193 current_state_ = State::RenderMessage;
194 clear();
195 ch = 27;
196 }
197 break;
198 case State::RenderMessage:
199 if ('h' == ch || 'H' == ch) {
200 current_state_ = State::RenderInterCmdInfo;
201 clear();
202 }
203 break;
204 default: {
205 }
206 }
207 return ch;
208}
209
211 if (stdscr == nullptr || current_render_obj_ == nullptr) {
212 return;
213 }
214
215 highlight_direction_ = 0;
216
217 void (Screen::*showFuncs[])(int) = {&Screen::ShowRenderMessage,
218 &Screen::ShowInteractiveCmd};
219
220 do {
221 int ch = getch();
222
223 if (ch == 'q' || ch == 'Q' || ch == 27) {
224 canRun_ = false;
225 break;
226 }
227
228 ch = SwitchState(ch);
229
230 (this->*showFuncs[static_cast<int>(current_state_)])(ch);
231
232 double fr = current_render_obj_->frame_ratio();
233 if (fr < MinHalfFrameRatio) {
234 fr = MinHalfFrameRatio;
235 }
236 int period = static_cast<int>(1000.0 / fr);
237 period >>= 1;
238 std::this_thread::sleep_for(std::chrono::milliseconds(period));
239 } while (canRun_);
240}
241
242void Screen::Resize(void) {
243 if (IsInit()) {
244 clear();
245 refresh();
246 }
247}
248
249void Screen::ShowRenderMessage(int ch) {
250 erase();
251 int line_num = current_render_obj_->Render(this, ch);
252 const int max_height = std::min(Height(), line_num);
253
254 int* y = current_render_obj_->line_no();
255
256 HighlightLine(*y);
257 move(*y, 0);
258 refresh();
259
260 switch (ch) {
261 case 's':
262 case 'S':
263 case KEY_DOWN:
264 ++(*y);
265 highlight_direction_ = -1;
266 if (*y >= max_height) {
267 *y = max_height - 1;
268 }
269 break;
270
271 case 'w':
272 case 'W':
273 case KEY_UP:
274 --(*y);
275 if (*y < 1) {
276 *y = 1;
277 }
278 highlight_direction_ = 1;
279 if (*y < 0) {
280 *y = 0;
281 }
282 break;
283
284 case 'a':
285 case 'A':
286 case KEY_BACKSPACE:
287 case KEY_LEFT: {
288 RenderableMessage* p = current_render_obj_->parent();
289 if (p) {
290 current_render_obj_ = p;
291 y = p->line_no();
292 clear();
293 }
294 break;
295 }
296
297 case '\n':
298 case '\r':
299 case 'd':
300 case 'D':
301 case KEY_RIGHT: {
302 RenderableMessage* child = current_render_obj_->Child(*y);
303
304 if (child) {
305 child->reset_line_page();
306 current_render_obj_ = child;
307 y = child->line_no();
308 clear();
309 }
310 break;
311 }
312 }
313}
314
315void Screen::ShowInteractiveCmd(int) {
316 unsigned y = 0;
317
319 AddStr((Width() - 19) / 2, y++, "Interactive Command");
320
321 const char* ptr = InteractiveCmdStr;
322 while (*ptr != '\0') {
323 const char* sub = std::strchr(ptr, '\n');
324 std::string subStr(ptr, sub);
325 AddStr(0, y++, subStr.c_str());
326 ptr = sub + 1;
327 }
328
330}
virtual int Render(const Screen *s, int key)=0
RenderableMessage * parent(void) const
virtual double frame_ratio(void)
virtual RenderableMessage * Child(int) const =0
void MoveOffsetXY(int offsetX, int offsetY) const
Definition screen.cc:160
void AddStr(int x, int y, ColorPair color, const char *str) const
Definition screen.cc:152
void Init(void)
Definition screen.cc:94
void Run(void)
Definition screen.cc:210
int Height(void) const
Definition screen.cc:122
int Width(void) const
Definition screen.cc:120
void Resize()
Definition screen.cc:242
static const char InteractiveCmdStr[]
Definition screen.h:32
void SetCurrentColor(ColorPair color) const
Definition screen.cc:124
void ClearCurrentColor(void) const
Definition screen.cc:145
~Screen(void)
Definition screen.cc:87
static Screen * Instance(void)
Definition screen.cc:39
ColorPair
Definition screen.h:34
@ BLACK_WHITE
Definition screen.h:40
@ INVALID
Definition screen.h:35
@ WHITE_BLACK
Definition screen.h:39
@ GREEN_BLACK
Definition screen.h:36
@ YELLOW_BLACK
Definition screen.h:37
@ RED_BLACK
Definition screen.h:38