SectorZone: add attribute arc_boundary
[xcsoar.git] / src / Dialogs / ComboPicker.cpp
blobcc74e15b1485aca4a60145fa838fc880d9ef7057
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 "Dialogs/ComboPicker.hpp"
25 #include "Dialogs/ListPicker.hpp"
26 #include "Form/List.hpp"
27 #include "Form/Edit.hpp"
28 #include "Form/DataField/Base.hpp"
29 #include "Form/DataField/ComboList.hpp"
30 #include "Screen/Canvas.hpp"
31 #include "Screen/Layout.hpp"
32 #include "UIGlobals.hpp"
33 #include "Look/DialogLook.hpp"
35 #include <assert.h>
37 static WndProperty *wComboPopupWndProperty;
38 static DataField *ComboPopupDataField;
39 static const ComboList *ComboListPopup;
41 class ComboPickerSupport : public ListItemRenderer {
42 const ComboList &combo_list;
43 const UPixelScalar padding;
45 public:
46 ComboPickerSupport(const ComboList &_combo_list,
47 const UPixelScalar _padding)
48 :combo_list(_combo_list), padding(_padding) {}
51 virtual void OnPaintItem(Canvas &canvas, const PixelRect rc,
52 unsigned i) override {
53 canvas.DrawClippedText(rc.left + padding,
54 rc.top + padding, rc,
55 combo_list[i].StringValueFormatted);
59 static const TCHAR*
60 OnItemHelp(unsigned i)
62 if ((*ComboListPopup)[i].StringHelp)
63 return (*ComboListPopup)[i].StringHelp;
65 return _T("");
68 int
69 ComboPicker(const TCHAR *caption,
70 const ComboList &combo_list,
71 ListHelpCallback_t help_callback,
72 bool enable_item_help)
74 ComboListPopup = &combo_list;
76 const UPixelScalar font_height =
77 UIGlobals::GetDialogLook().text_font->GetHeight() + Layout::FastScale(2);
78 const UPixelScalar max_height = Layout::GetMaximumControlHeight();
79 const UPixelScalar row_height = font_height >= max_height
80 ? font_height
81 /* this formula is supposed to be a compromise between too small
82 and too large: */
83 : (font_height + max_height) / 2;
85 const UPixelScalar padding = (row_height - font_height) / 2;
87 ComboPickerSupport support(combo_list, padding);
88 return ListPicker(caption,
89 combo_list.size(),
90 combo_list.ComboPopupItemSavedIndex,
91 row_height,
92 support, false,
93 help_callback,
94 enable_item_help ? OnItemHelp : NULL);
97 static void
98 OnHelpClicked(unsigned i)
100 if (i < ComboListPopup->size()) {
101 const ComboList::Item &item = (*ComboListPopup)[i];
102 ComboPopupDataField->SetFromCombo(item.DataFieldIndex,
103 item.StringValue);
106 wComboPopupWndProperty->OnHelp();
109 static int
110 ComboPicker(const WndProperty &control,
111 const ComboList &combo_list, bool EnableItemHelp)
113 return ComboPicker(control.GetCaption(), combo_list,
114 control.HasHelp() ? OnHelpClicked : nullptr,
115 EnableItemHelp);
119 dlgComboPicker(WndProperty *theProperty)
121 static bool bInComboPicker = false;
122 bool bInitialPage = true;
123 // used to exit loop (optionally reruns combo with
124 // lower/higher index of items for int/float
125 bool bOpenCombo = true;
127 // prevents multiple instances
128 if (bInComboPicker)
129 return 0;
131 bInComboPicker = true;
133 TCHAR sSavedInitialValue[100];
134 int iSavedInitialDataIndex = -1;
136 while (bOpenCombo) {
137 assert(theProperty != NULL);
138 wComboPopupWndProperty = theProperty;
140 ComboPopupDataField = wComboPopupWndProperty->GetDataField();
141 assert(ComboPopupDataField != NULL);
143 ComboListPopup = ComboPopupDataField->CreateComboList();
144 if (bInitialPage) { // save values for "Cancel" from first page only
145 bInitialPage = false;
146 iSavedInitialDataIndex =
147 (*ComboListPopup)[ComboListPopup->ComboPopupItemSavedIndex]
148 .DataFieldIndex;
149 ComboPopupDataField->CopyString(sSavedInitialValue, false);
152 int idx = ComboPicker(*theProperty, *ComboListPopup, ComboPopupDataField->GetItemHelpEnabled());
154 bOpenCombo = false; //tell combo to exit loop after close
156 if (idx >= 0 && (unsigned)idx < ComboListPopup->size()) {
157 const ComboList::Item *item = &(*ComboListPopup)[idx];
159 // OK/Select
160 if (item->DataFieldIndex == ComboList::Item::NEXT_PAGE) {
161 // we're last in list and the want more past end of list so select last real list item and reopen
162 ComboPopupDataField->SetDetachGUI(true);
163 // we'll reopen, so don't call xcsoar data changed routine yet
164 item = &(*ComboListPopup)[idx - 1];
165 bOpenCombo = true; // reopen combo with new selected index at center
166 } else if (item->DataFieldIndex == ComboList::Item::PREVIOUS_PAGE) {
167 // same as above but lower items needed
168 ComboPopupDataField->SetDetachGUI(true);
169 item = &(*ComboListPopup)[idx + 1];
170 bOpenCombo = true;
173 ComboPopupDataField->SetFromCombo(item->DataFieldIndex,
174 item->StringValue);
175 } else {
176 // Cancel
177 // if we've detached the GUI during the load, then there is nothing to do here
178 assert(iSavedInitialDataIndex >= 0);
179 if (iSavedInitialDataIndex >= 0)
180 // use statics here - saved from first page if multiple were used
181 ComboPopupDataField->SetFromCombo(iSavedInitialDataIndex,
182 sSavedInitialValue);
185 delete ComboListPopup;
187 wComboPopupWndProperty->RefreshDisplay();
188 } // loop reopen combo if <<More>> or <<Less>> picked
190 bInComboPicker = false;
191 return 1;