diff options
-rw-r--r-- | glcdskin/object.c | 118 | ||||
-rw-r--r-- | glcdskin/object.h | 20 | ||||
-rw-r--r-- | glcdskin/parser.c | 25 | ||||
-rw-r--r-- | glcdskin/string.c | 11 |
4 files changed, 135 insertions, 39 deletions
diff --git a/glcdskin/object.c b/glcdskin/object.c index 107e8f5..82a0d89 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -32,8 +32,14 @@ cSkinObject::cSkinObject(cSkinDisplay * Parent) : mDisplay(Parent), mSkin(Parent->Skin()), mType((eType) __COUNT_OBJECT__), - mPos1(0, 0), - mPos2(-1, -1), + //mPos1(0, 0), + //mPos2(-1, -1), + mX1(this, false), + mY1(this, false), + mX2(this, false), + mY2(this, false), + mWidth(this, false), + mHeight(this, false), mColor(this, cColor(cColor::Black)), mBackgroundColor(this, cColor(cColor::Transparent)), mFilled(false), @@ -46,11 +52,13 @@ cSkinObject::cSkinObject(cSkinDisplay * Parent) mPath(this, false), mCurrent(this, false), mTotal(this, false), + mPeak(this, false), mFont(this, false), mText(this, false), mCondition(NULL), mEffect(tfxNone), mEffectColor(this, cColor(cColor::White)), + mPeakColor(this, cColor(cColor::ERRCOL)), // if ERRCOL -> use mColor mLastChange(0), mChangeDelay(-1), // delay between two images frames: -1: not animated / don't care mStoredImagePath(""), @@ -75,8 +83,14 @@ cSkinObject::cSkinObject(const cSkinObject & Src) : mDisplay(Src.mDisplay), mSkin(Src.mSkin), mType(Src.mType), - mPos1(Src.mPos1), - mPos2(Src.mPos2), + //mPos1(Src.mPos1), + //mPos2(Src.mPos2), + mX1(Src.mX1), + mY1(Src.mY1), + mX2(Src.mX2), + mY2(Src.mY2), + mWidth(Src.mWidth), + mHeight(Src.mHeight), mColor(Src.mColor), mBackgroundColor(Src.mBackgroundColor), mFilled(Src.mFilled), @@ -89,11 +103,13 @@ cSkinObject::cSkinObject(const cSkinObject & Src) mPath(Src.mPath), mCurrent(Src.mCurrent), mTotal(Src.mTotal), + mPeak(Src.mPeak), mFont(Src.mFont), mText(Src.mText), mCondition(Src.mCondition), mEffect(Src.mEffect), mEffectColor(Src.mEffectColor), + mPeakColor(Src.mPeakColor), mLastChange(0), mChangeDelay(-1), mStoredImagePath(Src.mStoredImagePath), @@ -231,6 +247,7 @@ bool cSkinObject::ParseIntParam(const std::string &Text, int & Param) return true; } +#if 0 bool cSkinObject::ParseWidth(const std::string &Text) { int w; @@ -256,6 +273,7 @@ bool cSkinObject::ParseHeight(const std::string &Text) } return false; } +#endif bool cSkinObject::ParseFontFace(const std::string & Text) { @@ -334,16 +352,33 @@ const std::string & cSkinObject::TypeName(void) const tPoint cSkinObject::Pos(void) const { - return tPoint(mPos1.x < 0 ? mSkin->BaseSize().w + mPos1.x : mPos1.x, - mPos1.y < 0 ? mSkin->BaseSize().h + mPos1.y : mPos1.y); + int x1 = mX1.Evaluate(); + int y1 = mY1.Evaluate(); + return tPoint(x1 < 0 ? mSkin->BaseSize().w + x1 : x1, + y1 < 0 ? mSkin->BaseSize().h + y1 : y1); } tSize cSkinObject::Size(void) const { - tPoint p1(mPos1.x < 0 ? mSkin->BaseSize().w + mPos1.x : mPos1.x, - mPos1.y < 0 ? mSkin->BaseSize().h + mPos1.y : mPos1.y); - tPoint p2(mPos2.x < 0 ? mSkin->BaseSize().w + mPos2.x : mPos2.x, - mPos2.y < 0 ? mSkin->BaseSize().h + mPos2.y : mPos2.y); + int x1 = mX1.Evaluate(); + int y1 = mY1.Evaluate(); + tPoint p1(x1 < 0 ? mSkin->BaseSize().w + x1 : x1, + y1 < 0 ? mSkin->BaseSize().h + y1 : y1); + + int w = mWidth.Evaluate(); + int h = mHeight.Evaluate(); + + int x2 = mX2.Evaluate(); + if (w != 0 && x2 == -1) { + x2 = x1 + w - 1; + } + int y2 = mY2.Evaluate(); + if (h != 0 && y2 == -1) { + y2 = y1 + h - 1; + } + + tPoint p2((x2 < 0) ? mSkin->BaseSize().w + x2 : x2, + (y2 < 0) ? mSkin->BaseSize().h + y2 : y2); return tSize(p2.x - p1.x + 1, p2.y - p1.y + 1); } @@ -450,33 +485,61 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { int current = mCurrent.Evaluate(); int total = mTotal.Evaluate(); + int peak = mPeak.Evaluate(); if (total == 0) total = 1; if (current > total) current = total; + if (peak > total) + peak = total; + + int maxSize = ( (mDirection % 2) == 0 ) ? Size().w : Size().h; + int currSize = maxSize * current / total; + + int peakSize = 0; + int peakBarSize = 2; + uint32_t peakColor = (mPeakColor == cColor::ERRCOL) ? mColor : mPeakColor; + if (peak > 0) { + peakSize = maxSize * peak / total; + if (mRadius <= 0) { + peakBarSize = maxSize / 20; + if (peakBarSize < 2) + peakBarSize = 2; + } else { + peakBarSize = mRadius; + } + // at least peakBarSize of empty space between normal progress bar and peak marker. if too small: don't show peak marker + if (currSize + peakBarSize + (peakBarSize / 2) >= peakSize) + peakSize = 0; // don't show at all + } + if (mDirection == 0) { - int w = Size().w * current / total; - if (w > 0) - screen->DrawRectangle(Pos().x, Pos().y, Pos().x + w - 1, Pos().y + Size().h - 1, mColor, true); + if (currSize > 0) + screen->DrawRectangle(Pos().x, Pos().y, Pos().x + currSize - 1, Pos().y + Size().h - 1, mColor, true); + if (peakSize > 0) + screen->DrawRectangle(Pos().x + peakSize-1, Pos().y, Pos().x + peakSize-1 + peakBarSize-1, Pos().y + Size().h - 1, peakColor, true); } else if (mDirection == 1) { - int h = Size().h * current / total; - if (h > 0) - screen->DrawRectangle(Pos().x, Pos().y, Pos().x + Size().w - 1, Pos().y + h - 1, mColor, true); + if (currSize > 0) + screen->DrawRectangle(Pos().x, Pos().y, Pos().x + Size().w - 1, Pos().y + currSize - 1, mColor, true); + if (peakSize > 0) + screen->DrawRectangle(Pos().x, Pos().y + peakSize-1, Pos().x + Size().w - 1, Pos().y + peakSize-1 + peakBarSize-1, peakColor, true); } else if (mDirection == 2) { - int w = Size().w * current / total; - if (w > 0) - screen->DrawRectangle(Pos().x + Size().w - w, Pos().y, Pos().x + Size().w - 1, Pos().y + Size().h - 1, mColor, true); + if (currSize > 0) + screen->DrawRectangle(Pos().x + Size().w - currSize, Pos().y, Pos().x + Size().w - 1, Pos().y + Size().h - 1, mColor, true); + if (peakSize > 0) + screen->DrawRectangle(Pos().x + Size().w + maxSize - peakSize, Pos().y, Pos().x + maxSize - peakSize + peakBarSize-1, Pos().y + Size().h - 1, peakColor, true); } else if (mDirection == 3) { - int h = Size().h * current / total; - if (h > 0) - screen->DrawRectangle(Pos().x, Pos().y + Size().h - h, Pos().x + Size().w - 1, Pos().y + Size().h - 1, mColor, true); + if (currSize > 0) + screen->DrawRectangle(Pos().x, Pos().y + Size().h - currSize, Pos().x + Size().w - 1, Pos().y + Size().h - 1, mColor, true); + if (peakSize > 0) + screen->DrawRectangle(Pos().x, Pos().y + maxSize - peakSize, Pos().x + Size().w - 1, Pos().y + maxSize - peakSize + peakBarSize-1, peakColor, true); } break; } @@ -816,14 +879,19 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { for (int j = 1; j < (int) NumObjects(); j++) { + int px1, py1, py2; + char buf[10]; const cSkinObject * o = GetObject(j); cSkinObject obj(*o); obj.SetListIndex(maxitems, i); if (obj.Condition() != NULL && !obj.Condition()->Evaluate()) continue; - obj.mPos1.x += mPos1.x; - obj.mPos1.y += mPos1.y + yoffset; - obj.mPos2.y += mPos1.y + yoffset; + px1 = obj.Pos().x + Pos().x; // obj.mPos1.x += mPos1.x; + py1 = obj.Pos().y + Pos().y + yoffset; // obj.mPos1.y += mPos1.y + yoffset; + py2 = obj.Pos().y + obj.Size().w -1 + yoffset; // obj.mPos2.y += mPos1.y + yoffset; + snprintf(buf, 9, "%d", px1); obj.mX1.Parse((const char*)buf); + snprintf(buf, 9, "%d", py1); obj.mY1.Parse((const char*)buf); + snprintf(buf, 9, "%d", py2); obj.mY2.Parse((const char*)buf); obj.Render(screen); } yoffset += itemheight; diff --git a/glcdskin/object.h b/glcdskin/object.h index e48b46f..cbb6966 100644 --- a/glcdskin/object.h +++ b/glcdskin/object.h @@ -121,8 +121,14 @@ private: cSkinDisplay * mDisplay; // parent display cSkin * mSkin; eType mType; // type of object, one of enum eType - tPoint mPos1; - tPoint mPos2; + //tPoint mPos1; + //tPoint mPos2; + cSkinString mX1; // either mX1 and mWidth or mX1 and mX2 are defined. not all three + cSkinString mY1; + cSkinString mX2; + cSkinString mY2; + cSkinString mWidth; + cSkinString mHeight; cSkinColor mColor; cSkinColor mBackgroundColor; bool mFilled; @@ -133,13 +139,15 @@ private: eTextVerticalAlignment mVerticalAlign; bool mMultiline; cSkinString mPath; - cSkinString mCurrent; - cSkinString mTotal; + cSkinString mCurrent; // progress bar: current value + cSkinString mTotal; // progress bar: maximum valid value + cSkinString mPeak; // progress bar: peak value (<= 0: disabled) cSkinString mFont; cSkinString mText; cSkinFunction * mCondition; eEffect mEffect; // effect: none, shadow, or outline cSkinColor mEffectColor; // effect colour (= shadow colour or colour of outline) + cSkinColor mPeakColor; // colour of peak marker uint64_t mLastChange; // timestamp: last change in dynamic object (scroll, frame change, ...) int mChangeDelay; // delay between two changes (frame change, scrolling, ...) @@ -176,8 +184,8 @@ public: bool ParseEffect(const std::string &Text); bool ParseFontFace(const std::string &Text); bool ParseIntParam(const std::string &Text, int & Param); - bool ParseWidth(const std::string &Text); - bool ParseHeight(const std::string &Text); + //bool ParseWidth(const std::string &Text); + //bool ParseHeight(const std::string &Text); bool ParseScrollLoopMode(const std::string & Text); // parse scroll mode ([never|once|always]) bool ParseScrollSpeed(const std::string & Text); // parse scroll speed diff --git a/glcdskin/parser.c b/glcdskin/parser.c index 71df8e1..a06ebc4 100644 --- a/glcdskin/parser.c +++ b/glcdskin/parser.c @@ -262,14 +262,20 @@ bool StartElem(const std::string & name, std::map<std::string,std::string> & att if (object->ParseType(name)) { - ATTRIB_OPT_FUNC_PARAM("x", object->ParseIntParam, object->mPos1.x); - ATTRIB_OPT_FUNC_PARAM("y", object->ParseIntParam, object->mPos1.y); - ATTRIB_OPT_FUNC_PARAM("x1", object->ParseIntParam, object->mPos1.x); - ATTRIB_OPT_FUNC_PARAM("y1", object->ParseIntParam, object->mPos1.y); - ATTRIB_OPT_FUNC_PARAM("x2", object->ParseIntParam, object->mPos2.x); - ATTRIB_OPT_FUNC_PARAM("y2", object->ParseIntParam, object->mPos2.y); - ATTRIB_OPT_FUNC("width", object->ParseWidth); - ATTRIB_OPT_FUNC("height", object->ParseHeight); + object->mX1.Parse("0"); + object->mY1.Parse("0"); + object->mX2.Parse("-1"); + object->mY2.Parse("-1"); + object->mWidth.Parse("0"); + object->mHeight.Parse("0"); + ATTRIB_OPT_FUNC("x", object->mX1.Parse); + ATTRIB_OPT_FUNC("y", object->mY1.Parse); + ATTRIB_OPT_FUNC("x1", object->mX1.Parse); + ATTRIB_OPT_FUNC("y1", object->mY1.Parse); + ATTRIB_OPT_FUNC("x2", object->mX2.Parse); + ATTRIB_OPT_FUNC("y2", object->mY2.Parse); + ATTRIB_OPT_FUNC("width", object->mWidth.Parse); + ATTRIB_OPT_FUNC("height", object->mHeight.Parse); ATTRIB_OPT_FUNC("condition", object->ParseCondition); ATTRIB_OPT_STRING("action", object->mAction); @@ -335,6 +341,9 @@ bool StartElem(const std::string & name, std::map<std::string,std::string> & att ATTRIB_OPT_NUMBER("direction", object->mDirection); ATTRIB_OPT_FUNC("current", object->mCurrent.Parse); ATTRIB_OPT_FUNC("total", object->mTotal.Parse); + ATTRIB_OPT_FUNC("peak", object->mPeak.Parse); + ATTRIB_OPT_FUNC_PARAM("peakcolor", object->ParseColor, object->mPeakColor); + ATTRIB_OPT_NUMBER("radius", object->mRadius); } #if 0 else if (name == "item") { diff --git a/glcdskin/string.c b/glcdskin/string.c index a174964..bc3070d 100644 --- a/glcdskin/string.c +++ b/glcdskin/string.c @@ -274,6 +274,17 @@ cType cSkinString::Evaluate(void) const pos = idxstart; } result_trans.append(result_raw.substr(pos)); + + // re-evaluate resulting string + if ((mText.size() > 0) && mText[0] != '#' && mObject != NULL ) { + cSkinFunction *result = new cSkinFunction(mObject); + if (result->Parse(result_trans)) { + std::string result_rescan = (std::string)result->Evaluate(); + if (result_rescan != "") + result_trans = result_rescan; + } + delete result; + } return result_trans; } |