aboutsummaryrefslogtreecommitdiff
path: root/lib/gui
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
downloadenigma2-fc2f5b2cd655f1391f2abda1b39e37cdec98a951.tar.gz
enigma2-fc2f5b2cd655f1391f2abda1b39e37cdec98a951.zip
Initial revision
Diffstat (limited to 'lib/gui')
-rw-r--r--lib/gui/.cvsignore7
-rw-r--r--lib/gui/Makefile.am13
-rw-r--r--lib/gui/actions.cpp378
-rw-r--r--lib/gui/actions.h138
-rw-r--r--lib/gui/combobox.cpp298
-rw-r--r--lib/gui/combobox.h50
-rw-r--r--lib/gui/decoration.cpp181
-rw-r--r--lib/gui/decoration.h49
-rw-r--r--lib/gui/ebutton.cpp134
-rw-r--r--lib/gui/ebutton.h37
-rw-r--r--lib/gui/echeckbox.cpp138
-rw-r--r--lib/gui/echeckbox.h25
-rw-r--r--lib/gui/elabel.cpp253
-rw-r--r--lib/gui/elabel.h44
-rw-r--r--lib/gui/emessage.cpp163
-rw-r--r--lib/gui/emessage.h40
-rw-r--r--lib/gui/enumber.cpp447
-rw-r--r--lib/gui/enumber.h69
-rw-r--r--lib/gui/epixmap.cpp44
-rw-r--r--lib/gui/epixmap.h18
-rw-r--r--lib/gui/eprogress.cpp136
-rw-r--r--lib/gui/eprogress.h49
-rw-r--r--lib/gui/eservicegrid.cpp74
-rw-r--r--lib/gui/eservicegrid.h27
-rw-r--r--lib/gui/eskin.cpp760
-rw-r--r--lib/gui/eskin.h87
-rw-r--r--lib/gui/eskin_register.cpp44
-rw-r--r--lib/gui/eskin_register.h8
-rw-r--r--lib/gui/ewidget.cpp1137
-rw-r--r--lib/gui/ewidget.h498
-rw-r--r--lib/gui/ewindow.cpp160
-rw-r--r--lib/gui/ewindow.h48
-rw-r--r--lib/gui/guiactions.cpp8
-rw-r--r--lib/gui/guiactions.h90
-rw-r--r--lib/gui/listbox.cpp894
-rw-r--r--lib/gui/listbox.h278
-rw-r--r--lib/gui/multipage.cpp64
-rw-r--r--lib/gui/multipage.h24
-rw-r--r--lib/gui/numberactions.cpp5
-rw-r--r--lib/gui/numberactions.h31
-rw-r--r--lib/gui/slider.cpp188
-rw-r--r--lib/gui/slider.h27
-rw-r--r--lib/gui/statusbar.cpp83
-rw-r--r--lib/gui/statusbar.h25
-rw-r--r--lib/gui/testpicture.cpp229
-rw-r--r--lib/gui/testpicture.h36
-rw-r--r--lib/gui/textinput.cpp388
-rw-r--r--lib/gui/textinput.h31
48 files changed, 7955 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..b55c43df
--- /dev/null
+++ b/lib/gui/actions.cpp
@@ -0,0 +1,378 @@
+#include <lib/gui/actions.h>
+
+#include <xmltree.h>
+#include <lib/base/eerror.h>
+#include <lib/base/econfig.h>
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+#include <lib/base/nconfig.h>
+
+eAction::eAction(eActionMap &map, char *identifier, char *description, int priority)
+ : description(description), identifier(identifier), map(&map), priority(priority)
+{
+ map.add(this);
+}
+
+eAction::~eAction()
+{
+ map->remove(this);
+}
+
+/*eAction::keylist &eAction::getKeyList()
+{
+ std::map<eString, keylist>::iterator it=keys.find( eActionMapList::getInstance()->getCurrentStyle() );
+ if ( it != keys.end() )
+ return it->second;
+ it = keys.find("default);
+ return it->second;
+}*/
+
+int eAction::containsKey(const eRCKey &key, const eString &style ) const
+{
+ std::map<eString, keylist>::const_iterator it=keys.find( style );
+ if ( it != keys.end() )
+ {
+ if (it->second.find(key)!=it->second.end())
+ return 1;
+ }
+ return 0;
+}
+
+// ---------------------------------------------------------------------------
+
+void eActionMap::findAction(eActionPrioritySet &list, const eRCKey &key, void *context, const eString &style) const
+{
+ for (std::list<eAction*>::const_iterator i=actions.begin(); i!=actions.end(); ++i)
+ {
+ if ((*i)->containsKey(key, style))
+ list.insert(eAction::directedAction(context, *i));
+ }
+}
+
+eAction *eActionMap::findAction(const char *id) const
+{
+ for (std::list<eAction*>::const_iterator i=actions.begin(); i!=actions.end(); ++i)
+ if (!strcmp((*i)->getIdentifier(), id))
+ return *i;
+ return 0;
+}
+
+eActionMap::eActionMap(const char *identifier, char *description):
+ identifier(identifier), description(description)
+{
+ eActionMapList::getInstance()->addActionMap(identifier, this);
+}
+
+eActionMap::~eActionMap()
+{
+ eActionMapList::getInstance()->removeActionMap(identifier);
+}
+
+void eActionMap::loadXML(eRCDevice *device, std::map<std::string,int> &keymap, const XMLTreeNode *node, const eString& style)
+{
+ for (XMLTreeNode *xaction=node->GetChild(); xaction; xaction=xaction->GetNext())
+ {
+ if (strcmp(xaction->GetType(), "action"))
+ {
+ eFatal("illegal type %s, expected 'action'", xaction->GetType());
+ continue;
+ }
+ const char *name=xaction->GetAttributeValue("name");
+ eAction *action=0;
+ if (name)
+ action=findAction(name);
+ if (!action)
+ {
+ eWarning("please specify a valid action with name=. valid actions are:");
+ for (actionList::iterator i(actions.begin()); i != actions.end(); ++i)
+ eWarning(" %s (%s)", (*i)->getIdentifier(), (*i)->getDescription());
+ eFatal("but NOT %s", name);
+ continue;
+ }
+ const char *code=xaction->GetAttributeValue("code");
+ int icode=-1;
+ if (!code)
+ {
+ const char *key=xaction->GetAttributeValue("key");
+ if (!key)
+ {
+ eFatal("please specify a number as code= or a defined key with key=.");
+ continue;
+ }
+ std::map<std::string,int>::iterator i=keymap.find(std::string(key));
+ if (i == keymap.end())
+ {
+ eFatal("undefined key '%s' specified!", key);
+ continue;
+ }
+ icode=i->second;
+ } else
+ sscanf(code, "%x", &icode);
+ const char *flags=xaction->GetAttributeValue("flags");
+ if (!flags || !*flags)
+ flags="b";
+ if (strchr(flags, 'm'))
+ action->insertKey( style, eRCKey(device, icode, 0) );
+ if (strchr(flags, 'b'))
+ action->insertKey( style, eRCKey(device, icode, eRCKey::flagBreak) );
+ if (strchr(flags, 'r'))
+ action->insertKey( style, eRCKey(device, icode, eRCKey::flagRepeat) );
+ }
+}
+
+void eActionMap::reloadConfig()
+{
+#if 0
+ NConfig &nc=eDVB::getInstance()->config;
+ std::string path="/ezap/rc/keymaps/";
+ path+=identifier;
+ path+="/";
+
+ for (actionList::iterator i(actions.begin()); i!=actions.end(); ++i)
+ {
+ std::string key=path+i->getIdentifier();
+ qDebug("loading %s", key.c_str());
+ char *value;
+ int len;
+ int err;
+ if (!(err=nc.getKey(value, len)))
+ {
+ qDebug("have data!");
+ } else
+ qDebug("error %d", err);
+ }
+#endif
+}
+
+void eActionMap::saveConfig()
+{
+#if 0
+ NConfig &nc=eDVB::getInstance()->config;
+ std::string path="/ezap/rc/keymaps/";
+ path+=identifier;
+ path+="/";
+
+ for (actionList::iterator i(actions.begin()); i!=actions.end(); ++i)
+ {
+ std::string key=path+i->second.getIdentifier();
+ qDebug("saving %s", key.c_str());
+ std::string value;
+
+ eAction::keyList &kl=i->second.getKeyList();
+
+ for (eAction::keylist::iterator kli(kl.begin()); kli!=kl.end(); ++kli)
+ {
+ eRCKey &key=kli->second;
+ qDebug("%s, %x, %x", key.producer->getIdentifier(), key.code, key.flags);
+ value+=key.producer->getIdentifier();
+ value+=0;
+
+ value+=(key.code>>24)&0xFF;
+ value+=(key.code>>16)&0xFF;
+ value+=(key.code>>8)&0xFF;
+ value+=key.code&0xFF;
+
+ value+=(key.flags>>24)&0xFF;
+ value+=(key.flags>>16)&0xFF;
+ value+=(key.flags>>8)&0xFF;
+ value+=key.flags&0xFF;
+ }
+ nc.setKey(key.c_str(), value.data(), value.size());
+ }
+#endif
+}
+
+// ---------------------------------------------------------------------------
+
+eActionMapList *eActionMapList::instance;
+
+eActionMapList::eActionMapList()
+{
+ if (!instance)
+ instance=this;
+ char * tmp;
+ if ( eConfig::getInstance()->getKey("/ezap/rc/style", tmp ) )
+ currentStyle="default";
+ else
+ {
+ currentStyle=tmp;
+ delete [] tmp;
+ }
+ eDebug("currentStyle=%s", currentStyle.c_str() );
+ xmlfiles.setAutoDelete(1);
+}
+
+eActionMapList::~eActionMapList()
+{
+ eConfig::getInstance()->setKey("/ezap/rc/style", currentStyle.c_str() ) ;
+
+ if (instance==this)
+ instance=0;
+}
+
+void eActionMapList::addActionMap(const char *id, eActionMap *am)
+{
+ actionmaps.insert(std::pair<const char*,eActionMap*>(id,am));
+}
+
+void eActionMapList::removeActionMap(const char *id)
+{
+ actionmaps.erase(id);
+}
+
+int eActionMapList::loadXML(const char *filename)
+{
+ FILE *in=fopen(filename, "rt");
+ if (!in)
+ {
+// eDebug("cannot open %s", filename);
+ return -1;
+ }
+
+ XMLTreeParser *parser=new XMLTreeParser("ISO-8859-1");
+ 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))
+ {
+ eFatal("parse error: %s at line %d",
+ parser->ErrorString(parser->GetErrorCode()),
+ parser->GetCurrentLineNumber());
+ delete parser;
+ parser=0;
+ fclose(in);
+ return -1;
+ }
+ } while (!done);
+ fclose(in);
+
+ XMLTreeNode *root=parser->RootNode();
+ if (!root)
+ return -1;
+ if (strcmp(root->GetType(), "rcdefaults"))
+ {
+ eFatal("not a rcdefaults file.");
+ return -1;
+ }
+
+
+ xmlfiles.push_back(parser);
+
+ return 0;
+}
+
+XMLTreeNode *eActionMapList::searchDevice(const eString &id)
+{
+ for (ePtrList<XMLTreeParser>::iterator parser(xmlfiles.begin()); parser != xmlfiles.end(); ++parser)
+ {
+ XMLTreeNode *node=parser->RootNode();
+
+ for (node=node->GetChild(); node; node=node->GetNext())
+ if (!strcmp(node->GetType(), "device"))
+ {
+ const char *identifier=node->GetAttributeValue("identifier");
+ if (!identifier)
+ {
+ eFatal("please specify an remote control identifier!");
+ continue;
+ }
+ if (id == identifier)
+ return node;
+ }
+ }
+ return 0;
+}
+
+int eActionMapList::loadDevice(eRCDevice *device)
+{
+ XMLTreeNode *node=searchDevice(device->getIdentifier());
+ if (!node)
+ node=searchDevice("generic");
+ if (!node)
+ {
+ eFatal("couldn't load key bindings for device %s", device->getDescription());
+ return -1;
+ }
+
+ std::map<std::string,int> keymap;
+
+ for (XMLTreeNode *xam=node->GetChild(); xam; xam=xam->GetNext())
+ if (!strcmp(xam->GetType(), "actionmap"))
+ {
+ eActionMap *am=0;
+ const char *name=xam->GetAttributeValue("name");
+ if (name)
+ am=findActionMap(name);
+ if (!am)
+ {
+ eWarning("please specify a valid actionmap name (with name=)");
+ eWarning("valid actionmaps are:");
+ for (actionMapList::iterator i(actionmaps.begin()); i != actionmaps.end(); ++i)
+ eWarning(" %s", i->first);
+ eWarning("end.");
+ eFatal("invalid actionmap: \"%s\"", name?name:"");
+ continue;
+ }
+ const char *style=xam->GetAttributeValue("style");
+ if (style)
+ {
+ const char *descr=xam->GetAttributeValue("descr");
+ std::map<eString,eString>::iterator it = existingStyles.find(style);
+ if ( it == existingStyles.end() ) // not in map..
+ {
+ if (descr)
+ existingStyles[style]=descr;
+ else
+ existingStyles[style]=style;
+ }
+ else if ( descr && existingStyles[style] == style )
+ existingStyles[style]=descr;
+ am->loadXML(device, keymap, xam, style );
+ }
+ else
+ am->loadXML( device, keymap, xam );
+ } else if (!strcmp(xam->GetType(), "keys"))
+ {
+ for (XMLTreeNode *k=xam->GetChild(); k; k=k->GetNext())
+ {
+ if (!strcmp(k->GetType(), "key"))
+ {
+ const char *name=k->GetAttributeValue("name");
+ if (name)
+ {
+ const char *acode=k->GetAttributeValue("code");
+ int code=-1;
+ if (acode)
+ sscanf(acode, "%x", &code);
+ else
+ {
+ acode=k->GetAttributeValue("icode");
+ sscanf(acode, "%d", &code);
+ }
+
+ if (code != -1)
+ keymap.insert(std::pair<std::string,int>(name, code));
+ else
+ eFatal("no code specified for key %s!", name);
+ } else
+ eFatal("no name specified in keys!");
+ }
+ }
+ }
+ return 0;
+}
+
+eActionMap *eActionMapList::findActionMap(const char *id) const
+{
+ std::map<const char *,eActionMap*>::const_iterator i;
+ i=(actionmaps.find(id));
+ if (i==actionmaps.end())
+ return 0;
+ return i->second;
+}
+
+eAutoInitP0<eActionMapList> init_eActionMapList(eAutoInitNumbers::lowlevel, "eActionMapList");
diff --git a/lib/gui/actions.h b/lib/gui/actions.h
new file mode 100644
index 00000000..8cda4bc0
--- /dev/null
+++ b/lib/gui/actions.h
@@ -0,0 +1,138 @@
+#ifndef __actions_h
+#define __actions_h
+
+#include <string.h>
+#include <list>
+#include <string>
+#include <functional>
+#include <set>
+
+#include <libsig_comp.h>
+#include <lib/base/i18n.h>
+#include <lib/base/estring.h>
+#include <lib/driver/rc.h>
+
+class eActionMap;
+class eActionMapList;
+
+/**
+ * \brief An action
+ *
+ * An action is an action of the user. It might raise by a keypress or otherwise. bla.
+ */
+class eAction
+{
+ typedef std::set<eRCKey> keylist;
+ char *description, *identifier;
+ eActionMap *map;
+ friend struct priorityComperator;
+ std::map<eString, keylist> keys;
+ int priority;
+public:
+ typedef std::pair<void*,eAction*> directedAction;
+ /**
+ * \brief Functor to compare by priority.
+ *
+ * This is useful in sorted priority lists.
+ */
+ struct priorityComperator
+ {
+ bool operator()(const directedAction &a, const directedAction &b)
+ {
+ return a.second->priority > b.second->priority;
+ }
+ };
+
+ enum
+ {
+ prioGlobal=0, prioDialog=10, prioWidget=20, prioDialogHi=30
+ };
+ /**
+ * \param priority The priority of this action. 0 should be used for
+ * global actions, 10 for dialog-local actions, 20 for widget-local actions,
+ * 30 for dialog-hi-priority actions.
+ */
+ eAction(eActionMap &map, char *identifier, char *description, int priority=0 );
+ ~eAction();
+ const char *getDescription() const { return description; }
+ const char *getIdentifier() const { return identifier; }
+
+ void insertKey(const eString& style, const eRCKey& key )
+ {
+ keys[style].insert(key);
+ }
+
+ Signal0<void> handler;
+
+// keylist &getKeyList();
+ int containsKey(const eRCKey &key, const eString& style ) const;
+};
+
+typedef std::multiset<eAction::directedAction,eAction::priorityComperator> eActionPrioritySet;
+
+class XMLTreeNode;
+class XMLTreeParser;
+
+class eActionMap
+{
+ typedef std::list<eAction*> actionList;
+ actionList actions;
+ const char *identifier, *description;
+public:
+ eActionMap(const char *identifier, char *description);
+ ~eActionMap();
+ void add(eAction *action)
+ {
+ actions.push_back(action);
+ }
+ void remove(eAction *action)
+ {
+ actions.remove(action);
+ }
+ void findAction(eActionPrioritySet &list, const eRCKey &key, void *context, const eString &style) const;
+ eAction *findAction(const char *id) const;
+ const char *getDescription() const { return description; }
+ const char *getIdentifier() const { return identifier; }
+ void reloadConfig();
+ void loadXML(eRCDevice *device, std::map<std::string,int> &keymap, const XMLTreeNode *node, const eString& s="");
+ void saveConfig();
+};
+
+class eActionMapList
+{
+ struct lstr
+ {
+ bool operator()(const char *a, const char *b) const
+ {
+ return strcmp(a, b)<0;
+ }
+ };
+ typedef std::map<const char*,eActionMap*,lstr> actionMapList;
+
+ actionMapList actionmaps;
+
+ std::map<eString, eString> existingStyles;
+ eString currentStyle;
+
+ ePtrList<XMLTreeParser> xmlfiles;
+ XMLTreeNode *searchDevice(const eString &id);
+
+ static eActionMapList *instance;
+public:
+ eActionMapList();
+ ~eActionMapList();
+ const eString &getCurrentStyle() const { return currentStyle; }
+ void setCurrentStyle( const eString& style ) { currentStyle = style; }
+ eString getStyleDescription(const eString &style) const { std::map<eString, eString>::const_iterator i=existingStyles.find(style); if (i==existingStyles.end()) return ""; else return i->second; }
+ const std::map<eString, eString> &getExistingStyles() const { return existingStyles; }
+ void addActionMap(const char *, eActionMap * );
+ void removeActionMap(const char *);
+ int loadXML(const char *filename);
+ int loadDevice(eRCDevice *device);
+ eActionMap *findActionMap(const char *id) const;
+ actionMapList &getActionMapList() { return actionmaps; }
+
+ static eActionMapList *getInstance() { return instance; }
+};
+
+#endif
diff --git a/lib/gui/combobox.cpp b/lib/gui/combobox.cpp
new file mode 100644
index 00000000..cb90687b
--- /dev/null
+++ b/lib/gui/combobox.cpp
@@ -0,0 +1,298 @@
+#include <lib/gui/combobox.h>
+#include <lib/gdi/font.h>
+
+eComboBox::eComboBox( eWidget* parent, int OpenEntries, eLabel* desc, int takefocus, const char *deco )
+:eButton(parent, desc, takefocus, deco),
+listbox(0, 0, takefocus),
+button( this, 0, 0, eSkin::getActive()->queryValue("eComboBox.smallButton.decoWidth",0)?"eButton":""),
+pm(0), entries(OpenEntries), current(0)
+{
+ align=eTextPara::dirLeft;
+ if ( eSkin::getActive()->queryValue("eComboBox.smallButton.decoWidth",0) )
+ button.loadDeco();
+ button.setBlitFlags(BF_ALPHATEST);
+
+ eSkin::getActive()->queryImage(pm, "eComboBox.arrow");
+ button.setPixmap(pm);
+ listbox.hide();
+ listbox.setDeco("eComboBox.listbox");
+ listbox.loadDeco();
+ CONNECT( selected, eComboBox::onOkPressed );
+ CONNECT( listbox.selected, eComboBox::onEntrySelected );
+ CONNECT( listbox.selchanged, eComboBox::onSelChanged );
+ listbox.zOrderRaise();
+ addActionMap(&i_cursorActions->map);
+}
+
+eComboBox::~eComboBox()
+{
+ if ( listbox.isVisible() )
+ {
+ eDebug("KILL COMBOBOX WITH OPEN LISTBOX");
+ listbox.hide();
+ setFocus(this);
+ eWindow::globalCancel( eWindow::ON );
+ }
+}
+
+void eComboBox::redrawWidget(gPainter *target, const eRect &rc)
+{
+// target->clip( eRect( rc.left(), rc.top(), rc.width()-button.width(), rc.bottom() ) );
+ eLabel::redrawWidget(target, rc);
+// target->clippop();
+}
+
+void eComboBox::onOkPressed()
+{
+ if ( flags & flagShowEntryHelp)
+ {
+ oldHelpText=helptext;
+ setHelpText( listbox.getCurrent()->getHelpText() );
+ }
+ if ( flags & flagSorted )
+ listbox.sort();
+ parent->setFocus( &listbox );
+ ePoint pt = getAbsolutePosition();
+ if ( pt.y() + getSize().height() + listbox.getSize().height() > 520)
+ listbox.move( ePoint( pt.x(), pt.y()-listbox.getSize().height() ) );
+ else
+ listbox.move( ePoint( pt.x(), pt.y()+getSize().height() ) );
+
+ eWindow::globalCancel( eWindow::OFF );
+ listbox.show();
+}
+
+int eComboBox::setProperty( const eString& prop, const eString& val )
+{
+ if ( prop == "sorted" )
+ flags |= flagSorted;
+ else if (prop == "openEntries" )
+ entries = atoi( val.c_str() );
+ else if (prop == "showEntryHelp" )
+ flags |= flagShowEntryHelp;
+ else if (prop == "openWidth" )
+ {
+ int width=listbox.getSize().width();
+ width = atoi(val.c_str());
+ setOpenWidth( width );
+ }
+ else
+ return eButton::setProperty( prop, val);
+ return 0;
+}
+
+int eComboBox::eventHandler( const eWidgetEvent& event )
+{
+ switch (event.type)
+ {
+ case eWidgetEvent::evtShortcut:
+ onOkPressed();
+ break;
+ case eWidgetEvent::changedPosition:
+ case eWidgetEvent::changedSize:
+ {
+ eListBoxEntryText* cur = listbox.getCount()?listbox.getCurrent():0;
+ listbox.resize( eSize( getSize().width(), eListBoxEntryText::getEntryHeight()*entries+listbox.getDeco().borderBottom+listbox.getDeco().borderTop ) );
+ int smButtonDeco = eSkin::getActive()->queryValue("eComboBox.smallButton.decoWidth", pm?pm->x:0 );
+ if (deco)
+ {
+ button.resize( eSize(smButtonDeco, crect.height()) );
+ button.move( ePoint( crect.right()-smButtonDeco, crect.top() ) );
+ }
+ else
+ {
+ button.resize( eSize(smButtonDeco, height()) );
+ button.move( ePoint( position.x()+size.width()-smButtonDeco, 0 ) );
+ }
+ if (pm)
+ button.pixmap_position = ePoint( (button.getSize().width() - pm->x) / 2, (button.getSize().height() - pm->y) / 2 );
+ if (cur)
+ listbox.setCurrent(cur);
+ }
+ default:
+ return eButton::eventHandler( event );
+ }
+ return 1;
+}
+
+int eComboBox::moveSelection ( int dir, bool sendSelChanged )
+{
+ int ret = listbox.moveSelection( dir, sendSelChanged );
+ eListBoxEntryText *cur = listbox.getCurrent();
+ if ( cur )
+ {
+ setText( cur->getText() );
+ current = cur;
+ }
+ return ret;
+}
+
+
+void eComboBox::onEntrySelected( eListBoxEntryText* e)
+{
+ listbox.hide();
+ if (flags & flagShowEntryHelp)
+ setHelpText( oldHelpText );
+
+ if (e && button.getText() != e->getText() )
+ {
+ setText(e->getText());
+ setFocus( this );
+#ifndef DISABLE_LCD
+ if ( parent->LCDElement )
+ parent->LCDElement->setText("");
+#endif
+ current = e;
+ /* emit */ selchanged_id(this, current);
+ /* emit */ selchanged(current);
+ }
+ else
+ setFocus( this );
+
+ eWindow::globalCancel( eWindow::ON );
+}
+
+void eComboBox::onSelChanged(eListBoxEntryText* le)
+{
+ if (flags & flagShowEntryHelp )
+ setHelpText( le->getHelpText() );
+#ifndef DISABLE_LCD
+ if ( parent->getFocus() == &listbox )
+ {
+ if ( LCDTmp )
+ LCDTmp->setText( le->getText() );
+ else if ( parent->LCDElement )
+ parent->LCDElement->setText( le->getText() );
+ }
+#endif
+}
+
+void eComboBox::removeEntry( eListBoxEntryText* le )
+{
+ if (le)
+ {
+ listbox.remove(le);
+ if ( flags & flagSorted )
+ listbox.sort();
+ }
+}
+
+void eComboBox::removeEntry( int num )
+{
+ if ( listbox.getCount() >= num)
+ {
+ setCurrent( num );
+ listbox.remove( listbox.getCurrent() );
+ if ( flags & flagSorted )
+ listbox.sort();
+ }
+}
+
+void eComboBox::removeEntry( void* key )
+{
+ setCurrent(key);
+ if (listbox.getCurrent() && key == listbox.getCurrent()->getKey() )
+ {
+ listbox.remove( listbox.getCurrent() );
+ if ( flags & flagSorted )
+ listbox.sort();
+ }
+}
+
+int eComboBox::setCurrent( eListBoxEntryText* le, bool sendSelChanged )
+{
+ if (!le)
+ return E_INVALID_ENTRY;
+
+ int err = listbox.setCurrent( le, sendSelChanged );
+ if( err && err != E_ALLREADY_SELECTED )
+ return err;
+
+ setText( listbox.getCurrent()->getText() );
+ current = listbox.getCurrent();
+
+ return OK;
+}
+
+struct selectEntryByNum: public std::unary_function<const eListBoxEntryText&, void>
+{
+ int num;
+ eListBox<eListBoxEntryText>* lb;
+ bool sendSelChanged;
+
+ selectEntryByNum(int num, eListBox<eListBoxEntryText> *lb, bool sendSelChanged=false): num(num), lb(lb), sendSelChanged(sendSelChanged)
+ {
+ }
+
+ bool operator()(const eListBoxEntryText& le)
+ {
+ if (!num--)
+ {
+ lb->setCurrent(&le, sendSelChanged);
+ return 1;
+ }
+ return 0;
+ }
+};
+
+int eComboBox::setCurrent( int num, bool sendSelChanged )
+{
+ if ( num > listbox.getCount() )
+ return E_INVALID_ENTRY;
+
+ int err = listbox.forEachEntry( selectEntryByNum(num, &listbox, sendSelChanged ) );
+ if ( err )
+ return E_COULDNT_FIND;
+
+ setText( listbox.getCurrent()->getText() );
+ current = listbox.getCurrent();
+
+ return OK;
+}
+
+struct selectEntryByKey: public std::unary_function<const eListBoxEntryText&, void>
+{
+ void* key;
+ eListBox<eListBoxEntryText>* lb;
+ bool sendSelChanged;
+
+ selectEntryByKey(void *key, eListBox<eListBoxEntryText> *lb, bool sendSelChanged=false):key(key), lb(lb), sendSelChanged(sendSelChanged)
+ {
+ }
+
+ bool operator()(const eListBoxEntryText& le)
+ {
+ if ( le.getKey() == key )
+ {
+ lb->setCurrent(&le, sendSelChanged );
+ return 1;
+ }
+ return 0;
+ }
+};
+
+int eComboBox::setCurrent( void* key, bool sendSelChanged )
+{
+ if (!listbox.getCount())
+ return E_INVALID_ENTRY;
+
+ eListBoxEntryText* cur = listbox.getCurrent();
+
+ if ( cur && cur->getKey() == key )
+ goto ok;
+
+ int err;
+ if ( (err=listbox.forEachEntry( selectEntryByKey(key, &listbox, sendSelChanged ) ) ) )
+ return E_COULDNT_FIND;
+
+ok:
+ setText( listbox.getCurrent()->getText() );
+ current = listbox.getCurrent();
+
+ return OK;
+}
+
+eListBoxEntryText* eComboBox::getCurrent()
+{
+ return current;
+}
diff --git a/lib/gui/combobox.h b/lib/gui/combobox.h
new file mode 100644
index 00000000..55c1d469
--- /dev/null
+++ b/lib/gui/combobox.h
@@ -0,0 +1,50 @@
+#ifndef __E_COMBOBOX__
+#define __E_COMBOBOX__
+
+#include <lib/gui/listbox.h>
+#include <lib/gui/ebutton.h>
+
+class eComboBox: public eButton
+{
+ eListBox<eListBoxEntryText> listbox;
+ eLabel button; // the small buttin with arrow png...
+ ePtr<gPixmap> pm;
+ int entries;
+ eListBoxEntryText *current;
+ void onOkPressed();
+ void onEntrySelected( eListBoxEntryText* );
+ void onSelChanged( eListBoxEntryText* ); // für setzen des HelpTextes ( Statusbar )
+ int eventHandler( const eWidgetEvent& );
+ eString oldHelpText;
+ int setProperty( const eString&, const eString& );
+ void redrawWidget(gPainter *target, const eRect &rc);
+public:
+ ~eComboBox();
+ void setOpenWidth( int w ) { listbox.resize( eSize(w, listbox.getSize().height()) ); }
+ enum { OK = 0, ERROR=1, E_ALLREADY_SELECTED = 2, E_COULDNT_FIND = 4, E_INVALID_ENTRY = 8 };
+ Signal1< void, eListBoxEntryText* > selchanged;
+ Signal2< void, eComboBox*, eListBoxEntryText* > selchanged_id;
+ enum { /*flagVCenter=64 in eLabel*/ flagSorted=128, flagShowEntryHelp=256 };
+ eComboBox(eWidget* parent, int OpenEntries=5, eLabel* desc=0, int takefocus=1, const char *deco="eComboBox" );
+ void removeEntry( eListBoxEntryText* );
+ void removeEntry( int );
+ void removeEntry( void* );
+ void sort() { listbox.sort(); }
+ int setCurrent( eListBoxEntryText*, bool=false );
+ int setCurrent( int, bool=false );
+ int setCurrent( void*, bool=false );
+ int getCount() { return listbox.getCount(); }
+ int moveSelection ( int dir, bool=false );
+ void clear() { listbox.clearList(); }
+ eListBoxEntryText* getCurrent();
+ operator eListBox<eListBoxEntryText>*() { return &listbox; }
+
+ template <class Z>
+ int forEachEntry(Z ob)
+ {
+ return listbox.forEachEntry(ob);
+ }
+};
+
+
+#endif // __E_COMBOBOX__
diff --git a/lib/gui/decoration.cpp b/lib/gui/decoration.cpp
new file mode 100644
index 00000000..4debef98
--- /dev/null
+++ b/lib/gui/decoration.cpp
@@ -0,0 +1,181 @@
+#include <lib/gui/decoration.h>
+#include <lib/gdi/gpixmap.h>
+#include <lib/gdi/grc.h>
+#include <lib/gui/eskin.h>
+#include <lib/gui/ewidget.h>
+
+/*
+
+ +-------+-----------------+--------+
+ |TopLeft| Top |TopRight|
+ +------++-----------------+--+-----+
+ | Left| client |Right|
+ +------+---+-----------+-----+-----+
+ |BottomLeft| Bottom |BottomRight|
+ +----------+-----------+-----------+
+
+*/
+
+eDecoration::eDecoration()
+{
+ iTopLeft=iTop=iTopRight=iLeft=iRight=iBottomLeft=iBottom=iBottomRight=0;
+ borderLeft=borderTop=borderRight=borderBottom=0;
+}
+
+bool eDecoration::load(const eString& base)
+{
+ if (basename != base)
+ {
+ basename=base; // all your
+
+ eSkin::getActive()->queryImage(iTopLeft, basename + ".topLeft");
+ eSkin::getActive()->queryImage(iTop, basename + ".top");
+ eSkin::getActive()->queryImage(iTopRight, basename + ".topRight");
+ eSkin::getActive()->queryImage(iLeft, basename + ".left");
+ eSkin::getActive()->queryImage(iRight, basename + ".right");
+ eSkin::getActive()->queryImage(iBottomLeft, basename + ".bottomLeft");
+ eSkin::getActive()->queryImage(iBottom, basename + ".bottom");
+ eSkin::getActive()->queryImage(iBottomRight, basename + ".bottomRight");
+
+ borderLeft=borderTop=borderRight=borderBottom=0;
+
+ if (iTop)
+ borderTop = iTop->y;
+ if (iLeft)
+ borderLeft = iLeft->x;
+ if (iRight)
+ borderRight = iRight->x;
+ if (iBottom)
+ borderBottom = iBottom->y;
+ }
+ return operator bool();
+}
+
+void eDecoration::drawDecoration(gPainter *target, ePoint size)
+{
+ int x=0, xm=size.x(), y, ym;
+
+ if (iBottomLeft)
+ {
+ target->blit(iBottomLeft, ePoint(0, size.y()-iBottomLeft->y));
+ x+=iBottomLeft->x;
+ }
+
+ if (iBottomRight)
+ {
+ xm-=iBottomRight->x;
+ target->blit(iBottomRight, ePoint(xm, size.y()-iBottomRight->y), eRect(x, size.y()-iBottomRight->y, size.x()-x, iBottomRight->y));
+ }
+
+ if (iBottom)
+ {
+ while (x<xm)
+ {
+ target->blit(iBottom, ePoint(x, size.y()-iBottom->y), eRect(x, size.y()-iBottom->y, xm-x, size.y()));
+ x+=iBottom->x;
+ }
+ }
+
+ x=0;
+ xm=size.x();
+
+ if (iTopLeft)
+ {
+ target->blit(iTopLeft, ePoint(0, 0) );
+ x+=iTopLeft->x;
+ }
+
+ if (iTopRight)
+ {
+ xm-=iTopRight->x;
+ target->blit(iTopRight, ePoint(xm, 0), eRect(x, 0, size.x()-x, size.y()));
+ }
+
+ if (iTop)
+ {
+ while (x<xm)
+ {
+ target->blit(iTop, ePoint(x, 0), eRect(x, 0, xm-x, size.y()));
+ x+=iTop->x;
+ }
+ }
+
+ y=0; ym=size.y();
+
+ if (iTopLeft)
+ y=iTopLeft->y;
+ if (iBottomLeft)
+ ym=size.y()-iBottomLeft->y;
+ if (iLeft)
+ {
+ while (y<ym)
+ {
+ target->blit(iLeft, ePoint(0, y), eRect(0, y, iLeft->x, ym-y));
+ y+=iLeft->y;
+ }
+ }
+
+ if (iTopRight)
+ y=iTopRight->y;
+ if (iBottomRight)
+ ym=size.y()-iBottomRight->y;
+ if (iRight)
+ {
+ while (y<ym)
+ {
+ target->blit(iRight, ePoint(size.x()-iRight->x, y), eRect(size.x()-iRight->x, y, iRight->x, ym-y));
+ y+=iRight->y;
+ }
+ }
+
+ target->flush();
+}
+
+int eDecoWidget::setProperty( const eString &prop, const eString &value)
+{
+ if (prop == "loadDeco")
+ {
+ if ( value != "" )
+ strDeco=value;
+
+ loadDeco();
+ }
+ else
+ return eWidget::setProperty( prop, value );
+
+ return 0;
+}
+
+int eDecoWidget::eventFilter( const eWidgetEvent &evt )
+{
+ if ( evt.type == eWidgetEvent::changedSize )
+ {
+ if (deco)
+ {
+ crect.setLeft( deco.borderLeft );
+ crect.setTop( deco.borderTop );
+ crect.setWidth( width() - (deco.borderRight + deco.borderLeft) );
+ crect.setHeight( height() - (deco.borderBottom + deco.borderTop ) );
+ }
+ if (deco_selected)
+ {
+ crect_selected.setLeft( deco_selected.borderLeft );
+ crect_selected.setTop( deco_selected.borderTop );
+ crect_selected.setWidth( width() - (deco_selected.borderRight + deco_selected.borderLeft) );
+ crect_selected.setHeight( height() - (deco_selected.borderBottom + deco_selected.borderTop ) );
+ }
+ }
+ return 0; //always return 0... the eventHandler must been called...
+}
+
+void eDecoWidget::loadDeco()
+{
+ int i = 0;
+ if ( deco.load( strDeco ) )
+ i |= 1;
+ if ( deco_selected.load( strDeco+".selected" ) )
+ i |= 1;
+ if (i)
+ event( eWidgetEvent::changedSize );
+}
+
diff --git a/lib/gui/decoration.h b/lib/gui/decoration.h
new file mode 100644
index 00000000..4a5e4eec
--- /dev/null
+++ b/lib/gui/decoration.h
@@ -0,0 +1,49 @@
+#ifndef __lib_gui_decoration_h
+#define __lib_gui_decoration_h
+
+#include <lib/gdi/erect.h>
+#include <lib/base/estring.h>
+#include <lib/gui/ewidget.h>
+class gPixmap;
+class gPainter;
+
+class eDecoration
+{
+ ePtr<gPixmap> iTopLeft, iTop,
+ iTopRight, iLeft, iRight,
+ iBottomLeft, iBottom, iBottomRight;
+
+ eString basename;
+public:
+ operator bool() { return iTopLeft || iTop || iTopRight || iLeft || iRight || iBottomLeft || iBottom || iBottomRight; }
+
+ eDecoration();
+
+ bool load(const eString& basename);
+
+ void drawDecoration(gPainter *target, ePoint size );
+ int borderTop, borderLeft, borderBottom, borderRight;
+};
+
+class eDecoWidget:public eWidget
+{
+protected:
+ eString strDeco;
+ eRect crect, crect_selected;
+ eDecoration deco, deco_selected;
+ int setProperty( const eString &prop, const eString &value);
+ int eventFilter( const eWidgetEvent &evt);
+public:
+ void setDeco( const char* deco )
+ {
+ strDeco = deco;
+ }
+ void loadDeco();
+ eDecoWidget( eWidget* parent=0, int takefocus=0, const char* deco="" )
+ :eWidget(parent, takefocus), strDeco( deco )
+ { }
+ const eDecoration& getDeco() { return deco; }
+ const eDecoration& getDecoSelected() { return deco_selected; }
+};
+
+#endif
diff --git a/lib/gui/ebutton.cpp b/lib/gui/ebutton.cpp
new file mode 100644
index 00000000..9e97d581
--- /dev/null
+++ b/lib/gui/ebutton.cpp
@@ -0,0 +1,134 @@
+#include <lib/gui/ebutton.h>
+#include <lib/gui/eskin.h>
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+#include <lib/gdi/font.h>
+#include <lib/gui/guiactions.h>
+
+eButton::eButton(eWidget *parent, eLabel* desc, int takefocus, const char *deco)
+ :eLabel(parent, 0, takefocus, deco),
+#ifndef DISABLE_LCD
+ tmpDescr(0),
+#endif
+ focusB(eSkin::getActive()->queryScheme("global.selected.background")),
+ focusF(eSkin::getActive()->queryScheme("global.selected.foreground")),
+ normalB(eSkin::getActive()->queryScheme("button.normal.background")),
+ normalF(eSkin::getActive()->queryScheme("global.normal.foreground")),
+ descr(desc)
+{
+ align=eTextPara::dirCenter;
+ flags |= eLabel::flagVCenter;
+ addActionMap(&i_cursorActions->map);
+}
+
+void eButton::gotFocus()
+{
+#ifndef DISABLE_LCD
+ if (parent && parent->LCDElement)
+ {
+ if (descr)
+ {
+ LCDTmp = new eLabel(parent->LCDElement);
+ LCDTmp->hide();
+ eSize s = parent->LCDElement->getSize();
+ LCDTmp->move(ePoint(0,s.height()/2));
+ LCDTmp->resize(eSize(s.width(), s.height()/2));
+ LCDTmp->setText(text);
+ LCDTmp->setBackgroundColor(255);
+ LCDTmp->show();
+ 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
+ parent->LCDElement->setText(text);
+ }
+#endif
+ setForegroundColor(focusF,false);
+ setBackgroundColor(focusB);
+
+//invalidate();
+}
+
+void eButton::lostFocus()
+{
+#ifndef DISABLE_LCD
+ if (parent && parent->LCDElement)
+ {
+ if (LCDTmp)
+ {
+ delete LCDTmp;
+ LCDTmp = 0;
+ if (tmpDescr)
+ {
+ delete tmpDescr;
+ tmpDescr=0;
+ }
+ }
+ else
+ parent->LCDElement->setText("");
+ }
+#endif
+ setForegroundColor(normalF,false);
+ setBackgroundColor(normalB);
+
+// invalidate();
+}
+
+int eButton::eventHandler(const eWidgetEvent &event)
+{
+ switch (event.type)
+ {
+ case eWidgetEvent::evtAction:
+ if (event.action == &i_cursorActions->ok)
+ {
+ /*emit*/ selected();
+ /*emit*/ selected_id(this);
+
+/*#ifndef DISABLE_LCD
+ if (parent && parent->LCDElement)
+ {
+ if (LCDTmp)
+ LCDTmp->setText(text);
+ else
+ parent->LCDElement->setText(text);
+ }
+#endif*/
+ }
+ else
+ return eLabel::eventHandler(event);
+ break;
+ case eWidgetEvent::evtShortcut:
+ /*emit*/ selected();
+ /*emit*/ selected_id(this);
+ return 0;
+ break;
+ default:
+ return eLabel::eventHandler(event);
+ break;
+ }
+ return 1;
+}
+
+static eWidget *create_eButton(eWidget *parent)
+{
+ return new eButton(parent);
+}
+
+class eButtonSkinInit
+{
+public:
+ eButtonSkinInit()
+ {
+ eSkin::addWidgetCreator("eButton", create_eButton);
+ }
+ ~eButtonSkinInit()
+ {
+ eSkin::removeWidgetCreator("eButton", create_eButton);
+ }
+};
+
+eAutoInitP0<eButtonSkinInit> init_eButtonSkinInit(eAutoInitNumbers::guiobject, "eButton");
diff --git a/lib/gui/ebutton.h b/lib/gui/ebutton.h
new file mode 100644
index 00000000..6e9783eb
--- /dev/null
+++ b/lib/gui/ebutton.h
@@ -0,0 +1,37 @@
+#ifndef __ebutton_h
+#define __ebutton_h
+
+#include <lib/gui/elabel.h>
+#include <lib/gdi/grc.h>
+
+/**
+ * \brief A widget which acts like a button.
+ */
+class eButton: public eLabel
+{
+#ifndef DISABLE_LCD
+ eLabel* tmpDescr; // used for LCD with description
+#endif
+protected:
+ gColor focusB, focusF, normalB, normalF;
+ eLabel *descr;
+ int eventHandler(const eWidgetEvent &event);
+ void gotFocus();
+ void lostFocus();
+public:
+ /**
+ * \brief Constructs a button.
+ *
+ * \param descr is for use with lcd
+ */
+ eButton(eWidget *parent, eLabel* descr=0, int takefocus=1, const char *deco="eButton" );
+ /**
+ * \brief the "selected" signal.
+ *
+ * This signals is emitted when OK is pressed.
+ */
+ Signal0<void> selected;
+ Signal1<void, eButton*> selected_id;
+};
+
+#endif
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..92f6e4d5
--- /dev/null
+++ b/lib/gui/echeckbox.h
@@ -0,0 +1,25 @@
+#ifndef __echeckbox_h
+#define __echeckbox_h
+
+#include <lib/gui/ebutton.h>
+
+class eCheckbox: public eButton
+{
+protected:
+ int ischecked;
+private:
+ void sel();
+ int eventHandler(const eWidgetEvent &event);
+ int setProperty(const eString &prop, const eString &value);
+ void gotFocus();
+ void lostFocus();
+ bool swapTxtPixmap;
+public:
+ Signal1<void, int> checked;
+ eCheckbox(eWidget *parent, int checked=0, int takefocus=1, bool swapTxtPixmap=false, const char *deco="eCheckBox" );
+ ~eCheckbox();
+ void setCheck(int c);
+ int isChecked() { return ischecked; }
+};
+
+#endif
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..096ef0d8
--- /dev/null
+++ b/lib/gui/elabel.h
@@ -0,0 +1,44 @@
+#ifndef __elabel_h
+#define __elabel_h
+
+#include <lib/gui/ewidget.h>
+#include <lib/gdi/grc.h>
+#include <lib/gui/decoration.h>
+
+// Definition Blit Flags
+#define BF_ALPHATEST 1
+
+class eLabel: public eDecoWidget
+{
+protected:
+ int blitFlags;
+ int flags;
+ eTextPara *para;
+ gColor transparentBackgroundColor;
+ int align;
+ void validate( const eSize* s=0 );
+ int eventHandler(const eWidgetEvent &event);
+ void redrawWidget(gPainter *target, const eRect &area);
+ int yOffs;
+ ePtr<gPixmap> shortcutPixmap; // shortcut pixmap to be displayed right after description
+public:
+ void invalidate();
+ enum { flagVCenter = 64 };
+ eLabel(eWidget *parent, int flags=0 /* RS_WRAP */ , int takefocus=0, const char* deco="eLabel" );
+ ~eLabel();
+
+ void setBlitFlags( int flags );
+ void setFlags(int flags);
+ void removeFlags(int flags);
+ void setAlign(int align);
+ void setShortcutPixmap(const eString &shortcut);
+ int setProperty(const eString &prop, const eString &value);
+ void setPixmapPosition( const ePoint &p );
+
+ eSize getExtend();
+ ePoint getLeftTop();
+
+ ePoint pixmap_position, text_position;
+};
+
+#endif
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..23e4b152
--- /dev/null
+++ b/lib/gui/emessage.h
@@ -0,0 +1,40 @@
+#ifndef __emessage_h
+#define __emessage_h
+
+#include <lib/gui/ewindow.h>
+
+class eLabel;
+
+/**
+ * \brief A (modal) messagebox.
+ */
+class eMessageBox: public eWindow
+{
+ eLabel *text, *icon;
+public:
+ void pressedOK();
+ void pressedCancel();
+ void pressedYes();
+ void pressedNo();
+public:
+ enum { btOK=1, btCancel=2, btYes=4, btNo=8, btMax};
+ enum { iconInfo=16, iconWarning=32, iconQuestion=64, iconError=128 };
+ /**
+ * \brief Creates a messagebox.
+ *
+ * example:
+ * \code
+{
+ eMessageBox message("Your documentation sucks!\nPlease consider using Neutrino!", "Documentation");
+ message.show();
+ message.exec();
+ message.hide();
+} \endcode
+ * \param string The string displayed inside the messagebox.
+ * \param caption The title of the messagebox.
+ */
+ eMessageBox(eString string, eString caption, int flags=btOK, int def=btOK );
+ ~eMessageBox();
+};
+
+#endif
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..e1b2dcc3
--- /dev/null
+++ b/lib/gui/enumber.h
@@ -0,0 +1,69 @@
+#ifndef __enumber_h
+#define __enumber_h
+
+#include <lib/gui/ewidget.h>
+#include <lib/gui/decoration.h>
+
+class eLabel;
+class gPainter;
+
+/**
+ * \brief A widget to enter a number.
+ */
+class eNumber: public eDecoWidget
+{
+private:
+ void redrawNumber(gPainter *, int n, const eRect &rect);
+ void redrawWidget(gPainter *, const eRect &rect);
+ eRect getNumberRect(int n);
+ int eventHandler(const eWidgetEvent &event);
+ int number[24];
+ int len, dspace, space_selected, active;
+ gColor cursorB, cursorF, normalB, normalF;
+ int oldmax;
+ int have_focus;
+ int min, max, digit, maxdigits, isactive;
+ int flags;
+ int base;
+ eWidget* descr;
+ eLabel* tmpDescr; // used for description Label in LCD
+ bool neg;
+protected:
+ int getActive() { return active; }
+ int keyDown(int key);
+ void gotFocus();
+ void lostFocus();
+public:
+ static void unpack(__u32 l, int *t);
+ static void pack(__u32 &l, int *t);
+ void invalidateNum();
+ Signal1<void, int*> selected;
+ Signal0<void> numberChanged;
+ eNumber(eWidget *parent, int len, int min, int max, int maxdigits, int *init, int isactive=0, eWidget* descr=0, int grabfocus=1, const char* deco="eNumber" );
+ ~eNumber();
+ int getNumber(int f) { if ((f>=0) && (f<len)) return number[f]; return -1; }
+ double getFixedNum();
+ void setFixedNum(double);
+ void setNumber(int f, int n);
+ void setLimits(int min, int max);
+ void setNumberOfFields(int n);
+ void setMaximumDigits(int n);
+ enum
+ {
+ flagDrawPoints=1,
+ flagDrawBoxes=2,
+ flagFillWithZeros=4,
+ flagTime=8,
+ flagPosNeg=16,
+ flagHideInput=32,
+ flagFixedNum=64
+ };
+ void setFlags(int flags);
+ void setBase(int base);
+
+ void setNumber(int n);
+ int getNumber();
+ void setDescr( eWidget *d ) { descr = d; }
+};
+
+#endif
diff --git a/lib/gui/epixmap.cpp b/lib/gui/epixmap.cpp
new file mode 100644
index 00000000..c544b007
--- /dev/null
+++ b/lib/gui/epixmap.cpp
@@ -0,0 +1,44 @@
+#include <lib/gui/epixmap.h>
+#include <lib/gui/eskin.h>
+#include <lib/gui/init.h>
+#include <lib/gui/init_num.h>
+
+ePixmap::ePixmap(eWidget *parent): eWidget(parent)
+{
+ position=ePoint(0, 0);
+ setBackgroundColor(getForegroundColor());
+}
+
+ePixmap::~ePixmap()
+{
+}
+
+void ePixmap::redrawWidget(gPainter *paint, const eRect &area)
+{
+ if (pixmap)
+ paint->blit(*pixmap, position);
+}
+
+void ePixmap::eraseBackground(gPainter *target, const eRect &area)
+{
+}
+
+static eWidget *create_ePixmap(eWidget *parent)
+{
+ return new ePixmap(parent);
+}
+
+class ePixmapSkinInit
+{
+public:
+ ePixmapSkinInit()
+ {
+ eSkin::addWidgetCreator("ePixmap", create_ePixmap);
+ }
+ ~ePixmapSkinInit()
+ {
+ eSkin::removeWidgetCreator("ePixmap", create_ePixmap);
+ }
+};
+
+eAutoInitP0<ePixmapSkinInit> init_ePixmapSkinInit(eAutoInitNumbers::guiobject, "ePixmap");
diff --git a/lib/gui/epixmap.h b/lib/gui/epixmap.h
new file mode 100644
index 00000000..e03c76bf
--- /dev/null
+++ b/lib/gui/epixmap.h
@@ -0,0 +1,18 @@
+#ifndef __epixmap_h
+#define __epixmap_h
+
+#include "ewidget.h"
+class gPixmap;
+
+class ePixmap: public eWidget
+{
+ ePoint position;
+public:
+ ePixmap(eWidget *parent);
+ ~ePixmap();
+
+ void redrawWidget(gPainter *paint, const eRect &area);
+ void eraseBackground(gPainter *target, const eRect &area);
+};
+
+#endif
diff --git a/lib/gui/eprogress.cpp b/lib/gui/eprogress.cpp
new file mode 100644
index 00000000..3528929e
--- /dev/null
+++ b/lib/gui/eprogress.cpp
@@ -0,0 +1,136 @@
+#include <lib/gui/eprogress.h>
+
+#include <stdlib.h>
+
+#include <lib/gdi/erect.h>
+#include <lib/gdi/fb.h>
+#include <lib/gdi/lcd.h>
+#include <lib/gui/eskin.h>
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+
+eProgress::eProgress(eWidget *parent, int takefocus)
+ : eWidget(parent, takefocus)
+{
+ left=eSkin::getActive()->queryScheme("eProgress.left");
+ right=eSkin::getActive()->queryScheme("eProgress.right");
+ perc=start=0;
+ border=2;
+ direction=0;
+ setForegroundColor(eSkin::getActive()->queryScheme("eProgress.border"));
+}
+
+eProgress::~eProgress()
+{
+}
+
+void eProgress::setPerc(int p)
+{
+ if (perc != p)
+ {
+ perc=p;
+ invalidate();
+ }
+}
+
+void eProgress::setStart(int p)
+{
+ if (start != p)
+ {
+ start=p;
+ invalidate();
+ }
+}
+
+void eProgress::redrawWidget(gPainter *target, const eRect &area)
+{
+ // border malen
+ target->setForegroundColor(getForegroundColor());
+ target->fill(eRect(0, 0, size.width(), border));
+ target->fill(eRect(0, border, border, size.height()-border));
+ target->fill(eRect(border, size.height()-border, size.width()-border, border));
+ target->fill(eRect(size.width()-border, border, border, size.height()-border));
+
+ switch (direction)
+ {
+ case 0:
+ {
+ int st=start*(size.width()-border*2)/100;
+ if (st<0)
+ st=0;
+ if (st>(size.width()-border*2))
+ st=size.width()-border*2;
+
+ int dh=perc*(size.width()-border*2)/100;
+ if (dh<0)
+ dh=0;
+ if ((dh+st)>(size.width()-border*2))
+ dh=size.width()-border*2-st;
+
+ target->setForegroundColor(left);
+ target->fill(eRect(border+start, border, dh, size.height()-border*2));
+ target->setForegroundColor(right);
+ target->fill(eRect(border+dh+st, border, size.width()-border*2-dh-st, size.height()-border*2));
+ if (st)
+ target->fill(eRect(border, border, st, size.height()-border*2));
+ break;
+ }
+ case 1:
+ {
+ int st=start*(size.height()-border*2)/100;
+ if (st<0)
+ st=0;
+ if (st>(size.height()-border*2))
+ st=size.height()-border*2;
+
+ int dh=perc*(size.height()-border*2)/100;
+ if (dh<0)
+ dh=0;
+ if ((dh+st)>(size.height()-border*2))
+ dh=size.height()-border*2-st;
+
+ target->setForegroundColor(left);
+ target->fill(eRect(border, border+st, size.width()-border*2, dh));
+ target->setForegroundColor(right);
+ target->fill(eRect(border, border+dh+st, size.width()-border*2, size.height()-border*2-dh-st));
+ if (st)
+ target->fill(eRect(border, border, size.width()-border*2, st));
+ break;
+ }
+ }
+}
+
+int eProgress::setProperty(const eString &prop, const eString &value)
+{
+ if (prop=="leftColor")
+ left=eSkin::getActive()->queryColor(value);
+ else if (prop=="rightColor")
+ right=eSkin::getActive()->queryColor(value);
+ else if (prop=="border")
+ border=atoi(value.c_str());
+ else if (prop=="direction")
+ direction=atoi(value.c_str());
+ else
+ return eWidget::setProperty(prop, value);
+ return 0;
+}
+
+static eWidget *create_eProgress(eWidget *parent)
+{
+ return new eProgress(parent);
+}
+
+class eProgressSkinInit
+{
+public:
+ eProgressSkinInit()
+ {
+ eSkin::addWidgetCreator("eProgress", create_eProgress);
+ }
+ ~eProgressSkinInit()
+ {
+ eSkin::removeWidgetCreator("eProgress", create_eProgress);
+ }
+};
+
+eAutoInitP0<eProgressSkinInit> init_eProgressSkinInit(eAutoInitNumbers::guiobject, "eProgress");
diff --git a/lib/gui/eprogress.h b/lib/gui/eprogress.h
new file mode 100644
index 00000000..23fb40ca
--- /dev/null
+++ b/lib/gui/eprogress.h
@@ -0,0 +1,49 @@
+#ifndef __eprogress_h
+#define __eprogress_h
+
+#include <lib/gui/ewidget.h>
+#include <lib/gdi/grc.h>
+
+/**
+ * \brief A progressbar.
+ *
+ * Useful for displaying a progress or stuff.
+ */
+class eProgress: public eWidget
+{
+protected:
+ int perc, border, start;
+ int direction;
+ gColor left, right;
+public:
+ eProgress(eWidget *parent, int takeFocus=0);
+ ~eProgress();
+
+ /**
+ * \brief Sets the value.
+ *
+ * \param perc The range is \c 0..100
+ */
+ void setPerc(int perc);
+ void setStart(int perc);
+ void redrawWidget(gPainter *target, const eRect &area);
+
+ /**
+ * \brief Sets a property.
+ *
+ * Valid, eProgress specific properties are:
+ * \arg \c leftColor, the color of the left part
+ * \arg \c rightColor, the color of the right part
+ * \arg \c border, the size of the border (in pixels)
+ * \arg \c direction, direction (0 for horiz., 1 for vert.)
+ * \sa eWidget::setProperty
+ */
+ int setProperty(const eString &prop, const eString &value);
+
+ void setDirection(int d) { direction = d; }
+ void setBorder( int b ) { border = b; }
+ void setLeftColor( const gColor& c ) { left = c; }
+ void setRightColor( const gColor& c ) { right = c; }
+};
+
+#endif
diff --git a/lib/gui/eservicegrid.cpp b/lib/gui/eservicegrid.cpp
new file mode 100644
index 00000000..f80c6734
--- /dev/null
+++ b/lib/gui/eservicegrid.cpp
@@ -0,0 +1,74 @@
+#include <lib/gui/eservicegrid.h>
+
+eServiceGrid::eServiceGrid(eWidget *parent): eWidget(parent)
+{
+ para=0;
+ grid=0;
+
+ elemsize=eSize(16, 16);
+}
+
+void eServiceGrid::createGrid(eSize gs)
+{
+ gridsize=gs;
+ if (grid)
+ delete[] grid;
+ if (!(gridsize.x() && gridsize.y()))
+ return;
+ grid=new (eService*)[gridsize.x()*gridsize.y()];
+}
+
+eService **eServiceGrid::allocateGrid(eSize size)
+{
+ for (int y=0; y<gridsize.height(); y++)
+ for (int x=0; x<gridsize.width(); x++)
+ {
+ int ok=1;
+ for (int cy=0; ok && cy<size.height(); cy++)
+ for (int cx=0; ok && cx<size.width(); cx++)
+ if (grid[gridsize.width()*(y+cy)+x+cx])
+ {
+ ok=0;
+ break;
+ }
+ if (ok)
+ return grid+gridsize.width()*(y+cy)+x+cx;
+ }
+ return 0;
+}
+
+void eServiceGrid::setGridSize(int gx, int gy)
+{
+ createGrid(eSize(gx, gy));
+}
+
+void eServiceGrid::addService(eService *service)
+{
+ eTextPara temp;
+ temp.setFont(font);
+ temp.renderText(service->service_name);
+ eSize size=temp.getExtends();
+ eSize gsize=eSize((size.width()+elemsize.width()-1)/elemsize.width(), (size.height()+elemsize.height()-1)/elemsize.height());
+ eService **sp=allocateGrid(gsize);
+ if (!sp)
+ return;
+ for (int cy=0; ok && cy<gsize.height(); cy++)
+ for (int cx=0; ok && cx<gsize.width(); cx++)
+ sp[cy*gridsize.width()+cx]=service;
+}
+
+
+void eServiceGrid::validate()
+{
+ eService **gp=grid;
+ for (int y=0; y<gridsize.height(); y++)
+ for (int x=0; x<gridsize.width(); x++)
+ {
+ if (*gp)
+ {
+ para->setCursor(x*elemsize.width(), y*elemsize.height());
+ para->renderString((*gp)->service_name);
+ }
+ *gp++;
+ }
+}
diff --git a/lib/gui/eservicegrid.h b/lib/gui/eservicegrid.h
new file mode 100644
index 00000000..69d3fd9a
--- /dev/null
+++ b/lib/gui/eservicegrid.h
@@ -0,0 +1,27 @@
+#ifndef __eservicegrid_h
+#define __eservicegrid_h
+
+#include "ewidget.h"
+
+class eServiceGrid: public eWidget
+{
+ eService *(*grid);
+ eSize gridsize;
+ eSize elemsize;
+
+ eTextPara *para;
+
+ void validate();
+
+ void createGrid(eSize gridsize);
+ eService **allocateGrid(eSize size);
+
+public:
+ eServiceGrid(eWidget *parent);
+
+ void setGridSize(int gx, int gy);
+ void addService(eService *service);
+
+};
+
+#endif
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..a212449b
--- /dev/null
+++ b/lib/gui/eskin_register.cpp
@@ -0,0 +1,44 @@
+#include <lib/gui/eskin_register.h>
+#include <lib/gui/eskin.h>
+#include <lib/gdi/gfbdc.h>
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+#include <lib/base/econfig.h>
+
+#define DEFAULTSKIN "stone.esml"
+
+class eSkinInit
+{
+ eSkin default_skin;
+public:
+ eSkinInit()
+ {
+ if (default_skin.load( CONFIGDIR "/enigma/skins/default.esml"))
+ if (default_skin.load( DATADIR "/enigma/skins/default.esml"))
+ eFatal("skin load failed (" DATADIR "/enigma/skins/default.esml)");
+
+ eString skinfile=DEFAULTSKIN;
+
+ char *temp=0;
+ if (!eConfig::getInstance()->getKey("/ezap/ui/skin", temp))
+ {
+ skinfile=temp;
+ free(temp);
+ }
+
+ if (default_skin.load(skinfile.c_str()))
+ {
+ eWarning("failed to load user defined skin %s, falling back to " DEFAULTSKIN, skinfile.c_str());
+ if (default_skin.load(CONFIGDIR "/enigma/skins/" DEFAULTSKIN))
+ if (default_skin.load(DATADIR "/enigma/skins/" DEFAULTSKIN))
+ eFatal("couldn't load fallback skin " DATADIR "/enigma/skins/" DEFAULTSKIN);
+ }
+
+ default_skin.parseSkins();
+
+ default_skin.setPalette(gFBDC::getInstance());
+ default_skin.makeActive();
+ }
+};
+
+eAutoInitP0<eSkinInit> init_skin(eAutoInitNumbers::skin, "skin subsystem");
diff --git a/lib/gui/eskin_register.h b/lib/gui/eskin_register.h
new file mode 100644
index 00000000..d9373c71
--- /dev/null
+++ b/lib/gui/eskin_register.h
@@ -0,0 +1,8 @@
+#ifndef __eskin_register
+#define __eskin_register
+
+void eSkin_init();
+void eSkin_close();
+
+#endif
+
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");
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..de7fe3db
--- /dev/null
+++ b/lib/gui/ewindow.cpp
@@ -0,0 +1,160 @@
+#include <lib/gui/ewindow.h>
+#include <lib/gdi/grc.h>
+#include <lib/gui/eskin.h>
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+#include <lib/gdi/epng.h>
+#include <lib/gui/elabel.h>
+#include <lib/gui/guiactions.h>
+#include <lib/gdi/font.h>
+
+int eWindow::globCancel = eWindow::ON;
+
+eWindow::eWindow(int takefocus)
+ :eWidget(0, takefocus)
+{
+ deco.load("eWindow");
+
+ titleBarColor=eSkin::getActive()->queryScheme("eWindow.titleBar");
+ fontColor=eSkin::getActive()->queryScheme("eWindow.titleBarFont");
+
+ borderLeft=eSkin::getActive()->queryValue("eWindow.borderLeft", deco.borderLeft);
+ borderRight=eSkin::getActive()->queryValue("eWindow.borderRight", deco.borderRight);
+ borderBottom=eSkin::getActive()->queryValue("eWindow.borderBottom", deco.borderBottom);
+ borderTop=eSkin::getActive()->queryValue("eWindow.borderTop", deco.borderTop );
+
+ titleOffsetLeft=eSkin::getActive()->queryValue("eWindow.titleOffsetLeft", 0);
+ titleOffsetRight=eSkin::getActive()->queryValue("eWindow.titleOffsetRight", 0);
+ titleOffsetTop=eSkin::getActive()->queryValue("eWindow.titleOffsetTop", 0);
+ titleHeight=eSkin::getActive()->queryValue("eWindow.titleHeight", titleFontSize+10);
+ titleFontSize=eSkin::getActive()->queryValue("eWindow.titleFontSize", 20);
+
+ font = eSkin::getActive()->queryFont("eWindow.Childs");
+
+ addActionMap(&i_cursorActions->map);
+}
+
+eWindow::~eWindow()
+{
+}
+
+eRect eWindow::getTitleBarRect()
+{
+ eRect rc;
+ rc.setLeft( deco.borderLeft > titleOffsetLeft ? deco.borderLeft : titleOffsetLeft );
+ rc.setTop( titleOffsetTop );
+ rc.setRight( width() - ( deco.borderRight > titleOffsetRight ? deco.borderRight : titleOffsetRight ) );
+ rc.setBottom( rc.top() + (titleHeight?titleHeight:deco.borderTop) ); // deco.borderTop sucks...
+ return rc;
+}
+
+void eWindow::redrawWidget(gPainter *target, const eRect &where)
+{
+ if ( deco ) // then draw Deco
+ deco.drawDecoration(target, ePoint(width(), height()));
+ else
+ {
+ gColor border = eSkin::getActive()->queryColor("eWindow.border");
+ target->setForegroundColor(border);
+ target->line( ePoint(0,0), ePoint(0, height()) );
+ target->line( ePoint(0,0), ePoint(width(), 0) );
+ target->line( ePoint(width()-1,0), ePoint(width()-1, height()-1) );
+ target->line( ePoint(0,height()-1), ePoint(width()-1, height()-1) );
+ }
+ drawTitlebar(target);
+}
+
+void eWindow::eraseBackground(gPainter *target, const eRect &clip)
+{
+ target->clip(getClientRect());
+ target->clear();
+ target->clippop();
+}
+
+void eWindow::drawTitlebar(gPainter *target)
+{
+ eRect rc = getTitleBarRect();
+ target->clip( rc );
+ if ( titleHeight )
+ {
+ target->setForegroundColor(titleBarColor);
+ target->fill( rc );
+ }
+ rc.setWidth(rc.width()-10);
+ eTextPara *p = new eTextPara( rc );
+ p->setFont( eSkin::getActive()->queryFont("eWindow.TitleBar") );
+ p->renderString( text );
+ target->setBackgroundColor(titleBarColor);
+ target->setForegroundColor(fontColor);
+ target->renderPara( *p );
+ p->destroy();
+ target->clippop();
+}
+
+void eWindow::recalcClientRect()
+{
+ clientrect=eRect( borderLeft, borderTop, width() - (borderLeft+borderRight), height() - ( borderTop+borderBottom) );
+}
+
+int eWindow::eventHandler(const eWidgetEvent &event)
+{
+ switch (event.type)
+ {
+ case eWidgetEvent::willShow:
+ if (focus)
+ focusChanged( focus );
+ break;
+ case eWidgetEvent::changedText:
+ {
+ redraw(getTitleBarRect());
+ return 1;
+ }
+
+ case eWidgetEvent::evtAction:
+ if (globCancel && (event.action == &i_cursorActions->cancel) && in_loop) // hack
+ {
+ close(-1);
+ return eWidget::eventHandler(event);
+ }
+ else
+ break;
+ return 1;
+ default:
+ break;
+ }
+ return eWidget::eventHandler(event);
+}
+
+void eWindow::willShow()
+{
+#ifndef DISABLE_LCD
+ if (LCDTitle)
+ LCDTitle->setText(text);
+#endif
+ eWidget::willShow();
+}
+
+void eWindow::willHide()
+{
+ eWidget::willHide();
+}
+
+static eWidget *create_eWindow(eWidget *parent)
+{
+ return new eWindow();
+}
+
+class eWindowSkinInit
+{
+public:
+ eWindowSkinInit()
+ {
+ eSkin::addWidgetCreator("eWindow", create_eWindow);
+ }
+ ~eWindowSkinInit()
+ {
+ eSkin::removeWidgetCreator("eWindow", create_eWindow);
+ }
+};
+
+eAutoInitP0<eWindowSkinInit> init_eWindowSkinInit(eAutoInitNumbers::guiobject, "eWindow");
diff --git a/lib/gui/ewindow.h b/lib/gui/ewindow.h
new file mode 100644
index 00000000..34cef8c4
--- /dev/null
+++ b/lib/gui/ewindow.h
@@ -0,0 +1,48 @@
+#ifndef __ewindow_h
+#define __ewindow_h
+
+#include <lib/gui/ewidget.h>
+#include <lib/gui/decoration.h>
+
+/**
+ * \brief A (decorated) top level widget.
+ *
+ * An eWindow is whats actually seen as a window. It's top level (thus you cannot specify a parent),
+ * and may have a (skinned) decoration. It's clientrect is usually a bit smaller since it has a titlebar
+ * and a border.
+ *
+ */
+class eWindow: public eWidget
+{
+ eDecoration deco;
+ gColor fontColor, titleBarColor;
+ static int globCancel;
+protected:
+ int borderTop, borderLeft, borderBottom, borderRight;
+ int titleOffsetLeft, titleOffsetRight, titleOffsetTop, titleFontSize, titleHeight;
+ void redrawWidget(gPainter *target, const eRect &where);
+ void eraseBackground(gPainter *target, const eRect &where);
+ void drawTitlebar(gPainter *target);
+ void recalcClientRect();
+ int eventHandler(const eWidgetEvent &event);
+ void willShow();
+ void willHide();
+public:
+ enum { OFF, ON };
+ static void globalCancel(int mode) { globCancel=mode; }
+ eRect getTitleBarRect();
+ /**
+ * \brief Constructs the window
+ *
+ * \arg takefocus the \c eWidget::eWidget takefocus parameter. You don't need to set it if just
+ * one widget \e inside the parent needs focus. That widget can apply for it by itself.
+ */
+ eWindow(int takefocus=0);
+
+ /**
+ * destructs the window.
+ */
+ ~eWindow();
+};
+
+#endif
diff --git a/lib/gui/guiactions.cpp b/lib/gui/guiactions.cpp
new file mode 100644
index 00000000..f31fa78c
--- /dev/null
+++ b/lib/gui/guiactions.cpp
@@ -0,0 +1,8 @@
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+#include <lib/gui/guiactions.h>
+
+eAutoInitP0<cursorActions> i_cursorActions(eAutoInitNumbers::actions, "cursor actions");
+eAutoInitP0<focusActions> i_focusActions(eAutoInitNumbers::actions, "focus actions");
+eAutoInitP0<listActions> i_listActions(eAutoInitNumbers::actions, "list actions");
+eAutoInitP0<shortcutActions> i_shortcutActions(eAutoInitNumbers::actions, "shortcut actions");
diff --git a/lib/gui/guiactions.h b/lib/gui/guiactions.h
new file mode 100644
index 00000000..82967673
--- /dev/null
+++ b/lib/gui/guiactions.h
@@ -0,0 +1,90 @@
+#ifndef __src__lib__gui__guiactions_h__
+#define __src__lib__gui__guiactions_h__
+
+#include <lib/base/init.h>
+#include <lib/base/i18n.h>
+#include <lib/gui/actions.h>
+
+struct cursorActions
+{
+ eActionMap map;
+ eAction up, down, left, right, insertchar, deletechar, capslock, ok, cancel, help;
+ cursorActions():
+ map("cursor", "Cursor"),
+ up(map, "up", _("up"), eAction::prioWidget),
+ down(map, "down", _("down"), eAction::prioWidget),
+ left(map, "left", _("left"), eAction::prioWidget),
+ right(map, "right", _("right"), eAction::prioWidget),
+ insertchar(map, "insertchar", _("next char"), eAction::prioWidget),
+ deletechar(map, "deletechar", _("prev char"), eAction::prioWidget),
+ capslock(map, "capslock", _("CapsLock"), eAction::prioWidget),
+ ok(map, "ok", "OK", eAction::prioWidget),
+ cancel(map, "cancel", _("cancel"), eAction::prioDialog),
+ help(map, "help", _("show the help window"), eAction::prioGlobal)
+ {
+ }
+};
+
+extern eAutoInitP0<cursorActions> i_cursorActions;
+
+struct focusActions
+{
+ eActionMap map;
+ eAction up, down, left, right;
+ focusActions():
+ map("focus", "Focus"),
+ up(map, "up", _("up"), eAction::prioGlobal),
+ down(map, "down", _("down"), eAction::prioGlobal),
+ left(map, "left", _("left"), eAction::prioGlobal),
+ right(map, "right", _("right"), eAction::prioGlobal)
+ {
+ }
+};
+
+extern eAutoInitP0<focusActions> i_focusActions;
+
+struct listActions
+{
+ eActionMap map;
+ eAction pageup, pagedown;
+ listActions():
+ map("list", "Listen"),
+ pageup(map, "pageup", _("page up"), eAction::prioWidget+1),
+ pagedown(map, "pagedown", _("page down"), eAction::prioWidget+1)
+ {
+ }
+};
+
+extern eAutoInitP0<listActions> i_listActions;
+
+struct shortcutActions
+{
+ eActionMap map;
+ eAction number0, number1, number2, number3, number4,
+ number5, number6, number7, number8, number9,
+ red, green, yellow, blue, escape;
+ shortcutActions():
+ map("shortcut", "Shortcuts"),
+ number0(map, "0", "0", eAction::prioGlobal),
+ number1(map, "1", "1", eAction::prioGlobal),
+ number2(map, "2", "2", eAction::prioGlobal),
+ number3(map, "3", "3", eAction::prioGlobal),
+ number4(map, "4", "4", eAction::prioGlobal),
+ number5(map, "5", "5", eAction::prioGlobal),
+ number6(map, "6", "6", eAction::prioGlobal),
+ number7(map, "7", "7", eAction::prioGlobal),
+ number8(map, "8", "8", eAction::prioGlobal),
+ number9(map, "9", "9", eAction::prioGlobal),
+ red(map, "red", _("red"), eAction::prioGlobal),
+ green(map, "green", _("green"), eAction::prioGlobal),
+ yellow(map, "yellow", _("yellow"), eAction::prioGlobal),
+ blue(map, "blue", _("blue"), eAction::prioGlobal),
+ escape(map, "escape", _("escape"), eAction::prioGlobal)
+ {
+ }
+};
+
+extern eAutoInitP0<shortcutActions> i_shortcutActions;
+
+
+#endif
diff --git a/lib/gui/listbox.cpp b/lib/gui/listbox.cpp
new file mode 100644
index 00000000..823d8da1
--- /dev/null
+++ b/lib/gui/listbox.cpp
@@ -0,0 +1,894 @@
+#include <lib/gui/listbox.h>
+#include <lib/gdi/font.h>
+
+gFont eListBoxEntryText::font;
+gFont eListBoxEntryTextStream::font;
+
+eListBoxBase::eListBoxBase(eWidget* parent, const eWidget* descr, int takefocus, int item_height, const char *deco )
+: eDecoWidget(parent, takefocus, deco),
+ recalced(0), descr(descr),
+#ifndef DISABLE_LCD
+ tmpDescr(0),
+#endif
+ colorActiveB(eSkin::getActive()->queryScheme("global.selected.background")),
+ colorActiveF(eSkin::getActive()->queryScheme("global.selected.foreground")),
+ movemode(0), MaxEntries(0), flags(0), item_height(item_height),
+ columns(1), in_atomic(0), top(childs.end()), bottom(childs.end()), current(childs.end())
+{
+ childs.setAutoDelete(false); // machen wir selber
+ addActionMap(&i_cursorActions->map);
+ addActionMap(&i_listActions->map);
+}
+
+eListBoxBase::~eListBoxBase()
+{
+ while (childs.begin() != childs.end())
+ delete childs.front();
+}
+
+void eListBoxBase::setFlags(int _flags)
+{
+ flags |= _flags;
+}
+
+void eListBoxBase::removeFlags(int _flags)
+{
+ flags &= ~_flags;
+}
+
+void eListBoxBase::recalcMaxEntries()
+{
+ // MaxEntries is PER COLUMN
+ if (deco_selected && have_focus)
+ MaxEntries = crect_selected.height();
+ else if (deco)
+ MaxEntries = crect.height();
+ else
+ MaxEntries = height();
+ MaxEntries /= item_height;
+}
+
+eRect eListBoxBase::getEntryRect(int pos)
+{
+ int lme=MaxEntries;
+ // in case we show partial last lines (which only works in single-column),
+ // we increase MaxEntries by one since we don't want the last line
+ // one the next (invisible) column
+ if ( (columns == 1) && (flags & flagShowPartial))
+ ++lme;
+ if ( deco_selected && have_focus )
+ return eRect( ePoint( deco_selected.borderLeft + ( ( pos / lme) * ( crect_selected.width() / columns ) ) , deco_selected.borderTop + ( pos % lme) * item_height ), eSize( crect_selected.width() / columns , item_height ) );
+ else if (deco)
+ return eRect( ePoint( deco.borderLeft + ( ( pos / lme ) * ( crect.width() / columns ) ) , deco.borderTop + ( pos % lme) * item_height ), eSize( crect.width() / columns , item_height ) );
+ else if ( deco_selected )
+ return eRect( ePoint( deco_selected.borderLeft + ( ( pos / lme) * ( crect_selected.width() / columns ) ) , deco_selected.borderTop + ( pos % lme) * item_height ), eSize( crect_selected.width() / columns , item_height ) );
+ else
+ return eRect( ePoint( ( ( pos / lme ) * ( size.width() / columns ) ) , ( pos % lme) * item_height ), eSize( size.width() / columns , item_height ) );
+}
+
+void eListBoxBase::setColumns(int col)
+{
+ if (col)
+ columns=col;
+}
+
+int eListBoxBase::setProperty(const eString &prop, const eString &value)
+{
+ if (prop == "noPageMovement")
+ {
+ if (value == "off")
+ flags |= ~flagNoPageMovement;
+ else
+ flags |= flagNoPageMovement;
+ }
+ else if (prop == "noUpDownMovement")
+ {
+ if (value == "off")
+ flags |= ~flagNoUpDownMovement;
+ else
+ flags |= flagNoUpDownMovement;
+ }
+ else if (prop=="activeForegroundColor")
+ colorActiveF=eSkin::getActive()->queryScheme(value);
+ else if (prop=="activeBackgroundColor")
+ colorActiveB=eSkin::getActive()->queryScheme(value);
+ else if (prop=="showEntryHelp")
+ setFlags( flagShowEntryHelp );
+ else if (prop=="columns")
+ setColumns( value?atoi(value.c_str()):1 );
+ else
+ return eDecoWidget::setProperty(prop, value);
+
+ return 0;
+}
+
+void eListBoxBase::recalcClientRect()
+{
+ if (deco)
+ {
+ crect.setLeft( deco.borderLeft );
+ crect.setTop( deco.borderTop );
+ crect.setRight( width() - deco.borderRight );
+ crect.setBottom( height() - deco.borderBottom );
+ }
+ if (deco_selected)
+ {
+ crect_selected.setLeft( deco_selected.borderLeft );
+ crect_selected.setTop( deco_selected.borderTop );
+ crect_selected.setRight( width() - deco_selected.borderRight );
+ crect_selected.setBottom( height() - deco_selected.borderBottom );
+ }
+}
+
+int eListBoxBase::eventHandler(const eWidgetEvent &event)
+{
+ switch (event.type)
+ {
+ case eWidgetEvent::changedSize:
+ recalcClientRect();
+ recalcMaxEntries();
+ init();
+ break;
+ case eWidgetEvent::evtAction:
+ if ((event.action == &i_listActions->pageup) && !(flags & flagNoPageMovement))
+ moveSelection(dirPageUp);
+ else if ((event.action == &i_listActions->pagedown) && !(flags & flagNoPageMovement))
+ moveSelection(dirPageDown);
+ else if ((event.action == &i_cursorActions->up) && !(flags & flagNoUpDownMovement))
+ moveSelection(dirUp);
+ else if ((event.action == &i_cursorActions->down) && !(flags & flagNoUpDownMovement))
+ moveSelection(dirDown);
+ else if (event.action == &i_cursorActions->ok)
+ {
+ if ( current == childs.end() )
+ /*emit*/ SendSelected(0);
+ else
+ /*emit*/ SendSelected(*current);
+ }
+ else if (event.action == &i_cursorActions->cancel && MaxEntries > 1 )
+ /*emit*/ SendSelected(0);
+ else
+ break;
+ return 1;
+ default:
+ break;
+ }
+ return eWidget::eventHandler(event);
+}
+
+void eListBoxBase::invalidateContent()
+{
+ if ( have_focus && deco_selected )
+ invalidate( crect_selected );
+ else if ( deco )
+ invalidate( crect );
+ else
+ invalidate();
+}
+
+int eListBoxBase::newFocus()
+{
+ if (deco && deco_selected)
+ {
+ recalcMaxEntries();
+
+ if (isVisible())
+ invalidate();
+
+ return 1;
+ }
+ return 0;
+}
+
+int eListBoxBase::setCurrent(const eListBoxEntry *c, bool sendSelected )
+{
+/* if (childs.empty() || ((current != childs.end()) && (*current == c))) // no entries or current is equal the entry to search
+ return E_ALLREADY_SELECTED; // do nothing*/
+
+ if ( childs.empty() )
+ return E_COULDNT_FIND;
+
+ ePtrList<eListBoxEntry>::iterator item(childs.begin()), it(childs.begin());
+
+ for ( ; item != childs.end(); ++item)
+ if ( *item == c )
+ break;
+
+ if ( item == childs.end() ) // entry not in listbox... do nothing
+ return E_COULDNT_FIND;
+
+ int newCurPos=-1;
+ int oldCurPos=-1;
+ ePtrList<eListBoxEntry>::iterator oldCur(current);
+
+ int i = 0;
+
+ for (it=top; it != bottom; ++it, ++i) // check if entry to set between bottom and top
+ {
+ if (it == item)
+ {
+ newCurPos=i;
+ current = it;
+ }
+ if ( it == oldCur)
+ oldCurPos=i;
+ }
+
+ if (newCurPos != -1) // found on current screen, so redraw only old and new
+ {
+ if (isVisible())
+ {
+ if (in_atomic)
+ {
+ if (atomic_redraw == arNothing)
+ {
+ atomic_redraw = arCurrentOld;
+ atomic_old = oldCurPos;
+ }
+ if (atomic_redraw == arCurrentOld)
+ atomic_new = newCurPos;
+ } else
+ {
+ invalidateEntry(newCurPos);
+ if (oldCurPos != -1)
+ invalidateEntry(oldCurPos);
+ }
+ }
+ } else // the we start to search from begin
+ {
+ bottom = childs.begin();
+
+ while (newCurPos == -1 && MaxEntries ) // MaxEntries is already checked above...
+ {
+ if ( bottom != childs.end() )
+ top = bottom; // nächster Durchlauf
+
+ for ( i = 0; (i < (MaxEntries*columns) ) && (bottom != childs.end()); ++bottom, ++i)
+ {
+ if (bottom == item)
+ {
+ current = bottom; // we have found
+ ++newCurPos;
+ }
+ }
+ }
+ if (isVisible())
+ {
+ if (!in_atomic)
+ invalidateContent(); // Draw all
+ else
+ atomic_redraw=arAll;
+ }
+ }
+
+ if (!in_atomic)
+ {
+ /*emit*/ SendSelChanged(*current);
+ if ( sendSelected )
+ /*emit*/ SendSelected(*current);
+ }
+ else
+ {
+ atomic_selchanged=1;
+ if ( sendSelected )
+ atomic_selected=1;
+ }
+
+ return OK;
+}
+
+void eListBoxBase::append(eListBoxEntry* entry, bool holdCurrent, bool front)
+{
+ eListBoxEntry* cur = 0;
+ if (holdCurrent)
+ cur = current;
+
+ if ( front )
+ childs.push_front(entry);
+ else
+ childs.push_back(entry);
+ init();
+
+ if (cur)
+ setCurrent(cur);
+}
+
+void eListBoxBase::remove(eListBoxEntry* entry, bool holdCurrent)
+{
+ eListBoxEntry* cur = 0;
+
+ if (holdCurrent && current != entry)
+ cur = current;
+
+ childs.take(entry);
+ init();
+
+ if (cur)
+ setCurrent(cur);
+}
+
+void eListBoxBase::clearList()
+{
+ while (!childs.empty())
+ delete childs.first();
+ current = top = bottom = childs.end();
+ if (!in_atomic)
+ {
+ /*emit*/ SendSelChanged(0);
+ invalidateContent();
+ } else
+ {
+ atomic_selected=0;
+ atomic_selchanged=0;
+ atomic_redraw=arAll;
+ atomic_new=0;
+ atomic_old=0;
+ }
+}
+
+eListBoxEntry *eListBoxBase::goNext()
+{
+ moveSelection(dirDown);
+ return current!=childs.end() ? *current : 0;
+}
+
+eListBoxEntry* eListBoxBase::goPrev()
+{
+ moveSelection(dirUp);
+ return current!=childs.end() ? *current : 0;
+}
+
+void eListBoxBase::redrawWidget(gPainter *target, const eRect &where)
+{
+ eRect rc;
+
+ if (deco_selected && have_focus)
+ {
+ deco_selected.drawDecoration(target, ePoint(width(), height()));
+ rc = crect_selected;
+ }
+ else if (deco)
+ {
+ deco.drawDecoration(target, ePoint(width(), height()));
+ rc = crect;
+ }
+ else
+ rc = where;
+
+ int i=0;
+ for (ePtrList<eListBoxEntry>::iterator entry(top); ((flags & flagShowPartial) || (entry != bottom)) && (entry != childs.end()); ++entry)
+ {
+ eRect rect = getEntryRect(i);
+
+ eString s;
+
+ if ( rc.intersects(rect) )
+ {
+ target->clip(rect & rc);
+ if ( entry == current )
+ {
+#ifndef DISABLE_LCD
+ if ( LCDTmp ) // LCDTmp is only valid, when we have the focus
+ LCDTmp->setText( entry->redraw(target, rect, colorActiveB, colorActiveF, getBackgroundColor(), getForegroundColor(), 1 ) );
+ else if ( parent->LCDElement && have_focus )
+ parent->LCDElement->setText( entry->redraw(target, rect, colorActiveB, colorActiveF, getBackgroundColor(), getForegroundColor(), 1 ) );
+ else
+#endif
+ entry->redraw(target, rect, colorActiveB, colorActiveF, getBackgroundColor(), getForegroundColor(), ( have_focus ? 1 : ( MaxEntries > 1 ? 2 : 0 ) ) );
+ }
+ else
+ entry->redraw(target, rect, colorActiveB, colorActiveF, getBackgroundColor(), getForegroundColor(), 0 /*( have_focus ? 0 : ( MaxEntries > 1 ? 2 : 0 ) )*/ );
+ target->clippop();
+ }
+ // special case for "showPartial": as bottom is set to the
+ // last, half visible entry we want to redraw this, too.
+ if (flags & flagShowPartial)
+ if (entry == bottom)
+ break;
+
+ ++i;
+ }
+}
+
+void eListBoxBase::gotFocus()
+{
+#ifndef DISABLE_LCD
+ if (parent && parent->LCDElement) // detect if LCD Avail
+ if (descr)
+ {
+ parent->LCDElement->setText("");
+ LCDTmp = new eLabel(parent->LCDElement);
+ LCDTmp->hide();
+ eSize s = parent->LCDElement->getSize();
+ LCDTmp->move(ePoint(0,s.height()/2));
+ LCDTmp->resize(eSize(s.width(), s.height()/2));
+ LCDTmp->show();
+ 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();
+ }
+#endif
+ ++have_focus;
+
+ if (!childs.empty())
+ {
+ if ( newFocus() ) // recalced ?
+ {
+ ePtrList<eListBoxEntry>::iterator it = current;
+ init();
+ setCurrent(it);
+ }
+ else if ( isVisible() )
+ {
+ int i=0;
+ for (ePtrList<eListBoxEntry>::iterator entry(top); entry != bottom; ++i, ++entry)
+ if (entry == current)
+ invalidateEntry(i);
+ }
+ }
+ if (flags & flagShowEntryHelp)
+ setHelpText( current != childs.end() ? current->getHelpText(): eString(" ")); // eString(_("no description available")));
+}
+
+void eListBoxBase::lostFocus()
+{
+#ifndef DISABLE_LCD
+ if ( descr )
+ {
+ delete LCDTmp;
+ LCDTmp=0;
+ delete tmpDescr;
+ tmpDescr=0;
+ }
+#endif
+ --have_focus;
+
+ if (!childs.empty())
+ if ( newFocus() ) //recalced ?
+ {
+ ePtrList<eListBoxEntry>::iterator it = current;
+ init();
+ setCurrent(it);
+ }
+ else if ( isVisible() )
+ {
+ int i = 0;
+ for (ePtrList<eListBoxEntry>::iterator entry(top); entry != bottom; ++i, ++entry)
+ if (entry == current)
+ invalidateEntry(i);
+ }
+#ifndef DISABLE_LCD
+ if (parent && parent->LCDElement)
+ parent->LCDElement->setText("");
+#endif
+}
+
+void eListBoxBase::init()
+{
+ current = top = bottom = childs.begin();
+ for (int i = 0; i < (MaxEntries*columns); ++i, ++bottom)
+ if (bottom == childs.end() )
+ break;
+ if (!in_atomic)
+ {
+ invalidateContent();
+ }
+ else
+ {
+ atomic_redraw=arAll;
+ }
+}
+
+int eListBoxBase::moveSelection(int dir, bool sendSelected)
+{
+ int direction=0, forceredraw=0;
+
+ if (childs.empty())
+ return 0;
+
+ ePtrList<eListBoxEntry>::iterator oldptr=current, oldtop=top;
+
+ switch (dir)
+ {
+ case dirPageDown:
+ direction=+1;
+ for (int i = 0; i < MaxEntries; ++i)
+ {
+ if (++current == bottom) // unten (rechts) angekommen? page down
+ {
+ if (bottom == childs.end()) // einzige ausnahme: unten (rechts) angekommen
+ {
+ --current;
+ break;
+ }
+ for (int i = 0; i < MaxEntries * columns; ++i)
+ {
+ if (bottom != childs.end())
+ {
+ ++bottom;
+ ++top;
+ }
+ }
+ }
+ }
+ break;
+
+ case dirPageUp:
+ direction=-1;
+ for (int i = 0; i < MaxEntries; ++i)
+ {
+ if (current == childs.begin())
+ break;
+
+ if (current-- == top/* && current != childs.begin()*/ ) // oben (links) angekommen? page up
+ {
+ for (int i = 0; i < MaxEntries * columns; ++i)
+ {
+ if (--top == childs.begin()) // einzige ausnahme: oben (links) angekommen
+ break;
+ }
+
+ // und einmal bottom neuberechnen :)
+ bottom=top;
+ for (int i = 0; i < MaxEntries*columns; ++i)
+ if (bottom != childs.end())
+ ++bottom;
+ }
+ }
+ break;
+
+ case dirUp:
+ if ( current == childs.begin() ) // wrap around?
+ {
+ direction=+1;
+ current = childs.end(); // select last
+ --current;
+ top = bottom = childs.end();
+ for (int i = 0; i < MaxEntries*columns; ++i, --top)
+ if (top == childs.begin())
+ break;
+ } else
+ {
+ direction=-1;
+ if (current-- == top) // new top must set
+ {
+ for (int i = 0; i < MaxEntries*columns; ++i, --top)
+ if (top == childs.begin())
+ break;
+ bottom=top;
+ for (int i = 0; i < MaxEntries*columns; ++i, ++bottom)
+ if (bottom == childs.end())
+ break;
+ }
+ }
+ break;
+
+ case dirDown:
+ if ( current == --ePtrList<eListBoxEntry>::iterator(childs.end()) ) // wrap around?
+ {
+ direction=-1;
+ top = current = bottom = childs.begin(); // goto first
+ for (int i = 0; i < MaxEntries * columns; ++i, ++bottom)
+ if ( bottom == childs.end() )
+ break;
+ }
+ else
+ {
+ direction=+1;
+ if (++current == bottom) // ++current ??
+ {
+ for (int i = 0; i<MaxEntries * columns; ++i)
+ {
+ if (bottom != childs.end() )
+ ++bottom;
+ if (top != childs.end() )
+ ++top;
+ }
+ }
+ }
+ break;
+ case dirFirst:
+ direction=-1;
+ top = current = bottom = childs.begin(); // goto first;
+ for (int i = 0; i < MaxEntries * columns; ++i, ++bottom)
+ if ( bottom == childs.end() )
+ break;
+ break;
+ case dirLast:
+ direction=1;
+ top=bottom=current=childs.end();
+ if (current == childs.begin())
+ break; // empty.
+
+ for (int i = 0; i < MaxEntries * columns; ++i)
+ if (top != childs.begin())
+ --top;
+ --current;
+ break;
+ default:
+ return 0;
+ }
+
+ if (current != oldptr) // current has changed
+ {
+ if (movemode)
+ {
+ // feel free to rewrite using stl::copy[_backward], but i didn't succeed.
+ std::list<eListBoxEntry*>::iterator o=oldptr,
+ c=current,
+ curi=current,
+ oldi=oldptr;
+ int count=0;
+
+ eListBoxEntry* old=*o;
+
+ if (direction > 0)
+ {
+ ++o;
+ ++c;
+ while (o != c)
+ {
+ *oldi++=*o++;
+ ++count;
+ }
+ } else
+ {
+ while (o != curi)
+ {
+ *oldi--=*--o;
+ ++count;
+ }
+ }
+
+ if (count > 1)
+ forceredraw=1;
+
+ *curi=old;
+ }
+ }
+
+ if (!in_atomic)
+ {
+ /*emit*/ SendSelChanged(*current);
+ if ( sendSelected )
+ /*emit*/ SendSelected(*current);
+ }
+ else
+ {
+ atomic_selchanged=1;
+ if ( sendSelected )
+ atomic_selected=1;
+ }
+
+ if (flags & flagShowEntryHelp)
+ setHelpText( current != childs.end() ? current->getHelpText():eString(_("no description available")));
+
+ if (isVisible())
+ {
+ if ((oldtop != top) || forceredraw)
+ {
+ if (in_atomic)
+ atomic_redraw=arAll;
+ else
+ invalidateContent();
+ } else if ( current != oldptr)
+ {
+ int i=0;
+ int old=-1, cur=-1;
+
+ for (ePtrList<eListBoxEntry>::iterator entry(top); entry != bottom; ++i, ++entry)
+ if ( entry == oldptr)
+ old=i;
+ else if ( entry == current )
+ cur=i;
+
+ if (in_atomic)
+ {
+ if (atomic_redraw == arNothing)
+ {
+ atomic_old=old;
+ atomic_redraw = arCurrentOld;
+ }
+ if (atomic_redraw == arCurrentOld)
+ atomic_new=cur;
+ } else
+ {
+ if (old != -1)
+ invalidateEntry(old);
+ if (cur != -1)
+ invalidateEntry(cur);
+ }
+ }
+ }
+ return 1;
+}
+
+void eListBoxBase::setActiveColor(gColor back, gColor front)
+{
+ colorActiveB=back;
+ colorActiveF=front;
+
+ if (current != childs.end())
+ {
+ int i = 0;
+ for (ePtrList<eListBoxEntry>::iterator it(top); it != bottom; ++i, ++it)
+ {
+ if (it == current)
+ {
+ invalidateEntry(i);
+ break;
+ }
+ }
+ }
+}
+
+void eListBoxBase::beginAtomic()
+{
+ if (!in_atomic++)
+ {
+ atomic_redraw=arNothing;
+ atomic_selchanged=0;
+ atomic_selected=0;
+ atomic_new=-1;
+ }
+}
+
+void eListBoxBase::endAtomic()
+{
+ if (!--in_atomic)
+ {
+ if (atomic_redraw == arAll)
+ invalidateContent();
+ else if (atomic_redraw == arCurrentOld)
+ {
+ if (atomic_new != -1)
+ invalidateEntry(atomic_new);
+ if (atomic_old != -1)
+ invalidateEntry(atomic_old);
+ }
+ if (atomic_selchanged)
+ if (childs.empty())
+ /*emit*/ SendSelChanged(0);
+ else
+ /*emit*/ SendSelChanged(*current);
+
+ if (atomic_selected)
+ if (childs.empty())
+ /*emit*/ SendSelected(0);
+ else
+ /*emit*/ SendSelected(*current);
+ }
+}
+
+void eListBoxBase::sort()
+{
+ eListBoxEntry* cur = current;
+ childs.sort();
+
+ init();
+
+ if (cur)
+ setCurrent(cur);
+}
+
+void eListBoxEntry::drawEntryBorder(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF )
+{
+ rc->setForegroundColor(coActiveB);
+ rc->line( ePoint(rect.left(), rect.bottom()-1), ePoint(rect.right()-1, rect.bottom()-1) );
+ rc->line( ePoint(rect.left(), rect.top()), ePoint(rect.right()-1, rect.top()) );
+ rc->line( ePoint(rect.left(), rect.top()), ePoint(rect.left(), rect.bottom()-1) );
+ rc->line( ePoint(rect.right()-1, rect.top()), ePoint(rect.right()-1, rect.bottom()-1) );
+ rc->line( ePoint(rect.left()+1, rect.bottom()-2), ePoint(rect.right()-2, rect.bottom()-2) );
+ rc->line( ePoint(rect.left()+1, rect.top()+1), ePoint(rect.right()-2, rect.top()+1) );
+ rc->line( ePoint(rect.left()+1, rect.top()+2), ePoint(rect.left()+1, rect.bottom()-3) );
+ rc->line( ePoint(rect.right()-2, rect.top()+2), ePoint(rect.right()-2, rect.bottom()-3) );
+ rc->line( ePoint(rect.left()+2, rect.bottom()-3), ePoint(rect.right()-3, rect.bottom()-3) );
+ rc->line( ePoint(rect.left()+2, rect.top()+2), ePoint(rect.right()-3, rect.top()+2) );
+ rc->line( ePoint(rect.left()+2, rect.top()+3), ePoint(rect.left()+2, rect.bottom()-4) );
+ rc->line( ePoint(rect.right()-3, rect.top()+3), ePoint(rect.right()-3, rect.bottom()-4) );
+}
+
+void eListBoxEntry::drawEntryRect(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF, int state )
+{
+ if ( (coNormalB != -1 && !state) || (state && coActiveB != -1) )
+ {
+ rc->setForegroundColor(state?coActiveB:coNormalB);
+ rc->fill(rect);
+ rc->setBackgroundColor(state?coActiveB:coNormalB);
+ }
+ else
+ {
+ eWidget *w=listbox->getNonTransparentBackground();
+ rc->setForegroundColor(w->getBackgroundColor());
+ rc->fill(rect);
+ rc->setBackgroundColor(w->getBackgroundColor());
+ }
+ rc->setForegroundColor(state?coActiveF:coNormalF);
+}
+
+eListBoxEntryText::~eListBoxEntryText()
+{
+ if (para)
+ {
+ para->destroy();
+ para = 0;
+ }
+}
+
+int eListBoxEntryText::getEntryHeight()
+{
+ if ( !font.pointSize)
+ font = eSkin::getActive()->queryFont("eListBox.EntryText.normal");
+
+ return calcFontHeight( font ) + 4;
+}
+
+int eListBoxEntryTextStream::getEntryHeight()
+{
+ if ( !font.pointSize)
+ font = eSkin::getActive()->queryFont("eListBox.EntryText.normal");
+
+ return calcFontHeight( font ) + 4;
+}
+
+int calcFontHeight( const gFont& font)
+{
+ eTextPara *test;
+ test = new eTextPara( eRect(0,0,100,50) );
+ test->setFont( font );
+ test->renderString("Mjdyl");
+ int i = test->getBoundBox().height();
+ test->destroy();
+ return i;
+}
+
+const eString& eListBoxEntryText::redraw(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF, int state)
+{
+ bool b;
+
+ if ( (b = (state == 2)) )
+ state = 0;
+
+ drawEntryRect( rc, rect, coActiveB, coActiveF, coNormalB, coNormalF, state );
+
+ if (!para)
+ {
+ para = new eTextPara( eRect( 0, 0, rect.width(), rect.height() ) );
+ para->setFont( font );
+ para->renderString(text);
+ para->realign(align);
+// yOffs = ((rect.height() - para->getBoundBox().height()) / 2 + 0) - para->getBoundBox().top() ;
+ yOffs=0;
+ }
+ rc->renderPara(*para, ePoint( rect.left(), rect.top()+yOffs ) );
+
+ if (b)
+ drawEntryBorder( rc, rect, coActiveB, coActiveF, coNormalB, coNormalF );
+
+ return text;
+}
+
+const eString &eListBoxEntryTextStream::redraw(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF, int state)
+{
+ rc->setFont( font );
+
+ drawEntryRect( rc, rect, coActiveB, coActiveF, coNormalB, coNormalF, state );
+
+ rc->setForegroundColor(state?coActiveF:coNormalF);
+ rc->renderText(rect, text.str());
+
+ static eString ret;
+ return ret = text.str();
+}
+
+void eListBoxEntryText::SetText(const eString& txt)
+{
+ if(para){
+ para->destroy();
+ para=0;
+ };
+ text=txt;
+}
diff --git a/lib/gui/listbox.h b/lib/gui/listbox.h
new file mode 100644
index 00000000..b4461b20
--- /dev/null
+++ b/lib/gui/listbox.h
@@ -0,0 +1,278 @@
+#ifndef __listbox_h
+#define __listbox_h
+
+#include <sstream>
+
+#include <lib/driver/rc.h>
+#include <lib/gdi/grc.h>
+#include <lib/gdi/fb.h>
+#include <lib/gui/ewidget.h>
+#include <lib/gui/eskin.h>
+#include <lib/gui/ewindow.h>
+#include <lib/gui/guiactions.h>
+#include <lib/gui/statusbar.h>
+
+int calcFontHeight( const gFont& font );
+
+class eListBoxEntry;
+
+class eListBoxBase: public eDecoWidget
+{
+ int recalced;
+ const eWidget* descr;
+#ifndef DISABLE_LCD
+ eLabel* tmpDescr; // used for description Label in LCD
+#endif
+ gColor colorActiveB, colorActiveF;
+ eRect crect, crect_selected;
+ enum { arNothing, arCurrentOld, arAll};
+ int movemode, MaxEntries, flags, item_height, columns, in_atomic, atomic_redraw, atomic_old, atomic_new;
+ bool atomic_selchanged;
+ bool atomic_selected;
+protected:
+ ePtrList<eListBoxEntry>::iterator top, bottom, current;
+ eListBoxBase(eWidget* parent, const eWidget* descr=0, int takefocus=1, int item_height=0, const char *deco="eListBox" );
+ ePtrList<eListBoxEntry> childs;
+ eListBoxEntry* getCurrent() { return current != childs.end() ? *current : 0; }
+ eListBoxEntry* getNext() { ePtrList<eListBoxEntry>::iterator c=current; ++c; return c != childs.end() ? *c : 0; }
+ eListBoxEntry* goNext();
+ eListBoxEntry* goPrev();
+ int setProperty(const eString &prop, const eString &value);
+private:
+ eRect getEntryRect(int n);
+ int eventHandler(const eWidgetEvent &event);
+ void eraseBackground() {};
+ void recalcMaxEntries();
+ void recalcClientRect();
+ int newFocus();
+ void redrawWidget(gPainter *target, const eRect &area);
+ void lostFocus();
+ void gotFocus();
+ void init();
+ virtual void SendSelected( eListBoxEntry* entry )=0;
+ virtual void SendSelChanged( eListBoxEntry* entry )=0;
+public:
+ ~eListBoxBase();
+ enum { dirPageDown, dirPageUp, dirDown, dirUp, dirFirst, dirLast };
+ enum { flagNoUpDownMovement=1, flagNoPageMovement=2, flagShowEntryHelp=4, flagShowPartial=8 };
+ enum { OK = 0, ERROR=1, E_ALLREADY_SELECTED = 2, E_COULDNT_FIND = 4, E_INVALID_ENTRY = 8, E_NOT_VISIBLE = 16 };
+ void setFlags(int);
+ void removeFlags(int);
+ void invalidateEntry(int n){ invalidate(getEntryRect(n));}
+ void invalidateContent();
+ void setColumns(int col);
+ int getColumns() { return columns; }
+ void setMoveMode(int move) { movemode=move; }
+ void append(eListBoxEntry* e, bool holdCurrent=false, bool front=false);
+ void remove(eListBoxEntry* e, bool holdCurrent=false);
+ void clearList();
+ int getCount() { return childs.size(); }
+ int setCurrent(const eListBoxEntry *c, bool sendSelected=false);
+ void sort();
+ int moveSelection(int dir, bool sendSelected=false);
+ void setActiveColor(gColor back, gColor front);
+ void beginAtomic();
+ void endAtomic();
+ void FakeFocus( int i ) { have_focus=i; }
+ void invalidateCurrent()
+ {
+ int n=0;
+ for (ePtrList<eListBoxEntry>::iterator i(top); i != bottom; ++i, ++n)
+ if ( i == current )
+ invalidate(getEntryRect(n));
+ }
+};
+
+template <class T>
+class eListBox: public eListBoxBase
+{
+ void SendSelected( eListBoxEntry* entry )
+ {
+ /*emit*/ selected((T*)entry);
+ }
+ void SendSelChanged( eListBoxEntry* entry )
+ {
+ /*emit*/ selchanged((T*)entry);
+ }
+public:
+ Signal1<void, T*> selected;
+ Signal1<void, T*> selchanged;
+ eListBox(eWidget *parent, const eWidget* descr=0, int takefocus=1 )
+ :eListBoxBase( parent, descr, takefocus, T::getEntryHeight() )
+ {
+ }
+ T* getCurrent() { return (T*)eListBoxBase::getCurrent(); }
+ T* getNext() { return (T*)eListBoxBase::getNext(); }
+ T* goNext() { return (T*)eListBoxBase::goNext(); }
+ T* goPrev() { return (T*)eListBoxBase::goPrev(); }
+
+ template <class Z>
+ int forEachEntry(Z ob)
+ {
+ for (ePtrList<eListBoxEntry>::iterator i(childs.begin()); i!=childs.end(); ++i)
+ if ( ob((T&)(**i)) )
+ return OK;
+
+ return ERROR;
+ }
+
+ template <class Z>
+ int forEachVisibleEntry(Z ob)
+ {
+ if (!isVisible())
+ return E_NOT_VISIBLE;
+
+ for (ePtrList<eListBoxEntry>::iterator i(top); i!=bottom; ++i)
+ if ( ob((T&)(**i)) )
+ return OK;
+
+ return ERROR;
+ }
+};
+
+class eListBoxEntry: public Object
+{
+ friend class eListBox<eListBoxEntry>;
+protected:
+ eListBox<eListBoxEntry>* listbox;
+ eString helptext;
+public:
+ eListBoxEntry(eListBox<eListBoxEntry>* parent, eString hlptxt=0)
+ :listbox(parent), helptext(hlptxt?hlptxt:eString(" "))
+ {
+ if (listbox)
+ listbox->append(this);
+ }
+ virtual ~eListBoxEntry()
+ {
+ if (listbox)
+ listbox->remove(this);
+ }
+ virtual bool operator < ( const eListBoxEntry& e)const
+ {
+ return false;
+ }
+ virtual const eString& redraw(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF, int state )=0;
+ void drawEntryRect(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF, int state);
+ void drawEntryBorder(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF);
+ const eString &getHelpText() const { return helptext; }
+};
+
+class eListBoxEntryText: public eListBoxEntry
+{
+ friend class eListBox<eListBoxEntryText>;
+protected:
+ eString text;
+ void *key;
+ int align;
+ eTextPara *para;
+ int yOffs;
+ static gFont font;
+ int keytype;
+public:
+ enum { value, ptr };
+ static int getEntryHeight();
+
+ eListBoxEntryText(eListBox<eListBoxEntryText>* lb, const char* txt=0, void *key=0, int align=0, const eString &hlptxt="", int keytype = value )
+ :eListBoxEntry( (eListBox<eListBoxEntry>*)lb, hlptxt ), text(txt),
+ key(key), align(align), para(0), keytype(keytype)
+ {
+ }
+
+ eListBoxEntryText(eListBox<eListBoxEntryText>* lb, const eString& txt, void* key=0, int align=0, const eString &hlptxt="", int keytype = value )
+ :eListBoxEntry( (eListBox<eListBoxEntry>*)lb, hlptxt ), text(txt),
+ key(key), align(align), para(0), keytype(keytype)
+ {
+ }
+
+ ~eListBoxEntryText();
+
+ bool operator < ( const eListBoxEntry& e) const
+ {
+ if (key == ((eListBoxEntryText&)e).key || keytype == ptr)
+ return text < ((eListBoxEntryText&)e).text;
+ else
+ return key < ((eListBoxEntryText&)e).key;
+ }
+
+ void *& getKey() { return key; }
+ const void* getKey() const { return key; }
+ const eString& getText() { return text; }
+ void SetText(const eString& txt); // not setText !!!
+protected:
+ const eString& redraw(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF, int state );
+};
+
+class eListBoxEntryTextStream: public eListBoxEntry
+{
+ friend class eListBox<eListBoxEntryTextStream>;
+protected:
+ std::stringstream text;
+ static gFont font;
+public:
+ static int getEntryHeight();
+
+ eListBoxEntryTextStream(eListBox<eListBoxEntryTextStream>* lb)
+ :eListBoxEntry((eListBox<eListBoxEntry>*)lb)
+ {
+ }
+
+ bool operator < ( const eListBoxEntryTextStream& e) const
+ {
+ return text.str() < e.text.str();
+ }
+
+protected:
+ const eString &redraw(gPainter *rc, const eRect& rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF, int state );
+};
+
+class eListBoxEntryMenu: public eListBoxEntryText
+{
+ friend class eListBox<eListBoxEntryMenu>;
+public:
+ Signal0<void> selected;
+
+ eListBoxEntryMenu(eListBox<eListBoxEntryMenu>* lb, const char* txt, const eString &hlptxt="", int align=0 )
+ :eListBoxEntryText((eListBox<eListBoxEntryText>*)lb, txt, 0, align, hlptxt)
+ {
+ if (listbox)
+ CONNECT(listbox->selected, eListBoxEntryMenu::LBSelected);
+ }
+ void LBSelected(eListBoxEntry* t)
+ {
+ if (t == this)
+ /* emit */ selected();
+ }
+};
+
+template <class T>
+class eListBoxWindow: public eWindow
+{
+public:
+ int Entrys;
+ int width;
+ eListBox<T> list;
+ eStatusBar *statusbar;
+ eListBoxWindow(eString Title="", int Entrys=0, int width=400, bool sbar=0);
+};
+
+template <class T>
+inline eListBoxWindow<T>::eListBoxWindow(eString Title, int Entrys, int width, bool sbar)
+ : eWindow(0), Entrys(Entrys), width(width), list(this), statusbar(sbar?new eStatusBar(this):0)
+{
+ list.setFlags( eListBoxBase::flagShowEntryHelp );
+ setText(Title);
+ cresize( eSize(width, (sbar?40:10)+Entrys*T::getEntryHeight() ) );
+ list.move(ePoint(10, 5));
+ list.resize(eSize(getClientSize().width()-20, getClientSize().height()-(sbar?35:5) ));
+ if (sbar)
+ {
+ statusbar->setFlags(eStatusBar::flagVCenter);
+ statusbar->move( ePoint(0, getClientSize().height()-30) );
+ statusbar->resize( eSize( getClientSize().width(), 30) );
+ statusbar->loadDeco();
+ statusbar->show();
+ }
+}
+
+#endif
diff --git a/lib/gui/multipage.cpp b/lib/gui/multipage.cpp
new file mode 100644
index 00000000..e494078d
--- /dev/null
+++ b/lib/gui/multipage.cpp
@@ -0,0 +1,64 @@
+#include <errno.h>
+#include <lib/gui/multipage.h>
+#include <lib/gui/ewidget.h>
+
+eMultipage::eMultipage()
+{
+}
+
+int eMultipage::prev()
+{
+ if (list.current() == list.begin())
+ return -ENOENT;
+ if (list.current() != list.end())
+ list.current()->hide();
+ list.prev();
+ list.current()->show();
+ return 0;
+}
+
+int eMultipage::next()
+{
+ if (list.current() == *--list.end())
+ return -ENOENT;
+ list.current()->hide();
+ list.next();
+ if (list.current() == list.end())
+ return 0;
+ list.current()->show();
+ return 0;
+}
+
+void eMultipage::set(eWidget *widget)
+{
+ if (list.current() == widget)
+ return;
+ if (list.current() != list.end())
+ list.current()->hide();
+ list.setCurrent(widget);
+ if (list.current() != list.end())
+ list.current()->show();
+}
+
+void eMultipage::first()
+{
+ if (list.current() == list.begin())
+ return;
+ if (list.current() != list.end())
+ list.current()->hide();
+ list.first();
+ if (list.current() != list.end())
+ list.current()->show();
+}
+
+int eMultipage::at()
+{
+ int num=0;
+ for (ePtrList<eWidget>::iterator i(list.begin()); (i != list.end()) && (i != list.current()); ++i, ++num) ;
+ return num;
+}
+
+void eMultipage::addPage(eWidget *page)
+{
+ list.push_back(page);
+}
diff --git a/lib/gui/multipage.h b/lib/gui/multipage.h
new file mode 100644
index 00000000..5c3cb4ed
--- /dev/null
+++ b/lib/gui/multipage.h
@@ -0,0 +1,24 @@
+#ifndef __multipage_h_
+#define __multipage_h_
+
+#include <lib/base/eptrlist.h>
+class eWidget;
+
+class eMultipage
+{
+ ePtrList<eWidget> list;
+public:
+ eMultipage();
+
+ int prev();
+ int next();
+ void set(eWidget *page);
+ void first();
+ void addPage(eWidget *page);
+ eWidget *getCurrent() { return list.current(); }
+
+ int count() { return list.size(); }
+ int at();
+};
+
+#endif
diff --git a/lib/gui/numberactions.cpp b/lib/gui/numberactions.cpp
new file mode 100644
index 00000000..3503283d
--- /dev/null
+++ b/lib/gui/numberactions.cpp
@@ -0,0 +1,5 @@
+#include <lib/gui/numberactions.h>
+#include <lib/base/init_num.h>
+
+eAutoInitP0<numberActions> i_numberActions(eAutoInitNumbers::actions, "number actions");
+
diff --git a/lib/gui/numberactions.h b/lib/gui/numberactions.h
new file mode 100644
index 00000000..d12a620b
--- /dev/null
+++ b/lib/gui/numberactions.h
@@ -0,0 +1,31 @@
+#ifndef __CORE_GUI_NUMBERACTIONS__
+#define __CORE_GUI_NUMBERACTIONS__
+
+#include <lib/gui/actions.h>
+#include <lib/base/i18n.h>
+#include <lib/base/init.h>
+
+struct numberActions
+{
+ eActionMap map;
+ eAction key0, key1, key2, key3, key4, key5, key6, key7, key8, key9, keyExt1, keyExt2;
+ numberActions():
+ map("numbers", _("number actions")),
+ key0(map, "0", _("key 0"), eAction::prioDialog),
+ key1(map, "1", _("key 1"), eAction::prioDialog),
+ key2(map, "2", _("key 2"), eAction::prioDialog),
+ key3(map, "3", _("key 3"), eAction::prioDialog),
+ key4(map, "4", _("key 4"), eAction::prioDialog),
+ key5(map, "5", _("key 5"), eAction::prioDialog),
+ key6(map, "6", _("key 6"), eAction::prioDialog),
+ key7(map, "7", _("key 7"), eAction::prioDialog),
+ key8(map, "8", _("key 8"), eAction::prioDialog),
+ key9(map, "9", _("key 9"), eAction::prioDialog),
+ keyExt1(map, "ext1", _("extended key1"), eAction::prioDialog),
+ keyExt2(map, "ext2", _("extended key2"), eAction::prioDialog)
+ {
+ }
+};
+extern eAutoInitP0<numberActions> i_numberActions;
+#endif
+
diff --git a/lib/gui/slider.cpp b/lib/gui/slider.cpp
new file mode 100644
index 00000000..dc4b9d72
--- /dev/null
+++ b/lib/gui/slider.cpp
@@ -0,0 +1,188 @@
+#include <lib/gui/slider.h>
+
+#include <lib/gui/eskin.h>
+#include <lib/gui/elabel.h>
+#include <lib/gui/guiactions.h>
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+
+inline void swap( gColor& a, gColor& b )
+{
+ gColor tmp = a;
+ a = b;
+ b = tmp;
+}
+
+eSlider::eSlider( eWidget* parent, const eWidget *descr, int min, int max )
+ :eProgress( parent, 1), descr(descr)
+{
+ activated_left = eSkin::getActive()->queryScheme( "eSlider.activated.left" );
+ activated_right = eSkin::getActive()->queryScheme( "eSlider.activated.right" );
+ setMin(min);
+ setMax(max);
+ incrementation = 4; // in Percent
+ addActionMap(&i_cursorActions->map);
+}
+
+void eSlider::setMin( int i )
+{
+ min = i;
+}
+
+void eSlider::setMax( int i )
+{
+ max = (i <= min) ? 99 : i;
+}
+
+void eSlider::setValue( int i )
+{
+ if ( i >= min && i <= max )
+ setPerc( (int) round( i * (double)100/((max-min)+1) ) );
+ else
+ setPerc( 0 );
+}
+
+int eSlider::getValue()
+{
+ int ret = (int) ( (double) perc / 100 * ( (max-min)+1));
+ return (ret > max ? max : ret);
+}
+
+void eSlider::setIncrement( int i )
+{
+ if (!i)
+ incrementation = 4;
+ else
+ incrementation = i;
+}
+
+int eSlider::setProperty( const eString &prop, const eString &val)
+{
+ if (prop == "leftColorActive")
+ activated_left=eSkin::getActive()->queryColor( prop );
+ else if (prop == "rightColorActive")
+ activated_right=eSkin::getActive()->queryColor( prop );
+ else if (prop == "incrementation")
+ setIncrement( atoi( val.c_str() ) );
+ else if (prop == "min")
+ setMin( atoi(val.c_str()) );
+ else if (prop == "max")
+ setMax( atoi(val.c_str()) );
+ else
+ return eProgress::setProperty( prop, val );
+ return 0;
+}
+
+void eSlider::gotFocus()
+{
+ have_focus++;
+ swap( left, activated_left );
+ swap( right, activated_right );
+
+#ifndef DISABLE_LCD
+ if (parent && parent->LCDElement) // detect if LCD Avail
+ {
+ LCDTmp = new eProgress( parent->LCDElement );
+ LCDTmp->hide();
+ LCDTmp->setForegroundColor( 255 );
+ ((eSlider*)LCDTmp)->left=255;
+ ((eSlider*)LCDTmp)->right=0;
+ ((eProgress*)LCDTmp)->setPerc( perc );
+ eSize s = parent->LCDElement->getSize();
+
+ if (descr)
+ {
+ LCDTmp->move(ePoint(0, s.height()/2 + s.height()/4 - 6 ));
+ LCDTmp->resize( eSize(s.width(), 12) );
+ 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( eSize(s.width(), 8) );
+ LCDTmp->move(ePoint(0, s.height() / 2 - 6));
+ }
+ ((eProgress*)LCDTmp)->setPerc( perc );
+ LCDTmp->show();
+ }
+#endif // DISABLE_LCD
+ redraw();
+}
+
+void eSlider::lostFocus()
+{
+// swap back;
+ swap( left, activated_left );
+ swap( right, activated_right );
+
+#ifndef DISABLE_LCD
+ if (LCDTmp)
+ {
+ delete LCDTmp;
+ LCDTmp=0;
+ if (tmpDescr)
+ {
+ delete tmpDescr;
+ tmpDescr=0;
+ }
+ }
+#endif
+ have_focus--;
+ invalidate();
+}
+
+int eSlider::eventHandler( const eWidgetEvent& event )
+{
+ switch (event.type)
+ {
+ case eWidgetEvent::evtAction:
+ {
+ if(event.action == &i_cursorActions->right)
+ {
+ if ( (perc += incrementation) > 100 )
+ perc = 100;
+ }
+ else if(event.action == &i_cursorActions->left)
+ {
+ if ( (perc-=incrementation) < 0 )
+ perc = 0;
+ }
+ else
+ break;
+ redraw();
+ /* emit */ changed( getValue() );
+#ifndef DISABLE_LCD
+ if (LCDTmp)
+ ((eProgress*)LCDTmp)->setPerc( perc );
+#endif
+ return 1;
+ }
+ default:
+ break;
+ }
+ return eProgress::eventHandler( event );
+}
+
+static eWidget *create_eSlider(eWidget *parent)
+{
+ return new eSlider(parent);
+}
+
+class eSliderSkinInit
+{
+public:
+ eSliderSkinInit()
+ {
+ eSkin::addWidgetCreator("eSlider", create_eSlider);
+ }
+ ~eSliderSkinInit()
+ {
+ eSkin::removeWidgetCreator("eSlider", create_eSlider);
+ }
+};
+
+eAutoInitP0<eSliderSkinInit> init_eSliderSkinInit(eAutoInitNumbers::guiobject, "eSlider");
diff --git a/lib/gui/slider.h b/lib/gui/slider.h
new file mode 100644
index 00000000..81deee7c
--- /dev/null
+++ b/lib/gui/slider.h
@@ -0,0 +1,27 @@
+#ifndef __SRC_CORE_GUI_SLIDER_
+#define __SRC_CORE_GUI_SLIDER_
+
+#include <lib/gui/eprogress.h>
+
+class eSlider: public eProgress
+{
+ int incrementation, max, min;
+ gColor activated_left, activated_right;
+ const eWidget *descr;
+ int setProperty( const eString &prop, const eString &val);
+ void gotFocus();
+ void lostFocus();
+ int eventHandler( const eWidgetEvent& event );
+ eWidget *tmpDescr;
+ void update();
+public:
+ void setMin( int i );
+ void setMax( int i );
+ void setIncrement( int i );
+ void setValue( int i );
+ int getValue();
+ Signal1<void, int> changed;
+ eSlider( eWidget *parent, const eWidget *descr=0, int min=0, int max=99 );
+};
+
+#endif // __SRC_CORE_GUI_SLIDER_
diff --git a/lib/gui/statusbar.cpp b/lib/gui/statusbar.cpp
new file mode 100644
index 00000000..797c0a3b
--- /dev/null
+++ b/lib/gui/statusbar.cpp
@@ -0,0 +1,83 @@
+#include <lib/gui/statusbar.h>
+
+#include <lib/base/init.h>
+#include <lib/base/init_num.h>
+#include <lib/gui/eskin.h>
+#include <lib/gdi/font.h>
+
+eStatusBar::eStatusBar( eWidget* parent, const char *deco)
+ :eLabel(parent, 0, 0, deco), current(0)
+{
+ setFont( eSkin::getActive()->queryFont("eStatusBar") );
+ setForegroundColor ( eSkin::getActive()->queryColor("eStatusBar.foreground") );
+ setBackgroundColor ( eSkin::getActive()->queryColor("eStatusBar.background") );
+ eLabel::setFlags( RS_FADE );
+ initialize();
+}
+
+
+void eStatusBar::initialize()
+{
+ if ( parent )
+ {
+ if ( flags & flagOwnerDraw )
+ {
+ if ( conn.connected() )
+ conn.disconnect();
+ }
+ else
+ conn = CONNECT( parent->focusChanged, eStatusBar::update );
+ }
+}
+
+void eStatusBar::update( const eWidget* p )
+{
+ if (p)
+ {
+ current = p;
+ setText( current->getHelpText() );
+ }
+}
+
+void eStatusBar::setFlags( int fl )
+{
+ if( fl == flagOwnerDraw )
+ {
+ flags = fl;
+ initialize();
+ }
+ else
+ eLabel::setFlags(fl);
+}
+
+int eStatusBar::setProperty(const eString &prop, const eString &value)
+{
+ if (prop=="ownerDraw")
+ flags |= flagOwnerDraw;
+ else
+ return eLabel::setProperty(prop, value);
+
+ initialize();
+
+ return 0;
+}
+
+static eWidget *create_eStatusBar(eWidget *parent)
+{
+ return new eStatusBar(parent);
+}
+
+class eStatusBarSkinInit
+{
+public:
+ eStatusBarSkinInit()
+ {
+ eSkin::addWidgetCreator("eStatusBar", create_eStatusBar);
+ }
+ ~eStatusBarSkinInit()
+ {
+ eSkin::removeWidgetCreator("eStatusBar", create_eStatusBar);
+ }
+};
+
+eAutoInitP0<eStatusBarSkinInit> init_eStatusBarSkinInit(eAutoInitNumbers::guiobject, "eStatusBar");
diff --git a/lib/gui/statusbar.h b/lib/gui/statusbar.h
new file mode 100644
index 00000000..f7f74940
--- /dev/null
+++ b/lib/gui/statusbar.h
@@ -0,0 +1,25 @@
+#ifndef __CORE_GUI_STATUSBAR__
+#define __CORE_GUI_STATUSBAR__
+
+#include <lib/gui/ewidget.h>
+#include <lib/gui/elabel.h>
+
+class eStatusBar : public eLabel
+{
+ void update( const eWidget *);
+ const eWidget* current;
+
+ int setProperty(const eString &, const eString &);
+ void initialize();
+ Connection conn;
+public:
+ enum
+ {
+ flagOwnerDraw = 128,
+ };
+ eStatusBar( eWidget*, const char* deco="eStatusBar" );
+ void setFlags( int );
+};
+
+#endif // __CORE_GUI_STATUSBAR__
+
diff --git a/lib/gui/testpicture.cpp b/lib/gui/testpicture.cpp
new file mode 100644
index 00000000..7afc904c
--- /dev/null
+++ b/lib/gui/testpicture.cpp
@@ -0,0 +1,229 @@
+#include <lib/gui/testpicture.h>
+#include <lib/gui/eskin.h>
+#include <lib/gui/elabel.h>
+#include <lib/gdi/font.h>
+#include <lib/gui/guiactions.h>
+#include <lib/gui/numberactions.h>
+
+void eTestPicture::hideDesc()
+{
+ if (testmode != testFUBK)
+ description->hide();
+}
+
+int eTestPicture::eventHandler(const eWidgetEvent &event)
+{
+ switch (event.type)
+ {
+ case eWidgetEvent::evtAction:
+ if (event.action == &i_cursorActions->ok)
+ close(-1);
+ else if (event.action == &i_cursorActions->cancel)
+ close(-1);
+ else if (event.action == &i_numberActions->key0)
+ close(0);
+ else if (event.action == &i_numberActions->key1)
+ close(1);
+ else if (event.action == &i_numberActions->key2)
+ close(2);
+ else if (event.action == &i_numberActions->key3)
+ close(3);
+ else if (event.action == &i_numberActions->key4)
+ close(4);
+ else if (event.action == &i_numberActions->key5)
+ close(5);
+ else if (event.action == &i_numberActions->key6)
+ close(6);
+ else if (event.action == &i_numberActions->key7)
+ close(7);
+ else if (event.action == &i_numberActions->key8)
+ close(8);
+ else if (event.action == &i_numberActions->key9)
+ close(9);
+ else
+ break;
+ return 0;
+ case eWidgetEvent::willShow:
+ desctimer.start(1000);
+ break;
+ default:
+ break;
+ }
+ return eWidget::eventHandler(event);
+}
+
+void eTestPicture::redrawWidget(gPainter *target, const eRect &area)
+{
+ switch (testmode)
+ {
+ case testColorbar:
+ {
+ for (int i=0; i<8; ++i)
+ {
+ gColor c=basic[i];
+
+ target->setForegroundColor(c);
+ target->fill(eRect(720/8*i, 0, 720/8, 576));
+ }
+ break;
+ }
+ case testGray:
+ {
+ for (int i=0; i<8; ++i)
+ {
+ gColor c=gray+i;
+
+ target->setForegroundColor(c);
+ target->fill(eRect(720/8*i, 0, 720/8, 576));
+ }
+ break;
+ }
+ case testFUBK:
+ {
+ // background
+ target->setBackgroundColor(gray+2);
+ target->clear();
+
+ // white lines
+ target->setForegroundColor(white);
+ for (int x=6; x<720; x+=44)
+ target->fill(eRect(x, 0, 3, 576));
+ for (int y=34; y<576; y+=44)
+ target->fill(eRect(0, y, 720, 3));
+
+ for (int i=0; i<8; ++i)
+ {
+ target->setForegroundColor(basic[i]);
+ target->fill(eRect(140+i*55, 80, 55, 80));
+ target->setForegroundColor(gray+i);
+ target->fill(eRect(140+i*55, 160, 55, 80));
+ }
+#if 1
+ int freq;
+ int phase=0;
+ for (int x=0; x<440; x+=freq)
+ {
+ freq=(440-x)/44 + 1;
+ target->setForegroundColor(phase ? white : black);
+ target->fill(eRect(140+x, 320, freq, 160));
+ phase = !phase;
+ }
+#endif
+#if 0
+ double phase=0;
+ for (int x=0; x<440; ++x)
+ {
+ // freq = 0.5 .. 5Mhz -> 10 Pixel ~= 1Mhz
+ double inc = (x/440.0)*(x/440.0) * 3.141 * 2 / 5.0 + 0.5;
+ phase += inc;
+ int s = int((sin(phase) + 1) * 4);
+ if (s < 0)
+ s = 0;
+ if (s > 7)
+ s = 7;
+ target->setForegroundColor(gray + s);
+ target->fill(eRect(140+x, 320, 1, 160));
+ }
+#endif
+
+ break;
+ }
+ case testRed:
+ target->setBackgroundColor(red);
+ target->clear();
+ break;
+ case testGreen:
+ target->setBackgroundColor(green);
+ target->clear();
+ break;
+ case testBlue:
+ target->setBackgroundColor(blue);
+ target->clear();
+ break;
+ case testWhite:
+ target->setBackgroundColor(white);
+ target->clear();
+ break;
+ case testBlack:
+ target->setBackgroundColor(black);
+ target->clear();
+ break;
+ }
+}
+
+eTestPicture::eTestPicture(int testmode): eWidget(0, 1), testmode(testmode), desctimer(eApp)
+{
+ red = eSkin::getActive()->queryColor("std_red");
+ green = eSkin::getActive()->queryColor("std_green");
+ blue = eSkin::getActive()->queryColor("std_blue");
+ black = eSkin::getActive()->queryColor("std_black");
+ white = eSkin::getActive()->queryColor("std_white");
+ gray = eSkin::getActive()->queryColor("std_gray");
+ setBackgroundColor(-1);
+
+ CONNECT(desctimer.timeout, eTestPicture::hideDesc);
+
+ basic[0] = white;
+ basic[1] = eSkin::getActive()->queryColor("std_dyellow");
+ basic[2] = eSkin::getActive()->queryColor("std_dcyan");
+ basic[3] = eSkin::getActive()->queryColor("std_dgreen");
+ basic[4] = eSkin::getActive()->queryColor("std_dmagenta");
+ basic[5] = eSkin::getActive()->queryColor("std_dred");
+ basic[6] = eSkin::getActive()->queryColor("std_dblue");
+ basic[7] = black;
+
+ addActionMap(&i_numberActions->map);
+ addActionMap(&i_cursorActions->map);
+
+ description = new eLabel(this, eLabel::flagVCenter);
+ switch (testmode)
+ {
+ case testColorbar:
+ case testRed:
+ case testBlue:
+ case testGreen:
+ case testWhite:
+ case testBlack:
+ case testGray:
+ description->move(ePoint(100, 100));
+ description->resize(eSize(200, 30));
+ description->setBackgroundColor(black);
+ description->setForegroundColor(white);
+ break;
+ case testFUBK:
+ description->move(ePoint(140, 240));
+ description->resize(eSize(440, 80));
+ description->setBackgroundColor(black);
+ description->setForegroundColor(white);
+ description->setText("ENIGMA");
+ description->setAlign(eTextPara::dirCenter);
+ break;
+ default:
+ break;
+ }
+ switch (testmode)
+ {
+ case testColorbar: description->setText("COLORBAR"); break;
+ case testRed: description->setText("RED"); break;
+ case testBlue: description->setText("BLUE"); break;
+ case testGreen: description->setText("GREEN"); break;
+ case testWhite: description->setText("WHITE (100%)"); break;
+ case testGray: description->setText("0% TO 100%"); break;
+ case testBlack: description->setText("BLACK (0%)"); break;
+ }
+ description->show();
+
+ setHelpID(95);
+}
+
+int eTestPicture::display(int mode)
+{
+ int res;
+ eTestPicture test(mode);
+ test.move(ePoint(0, 0));
+ test.resize(eSize(720, 576));
+ test.show();
+ res = test.exec();
+ test.hide();
+ return res;
+}
diff --git a/lib/gui/testpicture.h b/lib/gui/testpicture.h
new file mode 100644
index 00000000..568cdede
--- /dev/null
+++ b/lib/gui/testpicture.h
@@ -0,0 +1,36 @@
+#ifndef __testpicture_h
+#define __testpicture_h
+
+#include <lib/gui/ewidget.h>
+#include <lib/gdi/grc.h>
+#include <lib/base/ebase.h>
+
+class eLabel;
+
+class eTestPicture: public eWidget
+{
+ gColor red, green, blue, white, black;
+ gColor basic[8];
+ gColor gray;
+ int testmode;
+ eLabel *description;
+ eTimer desctimer;
+ void hideDesc();
+protected:
+ int eventHandler(const eWidgetEvent &event);
+ void redrawWidget(gPainter *target, const eRect &area);
+public:
+ enum {
+ testColorbar,
+ testRed,
+ testGreen,
+ testBlue,
+ testWhite,
+ testFUBK, // without circle ;)
+ testGray,
+ testBlack};
+ eTestPicture(int testmode);
+ static int display(int mode);
+};
+
+#endif
diff --git a/lib/gui/textinput.cpp b/lib/gui/textinput.cpp
new file mode 100644
index 00000000..90ec0086
--- /dev/null
+++ b/lib/gui/textinput.cpp
@@ -0,0 +1,388 @@
+#include <lib/base/estring.h>
+#include <lib/gui/textinput.h>
+#include <lib/gui/guiactions.h>
+#include <lib/gui/numberactions.h>
+#include <lib/gui/eskin.h>
+#include <lib/gui/ewindow.h>
+#include <lib/base/init.h>
+#include <lib/base/econfig.h>
+#include <lib/gdi/font.h>
+
+eTextInputField::eTextInputField( eWidget *parent, eLabel *descr, const char *deco )
+ :eButton( parent, descr, 1, deco), maxChars(0), lastKey(-1), editMode(false), nextCharTimer(eApp),
+ useableChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+// " +-.,:?!\"';_*/()<=>%#@&"),
+ "ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîï°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ"
+ " +-.,:?!\"';_*/()<=>%#@&"), capslock(0)
+{
+ if ( eConfig::getInstance()->getKey("/ezap/rc/TextInputField/nextCharTimeout", nextCharTimeout ) )
+ nextCharTimeout=0;
+ CONNECT( nextCharTimer.timeout, eTextInputField::nextChar );
+ addActionMap(&i_numberActions->map);
+ flags=0;
+ align=eTextPara::dirLeft;
+}
+
+void eTextInputField::updated()
+{
+ unsigned char c[4096];
+ strcpy((char *)c,isotext.c_str());
+
+ text=convertDVBUTF8(c,strlen((char*)c));
+ eLabel::invalidate();
+ drawCursor();
+}
+
+void eTextInputField::nextChar()
+{
+ if ( curPos+1 < (int)maxChars )
+ {
+ ++curPos;
+ if ( curPos > (int)isotext.length()-1 )
+ isotext+=' ';
+ updated();
+ }
+ lastKey=-1;
+}
+
+// "abc2ABC", // 2
+// "def3DEF", // 3
+// "ghi4GHI»", // 4
+// "jkl5JKL", // 5
+// "mno6MNO", // 6
+// "pqrs7PQRS", // 7
+// "tuv8TUV", // 8
+// "wxyz9WXYZ", // 9
+
+const char *keys[2][12] = {
+// lowercase
+ { "+0-.,:?!\"';_", // 0
+ " 1#@&/()<=>%", // 1
+ "abc2ÐÑÒÓ", // 2
+ "def3ÔÕÖ×", // 3
+ "ghi4ØÙÚÛ", // 4
+ "jkl5ÜÝÞß", // 5
+ "mno6àáâã", // 6
+ "pqrs7äåæç", // 7
+ "tuv8èéêë", // 8
+ "wxyz9íîï", // 9
+ "*/()<=>%", // <
+ "#@&`" }, // >
+// uppercase
+ { "+0-.,:?!\"';_", // 0
+ " 1#@&/()<=>%", // 1
+ "ABC2°±²³", // 2
+ "DEF3´µ¶·", // 3
+ "GHI4¸¹º»", // 4
+ "JKL5¼½¾¿", // 5
+ "MNO6ÀÁÂÃ", // 6
+ "PQRS7ÄÅÆÇ", // 7
+ "TUV8ÈÉÊË", // 8
+ "WXYZ9ÍÎÏ", // 9
+ "*/()<=>%", // <
+ "#@&`" } // >
+};
+
+void eTextInputField::setUseableChars( const char* uchars )
+{
+ useableChars=uchars;
+}
+
+void eTextInputField::setNextCharTimeout( unsigned int newtimeout )
+{
+ nextCharTimeout=newtimeout;
+}
+
+void eTextInputField::drawCursor()
+{
+// eDebug("length = %d", isotext.length());
+ eRect rc;
+ rc.setTop(crect.bottom()-4);
+ rc.setHeight( 3 );
+ if ( isotext.length() ) // text exist?
+ {
+ if ( (int)isotext.length() > curPos) // before or on the last char?
+ {
+ const eRect &bbox = para->getGlyphBBox(curPos);
+ if ( !bbox.width() ) // Space
+ {
+ if (curPos) // char before space?
+ {
+ const eRect &bbBefore = para->getGlyphBBox(curPos-1);
+ rc.setLeft( bbBefore.right()+2 );
+ }
+ if ( (int)isotext.length() > curPos+1) // char after space ?
+ {
+ const eRect &bbAfter = para->getGlyphBBox(curPos+1);
+ rc.setRight( bbAfter.left()-2 );
+ }
+ else // no char behind Space
+ rc.setWidth( 10 );
+ }
+ else
+ {
+ rc.setLeft( bbox.left() );
+ rc.setWidth( bbox.width() );
+ }
+ }
+ else // we are behind the last character
+ {
+ const eRect &bbox = para->getGlyphBBox(isotext.length()-1);
+ rc.setLeft( bbox.right() + ( ( curPos-isotext.length() ) * 10 ) + 2 );
+ rc.setWidth( 10 );
+ }
+ }
+ else // no one character in text
+ {
+ rc.setLeft( 2 );
+ rc.setWidth( 10 );
+ }
+ rc.moveBy( (deco_selected?crect_selected.left():crect.left())+1, 0 );
+ gPainter *painter = getPainter( deco_selected?crect_selected:crect );
+ painter->setForegroundColor( getForegroundColor() );
+ painter->setBackgroundColor( getBackgroundColor() );
+ painter->clip( rc );
+ painter->fill( rc );
+ painter->clippop();
+ if(capslock)
+ {
+ rc.setTop(crect.top());
+ rc.setHeight( 3 );
+ painter->clip( rc );
+ painter->fill( rc );
+ painter->clippop();
+ }
+ delete painter;
+}
+
+int eTextInputField::eventHandler( const eWidgetEvent &event )
+{
+ isotext=convertUTF8DVB(text);
+ switch (event.type)
+ {
+ case eWidgetEvent::changedText:
+ if ( maxChars < isotext.length() )
+ maxChars = isotext.length();
+ return eButton::eventHandler( event );
+ break;
+ case eWidgetEvent::evtAction:
+ {
+ if ( curPos < 0 )
+ curPos=0;
+// eDebug("curPos=%d, isotext.length=%d",curPos, isotext.length());
+ int key = -1;
+ if ( event.action == &i_cursorActions->capslock && editMode)
+ {
+ capslock^=1;
+ eLabel::invalidate();
+ drawCursor();
+ }
+ else if ( (event.action == &i_cursorActions->up ||
+ event.action == &i_cursorActions->down) && editMode )
+ {
+ nextCharTimer.stop();
+ const char *pc1=useableChars.c_str();
+ const char *pc2=strchr( pc1, isotext[curPos] );
+
+ if( !pc2 || !pc2[0] )
+ pc2=pc1;
+
+ if(event.action == &i_cursorActions->up)
+ {
+ pc2++;
+ if(!*pc2)
+ pc2=pc1;
+ }
+ else
+ {
+ if(pc2==pc1)
+ while(*pc2)
+ pc2++;
+ pc2--;
+ }
+ if ( isotext.length() )
+ isotext[curPos] = *pc2;
+ else
+ isotext+=*pc2;
+ updated();
+ }
+ else if (event.action == &i_cursorActions->insertchar && editMode)
+ {
+ if ( isotext.length() && isotext.length() < maxChars )
+ {
+ isotext.insert( curPos, " ");
+ updated();
+ }
+ }
+ else if (event.action == &i_cursorActions->deletechar && editMode)
+ {
+ if ( isotext.length() )
+ {
+ isotext.erase( curPos, 1 );
+// eDebug("curPos=%d, length=%d", curPos, text.length() );
+ if ( (int)isotext.length() == curPos )
+ {
+// eDebug("curPos--");
+ --curPos;
+ }
+ updated();
+ }
+ }
+ else if (event.action == &i_cursorActions->left && editMode )
+ {
+ nextCharTimer.stop();
+ if ( curPos > 0 )
+ {
+ --curPos;
+ lastKey=-1;
+ updated();
+ }
+ }
+ else if (event.action == &i_cursorActions->right && editMode)
+ {
+ nextCharTimer.stop();
+ nextChar();
+ }
+ else if (event.action == &i_cursorActions->ok)
+ {
+ nextCharTimer.stop();
+ if ( editMode )
+ {
+ setHelpText(oldHelpText);
+
+ if(isotext.length()>0)
+ while ( isotext[isotext.length()-1] == ' ' )
+ isotext.erase( isotext.length()-1 );
+
+ updated();
+ eButton::invalidate(); // remove the underline
+ editMode=false;
+ eWindow::globalCancel(eWindow::ON);
+ }
+ else
+ {
+ oldHelpText=helptext;
+ oldText=text;
+ setHelpText(_("press ok to leave edit mode, yellow=capslock"));
+ editMode=true;
+ curPos=0;
+ drawCursor();
+ eWindow::globalCancel(eWindow::OFF);
+ }
+ }
+ else if ( editMode && event.action == &i_cursorActions->cancel)
+ {
+ nextCharTimer.stop();
+ editMode=false;
+ setText(oldText);
+ setHelpText(oldHelpText);
+ eWindow::globalCancel(eWindow::ON);
+ }
+ else if (event.action == &i_numberActions->key0)
+ key=0;
+ else if (event.action == &i_numberActions->key1)
+ key=1;
+ else if (event.action == &i_numberActions->key2)
+ key=2;
+ else if (event.action == &i_numberActions->key3)
+ key=3;
+ else if (event.action == &i_numberActions->key4)
+ key=4;
+ else if (event.action == &i_numberActions->key5)
+ key=5;
+ else if (event.action == &i_numberActions->key6)
+ key=6;
+ else if (event.action == &i_numberActions->key7)
+ key=7;
+ else if (event.action == &i_numberActions->key8)
+ key=8;
+ else if (event.action == &i_numberActions->key9)
+ key=9;
+ else if (event.action == &i_numberActions->keyExt1)
+ key=10;
+ else if (event.action == &i_numberActions->keyExt2)
+ key=11;
+ else
+ return eButton::eventHandler( event );
+ if ( key != lastKey && nextCharTimer.isActive() )
+ {
+ nextCharTimer.stop();
+ nextChar();
+ }
+// eDebug("editMode = %d, key = %d", editMode, key);
+ if ( editMode && key != -1 )
+ {
+ char newChar = 0;
+
+ if ( key == lastKey )
+ {
+ char *oldkey = strchr( keys[capslock][key], isotext[curPos] );
+ newChar = oldkey?keys[capslock][key][oldkey-keys[capslock][key]+1]:0;
+ }
+
+ if (!newChar)
+ {
+ newChar = keys[capslock][key][0];
+ }
+// eDebug("newChar = %d", newChar );
+ char testChar = newChar;
+ do
+ {
+ if ( strchr( useableChars.c_str(), newChar ) ) // char useable?
+ {
+ if ( curPos == (int)isotext.length() )
+ isotext += newChar;
+ else
+ isotext[curPos] = newChar;
+ updated();
+ if(nextCharTimeout)
+ nextCharTimer.start(nextCharTimeout,true);
+ break;
+ }
+ else
+ {
+ nextCharTimer.stop();
+ char *oldkey = strchr( keys[capslock][key], newChar );
+ newChar=oldkey?keys[capslock][key][oldkey-keys[capslock][key]+1]:0;
+ if (!newChar)
+ newChar=keys[capslock][key][0];
+ }
+ }
+ while( newChar != testChar ); // all chars tested.. and no char is useable..
+ lastKey=key;
+ }
+ }
+ break;
+
+ default:
+ return eButton::eventHandler( event );
+ break;
+ }
+ return 1;
+}
+
+void eTextInputField::redrawWidget( gPainter *target, const eRect &area )
+{
+ eButton::redrawWidget( target, area );
+}
+
+static eWidget *create_eTextInputField(eWidget *parent)
+{
+ return new eTextInputField(parent);
+}
+
+class eTextInputFieldSkinInit
+{
+public:
+ eTextInputFieldSkinInit()
+ {
+ eSkin::addWidgetCreator("eTextInputField", create_eTextInputField);
+ }
+ ~eTextInputFieldSkinInit()
+ {
+ eSkin::removeWidgetCreator("eTextInputField", create_eTextInputField);
+ }
+};
+
+eAutoInitP0<eTextInputFieldSkinInit> init_eTextInputFieldSkinInit(25, "eTextInputField");
+
diff --git a/lib/gui/textinput.h b/lib/gui/textinput.h
new file mode 100644
index 00000000..d0901dc2
--- /dev/null
+++ b/lib/gui/textinput.h
@@ -0,0 +1,31 @@
+#ifndef __LIB_GUI_TEXTINPUT_H__
+#define __LIB_GUI_TEXTINPUT_H__
+
+#include <lib/gui/ebutton.h>
+
+class eTextInputField: public eButton
+{
+ int curPos;
+ unsigned int maxChars;
+ int eventHandler( const eWidgetEvent &);
+ void redrawWidget( gPainter *target, const eRect &area );
+ void drawCursor();
+ void updated();
+ void nextChar();
+ int lastKey;
+ bool editMode;
+ eString oldText;
+ eString oldHelpText;
+ eTimer nextCharTimer;
+ eString useableChars;
+ unsigned int nextCharTimeout;
+ bool capslock;
+ eString isotext;
+public:
+ eTextInputField( eWidget* parent, eLabel *descr=0, const char *deco="eNumber" );
+ void setMaxChars( int i ) { maxChars = i; }
+ void setUseableChars( const char* );
+ void setNextCharTimeout( unsigned int );
+};
+
+#endif