~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to ext/native/ui/ui_screen.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <map>
 
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"
 
7
#include "ui/screen.h"
 
8
#include "i18n/i18n.h"
 
9
#include "gfx_es2/draw_buffer.h"
 
10
 
 
11
static const bool ClickDebug = false;
 
12
 
 
13
UIScreen::UIScreen()
 
14
        : Screen(), root_(0), recreateViews_(true), hatDown_(0) {
 
15
}
 
16
 
 
17
UIScreen::~UIScreen() {
 
18
        delete root_;
 
19
}
 
20
 
 
21
void UIScreen::DoRecreateViews() {
 
22
        if (recreateViews_) {
 
23
                UI::PersistMap persisted;
 
24
                bool persisting = root_ != nullptr;
 
25
                if (persisting) {
 
26
                        root_->PersistData(UI::PERSIST_SAVE, "root", persisted);
 
27
                }
 
28
 
 
29
                delete root_;
 
30
                root_ = nullptr;
 
31
                CreateViews();
 
32
                if (root_ && root_->GetDefaultFocusView()) {
 
33
                        root_->GetDefaultFocusView()->SetFocus();
 
34
                }
 
35
                recreateViews_ = false;
 
36
 
 
37
                if (persisting && root_ != nullptr) {
 
38
                        root_->PersistData(UI::PERSIST_RESTORE, "root", persisted);
 
39
 
 
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();
 
44
                        if (focused) {
 
45
                                root_->SubviewFocused(focused);
 
46
                        }
 
47
                }
 
48
        }
 
49
}
 
50
 
 
51
void UIScreen::update(InputState &input) {
 
52
        DoRecreateViews();
 
53
 
 
54
        if (root_) {
 
55
                UpdateViewHierarchy(input, root_);
 
56
        }
 
57
}
 
58
 
 
59
void UIScreen::preRender() {
 
60
        Thin3DContext *thin3d = screenManager()->getThin3DContext();
 
61
        if (!thin3d) {
 
62
                return;
 
63
        }
 
64
        thin3d->Begin(true, 0xFF000000, 0.0f, 0);
 
65
 
 
66
        T3DViewport viewport;
 
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);
 
75
}
 
76
 
 
77
void UIScreen::postRender() {
 
78
        Thin3DContext *thin3d = screenManager()->getThin3DContext();
 
79
        if (!thin3d) {
 
80
                return;
 
81
        }
 
82
        thin3d->End();
 
83
}
 
84
 
 
85
void UIScreen::render() {
 
86
        DoRecreateViews();
 
87
 
 
88
        if (root_) {
 
89
                UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_);
 
90
 
 
91
                screenManager()->getUIContext()->Begin();
 
92
                DrawBackground(*screenManager()->getUIContext());
 
93
                root_->Draw(*screenManager()->getUIContext());
 
94
                screenManager()->getUIContext()->End();
 
95
                screenManager()->getUIContext()->Flush();
 
96
        }
 
97
}
 
98
 
 
99
bool UIScreen::touch(const TouchInput &touch) {
 
100
        if (root_) {
 
101
                if (ClickDebug && (touch.flags & TOUCH_DOWN)) {
 
102
                        ILOG("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());
 
107
                        }
 
108
                }
 
109
 
 
110
                UI::TouchEvent(touch, root_);
 
111
                return true;
 
112
        }
 
113
        return false;
 
114
}
 
115
 
 
116
bool UIScreen::key(const KeyInput &key) {
 
117
        if (root_) {
 
118
                return UI::KeyEvent(key, root_);
 
119
        }
 
120
        return false;
 
121
}
 
122
 
 
123
bool UIDialogScreen::key(const KeyInput &key) {
 
124
        bool retval = UIScreen::key(key);
 
125
        if (!retval && (key.flags & KEY_DOWN) && UI::IsEscapeKey(key)) {
 
126
                if (finished_) {
 
127
                        ELOG("Screen already finished");
 
128
                } else {
 
129
                        finished_ = true;
 
130
                        screenManager()->finishDialog(this, DR_BACK);
 
131
                }
 
132
                return true;
 
133
        }
 
134
        return retval;
 
135
}
 
