X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fslider.cpp;h=29f906766ea52c087bb25a707ebc248677aa456a;hb=9678abb23abe450109e2feda081f5bba5f20cc94;hp=11e4c24dc6461c0c49910b030ee18a7a6240a00d;hpb=bcdbb414c5f1abe860cad6bb67fd5da7c0122cfd;p=libs%2Fgltk.git diff --git a/source/slider.cpp b/source/slider.cpp index 11e4c24..29f9067 100644 --- a/source/slider.cpp +++ b/source/slider.cpp @@ -1,45 +1,187 @@ +#include +#include +#include "graphic.h" +#include "part.h" #include "slider.h" +#include "style.h" namespace Msp { namespace GLtk { -Slider::Slider(const Resources &r): - Widget(r), - min(0), - max(1), - value(0), - step(0.1) +Slider::Slider(Direction d): + dir(d) { } +void Slider::set_value(double v) +{ + double old_value = value; + + if(vmax) + value = max; + else + { + unsigned steps = static_cast((v-min)/step+0.5); + value = min+steps*step; + } + + if(value!=old_value) + { + signal_value_changed.emit(value); + mark_rebuild(); + } +} + void Slider::set_range(double a, double b) { - min=a; - max=b; + min = a; + max = b; set_value(value); } void Slider::set_step(double s) { - step=s; + step = s; set_value(value); } -void Slider::set_value(double v) +void Slider::set_page_size(double p) { - double old_value=value; + page_size = p; + mark_rebuild(); +} - if(vmax) - value=max; +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); + float fill_fraction = ((max>min) ? page_size/(max-min+page_size) : 1); + + Alignment align = part.get_alignment(); + Geometry sgeom = geom; + if(dir==HORIZONTAL) + { + align.x = pos_fraction; + sgeom.w = std::max(slider_min_size+total_margin, static_cast(sgeom.w*fill_fraction)); + } + else + { + align.y = pos_fraction; + sgeom.h = std::max(slider_min_size+total_margin, static_cast(sgeom.h*fill_fraction)); + } + + sgeom.x = static_cast((geom.w-sgeom.w)*pos_fraction); + sgeom.y = static_cast((geom.h-sgeom.h)*pos_fraction); + + Geometry rgeom = part.get_geometry(); + align.apply(rgeom, sgeom, part.get_margin()); + slider_size = (dir==HORIZONTAL ? rgeom.w : rgeom.h); + + GL::MeshBuilder bld(part_cache.create_mesh(part, *graphic->get_texture())); + bld.transform(GL::Matrix::translation(sgeom.x+rgeom.x, sgeom.y+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; + + int sp = static_cast((drag_area_size-slider_size)*(value-min)/(max-min)); + if(p=static_cast(sp+slider_size)) + set_value(value+page_size); else { - unsigned steps=static_cast((v-min)/step+0.5); - value=min+steps*step; + dragging = true; + drag_start_pos = p; + drag_start_value = value; + set_state(ACTIVE); } +} - if(value!=old_value) - signal_value_changed.emit(value); +void Slider::button_release(int, int, unsigned btn) +{ + if(btn==1 && dragging) + { + dragging = false; + clear_state(ACTIVE); + } +} + +void Slider::pointer_motion(int x, int y) +{ + 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::on_size_change() +{ + 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->find_part("slider")) + { + const Geometry &pgeom = slider_part->get_geometry(); + const Sides &margin = slider_part->get_margin(); + if(dir==HORIZONTAL) + { + slider_min_size = pgeom.w; + drag_area_offset = margin.left; + total_margin = margin.left+margin.right; + } + else + { + slider_min_size = pgeom.h; + drag_area_offset = margin.bottom; + total_margin = margin.bottom+margin.top; + } + } + + on_size_change(); +} + + +Slider::Loader::Loader(Slider &s): + DataFile::DerivedObjectLoader(s) +{ + add("range", &Slider::min, &Slider::max); + add("step", &Slider::step); + add("page_size", &Slider::page_size); + add("value", &Slider::value); } } // namespace GLtk