changed: Use a single image control to handle the multiimage control now. Allows...
[xbmc:xbmc-antiquated.git] / XBMC / guilib / GUIMultiImage.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.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, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "include.h"
23 #include "GUIMultiImage.h"
24 #include "TextureManager.h"
25 #include "FileSystem/Directory.h"
26 #include "Util.h"
27 #include "FileItem.h"
28
29 using namespace std;
30 using namespace DIRECTORY;
31
32 CGUIMultiImage::CGUIMultiImage(DWORD dwParentID, DWORD dwControlId, float posX, float posY, float width, float height, const CTextureInfo& texture, DWORD timePerImage, DWORD fadeTime, bool randomized, bool loop, DWORD timeToPauseAtEnd)
33     : CGUIControl(dwParentID, dwControlId, posX, posY, width, height),
34       m_image(0, 0, posX, posY, width, height, texture)
35 {
36   m_currentImage = 0;
37   m_timePerImage = timePerImage + fadeTime;
38   m_timeToPauseAtEnd = timeToPauseAtEnd;
39   m_image.SetCrossFade(fadeTime);
40   m_randomized = randomized;
41   m_loop = loop;
42   ControlType = GUICONTROL_MULTI_IMAGE;
43   m_bDynamicResourceAlloc=false;
44   m_directoryLoaded = false;
45 }
46
47 CGUIMultiImage::CGUIMultiImage(const CGUIMultiImage &from)
48 : CGUIControl(from), m_image(from.m_image)
49 {
50   m_texturePath = from.m_texturePath;
51   m_timePerImage = from.m_timePerImage;
52   m_timeToPauseAtEnd = from.m_timeToPauseAtEnd;
53   m_randomized = from.m_randomized;
54   m_loop = from.m_loop;
55   m_bDynamicResourceAlloc=false;
56   m_directoryLoaded = false;
57   if (m_texturePath.IsConstant())
58     m_currentPath = m_texturePath.GetLabel(WINDOW_INVALID);
59   m_currentImage = 0;
60   ControlType = GUICONTROL_MULTI_IMAGE;
61 }
62
63 CGUIMultiImage::~CGUIMultiImage(void)
64 {
65 }
66
67 void CGUIMultiImage::UpdateVisibility(const CGUIListItem *item)
68 {
69   CGUIControl::UpdateVisibility(item);
70
71   // check if we're hidden, and deallocate if so
72   if (!IsVisible() && m_visible != DELAYED)
73   {
74     if (m_bDynamicResourceAlloc && m_bAllocated)
75       FreeResources();
76     return;
77   }
78
79   // we are either delayed or visible, so we can allocate our resources
80
81   // check for conditional information before we
82   // alloc as this can free our resources
83   if (!m_texturePath.IsConstant())
84   {
85     CStdString texturePath(m_texturePath.GetLabel(m_dwParentID));
86     if (texturePath != m_currentPath && !texturePath.IsEmpty())
87     {
88       m_currentPath = texturePath;
89       LoadDirectory();
90       m_image.SetFileName(m_files.size() ? m_files[0] : "");
91     }
92   }
93
94   // and allocate our resources
95   if (!m_bAllocated)
96     AllocResources();
97 }
98
99 void CGUIMultiImage::Render()
100 {
101   if (!m_files.empty())
102   {
103     // Set a viewport so that we don't render outside the defined area
104     g_graphicsContext.SetClipRegion(m_posX, m_posY, m_width, m_height);
105
106     unsigned int nextImage = m_currentImage + 1;
107     if (nextImage >= m_files.size())
108       nextImage = m_loop ? 0 : m_currentImage;  // stay on the last image if <loop>no</loop>
109
110     bool renderNext = false;
111     if (nextImage != m_currentImage)
112     {
113       // check if we should be loading a new image yet
114       DWORD timeToShow = m_timePerImage;
115       if (0 == nextImage) // last image should be paused for a bit longer if that's what the skinner wishes.
116         timeToShow += m_timeToPauseAtEnd;
117       if (m_imageTimer.IsRunning() && m_imageTimer.GetElapsedMilliseconds() > timeToShow)
118       {
119         // grab a new image
120         m_currentImage = nextImage;
121         m_image.SetFileName(m_files[m_currentImage]);
122         m_imageTimer.StartZero();
123       }
124     }
125     m_image.SetColorDiffuse(m_diffuseColor);
126     m_image.Render();
127     g_graphicsContext.RestoreClipRegion();
128   }
129   CGUIControl::Render();
130 }
131
132 bool CGUIMultiImage::OnAction(const CAction &action)
133 {
134   return false;
135 }
136
137 bool CGUIMultiImage::OnMessage(CGUIMessage &message)
138 {
139   if (message.GetMessage() == GUI_MSG_REFRESH_THUMBS)
140   {
141     if (!m_texturePath.IsConstant())
142       FreeResources();
143     return true;
144   }
145   return CGUIControl::OnMessage(message);
146 }
147
148 void CGUIMultiImage::AllocResources()
149 {
150   FreeResources();
151   CGUIControl::AllocResources();
152
153   if (!m_directoryLoaded)
154     LoadDirectory();
155
156   // Randomize or sort our images if necessary
157   if (m_randomized)
158     random_shuffle(m_files.begin(), m_files.end());
159
160   // Load in the current image, and reset our timer
161   m_currentImage = 0;
162   m_imageTimer.StartZero();
163
164   m_image.SetFileName(m_files.size() ? m_files[0] : "");
165 }
166
167 void CGUIMultiImage::FreeResources()
168 {
169   m_image.FreeResources();
170   m_currentImage = 0;
171   CGUIControl::FreeResources();
172 }
173
174 void CGUIMultiImage::DynamicResourceAlloc(bool bOnOff)
175 {
176   CGUIControl::DynamicResourceAlloc(bOnOff);
177   m_bDynamicResourceAlloc=bOnOff;
178 }
179
180 bool CGUIMultiImage::CanFocus() const
181 {
182   return false;
183 }
184
185 void CGUIMultiImage::SetAspectRatio(const CAspectRatio &ratio)
186 {
187   m_image.SetAspectRatio(ratio);
188 }
189
190 void CGUIMultiImage::LoadDirectory()
191 {
192   // Load any images from our texture bundle first
193   m_files.clear();
194
195   // don't load any images if our path is empty
196   if (m_currentPath.IsEmpty()) return;
197
198   // check to see if we have a single image or a folder of images
199   CFileItem item(m_currentPath, false);
200   if (item.IsPicture())
201   {
202     m_files.push_back(m_currentPath);
203   }
204   else
205   { // folder of images
206     g_TextureManager.GetBundledTexturesFromPath(m_currentPath, m_files);
207
208     // Load in our images from the directory specified
209     // m_currentPath is relative (as are all skin paths)
210     CStdString realPath = g_TextureManager.GetTexturePath(m_currentPath, true);
211     if (realPath.IsEmpty())
212       return;
213
214     CUtil::AddSlashAtEnd(realPath);
215     CFileItemList items;
216     CDirectory::GetDirectory(realPath, items);
217     for (int i=0; i < items.Size(); i++)
218     {
219       CFileItemPtr pItem = items[i];
220       if (pItem->IsPicture())
221         m_files.push_back(pItem->m_strPath);
222     }
223   }
224
225   // sort our images - they'll be randomized in AllocResources() if necessary
226   sort(m_files.begin(), m_files.end());
227
228   // flag as loaded - no point in constantly reloading them
229   m_directoryLoaded = true;
230 }
231
232 void CGUIMultiImage::SetInfo(const CGUIInfoLabel &info)
233 {
234   m_texturePath = info;
235   if (m_texturePath.IsConstant())
236     m_currentPath = m_texturePath.GetLabel(WINDOW_INVALID);
237 }