136
 
 
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?
 
140
        int flags = 0;
 
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;
 
146
        }
 
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;
 
152
        }
 
153
 
 
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));
 
165
        hatDown_ = flags;
 
166
        if (root_) {
 
167
                UI::AxisEvent(axis, root_);
 
168
                return true;
 
169
        }
 
170
        return (pressed & (PAD_BUTTON_LEFT | PAD_BUTTON_RIGHT | PAD_BUTTON_UP | PAD_BUTTON_DOWN)) != 0;
 
171
}
 
172
 
 
173
UI::EventReturn UIScreen::OnBack(UI::EventParams &e) {
 
174
        screenManager()->finishDialog(this, DR_BACK);
 
175
        return UI::EVENT_DONE;
 
176
}
 
177
 
 
178
UI::EventReturn UIScreen::OnOK(UI::EventParams &e) {
 
179
        screenManager()->finishDialog(this, DR_OK);
 
180
        return UI::EVENT_DONE;
 
181
}
 
182
 
 
183
UI::EventReturn UIScreen::OnCancel(UI::EventParams &e) {
 
184
        screenManager()->finishDialog(this, DR_CANCEL);
 
185
        return UI::EVENT_DONE;
 
186
}
 
187
 
 
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());
 
195
}
 
196
 
 
197
bool PopupScreen::touch(const TouchInput &touch) {
 
198
        if (!box_ || (touch.flags & TOUCH_DOWN) == 0 || touch.id != 0) {
 
199
                return UIDialogScreen::touch(touch);
 
200
        }
 
201
 
 
202
        if (!box_->GetBounds().Contains(touch.x, touch.y))
 
203
                screenManager()->finishDialog(this, DR_BACK);
 
204
 
 
205
        return UIDialogScreen::touch(touch);
 
206
}
 
207
 
 
208
bool PopupScreen::key(const KeyInput &key) {
 
209
        if (key.flags & KEY_DOWN) {
 
210
                if (key.keyCode == NKCODE_ENTER && defaultButton_) {
 
211
                        UI::EventParams e;
 
212
                        defaultButton_->OnClick.Trigger(e);
 
213
                        return true;
 
214
                }
 
215
        }
 
216
 
 
217
        return UIDialogScreen::key(key);
 
218
}
 
219
 
 
220
void PopupScreen::CreateViews() {
 
221
        using namespace UI;
 
222
 
 
223
        UIContext &dc = *screenManager()->getUIContext();
 
224
 
 
225
        AnchorLayout *anchor = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
 
226
        anchor->Overflow(false);
 
227
        root_ = anchor;
 
228
 
 
229
        float yres = screenManager()->getUIContext()->GetBounds().h;
 
230
 
 
231
        box_ = new LinearLayout(ORIENT_VERTICAL,
 
232
                new AnchorLayoutParams(PopupWidth(), FillVertical() ? yres - 30 : WRAP_CONTENT, dc.GetBounds().centerX(), dc.GetBounds().centerY(), NONE, NONE, true));
 
233
 
 
234
        root_->Add(box_);
 
235
        box_->SetBG(UI::Drawable(0xFF303030));
 
236
        box_->SetHasDropShadow(true);
 
237
 
 
238
        View *title = new PopupHeader(title_);
 
239
        box_->Add(title);
 
240
 
 
241
        CreatePopupContents(box_);
 
242
        root_->SetDefaultFocusView(box_);
 
243
 
 
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);
 
249
 
 
250
                // Adjust button order to the platform default.
 
251
#if defined(_WIN32)
 
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);
 
256
#else
 
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);
 
261
#endif
 
262
 
 
263
                box_->Add(buttonRow);
 
264
        }
 
265
}
 
266
 
 
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));
 
272
}
 
273
 
 
274
void MessagePopupScreen::OnCompleted(DialogResult result) {
 
275
        if (result == DR_OK) {
 
276
                if (callback_)
 
277
                        callback_(true);
 
278
        } else {
 
279
                if (callback_)
 
280
                        callback_(false);
 
281
        }
 
282
}
 
