diff --git a/Arona/src/widget/misc/slider.h b/Arona/src/widget/misc/slider.h index 6f70f09..d759e26 100644 --- a/Arona/src/widget/misc/slider.h +++ b/Arona/src/widget/misc/slider.h @@ -1 +1,80 @@ #pragma once +#include +#include +#include +#include "spdlog/spdlog.h" + +template +class w_slider : public Gtk::DrawingArea { +public: + explicit w_slider(bool vertical = false); + void set_value(T value) { + value_ = std::clamp(value, min_, max_); + queue_draw(); + } + void set_value_range(T min, T max) { + min_ = min; + max_ = max; + } + + sigc::signal signal_value_changed() { + return signal_value_changed_; + } + const bool is_vertical; +private: + void on_draw(const Cairo::RefPtr& cr, int width, int height); + void on_begin_drag(double x, double y); + void on_drag(double x, double y); + T value_ = T{}; + T min_ = T{}; + T max_ = T{}; + sigc::signal signal_value_changed_; + T begin_drag_value_ = T{}; +}; + +template +void w_slider::on_begin_drag(double x, double y) { + begin_drag_value_ = value_; +} + +template +void w_slider::on_drag(double x, double y) { + if (is_vertical) { + double delta = y / get_allocated_height(); + set_value(begin_drag_value_ - delta); + } else { + double delta = x / get_allocated_width(); + set_value(begin_drag_value_ + delta); + } + signal_value_changed_.emit(value_); +} + +template +w_slider::w_slider(bool vertical) : is_vertical(vertical) { + set_content_height(10); + set_content_width(10); + set_draw_func(sigc::mem_fun(*this, &w_slider::on_draw)); + auto controller = Gtk::GestureDrag::create(); + controller->signal_drag_begin().connect(sigc::mem_fun(*this, &w_slider::on_begin_drag)); + controller->signal_drag_update().connect(sigc::mem_fun(*this, &w_slider::on_drag)); + + add_controller(controller); +} + +template +void w_slider::on_draw(const Cairo::RefPtr &cr, int width, int height) { + // Draw a black rectangle. + cr->set_source_rgba(0.0, 0.0, 0.0, 1.0); + cr->fill(); + + // draw value bar + cr->set_source_rgba(0.0, 1.0, 1.0, 1.0); + if (is_vertical) { + cr->rectangle(0, height * (1 - value_), width, height * value_); + } else { + cr->rectangle(0, 0, width * value_, height); + } + cr->fill(); + + cr->stroke(); +} diff --git a/Arona/src/widget/mixer/w_mixer_track.cpp b/Arona/src/widget/mixer/w_mixer_track.cpp index 3ab6140..02c04ca 100644 --- a/Arona/src/widget/mixer/w_mixer_track.cpp +++ b/Arona/src/widget/mixer/w_mixer_track.cpp @@ -1,6 +1,7 @@ #include "w_mixer_track.h" #include "audio/mixer/mixer_track.h" +#include std::string vertical_text(const std::string& text) { std::string result; @@ -11,13 +12,23 @@ std::string vertical_text(const std::string& text) { return result; } -w_mixer_track::w_mixer_track() : Box(Gtk::Orientation::HORIZONTAL) { +w_mixer_track::w_mixer_track() : Box(Gtk::Orientation::HORIZONTAL), track_(nullptr), volume_scale_(true) { + auto volume_adjustment = Gtk::Adjustment::create(0.0, 0.0, 1.2, 0.01, 0.1, 0.0); + volume_scale_.set_value_range(0.0, 1.2); + volume_scale_.signal_value_changed().connect(sigc::mem_fun(*this, &w_mixer_track::on_volume_scale_value_changed)); + append(volume_scale_); append(audio_buffer_bar_); append(label_); } void w_mixer_track::set_mixer_track(mixer_track* track) { track_ = track; + volume_scale_.set_value(track_->get_volume()); audio_buffer_bar_.set_buffers(track_->ui_buffers); label_.set_text(vertical_text(track_->get_name().c_str())); } + +void w_mixer_track::on_volume_scale_value_changed(float value) { + if (track_) + track_->set_volume(value); +} diff --git a/Arona/src/widget/mixer/w_mixer_track.h b/Arona/src/widget/mixer/w_mixer_track.h index ec08394..037783e 100644 --- a/Arona/src/widget/mixer/w_mixer_track.h +++ b/Arona/src/widget/mixer/w_mixer_track.h @@ -3,6 +3,7 @@ #include #include "widget/misc/w_audio_buffer_bar.h" +#include "widget/misc/slider.h" class mixer_track; @@ -11,7 +12,9 @@ public: w_mixer_track(); void set_mixer_track(mixer_track* track); private: + void on_volume_scale_value_changed(float value); mixer_track* track_; w_audio_buffer_bar audio_buffer_bar_; Gtk::Label label_; + w_slider volume_scale_; };