+++ /dev/null
-/* $Id$
-
-This file is part of libmspgltk
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <msp/gl/transform.h>
-#include "alignment.h"
-#include "geometry.h"
-
-namespace Msp {
-namespace GLtk {
-
-void Alignment::apply(const Geometry &geom, unsigned wd, unsigned ht) const
-{
- GL::translate((geom.w-wd)*(x+1)/2, (geom.h-ht)*(y+1)/2, 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_ALIGNMENT_H_
-#define MSP_GLTK_ALIGNMENT_H_
-
-namespace Msp {
-namespace GLtk {
-
-class Geometry;
-
-/**
-Handles alignment of widget parts. Both x and y components can have values -1
-(left / bottom), 0 (center) or 1 (right / top).
-*/
-struct Alignment
-{
- int x, y;
-
- Alignment(): x(0), y(0) { }
- Alignment(int x_, int y_): x(x_), y(y_) { }
- void apply(const Geometry &, unsigned, unsigned) const;
-};
-
-} // namespace GLtk
-} // namespace Msp
-
-#endif
{
if(geom.is_inside(x, y))
{
- signal_clicked.emit();
state=HOVER;
+ signal_clicked.emit();
}
else
state=NORMAL;
state=NORMAL;
}
-void Button::render_part(const Part &part) const
+void Button::render_special(const Part &part) const
{
if(part.get_name()=="text")
render_text(part, text);
- else
- Widget::render_part(part);
}
virtual void pointer_leave();
private:
virtual const char *get_class() const { return "button"; }
- virtual void render_part(const Part &) const;
+ virtual void render_special(const Part &) const;
};
} // namespace GLtk
Distributed under the LGPL
*/
-#include <SDL/SDL_keysym.h>
#include <msp/gl/matrix.h>
#include <msp/gl/texture.h>
#include <msp/gl/transform.h>
#include "entry.h"
+#include "graphic.h"
#include "part.h"
#include "style.h"
void Entry::key_press(unsigned key, unsigned, wchar_t ch)
{
- if(key==SDLK_LEFT)
+ if(key==100)
{
if(edit_pos>0)
--edit_pos;
}
- else if(key==SDLK_RIGHT)
+ else if(key==102)
{
if(edit_pos<text.size())
++edit_pos;
}
- else if(key==SDLK_BACKSPACE)
+ else if(key==22)
{
if(edit_pos>0)
text.erase(--edit_pos, 1);
else
{
text+=ch;
+ ++edit_pos;
}
}
state=NORMAL;
}
-void Entry::render_part(const Part &part) const
+void Entry::render_special(const Part &part) const
{
if(part.get_name()=="text")
render_text(part, text);
- /*{
- const GL::Font *const font=style->get_font();
+ else if(part.get_name()=="cursor")
+ {
+ if(!part.get_graphic(state))
+ return;
+ const GL::Font *const font=style->get_font();
const float font_size=font->get_default_size();
- unsigned text_w=static_cast<unsigned>(font->get_string_width(text)*font_size);
- GL::push_matrix();
+ const Geometry &pgeom=part.get_geometry();
+ unsigned gw=pgeom.w;
+ unsigned gh=(part.get_fill_y() ? geom.h : pgeom.h);
- part.get_alignment().apply(geom, text_w, static_cast<unsigned>(font->get_ascent()*font_size));
- GL::scale_uniform(font_size);
-
- const Color &color=style->get_font_color();
- glColor3f(color.r, color.g, color.b);
- if(state==ACTIVE)
- {
- cout<<"foo\n";
- font->draw_string(text.substr(0, edit_pos));
- GL::Texture::unbind();
- glBegin(GL_LINES);
- glVertex2f(0, 0);
- glVertex2f(0, 1);
- glEnd();
- font->draw_string(text.substr(edit_pos));
- }
- else
- font->draw_string(text);
- glColor3f(1, 1, 1);
+ Geometry rgeom;
+ 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::pop_matrix();
- render_text(part, text);
- }*/
- /*else if(part.get_name()=="cursor")
- {
- unsigned gw=part.get_width();
- unsigned gh=(part.get_fill_y() ? geom.h : part.get_height());
+ GL::push_matrix();
+ GL::translate(rgeom.x, rgeom.y, 0);
- const float font_size=font->get_default_size();
- unsigned text_w=static_cast<unsigned>(font->get_string_width(text)*font_size);
+ part.get_graphic(state)->render(gw, gh);
- 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::pop_matrix();
- }*/
- else
- Widget::render_part(part);
+ }
}
+
+Entry::Loader::Loader(Entry &ent):
+ Widget::Loader(ent)
+{ }
+
} // namespace GLtk
} // namespace Msp
*/
class Entry: public Widget
{
+public:
+ class Loader: public Widget::Loader
+ {
+ public:
+ Loader(Entry &);
+ };
+
private:
std::string text;
unsigned edit_pos;
virtual void focus_out();
private:
virtual const char *get_class() const { return "entry"; }
- virtual void render_part(const Part &) const;
+ virtual void render_special(const Part &) const;
};
} // namespace GLtk
add("left", &Sides::left);
}
+
+void Alignment::apply(Geometry &geom, const Geometry &parent) const
+{
+ 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
+{
+ 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);
+}
+
} // namespace GLtk
} // namespace Msp
bool is_inside(int, int) const;
};
+
/**
Specifies margins on the sides of an element.
*/
Sides();
};
+
+/**
+Performs alignment of nested geometries, such as widgets and their parts.
+*/
+struct Alignment
+{
+ float x, y;
+
+ Alignment(): x(0), y(0) { }
+ Alignment(float x_, float y_): x(x_), y(y_) { }
+ void apply(Geometry &, const Geometry &) const;
+ void apply(Geometry &, const Geometry &, const Sides &) const;
+};
+
} // namespace GLtk
} // namespace Msp
}
}
-void HSlider::render_part(const Part &part) const
+void HSlider::render_special(const Part &part) const
{
if(part.get_name()=="slider")
{
- unsigned gw=part.get_width();
- unsigned gh=(part.get_fill_y() ? geom.h : part.get_height());
+ const Geometry &pgeom=part.get_geometry();
+ unsigned gw=pgeom.w;
+ unsigned gh=(part.get_fill_y() ? geom.h : pgeom.h);
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::pop_matrix();
}
- else
- Widget::render_part(part);
}
unsigned HSlider::get_slider_width() const
{
for(PartSeq::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
if(i->get_name()=="slider")
- return i->get_width();
+ return i->get_geometry().w;
return 0;
}
virtual void pointer_motion(int, int);
private:
virtual const char *get_class() const { return "hslider"; }
- virtual void render_part(const Part &) const;
+ virtual void render_special(const Part &) const;
unsigned get_slider_width() const;
};
text=t;
}
-void Label::render_part(const Part &part) const
+void Label::render_special(const Part &part) const
{
if(part.get_name()=="text")
render_text(part, text);
- else
- Widget::render_part(part);
}
private:
virtual const char *get_class() const { return "label"; }
- virtual void render_part(const Part &) const;
+ virtual void render_special(const Part &) const;
};
} // namespace GLtk
#include <msp/core/refptr.h>
#include "button.h"
+#include "entry.h"
#include "label.h"
#include "panel.h"
#include "part.h"
{
if(Widget *wdg=get_child_at(x, y))
{
- wdg->button_press(x-geom.x, y-geom.y, btn);
- pointer_grab=btn;
+ set_pointer_focus(wdg, btn);
set_input_focus(wdg);
+
+ wdg->button_press(x-geom.x, y-geom.y, btn);
}
}
}
pointer_focus->button_release(x-geom.x, y-geom.y, btn);
if(btn==pointer_grab)
- {
- pointer_grab=0;
-
- set_pointer_focus(get_child_at(x, y));
- }
+ set_pointer_focus(get_child_at(x, y), 0);
}
else if(geom.is_inside(x, y))
{
else if(geom.is_inside(x, y))
{
Widget *wdg=get_child_at(x, y);
- set_pointer_focus(wdg);
+ set_pointer_focus(wdg, 0);
if(wdg)
wdg->pointer_motion(x-geom.x, y-geom.y);
}
}
+void Panel::pointer_leave()
+{
+ set_pointer_focus(0, 0);
+}
+
void Panel::key_press(unsigned key, unsigned mod, wchar_t ch)
{
if(input_focus)
set_input_focus(0);
}
-void Panel::render_part(const Part &part) const
+void Panel::child_hidden(Widget &wdg)
+{
+ if(&wdg==pointer_focus)
+ set_pointer_focus(0, 0);
+}
+
+void Panel::render_special(const Part &part) const
{
if(part.get_name()=="children")
{
if((*i)->is_visible())
(*i)->render();
}
- else
- Widget::render_part(part);
}
-void Panel::set_pointer_focus(Widget *wdg)
+void Panel::set_pointer_focus(Widget *wdg, int grab)
{
- if(wdg!=pointer_focus && pointer_grab==0)
+ if(grab>0 && !wdg)
+ throw InvalidParameterValue("Can't grab on null widget");
+
+ if(wdg!=pointer_focus)
{
if(pointer_focus)
pointer_focus->pointer_leave();
if(pointer_focus)
pointer_focus->pointer_enter();
}
+
+ pointer_grab=grab;
}
void Panel::set_input_focus(Widget *wdg)
wdg_map(m)
{
add("button", &Loader::child<Button>);
+ add("entry", &Loader::child<Entry>);
add("label", &Loader::child<Label>);
add("panel", &Loader::panel);
}
virtual void button_press(int, int, unsigned);
virtual void button_release(int, int, unsigned);
virtual void pointer_motion(int, int);
+ virtual void pointer_leave();
virtual void key_press(unsigned, unsigned, wchar_t);
virtual void key_release(unsigned, unsigned);
virtual void focus_out();
+ void child_hidden(Widget &);
private:
virtual const char *get_class() const { return "panel"; }
- virtual void render_part(const Part &) const;
- void set_pointer_focus(Widget *);
+ virtual void render_special(const Part &) const;
+ void set_pointer_focus(Widget *, int);
void set_input_focus(Widget *);
Widget *get_child_at(int, int);
};
Distributed under the LGPL
*/
+#include <msp/gl/transform.h>
#include "geometry.h"
#include "part.h"
#include "resources.h"
Part::Part(const string &n):
name(n),
- width(1),
- height(1),
fill_x(true),
fill_y(true)
{
return graphic[state];
}
-void Part::render(const Geometry &geom, State state) const
+void Part::render(const Geometry &parent, State state) const
{
- unsigned gw=(fill_x ? geom.w : width);
- unsigned gh=(fill_y ? geom.h : height);
- align.apply(geom, gw, gh);
- graphic[state]->render(gw, gh);
+ if(!graphic[state])
+ 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);
}
add("graphic", &Loader::graphic);
add("align", &Loader::align);
add("fill", &Loader::fill);
+ add("margin", &Loader::margin);
}
Part::Loader::~Loader()
if(part.graphic[i])
{
const Sides &shadow=part.graphic[i]->get_shadow();
- part.width=max(part.width, part.graphic[i]->get_width()-shadow.left-shadow.right);
- part.height=max(part.height, part.graphic[i]->get_height()-shadow.bottom-shadow.top);
+ part.geom.w=max(part.geom.w, part.graphic[i]->get_width()-shadow.left-shadow.right);
+ part.geom.h=max(part.geom.h, part.graphic[i]->get_height()-shadow.bottom-shadow.top);
}
else
part.graphic[i]=part.graphic[NORMAL];
part.graphic[s]=res.get<Graphic>(n);
}
-void Part::Loader::align(int x, int y)
+void Part::Loader::align(float x, float y)
{
part.align.x=x;
part.align.y=y;
part.fill_y=y;
}
+void Part::Loader::margin()
+{
+ load_sub(part.margin);
+}
+
} // namespace GLtk
} // namespace Msp
#include <map>
#include <string>
#include <msp/datafile/loader.h>
-#include "alignment.h"
+//#include "alignment.h"
+#include "geometry.h"
#include "state.h"
namespace Msp {
~Loader();
private:
void graphic(State, const std::string &);
- void align(int, int);
+ void align(float, float);
void fill(bool, bool);
+ void margin();
};
private:
std::string name;
const Graphic *graphic[N_STATES_];
- unsigned width;
- unsigned height;
+ Geometry geom;
+ Sides margin;
Alignment align;
bool fill_x;
bool fill_y;
Part(const std::string &);
const std::string &get_name() const { return name; }
const Graphic *get_graphic(State) const;
- unsigned get_width() const { return width; }
- unsigned get_height() const { return height; }
+ 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; }
path("."),
default_font(0)
{
- add_keyword<GL::Font>("font");
add_keyword<Graphic>("graphic");
- add_keyword<Style>("style");
add_creator(&Resources::create_font);
add_creator(&Resources::create_texture);
GL::Font *Resources::create_font(const string &name)
{
RefPtr<GL::Font> fnt=new GL::Font;
- DataFile::load<GL::Font, Resources &>(*fnt, (path/(name+".font")).str(), *this);
+ DataFile::load<GL::Font, Resources &>(*fnt, (path/name).str(), *this);
if(!default_font)
default_font=fnt.get();
return fnt.release();
GL::Texture2D *Resources::create_texture(const string &name)
{
RefPtr<GL::Texture2D> tex=new GL::Texture2D;
- tex->load_image((path/(name+".png")).str());
+ tex->load_image((path/name).str());
tex->set_min_filter(GL::LINEAR);
return tex.release();
}
{
add("default_font", &Loader::default_font);
add("font", &Loader::font);
+ add("style", &Loader::style);
}
void Resources::Loader::default_font(const string &name)
fnt.release();
}
+void Resources::Loader::style(const string &name)
+{
+ RefPtr<Style> stl=new Style(res);
+ load_sub(*stl, res);
+ res.add(name, stl.get());
+ stl.release();
+}
+
} // namespace GLtk
} // namespace Msp
private:
void default_font(const std::string &);
void font(const std::string &);
+ void style(const std::string &);
};
Resources();
window.signal_button_press.connect(sigc::mem_fun(this, &Root::button_press_event));
window.signal_button_release.connect(sigc::mem_fun(this, &Root::button_release_event));
window.signal_pointer_motion.connect(sigc::mem_fun(this, &Root::pointer_motion_event));
+ window.signal_key_press.connect(sigc::mem_fun(this, &Root::key_press));
+ window.signal_key_release.connect(sigc::mem_fun(this, &Root::key_release));
}
void Root::button_press_event(int x, int y, unsigned btn, unsigned)
namespace Msp {
namespace GLtk {
-Style::Style():
- font(0)
+Style::Style(Resources &r):
+ font(&r.get_default_font())
{ }
add("font", &Style::font);
add("font_color", &Loader::font_color);
add("part", &Loader::part);
+ add("special", &Loader::special);
}
void Style::Loader::font_color(float r, float g, float b)
style.font_color=GL::Color(r, g, b);
}
-void Style::Loader::part(const string &n)
+void Style::Loader::part()
+{
+ Part p((string()));
+ load_sub(p, res);
+ style.parts.push_back(p);
+}
+
+void Style::Loader::special(const string &n)
{
Part p(n);
load_sub(p, res);
private:
void font(const std::string &);
void font_color(float, float, float);
- void part(const std::string &);
+ void part();
+ void special(const std::string &);
};
private:
PartSeq parts;
public:
- Style();
+ Style(Resources &);
const GL::Font *get_font() const { return font; }
const GL::Color &get_font_color() const { return font_color; }
const PartSeq &get_parts() const { return parts; }
update_style();
}
+void Widget::set_visible(bool v)
+{
+ if(v==visible)
+ return;
+
+ visible=v;
+
+ if(!visible && parent)
+ parent->child_hidden(*this);
+}
+
void Widget::render() const
{
if(!style)
GL::push_matrix();
GL::translate(geom.x, geom.y, 0);
for(PartSeq::const_iterator i=style->get_parts().begin(); i!=style->get_parts().end(); ++i)
- render_part(*i);
+ {
+ if(i->get_name().empty())
+ render_graphic(*i);
+ else
+ render_special(*i);
+ }
GL::pop_matrix();
}
-void Widget::render_part(const Part &part) const
-{
- render_graphic(part);
-}
-
void Widget::render_graphic(const Part &part) const
{
GL::push_matrix();
void Widget::render_text(const Part &part, const string &text) const
{
const GL::Font *const font=style->get_font();
-
const float font_size=font->get_default_size();
- unsigned text_w=static_cast<unsigned>(font->get_string_width(text)*font_size);
- GL::push_matrix();
+ Geometry rgeom;
+ rgeom.w=static_cast<unsigned>(font->get_string_width(text)*font_size);
+ rgeom.h=static_cast<unsigned>((font->get_ascent()-font->get_descent())*font_size);
+ part.get_alignment().apply(rgeom, geom, part.get_margin());
- part.get_alignment().apply(geom, text_w, static_cast<unsigned>(font->get_ascent()*font_size));
+ GL::push_matrix();
+ GL::translate(rgeom.x, rgeom.y-font->get_descent()*font_size, 0);
GL::scale_uniform(font_size);
const GL::Color &color=style->get_font_color();
*/
void set_style(const std::string &);
+ void set_visible(bool);
+
const Geometry &get_geometry() const { return geom; }
bool is_visible() const { return visible; }
void render() const;
protected:
- virtual void render_part(const Part &) const;
void render_graphic(const Part &) const;
void render_text(const Part &, const std::string &) const;
+ virtual void render_special(const Part &) const { }
public:
// Events