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()); } }
EVENT_RESULT CGUIBaseContainer::OnMouseEvent(const CPoint &point, const CMouseEvent &event) { if (event.m_id >= ACTION_MOUSE_LEFT_CLICK && event.m_id <= ACTION_MOUSE_DOUBLE_CLICK) { if (SelectItemFromPoint(point - CPoint(m_posX, m_posY))) { OnClick(event.m_id); return EVENT_RESULT_HANDLED; } } else if (event.m_id == ACTION_MOUSE_WHEEL_UP) { Scroll(-1); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_MOUSE_WHEEL_DOWN) { Scroll(1); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_GESTURE_NOTIFY) { return (m_orientation == HORIZONTAL) ? EVENT_RESULT_PAN_HORIZONTAL : EVENT_RESULT_PAN_VERTICAL; } else if (event.m_id == ACTION_GESTURE_BEGIN) { // grab exclusive access CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, GetID(), GetParentID()); SendWindowMessage(msg); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_GESTURE_PAN) { // do the drag and validate our offset (corrects for end of scroll) m_scroller.SetValue(m_scroller.GetValue() - ((m_orientation == HORIZONTAL) ? event.m_offsetX : event.m_offsetY)); float size = (m_layout) ? m_layout->Size(m_orientation) : 10.0f; int offset = (int)MathUtils::round_int(m_scroller.GetValue() / size); m_lastScrollStartTimer.Stop(); m_scrollTimer.Start(); SetOffset(offset); ValidateOffset(); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_GESTURE_END) { // release exclusive access CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, GetParentID()); SendWindowMessage(msg); m_scrollTimer.Stop(); // and compute the nearest offset from this and scroll there float size = (m_layout) ? m_layout->Size(m_orientation) : 10.0f; float offset = m_scroller.GetValue() / size; int toOffset = (int)MathUtils::round_int(offset); if (toOffset < offset) SetOffset(toOffset+1); else SetOffset(toOffset-1); ScrollToOffset(toOffset); return EVENT_RESULT_HANDLED; } return EVENT_RESULT_UNHANDLED; }
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); }
void CGUIFixedListContainer::SelectItem(int item) { // Check that m_offset 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 ScrollToOffset(item - m_cursor); } }
void CGUIControlGroupList::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { if (m_scroller.Update(currentTime)) MarkDirtyRegion(); // first we update visibility of all our items, to ensure our size and // alignment computations are correct. for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; GUIPROFILER_VISIBILITY_BEGIN(control); control->UpdateVisibility(); GUIPROFILER_VISIBILITY_END(control); } ValidateOffset(); if (m_pageControl && m_lastScrollerValue != m_scroller.GetValue()) { CGUIMessage message(GUI_MSG_LABEL_RESET, GetParentID(), m_pageControl, (int)Size(), (int)m_totalSize); SendWindowMessage(message); CGUIMessage message2(GUI_MSG_ITEM_SELECT, GetParentID(), m_pageControl, (int)m_scroller.GetValue()); SendWindowMessage(message2); m_lastScrollerValue = m_scroller.GetValue(); } // we run through the controls, rendering as we go int index = 0; float pos = GetAlignOffset(); for (iControls it = m_children.begin(); it != m_children.end(); ++it) { // note we render all controls, even if they're offscreen, as then they'll be updated // with respect to animations CGUIControl *control = *it; if (m_orientation == VERTICAL) g_graphicsContext.SetOrigin(m_posX, m_posY + pos - m_scroller.GetValue()); else g_graphicsContext.SetOrigin(m_posX + pos - m_scroller.GetValue(), m_posY); control->DoProcess(currentTime, dirtyregions); if (control->IsVisible()) { if (IsControlOnScreen(pos, control)) { if (control->HasFocus()) m_focusedPosition = index; index++; } pos += Size(control) + m_itemGap; } g_graphicsContext.RestoreOrigin(); } CGUIControl::Process(currentTime, dirtyregions); }
void CGUIControlGroupList::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { if (m_scrollSpeed != 0) { MarkDirtyRegion(); m_offset += m_scrollSpeed * (currentTime - m_scrollLastTime); if ((m_scrollSpeed < 0 && m_offset < m_scrollOffset) || (m_scrollSpeed > 0 && m_offset > m_scrollOffset)) { m_offset = m_scrollOffset; m_scrollSpeed = 0; } } m_scrollLastTime = currentTime; // first we update visibility of all our items, to ensure our size and // alignment computations are correct. for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; GUIPROFILER_VISIBILITY_BEGIN(control); control->UpdateVisibility(); GUIPROFILER_VISIBILITY_END(control); } ValidateOffset(); if (m_pageControl) { CGUIMessage message(GUI_MSG_LABEL_RESET, GetParentID(), m_pageControl, (int)m_height, (int)m_totalSize); SendWindowMessage(message); CGUIMessage message2(GUI_MSG_ITEM_SELECT, GetParentID(), m_pageControl, (int)m_offset); SendWindowMessage(message2); } // we run through the controls, rendering as we go float pos = GetAlignOffset(); for (iControls it = m_children.begin(); it != m_children.end(); ++it) { // note we render all controls, even if they're offscreen, as then they'll be updated // with respect to animations CGUIControl *control = *it; if (m_orientation == VERTICAL) g_graphicsContext.SetOrigin(m_posX, m_posY + pos - m_offset); else g_graphicsContext.SetOrigin(m_posX + pos - m_offset, m_posY); control->DoProcess(currentTime, dirtyregions); if (control->IsVisible()) pos += Size(control) + m_itemGap; g_graphicsContext.RestoreOrigin(); } CGUIControl::Process(currentTime, dirtyregions); }
void CGUIFixedListContainer::SelectItem(int item) { // Check that m_offset is valid ValidateOffset(); // only select an item if it's in a valid range if (item >= 0 && item < (int)m_items.size()) { if (m_items[item]->GetPropertyBOOL("isseparator")) { SelectItem(item + 1); return; } ScrollToOffset(item - m_cursor); } }
void CGUIPanelContainer::SelectItem(int item) { // Check that our offset 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 if (item >= GetOffset() * m_itemsPerRow && item < (GetOffset() + m_itemsPerPage) * m_itemsPerRow) { // the item is on the current page, so don't change it. SetCursor(item - GetOffset() * m_itemsPerRow); } else if (item < GetOffset() * m_itemsPerRow) { // item is on a previous page - make it the first item on the page SetCursor(item % m_itemsPerRow); ScrollToOffset((item - GetCursor()) / m_itemsPerRow); } else // (item >= GetOffset()+m_itemsPerPage) { // item is on a later page - make it the last row on the page SetCursor(item % m_itemsPerRow + m_itemsPerRow * (m_itemsPerPage - 1)); ScrollToOffset((item - GetCursor()) / m_itemsPerRow); } } }
void CGUIListContainer::SelectItem(int item) { // Check that m_offset 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 if (item >= m_offset && item < m_offset + m_itemsPerPage) { // the item is on the current page, so don't change it. SetCursor(item - m_offset); } else if (item < m_offset) { // item is on a previous page - make it the first item on the page SetCursor(0); ScrollToOffset(item); } else // (item >= m_offset+m_itemsPerPage) { // item is on a later page - make it the last item on the page SetCursor(m_itemsPerPage - 1); ScrollToOffset(item - m_cursor); } } }
bool CGUIControlGroupList::OnMessage(CGUIMessage& message) { switch (message.GetMessage() ) { case GUI_MSG_FOCUSED: { // a control has been focused // scroll if we need to and update our page control ValidateOffset(); float offset = 0; for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; if (!control->IsVisible()) continue; if (control->GetID() == message.GetControlId()) { // find out whether this is the first or last control if (IsFirstFocusableControl(control)) ScrollTo(0); else if (IsLastFocusableControl(control)) ScrollTo(m_totalSize - Size()); else if (offset < m_scroller.GetValue()) ScrollTo(offset); else if (offset + Size(control) > m_scroller.GetValue() + Size()) ScrollTo(offset + Size(control) - Size()); break; } offset += Size(control) + m_itemGap; } } break; case GUI_MSG_SETFOCUS: { // we've been asked to focus. We focus the last control if it's on this page, // else we'll focus the first focusable control from our offset (after verifying it) ValidateOffset(); // now check the focusControl's offset float offset = 0; for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; if (!control->IsVisible()) continue; if (control->GetID() == m_focusedControl) { if (IsControlOnScreen(offset, control)) return CGUIControlGroup::OnMessage(message); break; } offset += Size(control) + m_itemGap; } // find the first control on this page offset = 0; for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; if (!control->IsVisible()) continue; if (control->CanFocus() && IsControlOnScreen(offset, control)) { m_focusedControl = control->GetID(); break; } offset += Size(control) + m_itemGap; } } break; case GUI_MSG_PAGE_CHANGE: { if (message.GetSenderId() == m_pageControl) { // it's from our page control ScrollTo((float)message.GetParam1()); return true; } } break; } return CGUIControlGroup::OnMessage(message); }
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); }
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 CGUIControlGroupList::Render() { if (m_scrollSpeed != 0) { m_offset += m_scrollSpeed * (m_renderTime - m_scrollTime); if (m_scrollSpeed < 0 && m_offset < m_scrollOffset || m_scrollSpeed > 0 && m_offset > m_scrollOffset) { m_offset = m_scrollOffset; m_scrollSpeed = 0; } } m_scrollTime = m_renderTime; ValidateOffset(); if (m_pageControl) { CGUIMessage message(GUI_MSG_LABEL_RESET, GetParentID(), m_pageControl, (DWORD)m_height, (DWORD)m_totalSize); SendWindowMessage(message); CGUIMessage message2(GUI_MSG_ITEM_SELECT, GetParentID(), m_pageControl, (DWORD)m_offset); SendWindowMessage(message2); } // we run through the controls, rendering as we go bool render(g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height)); float pos = 0; float focusedPos = 0; CGUIControl *focusedControl = NULL; for (iControls it = m_children.begin(); it != m_children.end(); ++it) { // note we render all controls, even if they're offscreen, as then they'll be updated // with respect to animations CGUIControl *control = *it; control->UpdateVisibility(); if (m_renderFocusedLast && control->HasFocus()) { focusedControl = control; focusedPos = pos; } else { if (m_orientation == VERTICAL) g_graphicsContext.SetOrigin(m_posX, m_posY + pos - m_offset); else g_graphicsContext.SetOrigin(m_posX + pos - m_offset, m_posY); control->DoRender(m_renderTime); } if (control->IsVisible()) pos += Size(control) + m_itemGap; g_graphicsContext.RestoreOrigin(); } if (focusedControl) { if (m_orientation == VERTICAL) g_graphicsContext.SetOrigin(m_posX, m_posY + focusedPos - m_offset); else g_graphicsContext.SetOrigin(m_posX + focusedPos - m_offset, m_posY); focusedControl->DoRender(m_renderTime); } if (render) g_graphicsContext.RestoreClipRegion(); CGUIControl::Render(); }