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"
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
;
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
,
55 combo_list
[i
].StringValueFormatted
);
60 OnItemHelp(unsigned i
)
62 if ((*ComboListPopup
)[i
].StringHelp
)
63 return (*ComboListPopup
)[i
].StringHelp
;
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
81 /* this formula is supposed to be a compromise between too small
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
,
90 combo_list
.ComboPopupItemSavedIndex
,
94 enable_item_help
? OnItemHelp
: NULL
);
98 OnHelpClicked(unsigned i
)
100 if (i
< ComboListPopup
->size()) {
101 const ComboList::Item
&item
= (*ComboListPopup
)[i
];
102 ComboPopupDataField
->SetFromCombo(item
.DataFieldIndex
,
106 wComboPopupWndProperty
->OnHelp();
110 ComboPicker(const WndProperty
&control
,
111 const ComboList
&combo_list
, bool EnableItemHelp
)
113 return ComboPicker(control
.GetCaption(), combo_list
,
114 control
.HasHelp() ? OnHelpClicked
: nullptr,
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
131 bInComboPicker
= true;
133 TCHAR sSavedInitialValue
[100];
134 int iSavedInitialDataIndex
= -1;
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
]
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
];
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];
173 ComboPopupDataField
->SetFromCombo(item
->DataFieldIndex
,
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
,
185 delete ComboListPopup
;
187 wComboPopupWndProperty
->RefreshDisplay();
188 } // loop reopen combo if <<More>> or <<Less>> picked
190 bInComboPicker
= false;