2
#include "base/display.h"
3
#include "input/input_state.h"
4
#include "input/keycodes.h"
5
#include "ui/ui_screen.h"
6
#include "ui/ui_context.h"
9
#include "gfx_es2/draw_buffer.h"
11
static const bool ClickDebug = false;
14
: Screen(), root_(0), recreateViews_(true), hatDown_(0) {
17
UIScreen::~UIScreen() {
21
void UIScreen::DoRecreateViews() {
23
UI::PersistMap persisted;
24
bool persisting = root_ != nullptr;
26
root_->PersistData(UI::PERSIST_SAVE, "root", persisted);
32
if (root_ && root_->GetDefaultFocusView()) {
33
root_->GetDefaultFocusView()->SetFocus();
35
recreateViews_ = false;
37
if (persisting && root_ != nullptr) {
38
root_->PersistData(UI::PERSIST_RESTORE, "root", persisted);
40
// Update layout and refocus so things scroll into view.
41
// This is for resizing down, when focused on something now offscreen.
42
UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_);
43
UI::View *focused = UI::GetFocusedView();
45
root_->SubviewFocused(focused);
51
void UIScreen::update(InputState &input) {
55
UpdateViewHierarchy(input, root_);
59
void UIScreen::preRender() {
60
Thin3DContext *thin3d = screenManager()->getThin3DContext();
64
thin3d->Begin(true, 0xFF000000, 0.0f, 0);
67
viewport.TopLeftX = 0;
68
viewport.TopLeftY = 0;
69
viewport.Width = pixel_xres;
70
viewport.Height = pixel_yres;
71
viewport.MaxDepth = 1.0;
72
viewport.MinDepth = 0.0;
73
thin3d->SetViewports(1, &viewport);
74
thin3d->SetTargetSize(pixel_xres, pixel_yres);
77
void UIScreen::postRender() {
78
Thin3DContext *thin3d = screenManager()->getThin3DContext();
85
void UIScreen::render() {
89
UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_);
91
screenManager()->getUIContext()->Begin();
92
DrawBackground(*screenManager()->getUIContext());
93
root_->Draw(*screenManager()->getUIContext());
94
screenManager()->getUIContext()->End();
95
screenManager()->getUIContext()->Flush();
99
bool UIScreen::touch(const TouchInput &touch) {
101
if (ClickDebug && (touch.flags & TOUCH_DOWN)) {
103
std::vector<UI::View *> views;
104
root_->Query(touch.x, touch.y, views);
105
for (auto view : views) {
106
ILOG("%s", view->Describe().c_str());
110
UI::TouchEvent(touch, root_);
116
bool UIScreen::key(const KeyInput &key) {
118
return UI::KeyEvent(key, root_);
123
bool UIDialogScreen::key(const KeyInput &key) {
124
bool retval = UIScreen::key(key);
125
if (!retval && (key.flags & KEY_DOWN) && UI::IsEscapeKey(key)) {
127
ELOG("Screen already finished");
130
screenManager()->finishDialog(this, DR_BACK);
137
bool UIScreen::axis(const AxisInput &axis) {
138
// Simple translation of hat to keys for Shield and other modern pads.
139
// TODO: Use some variant of keymap?
141
if (axis.axisId == JOYSTICK_AXIS_HAT_X) {
142
if (axis.value < -0.7f)
143
flags |= PAD_BUTTON_LEFT;
144
if (axis.value > 0.7f)
145
flags |= PAD_BUTTON_RIGHT;
147
if (axis.axisId == JOYSTICK_AXIS_HAT_Y) {
148
if (axis.value < -0.7f)
149
flags |= PAD_BUTTON_UP;
150
if (axis.value > 0.7f)
151
flags |= PAD_BUTTON_DOWN;
154
// Yeah yeah, this should be table driven..
155
int pressed = flags & ~hatDown_;
156
int released = ~flags & hatDown_;
157
if (pressed & PAD_BUTTON_LEFT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT, KEY_DOWN));
158
if (pressed & PAD_BUTTON_RIGHT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT, KEY_DOWN));
159
if (pressed & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_DOWN));
160
if (pressed & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_DOWN));
161
if (released & PAD_BUTTON_LEFT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_LEFT, KEY_UP));
162
if (released & PAD_BUTTON_RIGHT) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_RIGHT, KEY_UP));
163
if (released & PAD_BUTTON_UP) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_UP, KEY_UP));
164
if (released & PAD_BUTTON_DOWN) key(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_DPAD_DOWN, KEY_UP));
167
UI::AxisEvent(axis, root_);
170
return (pressed & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) != 0;
173
UI::EventReturn UIScreen::OnBack(UI::EventParams &e) {
174
screenManager()->finishDialog(this, DR_BACK);
175
return UI::EVENT_DONE;
178
UI::EventReturn UIScreen::OnOK(UI::EventParams &e) {
179
screenManager()->finishDialog(this, DR_OK);
180
return UI::EVENT_DONE;
183
UI::EventReturn UIScreen::OnCancel(UI::EventParams &e) {
184
screenManager()->finishDialog(this, DR_CANCEL);
185
return UI::EVENT_DONE;
188
PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2)
189
: box_(0), defaultButton_(nullptr), title_(title) {
190
I18NCategory *di = GetI18NCategory("Dialog");
191
if (!button1.empty())
192
button1_ = di->T(button1.c_str());
193
if (!button2.empty())
194
button2_ = di->T(button2.c_str());
197
bool PopupScreen::touch(const TouchInput &touch) {
198
if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) {
199
return UIDialogScreen::touch(touch);
202
if (!box_->GetBounds().Contains(touch.x, touch.y))
203
screenManager()->finishDialog(this, DR_BACK);
205
return UIDialogScreen::touch(touch);
208
bool PopupScreen::key(const KeyInput &key) {
209
if (key.flags & KEY_DOWN) {
210
if (key.keyCode == NKCODE_ENTER && defaultButton_) {
212
defaultButton_->OnClick.Trigger(e);
217
return UIDialogScreen::key(key);
220
void PopupScreen::CreateViews() {
223
UIContext &dc = *screenManager()->getUIContext();
225
AnchorLayout *anchor = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
226
anchor->Overflow(false);
229
float yres = screenManager()->getUIContext()->GetBounds().h;
231
box_ = new LinearLayout(ORIENT_VERTICAL,
232
new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, dc.GetBounds().centerX(), dc.GetBounds().centerY(), NONE, NONE, true));
235
box_->SetBG(UI::Drawable(0xFF303030));
236
box_->SetHasDropShadow(true);
238
View *title = new PopupHeader(title_);
241
CreatePopupContents(box_);
242
root_->SetDefaultFocusView(box_);
244
if (ShowButtons() && !button1_.empty()) {
245
// And the two buttons at the bottom.
246
LinearLayout *buttonRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(200, WRAP_CONTENT));
247
buttonRow->SetSpacing(0);
248
Margins buttonMargins(5, 5);
250
// Adjust button order to the platform default.
252
defaultButton_ = buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f, buttonMargins)));
253
defaultButton_->OnClick.Handle(this, &PopupScreen::OnOK);
254
if (!button2_.empty())
255
buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f, buttonMargins)))->OnClick.Handle(this, &PopupScreen::OnCancel);
257
if (!button2_.empty())
258
buttonRow->Add(new Button(button2_, new LinearLayoutParams(1.0f)))->OnClick.Handle(this, &PopupScreen::OnCancel);
259
defaultButton_ = buttonRow->Add(new Button(button1_, new LinearLayoutParams(1.0f)));
260
defaultButton_->OnClick.Handle(this, &PopupScreen::OnOK);
263
box_->Add(buttonRow);
267
void MessagePopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
268
std::vector<std::string> messageLines;
269
SplitString(message_, '\n', messageLines);
270
for (const auto& lineOfText : messageLines)
271
parent->Add(new UI::TextView(lineOfText, ALIGN_LEFT | ALIGN_VCENTER, false));
274
void MessagePopupScreen::OnCompleted(DialogResult result) {
275
if (result == DR_OK) {
284
UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) {
286
screenManager()->finishDialog(this, DR_OK);
287
return UI::EVENT_DONE;
290
UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) {
291
OnCompleted(DR_CANCEL);
292
screenManager()->finishDialog(this, DR_CANCEL);
293
return UI::EVENT_DONE;
296
void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
299
listView_ = parent->Add(new ListView(&adaptor_, hidden_)); //, new LinearLayoutParams(1.0)));
300
listView_->SetMaxHeight(screenManager()->getUIContext()->GetBounds().h - 140);
301
listView_->OnChoice.Handle(this, &ListPopupScreen::OnListChoice);
304
UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) {
305
adaptor_.SetSelected(e.a);
307
callback_(adaptor_.GetSelected());
308
screenManager()->finishDialog(this, DR_OK);
310
OnChoice.Dispatch(e);
311
return UI::EVENT_DONE;
316
std::string ChopTitle(const std::string &title) {
317
size_t pos = title.find('\n');
318
if (pos != title.npos) {
319
return title.substr(0, pos);
324
UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) {
325
restoreFocus_ = HasFocus();
327
I18NCategory *category = category_ ? GetI18NCategory(category_) : nullptr;
329
std::vector<std::string> choices;
330
for (int i = 0; i < numChoices_; i++) {
331
choices.push_back(category ? category->T(choices_[i]) : choices_[i]);
334
ListPopupScreen *popupScreen = new ListPopupScreen(ChopTitle(text_), choices, *value_ - minVal_,
335
std::bind(&PopupMultiChoice::ChoiceCallback, this, placeholder::_1));
336
popupScreen->SetHiddenChoices(hidden_);
337
screenManager_->push(popupScreen);
338
return UI::EVENT_DONE;
341
void PopupMultiChoice::Update(const InputState &input_state) {
345
void PopupMultiChoice::UpdateText() {
346
I18NCategory *category = GetI18NCategory(category_);
347
// Clamp the value to be safe.
348
if (*value_ < minVal_ || *value_ > minVal_ + numChoices_ - 1) {
349
valueText_ = "(invalid choice)"; // Shouldn't happen. Should be no need to translate this.
351
valueText_ = category ? category->T(choices_[*value_ - minVal_]) : choices_[*value_ - minVal_];
355
void PopupMultiChoice::ChoiceCallback(int num) {
357
*value_ = num + minVal_;
366
SetFocusedView(this);
371
void PopupMultiChoice::Draw(UIContext &dc) {
372
Style style = dc.theme->itemStyle;
374
style = dc.theme->itemDisabledStyle;
377
dc.SetFontStyle(dc.theme->uiFont);
380
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, valueText_.c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
381
textPadding_.right += paddingX;
384
dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
387
PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams)
388
: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(1), units_(units), screenManager_(screenManager) {
390
OnClick.Handle(this, &PopupSliderChoice::HandleClick);
393
PopupSliderChoice::PopupSliderChoice(int *value, int minValue, int maxValue, const std::string &text, int step, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams)
394
: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), units_(units), screenManager_(screenManager) {
396
OnClick.Handle(this, &PopupSliderChoice::HandleClick);
399
PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams)
400
: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(1.0f), units_(units), screenManager_(screenManager) {
402
OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick);
405
PopupSliderChoiceFloat::PopupSliderChoiceFloat(float *value, float minValue, float maxValue, const std::string &text, float step, ScreenManager *screenManager, const std::string &units, LayoutParams *layoutParams)
406
: Choice(text, "", false, layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), step_(step), units_(units), screenManager_(screenManager) {
408
OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick);
411
EventReturn PopupSliderChoice::HandleClick(EventParams &e) {
412
restoreFocus_ = HasFocus();
414
SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, ChopTitle(text_), step_, units_);
415
popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange);
416
screenManager_->push(popupScreen);
420
EventReturn PopupSliderChoice::HandleChange(EventParams &e) {
425
SetFocusedView(this);
430
void PopupSliderChoice::Draw(UIContext &dc) {
431
Style style = dc.theme->itemStyle;
433
style = dc.theme->itemDisabledStyle;
436
dc.SetFontStyle(dc.theme->uiFont);
439
if (zeroLabel_.size() && *value_ == 0) {
440
strcpy(temp, zeroLabel_.c_str());
442
sprintf(temp, fmt_, *value_);
446
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, temp, &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
447
textPadding_.right += paddingX;
450
dc.DrawText(temp, bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
453
EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) {
454
restoreFocus_ = HasFocus();
456
SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, ChopTitle(text_), step_, units_);
457
popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange);
458
screenManager_->push(popupScreen);
462
EventReturn PopupSliderChoiceFloat::HandleChange(EventParams &e) {
467
SetFocusedView(this);
472
void PopupSliderChoiceFloat::Draw(UIContext &dc) {
473
Style style = dc.theme->itemStyle;
475
style = dc.theme->itemDisabledStyle;
478
dc.SetFontStyle(dc.theme->uiFont);
481
if (zeroLabel_.size() && *value_ == 0.0f) {
482
strcpy(temp, zeroLabel_.c_str());
484
sprintf(temp, fmt_, *value_);
488
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, temp, &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
489
textPadding_.right += paddingX;
492
dc.DrawText(temp, bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
495
EventReturn SliderPopupScreen::OnDecrease(EventParams ¶ms) {
496
if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) {
497
sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f);
499
sliderValue_ -= step_;
503
sprintf(temp, "%d", sliderValue_);
504
edit_->SetText(temp);
509
EventReturn SliderPopupScreen::OnIncrease(EventParams ¶ms) {
510
if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) {
511
sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f);
513
sliderValue_ += step_;
517
sprintf(temp, "%d", sliderValue_);
518
edit_->SetText(temp);
523
EventReturn SliderPopupScreen::OnSliderChange(EventParams ¶ms) {
526
sprintf(temp, "%d", sliderValue_);
527
edit_->SetText(temp);
532
EventReturn SliderPopupScreen::OnTextChange(EventParams ¶ms) {
534
sliderValue_ = atoi(edit_->GetText().c_str());
540
void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
542
sliderValue_ = *value_;
543
LinearLayout *vert = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::Margins(10, 10))));
544
slider_ = new Slider(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 10)));
545
slider_->OnChange.Handle(this, &SliderPopupScreen::OnSliderChange);
547
LinearLayout *lin = vert->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 10))));
548
lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderPopupScreen::OnDecrease);
549
lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderPopupScreen::OnIncrease);
551
sprintf(temp, "%d", sliderValue_);
552
edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f));
553
edit_->SetMaxLen(16);
554
edit_->OnTextChange.Handle(this, &SliderPopupScreen::OnTextChange);
558
lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)));
560
if (IsFocusMovementEnabled())
561
UI::SetFocusedView(slider_);
564
void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
566
sliderValue_ = *value_;
567
LinearLayout *vert = parent->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::Margins(10, 10))));
568
slider_ = new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 10)));
569
slider_->OnChange.Handle(this, &SliderFloatPopupScreen::OnSliderChange);
571
LinearLayout *lin = vert->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::Margins(10, 10))));
572
lin->Add(new Button(" - "))->OnClick.Handle(this, &SliderFloatPopupScreen::OnDecrease);
573
lin->Add(new Button(" + "))->OnClick.Handle(this, &SliderFloatPopupScreen::OnIncrease);
575
sprintf(temp, "%0.3f", sliderValue_);
576
edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f));
577
edit_->SetMaxLen(16);
578
edit_->OnTextChange.Handle(this, &SliderFloatPopupScreen::OnTextChange);
582
lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)));
584
// slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5))));
585
if (IsFocusMovementEnabled())
586
UI::SetFocusedView(slider_);
589
EventReturn SliderFloatPopupScreen::OnDecrease(EventParams ¶ms) {
590
if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) {
591
sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f);
593
sliderValue_ -= step_;
597
sprintf(temp, "%0.3f", sliderValue_);
598
edit_->SetText(temp);
603
EventReturn SliderFloatPopupScreen::OnIncrease(EventParams ¶ms) {
604
if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) {
605
sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f);
607
sliderValue_ += step_;
611
sprintf(temp, "%0.3f", sliderValue_);
612
edit_->SetText(temp);
617
EventReturn SliderFloatPopupScreen::OnSliderChange(EventParams ¶ms) {
620
sprintf(temp, "%0.3f", sliderValue_);
621
edit_->SetText(temp);
626
EventReturn SliderFloatPopupScreen::OnTextChange(EventParams ¶ms) {
628
sliderValue_ = atof(edit_->GetText().c_str());
634
void SliderPopupScreen::OnCompleted(DialogResult result) {
635
if (result == DR_OK) {
636
*value_ = sliderValue_;
644
void SliderFloatPopupScreen::OnCompleted(DialogResult result) {
645
if (result == DR_OK) {
646
*value_ = sliderValue_;
655
PopupTextInputChoice::PopupTextInputChoice(std::string *value, const std::string &title, const std::string &placeholder, int maxLen, ScreenManager *screenManager, LayoutParams *layoutParams)
656
: Choice(title, "", false, layoutParams), screenManager_(screenManager), value_(value), placeHolder_(placeholder), maxLen_(maxLen) {
657
OnClick.Handle(this, &PopupTextInputChoice::HandleClick);
660
EventReturn PopupTextInputChoice::HandleClick(EventParams &e) {
661
restoreFocus_ = HasFocus();
663
TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, ChopTitle(text_), maxLen_);
664
popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange);
665
screenManager_->push(popupScreen);
669
void PopupTextInputChoice::Draw(UIContext &dc) {
670
Style style = dc.theme->itemStyle;
672
style = dc.theme->itemDisabledStyle;
675
dc.SetFontStyle(dc.theme->uiFont);
678
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, value_->c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
679
textPadding_.right += paddingX;
682
dc.DrawText(value_->c_str(), bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
685
EventReturn PopupTextInputChoice::HandleChange(EventParams &e) {
690
SetFocusedView(this);
695
void TextEditPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
698
textEditValue_ = *value_;
699
LinearLayout *lin = parent->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams((UI::Size)300, WRAP_CONTENT)));
700
edit_ = new TextEdit(textEditValue_, placeholder_, new LinearLayoutParams(1.0f));
701
edit_->SetMaxLen(maxLen_);
704
if (IsFocusMovementEnabled())
705
UI::SetFocusedView(edit_);
708
void TextEditPopupScreen::OnCompleted(DialogResult result) {
709
if (result == DR_OK) {
710
*value_ = edit_->GetText();
717
void ChoiceWithValueDisplay::Draw(UIContext &dc) {
718
Style style = dc.theme->itemStyle;
720
style = dc.theme->itemDisabledStyle;
723
dc.SetFontStyle(dc.theme->uiFont);
725
I18NCategory *category = GetI18NCategory(category_);
726
std::ostringstream valueText;
727
if (sValue_ != nullptr) {
729
valueText << category->T(*sValue_);
731
valueText << *sValue_;
732
} else if (iValue_ != nullptr) {
733
valueText << *iValue_;
737
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, valueText.str().c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
738
textPadding_.right += paddingX;
741
dc.DrawText(valueText.str().c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);