Makefile: remove spurious tab
[xcsoar.git] / src / ActionInterface.cpp
blob8c856a267218a708038ab864772a29289fd73fc4
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.
24 #include "ActionInterface.hpp"
25 #include "Interface.hpp"
26 #include "Thread/Mutex.hpp"
27 #include "MainWindow.hpp"
28 #include "MapWindow/GlueMapWindow.hpp"
29 #include "Language/Language.hpp"
30 #include "StatusMessage.hpp"
31 #include "InfoBoxes/InfoBoxManager.hpp"
32 #include "InfoBoxes/InfoBoxLayout.hpp"
33 #include "Screen/Layout.hpp"
34 #include "Asset.hpp"
35 #include "Components.hpp"
36 #include "DrawThread.hpp"
37 #include "FLARM/Glue.hpp"
38 #include "Gauge/GlueGaugeVario.hpp"
39 #include "Gauge/GaugeFLARM.hpp"
40 #include "Time/PeriodClock.hpp"
41 #include "LogFile.hpp"
42 #include "Blackboard/DeviceBlackboard.hpp"
43 #include "CalculationThread.hpp"
44 #include "Task/ProtectedTaskManager.hpp"
45 #include "Profile/Profile.hpp"
46 #include "UIState.hpp"
47 #include "Operation/MessageOperationEnvironment.hpp"
49 using namespace CommonInterface;
51 namespace ActionInterface {
52 static void SendGetComputerSettings();
55 void
56 XCSoarInterface::ReceiveGPS()
59 ScopeLock protect(device_blackboard->mutex);
61 ReadBlackboardBasic(device_blackboard->Basic());
63 const NMEAInfo &real = device_blackboard->RealState();
64 Private::movement_detected = real.alive && real.gps.real &&
65 real.MovementDetected();
68 BroadcastGPSUpdate();
70 if (!Basic().flarm.traffic.IsEmpty())
71 /* auto-load FlarmNet when traffic is seen */
72 LoadFlarmDatabases();
75 void
76 XCSoarInterface::ReceiveCalculated()
79 ScopeLock protect(device_blackboard->mutex);
81 ReadBlackboardCalculated(device_blackboard->Calculated());
82 device_blackboard->ReadComputerSettings(GetComputerSettings());
85 BroadcastCalculatedUpdate();
88 void
89 XCSoarInterface::ExchangeBlackboard()
91 ExchangeDeviceBlackboard();
92 ActionInterface::SendGetComputerSettings();
93 ActionInterface::SendMapSettings();
96 void
97 XCSoarInterface::ExchangeDeviceBlackboard()
99 ScopeLock protect(device_blackboard->mutex);
101 device_blackboard->ReadComputerSettings(GetComputerSettings());
104 void
105 ActionInterface::SendGetComputerSettings()
107 assert(calculation_thread != NULL);
109 main_window->SetComputerSettings(GetComputerSettings());
111 calculation_thread->SetComputerSettings(GetComputerSettings());
112 calculation_thread->SetScreenDistanceMeters(main_window->GetProjection().GetScreenDistanceMeters());
115 void
116 ActionInterface::SetBallast(fixed ballast, bool to_devices)
118 // write ballast into settings
119 GlidePolar &polar = SetComputerSettings().polar.glide_polar_task;
120 polar.SetBallast(ballast);
122 // send to calculation thread and trigger recalculation
123 if (protected_task_manager != NULL)
124 protected_task_manager->SetGlidePolar(polar);
126 if (calculation_thread != NULL) {
127 calculation_thread->SetComputerSettings(GetComputerSettings());
128 calculation_thread->Trigger();
131 // send to external devices
132 if (to_devices) {
133 const Plane &plane = GetComputerSettings().plane;
134 if (positive(plane.dry_mass)) {
135 fixed overload = (plane.dry_mass + ballast * plane.max_ballast) /
136 plane.dry_mass;
138 MessageOperationEnvironment env;
139 device_blackboard->SetBallast(ballast, overload, env);
144 void
145 ActionInterface::SetBugs(fixed bugs, bool to_devices)
147 // Write Bugs into settings
148 CommonInterface::SetComputerSettings().polar.SetBugs(bugs);
149 GlidePolar &polar = SetComputerSettings().polar.glide_polar_task;
151 // send to calculation thread and trigger recalculation
152 if (protected_task_manager != NULL)
153 protected_task_manager->SetGlidePolar(polar);
155 if (calculation_thread != NULL) {
156 calculation_thread->SetComputerSettings(GetComputerSettings());
157 calculation_thread->Trigger();
160 // send to external devices
161 if (to_devices) {
162 MessageOperationEnvironment env;
163 device_blackboard->SetBugs(bugs, env);
167 void
168 ActionInterface::SetMacCready(fixed mc, bool to_devices)
170 // Repeated adjustment of MC with the +/- UI elements could result in
171 // an MC which is slightly larger than 0. Since the calculations
172 // fundamentally change depending on "MC == 0" or "MC <> 0" force
173 // a fixed(0) for small MC values.
174 if (mc < fixed(0.01))
175 mc = fixed(0);
177 /* update interface settings */
179 GlidePolar &polar = SetComputerSettings().polar.glide_polar_task;
180 polar.SetMC(mc);
182 /* update InfoBoxes (that might show the MacCready setting) */
184 InfoBoxManager::SetDirty();
186 /* send to calculation thread and trigger recalculation */
188 if (protected_task_manager != NULL)
189 protected_task_manager->SetGlidePolar(polar);
191 if (calculation_thread != NULL) {
192 calculation_thread->SetComputerSettings(GetComputerSettings());
193 calculation_thread->Trigger();
196 /* send to external devices */
198 if (to_devices) {
199 MessageOperationEnvironment env;
200 device_blackboard->SetMC(mc, env);
204 void ActionInterface::SetManualMacCready(fixed mc, bool to_devices)
206 TaskBehaviour &task_behaviour = CommonInterface::SetComputerSettings().task;
207 if (task_behaviour.auto_mc) {
208 task_behaviour.auto_mc = false;
209 Profile::Set(ProfileKeys::AutoMc, false);
212 SetMacCready(mc, to_devices);
215 void
216 ActionInterface::OffsetManualMacCready(fixed offset, bool to_devices)
218 const GlidePolar &polar = GetComputerSettings().polar.glide_polar_task;
219 const fixed old_mc = polar.GetMC();
220 fixed mc = old_mc + offset;
221 if (negative(mc))
222 mc = fixed(0);
223 else if (mc > fixed(5))
224 mc = fixed(5);
226 if (mc != old_mc)
227 SetManualMacCready(mc, to_devices);
230 void
231 ActionInterface::SendMapSettings(const bool trigger_draw)
233 // trigger_draw: asks for an immediate exchange of blackboard data
234 // (via ProcessTimer()) rather than waiting for the idle timer every 500ms
236 if (trigger_draw) {
237 main_window->UpdateGaugeVisibility();
238 InfoBoxManager::ProcessTimer();
241 /* Don't show indicator when the gauge is indicating the traffic anyway */
242 SetMapSettings().show_flarm_alarm_level =
243 !GetUISettings().traffic.enable_gauge;
245 main_window->SetMapSettings(GetMapSettings());
247 if (trigger_draw) {
248 main_window->FullRedraw();
249 BroadcastUISettingsUpdate();
252 // TODO: trigger refresh if the settings are changed
255 gcc_pure
256 static unsigned
257 GetPanelIndex(const UIState &ui_state)
259 if (ui_state.auxiliary_enabled) {
260 unsigned panel = ui_state.auxiliary_index;
261 if (panel >= InfoBoxSettings::MAX_PANELS)
262 panel = InfoBoxSettings::PANEL_AUXILIARY;
263 return panel;
265 else if (ui_state.display_mode == DisplayMode::CIRCLING)
266 return InfoBoxSettings::PANEL_CIRCLING;
267 else if (ui_state.display_mode == DisplayMode::FINAL_GLIDE)
268 return InfoBoxSettings::PANEL_FINAL_GLIDE;
269 else
270 return InfoBoxSettings::PANEL_CRUISE;
273 void
274 ActionInterface::UpdateDisplayMode()
276 UIState &state = SetUIState();
277 const UISettings &settings = GetUISettings();
279 state.display_mode = GetNewDisplayMode(settings.info_boxes, state,
280 Calculated());
281 state.panel_index = GetPanelIndex(state);
283 const auto &panel = settings.info_boxes.panels[state.panel_index];
284 state.panel_name = gettext(panel.name);
287 void
288 ActionInterface::SendUIState()
290 /* force-update all InfoBoxes just in case the display mode has
291 changed */
292 InfoBoxManager::SetDirty();
293 InfoBoxManager::ProcessTimer();
295 main_window->SetUIState(GetUIState());