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 "GUIViewControl.h"
22 #include "guilib/GUIWindowManager.h"
23 #include "utils/URIUtils.h"
24 #include "utils/StringUtils.h"
26 #include "guilib/LocalizeStrings.h"
27 #include "GUIInfoManager.h"
28 #include "guilib/WindowIDs.h"
29 #include "guilib/IGUIContainer.h"
31 CGUIViewControl::CGUIViewControl(void)
34 m_parentWindow = WINDOW_INVALID;
39 CGUIViewControl::~CGUIViewControl(void)
43 void CGUIViewControl::Reset()
46 m_visibleViews.clear();
50 void CGUIViewControl::AddView(const CGUIControl *control)
52 if (!control || !control->IsContainer()) return;
53 m_allViews.push_back((CGUIControl *)control);
56 void CGUIViewControl::SetViewControlID(int control)
58 m_viewAsControl = control;
61 void CGUIViewControl::SetParentWindow(int window)
63 m_parentWindow = window;
66 void CGUIViewControl::SetCurrentView(int viewMode, bool bRefresh /* = false */)
68 // grab the previous control
69 CGUIControl *previousView = NULL;
70 if (m_currentView >= 0 && m_currentView < (int)m_visibleViews.size())
71 previousView = m_visibleViews[m_currentView];
73 UpdateViewVisibility();
75 // viewMode is of the form TYPE << 16 | ID
76 VIEW_TYPE type = (VIEW_TYPE)(viewMode >> 16);
77 int id = viewMode & 0xffff;
79 // first find a view that matches this view, if possible...
80 int newView = GetView(type, id);
81 if (newView < 0) // no suitable view that matches both id and type, so try just type
82 newView = GetView(type, 0);
83 if (newView < 0 && type == VIEW_TYPE_BIG_ICON) // try icon view if they want big icon
84 newView = GetView(VIEW_TYPE_ICON, 0);
85 if (newView < 0 && type == VIEW_TYPE_BIG_INFO)
86 newView = GetView(VIEW_TYPE_INFO, 0);
87 if (newView < 0) // try a list view
88 newView = GetView(VIEW_TYPE_LIST, 0);
89 if (newView < 0) // try anything!
90 newView = GetView(VIEW_TYPE_NONE, 0);
95 m_currentView = newView;
96 CGUIControl *pNewView = m_visibleViews[m_currentView];
98 // make only current control visible...
99 for (ciViews view = m_allViews.begin(); view != m_allViews.end(); view++)
100 (*view)->SetVisible(false);
101 pNewView->SetVisible(true);
103 if (!bRefresh && pNewView == previousView)
104 return; // no need to actually update anything (other than visibility above)
106 // CLog::Log(LOGDEBUG,"SetCurrentView: Oldview: %i, Newview :%i", m_currentView, viewMode);
108 bool hasFocus(false);
111 { // have an old view - let's clear it out and hide it.
112 hasFocus = previousView->HasFocus();
113 item = GetSelectedItem(previousView);
114 CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, previousView->GetID());
115 previousView->OnMessage(msg);
118 // Update it with the contents
119 UpdateContents(pNewView, item);
121 // and focus if necessary
124 CGUIMessage msg(GUI_MSG_SETFOCUS, m_parentWindow, pNewView->GetID(), 0);
125 g_windowManager.SendMessage(msg, m_parentWindow);
128 // Update our view control only if we are not in the TV Window
129 if (m_parentWindow != WINDOW_PVR)
130 UpdateViewAsControl(((IGUIContainer *)pNewView)->GetLabel());
133 void CGUIViewControl::SetItems(CFileItemList &items)
135 // CLog::Log(LOGDEBUG,"SetItems: %i", m_currentView);
136 m_fileItems = &items;
137 // update our current view control...
141 void CGUIViewControl::UpdateContents(const CGUIControl *control, int currentItem)
143 if (!control || !m_fileItems) return;
144 CGUIMessage msg(GUI_MSG_LABEL_BIND, m_parentWindow, control->GetID(), currentItem, 0, m_fileItems);
145 g_windowManager.SendMessage(msg, m_parentWindow);
148 void CGUIViewControl::UpdateView()
150 // CLog::Log(LOGDEBUG,"UpdateView: %i", m_currentView);
151 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
152 return; // no valid current view!
154 CGUIControl *pControl = m_visibleViews[m_currentView];
155 // get the currently selected item
156 int item = GetSelectedItem(pControl);
157 UpdateContents(pControl, item < 0 ? 0 : item);
160 int CGUIViewControl::GetSelectedItem(const CGUIControl *control) const
162 if (!control || !m_fileItems) return -1;
163 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, m_parentWindow, control->GetID());
164 g_windowManager.SendMessage(msg, m_parentWindow);
166 int iItem = msg.GetParam1();
167 if (iItem >= m_fileItems->Size())
172 int CGUIViewControl::GetSelectedItem() const
174 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
175 return -1; // no valid current view!
177 return GetSelectedItem(m_visibleViews[m_currentView]);
180 void CGUIViewControl::SetSelectedItem(int item)
182 if (!m_fileItems || item < 0 || item >= m_fileItems->Size())
185 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
186 return; // no valid current view!
188 CGUIMessage msg(GUI_MSG_ITEM_SELECT, m_parentWindow, m_visibleViews[m_currentView]->GetID(), item);
189 g_windowManager.SendMessage(msg, m_parentWindow);
192 void CGUIViewControl::SetSelectedItem(const CStdString &itemPath)
194 if (!m_fileItems || itemPath.empty())
197 CStdString comparePath(itemPath);
198 URIUtils::RemoveSlashAtEnd(comparePath);
201 for (int i = 0; i < m_fileItems->Size(); ++i)
203 CStdString strPath =(*m_fileItems)[i]->GetPath();
204 URIUtils::RemoveSlashAtEnd(strPath);
205 if (strPath.CompareNoCase(comparePath) == 0)
211 SetSelectedItem(item);
214 void CGUIViewControl::SetFocused()
216 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
217 return; // no valid current view!
219 CGUIMessage msg(GUI_MSG_SETFOCUS, m_parentWindow, m_visibleViews[m_currentView]->GetID(), 0);
220 g_windowManager.SendMessage(msg, m_parentWindow);
223 bool CGUIViewControl::HasControl(int viewControlID) const
225 // run through our controls, checking for the id
226 for (ciViews it = m_allViews.begin(); it != m_allViews.end(); it++)
228 if ((*it)->GetID() == viewControlID)
234 int CGUIViewControl::GetCurrentControl() const
236 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
237 return -1; // no valid current view!
239 return m_visibleViews[m_currentView]->GetID();
242 // returns the number-th view's viewmode (type and id)
243 int CGUIViewControl::GetViewModeNumber(int number) const
245 IGUIContainer *nextView = NULL;
246 if (number >= 0 && number < (int)m_visibleViews.size())
247 nextView = (IGUIContainer *)m_visibleViews[number];
248 else if (m_visibleViews.size())
249 nextView = (IGUIContainer *)m_visibleViews[0];
251 return (nextView->GetType() << 16) | nextView->GetID();
252 return 0; // no view modes :(
255 int CGUIViewControl::GetViewModeByID(int id) const
257 for (unsigned int i = 0; i < m_visibleViews.size(); ++i)
259 IGUIContainer *view = (IGUIContainer *)m_visibleViews[i];
260 if (view->GetID() == id)
261 return (view->GetType() << 16) | view->GetID();
263 return 0; // no view modes :(
266 // returns the next viewmode in the cycle
267 int CGUIViewControl::GetNextViewMode(int direction) const
269 if (!m_visibleViews.size())
270 return 0; // no view modes :(
272 int viewNumber = (m_currentView + direction) % (int)m_visibleViews.size();
273 if (viewNumber < 0) viewNumber += m_visibleViews.size();
274 IGUIContainer *nextView = (IGUIContainer *)m_visibleViews[viewNumber];
275 return (nextView->GetType() << 16) | nextView->GetID();
278 void CGUIViewControl::Clear()
280 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
281 return; // no valid current view!
283 CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, m_visibleViews[m_currentView]->GetID(), 0);
284 g_windowManager.SendMessage(msg, m_parentWindow);
287 int CGUIViewControl::GetView(VIEW_TYPE type, int id) const
289 for (int i = 0; i < (int)m_visibleViews.size(); i++)
291 IGUIContainer *view = (IGUIContainer *)m_visibleViews[i];
292 if ((type == VIEW_TYPE_NONE || type == view->GetType()) && (!id || view->GetID() == id))
298 void CGUIViewControl::UpdateViewAsControl(const CStdString &viewLabel)
300 // the view as control could be a select/spin/dropdown button
301 CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, m_viewAsControl);
302 g_windowManager.SendMessage(msg, m_parentWindow);
303 for (unsigned int i = 0; i < m_visibleViews.size(); i++)
305 IGUIContainer *view = (IGUIContainer *)m_visibleViews[i];
306 CGUIMessage msg(GUI_MSG_LABEL_ADD, m_parentWindow, m_viewAsControl, i);
307 CStdString label = StringUtils::Format(g_localizeStrings.Get(534).c_str(), view->GetLabel().c_str()); // View: %s
309 g_windowManager.SendMessage(msg, m_parentWindow);
311 CGUIMessage msgSelect(GUI_MSG_ITEM_SELECT, m_parentWindow, m_viewAsControl, m_currentView);
312 g_windowManager.SendMessage(msgSelect, m_parentWindow);
314 // otherwise it's just a normal button
315 CStdString label = StringUtils::Format(g_localizeStrings.Get(534).c_str(), viewLabel.c_str()); // View: %s
316 CGUIMessage msgSet(GUI_MSG_LABEL_SET, m_parentWindow, m_viewAsControl);
317 msgSet.SetLabel(label);
318 g_windowManager.SendMessage(msgSet, m_parentWindow);
321 void CGUIViewControl::UpdateViewVisibility()
323 // first reset our infomanager cache, as it's likely that the vis conditions
324 // used for views (i.e. based on contenttype) may have changed
325 g_infoManager.ResetCache();
326 m_visibleViews.clear();
327 for (unsigned int i = 0; i < m_allViews.size(); i++)
329 CGUIControl *view = m_allViews[i];
330 if (view->GetVisibleCondition())
332 view->UpdateVisibility();
333 if (view->IsVisibleFromSkin())
334 m_visibleViews.push_back(view);
337 m_visibleViews.push_back(view);