const GL::Font *const font=style->get_font();
const float font_size=font->get_default_size();
- const Geometry &pgeom=part.get_geometry();
- unsigned gw=pgeom.w;
- unsigned gh=(part.get_fill_y() ? geom.h : pgeom.h);
-
- Geometry rgeom;
+ Geometry rgeom=part.get_geometry();
+ rgeom.x=static_cast<unsigned>(font->get_string_width(text.substr(0, edit_pos))*font_size);
rgeom.w=static_cast<unsigned>(font->get_string_width(text)*font_size);
- rgeom.h=(part.get_fill_y() ? geom.h : pgeom.h);
part.get_alignment().apply(rgeom, geom, part.get_margin());
- rgeom.x+=static_cast<unsigned>(font->get_string_width(text.substr(0, edit_pos))*font_size);
GL::push_matrix();
GL::translate(rgeom.x, rgeom.y, 0);
-
- part.get_graphic(state)->render(gw, gh);
-
+ part.get_graphic(state)->render(part.get_geometry().w, rgeom.h);
GL::pop_matrix();
}
}
void Alignment::apply(Geometry &geom, const Geometry &parent) const
{
+ if(parent.w>geom.w)
+ geom.w+=static_cast<unsigned>((parent.w-geom.w)*w);
+ if(parent.h>geom.h)
+ geom.h+=static_cast<unsigned>((parent.h-geom.h)*h);
+
geom.x+=static_cast<int>((parent.w-geom.w)*x);
geom.y+=static_cast<int>((parent.h-geom.h)*y);
}
void Alignment::apply(Geometry &geom, const Geometry &parent, const Sides &margin) const
{
+ if(parent.w>geom.w)
+ geom.w+=static_cast<unsigned>((parent.w-geom.w)*w);
+ if(parent.h>geom.h)
+ geom.h+=static_cast<unsigned>((parent.h-geom.h)*h);
+
geom.x+=static_cast<int>(margin.left+(parent.w-margin.left-margin.right-geom.w)*x);
geom.y+=static_cast<int>(margin.bottom+(parent.h-margin.bottom-margin.top-geom.h)*y);
}
struct Alignment
{
float x, y;
+ float w, h;
- Alignment(): x(0), y(0) { }
- Alignment(float x_, float y_): x(x_), y(y_) { }
+ Alignment(): x(0), y(0), w(1), h(1) { }
void apply(Geometry &, const Geometry &) const;
void apply(Geometry &, const Geometry &, const Sides &) const;
};
{
if(part.get_name()=="slider")
{
- const Geometry &pgeom=part.get_geometry();
- unsigned gw=pgeom.w;
- unsigned gh=(part.get_fill_y() ? geom.h : pgeom.h);
+ Alignment align=part.get_alignment();
+ align.x=(value-min)/(max-min);
+
+ Geometry pgeom=part.get_geometry();
+ align.apply(pgeom, geom, part.get_margin());
+
GL::push_matrix();
- GL::translate((geom.w-gw)*(value-min)/(max-min), (geom.h-gh)*(part.get_alignment().y+1)/2, 0);
- const Graphic *graphic=part.get_graphic(state);
- graphic->render(gw, gh);
+ GL::translate(pgeom.x, pgeom.y, 0);
+ part.get_graphic(state)->render(pgeom.w, pgeom.h);
GL::pop_matrix();
}
}
/**
Horizontal slider widget. A special part named "slider" will be positioned at
-the current value of the widget. The fill_x attribute is ignored.
+the current value of the widget.
*/
class HSlider: public Slider
{
#include <msp/core/refptr.h>
#include "button.h"
#include "entry.h"
+#include "hslider.h"
#include "label.h"
#include "panel.h"
#include "part.h"
+#include "vslider.h"
using namespace std;
{
add("button", &Loader::child<Button>);
add("entry", &Loader::child<Entry>);
+ add("hslider", &Loader::child<HSlider>);
add("label", &Loader::child<Label>);
add("panel", &Loader::panel);
+ add("vslider", &Loader::child<VSlider>);
}
template<typename T>
namespace GLtk {
Part::Part(const string &n):
- name(n),
- fill_x(true),
- fill_y(true)
+ name(n)
{
for(unsigned i=0; i<N_STATES_; ++i)
graphic[i]=0;
return;
Geometry rgeom=geom;
- if(fill_x)
- rgeom.w=parent.w-margin.left-margin.right;
- if(fill_y)
- rgeom.h=parent.h-margin.bottom-margin.top;
align.apply(rgeom, parent, margin);
GL::translate(rgeom.x, rgeom.y, 0);
graphic[state]->render(rgeom.w, rgeom.h);
part.align.y=y;
}
-void Part::Loader::fill(bool x, bool y)
+void Part::Loader::fill(float w, float h)
{
- part.fill_x=x;
- part.fill_y=y;
+ part.align.w=w;
+ part.align.h=h;
}
void Part::Loader::margin()
private:
void graphic(State, const std::string &);
void align(float, float);
- void fill(bool, bool);
+ void fill(float, float);
void margin();
};
Geometry geom;
Sides margin;
Alignment align;
- bool fill_x;
- bool fill_y;
public:
Part(const std::string &);
const Geometry &get_geometry() const { return geom; }
const Sides &get_margin() const { return margin; }
const Alignment &get_alignment() const { return align; }
- bool get_fill_x() const { return fill_x; }
- bool get_fill_y() const { return fill_y; }
void render(const Geometry &, State) const;
};
typedef std::list<Part> PartSeq;
set_value(value);
}
+
+Slider::Loader::Loader(Slider &s):
+ Widget::Loader(s)
+{
+ add("range", &Slider::min, &Slider::max);
+ add("step", &Slider::step);
+ add("value", &Slider::value);
+}
+
+Slider &Slider::Loader::get_object() const
+{
+ return static_cast<Slider &>(wdg);
+}
+
} // namespace GLtk
} // namespace Msp
/**
Sliders are used to adjust numeric values visually. This class provides the
-common interface for sliders - see classes HSlider and VSlider (NYI) for
-concrete variations.
+common interface for sliders - see classes HSlider and VSlider for concrete
+variations.
*/
class Slider: public Widget
{
+public:
+ class Loader: public Widget::Loader
+ {
+ public:
+ Loader(Slider &);
+ Slider &get_object() const;
+ };
+
protected:
double min, max;
double value;
--- /dev/null
+/* $Id$
+
+This file is part of libmspgltk
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/gl/matrix.h>
+#include <msp/gl/transform.h>
+#include "graphic.h"
+#include "part.h"
+#include "style.h"
+#include "vslider.h"
+
+namespace Msp {
+namespace GLtk {
+
+VSlider::VSlider(const Resources &r):
+ Slider(r),
+ dragging(false)
+{
+ update_style();
+}
+
+void VSlider::button_press(int x, int y, unsigned btn)
+{
+ if(geom.is_inside(x, y))
+ {
+ int sh=get_slider_height();
+ int sy=geom.y+static_cast<int>((geom.h-sh)*(value-min)/(max-min));
+ if(btn==1 && y>=sy && y<sy+sh)
+ {
+ dragging=true;
+ state=ACTIVE;
+ drag_start_y=y;
+ drag_start_value=value;
+ }
+ }
+}
+
+void VSlider::button_release(int, int, unsigned btn)
+{
+ if(btn==1)
+ {
+ dragging=false;
+ state=NORMAL;
+ }
+}
+
+void VSlider::pointer_motion(int, int y)
+{
+ if(dragging)
+ {
+ set_value(drag_start_value+(y-drag_start_y)*(max-min)/(geom.h-get_slider_height()));
+ }
+}
+
+void VSlider::render_special(const Part &part) const
+{
+ if(part.get_name()=="slider")
+ {
+ Alignment align=part.get_alignment();
+ align.y=(value-min)/(max-min);
+
+ Geometry pgeom=part.get_geometry();
+ align.apply(pgeom, geom, part.get_margin());
+
+ GL::push_matrix();
+ GL::translate(pgeom.x, pgeom.y, 0);
+ part.get_graphic(state)->render(pgeom.w, pgeom.h);
+ GL::pop_matrix();
+ }
+}
+
+unsigned VSlider::get_slider_height() const
+{
+ for(PartSeq::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
+ if(i->get_name()=="slider")
+ return i->get_geometry().h;
+
+ return 0;
+}
+
+} // namespace GLtk
+} // namespace Msp
+
--- /dev/null
+/* $Id$
+
+This file is part of libmspgltk
+Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GLTK_VSLIDER_H_
+#define MSP_GLTK_VSLIDER_H_
+
+#include "slider.h"
+
+namespace Msp {
+namespace GLtk {
+
+class VSlider: public Slider
+{
+private:
+ bool dragging;
+ int drag_start_y;
+ double drag_start_value;
+
+public:
+ VSlider(const Resources &);
+ virtual void button_press(int, int, unsigned);
+ virtual void button_release(int, int, unsigned);
+ virtual void pointer_motion(int, int);
+private:
+ virtual const char *get_class() const { return "vslider"; }
+ virtual void render_special(const Part &) const;
+ unsigned get_slider_height() const;
+};
+
+} // namespace GLtk
+} // namespace Msp
+
+#endif