summaryrefslogtreecommitdiff
path: root/recmenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'recmenu.c')
-rw-r--r--recmenu.c525
1 files changed, 525 insertions, 0 deletions
diff --git a/recmenu.c b/recmenu.c
new file mode 100644
index 0000000..66a5a84
--- /dev/null
+++ b/recmenu.c
@@ -0,0 +1,525 @@
+#include "recmenu.h"
+
+// --- cRecMenu -------------------------------------------------------------
+
+cRecMenu::cRecMenu(void) {
+ border = 10;
+ height = 2*border;
+ headerHeight = 0;
+ footerHeight = 0;
+ scrollHeight = 0;
+ scrollItemHeight = 0;
+ scrollable = false;
+ scrollbarWidth = 3 * border;
+ pixmapScrollBar = NULL;
+ imgScrollBar = NULL;
+ startIndex = 0;
+ stopIndex = 0;
+ numItems = 0;
+ header = NULL;
+ footer = NULL;
+}
+
+cRecMenu::~cRecMenu(void) {
+ if (header)
+ delete header;
+ menuItems.Clear();
+ if (footer)
+ delete footer;
+ if (pixmapScrollBar)
+ osdManager.releasePixmap(pixmapScrollBar);
+ if (imgScrollBar)
+ delete imgScrollBar;
+}
+
+void cRecMenu::SetWidthPercent(int percentOSDWidth) {
+ width = tvguideConfig.osdWidth * percentOSDWidth / 100;
+ x = (tvguideConfig.osdWidth - width) / 2;
+}
+
+void cRecMenu::SetWidthPixel(int pixel) {
+ width = pixel;
+ x = (tvguideConfig.osdWidth - width) / 2;
+}
+
+int cRecMenu::CalculateOptimalWidth(void) {
+ int optWidth = 0;
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ int itemWidth = item->GetWidth();
+ if (itemWidth > optWidth)
+ optWidth = itemWidth;
+ }
+ return optWidth;
+}
+
+
+void cRecMenu::AddMenuItem(cRecMenuItem *item, cRecMenuItem *before) {
+ if (!before)
+ menuItems.Add(item);
+ else
+ menuItems.Ins(item, before);
+}
+
+void cRecMenu::AddMenuItemScroll(cRecMenuItem *item) {
+ scrollHeight += item->GetHeight();
+ stopIndex++;
+ numItems++;
+ if (scrollItemHeight == 0)
+ scrollItemHeight = item->GetHeight();
+ menuItems.Add(item);
+}
+
+bool cRecMenu::CheckHeight(void) {
+ int nextHeight = headerHeight + footerHeight + scrollHeight + 2*border + 150;
+ if (nextHeight > tvguideConfig.osdHeight) {
+ scrollable = true;
+ return false;
+ }
+ return true;
+}
+
+void cRecMenu::CalculateHeight(void) {
+ height = 2*border;
+ if (header)
+ height += headerHeight;
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ height += item->GetHeight();
+ }
+ if (footer)
+ height += footerHeight;
+ y = (tvguideConfig.osdHeight - height) / 2;
+
+ if (scrollable) {
+ width += scrollbarWidth + border;
+ }
+}
+
+void cRecMenu::CreatePixmap(void) {
+ pixmap = osdManager.requestPixmap(3, cRect(x, y, width, height));
+ if (scrollable) {
+ int scrollBarX = x + width - scrollbarWidth - border;
+ int scrollBarY = y + border + headerHeight;
+ int scrollBarHeight = height - headerHeight - footerHeight - 2 * border;
+ pixmapScrollBar = osdManager.requestPixmap(4, cRect(scrollBarX, scrollBarY, scrollbarWidth, scrollBarHeight));
+ }
+}
+
+void cRecMenu::SetFooter(cRecMenuItem *footer) {
+ this->footer = footer;
+ footerHeight = footer->GetHeight();
+ height += footerHeight;
+}
+
+void cRecMenu::SetHeader(cRecMenuItem *header) {
+ this->header = header;
+ headerHeight = header->GetHeight();
+ height += headerHeight;
+}
+
+cRecMenuItem *cRecMenu::GetActiveMenuItem(void) {
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ if (item->isActive())
+ return item;
+ }
+ if (footer && footer->isActive())
+ return footer;
+ return NULL;
+}
+
+int cRecMenu::GetActive(bool withOffset) {
+ int numActive = withOffset?startIndex:0;
+ int i = 0;
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ if (item->isActive()) {
+ numActive += i;
+ break;
+ }
+ i++;
+ }
+ return numActive;
+}
+
+bool cRecMenu::ActivatePrev(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (!scrollable && footer && footer->isActive()) {
+ Activate(footer, menuItems.Last());
+ return true;
+ } else if (activeItem) {
+ cRecMenuItem *prev = NULL;
+ for (cRecMenuItem *item = menuItems.Prev(activeItem); item; item = menuItems.Prev(item)) {
+ if (item->isSelectable()) {
+ prev = item;
+ break;
+ }
+ }
+ if (prev) {
+ Activate(activeItem , prev);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool cRecMenu::ActivateNext(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (activeItem) {
+ cRecMenuItem *next = NULL;
+ for (cRecMenuItem *item = menuItems.Next(activeItem); item; item = menuItems.Next(item)) {
+ if (item->isSelectable()) {
+ next = item;
+ break;
+ }
+ }
+ if (next) {
+ Activate(activeItem , next);
+ return true;
+ } else if (!scrollable && footer && footer->isSelectable()) {
+ Activate(activeItem , footer);
+ return true;
+ }
+ }
+ return false;
+}
+
+void cRecMenu::Activate(cRecMenuItem *itemOld, cRecMenuItem *item) {
+ itemOld->setInactive();
+ itemOld->setBackground();
+ itemOld->Draw();
+ item->setActive();
+ item->setBackground();
+ item->Draw();
+}
+
+void cRecMenu::ScrollUp(void) {
+ if (footer && footer->isActive()) {
+ Activate(footer, menuItems.Last());
+ } else {
+ //get perv x items
+ int numNewItems = numItems / 2;
+ int numAdded = 0;
+ cRecMenuItem *newItem = NULL;
+ while (newItem = GetMenuItem(startIndex-1)) {
+ AddMenuItem(newItem, menuItems.First());
+ menuItems.Del(menuItems.Last(), true);
+ stopIndex--;
+ startIndex--;
+ numAdded++;
+ if (numAdded >= numNewItems)
+ break;
+ }
+ if (numAdded != 0) {
+ Arrange(true);
+ Display(true);
+ ActivatePrev();
+ }
+ }
+}
+
+void cRecMenu::ScrollDown(void) {
+ //get next x items
+ int numNewItems = numItems / 2;
+ int numAdded = 0;
+ cRecMenuItem *newItem = NULL;
+ while (newItem = GetMenuItem(stopIndex)) {
+ menuItems.Add(newItem);
+ menuItems.Del(menuItems.First(), true);
+ stopIndex++;
+ startIndex++;
+ numAdded++;
+ if (numAdded >= numNewItems)
+ break;
+ }
+ if (numAdded != 0) {
+ Arrange(true);
+ Display(true);
+ ActivateNext();
+ } else {
+ //last item reached, activate footer
+ if (footer) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ Activate(activeItem , footer);
+ }
+ }
+}
+
+void cRecMenu::JumpBegin(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (!scrollable) {
+ cRecMenuItem *firstSelectable= NULL;
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ if (item->isSelectable()) {
+ firstSelectable = item;
+ break;
+ }
+ }
+ if (activeItem && firstSelectable) {
+ Activate(activeItem , firstSelectable);
+ }
+ } else {
+ activeItem->setInactive();
+ activeItem->setBackground();
+ if (footer)
+ footer->Draw();
+ menuItems.Clear();
+ int currentItem = 0;
+ cRecMenuItem *newItem = NULL;
+ while (newItem = GetMenuItem(currentItem)) {
+ AddMenuItem(newItem);
+ currentItem++;
+ if (currentItem >= numItems)
+ break;
+ }
+ Arrange(true);
+ startIndex = 0;
+ stopIndex = numItems-1;
+ menuItems.First()->setActive();
+ menuItems.First()->setBackground();
+ menuItems.First()->Draw();
+ Display(true);
+ }
+}
+
+void cRecMenu::JumpEnd(void) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ if (!activeItem)
+ return;
+ if (!scrollable) {
+ cRecMenuItem *lastSelectable= NULL;
+ if (footer && footer->isSelectable()) {
+ lastSelectable = footer;
+ } else {
+ for (cRecMenuItem *item = menuItems.Last(); item; item = menuItems.Prev(item)) {
+ if (item->isSelectable()) {
+ lastSelectable = item;
+ break;
+ }
+ }
+ }
+ if (lastSelectable) {
+ Activate(activeItem , lastSelectable);
+ }
+ } else {
+ activeItem->setInactive();
+ activeItem->setBackground();
+ menuItems.Clear();
+ int totalNumItems = GetTotalNumMenuItems();
+ int currentItem = totalNumItems-1;
+ int itemsAdded = 0;
+ cRecMenuItem *newItem = NULL;
+ while (newItem = GetMenuItem(currentItem)) {
+ AddMenuItem(newItem, menuItems.First());
+ currentItem--;
+ itemsAdded++;
+ if (itemsAdded >= numItems)
+ break;
+ }
+ Arrange(true);
+ stopIndex = totalNumItems;
+ startIndex = stopIndex - numItems;
+ if (footer) {
+ footer->setActive();
+ footer->setBackground();
+ footer->Draw();
+ } else {
+ menuItems.Last()->setActive();
+ menuItems.Last()->setBackground();
+ menuItems.Last()->Draw();
+ }
+ Display(true);
+ }
+}
+
+void cRecMenu::Arrange(bool scroll) {
+ int xElement = x + border;
+ int yElement = y + border;
+ int widthElement = width - 2 * border;
+ if (scrollable)
+ widthElement -= scrollbarWidth + border;
+
+ if (header) {
+ if (!scroll) {
+ header->SetGeometry(xElement, yElement, widthElement);
+ header->SetPixmaps();
+ }
+ yElement += header->GetHeight();
+ }
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ item->SetGeometry(xElement, yElement, widthElement);
+ item->SetPixmaps();
+ yElement += item->GetHeight();
+ }
+ if (footer && !scroll) {
+ footer->SetGeometry(xElement, yElement, widthElement);
+ footer->SetPixmaps();
+ }
+}
+
+void cRecMenu::Display(bool scroll) {
+ pixmap->Fill(theme.Color(clrBackground));
+ drawBorder();
+ if (header && !scroll) {
+ header->setBackground();
+ header->Draw();
+ }
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ item->setBackground();
+ item->Draw();
+ }
+ if (footer && !scroll) {
+ footer->setBackground();
+ footer->Draw();
+ }
+ if (scrollable)
+ DrawScrollBar();
+}
+
+void cRecMenu::Hide(void) {
+ pixmap->SetLayer(-1);
+ if (pixmapScrollBar)
+ pixmapScrollBar->SetLayer(-1);
+ if (header)
+ header->Hide();
+ if (footer)
+ footer->Hide();
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ item->Hide();
+ }
+}
+
+void cRecMenu::Show(void) {
+ pixmap->SetLayer(3);
+ if (pixmapScrollBar)
+ pixmapScrollBar->SetLayer(3);
+ if (header)
+ header->Show();
+ if (footer)
+ footer->Show();
+ for (cRecMenuItem *item = menuItems.First(); item; item = menuItems.Next(item)) {
+ item->Show();
+ }
+}
+
+void cRecMenu::DrawScrollBar(void) {
+ pixmapScrollBar->Fill(theme.Color(clrBorder));
+ pixmapScrollBar->DrawRectangle(cRect(2,2,pixmapScrollBar->ViewPort().Width()-4, pixmapScrollBar->ViewPort().Height() - 4), theme.Color(clrBackground));
+
+ int totalNumItems = GetTotalNumMenuItems();
+ if (imgScrollBar == NULL) {
+ int scrollBarImgHeight = (pixmapScrollBar->ViewPort().Height() - 8) * numItems / totalNumItems;
+ imgScrollBar = createScrollbar(pixmapScrollBar->ViewPort().Width()-8, scrollBarImgHeight, theme.Color(clrHighlight), theme.Color(clrHighlightBlending));
+ }
+ int offset = (pixmapScrollBar->ViewPort().Height() - 8) * startIndex / totalNumItems;
+ pixmapScrollBar->DrawImage(cPoint(4, 2 + offset), *imgScrollBar);
+}
+
+int cRecMenu::GetIntValue(int itemNumber) {
+ cRecMenuItem *item = NULL;
+ item = menuItems.Get(itemNumber);
+ if (item) {
+ return item->GetIntValue();
+ }
+ return -1;
+}
+
+time_t cRecMenu::GetTimeValue(int itemNumber) {
+ cRecMenuItem *item = NULL;
+ item = menuItems.Get(itemNumber);
+ if (item) {
+ return item->GetTimeValue();
+ }
+ return 0;
+}
+
+bool cRecMenu::GetBoolValue(int itemNumber) {
+ cRecMenuItem *item = NULL;
+ item = menuItems.Get(itemNumber);
+ if (item) {
+ return item->GetBoolValue();
+ }
+ return false;
+}
+
+cString cRecMenu::GetStringValue(int itemNumber) {
+ cRecMenuItem *item = NULL;
+ item = menuItems.Get(itemNumber);
+ if (item) {
+ return item->GetStringValue();
+ }
+ return cString("");
+}
+
+const cEvent *cRecMenu::GetEventValue(int itemNumber) {
+ cRecMenuItem *item = NULL;
+ item = menuItems.Get(itemNumber);
+ if (item) {
+ return item->GetEventValue();
+ }
+ return NULL;
+}
+
+eRecMenuState cRecMenu::ProcessKey(eKeys Key) {
+ cRecMenuItem *activeItem = GetActiveMenuItem();
+ eRecMenuState state = rmsContinue;
+ if (!activeItem)
+ return state;
+
+ state = activeItem->ProcessKey(Key);
+ if (state == rmsRefresh) {
+ CreateMenuItems();
+ Display();
+ } else if (state == rmsNotConsumed) {
+ switch (Key & ~k_Repeat) {
+ case kUp:
+ if (!ActivatePrev() && scrollable)
+ ScrollUp();
+ state = rmsConsumed;
+ break;
+ case kDown:
+ if (!ActivateNext() && scrollable)
+ ScrollDown();
+ state = rmsConsumed;
+ break;
+ case kLeft:
+ JumpBegin();
+ state = rmsConsumed;
+ break;
+ case kRight:
+ JumpEnd();
+ state = rmsConsumed;
+ break;
+ default:
+ break;
+ }
+ }
+ return state;
+}
+
+cImage *cRecMenu::createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend) {
+ cImage *image = new cImage(cSize(width, height));
+ image->Fill(clrBgr);
+ if (tvguideConfig.useBlending) {
+ int numSteps = 64;
+ int alphaStep = 0x03;
+ if (height < 30)
+ return image;
+ else if (height < 100) {
+ numSteps = 32;
+ alphaStep = 0x06;
+ }
+ int stepY = 0.5*height / numSteps;
+ if (stepY == 0)
+ stepY = 1;
+ int alpha = 0x40;
+ tColor clr;
+ for (int i = 0; i<numSteps; i++) {
+ clr = AlphaBlend(clrBgr, clrBlend, alpha);
+ for (int y = i*stepY; y < (i+1)*stepY; y++) {
+ for (int x=0; x<width; x++) {
+ image->SetPixel(cPoint(x,y), clr);
+ }
+ }
+ alpha += alphaStep;
+ }
+ }
+ return image;
+}