283
 
 
284
UI::EventReturn PopupScreen::OnOK(UI::EventParams &e) {
 
285
        OnCompleted(DR_OK);
 
286
        screenManager()->finishDialog(this, DR_OK);
 
287
        return UI::EVENT_DONE;
 
288
}
 
289
 
 
290
UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) {
 
291
        OnCompleted(DR_CANCEL);
 
292
        screenManager()->finishDialog(this, DR_CANCEL);
 
293
        return UI::EVENT_DONE;
 
294
}
 
295
 
 
296
void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
 
297
        using namespace UI;
 
298
 
 
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);
 
302
}
 
303
 
 
304
UI::EventReturn ListPopupScreen::OnListChoice(UI::EventParams &e) {
 
305
        adaptor_.SetSelected(e.a);
 
306
        if (callback_)
 
307
                callback_(adaptor_.GetSelected());
 
308
        screenManager()->finishDialog(this, DR_OK);
 
309
        OnCompleted(DR_OK);
 
310
        OnChoice.Dispatch(e);
 
311
        return UI::EVENT_DONE;
 
312
}
 
313
 
 
314
namespace UI {
 
315
 
 
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);
 
320
        }
 
321
        return title;
 
322
}
 
323
 
 
324
UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) {
 
325
        restoreFocus_ = HasFocus();
 
326
 
 
327
        I18NCategory *category = category_ ? GetI18NCategory(category_) : nullptr;
 
328
 
 
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]);
 
332
        }
 
333
 
 
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;
 
339
}
 
340
 
 
341
void PopupMultiChoice::Update(const InputState &input_state) {
 
342
        UpdateText();
 
343
}
 
344
 
 
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.
 
350
        } else {
 
351
                valueText_ = category ? category->T(choices_[*value_ - minVal_]) : choices_[*value_ - minVal_];
 
352
        }
 
353
}
 
354
 
 
355
void PopupMultiChoice::ChoiceCallback(int num) {
 
356
        if (num != -1) {
 
357
                *value_ = num + minVal_;
 
358
                UpdateText();
 
359
 
 
360
                UI::EventParams e;
 
361
                e.v = this;
 
362
                e.a = num;
 
363
                OnChoice.Trigger(e);
 
364
 
 
365
                if (restoreFocus_) {
 
366
                        SetFocusedView(this);
 
367
                }
 
368
        }
 
369
}
 
370
 
 
371
void PopupMultiChoice::Draw(UIContext &dc) {
 
372
        Style style = dc.theme->itemStyle;
 
373
        if (!IsEnabled()) {
 
374
                style = dc.theme->itemDisabledStyle;
 
375
        }
 
376
        int paddingX = 12;
 
377
        dc.SetFontStyle(dc.theme->uiFont);
 
378
 
 
379
        float ignore;
 
380
        dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, valueText_.c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
 
381
        textPadding_.right += paddingX;
 
382
 
 
383
        Choice::Draw(dc);
 
384
        dc.DrawText(valueText_.c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
 
385
}
 
386
 
 
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) {
 
389
        fmt_ = "%i";
 
390
        OnClick.Handle(this, &PopupSliderChoice::HandleClick);
 
391
}
 
392
 
 
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) {
 
395
        fmt_ = "%i";
 
396
        OnClick.Handle(this, &PopupSliderChoice::HandleClick);
 
397
}
 
398
 
 
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) {
 
401
        fmt_ = "%2.2f";
 
402
        OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick);
 
403
}
 
404
 
 
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) {
 
407
        fmt_ = "%2.2f";
 
408
        OnClick.Handle(this, &PopupSliderChoiceFloat::HandleClick);
 
409
}
 
410
 
 
411
EventReturn PopupSliderChoice::HandleClick(EventParams &e) {
 
412
        restoreFocus_ = HasFocus();
 
413
 
 
414
        SliderPopupScreen *popupScreen = new SliderPopupScreen(value_, minValue_, maxValue_, ChopTitle(text_), step_, units_);
 
415
        popupScreen->OnChange.Handle(this, &PopupSliderChoice::HandleChange);
 
416
        screenManager_->push(popupScreen);
 
417
        return EVENT_DONE;
 
418
}
 
