#include "recmenu.h" #include "tvguidengosd.h" // --- cRecMenu ------------------------------------------------------------- cRecMenu::cRecMenu() { hidden = false; menuWidth = 50; menuHeight = 0; maxMenuHeight = 98; recMenuGrid = NULL; osdView = NULL; scrollBar = NULL; back = NULL; start = NULL; stop = NULL; itemCount = 0; active = NULL; header = NULL; footer = NULL; scrolling = false; } cRecMenu::~cRecMenu(void) { menuItems.Clear(); if (scrollBar) { scrollBar->Clear(); delete scrollBar; scrollBar = NULL; } if (back) { back->Clear(); delete back; back = NULL; } if (recMenuGrid) { recMenuGrid->Clear(); delete recMenuGrid; } if (hidden) osdView->Activate(); } /******************************************************************** * Public Functions ********************************************************************/ void cRecMenu::Init(cOsdView *osdView) { this->osdView = osdView; recMenuGrid = osdView->GetViewGrid(vgRecordingMenu); scrollBar = osdView->GetViewElement(vemScrollbar); back = osdView->GetViewElement(vemBackground); InitMenuItems(); } void cRecMenu::Draw(void) { DrawHeader(); double width = (double)menuWidth / (double)100; double x = (double)(100 - menuWidth)/(double)200; int totalHeight = GetHeight(); int yPerc = (100 - totalHeight) / 2; if (header) yPerc += header->GetHeight(); double y = (double)yPerc/(double)100; for (cRecMenuItem *current = start; current; current = menuItems.Next(current)) { double itemHeight = (double)(current->GetHeight())/(double)100; if (current->IsNew()) { current->SetTokens(recMenuGrid); recMenuGrid->SetGrid(current->Id(), x, y, width, itemHeight); } else { recMenuGrid->MoveGrid(current->Id(), x, y, width, itemHeight); } if (current->Active()) { recMenuGrid->SetCurrent(current->Id(), true); } y += itemHeight; if (current == stop) break; } DrawFooter(); recMenuGrid->Display(); } eRecMenuState cRecMenu::ProcessKey(eKeys Key) { eRecMenuState state = rmsContinue; if (!active) return state; state = active->ProcessKey(Key); if (state == rmsRefresh) { //Refresh current active->SetTokens(recMenuGrid); active->SetNew(); Draw(); } else if (state == rmsNotConsumed) { switch (Key & ~k_Repeat) { case kUp: if (ScrollUp(false)) Draw(); state = rmsConsumed; break; case kDown: if (ScrollDown(false)) Draw(); state = rmsConsumed; break; case kLeft: if (PageUp()) Draw(); state = rmsConsumed; break; case kRight: if (PageDown()) Draw(); state = rmsConsumed; break; case kBack: state = rmsClose; break; default: break; } } return state; } /******************************************************************** * Protected Functions ********************************************************************/ void cRecMenu::AddMenuItem(cRecMenuItem *item, bool inFront) { if (!inFront) menuItems.Add(item); else menuItems.Ins(item); } void cRecMenu::AddHeader(cRecMenuItem *header) { this->header = header; maxMenuHeight -= header->GetHeight(); } void cRecMenu::AddFooter(cRecMenuItem *footer) { this->footer = footer; maxMenuHeight -= footer->GetHeight(); } int cRecMenu::GetNumActive(void) { int num = 0; for (cRecMenuItem *current = start; current; current = menuItems.Next(current)) { if (current == active) return num; num++; } } bool cRecMenu::ScrollUp(bool retry) { if (active == start) { bool scrolled = SeekBack(false); if (scrolled && scrolling) DrawScrollbar(); } if (footer && active == footer) { recMenuGrid->SetCurrent(footer->Id(), false); footer->SetInactive(); active = stop; active->SetActive(); return true; } cRecMenuItem *prev = (cRecMenuItem*)active->Prev(); while (prev && !prev->Selectable()) { prev = (cRecMenuItem*)prev->Prev(); } if (prev) { recMenuGrid->SetCurrent(active->Id(), false); active->SetInactive(); active = prev; active->SetActive(); return true; } else { SeekBack(false); if (!retry) ScrollUp(true); } return false; } bool cRecMenu::ScrollDown(bool retry) { if (active == stop || retry) { bool scrolled = SeekForward(false); if (scrolled && scrolling) DrawScrollbar(); } cRecMenuItem *next = (cRecMenuItem*)active->Next(); while (next && !next->Selectable()) { if (next == stop) { return ScrollDown(true); } next = (cRecMenuItem*)next->Next(); } if (next) { recMenuGrid->SetCurrent(active->Id(), false); active->SetInactive(); active = next; active->SetActive(); return true; } else { SeekForward(false); if (!retry) ScrollDown(true); } if (footer) { recMenuGrid->SetCurrent(active->Id(), false); active->SetInactive(); active = footer; active->SetActive(); return true; } return false; } bool cRecMenu::PageUp(void) { bool scrolled = SeekBack(true); if (scrolled && scrolling) DrawScrollbar(); if (!scrolled) { recMenuGrid->SetCurrent(active->Id(), false); active->SetInactive(); active = start; active->SetActive(); return true; } if (!active) { active = stop; active->SetActive(); } return scrolled; } bool cRecMenu::PageDown(void) { bool scrolled = SeekForward(true); if (scrolled && scrolling) DrawScrollbar(); if (!scrolled) { recMenuGrid->SetCurrent(active->Id(), false); active->SetInactive(); active = stop; active->SetActive(); return true; } if (!active) { active = start; active->SetActive(); } return scrolled; } void cRecMenu::ClearMenuItems(void) { menuItems.Clear(); back->Clear(); scrollBar->Clear(); recMenuGrid->Clear(); if (footer) footer->SetNew(); active = NULL; } void cRecMenu::InitMenuItems(void) { if (menuItems.Count() == 0) return; scrolling = false; menuHeight = 0; start = menuItems.First(); cRecMenuItem *current = start; while (current) { int itemHeight = current->GetHeight(); if (menuHeight + itemHeight > maxMenuHeight) { scrolling = true; break; } if (current->Active()) active = current; itemCount++; stop = current; menuHeight += itemHeight; current = menuItems.Next(current); } DrawBackground(); Flush(); if (scrolling) { DrawScrollbar(); Flush(); } } int cRecMenu::GetHeight(void) { int totalHeight = menuHeight; if (header) totalHeight += header->GetHeight(); if (footer) totalHeight += footer->GetHeight(); return totalHeight; } /******************************************************************** * Private Functions ********************************************************************/ bool cRecMenu::SeekForward(bool page) { int jumpStep = 0; if (page) jumpStep = itemCount; else jumpStep = itemCount/2; int jump = 0; cRecMenuItem *next = (cRecMenuItem*)stop->Next(); while (next && jump < jumpStep) { stop = next; menuHeight += next->GetHeight(); next = (cRecMenuItem*)next->Next(); jump++; } while (start && menuHeight > maxMenuHeight) { if (active == start) { active = NULL; start->SetInactive(); } menuHeight -= start->GetHeight(); recMenuGrid->Delete(start->Id()); start->SetNew(); start = (cRecMenuItem*)start->Next(); } if (jump > 0) return true; return false; } bool cRecMenu::SeekBack(bool page) { int jumpStep = 0; if (page) jumpStep = itemCount; else jumpStep = itemCount/2; int jump = 0; cRecMenuItem *prev = (cRecMenuItem*)start->Prev(); while (prev && jump < jumpStep) { start = prev; menuHeight += prev->GetHeight(); prev = (cRecMenuItem*)prev->Prev(); jump++; } while (stop && menuHeight > maxMenuHeight) { if (active == stop) { active = NULL; stop->SetInactive(); } menuHeight -= stop->GetHeight(); recMenuGrid->Delete(stop->Id()); stop->SetNew(); stop = (cRecMenuItem*)stop->Prev(); } if (jump > 0) return true; return false; } void cRecMenu::DrawBackground(void) { back->Clear(); back->ClearTokens(); back->AddIntToken("menuwidth", menuWidth + 2); back->AddIntToken("menuheight", GetHeight() + 2); back->AddIntToken("hasscrollbar", scrolling); back->Display(); } void cRecMenu::DrawScrollbar(void) { if (menuItems.Count() == 0) return; int scrollBarHeight = (double)itemCount / (double)menuItems.Count() * 1000; int startPos = 0; for (cRecMenuItem *current = menuItems.First(); current; current = menuItems.Next(current)) { if (start == current) break; startPos++; } int offset = (double)startPos / (double)menuItems.Count() * 1000; scrollBar->Clear(); scrollBar->ClearTokens(); scrollBar->AddIntToken("menuwidth", menuWidth + 2); int y = (100 - GetHeight())/2; if (header) y += header->GetHeight(); scrollBar->AddIntToken("posy", y); scrollBar->AddIntToken("totalheight", menuHeight); scrollBar->AddIntToken("height", scrollBarHeight); scrollBar->AddIntToken("offset", offset); scrollBar->Display(); } void cRecMenu::DrawHeader(void) { if (!header) return; double width = (double)menuWidth / (double)100; double x = (double)(100 - menuWidth)/(double)200; int totalHeight = GetHeight(); double y = (double)((100 - totalHeight) / 2) / (double)100; if (header->IsNew()) { recMenuGrid->ClearTokens(); header->SetTokens(recMenuGrid); recMenuGrid->SetGrid(header->Id(), x, y, width, (double)header->GetHeight()/(double)100); } } void cRecMenu::DrawFooter(void) { if (!footer) return; double width = (double)menuWidth / (double)100; double x = (double)(100 - menuWidth)/(double)200; int totalHeight = GetHeight(); int totalMenuHeight = menuHeight; if (header) totalMenuHeight += header->GetHeight(); double y = (double)((100 - totalHeight) / 2 + totalMenuHeight) / (double)100; if (footer->IsNew()) { recMenuGrid->ClearTokens(); footer->SetTokens(recMenuGrid); recMenuGrid->SetGrid(footer->Id(), x, y, width, (double)footer->GetHeight()/(double)100); } else { recMenuGrid->MoveGrid(footer->Id(), x, y, width, (double)footer->GetHeight()/(double)100); } if (footer->Active()) { active = footer; recMenuGrid->SetCurrent(footer->Id(), true); } }