EVENT_RESULT CGUIControlGroupList::OnMouseEvent(const CPoint &point, const CMouseEvent &event) { if (event.m_id == ACTION_MOUSE_WHEEL_UP || event.m_id == ACTION_MOUSE_WHEEL_DOWN) { // find the current control and move to the next or previous float offset = 0; for (ciControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; if (!control->IsVisible()) continue; float nextOffset = offset + Size(control) + m_itemGap; if (event.m_id == ACTION_MOUSE_WHEEL_DOWN && nextOffset > m_scroller.GetValue() && m_scroller.GetValue() < m_totalSize - Size()) // past our current offset { ScrollTo(nextOffset); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_MOUSE_WHEEL_UP && nextOffset >= m_scroller.GetValue() && m_scroller.GetValue() > 0) // at least at our current offset { ScrollTo(offset); return EVENT_RESULT_HANDLED; } offset = nextOffset; } } return EVENT_RESULT_UNHANDLED; }
EVENT_RESULT CGUIControlGroupList::SendMouseEvent(const CPoint &point, const CMouseEvent &event) { // transform our position into child coordinates CPoint childPoint(point); m_transform.InverseTransformPosition(childPoint.x, childPoint.y); if (CGUIControl::CanFocus()) { float pos = 0; float alignOffset = GetAlignOffset(); for (ciControls i = m_children.begin(); i != m_children.end(); ++i) { CGUIControl *child = *i; if (child->IsVisible()) { if (IsControlOnScreen(pos, child)) { // we're on screen float offsetX = m_orientation == VERTICAL ? m_posX : m_posX + alignOffset + pos - m_scroller.GetValue(); float offsetY = m_orientation == VERTICAL ? m_posY + alignOffset + pos - m_scroller.GetValue() : m_posY; EVENT_RESULT ret = child->SendMouseEvent(childPoint - CPoint(offsetX, offsetY), event); if (ret) { // we've handled the action, and/or have focused an item return ret; } } pos += Size(child) + m_itemGap; } } // none of our children want the event, but we may want it. EVENT_RESULT ret; if (HitTest(childPoint) && (ret = OnMouseEvent(childPoint, event))) return ret; } m_focusedControl = 0; return EVENT_RESULT_UNHANDLED; }
float CGUIControlGroupList::GetTotalSize() const { float totalSize = 0; for (ciControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; if (!control->IsVisible()) continue; totalSize += Size(control) + m_itemGap; } if (totalSize > 0) totalSize -= m_itemGap; return totalSize; }
bool CGUIControlGroupList::IsLastFocusableControl(const CGUIControl *control) const { for (crControls it = m_children.rbegin(); it != m_children.rend(); ++it) { CGUIControl *child = *it; if (child->IsVisible() && child->CanFocus()) { // found first focusable return child == control; } } return false; }
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 CGUIControlGroupList::ValidateOffset() { // calculate how many items we have on this page m_totalSize = 0; for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; if (!control->IsVisible()) continue; m_totalSize += Size(control) + m_itemGap; } if (m_totalSize > 0) m_totalSize -= m_itemGap; // check our m_offset range if (m_offset > m_totalSize - Size()) m_offset = m_totalSize - Size(); if (m_offset < 0) m_offset = 0; }
EVENT_RESULT CGUIControlGroupList::OnMouseEvent(const CPoint &point, const CMouseEvent &event) { if (event.m_id == ACTION_MOUSE_WHEEL_UP || event.m_id == ACTION_MOUSE_WHEEL_DOWN) { // find the current control and move to the next or previous float offset = 0; for (ciControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; if (!control->IsVisible()) continue; float nextOffset = offset + Size(control) + m_itemGap; if (event.m_id == ACTION_MOUSE_WHEEL_DOWN && nextOffset > m_scroller.GetValue() && m_scroller.GetValue() < m_totalSize - Size()) // past our current offset { ScrollTo(nextOffset); return EVENT_RESULT_HANDLED; } else if (event.m_id == ACTION_MOUSE_WHEEL_UP && nextOffset >= m_scroller.GetValue() && m_scroller.GetValue() > 0) // at least at our current offset { ScrollTo(offset); return EVENT_RESULT_HANDLED; } offset = nextOffset; } } 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_END) { // release exclusive access CGUIMessage msg(GUI_MSG_EXCLUSIVE_MOUSE, 0, 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(CLAMP(m_scroller.GetValue() - ((m_orientation == HORIZONTAL) ? event.m_offsetX : event.m_offsetY), 0, m_totalSize - Size())); SetInvalid(); return EVENT_RESULT_HANDLED; } return EVENT_RESULT_UNHANDLED; }
CGUIControl *CGUIControlGroup::GetControl(int iControl) { CGUIControl *pPotential = NULL; LookupMap::iterator first = m_lookup.find(iControl); if (first != m_lookup.end()) { LookupMap::iterator last = m_lookup.upper_bound(iControl); for (LookupMap::iterator i = first; i != last; ++i) { CGUIControl *control = i->second; if (control->IsVisible()) return control; else if (!pPotential) pPotential = control; } } return pPotential; }
void CGUIControlGroup::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { CPoint pos(GetPosition()); g_graphicsContext.SetOrigin(pos.x, pos.y); CRect rect; for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; control->UpdateVisibility(); unsigned int oldDirty = dirtyregions.size(); control->DoProcess(currentTime, dirtyregions); if (control->IsVisible() || (oldDirty != dirtyregions.size())) // visible or dirty (was visible?) rect.Union(control->GetRenderRegion()); } g_graphicsContext.RestoreOrigin(); CGUIControl::Process(currentTime, dirtyregions); m_renderRegion = rect; }
void CGUIListGroup::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { CServiceBroker::GetWinSystem()->GetGfxContext().SetOrigin(m_posX, m_posY); CRect rect; for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *control = *it; control->UpdateVisibility(m_item); unsigned int oldDirty = dirtyregions.size(); control->DoProcess(currentTime, dirtyregions); if (control->IsVisible() || (oldDirty != dirtyregions.size())) // visible or dirty (was visible?) rect.Union(control->GetRenderRegion()); } CServiceBroker::GetWinSystem()->GetGfxContext().RestoreOrigin(); CGUIControl::Process(currentTime, dirtyregions); m_renderRegion = rect; m_item = NULL; }
void CGUIControlGroupList::UnfocusFromPoint(const CPoint &point) { float pos = 0; CPoint controlCoords(point); m_transform.InverseTransformPosition(controlCoords.x, controlCoords.y); for (iControls it = m_children.begin(); it != m_children.end(); ++it) { CGUIControl *child = *it; if (child->IsVisible()) { if (pos + Size(child) > m_offset && pos < m_offset + Size()) { // we're on screen CPoint offset = (m_orientation == VERTICAL) ? CPoint(m_posX, m_posY + pos - m_offset) : CPoint(m_posX + pos - m_offset, m_posY); child->UnfocusFromPoint(controlCoords - offset); } pos += Size(child) + m_itemGap; } } CGUIControl::UnfocusFromPoint(point); }
void CGUIControlGroupList::Render() { // we run through the controls, rendering as we go bool render(g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height)); float pos = GetAlignOffset(); 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; if (m_renderFocusedLast && control->HasFocus()) { focusedControl = control; focusedPos = pos; } else { 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->DoRender(); } 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_scroller.GetValue()); else g_graphicsContext.SetOrigin(m_posX + focusedPos - m_scroller.GetValue(), m_posY); focusedControl->DoRender(); } if (render) g_graphicsContext.RestoreClipRegion(); CGUIControl::Render(); }
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 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(); }