Added reload of levels on F7 (Update levelpack) to ease the test of changes.
[enigmagame.git] / src / gui / widgets.cc
blob0a6b70ea1317b88590d71d3bc1d964dd9bf8f60b
1 /*
2 * Copyright (C) 2002,2003,2004 Daniel Heck
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "gui/widgets.hh"
21 #include "enigma.hh"
22 #include "SoundEffectManager.hh"
23 #include "video.hh"
24 #include "options.hh"
25 #include "nls.hh"
26 #include "ecl.hh"
27 #include "ecl_font.hh"
28 #include <cassert>
29 #include <algorithm>
30 #include <iostream>
31 #include <climits>
33 using namespace enigma::gui;
34 using namespace ecl;
35 using namespace std;
37 #define SCREEN ecl::Screen::get_instance()
39 /* -------------------- Widget -------------------- */
41 Widget::Widget(Container *parent)
42 : area(), m_parent(parent), m_listener(0)
45 void Widget::invalidate() {
46 if (m_parent)
47 m_parent->invalidate_area(get_area());
49 void Widget::invalidate_area(const ecl::Rect& r) {
50 if (m_parent)
51 m_parent->invalidate_area(r);
54 void Widget::reconfigure()
56 if (m_parent)
57 m_parent->reconfigure_child(this);
60 void Widget::invoke_listener() {
61 if (m_listener)
62 m_listener->on_action(this);
65 void Widget::move(int x, int y) {
66 area.x = x; area.y = y;
69 void Widget::resize (int w, int h) {
70 area.w = w; area.h = h;
73 bool Widget::on_event(const SDL_Event &e) {
74 switch (e.type) {
75 case SDL_KEYDOWN:
76 modifierKeys = e.key.keysym.mod;
77 mouseButton = SDL_BUTTON_LEFT;
78 break;
79 case SDL_MOUSEBUTTONDOWN:
80 modifierKeys = SDL_GetModState();
81 mouseButton = e.button.button;
82 break;
84 return false;
87 /* -------------------- Image -------------------- */
89 void Image::draw (ecl::GC &gc, const ecl::Rect &/*r*/) {
90 // if (ecl::Surface *s = enigma::GetImage(imgname.c_str()))
91 // blit(gc, get_x(), get_y(), s);
92 if (ecl::Surface *s = enigma::GetImage(imgname.c_str())) {
93 int w=s->width();
94 int h=s->height();
95 int x = get_x() + (get_w()-w)/2;
96 int y = get_y() + (get_h()-h)/2;
97 blit(gc, x, y, s);
102 /* -------------------- AreaManager -------------------- */
104 AreaManager::AreaManager(Container *c)
105 : top_container(c)
107 assert(top_container->get_parent() == 0); // otherwise it's not the top_container
110 void AreaManager::invalidate_area(const ecl::Rect &r) {
111 dirtyrects.add(r);
114 void AreaManager::invalidate_all() {
115 dirtyrects.clear();
116 dirtyrects.push_back(SCREEN->size());
119 void AreaManager::refresh() {
120 if (!dirtyrects.empty()) {
121 video::HideMouse();
122 GC gc(SCREEN->get_surface());
123 for (RectList::iterator i = dirtyrects.begin(); i!=dirtyrects.end(); ++i) {
124 top_container->draw(gc, *i);
125 SCREEN->update_rect(*i);
127 video::ShowMouse();
128 dirtyrects.clear();
132 /* -------------------- Container -------------------- */
134 Container::Container()
135 : managed_by(0)
138 Container::~Container() {
139 clear();
140 delete managed_by;
143 AreaManager *Container::getAreaManager() {
144 if (Container *p = get_parent()) {
145 assert(!managed_by);
146 return p->getAreaManager();
149 if (!managed_by) {
150 managed_by = new AreaManager(this);
152 return managed_by;
155 void Container::invalidate_area(const ecl::Rect &r) { getAreaManager()->invalidate_area(r); }
156 void Container::invalidate_all() { getAreaManager()->invalidate_all(); }
157 void Container::refresh() { getAreaManager()->refresh(); }
159 void Container::clear() {
160 delete_sequence(m_widgets.begin(), m_widgets.end());
161 m_widgets.clear();
164 void Container::add_child (Widget *w) {
165 if (w && w != this) {
166 m_widgets.push_back(w);
167 w->set_parent(this);
168 // w->move (get_x() + w->get_x(),
169 // get_y() + w->get_y());
173 void Container::remove_child (Widget *w) {
174 for (iterator it = begin(); it != end(); it++) {
175 if (*it == w) {
176 m_widgets.erase(it);
177 return;
182 void Container::exchange_child (Widget *oldChild, Widget *newChild) {
183 for (unsigned int i = 0; i < m_widgets.size(); i++) {
184 if (m_widgets[i] == oldChild) {
185 m_widgets[i] = newChild;
186 newChild->set_parent(this);
187 return;
192 void Container::draw (ecl::GC& gc, const ecl::Rect &r) {
193 for (iterator i=begin(); i!=end(); ++i) {
194 Widget *w = *i;
195 Rect rr = intersect(r, w->get_area());
196 clip(gc, rr);
197 w->draw(gc,rr);
201 void Container::draw_all() {
202 invalidate_all();
203 refresh();
206 void Container::reconfigure_child (Widget *)
211 Widget * Container::find_widget(int x, int y) {
212 for (iterator i=begin(); i!=end(); ++i) {
213 Widget *w = *i;
214 if (w->get_area().contains(x,y)) {
215 Container *c = dynamic_cast<Container *> (w);
216 if (c) {
217 w = c->find_widget (x, y);
218 return w ? w : c;
220 return w;
223 return 0;
226 Widget * Container::find_adjacent_widget(Widget *from, int x, int y) {
227 // valid values for x/y : 1/0, -1/0, 0/1, 0/-1
228 assert(from && x>=-1 && x<=1 && y>=-1 && y<=1 && abs(x+y) == 1);
230 if (!from) return 0;
232 int best_distance = INT_MAX;
233 Widget *best_widget = 0;
234 ecl::Rect farea = from->get_area();
236 for (iterator i=begin(); i!=end(); ++i) {
237 Widget *w = *i;
238 ecl::Rect warea = w->get_area();
239 bool adjacent = true;
240 int distance = 0;
242 if (x) { // check for y-overlap
243 if (farea.y>(warea.y+warea.h-1) || warea.y>(farea.y+farea.h-1)) {
244 adjacent = false;
246 else {
247 distance = (warea.x-farea.x)*x;
250 else { // check for x-overlap
251 if (farea.x>(warea.x+warea.h-1) || warea.x>(farea.x+farea.h-1)) {
252 adjacent = false;
254 else {
255 distance = (warea.y-farea.y)*y;
259 if (adjacent && distance>0 && distance<best_distance) {
260 best_distance = distance;
261 best_widget = w;
265 return best_widget;
268 void Container::move (int x, int y) {
269 Rect a = get_area();
270 a.x = x;
271 a.y = y;
272 this->set_area (a);
274 int dx = x-get_x();
275 int dy = y-get_y();
277 for (iterator i=begin(); i!=end(); ++i) {
278 Widget *w = *i;
279 w->move(dx + w->get_x(), dy+w->get_y());
283 ecl::Rect Container::boundingbox() {
284 if (!m_widgets.empty()) {
285 iterator i=begin();
286 Rect bbox=(*i)->get_area();
287 for (++i; i!=end(); ++i)
288 bbox = ecl::boundingbox(bbox, (*i)->get_area());
289 return bbox;
290 } else
291 return get_area();
294 void Container::set_key_focus(Widget *newfocus) {
295 if (get_parent() != NULL) {
296 get_parent()->set_key_focus(newfocus);
300 bool Container::is_key_focus(Widget *focus) {
301 if (get_parent() != NULL) {
302 return get_parent()->is_key_focus(focus);
303 } else
304 return false;
307 /* -------------------- List -------------------- */
309 List::List (int spacing)
310 : m_spacing(spacing),
311 has_default_size (false),
312 defaultw (0),
313 defaulth (0),
314 m_halign (HALIGN_LEFT),
315 m_valign (VALIGN_TOP)
318 void List::remove_child (Widget *w) {
319 Container::remove_child(w);
320 recalc();
323 void List::exchange_child(Widget *oldChild, Widget *newChild) {
324 Container::exchange_child(oldChild, newChild);
325 recalc();
328 void List::set_spacing (int pixels)
330 m_spacing = pixels;
333 int List::get_spacing () const
335 return m_spacing;
338 int List::calc_minimum_height() const
340 int sum=0;
341 const WidgetList &wl = m_widgets;
342 if (!wl.empty()) {
343 sum = (wl.size() - 1) * m_spacing;
344 for (WidgetList::const_iterator i=wl.begin(); i!=wl.end(); ++i) {
345 int nw, nh;
346 get_size (*i, nw, nh);
347 sum += nh;
350 return sum;
353 int List::calc_minimum_width () const
355 int sum=0;
356 const WidgetList &wl = m_widgets;
357 if (!wl.empty()) {
358 sum = (wl.size() - 1) * m_spacing;
359 for (WidgetList::const_iterator i=wl.begin(); i!=wl.end(); ++i) {
360 int nw, nh;
361 get_size (*i, nw, nh);
362 sum += nw;
365 return sum;
368 void List::set_default_size (int w, int h)
370 has_default_size = true;
371 defaultw = w;
372 defaulth = h;
376 void List::get_size (const Widget *widget, int &w, int &h) const
378 if (has_default_size)
379 w = defaultw, h = defaulth;
380 else
381 widget->naturalsize (w, h);
384 void List::resize (int w, int h)
386 Container::resize (w, h);
387 recalc();
390 void List::move (int x, int y)
392 Container::move (x, y);
393 // recalc();
396 void List::reconfigure_child (Widget *w)
398 Container::reconfigure_child (w);
399 recalc();
400 invalidate();
403 void List::add_back (Widget *w, ExpansionMode m)
405 add_child (w);
406 m_expansionmodes.push_back (m);
407 recalc();
410 void List::set_alignment (HAlignment halign, VAlignment valign)
412 if (halign != m_halign || valign != m_valign) {
413 m_halign = halign;
414 m_valign = valign;
415 recalc();
421 /* -------------------- HList -------------------- */
423 void HList::recalc()
425 int targetw = this->get_w(); // The available space
426 int naturalw= calc_minimum_width();
427 int excessw = targetw - naturalw;
429 int num_expand = std::count (m_expansionmodes.begin(),
430 m_expansionmodes.end(),
431 List::EXPAND);
433 WidgetList::iterator i = m_widgets.begin(),
434 end = m_widgets.end();
435 int x = get_x(), y = get_y();
436 size_t j = 0;
438 if (num_expand == 0 && excessw > 0) {
439 switch (m_halign) {
440 case HALIGN_CENTER:
441 x += excessw / 2;
442 excessw = 0;
443 break;
444 default:
445 break;
449 for (; i != end; ++i, ++j) {
450 int w, h;
451 List::get_size (*i, w, h);
453 if (excessw > 0 && m_expansionmodes[j] == List::EXPAND) {
454 w += excessw / num_expand;
455 excessw -= excessw / num_expand;
456 num_expand -= 1;
458 (*i)->move (x, y);
459 (*i)->resize (w, get_h());
460 x += w + get_spacing();
464 bool HList::fits() {
465 int targetw = this->get_w(); // The available space
466 int naturalw= calc_minimum_width();
467 return targetw >= naturalw;
470 /* -------------------- VList -------------------- */
472 void VList::recalc()
474 int targeth = this->get_h(); // The available space
475 int naturalh= calc_minimum_height();
476 int excessh = targeth - naturalh;
478 int num_expand = std::count (m_expansionmodes.begin(),
479 m_expansionmodes.end(),
480 List::EXPAND);
482 WidgetList::iterator i = m_widgets.begin(),
483 end = m_widgets.end();
484 int x = get_x(), y = get_y();
485 size_t j = 0;
487 if (num_expand == 0 && excessh > 0) {
488 switch (m_valign) {
489 case VALIGN_CENTER:
490 y += excessh / 2;
491 excessh = 0;
492 break;
493 default:
494 break;
498 for (; i != end; ++i, ++j) {
499 int w, h;
500 List::get_size (*i, w, h);
502 if (excessh > 0 && m_expansionmodes[j] == List::EXPAND) {
503 h += excessh / num_expand;
504 excessh -= excessh / num_expand;
505 num_expand -= 1;
507 (*i)->move (x, y);
508 (*i)->resize (get_w(), h);
509 y += h + get_spacing();
513 bool VList::fits() {
514 int targeth = this->get_h(); // The available space
515 int naturalh= calc_minimum_height();
516 return targeth >= naturalh;
519 /* -------------------- Label -------------------- */
521 Label::Label (const std::string &text,
522 HAlignment halign,
523 VAlignment valign)
524 : m_text (text),
525 m_font(enigma::GetFont("menufont")),
526 m_halign(halign),
527 m_valign(valign)
531 void Label::set_text (const std::string &text) {
532 if (text != m_text) {
533 m_text = text;
534 reconfigure();
535 invalidate();
539 string Label::get_text() const {
540 return _(m_text.c_str());
543 string Label::getText() const {
544 return m_text;
547 void Label::set_font (ecl::Font *font) {
548 if (m_font != font) {
549 m_font = font;
550 reconfigure();
551 invalidate();
555 bool Label::text_fits(double area_fraction) {
556 int w, h;
557 naturalsize (w, h);
558 return w <= get_w()*area_fraction;
561 void Label::draw (ecl::GC &gc, const ecl::Rect &)
563 Font *f = m_font;
564 int w, h;
565 naturalsize (w, h);
567 int x = get_x(), y=get_y();
568 switch (m_halign) {
569 case HALIGN_LEFT: break;
570 case HALIGN_RIGHT: x += get_w() - w; break;
571 case HALIGN_CENTER: x += (get_w()-w)/2; break;
573 switch (m_valign) {
574 case VALIGN_TOP: break;
575 case VALIGN_BOTTOM: y += get_h() - h; break;
576 case VALIGN_CENTER: y += (get_h()-h)/2; break;
578 // translate if not an empty string
579 f->render (gc, x, y, m_text == "" ? "" : get_text().c_str());
582 void Label::set_alignment (HAlignment halign, VAlignment valign) {
583 if (halign != m_halign || valign != m_valign) {
584 m_halign = halign;
585 m_valign = valign;
586 invalidate();
590 void Label::naturalsize (int &w, int &h) const
592 h = m_font->get_height();
593 // width of translation if not an empty string
594 w = m_font->get_width (m_text == "" ? "" : get_text().c_str());
597 /* -------------------- UntranslatedLabel -------------------- */
599 UntranslatedLabel::UntranslatedLabel (const std::string &text,
600 HAlignment halign, VAlignment valign) : Label(text, halign, valign) {
603 string UntranslatedLabel::get_text() const {
604 return Label::m_text;
608 /* -------------------- Button -------------------- */
610 Button::Button()
611 : m_activep (false), highlight (false)
615 void Button::activate()
617 sound::EmitSoundEvent ("menuswitch");
618 m_activep = true;
619 invalidate();
622 void Button::deactivate() {
623 m_activep = false;
624 invalidate();
627 void Button::setHighlight(bool shouldHighlight) {
628 highlight = shouldHighlight;
629 invalidate();
631 bool Button::isHighlight() {
632 return highlight;
635 void Button::draw(ecl::GC &gc, const ecl::Rect &r) {
636 const int borderw = 4;
638 ecl::Surface *s = enigma::GetImage(m_activep ? "buttonhl" : "button");
640 if (s) { // Ugly, but hey, it works
641 Rect srcrect (0,0,borderw, borderw);
642 Rect area = get_area();
644 // background
645 if (highlight)
646 set_color (gc, 70, 70, 70);
647 else
648 set_color (gc, 0,0,0);
649 box (gc, smaller(area, borderw));
651 set_color (gc, 0,0,0);
652 // corners
653 blit (gc, area.x, area.y, s, srcrect);
654 srcrect.x += s->width()-borderw;
655 blit (gc, area.x+area.w-borderw, area.y, s, srcrect);
656 srcrect.x = 0;
657 srcrect.y += s->height()-borderw;
658 blit (gc, area.x, area.y+area.h-borderw, s, srcrect);
659 srcrect.x += s->width()-borderw;
660 blit (gc, area.x+area.w-borderw, area.y+area.h-borderw, s, srcrect);
662 // horizontal borders
664 int tilew = s->width() - 2*borderw;
665 int ntiles = (area.w - 2*borderw) / tilew;
666 int x = area.x + borderw;
667 for (int i=0; i<ntiles; ++i) {
668 blit (gc, x, area.y, s, Rect (borderw, 0, tilew, borderw));
669 blit (gc, x, area.y+area.h-borderw, s,
670 Rect (borderw, s->height()-borderw, tilew, borderw));
671 x += tilew;
673 int restw = (area.w - 2*borderw) - tilew*ntiles;
674 blit (gc, x, area.y, s, Rect (borderw, 0, restw, borderw));
675 blit (gc, x, area.y+area.h-borderw, s,
676 Rect (borderw, s->height()-borderw, restw, borderw));
678 // vertical borders
680 int tileh = s->height() - 2*borderw;
681 int ntiles = (area.h - 2*borderw) / tileh;
682 int y = area.y + borderw;
683 for (int i=0; i<ntiles; ++i) {
684 blit (gc, area.x, y, s, Rect (0, borderw, borderw, tileh));
685 blit (gc, area.x+area.w-borderw, y, s,
686 Rect (s->width()-borderw, borderw, borderw, tileh));
687 y += tileh;
689 int resth = (area.h - 2*borderw) - tileh*ntiles;
690 blit (gc, area.x, y, s, Rect (0, borderw, borderw, resth));
691 blit (gc, area.x+area.w-borderw, y, s,
692 Rect (s->width()-borderw, borderw, borderw, resth));
695 else {
696 set_color (gc, 0,0,0);
697 box (gc, r);
698 set_color (gc, 160,160,160);
699 frame (gc, r);
700 frame (gc, smaller(r, 1));
704 /* -------------------- PushButton -------------------- */
706 PushButton::PushButton() : m_pressedp (false) {
709 bool PushButton::on_event(const SDL_Event &e) {
710 Widget::on_event(e);
711 bool was_pressed = m_pressedp;
712 bool handeled = false;
714 switch (e.type) {
715 case SDL_KEYDOWN:
716 if (e.key.keysym.sym != SDLK_RETURN) break;
717 // fall-through
718 case SDL_MOUSEBUTTONDOWN:
719 m_pressedp = true;
720 handeled = true;
721 break;
723 case SDL_KEYUP:
724 if (e.key.keysym.sym != SDLK_RETURN) break;
725 lastUpSym = e.key.keysym.sym;
726 lastUpBotton = 0;
727 m_pressedp = false;
728 handeled = true;
729 break;
730 case SDL_MOUSEBUTTONUP:
731 lastUpSym = SDLK_UNKNOWN;
732 lastUpBotton = e.button.button;
733 m_pressedp = false;
734 handeled = true;
735 break;
738 bool changed = (was_pressed != m_pressedp);
739 if (changed) {
740 invalidate();
741 if (!m_pressedp) {
742 if (soundOk())
743 sound::EmitSoundEvent("menuok");
744 invoke_listener();
748 return handeled;
751 void PushButton::deactivate() {
752 m_pressedp = false;
753 lastUpSym = SDLK_UNKNOWN;
754 lastUpBotton = 0;
755 invalidate();
756 Button::deactivate();
759 SDLKey PushButton::getLastUpSym() {
760 return lastUpSym;
763 Uint8 PushButton::getLastUpButton() {
764 return lastUpBotton;
767 bool PushButton::soundOk() {
768 return true;
771 /* -------------------- TextButton -------------------- */
773 TextButton::TextButton(ActionListener *al) {
774 menufont = enigma::GetFont("menufont");
775 menufont_pressed = enigma::GetFont("menufontsel");
776 set_listener(al);
779 void TextButton::draw(ecl::GC &gc, const ecl::Rect &r) {
780 Button::draw(gc,r);
781 Font *f = is_pressed() ? menufont_pressed : menufont;
782 string text = get_text();
783 int h = f->get_height();
784 int w = f->get_width(text.c_str());
785 int x = get_x() + (get_w()-w)/2;
786 int y = get_y() + (get_h()-h)/2;
788 f->render (gc, x, y, text.c_str());
792 /* -------------------- StaticTextButton -------------------- */
794 StaticTextButton::StaticTextButton(const string &t, ActionListener *al)
795 : TextButton(al),
796 text(t)
800 void StaticTextButton::set_text(const std::string &t) {
801 if (t != text) {
802 text = t;
803 invalidate();
807 string StaticTextButton::get_text() const {
808 return _(text.c_str()); // translate
811 /* -------------------- UntranslatedStaticTextButton -------------------- */
813 UntranslatedStaticTextButton::UntranslatedStaticTextButton(const string &t,
814 ActionListener *al)
815 : StaticTextButton(t, al)
820 string UntranslatedStaticTextButton::get_text() const {
821 return StaticTextButton::text;
825 /* -------------------- Buttons for Options -------------------- */
827 BoolOptionButton::BoolOptionButton(const char *option_name,
828 const string& true_text, const string& false_text,
829 ActionListener *al)
830 : TextButton(al),
831 optionName(option_name),
832 trueText(true_text),
833 falseText(false_text)
837 bool BoolOptionButton::toggle() {
838 bool newval = !enigma_options::GetBool(optionName);
839 enigma_options::SetOption(optionName, newval);
840 invalidate();
841 return newval;
844 void BoolOptionButton::on_action(Widget *) {
845 toggle();
848 string BoolOptionButton::get_text() const {
849 return enigma_options::GetBool(optionName) ? _(trueText.c_str()) : _(falseText.c_str());
852 /* -------------------- ValueButton -------------------- */
854 ValueButton::ValueButton(int min_value_, int max_value_)
855 : TextButton(this),
856 min_value(min_value_),
857 max_value(max_value_)
861 void ValueButton::setMaxValue(int max) {
862 max_value = max;
865 void ValueButton::init() {
866 update_value(-1, get_value()); // fixes wrong values (e.g. from .enimarc)
869 bool ValueButton::inc_value(int offset) {
870 int old_value = get_value();
871 return update_value(old_value, old_value+offset);
874 string ValueButton::get_text() const {
875 return get_text(get_value());
878 bool ValueButton::update_value(int old_value, int new_value) {
879 new_value = Clamp(new_value, min_value, max_value);
880 if (new_value != old_value) {
881 set_value(new_value);
882 invalidate();
883 return true;
885 return false;
889 void ValueButton::on_action(Widget *) {
890 int incr = 1;
891 bool stop = false;
892 if (getLastUpSym() == SDLK_PAGEDOWN ||
893 getLastUpButton() == SDL_BUTTON_RIGHT ||
894 getLastUpButton() == 5) { // wheel down
895 incr = -1;
897 if (getLastUpSym() == SDLK_PAGEDOWN ||
898 getLastUpSym() == SDLK_PAGEUP ||
899 getLastUpButton() == SDL_BUTTON_RIGHT ||
900 getLastUpButton() == SDL_BUTTON_LEFT ||
901 getLastUpButton() == 4 || getLastUpButton() == 5) {
902 stop = true;
904 if (inc_value(incr)) {
905 sound::EmitSoundEvent("menuswitch");
906 } else {
907 if (stop) {
908 sound::EmitSoundEvent("menustop");
909 } else {
910 sound::EmitSoundEvent("menuswitch");
911 if (incr == 1)
912 update_value(get_value(), min_value);
913 else
914 update_value(get_value(), max_value);
919 bool ValueButton::soundOk() {
920 return false;
923 /* -------------------- ImageButton -------------------- */
925 ImageButton::ImageButton(const string &unselected,
926 const string &selected,
927 ActionListener *al)
928 : fname_sel(selected), fname_unsel(unselected)
930 set_listener(al);
933 void ImageButton::set_images(const string &unselected, const string &selected) {
934 fname_sel = selected;
935 fname_unsel = unselected;
938 void ImageButton::draw(ecl::GC &gc, const ecl::Rect &r) {
939 Button::draw(gc, r);
940 string &fname = is_pressed() ? fname_sel : fname_unsel;
942 if (Surface *s = enigma::GetImage(fname.c_str())) {
943 int w=s->width();
944 int h=s->height();
945 int x = get_x() + (get_w()-w)/2;
946 int y = get_y() + (get_h()-h)/2;
947 blit(gc, x, y, s);
951 /* -------------------- BorderlessImageButton -------------------- */
953 BorderlessImageButton::BorderlessImageButton(const string &unselected,
954 const string &selected, const string &mouseover, bool isSelected, ActionListener *al)
955 : fname_sel(selected), fname_unsel(unselected), fname_mouse(mouseover), state (isSelected)
957 set_listener(al);
960 void BorderlessImageButton::set_images(const string &unselected,
961 const string &selected, const string &mouseover) {
962 fname_sel = selected;
963 fname_unsel = unselected;
964 fname_mouse = mouseover;
967 void BorderlessImageButton::draw(ecl::GC &gc, const ecl::Rect &r) {
968 string &fname = m_activep ? fname_mouse : (state ? fname_sel : fname_unsel);
970 if (Surface *s = enigma::GetImage(fname.c_str())) {
971 int w=s->width();
972 int h=s->height();
973 int x = get_x() + (get_w()-w)/2;
974 int y = get_y() + (get_h()-h)/2;
975 blit(gc, x, y, s);
979 void BorderlessImageButton::setState(bool isSelected) {
980 state = isSelected;
981 invalidate();
984 bool BorderlessImageButton::getState() const {
985 return state;