diff options
Diffstat (limited to 'glcdskin/object.c')
-rw-r--r-- | glcdskin/object.c | 270 |
1 files changed, 265 insertions, 5 deletions
diff --git a/glcdskin/object.c b/glcdskin/object.c index c79fa59..5195806 100644 --- a/glcdskin/object.c +++ b/glcdskin/object.c @@ -3,6 +3,7 @@ #include "skin.h" #include "cache.h" #include "function.h" +#include <sys/time.h> namespace GLCD { @@ -43,6 +44,16 @@ cSkinObject::cSkinObject(cSkinDisplay * Parent) mFont(this, false), mText(this, false), mCondition(NULL), + mLastChange(0), + mChangeDelay(-1), // delay between two images frames: -1: not animated / don't care + mStoredImagePath(""), + mImageFrameId(0), // start with 1st frame + 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) + mScrollTime(0), // scroll time interval: default (0) + mScrollOffset(0), // scroll offset (pixels) + mCurrText(""), mObjects(NULL) { } @@ -66,6 +77,16 @@ cSkinObject::cSkinObject(const cSkinObject & Src) mFont(Src.mFont), mText(Src.mText), mCondition(Src.mCondition), + mLastChange(0), + mChangeDelay(-1), + mStoredImagePath(""), + mImageFrameId(0), + mScrollLoopMode(Src.mScrollLoopMode), + mScrollLoopReached(Src.mScrollLoopReached), + mScrollSpeed(Src.mScrollSpeed), + mScrollTime(Src.mScrollTime), + mScrollOffset(Src.mScrollOffset), + mCurrText(Src.mCurrText), mObjects(NULL) { if (Src.mObjects) @@ -181,6 +202,50 @@ bool cSkinObject::ParseFontFace(const std::string & Text) return mFont.Parse(Text); } + +bool cSkinObject::ParseScrollLoopMode(const std::string & Text) +{ + if (Text == "never") + mScrollLoopMode = 0; + else if (Text == "once") + mScrollLoopMode = 1; + else if (Text == "always") + mScrollLoopMode = 2; + else + return false; + return true; +} + +bool cSkinObject::ParseScrollSpeed(const std::string & Text) +{ + int val; + if (!ParseIntParam(Text, val)) + return false; + + if (val < 0 || val > 10) + return false; + + mScrollSpeed = val; + return true; +} + +bool cSkinObject::ParseScrollTime(const std::string & Text) +{ + int val; + if (!ParseIntParam(Text, val)) + return false; + + if (val < 0 || val > 2000) + return false; + + if (val > 0 && val < 100) + val = 100; + + mScrollTime = val; + return true; +} + + void cSkinObject::SetListIndex(int MaxItems, int Index) { mText.SetListIndex(MaxItems, Index); @@ -211,22 +276,63 @@ tSize cSkinObject::Size(void) const void cSkinObject::Render(GLCD::cBitmap * screen) { + struct timeval tv; + uint64_t timestamp; + if (mCondition != NULL && !mCondition->Evaluate()) return; + gettimeofday(&tv, 0); + timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000; + switch (Type()) { case cSkinObject::image: { cImageCache * cache = mSkin->ImageCache(); - GLCD::cImage * image = cache->Get(mPath.Evaluate()); + int currScrollLoopMode = 2; //default if not configured in the skin: always + + cType evalPath = mPath.Evaluate(); + std::string currPath = evalPath; + + if (currPath != mStoredImagePath) { + mImageFrameId = 0; + mStoredImagePath = currPath; + mScrollLoopReached = false; + mLastChange = timestamp; + } + + GLCD::cImage * image = cache->Get(evalPath); if (image) { - const GLCD::cBitmap * bitmap = image->GetBitmap(); + int framecount = image->Count(); + + const GLCD::cBitmap * bitmap = image->GetBitmap(mImageFrameId); + if (bitmap) { screen->DrawBitmap(Pos().x, Pos().y, *bitmap, mColor); } + + if (mScrollLoopMode != -1) // if == -1: currScrollLoopMode already contains correct value + currScrollLoopMode = mScrollLoopMode; + + mChangeDelay = image->Delay(); + if (mChangeDelay != -1 && currScrollLoopMode > 0 && !mScrollLoopReached && framecount > 1) { + + if ( (int)(timestamp - mLastChange) >= mChangeDelay) { + + if (currScrollLoopMode == 1 && mImageFrameId+1 == framecount) { + mScrollLoopReached = true; // stop looping and switch to 1st frame + } + + mImageFrameId = (mImageFrameId+1) % framecount; + mLastChange = timestamp; + } + } + + if (mLastChange == 0) + mLastChange = timestamp; } break; } @@ -301,14 +407,49 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } case cSkinObject::text: + case cSkinObject::scrolltext: { cSkinFont * skinFont = mSkin->GetFont(mFont.Evaluate()); + int currScrollLoopMode = 1; // default values if no setup default values available + int currScrollSpeed = 8; + int currScrollTime = 500; + + // get default values from derived config-class if available + tSkinToken token = tSkinToken(); + token.Id = mSkin->Config().GetTokenId("ScrollMode"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollLoopMode = (int)(t); + } + token.Id = mSkin->Config().GetTokenId("ScrollSpeed"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollSpeed = (int)(t); + } + token.Id = mSkin->Config().GetTokenId("ScrollTime"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollTime = (int)(t); + } + if (skinFont) { const cFont * font = skinFont->Font(); std::string text = mText.Evaluate(); + + if (! (text == mCurrText) ) { + mScrollOffset = 0; + mCurrText = text; + mScrollLoopReached = false; + mLastChange = timestamp; + } + if (mMultiline) { + + // scrolling in multiline not supported at the moment + mScrollLoopReached = true; // avoid check in NeedsUpdate() + std::vector <std::string> lines; font->WrapText(Size().w, Size().h, text, lines); for (size_t i = 0; i < lines.size(); i++) @@ -334,6 +475,9 @@ void cSkinObject::Render(GLCD::cBitmap * screen) if (text.find('\t') != std::string::npos && mSkin->Config().GetTabPosition(0, Size().w, *font) > 0) { + // scrolling in texts with tabulators not supported at the moment + mScrollLoopReached = true; // avoid check in NeedsUpdate() + std::string::size_type pos1; std::string::size_type pos2; std::string str; @@ -363,8 +507,12 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { int w = font->Width(text); int x = Pos().x; + bool updateScroll = false; + if (w < Size().w) { + mScrollLoopReached = true; // avoid check in NeedsUpdate() + if (mAlign == taRight) { x += Size().w - w; @@ -373,18 +521,53 @@ void cSkinObject::Render(GLCD::cBitmap * screen) { x += (Size().w - w) / 2; } + } else { + + if (mScrollLoopMode != -1) // if == -1: currScrollLoopMode already contains correct value + currScrollLoopMode = mScrollLoopMode; + + if (mScrollSpeed > 0) + currScrollSpeed = mScrollSpeed; + + if (mScrollTime > 0) + currScrollTime = mScrollTime; + + if (currScrollLoopMode > 0 && (!mScrollLoopReached || mScrollOffset) && + ((int)(timestamp-mLastChange) >= currScrollTime) + ) + { + if (mScrollLoopReached) + mScrollOffset = 0; + else + updateScroll = true; + } + + } + screen->DrawText(x, Pos().y, x + Size().w - 1, text, font, mColor, true, mScrollOffset); + + if (updateScroll) { + mScrollOffset += currScrollSpeed; + + if ( x + Size().w + mScrollOffset > w+Size().w) { + if (currScrollLoopMode == 1) + // reset mScrollOffset in next step (else: string not redrawn when scroll done) + mScrollLoopReached = true; + else + mScrollOffset= 0; + } + updateScroll = false; + mLastChange = timestamp; } - screen->DrawText(x, Pos().y, x + Size().w - 1, text, font, mColor); } } } break; } - case cSkinObject::scrolltext: +// case cSkinObject::scrolltext: //DrawScrolltext(Object->Pos(), Object->Size(), Object->Fg(), Object->Text(), Object->Font(), // Object->Align()); - break; +// break; case cSkinObject::scrollbar: //DrawScrollbar(Object->Pos(), Object->Size(), Object->Bg(), Object->Fg()); @@ -430,6 +613,83 @@ void cSkinObject::Render(GLCD::cBitmap * screen) } } +bool cSkinObject::NeedsUpdate(uint64_t CurrentTime) +{ + if (mCondition != NULL && !mCondition->Evaluate()) + return false; + + switch (Type()) + { + case cSkinObject::image: + { + int currScrollLoopMode = 2; + + if (mScrollLoopMode != -1) + currScrollLoopMode = mScrollLoopMode; + + if ( mChangeDelay > 0 && currScrollLoopMode > 0 && !mScrollLoopReached && + ( (int)(CurrentTime-mLastChange) >= mChangeDelay) + ) + { + return true; + } + return false; + break; + } + case cSkinObject::text: + case cSkinObject::scrolltext: + { + int currScrollLoopMode = 1; // default values if no setup default values available + int currScrollTime = 500; + + // get default values from derived config-class if available + tSkinToken token = tSkinToken(); + token.Id = mSkin->Config().GetTokenId("ScrollMode"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollLoopMode = (int)(t); + } + token.Id = mSkin->Config().GetTokenId("ScrollTime"); + if (token.Id >= 0) { + cType t = mSkin->Config().GetToken(token); + currScrollTime = (int)(t); + } + + if (mScrollLoopMode != -1) // if == -1: currScrollLoopMode already contains correct value + currScrollLoopMode = mScrollLoopMode; + + if (mScrollTime > 0) + currScrollTime = mScrollTime; + + if (currScrollLoopMode > 0 && (!mScrollLoopReached || mScrollOffset) && + (int)(CurrentTime-mLastChange) >= currScrollTime + ) + { + return true; + } + return false; + break; + } + case cSkinObject::progress: + return false; + break; + case cSkinObject::block: + { + for (uint32_t i = 0; i < NumObjects(); i++) { + if ( GetObject(i)->NeedsUpdate(CurrentTime) ) { + return true; + } + } + return false; + break; + } + default: // all other elements are static ones + return false; + } + return false; +} + + cSkinObjects::cSkinObjects(void) { } |