dlgTextEntry_Keyboard: rename to TouchTextEntry
[xcsoar.git] / src / Input / InputEventsActions.cpp
blob5af06a0a32de7ff68cce0567cc4de8f85fe59f79
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 InputEvents
28 This class is used to control all user and external InputEvents.
29 This includes some Nmea strings, virtual events (Glide Computer
30 Evnets) and Keyboard.
32 What it does not cover is Glide Computer normal processing - this
33 includes GPS and Vario processing.
35 What it does include is what to do when an automatic event (switch
36 to Climb mode) and user events are entered.
38 It also covers the configuration side of on screen labels.
40 For further information on config file formats see
42 source/Common/Data/Input/ALL
43 doc/html/advanced/input/ALL http://xcsoar.sourceforge.net/advanced/input/
47 #include "InputEvents.hpp"
48 #include "Protection.hpp"
49 #include "LogFile.hpp"
50 #include "Device/Parser.hpp"
51 #include "UIState.hpp"
52 #include "Computer/Settings.hpp"
53 #include "MapSettings.hpp"
54 #include "Math/FastMath.h"
55 #include "Dialogs/Dialogs.h"
56 #include "Dialogs/Device/Vega/VoiceSettingsDialog.hpp"
57 #include "Dialogs/Device/Vega/SwitchesDialog.hpp"
58 #include "Dialogs/Airspace/Airspace.hpp"
59 #include "Dialogs/Task/TaskDialogs.hpp"
60 #include "Dialogs/Traffic/TrafficDialogs.hpp"
61 #include "Dialogs/Waypoint/WaypointDialogs.hpp"
62 #include "Dialogs/Weather/WeatherDialogs.hpp"
63 #include "Dialogs/Plane/PlaneDialogs.hpp"
64 #include "Dialogs/Message.hpp"
65 #include "Dialogs/dlgAnalysis.hpp"
66 #include "Dialogs/FileManager.hpp"
67 #include "Dialogs/ReplayDialog.hpp"
68 #include "Message.hpp"
69 #include "Markers/ProtectedMarkers.hpp"
70 #include "InfoBoxes/InfoBoxLayout.hpp"
71 #include "MainWindow.hpp"
72 #include "Projection/MapWindowProjection.hpp"
73 #include "Gauge/GaugeFLARM.hpp"
74 #include "Profile/Profile.hpp"
75 #include "Profile/ProfileKeys.hpp"
76 #include "Util/StringUtil.hpp"
77 #include "Audio/Sound.hpp"
78 #include "UIActions.hpp"
79 #include "Interface.hpp"
80 #include "ActionInterface.hpp"
81 #include "Components.hpp"
82 #include "Language/Language.hpp"
83 #include "Logger/Logger.hpp"
84 #include "Asset.hpp"
85 #include "Logger/NMEALogger.hpp"
86 #include "Waypoint/Waypoints.hpp"
87 #include "Task/ProtectedTaskManager.hpp"
88 #include "Blackboard/DeviceBlackboard.hpp"
89 #include "UtilsSettings.hpp"
90 #include "PageActions.hpp"
91 #include "Hardware/AltairControl.hpp"
92 #include "NMEA/Aircraft.hpp"
93 #include "Compiler.h"
94 #include "Weather/Features.hpp"
95 #include "MapWindow/GlueMapWindow.hpp"
96 #include "Simulator.hpp"
98 #include <assert.h>
99 #include <ctype.h>
100 #include <tchar.h>
101 #include <algorithm>
103 static void
104 trigger_redraw()
106 if (!CommonInterface::Basic().location_available)
107 ForceCalculation();
108 TriggerMapUpdate();
111 // -----------------------------------------------------------------------
112 // Execution - list of things you can do
113 // -----------------------------------------------------------------------
116 // TODO code: Keep marker text for use in log file etc.
117 void
118 InputEvents::eventMarkLocation(const TCHAR *misc)
120 const NMEAInfo &basic = CommonInterface::Basic();
122 if (StringIsEqual(misc, _T("reset"))) {
123 protected_marks->Reset();
124 } else {
125 protected_marks->MarkLocation(basic.location, basic.date_time_utc);
127 if (CommonInterface::GetUISettings().sound.sound_modes_enabled)
128 PlayResource(_T("IDR_WAV_CLEAR"));
131 trigger_redraw();
134 void
135 InputEvents::eventScreenModes(const TCHAR *misc)
137 // toggle switches like this:
138 // -- normal infobox
139 // -- auxiliary infobox
140 // -- full screen
141 // -- normal infobox
143 const UIState &ui_state = CommonInterface::GetUIState();
145 if (StringIsEqual(misc, _T("normal"))) {
146 PageActions::OpenLayout(PageLayout::Default());
147 } else if (StringIsEqual(misc, _T("auxilary"))) {
148 PageActions::OpenLayout(PageLayout::Aux());
149 } else if (StringIsEqual(misc, _T("toggleauxiliary"))) {
150 PageActions::OpenLayout(ui_state.auxiliary_enabled
151 ? PageLayout::Default()
152 : PageLayout::Aux());
153 } else if (StringIsEqual(misc, _T("full"))) {
154 PageActions::OpenLayout(PageLayout::FullScreen());
155 } else if (StringIsEqual(misc, _T("togglefull"))) {
156 CommonInterface::main_window->SetFullScreen(
157 !CommonInterface::main_window->GetFullScreen());
158 } else if (StringIsEqual(misc, _T("show"))) {
159 if (CommonInterface::main_window->GetFullScreen())
160 Message::AddMessage(_("Screen Mode Full"));
161 else if (ui_state.auxiliary_enabled)
162 Message::AddMessage(_("Auxiliary InfoBoxes"));
163 else
164 Message::AddMessage(_("Default InfoBoxes"));
165 } else if (StringIsEqual(misc, _T("previous")))
166 PageActions::Prev();
167 else
168 PageActions::Next();
171 trigger_redraw();
174 // ClearStatusMessages
175 // Do Clear Event Warnings
176 void
177 InputEvents::eventClearStatusMessages(gcc_unused const TCHAR *misc)
179 // TODO enhancement: allow selection of specific messages (here we are acknowledging all)
180 CommonInterface::main_window->popup.Acknowledge();
183 // Mode
184 // Sets the current event mode.
185 // The argument is the label of the mode to activate.
186 // This is used to activate menus/submenus of buttons
187 void
188 InputEvents::eventMode(const TCHAR *misc)
190 assert(misc != NULL);
192 CommonInterface::main_window->SetDefaultFocus();
194 InputEvents::setMode(misc);
197 // Don't think we need this.
198 void
199 InputEvents::eventMainMenu(gcc_unused const TCHAR *misc)
201 // todo: popup main menu
204 // Checklist
205 // Displays the checklist dialog
206 // See the checklist dialog section of the reference manual for more info.
207 void
208 InputEvents::eventChecklist(gcc_unused const TCHAR *misc)
210 dlgChecklistShowModal();
213 // Status
214 // Displays one of the three status dialogs:
215 // system: display the system status
216 // aircraft: displays the aircraft status
217 // task: displays the task status
218 // See the status dialog section of the reference manual for more info
219 // on these.
220 void
221 InputEvents::eventStatus(const TCHAR *misc)
223 if (StringIsEqual(misc, _T("system"))) {
224 dlgStatusShowModal(1);
225 } else if (StringIsEqual(misc, _T("task"))) {
226 dlgStatusShowModal(2);
227 } else if (StringIsEqual(misc, _T("aircraft"))) {
228 dlgStatusShowModal(0);
229 } else {
230 dlgStatusShowModal(-1);
234 // Analysis
235 // Displays the analysis/statistics dialog
236 // See the analysis dialog section of the reference manual
237 // for more info.
238 void
239 InputEvents::eventAnalysis(gcc_unused const TCHAR *misc)
241 dlgAnalysisShowModal(*CommonInterface::main_window,
242 CommonInterface::main_window->GetLook(),
243 CommonInterface::Full(),
244 *glide_computer,
245 protected_task_manager,
246 &airspace_database,
247 terrain);
250 // WaypointDetails
251 // Displays waypoint details
252 // current: the current active waypoint
253 // select: brings up the waypoint selector, if the user then
254 // selects a waypoint, then the details dialog is shown.
255 // See the waypoint dialog section of the reference manual
256 // for more info.
257 void
258 InputEvents::eventWaypointDetails(const TCHAR *misc)
260 const NMEAInfo &basic = CommonInterface::Basic();
261 const Waypoint* wp = NULL;
263 if (StringIsEqual(misc, _T("current"))) {
264 if (protected_task_manager == NULL)
265 return;
267 wp = protected_task_manager->GetActiveWaypoint();
268 if (!wp) {
269 Message::AddMessage(_("No active waypoint!"));
270 return;
272 } else if (StringIsEqual(misc, _T("select"))) {
273 wp = ShowWaypointListDialog(basic.location);
275 if (wp)
276 dlgWaypointDetailsShowModal(*wp);
279 // StatusMessage
280 // Displays a user defined status message.
281 // The argument is the text to be displayed.
282 // No punctuation characters are allowed.
283 void
284 InputEvents::eventStatusMessage(const TCHAR *misc)
286 if (misc != NULL)
287 Message::AddMessage(gettext(misc));
290 // Plays a sound from the filename
291 void
292 InputEvents::eventPlaySound(const TCHAR *misc)
294 PlayResource(misc);
297 void
298 InputEvents::eventAutoLogger(const TCHAR *misc)
300 if (is_simulator())
301 return;
303 LoggerSettings::AutoLogger auto_logger =
304 CommonInterface::GetComputerSettings().logger.auto_logger;
306 if (auto_logger == LoggerSettings::AutoLogger::OFF)
307 return;
309 if (auto_logger == LoggerSettings::AutoLogger::START_ONLY &&
310 !StringIsEqual(misc, _T("start")))
311 return;
313 eventLogger(misc);
316 // Logger
317 // Activates the internal IGC logger
318 // start: starts the logger
319 // start ask: starts the logger after asking the user to confirm
320 // stop: stops the logger
321 // stop ask: stops the logger after asking the user to confirm
322 // toggle: toggles between on and off
323 // toggle ask: toggles between on and off, asking the user to confirm
324 // show: displays a status message indicating whether the logger is active
325 // nmea: turns on and off NMEA logging
326 // note: the text following the 'note' characters is added to the log file
327 void
328 InputEvents::eventLogger(const TCHAR *misc)
330 if (logger == nullptr)
331 return;
333 // TODO feature: start logger without requiring feedback
334 // start stop toggle addnote
336 const NMEAInfo &basic = CommonInterface::Basic();
337 const ComputerSettings &settings_computer =
338 CommonInterface::GetComputerSettings();
340 if (StringIsEqual(misc, _T("start ask")))
341 logger->GUIStartLogger(basic, settings_computer,
342 protected_task_manager);
343 else if (StringIsEqual(misc, _T("start")))
344 logger->GUIStartLogger(basic, settings_computer,
345 protected_task_manager, true);
346 else if (StringIsEqual(misc, _T("stop ask")))
347 logger->GUIStopLogger(basic);
348 else if (StringIsEqual(misc, _T("stop")))
349 logger->GUIStopLogger(basic, true);
350 else if (StringIsEqual(misc, _T("toggle ask")))
351 logger->GUIToggleLogger(basic, settings_computer,
352 protected_task_manager);
353 else if (StringIsEqual(misc, _T("toggle")))
354 logger->GUIToggleLogger(basic, settings_computer,
355 protected_task_manager, true);
356 else if (StringIsEqual(misc, _T("nmea"))) {
357 NMEALogger::enabled = !NMEALogger::enabled;
358 if (NMEALogger::enabled) {
359 Message::AddMessage(_("NMEA log on"));
360 } else {
361 Message::AddMessage(_("NMEA log off"));
363 } else if (StringIsEqual(misc, _T("show")))
364 if (logger->IsLoggerActive()) {
365 Message::AddMessage(_("Logger on"));
366 } else {
367 Message::AddMessage(_("Logger off"));
369 else if (_tcsncmp(misc, _T("note"), 4))
370 // add note to logger file if available..
371 logger->LoggerNote(misc + 4);
374 // RepeatStatusMessage
375 // Repeats the last status message. If pressed repeatedly, will
376 // repeat previous status messages
377 void
378 InputEvents::eventRepeatStatusMessage(gcc_unused const TCHAR *misc)
380 // new interface
381 // TODO enhancement: display only by type specified in misc field
382 CommonInterface::main_window->popup.Repeat();
385 // NearestWaypointDetails
386 // Displays the waypoint details dialog
387 // aircraft: the waypoint nearest the aircraft
388 // pan: the waypoint nearest to the pan cursor
389 void
390 InputEvents::eventNearestWaypointDetails(const TCHAR *misc)
392 if (StringIsEqual(misc, _T("aircraft")))
393 // big range..
394 PopupNearestWaypointDetails(way_points, CommonInterface::Basic().location,
395 1.0e5);
396 else if (StringIsEqual(misc, _T("pan"))) {
397 const Projection &projection =
398 CommonInterface::main_window->GetProjection();
400 // big range..
401 if (projection.IsValid())
402 PopupNearestWaypointDetails(way_points, projection.GetGeoLocation(),
403 1.0e5);
407 // NearestMapItems
408 // Displays the map item list dialog
409 // aircraft: the map items to nearest the aircraft
410 // pan: the map items nearest to the pan cursor
411 void
412 InputEvents::eventNearestMapItems(const TCHAR *misc)
414 if (StringIsEqual(misc, _T("aircraft")))
415 CommonInterface::main_window->GetMap()->ShowMapItems(
416 CommonInterface::Basic().location);
418 else if (StringIsEqual(misc, _T("pan")))
419 CommonInterface::main_window->GetMap()->ShowMapItems(
420 CommonInterface::main_window->GetProjection().GetGeoLocation());
423 // Null
424 // The null event does nothing. This can be used to override
425 // default functionality
426 void
427 InputEvents::eventNull(gcc_unused const TCHAR *misc)
429 // do nothing
432 void
433 InputEvents::eventBeep(gcc_unused const TCHAR *misc)
435 #if defined(GNAV)
436 altair_control.ShortBeep();
437 #elif defined(WIN32)
438 MessageBeep(MB_ICONEXCLAMATION);
439 #else
440 PlayResource(_T("IDR_WAV_CLEAR"));
441 #endif
444 // Setup
445 // Activates configuration and setting dialogs
446 // Basic: Basic settings (QNH/Bugs/Ballast/MaxTemperature)
447 // Wind: Wind settings
448 // Task: Task editor
449 // Airspace: Airspace filter settings
450 // Replay: IGC replay dialog
451 void
452 InputEvents::eventSetup(const TCHAR *misc)
454 if (StringIsEqual(misc, _T("Basic")))
455 dlgBasicSettingsShowModal();
456 else if (StringIsEqual(misc, _T("Wind")))
457 ShowWindSettingsDialog();
458 else if (StringIsEqual(misc, _T("System")))
459 SystemConfiguration();
460 else if (StringIsEqual(misc, _T("Task")))
461 dlgTaskManagerShowModal(*CommonInterface::main_window);
462 else if (StringIsEqual(misc, _T("Airspace")))
463 dlgAirspaceShowModal(false);
464 else if (StringIsEqual(misc, _T("Weather")))
465 dlgWeatherShowModal();
466 else if (StringIsEqual(misc, _T("Replay"))) {
467 if (!CommonInterface::MovementDetected())
468 ShowReplayDialog();
469 } else if (StringIsEqual(misc, _T("Switches")))
470 dlgSwitchesShowModal();
471 else if (StringIsEqual(misc, _T("Voice")))
472 dlgVoiceShowModal();
473 else if (StringIsEqual(misc, _T("Teamcode")))
474 dlgTeamCodeShowModal();
475 else if (StringIsEqual(misc, _T("Target")))
476 dlgTargetShowModal();
477 else if (StringIsEqual(misc, _T("Plane")))
478 dlgPlanesShowModal();
479 else if (StringIsEqual(misc, _T("Alternates")))
480 dlgAlternatesListShowModal();
482 trigger_redraw();
485 void
486 InputEvents::eventCredits(gcc_unused const TCHAR *misc)
488 dlgCreditsShowModal(*CommonInterface::main_window);
491 // Run
492 // Runs an external program of the specified filename.
493 // Note that XCSoar will wait until this program exits.
494 void
495 InputEvents::eventRun(const TCHAR *misc)
497 #ifdef WIN32
498 PROCESS_INFORMATION pi;
499 if (!::CreateProcess(misc, NULL, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi))
500 return;
502 // wait for program to finish!
503 ::WaitForSingleObject(pi.hProcess, INFINITE);
504 ::CloseHandle(pi.hProcess);
505 ::CloseHandle(pi.hThread);
507 #else /* !WIN32 */
508 system(misc);
509 #endif /* !WIN32 */
512 void
513 InputEvents::eventBrightness(gcc_unused const TCHAR *misc)
515 dlgBrightnessShowModal();
518 void
519 InputEvents::eventExit(gcc_unused const TCHAR *misc)
521 UIActions::SignalShutdown(false);
524 void
525 InputEvents::eventUserDisplayModeForce(const TCHAR *misc)
527 UIState &ui_state = CommonInterface::SetUIState();
529 if (StringIsEqual(misc, _T("unforce")))
530 ui_state.force_display_mode = DisplayMode::NONE;
531 else if (StringIsEqual(misc, _T("forceclimb")))
532 ui_state.force_display_mode = DisplayMode::CIRCLING;
533 else if (StringIsEqual(misc, _T("forcecruise")))
534 ui_state.force_display_mode = DisplayMode::CRUISE;
535 else if (StringIsEqual(misc, _T("forcefinal")))
536 ui_state.force_display_mode = DisplayMode::FINAL_GLIDE;
538 ActionInterface::UpdateDisplayMode();
539 ActionInterface::SendUIState();
542 void
543 InputEvents::eventAddWaypoint(const TCHAR *misc)
545 const NMEAInfo &basic = CommonInterface::Basic();
546 const DerivedInfo &calculated = CommonInterface::Calculated();
548 if (StringIsEqual(misc, _T("takeoff"))) {
549 if (basic.location_available && calculated.terrain_valid) {
550 ScopeSuspendAllThreads suspend;
551 way_points.AddTakeoffPoint(basic.location, calculated.terrain_altitude);
552 way_points.Optimise();
554 } else {
555 Waypoint edit_waypoint = way_points.Create(basic.location);
556 edit_waypoint.elevation = calculated.terrain_altitude;
557 if (!dlgWaypointEditShowModal(edit_waypoint) || edit_waypoint.name.empty()) {
558 trigger_redraw();
559 return;
562 ScopeSuspendAllThreads suspend;
563 way_points.Append(std::move(edit_waypoint));
564 way_points.Optimise();
568 trigger_redraw();
571 // JMW TODO enhancement: have all inputevents return bool, indicating whether
572 // the button should after processing be hilit or not.
573 // this allows the buttons to indicate whether things are enabled/disabled
574 // SDP TODO enhancement: maybe instead do conditional processing ?
575 // I like this idea; if one returns false, then don't execute the
576 // remaining events.
578 // JMW TODO enhancement: make sure when we change things here we also set registry values...
579 // or maybe have special tag "save" which indicates it should be saved (notice that
580 // the wind adjustment uses this already, see in Process.cpp)
582 /* Recently done
584 eventTaskLoad - Load tasks from a file (misc = filename)
585 eventTaskSave - Save tasks to a file (misc = filename)
586 eventProfileLoad - Load profile from a file (misc = filename)
587 eventProfileSave - Save profile to a file (misc = filename)
591 /* TODO feature: - new events
593 eventPanWaypoint - Set pan to a waypoint
594 - Waypoint could be "next", "first", "last", "previous", or named
595 - Note: wrong name - probably just part of eventPan
596 eventPressure - Increase, Decrease, show, Set pressure value
597 eventDeclare - (JMW separate from internal logger)
598 eventAirspaceDisplay - all, below nnn, below me, auto nnn
599 eventAirspaceWarnings- on, off, time nn, ack nn
600 eventTerrain - see map_window.Event_Terrain
601 eventCompass - on, off, cruise on, crusie off, climb on, climb off
602 eventVario - on, off // JMW what does this do?
603 eventOrientation - north, track, ???
604 eventTerrainRange - on, off (might be part of eventTerrain)
605 eventSounds - Include Task and Modes sounds along with Vario
606 - Include master nn, deadband nn, netto trigger mph/kts/...
610 // helpers
612 void
613 InputEvents::eventWeather(const TCHAR *misc)
615 #ifdef HAVE_NOAA
616 if (StringIsEqual(misc, _T("list")))
617 dlgNOAAListShowModal();
618 #endif
621 void
622 InputEvents::eventQuickMenu(gcc_unused const TCHAR *misc)
624 dlgQuickMenuShowModal(*CommonInterface::main_window);
627 void
628 InputEvents::eventFileManager(const TCHAR *misc)
630 ShowFileManager();