diff options
| author | Felix Domke <tmbinc@elitedvb.net> | 2003-10-17 15:36:42 +0000 |
|---|---|---|
| committer | Felix Domke <tmbinc@elitedvb.net> | 2003-10-17 15:36:42 +0000 |
| commit | d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5 (patch) | |
| tree | 84d0cacfd0b6c1241c236c7860f7cbd7f26901bb /lib/gui | |
| download | enigma2-d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5.tar.gz enigma2-d63d2c3c6cbbd574dda4f8b00ebe6c661735edd5.zip | |
import of enigma2
Diffstat (limited to 'lib/gui')
48 files changed, 2366 insertions, 0 deletions
diff --git a/lib/gui/.cvsignore b/lib/gui/.cvsignore new file mode 100644 index 00000000..316b06f5 --- /dev/null +++ b/lib/gui/.cvsignore @@ -0,0 +1,7 @@ +*.moc.* +Makefile +Makefile.in +.deps +.libs +*.lo +*.la diff --git a/lib/gui/Makefile.am b/lib/gui/Makefile.am new file mode 100644 index 00000000..634f85b6 --- /dev/null +++ b/lib/gui/Makefile.am @@ -0,0 +1,13 @@ +INCLUDES = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src + +noinst_LIBRARIES = libenigma_gui.a + +libenigma_gui_a_SOURCES = \ + ebutton.cpp echeckbox.cpp elabel.cpp emessage.cpp \ + enumber.cpp eprogress.cpp eskin.cpp listbox.cpp eskin_register.cpp \ + ewidget.cpp ewindow.cpp multipage.cpp actions.cpp guiactions.cpp \ + decoration.cpp statusbar.cpp combobox.cpp numberactions.cpp slider.cpp \ + textinput.cpp testpicture.cpp + diff --git a/lib/gui/actions.cpp b/lib/gui/actions.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/actions.cpp diff --git a/lib/gui/actions.h b/lib/gui/actions.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/actions.h diff --git a/lib/gui/combobox.cpp b/lib/gui/combobox.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/combobox.cpp diff --git a/lib/gui/combobox.h b/lib/gui/combobox.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/combobox.h diff --git a/lib/gui/decoration.cpp b/lib/gui/decoration.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/decoration.cpp diff --git a/lib/gui/decoration.h b/lib/gui/decoration.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/decoration.h diff --git a/lib/gui/ebutton.cpp b/lib/gui/ebutton.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/ebutton.cpp diff --git a/lib/gui/ebutton.h b/lib/gui/ebutton.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/ebutton.h diff --git a/lib/gui/echeckbox.cpp b/lib/gui/echeckbox.cpp new file mode 100644 index 00000000..c41721ce --- /dev/null +++ b/lib/gui/echeckbox.cpp @@ -0,0 +1,138 @@ +#include <lib/gui/echeckbox.h> + +#include <lib/gdi/font.h> +#include <lib/base/init.h> +#include <lib/base/init_num.h> +#include <lib/gui/eskin.h> + +eCheckbox::eCheckbox(eWidget *parent, int checked, int takefocus, bool swapTxtPixmap, const char *deco) + :eButton(parent, 0, takefocus, deco), swapTxtPixmap(swapTxtPixmap) +{ + align=eTextPara::dirLeft; + ischecked = -1; + setCheck(checked); + CONNECT(selected, eCheckbox::sel); +} + +eCheckbox::~eCheckbox() +{ +} + +void eCheckbox::sel() +{ + setCheck(ischecked?0:1); + /*emit*/ checked(ischecked); +} + +void eCheckbox::gotFocus() +{ +#ifndef DISABLE_LCD + if (parent && parent->LCDElement) + { + LCDTmp = new eLabel(parent->LCDElement); + LCDTmp->hide(); + eSize s = parent->LCDElement->getSize(); + LCDTmp->move(ePoint(0,0)); + LCDTmp->resize(eSize(s.width(), s.height())); + ((eLabel*)LCDTmp)->setFlags(RS_WRAP); + ePtr<gPixmap> pm; + eSkin::getActive()->queryImage(pm, ischecked?"eCheckboxLCD.checked":"eCheckboxLCD.unchecked"); + LCDTmp->setPixmap(pm); + ((eLabel*)LCDTmp)->pixmap_position=ePoint(0, (size.height()-15)/2); + ((eLabel*)LCDTmp)->text_position=ePoint(21, 0); + LCDTmp->setText(text); + LCDTmp->show(); + } +#endif + setForegroundColor(focusF, false); + setBackgroundColor(focusB); +// invalidate(); +} + +void eCheckbox::lostFocus() +{ +#ifndef DISABLE_LCD + if (LCDTmp) + { + delete LCDTmp; + LCDTmp = 0; + } +#endif + eButton::lostFocus(); +} + + +void eCheckbox::setCheck(int c) +{ + if (ischecked != -1 && ischecked == c) + return; + + ischecked=c; + + ePtr<gPixmap> pixmap; + eSkin::getActive()->queryImage(pixmap, ischecked?"eCheckbox.checked":"eCheckbox.unchecked"); + setPixmap(pixmap); +#ifndef DISABLE_LCD + eSkin::getActive()->queryImage(pixmap, ischecked?"eCheckboxLCD.checked":"eCheckboxLCD.unchecked"); + if (LCDTmp) + LCDTmp->setPixmap(pixmap); +#endif +} + +int eCheckbox::setProperty(const eString &prop, const eString &value) +{ + if (prop=="swaptxtpixmap") + { + swapTxtPixmap = (value != "off"); + event( eWidgetEvent::changedSize ); + } + else + return eButton::setProperty(prop, value); + return 0; +} + +int eCheckbox::eventHandler(const eWidgetEvent &event) +{ + switch (event.type) + { + case eWidgetEvent::changedSize: + if (swapTxtPixmap) + { + text_position=ePoint(0,0); + eLabel::invalidate(); + validate(); + pixmap_position=ePoint( para->getBoundBox().right()+5, (size.height()-pixmap->y) / 2 ); + } + else + { + pixmap_position=ePoint(0, (size.height()-pixmap->y)/2); + text_position=ePoint((int)(pixmap->x*1.25), 0); + } + //return eButton::eventHandler(event); // changed Size must seen by eLabel... + break; + + default: + return eButton::eventHandler(event); + } + return 1; +} + +static eWidget *create_eCheckbox(eWidget *parent) +{ + return new eCheckbox(parent); +} + +class eCheckboxSkinInit +{ +public: + eCheckboxSkinInit() + { + eSkin::addWidgetCreator("eCheckbox", create_eCheckbox); + } + ~eCheckboxSkinInit() + { + eSkin::removeWidgetCreator("eCheckbox", create_eCheckbox); + } +}; + +eAutoInitP0<eCheckboxSkinInit> init_eCheckboxSkinInit(eAutoInitNumbers::guiobject, "eCheckbox"); diff --git a/lib/gui/echeckbox.h b/lib/gui/echeckbox.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/echeckbox.h diff --git a/lib/gui/elabel.cpp b/lib/gui/elabel.cpp new file mode 100644 index 00000000..ae04eb46 --- /dev/null +++ b/lib/gui/elabel.cpp @@ -0,0 +1,253 @@ +#include <lib/gui/elabel.h> + +#include <lib/gdi/fb.h> +#include <lib/gdi/font.h> +#include <lib/gdi/lcd.h> +#include <lib/gui/eskin.h> +#include <lib/base/init.h> +#include <lib/base/init_num.h> + +eLabel::eLabel(eWidget *parent, int flags, int takefocus, const char *deco ): + eDecoWidget(parent, takefocus, deco), blitFlags(0), flags(flags), + para(0), align( eTextPara::dirLeft ), shortcutPixmap(0) +{ +} + +eLabel::~eLabel() +{ + if (para) + { + para->destroy(); + para=0; + } +} + +void eLabel::setPixmapPosition( const ePoint &p ) +{ + pixmap_position = p; + invalidate(); +} + +void eLabel::validate( const eSize* s ) +{ + if (!para) + { + if (s) + para=new eTextPara( eRect(text_position.x(), text_position.y(), s->width() - text_position.x(), s->height() - text_position.y())); + else + para=new eTextPara( eRect(text_position.x(), text_position.y(), size.width() - text_position.x(), size.height() - text_position.y())); + + para->setFont(font); + para->renderString(text, flags); + para->realign(align); + } +} + +void eLabel::invalidate() +{ + if (para) + { + para->destroy(); + para=0; + } + if (isVisible()) + eDecoWidget::invalidate(); // we must redraw... +} + +void eLabel::setFlags(int flag) +{ + flags|=flag; + if (flag) + invalidate(); +} + +void eLabel::setBlitFlags( int flags ) +{ + blitFlags |= flags; +} + +void eLabel::removeFlags(int flag) +{ + flags &= ~flag; + if (flag) + invalidate(); +} + +void eLabel::setAlign(int align) +{ + this->align = align; + invalidate(); +} + +void eLabel::redrawWidget(gPainter *target, const eRect &rc) +{ +/* eDebug("decoStr = %s, text=%s, name=%s, %p left = %d, top = %d, width=%d, height = %d", strDeco?strDeco.c_str():"no", text?text.c_str():"no" , name?name.c_str():"no", this, this->getPosition().x(), this->getPosition().y(), this->getSize().width(), this->getSize().height() ); + eDebug("renderContext left = %d, top = %d, width = %d, height = %d", rc.left(), rc.top(), rc.width(), rc.height() );*/ + + target->clip( rc ); + eRect area=eRect(ePoint(0, 0), ePoint(width(), height())); +/* eDebug("area left = %d, top = %d, width = %d, height = %d", + area.left(), area.top(), + area.width(), area.height() );*/ + + if (deco_selected && have_focus) + { + deco_selected.drawDecoration(target, ePoint(width(), height())); + area=crect_selected; + } else if (deco) + { + deco.drawDecoration(target, ePoint(width(), height())); + area=crect; + } +/* eDebug("area left = %d, top = %d, width = %d, height = %d", + area.left(), area.top(), + area.width(), area.height() );*/ + + if (shortcutPixmap) + { + //area.setWidth(area.width()-area.height()); + area.setX(area.height()); + } + + if (text.length()) + { + if ( area.size().height() < size.height() || + area.size().width() < size.width() ) + { + // then deco is drawed + eSize s=area.size(); + validate( &s ); + } else + validate(); + + if (flags & flagVCenter) + yOffs = ( (area.height() - para->getBoundBox().height() ) / 2 + 0) - para->getBoundBox().top(); + else + yOffs = 0; + + eWidget *w; + if ((blitFlags & BF_ALPHATEST) && (transparentBackgroundColor >= 0)) + { + w=this; + target->setBackgroundColor(transparentBackgroundColor); + } else + { + w=getNonTransparentBackground(); + target->setBackgroundColor(w->getBackgroundColor()); + } + target->setFont(font); + target->renderPara(*para, ePoint( area.left(), area.top()+yOffs) ); + } + if (pixmap) + { +// eDebug("blit pixmap area left=%d, top=%d, right=%d, bottom=%d", rc.left(), rc.top(), rc.right(), rc.bottom() ); +// eDebug("pixmap_pos x = %d, y = %d, xsize=%d, ysize=%d", pixmap_position.x(), pixmap_position.y(), pixmap->x, pixmap->y ); + target->blit(pixmap, shortcutPixmap?pixmap_position+ePoint( area.left(), 0):pixmap_position, area, (blitFlags & BF_ALPHATEST) ? gPixmap::blitAlphaTest : 0); + } + if (shortcutPixmap) + target->blit(shortcutPixmap, + ePoint((area.height()-shortcutPixmap->x)/2, area.top()+(area.height()-shortcutPixmap->y)/2), + eRect(), + gPixmap::blitAlphaTest); + target->clippop(); +} + +int eLabel::eventHandler(const eWidgetEvent &event) +{ + switch (event.type) + { + case eWidgetEvent::changedFont: + case eWidgetEvent::changedText: + if (para) + { + para->destroy(); + para=0; + } + if ( have_focus && deco_selected ) + eDecoWidget::invalidate( crect_selected ); + else if ( deco ) + eDecoWidget::invalidate( crect ); + else + eDecoWidget::invalidate(); + break; + + case eWidgetEvent::changedSize: + invalidate(); + break; + + default: + return eDecoWidget::eventHandler(event); + break; + } + return 1; +} + +eSize eLabel::getExtend() +{ + validate(); + return eSize(para->getBoundBox().width()+(shortcutPixmap?shortcutPixmap->x*2:0), para->getBoundBox().height()); +} + +ePoint eLabel::getLeftTop() +{ + validate(); + return ePoint(para->getBoundBox().left(), para->getBoundBox().top()); +} + +int eLabel::setProperty(const eString &prop, const eString &value) +{ + if (prop=="wrap" && value == "on") + setFlags(RS_WRAP); + else if (prop=="alphatest" && value == "on") + { + transparentBackgroundColor=getBackgroundColor(); + setBackgroundColor(-1); + blitFlags |= BF_ALPHATEST; + } else if (prop=="align") + { + if (value=="left") + setAlign(eTextPara::dirLeft); + else if (value=="center") + setAlign(eTextPara::dirCenter); + else if (value=="right") + setAlign(eTextPara::dirRight); + else if (value=="block") + setAlign(eTextPara::dirBlock); + else + setAlign(eTextPara::dirLeft); + } + else if (prop=="vcenter") + setFlags( flagVCenter ); + else if (prop == "shortcut") + { + setShortcutPixmap(value); + return eWidget::setProperty(prop, value); + } else + return eDecoWidget::setProperty(prop, value); + return 0; +} + +void eLabel::setShortcutPixmap(const eString &shortcut) +{ + eSkin::getActive()->queryImage(shortcutPixmap, "shortcut." + shortcut); +} + +static eWidget *create_eLabel(eWidget *parent) +{ + return new eLabel(parent); +} + +class eLabelSkinInit +{ +public: + eLabelSkinInit() + { + eSkin::addWidgetCreator("eLabel", create_eLabel); + } + ~eLabelSkinInit() + { + eSkin::removeWidgetCreator("eLabel", create_eLabel); + } +}; + +eAutoInitP0<eLabelSkinInit> init_eLabelSkinInit(eAutoInitNumbers::guiobject, "eLabel"); diff --git a/lib/gui/elabel.h b/lib/gui/elabel.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/elabel.h diff --git a/lib/gui/emessage.cpp b/lib/gui/emessage.cpp new file mode 100644 index 00000000..388eb14a --- /dev/null +++ b/lib/gui/emessage.cpp @@ -0,0 +1,163 @@ +#include <lib/gui/emessage.h> + +#include <lib/gui/elabel.h> +#include <lib/gui/ebutton.h> +#include <lib/gui/eskin.h> +#include <lib/gdi/font.h> +#include <lib/base/i18n.h> + +eMessageBox::eMessageBox(eString message, eString caption, int flags, int def): eWindow(0), icon(0) +{ + setText(caption); + int fontsize=eSkin::getActive()->queryValue("fontsize", 20); + int posx = eSkin::getActive()->queryValue("eMessageBox.pos.x", 100); + int posy = eSkin::getActive()->queryValue("eMessageBox.pos.y", 70); + move(ePoint(posx, posy)); + resize(eSize(450, 430)); + + if ( flags > 15 ) // we have to draw an icon + { + ePtr<gPixmap> pm; + switch ( flags & ~15 ) + { + case iconInfo: + eSkin::getActive()->queryImage(pm, "icon_info" ); + break; + case iconQuestion: + eSkin::getActive()->queryImage(pm, "icon_question" ); + break; + case iconWarning: + eSkin::getActive()->queryImage(pm, "icon_warning" ); + break; + case iconError: + eSkin::getActive()->queryImage(pm, "icon_error" ); + break; + } + if (pm) + { + icon = new eLabel(this); + icon->setPixmap( pm ); + icon->pixmap_position=ePoint(0,0); + icon->resize( eSize(pm->x, pm->y) ); + icon->setBlitFlags( BF_ALPHATEST ); + } + } + + text=new eLabel(this); + text->setText(message); + text->resize( eSize( clientrect.width(), clientrect.height() )); + text->setFlags( RS_WRAP|eLabel::flagVCenter ); + eSize txtSize=text->getExtend(); + txtSize+=eSize(8,4); // the given Size of the Text is okay... but the renderer sucks... + text->resize(txtSize); + + // here the two labels ( icon, text) has the correct size.. now we calc the border + + eSize ext; + + if ( icon ) + { + if ( icon->getSize().height() > text->getSize().height() ) + { + eDebug("icon is higher"); + eSize s = icon->getSize(); + icon->move( ePoint( 20, 20 ) ); + text->move( ePoint( 20 + s.width() + 20, icon->getPosition().y() + s.height() / 2 - txtSize.height() / 2 ) ); + ext.setHeight( icon->getPosition().y() + icon->getSize().height() + 20 ); + } + else + { + eDebug("text is higher"); + text->move( ePoint( 20 + icon->getSize().width() + 20 , 20 ) ); + icon->move( ePoint( 20, text->getPosition().y() + text->getSize().height() / 2 - icon->getSize().height() / 2 ) ); + ext.setHeight( text->getPosition().y() + text->getSize().height() + 20 ); + } + ext.setWidth( text->getPosition().x() + text->getSize().width() + 20 ); + } + else + { + text->move( ePoint(20, 20) ); + ext.setWidth( text->getPosition().x() + text->getSize().width()+20 ); + ext.setHeight( text->getPosition().y() + text->getSize().height() + 20 ); + } + + if (ext.width()<150) + ext.setWidth(150); + + int xpos=20; + + if ( flags & 15) + { + for (int i=btOK; i<btMax; i<<=1) + if (flags & i) + { + eButton *b=new eButton(this); + b->resize(eSize(size.width(), fontsize+4)); + const char *t="", *shortcut=""; + switch (i) + { + case btOK: t=_("OK"); shortcut="green"; CONNECT(b->selected, eMessageBox::pressedOK); break; + case btCancel: t=_("Cancel"); shortcut="red"; CONNECT(b->selected, eMessageBox::pressedCancel); break; + case btYes: t=_("Yes"); shortcut="green"; CONNECT(b->selected, eMessageBox::pressedYes); break; + case btNo: t=_("No"); shortcut="red"; CONNECT(b->selected, eMessageBox::pressedNo); break; + } + b->setProperty("shortcut", shortcut); + b->setText(t); + eSize bSize=b->getExtend(); + bSize.setWidth( bSize.width() * 2 ); + bSize.setHeight( fontsize + 4 + 10 ); + b->resize(bSize); + b->move( ePoint( xpos, ext.height() ) ); + + b->loadDeco(); + + if (def == i) + setFocus(b); + + xpos += bSize.width()+20; + if ( xpos+20 > ext.width() ) + cresize( eSize( xpos+20, ext.height() + bSize.height() + 20 ) ); + else + cresize( eSize( ext.width(), ext.height() + bSize.height() + 20 ) ); + } + } + else + cresize( ext ); + zOrderRaise(); +} + +eMessageBox::~eMessageBox() +{ +} + +void eMessageBox::pressedOK() +{ + if ( in_loop ) + close(btOK); + else + hide(); +} + +void eMessageBox::pressedCancel() +{ + if ( in_loop ) + close(btCancel); + else + hide(); +} + +void eMessageBox::pressedYes() +{ + if ( in_loop ) + close(btYes); + else + hide(); +} + +void eMessageBox::pressedNo() +{ + if ( in_loop ) + close(btNo); + else + hide(); +} diff --git a/lib/gui/emessage.h b/lib/gui/emessage.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/emessage.h diff --git a/lib/gui/enumber.cpp b/lib/gui/enumber.cpp new file mode 100644 index 00000000..c03ec8f7 --- /dev/null +++ b/lib/gui/enumber.cpp @@ -0,0 +1,447 @@ +#include <lib/gui/enumber.h> +#include <lib/driver/rc.h> +#include <lib/gui/eskin.h> +#include <lib/gui/elabel.h> +#include <lib/gdi/fb.h> +#include <lib/gdi/grc.h> +#include <lib/gdi/font.h> +#include <lib/gui/guiactions.h> + +void eNumber::unpack(__u32 l, int *t) +{ + for (int i=0; i<4; i++) + *t++=(l>>((3-i)*8))&0xFF; +} + +void eNumber::pack(__u32 &l, int *t) +{ + l=0; + for (int i=0; i<4; i++) + l|=(*t++)<<((3-i)*8); +} + +eRect eNumber::getNumberRect(int n) +{ + if (deco_selected && have_focus) + return eRect( deco_selected.borderLeft + n * space_selected, deco_selected.borderTop, dspace, crect_selected.height() ); + else if (deco) + return eRect( deco.borderLeft + n * dspace, deco.borderTop, dspace, crect.height() ); + else + return eRect( n * dspace, 0, dspace, height() ); +} + +void eNumber::redrawNumber(gPainter *p, int n, const eRect &area) +{ + eRect pos = getNumberRect(n); + + if (!area.contains(pos) ) + return; + + p->setForegroundColor((have_focus && n==active)?cursorB:normalB); + p->fill(pos); + p->setFont(font); + + eString t; + if (flags & flagFillWithZeros || ( (flags & flagFixedNum) && n )) + { + eString s = "%0"+eString().setNum(maxdigits)+(base==10?"d":"X"); + const char* p = s.c_str(); + char* tmp = new char[10]; + strcpy( tmp, p ); + t.sprintf(tmp, number[n]); + delete [] tmp; + } + else + { + if (flags&flagHideInput) + t="*"; + else if (base==10) + t.sprintf("%d", number[n]); + else if (base==0x10) + t.sprintf("%X", number[n]); + } + + if (!n && flags & flagPosNeg && neg) + t="-"+t; + + if (n && (flags & flagTime)) + t=":"+t; + + else if (n && ( (flags & flagDrawPoints) || (flags & flagFixedNum)) ) + t="."+t; + + p->setForegroundColor((have_focus && n==active)?cursorF:normalF); + p->setBackgroundColor((have_focus && n==active)?cursorB:normalB); + + p->clip( pos ); + if (!n && len==2 && ((flags & flagFixedNum) || (flags & flagTime)) ) // first element... + { + eTextPara *para = new eTextPara( pos ); + para->setFont( font ); + para->renderString( t ); + para->realign( eTextPara::dirRight ); + p->renderPara( *para ); + para->destroy(); + } + else + p->renderText(pos, t); + + p->clippop(); +} + +double eNumber::getFixedNum() +{ + if (flags & flagFixedNum) + { + if (flags&flagPosNeg && neg) + { + double d = -((double)number[0]+(double)number[1]/1000); + eDebug("getFixedNum %lf", d); + return d; + } + else + { + float d = (double)number[0]+(double)number[1]/1000; + eDebug("getFixedNum %lf", d); + return d; + } + } + else + return 0; +} + +void eNumber::setFixedNum(double d) +{ + eDebug("setFixedNum %lf", d); + if (flags & flagPosNeg) + neg=d<0; + else + neg=0; + + d=fabs(d); + + if (flags & flagFixedNum) + { + number[0]=(int)d; + number[1]=(int)round(( ( d - number[0] ) * 1000) ); + } + else + eDebug("eNumber bug... the Number %s is not a fixed Point number", name.c_str()); +} + +void eNumber::redrawWidget(gPainter *p, const eRect &area) +{ + for (int i=0; i<len; i++) + redrawNumber(p, i, area); + + if (deco_selected && have_focus) + deco_selected.drawDecoration(p, ePoint(width(), height())); + else if (deco) + deco.drawDecoration(p, ePoint(width(), height())); +} + +void eNumber::invalidateNum() +{ + if ( have_focus && deco_selected ) + invalidate( crect_selected ); + else if ( deco ) + invalidate( crect ); + else + invalidate(); +} + +int eNumber::eventHandler(const eWidgetEvent &event) +{ +#ifndef DISABLE_LCD + if (LCDTmp) + ((eNumber*) LCDTmp)->eventHandler(event); +#endif + switch (event.type) + { + case eWidgetEvent::changedSize: + if (deco) + dspace = (crect.width()) / len; + else + dspace = (size.width()) / len; + if (deco_selected) + space_selected = (crect_selected.width()) / len; + break; + case eWidgetEvent::evtAction: + if ( len > 1 && event.action == &i_cursorActions->left) + { + int oldac=active; + active--; + invalidate(getNumberRect(oldac)); + if (active<0) + active=len-1; + if (active!=oldac) + invalidate(getNumberRect(active)); + digit=0; + } else if ( len > 1 && (event.action == &i_cursorActions->right) || (event.action == &i_cursorActions->ok)) + { + int oldac=active; + active++; + invalidate(getNumberRect(oldac)); + if (active>=len) + { + if (event.action == &i_cursorActions->ok) + /*emit*/ selected(number); + active=0; + } + if (active!=oldac) + invalidate(getNumberRect(active)); + digit=0; + } else + break; + return 1; + default: + break; + } + return eDecoWidget::eventHandler(event); +} + +// isactive is the digit (always in the first field ) +// that ist active after get the first focus ! + +eNumber::eNumber(eWidget *parent, int _len, int _min, int _max, int _maxdigits, int *init, int isactive, eWidget* descr, int grabfocus, const char *deco) + :eDecoWidget(parent, grabfocus, deco ), + active(0), + cursorB(eSkin::getActive()->queryScheme("global.selected.background")), + cursorF(eSkin::getActive()->queryScheme("global.selected.foreground")), + normalB(eSkin::getActive()->queryScheme("global.normal.background")), + normalF(eSkin::getActive()->queryScheme("global.normal.foreground")), + have_focus(0), digit(isactive), isactive(isactive), flags(0), descr(descr), tmpDescr(0), + neg(false) +{ + setNumberOfFields(_len); + setLimits(_min, _max); + setMaximumDigits(_maxdigits); + setBase(10); + for (int i=0; init && i<len; i++) + number[i]=init[i]; + addActionMap(&i_cursorActions->map); +} + +eNumber::~eNumber() +{ +} + +int eNumber::keyDown(int key) +{ +#ifndef DISABLE_LCD + if (LCDTmp) + ((eNumber*) LCDTmp)->keyDown(key); +#endif + switch (key) + { + case eRCInput::RC_0 ... eRCInput::RC_9: + { + int nn=(digit!=0)?number[active]*10:0; + nn+=key-eRCInput::RC_0; + if (flags & flagTime) + { + if ( active ) + max = 59; + else + max = 23; + } + else if (flags & flagFixedNum) + { + if (active) + max=999; + else + max=oldmax; + } + if (nn>=min && nn<=max) + { + number[active]=nn; + invalidate(getNumberRect(active)); + digit++; + if ((digit>=maxdigits) || (nn==0)) + { + active++; + invalidate(getNumberRect(active-1)); + digit=0; + /*emit*/ numberChanged(); + if (active>=len) + { + /*emit*/ selected(number); + active=0; + } + else + invalidate(getNumberRect(active)); + } + } + break; + + break; + } + case eRCInput::RC_PLUS: + if (flags & flagPosNeg && neg ) + { + neg=false; + invalidate(getNumberRect(0)); + } + break; + + case eRCInput::RC_MINUS: + if (flags & flagPosNeg && !neg ) + { + neg=true; + invalidate(getNumberRect(0)); + } + default: + return 0; + } + return 1; +} + +void eNumber::gotFocus() +{ + have_focus++; + digit=isactive; + + if (deco && deco_selected) + invalidate(); + else + invalidate(getNumberRect(active)); + +#ifndef DISABLE_LCD + if (parent && parent->LCDElement) // detect if LCD Avail + { + LCDTmp = new eNumber(parent->LCDElement, len, min, max, maxdigits, &(number[0]), isactive, 0, 0); + LCDTmp->hide(); + ((eNumber*)LCDTmp)->setFlags(flags); + eSize s = parent->LCDElement->getSize(); + + if (descr) + { + LCDTmp->move(ePoint(0,s.height()/2)); + LCDTmp->resize(eSize(s.width(), s.height()/2)); + tmpDescr = new eLabel(parent->LCDElement); + tmpDescr->hide(); + tmpDescr->move(ePoint(0,0)); + tmpDescr->resize(eSize(s.width(), s.height()/2)); + tmpDescr->setText(descr->getText()); + tmpDescr->show(); + } + else + { + LCDTmp->resize(s); + LCDTmp->move(ePoint(0,0)); + } + ((eNumber*)LCDTmp)->digit=digit; + ((eNumber*)LCDTmp)->active=active; + ((eNumber*)LCDTmp)->normalF=255; + ((eNumber*)LCDTmp)->normalB=0; + ((eNumber*)LCDTmp)->cursorF=0; + ((eNumber*)LCDTmp)->cursorB=255; + ((eNumber*)LCDTmp)->have_focus=1; + LCDTmp->show(); + } + #endif //DISABLE_LCD +} + +void eNumber::lostFocus() +{ +#ifndef DISABLE_LCD + if (LCDTmp) + { + delete LCDTmp; + LCDTmp=0; + if (tmpDescr) + { + delete tmpDescr; + tmpDescr=0; + } + } +#endif + have_focus--; + + if (deco && deco_selected) + invalidate(); + else + invalidate(getNumberRect(active)); + isactive=0; +} + +void eNumber::setNumber(int f, int n) +{ + if (flags & flagPosNeg) + { + if(!f && n<0) + neg=true; + else + neg=false; + } + else + neg=false; + + if ((f>=0) && (f<len)) + number[f]=abs(n); + + invalidate(getNumberRect(f)); +} + +void eNumber::setLimits(int _min, int _max) +{ + min=_min; + max=_max; + oldmax=max; +} + +void eNumber::setNumberOfFields(int n) +{ + len=n; +} + +void eNumber::setMaximumDigits(int n) +{ + if (n > 16) + n=16; + maxdigits=n; + if (digit >= maxdigits) + digit=0; +} + +void eNumber::setFlags(int _flags) +{ + if (flags&flagFixedNum) + len=2; + + flags=_flags; +} + +void eNumber::setBase(int _base) +{ + base=_base; +} + +void eNumber::setNumber(int n) +{ + if ( flags&flagPosNeg ) + neg = n < 0; + else + neg=0; + + if( len == 1 ) + number[0]=abs(n); + else + for (int i=len-1; i>=0; --i) + { + number[i]=n%base; + n/=base; + } + invalidateNum(); +} + +int eNumber::getNumber() +{ + int n=0; + for (int i=0; i<len; i++) + { + n*=base; + n+=number[i]; + } + return flags&flagPosNeg && neg ? -n : n; +} diff --git a/lib/gui/enumber.h b/lib/gui/enumber.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/enumber.h diff --git a/lib/gui/epixmap.cpp b/lib/gui/epixmap.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/epixmap.cpp diff --git a/lib/gui/epixmap.h b/lib/gui/epixmap.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/epixmap.h diff --git a/lib/gui/eprogress.cpp b/lib/gui/eprogress.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/eprogress.cpp diff --git a/lib/gui/eprogress.h b/lib/gui/eprogress.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/eprogress.h diff --git a/lib/gui/eservicegrid.cpp b/lib/gui/eservicegrid.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/eservicegrid.cpp diff --git a/lib/gui/eservicegrid.h b/lib/gui/eservicegrid.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/eservicegrid.h diff --git a/lib/gui/eskin.cpp b/lib/gui/eskin.cpp new file mode 100644 index 00000000..6cb98abd --- /dev/null +++ b/lib/gui/eskin.cpp @@ -0,0 +1,760 @@ +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> + +#include <lib/gui/eskin.h> +#include <lib/gui/ewidget.h> +#include <lib/gdi/gfbdc.h> +#include <lib/gdi/glcddc.h> +#include <lib/gdi/epng.h> +#include <lib/base/eerror.h> +#include <lib/gdi/font.h> +#include <lib/base/eptrlist.h> + +std::map< eString,tWidgetCreator > eSkin::widget_creator; + +eSkin *eSkin::active; + +eNamedColor *eSkin::searchColor(const eString &name) +{ + for (std::list<eNamedColor>::iterator i(colors.begin()); i != colors.end(); ++i) + { + if (!i->name.compare(name)) + return &*i; + } + return 0; +} + +void eSkin::clear() +{ +} + +void eSkin::addWidgetCreator(const eString &name, tWidgetCreator creator) +{ + widget_creator[name] = creator; // add this tWidgetCreator to map... if exist.. overwrite +} + +void eSkin::removeWidgetCreator(const eString &name, tWidgetCreator creator) +{ + widget_creator.erase(name); +} + +int eSkin::parseColor(const eString &name, const char* color, gRGB &col) +{ + if (color[0]=='#') + { + unsigned long vcol=0; + if (sscanf(color+1, "%lx", &vcol)!=1) + { + eDebug("invalid color named \"%s\" (value: %s)", name.c_str(), color+1); + return -1; + } + col.r=(vcol>>16)&0xFF; + col.g=(vcol>>8)&0xFF; + col.b=vcol&0xFF; + col.a=(vcol>>24)&0xFF; + } else + { + eNamedColor *n=searchColor(color); + if (!n) + { + eDebug("invalid color named \"%s\" (alias to: \"%s\")", name.c_str(), color); + return -1; + } + col=n->value; + } + return 0; +} + +int eSkin::parseColors(XMLTreeNode *xcolors) +{ + XMLTreeNode *node; + + std::list<eNamedColor>::iterator newcolors=colors.end(); + + for (node=xcolors->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "color")) + { + eDebug("junk found in colorsection (%s)", node->GetType()); + continue; + } + + const char *name=node->GetAttributeValue("name"), *color=node->GetAttributeValue("color"), *end=node->GetAttributeValue("end"); + + if (!color || !name) + { + eDebug("no color/name specified"); + continue; + } + + eNamedColor col; + col.name=name; + + const char *size=node->GetAttributeValue("size"); + + if (size) + col.size=atoi(size); + else + col.size=0; + + if (!col.size) + col.size=1; + + if ((col.size>1) && (!end)) + { + eDebug("no end specified in \"%s\" but is gradient", name); + continue; + } + + if (parseColor(name, color, col.value)) + continue; + + if (end && parseColor(name, end, col.end)) + continue; + + colors.push_back(col); + if (newcolors == colors.end()) + --newcolors; + } + + for (std::list<eNamedColor>::iterator i(newcolors); i != colors.end(); ++i) + { + eNamedColor &col=*i; + int d; + for (d=0; d<maxcolors; d+=col.size) + { + int s; + for (s=0; s<col.size; s++) + if ((d+s>maxcolors) || colorused[d+s]) + break; + if (s==col.size) + break; + } + if (d==maxcolors) + continue; + col.index=gColor(d); + for (int s=0; s<col.size; s++, d++) + { + colorused[d]=1; + if (s) + { + int rdiff=-col.value.r+col.end.r; + int gdiff=-col.value.g+col.end.g; + int bdiff=-col.value.b+col.end.b; + int adiff=-col.value.a+col.end.a; + rdiff*=s; rdiff/=(col.size-1); + gdiff*=s; gdiff/=(col.size-1); + bdiff*=s; bdiff/=(col.size-1); + adiff*=s; adiff/=(col.size-1); + palette[d].r=col.value.r+rdiff; + palette[d].g=col.value.g+gdiff; + palette[d].b=col.value.b+bdiff; + palette[d].a=col.value.a+adiff; + } else + palette[d]=col.value; + } + } + return 0; +} + +int eSkin::parseScheme(XMLTreeNode *xscheme) +{ + XMLTreeNode *node; + for (node=xscheme->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal scheme entry found: %s", node->GetType()); + continue; + } + char *name=node->GetAttributeValue("name"), *color=node->GetAttributeValue("color"); + if (!name || !color) + { + eDebug("no name or color specified in colorscheme"); + continue; + } + eString base=color; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + eNamedColor *n=searchColor(base); + if (!n) + { + eDebug("illegal color \"%s\" specified", base.c_str()); + continue; + } + scheme[name] = gColor(n->index+offset); + } + return 0; +} + +int eSkin::parseFontAlias(XMLTreeNode *xscheme) +{ + XMLTreeNode *node; + for (node=xscheme->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal fontalias entry found: %s", node->GetType()); + continue; + } + char *font=node->GetAttributeValue("font"), + *name=node->GetAttributeValue("name"), + *size=node->GetAttributeValue("size"); + + if (!name || !font || !size) + { + eDebug("no name, alias or size spezified in fontaliase"); + continue; + } + + std::map<eString, gFont>::iterator it = fontAlias.find(name); + if (it != fontAlias.end()) + continue; + + std::map<eString, eString>::iterator i = fonts.find(font); + if (i == fonts.end()) + { + eDebug("font %s not found, skip make alias %s", font, name); + continue; + } + fontAlias[name]=gFont(i->second, atoi(size)); + } + return 0; +} + +int eSkin::parseImages(XMLTreeNode *inode) +{ + char *abasepath=inode->GetAttributeValue("basepath"); + if (!abasepath) + abasepath=""; + eString basepath=eString("/enigma/pictures/"); + if (abasepath[0] == '/') // allow absolute paths + basepath=""; + basepath+=abasepath; + if (basepath[basepath.length()-1]!='/') + basepath+="/"; + + for (XMLTreeNode *node=inode->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "img")) + { + eDebug("illegal image entry found: %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("illegal <img> entry: no name"); + continue; + } + const char *src=node->GetAttributeValue("src"); + if (!src) + { + eDebug("image/img=\"%s\" no src given", name); + continue; + } + std::map<eString, ePtr<gPixmap> >::iterator it = images.find(name); + if (it != images.end()) + { +// eDebug("Image with name %s already loaded, skip %s", name, src); + continue; + } + ePtr<gPixmap> image=0; + eString filename=basepath + eString(src); + if (abasepath[0] != '/') + { + // search first in CONFIGDIR + image=loadPNG((eString(CONFIGDIR)+filename).c_str()); + if (!image) + image=loadPNG((eString(DATADIR)+filename).c_str()); + } + else // abs path + image=loadPNG(filename.c_str()); + + if (!image) + { + eDebug("image/img=\"%s\" - %s: file not found", name, filename.c_str()); + continue; + } + + if (paldummy && !node->GetAttributeValue("nomerge")) + { + gPixmapDC mydc(image); + gPainter p(mydc); + p.mergePalette(paldummy); + } + images[name] = image; + } + return 0; +} + +int eSkin::parseImageAlias(XMLTreeNode *xvalues) +{ + for (XMLTreeNode *node=xvalues->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "map")) + { + eDebug("illegal values entry %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"), + *img=node->GetAttributeValue("img"); + if (!name || !img) + { + eDebug("map entry has no name or img"); + continue; + } + std::map<eString, eString>::iterator it = imageAlias.find(name); + if (it != imageAlias.end()) + { + eDebug("imagealias %s does exist, skip make alias for image %s", name, img); + continue; + } + std::map<eString, ePtr<gPixmap> >::iterator i = images.find(img); + if (i == images.end()) + { + eDebug("image %s not found, skip make alias %s", img , name); + continue; + } + imageAlias[name]=img; + } + return 0; +} + +int eSkin::parseFonts(XMLTreeNode *xfonts) +{ + const char *abasepath=xfonts->GetAttributeValue("basepath"); + eString basepath=abasepath?abasepath:FONTDIR; + + if (basepath.length()) + if (basepath[basepath.length()-1]!='/') + basepath+="/"; + + for (XMLTreeNode *node=xfonts->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "font")) + { + eDebug("illegal fonts entry %s", node->GetType()); + continue; + } + const char *file=node->GetAttributeValue("file"); + if (!file) + { + eDebug("fonts entry has no file"); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("fonts entry has no name use filename %s as name", file); + name = file; + } + std::map<eString, eString>::iterator it = fonts.find(name); + const char *ascale=node->GetAttributeValue("scale"); + int scale=0; + if (ascale) + scale=atoi(ascale); + if (!scale) + scale=100; + if (it != fonts.end()) + { + eDebug("Font with name %s already loaded, skip %s", name, file); + continue; + } + fonts[name]=fontRenderClass::getInstance()->AddFont(basepath+eString(file), name, scale); + if (node->GetAttributeValue("replacement")) + eTextPara::setReplacementFont(name); + } + return 0; +} + +int eSkin::parseValues(XMLTreeNode *xvalues) +{ + for (XMLTreeNode *node=xvalues->GetChild(); node; node=node->GetNext()) + { + if (strcmp(node->GetType(), "value")) + { + eDebug("illegal values entry %s", node->GetType()); + continue; + } + const char *name=node->GetAttributeValue("name"); + if (!name) + { + eDebug("values entry has no name"); + continue; + } + const char *value=node->GetAttributeValue("value"); + if (!value) + { + eDebug("values entry has no value"); + continue; + } + std::map<eString, int>::iterator it = values.find(name); + if (it != values.end()) + { + eDebug("value %s does exist, skip make value %s=%i", name, value); + continue; + } + values[name]=atoi(value); + } + return 0; +} + +gDC *eSkin::getDCbyName(const char *name) +{ + gPixmapDC *dc=0; + if (!strcmp(name, "fb")) + dc=gFBDC::getInstance(); +#ifndef DISABLE_LCD + else if (!strcmp(name, "lcd")) + dc=gLCDDC::getInstance(); +#endif + return dc; +} + +int eSkin::build(eWidget *widget, XMLTreeNode *node) +{ +// eDebug("building a %s", node->GetType()); +/* if (widget->getType() != node->GetType()) + return -1;*/ + + for (XMLAttribute *attrib=node->GetAttributes(); attrib; attrib=attrib->GetNext()) + { +// eDebug("setting %s := %s", attrib->GetName(), attrib->GetValue()); + if (widget->setProperty(attrib->GetName(), attrib->GetValue())) + { + eDebug("failed"); + return -1; + } + } + for (XMLTreeNode *c=node->GetChild(); c; c=c->GetNext()) + { + eWidget *w=0; + + const char *name=c->GetAttributeValue("name"); + + if (name) + w=widget->search(name); + + if (!w) + { + std::map< eString, tWidgetCreator >::iterator it = widget_creator.find(c->GetType()); + + if ( it == widget_creator.end() ) + { + eWarning("widget class %s does not exist", c->GetType()); + return -ENOENT; + } + w = (it->second)(widget); + } + if (!w) + { + // eDebug("failed."); + return -EINVAL; + } + w->zOrderRaise(); + int err; + if ((err=build(w, c))) + { + return err; + } + } + return 0; +} + +eSkin::eSkin() +{ + maxcolors=256; + + palette=new gRGB[maxcolors]; + + memset(palette, 0, sizeof(gRGB)*maxcolors); + paldummy=new gImage(eSize(1, 1), 8); + paldummy->clut.data=palette; + paldummy->clut.colors=maxcolors; + + colorused=new int[maxcolors]; + memset(colorused, 0, maxcolors*sizeof(int)); +} + +eSkin::~eSkin() +{ + if (active==this) + active=0; + + clear(); + + delete colorused; + + for (std::map<eString, ePtr<gPixmap> >::iterator it(images.begin()); it != images.end(); it++) + delete it->second; + + if (paldummy) + delete paldummy; +} + +int eSkin::load(const char *filename) +{ + eDebug("loading skin: %s", filename); + FILE *in=fopen(filename, "rt"); + if (!in) + return -1; + + parsers.push_front(new XMLTreeParser("ISO-8859-1")); + XMLTreeParser &parser=*parsers.first(); + char buf[2048]; + + int done; + do + { + unsigned int len=fread(buf, 1, sizeof(buf), in); + done=len<sizeof(buf); + if (!parser.Parse(buf, len, done)) + { + eDebug("parse error: %s at line %d", + parser.ErrorString(parser.GetErrorCode()), + parser.GetCurrentLineNumber()); + parsers.pop_front(); + fclose(in); + return -1; + } + } while (!done); + fclose(in); + + XMLTreeNode *root=parser.RootNode(); + if (!root) + return -1; + if (strcmp(root->GetType(), "eskin")) + { + eDebug("not an eskin"); + return -1; + } + + return 0; +} + +void eSkin::parseSkins() +{ + for (ePtrList<XMLTreeParser>::reverse_iterator it(parsers); it != parsers.rend(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "colors")) + parseColors(node); + } + + for (ePtrList<XMLTreeParser>::reverse_iterator it(parsers); it != parsers.rend(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "colorscheme")) + parseScheme(node); + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "fonts")) + parseFonts(node); + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "fontalias")) + parseFontAlias(node); + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "images")) + parseImages(node); + + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "imagealias")) + parseImageAlias(node); + + } + + for (ePtrList<XMLTreeParser>::iterator it(parsers); it != parsers.end(); it++) + { + XMLTreeNode *node=it->RootNode(); + + for (node=node->GetChild(); node; node=node->GetNext()) + if (!strcmp(node->GetType(), "values")) + parseValues(node); + } +} + + +int eSkin::build(eWidget *widget, const char *name) +{ + for (parserList::iterator i(parsers.begin()); i!=parsers.end(); ++i) + { + XMLTreeNode *node=i->RootNode(); + node=node->GetChild(); + while (node) + { + if (!strcmp(node->GetType(), "object")) + { + const char *oname=node->GetAttributeValue("name"); + if (!std::strcmp(name, oname)) + { + node=node->GetChild(); + return build(widget, node); + } + } + node=node->GetNext(); + } + } + eDebug("didn't found it"); + return -ENOENT; +} + +void eSkin::setPalette(gPixmapDC *pal) +{ + if (palette) + { + gPainter p(*pal); + p.setPalette(palette, 0, 256); + } +} + +eSkin *eSkin::getActive() +{ + if (!active) + eFatal("no active skin"); + return active; +} + +void eSkin::makeActive() +{ + active=this; +} + +gColor eSkin::queryScheme(const eString& name) const +{ + eString base=name; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + + std::map<eString, gColor>::const_iterator it = scheme.find(base); + + if (it != scheme.end()) + return it->second + offset; + +// eWarning("%s does not exist", name.c_str()); + + return gColor(0); +} + +RESULT eSkin::queryImage(ePtr<gPixmap> &ptr, const eString& name) const +{ + eString img; + + std::map<eString, eString>::const_iterator i = imageAlias.find(name); + + if (i != imageAlias.end()) + img = i->second; + else + img = name; + + std::map<eString, ePtr<gPixmap> >::const_iterator it = images.find(img); + + if (it != images.end()) + ptr = it->second; + + return 0; +} + +int eSkin::queryValue(const eString& name, int d) const +{ + std::map<eString, int>::const_iterator it = values.find(name); + + if (it != values.end()) + return it->second; + + return d; +} + +gColor eSkin::queryColor(const eString& name) +{ + char *end; + + int numcol=strtol(name.c_str(), &end, 10); + + if (!*end) + return gColor(numcol); + + eString base=name; + int offset=0, p; + if ((p=base.find('+'))!=-1) + { + offset=atoi(base.mid(p).c_str()); + base=base.left(p); + } + + eNamedColor *col=searchColor(base); + + if (!col) + { + return queryScheme(name); + } else + return col->index + offset; +} + +gFont eSkin::queryFont(const eString& name) +{ + std::map<eString, gFont>::iterator it = fontAlias.find(name); // check if name is a font alias + + if ( it != fontAlias.end() ) // font alias found + return it->second; + + eString family; + int size=0; + + unsigned int sem = name.rfind(';'); // check if exist ';' in name + if (sem != eString::npos) // then exist + { + family=name.left(sem); + size = atoi( name.mid(sem+1).c_str() ); + if (size<=0) + size=16; + } + + std::map<eString, eString>::iterator i = fonts.find(family); // check if family is a font name + if ( i != fonts.end() ) // font exist + return gFont(i->second, size); + + for (i = fonts.begin() ; i != fonts.end(); i++) // as last check if family name is a complete font Face + if ( i->second == family) + return gFont(i->second, size); + + eFatal("Font %s does not exist", name.c_str() ); // halt Programm now... Font does not exist + + return gFont(); +} diff --git a/lib/gui/eskin.h b/lib/gui/eskin.h new file mode 100644 index 00000000..0a6bd352 --- /dev/null +++ b/lib/gui/eskin.h @@ -0,0 +1,87 @@ +#ifndef __eskin_h +#define __eskin_h + +#include <list> +#include <map> +#include <xmltree.h> + +#include <lib/base/estring.h> +#include <lib/base/eptrlist.h> +#include <lib/gdi/grc.h> + +class eWidget; +class gPixmap; +typedef eWidget *(*tWidgetCreator)(eWidget *parent); + +struct eNamedColor +{ + eString name; + gRGB value, end; + int index; + int size; +}; + +class eSkin +{ + typedef ePtrList<XMLTreeParser> parserList; + parserList parsers; + void clear(); + + int parseColor(const eString& name, const char *color, gRGB &col); + int parseColors(XMLTreeNode *colors); + int parseScheme(XMLTreeNode *scheme); + int parseImages(XMLTreeNode *images); + int parseImageAlias(XMLTreeNode *images); + int parseValues(XMLTreeNode *values); + int parseFonts(XMLTreeNode *fonts); + int parseFontAlias(XMLTreeNode *fonts); + + gDC *getDCbyName(const char *name); + + gRGB *palette; + int maxcolors; + gImage *paldummy; + int *colorused; + + static std::map< eString, tWidgetCreator > widget_creator; + int build(eWidget *widget, XMLTreeNode *rootwidget); + + std::list<eNamedColor> colors; + std::map<eString, gColor> scheme; + std::map<eString, ePtr<gPixmap> > images; + std::map<eString, int> values; + std::map<eString, eString> fonts; + std::map<eString, gFont> fontAlias; + std::map<eString, eString> imageAlias; + + eNamedColor *searchColor(const eString &name); + + static eSkin *active; +public: + eSkin(); + ~eSkin(); + + static void addWidgetCreator(const eString &name, tWidgetCreator creator); + static void removeWidgetCreator(const eString &name, tWidgetCreator creator); + + int load(const char *filename); + void parseSkins(); + + int build(eWidget *widget, const char *name); + void setPalette(gPixmapDC *pal); + + gColor queryColor(const eString &name); + gColor queryScheme(const eString &name) const; + RESULT queryImage(ePtr<gPixmap> &pixmap, const eString &name) const; + int queryValue(const eString &name, int d) const; + gFont queryFont(const eString &name); + + void makeActive(); + + static eSkin *getActive(); +}; + +#define ASSIGN(v, t, n) \ + v =(t*)search(n); if (! v ) { eWarning("skin has undefined element: %s", n); v=new t(this); } + +#endif diff --git a/lib/gui/eskin_register.cpp b/lib/gui/eskin_register.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/eskin_register.cpp diff --git a/lib/gui/eskin_register.h b/lib/gui/eskin_register.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/eskin_register.h diff --git a/lib/gui/ewidget.cpp b/lib/gui/ewidget.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/ewidget.cpp diff --git a/lib/gui/ewidget.h b/lib/gui/ewidget.h new file mode 100644 index 00000000..3a1199a0 --- /dev/null +++ b/lib/gui/ewidget.h @@ -0,0 +1,498 @@ +#ifndef __ewidget_h +#define __ewidget_h + +#include <lib/base/ebase.h> +#include <lib/base/estring.h> +#include <lib/gdi/epoint.h> +#include <lib/gdi/esize.h> +#include <lib/gdi/erect.h> +#include <lib/base/eptrlist.h> +#include <libsig_comp.h> +#include <lib/gdi/grc.h> +#include <lib/driver/rc.h> +#include <lib/gui/actions.h> + +class eWidgetEvent +{ +public: + enum eventType + { + evtKey, + willShow, willHide, + execBegin, execDone, + gotFocus, lostFocus, + + changedText, changedFont, changedForegroundColor, changedBackgroundColor, + changedSize, changedPosition, changedPixmap, childChangedHelpText, + + evtAction, evtShortcut + } type; + union + { + int parameter; + const eAction *action; + const eRCKey *key; + }; + eWidgetEvent(eventType type, int parameter=0): type(type), parameter(parameter) { } + eWidgetEvent(eventType type, const eAction *action): type(type), action(action) { } + eWidgetEvent(eventType type, const eRCKey &key): type(type), key(&key) { } + + /** + * \brief Event should be delivered to the focused widget. + * + * \return true if the event should be delivered to the focused widget instead of the widget itself. + */ + int toFocus() const + { + switch (type) + { + case evtKey: + return 1; + default: + return 0; + } + } +}; + +/** \brief The main widget class. All widgets inherit this class. + * eWidget handles focus management. + */ +class eWidget: public Object +{ + enum + { + /// Widget was shown with show() or implicit show() + stateShow=1, + /// Widget is visible on screen. Implies stateShow. + stateVisible=2 + }; + +public: + /** + * \brief Exits a (model) widget. + * + * Quit the local event loop, thus returning the control to the function which called \a exec. + * \sa eWidget::accept + * \sa eWidget::reject + */ + void close(int result); + + /** + * \brief Closes with a returncode of 0 (success). + * + * Synonym to \a close(0);. Useful to use as a slot. + * \sa eWidget::close + */ + void accept(); + + /** + * \brief Closes with a returncode of -1 (failure). + * + * Synonym to \a close(-1);. Useful to use as a slot. + * \sa eWidget::close + */ + void reject(); + /** + * \brief Signal is send, when the focus Changed + * + * used from a existing statusbar. + * \sa eWidget::focusChanged + */ + Signal1<void, const eWidget*> focusChanged; + static Signal2< void, ePtrList<eAction>*, int > showHelp; +protected: + ePtrList<eAction> actionHelpList; + int helpID; + ePtrList<eWidget> childlist; + static eWidget *root; + eWidget *parent; + eString name; + eString helptext; + ePoint position; + ePoint absPosition; + eSize size; + eRect clientrect; + eRect clientclip; + + eAction *shortcut; + eWidget *shortcutFocusWidget; + + ePtrList<eWidget> _focusList; + + ePtrList<eWidget> actionListener; + eWidget *focus, *TLW; + + /// old top-level focus + eWidget *oldTLfocus; + int takefocus; + int state; + + gDC *target; + + inline eWidget *getTLW() // pseudoTLW !! + { + return TLW ? TLW : (TLW = (parent && parent->parent) ? parent->getTLW() : this ); + } + int result, in_loop, have_focus, just_showing; + void takeFocus(); + void releaseFocus(); + + void _willShow(); + void _willHide(); + + virtual void willShow(); + virtual void willHide(); + + virtual void setPalette(); + + void willShowChildren(); + void willHideChildren(); + + /** + * \brief Hi priority event filter. + * + * This event filter is called before the event is delivered via \a event. + * \return 1 if the event should NOT be forwarded. + */ + virtual int eventFilter(const eWidgetEvent &event); + + /** + * \brief Handles an event. + * + * If re-implemented in a widget-sub-class, \c eWidget::event should be called whenever the event is + * not processed by the widget. + * \return 1 if the event was processed, 0 if ignored. it might be forwarded to other widgets then. + */ + + virtual int keyDown(int rc); + virtual int keyUp(int rc); + + virtual void gotFocus(); + virtual void lostFocus(); + + virtual void recalcClientRect(); + void recalcClip(); + void checkFocus(); + + typedef ePtrList<eActionMap> actionMapList; + + void findAction(eActionPrioritySet &prio, const eRCKey &key, eWidget *context); + void addActionMap(eActionMap *map); + void removeActionMap(eActionMap *map); + actionMapList actionmaps; + static actionMapList globalActions; + + // generic properties + gFont font; + eString text; + gColor backgroundColor, foregroundColor; + + ePtr<gPixmap> pixmap; + + eString descr; + +public: + virtual int eventHandler(const eWidgetEvent &event); + static void addGlobalActionMap(eActionMap *map); + static void removeGlobalActionMap(eActionMap *map); + inline eWidget *getNonTransparentBackground() + { + if (backgroundColor >= 0) + return this; + return parent?parent->getNonTransparentBackground():this; + } + +#ifndef DISABLE_LCD + eWidget *LCDTitle; + eWidget *LCDElement; + eWidget *LCDTmp; +#endif + + void recalcAbsolutePosition(); + + inline const ePoint &getAbsolutePosition() const + { + return absPosition; + } + + inline ePoint getRelativePosition(eWidget *e) const + { + ePoint pos=position; + if (this != e) + for (eWidget *a=parent; a && (a != e); a=a->parent) + pos+=a->clientrect.topLeft(); + return pos; + } + + virtual void redrawWidget(gPainter *target, const eRect &area); + + virtual void eraseBackground(gPainter *target, const eRect &area); + + /** + * \brief Constructs a new eWidget. + * \param parent The parent widget. The widget gets automatically removed when the parent gets removed. + * \param takefocus Specifies if the widget should be appended to the focus list of the TLW, i.e. if it can + receive keys. + */ + eWidget(eWidget *parent=0, int takefocus=0); + + /** + * \brief Destructs an eWidget and all its childs. + * + * hide() is called when the widget is shown. The set ePixmap is \e not + * freed. If the widget acquired focus, it will be removed from the focuslist. + * \sa eWidget::setPixmap + */ + virtual ~eWidget(); + + /** + * \brief Returns a pointer to the focus list. + * + * The focus list is the list of childs which have the \c takefocus flag set. + * This list is only maintained for TLWs. + */ + ePtrList<eWidget> *focusList() { return &_focusList; } + + /** + * \brief Resizes the widget. + * + * Sets the size of the widget to the given size. The event \c changedSize event will be generated. + * \param size The new size, relative to the position. + */ + void resize(const eSize& size); + + /** + * \brief Resizes clientrect (and the widget). + * + * Sets the clientrect of the widget to the given size. The real size of the widget will be set to met + * these requirement. The event \c changedSize event will be generated. + * \param size The new size of the clientrect, relative to the position. + */ + void cresize(const eSize& size); + + /** + * \brief Moves the widget. + * + * Set the new position of the widget to the given position. The \c changedPosition event will be generated. + * \param position The new position, relative to the parent's \c clientrect. + */ + void move(const ePoint& position); + + /** + * \brief Moves the clientrect (and the widget). + * + * Set the new position of the clientrect to the given position. The \c changedPosition event will be generated. + * \param position The new position, relative to the parent's \c clientrect. + */ + void cmove(const ePoint& position); + + /** + * \brief Returns the current size. + * + * \return Current size of the widget, relative to the position. + */ + const eSize& getSize() const { return size; } + + /** + * \brief Returns the current position. + * + * \return Current position, relative to the parent's \c clientrect. + */ + const ePoint& getPosition() const { return position; } + + /** + * \brief Returns the size of the clientrect. + * + * \return The usable size for the childwidgets. + */ + eSize getClientSize() const { return clientrect.size(); } + + /** + * \brief Returns the clientrect. + * + * \return The area usable for the childwidgets. + */ + const eRect& getClientRect() const { return clientrect; } + + /** + * \brief Recursive redraw of a widget. + * + * All client windows get repaint too, but no widgets above. Unless you have a good reason, you shouldn't + * use this function and use \c invalidate(). + * \param area The area which should be repaint. The default is to repaint the whole widget. + * \sa eWidget::invalidate + */ + void redraw(eRect area=eRect()); + + /** + * \brief Recursive (complete) redraw of a widget. + * + * Redraws the widget including background. This is the function to use if you want to manually redraw something! + * \param area The area which should be repaint. The default is to repaint the whole widget. + * \param force Forces a parent-invalidate even on non-visible widgets. Shouldn't be used outside eWidget. + * \sa eWidget::redraw + */ + void invalidate(eRect area=eRect(), int force=0); + + /** + * \brief Enters modal message loop. + * + * A new event loop will be launched. The function returns when \a close is called. + * \return The argument of \a close. + * \sa eWidget::close + */ + int exec(); + + /** + * \brief Visually clears the widget. + * + * Clears the widget. This is done on \a hide(). + * \sa eWidget::hide + */ + void clear(); + + /** + * \brief Delivers a widget-event. + * + * Internally calles \a eventFilter, then \a eventHandler() (in some cases of the focused widget) + * \param event The event to deliver. + */ + int event(const eWidgetEvent &event); + + /** + * \brief Shows the widget. + * + * If necessary, the widget will be linked into the TLW's active focus list. The widget will + * visually appear. + * \sa eWidget::hide + */ + void show(); + + /** + * \brief Hides the widget. + * + * The widget will be removed from the screen. All childs will be hidden too. + * \sa eWidget::show + */ + void hide(); + + /** + * \brief Returns if the widget is vissible. + * + * \return If the widget and all parents are visible, \c true is returned, else false. + */ + int isVisible() { return (state&stateVisible) && ( (!parent) || parent->isVisible() ); } + + /** + * \brief Possible focus directions. + */ + enum focusDirection + { + focusDirNext, focusDirPrev, focusDirN, focusDirE, focusDirS, focusDirW + }; + + /** + * \brief changes the focused widget. + * + * Focuses the next or previous widget of the \c focuslist. An \c gotFocus and \c lostFocus event will be + * generated. + * \param dir The direction, \c focusDirection. + */ + void focusNext(int dir=0); + + /** + * \brief Gives focus to a widget. + * + * Set the focus to the specified widget. The \c focuslist is updated, too. + * An \c gotFocus and \c lostFocus event will be generated. + * \param newfocus The new widget to focus. + */ + void setFocus(eWidget *newfocus); + + /** + * \brief Sets the widget font. + * + * The font is used for example by the \c eLabel. + * \sa eLabel + * \param font The new font used by widget-specific drawing code. + */ + void setFont(const gFont &font); + + /** + * \brief Sets the widget caption or text. + * + * \param label The text to assign to the widget. + */ + void setText(const eString &label); + + const eString& getText() const { return text; } + void setBackgroundColor(const gColor& color, bool inv=true); + void setForegroundColor(const gColor& color, bool inv=true); + void setPixmap(gPixmap *pmap); + void setTarget(gDC *target); + gDC *getTarget() { return target; } + +#ifndef DISABLE_LCD + void setLCD(eWidget *lcdtitle, eWidget *lcdelement); +#endif + + void setName(const char *name); + const eString& getName() const { return name; } + eWidget*& getParent() { return parent; } + const gFont& getFont() const { return font; } + + const gColor& getBackgroundColor() const { return backgroundColor; } + const gColor& getForegroundColor() const { return foregroundColor; } + + int width() { return getSize().width(); } + int height() { return getSize().height(); } + + gPainter *getPainter(eRect area); + + const eString& getHelpText() const { return helptext; } + + void setHelpText( const eString&); + /** + * \brief Sets a property. + * + * A property is a value/data pair which is used for serializing widgets (like in skinfiles). + * These properties are available to all \c "eWidget"-based classes. + * \arg \c position, the position of the widget, relative to the parent's childarea. Consider using csize for TLWs. + * Positions are specified in a "x:y" manner. + * \arg \c cposition, the position of the widget's clientrect (upper left). + * This is useful for specifing a position independant of a decoration which might be + * different sized. The real position will be calculated to match the requested position. + * \arg \c size, the size of the widget. Consider using csize for TLWs. Sizes are specified in a "width:height" manner. + * \arg \c csize, the size of the clientrect. The real size will be calculated to match the requested size. + * \arg \c text, the text/caption of the widget. + * \arg \c font, the primary font used in the widget. + * \arg \c name, the name of the widget for referring them. + * \arg \c pixmap, an already loaded, named pixmap to be used as the widget's pixmap. + * \arg \c foregroundColor, a named color, which will be used for the widget's foreground color. + * \arg \c backgroundColor + * \param prop The property to be set. + * \param value The value to be set. + */ + virtual int setProperty(const eString &prop, const eString &value); + + eWidget *search(const eString &name); + + eWidget* getFocus() { return focus; } + + void makeRoot(); + + void zOrderLower(); + void zOrderRaise(); + + /** + * \brief sets the shortcut (generate evtShortcut) + */ + void setShortcut(const eString &shortcut); + void setShortcutFocus(eWidget *focus); + + void addActionToHelpList(eAction *action); + void clearHelpList(); + void setHelpID(int fHelpID); +}; + +#endif diff --git a/lib/gui/ewindow.cpp b/lib/gui/ewindow.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/ewindow.cpp diff --git a/lib/gui/ewindow.h b/lib/gui/ewindow.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/ewindow.h diff --git a/lib/gui/guiactions.cpp b/lib/gui/guiactions.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/guiactions.cpp diff --git a/lib/gui/guiactions.h b/lib/gui/guiactions.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/guiactions.h diff --git a/lib/gui/listbox.cpp b/lib/gui/listbox.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/listbox.cpp diff --git a/lib/gui/listbox.h b/lib/gui/listbox.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/listbox.h diff --git a/lib/gui/multipage.cpp b/lib/gui/multipage.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/multipage.cpp diff --git a/lib/gui/multipage.h b/lib/gui/multipage.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/multipage.h diff --git a/lib/gui/numberactions.cpp b/lib/gui/numberactions.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/numberactions.cpp diff --git a/lib/gui/numberactions.h b/lib/gui/numberactions.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/numberactions.h diff --git a/lib/gui/slider.cpp b/lib/gui/slider.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/slider.cpp diff --git a/lib/gui/slider.h b/lib/gui/slider.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/slider.h diff --git a/lib/gui/statusbar.cpp b/lib/gui/statusbar.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/statusbar.cpp diff --git a/lib/gui/statusbar.h b/lib/gui/statusbar.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/statusbar.h diff --git a/lib/gui/testpicture.cpp b/lib/gui/testpicture.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/testpicture.cpp diff --git a/lib/gui/testpicture.h b/lib/gui/testpicture.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/testpicture.h diff --git a/lib/gui/textinput.cpp b/lib/gui/textinput.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/textinput.cpp diff --git a/lib/gui/textinput.h b/lib/gui/textinput.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/gui/textinput.h |
