int CGUIFixedListContainer::GetCursorFromPoint(const CPoint &point, CPoint *itemPoint) const { if (!m_focusedLayout || !m_layout) return -1; int minCursor, maxCursor; GetCursorRange(minCursor, maxCursor); // see if the point is either side of our focus range float start = (minCursor + 0.2f) * m_layout->Size(m_orientation); float end = (maxCursor - 0.2f) * m_layout->Size(m_orientation) + m_focusedLayout->Size(m_orientation); float pos = (m_orientation == VERTICAL) ? point.y : point.x; if (pos >= start && pos <= end) { // select the appropriate item pos -= minCursor * m_layout->Size(m_orientation); for (int row = minCursor; row <= maxCursor; row++) { const CGUIListItemLayout *layout = (row == GetCursor()) ? m_focusedLayout : m_layout; if (pos < layout->Size(m_orientation)) { if (!InsideLayout(layout, point)) return -1; return row; } pos -= layout->Size(m_orientation); } } return -1; }
void CGUIFixedListContainer::SelectItem(int item) { // Check that GetOffset() is valid ValidateOffset(); // only select an item if it's in a valid range if (item >= 0 && item < (int)m_items.size()) { // Select the item requested - we first set the cursor position // which may be different at either end of the list, then the offset int minCursor, maxCursor; GetCursorRange(minCursor, maxCursor); int cursor; if ((int)m_items.size() - 1 - item <= maxCursor - m_fixedCursor) cursor = std::max(m_fixedCursor, maxCursor + item - (int)m_items.size() + 1); else if (item <= m_fixedCursor - minCursor) cursor = std::min(m_fixedCursor, minCursor + item); else cursor = m_fixedCursor; if (cursor != GetCursor()) SetContainerMoving(cursor - GetCursor()); SetCursor(cursor); ScrollToOffset(item - GetCursor()); } }
void CGUIFixedListContainer::ValidateOffset() { if (!m_layout) return; // ensure our fixed cursor position is valid if (m_fixedCursor >= m_itemsPerPage) m_fixedCursor = m_itemsPerPage - 1; if (m_fixedCursor < 0) m_fixedCursor = 0; // compute our minimum and maximum cursor positions int minCursor, maxCursor; GetCursorRange(minCursor, maxCursor); // assure our cursor is between these limits SetCursor(std::max(GetCursor(), minCursor)); SetCursor(std::min(GetCursor(), maxCursor)); int minOffset, maxOffset; GetOffsetRange(minOffset, maxOffset); // and finally ensure our offset is valid // don't validate offset if we are scrolling in case the tween image exceed <0, 1> range if (GetOffset() > maxOffset || (!m_scroller.IsScrolling() && m_scroller.GetValue() > maxOffset * m_layout->Size(m_orientation))) { SetOffset(std::max(-minCursor, maxOffset)); m_scroller.SetValue(GetOffset() * m_layout->Size(m_orientation)); } if (GetOffset() < minOffset || (!m_scroller.IsScrolling() && m_scroller.GetValue() < minOffset * m_layout->Size(m_orientation))) { SetOffset(minOffset); m_scroller.SetValue(GetOffset() * m_layout->Size(m_orientation)); } }
bool CGUIFixedListContainer::GetOffsetRange(int &minOffset, int &maxOffset) const { GetCursorRange(minOffset, maxOffset); minOffset = -minOffset; maxOffset = m_items.size() - maxOffset - 1; return true; }
void CGUIFixedListContainer::ValidateOffset() { if (!m_layout) return; // ensure our fixed cursor position is valid if (m_fixedCursor >= m_itemsPerPage) m_fixedCursor = m_itemsPerPage - 1; if (m_fixedCursor < 0) m_fixedCursor = 0; // compute our minimum and maximum cursor positions int minCursor, maxCursor; GetCursorRange(minCursor, maxCursor); // assure our cursor is between these limits m_cursor = max(m_cursor, minCursor); m_cursor = min(m_cursor, maxCursor); // and finally ensure our offset is valid if (m_offset + maxCursor >= (int)m_items.size() || m_scrollOffset > ((int)m_items.size() - maxCursor - 1) * m_layout->Size(m_orientation)) { m_offset = m_items.size() - maxCursor - 1; m_scrollOffset = m_offset * m_layout->Size(m_orientation); } if (m_offset < -minCursor || m_scrollOffset < -minCursor * m_layout->Size(m_orientation)) { m_offset = -minCursor; m_scrollOffset = m_offset * m_layout->Size(m_orientation); } }
bool CGUIFixedListContainer::SelectItemFromPoint(const CPoint &point) { if (!m_focusedLayout || !m_layout) return false; MarkDirtyRegion(); const float mouse_scroll_speed = 0.25f; const float mouse_max_amount = 1.5f; float sizeOfItem = m_layout->Size(m_orientation); int minCursor, maxCursor; GetCursorRange(minCursor, maxCursor); // see if the point is either side of our focus range float start = (minCursor + 0.2f) * sizeOfItem; float end = (maxCursor - 0.2f) * sizeOfItem + m_focusedLayout->Size(m_orientation); float pos = (m_orientation == VERTICAL) ? point.y : point.x; if (pos < start && GetOffset() > -minCursor) { // scroll backward if (!InsideLayout(m_layout, point)) return false; float amount = std::min((start - pos) / sizeOfItem, mouse_max_amount); m_analogScrollCount += amount * amount * mouse_scroll_speed; if (m_analogScrollCount > 1) { ScrollToOffset(GetOffset() - 1); m_analogScrollCount = 0; } return true; } else if (pos > end && GetOffset() + maxCursor < (int)m_items.size() - 1) { if (!InsideLayout(m_layout, point)) return false; // scroll forward float amount = std::min((pos - end) / sizeOfItem, mouse_max_amount); m_analogScrollCount += amount * amount * mouse_scroll_speed; if (m_analogScrollCount > 1) { ScrollToOffset(GetOffset() + 1); m_analogScrollCount = 0; } return true; } else { // select the appropriate item int cursor = GetCursorFromPoint(point); if (cursor < 0) return false; // calling SelectItem() here will focus the item and scroll, which isn't really what we're after SetCursor(cursor); return true; } }
void CGUIFixedListContainer::Scroll(int amount) { // increase or decrease the offset within [-minCursor, m_items.size() - maxCursor] int minCursor, maxCursor; GetCursorRange(minCursor, maxCursor); int offset = GetOffset() + amount; if (offset < -minCursor) { offset = -minCursor; SetCursor(minCursor); } if (offset > (int)m_items.size() - 1 - maxCursor) { offset = m_items.size() - 1 - maxCursor; SetCursor(maxCursor); } ScrollToOffset(offset); }