From ab9fd8084f8bf8770d8d968354550cb2df99192f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 24 Sep 2019 01:10:45 +0300 Subject: [PATCH] Refactor all slider logic into the Slider class Having to write the same logic twice is annoying and more prone to errors. --- source/entry.cpp | 2 +- source/hslider.cpp | 87 ----------------------------------- source/hslider.h | 39 +--------------- source/list.cpp | 1 - source/list.h | 2 +- source/panel.cpp | 3 +- source/slider.cpp | 110 +++++++++++++++++++++++++++++++++++++++------ source/slider.h | 48 +++++++++++++++++--- source/vslider.cpp | 88 ------------------------------------ source/vslider.h | 35 +-------------- 10 files changed, 142 insertions(+), 273 deletions(-) delete mode 100644 source/hslider.cpp delete mode 100644 source/vslider.cpp diff --git a/source/entry.cpp b/source/entry.cpp index 11fd242..83ed563 100644 --- a/source/entry.cpp +++ b/source/entry.cpp @@ -5,8 +5,8 @@ #include "entry.h" #include "graphic.h" #include "part.h" +#include "slider.h" #include "style.h" -#include "vslider.h" using namespace std; diff --git a/source/hslider.cpp b/source/hslider.cpp deleted file mode 100644 index 1b6fadf..0000000 --- a/source/hslider.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include "graphic.h" -#include "hslider.h" -#include "part.h" -#include "style.h" - -namespace Msp { -namespace GLtk { - -HSlider::HSlider(): - total_margin(0) -{ } - -void HSlider::autosize_special(const Part &part, Geometry &ageom) const -{ - if(part.get_name()=="slider") - { - const Sides &margin = part.get_margin(); - const Geometry &pgeom = part.get_geometry(); - ageom.w = std::max(ageom.w, pgeom.w*3/2+margin.left+margin.right); - ageom.h = std::max(ageom.h, pgeom.h+margin.top+margin.bottom); - } -} - -void HSlider::rebuild_special(const Part &part) -{ - if(part.get_name()=="slider") - { - const Graphic *graphic = part.get_graphic(state); - if(!graphic || !graphic->get_texture()) - return; - - Alignment align = part.get_alignment(); - if(max>min) - align.x = (value-min)/(max-min); - - Geometry pgeom = part.get_geometry(); - align.apply(pgeom, geom, part.get_margin()); - - GL::MeshBuilder bld(part_cache.create_mesh(part, *graphic->get_texture())); - bld.matrix() *= GL::Matrix::translation(pgeom.x, pgeom.y, 0); - graphic->build(pgeom.w, pgeom.h, bld); - } -} - -void HSlider::button_press(int x, int, unsigned btn) -{ - if(btn==1 && max>min) - click(x); -} - -void HSlider::button_release(int, int, unsigned btn) -{ - if(btn==1 && dragging) - end_drag(); -} - -void HSlider::pointer_motion(int x, int) -{ - if(dragging) - drag(x); -} - -void HSlider::on_size_change() -{ - drag_area_size = geom.w-total_margin; -} - -void HSlider::on_style_change() -{ - if(!style) - return; - - if(const Part *slider_part = style->get_part("slider")) - { - slider_size = slider_part->get_geometry().w; - const Sides &margin = slider_part->get_margin(); - drag_area_offset = margin.left; - total_margin = margin.left+margin.right; - } - - on_size_change(); -} - -} // namespace GLtk -} // namespace Msp diff --git a/source/hslider.h b/source/hslider.h index 3784a7d..59222eb 100644 --- a/source/hslider.h +++ b/source/hslider.h @@ -1,39 +1,2 @@ -#ifndef MSP_GLTK_HSLIDER_H_ -#define MSP_GLTK_HSLIDER_H_ - +// Deprecated, use slider.h instead #include "slider.h" - -namespace Msp { -namespace GLtk { - -/** -Horizontal slider widget. A special part named "slider" will be positioned at -the current value of the widget. -*/ -class HSlider: public Slider -{ -private: - unsigned total_margin; - -public: - HSlider(); - - virtual const char *get_class() const { return "hslider"; } - -private: - virtual void autosize_special(const Part &, Geometry &) const; - virtual void rebuild_special(const Part &); - -public: - virtual void button_press(int, int, unsigned); - virtual void button_release(int, int, unsigned); - virtual void pointer_motion(int, int); -private: - virtual void on_size_change(); - virtual void on_style_change(); -}; - -} // namespace GLtk -} // namespace Msp - -#endif diff --git a/source/list.cpp b/source/list.cpp index 5493947..13a5619 100644 --- a/source/list.cpp +++ b/source/list.cpp @@ -9,7 +9,6 @@ #include "part.h" #include "style.h" #include "text.h" -#include "vslider.h" using namespace std; diff --git a/source/list.h b/source/list.h index 8b9db40..19fdaa5 100644 --- a/source/list.h +++ b/source/list.h @@ -7,7 +7,7 @@ #include "container.h" #include "label.h" #include "listdata.h" -#include "vslider.h" +#include "slider.h" namespace Msp { namespace GLtk { diff --git a/source/panel.cpp b/source/panel.cpp index c97cd6d..b4f4f5f 100644 --- a/source/panel.cpp +++ b/source/panel.cpp @@ -7,7 +7,6 @@ #include "dropdown.h" #include "entry.h" #include "grid.h" -#include "hslider.h" #include "image.h" #include "indicator.h" #include "label.h" @@ -15,9 +14,9 @@ #include "panel.h" #include "part.h" #include "row.h" +#include "slider.h" #include "stack.h" #include "toggle.h" -#include "vslider.h" using namespace std; diff --git a/source/slider.cpp b/source/slider.cpp index 5034b24..8ff342d 100644 --- a/source/slider.cpp +++ b/source/slider.cpp @@ -1,9 +1,15 @@ +#include +#include +#include "graphic.h" +#include "part.h" #include "slider.h" +#include "style.h" namespace Msp { namespace GLtk { -Slider::Slider(): +Slider::Slider(Direction d): + dir(d), min(0), max(1), value(0), @@ -11,7 +17,8 @@ Slider::Slider(): dragging(false), drag_area_size(0), drag_area_offset(0), - slider_size(1) + slider_size(1), + total_margin(0) { } void Slider::set_value(double v) @@ -48,8 +55,49 @@ void Slider::set_step(double s) set_value(value); } -void Slider::click(int p) +void Slider::autosize_special(const Part &part, Geometry &ageom) const { + if(part.get_name()=="slider") + { + const Sides &margin = part.get_margin(); + const Geometry &pgeom = part.get_geometry(); + ageom.w = std::max(ageom.w, pgeom.w*(dir==HORIZONTAL)/2+margin.left+margin.right); + ageom.h = std::max(ageom.h, pgeom.h*(dir==VERTICAL)/2+margin.top+margin.bottom); + } +} + +void Slider::rebuild_special(const Part &part) +{ + if(part.get_name()=="slider") + { + const Graphic *graphic = part.get_graphic(state); + if(!graphic || !graphic->get_texture()) + return; + + float pos_fraction = ((max>min) ? (value-min)/(max-min) : 0); + + Alignment align = part.get_alignment(); + if(dir==HORIZONTAL) + align.x = pos_fraction; + else + align.y = pos_fraction; + + Geometry rgeom = part.get_geometry(); + align.apply(rgeom, geom, part.get_margin()); + + GL::MeshBuilder bld(part_cache.create_mesh(part, *graphic->get_texture())); + bld.matrix() *= GL::Matrix::translation(rgeom.x, rgeom.y, 0); + graphic->build(rgeom.w, rgeom.h, bld); + } +} + +void Slider::button_press(int x, int y, unsigned btn) +{ + if(btn!=1) + return; + + int p = (dir==HORIZONTAL ? x : y); + p -= drag_area_offset; if(p<0 || p>=static_cast(drag_area_size)) return; @@ -60,27 +108,61 @@ void Slider::click(int p) else if(p>=static_cast(sp+slider_size)) set_value(value+step*10); else - start_drag(drag_area_offset+p); + { + dragging = true; + drag_start_pos = p; + drag_start_value = value; + set_state(ACTIVE); + } } -void Slider::start_drag(int p) +void Slider::button_release(int, int, unsigned btn) { - dragging = true; - drag_start_pos = p; - drag_start_value = value; - set_state(ACTIVE); + if(btn==1 && dragging) + { + dragging = false; + clear_state(ACTIVE); + } } -void Slider::drag(int p) +void Slider::pointer_motion(int x, int y) { - if(max>min) + if(dragging && max>min) + { + int p = (dir==HORIZONTAL ? x : y); set_value(drag_start_value+(p-drag_start_pos)*(max-min)/(drag_area_size-slider_size)); + } } -void Slider::end_drag() +void Slider::on_size_change() { - dragging = false; - clear_state(ACTIVE); + drag_area_size = (dir==HORIZONTAL ? geom.w : geom.h)-total_margin; +} + +void Slider::on_style_change() +{ + if(!style) + return; + + if(const Part *slider_part = style->get_part("slider")) + { + const Geometry &pgeom = slider_part->get_geometry(); + const Sides &margin = slider_part->get_margin(); + if(dir==HORIZONTAL) + { + slider_size = pgeom.w; + drag_area_offset = margin.left; + total_margin = margin.left+margin.right; + } + else + { + slider_size = pgeom.h; + drag_area_offset = margin.bottom; + total_margin = margin.bottom+margin.top; + } + } + + on_size_change(); } diff --git a/source/slider.h b/source/slider.h index a95a6a5..b6041af 100644 --- a/source/slider.h +++ b/source/slider.h @@ -9,8 +9,8 @@ namespace GLtk { /** Sliders are used to adjust numeric values visually. This class provides the -common interface for sliders - see classes HSlider and VSlider for concrete -variations. +common interface and logic for sliders but can't be instantiated. Use HSlider +or VSlider depending on which direction you want the slider to be in. */ class Slider: public Widget { @@ -21,9 +21,18 @@ public: Loader(Slider &); }; +protected: + enum Direction + { + HORIZONTAL, + VERTICAL + }; + +public: sigc::signal signal_value_changed; protected: + Direction dir; double min, max; double value; double step; @@ -34,8 +43,9 @@ protected: unsigned drag_area_size; unsigned drag_area_offset; unsigned slider_size; + unsigned total_margin; - Slider(); + Slider(Direction); public: void set_value(double); @@ -44,10 +54,34 @@ public: double get_value() const { return value; } protected: - void click(int); - void start_drag(int); - void drag(int); - void end_drag(); + virtual void autosize_special(const Part &, Geometry &) const; + virtual void rebuild_special(const Part &); + +public: + virtual void button_press(int, int, unsigned); + virtual void button_release(int, int, unsigned); + virtual void pointer_motion(int, int); + +protected: + virtual void on_size_change(); + virtual void on_style_change(); +}; + + +class VSlider: public Slider +{ +public: + VSlider(): Slider(VERTICAL) { } + + virtual const char *get_class() const { return "vslider"; } +}; + +class HSlider: public Slider +{ +public: + HSlider(): Slider(HORIZONTAL) { } + + virtual const char *get_class() const { return "hslider"; } }; } // namespace GLtk diff --git a/source/vslider.cpp b/source/vslider.cpp deleted file mode 100644 index cb345bb..0000000 --- a/source/vslider.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include "graphic.h" -#include "part.h" -#include "style.h" -#include "vslider.h" - -namespace Msp { -namespace GLtk { - -VSlider::VSlider(): - total_margin(0) -{ } - -void VSlider::autosize_special(const Part &part, Geometry &ageom) const -{ - if(part.get_name()=="slider") - { - const Sides &margin = part.get_margin(); - const Geometry &pgeom = part.get_geometry(); - ageom.w = std::max(ageom.w, pgeom.w+margin.left+margin.right); - ageom.h = std::max(ageom.h, pgeom.h*3/2+margin.top+margin.bottom); - } -} - -void VSlider::rebuild_special(const Part &part) -{ - if(part.get_name()=="slider") - { - const Graphic *graphic = part.get_graphic(state); - if(!graphic || !graphic->get_texture()) - return; - - Alignment align = part.get_alignment(); - if(max>min) - align.y = (value-min)/(max-min); - - Geometry pgeom = part.get_geometry(); - align.apply(pgeom, geom, part.get_margin()); - - GL::MeshBuilder bld(part_cache.create_mesh(part, *graphic->get_texture())); - bld.matrix() *= GL::Matrix::translation(pgeom.x, pgeom.y, 0); - graphic->build(pgeom.w, pgeom.h, bld); - } -} - -void VSlider::button_press(int, int y, unsigned btn) -{ - if(btn==1 && max>min) - click(y); -} - -void VSlider::button_release(int, int, unsigned btn) -{ - if(btn==1 && dragging) - end_drag(); -} - -void VSlider::pointer_motion(int, int y) -{ - if(dragging) - drag(y); -} - -void VSlider::on_size_change() -{ - drag_area_size = geom.h-total_margin; -} - -void VSlider::on_style_change() -{ - if(!style) - return; - - if(const Part *slider_part = style->get_part("slider")) - { - slider_size = slider_part->get_geometry().h; - const Sides &margin = slider_part->get_margin(); - drag_area_offset = margin.bottom; - total_margin = margin.bottom+margin.top; - } - - on_size_change(); -} - -} // namespace GLtk -} // namespace Msp - diff --git a/source/vslider.h b/source/vslider.h index 96fd03f..59222eb 100644 --- a/source/vslider.h +++ b/source/vslider.h @@ -1,35 +1,2 @@ -#ifndef MSP_GLTK_VSLIDER_H_ -#define MSP_GLTK_VSLIDER_H_ - +// Deprecated, use slider.h instead #include "slider.h" - -namespace Msp { -namespace GLtk { - -class VSlider: public Slider -{ -private: - unsigned total_margin; - -public: - VSlider(); - - virtual const char *get_class() const { return "vslider"; } - -private: - virtual void autosize_special(const Part &, Geometry &) const; - virtual void rebuild_special(const Part &); - -public: - virtual void button_press(int, int, unsigned); - virtual void button_release(int, int, unsigned); - virtual void pointer_motion(int, int); -private: - virtual void on_size_change(); - virtual void on_style_change(); -}; - -} // namespace GLtk -} // namespace Msp - -#endif -- 2.43.0