diff options
Diffstat (limited to 'recmenuitem.c')
-rw-r--r-- | recmenuitem.c | 2016 |
1 files changed, 2016 insertions, 0 deletions
diff --git a/recmenuitem.c b/recmenuitem.c new file mode 100644 index 0000000..eb931e9 --- /dev/null +++ b/recmenuitem.c @@ -0,0 +1,2016 @@ +#include <math.h> +#include <vdr/remote.h> +#include "recmenuitem.h" + +// --- cRecMenuItem ------------------------------------------------------------- + +cRecMenuItem::cRecMenuItem(void) { + height = 0; + action = rmsNotConsumed; + drawn = false; + font = tvguideConfig.FontRecMenuItem; + fontSmall = tvguideConfig.FontRecMenuItemSmall; +} + +cRecMenuItem::~cRecMenuItem(void) { +} + +void cRecMenuItem::SetGeometry(int x, int y, int width) { + this->x = x; + this->y = y; + this->width = width; + +} + +void cRecMenuItem::SetPixmaps(void) { + if (!pixmap) + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + else + pixmap->SetViewPort(cRect(x, y, width, height)); +} + +void cRecMenuItem::setBackground(void) { + if (active) { + color = theme.Color(clrHighlight); + colorBlending = theme.Color(clrHighlightBlending); + colorText = theme.Color(clrFontActive); + } else { + color = theme.Color(clrGrid1); + colorBlending = theme.Color(clrGrid1Blending); + colorText = theme.Color(clrFont); + } + colorTextBack = (tvguideConfig.useBlending==0)?color:clrTransparent; + drawBackground(); + drawBorder(); +} + +// --- cRecMenuItemButton ------------------------------------------------------- + +cRecMenuItemButton::cRecMenuItemButton(const char *text, eRecMenuState action, bool active, bool halfWidth) { + selectable = true; + this->text = text; + this->action = action; + this->active = active; + height = 3 * font->Height() / 2; + this->halfWidth = halfWidth; +} + +cRecMenuItemButton::~cRecMenuItemButton(void) { +} + +int cRecMenuItemButton::GetWidth(void) { + return font->Width(*text); +} + +void cRecMenuItemButton::SetPixmaps(void) { + if (halfWidth) { + x += width / 4; + width = width / 2; + } + if (!pixmap) + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + else + pixmap->SetViewPort(cRect(x, y, width, height)); +} + +void cRecMenuItemButton::Draw(void) { + int y = (height - font->Height()) / 2; + int x = (width - font->Width(*text)) / 2;; + pixmap->DrawText(cPoint(x, y), *text, colorText, colorTextBack, font); +} + +eRecMenuState cRecMenuItemButton::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kOk: + return action; + break; + default: + break; + } + return rmsNotConsumed; +} + + +// --- cRecMenuItemButtonYesNo ------------------------------------------------------- +cRecMenuItemButtonYesNo::cRecMenuItemButtonYesNo(cString textYes, + cString textNo, + eRecMenuState actionYes, + eRecMenuState actionNo, + bool active) { + selectable = true; + this->textYes = textYes; + this->textNo = textNo; + this->action = actionYes; + this->actionNo = actionNo; + this->active = active; + yesActive = true; + height = 3 * font->Height() / 2; + pixmapNo = NULL; +} + +cRecMenuItemButtonYesNo::~cRecMenuItemButtonYesNo(void) { + if (pixmapNo) + delete pixmapNo; +} + +void cRecMenuItemButtonYesNo::SetPixmaps(void) { + int buttonWidth = 44 * width / 100; + int yesX = x + width / 25; + int noX = x + 52 * width / 100; + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(yesX, y, buttonWidth, height)); + pixmapNo = new cStyledPixmap(osdManager.requestPixmap(4, cRect(noX, y, buttonWidth, height))); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapNo->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemButtonYesNo::Hide(void) { + pixmap->SetLayer(-1); + pixmapNo->SetLayer(-1); +} + +void cRecMenuItemButtonYesNo::Show(void) { + pixmap->SetLayer(4); + pixmapNo->SetLayer(4); +} + +void cRecMenuItemButtonYesNo::setBackground() { + if (active) { + if (yesActive) { + color = theme.Color(clrHighlight); + colorBlending = theme.Color(clrHighlightBlending); + colorText = theme.Color(clrFontActive); + pixmapNo->setColor( theme.Color(clrGrid1), + theme.Color(clrGrid1Blending)); + colorTextNo = theme.Color(clrFont); + } else { + color = theme.Color(clrGrid1); + colorBlending = theme.Color(clrGrid1Blending); + colorText = theme.Color(clrFont); + pixmapNo->setColor( theme.Color(clrHighlight), + theme.Color(clrHighlightBlending)); + colorTextNo = theme.Color(clrFontActive); + } + } else { + color = theme.Color(clrGrid1); + colorBlending = theme.Color(clrGrid1Blending); + colorText = theme.Color(clrFont); + pixmapNo->setColor( theme.Color(clrGrid1), + theme.Color(clrGrid1Blending)); + colorTextNo = theme.Color(clrFont); + } + colorTextBack = (tvguideConfig.useBlending==0)?color:clrTransparent; + drawBackground(); + drawBorder(); + pixmapNo->drawBackground(); + pixmapNo->drawBorder(); +} + +void cRecMenuItemButtonYesNo::Draw(void) { + int textYesX = (pixmap->ViewPort().Width() - font->Width(*textYes)) / 2; + int textNoX = (pixmapNo->Width() - font->Width(*textNo)) / 2; + int textY = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(textYesX, textY), *textYes, colorText, clrTransparent, font); + pixmapNo->DrawText(cPoint(textNoX, textY), *textNo, colorTextNo, clrTransparent, font); +} + +eRecMenuState cRecMenuItemButtonYesNo::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + if (!yesActive) { + yesActive = true; + setBackground(); + Draw(); + return rmsConsumed; + } else + return rmsNotConsumed; + break; + case kRight: + if (yesActive) { + yesActive = false; + setBackground(); + Draw(); + return rmsConsumed; + } else + return rmsNotConsumed; + break; + case kOk: + if (yesActive) + return action; + return actionNo; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemInfo ------------------------------------------------------- +cRecMenuItemInfo::cRecMenuItemInfo(const char *text) { + selectable = false; + active = false; + this->text = text; + border = 10; +} + +cRecMenuItemInfo::~cRecMenuItemInfo(void) { +} + +void cRecMenuItemInfo::CalculateHeight(int textWidth) { + wrapper.Set(*text, font, textWidth); + height = font->Height() * wrapper.Lines() + 2*border; +} + +void cRecMenuItemInfo::setBackground(void) { + pixmap->Fill(clrTransparent); +} + +void cRecMenuItemInfo::Draw(void) { + int lines = wrapper.Lines(); + int lineHeight = font->Height(); + int x = 0; + int y = border; + for (int i = 0; i < lines; i++) { + x = (width - font->Width(wrapper.GetLine(i))) / 2; + pixmap->DrawText(cPoint(x,y), wrapper.GetLine(i), theme.Color(clrFont), clrTransparent, font); + y += lineHeight; + } +} + +// --- cRecMenuItemInt ------------------------------------------------------- +cRecMenuItemInt::cRecMenuItemInt(cString text, + int initialVal, + int minVal, + int maxVal, + bool active) { + selectable = true; + this->text = text; + this->currentVal = initialVal; + this->minVal = minVal; + this->maxVal = maxVal; + this->active = active; + height = 3 * font->Height() / 2; + pixmapVal = NULL; + fresh = true; +} + +cRecMenuItemInt::~cRecMenuItemInt(void) { + if (pixmapVal) + osdManager.releasePixmap(pixmapVal); +} + +void cRecMenuItemInt::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapVal->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemInt::Hide(void) { + pixmap->SetLayer(-1); + pixmapVal->SetLayer(-1); +} + +void cRecMenuItemInt::Show(void) { + pixmap->SetLayer(4); + pixmapVal->SetLayer(5); +} + +void cRecMenuItemInt::setBackground() { + cRecMenuItem::setBackground(); + fresh = true; +} + +void cRecMenuItemInt::Draw(void) { + int textY = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font); + DrawValue(); +} + +void cRecMenuItemInt::DrawValue(void) { + pixmapVal->Fill(clrTransparent); + cString textVal = cString::sprintf("%d", currentVal); + int textX = width - font->Width(*textVal) - 10; + int textY = (height - font->Height()) / 2; + pixmapVal->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font); +} + +eRecMenuState cRecMenuItemInt::ProcessKey(eKeys Key) { + int oldValue = currentVal; + switch (Key & ~k_Repeat) { + case kLeft: + fresh = true; + if (currentVal > minVal) { + currentVal--; + DrawValue(); + } + return rmsConsumed; + break; + case kRight: + fresh = true; + if (currentVal < maxVal) { + currentVal++; + DrawValue(); + } + return rmsConsumed; + break; + case k0 ... k9: + if (fresh) { + currentVal = 0; + fresh = false; + } + currentVal = currentVal * 10 + (Key - k0); + if (!((currentVal >= minVal) && (currentVal <= maxVal))) + currentVal = oldValue; + DrawValue(); + return rmsConsumed; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemBool ------------------------------------------------------- +cRecMenuItemBool::cRecMenuItemBool(cString text, + bool initialVal, + bool refresh, + bool active) { + selectable = true; + this->text = text; + this->yes = initialVal; + this->refresh = refresh; + this->active = active; + height = 3 * font->Height() / 2; + pixmapVal = NULL; +} + +cRecMenuItemBool::~cRecMenuItemBool(void) { + if (pixmapVal) + osdManager.releasePixmap(pixmapVal); +} + +void cRecMenuItemBool::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapVal->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemBool::Hide(void) { + pixmap->SetLayer(-1); + pixmapVal->SetLayer(-1); +} + +void cRecMenuItemBool::Show(void) { + pixmap->SetLayer(4); + pixmapVal->SetLayer(5); +} + +void cRecMenuItemBool::Draw(void) { + int textY = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font); + DrawValue(); +} + +void cRecMenuItemBool::DrawValue(void) { + pixmapVal->Fill(clrTransparent); + cString strIcon = yes?"yes":"no"; + int iconSize = height - 8; + int iconX = width - iconSize - 10; + int iconY = (height - iconSize) / 2; + cImageLoader imgLoader; + if (imgLoader.LoadIcon(strIcon, iconSize)) { + cImage icon = imgLoader.GetImage(); + pixmapVal->DrawImage(cPoint(iconX, iconY), icon); + } +} + +eRecMenuState cRecMenuItemBool::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + case kRight: + yes = !yes; + DrawValue(); + if (refresh) + return rmsRefresh; + else + return rmsConsumed; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemSelect ------------------------------------------------------- +cRecMenuItemSelect::cRecMenuItemSelect(cString text, + const char * const *Strings, + int initialVal, + int numValues, + bool active) { + selectable = true; + this->text = text; + strings = Strings; + this->numValues = numValues; + if ((initialVal < 0) || (initialVal > numValues-1)) + this->currentVal = 0; + else + this->currentVal = initialVal; + this->active = active; + height = 3 * font->Height() / 2; + pixmapVal = NULL; +} + +cRecMenuItemSelect::~cRecMenuItemSelect(void) { + if (pixmapVal) + osdManager.releasePixmap(pixmapVal); +} + +void cRecMenuItemSelect::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapVal->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemSelect::Hide(void) { + pixmap->SetLayer(-1); + pixmapVal->SetLayer(-1); +} + +void cRecMenuItemSelect::Show(void) { + pixmap->SetLayer(4); + pixmapVal->SetLayer(5); +} + +void cRecMenuItemSelect::Draw(void) { + int textY = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font); + DrawValue(); +} + +void cRecMenuItemSelect::DrawValue(void) { + pixmapVal->Fill(clrTransparent); + const char *textVal = strings[currentVal]; + int iconSize = min(128, height); + int textX = width - font->Width(textVal) - iconSize; + int textY = (height - font->Height()) / 2; + pixmapVal->DrawText(cPoint(textX, textY), textVal, colorText, clrTransparent, font); + int iconLeftX = textX - iconSize; + int iconRightX = width - iconSize; + int iconY = (height - iconSize) / 2; + cImageLoader imgLoader; + if (imgLoader.LoadIcon("arrow_left", iconSize)) { + cImage icon = imgLoader.GetImage(); + pixmapVal->DrawImage(cPoint(iconLeftX, iconY), icon); + } + if (imgLoader.LoadIcon("arrow_right", iconSize)) { + cImage icon = imgLoader.GetImage(); + pixmapVal->DrawImage(cPoint(iconRightX, iconY), icon); + } +} + +eRecMenuState cRecMenuItemSelect::ProcessKey(eKeys Key) { + int oldValue = currentVal; + switch (Key & ~k_Repeat) { + case kLeft: + currentVal--; + if (currentVal<0) + currentVal = numValues - 1; + DrawValue(); + return rmsConsumed; + break; + case kRight: + currentVal = (currentVal+1)%numValues; + DrawValue(); + return rmsConsumed; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemText ------------------------------------------------------- +cRecMenuItemText::cRecMenuItemText(cString title, + char *initialVal, + int length, + bool active) { + selectable = true; + this->title = title; + value = initialVal; + this->active = active; + height = 3 * font->Height(); + pixmapVal = NULL; + pixmapKeyboard = NULL; + pixmapKeyboardHighlight = NULL; + pixmapKeyboardIcons = NULL; + keyboardWidth = 50; + gridHeight = 3 * fontSmall->Height(); + keyboardHeight = 5 * gridHeight; + + this->length = length; + allowed = trVDR(FileNameChars); + pos = -1; + offset = 0; + insert = uppercase = false; + newchar = true; + lengthUtf8 = 0; + valueUtf8 = NULL; + allowedUtf8 = NULL; + charMapUtf8 = NULL; + currentCharUtf8 = NULL; + lastKey = kNone; + keyboardDrawn = false; +} + +cRecMenuItemText::~cRecMenuItemText(void) { + if (pixmapVal) + osdManager.releasePixmap(pixmapVal); + if (pixmapKeyboard) + delete pixmapKeyboard; + if (pixmapKeyboardHighlight) + osdManager.releasePixmap(pixmapKeyboardHighlight); + if (pixmapKeyboardIcons) + osdManager.releasePixmap(pixmapKeyboardIcons); + delete[] valueUtf8; + delete[] allowedUtf8; + delete[] charMapUtf8; +} + +void cRecMenuItemText::SetPixmaps(void) { + int xPixmapVal = x + 20; + int yPixmapVal = y + height / 2 + 10; + int widthPixmapVal = width - 40; + int heightPixmapVal = height / 2 - 20; + int keyboardX = x + (100 - keyboardWidth)*width / 100; + int keyboardY = y + height; + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapVal = osdManager.requestPixmap(5, cRect(xPixmapVal, yPixmapVal, widthPixmapVal, heightPixmapVal)); + pixmapKeyboard = new cStyledPixmap(osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight))); + pixmapKeyboardHighlight = osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight)); + pixmapKeyboardIcons = osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapVal->SetViewPort(cRect(xPixmapVal, yPixmapVal, widthPixmapVal, heightPixmapVal)); + pixmapKeyboard->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight)); + pixmapKeyboardHighlight->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight)); + pixmapKeyboardIcons->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight)); + } + pixmapKeyboardIcons->Fill(clrTransparent); +} + +void cRecMenuItemText::Hide(void) { + pixmap->SetLayer(-1); + pixmapVal->SetLayer(-1); + pixmapKeyboard->SetLayer(-1); + pixmapKeyboardHighlight->SetLayer(-1); + pixmapKeyboardIcons->SetLayer(-1); +} + +void cRecMenuItemText::Show(void) { + pixmap->SetLayer(4); + pixmapVal->SetLayer(5); +} + +void cRecMenuItemText::setBackground() { + if (!active) { + DeactivateKeyboard(); + } + cRecMenuItem::setBackground(); +} + +void cRecMenuItemText::Draw(void) { + int textY = (height/2 - font->Height()) / 2; + pixmap->DrawText(cPoint(10, textY), *title, colorText, colorTextBack, font); + DrawValue(value); +} + +void cRecMenuItemText::DrawValue(char *newValue) { + tColor clrBack = InEditMode()?theme.Color(clrRecMenuTextActiveBack):theme.Color(clrRecMenuTextBack); + pixmapVal->Fill(clrBack); + int textX = pixmapVal->DrawPort().Width() - font->Width(newValue) - 10; + int textY = (pixmapVal->DrawPort().Height() - font->Height()) / 2; + pixmapVal->DrawText(cPoint(textX, textY), newValue, colorText, clrTransparent, font); +} + +void cRecMenuItemText::ActivateKeyboard(void) { + pixmapKeyboard->SetLayer(6); + pixmapKeyboardHighlight->SetLayer(6); + pixmapKeyboardIcons->SetLayer(6); + pixmapKeyboardHighlight->Fill(clrTransparent); + + if (keyboardDrawn) + return; + + pixmapKeyboard->setColor(theme.Color(clrRecMenuKeyboardBack), theme.Color(clrRecMenuKeyboardBack)); + pixmapKeyboard->drawBackground(); + + int widthKeyBoard = pixmapKeyboard->Width(); + gridWidth = widthKeyBoard / 3; + + pixmapKeyboard->DrawRectangle(cRect(0, 0, widthKeyBoard, keyboardHeight), theme.Color(clrRecMenuKeyboardBorder)); + int num = 1; + for (int row = 0; row < 5; row++) { + for (int col = 0; col < 3; col++) { + int X = col*gridWidth; + int Y = row*gridHeight; + tColor clrBack = theme.Color(clrRecMenuKeyboardBack); + if (num==13) + clrBack = theme.Color(clrButtonRedKeyboard); + else if (num==14) + clrBack = theme.Color(clrButtonGreenKeyboard); + else if (num==15) + clrBack = theme.Color(clrButtonYellowKeyboard); + pixmapKeyboard->DrawRectangle(cRect(X+2, Y+2, gridWidth-4, gridHeight-4), clrBack); + pixmapKeyboard->DrawEllipse(cRect(X, Y, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-2); + pixmapKeyboard->DrawEllipse(cRect(X, Y+gridHeight-20, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-3); + pixmapKeyboard->DrawEllipse(cRect(X+gridWidth-20, Y+gridHeight-20, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-4); + pixmapKeyboard->DrawEllipse(cRect(X+gridWidth-20, Y, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-1); + bool draw = false; + bool drawIcon = false; + cString strNum; + cString strIcon; + cImageLoader imgLoader; + if (num<10) { + strNum = *cString::sprintf("%d", num); + draw = true; + } else if (num == 11) { + strNum = *cString::sprintf("%d", 0); + draw = true; + } else if (num==13) { + strIcon = "icon_shift"; + drawIcon = true; + } else if (num==14) { + strIcon = "icon_del_ins"; + drawIcon = true; + } else if (num==15) { + strIcon = "icon_backspace"; + drawIcon = true; + } + if (draw) { + int numX = X + (gridWidth - font->Width(*strNum))/2; + int numY = Y + font->Height() / 4; + pixmapKeyboard->DrawText(cPoint(numX, numY), *strNum, colorText, colorTextBack, font); + char *smsKeys = GetSMSKeys(num); + int smsKeysX = X + (gridWidth - fontSmall->Width(smsKeys))/2; + int smsKeysY = Y + gridHeight - fontSmall->Height() - 10; + pixmapKeyboard->DrawText(cPoint(smsKeysX, smsKeysY), smsKeys, theme.Color(clrRecMenuKeyboardBorder), colorTextBack, fontSmall); + delete[] smsKeys; + } + if (drawIcon) { + int iconSize = gridHeight - 10; + if (imgLoader.LoadIcon(strIcon, iconSize)) { + cImage icon = imgLoader.GetImage(); + int iconX = X + (gridWidth - iconSize) / 2; + pixmapKeyboardIcons->DrawImage(cPoint(iconX, Y + 5), icon); + } + } + num++; + } + } + keyboardDrawn = true; +} + +void cRecMenuItemText::DeactivateKeyboard(void) { + pixmapKeyboard->SetLayer(-1); + pixmapKeyboardHighlight->SetLayer(-1); + pixmapKeyboardIcons->SetLayer(-1); +} + +void cRecMenuItemText::HighlightSMSKey(int num) { + int x = 0; + int y = 0; + if (num == 0) { + x = gridWidth; + y = 3 * gridHeight; + } else { + x = (num-1)%3 * gridWidth; + y = (num-1)/3 * gridHeight; + } + pixmapKeyboardHighlight->DrawRectangle(cRect(x, y, gridWidth, gridHeight), theme.Color(clrRecMenuKeyboardHigh)); +} + +void cRecMenuItemText::ClearSMSKey(void) { + pixmapKeyboardHighlight->Fill(clrTransparent); +} + + +char *cRecMenuItemText::GetSMSKeys(int num) { + if (num == 11) + num = 0; + if (num > 9) + return NULL; + + currentCharUtf8 = charMapUtf8; + int pos = num; + while (pos > 0 && *currentCharUtf8) { + if (*currentCharUtf8++ == '\t') + pos--; + } + while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)) { + currentCharUtf8++; + } + uint *startCharUtf8 = currentCharUtf8; + int numChars = 0; + bool specialChar = false; + while(*currentCharUtf8 && *currentCharUtf8 != '\t' && IsAllowed(*currentCharUtf8)) { + currentCharUtf8++; + if (Utf8CharSet(*currentCharUtf8) > 1) + specialChar = true; + numChars++; + } + char buf[100]; + char *p = buf; + int addition = 0; + if (specialChar) + addition = 1; + Utf8FromArray(startCharUtf8, p, numChars+addition); + int maxChars = min(numChars+1+addition, 8); + char *smskey = new char[maxChars]; + Utf8Strn0Cpy(smskey, p, maxChars); + return smskey; +} + +void cRecMenuItemText::EnterEditMode(void) { + if (!valueUtf8) { + valueUtf8 = new uint[length]; + lengthUtf8 = Utf8ToArray(value, valueUtf8, length); + int l = strlen(allowed) + 1; + allowedUtf8 = new uint[l]; + Utf8ToArray(allowed, allowedUtf8, l); + const char *charMap = trVDR("CharMap$ 0\t-.,1#~\\^$[]|()*+?{}/:%@&\tabc2\tdef3\tghi4\tjkl5\tmno6\tpqrs7\ttuv8\twxyz9"); + l = strlen(charMap) + 1; + charMapUtf8 = new uint[l]; + Utf8ToArray(charMap, charMapUtf8, l); + currentCharUtf8 = charMapUtf8; + AdvancePos(); + } +} + +void cRecMenuItemText::LeaveEditMode(bool SaveValue) { + if (valueUtf8) { + if (SaveValue) { + Utf8FromArray(valueUtf8, value, length); + stripspace(value); + } + lengthUtf8 = 0; + delete[] valueUtf8; + valueUtf8 = NULL; + delete[] allowedUtf8; + allowedUtf8 = NULL; + delete[] charMapUtf8; + charMapUtf8 = NULL; + pos = -1; + offset = 0; + newchar = true; + } +} + +void cRecMenuItemText::AdvancePos(void) { + if (pos < length - 2 && pos < lengthUtf8) { + if (++pos >= lengthUtf8) { + if (pos >= 2 && valueUtf8[pos - 1] == ' ' && valueUtf8[pos - 2] == ' ') + pos--; // allow only two blanks at the end + else { + valueUtf8[pos] = ' '; + valueUtf8[pos + 1] = 0; + lengthUtf8++; + } + } + } + newchar = true; + if (!insert && Utf8is(alpha, valueUtf8[pos])) + uppercase = Utf8is(upper, valueUtf8[pos]); +} + +uint cRecMenuItemText::Inc(uint c, bool Up) { + uint *p = IsAllowed(c); + if (!p) + p = allowedUtf8; + if (Up) { + if (!*++p) + p = allowedUtf8; + } else if (--p < allowedUtf8) { + p = allowedUtf8; + while (*p && *(p + 1)) + p++; + } + return *p; +} + +void cRecMenuItemText::Type(uint c) { + if (insert && lengthUtf8 < length - 1) + Insert(); + valueUtf8[pos] = c; + if (pos < length - 2) + pos++; + if (pos >= lengthUtf8) { + valueUtf8[pos] = ' '; + valueUtf8[pos + 1] = 0; + lengthUtf8 = pos + 1; + } +} + +void cRecMenuItemText::Insert(void) { + memmove(valueUtf8 + pos + 1, valueUtf8 + pos, (lengthUtf8 - pos + 1) * sizeof(*valueUtf8)); + lengthUtf8++; + valueUtf8[pos] = ' '; +} + +void cRecMenuItemText::Delete(void) { + memmove(valueUtf8 + pos, valueUtf8 + pos + 1, (lengthUtf8 - pos) * sizeof(*valueUtf8)); + lengthUtf8--; +} + +uint *cRecMenuItemText::IsAllowed(uint c) { + if (allowedUtf8) { + for (uint *a = allowedUtf8; *a; a++) { + if (c == *a) + return a; + } + } + return NULL; +} + +void cRecMenuItemText::SetText(void) { + if (InEditMode()) { + int textAreaWidth = width - 20; + textAreaWidth -= font->Width("[]"); + textAreaWidth -= font->Width("<>"); // reserving this anyway make the whole thing simpler + if (pos < offset) + offset = pos; + int WidthFromOffset = 0; + int EndPos = lengthUtf8; + for (int i = offset; i < lengthUtf8; i++) { + WidthFromOffset += font->Width(valueUtf8[i]); + if (WidthFromOffset > textAreaWidth) { + if (pos >= i) { + do { + WidthFromOffset -= font->Width(valueUtf8[offset]); + offset++; + } while (WidthFromOffset > textAreaWidth && offset < pos); + EndPos = pos + 1; + } else { + EndPos = i; + break; + } + } + } + char buf[1000]; + char *p = buf; + if (offset) + *p++ = '<'; + p += Utf8FromArray(valueUtf8 + offset, p, sizeof(buf) - (p - buf), pos - offset); + *p++ = '['; + if (insert && newchar) + *p++ = ']'; + p += Utf8FromArray(&valueUtf8[pos], p, sizeof(buf) - (p - buf), 1); + if (!(insert && newchar)) + *p++ = ']'; + p += Utf8FromArray(&valueUtf8[pos + 1], p, sizeof(buf) - (p - buf), EndPos - pos - 1); + if (EndPos != lengthUtf8) + *p++ = '>'; + *p = 0; + DrawValue(buf); + } else { + DrawValue(value); + } +} + +eRecMenuState cRecMenuItemText::ProcessKey(eKeys Key) { + bool consumed = false; + bool SameKey = NORMALKEY(Key) == lastKey; + ClearSMSKey(); + if (Key != kNone) { + lastKey = NORMALKEY(Key); + } else if (!newchar && k0 <= lastKey && lastKey <= k9 && autoAdvanceTimeout.TimedOut()) { + AdvancePos(); + newchar = true; + currentCharUtf8 = NULL; + SetText(); + return rmsConsumed; + } + + switch ((int)Key) { + case kRed: // Switch between upper- and lowercase characters + if (InEditMode()) { + if (!insert || !newchar) { + uppercase = !uppercase; + valueUtf8[pos] = uppercase ? Utf8to(upper, valueUtf8[pos]) : Utf8to(lower, valueUtf8[pos]); + } + consumed = true; + } + break; + case kGreen: // Toggle insert/overwrite modes + if (InEditMode()) { + insert = !insert; + newchar = true; + consumed = true; + } + break; + case kYellow|k_Repeat: + case kYellow: // Remove the character at the current position; in insert mode it is the character to the right of the cursor + if (InEditMode()) { + if (lengthUtf8 > 1) { + if (!insert || pos < lengthUtf8 - 1) + Delete(); + else if (insert && pos == lengthUtf8 - 1) + valueUtf8[pos] = ' '; // in insert mode, deleting the last character replaces it with a blank to keep the cursor position + // reduce position, if we removed the last character + if (pos == lengthUtf8) + pos--; + } else if (lengthUtf8 == 1) + valueUtf8[0] = ' '; // This is the last character in the string, replace it with a blank + if (Utf8is(alpha, valueUtf8[pos])) + uppercase = Utf8is(upper, valueUtf8[pos]); + newchar = true; + consumed = true; + } + break; + case kLeft|k_Repeat: + case kLeft: + + if (pos > 0) { + if (!insert || newchar) + pos--; + newchar = true; + if (!insert && Utf8is(alpha, valueUtf8[pos])) + uppercase = Utf8is(upper, valueUtf8[pos]); + } + consumed = true; + break; + case kRight|k_Repeat: + case kRight: + if (InEditMode()) { + AdvancePos(); + } else { + EnterEditMode(); + ActivateKeyboard(); + } + consumed = true; + break; + case kUp|k_Repeat: + case kUp: + case kDown|k_Repeat: + case kDown: + if (InEditMode()) { + if (insert && newchar) { + // create a new character in insert mode + if (lengthUtf8 < length - 1) + Insert(); + } + if (uppercase) + valueUtf8[pos] = Utf8to(upper, Inc(Utf8to(lower, valueUtf8[pos]), NORMALKEY(Key) == kUp)); + else + valueUtf8[pos] = Inc( valueUtf8[pos], NORMALKEY(Key) == kUp); + newchar = false; + consumed = true; + } + break; + case k0|k_Repeat ... k9|k_Repeat: + case k0 ... k9: { + if (InEditMode()) { + if (Setup.NumberKeysForChars) { + HighlightSMSKey(NORMALKEY(Key) - k0); + if (!SameKey) { + if (!newchar) + AdvancePos(); + currentCharUtf8 = NULL; + } + if (!currentCharUtf8 || !*currentCharUtf8 || *currentCharUtf8 == '\t') { + // find the beginning of the character map entry for Key + int n = NORMALKEY(Key) - k0; + currentCharUtf8 = charMapUtf8; + while (n > 0 && *currentCharUtf8) { + if (*currentCharUtf8++ == '\t') + n--; + } + // find first allowed character + while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)) + currentCharUtf8++; + } + if (*currentCharUtf8 && *currentCharUtf8 != '\t') { + if (insert && newchar) { + // create a new character in insert mode + if (lengthUtf8 < length - 1) + Insert(); + } + valueUtf8[pos] = *currentCharUtf8; + if (uppercase) + valueUtf8[pos] = Utf8to(upper, valueUtf8[pos]); + // find next allowed character + do { + currentCharUtf8++; + } while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)); + newchar = false; + autoAdvanceTimeout.Set(AUTO_ADVANCE_TIMEOUT); + } + } else { + Type('0' + NORMALKEY(Key) - k0); + } + consumed = true; + } + break; } + case kBack: + case kOk: + if (InEditMode()) { + LeaveEditMode(Key == kOk); + DeactivateKeyboard(); + } else { + EnterEditMode(); + ActivateKeyboard(); + } + consumed = true; + break; + default: + if (InEditMode() && BASICKEY(Key) == kKbd) { + int c = KEYKBD(Key); + if (c <= 0xFF) { + if (IsAllowed(Utf8to(lower, c))) + Type(c); + else { + switch (c) { + case 0x7F: // backspace + if (pos > 0) { + pos--; + ProcessKey(kYellow); + } + break; + default: ; + } + } + } else { + switch (c) { + case kfHome: pos = 0; break; + case kfEnd: pos = lengthUtf8 - 1; break; + case kfIns: ProcessKey(kGreen); + case kfDel: ProcessKey(kYellow); + default: ; + } + } + consumed = true; + } + break; + } + SetText(); + if (consumed) + return rmsConsumed; + return rmsNotConsumed; +} + +// --- cRecMenuItemTime ------------------------------------------------------- +cRecMenuItemTime::cRecMenuItemTime(cString text, + int initialVal, + bool active) { + selectable = true; + this->text = text; + this->value = initialVal; + hh = value / 100; + mm = value % 100; + pos = 0; + fresh = true; + this->active = active; + height = 3 * font->Height() / 2; + pixmapVal = NULL; +} + +cRecMenuItemTime::~cRecMenuItemTime(void) { + if (pixmapVal) + osdManager.releasePixmap(pixmapVal); +} + +void cRecMenuItemTime::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapVal->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemTime::Hide(void) { + pixmap->SetLayer(-1); + pixmapVal->SetLayer(-1); +} + +void cRecMenuItemTime::Show(void) { + pixmap->SetLayer(4); + pixmapVal->SetLayer(5); +} + +void cRecMenuItemTime::Draw(void) { + int textY = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font); + DrawValue(); +} + +void cRecMenuItemTime::DrawValue(void) { + pixmapVal->Fill(clrTransparent); + char buf[10]; + switch (pos) { + case 1: snprintf(buf, sizeof(buf), "%01d-:--", hh / 10); break; + case 2: snprintf(buf, sizeof(buf), "%02d:--", hh); break; + case 3: snprintf(buf, sizeof(buf), "%02d:%01d-", hh, mm / 10); break; + default: snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm); + } + int textX = width - font->Width(buf) - 10; + int textY = (height - font->Height()) / 2; + pixmapVal->DrawText(cPoint(textX, textY), buf, colorText, clrTransparent, font); +} + +eRecMenuState cRecMenuItemTime::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft|k_Repeat: + case kLeft: { + if (--mm < 0) { + mm = 59; + if (--hh < 0) + hh = 23; + } + fresh = true; + value = hh * 100 + mm; + DrawValue(); + return rmsConsumed; + break; } + case kRight|k_Repeat: + case kRight: { + if (++mm > 59) { + mm = 0; + if (++hh > 23) + hh = 0; + } + fresh = true; + value = hh * 100 + mm; + DrawValue(); + return rmsConsumed; + break; } + case k0|k_Repeat ... k9|k_Repeat: + case k0 ... k9: { + if (fresh || pos > 3) { + pos = 0; + fresh = false; + } + int n = Key - k0; + switch (pos) { + case 0: + if (n <= 2) { + hh = n * 10; + mm = 0; + pos++; + } + break; + case 1: + if (hh + n <= 23) { + hh += n; + pos++; + } + break; + case 2: + if (n <= 5) { + mm += n * 10; + pos++; + } + break; + case 3: + if (mm + n <= 59) { + mm += n; + pos++; + } + break; + default: ; + } + value = hh * 100 + mm; + DrawValue(); + return rmsConsumed; + break; } + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemDay ------------------------------------------------------- +cRecMenuItemDay::cRecMenuItemDay(cString text, + time_t initialVal, + bool active) { + selectable = true; + this->text = text; + this->currentVal = cTimer::SetTime(initialVal, 0); + this->active = active; + height = 3 * font->Height() / 2; + pixmapVal = NULL; +} + +cRecMenuItemDay::~cRecMenuItemDay(void) { + if (pixmapVal) + osdManager.releasePixmap(pixmapVal); +} + +void cRecMenuItemDay::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapVal->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemDay::Hide(void) { + pixmap->SetLayer(-1); + pixmapVal->SetLayer(-1); +} + +void cRecMenuItemDay::Show(void) { + pixmap->SetLayer(4); + pixmapVal->SetLayer(5); +} + +void cRecMenuItemDay::Draw(void) { + int textY = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font); + DrawValue(); +} + +void cRecMenuItemDay::DrawValue(void) { + pixmapVal->Fill(clrTransparent); + cString textVal = DateString(currentVal); + int textX = width - font->Width(*textVal) - 10; + int textY = (height - font->Height()) / 2; + pixmapVal->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font); +} + +eRecMenuState cRecMenuItemDay::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + currentVal -= 60*60*24; + DrawValue(); + return rmsConsumed; + break; + case kRight: + currentVal += 60*60*24; + DrawValue(); + return rmsConsumed; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemTimer ------------------------------------------------------- +cRecMenuItemTimer::cRecMenuItemTimer(const cTimer *timer, + eRecMenuState action1, + eRecMenuState action2, + eRecMenuState action3, + time_t conflictStart, + time_t conflictStop, + time_t overlapStart, + time_t overlapStop, + bool active) { + selectable = true; + this->timer = timer; + this->action = action1; + this->action2 = action2; + this->action3 = action3; + iconActive = 0; + this->conflictStart = conflictStart; + this->conflictStop = conflictStop; + this->overlapStart = overlapStart; + this->overlapStop = overlapStop; + this->active = active; + height = 3 * font->Height(); + pixmapIcons = NULL; +} + +cRecMenuItemTimer::~cRecMenuItemTimer(void) { + if (pixmapIcons) + osdManager.releasePixmap(pixmapIcons); + if (pixmapStatus) + osdManager.releasePixmap(pixmapStatus); +} + +void cRecMenuItemTimer::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapStatus = osdManager.requestPixmap(5, cRect(x, y, width, height)); + pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapStatus->SetViewPort(cRect(x, y, width, height)); + pixmapIcons->SetViewPort(cRect(x, y, width, height)); + } + pixmapStatus->Fill(clrTransparent); + pixmapIcons->Fill(clrTransparent); +} + +void cRecMenuItemTimer::Hide(void) { + pixmap->SetLayer(-1); + pixmapStatus->SetLayer(-1); + pixmapIcons->SetLayer(-1); +} + +void cRecMenuItemTimer::Show(void) { + pixmap->SetLayer(4); + pixmapStatus->SetLayer(5); + pixmapIcons->SetLayer(6); +} + +void cRecMenuItemTimer::Draw(void) { + const cChannel *channel = timer->Channel(); + cString channelName(""); + int channelTransponder = 0; + if (channel) { + channelName = channel->Name(); + channelTransponder = channel->Transponder(); + } + int logoX = DrawIcons(); + int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio; + cImageLoader imgLoader; + if (!tvguideConfig.hideChannelLogos) { + if (imgLoader.LoadLogo(*channelName, logoWidth, height)) { + cImage logo = imgLoader.GetImage(); + pixmapIcons->DrawImage(cPoint(logoX, 0), logo); + logoX += logoWidth + 5; + } + } + int textX = logoX; + int textHeightLine1 = (height/2 - font->Height()) / 2; + int textHeightLine2 = height/2 - 5 + (height/4 - fontSmall->Height()) / 2; + int textHeightLine3 = 3*height/4 - 5 + (height/4 - fontSmall->Height()) / 2; + const cEvent *event = timer->Event(); + cString timerTitle(""); + if (event) + timerTitle = event->Title(); + cString timeStart = DayDateTime(timer->StartTime()); + cString timeEnd = TimeString(timer->StopTime()); + cString timerTime = cString::sprintf("%s - %s", *timeStart, *timeEnd); + cString channelInfo = cString::sprintf("%s, %s %d", *channelName, tr("Transp."), channelTransponder); + pixmap->DrawText(cPoint(textX, textHeightLine1), *timerTitle, theme.Color(clrFont), clrTransparent, font); + pixmap->DrawText(cPoint(textX, textHeightLine2), *timerTime, theme.Color(clrFont), clrTransparent, fontSmall); + pixmap->DrawText(cPoint(textX, textHeightLine3), *channelInfo, theme.Color(clrFont), clrTransparent, fontSmall); + + DrawTimerConflict(); +} + +int cRecMenuItemTimer::DrawIcons(void) { + int iconsX = 10; + int iconSize = 64; + int iconY = (height - iconSize) / 2; + cString iconInfo, iconDelete, iconEdit; + if (active) { + iconInfo = (iconActive==0)?"info_active":"info_inactive"; + iconDelete = (iconActive==1)?"delete_active":"delete_inactive"; + iconEdit = (iconActive==2)?"edit_active":"edit_inactive"; + } else { + iconInfo = "info_inactive"; + iconDelete = "delete_inactive"; + iconEdit = "edit_inactive"; + } + cImageLoader imgLoader; + if (imgLoader.LoadIcon(iconInfo, iconSize)) { + cImage icon = imgLoader.GetImage(); + pixmapIcons->DrawImage(cPoint(iconsX, iconY), icon); + iconsX += iconSize + 5; + } + if (imgLoader.LoadIcon(iconDelete, iconSize)) { + cImage icon = imgLoader.GetImage(); + pixmapIcons->DrawImage(cPoint(iconsX, iconY), icon); + iconsX += iconSize + 5; + } + if (imgLoader.LoadIcon(iconEdit, iconSize)) { + cImage icon = imgLoader.GetImage(); + pixmapIcons->DrawImage(cPoint(iconsX, iconY), icon); + iconsX += iconSize + 5; + } + return iconsX; +} + +void cRecMenuItemTimer::DrawTimerConflict(void) { + int widthConfl = 30 * width / 100; + int xConfl = width - widthConfl; + int heightConflBar = height / 4; + int yConflBar = (height - heightConflBar) / 2; + pixmapStatus->DrawRectangle(cRect(xConfl, 0, widthConfl, height), theme.Color(clrRecMenuTimerConflictBackground)); + + int completeWidthSecs = conflictStop - conflictStart; + int xConfBar = xConfl + (timer->StartTime() - conflictStart) * widthConfl / completeWidthSecs; + int widthConfBar = (timer->StopTime() - timer->StartTime()) * widthConfl / completeWidthSecs; + pixmapStatus->DrawRectangle(cRect(xConfBar, yConflBar, widthConfBar, heightConflBar), theme.Color(clrRecMenuTimerConflictBar)); + + int xOverlap = xConfl + (overlapStart - conflictStart) * widthConfl / completeWidthSecs; + int widthOverlap = (overlapStop - overlapStart) * widthConfl / completeWidthSecs; + + pixmapIcons->DrawRectangle(cRect(xOverlap, 0, widthOverlap, height), theme.Color(clrRecMenuTimerConflictOverlap)); + + pixmapStatus->DrawRectangle(cRect(xConfl-3,2,1,height-4), theme.Color(clrBorder)); + pixmapStatus->DrawRectangle(cRect(xConfl-2,0,2,height), theme.Color(clrBackground)); +} + +eRecMenuState cRecMenuItemTimer::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: + if (iconActive > 0) { + iconActive--; + DrawIcons(); + return rmsConsumed; + } else + return rmsNotConsumed; + break; + case kRight: + if (iconActive < 2) { + iconActive++; + DrawIcons(); + return rmsConsumed; + } else + return rmsNotConsumed; + break; + case kOk: + if (iconActive == 0) + return action; + else if (iconActive == 1) + return action2; + else if (iconActive == 2) + return action3; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemTimerConflictHeader ------------------------------------------------------- + +cRecMenuItemTimerConflictHeader::cRecMenuItemTimerConflictHeader(time_t conflictStart, + time_t conflictStop, + time_t overlapStart, + time_t overlapStop) { + selectable = false; + active = false; + this->conflictStart = conflictStart; + this->conflictStop = conflictStop; + this->overlapStart = overlapStart; + this->overlapStop = overlapStop; + height = 3*font->Height()/2; + pixmapStatus = NULL; +} + +cRecMenuItemTimerConflictHeader::~cRecMenuItemTimerConflictHeader(void) { + if (pixmapStatus) + osdManager.releasePixmap(pixmapStatus); +} + +void cRecMenuItemTimerConflictHeader::SetPixmaps(void) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapStatus = osdManager.requestPixmap(5, cRect(x, y, width, height)); + pixmapStatus->Fill(clrTransparent); +} + +void cRecMenuItemTimerConflictHeader::Hide(void) { + pixmap->SetLayer(-1); + pixmapStatus->SetLayer(-1); +} + +void cRecMenuItemTimerConflictHeader::Show(void) { + pixmap->SetLayer(4); + pixmapStatus->SetLayer(5); +} + +void cRecMenuItemTimerConflictHeader::setBackground(void) { + pixmap->Fill(clrTransparent); +} + +void cRecMenuItemTimerConflictHeader::Draw(void) { + int widthConfl = 30 * width / 100; + int xConfl = width - widthConfl; + cString headerText = tr("Timer Conflict"); + int xHeader = (xConfl - font->Width(*headerText)) / 2; + int yHeader = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(xHeader, yHeader), *headerText, theme.Color(clrFont), clrTransparent, font); + + pixmap->DrawRectangle(cRect(xConfl, 0, widthConfl, height), theme.Color(clrRecMenuTimerConflictBackground)); + + int completeWidthSecs = conflictStop - conflictStart; + int xOverlap = xConfl + (overlapStart - conflictStart) * widthConfl / completeWidthSecs; + int yOverlap = height - fontSmall->Height(); + int widthOverlap = (overlapStop - overlapStart) * widthConfl / completeWidthSecs; + + pixmapStatus->DrawRectangle(cRect(xOverlap, yOverlap, widthOverlap, height), theme.Color(clrRecMenuTimerConflictOverlap)); + + cString strConflStart = TimeString(conflictStart); + cString strConflStop = TimeString(conflictStop); + cString strOverlapStart = TimeString(overlapStart); + cString strOverlapStop = TimeString(overlapStop); + int y1 = 5; + int y2 = yOverlap; + int xConflStart = xConfl + 2; + int xConflStop = width - fontSmall->Width(*strConflStop) - 2; + int xOverlapStart = xOverlap - fontSmall->Width(*strOverlapStart) - 2; + int xOverlapStop = xOverlap + widthOverlap + 2; + pixmap->DrawText(cPoint(xConflStart, y1), *strConflStart, theme.Color(clrRecMenuTimerConflictBar), clrTransparent, fontSmall); + pixmap->DrawText(cPoint(xConflStop, y1), *strConflStop, theme.Color(clrRecMenuTimerConflictBar), clrTransparent, fontSmall); + pixmap->DrawText(cPoint(xOverlapStart, y2), *strOverlapStart, theme.Color(clrRecMenuTimerConflictOverlap), clrTransparent, fontSmall); + pixmap->DrawText(cPoint(xOverlapStop, y2), *strOverlapStop, theme.Color(clrRecMenuTimerConflictOverlap), clrTransparent, fontSmall); +} + +// --- cRecMenuItemEvent ------------------------------------------------------- +cRecMenuItemEvent::cRecMenuItemEvent(const cEvent *event, + eRecMenuState action1, + eRecMenuState action2, + bool active) { + selectable = true; + this->event = event; + this->action = action1; + this->action2 = action2; + iconActive = 0; + this->active = active; + height = font->Height() + 2*fontSmall->Height() + 10; + pixmapText = NULL; + pixmapIcons = NULL; +} + +cRecMenuItemEvent::~cRecMenuItemEvent(void) { + if (pixmapIcons) + osdManager.releasePixmap(pixmapIcons); + if (pixmapText) + osdManager.releasePixmap(pixmapText); +} + +void cRecMenuItemEvent::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height)); + pixmapText->Fill(clrTransparent); + pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height)); + pixmapIcons->Fill(clrTransparent); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapText->SetViewPort(cRect(x, y, width, height)); + pixmapIcons->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemEvent::Draw(void) { + if (!event) + return; + int logoX = DrawIcons(); + const cChannel *channel = Channels.GetByChannelID(event->ChannelID()); + cString channelName(""); + if (channel) { + channelName = channel->Name(); + } + int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio; + cImageLoader imgLoader; + if (!tvguideConfig.hideChannelLogos) { + if (imgLoader.LoadLogo(*channelName, logoWidth, height)) { + cImage logo = imgLoader.GetImage(); + pixmapText->DrawImage(cPoint(logoX, 0), logo); + logoX += logoWidth + 5; + } + } + + int textX = logoX; + int textHeightLine1 = 5; + int textHeightLine2 = 5 + fontSmall->Height(); + int textHeightLine3 = height - fontSmall->Height() - 5; + + cString title = event->Title(); + cString desc = event->ShortText(); + cString start = DayDateTime(event->StartTime()); + cString end = event->GetEndTimeString(); + + colorText = active?theme.Color(clrFontActive):theme.Color(clrFont); + cString info = cString::sprintf("%s - %s, %s", *start, *end, *channelName); + pixmapText->DrawText(cPoint(textX, textHeightLine1), *info, colorText, clrTransparent, fontSmall); + pixmapText->DrawText(cPoint(textX, textHeightLine2), *title, colorText, clrTransparent, font); + pixmapText->DrawText(cPoint(textX, textHeightLine3), *desc, colorText, clrTransparent, fontSmall); +} + +int cRecMenuItemEvent::DrawIcons(void) { + pixmapIcons->Fill(clrTransparent); + int iconsX = 10; + int iconSize = 64; + int iconY = (height - iconSize) / 2; + cString iconInfo, iconRecord; + if (active) { + iconInfo = (iconActive==0)?"info_active":"info_inactive"; + if (action2 != rmsDisabled) + iconRecord = (iconActive==1)?"record_active":"record_inactive"; + } else { + iconInfo = "info_inactive"; + if (action2 != rmsDisabled) + iconRecord = "record_inactive"; + } + cImageLoader imgLoader; + if (imgLoader.LoadIcon(iconInfo, iconSize)) { + cImage icon = imgLoader.GetImage(); + pixmapIcons->DrawImage(cPoint(iconsX, iconY), icon); + iconsX += iconSize + 5; + } + if ((action2 != rmsDisabled) && imgLoader.LoadIcon(iconRecord, iconSize)) { + cImage icon = imgLoader.GetImage(); + pixmapIcons->DrawImage(cPoint(iconsX, iconY), icon); + iconsX += iconSize + 5; + } + return iconsX; +} + +void cRecMenuItemEvent::Hide(void) { + pixmap->SetLayer(-1); + pixmapText->SetLayer(-1); + pixmapIcons->SetLayer(-1); +} + +void cRecMenuItemEvent::Show(void) { + pixmap->SetLayer(4); + pixmapText->SetLayer(5); + pixmapIcons->SetLayer(6); +} + +eRecMenuState cRecMenuItemEvent::ProcessKey(eKeys Key) { + bool consumed = false; + switch (Key & ~k_Repeat) { + case kLeft: + if (action2 == rmsDisabled) + return rmsNotConsumed; + if (iconActive == 1) { + iconActive = 0; + consumed = true; + } + DrawIcons(); + if (consumed) + return rmsConsumed; + else + return rmsNotConsumed; + break; + case kRight: { + if (action2 == rmsDisabled) + return rmsNotConsumed; + if (iconActive == 0) { + iconActive = 1; + consumed = true; + } + DrawIcons(); + if (consumed) + return rmsConsumed; + else + return rmsNotConsumed; + break; } + case kOk: + if (iconActive == 0) + return action; + else if (iconActive == 1) + return action2; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemChannelChooser ------------------------------------------------------- +cRecMenuItemChannelChooser::cRecMenuItemChannelChooser(cString text, + cChannel *initialChannel, + bool active) { + selectable = true; + this->text = text; + this->channel = initialChannel; + if (initialChannel) + initialChannelSet = true; + else + initialChannelSet = false; + channelNumber = 0; + fresh = true; + this->active = active; + height = 2 * font->Height(); + pixmapChannel = NULL; +} + +cRecMenuItemChannelChooser::~cRecMenuItemChannelChooser(void) { + if (pixmapChannel) + osdManager.releasePixmap(pixmapChannel); +} + +void cRecMenuItemChannelChooser::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapChannel = osdManager.requestPixmap(5, cRect(x, y, width, height)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapChannel->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemChannelChooser::Hide(void) { + pixmap->SetLayer(-1); + pixmapChannel->SetLayer(-1); +} + +void cRecMenuItemChannelChooser::Show(void) { + pixmap->SetLayer(4); + pixmapChannel->SetLayer(5); +} + +void cRecMenuItemChannelChooser::Draw(void) { + int textY = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font); + DrawValue(); +} + +void cRecMenuItemChannelChooser::DrawValue(void) { + pixmapChannel->Fill(clrTransparent); + int textY = (height - font->Height()) / 2; + if (channel) { + cString textVal = cString::sprintf("%d - %s", channel->Number(), channel->Name()); + int textX = width - font->Width(*textVal) - 10; + pixmapChannel->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font); + int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio; + int logoX = textX - logoWidth - 10; + cImageLoader imgLoader; + if (imgLoader.LoadLogo(channel->Name(), logoWidth, height)) { + cImage logo = imgLoader.GetImage(); + pixmapChannel->DrawImage(cPoint(logoX, 0), logo); + } + } else { + cString textVal = tr("all Channels"); + int textX = width - font->Width(*textVal) - 10; + pixmapChannel->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font); + } +} + +int cRecMenuItemChannelChooser::GetIntValue(void) { + if (channel) + return channel->Number(); + return 0; +} + + +eRecMenuState cRecMenuItemChannelChooser::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: { + fresh = true; + if (!channel) + return rmsConsumed; + cChannel *prev = channel; + cChannel *firstChannel = Channels.First(); + if(firstChannel->GroupSep()) + firstChannel = Channels.Next(firstChannel); + if (prev == firstChannel) { + if (!initialChannelSet) + channel = NULL; + } else { + while (prev = Channels.Prev(prev)) { + if(!prev->GroupSep()) { + channel = prev; + break; + } + } + } + DrawValue(); + return rmsConsumed; + break; } + case kRight: { + fresh = true; + if (!channel) { + channel = Channels.First(); + if(channel->GroupSep()) + channel = Channels.Next(channel); + } else { + cChannel *next = channel; + while (next = Channels.Next(next)) { + if(!next->GroupSep()) { + channel = next; + break; + } + } + } + DrawValue(); + return rmsConsumed; + break; } + case k0 ... k9: { + if (fresh) { + channelNumber = 0; + fresh = false; + } + channelNumber = channelNumber * 10 + (Key - k0); + cChannel *chanNew = Channels.GetByNumber(channelNumber); + if (chanNew) { + channel = chanNew; + DrawValue(); + } + return rmsConsumed; + break; } + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemDayChooser ------------------------------------------------------- +cRecMenuItemDayChooser::cRecMenuItemDayChooser(cString text, + int weekdays, + bool active) { + selectable = true; + this->text = text; + this->weekdays = weekdays; + this->active = active; + height = 2 * font->Height(); + selectedDay = 0; + pixmapWeekdays = NULL; + pixmapWeekdaysSelect = NULL; +} + +cRecMenuItemDayChooser::~cRecMenuItemDayChooser(void) { + if (pixmapWeekdays) + osdManager.releasePixmap(pixmapWeekdays); + if (pixmapWeekdaysSelect) + osdManager.releasePixmap(pixmapWeekdaysSelect); +} + +void cRecMenuItemDayChooser::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapWeekdays = osdManager.requestPixmap(5, cRect(x, y, width, height)); + pixmapWeekdaysSelect = osdManager.requestPixmap(6, cRect(x, y, width, height)); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapWeekdays->SetViewPort(cRect(x, y, width, height)); + pixmapWeekdaysSelect->SetViewPort(cRect(x, y, width, height)); + } + SetSizes(); +} + +void cRecMenuItemDayChooser::Hide(void) { + pixmap->SetLayer(-1); + pixmapWeekdays->SetLayer(-1); + pixmapWeekdaysSelect->SetLayer(-1); +} + +void cRecMenuItemDayChooser::Show(void) { + pixmap->SetLayer(4); + pixmapWeekdays->SetLayer(5); + pixmapWeekdaysSelect->SetLayer(6); +} + +void cRecMenuItemDayChooser::SetSizes(void) { + days = trVDR("MTWTFSS"); + int maxWidth = 0; + for (unsigned i=0; i<days.length(); ++i) { + int charWidth = font->Width(days.at(i)); + if (charWidth > maxWidth) + maxWidth = charWidth; + } + daysSize = min(maxWidth + 15, height-4); + daysX = width - 10 - 7*daysSize; + daysY = (height - daysSize) / 2; +} + +void cRecMenuItemDayChooser::setBackground() { + cRecMenuItem::setBackground(); + if (active) { + DrawHighlight(selectedDay); + } else { + DrawHighlight(-1); + } +} + +void cRecMenuItemDayChooser::Draw(void) { + int textY = (height - font->Height()) / 2; + pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font); + DrawDays(); +} + +void cRecMenuItemDayChooser::DrawDays(void) { + pixmapWeekdays->Fill(clrTransparent); + int textY = (height - font->Height()) / 2; + pixmapWeekdays->DrawRectangle(cRect(daysX, daysY, 7*daysSize, daysSize), theme.Color(clrBorder)); + int currentX = daysX; + for (unsigned day=0; day<days.length(); ++day) { + cString strDay = cString::sprintf("%c", days.at(day)); + pixmapWeekdays->DrawRectangle(cRect(currentX+2, daysY+2, daysSize-4, daysSize-4), theme.Color(clrBackground)); + tColor colorDay = WeekDaySet(day)?theme.Color(clrRecMenuDayActive) + :theme.Color(clrRecMenuDayInactive); + int textX = currentX + (daysSize - font->Width(*strDay)) / 2; + pixmapWeekdays->DrawText(cPoint(textX, textY), *strDay, colorDay, clrTransparent, font); + currentX += daysSize; + } +} + +void cRecMenuItemDayChooser::DrawHighlight(int day) { + pixmapWeekdaysSelect->Fill(clrTransparent); + if (day > -1) { + int currentX = daysX + day*daysSize; + pixmapWeekdaysSelect->DrawRectangle(cRect(currentX, daysY, daysSize, daysSize), theme.Color(clrRecMenuDayHighlight)); + } +} + +bool cRecMenuItemDayChooser::WeekDaySet(unsigned day) { + return weekdays & (1 << day); +} + +void cRecMenuItemDayChooser::ToggleDay(void) { + bool dayActive = WeekDaySet(selectedDay); + int dayBit = pow(2, selectedDay); + if (dayActive) { + weekdays -= dayBit; + } else { + weekdays += dayBit; + } +} + +eRecMenuState cRecMenuItemDayChooser::ProcessKey(eKeys Key) { + switch (Key & ~k_Repeat) { + case kLeft: { + selectedDay--; + if (selectedDay<0) + selectedDay += 7; + DrawHighlight(selectedDay); + return rmsConsumed; + break; } + case kRight: { + selectedDay = (selectedDay+1)%7; + DrawHighlight(selectedDay); + return rmsConsumed; + break; } + case kOk: + ToggleDay(); + DrawDays(); + return rmsConsumed; + break; + default: + break; + } + return rmsNotConsumed; +} + +// --- cRecMenuItemRecording ------------------------------------------------------- +cRecMenuItemRecording::cRecMenuItemRecording(cRecording *recording, bool active) { + selectable = true; + this->recording = recording; + this->active = active; + height = font->Height() + 2*fontSmall->Height() + 10; + pixmapText = NULL; +} + +cRecMenuItemRecording::~cRecMenuItemRecording(void) { + if (pixmapText) + osdManager.releasePixmap(pixmapText); +} + +void cRecMenuItemRecording::SetPixmaps(void) { + if (!pixmap) { + pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height)); + pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height)); + pixmapText->Fill(clrTransparent); + } else { + pixmap->SetViewPort(cRect(x, y, width, height)); + pixmapText->SetViewPort(cRect(x, y, width, height)); + } +} + +void cRecMenuItemRecording::Draw(void) { + if (!recording) + return; + const cRecordingInfo *recInfo = recording->Info(); + cChannel *channel = Channels.GetByChannelID(recInfo->ChannelID()); + cString channelName = tr("unknown channel"); + if (channel) + channelName = channel->Name(); + cString name = recording->Name(); + cString dateTime = cString::sprintf("%s, %s", *DateString(recording->Start()), *TimeString(recording->Start())); + + int recDuration = recording->LengthInSeconds() / 60; + + cString recDetails = cString::sprintf("%s: %d %s, %s %s %s \"%s\"", tr("Duration"), recDuration, tr("min"), tr("recorded at"), *dateTime, tr("from"), *channelName); + recDetails = CutText(*recDetails, width - 40, fontSmall).c_str(); + int text1Y = (height/2 - font->Height()) / 2 + 5; + int text2Y = height/2 + (height/2 - fontSmall->Height())/2 - 5; + colorText = active?theme.Color(clrFontActive):theme.Color(clrFont); + pixmapText->DrawText(cPoint(10, text1Y), *name, colorText, clrTransparent, font); + pixmapText->DrawText(cPoint(10, text2Y), *recDetails, colorText, clrTransparent, fontSmall); +} + +void cRecMenuItemRecording::Hide(void) { + pixmap->SetLayer(-1); + pixmapText->SetLayer(-1); +} + +void cRecMenuItemRecording::Show(void) { + pixmap->SetLayer(4); + pixmapText->SetLayer(5); +} |