419
 
 
420
EventReturn PopupSliderChoice::HandleChange(EventParams &e) {
 
421
        e.v = this;
 
422
        OnChange.Trigger(e);
 
423
 
 
424
        if (restoreFocus_) {
 
425
                SetFocusedView(this);
 
426
        }
 
427
        return EVENT_DONE;
 
428
}
 
429
 
 
430
void PopupSliderChoice::Draw(UIContext &dc) {
 
431
        Style style = dc.theme->itemStyle;
 
432
        if (!IsEnabled()) {
 
433
                style = dc.theme->itemDisabledStyle;
 
434
        }
 
435
        int paddingX = 12;
 
436
        dc.SetFontStyle(dc.theme->uiFont);
 
437
 
 
438
        char temp[32];
 
439
        if (zeroLabel_.size() && *value_ == 0) {
 
440
                strcpy(temp, zeroLabel_.c_str());
 
441
        } else {
 
442
                sprintf(temp, fmt_, *value_);
 
443
        }
 
444
 
 
445
        float ignore;
 
446
        dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, temp, &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
 
447
        textPadding_.right += paddingX;
 
448
 
 
449
        Choice::Draw(dc);
 
450
        dc.DrawText(temp, bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
 
451
}
 
452
 
 
453
EventReturn PopupSliderChoiceFloat::HandleClick(EventParams &e) {
 
454
        restoreFocus_ = HasFocus();
 
455
 
 
456
        SliderFloatPopupScreen *popupScreen = new SliderFloatPopupScreen(value_, minValue_, maxValue_, ChopTitle(text_), step_, units_);
 
457
        popupScreen->OnChange.Handle(this, &PopupSliderChoiceFloat::HandleChange);
 
458
        screenManager_->push(popupScreen);
 
459
        return EVENT_DONE;
 
460
}
 
461
 
 
462
EventReturn PopupSliderChoiceFloat::HandleChange(EventParams &e) {
 
463
        e.v = this;
 
464
        OnChange.Trigger(e);
 
465
 
 
466
        if (restoreFocus_) {
 
467
                SetFocusedView(this);
 
468
        }
 
469
        return EVENT_DONE;
 
470
}
 
471
 
 
472
void PopupSliderChoiceFloat::Draw(UIContext &dc) {
 
473
        Style style = dc.theme->itemStyle;
 
474
        if (!IsEnabled()) {
 
475
                style = dc.theme->itemDisabledStyle;
 
476
        }
 
477
        int paddingX = 12;
 
478
        dc.SetFontStyle(dc.theme->uiFont);
 
479
 
 
480
        char temp[32];
 
481
        if (zeroLabel_.size() && *value_ == 0.0f) {
 
482
                strcpy(temp, zeroLabel_.c_str());
 
483
        } else {
 
484
                sprintf(temp, fmt_, *value_);
 
485
        }
 
486
 
 
487
        float ignore;
 
488
        dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, temp, &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
 
489
        textPadding_.right += paddingX;
 
490
 
 
491
        Choice::Draw(dc);
 
492
        dc.DrawText(temp, bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
 
493
}
 
494
 
 
495
EventReturn SliderPopupScreen::OnDecrease(EventParams &params) {
 
496
        if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) {
 
497
                sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f);
 
498
        }
 
499
        sliderValue_ -= step_;
 
500
        slider_->Clamp();
 
501
        changing_ = true;
 
502
        char temp[64];
 
503
        sprintf(temp, "%d", sliderValue_);
 
504
        edit_->SetText(temp);
 
505
        changing_ = false;
 
506
        return EVENT_DONE;
 
507
}
 
508
 
 
509
EventReturn SliderPopupScreen::OnIncrease(EventParams &params) {
 
510
        if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) {
 
511
                sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f);
 
512
        }
 
513
        sliderValue_ += step_;
 
514
        slider_->Clamp();
 
515
        changing_ = true;
 
