SectorZone: add attribute arc_boundary
[xcsoar.git] / src / InfoBoxes / InfoBoxManager.cpp
blob3a60f65f529cf294819484866fef00d4038a7413
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.
25 #include "InfoBoxes/InfoBoxManager.hpp"
26 #include "InfoBoxes/InfoBoxWindow.hpp"
27 #include "InfoBoxes/InfoBoxLayout.hpp"
28 #include "Look/InfoBoxLook.hpp"
29 #include "InfoBoxes/Content/Factory.hpp"
30 #include "InfoBoxes/Content/Base.hpp"
31 #include "Profile/InfoBoxConfig.hpp"
32 #include "Screen/Layout.hpp"
33 #include "Hardware/Battery.hpp"
34 #include "Language/Language.hpp"
35 #include "Form/DataField/ComboList.hpp"
36 #include "Dialogs/HelpDialog.hpp"
37 #include "Dialogs/ComboPicker.hpp"
38 #include "Profile/InfoBoxConfig.hpp"
39 #include "Interface.hpp"
40 #include "UIState.hpp"
41 #include "UIGlobals.hpp"
43 #include <assert.h>
44 #include <stdio.h>
46 #include <algorithm>
48 namespace InfoBoxManager
50 InfoBoxLayout::Layout layout;
52 /**
53 * Is this the initial DisplayInfoBox() call? If yes, then all
54 * content objects need to be created.
56 static bool first;
58 static void DisplayInfoBox();
59 static void InfoBoxDrawIfDirty();
61 gcc_pure
62 static int GetFocused();
65 static bool infoboxes_dirty = false;
66 static bool infoboxes_hidden = false;
68 static InfoBoxWindow *infoboxes[InfoBoxSettings::Panel::MAX_CONTENTS];
70 // TODO locking
71 void
72 InfoBoxManager::Hide()
74 if (infoboxes_hidden)
75 return;
77 infoboxes_hidden = true;
79 for (unsigned i = 0; i < layout.count; i++)
80 infoboxes[i]->FastHide();
83 void
84 InfoBoxManager::Show()
86 if (!infoboxes_hidden)
87 return;
89 infoboxes_hidden = false;
91 for (unsigned i = 0; i < layout.count; i++)
92 infoboxes[i]->Show();
94 SetDirty();
97 int
98 InfoBoxManager::GetFocused()
100 for (unsigned i = 0; i < layout.count; i++)
101 if (infoboxes[i]->HasFocus())
102 return i;
104 return -1;
107 void
108 InfoBoxManager::Event_Select(int i)
110 int InfoFocus = GetFocused();
112 if (InfoFocus < 0) {
113 InfoFocus = (i >= 0 ? 0 : layout.count - 1);
114 } else {
115 InfoFocus += i;
117 if (InfoFocus < 0 || (unsigned)InfoFocus >= layout.count)
118 InfoFocus = -1;
121 if (InfoFocus >= 0)
122 infoboxes[InfoFocus]->SetFocus();
123 else
124 infoboxes[0]->FocusParent();
127 void
128 InfoBoxManager::Event_Change(int i)
130 InfoBoxFactory::Type j = InfoBoxFactory::MIN_TYPE_VAL;
131 InfoBoxFactory::Type k;
133 int InfoFocus = GetFocused();
134 if (InfoFocus < 0)
135 return;
137 InfoBoxSettings &settings = CommonInterface::SetUISettings().info_boxes;
138 const unsigned panel_index = CommonInterface::GetUIState().panel_index;
139 InfoBoxSettings::Panel &panel = settings.panels[panel_index];
141 k = panel.contents[InfoFocus];
142 if (i > 0)
143 j = InfoBoxFactory::GetNext(k);
144 else if (i < 0)
145 j = InfoBoxFactory::GetPrevious(k);
147 // TODO code: if i==0, go to default or reset
149 if (j == k)
150 return;
152 panel.contents[InfoFocus] = j;
154 infoboxes[InfoFocus]->UpdateContent();
157 void
158 InfoBoxManager::DisplayInfoBox()
160 static int DisplayTypeLast[InfoBoxSettings::Panel::MAX_CONTENTS];
162 // JMW note: this is updated every GPS time step
164 const unsigned panel = CommonInterface::GetUIState().panel_index;
166 const InfoBoxSettings::Panel &settings =
167 CommonInterface::GetUISettings().info_boxes.panels[panel];
169 for (unsigned i = 0; i < layout.count; i++) {
170 // All calculations are made in a separate thread. Slow calculations
171 // should apply to the function DoCalculationsSlow()
172 // Do not put calculations here!
174 InfoBoxFactory::Type DisplayType = settings.contents[i];
175 if ((unsigned)DisplayType > (unsigned)InfoBoxFactory::MAX_TYPE_VAL)
176 DisplayType = InfoBoxFactory::NavAltitude;
178 bool needupdate = ((DisplayType != DisplayTypeLast[i]) || first);
180 if (needupdate) {
181 infoboxes[i]->SetTitle(gettext(InfoBoxFactory::GetCaption(DisplayType)));
182 infoboxes[i]->SetContentProvider(InfoBoxFactory::Create(DisplayType));
183 DisplayTypeLast[i] = DisplayType;
186 infoboxes[i]->UpdateContent();
189 first = false;
192 void
193 InfoBoxManager::InfoBoxDrawIfDirty()
195 // No need to redraw map or infoboxes if screen is blanked.
196 // This should save lots of battery power due to CPU usage
197 // of drawing the screen
199 if (infoboxes_dirty && !infoboxes_hidden &&
200 !CommonInterface::GetUIState().screen_blanked) {
201 DisplayInfoBox();
202 infoboxes_dirty = false;
206 void
207 InfoBoxManager::SetDirty()
209 infoboxes_dirty = true;
212 void
213 InfoBoxManager::ProcessTimer()
215 InfoBoxDrawIfDirty();
218 void
219 InfoBoxManager::Create(ContainerWindow &parent,
220 const InfoBoxLayout::Layout &_layout,
221 const InfoBoxLook &look, const UnitsLook &units_look)
223 const InfoBoxSettings &settings =
224 CommonInterface::GetUISettings().info_boxes;
226 first = true;
227 layout = _layout;
229 WindowStyle style;
230 style.Hide();
232 // create infobox windows
233 for (unsigned i = layout.count; i-- > 0;) {
234 const PixelRect &rc = layout.positions[i];
235 int Border =
236 settings.border_style == InfoBoxSettings::BorderStyle::TAB
238 /* layout.geometry is the effective layout, while
239 settings.geometry is the configured layout */
240 : InfoBoxLayout::GetBorder(layout.geometry, i);
242 infoboxes[i] = new InfoBoxWindow(parent, rc,
243 Border, settings, look, units_look,
244 i, style);
247 infoboxes_hidden = true;
250 void
251 InfoBoxManager::Destroy()
253 for (unsigned i = 0; i < layout.count; i++) {
254 delete infoboxes[i];
255 infoboxes[i] = NULL;
259 static const ComboList *info_box_combo_list;
261 static void
262 OnInfoBoxHelp(unsigned item)
264 InfoBoxFactory::Type type = (InfoBoxFactory::Type)
265 (*info_box_combo_list)[item].DataFieldIndex;
267 StaticString<100> caption;
268 caption.Format(_T("%s: %s"), _("InfoBox"),
269 gettext(InfoBoxFactory::GetName(type)));
271 const TCHAR* text = InfoBoxFactory::GetDescription(type);
272 if (text == nullptr)
273 text = N_("No help available on this item");
275 dlgHelpShowModal(UIGlobals::GetMainWindow(), caption, gettext(text));
278 void
279 InfoBoxManager::ShowInfoBoxPicker(const int id)
281 int i;
283 if (id < 0) i = GetFocused();
284 else i = id;
286 if (i < 0)
287 return;
289 InfoBoxSettings &settings = CommonInterface::SetUISettings().info_boxes;
290 const unsigned panel_index = CommonInterface::GetUIState().panel_index;
291 InfoBoxSettings::Panel &panel = settings.panels[panel_index];
293 const InfoBoxFactory::Type old_type = panel.contents[i];
295 ComboList list;
296 for (unsigned j = InfoBoxFactory::MIN_TYPE_VAL; j < InfoBoxFactory::NUM_TYPES; j++) {
297 const TCHAR *desc = InfoBoxFactory::GetDescription((InfoBoxFactory::Type)j);
298 list.Append(j, gettext(InfoBoxFactory::GetName((InfoBoxFactory::Type)j)),
299 gettext(InfoBoxFactory::GetName((InfoBoxFactory::Type)j)),
300 desc != NULL ? gettext(desc) : NULL);
303 list.Sort();
304 list.ComboPopupItemSavedIndex = list.LookUp(old_type);
306 /* let the user select */
308 StaticString<20> caption;
309 caption.Format(_T("%s: %d"), _("InfoBox"), i + 1);
310 info_box_combo_list = &list;
311 int result = ComboPicker(caption, list, OnInfoBoxHelp, true);
312 if (result < 0)
313 return;
315 /* was there a modification? */
317 InfoBoxFactory::Type new_type = (InfoBoxFactory::Type)list[result].DataFieldIndex;
318 if (new_type == old_type)
319 return;
321 /* yes: apply and save it */
323 panel.contents[i] = new_type;
324 DisplayInfoBox();
326 Profile::Save(panel, panel_index);