#include "slider.hpp" LooperSlider::LooperSlider(const char *name, const char *label, double min, double max, double tick, bool logarithmic) : QWidget() { root_layout = new QBoxLayout(QBoxLayout::LeftToRight, this); text_layout_view = new QBoxLayout(QBoxLayout::TopToBottom); QWidget *text_layout_widget = new QWidget(); text_layout_widget->setLayout(text_layout_view); root_layout->addWidget(text_layout_widget); text_label = new QLabel(); slider = new _looperSlider(Qt::Orientation::Horizontal); slider->connect(slider, &_looperSlider::mousePressed, [=,this]() { pressed = true; slider_value_changed_after_release = false; emit(mousePressed()); }); slider->connect(slider, &_looperSlider::mouseReleased, [=,this]() { emit(mouseReleased()); pressed = false; }); slider->connect(slider, &QSlider::valueChanged, [=,this](int value) { if (slider_value_updating) return; double actual_value = value * tick; if (logarithmic) actual_value = scaler->unscale_log(actual_value); this->SetValue(actual_value); emit(changed(actual_value)); slider_value_changed_after_release = true; }); text_layout_view->addWidget(slider); btn = new QPushButton(); btn->connect(btn, &QPushButton::pressed, [=,this]() { SwitchModes(); }); root_layout->addWidget(btn); text = new QLineEdit(); text->setVisible(false); text_layout_view->addWidget(text); text->connect(text, &QLineEdit::textChanged, [=,this]() { const char *value = text->text().toLocal8Bit().constData(); bool ok = true; double output = this->Value(); try { output = std::stod(value); } catch (std::exception) { ok = false; } if (ok) { textChanged = true; emit(changed(output)); this->SetValue(output); } }); limits_view = new QBoxLayout(QBoxLayout::LeftToRight); min_label_view = new QLabel(); limits_view->addWidget(min_label_view, 0, Qt::Alignment::enum_type::AlignLeft); max_label_view = new QLabel(); limits_view->addWidget(max_label_view, 0, Qt::Alignment::enum_type::AlignRight); scaler = new LooperLogScaler(min, max); set_min(min); set_max(max); set_tick(tick); set_logarithmic(logarithmic); this->label = strdup(label); this->value = min; UpdateSlider(true); } bool LooperSlider::IsPressed() { return pressed; } double LooperSlider::Value() { return value; } void LooperSlider::set_value(double value) { if (!pressed && slider_value_changed_after_release) this->value = value; this->UpdateSlider(true); } void LooperSlider::SetValue(double value) { set_value(value); } void LooperSlider::set_min(double min) { settings_changed = true; this->min = min; } void LooperSlider::set_max(double max) { settings_changed = true; this->max = max; } void LooperSlider::set_logarithmic(bool logarithmic) { settings_changed = true; this->logarithmic = true; } void LooperSlider::UpdateLogScaler() { this->scaler->update_min_max(this->min, this->max); } void LooperSlider::SetMin(double min) { this->set_min(min); UpdateSlider(false); } void LooperSlider::SetMax(double max) { this->set_max(max); UpdateSlider(false); } double LooperSlider::Min() { return this->min; } double LooperSlider::Max() { return this->max; } void LooperSlider::SetLimits(double min, double max) { set_min(min); set_max(max); UpdateSlider(false); } void LooperSlider::SetMinLabel(const char *label) { if (this->min_label) free((void*)this->min_label); this->min_label = strdup(label); UpdateSlider(); } void LooperSlider::SetMaxLabel(const char *label) { if (this->max_label) free((void*)this->max_label); this->max_label = strdup(label); UpdateSlider(); } void LooperSlider::SetLimitLabels(const char *min, const char *max) { SetMinLabel(min); SetMaxLabel(max); } LooperSlider::~LooperSlider() { if (this->min_label) free((void*)this->min_label); if (this->max_label) free((void*)this->max_label); if (this->label) free((void*)this->label); } const char *LooperSlider::MinLabel() { return this->min_label; } const char *LooperSlider::MaxLabel() { return this->max_label; } void LooperSlider::SetLogarithmic(bool logarithmic) { set_logarithmic(logarithmic); UpdateSlider(false); } bool LooperSlider::IsLogarithmic() { return this->logarithmic; } void LooperSlider::SetLabel(const char *label) { if (this->label) free((void*)this->label); this->label = strdup(label); } const char *LooperSlider::Label() { return this->label; } double LooperSlider::Tick() { return this->tick; } void LooperSlider::SetMode(bool use_text_editor) { this->text_edit_mode = use_text_editor; UpdateSlider(true); } void LooperSlider::EnableModeButton(bool enabled) { btn->setVisible(enabled); } void LooperSlider::SetTick(double value) { set_tick(value); UpdateSlider(false); } void LooperSlider::set_tick(double value) { this->settings_changed = true; this->tick = value; } void LooperSlider::UpdateSlider(bool update_value) { UpdateLogScaler(); if (this->min_label == NULL) { this->min_label_view->setText(""); } else { this->min_label_view->setText(this->min_label); } if (this->max_label == NULL) { this->max_label_view->setText(""); } else { this->max_label_view->setText(this->max_label); } limits_visible = (this->min_label == NULL && this->max_label == NULL); if (limits_visible) { if (!limits_actually_visible) { this->text_layout_view->addItem(this->limits_view); limits_actually_visible = true; } } else { if (limits_actually_visible) { this->text_layout_view->removeItem(this->limits_view); limits_actually_visible = false; } } if (this->label == NULL) { if (text_label_visible) { this->text_layout_view->removeWidget(this->text_label); text_label_visible = false; } } else { this->text_label->setText(this->label); if (!text_label_visible) { this->text_layout_view->insertWidget(0, this->text_label); text_label_visible = true; } } if (this->text_edit_mode) { if (!text_editor_visible) { this->text_layout_view->insertWidget(1, this->text); text_editor_visible = true; } if (slider_visible) { this->text_layout_view->removeWidget(this->slider); slider_visible = false; } } else { if (!slider_visible) { this->text_layout_view->insertWidget(1, this->slider); slider_visible = true; } if (text_editor_visible) { this->text_layout_view->removeWidget(this->text); text_editor_visible = false; } } auto icon = QIcon::fromTheme(text_edit_mode ? "slider_edit_mode" : "text_edit_mode", QIcon::fromTheme(text_edit_mode ? "dialog-ok" : "edit")); auto text = text_edit_mode ? "Imprecise" : "Precise"; if (icon.isNull() || show_button_text) { this->btn->setText(text); } else { this->btn->setText(""); } if (show_button_icon && !icon.isNull()) { this->btn->setIcon(icon); } else { QIcon emptyIcon; this->btn->setIcon(emptyIcon); } this->slider->setVisible(slider_visible); this->text->setVisible(text_editor_visible); this->text_label->setVisible(text_label_visible); this->min_label_view->setVisible(limits_actually_visible); this->max_label_view->setVisible(limits_actually_visible); if (update_value) { if (textChanged) { textChanged = false; } else { if (!pressed && !text_edit_mode) this->text->setText(fmt::to_string(this->value).c_str()); } slider_value_updating = true; if (!pressed && slider_value_changed_after_release) { this->slider->setValue(this->logarithmic ? (this->scaler->scale_log(this->value) / this->tick) : (this->value / this->tick)); this->slider->setMinimum(this->min / tick); this->slider->setMaximum(this->max / tick); } slider_value_updating = false; } } bool LooperSlider::ShowButtonText() { return show_button_text; } bool LooperSlider::ShowButtonIcon() { return show_button_icon; } void LooperSlider::SetShowButtonIcon(bool enable) { this->show_button_icon = enable; UpdateSlider(); } void LooperSlider::SetShowButtonText(bool enable) { this->show_button_text = enable; UpdateSlider(); } void LooperSlider::changeEvent(QEvent *event) { if (event->type() == QEvent::EnabledChange) { this->slider->setEnabled(isEnabled()); this->text->setEnabled(isEnabled()); } }