From: Mikko Rasa Date: Tue, 11 Dec 2007 13:30:49 +0000 (+0000) Subject: Enable loading of entry widgets from datafiles X-Git-Tag: 0.9~22 X-Git-Url: http://git.tdb.fi/?p=libs%2Fgltk.git;a=commitdiff_plain;h=ed9873ba7ee862ad76937f579fe371c1a27d5715 Enable loading of entry widgets from datafiles Fix focus control logic Refactor part specification and rendering Change Alignment to use floats and move it to geometry.* Add margins for parts Add cursor to entry widget Require full filenames of external resources to avoid name conflicts --- diff --git a/source/alignment.cpp b/source/alignment.cpp deleted file mode 100644 index 110aa09..0000000 --- a/source/alignment.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* $Id$ - -This file is part of libmspgltk -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - -#include -#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 diff --git a/source/alignment.h b/source/alignment.h deleted file mode 100644 index 56d6766..0000000 --- a/source/alignment.h +++ /dev/null @@ -1,32 +0,0 @@ -/* $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 diff --git a/source/button.cpp b/source/button.cpp index f078ca6..58e69bf 100644 --- a/source/button.cpp +++ b/source/button.cpp @@ -35,8 +35,8 @@ void Button::button_release(int x, int y, unsigned btn) { if(geom.is_inside(x, y)) { - signal_clicked.emit(); state=HOVER; + signal_clicked.emit(); } else state=NORMAL; @@ -53,12 +53,10 @@ void Button::pointer_leave() 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); } diff --git a/source/button.h b/source/button.h index 55cb2b0..ea96a7d 100644 --- a/source/button.h +++ b/source/button.h @@ -43,7 +43,7 @@ public: 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 diff --git a/source/entry.cpp b/source/entry.cpp index 2c9b9d6..eed2c39 100644 --- a/source/entry.cpp +++ b/source/entry.cpp @@ -5,11 +5,11 @@ Copyright © 2007 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ -#include #include #include #include #include "entry.h" +#include "graphic.h" #include "part.h" #include "style.h" @@ -35,17 +35,17 @@ void Entry::set_text(const string &t) 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_pos0) text.erase(--edit_pos, 1); @@ -53,6 +53,7 @@ void Entry::key_press(unsigned key, unsigned, wchar_t ch) else { text+=ch; + ++edit_pos; } } @@ -68,58 +69,41 @@ void Entry::focus_out() 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(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(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(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(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(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 diff --git a/source/entry.h b/source/entry.h index 4cbb2a9..c880bb4 100644 --- a/source/entry.h +++ b/source/entry.h @@ -23,6 +23,13 @@ Special parts: */ class Entry: public Widget { +public: + class Loader: public Widget::Loader + { + public: + Loader(Entry &); + }; + private: std::string text; unsigned edit_pos; @@ -38,7 +45,7 @@ public: 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 diff --git a/source/geometry.cpp b/source/geometry.cpp index 6183928..81efcd0 100644 --- a/source/geometry.cpp +++ b/source/geometry.cpp @@ -33,5 +33,18 @@ Sides::Loader::Loader(Sides &s): add("left", &Sides::left); } + +void Alignment::apply(Geometry &geom, const Geometry &parent) const +{ + geom.x+=static_cast((parent.w-geom.w)*x); + geom.y+=static_cast((parent.h-geom.h)*y); +} + +void Alignment::apply(Geometry &geom, const Geometry &parent, const Sides &margin) const +{ + geom.x+=static_cast(margin.left+(parent.w-margin.left-margin.right-geom.w)*x); + geom.y+=static_cast(margin.bottom+(parent.h-margin.bottom-margin.top-geom.h)*y); +} + } // namespace GLtk } // namespace Msp diff --git a/source/geometry.h b/source/geometry.h index 6dc9827..6559414 100644 --- a/source/geometry.h +++ b/source/geometry.h @@ -26,6 +26,7 @@ struct Geometry bool is_inside(int, int) const; }; + /** Specifies margins on the sides of an element. */ @@ -48,6 +49,20 @@ struct Sides 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 diff --git a/source/hslider.cpp b/source/hslider.cpp index f19eafe..d764797 100644 --- a/source/hslider.cpp +++ b/source/hslider.cpp @@ -55,27 +55,26 @@ void HSlider::pointer_motion(int x, int) } } -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; } diff --git a/source/hslider.h b/source/hslider.h index 4f05d6d..310cc4e 100644 --- a/source/hslider.h +++ b/source/hslider.h @@ -31,7 +31,7 @@ public: 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; }; diff --git a/source/label.cpp b/source/label.cpp index 36637d0..0e0134d 100644 --- a/source/label.cpp +++ b/source/label.cpp @@ -23,12 +23,10 @@ void Label::set_text(const std::string &t) 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); } diff --git a/source/label.h b/source/label.h index 0bd326f..baa0ddc 100644 --- a/source/label.h +++ b/source/label.h @@ -35,7 +35,7 @@ public: 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 diff --git a/source/panel.cpp b/source/panel.cpp index 36585c9..bfd0aa8 100644 --- a/source/panel.cpp +++ b/source/panel.cpp @@ -7,6 +7,7 @@ Distributed under the LGPL #include #include "button.h" +#include "entry.h" #include "label.h" #include "panel.h" #include "part.h" @@ -55,9 +56,10 @@ void Panel::button_press(int x, int y, unsigned btn) { 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); } } } @@ -69,11 +71,7 @@ void Panel::button_release(int x, int y, unsigned 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)) { @@ -89,12 +87,17 @@ void Panel::pointer_motion(int x, int 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) @@ -112,7 +115,13 @@ void Panel::focus_out() 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") { @@ -120,13 +129,14 @@ void Panel::render_part(const Part &part) const 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(); @@ -136,6 +146,8 @@ void Panel::set_pointer_focus(Widget *wdg) if(pointer_focus) pointer_focus->pointer_enter(); } + + pointer_grab=grab; } void Panel::set_input_focus(Widget *wdg) @@ -168,6 +180,7 @@ Panel::Loader::Loader(Panel &p, map &m): wdg_map(m) { add("button", &Loader::child