diff --git a/Telegram/SourceFiles/info/bot/starref/info_bot_starref_setup_widget.cpp b/Telegram/SourceFiles/info/bot/starref/info_bot_starref_setup_widget.cpp index fc7e4605c..5753e2c24 100644 --- a/Telegram/SourceFiles/info/bot/starref/info_bot_starref_setup_widget.cpp +++ b/Telegram/SourceFiles/info/bot/starref/info_bot_starref_setup_widget.cpp @@ -104,6 +104,126 @@ private: }; } +[[nodiscard]] object_ptr MakeSliderWithTopTag( + QWidget *parent, + not_null sliderStyle, + not_null labelStyle, + int valuesCount, + Fn valueByIndex, + int value, + Fn valueProgress, + Fn valueFinished, + Fn textByValue) { + auto result = object_ptr(parent); + const auto raw = result.data(); + + const auto labels = raw->add(object_ptr(raw)); + const auto min = Ui::CreateChild( + raw, + textByValue(valueByIndex(0)), + *labelStyle); + const auto max = Ui::CreateChild( + raw, + textByValue(valueByIndex(valuesCount - 1)), + *labelStyle); + const auto current = Ui::CreateChild( + raw, + textByValue(value), + *labelStyle); + const auto slider = raw->add(object_ptr( + raw, + *sliderStyle)); + labels->resize(labels->width(), current->height()); + struct State { + int index = 0; + }; + const auto state = raw->lifetime().make_state(State{ 0 }); + const auto updatePalette = [=] { + min->setTextColorOverride(!state->index + ? st::windowActiveTextFg->c + : st::windowSubTextFg->c); + max->setTextColorOverride((state->index == valuesCount - 1) + ? st::windowActiveTextFg->c + : st::windowSubTextFg->c); + current->setTextColorOverride(st::windowActiveTextFg->c); + }; + const auto updateByIndex = [=] { + updatePalette(); + + current->setVisible(state->index > 0 + && state->index < valuesCount - 1); + const auto outer = labels->width(); + const auto minWidth = min->width(); + const auto maxWidth = max->width(); + const auto currentWidth = current->width(); + if (minWidth + maxWidth + currentWidth > outer) { + return; + } + + min->moveToLeft(0, 0, outer); + max->moveToRight(0, 0, outer); + + const auto sliderSkip = sliderStyle->seekSize.width(); + const auto availableForCurrent = outer - sliderSkip; + const auto ratio = state->index / float64(valuesCount - 1); + const auto desiredLeft = (sliderSkip / 2) + + availableForCurrent * ratio + - (currentWidth / 2); + const auto minLeft = minWidth; + const auto maxLeft = outer - maxWidth - currentWidth; + current->moveToLeft( + std::clamp(int(base::SafeRound(desiredLeft)), minLeft, maxLeft), + 0, + outer); + }; + const auto updateByValue = [=](int value) { + current->setText(textByValue(value)); + + state->index = 0; + auto maxIndex = valuesCount - 1; + while (state->index < maxIndex) { + const auto mid = (state->index + maxIndex) / 2; + const auto midValue = valueByIndex(mid); + if (midValue == value) { + state->index = mid; + break; + } else if (midValue < value) { + state->index = mid + 1; + } else { + maxIndex = mid - 1; + } + } + updateByIndex(); + }; + const auto progress = [=](int value) { + updateByValue(value); + valueProgress(value); + }; + const auto finished = [=](int value) { + updateByValue(value); + valueFinished(value); + }; + style::PaletteChanged() | rpl::start_with_next([=] { + updatePalette(); + }, raw->lifetime()); + updateByValue(value); + + slider->setPseudoDiscrete( + valuesCount, + valueByIndex, + value, + progress, + finished); + slider->resize(slider->width(), sliderStyle->seekSize.height()); + + raw->widthValue() | rpl::start_with_next([=](int width) { + labels->resizeToWidth(width); + updateByIndex(); + }, slider->lifetime()); + + return result; +} + InnerWidget::InnerWidget(QWidget *parent, not_null controller) : RpWidget(parent) , _controller(controller) @@ -165,36 +285,21 @@ void InnerWidget::setupCommission() { } } const auto valuesCount = int(values.size()); - - auto sliderWithLabel = ::Settings::MakeSliderWithLabel( - _container, - st::settingsScale, - st::settingsScaleLabel, - st::normalFont->spacew * 2, - st::settingsScaleLabel.style.font->width("89.9%"), - true); - _container->add( - std::move(sliderWithLabel.widget), - st::settingsBigScalePadding); - const auto slider = sliderWithLabel.slider; - const auto label = sliderWithLabel.label; - - const auto updateLabel = [=](int value) { - const auto labelText = QString::number(value / 10.) + '%'; - label->setText(labelText); - }; const auto setCommission = [=](int value) { _state.program.commission = value; - updateLabel(value); }; - updateLabel(commission); - - slider->setPseudoDiscrete( - valuesCount, - [=](int index) { return values[index]; }, - commission, - setCommission, - setCommission); + _container->add( + MakeSliderWithTopTag( + _container, + &st::settingsScale, + &st::settingsScaleLabel, + valuesCount, + [=](int index) { return values[index]; }, + commission, + setCommission, + setCommission, + [=](int value) { return QString::number(value / 10.) + '%'; }), + st::boxRowPadding); Ui::AddSkip(_container); Ui::AddDividerText(_container, tr::lng_star_ref_commission_about()); @@ -233,7 +338,7 @@ void InnerWidget::setupDuration() { _state.program.durationMonths = (value == kDurationForeverValue) ? 0 : value; - updateLabel(durationMonths); + updateLabel(value); }; updateLabel(durationMonths);