516
        char temp[64];
 
517
        sprintf(temp, "%d", sliderValue_);
 
518
        edit_->SetText(temp);
 
519
        changing_ = false;
 
520
        return EVENT_DONE;
 
521
}
 
522
 
 
523
EventReturn SliderPopupScreen::OnSliderChange(EventParams &params) {
 
524
        changing_ = true;
 
525
        char temp[64];
 
526
        sprintf(temp, "%d", sliderValue_);
 
527
        edit_->SetText(temp);
 
528
        changing_ = false;
 
529
        return EVENT_DONE;
 
530
}
 
531
 
 
532
EventReturn SliderPopupScreen::OnTextChange(EventParams &params) {
 
533
        if (!changing_) {
 
534
                sliderValue_ = atoi(edit_->GetText().c_str());
 
535
                slider_->Clamp();
 
536
        }
 
537
        return EVENT_DONE;
 
538
}
 
539
 
 
540
void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
 
541
        using namespace UI;
 
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);
 
546
        vert->Add(slider_);
 
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);
 
550
        char temp[64];
 
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);
 
555
        changing_ = false;
 
556
        lin->Add(edit_);
 
557
        if (!units_.empty())
 
558
                lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)));
 
559
 
 
560
        if (IsFocusMovementEnabled())
 
561
                UI::SetFocusedView(slider_);
 
562
}
 
563
 
 
564
void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
 
565
        using namespace UI;
 
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);
 
570
        vert->Add(slider_);
 
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);
 
574
        char temp[64];
 
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);
 
579
        changing_ = false;
 
580
        lin->Add(edit_);
 
581
        if (!units_.empty())
 
582
                lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)));
 
583
 
 
584
        // slider_ = parent->Add(new SliderFloat(&sliderValue_, minValue_, maxValue_, new LinearLayoutParams(UI::Margins(10, 5))));
 
585
        if (IsFocusMovementEnabled())
 
586
                UI::SetFocusedView(slider_);
 
587
}
 
588
 
 
589
EventReturn SliderFloatPopupScreen::OnDecrease(EventParams &params) {
 
590
        if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) {
 
591
                sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f);
 
592
        }
 
593
        sliderValue_ -= step_;
 
594
        slider_->Clamp();
 
595
        changing_ = true;
 
596
        char temp[64];
 
597
        sprintf(temp, "%0.3f", sliderValue_);
 
598
        edit_->SetText(temp);
 
599
        changing_ = false;
 
600
        return EVENT_DONE;
 
601
}
 
602
 
 
603
EventReturn SliderFloatPopupScreen::OnIncrease(EventParams &params) {
 
604
        if (sliderValue_ > minValue_ && sliderValue_ < maxValue_) {
 
605
                sliderValue_ = step_ * floor((sliderValue_ / step_) + 0.5f);
 
606
        }
 
607
        sliderValue_ += step_;
 
608
        slider_->Clamp();
 
609
        changing_ = true;
 
610
        char temp[64];
 
611
        sprintf(temp, "%0.3f", sliderValue_);
 
612
        edit_->SetText(temp);
 
613
        changing_ = false;
 
614
        return EVENT_DONE;
 
615
}
 
616
 
 
617
EventReturn SliderFloatPopupScreen::OnSliderChange(EventParams &params) {
 
618
        changing_ = true;
 
619
        char temp[64];
 
620
        sprintf(temp, "%0.3f", sliderValue_);
 
621
        edit_->SetText(temp);
 
622
        changing_ = false;
 
623
        return EVENT_DONE;
 
624
}
 
625
 
 
626
EventReturn SliderFloatPopupScreen::OnTextChange(EventParams &params) {
 
627
        if (!changing_) {
 
628
                sliderValue_ = atof(edit_->GetText().c_str());
 
629
                slider_->Clamp();
 
630
        }
 
631
        return EVENT_DONE;
 
632
}
 
633
 
 
634
void SliderPopupScreen::OnCompleted(DialogResult result) {
 
635
        if (result == DR_OK) {
 
636
                *value_ = sliderValue_;
 
637
                EventParams e;
 
638
                e.v = 0;
 
639
                e.a = *value_;
 
640
                OnChange.Trigger(e);
 
641
        }
 
642
}
 
