[cstdstring] remove IsEmpty() and replace with empty()
[vuplus_xbmc] / xbmc / view / GUIViewControl.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 #include "GUIViewControl.h"
22 #include "guilib/GUIWindowManager.h"
23 #include "utils/URIUtils.h"
24 #include "utils/StringUtils.h"
25 #include "FileItem.h"
26 #include "guilib/LocalizeStrings.h"
27 #include "GUIInfoManager.h"
28 #include "guilib/WindowIDs.h"
29 #include "guilib/IGUIContainer.h"
30
31 CGUIViewControl::CGUIViewControl(void)
32 {
33   m_viewAsControl = -1;
34   m_parentWindow = WINDOW_INVALID;
35   m_fileItems = NULL;
36   Reset();
37 }
38
39 CGUIViewControl::~CGUIViewControl(void)
40 {
41 }
42
43 void CGUIViewControl::Reset()
44 {
45   m_currentView = -1;
46   m_visibleViews.clear();
47   m_allViews.clear();
48 }
49
50 void CGUIViewControl::AddView(const CGUIControl *control)
51 {
52   if (!control || !control->IsContainer()) return;
53   m_allViews.push_back((CGUIControl *)control);
54 }
55
56 void CGUIViewControl::SetViewControlID(int control)
57 {
58   m_viewAsControl = control;
59 }
60
61 void CGUIViewControl::SetParentWindow(int window)
62 {
63   m_parentWindow = window;
64 }
65
66 void CGUIViewControl::SetCurrentView(int viewMode, bool bRefresh /* = false */)
67 {
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];
72
73   UpdateViewVisibility();
74
75   // viewMode is of the form TYPE << 16 | ID
76   VIEW_TYPE type = (VIEW_TYPE)(viewMode >> 16);
77   int id = viewMode & 0xffff;
78
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);
91
92   if (newView < 0)
93     return;
94
95   m_currentView = newView;
96   CGUIControl *pNewView = m_visibleViews[m_currentView];
97
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);
102
103   if (!bRefresh && pNewView == previousView)
104     return; // no need to actually update anything (other than visibility above)
105
106 //  CLog::Log(LOGDEBUG,"SetCurrentView: Oldview: %i, Newview :%i", m_currentView, viewMode);
107
108   bool hasFocus(false);
109   int item = -1;
110   if (previousView)
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);
116   }
117
118   // Update it with the contents
119   UpdateContents(pNewView, item);
120
121   // and focus if necessary
122   if (hasFocus)
123   {
124     CGUIMessage msg(GUI_MSG_SETFOCUS, m_parentWindow, pNewView->GetID(), 0);
125     g_windowManager.SendMessage(msg, m_parentWindow);
126   }
127
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());
131 }
132
133 void CGUIViewControl::SetItems(CFileItemList &items)
134 {
135 //  CLog::Log(LOGDEBUG,"SetItems: %i", m_currentView);
136   m_fileItems = &items;
137   // update our current view control...
138   UpdateView();
139 }
140
141 void CGUIViewControl::UpdateContents(const CGUIControl *control, int currentItem)
142 {
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);
146 }
147
148 void CGUIViewControl::UpdateView()
149 {
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!
153
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);
158 }
159
160 int CGUIViewControl::GetSelectedItem(const CGUIControl *control) const
161 {
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);
165
166   int iItem = msg.GetParam1();
167   if (iItem >= m_fileItems->Size())
168     return -1;
169   return iItem;
170 }
171
172 int CGUIViewControl::GetSelectedItem() const
173 {
174   if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
175     return -1; // no valid current view!
176
177   return GetSelectedItem(m_visibleViews[m_currentView]);
178 }
179
180 void CGUIViewControl::SetSelectedItem(int item)
181 {
182   if (!m_fileItems || item < 0 || item >= m_fileItems->Size())
183     return;
184
185   if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
186     return; // no valid current view!
187
188   CGUIMessage msg(GUI_MSG_ITEM_SELECT, m_parentWindow, m_visibleViews[m_currentView]->GetID(), item);
189   g_windowManager.SendMessage(msg, m_parentWindow);
190 }
191
192 void CGUIViewControl::SetSelectedItem(const CStdString &itemPath)
193 {
194   if (!m_fileItems || itemPath.empty())
195     return;
196
197   CStdString comparePath(itemPath);
198   URIUtils::RemoveSlashAtEnd(comparePath);
199
200   int item = -1;
201   for (int i = 0; i < m_fileItems->Size(); ++i)
202   {
203     CStdString strPath =(*m_fileItems)[i]->GetPath();
204     URIUtils::RemoveSlashAtEnd(strPath);
205     if (strPath.CompareNoCase(comparePath) == 0)
206     {
207       item = i;
208       break;
209     }
210   }
211   SetSelectedItem(item);
212 }
213
214 void CGUIViewControl::SetFocused()
215 {
216   if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
217     return; // no valid current view!
218
219   CGUIMessage msg(GUI_MSG_SETFOCUS, m_parentWindow, m_visibleViews[m_currentView]->GetID(), 0);
220   g_windowManager.SendMessage(msg, m_parentWindow);
221 }
222
223 bool CGUIViewControl::HasControl(int viewControlID) const
224 {
225   // run through our controls, checking for the id
226   for (ciViews it = m_allViews.begin(); it != m_allViews.end(); it++)
227   {
228     if ((*it)->GetID() == viewControlID)
229       return true;
230   }
231   return false;
232 }
233
234 int CGUIViewControl::GetCurrentControl() const
235 {
236   if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
237     return -1; // no valid current view!
238
239   return m_visibleViews[m_currentView]->GetID();
240 }
241
242 // returns the number-th view's viewmode (type and id)
243 int CGUIViewControl::GetViewModeNumber(int number) const
244 {
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];
250   if (nextView)
251     return (nextView->GetType() << 16) | nextView->GetID();
252   return 0;  // no view modes :(
253 }
254
255 int CGUIViewControl::GetViewModeByID(int id) const
256 {
257   for (unsigned int i = 0; i < m_visibleViews.size(); ++i)
258   {
259     IGUIContainer *view = (IGUIContainer *)m_visibleViews[i];
260     if (view->GetID() == id)
261       return (view->GetType() << 16) | view->GetID();
262   }
263   return 0;  // no view modes :(
264 }
265
266 // returns the next viewmode in the cycle
267 int CGUIViewControl::GetNextViewMode(int direction) const
268 {
269   if (!m_visibleViews.size())
270     return 0; // no view modes :(
271
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();
276 }
277
278 void CGUIViewControl::Clear()
279 {
280   if (m_currentView < 0 || m_currentView >= (int)m_visibleViews.size())
281     return; // no valid current view!
282
283   CGUIMessage msg(GUI_MSG_LABEL_RESET, m_parentWindow, m_visibleViews[m_currentView]->GetID(), 0);
284   g_windowManager.SendMessage(msg, m_parentWindow);
285 }
286
287 int CGUIViewControl::GetView(VIEW_TYPE type, int id) const
288 {
289   for (int i = 0; i < (int)m_visibleViews.size(); i++)
290   {
291     IGUIContainer *view = (IGUIContainer *)m_visibleViews[i];
292     if ((type == VIEW_TYPE_NONE || type == view->GetType()) && (!id || view->GetID() == id))
293       return i;
294   }
295   return -1;
296 }
297
298 void CGUIViewControl::UpdateViewAsControl(const CStdString &viewLabel)
299 {
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++)
304   {
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
308     msg.SetLabel(label);
309     g_windowManager.SendMessage(msg, m_parentWindow);
310   }
311   CGUIMessage msgSelect(GUI_MSG_ITEM_SELECT, m_parentWindow, m_viewAsControl, m_currentView);
312   g_windowManager.SendMessage(msgSelect, m_parentWindow);
313
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);
319 }
320
321 void CGUIViewControl::UpdateViewVisibility()
322 {
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++)
328   {
329     CGUIControl *view = m_allViews[i];
330     if (view->GetVisibleCondition())
331     {
332       view->UpdateVisibility();
333       if (view->IsVisibleFromSkin())
334         m_visibleViews.push_back(view);
335     }
336     else
337       m_visibleViews.push_back(view);
338   }
339 }
340