diff options
Diffstat (limited to 'glcdskin/object.c')
-rw-r--r-- | glcdskin/object.c | 594 |
1 files changed, 530 insertions, 64 deletions
diff --git a/glcdskin/object.c b/glcdskin/object.c index ab00a44..796e436 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -4,6 +4,8 @@ #include "cache.h" #include "function.h" +#include <typeinfo> + namespace GLCD { @@ -19,18 +21,27 @@ static const std::string ObjectNames[] = "text", "scrolltext", "scrollbar", + "button", "block", "list", - "item" + "item", + "condblock" }; cSkinObject::cSkinObject(cSkinDisplay * Parent) : mDisplay(Parent), mSkin(Parent->Skin()), mType((eType) __COUNT_OBJECT__), - mPos1(0, 0), - mPos2(-1, -1), - mColor(GLCD::clrBlack), + //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), mRadius(0), mArc(0), @@ -41,13 +52,20 @@ 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)), + mPeakGradientColor(this, cColor(cColor::ERRCOL)), // color for peak or gradient; if ERRCOL -> use mColor + mGradient(tgrdNone), // default: no gradient mLastChange(0), mChangeDelay(-1), // delay between two images frames: -1: not animated / don't care mStoredImagePath(""), mImageFrameId(0), // start with 1st frame + mOpacity(255), // default: full opacity + mScale(tscNone), // scale image: default: don't scale mScrollLoopMode(-1), // scroll (text) or loop (image) mode: default (-1) mScrollLoopReached(false), // if scroll/loop == once: already looped once? mScrollSpeed(0), // scroll speed: default (0) @@ -56,17 +74,29 @@ cSkinObject::cSkinObject(cSkinDisplay * Parent) mCurrText(""), // current text (for checks if text has changed) mAltText(""), // alternative text source for text-objects mAltCondition(NULL), // condition when alternative sources are used + mAction(""), // action (e.g. touchscreen action) + mMultilineScrollPosition(0), + mMultilineRelScroll(this, false), mObjects(NULL) { + mColor.SetColor(Parent->Skin()->Config().GetDriver()->GetForegroundColor()); + mBackgroundColor.SetColor(Parent->Skin()->Config().GetDriver()->GetBackgroundColor()); } 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), mRadius(Src.mRadius), mArc(Src.mArc), @@ -77,13 +107,20 @@ 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), + mPeakGradientColor(Src.mPeakGradientColor), + mGradient(Src.mGradient), mLastChange(0), mChangeDelay(-1), mStoredImagePath(Src.mStoredImagePath), mImageFrameId(0), + mOpacity(Src.mOpacity), + mScale(Src.mScale), mScrollLoopMode(Src.mScrollLoopMode), mScrollLoopReached(Src.mScrollLoopReached), mScrollSpeed(Src.mScrollSpeed), @@ -92,6 +129,9 @@ cSkinObject::cSkinObject(const cSkinObject & Src) mCurrText(Src.mCurrText), mAltText(Src.mAltText), mAltCondition(Src.mAltCondition), + mAction(Src.mAction), + mMultilineScrollPosition(Src.mMultilineScrollPosition), + mMultilineRelScroll(Src.mMultilineRelScroll), mObjects(NULL) { if (Src.mObjects) @@ -116,14 +156,27 @@ bool cSkinObject::ParseType(const std::string & Text) return false; } -bool cSkinObject::ParseColor(const std::string & Text) +bool cSkinObject::ParseColor(const std::string & Text, cSkinColor & ParamColor) { - if (Text == "white") - mColor = GLCD::clrWhite; - else if (Text == "black") - mColor = GLCD::clrBlack; - else + std::string text = (std::string) Text; + cColor color = cColor::ERRCOL; + if (text[0] == '#') { + cSkinVariable * variable = mSkin->GetVariable(text.substr(1)); + if (variable) { + color = cColor::ParseColor(variable->Value().String()); + if (color == cColor::ERRCOL) { + return false; + } + ParamColor.SetVarId(text.substr(1)); + return true; + } return false; + } + color = cColor::ParseColor(text); + if (color == cColor::ERRCOL) { + return false; + } + ParamColor.SetColor(color); return true; } @@ -165,6 +218,51 @@ bool cSkinObject::ParseVerticalAlignment(const std::string & Text) return true; } +bool cSkinObject::ParseEffect(const std::string & Text) +{ + if (Text == "none") + mEffect = tfxNone; + else if (Text == "shadow") + mEffect = tfxShadow; + else if (Text == "outline") + mEffect = tfxOutline; + else + return false; + return true; +} + +bool cSkinObject::ParseScale(const std::string & Text) +{ + if (Text == "none") + mScale = tscNone; + else if (Text == "auto") + mScale = tscAuto; + else if (Text == "autox") + mScale = tscAutoX; + else if (Text == "autoy") + mScale = tscAutoY; + else if (Text == "fill") + mScale = tscFill; + else + return false; + return true; +} + +bool cSkinObject::ParseGradient(const std::string & Text) +{ + if (Text == "none") + mGradient = tgrdNone; + else if (Text == "total" || Text == "default") + mGradient = tgrdTotal; + else if (Text == "current" || Text == "currentonly") + mGradient = tgrdCurrent; + else if (Text == "vertical") + mGradient = tgrdVertical; + else + return false; + return true; +} + bool cSkinObject::ParseIntParam(const std::string &Text, int & Param) { if (isalpha(Text[0]) || Text[0] == '#') @@ -189,6 +287,7 @@ bool cSkinObject::ParseIntParam(const std::string &Text, int & Param) return true; } +#if 0 bool cSkinObject::ParseWidth(const std::string &Text) { int w; @@ -214,6 +313,7 @@ bool cSkinObject::ParseHeight(const std::string &Text) } return false; } +#endif bool cSkinObject::ParseFontFace(const std::string & Text) { @@ -292,16 +392,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); } @@ -332,7 +449,47 @@ void cSkinObject::Render(GLCD::cBitmap * screen) mChangeDelay = -1; } - GLCD::cImage * image = cache->Get(evalPath); + uint16_t scalew = 0; + uint16_t scaleh = 0; + + switch (mScale) { + case tscAuto: + { + uint16_t w_temp = 0; + uint16_t h_temp = 0; + // get dimensions of unscaled image + GLCD::cImage * image = cache->Get(evalPath, w_temp, h_temp); + if (image) { + w_temp = image->Width(); + h_temp = image->Height(); + if (w_temp != Size().w || h_temp != Size().h) { + double fw = (double)Size().w / (double)w_temp; + double fh = (double)Size().h / (double)h_temp; + if (fw < fh) { + scalew = Size().w; + } else { + scaleh = Size().h; + } + } + } + } + break; + case tscAutoX: + scalew = Size().w; + break; + case tscAutoY: + scaleh = Size().h; + break; + case tscFill: + scalew = Size().w; + scaleh = Size().h; + break; + default: + scalew = 0; + scaleh = 0; + } + + GLCD::cImage * image = cache->Get(evalPath, scalew, scaleh); if (image) { int framecount = image->Count(); @@ -341,7 +498,20 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (bitmap) { - screen->DrawBitmap(Pos().x, Pos().y, *bitmap, mColor); + uint16_t xoff = 0; + uint16_t yoff = 0; + if (scalew || scaleh) { + if (image->Width() < (uint16_t)Size().w) { + xoff = (Size().w - image->Width() ) / 2; + } else if (image->Height() < (uint16_t)Size().h) { + yoff = (Size().h - image->Height() ) / 2; + } + } + + if (mColor == cColor::ERRCOL) + screen->DrawBitmap(Pos().x + xoff, Pos().y + yoff, *bitmap); + else + screen->DrawBitmap(Pos().x + xoff, Pos().y + yoff, *bitmap, mColor, mBackgroundColor, mOpacity); } if (mScrollLoopMode != -1) // if == -1: currScrollLoopMode already contains correct value @@ -350,7 +520,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (framecount > 1 && currScrollLoopMode > 0 && !mScrollLoopReached) { mChangeDelay = image->Delay(); - if ( (int)(timestamp - mLastChange) >= mChangeDelay) { + if ( (uint32_t)(timestamp - mLastChange) >= (uint32_t)mChangeDelay) { if (currScrollLoopMode == 1 && mImageFrameId+1 == framecount) { mScrollLoopReached = true; // stop looping and switch to 1st frame @@ -405,33 +575,135 @@ 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 (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); - } - 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); - } - 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 (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 peakGradientColor = (mPeakGradientColor == cColor::ERRCOL) ? mColor : mPeakGradientColor; + + bool gradient = false; + + if (peakGradientColor != mColor) { + if (mGradient != tgrdNone) { + gradient = true; + } else 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 + } } - 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 (! gradient) { + if (mDirection == 0) + { + 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, peakGradientColor, true); + } + else if (mDirection == 1) + { + 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, peakGradientColor, true); + } + else if (mDirection == 2) + { + 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, peakGradientColor, true); + } + else if (mDirection == 3) + { + 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, peakGradientColor, true); + } + } else { + if (currSize > 0) { + int s_a = (mColor & 0xFF000000) >> 24; + int s_r = (mColor & 0x00FF0000) >> 16; + int s_g = (mColor & 0x0000FF00) >> 8; + int s_b = (mColor & 0x000000FF) ; + int delta_a = ((peakGradientColor & 0xFF000000) >> 24) - s_a; + int delta_r = ((peakGradientColor & 0x00FF0000) >> 16) - s_r; + int delta_g = ((peakGradientColor & 0x0000FF00) >> 8) - s_g; + int delta_b = ((peakGradientColor & 0x000000FF) ) - s_b; + int c_a, c_r, c_g, c_b; + double fact; + uint32_t currCol; + int gradSize = 0; + switch (mGradient) { + case tgrdCurrent: gradSize = currSize; break; + case tgrdVertical: gradSize = (mDirection % 2 == 0) ? Size().h : Size().w ; break; + default: gradSize = maxSize; break; + } + + for (int i = 0; i < ((mGradient == tgrdVertical) ? gradSize : currSize); i++) { + fact = (double)i / (double)(gradSize - 1); + c_a = s_a + int( double(delta_a) * fact ); + c_r = s_r + int( double(delta_r) * fact ); + c_g = s_g + int( double(delta_g) * fact ); + c_b = s_b + int( double(delta_b) * fact ); + currCol = (c_a << 24) | (c_r << 16) | (c_g << 8) | c_b; + //fprintf(stderr, "i: %d / %08x -> %08x / currCol: %08x\n", i, (uint32_t)mColor, peakGradientColor, currCol); + if (mGradient == tgrdVertical) { + if (mDirection == 0) + screen->DrawLine(Pos().x, Pos().y + i, + Pos().x + currSize - 1, Pos().y + i, currCol); + else if (mDirection == 2) + screen->DrawLine(Pos().x + Size().w - currSize, Pos().y + i, + Pos().x + Size().w - 1, Pos().y + i, currCol); + else if (mDirection == 1) + screen->DrawLine(Pos().x + Size().w - 1 - i, Pos().y, + Pos().x + Size().w - 1 - i, Pos().y + currSize - 1, currCol); + else if (mDirection == 3) + screen->DrawLine(Pos().x + i, Pos().y + Size().h - currSize, + Pos().x + i, Pos().y + Size().h - 1 , currCol); + } else { + if (mDirection == 0) + screen->DrawLine(Pos().x + i, Pos().y, + Pos().x + i, Pos().y + Size().h - 1, currCol); + else if (mDirection == 2) + screen->DrawLine(Pos().x + Size().w - 1 - i, Pos().y, + Pos().x + Size().w - 1 - i, Pos().y + Size().h - 1, currCol); + else if (mDirection == 1) + screen->DrawLine(Pos().x , Pos().y + i, + Pos().x + Size().w - 1, Pos().y + i, currCol); + else if (mDirection == 3) + screen->DrawLine(Pos().x , Pos().y + Size().h - 1 - i, + Pos().x + Size().w - 1, Pos().y + Size().h - 1 - i , currCol); + } + } + } } break; } @@ -462,8 +734,48 @@ void cSkinObject::Render(GLCD::cBitmap * screen) currScrollTime = (int)(t); } + // amount of loops for effects (no effect: 1 loop) + int loop; + int loops = 1; + int varx[6] = {0, 0, 0, 0, 0, 0}; + int vary[6] = {0, 0, 0, 0, 0, 0}; + uint32_t varcol[6] = { mColor, mColor, mColor, mColor, mColor, mColor }; + + int fxOff = 1; + if (mRadius > 1) + fxOff = 2; + + switch (mEffect) { + case tfxShadow: + loops = 1; + for (int fxi = 0; fxi < fxOff; fxi++) { + varx[fxi] = fxi + 1; vary[fxi] = fxi + 1; + varcol[loops-1] = mEffectColor; + loops++; + } + varcol[loops-1] = cColor::Transparent; + loops++; + break; + case tfxOutline: + loops = 6; + varx[0] = -fxOff; vary[0] = 0; + varx[1] = fxOff; vary[1] = 0; + varx[2] = 0; vary[2] = -fxOff; + varx[3] = 0; vary[3] = fxOff; + varcol[0] = varcol[1] = varcol[2] = varcol[3] = mEffectColor; + varcol[4] = cColor::Transparent; + break; + case tfxNone: // no-one gets forgotten here, so make g++ happy + default: + loops = 1; + } + if (skinFont) { + + cBitmap* pane = new cBitmap(Size().w, Size().h, cColor::Transparent); + pane->SetProcessAlpha(false); + const cFont * font = skinFont->Font(); std::string text = ""; @@ -484,6 +796,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) mCurrText = text; mScrollLoopReached = false; mLastChange = timestamp; + mMultilineScrollPosition = 0; } if (mMultiline) @@ -492,7 +805,24 @@ void cSkinObject::Render(GLCD::cBitmap * screen) mScrollLoopReached = true; // avoid check in NeedsUpdate() std::vector <std::string> lines; - font->WrapText(Size().w, Size().h, text, lines); + font->WrapText(Size().w, 0/*Size().h*/, text, lines); + + size_t amount_lines = Size().h / font->LineHeight(); + + if (amount_lines < lines.size()) { + int multilineRelScroll = mMultilineRelScroll.Evaluate(); + if (multilineRelScroll != 0) { + if (multilineRelScroll < 0) { + mMultilineScrollPosition += multilineRelScroll; + if (mMultilineScrollPosition < 0) + mMultilineScrollPosition = 0; + } else if (multilineRelScroll > 0) { + mMultilineScrollPosition += multilineRelScroll; + if (mMultilineScrollPosition > (int)((lines.size() - amount_lines)) ) + mMultilineScrollPosition = lines.size() - amount_lines; + } + } + } // vertical alignment, calculate y offset int yoff = 0; @@ -507,10 +837,14 @@ void cSkinObject::Render(GLCD::cBitmap * screen) default: yoff = 0; } - for (size_t i = 0; i < lines.size(); i++) + int end_line = amount_lines; + if (amount_lines > lines.size() ) + end_line = lines.size(); + + for (size_t i = 0; i < (size_t)end_line; i++) { - int w = font->Width(lines[i]); - int x = Pos().x; + int w = font->Width(lines[i + mMultilineScrollPosition]); + int x = 0; if (w < Size().w) { if (mAlign == taRight) @@ -522,7 +856,12 @@ void cSkinObject::Render(GLCD::cBitmap * screen) x += (Size().w - w) / 2; } } - screen->DrawText(x, yoff + Pos().y + i * font->LineHeight(), x + Size().w - 1, lines[i], font, mColor); + for (loop = 0; loop < loops; loop++) { + pane->DrawText( + varx[loop] + x, vary[loop] + yoff + i * font->LineHeight(), + x + Size().w - 1, lines[i + mMultilineScrollPosition], font, varcol[loop], mBackgroundColor + ); + } } } else @@ -549,7 +888,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) std::string::size_type pos1; std::string::size_type pos2; std::string str; - int x = Pos().x; + int x = 0; int w = Size().w; int tab = 0; int tabWidth; @@ -560,7 +899,9 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { str = text.substr(pos1, pos2 - pos1); tabWidth = mSkin->Config().GetTabPosition(tab, Size().w, *font); - screen->DrawText(x, yoff + Pos().y, x + tabWidth - 1, str, font, mColor); + for (loop = 0; loop < loops; loop++) { + pane->DrawText( varx[loop] + x, vary[loop] + yoff, x + tabWidth - 1, str, font, varcol[loop], mBackgroundColor ); + } pos1 = pos2 + 1; pos2 = text.find('\t', pos1); tabWidth += font->Width(' '); @@ -569,12 +910,14 @@ void cSkinObject::Render(GLCD::cBitmap * screen) tab++; } str = text.substr(pos1); - screen->DrawText(x, yoff + Pos().y, x + w - 1, str, font, mColor); + for (loop = 0; loop < loops; loop++) { + pane->DrawText( varx[loop] + x, vary[loop] + yoff, x + w - 1, str, font, varcol[loop], mBackgroundColor ); + } } else { int w = font->Width(text); - int x = Pos().x; + int x = 0; bool updateScroll = false; if (w < Size().w) @@ -601,7 +944,7 @@ void cSkinObject::Render(GLCD::cBitmap * screen) currScrollTime = mScrollTime; if (currScrollLoopMode > 0 && (!mScrollLoopReached || mScrollOffset) && - ((int)(timestamp-mLastChange) >= currScrollTime) + ((uint32_t)(timestamp-mLastChange) >= (uint32_t)currScrollTime) ) { if (mScrollLoopReached) @@ -615,22 +958,31 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (mScrollOffset) { int corr_scrolloffset = mScrollOffset; /* object update before scrolltime? use previous offset to avoid 'stumbling' scrolling */ - if ((int)(timestamp-mLastChange) < currScrollTime) { + if ((uint32_t)(timestamp-mLastChange) < (uint32_t)currScrollTime) { corr_scrolloffset -= currScrollSpeed; if (corr_scrolloffset < 0) corr_scrolloffset = 0; } w += font->Width(" "); std::string textdoubled = text + " " + text; - screen->DrawText(x, yoff + Pos().y, x + Size().w - 1, textdoubled, font, mColor, true, corr_scrolloffset); + for (loop = 0; loop < loops; loop++) { + pane->DrawText( + varx[loop] + x, vary[loop] + yoff, x + Size().w - 1, textdoubled, font, + varcol[loop], mBackgroundColor, true, corr_scrolloffset + ); + } } else { - screen->DrawText(x, yoff + Pos().y, x + Size().w - 1, text, font, mColor, true, mScrollOffset); + for (loop = 0; loop < loops; loop++) { + pane->DrawText( + varx[loop] + x, vary[loop] + yoff, x + Size().w - 1, text, font, + varcol[loop], mBackgroundColor, true, mScrollOffset + ); + } } if (updateScroll) { - mScrollOffset += currScrollSpeed; - - if ( x + Size().w + mScrollOffset >= (w+Size().w - font->Width(" "))) { + mScrollOffset += currScrollSpeed; + if ( mScrollOffset >= w ) { if (currScrollLoopMode == 1) // reset mScrollOffset in next step (else: string not redrawn when scroll done) mScrollLoopReached = true; @@ -642,6 +994,8 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } } } + screen->DrawBitmap(Pos().x, Pos().y, *pane, cColor::White, cColor::Transparent); + delete pane; } break; } @@ -651,6 +1005,44 @@ void cSkinObject::Render(GLCD::cBitmap * screen) // Object->Align()); // break; + case cSkinObject::button: + { + cSkinFont * skinFont = mSkin->GetFont(mFont.Evaluate()); + + if (mBackgroundColor == mColor || mBackgroundColor == cColor::Transparent) + mBackgroundColor.SetColor( (cColor(mColor).Invert()) ); + + if (mRadius == 0) + screen->DrawRectangle(Pos().x, Pos().y, Pos().x + Size().w - 1, Pos().y + Size().h - 1, mBackgroundColor, true); + else + screen->DrawRoundRectangle(Pos().x, Pos().y, Pos().x + Size().w - 1, Pos().y + Size().h - 1, mBackgroundColor, true, mRadius); + + if (skinFont) + { + const cFont * font = skinFont->Font(); + std::string text = ""; + + text = (std::string) mText.Evaluate(); + + if (! (text == mCurrText) ) { + mCurrText = text; + } + std::vector <std::string> lines; + font->WrapText(Size().w, Size().h, text, lines); + + // always use middle vertical alignment for buttons + int diff = Size().h - lines.size() * font->LineHeight(); + int yoff = (diff > 0) ? diff >> 1 : 0; + + int w = font->Width(text); + int x = Pos().x; + if (w < Size().w) // always center alignment for buttons + x += (Size().w - w) / 2; + screen->DrawText(x, yoff + Pos().y, x + Size().w - 1, text, font, mColor, mBackgroundColor); + } + break; + } + case cSkinObject::scrollbar: //DrawScrollbar(Object->Pos(), Object->Size(), Object->Bg(), Object->Fg()); break; @@ -673,14 +1065,22 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { for (int j = 1; j < (int) NumObjects(); j++) { + int px, py, ph,pw; + 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; + px = obj.Pos().x + Pos().x; // obj.mPos1.x += mPos1.x; + py = obj.Pos().y + Pos().y + yoffset; // obj.mPos1.y += mPos1.y + yoffset; + ph = o->Size().h; // obj.mPos2.y += mPos1.y + yoffset; + pw = o->Size().w; + snprintf(buf, 9, "%d", px); obj.mX1.Parse((const char*)buf); + snprintf(buf, 9, "%d", py); obj.mY1.Parse((const char*)buf); + if (ph > 0) + snprintf(buf, 9, "%d", ph); obj.mHeight.Parse((const char*)buf); + snprintf(buf, 9, "%d", pw); obj.mWidth.Parse((const char*)buf); obj.Render(screen); } yoffset += itemheight; @@ -710,7 +1110,7 @@ bool cSkinObject::NeedsUpdate(uint64_t CurrentTime) currScrollLoopMode = mScrollLoopMode; if ( mChangeDelay > 0 && currScrollLoopMode > 0 && !mScrollLoopReached && - ( (int)(CurrentTime-mLastChange) >= mChangeDelay) + ( (uint32_t)(CurrentTime-mLastChange) >= (uint32_t)mChangeDelay) ) { return true; @@ -720,6 +1120,7 @@ bool cSkinObject::NeedsUpdate(uint64_t CurrentTime) } case cSkinObject::text: case cSkinObject::scrolltext: + //case cSkinObject::button: { int currScrollLoopMode = 1; // default values if no setup default values available int currScrollTime = 500; @@ -759,7 +1160,7 @@ bool cSkinObject::NeedsUpdate(uint64_t CurrentTime) if ( (text != mCurrText) || ( (currScrollLoopMode > 0) && (!mScrollLoopReached || mScrollOffset) && - ((int)(CurrentTime-mLastChange) >= currScrollTime) + ((uint32_t)(CurrentTime-mLastChange) >= (uint32_t)currScrollTime) ) ) { @@ -788,6 +1189,71 @@ bool cSkinObject::NeedsUpdate(uint64_t CurrentTime) } +std::string cSkinObject::CheckAction(cGLCDEvent * ev) +{ + if (mCondition != NULL && !mCondition->Evaluate()) + return ""; + + switch (Type()) + { + case cSkinObject::image: + case cSkinObject::text: + case cSkinObject::scrolltext: + case cSkinObject::progress: + case cSkinObject::rectangle: + case cSkinObject::ellipse: + case cSkinObject::slope: + case cSkinObject::button: + case cSkinObject::item: + { + if (mAction == "") + return ""; + + if (ev && (typeid(*ev) == typeid(cTouchEvent))) { + cTouchEvent * stev = (cTouchEvent*)ev; + // check if touch event is in bounding box of object + // uses > and < -1 instead of >= and < -0 for better results + if ( (stev->x > Pos().x) && (stev->x < (Pos().x+Size().w -1)) && + (stev->y > Pos().y) && (stev->y < (Pos().y+Size().h -1)) + ) + { + return mAction; + } + } + return ""; + break; + } + case cSkinObject::block: + { + std::string rv = ""; + for (uint32_t i = 0; i < NumObjects(); i++) { + if ( (rv = GetObject(i)->CheckAction(ev)) != "" ) { + return rv; + } + } + return ""; + break; + } + default: + return ""; + } + return ""; +} + + + +uint32_t cSkinColor::GetColor(void) { + if (mVarId != "") { + cSkinVariable * variable = mObject->Skin()->GetVariable(mVarId); + if (variable) { + return cColor::ParseColor(variable->Value().String()); + } + return cColor::ERRCOL; + } + return (uint32_t) mColor; +} + + cSkinObjects::cSkinObjects(void) { } |