643
 
 
644
void SliderFloatPopupScreen::OnCompleted(DialogResult result) {
 
645
        if (result == DR_OK) {
 
646
                *value_ = sliderValue_;
 
647
                EventParams e;
 
648
                e.v = 0;
 
649
                e.a = (int)*value_;
 
650
                e.f = *value_;
 
651
                OnChange.Trigger(e);
 
652
        }
 
653
}
 
654
 
 
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);
 
658
}
 
659
 
 
660
EventReturn PopupTextInputChoice::HandleClick(EventParams &e) {
 
661
        restoreFocus_ = HasFocus();
 
662
 
 
663
        TextEditPopupScreen *popupScreen = new TextEditPopupScreen(value_, placeHolder_, ChopTitle(text_), maxLen_);
 
664
        popupScreen->OnChange.Handle(this, &PopupTextInputChoice::HandleChange);
 
665
        screenManager_->push(popupScreen);
 
666
        return EVENT_DONE;
 
667
}
 
668
 
 
669
void PopupTextInputChoice::Draw(UIContext &dc) {
 
670
        Style style = dc.theme->itemStyle;
 
671
        if (!IsEnabled()) {
 
672
                style = dc.theme->itemDisabledStyle;
 
673
        }
 
674
        int paddingX = 12;
 
675
        dc.SetFontStyle(dc.theme->uiFont);
 
676
 
 
677
        float ignore;
 
678
        dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, value_->c_str(), &textPadding_.right, &ignore, ALIGN_RIGHT | ALIGN_VCENTER);
 
679
        textPadding_.right += paddingX;
 
680
 
 
681
        Choice::Draw(dc);
 
682
        dc.DrawText(value_->c_str(), bounds_.x2() - 12, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
 
683
}
 
684
 
 
685
EventReturn PopupTextInputChoice::HandleChange(EventParams &e) {
 
686
        e.v = this;
 
687
        OnChange.Trigger(e);
 
688
 
 
689
        if (restoreFocus_) {
 
690
                SetFocusedView(this);
 
691
        }
 
692
        return EVENT_DONE;
 
693
}
 
694
 
 
695
void TextEditPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
 
696
        using namespace UI;
 
697
 
 
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_);
 
702
        lin->Add(edit_);
 
703
 
 
704
        if (IsFocusMovementEnabled())
 
705
                UI::SetFocusedView(edit_);
 
706
}
 
707
 
 
708
void TextEditPopupScreen::OnCompleted(DialogResult result) {
 
709
        if (result == DR_OK) {
 
710
                *value_ = edit_->GetText();
 
711
                EventParams e;
 
712
                e.v = edit_;
 
713
                OnChange.Trigger(e);
 
714
        }
 
715
}
 
716
 
 
717
void ChoiceWithValueDisplay::Draw(UIContext &dc) {
 
718
        Style style = dc.theme->itemStyle;
 
719
        if (!IsEnabled()) {
 
720
                style = dc.theme->itemDisabledStyle;
 
721
        }
 
722
        int paddingX = 12;
 
723
        dc.SetFontStyle(dc.theme->uiFont);
 
724
 
 
725
        I18NCategory *category = GetI18NCategory(category_);
 
726
        std::ostringstream valueText;
 
727
        if (sValue_ != nullptr) {
 
728
                if (category)
 
729
                        valueText << category->T(*sValue_);
 
730
                else
 
731
                        valueText << *sValue_;
 
732
        } else if (iValue_ != nullptr) {
 
733
                valueText << *iValue_;
 
734
        }
 
735
 
 
736
        float ignore;
 
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;
 
739
 
 
740
        Choice::Draw(dc);
 
741
        dc.DrawText(valueText.str().c_str(), bounds_.x2() - paddingX, bounds_.centerY(), style.fgColor, ALIGN_RIGHT | ALIGN_VCENTER);
 
742
}
 
743
 
 
744
}  // namespace UI