diff options
Diffstat (limited to 'xml')
-rw-r--r-- | xml/display.c | 3 | ||||
-rw-r--r-- | xml/display.h | 3 | ||||
-rw-r--r-- | xml/object.c | 193 | ||||
-rw-r--r-- | xml/object.h | 64 | ||||
-rw-r--r-- | xml/parser.c | 37 | ||||
-rw-r--r-- | xml/skin.c | 31 | ||||
-rw-r--r-- | xml/skin.h | 45 |
7 files changed, 351 insertions, 25 deletions
diff --git a/xml/display.c b/xml/display.c index a8268c4..adf500b 100644 --- a/xml/display.c +++ b/xml/display.c @@ -11,7 +11,8 @@ static const std::string DisplayNames[] = cxDisplay::cxDisplay(cxSkin *parent): mSkin(parent), mType((eType)__COUNT_DISPLAY__), - mNumWindows(0) + mNumWindows(0), + mRefreshDefault(NULL) { } diff --git a/xml/display.h b/xml/display.h index 319cc7e..af1f590 100644 --- a/xml/display.h +++ b/xml/display.h @@ -35,6 +35,7 @@ private: int mNumWindows; int mNumMarquees; cxObjects mObjects; + cxRefresh mRefreshDefault; public: cxDisplay(cxSkin *Parent); @@ -48,7 +49,7 @@ public: cxSkin *Skin(void) const { return mSkin; } uint Objects(void) const { return mObjects.size(); } - const cxObject *GetObject(int n) const { return mObjects[n]; } + cxObject *GetObject(int n) const { return mObjects[n]; } }; class cxDisplays: public std::map<cxDisplay::eType,cxDisplay*> { diff --git a/xml/object.c b/xml/object.c index 4a3beec..ec69fe7 100644 --- a/xml/object.c +++ b/xml/object.c @@ -16,6 +16,7 @@ cxObject::cxObject(cxDisplay *Parent): mType((eType)__COUNT_OBJECT__), mPos1(0, 0), mPos2(-1, -1), + mVirtSize(-1, -1), mAlpha(255), mColors(0), mArc(0), @@ -30,7 +31,9 @@ cxObject::cxObject(cxDisplay *Parent): mFontWidth(0), mDelay(150), mIndex(0), - mObjects(NULL) + mRefresh(this), + mObjects(NULL), + mListIndex(0) { } @@ -40,11 +43,13 @@ cxObject::cxObject(const cxObject &Src): mType(Src.mType), mPos1(Src.mPos1), mPos2(Src.mPos2), + mVirtSize(Src.mVirtSize), mAlpha(Src.mAlpha), mColors(Src.mColors), mArc(Src.mArc), mFg(Src.mFg), mBg(Src.mBg), + mBl(Src.mBl), mMask(Src.mMask), mMark(Src.mMark), mActive(Src.mActive), @@ -59,7 +64,9 @@ cxObject::cxObject(const cxObject &Src): mFontSize(Src.mFontSize), mFontWidth(Src.mFontWidth), mDelay(Src.mDelay), - mObjects(NULL) + mRefresh(Src.mRefresh), + mObjects(NULL), + mListIndex(Src.mListIndex) { if (Src.mCondition) mCondition = new cxFunction(*Src.mCondition); @@ -128,7 +135,8 @@ bool cxObject::ParseFontFace(const std::string &Text) void cxObject::SetListIndex(uint Index, int Tab) { - mIndex = mDisplay->Objects() + (Index * cSkinDisplayMenu::MaxTabs + Tab); + Tab = (Tab >= 0 ? Tab : -1); + mListIndex = 1 + Index * cSkinDisplayMenu::MaxTabs + Tab; mText.SetListIndex(Index, Tab); mPath.SetListIndex(Index, Tab); if (mCondition != NULL) @@ -154,18 +162,39 @@ const cFont *cxObject::Font(void) const return cFont::GetFont(fontOsd); } -txPoint cxObject::Pos(void) const +txPoint cxObject::Pos(const txPoint &BaseOffset, const txSize &BaseSize, const txSize &VirtSize) const { - return txPoint(mSkin->BaseOffset().x + (mPos1.x < 0 ? Skin()->BaseSize().w + mPos1.x : mPos1.x), - mSkin->BaseOffset().y + (mPos1.y < 0 ? Skin()->BaseSize().h + mPos1.y : mPos1.y)); + txPoint bOffset = BaseOffset.x < 0 ? mSkin->BaseOffset() : BaseOffset; + txSize bSize = BaseSize.w < 0 ? mSkin->BaseSize() : BaseSize; + + double scale_x = VirtSize.w > 0 ? (double)BaseSize.w / VirtSize.w : 1.0, + scale_y = VirtSize.h > 0 ? (double)BaseSize.h / VirtSize.h : 1.0; + + int x1 = mPos1.x < 0 ? (int)((mPos1.x + 1) * scale_x - 1) : (int)(mPos1.x * scale_x); + int y1 = mPos1.y < 0 ? (int)((mPos1.y + 1) * scale_x - 1) : (int)(mPos1.y * scale_y); + + return txPoint(bOffset.x + (x1 < 0 ? bSize.w + x1 : x1), + bOffset.y + (y1 < 0 ? bSize.h + y1 : y1)); } -txSize cxObject::Size(void) const +txSize cxObject::Size(const txPoint &BaseOffset, const txSize &BaseSize, const txSize &VirtSize) const { - txPoint p1(mSkin->BaseOffset().x + (mPos1.x < 0 ? Skin()->BaseSize().w + mPos1.x : mPos1.x), - mSkin->BaseOffset().y + (mPos1.y < 0 ? Skin()->BaseSize().h + mPos1.y : mPos1.y)); - txPoint p2(mSkin->BaseOffset().x + (mPos2.x < 0 ? Skin()->BaseSize().w + mPos2.x : mPos2.x), - mSkin->BaseOffset().y + (mPos2.y < 0 ? Skin()->BaseSize().h + mPos2.y : mPos2.y)); + //txPoint bOffset = BaseOffset.x < 0 ? mSkin->BaseOffset() : BaseOffset; + txSize bSize = BaseSize.w < 0 ? mSkin->BaseSize() : BaseSize; + + double scale_x = VirtSize.w > 0 ? (double)BaseSize.w / VirtSize.w : 1.0, + scale_y = VirtSize.h > 0 ? (double)BaseSize.h / VirtSize.h : 1.0; + + int x1 = mPos1.x < 0 ? (int)((mPos1.x + 1) * scale_x - 1) : (int)(mPos1.x * scale_x); + int y1 = mPos1.y < 0 ? (int)((mPos1.y + 1) * scale_x - 1) : (int)(mPos1.y * scale_y); + int x2 = mPos2.x < 0 ? (int)((mPos2.x + 1) * scale_x - 1) : (int)(mPos2.x * scale_x); + int y2 = mPos2.y < 0 ? (int)((mPos2.y + 1) * scale_x - 1) : (int)(mPos2.y * scale_y); + + txPoint p1(x1 < 0 ? bSize.w + x1 : x1, + y1 < 0 ? bSize.h + y1 : y1); + txPoint p2(x2 < 0 ? bSize.w + x2 : x2, + y2 < 0 ? bSize.h + y2 : y2); + return txSize(p2.x - p1.x + 1, p2.y - p1.y + 1); } @@ -181,6 +210,12 @@ const tColor *cxObject::Bg(void) const return cText2SkinRender::ItemColor(mBg, Bg) ? &Bg : NULL; } +const tColor *cxObject::Bl(void) const +{ + static tColor Bl; + return cText2SkinRender::ItemColor(mBl, Bl) ? &Bl : NULL; +} + const tColor *cxObject::Mask(void) const { static tColor Mask; @@ -215,3 +250,139 @@ cxObjects::~cxObjects() delete operator[](i); } + +/////////////////////////////////////////////////////////////////////////////// +// ---------- class cxRefresh ---------------------------------------------- // + +cxRefresh::cxRefresh(cxObject *Object): + mRefreshType(0xFF), + mText(NULL), + mChanged(NULL), + mObject(Object), + mForce(true), + mFull(true) +{ +} + +cxRefresh::~cxRefresh() +{ + delete mText; +} + +bool cxRefresh::Dirty(uint dirty, uint &updatein, bool force, uint now) +{ + // check if the timeout of the object has expired + uint nexttime = mObject->State().nexttime; + + bool to = force || mForce || + mObject->Type() == cxObject::block || mObject->Type() == cxObject::list; + bool changed = force || mForce; + + if (now > 0 && nexttime > 0) { + // timeout was set + if (now >= nexttime) + // timeout has expired + to = true; + else { + // time left -> set new update interval + uint nextin = nexttime - now; + if (updatein == 0 || nextin < updatein) + updatein = nextin; + } + } + + // Object has changed since last redraw + if (mChanged != NULL) { + mEval = mChanged->Evaluate(); + if (mEval != mLastEval) + changed = true; + } + + // refresh + if ((mRefreshType & dirty & ~(1<<timeout) & ~(1<<update))) { + if (changed) + mLastEval = mEval; + return true; + } + + // timeout + if ((mRefreshType & dirty & (1<<timeout)) && to) { + if (changed) + mLastEval = mEval; + return true; + } + + // update + if ((mRefreshType & dirty & (1<<update)) && changed) { + mLastEval = mEval; + return true; + } + + return false; +} + +bool cxRefresh::Parse(const std::string &Text) +{ + uint refresh = 0; + bool force = false, full = false; + + if (Text.find("all") != std::string::npos) + refresh |= (1<<all); + + if (Text.find("timeout") != std::string::npos) + refresh |= (1<<timeout); + + if (Text.find("update") != std::string::npos) + refresh |= (1<<update); + + //if (Text.find("message") != std::string::npos) + // refresh |= (1<<list); + + if (Text.find("list") != std::string::npos) + refresh |= (1<<list); + + if (Text.find("scroll") != std::string::npos) + refresh |= (1<<scroll); + + if (Text.find("allways") != std::string::npos) + refresh |= 0xFF; + + if (Text.find("full") != std::string::npos) + full = true; + + if (Text.find("force") != std::string::npos) + force = true; + + if (refresh == 0) + return false; + + mForce = force; + mFull = full; + mRefreshType = refresh; + + return true; +} + +bool cxRefresh::ParseChanged(const std::string &Text) +{ + if (mObject == NULL) + return false; + + if (mText == NULL) + mText = new cxString(mObject, false); + + if (mText->Parse(Text)) { + mChanged = mText; + return true; + } + + return false; +} + +cxRefresh &cxRefresh::operator=(const cxRefresh &a) +{ + mRefreshType = a.mRefreshType; + mForce = a.mForce; + mFull = a.mFull; + return *this; +} diff --git a/xml/object.h b/xml/object.h index bbc37a0..18600fe 100644 --- a/xml/object.h +++ b/xml/object.h @@ -33,6 +33,50 @@ struct txWindow { pos1(_x1, _y2), pos2(_x2, _y2), bpp(_bpp) {} }; +// state information for marquee, blink, scroll +struct txState { + bool scrolling; + int offset; + int direction; + uint nexttime; + std::string text; + txState(void): scrolling(false), offset(0), direction(1), nexttime(0) {} +}; + +class cxObject; + +class cxRefresh { + friend bool xEndElem(const std::string &name); + +public: + enum eRefreshType { + all, // complete redraw of the screen + timeout, // redraw due to a timeout + //message, // a message was set or removed + update, // update of the osd elements + scroll, // a scroll event + list, // list items or the current item have changed + }; + + cxRefresh(cxObject *Object); + ~cxRefresh(); + bool Dirty(uint dirty, uint &updatein, bool force = false, uint now = 0); + bool Full(void) const { return mFull; } + uint Type(void) const { return mRefreshType; } + bool Parse(const std::string &Text); + bool ParseChanged(const std::string &Text); + cxRefresh &operator=(const cxRefresh &b); + +private: + uint mRefreshType; + cxType mLastEval; + cxType mEval; + cxString *mText; + cxString *mChanged; + cxObject *mObject; + bool mForce, mFull; +}; + class cxObjects; class cxObject { @@ -68,11 +112,13 @@ private: eType mType; txPoint mPos1; txPoint mPos2; + txSize mVirtSize; int mAlpha; int mColors; int mArc; std::string mFg; std::string mBg; + std::string mBl; std::string mMask; std::string mMark; std::string mActive; @@ -88,8 +134,14 @@ private: int mFontWidth; uint mDelay; uint mIndex; + cxRefresh mRefresh; cxObjects *mObjects; // used for block objects such as <list> + // state information for marquee, blink, scroll + uint mListIndex; + typedef std::map<uint,txState> tStates; + tStates mStates; + public: cxObject(cxDisplay *parent); cxObject(const cxObject &Src); @@ -116,20 +168,24 @@ public: uint Index(void) const { return mIndex; } cxDisplay *Display(void) const { return mDisplay; } cxSkin *Skin(void) const { return mSkin; } + txState &State(void) { return mStates[mListIndex]; } const std::string &TypeName(void) const; - txPoint Pos(void) const; - txSize Size(void) const; + txPoint Pos(const txPoint &BaseOffset = txPoint(-1, -1), const txSize &BaseSize = txSize(-1, -1), + const txSize &VirtSize = txSize(-1, -1)) const; + txSize Size(const txPoint &BaseOffset = txPoint(-1, -1), const txSize &BaseSize = txSize(-1, -1), + const txSize &VirtSize = txSize(-1, -1)) const; const cFont *Font(void) const; const tColor *Fg(void) const; const tColor *Bg(void) const; + const tColor *Bl(void) const; const tColor *Mask(void) const; const tColor *Mark(void) const; const tColor *Active(void) const; const tColor *Keep(void) const; uint Objects(void) const; - const cxObject *GetObject(uint Index) const; + cxObject *GetObject(uint Index) const; }; class cxObjects: public std::vector<cxObject*> { @@ -144,7 +200,7 @@ inline uint cxObject::Objects(void) const return mObjects ? mObjects->size() : 0; } -inline const cxObject *cxObject::GetObject(uint Index) const +inline cxObject *cxObject::GetObject(uint Index) const { return mObjects ? (*mObjects)[Index] : NULL; } diff --git a/xml/parser.c b/xml/parser.c index f573398..fe93602 100644 --- a/xml/parser.c +++ b/xml/parser.c @@ -45,7 +45,7 @@ #define ATTRIB_OPT_NUMBER(_attr,_target) \ if (attrs.find(_attr) != attrs.end()) { \ char *_e; const char *_t = attrs[_attr].c_str(); \ - long _l = strtol(_t, &_e, 10); \ + long _l = strtol(_t, &_e, 0); \ if (_e ==_t || *_e != '\0') { \ esyslog("ERROR: Text2Skin: Invalid numeric value \"%s\" in attribute %s", \ _t, _attr); \ @@ -91,7 +91,7 @@ bool xStartElem(const std::string &name, std::map<std::string,std::string> &attr if (context.size() == 0) { if (name == "skin") { - ATTRIB_MAN_STRING("version", skin->mVersion); + ATTRIB_MAN_FUNC ("version", skin->mVersion.Parse); ATTRIB_MAN_STRING("name", skin->mTitle); ATTRIB_MAN_FUNC ("screenBase", skin->ParseBase); } @@ -102,7 +102,8 @@ bool xStartElem(const std::string &name, std::map<std::string,std::string> &attr if (name == "display") { display = new cxDisplay(skin); ATTRIB_MAN_FUNC ("id", display->ParseType); - } + ATTRIB_OPT_FUNC ("refresh", display->mRefreshDefault.Parse); + } else TAG_ERR_REMAIN("skin"); } @@ -129,12 +130,18 @@ bool xStartElem(const std::string &name, std::map<std::string,std::string> &attr else { object = new cxObject(display); if (object->ParseType(name)) { + if (parents.size() > 0) + object->mRefresh = parents.back()->mRefresh; + else + object->mRefresh = display->mRefreshDefault; + ATTRIB_OPT_NUMBER("x1", object->mPos1.x); ATTRIB_OPT_NUMBER("y1", object->mPos1.y); ATTRIB_OPT_NUMBER("x2", object->mPos2.x); ATTRIB_OPT_NUMBER("y2", object->mPos2.y); ATTRIB_OPT_FUNC ("condition", object->ParseCondition); - + ATTRIB_OPT_FUNC ("refresh", object->mRefresh.Parse); + ATTRIB_OPT_FUNC ("changed", object->mRefresh.ParseChanged); if (name == "image") { ATTRIB_OPT_NUMBER("x", object->mPos1.x); ATTRIB_OPT_NUMBER("y", object->mPos1.y); @@ -152,11 +159,12 @@ bool xStartElem(const std::string &name, std::map<std::string,std::string> &attr || name == "blink" || name == "scrolltext") { ATTRIB_OPT_STRING("color", object->mFg); + ATTRIB_OPT_STRING("bgColor", object->mBg); ATTRIB_OPT_FUNC ("align", object->ParseAlignment); ATTRIB_OPT_FUNC ("font", object->ParseFontFace); if (name == "blink") { - ATTRIB_OPT_STRING("blinkColor", object->mBg); + ATTRIB_OPT_STRING("blinkColor", object->mBl); ATTRIB_OPT_NUMBER("delay", object->mDelay); if (object->mDelay == 0) @@ -190,6 +198,11 @@ bool xStartElem(const std::string &name, std::map<std::string,std::string> &attr ATTRIB_MAN_NUMBER("height", object->mPos2.y); --object->mPos2.y; } + else if (name == "block" + || name == "list") { + ATTRIB_OPT_NUMBER("w", object->mVirtSize.w); + ATTRIB_OPT_NUMBER("h", object->mVirtSize.h); + } } else TAG_ERR_REMAIN(context[context.size() - 1].c_str()); } @@ -256,6 +269,20 @@ bool xEndElem(const std::string &name) { } } + if (object->mRefresh.mChanged == NULL) { + switch (object->mType) { + case cxObject::text: + case cxObject::marquee: + case cxObject::blink: + case cxObject::scrolltext: + object->mRefresh.mChanged = &object->mText; + break; + + default: + break; + } + } + object->mIndex = oindex++; if (parents.size() > 0) { Dprintf("pushing to parent\n"); @@ -9,6 +9,37 @@ const std::string ScreenBases[] = { "relative", "absolute" }; +cxVersion::cxVersion(int ma, int min): + mMajor(ma), + mMinor(min) +{ +} + +bool cxVersion::Parse(const std::string &Text) +{ + int dot = Text.find("."); + std::string ma(Text, 0, dot), min(Text, dot + 1); + char *e = NULL; + const char *t = NULL; + long l = 0; + + t = ma.c_str(); + l = strtol(t, &e, 10); + if (e == t || *e != '\0') + return false; + else + mMajor = l; + + t = min.c_str(); + l = strtol(t, &e, 10); + if (e == t || *e != '\0') + return false; + else + mMinor = l; + + return true; +} + cxSkin::cxSkin(const std::string &Name, cText2SkinI18n *I18n, cText2SkinTheme *Theme): mName(Name), mI18n(I18n), @@ -15,6 +15,45 @@ class cText2SkinI18n; class cText2SkinTheme; +class cxVersion { +public: + cxVersion(int ma = 0, int min = 0); + bool Parse(const std::string &Text); + int Major(void) const { return mMajor; } + int Minor(void) const { return mMinor; } + bool Require(int ma, int min) const { + return mMajor > ma ? true : (mMajor == ma ? mMinor >= min : false); + } + bool Limit(int ma, int min) const { + return mMajor < ma ? true : (mMajor == ma ? mMinor <= min : false); + } + bool operator==(const cxVersion &v) const { + return mMajor == v.mMajor && mMinor == v.mMinor; + } + bool operator>=(const cxVersion &v) const { + return Require(v.mMajor, v.mMinor); + } + bool operator>=(const char *c) const { + cxVersion v; + if (!v.Parse(c)) + return false; + return Require(v.mMajor, v.mMinor); + } + bool operator<=(const cxVersion &v) const { + return Limit(v.mMajor, v.mMinor); + } + bool operator<=(const char *c) const { + cxVersion v; + if (!v.Parse(c)) + return false; + return Limit(v.mMajor, v.mMinor); + } + +private: + int mMajor; + int mMinor; +}; + class cxSkin { friend bool xStartElem(const std::string &name, std::map<std::string,std::string> &attrs); friend bool xEndElem(const std::string &name); @@ -35,8 +74,8 @@ private: txSize mBaseSize; std::string mName; std::string mTitle; - std::string mVersion; - + cxVersion mVersion; + cxDisplays mDisplays; cText2SkinI18n *mI18n; // TODO: should move here completely @@ -55,7 +94,7 @@ public: const txSize &BaseSize(void) const { return mBaseSize; } const std::string &Name(void) const { return mName; } const std::string &Title(void) const { return mTitle; } - const std::string &Version(void) const { return mVersion; } + const cxVersion &Version(void) const { return mVersion; } // functions for object classes to obtain dynamic item information std::string Translate(const std::string &Text); |