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"
25 #include "guilib/LocalizeStrings.h"
26 #include "GUIInfoManager.h"
27 #include "guilib/Key.h"
29 CGUIViewControl::CGUIViewControl(void)
32 m_parentWindow = WINDOW_INVALID;
37 CGUIViewControl::~CGUIViewControl(void)
41 void CGUIViewControl::Reset()
44 m_visibleViews.clear();
48 void CGUIViewControl::AddView(const CGUIControl *control)
50 if (!control || !control->IsContainer()) return;
51 m_allViews.push_back((CGUIControl *)control);
54 void CGUIViewControl::SetViewControlID(int control)
56 m_viewAsControl = control;
59 void CGUIViewControl::SetParentWindow(int window)
61 m_parentWindow = window;
64 void CGUIViewControl::SetCurrentView(int viewMode, bool bRefresh /* = false */)
66 // grab the previous control
67 CGUIControl *previousView = NULL;
68 if (m_currentView >= 0 && m_currentView < (int)m_visibleViews.size())
69 previousView = m_visibleViews[m_currentView];
71 UpdateViewVisibility();
73 // viewMode is of the form TYPE << 16 | ID
74 VIEW_TYPE type = (VIEW_TYPE)(viewMode >> 16);
75 int id = viewMode & 0xffff;
77 // first find a view that matches this view, if possible...
78 int newView = GetView(type, id);
79 if (newView < 0) // no suitable view that matches both id and type, so try just type
80 newView = GetView(type, 0);
81 if (newView < 0 && type == VIEW_TYPE_BIG_ICON) // try icon view if they want big icon
82 newView = GetView(VIEW_TYPE_ICON, 0);
83 if (newView < 0 && type == VIEW_TYPE_BIG_INFO)
84 newView = GetView(VIEW_TYPE_INFO, 0);
85 if (newView < 0) // try a list view
86 newView = GetView(VIEW_TYPE_LIST, 0);
87 if (newView < 0) // try anything!
88 newView = GetView(VIEW_TYPE_NONE, 0);
93 m_currentView = newView;
94 CGUIControl *pNewView = m_visibleViews[m_currentView];
96 // make only current control visible...
97 for (ciViews view = m_allViews.begin(); view != m_allViews.end(); view++)
98 (*view)->SetVisible(false);
99 pNewView->SetVisible(true);
101 if (!bRefresh && pNewView == previousView)
102 return; // no need to actually update anything (other than visibility above)
104 // CLog::Log(LOGDEBUG,"SetCurrentView: Oldview: %i, Newview :%i", m_currentView, viewMode);
106 bool hasFocus(false);
109 { // have an old view - let's clear it out and hide it.
110 hasFocus = previousView->HasFocus();
111 item = GetSelectedItem(previousView);
112 CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, previousView->GetID());
113 previousView->OnMessage(msg);
116 // Update it with the contents
117 UpdateContents(pNewView, item);
119 // and focus if necessary
122 CGUIMessage msg(GUI_MSG_SETFOCUS, m_parentWindow, pNewView->GetID(), 0);
123 g_windowManager.SendMessage(msg);
126 // Update our view control only if we are not in the TV Window
127 if (m_parentWindow != WINDOW_PVR)
128 UpdateViewAsControl(((IGUIContainer *)pNewView)->GetLabel());
131 void CGUIViewControl::SetItems(CFileItemList &items)
133 // CLog::Log(LOGDEBUG,"SetItems: %i", m_currentView);
134 m_fileItems = &items;
135 // update our current view control...
139 void CGUIViewControl::UpdateContents(const CGUIControl *control, int currentItem)
141 if (!control || !m_fileItems) return;
142 CGUIMessage msg(GUI_MSG_LABEL_BIND, m_parentWindow, control->GetID(), currentItem, 0, m_fileItems);
143 g_windowManager.SendMessage(msg);
146 void CGUIViewControl::UpdateView()
148 // CLog::Log(LOGDEBUG,"UpdateView: %i", m_currentView);
149 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
150 return; // no valid current view!
152 CGUIControl *pControl = m_visibleViews[m_currentView];
153 // get the currently selected item
154 int item = GetSelectedItem(pControl);
155 UpdateContents(pControl, item < 0 ? 0 : item);
158 int CGUIViewControl::GetSelectedItem(const CGUIControl *control) const
160 if (!control || !m_fileItems) return -1;
161 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, m_parentWindow, control->GetID());
162 g_windowManager.SendMessage(msg);
164 int iItem = msg.GetParam1();
165 if (iItem >= m_fileItems->Size())
170 int CGUIViewControl::GetSelectedItem() const
172 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
173 return -1; // no valid current view!
175 return GetSelectedItem(m_visibleViews[m_currentView]);
178 void CGUIViewControl::SetSelectedItem(int item)
180 if (!m_fileItems || item < 0 || item >= m_fileItems->Size())
183 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
184 return; // no valid current view!
186 CGUIMessage msg(GUI_MSG_ITEM_SELECT, m_parentWindow, m_visibleViews[m_currentView]->GetID(), item);
187 g_windowManager.SendMessage(msg);
190 void CGUIViewControl::SetSelectedItem(const CStdString &itemPath)
192 if (!m_fileItems || itemPath.IsEmpty())
195 CStdString comparePath(itemPath);
196 URIUtils::RemoveSlashAtEnd(comparePath);
199 for (int i = 0; i < m_fileItems->Size(); ++i)
201 CStdString strPath =(*m_fileItems)[i]->GetPath();
202 URIUtils::RemoveSlashAtEnd(strPath);
203 if (strPath.CompareNoCase(comparePath) == 0)
209 SetSelectedItem(item);
212 void CGUIViewControl::SetFocused()
214 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
215 return; // no valid current view!
217 CGUIMessage msg(GUI_MSG_SETFOCUS, m_parentWindow, m_visibleViews[m_currentView]->GetID(), 0);
218 g_windowManager.SendMessage(msg);
221 bool CGUIViewControl::HasControl(int viewControlID) const
223 // run through our controls, checking for the id
224 for (ciViews it = m_allViews.begin(); it != m_allViews.end(); it++)
226 if ((*it)->GetID() == viewControlID)
232 int CGUIViewControl::GetCurrentControl() const
234 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
235 return -1; // no valid current view!
237 return m_visibleViews[m_currentView]->GetID();
240 // returns the number-th view's viewmode (type and id)
241 int CGUIViewControl::GetViewModeNumber(int number) const
243 IGUIContainer *nextView = NULL;
244 if (number >= 0 && number < (int)m_visibleViews.size())
245 nextView = (IGUIContainer *)m_visibleViews[number];
246 else if (m_visibleViews.size())
247 nextView = (IGUIContainer *)m_visibleViews[0];
249 return (nextView->GetType() << 16) | nextView->GetID();
250 return 0; // no view modes :(
253 int CGUIViewControl::GetViewModeByID(int id) const
255 for (unsigned int i = 0; i < m_visibleViews.size(); ++i)
257 IGUIContainer *view = (IGUIContainer *)m_visibleViews[i];
258 if (view->GetID() == id)
259 return (view->GetType() << 16) | view->GetID();
261 return 0; // no view modes :(
264 // returns the next viewmode in the cycle
265 int CGUIViewControl::GetNextViewMode(int direction) const
267 if (!m_visibleViews.size())
268 return 0; // no view modes :(
270 int viewNumber = (m_currentView + direction) % (int)m_visibleViews.size();
271 if (viewNumber < 0) viewNumber += m_visibleViews.size();
272 IGUIContainer *nextView = (IGUIContainer *)m_visibleViews[viewNumber];
273 return (nextView->GetType() << 16) | nextView->GetID();
276 void CGUIViewControl::Clear()
278 if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
279 return; // no valid current view!
281 CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, m_visibleViews[m_currentView]->GetID(), 0);
282 g_windowManager.SendMessage(msg);
285 int CGUIViewControl::GetView(VIEW_TYPE type, int id) const
287 for (int i = 0; i < (int)m_visibleViews.size(); i++)
289 IGUIContainer *view = (IGUIContainer *)m_visibleViews[i];
290 if ((type == VIEW_TYPE_NONE || type == view->GetType()) && (!id || view->GetID() == id))
296 void CGUIViewControl::UpdateViewAsControl(const CStdString &viewLabel)
298 // the view as control could be a select/spin/dropdown button
299 CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, m_viewAsControl);
300 g_windowManager.SendMessage(msg);
301 for (unsigned int i = 0; i < m_visibleViews.size(); i++)
303 IGUIContainer *view = (IGUIContainer *)m_visibleViews[i];
304 CGUIMessage msg(GUI_MSG_LABEL_ADD, m_parentWindow, m_viewAsControl, i);
306 label.Format(g_localizeStrings.Get(534).c_str(), view->GetLabel().c_str()); // View: %s
308 g_windowManager.SendMessage(msg);
310 CGUIMessage msgSelect(GUI_MSG_ITEM_SELECT, m_parentWindow, m_viewAsControl, m_currentView);
311 g_windowManager.SendMessage(msgSelect);
313 // otherwise it's just a normal button
315 label.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);
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);