2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "GUIWrappingListContainer.h"
24 #include "utils/log.h"
26 CGUIWrappingListContainer::CGUIWrappingListContainer(int parentID, int controlID, float posX, float posY, float width, float height, ORIENTATION orientation, const CScroller& scroller, int preloadItems, int fixedPosition)
27 : CGUIBaseContainer(parentID, controlID, posX, posY, width, height, orientation, scroller, preloadItems)
29 SetCursor(fixedPosition);
30 ControlType = GUICONTAINER_WRAPLIST;
31 m_type = VIEW_TYPE_LIST;
35 CGUIWrappingListContainer::~CGUIWrappingListContainer(void)
39 void CGUIWrappingListContainer::UpdatePageControl(int offset)
42 { // tell our pagecontrol (scrollbar or whatever) to update (offset it by our cursor position)
43 CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), m_pageControl, GetNumItems() ? CorrectOffset(offset, GetCursor()) % GetNumItems() : 0);
44 SendWindowMessage(msg);
48 bool CGUIWrappingListContainer::OnAction(const CAction &action)
50 switch (action.GetID())
53 Scroll(-m_itemsPerPage);
55 case ACTION_PAGE_DOWN:
56 Scroll(m_itemsPerPage);
58 // smooth scrolling (for analog controls)
59 case ACTION_SCROLL_UP:
61 m_analogScrollCount += action.GetAmount() * action.GetAmount();
63 while (m_analogScrollCount > 0.4)
66 m_analogScrollCount -= 0.4f;
72 case ACTION_SCROLL_DOWN:
74 m_analogScrollCount += action.GetAmount() * action.GetAmount();
76 while (m_analogScrollCount > 0.4)
79 m_analogScrollCount -= 0.4f;
86 return CGUIBaseContainer::OnAction(action);
89 bool CGUIWrappingListContainer::OnMessage(CGUIMessage& message)
91 if (message.GetControlId() == GetID() )
93 if (message.GetMessage() == GUI_MSG_PAGE_CHANGE)
95 if (message.GetSenderId() == m_pageControl && IsVisible())
96 { // offset by our cursor position
97 message.SetParam1(message.GetParam1() - GetCursor());
101 return CGUIBaseContainer::OnMessage(message);
104 bool CGUIWrappingListContainer::MoveUp(bool wrapAround)
110 bool CGUIWrappingListContainer::MoveDown(bool wrapAround)
116 // scrolls the said amount
117 void CGUIWrappingListContainer::Scroll(int amount)
119 ScrollToOffset(GetOffset() + amount);
122 bool CGUIWrappingListContainer::GetOffsetRange(int &minOffset, int &maxOffset) const
127 void CGUIWrappingListContainer::ValidateOffset()
129 // our minimal amount of items - we need to take into acount extra items to display wrapped items when scrolling
130 unsigned int minItems = (unsigned int)m_itemsPerPage + ScrollCorrectionRange() + GetCacheCount() / 2;
131 if (minItems <= m_items.size())
134 // no need to check the range here, but we need to check we have
135 // more items than slots.
139 unsigned int numItems = m_items.size();
140 while (m_items.size() < minItems)
142 // add additional copies of items, as we require extras at render time
143 for (unsigned int i = 0; i < numItems; i++)
145 m_items.push_back(CGUIListItemPtr(m_items[i]->Clone()));
152 int CGUIWrappingListContainer::CorrectOffset(int offset, int cursor) const
156 int correctOffset = (offset + cursor) % (int)m_items.size();
157 if (correctOffset < 0) correctOffset += m_items.size();
158 return correctOffset;
163 int CGUIWrappingListContainer::GetSelectedItem() const
165 if (m_items.size() > m_extraItems)
167 int numItems = (int)(m_items.size() - m_extraItems);
168 int correctOffset = (GetOffset() + GetCursor()) % numItems;
169 if (correctOffset < 0) correctOffset += numItems;
170 return correctOffset;
175 bool CGUIWrappingListContainer::SelectItemFromPoint(const CPoint &point)
177 if (!m_focusedLayout || !m_layout)
180 const float mouse_scroll_speed = 0.05f;
181 const float mouse_max_amount = 1.0f; // max speed: 1 item per frame
182 float sizeOfItem = m_layout->Size(m_orientation);
183 // see if the point is either side of our focused item
184 float start = GetCursor() * sizeOfItem;
185 float end = start + m_focusedLayout->Size(m_orientation);
186 float pos = (m_orientation == VERTICAL) ? point.y : point.x;
187 if (pos < start - 0.5f * sizeOfItem)
189 if (!InsideLayout(m_layout, point))
191 float amount = std::min((start - pos) / sizeOfItem, mouse_max_amount);
192 m_analogScrollCount += amount * amount * mouse_scroll_speed;
193 if (m_analogScrollCount > 1)
196 m_analogScrollCount-=1.0f;
200 else if (pos > end + 0.5f * sizeOfItem)
202 if (!InsideLayout(m_layout, point))
205 float amount = std::min((pos - end) / sizeOfItem, mouse_max_amount);
206 m_analogScrollCount += amount * amount * mouse_scroll_speed;
207 if (m_analogScrollCount > 1)
210 m_analogScrollCount-=1.0f;
214 return InsideLayout(m_focusedLayout, point);
217 void CGUIWrappingListContainer::SelectItem(int item)
219 if (item >= 0 && item < (int)m_items.size())
220 ScrollToOffset(item - GetCursor());
223 void CGUIWrappingListContainer::ResetExtraItems()
225 // delete any extra items
227 m_items.erase(m_items.begin() + m_items.size() - m_extraItems, m_items.end());
231 void CGUIWrappingListContainer::Reset()
234 CGUIBaseContainer::Reset();
237 int CGUIWrappingListContainer::GetCurrentPage() const
239 int offset = CorrectOffset(GetOffset(), GetCursor());
240 if (offset + m_itemsPerPage - GetCursor() >= (int)GetRows()) // last page
241 return (GetRows() + m_itemsPerPage - 1) / m_itemsPerPage;
242 return offset / m_itemsPerPage + 1;
245 void CGUIWrappingListContainer::SetPageControlRange()
249 CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), m_pageControl, m_itemsPerPage, GetNumItems());
250 SendWindowMessage(msg);