aboutsummaryrefslogtreecommitdiff
path: root/lib/gui/ewidget.cpp
diff options
context:
space:
mode:
authorFelix Domke <tmbinc@elitedvb.net>2003-10-17 15:35:43 +0000
committerFelix Domke <tmbinc@elitedvb.net>2003-10-17 15:35:43 +0000
commitfc2f5b2cd655f1391f2abda1b39e37cdec98a951 (patch)
tree312efcea86a319de407a7c314fb981fb1c71019a /lib/gui/ewidget.cpp
downloadenigma2-fc2f5b2cd655f1391f2abda1b39e37cdec98a951.tar.gz
enigma2-fc2f5b2cd655f1391f2abda1b39e37cdec98a951.zip
Initial revision
Diffstat (limited to 'lib/gui/ewidget.cpp')
-rw-r--r--lib/gui/ewidget.cpp1137
1 files changed, 1137 insertions, 0 deletions
diff --git a/lib/gui/ewidget.cpp b/lib/gui/ewidget.cpp
new file mode 100644
index 00000000..72abcc43
--- /dev/null
+++ b/lib/gui/ewidget.cpp
@@ -0,0 +1,1137 @@
+#include <errno.h>
+
+#include <lib/base/eptrlist.h>
+#include <lib/base/eerror.h>
+#include <lib/gdi/gfbdc.h>
+#include <lib/gdi/epng.h>
+#include <lib/gui/actions.h>
+#include <lib/gui/eskin.h>
+#include <lib/gui/ewidget.h>
+#include <lib/gui/guiactions.h>
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+
+eWidget *eWidget::root;
+Signal2< void, ePtrList<eAction>*, int >eWidget::showHelp;
+eWidget::actionMapList eWidget::globalActions;
+
+eWidget::eWidget(eWidget *_parent, int takefocus)
+ :helpID(0), parent(_parent ? _parent : root),
+ shortcut(0), shortcutFocusWidget(0),
+ focus(0), TLW(0), takefocus(takefocus),
+ state( parent && !(parent->state&stateVisible) ? stateShow : 0 ),
+ target(0), in_loop(0), have_focus(0), just_showing(0),
+ font( parent ? parent->font : eSkin::getActive()->queryFont("global.normal") ),
+ backgroundColor(_parent?gColor(-1):gColor(eSkin::getActive()->queryScheme("global.normal.background"))),
+ foregroundColor(_parent?parent->foregroundColor:gColor(eSkin::getActive()->queryScheme("global.normal.foreground"))),
+ pixmap(0)
+#ifndef DISABLE_LCD
+ ,LCDTitle(0)
+ ,LCDElement(0)
+ ,LCDTmp(0)
+#endif
+{
+ if (takefocus)
+ getTLW()->focusList()->push_back(this);
+
+ if (parent)
+ parent->childlist.push_back(this);
+
+ addActionMap(&i_cursorActions->map);
+}
+
+eWidget::~eWidget()
+{
+ hide();
+ if (takefocus)
+ {
+ getTLW()->focusList()->remove(this);
+ if (getTLW()->focus == this)
+ eFatal("focus still held.");
+ }
+
+ if (shortcut)
+ getTLW()->actionListener.remove(this);
+
+ if (parent && !parent->childlist.empty())
+ parent->childlist.remove(this);
+
+ while (!childlist.empty())
+ delete childlist.front();
+}
+
+void eWidget::takeFocus()
+{
+ // desktop shouldnt receive global focus
+ ASSERT (parent);
+ // childs shouldnt receive global focus
+ ASSERT (!parent->parent);
+#warning fix me
+#if 0
+ if (!have_focus)
+ {
+ oldTLfocus=eZap::getInstance()->focus;
+ eZap::getInstance()->focus=this;
+/* if (oldTLfocus)
+ {
+ eDebug("focus problem");
+ eFatal("da hat %s den focus und %s will ihn haben", oldTLfocus->getText().c_str(), getText().c_str());
+ } */
+ addActionMap(&i_focusActions->map);
+ }
+#endif
+ ++have_focus;
+}
+
+void eWidget::releaseFocus()
+{
+ // desktop shouldnt receive global focus
+ ASSERT (parent);
+ // childs shouldnt receive global focus
+ ASSERT (!parent->parent);
+ ASSERT (have_focus);
+
+ if (have_focus)
+ {
+ --have_focus;
+ if (!have_focus)
+ {
+ removeActionMap(&i_focusActions->map);
+#warning fixme
+#if 0
+ if (eZap::getInstance()->focus==this) // if we don't have lost the focus, ...
+ eZap::getInstance()->focus=oldTLfocus; // give it back
+ else
+ eFatal("someone has stolen the focus");
+#endif
+ }
+ }
+}
+
+void eWidget::_willShow()
+{
+ ASSERT(state&stateShow);
+ ASSERT(!(state&stateVisible));
+ state|=stateVisible;
+ if (takefocus)
+ getTLW()->takeFocus();
+ willShow();
+}
+
+void eWidget::_willHide()
+{
+ ASSERT(state&stateShow);
+ ASSERT(state&stateVisible);
+ state&=~stateVisible;
+
+ willHide();
+ if (takefocus)
+ getTLW()->releaseFocus();
+}
+
+void eWidget::willShow()
+{
+ event(eWidgetEvent(eWidgetEvent::willShow));
+}
+
+void eWidget::willHide()
+{
+ event(eWidgetEvent(eWidgetEvent::willHide));
+}
+
+void eWidget::setPalette()
+{
+}
+
+void eWidget::resize(const eSize& nsize)
+{
+ size=nsize;
+ recalcClientRect();
+ event(eWidgetEvent(eWidgetEvent::changedSize));
+ recalcClip();
+}
+
+void eWidget::recalcAbsolutePosition()
+{
+ absPosition = (parent?(parent->getAbsolutePosition()+parent->clientrect.topLeft()+position):position);
+ for (ePtrList<eWidget>::iterator it( childlist ); it != childlist.end(); ++it )
+ it->recalcAbsolutePosition();
+}
+
+void eWidget::move(const ePoint& nposition)
+{
+ position=nposition;
+ recalcClip();
+ recalcAbsolutePosition();
+ event(eWidgetEvent(eWidgetEvent::changedPosition));
+}
+
+void eWidget::cresize(const eSize& nsize)
+{
+ recalcClientRect();
+ resize(eSize(nsize.width()+size.width()-clientrect.width(), nsize.height()+size.height()-clientrect.height()));
+}
+
+void eWidget::cmove(const ePoint& nposition)
+{
+ recalcClientRect();
+ move(ePoint(nposition.x()-clientrect.x(), nposition.y()-clientrect.y()));
+}
+
+void eWidget::redraw(eRect area) // area bezieht sich nicht auf die clientarea
+{
+ if (getTLW()->just_showing)
+ return;
+ if (state & stateVisible )
+ {
+ if (area.isNull())
+ area=eRect(0, 0, size.width(), size.height());
+ if (area.width()>0)
+ {
+ gPainter *p=getPainter(area);
+ if (p)
+ {
+ eraseBackground(p, area);
+ redrawWidget(p, area);
+ delete p;
+ }
+ }
+ if(!childlist.empty())
+ {
+ area.moveBy(-clientrect.x(), -clientrect.y()); // ab hier jetzt schon.
+
+ ePtrList<eWidget>::iterator It(childlist);
+ while (It != childlist.end())
+ {
+ eRect cr=area&eRect((*It)->position, (*It)->size);
+ if (!cr.isEmpty())
+ {
+ cr.moveBy(-It->position.x(), -It->position.y());
+ It->redraw(cr);
+ }
+ ++It;
+ }
+ }
+ }
+}
+
+void eWidget::invalidate(eRect area, int force)
+{
+ if ( (!(state & stateVisible)) && (!force))
+ return;
+
+ if (area.isNull())
+ area=eRect(0, 0, size.width(), size.height());
+
+ eWidget *w=this;
+
+ // problem: überlappende, nicht transparente fenster
+
+ while (force || (((int)w->getBackgroundColor())==-1))
+ // while (1)
+ {
+ force=0;
+ if (!w->parent) // spaetestens fuers TLW sollte backgroundcolor aber non-transparent sein
+ break;
+ area.moveBy(w->position.x(), w->position.y());
+ w=w->parent;
+ area.moveBy(w->clientrect.x(), w->clientrect.y());
+ area&=w->clientrect;
+ }
+ w->redraw(area);
+}
+
+int eWidget::event(const eWidgetEvent &event)
+{
+ if (!eventFilter(event))
+ {
+ eWidget *target=this;
+/* if (have_focus && event.toFocus()) // bypassing focus handling for root-widget
+ target=focusList()->current(); */
+ if (target)
+ {
+ while (target)
+ {
+ if (target->eventHandler(event))
+ return 1;
+ if (target==this)
+ break;
+ target=target->parent;
+ }
+ }
+ }
+ return 0;
+}
+
+ /* das ist bestimmt ne einzige race hier :) */
+int eWidget::exec()
+{
+ if (in_loop)
+ eFatal("double exec");
+
+ in_loop=-1; // hey, exec hat angefangen aber noch nicht in der mainloop
+
+ event(eWidgetEvent(eWidgetEvent::execBegin)); // hat jemand was dagegen einzuwenden?
+
+ if (in_loop) // hatte wohl jemand.
+ {
+ in_loop=1; // wir betreten die mainloop
+ eApp->enter_loop(); // oder wir machen das halt selber.
+ in_loop=0; // nu sind wir jedenfalls draussen.
+ }
+ event(eWidgetEvent(eWidgetEvent::execDone));
+
+ return result;
+}
+
+void eWidget::clear()
+{
+#if 0
+ eWidget *root=this;
+ while (root->parent)
+ root=root->parent;
+ eRect me(getRelativePosition(root), size);
+ root->invalidate(me);
+#endif
+ invalidate(eRect(), 1);
+}
+
+void eWidget::close(int res)
+{
+ if (in_loop==0)
+ eFatal("attempt to close non-execing widget");
+ if (in_loop==1) // nur wenn das ne echte loop ist
+ eApp->exit_loop();
+ result=res;
+}
+
+void eWidget::show()
+{
+ if (state & stateShow)
+ return;
+
+ ASSERT(!(state&stateVisible));
+
+ state|=stateShow;
+
+ if (!parent || (parent->state&stateVisible))
+ {
+ ++getTLW()->just_showing;
+ willShowChildren();
+
+ checkFocus();
+ --getTLW()->just_showing;
+ redraw();
+ }
+}
+
+
+void eWidget::accept()
+{
+ close(0);
+}
+
+void eWidget::reject()
+{
+ close(-1);
+}
+
+void eWidget::willShowChildren()
+{
+ if (!(state & stateShow))
+ return;
+ _willShow();
+ if (!childlist.empty())
+ {
+ ePtrList<eWidget>::iterator It(childlist);
+ while(It != childlist.end())
+ {
+ It->willShowChildren();
+ ++It;
+ }
+ }
+}
+
+void eWidget::hide()
+{
+ if (!(state&stateShow))
+ return;
+
+ if (state&stateVisible)
+ {
+ willHideChildren();
+ clear(); // hide -> immer erasen. dieses Hide ist IMMER explizit.
+ }
+ state&=~stateShow;
+ checkFocus();
+}
+
+void eWidget::willHideChildren()
+{
+ if (!(state & stateShow))
+ return;
+ _willHide();
+ if (!childlist.empty())
+ {
+ ePtrList<eWidget>::iterator It(childlist);
+ while(It != childlist.end())
+ {
+ It->willHideChildren();
+ ++It;
+ }
+ }
+}
+
+void eWidget::findAction(eActionPrioritySet &prio, const eRCKey &key, eWidget *context)
+{
+#if 0
+ for (actionMapList::iterator i = actionmaps.begin(); i != actionmaps.end(); ++i)
+ {
+ const std::set<eString> &styles=eActionMapList::getInstance()->getCurrentStyles();
+ for (std::set<eString>::const_iterator si(styles.begin()); si != styles.end(); ++si)
+ (*i)->findAction(prio, key, context, *si);
+ }
+#endif
+
+ for(ePtrList<eWidget>::iterator w(actionListener.begin()); w != actionListener.end(); ++w)
+ i_shortcutActions->map.findAction(prio, key, w, "");
+
+ if (focus && focus != this)
+ focus->findAction(prio, key, context);
+}
+
+int eWidget::eventFilter(const eWidgetEvent &event)
+{
+ return 0;
+}
+
+void eWidget::addActionToHelpList(eAction *action)
+{
+ actionHelpList.push_back( action );
+}
+
+void eWidget::clearHelpList()
+{
+ actionHelpList.clear();
+}
+
+void eWidget::setHelpID(int fHelpID)
+{
+ helpID=fHelpID;
+}
+
+int eWidget::eventHandler(const eWidgetEvent &evt)
+{
+ switch (evt.type)
+ {
+ case eWidgetEvent::childChangedHelpText:
+ /* emit */ focusChanged(focus); // faked focusChanged Signal to the Statusbar
+ break;
+ case eWidgetEvent::evtAction:
+ if (evt.action == shortcut && isVisible())
+ (shortcutFocusWidget?shortcutFocusWidget:this)->
+ event(eWidgetEvent(eWidgetEvent::evtShortcut));
+ else if (evt.action == &i_focusActions->up)
+ focusNext(focusDirPrev);
+ else if (evt.action == &i_focusActions->down)
+ focusNext(focusDirNext);
+ else if (evt.action == &i_focusActions->left)
+ focusNext(focusDirPrev);
+ else if (evt.action == &i_focusActions->right)
+ focusNext(focusDirNext);
+ else if (evt.action == &i_cursorActions->help)
+ {
+ int wasvisible=state&stateShow;
+ if (wasvisible)
+ hide();
+ /* emit */ showHelp( &actionHelpList, helpID );
+ if (wasvisible)
+ show();
+ } else
+ return 0;
+ return 1;
+ case eWidgetEvent::evtKey:
+ {
+ eActionPrioritySet prio;
+
+ findAction(prio, *evt.key, this);
+
+ if (focus && (focus != this))
+ focus->findAction(prio, *evt.key, focus);
+
+#if 0
+ for (actionMapList::iterator i = globalActions.begin(); i != globalActions.end(); ++i)
+ {
+ const std::set<eString> &styles=eActionMapList::getInstance()->getCurrentStyles();
+ for (std::set<eString>::const_iterator si(styles.begin()); si != styles.end(); ++si)
+ (*i)->findAction(prio, *evt.key, 0, *si);
+ }
+#endif
+
+ for (eActionPrioritySet::iterator i(prio.begin()); i != prio.end(); ++i)
+ {
+ if (i->first)
+ {
+ if (((eWidget*)i->first)->event(eWidgetEvent(eWidgetEvent::evtAction, i->second)))
+ break;
+ } else
+ {
+ (const_cast<eAction*>(i->second))->handler(); // only useful for global actions
+ break;
+ }
+ }
+
+ if (focus)
+ {
+ /* Action not found, try to use old Keyhandle */
+ int c = evt.key->producer->getKeyCompatibleCode(*evt.key);
+ if (c != -1)
+ {
+ if (evt.key->flags & eRCKey::flagBreak)
+ focus->keyUp(c);
+ else
+ focus->keyDown(c);
+ }
+ }
+ return 1;
+ break;
+ }
+ case eWidgetEvent::gotFocus:
+ gotFocus();
+ break;
+ case eWidgetEvent::lostFocus:
+ lostFocus();
+ break;
+
+ case eWidgetEvent::changedSize:
+ case eWidgetEvent::changedFont:
+ case eWidgetEvent::changedPosition:
+ case eWidgetEvent::changedPixmap:
+ invalidate();
+ break;
+ case eWidgetEvent::evtShortcut:
+ setFocus(this);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int eWidget::keyDown(int rc)
+{
+ return 0;
+}
+
+int eWidget::keyUp(int rc)
+{
+ return 0;
+}
+
+void eWidget::gotFocus()
+{
+}
+
+void eWidget::lostFocus()
+{
+}
+
+void eWidget::recalcClientRect()
+{
+ clientrect=eRect(0, 0, size.width(), size.height());
+}
+
+void eWidget::recalcClip()
+{
+ eWidget *t=this;
+ eRect rect=eRect(0, 0, size.width(), size.height());
+ while (t)
+ {
+ rect&=t->clientrect;
+ rect.moveBy(t->position.x(), t->position.y());
+ t=t->parent;
+ if (t)
+ rect.moveBy(t->clientrect.x(), t->clientrect.y());
+ }
+ clientclip=rect;
+}
+
+void eWidget::checkFocus()
+{
+ ePtrList<eWidget> *l=getTLW()->focusList();
+ if (!(getTLW()->focus && getTLW()->focus->state&stateVisible))
+ {
+ l->first();
+
+ while (l->current() && !(l->current()->state&stateVisible))
+ l->next();
+
+ setFocus(l->current());
+ }
+}
+
+void eWidget::addActionMap(eActionMap *map)
+{
+ actionmaps.push_back(map);
+}
+
+void eWidget::removeActionMap(eActionMap *map)
+{
+ actionmaps.remove(map);
+}
+
+void eWidget::addGlobalActionMap(eActionMap *map)
+{
+ globalActions.push_back(map);
+}
+
+void eWidget::removeGlobalActionMap(eActionMap *map)
+{
+ globalActions.remove(map);
+}
+
+void eWidget::redrawWidget(gPainter *target, const eRect &clip)
+{
+}
+
+void eWidget::eraseBackground(gPainter *target, const eRect &clip)
+{
+ if (((int)getBackgroundColor()) >= 0)
+ target->clear();
+}
+
+void eWidget::focusNext(int dir)
+{
+ if (parent && parent->parent)
+ return getTLW()->focusNext(dir);
+
+ if (!_focusList.current())
+ _focusList.first();
+ if (!_focusList.current())
+ {
+ setFocus(0);
+ return;
+ }
+
+ switch (dir)
+ {
+ case focusDirNext:
+ case focusDirPrev:
+ {
+ int tries=2;
+ while (tries)
+ {
+ if (dir == focusDirNext)
+ {
+ _focusList.next();
+ if (!_focusList.current())
+ {
+ _focusList.first();
+ --tries;
+ }
+ } else if (dir == focusDirPrev)
+ {
+ if (_focusList.current() == _focusList.begin())
+ {
+ _focusList.last();
+ --tries;
+ } else
+ _focusList.prev();
+ }
+ if (_focusList.current() && _focusList.current()->state&stateVisible)
+ break;
+ }
+ if (!tries)
+ {
+ setFocus(0);
+ return;
+ }
+ break;
+ }
+ case focusDirN:
+ case focusDirE:
+ case focusDirS:
+ case focusDirW:
+ {
+ eWidget *nearest=_focusList.current();
+ int difference=1<<30;
+ for (ePtrList<eWidget>::iterator i(_focusList.begin()); i != _focusList.end(); ++i)
+ {
+ if (_focusList.current() == i)
+ continue;
+ if (!(i->state&stateVisible))
+ continue;
+ ePoint m1=i->getAbsolutePosition();
+ ePoint m2=_focusList.current()->getAbsolutePosition();
+ switch (dir)
+ {
+ case focusDirN: // diff between our TOP and new BOTTOM
+ m1+=ePoint(i->getSize().width()/2, i->getSize().height());
+ m2+=ePoint(_focusList.current()->getSize().width()/2, 0);
+ break;
+ case focusDirS: // diff between our BOTTOM and new TOP
+ m1+=ePoint(i->getSize().width()/2, 0);
+ m2+=ePoint(_focusList.current()->getSize().width()/2, _focusList.current()->getSize().height());
+ break;
+ case focusDirE: // diff between our RIGHT and new LEFT border
+ m1+=ePoint(0, i->getSize().height()/2);
+ m2+=ePoint(_focusList.current()->getSize().width(), _focusList.current()->getSize().height()/2);
+ break;
+ case focusDirW: // diff between our LEFT and new RIGHT border
+ m1+=ePoint(i->getSize().width(), i->getSize().height()/2);
+ m2+=ePoint(0, _focusList.current()->getSize().height()/2);
+ break;
+ }
+
+ int xd=m1.x()-m2.x();
+ int yd=m1.y()-m2.y();
+#define METHOD 0
+#if METHOD == 0
+ int dif=xd*xd+yd*yd;
+ int eff=0;
+
+ switch (dir)
+ {
+ case focusDirN:
+ yd=-yd;
+ case focusDirS:
+ if (yd > 0)
+ eff=dif/yd;
+ else
+ eff=1<<30;
+ break;
+ case focusDirW:
+ xd=-xd;
+ case focusDirE:
+ if (xd > 0)
+ eff=dif/xd;
+ else
+ eff=1<<30;
+ break;
+ }
+
+ if (eff < difference)
+ {
+ difference=eff;
+ nearest=*i;
+ }
+#elif METHOD == 1
+ int ldir=focusDirN;
+ int mydiff=0;
+
+ if (xd > mydiff) // rechts
+ {
+ mydiff=xd;
+ ldir=focusDirE;
+ }
+ if ((-xd) > mydiff) // links
+ {
+ mydiff=-xd;
+ ldir=focusDirW;
+ }
+ if (yd > mydiff) // unten
+ {
+ mydiff=yd;
+ ldir=focusDirS;
+ }
+ if ((-yd) > mydiff) // oben
+ {
+ mydiff=-yd;
+ ldir=focusDirN;
+ }
+ if (dir == ldir) // nur elemente beruecksichtigen die in der richtung liegen...
+ {
+ int entf=xd*xd+yd*yd;
+ if (entf < difference)
+ {
+ difference=entf;
+ nearest=*i;
+ }
+ }
+#elif METHOD == 2
+
+#endif
+
+ }
+ _focusList.setCurrent(nearest);
+ break;
+ }
+ }
+
+ setFocus(_focusList.current());
+}
+
+void eWidget::setFocus(eWidget *newfocus)
+{
+ if (parent && parent->parent)
+ return getTLW()->setFocus(newfocus);
+
+ if (focus == newfocus)
+ {
+// eDebug("focus == newfocus");
+// /* emit */ focusChanged(focus);
+ return;
+ }
+
+ if (focus)
+ focus->event(eWidgetEvent(eWidgetEvent::lostFocus));
+
+ focus=newfocus;
+
+ if (focus)
+ focus->event(eWidgetEvent(eWidgetEvent::gotFocus));
+
+ _focusList.setCurrent(focus);
+
+ /* emit */ focusChanged(focus);
+}
+
+void eWidget::setHelpText( const eString& e)
+{
+ helptext=e;
+ if ( parent )
+ parent->event( eWidgetEvent::childChangedHelpText );
+}
+
+void eWidget::setFont(const gFont &fnt)
+{
+ font=fnt;
+ event(eWidgetEvent(eWidgetEvent::changedFont));
+}
+
+void eWidget::setText(const eString &label)
+{
+ if (label != text) // ein compare ist immer weniger arbeit als ein unnoetiges redraw
+ {
+ text=label;
+ event(eWidgetEvent(eWidgetEvent::changedText));
+ }
+}
+
+void eWidget::setBackgroundColor(const gColor& color, bool inv)
+{
+ if (color!=backgroundColor)
+ {
+ backgroundColor=color;
+ event(eWidgetEvent(eWidgetEvent::changedBackgroundColor));
+ if (inv)
+ invalidate();
+ }
+}
+
+void eWidget::setForegroundColor(const gColor& color, bool inv)
+{
+ if (color != foregroundColor)
+ {
+ foregroundColor=color;
+ event(eWidgetEvent(eWidgetEvent::changedForegroundColor));
+ if (inv)
+ invalidate();
+ }
+}
+
+void eWidget::setPixmap(gPixmap *pmap)
+{
+ if ( pixmap != pmap )
+ {
+ pixmap=pmap;
+ event(eWidgetEvent(eWidgetEvent::changedPixmap));
+ }
+}
+
+void eWidget::setTarget(gDC *newtarget)
+{
+ target=newtarget;
+}
+
+#ifndef DISABLE_LCD
+void eWidget::setLCD(eWidget *_lcdtitle, eWidget *_lcdelement)
+{
+ LCDTitle=_lcdtitle;
+ LCDElement=_lcdelement;
+}
+#endif
+
+void eWidget::setName(const char *_name)
+{
+ name=_name;
+}
+
+gPainter *eWidget::getPainter(eRect area)
+{
+ eRect myclip=eRect(getAbsolutePosition(), size);
+ if (parent)
+ myclip&=parent->clientclip;
+
+ eWidget *r=this;
+ while (r && r->parent && !r->target)
+ r = r->parent;
+
+ ASSERT(r);
+// ASSERT(r->target);
+ if (!r->target) // if target is 0, device is locked.
+ return 0;
+
+ gPainter *p=new gPainter(*r->target, myclip);
+ p->setLogicalZero(getAbsolutePosition());
+ if (!area.isNull())
+ p->clip(area);
+ p->setForegroundColor(foregroundColor);
+ p->setBackgroundColor(backgroundColor);
+ return p;
+}
+
+static int parse(const char* p, int *v, int *e, int max)
+{
+ int i=0;
+
+ while ( (i<max) && (*p) )
+ {
+ int ea=0;
+
+ if (*p=='e')
+ {
+ ++p;
+ ea=1;
+ }
+
+ char *x;
+ v[i]=strtol(p, &x, 10);
+ p=x;
+
+ if (*p && *p!=':')
+ return -3;
+
+ if (*p==':')
+ ++p;
+
+ if (ea)
+ v[i]+=e[i];
+
+ ++i;
+ }
+
+ if (*p)
+ return -1;
+
+ if (i<max)
+ return -2;
+
+ return 0;
+}
+
+int eWidget::setProperty(const eString &prop, const eString &value)
+{
+ if (prop=="position")
+ {
+ int v[2], e[2]={0, 0};
+ if (parent)
+ {
+ e[0]=parent->clientrect.width();
+ e[1]=parent->clientrect.height();
+ }
+ int err=parse(value.c_str(), v, e, 2);
+ if (err)
+ return err;
+ move(ePoint(v[0], v[1]));
+ }
+ else if (prop=="cposition")
+ {
+ int v[2], e[2];
+ e[0]=e[1]=0;
+ if (parent)
+ {
+ e[0]=parent->clientrect.width();
+ e[1]=parent->clientrect.height();
+ }
+ int err=parse(value.c_str(), v, e, 2);
+ if (err)
+ return err;
+
+ cmove(ePoint(v[0], v[1]));
+ }
+ else if (prop=="size")
+ {
+ int v[2], e[2];
+ e[0]=e[1]=0;
+ if (parent)
+ {
+ e[0]=parent->clientrect.width()-position.x();
+ e[1]=parent->clientrect.height()-position.y();
+ }
+ int err=parse(value.c_str(), v, e, 2);
+ if (err)
+ return err;
+ resize(eSize(v[0], v[1]));
+ }
+ else if (prop=="csize")
+ {
+ int v[2], e[2];
+ e[0]=e[1]=0;
+ if (parent)
+ {
+ e[0]=parent->clientrect.width()-position.x();
+ e[1]=parent->clientrect.height()-position.y();
+ }
+ int err=parse(value.c_str(), v, e, 2);
+ if (err)
+ return err;
+ cresize(eSize(v[0], v[1]));
+ }
+ else if (prop=="text")
+/* {
+ eString text;
+
+ std::string::const_iterator p(value.begin());
+
+ while(*p)
+ {
+ if (*p=='\\')
+ {
+ switch (*(++p))
+ {
+ case 'n':
+ text+='\n';
+ break;
+ case 'r':
+ text+='\r';
+ break;
+ case 't':
+ text+='\t';
+ break;
+ case 'b':
+ text+='\b';
+ break;
+ case '\\':
+ text+='\\';
+ break;
+ default:
+ text+='?';
+ break;
+ }
+ }
+ else
+ text+=*p;
+
+ p++;
+ }
+ setText(text);
+ }*/
+ setText(::gettext(value.c_str()));
+ else if (prop=="helptext")
+ setHelpText(::gettext(value.c_str()));
+ else if (prop=="font")
+ setFont(eSkin::getActive()->queryFont(value));
+ else if (prop=="name")
+ name=value;
+ else if (prop=="pixmap")
+ {
+ ePtr<gPixmap> pixmap;
+ eSkin::getActive()->queryImage(pixmap, value);
+ setPixmap(pixmap);
+ } else if (prop=="foregroundColor")
+ setForegroundColor(eSkin::getActive()->queryColor(value));
+ else if (prop=="backgroundColor")
+ setBackgroundColor(eSkin::getActive()->queryColor(value));
+ else if (prop=="shortcut")
+ setShortcut(value);
+ else if (prop=="shortcutFocus")
+ setShortcutFocus(parent ? parent->search(value) : 0);
+ else
+ {
+ eFatal("skin property %s does not exist", prop.c_str());
+ return -ENOENT;
+ }
+ return 0;
+}
+
+eWidget *eWidget::search(const eString &sname)
+{
+ if (name==sname)
+ return this;
+
+ if (!childlist.empty())
+ {
+ std::list<eWidget*>::iterator It = childlist.begin();
+ while(It != childlist.end())
+ {
+ eWidget* p = (*It)->search(sname);
+ if (p)
+ return p;
+ ++It;
+ }
+ }
+ return 0;
+}
+
+void eWidget::makeRoot()
+{
+ root=this;
+}
+
+void eWidget::zOrderLower()
+{
+ if (!parent)
+ return;
+ int isshown=0;
+ if (state & stateShow)
+ {
+ isshown=1;
+ hide();
+ }
+ parent->childlist.remove(this);
+ parent->childlist.push_front(this);
+ if (isshown)
+ show();
+}
+
+void eWidget::zOrderRaise()
+{
+ if (!parent)
+ return;
+ int isshown=0;
+ if (state & stateShow)
+ {
+ isshown=1;
+ hide();
+ }
+ parent->childlist.remove(this);
+ parent->childlist.push_back(this);
+ if (isshown)
+ show();
+}
+
+void eWidget::setShortcut(const eString &shortcutname)
+{
+ if (shortcut)
+ getTLW()->actionListener.remove(this);
+ shortcut=i_shortcutActions->map.findAction(shortcutname.c_str());
+ if (shortcut)
+ getTLW()->actionListener.push_back(this);
+}
+
+void eWidget::setShortcutFocus(eWidget *focus)
+{
+ shortcutFocusWidget=focus;
+ if (!focus)
+ eFatal("setShortcutFocus with unknown widget!");
+}
+
+static eWidget *create_eWidget(eWidget *parent)
+{
+ return new eWidget(parent);
+}
+
+class eWidgetSkinInit
+{
+public:
+ eWidgetSkinInit()
+ {
+ eSkin::addWidgetCreator("eWidget", create_eWidget);
+ }
+ ~eWidgetSkinInit()
+ {
+ eSkin::removeWidgetCreator("eWidget", create_eWidget);
+ }
+};
+eAutoInitP0<eWidgetSkinInit> init_eWidgetSkinInit(eAutoInitNumbers::guiobject, "eWidget");