summaryrefslogtreecommitdiff
path: root/LibGUI
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-04-29 19:20:34 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-04-29 19:20:34 +0200
commit9c6be9b21e3da727ef41908f0377cf1547dfc9c3 (patch)
tree20bd887a87710c74903b3b2eb364726e00371156 /LibGUI
parent65f2f19b41f3220f1f6f0f52f09ac7a6bea7a16d (diff)
downloadserenity-9c6be9b21e3da727ef41908f0377cf1547dfc9c3.zip
LibGUI: Add a GSlider widget.
Diffstat (limited to 'LibGUI')
-rw-r--r--LibGUI/GSlider.cpp106
-rw-r--r--LibGUI/GSlider.h40
-rw-r--r--LibGUI/Makefile1
3 files changed, 147 insertions, 0 deletions
diff --git a/LibGUI/GSlider.cpp b/LibGUI/GSlider.cpp
new file mode 100644
index 0000000000..7f053ddf2b
--- /dev/null
+++ b/LibGUI/GSlider.cpp
@@ -0,0 +1,106 @@
+#include <LibGUI/GSlider.h>
+#include <LibGUI/GPainter.h>
+#include <SharedGraphics/StylePainter.h>
+
+GSlider::GSlider(GWidget* parent)
+ : GWidget(parent)
+{
+}
+
+GSlider::~GSlider()
+{
+}
+
+void GSlider::set_range(int min, int max)
+{
+ ASSERT(min <= max);
+ if (m_min == min && m_max == max)
+ return;
+ m_min = min;
+ m_max = max;
+
+ if (m_value > max)
+ m_value = max;
+ if (m_value < min)
+ m_value = min;
+ update();
+}
+
+void GSlider::set_value(int value)
+{
+ if (value > m_max)
+ value = m_max;
+ if (value < m_min)
+ value = m_min;
+ if (m_value == value)
+ return;
+ m_value = value;
+ update();
+
+ if (on_value_changed)
+ on_value_changed(m_value);
+}
+
+void GSlider::paint_event(GPaintEvent& event)
+{
+ GPainter painter(*this);
+ painter.add_clip_rect(event.rect());
+
+ auto inner_rect = this->inner_rect();
+
+ Rect track_rect { inner_rect.x(), 0, inner_rect.width(), track_height() };
+ track_rect.center_vertically_within(inner_rect);
+
+ StylePainter::paint_frame(painter, track_rect, FrameShape::Panel, FrameShadow::Sunken, 1);
+
+ StylePainter::paint_button(painter, knob_rect(), ButtonStyle::Normal, false, false);
+}
+
+Rect GSlider::knob_rect() const
+{
+ auto inner_rect = this->inner_rect();
+ float range_size = m_max - m_min;
+ float adjusted_value = m_value - m_min;
+ float relative_value = adjusted_value / range_size;
+ Rect rect { inner_rect.x() + (int)(relative_value * inner_rect.width()) - knob_width() / 2, 0, knob_width(), knob_height() };
+ rect.center_vertically_within(inner_rect);
+ return rect;
+}
+
+void GSlider::mousedown_event(GMouseEvent& event)
+{
+ if (event.button() == GMouseButton::Left) {
+ if (knob_rect().contains(event.position())) {
+ m_dragging = true;
+ m_drag_origin = event.position();
+ m_drag_origin_value = m_value;
+ return;
+ }
+ }
+
+ return GWidget::mousedown_event(event);
+}
+
+void GSlider::mousemove_event(GMouseEvent& event)
+{
+ if (m_dragging) {
+ float delta = event.position().x() - m_drag_origin.x();
+ float scrubbable_range = inner_rect().width();
+ float value_steps_per_scrubbed_pixel = (m_max - m_min) / scrubbable_range;
+ float new_value = m_drag_origin_value + (value_steps_per_scrubbed_pixel * delta);
+ set_value(new_value);
+ return;
+ }
+
+ return GWidget::mousemove_event(event);
+}
+
+void GSlider::mouseup_event(GMouseEvent& event)
+{
+ if (event.button() == GMouseButton::Left) {
+ m_dragging = false;
+ return;
+ }
+
+ return GWidget::mouseup_event(event);
+}
diff --git a/LibGUI/GSlider.h b/LibGUI/GSlider.h
new file mode 100644
index 0000000000..b90cdb2ed8
--- /dev/null
+++ b/LibGUI/GSlider.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <LibGUI/GWidget.h>
+
+class GSlider : public GWidget {
+public:
+ explicit GSlider(GWidget*);
+ virtual ~GSlider() override;
+
+ int value() const { return m_value; }
+ int min() const { return m_min; }
+ int max() const { return m_max; }
+
+ void set_range(int min, int max);
+ void set_value(int);
+
+ int track_height() const { return 4; }
+ int knob_width() const { return 8; }
+ int knob_height() const { return 20; }
+
+ Rect knob_rect() const;
+ Rect inner_rect() const { return rect().shrunken(20, 0); }
+
+ Function<void(int)> on_value_changed;
+
+protected:
+ virtual void paint_event(GPaintEvent&) override;
+ virtual void mousedown_event(GMouseEvent&) override;
+ virtual void mousemove_event(GMouseEvent&) override;
+ virtual void mouseup_event(GMouseEvent&) override;
+
+private:
+ int m_value { 0 };
+ int m_min { 0 };
+ int m_max { 100 };
+
+ bool m_dragging { false };
+ int m_drag_origin_value { 0 };
+ Point m_drag_origin;
+};
diff --git a/LibGUI/Makefile b/LibGUI/Makefile
index 924a5d3f60..0255d05520 100644
--- a/LibGUI/Makefile
+++ b/LibGUI/Makefile
@@ -52,6 +52,7 @@ LIBGUI_OBJS = \
GSplitter.o \
GSpinBox.o \
GGroupBox.o \
+ GSlider.o \
GWindow.o
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)