void CGUIPanelContainer::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { ValidateOffset(); if (m_bInvalidated) UpdateLayout(); if (!m_layout || !m_focusedLayout) return; UpdateScrollOffset(currentTime); int offset = (int)(m_scroller.GetValue() / m_layout->Size(m_orientation)); int cacheBefore, cacheAfter; GetCacheOffsets(cacheBefore, cacheAfter); // Free memory not used on screen if ((int)m_items.size() > m_itemsPerPage + cacheBefore + cacheAfter) FreeMemory(CorrectOffset(offset - cacheBefore, 0), CorrectOffset(offset + m_itemsPerPage + 1 + cacheAfter, 0)); CPoint origin = CPoint(m_posX, m_posY) + m_renderOffset; float pos = (m_orientation == VERTICAL) ? origin.y : origin.x; float end = (m_orientation == VERTICAL) ? m_posY + m_height : m_posX + m_width; pos += (offset - cacheBefore) * m_layout->Size(m_orientation) - m_scroller.GetValue(); end += cacheAfter * m_layout->Size(m_orientation); int current = (offset - cacheBefore) * m_itemsPerRow; int col = 0; while (pos < end && m_items.size()) { if (current >= (int)m_items.size()) break; if (current >= 0) { CGUIListItemPtr item = m_items[current]; bool focused = (current == GetOffset() * m_itemsPerRow + GetCursor()) && m_bHasFocus; if (m_orientation == VERTICAL) ProcessItem(origin.x + col * m_layout->Size(HORIZONTAL), pos, item, focused, currentTime, dirtyregions); else ProcessItem(pos, origin.y + col * m_layout->Size(VERTICAL), item, focused, currentTime, dirtyregions); } // increment our position if (col < m_itemsPerRow - 1) col++; else { pos += m_layout->Size(m_orientation); col = 0; } current++; } // when we are scrolling up, offset will become lower (integer division, see offset calc) // to have same behaviour when scrolling down, we need to set page control to offset+1 UpdatePageControl(offset + (m_scroller.IsScrollingDown() ? 1 : 0)); CGUIControl::Process(currentTime, dirtyregions); }
int CGUIFixedListContainer::GetCurrentPage() const { int offset = CorrectOffset(GetOffset(), GetCursor()); if (offset + m_itemsPerPage - GetCursor() >= (int)GetRows()) // last page return (GetRows() + m_itemsPerPage - 1) / m_itemsPerPage; return offset / m_itemsPerPage + 1; }
int CGUIWrappingListContainer::GetCurrentPage() const { int offset = CorrectOffset(m_offset, m_cursor); if (offset + m_itemsPerPage - m_cursor >= (int)GetRows()) // last page return (GetRows() + m_itemsPerPage - 1) / m_itemsPerPage; return offset / m_itemsPerPage + 1; }
bool PipeManager::CheckTubes(std::shared_ptr<BirdObject> bird) { if (m_pipes[0]->ShouldBeDeleted()) { CorrectOffset(); m_pipes.erase(m_pipes.begin() + 0); m_pipes.erase(m_pipes.begin() + 0); AddPipe(true); AddPipe(false); return false; } else if (!bird->GetIsDead() && !bird->GetIsInvulnerable() && (bird->CheckInteractWithTube(m_pipes[0]) || bird->CheckInteractWithTube(m_pipes[1]))) { bird->SetIsDead(true); return false; } else if (!bird->GetIsDead() && !m_pipes[0]->IsScored()) { if (bird->CheckScore(m_pipes[0])) { m_pipes[0]->SetIsScored(true); return true; } } return false; }
void CGUIBaseContainer::OnNextLetter() { int offset = CorrectOffset(GetOffset(), GetCursor()); for (unsigned int i = 0; i < m_letterOffsets.size(); i++) { if (m_letterOffsets[i].first > offset) { SelectItem(m_letterOffsets[i].first); return; } } }
void CGUIBaseContainer::OnPrevLetter() { int offset = CorrectOffset(GetOffset(), GetCursor()); if (!m_letterOffsets.size()) return; for (int i = (int)m_letterOffsets.size() - 1; i >= 0; i--) { if (m_letterOffsets[i].first < offset) { SelectItem(m_letterOffsets[i].first); return; } } }
CGUIListItemPtr CGUIBaseContainer::GetListItem(int offset, unsigned int flag) const { if (!m_items.size() || !m_layout) return CGUIListItemPtr(); int item = GetSelectedItem() + offset; if (flag & INFOFLAG_LISTITEM_POSITION) // use offset from the first item displayed, taking into account scrolling item = CorrectOffset((int)(m_scroller.GetValue() / m_layout->Size(m_orientation)), offset); if (flag & INFOFLAG_LISTITEM_ABSOLUTE) // use offset from the first item item = CorrectOffset(0, offset); if (flag & INFOFLAG_LISTITEM_WRAP) { item %= ((int)m_items.size()); if (item < 0) item += m_items.size(); return m_items[item]; } else { if (item >= 0 && item < (int)m_items.size()) return m_items[item]; } return CGUIListItemPtr(); }
void CGUIBaseContainer::OnJumpSMS(int letter) { static const char letterMap[8][6] = { "ABC2", "DEF3", "GHI4", "JKL5", "MNO6", "PQRS7", "TUV8", "WXYZ9" }; // only 2..9 supported if (letter < 2 || letter > 9 || !m_letterOffsets.size()) return; const std::string letters = letterMap[letter - 2]; // find where we currently are int offset = CorrectOffset(GetOffset(), GetCursor()); unsigned int currentLetter = 0; while (currentLetter + 1 < m_letterOffsets.size() && m_letterOffsets[currentLetter + 1].first <= offset) currentLetter++; // now switch to the next letter std::string current = m_letterOffsets[currentLetter].second; size_t startPos = (letters.find(current) + 1) % letters.size(); // now jump to letters[startPos], or another one in the same range if possible size_t pos = startPos; while (true) { // check if we can jump to this letter for (size_t i = 0; i < m_letterOffsets.size(); i++) { if (m_letterOffsets[i].second == letters.substr(pos, 1)) { SelectItem(m_letterOffsets[i].first); return; } } pos = (pos + 1) % letters.size(); if (pos == startPos) return; } }
void CGUIBaseContainer::OnJumpLetter(char letter, bool skip /*=false*/) { if (m_matchTimer.GetElapsedMilliseconds() < letter_match_timeout) m_match.push_back(letter); else m_match = StringUtils::Format("%c", letter); m_matchTimer.StartZero(); // we can't jump through letters if we have none if (0 == m_letterOffsets.size()) return; // find the current letter we're focused on unsigned int offset = CorrectOffset(GetOffset(), GetCursor()); unsigned int i = (offset + ((skip) ? 1 : 0)) % m_items.size(); do { CGUIListItemPtr item = m_items[i]; std::string label = item->GetLabel(); if (CServiceBroker::GetSettings().GetBool(CSettings::SETTING_FILELISTS_IGNORETHEWHENSORTING)) label = SortUtils::RemoveArticles(label); if (0 == strnicmp(label.c_str(), m_match.c_str(), m_match.size())) { SelectItem(i); return; } i = (i+1) % m_items.size(); } while (i != offset); // no match found - repeat with a single letter if (m_match.size() > 1) { m_match.clear(); OnJumpLetter(letter, true); } }
void CGUIBaseContainer::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { // update our auto-scrolling as necessary UpdateAutoScrolling(currentTime); ValidateOffset(); if (m_bInvalidated) UpdateLayout(); if (!m_layout || !m_focusedLayout) return; UpdateScrollOffset(currentTime); int offset = (int)floorf(m_scroller.GetValue() / m_layout->Size(m_orientation)); int cacheBefore, cacheAfter; GetCacheOffsets(cacheBefore, cacheAfter); // Free memory not used on screen if ((int)m_items.size() > m_itemsPerPage + cacheBefore + cacheAfter) FreeMemory(CorrectOffset(offset - cacheBefore, 0), CorrectOffset(offset + m_itemsPerPage + 1 + cacheAfter, 0)); CPoint origin = CPoint(m_posX, m_posY) + m_renderOffset; float pos = (m_orientation == VERTICAL) ? origin.y : origin.x; float end = (m_orientation == VERTICAL) ? m_posY + m_height : m_posX + m_width; // we offset our draw position to take into account scrolling and whether or not our focused // item is offscreen "above" the list. float drawOffset = (offset - cacheBefore) * m_layout->Size(m_orientation) - m_scroller.GetValue(); if (GetOffset() + GetCursor() < offset) drawOffset += m_focusedLayout->Size(m_orientation) - m_layout->Size(m_orientation); pos += drawOffset; end += cacheAfter * m_layout->Size(m_orientation); int current = offset - cacheBefore; while (pos < end && m_items.size()) { int itemNo = CorrectOffset(current, 0); if (itemNo >= (int)m_items.size()) break; bool focused = (current == GetOffset() + GetCursor()); if (itemNo >= 0) { CGUIListItemPtr item = m_items[itemNo]; // render our item if (m_orientation == VERTICAL) ProcessItem(origin.x, pos, item, focused, currentTime, dirtyregions); else ProcessItem(pos, origin.y, item, focused, currentTime, dirtyregions); } // increment our position pos += focused ? m_focusedLayout->Size(m_orientation) : m_layout->Size(m_orientation); current++; } // when we are scrolling up, offset will become lower (integer division, see offset calc) // to have same behaviour when scrolling down, we need to set page control to offset+1 UpdatePageControl(offset + (m_scroller.IsScrollingDown() ? 1 : 0)); m_lastRenderTime = currentTime; CGUIControl::Process(currentTime, dirtyregions); }
int CGUIBaseContainer::GetSelectedItem() const { return CorrectOffset(GetOffset(), GetCursor()); }
void CGUIBaseContainer::Render() { if (!m_layout || !m_focusedLayout) return; int offset = (int)floorf(m_scroller.GetValue() / m_layout->Size(m_orientation)); int cacheBefore, cacheAfter; GetCacheOffsets(cacheBefore, cacheAfter); if (g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height)) { CPoint origin = CPoint(m_posX, m_posY) + m_renderOffset; float pos = (m_orientation == VERTICAL) ? origin.y : origin.x; float end = (m_orientation == VERTICAL) ? m_posY + m_height : m_posX + m_width; // we offset our draw position to take into account scrolling and whether or not our focused // item is offscreen "above" the list. float drawOffset = (offset - cacheBefore) * m_layout->Size(m_orientation) - m_scroller.GetValue(); if (GetOffset() + GetCursor() < offset) drawOffset += m_focusedLayout->Size(m_orientation) - m_layout->Size(m_orientation); pos += drawOffset; end += cacheAfter * m_layout->Size(m_orientation); float focusedPos = 0; CGUIListItemPtr focusedItem; int current = offset - cacheBefore; while (pos < end && m_items.size()) { int itemNo = CorrectOffset(current, 0); if (itemNo >= (int)m_items.size()) break; bool focused = (current == GetOffset() + GetCursor()); if (itemNo >= 0) { CGUIListItemPtr item = m_items[itemNo]; // render our item if (focused) { focusedPos = pos; focusedItem = item; } else { if (m_orientation == VERTICAL) RenderItem(origin.x, pos, item.get(), false); else RenderItem(pos, origin.y, item.get(), false); } } // increment our position pos += focused ? m_focusedLayout->Size(m_orientation) : m_layout->Size(m_orientation); current++; } // render focused item last so it can overlap other items if (focusedItem) { if (m_orientation == VERTICAL) RenderItem(origin.x, focusedPos, focusedItem.get(), true); else RenderItem(focusedPos, origin.y, focusedItem.get(), true); } g_graphicsContext.RestoreClipRegion(); } CGUIControl::Render(); }
void CGUIWrappingListContainer::Render() { if (!IsVisible()) return; ValidateOffset(); if (m_bInvalidated) UpdateLayout(); if (!m_layout || !m_focusedLayout) return; UpdateScrollOffset(); int offset = (int)floorf(m_scrollOffset / m_layout->Size(m_orientation)); // Free memory not used on scre if (m_scrollSpeed) if ((int)m_items.size() > m_itemsPerPage) FreeMemory(CorrectOffset(offset, 0), CorrectOffset(offset, m_itemsPerPage + 1)); g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height); float posX = m_posX; float posY = m_posY; if (m_orientation == VERTICAL) posY += (offset * m_layout->Size(m_orientation) - m_scrollOffset); else posX += (offset * m_layout->Size(m_orientation) - m_scrollOffset);; float focusedPosX = 0; float focusedPosY = 0; CGUIListItemPtr focusedItem; int current = offset; while (posX < m_posX + m_width && posY < m_posY + m_height && m_items.size()) { CGUIListItemPtr item = m_items[CorrectOffset(current, 0)]; bool focused = (current == m_offset + m_cursor) && m_bHasFocus; // render our item if (focused) { focusedPosX = posX; focusedPosY = posY; focusedItem = item; } else RenderItem(posX, posY, item.get(), focused); // increment our position if (m_orientation == VERTICAL) posY += focused ? m_focusedLayout->Size(m_orientation) : m_layout->Size(m_orientation); else posX += focused ? m_focusedLayout->Size(m_orientation) : m_layout->Size(m_orientation); current++; } // render focused item last so it can overlap other items if (focusedItem) RenderItem(focusedPosX, focusedPosY, focusedItem.get(), true); g_graphicsContext.RestoreClipRegion(); if (m_pageControl) { // tell our pagecontrol (scrollbar or whatever) to update CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), m_pageControl, CorrectOffset(offset, 0)); SendWindowMessage(msg); } CGUIBaseContainer::Render(); }
void CGUIFixedListContainer::Render() { ValidateOffset(); if (m_bInvalidated) UpdateLayout(); if (!m_focusedLayout || !m_layout) return; UpdateScrollOffset(); int offset = (int)(m_scrollOffset / m_layout->Size(m_orientation)); // Free memory not used on screen at the moment, do this first so there's more memory for the new items. FreeMemory(CorrectOffset(offset, 0), CorrectOffset(offset, m_itemsPerPage + 1)); g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height); float posX = m_posX; float posY = m_posY; if (m_orientation == VERTICAL) posY += (offset * m_layout->Size(m_orientation) - m_scrollOffset); else posX += (offset * m_layout->Size(m_orientation) - m_scrollOffset);; float focusedPosX = 0; float focusedPosY = 0; CGUIListItemPtr focusedItem; int current = offset; while (posX < m_posX + m_width && posY < m_posY + m_height && m_items.size()) { if (current >= (int)m_items.size()) break; bool focused = (current == m_offset + m_cursor); if (current >= 0) { CGUIListItemPtr item = m_items[current]; // render our item if (focused) { focusedPosX = posX; focusedPosY = posY; focusedItem = item; } else RenderItem(posX, posY, item.get(), focused); } // increment our position if (m_orientation == VERTICAL) posY += focused ? m_focusedLayout->Size(m_orientation) : m_layout->Size(m_orientation); else posX += focused ? m_focusedLayout->Size(m_orientation) : m_layout->Size(m_orientation); current++; } // and render the focused item last (for overlapping purposes) if (focusedItem) RenderItem(focusedPosX, focusedPosY, focusedItem.get(), true); g_graphicsContext.RestoreClipRegion(); if (m_pageControl) { // tell our pagecontrol (scrollbar or whatever) to update CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), m_pageControl, offset); SendWindowMessage(msg); } CGUIBaseContainer::Render(); }
void CGUIFixedListContainer::ScrollToOffset(int offset) { CLog::Log(LOGDEBUG,"CGUIFixedListContainer::ScrollToOffset - ENTER. [m_cursor=%d][offset=%d][m_offset=%d] (scroll)", m_cursor, offset, m_offset); bool wrapAround = IsWrapAround(); if ( wrapAround || m_bPinnedPosition) { CGUIBaseContainer::ScrollToOffset(offset); return; } int nCurrOffset = CorrectOffset(m_offset, m_cursor); int nTargetOffset = CorrectOffset(offset, m_cursor); int last_section = m_items.size() - (m_itemsPerPage / 2); int first_section = (m_itemsPerPage / 2); CLog::Log(LOGDEBUG, "CGUIFixedListContainer::ScrollToOffset - [m_cursor=%d][offset=%d][m_offset=%d][nCurrOffset=%d][nTargetOffset=%d][numOfItems=%zu][m_itemsPerPage=%d] (scroll)", m_cursor, offset, m_offset, nCurrOffset, nTargetOffset, m_items.size(), m_itemsPerPage); // Case 1: // Someone initialized the window and immediately scrolled to a cached offset, and we have more than one page of content // We detect this case by seeing that we are not stepping by an increment of one // In this situation we recalculate the cursor and the list offset from scratch and call base seek, but only if we have more than a page // if we have less than a page we never scroll if( nTargetOffset != nCurrOffset+1 && nTargetOffset != nCurrOffset-1 && nTargetOffset != nCurrOffset) { // BUGBUG: we don't handle separators properly here, but normally SelectItem will handle that for us (since that is the likely call path here) // See if any scroll is required. If we have a page or less then no if( m_items.size() > (size_t) m_itemsPerPage ) { // see if we are in the first block if( nTargetOffset <= first_section ) { m_cursor = nTargetOffset; nTargetOffset = 0; } // or in the last block else if( nTargetOffset >= last_section ) { int off = m_items.size() - m_itemsPerPage; m_cursor = nTargetOffset - off; nTargetOffset = off; } // otherwise, just center us else { m_cursor = m_itemsPerPage / 2; nTargetOffset -= m_cursor; } //avoid scrolling and starting the scrolltimer, used when we're setting selection on specific item m_wasReset = true; CGUIBaseContainer::ScrollToOffset(nTargetOffset); } else { CGUIBaseContainer::ScrollToOffset(0); m_cursor = nTargetOffset; } } else // Case 2: // We are stepping backwards in the list. I.e. moving up or left depending on orientation (nCurrOffset > nTargetOffset) // We are moving in the fixed pane of the content // If we hit a separator then we recurse to ensure we shift appropriately. if (nCurrOffset >= nTargetOffset && ((size_t) nCurrOffset >= m_items.size() - (m_itemsPerPage / 2) || nCurrOffset == 0 )) { // Move the cursor by the requested delta m_cursor -= (nCurrOffset - nTargetOffset); // Handle the case where we land on a separator by moving us along one extra space if (m_items.size() > (size_t) (m_offset +m_cursor) && m_items[m_offset +m_cursor]->GetPropertyBOOL("isseparator")) { if (m_offset +m_cursor == 0) { MoveDown(false); } else { MoveUp(false); } } } // Case 3: // We are stepping forwards in the list. I.e. moving down or right depending on the orientation (nTargetOffset > nCurrOffset) // We are moving in the fixed pane of the content // If we hit a separator then we recurse to ensure we shift appropriately. else if (nCurrOffset <= nTargetOffset && (nCurrOffset < m_itemsPerPage / 2 || (m_items.size() - m_itemsPerPage) == (size_t) m_offset) ) { // Move the cursor by the requested delta m_cursor += (nTargetOffset - nCurrOffset); // Handle the case where we land ona separator by moving us along one extra space if (m_items.size() > (size_t) (m_offset +m_cursor) && m_items[m_offset +m_cursor]->GetPropertyBOOL("isseparator")) { if ((size_t) (m_offset +m_cursor) == m_items.size() - 1) { MoveUp(false); } else { MoveDown(false); } } } else if( (size_t) m_itemsPerPage < m_items.size() ) { // Case 4: // We are stepping forwards or back in the list, not within the fixed block, and have no special conditions. // We actually need to scroll the contents of the list // BUGBUG: in a long list this means we land on separators and don't shuffle off them?? if( offset >= 0 ) CGUIBaseContainer::ScrollToOffset(offset); else m_cursor += offset; } else { // Case 5: // Don't scroll; just move the cursor m_cursor += offset; } // This centers the cursor in the list if (m_cursor > m_itemsPerPage) { CGUIBaseContainer::ScrollToOffset(m_cursor - m_itemsPerPage / 2); m_cursor = m_itemsPerPage / 2; } CLog::Log(LOGDEBUG,"CGUIFixedListContainer::ScrollToOffset - EXIT. [m_cursor=%d][offset=%d][m_offset=%d] (scroll)",m_cursor,offset,m_offset); }