sources/interface.cpp

changeset 27
089e37c0887e
parent 25
88b41eea08e0
child 28
3cc042af3090
equal deleted inserted replaced
26:24c7b804c99f 27:089e37c0887e
48 static int g_pan = 0; 48 static int g_pan = 0;
49 static bool g_needRefresh = false; 49 static bool g_needRefresh = false;
50 static bool g_needStatusBarRender = false; 50 static bool g_needStatusBarRender = false;
51 static bool g_needInputRender = false; 51 static bool g_needInputRender = false;
52 static bool g_needOutputRender = false; 52 static bool g_needOutputRender = false;
53 static String g_statusBarText;
54 static struct { char ch; int x; } g_cursorChar; 53 static struct { char ch; int x; } g_cursorChar;
55 static Vector<String> g_output = {""}; 54 static Vector<String> g_output = {""};
56 static int g_outputScroll = 0; 55 static int g_outputScroll = 0;
57 static String g_title; 56 static String g_title;
58 static InputState g_inputState = INPUTSTATE_NORMAL; 57 static InputState g_inputState = INPUTSTATE_NORMAL;
58 static Function<void (void)> g_disconnectConfirmFunction = nullptr;
59 static IPAddress g_address; 59 static IPAddress g_address;
60 static String g_statusBarText;
60 61
61 // ------------------------------------------------------------------------------------------------- 62 // -------------------------------------------------------------------------------------------------
62 // 63 //
63 static FUNCTION 64 static FUNCTION
64 interface_color_pair (Color fg, Color bg) -> int 65 interface_color_pair (Color fg, Color bg) -> int
80 case INPUTSTATE_PASSWORD: prompt = "password:"; break; 81 case INPUTSTATE_PASSWORD: prompt = "password:"; break;
81 case INPUTSTATE_CONFIRM_DISCONNECTION: break; 82 case INPUTSTATE_CONFIRM_DISCONNECTION: break;
82 } 83 }
83 84
84 return prompt; 85 return prompt;
86 }
87
88 // -------------------------------------------------------------------------------------------------
89 //
90 static FUNCTION
91 set_input_state (InputState newstate) -> void
92 {
93 // Clear the input row (unless going to or from confirm state)
94 if (newstate != INPUTSTATE_CONFIRM_DISCONNECTION
95 and g_inputState != INPUTSTATE_CONFIRM_DISCONNECTION)
96 {
97 g_input.clear();
98 }
99
100 switch (newstate)
101 {
102 case INPUTSTATE_ADDRESS:
103 if (g_address.host != 0)
104 g_input = g_address.to_string (IP_WITH_PORT);
105 break;
106
107 default:
108 break;
109 }
110
111 g_inputState = newstate;
112 g_needInputRender = true;
85 } 113 }
86 114
87 // ------------------------------------------------------------------------------------------------- 115 // -------------------------------------------------------------------------------------------------
88 // 116 //
89 FUNCTION 117 FUNCTION
109 render_full(); 137 render_full();
110 refresh(); 138 refresh();
111 g_needRefresh = false; 139 g_needRefresh = false;
112 print ("Interface initialized.\n"); 140 print ("Interface initialized.\n");
113 } 141 }
114 // -------------------------------------------------------------------------------------------------
115 //
116 static FUNCTION
117 interface_sessions_width() -> int
118 {
119 return COLS / 3;
120 }
121 142
122 // ------------------------------------------------------------------------------------------------- 143 // -------------------------------------------------------------------------------------------------
123 // 144 //
124 static FUNCTION 145 static FUNCTION
125 interface_render_titlebar() -> void 146 interface_render_titlebar() -> void
149 } 170 }
150 171
151 // ------------------------------------------------------------------------------------------------- 172 // -------------------------------------------------------------------------------------------------
152 // 173 //
153 static FUNCTION 174 static FUNCTION
175 safe_disconnect (Function<void()> afterwards) -> void
176 {
177 if (RCONSession::get_session() != nullptr
178 and RCONSession::get_session()->state() != RCON_DISCONNECTED)
179 {
180 g_disconnectConfirmFunction = afterwards;
181 set_input_state (INPUTSTATE_CONFIRM_DISCONNECTION);
182 }
183 else
184 afterwards();
185 }
186
187 // -------------------------------------------------------------------------------------------------
188 //
189 static FUNCTION
154 interface_render_output() -> void 190 interface_render_output() -> void
155 { 191 {
156 int height = LINES - 3; 192 int height = LINES - 3;
157 193
158 // ensure we're within bounds 194 // ensure we're within bounds
231 // ------------------------------------------------------------------------------------------------- 267 // -------------------------------------------------------------------------------------------------
232 // 268 //
233 static FUNCTION 269 static FUNCTION
234 interface_render_statusbar() -> void 270 interface_render_statusbar() -> void
235 { 271 {
272 int color = interface_color_pair (WHITE, BLUE);
236 int y = LINES - 1; 273 int y = LINES - 1;
274 attron (color);
237 mvhline (y, 0, ' ', COLS); 275 mvhline (y, 0, ' ', COLS);
238 mvprintw (y, 0, "%s", g_statusBarText.chars()); 276 mvprintw (y, 0, "%s", g_statusBarText.chars());
277 attroff (color);
239 g_needRefresh = true; 278 g_needRefresh = true;
240 g_needStatusBarRender = false; 279 g_needStatusBarRender = false;
241 } 280 }
242 281
243 // ------------------------------------------------------------------------------------------------- 282 // -------------------------------------------------------------------------------------------------
244 // 283 //
245 static FUNCTION 284 FUNCTION
246 set_statusbar_text (const String& a) -> void 285 Interface::update_statusbar() -> void
247 { 286 {
248 g_statusBarText = a; 287 String text;
249 g_needStatusBarRender = true; 288 RCONSession* session = RCONSession::get_session();
289
290 if (session == nullptr)
291 {
292 text = "[DISCONNECTED]";
293 }
294 else
295 {
296 switch (session->state())
297 {
298 case RCON_DISCONNECTED:
299 text = "[DISCONNECTED]";
300 break;
301
302 case RCON_CONNECTING:
303 case RCON_AUTHENTICATING:
304 text = "Connecting to " + session->address().to_string (IP_WITH_PORT) + "...";
305 break;
306
307 case RCON_CONNECTED:
308 {
309 String adminText;
310
311 if (session->num_admins() == 0)
312 adminText = "No other admins";
313 else
314 adminText = format ("%1 other admin%s1", session->num_admins());
315
316 text = format ("%1 | %2 | %3", session->address().to_string (IP_WITH_PORT),
317 session->level(), adminText);
318 }
319 break;
320 }
321 }
322
323 if (text != g_statusBarText)
324 {
325 g_statusBarText = text;
326 g_needStatusBarRender = true;
327 }
250 } 328 }
251 329
252 // ------------------------------------------------------------------------------------------------- 330 // -------------------------------------------------------------------------------------------------
253 // 331 //
254 FUNCTION 332 FUNCTION
255 Interface::render_full() -> void 333 Interface::render_full() -> void
256 { 334 {
335 update_statusbar();
257 interface_render_titlebar(); 336 interface_render_titlebar();
258 interface_render_output(); 337 interface_render_output();
259 interface_render_statusbar(); 338 interface_render_statusbar();
260 interface_render_input(); 339 interface_render_input();
261 } 340 }
277 mvprintw (y, interface_prompt_string().length(), " "); 356 mvprintw (y, interface_prompt_string().length(), " ");
278 } 357 }
279 358
280 // ------------------------------------------------------------------------------------------------- 359 // -------------------------------------------------------------------------------------------------
281 // 360 //
282 static FUNCTION
283 set_input_state (InputState newstate) -> void
284 {
285 // Clear the input row (unless going to or from confirm state)
286 if (newstate != INPUTSTATE_CONFIRM_DISCONNECTION
287 and g_inputState != INPUTSTATE_CONFIRM_DISCONNECTION)
288 {
289 g_input.clear();
290 }
291
292 switch (newstate)
293 {
294 case INPUTSTATE_ADDRESS:
295 if (g_address.host != 0)
296 g_input = g_address.to_string (IP_WITH_PORT);
297 break;
298
299 default:
300 break;
301 }
302
303 g_inputState = newstate;
304 g_needInputRender = true;
305 }
306
307 // -------------------------------------------------------------------------------------------------
308 //
309 FUNCTION 361 FUNCTION
310 Interface::handle_input() -> void 362 Interface::handle_input() -> void
311 { 363 {
312 int ch = ::getch(); 364 int ch = ::getch();
313 set_statusbar_text (String::from_number (ch));
314 365
315 if (g_inputState == INPUTSTATE_CONFIRM_DISCONNECTION) 366 if (g_inputState == INPUTSTATE_CONFIRM_DISCONNECTION)
316 { 367 {
317 if (ch == 'y' or ch == 'Y') 368 if (ch == 'y' or ch == 'Y')
318 set_input_state (INPUTSTATE_ADDRESS); 369 g_disconnectConfirmFunction();
319 else if (ch == 'n' or ch == 'N') 370 else if (ch == 'n' or ch == 'N')
320 set_input_state (INPUTSTATE_NORMAL); 371 set_input_state (INPUTSTATE_NORMAL);
321 return; 372 return;
322 } 373 }
323 374
326 g_input.insert (g_cursor++, char (ch)); 377 g_input.insert (g_cursor++, char (ch));
327 g_needInputRender = true; 378 g_needInputRender = true;
328 } 379 }
329 else switch (ch) 380 else switch (ch)
330 { 381 {
331 case KEY_F(1): 382 case 'Q' - 'A' + 1: // ^Q
332 endwin(); 383 switch (g_inputState)
333 exit (EXIT_SUCCESS); 384 {
385 case INPUTSTATE_CONFIRM_DISCONNECTION:
386 break;
387
388 case INPUTSTATE_NORMAL:
389 safe_disconnect ([]()
390 {
391 endwin();
392 throw Exitception();
393 });
394 break;
395
396 case INPUTSTATE_PASSWORD:
397 set_input_state (INPUTSTATE_ADDRESS);
398 break;
399
400 case INPUTSTATE_ADDRESS:
401 set_input_state (INPUTSTATE_NORMAL);
402 }
403 break;
404
405 case '\e':
406 if (g_inputState == INPUTSTATE_PASSWORD)
407 set_input_state (INPUTSTATE_ADDRESS);
408 else if (g_inputState == INPUTSTATE_ADDRESS)
409 set_input_state (INPUTSTATE_NORMAL);
334 break; 410 break;
335 411
336 case KEY_LEFT: 412 case KEY_LEFT:
337 if (g_cursor > 0) 413 if (g_cursor > 0)
338 { 414 {
436 } 512 }
437 break; 513 break;
438 514
439 case 'N' - 'A' + 1: // ^N 515 case 'N' - 'A' + 1: // ^N
440 if (g_inputState == INPUTSTATE_NORMAL) 516 if (g_inputState == INPUTSTATE_NORMAL)
441 { 517 safe_disconnect ([]() {set_input_state (INPUTSTATE_ADDRESS);});
442 if (RCONSession::get_session() != nullptr
443 and RCONSession::get_session()->state() != RCON_DISCONNECTED)
444 {
445 set_input_state (INPUTSTATE_CONFIRM_DISCONNECTION);
446 }
447 else
448 {
449 set_input_state (INPUTSTATE_ADDRESS);
450 }
451 }
452 break; 518 break;
453 } 519 }
454 } 520 }
455 521
456 // ------------------------------------------------------------------------------------------------- 522 // -------------------------------------------------------------------------------------------------

mercurial